From 3f2f53648fddaded1220797d54eabbcb322c5c59 Mon Sep 17 00:00:00 2001 From: drycc Date: Fri, 4 Oct 2024 00:01:46 +0000 Subject: [PATCH] init repo --- 404.html | 147 + CNAME | 4 + about/featured-background.svg | 65 + about/index.html | 253 + blog/2018/10/06/welcome-to-drycc/index.html | 266 + .../10/06/drycc-workflow-v1.2.0/index.html | 316 + .../10/06/drycc-workflow-v1.3.0/index.html | 318 + .../10/06/drycc-workflow-v1.4.0/index.html | 521 + .../10/06/drycc-workflow-v1.5.0/index.html | 589 + .../10/21/drycc-workflow-v1.6.0/index.html | 733 ++ .../12/08/drycc-workflow-v1.7.0/index.html | 547 + .../01/29/drycc-workflow-v1.7.2/index.html | 319 + .../02/27/drycc-workflow-v1.7.5/index.html | 316 + .../02/27/drycc-workflow-v1.7.6/index.html | 284 + .../04/30/drycc-workflow-v1.7.7/index.html | 436 + .../05/01/drycc-workflow-v1.7.8/index.html | 288 + blog/_print/index.html | 2411 ++++ blog/index.html | 445 + blog/index.xml | 1818 +++ blog/news/_print/index.html | 244 + blog/news/index.html | 261 + blog/news/index.xml | 33 + blog/news/page/1/index.html | 10 + blog/page/1/index.html | 10 + blog/page/2/index.html | 301 + blog/releases/_print/index.html | 2254 ++++ blog/releases/index.html | 445 + blog/releases/index.xml | 1803 +++ blog/releases/page/1/index.html | 10 + blog/releases/page/2/index.html | 280 + categories/index.html | 148 + categories/index.xml | 18 + community/_print/index.html | 199 + community/index.html | 199 + community/index.xml | 18 + css/prism.css | 4 + docs/_print/index.html | 10064 ++++++++++++++++ docs/applications/_print/index.html | 1953 +++ docs/applications/deploying-apps/index.html | 561 + .../domains-and-routing/index.html | 479 + docs/applications/index.html | 550 + docs/applications/index.xml | 1574 +++ .../inter-app-communication/index.html | 466 + .../managing-app-configuration/index.html | 631 + .../managing-app-gateway/index.html | 491 + .../managing-app-lifecycle/index.html | 554 + .../managing-app-metrics/index.html | 485 + .../managing-app-processes/index.html | 699 ++ .../managing-app-resources/index.html | 567 + .../managing-app-volumes/index.html | 527 + .../managing-resource-limits/index.html | 484 + docs/applications/ssl-certificates/index.html | 618 + docs/applications/using-buildpacks/index.html | 600 + .../using-container-images/index.html | 530 + .../applications/using-dockerfiles/index.html | 582 + docs/applications/using-dryccfile/index.html | 509 + .../contribution-guidelines/_print/index.html | 838 ++ .../community/index.html | 465 + .../conduct/index.html | 475 + .../design-documents/index.html | 491 + .../development-environment/index.html | 592 + docs/contribution-guidelines/index.html | 508 + docs/contribution-guidelines/index.xml | 543 + .../maintainers/index.html | 525 + .../overview/index.html | 479 + .../submitting-a-pull-request/index.html | 531 + .../testing/index.html | 476 + .../triaging-issues/index.html | 556 + docs/diagrams/Application_Layout.png | Bin 0 -> 74455 bytes docs/diagrams/Diagrams.graffle | Bin 0 -> 373823 bytes docs/diagrams/Ecosystem_Basic.jpg | Bin 0 -> 102233 bytes docs/diagrams/Ecosystem_Complex.png | Bin 0 -> 160889 bytes docs/diagrams/Git_Push_Flow.png | Bin 0 -> 41453 bytes docs/diagrams/Workflow_Detail.png | Bin 0 -> 45357 bytes docs/diagrams/Workflow_Overview.jpg | Bin 0 -> 96949 bytes docs/index.html | 537 + docs/index.xml | 8052 +++++++++++++ docs/installing-workflow/_print/index.html | 674 ++ .../configuring-object-storage/index.html | 496 + .../configuring-postgres/index.html | 494 + .../configuring-registry/index.html | 517 + .../download-linux-brightgreen.svg | 1 + .../download-osx-brightgreen.svg | 1 + docs/installing-workflow/gateway/index.html | 535 + docs/installing-workflow/index.html | 490 + docs/installing-workflow/index.xml | 415 + .../system-requirements/index.html | 491 + docs/installing-workflow/workflow/index.html | 567 + docs/managing-workflow/_print/index.html | 1037 ++ .../configuring-dns/index.html | 554 + .../managing-workflow/deploy-hooks/index.html | 489 + docs/managing-workflow/index.html | 496 + docs/managing-workflow/index.xml | 766 ++ .../platform-logging/index.html | 498 + .../platform-monitoring/index.html | 541 + .../production-deployments/index.html | 502 + .../tuning-component-settings/index.html | 822 ++ .../upgrading-workflow/index.html | 514 + docs/quickstart/_print/index.html | 772 ++ docs/quickstart/deploy-an-app/index.html | 544 + docs/quickstart/index.html | 478 + docs/quickstart/index.xml | 537 + docs/quickstart/install-cli-tools/index.html | 483 + docs/quickstart/install-workflow/index.html | 826 ++ docs/quickstart/overview/index.html | 474 + docs/reference-guide/_print/index.html | 4273 +++++++ .../controller-api-v2-0/index.html | 1500 +++ .../controller-api-v2-1/index.html | 1499 +++ .../controller-api-v2-2/index.html | 1523 +++ .../controller-api-v2-3/index.html | 1568 +++ .../index.html | 510 + docs/reference-guide/index.html | 484 + docs/reference-guide/index.xml | 4026 +++++++ docs/roadmap/_print/index.html | 515 + docs/roadmap/index.html | 472 + docs/roadmap/index.xml | 292 + docs/roadmap/planning-process/index.html | 478 + docs/roadmap/releases/index.html | 658 + docs/roadmap/roadmap/index.html | 508 + docs/security/1d6a97d0.txt | 92 + docs/troubleshooting/_print/index.html | 402 + docs/troubleshooting/applications/index.html | 495 + docs/troubleshooting/index.html | 472 + docs/troubleshooting/index.xml | 179 + docs/troubleshooting/kubectl/index.html | 530 + docs/troubleshooting/workflow/index.html | 478 + docs/understanding-workflow/_print/index.html | 513 + .../architecture/index.html | 506 + .../components/index.html | 576 + .../concepts/index.html | 556 + docs/understanding-workflow/index.html | 472 + docs/understanding-workflow/index.xml | 290 + docs/users/_print/index.html | 435 + docs/users/cli/index.html | 555 + docs/users/index.html | 472 + docs/users/index.xml | 212 + docs/users/registration/index.html | 484 + docs/users/ssh-keys/index.html | 500 + favicons/android-144x144.png | Bin 0 -> 4299 bytes favicons/android-192x192.png | Bin 0 -> 5264 bytes favicons/android-36x36.png | Bin 0 -> 980 bytes favicons/android-48x48.png | Bin 0 -> 1071 bytes favicons/android-72x72.png | Bin 0 -> 1926 bytes favicons/android-96x96.png | Bin 0 -> 2309 bytes favicons/apple-touch-icon-180x180.png | Bin 0 -> 4748 bytes favicons/favicon-1024.png | Bin 0 -> 27759 bytes favicons/favicon-16x16.png | Bin 0 -> 498 bytes favicons/favicon-256.png | Bin 0 -> 8037 bytes favicons/favicon-32x32.png | Bin 0 -> 807 bytes favicons/favicon.ico | Bin 0 -> 1150 bytes favicons/pwa-192x192.png | Bin 0 -> 5264 bytes favicons/pwa-512x512.png | Bin 0 -> 20743 bytes favicons/tile150x150.png | Bin 0 -> 8985 bytes favicons/tile310x150.png | Bin 0 -> 11661 bytes favicons/tile310x310.png | Bin 0 -> 23621 bytes favicons/tile70x70.png | Bin 0 -> 3592 bytes featured-background.svg | 29 + index.html | 288 + index.xml | 1817 +++ install-cli.sh | 73 + install.sh | 687 ++ ...a2e53e2b34bf42026bf399ebb21bb02212402d1.js | 2 + js/deflate.js | 1652 +++ ...7aa5357805d0ec66bdb741b591cd35fb5f629ab.js | 5 + js/prism.js | 21 + js/tabpane-persist.js | 116 + ...ndex.16ddb05ee41dd47586f606ac04120324.json | 1 + robots.txt | 1 + ...4100bf83163d9bce2eabc28b44f9ef96cb84a0.css | 10 + search/index.html | 153 + sitemap.xml | 276 + tags/index.html | 148 + tags/index.xml | 18 + uninstall.sh | 33 + webfonts/fa-brands-400.ttf | Bin 0 -> 207972 bytes webfonts/fa-brands-400.woff2 | Bin 0 -> 117400 bytes webfonts/fa-regular-400.ttf | Bin 0 -> 68004 bytes webfonts/fa-regular-400.woff2 | Bin 0 -> 25464 bytes webfonts/fa-solid-900.ttf | Bin 0 -> 419720 bytes webfonts/fa-solid-900.woff2 | Bin 0 -> 156496 bytes webfonts/fa-v4compatibility.ttf | Bin 0 -> 10832 bytes webfonts/fa-v4compatibility.woff2 | Bin 0 -> 4792 bytes workflow-cli.txt | 8 + 183 files changed, 101182 insertions(+) create mode 100644 404.html create mode 100644 CNAME create mode 100644 about/featured-background.svg create mode 100644 about/index.html create mode 100644 blog/2018/10/06/welcome-to-drycc/index.html create mode 100644 blog/2019/10/06/drycc-workflow-v1.2.0/index.html create mode 100644 blog/2020/10/06/drycc-workflow-v1.3.0/index.html create mode 100644 blog/2021/10/06/drycc-workflow-v1.4.0/index.html create mode 100644 blog/2022/10/06/drycc-workflow-v1.5.0/index.html create mode 100644 blog/2022/10/21/drycc-workflow-v1.6.0/index.html create mode 100644 blog/2023/12/08/drycc-workflow-v1.7.0/index.html create mode 100644 blog/2024/01/29/drycc-workflow-v1.7.2/index.html create mode 100644 blog/2024/02/27/drycc-workflow-v1.7.5/index.html create mode 100644 blog/2024/02/27/drycc-workflow-v1.7.6/index.html create mode 100644 blog/2024/04/30/drycc-workflow-v1.7.7/index.html create mode 100644 blog/2024/05/01/drycc-workflow-v1.7.8/index.html create mode 100644 blog/_print/index.html create mode 100644 blog/index.html create mode 100644 blog/index.xml create mode 100644 blog/news/_print/index.html create mode 100644 blog/news/index.html create mode 100644 blog/news/index.xml create mode 100644 blog/news/page/1/index.html create mode 100644 blog/page/1/index.html create mode 100644 blog/page/2/index.html create mode 100644 blog/releases/_print/index.html create mode 100644 blog/releases/index.html create mode 100644 blog/releases/index.xml create mode 100644 blog/releases/page/1/index.html create mode 100644 blog/releases/page/2/index.html create mode 100644 categories/index.html create mode 100644 categories/index.xml create mode 100644 community/_print/index.html create mode 100644 community/index.html create mode 100644 community/index.xml create mode 100644 css/prism.css create mode 100644 docs/_print/index.html create mode 100644 docs/applications/_print/index.html create mode 100644 docs/applications/deploying-apps/index.html create mode 100644 docs/applications/domains-and-routing/index.html create mode 100644 docs/applications/index.html create mode 100644 docs/applications/index.xml create mode 100644 docs/applications/inter-app-communication/index.html create mode 100644 docs/applications/managing-app-configuration/index.html create mode 100644 docs/applications/managing-app-gateway/index.html create mode 100644 docs/applications/managing-app-lifecycle/index.html create mode 100644 docs/applications/managing-app-metrics/index.html create mode 100644 docs/applications/managing-app-processes/index.html create mode 100644 docs/applications/managing-app-resources/index.html create mode 100644 docs/applications/managing-app-volumes/index.html create mode 100644 docs/applications/managing-resource-limits/index.html create mode 100644 docs/applications/ssl-certificates/index.html create mode 100644 docs/applications/using-buildpacks/index.html create mode 100644 docs/applications/using-container-images/index.html create mode 100644 docs/applications/using-dockerfiles/index.html create mode 100644 docs/applications/using-dryccfile/index.html create mode 100644 docs/contribution-guidelines/_print/index.html create mode 100644 docs/contribution-guidelines/community/index.html create mode 100644 docs/contribution-guidelines/conduct/index.html create mode 100644 docs/contribution-guidelines/design-documents/index.html create mode 100644 docs/contribution-guidelines/development-environment/index.html create mode 100644 docs/contribution-guidelines/index.html create mode 100644 docs/contribution-guidelines/index.xml create mode 100644 docs/contribution-guidelines/maintainers/index.html create mode 100644 docs/contribution-guidelines/overview/index.html create mode 100644 docs/contribution-guidelines/submitting-a-pull-request/index.html create mode 100644 docs/contribution-guidelines/testing/index.html create mode 100644 docs/contribution-guidelines/triaging-issues/index.html create mode 100644 docs/diagrams/Application_Layout.png create mode 100644 docs/diagrams/Diagrams.graffle create mode 100644 docs/diagrams/Ecosystem_Basic.jpg create mode 100644 docs/diagrams/Ecosystem_Complex.png create mode 100644 docs/diagrams/Git_Push_Flow.png create mode 100644 docs/diagrams/Workflow_Detail.png create mode 100644 docs/diagrams/Workflow_Overview.jpg create mode 100644 docs/index.html create mode 100644 docs/index.xml create mode 100644 docs/installing-workflow/_print/index.html create mode 100644 docs/installing-workflow/configuring-object-storage/index.html create mode 100644 docs/installing-workflow/configuring-postgres/index.html create mode 100644 docs/installing-workflow/configuring-registry/index.html create mode 100644 docs/installing-workflow/download-linux-brightgreen.svg create mode 100644 docs/installing-workflow/download-osx-brightgreen.svg create mode 100644 docs/installing-workflow/gateway/index.html create mode 100644 docs/installing-workflow/index.html create mode 100644 docs/installing-workflow/index.xml create mode 100644 docs/installing-workflow/system-requirements/index.html create mode 100644 docs/installing-workflow/workflow/index.html create mode 100644 docs/managing-workflow/_print/index.html create mode 100644 docs/managing-workflow/configuring-dns/index.html create mode 100644 docs/managing-workflow/deploy-hooks/index.html create mode 100644 docs/managing-workflow/index.html create mode 100644 docs/managing-workflow/index.xml create mode 100644 docs/managing-workflow/platform-logging/index.html create mode 100644 docs/managing-workflow/platform-monitoring/index.html create mode 100644 docs/managing-workflow/production-deployments/index.html create mode 100644 docs/managing-workflow/tuning-component-settings/index.html create mode 100644 docs/managing-workflow/upgrading-workflow/index.html create mode 100644 docs/quickstart/_print/index.html create mode 100644 docs/quickstart/deploy-an-app/index.html create mode 100644 docs/quickstart/index.html create mode 100644 docs/quickstart/index.xml create mode 100644 docs/quickstart/install-cli-tools/index.html create mode 100644 docs/quickstart/install-workflow/index.html create mode 100644 docs/quickstart/overview/index.html create mode 100644 docs/reference-guide/_print/index.html create mode 100644 docs/reference-guide/controller-api-v2-0/index.html create mode 100644 docs/reference-guide/controller-api-v2-1/index.html create mode 100644 docs/reference-guide/controller-api-v2-2/index.html create mode 100644 docs/reference-guide/controller-api-v2-3/index.html create mode 100644 docs/reference-guide/creating-a-self-signed-ssl-certificate/index.html create mode 100644 docs/reference-guide/index.html create mode 100644 docs/reference-guide/index.xml create mode 100644 docs/roadmap/_print/index.html create mode 100644 docs/roadmap/index.html create mode 100644 docs/roadmap/index.xml create mode 100644 docs/roadmap/planning-process/index.html create mode 100644 docs/roadmap/releases/index.html create mode 100644 docs/roadmap/roadmap/index.html create mode 100644 docs/security/1d6a97d0.txt create mode 100644 docs/troubleshooting/_print/index.html create mode 100644 docs/troubleshooting/applications/index.html create mode 100644 docs/troubleshooting/index.html create mode 100644 docs/troubleshooting/index.xml create mode 100644 docs/troubleshooting/kubectl/index.html create mode 100644 docs/troubleshooting/workflow/index.html create mode 100644 docs/understanding-workflow/_print/index.html create mode 100644 docs/understanding-workflow/architecture/index.html create mode 100644 docs/understanding-workflow/components/index.html create mode 100644 docs/understanding-workflow/concepts/index.html create mode 100644 docs/understanding-workflow/index.html create mode 100644 docs/understanding-workflow/index.xml create mode 100644 docs/users/_print/index.html create mode 100644 docs/users/cli/index.html create mode 100644 docs/users/index.html create mode 100644 docs/users/index.xml create mode 100644 docs/users/registration/index.html create mode 100644 docs/users/ssh-keys/index.html create mode 100644 favicons/android-144x144.png create mode 100644 favicons/android-192x192.png create mode 100644 favicons/android-36x36.png create mode 100644 favicons/android-48x48.png create mode 100644 favicons/android-72x72.png create mode 100644 favicons/android-96x96.png create mode 100644 favicons/apple-touch-icon-180x180.png create mode 100644 favicons/favicon-1024.png create mode 100644 favicons/favicon-16x16.png create mode 100644 favicons/favicon-256.png create mode 100644 favicons/favicon-32x32.png create mode 100644 favicons/favicon.ico create mode 100644 favicons/pwa-192x192.png create mode 100644 favicons/pwa-512x512.png create mode 100644 favicons/tile150x150.png create mode 100644 favicons/tile310x150.png create mode 100644 favicons/tile310x310.png create mode 100644 favicons/tile70x70.png create mode 100644 featured-background.svg create mode 100644 index.html create mode 100644 index.xml create mode 100644 install-cli.sh create mode 100644 install.sh create mode 100644 js/click-to-copy.min.f724d3de49218995223b7316aa2e53e2b34bf42026bf399ebb21bb02212402d1.js create mode 100644 js/deflate.js create mode 100644 js/main.min.248655eb216150e39da254c2f7aa5357805d0ec66bdb741b591cd35fb5f629ab.js create mode 100644 js/prism.js create mode 100644 js/tabpane-persist.js create mode 100644 offline-search-index.16ddb05ee41dd47586f606ac04120324.json create mode 100644 robots.txt create mode 100644 scss/main.min.3a5b24585fce93f20631bc122a4100bf83163d9bce2eabc28b44f9ef96cb84a0.css create mode 100644 search/index.html create mode 100644 sitemap.xml create mode 100644 tags/index.html create mode 100644 tags/index.xml create mode 100644 uninstall.sh create mode 100644 webfonts/fa-brands-400.ttf create mode 100644 webfonts/fa-brands-400.woff2 create mode 100644 webfonts/fa-regular-400.ttf create mode 100644 webfonts/fa-regular-400.woff2 create mode 100644 webfonts/fa-solid-900.ttf create mode 100644 webfonts/fa-solid-900.woff2 create mode 100644 webfonts/fa-v4compatibility.ttf create mode 100644 webfonts/fa-v4compatibility.woff2 create mode 100644 workflow-cli.txt diff --git a/404.html b/404.html new file mode 100644 index 000000000..d0ae8ac41 --- /dev/null +++ b/404.html @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + +404 Page not found | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+

Not found

+

Oops! This page doesn't exist. Try going back to the home page.

+

You can learn how to make a 404 page like this in Custom 404 Pages.

+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/CNAME b/CNAME new file mode 100644 index 000000000..170be2baa --- /dev/null +++ b/CNAME @@ -0,0 +1,4 @@ +www.drycc.cc +www.drycc.com +drycc.cc +drycc.com diff --git a/about/featured-background.svg b/about/featured-background.svg new file mode 100644 index 000000000..4400b877e --- /dev/null +++ b/about/featured-background.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/about/index.html b/about/index.html new file mode 100644 index 000000000..07e955a34 --- /dev/null +++ b/about/index.html @@ -0,0 +1,253 @@ + + + + + + + + + + + + + + + + + + + +About | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + + +
+
+
+
+

About Drycc

+ +
+ +

Drycc, the only Container as a Service (CaaS) you need.

+ + +
+
+
+
+ +
+ +
+
+
+
+
+

Native to Kubernetes, Drycc is the Container as a Service(CaaS) suite available on every public cloud, every Kubernetes distribution, the private cloud and the edge.

+
+
+
+
+
+
+
+
+

Mission

+

Empower engineers and enterprises to innovate with speed, agility, and scale.

+
+
+
+
+
+
+
+

Vision

+

Become the best and most respected infrastructure software company in the world.

+
+
+
+
+
+
+
+

Core values

+

Native to Kubernetes, Drycc is the Container as a Service(CaaS) suite available on every public cloud, every Kubernetes distribution, the private cloud and the edge.

+

We value each other

+

We recognize we come from a variety of backgrounds and have a variety of beliefs and values. We embrace each other as people, respect our differences, and are committed to working together to achieve our shared objectives.

+

Work for Customer Success

+

We listen to our customers to understand their needs and think from their perspective. We identify current and potential challenges and optimize business value for our customers. Our goal is to be a trusted, reliable, and long-term partner providing leading technology to our users.

+

We embrace failure

+

We try things, break things, take risks, and believe failure is key to innovation. We bounce back from failure and learn quickly.

+

We are committed to open source

+

We strive to make information and the decision process as transparent as possible. We endeavor to be humble, curious, and always open to learning and improving ourselves. We are open to different opinions, diverse perspectives and challenges, but after a decision is made, we fully commit to it. We believe in open source and are committed to participating in and contributing to the open source community in meaningful ways.

+

We are committed to helping our customers build cool stuff that transforms their business in less time – we call it Time to Awesome.

+
+
+
+ +
+ + +
+ + + + + + \ No newline at end of file diff --git a/blog/2018/10/06/welcome-to-drycc/index.html b/blog/2018/10/06/welcome-to-drycc/index.html new file mode 100644 index 000000000..84e449ff3 --- /dev/null +++ b/blog/2018/10/06/welcome-to-drycc/index.html @@ -0,0 +1,266 @@ + + + + + + + + + + + + + + + + + + + +Welcome to Drycc | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + +
+

Welcome to Drycc

+
Drycc Workflow is A Open, Unified, Lightweight, Simpler Containers as a Service (CaaS).
+ + +

Drycc Workflow is an open source Container as a Service (CaaS) that adds a developer-friendly layer to any Kubernetes cluster, making it easy to deploy and manage applications.

+

We welcome your input! If you have feedback, please submit an issue. If you’d like to participate in development, please read the “Working on Documentation” section below and submit a pull request.

+ + + +
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/blog/2019/10/06/drycc-workflow-v1.2.0/index.html b/blog/2019/10/06/drycc-workflow-v1.2.0/index.html new file mode 100644 index 000000000..1b1a9b0f2 --- /dev/null +++ b/blog/2019/10/06/drycc-workflow-v1.2.0/index.html @@ -0,0 +1,316 @@ + + + + + + + + + + + + + + + + + + + +Drycc Workflow v1.2.0 | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + +
+

Drycc Workflow v1.2.0

+
New Drycc Workflow Release v1.2.0
+ + +

These release notes for Drycc Workflow v1.2.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.1.0, please refer to the following change summary.

+

Workflow ## v1.1.0 -> v1.2.0

+

Releases

+
    +
  • builder v1.0.1 -> v1.0.2
  • +
  • slugbuilder v1.0.0 -> v1.1.0
  • +
  • dockerbuilder v1.0.0 -> v1.1.0
  • +
  • controller v1.1.0 -> v1.2.0
  • +
  • slugrunner v1.0.0 -> v1.1.0
  • +
  • registry v1.0.0 -> v1.0.1
  • +
  • registry-proxy v1.0.1 -> v1.0.2
  • +
+

Features

+
    +
  • e5584e3 (controller) - controller: add STACK support
  • +
  • ad34dc1 (dockerbuilder) - kaniko: use kaniko replace docker-py
  • +
  • b81430e (dockerbuilder) - dockerbuilder: change image to image.json format
  • +
  • 60dde96 (slugbuilder) - slugbuilder: add STACK support
  • +
  • fe8b6e5 (slugrunner) - slugrunner: add STACK support
  • +
+

Maintenance

+
    +
  • 942f050 (builder) - registry: remove env DRYCC_REGISTRY_PROXY_PORT
  • +
  • ff7a16f (builder) - registry: remove ecr and gcr registry
  • +
  • ad13683 (builder) - builder: change DRYCC_BUILD_TYPE to DRYCC_STACK
  • +
  • 6def637 (builder) - registry: rename DRYCC_REGISTRY_SERVICE to DRYCC_REGISTRY_PROXY
  • +
  • 5044e22 (builder) - registry: remove registry_secret_prefix
  • +
  • 2ea39cc (builder) - controller-go-sdk: upgrade controller-go-sdk
  • +
  • 6aee0d7 (builder) - registry: optimizing variable naming
  • +
  • f9c62d9 (controller) - domain: added reserved domain check
  • +
  • f5a135b (controller) - migrations: clean old migrations
  • +
  • 4369b2c (controller) - registry: rename DRYCC_REGISTRY_SERVICE to DRYCC_REGISTRY_PROXY
  • +
  • 1057ca5 (controller) - registry: remove registry_secret_prefix
  • +
  • d114b3e (controller) - docker: update docker client
  • +
  • edbe963 (dockerbuilder) - dockerfile: change base image to alpine
  • +
  • fb35baf (dockerbuilder) - registry: rename DRYCC_REGISTRY_SERVICE to DRYCC_REGISTRY_PROXY
  • +
  • 946dbf6 (dockerbuilder) - docker: remove insecure support
  • +
  • 628d853 (dockerbuilder) - proxy: add registry proxy
  • +
  • ff27cbd (registry) - env: remove unused env
  • +
  • 7204d72 (registry-proxy) - registry: optimizing variable naming
  • +
+ + + +
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/blog/2020/10/06/drycc-workflow-v1.3.0/index.html b/blog/2020/10/06/drycc-workflow-v1.3.0/index.html new file mode 100644 index 000000000..40e86c95c --- /dev/null +++ b/blog/2020/10/06/drycc-workflow-v1.3.0/index.html @@ -0,0 +1,318 @@ + + + + + + + + + + + + + + + + + + + +Drycc Workflow v1.3.0 | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + +
+

Drycc Workflow v1.3.0

+
New Drycc Workflow Release v1.3.0
+ + +

These release notes for Drycc Workflow v1.3.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.2.0, please refer to the following change summary.

+

Workflow ## v1.2.0 -> v1.3.0

+

Releases

+
    +
  • builder v1.0.2 -> v1.1.0
  • +
  • slugbuilder v1.1.0 -> v1.1.1
  • +
  • dockerbuilder v1.1.0 -> v1.1.1
  • +
  • controller v1.2.0 -> v1.2.1
  • +
  • slugrunner v1.1.0 -> v1.1.1
  • +
  • database v1.0.0 -> v1.0.1
  • +
  • fluentd v1.0.0 -> v1.0.1
  • +
  • minio v1.0.0 -> v1.0.1
  • +
  • monitor v1.0.0 -> v1.0.1
  • +
  • registry v1.0.1 -> v1.0.2
  • +
  • workflow-manager v1.0.0 -> v1.0.1
  • +
+

Features

+
    +
  • 9c7cceb (builder) - builder: add app config to env
  • +
+

Fixes

+
    +
  • 7fe44fa (controller) - docker: docker timeout must be an int, float or None
  • +
  • b196550 (controller) - controller: revert release.check_image_access for now
  • +
  • cc3ec13 (workflow-manager) - glide: bump goautoneg
  • +
+

Maintenance

+
    +
  • ef932c4 (builder) - controller-sdk-go: upgrade controller-sdk-go
  • +
  • 4654cf6 (controller) - django-rest-framework: upgrade to 3.9.3
  • +
  • 14121f1 (controller) - deps: bump djangorestframework from 3.9.3 to 3.9.4 in /rootfs
  • +
  • 385acdc (controller) - deps: bump django from 1.11.20 to 1.11.21 in /rootfs
  • +
  • fa312bb (database) - postgres: set max_connections = 1024
  • +
  • 7ebecdf (database) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z
  • +
  • b8878f6 (dockerbuilder) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z
  • +
  • b097451 (fluentd) - fluent: upgrade fluent to v1.4
  • +
  • 4341f9a (minio) - mc: upgrade mc and minio
  • +
  • c1ee2a4 (monitor) - monitor: remove copyrights.tar.gz
  • +
  • 9854260 (registry) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z
  • +
  • acc5627 (slugbuilder) - slugbuilder: internal support for multi buildpack
  • +
  • d58907e (slugbuilder) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z
  • +
  • b39a0c2 (slugrunner) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z
  • +
+ + + +
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/blog/2021/10/06/drycc-workflow-v1.4.0/index.html b/blog/2021/10/06/drycc-workflow-v1.4.0/index.html new file mode 100644 index 000000000..94ff1a414 --- /dev/null +++ b/blog/2021/10/06/drycc-workflow-v1.4.0/index.html @@ -0,0 +1,521 @@ + + + + + + + + + + + + + + + + + + + +Drycc Workflow v1.4.0 | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + +
+

Drycc Workflow v1.4.0

+
New Drycc Workflow Release v1.4.0
+ + +

These release notes for Drycc Workflow v1.3.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.4.0, please refer to the following change summary.

+

Workflow ## v1.3.0 -> v1.4.0

+

Releases

+
    +
  • builder v1.1.0 -> v1.2.0
  • +
  • slugbuilder v1.1.1 -> v1.2.0
  • +
  • dockerbuilder v1.1.1 -> v1.1.2
  • +
  • controller v1.2.1 -> v1.3.0
  • +
  • slugrunner v1.1.1 -> v1.1.2
  • +
  • database v1.0.1 -> v1.0.2
  • +
  • fluentd v1.0.1 -> v1.1.0
  • +
  • redis v1.0.0 -> v1.1.0
  • +
  • logger v1.0.0 -> v1.1.0
  • +
  • minio v1.0.1 -> v1.1.0
  • +
  • monitor v1.0.1 -> v1.1.0
  • +
  • nsqd v1.0.0 -> v1.1.0
  • +
  • registry v1.0.2 -> v1.0.3
  • +
  • registry-proxy v1.0.0 -> v1.0.1
  • +
+

Features

+
    +
  • fc7d93f (builder) - builder: use go-dev
  • +
  • 0c2159e (builder) - builder: fmt code and add create_bucket script
  • +
  • 1b88340 (controller) - controller: remove deprecated api
  • +
  • a92fdeb (controller) - routable: ingress support routable
  • +
  • 1e3eab3 (controller) - maintenance: add maintenance support for ingress
  • +
  • 56b9dd0 (controller) - crt: support containerd-ctr
  • +
  • 5fc3b46 (controller) - controller: add ephemeral-storage restriction
  • +
  • d677e52 (controller) - controller: add a volume command
  • +
  • 5f1323a (controller) - controller:drycc run cmd add –mount para
  • +
  • 74c36a5 (controller) - tasks: add distributed async task
  • +
  • 139c3ca (controller) - tasks: change nsq reader to async
  • +
  • f237d74 (controller) - controller:add drycc resource cmd
  • +
  • 41b46d0 (controller) - controller:add drycc resource cmd improvement
  • +
  • c26f7d8 (controller) - controller: add LimitRanges support
  • +
  • 45b5d1b (controller) - users: add users status api
  • +
  • 4e16f9b (controller) - ps:add ps:stop/start command
  • +
  • c659fa9 (controller) - k8s: add k8s cluster domain
  • +
  • 31a625d (controller) - ps:add ps:stop/start command
  • +
  • 00a779a (fluentd) - fluentd: support containerd log format
  • +
  • f3f1bd4 (fluentd) - nsqd: add stateless nsqd cluster support
  • +
  • db7147c (fluentd) - mirrors: delete aliyun mirrors
  • +
  • 689c12e (logger) - nsqd: add stateless nsqd cluster support
  • +
  • 78ccc5d (logger) - redis: add redis client cluster support
  • +
  • 9843f2c (logger) - k8s: add k8s cluster domain
  • +
  • 6ba122e (minio) - minio: add pvc support
  • +
  • 6973550 (monitor) - monitor: add ingress for monitor
  • +
  • cd73305 (monitor) - charts: add volumeName support
  • +
  • 4769fe9 (monitor) - nsqd: add stateless nsqd cluster support
  • +
  • 87806df (monitor) - k8s: add k8s cluster domain
  • +
  • 4db40c4 (nsqd) - nsqd: add stateless nsqd cluster support
  • +
  • b6f3d4f (nsqd) - nsqd: add stateless nsqd cluster support
  • +
  • 74b85bb (redis) - redis: change redis to statefulset
  • +
  • ff98b50 (slugbuilder) - slugbuilder: delete build hook
  • +
  • b201c2f (slugbuilder) - buildpacks: use drycc buildpacks
  • +
+

Fixes

+
    +
  • 0ec042d (builder) - test: fix test case error
  • +
  • 4fb113b (builder) - build: base image replace by alpine
  • +
  • 443df48 (builder) - minio: fix not bucket error
  • +
  • 3dab5b0 (builder) - minio: create bucket error
  • +
  • 734fca6 (controller) - autoscale: Fix for autoscale on k8s-1.9+ without breaking manual scaling
  • +
  • a7dcd10 (controller) - controller: test pass
  • +
  • 93f0f2e (controller) - controller: fix migrations error
  • +
  • 4724375 (controller) - controller: fix test error
  • +
  • 7bacf29 (controller) - charts: fix clusterrole
  • +
  • 90957f7 (controller) - pod: sort events error
  • +
  • 440b13e (controller) - controller: review table structure
  • +
  • 0a470a6 (controller) - controller: bump tornado 5.1.1
  • +
  • e39218b (controller) - pynsq: no current event loop in thread
  • +
  • 1d8630e (controller) - tests: fix test_task.py run error
  • +
  • 1ff1202 (controller) - controller: fix test case
  • +
  • d8c0da3 (controller) - settings: fix env name
  • +
  • 6d8fd36 (database) - 003_restore_from_backup.sh: ignore script exit 1
  • +
  • e0394a9 (database) - minio: fix not bucket error
  • +
  • f35f252 (database) - mc: fix create_bucket error
  • +
  • 74d6886 (database) - postgres: recovery mode not run
  • +
  • e50d0c1 (dockerbuilder) - caddy: fix caddy not start
  • +
  • f3bec7a (fluentd) - influxdb: fix influxdb host and port
  • +
  • bc19f27 (fluentd) - charts: skipped value for daemon_environment: Not a table
  • +
  • 338d623 (logger) - logger: logger not run in alpine
  • +
  • 7788302 (minio) - minio: bump minio version
  • +
  • 619eed0 (minio) - fix: use go mod replace dep
  • +
  • 3b42122 (monitor) - monitor: fix host error
  • +
  • 67998ef (monitor) - influxdb: replace drycc-monitor-influxapi to drycc-monitor-influx-api
  • +
  • 2cc361c (registry) - registry: fix test case
  • +
  • 548297a (registry) - minio: fix not bucket error
  • +
  • 5412ddb (registry) - minio: create bucket error
  • +
  • d0d629e (slugbuilder) - slugbuilder:fix normalize_storage path
  • +
  • d76ecbe (slugbuilder) - slugbuilder: use v3 api
  • +
  • c505e18 (slugbuilder) - shellcheck: SC2039
  • +
+

Style

+
    +
  • c893a17 (builder) - builder: fmt code
  • +
  • bba5795 (controller) - controller: format code
  • +
  • d36082b (controller) - controller: fix pep8
  • +
  • 66026f2 (controller) - resource: standardize the naming of resource
  • +
  • 03d7e2c (controller) - servicecatalog: change servicecatalog to svcat
  • +
  • 49dbb6d (controller) - controller: flake8 upgrade
  • +
  • cbfc108 (monitor) - monitor: format charts and dashboard
  • +
  • ee85954 (slugbuilder) - slugbuilder: use shellcheck
  • +
  • 3afed2e (slugbuilder) - docker: simplify dockerfile
  • +
  • 36b7f68 (slugrunner) - docker: simplify dockerfile
  • +
+

Maintenance

+
    +
  • 61bb0ef (builder) - aws: upgrade aws sdk version
  • +
  • 0f2e074 (builder) - chore: use go mode replace dep
  • +
  • e9a2219 (builder) - builder: delete glide up
  • +
  • bb8c518 (builder) - registry: del quay.io
  • +
  • fa6d02f (builder) - builder: upgrade go.sum
  • +
  • 9d61e8d (builder) - build: upgrade go.mod
  • +
  • d763a98 (builder) - charts: upgrade k8s newer API versions
  • +
  • d1bc1aa (builder) - pkg: upgrade to new drycc/pkg
  • +
  • 02b1e98 (builder) - builder: update go mod
  • +
  • 8e17d65 (builder) - builder: change alpine repositories
  • +
  • f32b723 (builder) - mirrors: delete aliyun mirrors
  • +
  • e33dc61 (builder) - minio: use bin mc replace docker images
  • +
  • 3ab4f1c (builder) - builder: update controller-sdk-go
  • +
  • b2adfac (builder) - heroku: remove heroku-16 support
  • +
  • f429ac8 (builder) - builder: set GIT_LOCK_TIMEOUT to 30 minutes
  • +
  • 7197c83 (builder) - go.mod:upgrade require pkg controller-sdk-go
  • +
  • 5f3e22d (controller) - deps: bump django from 1.11.21 to 1.11.22 in /rootfs
  • +
  • 1db645a (controller) - deps: bump django from 1.11.22 to 1.11.23 in /rootfs
  • +
  • fbe8067 (controller) - deps: bump django from 1.11.23 to 1.11.29 in /rootfs
  • +
  • 537d667 (controller) - registry: del quay.io
  • +
  • a23c65b (controller) - deps: update all deps to the latest version
  • +
  • 546337e (controller) - charts: upgrade k8s newer API versions
  • +
  • 06023f8 (controller) - workflow-manager: del workflow-manager
  • +
  • bba5736 (controller) - controller: change cluster-issuer location
  • +
  • 6c43661 (controller) - Certificatechange cluster-issuer location
  • +
  • 39a4728 (controller) - controller:change cluster-issuer location del controller-cluster-issuer.yaml
  • +
  • 9e96d3f (controller) - Certificate:upgrade version cert-manager.io/v1alpha2
  • +
  • 8e68049 (controller) - docker: use INDEX_URL replace index.docker.io
  • +
  • 8fda205 (controller) - cert_manager: change cert_manager_enabled to global
  • +
  • 6fefb6d (controller) - charts: change platform_domain to global
  • +
  • 064b2ad (controller) - maintenance: remove maintenance support
  • +
  • b8797c9 (controller) - workflow: remove namespace
  • +
  • 1b20d76 (controller) - quota: add kube quota config
  • +
  • d780075 (controller) - pod: add pod default resources support
  • +
  • 3d72c08 (controller) - rename: rename ingress name
  • +
  • 0aa6ab9 (controller) - mirrors: delete aliyun mirrors
  • +
  • 7533a65 (controller) - heroku: remove heroku-16 support
  • +
  • e5a885d (controller) - controller:check mount volume path
  • +
  • 9014e74 (controller) - test: optimization Dockerfile.test
  • +
  • 0b6ebb2 (controller) - tasks: change apply_async parameters
  • +
  • 835f009 (controller) - wsgi: add tornado 6 support
  • +
  • 67a4ad7 (controller) - utils: use threads replace asyncio
  • +
  • a28949b (controller) - ldap: add AUTH_LDAP_USER_FLAGS_BY_GROUP
  • +
  • a903209 (controller) - charts: add custom controller environment variables support
  • +
  • e0e783e (controller) - ldap: change filter style
  • +
  • d760825 (controller) - scheduler: remove debug log
  • +
  • a25928e (controller) - wsgi: remove a wsgi.py file
  • +
  • 7b2696e (controller) - log: disable nsq.client info log
  • +
  • 8d5c07b (controller) - charts: add default environment
  • +
  • 025f4a2 (controller) - controller: change quota name
  • +
  • ebda60e (controller) - controller: review pvc code
  • +
  • 8832ba9 (controller) - controller: change status\binding model type and mount path check container_types
  • +
  • 7148d04 (controller) - controller: add overcommit cpu and ram support
  • +
  • 4d2087c (controller) - limits: modify limits unit verification
  • +
  • af36970 (controller) - api: check cpu/memory range for api
  • +
  • 329355b (controller) - volumes: modify the volume size
  • +
  • 9dfee09 (controller) - LimitRanges: modify the default limits
  • +
  • 5205bca (controller) - controller: improve the details of certificate
  • +
  • 7ebecdf (database) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z
  • +
  • 6415e2c (database) - postgres: upgrade to pg13
  • +
  • 12e6806 (database) - charts: upgrade k8s newer API versions
  • +
  • d294509 (database) - minio: use canary minio test
  • +
  • 1bad02e (database) - mirrors: delete aliyun mirrors
  • +
  • d51420b (database) - minio: use bin mc replace docker images
  • +
  • 4133d05 (dockerbuilder) - dockerbuilder: update caddy and kaniko
  • +
  • 6b4dd18 (dockerbuilder) - minio: use bin mc replace docker images
  • +
  • 6df9b7c (fluentd) - deps-dev: update rake requirement from ~> 10.0 to ~> 12.3
  • +
  • c2490f8 (fluentd) - fluentd: upgrade fluentd
  • +
  • be4a56a (fluentd) - fluentd: add Gemfile.lock
  • +
  • 2237f75 (fluentd) - charts: upgrade k8s newer API versions
  • +
  • c574065 (fluentd) - charts: upgrade k8s newer API versions
  • +
  • 52b8084 (fluentd) - router: delete obsolete router code
  • +
  • 3b3cceb (fluentd) - fluentd: remove manifests dir
  • +
  • 25c6702 (fluentd) - nsqd: change var name
  • +
  • bd571be (fluentd) - nsqd: change DRYCC_NSQD_ADDRESSES to DRYCC_NSQD_ADDRS
  • +
  • 72aa4e6 (fluentd) - influxdb: change influxdb service name
  • +
  • bd61903 (logger) - logger: use go mod replace dep
  • +
  • 69c63a1 (logger) - logger: update go.mod
  • +
  • 3aa9cd7 (logger) - registry: del quay.io
  • +
  • f058496 (logger) - nsqd: change var name
  • +
  • 6d9787c (logger) - nsqd: change DRYCC_NSQD_ADDRESSES to DRYCC_NSQD_ADDRS
  • +
  • 85ed307 (logger) - logger: standard naming
  • +
  • d88e7b6 (minio) - minio: update minio api to v7
  • +
  • 43715d2 (minio) - minio: upgrade minio
  • +
  • 0e1239b (minio) - minio: use docker.io replace quay.io
  • +
  • f7f047b (minio) - registry: del quay.io
  • +
  • afa7128 (minio) - build: upgrade go.mod
  • +
  • aff2db5 (minio) - charts: upgrade k8s newer API versions
  • +
  • 4547f14 (minio) - pkg: upgrade to new drycc/pkg
  • +
  • 2769b85 (minio) - minio: use bin mc replace docker images
  • +
  • 35dde8d (monitor) - monitor: update grafana influxdb telegraf
  • +
  • 9e3a949 (monitor) - charts: upgrade k8s newer API versions
  • +
  • 6af0432 (monitor) - workflow-manager: remove workflow-manager
  • +
  • 0611c07 (monitor) - router: delete obsolete router code
  • +
  • be04824 (monitor) - cert_manager: change cert_manager_enabled to global
  • +
  • 3780165 (monitor) - charts: change platform_domain to global
  • +
  • 50b04e1 (monitor) - influxdb: remove influxdb admin ui
  • +
  • 6ab4d68 (monitor) - influxdb: remove unuse port
  • +
  • f1510bd (monitor) - monitor: update grafana dashboard,telegraf inputs.kubernetes
  • +
  • f36de2c (monitor) - pvc: upgrade to new format
  • +
  • fc78a0a (monitor) - workflow: remove namespace
  • +
  • e85890f (monitor) - monitor: monitoring nsqd and redis separately
  • +
  • 694f6b1 (monitor) - mirrors: delete aliyun mirrors
  • +
  • 4aea36a (monitor) - grafana: add ldap support for grafana
  • +
  • 68fc30f (nsqd) - nsq: update nsq
  • +
  • 16f32aa (nsqd) - charts: upgrade k8s newer API versions
  • +
  • 04db389 (redis) - reids: update to redis 6
  • +
  • 3f01bab (redis) - charts: upgrade k8s newer API versions
  • +
  • 647e4be (registry) - registry: del quay.io
  • +
  • 0bbce99 (registry) - charts: upgrade k8s newer API versions
  • +
  • a982b50 (registry) - minio: use bin mc replace docker images
  • +
  • e088da3 (registry-proxy) - ingress: renmae use_native_ingress to use_ingress
  • +
  • 7e88337 (registry-proxy) - nginx: upgrade nginx to mainline
  • +
  • 7204d72 (registry-proxy) - registry: optimizing variable naming
  • +
  • 2eafc59 (registry-proxy) - registry-proxy: update nginx
  • +
  • 071bd86 (registry-proxy) - charts: upgrade k8s newer API versions
  • +
  • c72db96 (registry-proxy) - registry-proxy: change travis icon url
  • +
  • ca9f962 (slugbuilder) - slugbuilder: del BUILDPACK_URL support
  • +
  • 1b74dd5 (slugbuilder) - slugbuilder: add heroku-20 support
  • +
  • 54d4ad2 (slugbuilder) - slugbuilder: del quay.io
  • +
  • a78f37e (slugbuilder) - slugbuilder: add heroku-20 stack
  • +
  • 94ac94a (slugbuilder) - minio: use bin mc replace docker images
  • +
  • 53b4b8b (slugbuilder) - slugbuilder: modify stack priority
  • +
  • 58e2bd2 (slugbuilder) - dockerfile: add WORKDIR /tmp
  • +
  • b29cd04 (slugbuilder) - slugbuilder: add pre_build.sh
  • +
  • 9d319f6 (slugbuilder) - slugbuilder: silent mc command output
  • +
  • d1ec3c9 (slugbuilder) - heroku: remove heroku-16 support
  • +
  • 5048534 (slugbuilder) - slugbuilder: use drycc stack-images
  • +
  • a116537 (slugrunner) - slugrunner: add heroku-20 support
  • +
  • a1196bf (slugrunner) - slugrunner: del quay.io
  • +
  • 64c96d7 (slugrunner) - slugrunner: add heroku-20 stack
  • +
  • cc3e226 (slugrunner) - minio: use bin mc replace docker images
  • +
  • 9130bde (slugrunner) - shellcheck: shellcheck installer
  • +
  • 4ea33e1 (slugrunner) - slugrunner: modify stack priority
  • +
  • 5514e8b (slugrunner) - heroku: remove heroku-16 support
  • +
  • be829fb (slugrunner) - slugrunner: use drycc stack-images
  • +
  • e1e06be (slugrunner) - slugrunner: remove Dockerfile.heroku-16
  • +
+ + + +
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/blog/2022/10/06/drycc-workflow-v1.5.0/index.html b/blog/2022/10/06/drycc-workflow-v1.5.0/index.html new file mode 100644 index 000000000..959205459 --- /dev/null +++ b/blog/2022/10/06/drycc-workflow-v1.5.0/index.html @@ -0,0 +1,589 @@ + + + + + + + + + + + + + + + + + + + +Drycc Workflow v1.5.0 | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + +
+

Drycc Workflow v1.5.0

+
New Drycc Workflow Release v1.5.0
+ + +

These release notes for Drycc Workflow v1.5.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.4.0, please refer to the following change summary.

+

Workflow ## v1.4.0 -> v1.5.0

+

Releases

+
    +
  • passport v1.0.0
  • +
  • rabbitmq v1.0.0
  • +
  • imagebuilder v1.0.0
  • +
  • builder v1.2.0 -> v1.3.0
  • +
  • controller v1.3.0 -> v1.4.0
  • +
  • database v1.0.2 -> v1.1.0
  • +
  • fluentd v1.1.0 -> v1.2.0
  • +
  • redis v1.1.0 -> v1.2.0
  • +
  • influxdb v1.0.1 -> v1.1.0
  • +
  • logger v1.1.0 -> v1.2.0
  • +
  • minio v1.1.0 -> v1.2.0
  • +
  • monitor v1.1.0 -> v1.2.0
  • +
  • nsqd v1.1.0 -> v1.2.0
  • +
  • registry v1.0.3 -> v1.1.0
  • +
  • registry-proxy v1.0.2 -> v1.1.0
  • +
+

Features

+
    +
  • 0f5f8e4 (builder) - builder: multi-platform support
  • +
  • f269d06 (builder) - build: add buildx supportjkjkk:q
  • +
  • 5e72fe8 (builder) - registry: use docker build
  • +
  • 25d8a4c (builder) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 7a3e1c5 (builder) - charts: set the default chart version
  • +
  • 46b75ff (builder) - builder: add cloud native buildpacks support
  • +
  • 2db2054 (builder) - builder: unified build model
  • +
  • 4b7f9d9 (builder) - builder: add initContainers
  • +
  • b78c936 (controller) - token: add get token api
  • +
  • bac52a5 (controller) - tasks: use celery replace nsqd
  • +
  • b9b0c58 (controller) - build: add buildx support
  • +
  • 205dcb3 (controller) - influxdb: add influxdb client
  • +
  • ff15849 (controller) - influxdb: upgrade to influxdb 2.x
  • +
  • 4016244 (controller) - controller: push data to influx
  • +
  • fcfce2e (controller) - workflow-manager: add workflow-manager support
  • +
  • 00e9bfb (controller) - influxdb: review influxdb code
  • +
  • dd644d5 (controller) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 118278b (controller) - charts: set the default chart version
  • +
  • 122a9cd (controller) - oauth2: add oauth2 support
  • +
  • 559a5b6 (controller) - controller: use cncf buildpacks replace slugrunner
  • +
  • 96130e6 (controller) - charts: database configuration optimization of passport and controller
  • +
  • 2ea8508 (controller) - oauth: using passport authentication
  • +
  • 868c437 (database) - database: multi-platform support
  • +
  • eadd5da (database) - build: add buildx support
  • +
  • b6eea4c (database) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 04a88db (database) - charts: set the default chart version
  • +
  • 92ed309 (database) - database: add initContainer
  • +
  • ee6b78f (fluentd) - build: add buildx support
  • +
  • f523e30 (fluentd) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • ee47b53 (fluentd) - charts: set the default chart version
  • +
  • 80a51af (influxdb) - influxdb: modify influxdb naming rules
  • +
  • fb10030 (influxdb) - influxdb: use influxdb v2
  • +
  • 0e87ad8 (influxdb) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 9d10801 (influxdb) - charts: set the default chart version
  • +
  • d825c9f (logger) - build: add buildx support
  • +
  • b139576 (logger) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 88f84ea (logger) - charts: set the default chart version
  • +
  • 5ccae3e (logger) - dockerfile: remove chmod cmd
  • +
  • 193aefc (logger) - logger: add initContainers
  • +
  • baee330 (minio) - minio: multi-platform support
  • +
  • ad5d055 (minio) - build: add buildx support
  • +
  • 19868d4 (minio) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 4bd84b8 (minio) - charts: set the default chart version
  • +
  • 79d1f2f (monitor) - database: multi-platform support
  • +
  • 88e5a7f (monitor) - build: add buildx support
  • +
  • 5672e99 (monitor) - influxdb: modify influxdb naming rules
  • +
  • 8672103 (monitor) - influxdb: use influxdb v2
  • +
  • 66cb4c8 (monitor) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 9576eb3 (monitor) - charts: set the default chart version
  • +
  • 30809c9 (monitor) - monitor: add initContainers
  • +
  • 70d140c (nsqd) - nsqd: using self compiled nsq binary
  • +
  • 1073d4f (nsqd) - nsqd: use GOPATH replace /go
  • +
  • e498480 (nsqd) - build: add buildx support
  • +
  • cf9b7d5 (nsqd) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • c335856 (nsqd) - charts: set the default chart version
  • +
  • efba713 (redis) - build: add buildx support
  • +
  • c7a3b53 (redis) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 4cdad7b (redis) - charts: set the default chart version
  • +
  • 652b443 (registry) - registry: multi-platform support
  • +
  • 4060176 (registry) - registry: use docker build
  • +
  • 7102a03 (registry) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 6c8600d (registry) - charts: set the default chart version
  • +
  • 33a51c9 (registry) - registry: add initContainers
  • +
  • bef70dc (registry-proxy) - build: add buildx support
  • +
  • d2319c1 (registry-proxy) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 02fafed (registry-proxy) - charts: set the default chart version
  • +
+

Fixes

+
    +
  • 5499c9a (controller) - gunicorn: gunicorn not running
  • +
  • 06e9e88 (controller) - controller: error loading shared library
  • +
  • 01b5bd0 (controller) - controller: upgrade celery config
  • +
  • 6e32d55 (controller) - controller: fix update resources bug
  • +
  • 0e0d53f (controller) - chart: set the domain depends certManagerEnabled
  • +
  • 2ac4ca8 (controller) - passport: error loading shared library libexpat.so.1
  • +
  • a0dd517 (fluentd) - fluentd: drone build
  • +
  • 6eca2a3 (logger) - logger: golang lint
  • +
  • 63b0aa0 (registry) - drone: charts url error
  • +
+

Docs

+
    +
  • 472cfcc (controller) - controller organize README.md document
  • +
  • d9d6e29 (redis) - redis: delete links that do not exist
  • +
+

Test case

+
    +
  • 1468f57 (controller) - controller: add command unittest
  • +
+

Maintenance

+
    +
  • 9999bfd (builder) - builder:replace the special words
  • +
  • cda8b58 (builder) - builder: remove docker keyword from charts
  • +
  • dc575dd (builder) - builder: use imagebuilder replace dockerbuilder
  • +
  • d3bb183 (builder) - docker: use the full name of registry
  • +
  • 5fe34d1 (builder) - travis: add DEV_REGISTRY
  • +
  • 7e36453 (builder) - CICD: use drone
  • +
  • 52b8d9d (builder) - drone: add image_registries volumes
  • +
  • 65963f4 (builder) - k8s: add privileged to dind
  • +
  • d345fcf (builder) - LICENSE: revert modifications to Apache license
  • +
  • 7975c99 (builder) - drone: always pull image
  • +
  • 59633dd (builder) - builder: modify launch imagebuild pod
  • +
  • 8d14e67 (builder) - builder: use Procfile in anywhere
  • +
  • 5357fa8 (builder) - go: bump go mod
  • +
  • 8d26ac0 (builder) - k8s: k8s deprecated api migration
  • +
  • 0af620d (builder) - chars: change org to imageTag
  • +
  • ae84303 (builder) - builder: run imagebuider replace pod with job
  • +
  • 3b2c496 (builder) - builder: change docs website
  • +
  • 5679a4c (builder) - builder: upgrade to golang1.17
  • +
  • a214503 (controller) - controller:replace whitelist with allowlist
  • +
  • 375ddcc (controller) - ps:drycc ps:list show autoscale num
  • +
  • c32e409 (controller) - ldap: canot register when ldap is enabled
  • +
  • c46580a (controller) - controller:modify redis config
  • +
  • fa9e87b (controller) - chart:modify controller charts
  • +
  • 6f9fd08 (controller) - nsq: remove nsq
  • +
  • 994b2dc (controller) - docker-buildx: add check-docker
  • +
  • a720c3a (controller) - controller: remove docker keyword from charts
  • +
  • e9a5c84 (controller) - docker: use the full name of registry
  • +
  • a26614a (controller) - controller: add rabbitmq env
  • +
  • 3df229d (controller) - controller: modify database config && remove redis port config && add env prefix with DRYCC
  • +
  • 257e94b (controller) - controller: CELERY_BROKER use rabbitmq and modify celery-deployment cronjob
  • +
  • f4d6ec3 (controller) - chart: pretty chart format
  • +
  • 63e6195 (controller) - influxdb: modify influxdb code
  • +
  • 0f6d408 (controller) - CICD: use drone
  • +
  • 87bad28 (controller) - python: upgrade to python3.9
  • +
  • e8f7560 (controller) - volumes: modify mount summary
  • +
  • 6cf6c6b (controller) - drone: add image_registries volumes
  • +
  • a9397e8 (controller) - oauth: modify token Authentication
  • +
  • c7f8c8b (controller) - deps: bump django from 2.2.14 to 2.2.18 in /rootfs
  • +
  • a1a08aa (controller) - deps: bump djangorestframework from 3.11.0 to 3.11.2 in /rootfs
  • +
  • efd78b4 (controller) - deps: bump django from 2.2.18 to 2.2.20 in /rootfs
  • +
  • 649b044 (controller) - deps: bump django from 2.2.20 to 2.2.22 in /rootfs
  • +
  • 41b742b (controller) - deps: bump django from 2.2.22 to 2.2.24 in /rootfs
  • +
  • 22ffe5d (controller) - LICENSE: revert modifications to Apache license
  • +
  • c98b468 (controller) - drone: always pull image
  • +
  • 20e6edb (controller) - chart: modify the problem of using buildpack
  • +
  • db16879 (controller) - controller: pretty pods list print
  • +
  • ba6f456 (controller) - test: pretty pods list print
  • +
  • 5fce4b7 (controller) - k8s: k8s deprecated api migration
  • +
  • e9e0bcb (controller) - oauth: using passport authentication
  • +
  • 0311172 (controller) - chars: change org to imageTag
  • +
  • 150eff1 (controller) - charts: update cert-manager api version
  • +
  • de8545a (controller) - controller: update requirements
  • +
  • 1442207 (controller) - controller: using django native JSONFiled
  • +
  • ab4e836 (controller) - oauth: modify passport api
  • +
  • 5c54e06 (controller) - controller: eliminate pip warnings
  • +
  • 870328d (controller) - controller: remove entrypoint
  • +
  • 5e5e6ae (controller) - controller: upgrade celery config
  • +
  • 607778f (controller) - controller: add initContainer
  • +
  • 23dc016 (controller) - chart: set the domain depends certManagerEnabled
  • +
  • f3cf20b (controller) - controller: remove default bash env
  • +
  • 73f2636 (controller) - controller: modify alpinelinux repositories
  • +
  • 498e9f2 (controller) - chart: change certManagerEnabled to boolean type
  • +
  • 27f5308 (controller) - passport: exclude cryptography
  • +
  • 370b75d (controller) - controller: use sh env
  • +
  • 07585b4 (database) - postgres:replace the special words
  • +
  • 20172dc (database) - database: remove docker keyword from charts
  • +
  • abb9b88 (database) - docker: use the full name of registry
  • +
  • e72f58f (database) - chart: modify the off-cluster database
  • +
  • a91f64f (database) - travis: add DEV_REGISTRY
  • +
  • 614fb76 (database) - tests: use add-host replace link
  • +
  • a3428f3 (database) - CICD: use drone
  • +
  • 239fef1 (database) - drone: add image_registries volumes
  • +
  • 42858e1 (database) - LICENSE: revert modifications to Apache license
  • +
  • d0fe850 (database) - drone: always pull image
  • +
  • 34a36ad (database) - charts: Nn secret is generated during off-cluster
  • +
  • 064ccf4 (database) - database: create database
  • +
  • 9228992 (database) - chars: change org to imageTag
  • +
  • 9f7810c (database) - database: upgrade to wal-g v1.1
  • +
  • 05783f4 (fluentd) - fluentd:replace the special words
  • +
  • 0739809 (fluentd) - influxdb:replace monitor-influx with influx
  • +
  • f02487c (fluentd) - fluentd: remove docker keyword from charts
  • +
  • 2c96cc0 (fluentd) - docker: use the full name of registry
  • +
  • b20c429 (fluentd) - charts: remove port config
  • +
  • 6dd0197 (fluentd) - travis: add DEV_REGISTRY
  • +
  • c5bec51 (fluentd) - CICD: use drone
  • +
  • f8524b7 (fluentd) - drone: add image_registries volumes
  • +
  • a50878a (fluentd) - LICENSE: revert modifications to Apache license
  • +
  • 14fe20e (fluentd) - drone: always pull image
  • +
  • 4a2f660 (fluentd) - k8s: k8s deprecated api migration
  • +
  • de2dd91 (fluentd) - chars: change org to imageTag
  • +
  • a9f1944 (fluentd) - fluentd: upgrade to fluentd1.14
  • +
  • 7cb4e95 (influxdb) - influxdb: change username to user
  • +
  • 0fdc21b (influxdb) - influxdb: remove docker keyword from charts
  • +
  • b2acddb (influxdb) - influxdb: change default path
  • +
  • ba88919 (influxdb) - influxdb: add check_env function
  • +
  • 9117401 (influxdb) - influxdb: modify init_influxdb has_bucket
  • +
  • 092a3e6 (influxdb) - chart: pod not readiness
  • +
  • 51de380 (influxdb) - travis: add DEV_REGISTRY
  • +
  • 66d7667 (influxdb) - docker: replace influxdb base image
  • +
  • 3aa3094 (influxdb) - CICD: use drone
  • +
  • 14b9c24 (influxdb) - drone: add image_registries volumes
  • +
  • 02b4cd1 (logger) - logger:replace the special words
  • +
  • 114b5d5 (logger) - reids: delete the logger prefix of redis
  • +
  • 639278a (logger) - redis: remove logger from redis conf
  • +
  • 90195e2 (logger) - go: remove GOOS and GOARCH
  • +
  • 31e2e27 (logger) - logger: remove docker keyword from charts
  • +
  • 8fbd9fa (logger) - docker: use the full name of registry
  • +
  • b39df2d (logger) - charts: remove redis\nsqd port config
  • +
  • 35d6d07 (logger) - travis: add DEV_REGISTRY
  • +
  • 69aabf5 (logger) - tests: remove docker link
  • +
  • e916644 (logger) - CICD: use drone
  • +
  • d6872b7 (logger) - drone: add image_registries volumes
  • +
  • 37801da (logger) - LICENSE: revert modifications to Apache license
  • +
  • cfb4b38 (logger) - drone: always pull image
  • +
  • 8bda3bf (logger) - go: bump go mod
  • +
  • e13ebfc (logger) - chars: change org to imageTag
  • +
  • 38e6d8d (minio) - minio:replace the special words
  • +
  • d6925dd (minio) - minio: remove docker keyword from charts
  • +
  • d56bc39 (minio) - docker: use the full name of registry
  • +
  • e4696cc (minio) - travis: add DEV_REGISTRY
  • +
  • 70c5c79 (minio) - minio: use latest version
  • +
  • 773cf6c (minio) - Makefile: remove DEV_REGISTRY ?=
  • +
  • 5ce5bc6 (minio) - CICD: use drone
  • +
  • 5da8be3 (minio) - drone: add image_registries volumes
  • +
  • c1f0611 (minio) - LICENSE: revert modifications to Apache license
  • +
  • b73f792 (minio) - drone: always pull image
  • +
  • 79d1c93 (minio) - go: bump go mod
  • +
  • c448899 (minio) - chars: change org to imageTag
  • +
  • 15ee49e (minio) - minio: migrate deprecated warning
  • +
  • 9968a1a (minio) - minio: upgrade to golang1.7
  • +
  • 14fedd2 (monitor) - monitor:replace the special works
  • +
  • 52c431a (monitor) - reids: delete the logger prefix of redis
  • +
  • 2c95b47 (monitor) - redis: remove logger from redis conf
  • +
  • da9bc56 (monitor) - monitor:remove influxdb
  • +
  • 53f47b9 (monitor) - grafana: use grafana docker image
  • +
  • 5bdb188 (monitor) - grafana: use grafana docker image
  • +
  • c0586dd (monitor) - monitor: remove docker keyword from charts
  • +
  • 87d02b6 (monitor) - charts: add nodes and persistentvolumes rule
  • +
  • 1b5598f (monitor) - monitor: modify grafana dashboard with FLUX and pretty config.toml
  • +
  • bcbc0d5 (monitor) - docker: use the full name of registry
  • +
  • 9418c9e (monitor) - monitor: fix upload dashboard error and modify INFLUXDB input
  • +
  • 589f29a (monitor) - travis: add DEV_REGISTRY
  • +
  • f776f8a (monitor) - CICD: use drone
  • +
  • 6ca3060 (monitor) - drone: add image_registries volumes
  • +
  • 6a9ffb2 (monitor) - LICENSE: revert modifications to Apache license
  • +
  • 45e41ed (monitor) - drone: always pull image
  • +
  • 654d407 (monitor) - k8s: k8s deprecated api migration
  • +
  • 41e9b9c (monitor) - chars: change org to imageTag
  • +
  • 99c10d3 (monitor) - charts: update cert-manager api version
  • +
  • 9bf83c4 (monitor) - oauth: user oauth passport
  • +
  • a128f6d (monitor) - chart: change certManagerEnabled to boolean type
  • +
  • 8f897fe (monitor) - chart: set the domain depends certManagerEnabled
  • +
  • ba6d793 (nsqd) - README:update travis build status
  • +
  • 49879c4 (nsqd) - nsqd: minimum git clone code
  • +
  • c5e2680 (nsqd) - nsqd: remove docker keyword from charts
  • +
  • 21dd17b (nsqd) - docker: use the full name of registry
  • +
  • 7d86b3c (nsqd) - charts: remove port config
  • +
  • c073d95 (nsqd) - travis: add DEV_REGISTRY
  • +
  • 55c297c (nsqd) - CICD: use drone
  • +
  • 165c2ae (nsqd) - drone: add image_registries volumes
  • +
  • 9c6a1f8 (nsqd) - LICENSE: revert modifications to Apache license
  • +
  • 9283098 (nsqd) - drone: always pull image
  • +
  • 46acf8a (nsqd) - k8s: k8s deprecated api migration
  • +
  • 43caf80 (nsqd) - chars: change org to imageTag
  • +
  • 6897471 (nsqd) - nsqd: use official image
  • +
  • 297bc05 (redis) - redis:replace the special words
  • +
  • f5f8b5e (redis) - reids: delete the logger prefix of redis
  • +
  • af7b657 (redis) - redis: change logger-redis to redis
  • +
  • 8dca154 (redis) - redis: remove logger from redis conf
  • +
  • eaeda2d (redis) - redis: remove docker keyword from charts
  • +
  • 53c6358 (redis) - docker: use the full name of registry
  • +
  • ae37416 (redis) - charts: remove port config
  • +
  • e985656 (redis) - travis: add DEV_REGISTRY
  • +
  • 423336a (redis) - CICD: use drone
  • +
  • be64ab4 (redis) - drone: add image_registries volumes
  • +
  • 3bec735 (redis) - LICENSE: revert modifications to Apache license
  • +
  • 4f934f6 (redis) - drone: always pull image
  • +
  • 359b878 (redis) - chars: change org to imageTag
  • +
  • 83b8ac2 (registry) - workflow:replace the special words
  • +
  • 869b280 (registry) - registry: remove docker keyword from charts
  • +
  • 999c1e9 (registry) - docker: use the full name of registry
  • +
  • 5652da9 (registry) - travis: add DEV_REGISTRY
  • +
  • cc8c6c2 (registry) - CICD: use drone
  • +
  • c7bdbd0 (registry) - CICD: pretty .drone.yaml format
  • +
  • 5c55a38 (registry) - test: use add-host replace link
  • +
  • f8866f3 (registry) - drone: add image_registries volumes
  • +
  • 6c8292f (registry) - LICENSE: revert modifications to Apache license
  • +
  • 1d50f2c (registry) - drone: always pull image
  • +
  • efbca6d (registry) - chars: change org to imageTag
  • +
  • 2eafc59 (registry-proxy) - registry-proxy: update nginx
  • +
  • 071bd86 (registry-proxy) - charts: upgrade k8s newer API versions
  • +
  • c72db96 (registry-proxy) - registry-proxy: change travis icon url
  • +
  • 63ffb92 (registry-proxy) - registry-proxy:replace the special works
  • +
  • 1d904a6 (registry-proxy) - registry-proxy: remove docker keyword from charts
  • +
  • c8200b1 (registry-proxy) - docker: use the full name of registry
  • +
  • d3fa939 (registry-proxy) - travis: add DEV_REGISTRY
  • +
  • 5a8b353 (registry-proxy) - CICD: use drone
  • +
  • 703d05a (registry-proxy) - drone: add image_registries volumes
  • +
  • aa71db1 (registry-proxy) - LICENSE: revert modifications to Apache license
  • +
  • 710c126 (registry-proxy) - drone: always pull image
  • +
  • 2dcc5e6 (registry-proxy) - chars: change org to imageTag
  • +
+ + + +
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/blog/2022/10/21/drycc-workflow-v1.6.0/index.html b/blog/2022/10/21/drycc-workflow-v1.6.0/index.html new file mode 100644 index 000000000..496745150 --- /dev/null +++ b/blog/2022/10/21/drycc-workflow-v1.6.0/index.html @@ -0,0 +1,733 @@ + + + + + + + + + + + + + + + + + + + +Drycc Workflow v1.6.0 | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + +
+

Drycc Workflow v1.6.0

+
New Drycc Workflow Release v1.6.0
+ + +

These release notes for Drycc Workflow v1.6.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.5.0, please refer to the following change summary.

+

Workflow ## v1.5.0 -> v1.6.0

+

Releases

+
    +
  • builder v1.3.0 -> v1.4.0
  • +
  • controller v1.4.0 -> v1.5.0
  • +
  • passport v1.0.0 -> v1.1.0
  • +
  • database v1.1.0 -> v1.2.0
  • +
  • imagebuilder v1.0.1 -> v1.1.0
  • +
  • fluentd v1.2.0 -> v1.3.0
  • +
  • logger v1.2.0 -> v1.3.0
  • +
  • storage v1.2.0 -> v1.3.0
  • +
  • monitor v1.2.0 -> v1.3.0
  • +
  • redis v1.2.0 -> v1.3.0
  • +
  • influxdb v1.1.0 -> v1.2.0
  • +
  • rabbitmq v1.0.0 -> v1.1.0
  • +
  • registry v1.1.0 -> v1.2.0
  • +
  • registry-proxy v1.1.0 -> v1.2.0
  • +
+

Features

+
    +
  • 52517d9 (builder) - builder: update controller-sdk-go
  • +
  • 1d78ca0 (builder) - builder: add affinity
  • +
  • 26b6980 (builder) - builder: switch charts to oci
  • +
  • bfd4385 (controller) - controller: add get manager user status
  • +
  • 874208d (controller) - controller: unified measurement model
  • +
  • cadf98f (controller) - controller: add admission webhook
  • +
  • e0050c2 (controller) - controller: new measurement model
  • +
  • a11ba58 (controller) - controller: multi pod restart uses async
  • +
  • fb3c15d (controller) - controller: add check app owner status
  • +
  • 3d78b76 (controller) - controller: add resource services api
  • +
  • 3d6a201 (controller) - controller: add search apps api
  • +
  • 01c443a (controller) - controller: add KUBERNETES_CPU_MEMORY_RATIO parameter
  • +
  • 7c26232 (controller) - controller: add volume size limit
  • +
  • 3bee749 (controller) - controller: add annotations support
  • +
  • 23cd97c (controller) - controller: traefik v2 support
  • +
  • e37b7db (controller) - controller: add affinity
  • +
  • b3b367b (controller) - controller: add volume expand support
  • +
  • a4e154a (controller) - controller: add database replica support
  • +
  • 2f37216 (controller) - controller: switch wsgi to asgi
  • +
  • b3314a5 (controller) - controller: add pod exec api
  • +
  • 75df2dc (controller) - controller: add stream support for app logs
  • +
  • 4229bad (controller) - ccontroller: switch charts to oci
  • +
  • 89bb19b (database) - database: upgrade to pg14
  • +
  • 9f45a5d (database) - database: add hugepages support
  • +
  • c4008c9 (database) - database: add affinity
  • +
  • 411a7b2 (database) - postgres: use patroni
  • +
  • 64e5cb0 (database) - database: switch charts to oci
  • +
  • 2bab823 (fluentd) - fluentd: switch charts to oci
  • +
  • 337ba62 (imagebuilder) - imagebuilder: run podman as rootless
  • +
  • 4396ffa (imagebuilder) - imagebuilder: switch to oci charts
  • +
  • f37ae09 (influxdb) - influxdb: add affinity
  • +
  • 04503b2 (influxdb) - influxdb: add influxdb ha
  • +
  • 41ddad5 (influxdb) - influxdb: switch charts to oci
  • +
  • 2006480 (logger) - logger: use redis stream replace nsqd
  • +
  • ab23d17 (logger) - logger: add affinity
  • +
  • 81d4e9d (logger) - logger: switch charts to oci
  • +
  • c3d9796 (monitor) - monitor: add affinity
  • +
  • cd9de3c (monitor) - monitor: switch to oci charts
  • +
  • 318a73f (passport) - passport: add change user confirm
  • +
  • 79ef100 (passport) - passport: add re login at authorize
  • +
  • 6927bb5 (passport) - passport: add affinity
  • +
  • 3146a09 (passport) - passport: add google reCAPTCHA
  • +
  • 802abcd (passport) - passport: add replica database support
  • +
  • a0dcd1b (passport) - passport: switch wsgi to asgi
  • +
  • 4c9dbba (passport) - passport: switch charts to oci
  • +
  • 74825f7 (rabbitmq) - rabbitmq: add rabbitmq managentment ingress
  • +
  • 12cf7d6 (rabbitmq) - rabbitmq: add affinity
  • +
  • 103417d (rabbitmq) - rabbitmq: switch charts to oci
  • +
  • 5d428bb (redis) - redis: add affinity
  • +
  • a88c1a9 (redis) - redis: switch charts to oci
  • +
  • 541585d (registry) - registry: add affinity
  • +
  • e9ca9d4 (registry) - registry: add garbage-collect cronjob
  • +
  • ec62a59 (registry) - registry: switch charts to oci
  • +
  • fde0b07 (registry-proxy) - registry-proxy: switch charts to oci
  • +
  • be14eb4 (storage) - minio: add affinity
  • +
  • 51af696 (storage) - storage: add k8s csi support
  • +
  • 76a75d9 (storage) - storage: add cluster health checker
  • +
  • a17dc8c (storage) - storage: switch charts to oci
  • +
+

Fixes

+
    +
  • e4f44fb (builder) - builder: no error return
  • +
  • e38dfc7 (builder) - builderControllerHost/ControllerPort init error
  • +
  • ff9069f (controller) - controller: influxdb query error
  • +
  • f7f5069 (controller) - controller: authentication 500
  • +
  • 7e297a8 (controller) - controller: add check remote user status
  • +
  • 9db28e1 (controller) - controller: celery MaxRetriesExceededError
  • +
  • 4bcff08 (controller) - controller: wrong name
  • +
  • d69fde2 (controller) - controller: traefik ingress create error
  • +
  • a3ad743 (controller) - fixup(controller: user login error
  • +
  • 662c8dd (controller) - controller: change influxdb port
  • +
  • 957bdf6 (controller) - controller: validate rsa key pairing before storage
  • +
  • 419ec4c (controller) - controller: kubernetes pod/exec cluster role
  • +
  • a67edaa (controller) - controller: Cannot routing:disable
  • +
  • e09e214 (controller) - controller: allowlist cannot remove
  • +
  • 318b126 (controller) - controller: domains update error
  • +
  • 92855eb (database) - database: premission denied
  • +
  • bde945a (database) - fixup(postgres: support arm, fix Failed to build psutil
  • +
  • 7854d45 (database) - fixup(postgres: user name converted to lowercase letters
  • +
  • 57b2a07 (fluentd) - fluentd: ifconfig_path not found
  • +
  • 20e72b9 (imagebuilder) - imagebuilder: upgrade pack version
  • +
  • 651db8a (imagebuilder) - imagebuilder: chown uid gid order
  • +
  • d2e9164 (influxdb) - influxdb: proxy not running
  • +
  • 3a1d361 (monitor) - monitor: charts naming
  • +
  • d754ae0 (monitor) - monitor: telegraf init error
  • +
  • 63f9e34 (monitor) - monitor: affinity error
  • +
  • 95ae1e5 (passport) - passport: yarn build fail
  • +
  • 3f5365e (passport) - passport: wrong name
  • +
  • 907f17b (passport) - passport: change uid gid to 1001
  • +
  • e3911e0 (passport) - passport: ‘registration_done’ not found
  • +
  • 2ace5f0 (passport) - passport: ui style
  • +
  • b3ba1e1 (passport) - passport privacy policy link
  • +
  • 172e9c8 (passport) - passport: check databaseReplicaUrl error
  • +
  • a3aeb70 (rabbitmq) - passport: change uid gid to 1001
  • +
  • 5c73dcf (redis) - reids: DRYCC_REGISTY misspelling
  • +
  • d7e3baf (redis) - redis: env miss
  • +
  • cadaa91 (registry) - registry: set gid uid to 1001
  • +
  • d524217 (registry) - registry: storage run error
  • +
  • 854f912 (registry) - registry: chown uid gid order
  • +
  • e642bb7 (registry-proxy) - registry-proxy: containerPort error
  • +
  • 8dfd029 (registry-proxy) - registry-proxy: chown uid gid order
  • +
  • bbea364 (storage) - minio: premission denied
  • +
  • 97deba1 (storage) - storage: node unimplemented error
  • +
  • b9bdeff (storage) - storage: pd can not connect each other
  • +
+

Style

+
    +
  • 1edb10c (controller) - controller: database convention over configuration
  • +
  • 1960cc3 (database) - database: database name convention over configuration
  • +
  • 06d1f5d (imagebuilder) - imagebuilder: URL to Url
  • +
  • b8a8941 (passport) - passport: database convention over configuration
  • +
+

Maintenance

+
    +
  • 8e9a199 (builder) - builder: upgrade controller-sdk-go
  • +
  • 4840151 (builder) - builder: use exec runner replace docker runner
  • +
  • 68ccfb1 (builder) - builder: canonical charts naming
  • +
  • 8f971cb (builder) - builder: provide any additional service annotations
  • +
  • fe2c55d (builder) - dockerfile: use drycc/base image
  • +
  • 2b5e706 (builder) - dockerfile: change user and workdir
  • +
  • 7a6c8d3 (builder) - builder: set gid uid to 1001
  • +
  • fe494f7 (builder) - dockerfile: use uid gid
  • +
  • a7c8752 (builder) - builder: change nodes to pod affinity
  • +
  • eb2e94c (builder) - database: bump mc 2022.04.01.23.44.48
  • +
  • cfaae66 (builder) - builder: use registry.drycc.cc replace docker.io
  • +
  • d7d2890 (builder) - builder: change default imagebuilder registry
  • +
  • ecfdb19 (builder) - imagebuilder: change python-dev registry
  • +
  • 6da17f4 (builder) - builder: https://github.com/minio/minio/issues/14331
  • +
  • 1a57e5b (builder) - builder: https://github.com/minio/minio/issues/14331
  • +
  • f1464fa (builder) - builder: https://github.com/minio/minio/issues/13799
  • +
  • b1e1c4f (builder) - builder: use env replace creds volume
  • +
  • 71a4145 (builder) - builder: bump go.mod
  • +
  • 3567688 (builder) - builder: fine management affinity
  • +
  • 73ea38b (builder) - builder: change storage to minio
  • +
  • 1f91321 (builder) - builder: use testify replace assert
  • +
  • d148b9c (builder) - builder: add check storage health
  • +
  • b768101 (builder) - builder: change initContainers
  • +
  • 1b3bec3 (builder) - builder: add replicas
  • +
  • 5cb0d61 (builder) - builder: upgrade to latest controller-sdk-go
  • +
  • 98b9d58 (builder) - builder: upgrade new require
  • +
  • 65817c3 (builder) - builder: change drycc.cc to www.drycc.cc
  • +
  • 4e3f9d0 (controller) - controller: add celery retry mechanism
  • +
  • f6716fe (controller) - controller: change cronjob name
  • +
  • eb60693 (controller) - controller: refine celery task priority
  • +
  • 66905e9 (controller) - controller: change manager auth
  • +
  • ea20c41 (controller) - controller: remove start/stop api
  • +
  • 4c8fc80 (controller) - controller: improve tasks error handling
  • +
  • cf7402e (controller) - controller: add blocklist api
  • +
  • 80f14dd (controller) - controller: use get_user_model replace auth.User
  • +
  • ffc7bb7 (controller) - controller: use JSONField replace ArrayField
  • +
  • 370df8c (controller) - controller: add validate metric
  • +
  • 29084ce (controller) - controller: use user id request manager api
  • +
  • 718fe12 (controller) - controller change urlpatterns order
  • +
  • 71f4042 (controller) - controller: measurements uses lowercase letters
  • +
  • e5123ea (controller) - controller: change resource unit to number
  • +
  • 18fee9a (controller) - deps: bump celery from 5.1.2 to 5.2.2 in /rootfs
  • +
  • ffca6c1 (controller) - controller: use exec runner replace docker runner
  • +
  • 9ec12e1 (controller) - controller: simplify drone configuration
  • +
  • 4b4749e (controller) - controller: set default CSRF_COOKIE_SECURE false
  • +
  • 2ef6338 (controller) - deps: bump django from 3.2.5 to 3.2.10 in /rootfs
  • +
  • c7570d0 (controller) - deps: bump django from 3.2.10 to 3.2.11 in /rootfs
  • +
  • 8b17bc1 (controller) - controller: canonical charts naming
  • +
  • c928fb0 (controller) - controller: use rabbitmq cluster
  • +
  • f917185 (controller) - controller: provide any additional service annotations
  • +
  • 22a8f63 (controller) - deps: bump django from 3.2.11 to 3.2.12 in /rootfs
  • +
  • 3cc3b00 (controller) - dockerfile: use drycc/base image
  • +
  • ee274f6 (controller) - controller: set venv profile
  • +
  • ce6b069 (controller) - controller: set gid uid to 1001
  • +
  • 3a105d3 (controller) - dockerfile: use uid gid
  • +
  • 15f9b0e (controller) - controller: code review
  • +
  • 01e6fd9 (controller) - controller: use passport user id
  • +
  • 893ee31 (controller) - oauth2: update user info pipline
  • +
  • 3028fb4 (controller) - user: set AnonymousUser username
  • +
  • 5daf82d (controller) - controller: set worker_cancel_long_running_tasks_on_connection_loss
  • +
  • 61f2c53 (controller) - controller: change nodes to pod affinity
  • +
  • 88feb1d (controller) - imagebuilder: python=3.10.4 rabbitmq=3.9.14
  • +
  • 914e03f (controller) - controller: use registry.drycc.cc replace docker.io
  • +
  • a5bb548 (controller) - controller: change python-dev registry
  • +
  • 3ecdd7c (controller) - controller: add a separate rabbitmqUrl configuration
  • +
  • 967cb11 (controller) - controller: remove APP_STORAGE
  • +
  • 473d2b5 (controller) - controller: use env replace creds volume
  • +
  • e410d4c (controller) - deps: bump django from 3.2.12 to 3.2.13 in /rootfs
  • +
  • c6ef777 (controller) - controller: simplified passport config
  • +
  • 0fd3233 (controller) - controller: remove settings hardcode
  • +
  • a64e99c (controller) - controller: change passport config
  • +
  • 62aba25 (controller) - controller: set cronjob timezone to utc
  • +
  • 760b70b (controller) - controller: change default ratio
  • +
  • 8dffc3a (controller) - controller: fine management affinity
  • +
  • 26043c4 (controller) - controller: change default app storage
  • +
  • 608bd8d (controller) - deps: bump django from 3.2.13 to 3.2.14 in /rootfs
  • +
  • 18ed0c2 (controller) - controller: remove conjob affinity
  • +
  • add6712 (controller) - controller: add volume expand support use patch
  • +
  • cc1ad13 (controller) - controller: add startupProbe
  • +
  • 0e9a603 (controller) - controller: add clearsocial cronjob
  • +
  • eb6f05d (controller) - controller: change initContainers
  • +
  • 762c676 (controller) - controller: change replicas
  • +
  • abd7e8c (controller) - deps: bump django from 3.2.14 to 3.2.15 in /rootfs
  • +
  • 07fdf1b (controller) - controller: remove database conn_max_age
  • +
  • ef8e41f (controller) - controller: add database replica check
  • +
  • 79143f2 (controller) - controller: upgrade new require
  • +
  • a624048 (controller) - controller: add app.refresh func annotation
  • +
  • b22d367 (controller) - controller: optimize app refresh timing
  • +
  • fe98f0c (database) - database: use exec runner replace docker runner
  • +
  • 5e00c11 (database) - database: canonical charts naming
  • +
  • d2cb860 (database) - database: disable huge_pages
  • +
  • 197d80d (database) - database: add persistence
  • +
  • 1c3e645 (database) - database: provide any additional service annotations
  • +
  • 37730ab (database) - dockerfile: use drycc/base image
  • +
  • 5014112 (database) - dockerfile: change entrypoint
  • +
  • 29b538e (database) - database: change nodes to pod affinity
  • +
  • c2bb074 (database) - database: bump python 3.10.4 and mc 2022.04.01.23.44.48
  • +
  • 077a4e9 (database) - database: use registry.drycc.cc replace docker.io
  • +
  • 560bdb9 (database) - database: change python-dev registry
  • +
  • 1e54b55 (database) - database: https://github.com/minio/minio/issues/14331
  • +
  • d646672 (database) - database: https://github.com/minio/minio/issues/13799
  • +
  • a6ac4e3 (database) - database: use env replace creds volume
  • +
  • 9618d87 (database) - database: fine management affinity
  • +
  • b823273 (database) - database: change minio to storage
  • +
  • 7bd5a90 (database) - database: add check storage health
  • +
  • 20c6d96 (database) - database: fix storage run error
  • +
  • 8bde830 (database) - database: upgrade to pg 14.5
  • +
  • a33b5e5 (fluentd) - fluentd: update plugins
  • +
  • eed7a78 (fluentd) - fluentd: update filter kubernetes setting
  • +
  • cc83dd8 (fluentd) - fluentd: update elasticsearch store setting and support exclude specific container logs
  • +
  • ba2feb2 (fluentd) - fluentd: use exec runner replace docker runner
  • +
  • d528676 (fluentd) - fluentd: simplify drone configuration
  • +
  • dece82d (fluentd) - fluentd: canonical charts naming
  • +
  • 4e0a802 (fluentd) - fluend: replace nsqd with redis
  • +
  • 15ceca0 (fluentd) - dockerfile: use drycc/base image
  • +
  • a7f619f (fluentd) - dockerfile: change workdir
  • +
  • 9adf5ed (fluentd) - database: bump fluentd 1.14.6
  • +
  • 50c14c2 (fluentd) - fluentd: use registry.drycc.cc replace docker.io
  • +
  • 83171b1 (fluentd) - fluentd: change python-dev registry
  • +
  • ec83581 (fluentd) - fluentd: unified reids declaration
  • +
  • 07c63e2 (fluentd) - fluentd: upgrade fluentd 1.15.2
  • +
  • 65df9be (imagebuilder) - imagebuilder: update pack version
  • +
  • 66cab35 (imagebuilder) - imagebuilder: use dind replace go-dev
  • +
  • 0c82060 (imagebuilder) - imagebuilder: use exec runner replace docker runner
  • +
  • 8146da9 (imagebuilder) - imagebuilder: canonical charts naming
  • +
  • 7d97241 (imagebuilder) - dockerfile: use drycc/base image
  • +
  • 07e805c (imagebuilder) - imagebuilder: change default buildpack
  • +
  • 8d1038d (imagebuilder) - imagebuilder: upgrade podman to 4.0.1
  • +
  • 62d3687 (imagebuilder) - imagebuilder: change workdir to /workspace
  • +
  • da8bfb0 (imagebuilder) - imagebuilder: change uid gid to 1001
  • +
  • d44e3bc (imagebuilder) - imagebuilder: upgrade stack
  • +
  • 5b0c7e6 (imagebuilder) - imagebuilder: use registry.drycc.cc replace docker.io
  • +
  • f74cbf6 (imagebuilder) - imagebuilder: add defaultBuildpacksURL
  • +
  • 941d493 (imagebuilder) - imagebuilder: https://github.com/minio/minio/issues/14331
  • +
  • 449be91 (imagebuilder) - imagebuilder: https://github.com/minio/minio/issues/13799
  • +
  • 63b0523 (imagebuilder) - imagebuilder: use env replace creds volume
  • +
  • 4e8a6e5 (imagebuilder) - imagebuilder: add imagebuilder config
  • +
  • 2d891f5 (imagebuilder) - imagebuilder: change minio to storage
  • +
  • addceda (imagebuilder) - imagebuilder: upgrade new require
  • +
  • a6e569f (imagebuilder) - imagebuilder: pack_build add –env-file parameter
  • +
  • 6191ff5 (influxdb) - influxdb: use exec runner replace docker runner
  • +
  • dc3f8c7 (influxdb) - influxdb: canonical charts naming
  • +
  • 6b5c819 (influxdb) - influxdb: new ingress style
  • +
  • 68b381d (influxdb) - influxdb: provide any additional service annotations
  • +
  • ea20eb8 (influxdb) - dockerfile: use drycc/base image
  • +
  • 64c0a71 (influxdb) - influxdb: set gid uid to 1001
  • +
  • a709ca1 (influxdb) - influxdb: use DRYCC_UID DRYCC_GID env
  • +
  • 740dff0 (influxdb) - influxdb: use common affinity template
  • +
  • e035673 (influxdb) - influxdb: change nodes to pod affinity
  • +
  • f1cefbd (influxdb) - influxdb: use registry.drycc.cc replace docker.io
  • +
  • a00100e (influxdb) - influxdb: fine management affinity
  • +
  • 9d165ef (influxdb) - influxdb: add probe
  • +
  • bee7fff (influxdb) - influxdb: upgrade to influxdb 2.4.0
  • +
  • 254914c (logger) - logger: use exec runner replace docker runner
  • +
  • 8d91c68 (logger) - logger: canonical charts naming
  • +
  • b6d2182 (logger) - logger: provide any additional service annotations
  • +
  • c35e59a (logger) - dockerfile: use drycc/base image
  • +
  • a63c070 (logger) - logger: change workdir to /workspace
  • +
  • a594b28 (logger) - logger: set gid uid to 1001
  • +
  • 9a90e22 (logger) - dockerfile: use uid gid
  • +
  • 36493b4 (logger) - logger: use common affinity template
  • +
  • 897a3a5 (logger) - logger: change nodes to pod affinity
  • +
  • 03b32ab (logger) - logger: use registry.drycc.cc replace docker.io
  • +
  • a50ba5f (logger) - logger: change python-dev registry
  • +
  • 23187a3 (logger) - logger: unified reids declaration
  • +
  • aaa129a (logger) - logger: fine management affinity
  • +
  • be4f656 (logger) - logger: add replicas
  • +
  • 7c25459 (logger) - charts: add NetworkPolicy
  • +
  • 6810149 (logger) - logger: remove memory storage
  • +
  • a918c50 (logger) - logger: add .vscode to .gitignore
  • +
  • a415210 (logger) - logger: add log follow support
  • +
  • 59b1da3 (logger) - logger: upgrade new require
  • +
  • 27cc151 (monitor) - monitor: use exec runner replace docker runner
  • +
  • 07d6a9d (monitor) - monitor: canonical charts naming
  • +
  • 1054357 (monitor) - monitor: use redis default port
  • +
  • e3673df (monitor) - monitor: remove nsqd
  • +
  • fc9dd3e (monitor) - monitor: new ingress style
  • +
  • 856a898 (monitor) - monitor: add default user env
  • +
  • 9857535 (monitor) - monitor: add random user
  • +
  • 38b5a04 (monitor) - grafana: oauth auto login
  • +
  • 5dfc579 (monitor) - monitor: upgrade version
  • +
  • e121b5a (monitor) - monitor: provide any additional service annotations
  • +
  • 84462a0 (monitor) - dockerfile: use drycc/base image
  • +
  • b9e8ce8 (monitor) - monitor: chore(imagebuilder): change uid gid to 1001
  • +
  • 05ee8ab (monitor) - dockerfile: use uid gid
  • +
  • e1fa68e (monitor) - monitor: use common affinity template
  • +
  • b8f302b (monitor) - monitor: change nodes to pod affinity
  • +
  • 4fc991f (monitor) - database: bump telegraf 1.22.0 and grafana 8.4.5
  • +
  • 21a2f6a (monitor) - monitor: use registry.drycc.cc replace docker.io
  • +
  • acc976f (monitor) - monitor: change python-dev registry
  • +
  • 62d76c1 (monitor) - monitor: unified reids declaration
  • +
  • b3c57ad (monitor) - monitor: optimize oauth2 configuration
  • +
  • 70af6b0 (monitor) - monitor: change passport config
  • +
  • 69f9a88 (monitor) - monitor: fine management affinity
  • +
  • 2fb278f (monitor) - monitor: rename influxdb port
  • +
  • 17548ff (monitor) - grafana: update dashborad
  • +
  • 69d7bbd (monitor) - grafana: influx dashborad disk size
  • +
  • 75db1b0 (monitor) - monitor: upgrade new grafana/telegraf
  • +
  • 80504a1 (monitor) - grafana: update influx and redis dashboard
  • +
  • f7078cb (monitor) - monitor:chown use env
  • +
  • 91ae0dd (passport) - passport: optimize login display
  • +
  • 2d3bbbc (passport) - passport: change drycc logo
  • +
  • 59790a7 (passport) - passport: make user email unique
  • +
  • faea034 (passport) - passport: use strtobool
  • +
  • 1fbf2bc (passport) - passport: use yarn replace npm
  • +
  • 119cac8 (passport) - passport: use exec runner replace docker runner
  • +
  • cff5062 (passport) - passport: set default CSRF_COOKIE_SECURE false
  • +
  • 9cc0210 (passport) - passport: canonical charts naming
  • +
  • 9ab3896 (passport) - passport: new ingress style
  • +
  • 259ccc9 (passport) - passport: provide any additional service annotations
  • +
  • af1bbcd (passport) - dockerfile: use drycc/base image
  • +
  • 9ae5373 (passport) - passport: set venv profile
  • +
  • 8f61090 (passport) - dockerfile: use uid gid
  • +
  • fcaf72d (passport) - passport: upgrade npm package
  • +
  • 546dcd5 (passport) - passport: add license
  • +
  • 4bda2d6 (passport) - passport: use minify
  • +
  • 73b0fd1 (passport) - passport: use common affinity template
  • +
  • 278fe7a (passport) - passport: change nodes to pod affinity
  • +
  • 3cd93d3 (passport) - passport: add reactive
  • +
  • 370b493 (passport) - passport: add footer
  • +
  • 483cbd6 (passport) - passport: use h_captcha replace re_captcha
  • +
  • 3d1675e (passport) - database: bump python 3.10.4 and node 16.14.2
  • +
  • 86a7835 (passport) - passport: use registry.drycc.cc replace docker.io
  • +
  • 2d65355 (passport) - passport: change python-dev registry
  • +
  • 90c1444 (passport) - passport: unified reids declaration
  • +
  • 2e0e417 (passport) - passport: fix firefox footer
  • +
  • ad274be (passport) - passport: use bulecss
  • +
  • f986d8b (passport) - passport: add main footer
  • +
  • 3e52867 (passport) - passport: dynamic settings for vue
  • +
  • 38adabc (passport) - passport: change passport config
  • +
  • f8d6b60 (passport) - passport: fine management affinity
  • +
  • 2cbd79d (passport) - passport: remove database conn_max_age
  • +
  • 7122797 (passport) - passport: change drycc.cc to www.drycc.cc
  • +
  • 8cc84cd (rabbitmq) - rabbitmq: use exec runner replace docker runner
  • +
  • f35930f (rabbitmq) - rabbitmq: add rabbitmq cluster support
  • +
  • fbfa3ba (rabbitmq) - rabbitmq: canonical charts naming
  • +
  • ca60701 (rabbitmq) - rabbitmq: use volumeClaimTemplates
  • +
  • fe5d1b4 (rabbitmq) - rabbitmq: add sharding support
  • +
  • 9c4ab97 (rabbitmq) - rabbitmq: provide any additional service annotations
  • +
  • 348a88a (rabbitmq) - dockerfile: use drycc/base image
  • +
  • 2388be1 (rabbitmq) - rabbitmq: upgrade erlang to 24.2.2
  • +
  • db2eaa5 (rabbitmq) - dockerfile: use uid gid
  • +
  • 772afd1 (rabbitmq) - rabbitmq: change to wait pid file
  • +
  • 2bfc25e (rabbitmq) - rabbitmq: use common affinity template
  • +
  • 11d505e (rabbitmq) - rabbitmq: change nodes to pod affinity
  • +
  • 69d63f1 (rabbitmq) - database: bump erlang 24.3.3 and rabbitmq 3.9.14
  • +
  • 8380299 (rabbitmq) - rabbitmq: use registry.drycc.cc replace docker.io
  • +
  • b3f69f1 (rabbitmq) - rabbitmq: add check rabbitmqLocaltion
  • +
  • 5327c76 (rabbitmq) - rabbitmq: fine management affinity
  • +
  • 5c66b5a (rabbitmq) - rabbitmq: change probe
  • +
  • 27bebf9 (rabbitmq) - rabbitmq: add start-rabbitmq script
  • +
  • 86ee6a7 (rabbitmq) - rabbitmq: upgrade to rabbitmq 3.10.7
  • +
  • 1f29683 (redis) - redis: use exec runner replace docker runner
  • +
  • a5041fc (redis) - redis: canonical charts naming
  • +
  • 64468c2 (redis) - redis: add redis persistence
  • +
  • de5d753 (redis) - redis: provide any additional service annotations
  • +
  • f644639 (redis) - dockerfile: use drycc/base image
  • +
  • 98051d2 (redis) - redis: premission denied
  • +
  • bcb548e (redis) - dockerfile: use uid gid
  • +
  • 524aa41 (redis) - redis: use common affinity template
  • +
  • 26c9466 (redis) - redis: change nodes to pod affinity
  • +
  • b67d7a2 (redis) - redis: use registry.drycc.cc replace docker.io
  • +
  • 839ec50 (redis) - redis: use env replace creds volume
  • +
  • 237ca86 (redis) - redis: fine management affinity
  • +
  • bdd968d (redis) - redis: upgrade neew require
  • +
  • 8b2910f (registry) - registry: use exec runner replace docker runner
  • +
  • eedbe78 (registry) - registry: canonical charts naming
  • +
  • 0241615 (registry) - registry: provide any additional service annotations
  • +
  • 9b58da4 (registry) - dockerfile: use drycc/base image
  • +
  • ab6acb7 (registry) - registry: change workdir to /workspace
  • +
  • f368bf7 (registry) - registry: use DRYCC_UID DRYCC_GID env
  • +
  • f4b9041 (registry) - registry: use common affinity template
  • +
  • c2e87ca (registry) - registry: change nodes to pod affinity
  • +
  • feb6aba (registry) - database: bump mc 2022.04.01.23.44.48
  • +
  • 956932b (registry) - rregistry: use registry.drycc.cc replace docker.io
  • +
  • deda8d8 (registry) - registry: move registry-secret.yaml from workflow to registry
  • +
  • f52c7bf (registry) - registry: change python-dev registry
  • +
  • 007fe03 (registry) - registry: https://github.com/minio/minio/issues/14331
  • +
  • d620c6d (registry) - registry: https://github.com/minio/minio/issues/13799
  • +
  • 85e6b73 (registry) - registry: use env replace creds volume
  • +
  • 6a1155d (registry) - registry: fine management affinity
  • +
  • 7b8ebae (registry) - registry: change minio to storage
  • +
  • 1338951 (registry) - registry: add check storage health
  • +
  • 2fa769d (registry) - registry: change probe
  • +
  • f187cbf (registry) - registry: add replicas
  • +
  • 09d8a7b (registry) - registry: upgrade to mc 2022.08.28.20.08.11
  • +
  • 4b187b8 (registry-proxy) - registry-proxy: use exec runner replace docker runner
  • +
  • 29ffbbe (registry-proxy) - registry-proxy: canonical charts naming
  • +
  • 6d783ba (registry-proxy) - registry-proxy: remove use_cni
  • +
  • 8cf05cf (registry-proxy) - dockerfile: use drycc/base image
  • +
  • 090e286 (registry-proxy) - registry-proxy: chore(imagebuilder): change uid gid to 1001
  • +
  • 7cf6120 (registry-proxy) - registry-proxy: use DRYCC_UID DRYCC_GID env
  • +
  • 3a00697 (registry-proxy) - registry-proxy: use registry.drycc.cc replace docker.io
  • +
  • 30e69e8 (registry-proxy) - registry-proxy: add registry basic auth proxy
  • +
  • 942abce (registry-proxy) - registry-proxy: upgrade to nginx 1.23.1
  • +
  • 5ea3297 (storage) - minio: use exec runner replace docker runner
  • +
  • 8306add (storage) - minio: canonical charts naming
  • +
  • c917e9f (storage) - minio: provide any additional service annotations
  • +
  • 042c732 (storage) - dockerfile: use drycc/base image
  • +
  • 7b47b82 (storage) - minio: change workdir to /workspace
  • +
  • 6f3531e (storage) - minio: use DRYCC_UID DRYCC_GID env
  • +
  • 9795fb1 (storage) - minio: use common affinity template
  • +
  • a7b09c5 (storage) - minio: change nodes to pod affinity
  • +
  • 7607342 (storage) - database: bump mc 2022.04.01.23.44.48 and minio 2022.04.01.03.41.39
  • +
  • ea2b2f1 (storage) - minio: use registry.drycc.cc replace docker.io
  • +
  • 445b501 (storage) - minio: https://github.com/minio/minio/issues/14331
  • +
  • f19fbc7 (storage) - minio: use env replace creds volume
  • +
  • 8982e2e (storage) - minio: use minio to distributed
  • +
  • 06bec73 (storage) - minio: fine management affinity
  • +
  • 9b8f006 (storage) - storage: remove assert
  • +
  • 59d64b9 (storage) - storage: change listen to POD_IP
  • +
  • 60044ee (storage) - storage: add juicefs mount options
  • +
  • 189f944 (storage) - storage: remove volumeName
  • +
  • 302fe89 (storage) - storage: mv to minio dir
  • +
  • 6ec586d (storage) - storage: change readinessProbee andlivenessProbe
  • +
  • 0e028df (storage) - storage: add minio pdb
  • +
  • cf9bd2d (storage) - storage: add check storage health svc
  • +
  • 2dd5c9f (storage) - storage: add volumeBindingMode
  • +
  • fa2effc (storage) - storage: remove databaseBucket
  • +
  • d166cc7 (storage) - charts: format network-policy name
  • +
  • d06bcce (storage) - storage: upgrade to golang 1.19
  • +
  • c2ca05c (storage) - storage: upgrade new require
  • +
+ + + +
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/blog/2023/12/08/drycc-workflow-v1.7.0/index.html b/blog/2023/12/08/drycc-workflow-v1.7.0/index.html new file mode 100644 index 000000000..ec35b5b55 --- /dev/null +++ b/blog/2023/12/08/drycc-workflow-v1.7.0/index.html @@ -0,0 +1,547 @@ + + + + + + + + + + + + + + + + + + + +Drycc Workflow v1.7.0 | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + +
+

Drycc Workflow v1.7.0

+
New Drycc Workflow Release v1.7.0
+ + +

These release notes for Drycc Workflow v1.7.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.6.0, please refer to the following change summary.

+

Workflow ## v1.6.0 -> v1.7.0

+

Releases

+
    +
  • builder v1.4.0 -> v1.5.0
  • +
  • controller v1.5.1 -> v1.6.0
  • +
  • database v1.2.0 -> v1.2.1
  • +
  • passport v1.1.0 -> v1.2.0
  • +
  • imagebuilder v1.1.0 -> v1.1.1
  • +
  • fluentbit v0.0.0 -> v0.0.1
  • +
  • logger v1.3.0 -> v1.3.1
  • +
  • storage v0.0.0 -> v0.0.1
  • +
  • gateway v0.0.0 -> v0.0.1
  • +
  • monitor v1.3.0 -> v1.4.0
  • +
  • redis v1.3.0 -> v1.3.1
  • +
  • timeseries v0.0.0 -> v0.0.1
  • +
  • prometheus v0.0.0 -> v0.1.0
  • +
  • rabbitmq v1.1.0 -> v1.2.0
  • +
  • registry v1.2.0 -> v1.2.1
  • +
  • registry-proxy v1.2.0 -> v1.2.1
  • +
+

Features

+
    +
  • fcbebda (builder) - builder: use TCPRoute expose service
  • +
  • d02bb5d (controller) - controller: support app dns policy config
  • +
  • 9aa968e (controller) - controller: add svc type support
  • +
  • 62e2d34 (controller) - controller: improve the services api
  • +
  • 4393755 (controller) - controller: use gateway replace ingress
  • +
  • 323045d (controller) - controller: add canary support
  • +
  • 3f81c97 (controller) - gateways: add addresses field
  • +
  • 4e64aa7 (controller) - gateways: add addresses field
  • +
  • 02ad581 (monitor) - grafana: add pd tikv dashboard
  • +
  • 2a9e2b0 (monitor) - monitor: add storage monitor
  • +
  • 41d5057 (monitor) - grafana: data source change to prometheus
  • +
  • ec035d1 (monitor) - monitor: usegateway replace ingress
  • +
  • c694c98 (monitor) - grafana: add drycc storage seaweedfs dashboard
  • +
  • 1e1fdc8 (passport) - passport: use gateway replace ingress
  • +
  • ffdb408 (prometheus) - prometheus: use gateway replace ingress
  • +
  • 04152b9 (rabbitmq) - rabbitmq: use gateway replace ingress
  • +
+

Fixes

+
    +
  • 0499500 (builder) - builder: manifest error
  • +
  • 642491d (builder) - builder: no build log
  • +
  • 873d146 (controller) - controller: do not set entrypoint when no procfile
  • +
  • d9028c5 (controller) - controller: pip8 error
  • +
  • 3efcfb7 (controller) - controller: manifest error
  • +
  • 18a3a1a (controller) - controller: miss service error
  • +
  • 94f796c (controller) - controller: drycc run pod should not restart
  • +
  • 80f3161 (controller) - controller: monitor query error
  • +
  • b76f2c5 (controller) - controller: read websocket delay
  • +
  • b6e068e (controller) - controller: metrics sql tpl, gateway pod should not restart, cleanup old rs, update monitor datatbase config
  • +
  • ad9adc6 (controller) - controller: rabbitmq sharding err
  • +
  • 6773907 (controller) - controller: default k8s pod annotaions
  • +
  • ffcf1f9 (controller) - controller: under-indented for visual indent
  • +
  • 3afd0cf (controller) - controller: charts env error
  • +
  • 769bb8b (database) - database: manifest error
  • +
  • 769bb8b (database) - database: label conflict error
  • +
  • 6a321c5 (database) - database: link error
  • +
  • 558feae (fluentbit) - fluentbit: build charts error
  • +
  • 98d8a2a (gateway) - fixup
  • +
  • 8b5dde1 (gateway) - gateway: secretName
  • +
  • 702866d (gateway) - gateway: build status
  • +
  • f55dac1 (imagebuilder) - imagebuilder: manifest error
  • +
  • ac13b5f (imagebuilder) - imagebuilder: build svg
  • +
  • 6b7bbc5 (logger) - logger: manifest error
  • +
  • 0136b5c (monitor) - monitor: manifest error
  • +
  • f03d975 (passport) - passport: DRYCC_GRAFANA_DOMAIN error
  • +
  • b530ea8 (passport) - passport: manifest error
  • +
  • be5a0a7 (passport) - passport: change passport
  • +
  • 1596c7f (rabbitmq) - rabbitmq: manifest error
  • +
  • 0dc4f6f (rabbitmq) - rabbitmq: images-shard error
  • +
  • 43293ae (redis) - redis: manifest error
  • +
  • ca13b7d (registry) - registry: manifest error
  • +
  • ab5c793 (registry) - registry: garbage collect error
  • +
  • ab0fabc (registry-proxy) - registry-proxy: manifest error
  • +
  • dfc7236 (registry-proxy) - registry-proxy: daemon yaml format
  • +
  • 42c03be (storage) - storage: seaweedfs csi error
  • +
  • 453e41a (timeseries) - timeseries: could not register node
  • +
+

Docs

+
    +
  • 5433c89 (gateway) - gateway: add prerequisites
  • +
  • 2f0c5d8 (logger) - logger: change architecture
  • +
+

Maintenance

+
    +
  • bdd02eb (builder) - builder: use dynamic clusterrole name
  • +
  • 66b4b25 (builder) - builder: upgrade new controller-go-sdk
  • +
  • 219d86f (builder) - builder: upgrade go.mod
  • +
  • 91f2f14 (builder) - builder: use woodpecker replace drone
  • +
  • 9abca16 (builder) - woodpecker: use woodpecker ci build status
  • +
  • f43dd50 (builder) - deps: bump golang.org/x/net from 0.2.0 to 0.7.0
  • +
  • 0384c69 (builder) - builder: add chart appVersion
  • +
  • e3149b9 (builder) - builder: upgrade codename to bookworm
  • +
  • d88ea1b (builder) - builder: add codename build-arg
  • +
  • ba59030 (builder) - builder: upgrade go.mod
  • +
  • 1114dd7 (builder) - builder: bump common 1.1.2
  • +
  • fe50b62 (builder) - builder: change drycc gateway listener name
  • +
  • db3950c (builder) - builder: remove gateway route
  • +
  • 5a508bb (builder) - builder: use podman replace docker
  • +
  • bbb9029 (builder) - deps: bump golang.org/x/net from 0.12.0 to 0.17.0
  • +
  • f4e5d6c (builder) - builder: remove health url
  • +
  • 9111c8f (builder) - builder: remove io/ioutil
  • +
  • 1f36e3d (controller) - deps: bump django from 4.1.2 to 4.1.6 in /rootfs
  • +
  • e4ab434 (controller) - controller: use woodpecker replace drone
  • +
  • 9f0301e (controller) - deps: bump django from 4.1.6 to 4.1.7 in /rootfs
  • +
  • 3932423 (controller) - woodpecker: use woodpecker ci build status
  • +
  • ae8b6b4 (controller) - setting: support KUBERNETES_LIMITS env config
  • +
  • c10b9bc (controller) - controller: using the api_version instead of hard coding
  • +
  • e6908cd (controller) - controller: upgrade requirements
  • +
  • b0eba0c (controller) - controller: add route rules serializer
  • +
  • 2e4b6a4 (controller) - controller: add chart appVersion
  • +
  • 7d32b55 (controller) - controller: upgrade to bookworm
  • +
  • f2dc8dd (controller) - controller: add codename build-arg
  • +
  • 5739b83 (controller) - controller: use timescaledb replace influxdb
  • +
  • 53892cb (controller) - controller: add timeseries
  • +
  • 0fe0eae (controller) - controller: upgrade requirements
  • +
  • 18b2a91 (controller) - deps: bump aiohttp from 3.8.4 to 3.8.5 in /rootfs
  • +
  • f50874a (controller) - controller: bump common 1.1.2
  • +
  • 956cd08 (controller) - controller: change drycc gateway listener name
  • +
  • 9ab3ead (controller) - controller: remove passport url check
  • +
  • a24c7b0 (controller) - controller: remove gateway route
  • +
  • f7e539a (controller) - controller: change celery priority
  • +
  • ab77a52 (controller) - controller: use podman replace docker
  • +
  • 8e27501 (controller) - controller: dynamic app storage class
  • +
  • 385978b (controller) - controller: list_pods datetime format
  • +
  • b20362c (controller) - deps: bump django from 4.2.3 to 4.2.7 in /rootfs
  • +
  • e11ae1b (controller) - controller: add cluster migrate
  • +
  • ca6e9df (controller) - controller: async mount
  • +
  • 9a7fbfc (controller) - controller: remove FOSSA
  • +
  • 3d55279 (controller) - deps: bump aiohttp from 3.8.5 to 3.8.6 in /rootfs
  • +
  • d498a11 (controller) - controller: add measure loalancers
  • +
  • 249a985 (controller) - deps: bump aiohttp from 3.8.5 to 3.8.6 in /rootfs
  • +
  • b967f58 (controller) - deps: bump aiohttp from 3.8.6 to 3.9.0 in /rootfs (#107)
  • +
  • 8ca9ed6 (controller) - controller: no longer restrict reserved domain
  • +
  • 9ff6649 (database) - database: add init database configure
  • +
  • 9b4cd26 (database) - database: use dynamic clusterrole name
  • +
  • b59cde4 (database) - database: remove minio require
  • +
  • 86462f8 (database) - database: use woodpecker replace drone
  • +
  • 1e8555a (database) - database: add chart appVersion
  • +
  • 1b762d5 (database) - database: upgrade codename to bookworm
  • +
  • 9ffe1fd (database) - database: add codename build-arg
  • +
  • 69466d7 (database) - database: add database extension
  • +
  • beb4b62 (database) - database: bump common 1.1.2
  • +
  • 67e2714 (database) - database: use podman replace docker
  • +
  • 8f328f8 (fluentbit) - fluentbit: no limit buffer size for kube api
  • +
  • fc0552c (fluentbit) - fluentbit: use podman replace docker
  • +
  • 63a6cab (fluentbit) - fluentbit: change fluentbit match
  • +
  • 220f81a (fluentbit) - fluentbit: run as no-root
  • +
  • aec1393 (fluentbit) - fluentbit: change configmap name
  • +
  • 1af4fd2 (fluentbit) - fluentbit: change default stream name
  • +
  • bef90ad (gateway) - gateway: add route for gateway
  • +
  • d523ddb (gateway) - gateway: change drycc gateway listener name
  • +
  • d9137f4 (gateway) - gateway: add chart appVersion
  • +
  • 0425dd4 (gateway) - gateway: add customListeners
  • +
  • 3982b86 (imagebuilder) - imagebuilder: use woodpecker replace drone
  • +
  • 3e4e7a3 (imagebuilder) - imagebuilder: add chart appVersion
  • +
  • 8df6e8e (imagebuilder) - imagebuilder: upgrade stack version
  • +
  • a5601f7 (imagebuilder) - imagebuilder: add drycc_app env
  • +
  • 07465f8 (imagebuilder) - imagebuilder: upgrade to bookworm
  • +
  • 00d22d2 (imagebuilder) - imagebuilder: add codename build-arg
  • +
  • 0b7a24e (imagebuilder) - imagebuilder: upgrade podman/mc/caddy
  • +
  • a7d8be8 (imagebuilder) - imagebuilder: use podman replace docker
  • +
  • 6b2da83 (logger) - logger: use woodpecker replace drone
  • +
  • 8245b25 (logger) - woodpecker: use woodpecker ci build status
  • +
  • f811a74 (logger) - logger: add chart appVersion
  • +
  • 413f6f6 (logger) - logger: upgrade codename to bookworm
  • +
  • 2ac6b10 (logger) - logger: add codename build-arg
  • +
  • 2581426 (logger) - logger: bump redis to v9
  • +
  • 364b25a (logger) - logger: bump common 1.1.2
  • +
  • dc169a3 (logger) - logger: use fluentbit replace fluentd
  • +
  • d855d91 (logger) - logger: use podman replace docker
  • +
  • f767235 (monitor) - monitor: add off-cluster passport configure
  • +
  • ab23936 (monitor) - monitor: use dynamic clusterrole name
  • +
  • 47beee0 (monitor) - monitor: change tikv secret key
  • +
  • af7703f (monitor) - grafana: remove panel when component off-cluster
  • +
  • 1b870c2 (monitor) - monitor: use woodpecker replace drone
  • +
  • 4a5f1f1 (monitor) - grafana: up ldap api_url config
  • +
  • 143cabe (monitor) - monitor: add prometheus architecture diagram
  • +
  • 93091c2 (monitor) - woodpecker: use woodpecker ci build status
  • +
  • 0b7045a (monitor) - grafana: add dashboard kubernetes_deployment_metrics
  • +
  • 2fb1839 (monitor) - woodpecker: pipeline config VERSION, when build container image
  • +
  • e272416 (monitor) - monitor: add chart appVersion
  • +
  • abc0e53 (monitor) - monitor: upgrade codename to bookworm
  • +
  • 86cc01b (monitor) - monitor: add codename build-arg
  • +
  • 1cd849f (monitor) - monitor: add postgresql outputs
  • +
  • c3205c0 (monitor) - monitor: change default agent config
  • +
  • 8c802c0 (monitor) - monitor: add timeseries database
  • +
  • e9abc40 (monitor) - monitor: bump common 1.1.2
  • +
  • 6af66cd (monitor) - monitor: change drycc gateway listener name
  • +
  • d02d718 (monitor) - monitor: remove gateway route
  • +
  • 3509c29 (monitor) - monitor: use podman replace docker
  • +
  • ed7bfa2 (monitor) - monitor: optimize env PROMETHEUS_URL
  • +
  • da89bef (passport) - passport: charts codereview
  • +
  • 61c4a96 (passport) - passport: support init app config
  • +
  • 9101006 (passport) - passport: add initApplications to charts
  • +
  • 7dd7fa4 (passport) - passport: use woodpecker replace drone
  • +
  • 4400199 (passport) - woodpecker: use woodpecker ci build status
  • +
  • 6b2c546 (passport) - passport: change secret name to drycc-passport-auto-tls
  • +
  • c8bd824 (passport) - passport: upgrade requirements
  • +
  • aee5aef (passport) - passport: add chart appVersion
  • +
  • 2d81953 (passport) - passport: upgrade codename to bookworm
  • +
  • 9e66242 (passport) - passport: add codename build-arg
  • +
  • 0fca998 (passport) - passport: upgrade requirements
  • +
  • 3482528 (passport) - passport: bump common 1.1.2
  • +
  • 0c5ec93 (passport) - passport: change drycc gateway listener name
  • +
  • f7b8f53 (passport) - passport: remove gateway route
  • +
  • baf69da (passport) - passport: use podman replace docker
  • +
  • fcd45dd (passport) - passport: add cluster migrate
  • +
  • da6d32a (prometheus) - prometheus: add prometheus-config
  • +
  • 683de9e (prometheus) - prometheus: use podman replace docker
  • +
  • 3323300 (prometheus) - prometheus: remove gateway route
  • +
  • da1d356 (prometheus) - prometheus: change drycc gateway listener name
  • +
  • 4e7a936 (prometheus) - prometheus: bump common 1.1.2
  • +
  • 44c1c6f (prometheus) - prometheus: add codename build-arg
  • +
  • d1f1dda (prometheus) - prometheus: upgrade codename to bookworm
  • +
  • 0836fc1 (prometheus) - prometheus: add chart appVersion
  • +
  • 9e13232 (prometheus) - prometheus: add LICENSE
  • +
  • f53e14a (rabbitmq) - rabbitmq: remove auto user
  • +
  • 0ec7277 (rabbitmq) - rabbitmq: use woodpecker replace drone
  • +
  • f376a30 (rabbitmq) - woodpecker: use woodpecker ci build status
  • +
  • 51405d8 (rabbitmq) - rabbitmq: add chart appVersion
  • +
  • 463ca03 (rabbitmq) - rabbitmq: upgrade codename to bookworm
  • +
  • 1978a71 (rabbitmq) - rabbitmq: add codename build-arg
  • +
  • 139277f (rabbitmq) - rabbitmq: bump common 1.1.2
  • +
  • be49741 (rabbitmq) - rabbitmq: change drycc gateway listener name
  • +
  • 6d22518 (rabbitmq) - rabbitmq: remove gateway route
  • +
  • 0eb7833 (rabbitmq) - rabbitmq: add check shards
  • +
  • 9211063 (rabbitmq) - rabbitmq: erlang vm tuning optimization
  • +
  • 648a78d (rabbitmq) - rabbitmq: use podman replace docker
  • +
  • 0b43a4d (rabbitmq) - rabbitmq: add x-random exchange
  • +
  • ad1c4da (redis) - redis: use woodpecker replace drone
  • +
  • 3f37f92 (redis) - redis: add chart appVersion
  • +
  • e3bef7a (redis) - redis: upgrade codename to bookworm
  • +
  • 4e806d4 (redis) - redis: add codename build-arg
  • +
  • d5023be (redis) - redis: bump common 1.1.2
  • +
  • 98f5d6f (redis) - redis: use podman replace docker
  • +
  • 063f29e (registry) - registry: use woodpecker replace drone
  • +
  • 17bf8ae (registry) - woodpecker: use woodpecker ci build status
  • +
  • 7bbad15 (registry) - registry: add chart appVersion
  • +
  • 279154f (registry) - registry: upgrade codename to bookworm
  • +
  • 3e4ae84 (registry) - registry: add codename build-arg
  • +
  • fa322d6 (registry) - registry: bump common 1.1.2
  • +
  • 6c18fe0 (registry) - registry: use podman replace docker
  • +
  • 0bc8472 (registry) - registry: remove health url
  • +
  • 5dacd9f (registry) - registry: add wait-for-port check
  • +
  • fdeefc3 (registry) - registry: use headless
  • +
  • 08bf9f8 (registry) - registry: change registry port to 5000
  • +
  • 40bcea2 (registry) - registry: add registry push test
  • +
  • 871b8e7 (registry) - registry: add default env
  • +
  • 7f3b3ac (registry) - registry: bump registry 2.8.3
  • +
  • 569f15d (registry-proxy) - registry-proxy: use woodpecker replace drone
  • +
  • cc33caf (registry-proxy) - woodpecker: use woodpecker ci build status
  • +
  • 0002aab (registry-proxy) - registry-proxy: add chart appVersion
  • +
  • 40af10b (registry-proxy) - registry-proxy: upgrade codename to bookworm
  • +
  • c56b9df (registry-proxy) - registry-proxy: add codename build-arg
  • +
  • 9d5bfe0 (registry-proxy) - registry-proxy: use podman replace docker
  • +
  • e6a3350 (registry-proxy) - registry-proxy: change worker_processes to 1
  • +
  • 726f39d (storage) - storage: add volume compactionMBps
  • +
  • a5aa2d8 (storage) - storage: add threshold to vacuum and reclaim spaces
  • +
  • e687d04 (storage) - storage: delete disk type in single disk case
  • +
  • 75ee2e4 (storage) - storage: change datanode replicas to 4
  • +
  • c5fd7ba (storage) - storage: delete useless env
  • +
  • b3826ea (storage) - storage: add ssd hdd dir
  • +
  • 29881a0 (storage) - storage: add balance cronjob
  • +
  • c5a0f51 (storage) - storage: add defaultReplication for seaweedfs master
  • +
  • 543c7a2 (timeseries) - timeseries: use podman replace docker
  • +
  • 5376024 (timeseries) - timeseries: update timeseries-service-replica
  • +
  • 52e8520 (timeseries) - timeseries: bump common 1.1.2
  • +
  • f82657c (timeseries) - timeseries: add start script
  • +
+ + + +
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/blog/2024/01/29/drycc-workflow-v1.7.2/index.html b/blog/2024/01/29/drycc-workflow-v1.7.2/index.html new file mode 100644 index 000000000..2a23a1365 --- /dev/null +++ b/blog/2024/01/29/drycc-workflow-v1.7.2/index.html @@ -0,0 +1,319 @@ + + + + + + + + + + + + + + + + + + + +Drycc Workflow v1.7.2 | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + +
+

Drycc Workflow v1.7.2

+
New Drycc Workflow Release v1.7.2
+ + +

These release notes for Drycc Workflow v1.7.2 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.7.1, please refer to the following change summary.

+

Workflow ## v1.7.1 -> v1.7.2

+

Releases

+
    +
  • controller v1.6.0 -> v1.6.1
  • +
  • logger v1.3.1 -> v1.3.2
  • +
  • storage v0.0.1 -> v0.0.2
  • +
  • timeseries v0.0.1 -> v0.0.2
  • +
  • prometheus v0.1.0 -> v0.1.1
  • +
  • workflow-cli v1.5.0 -> v1.5.1
  • +
+

Fixes

+
    +
  • 2fe80a6 (controller) - resources: after resources instance update, could not delete (#111)
  • +
  • a4082ad (controller) - controller: resource status and binding
  • +
  • e9bfccc (controller) - controller: fix multiple volumes mount at one dir error (#116)
  • +
  • 58d2b4c (logger) - logger: redis conn error block
  • +
  • 7cb2700 (prometheus) - prometheus: prometheus config basic_auth
  • +
  • 7838c6b (storage) - storage: random accesskey secretkey
  • +
  • d9dcdfb (storage) - storage: pod restart loses data
  • +
  • 3cbdd29 (storage) - storage: tipd cannot start after deleting pod
  • +
  • be7e11f (storage) - storage: jq command not found
  • +
  • 878f674 (storage) - storage: charts updateStrategy error
  • +
  • 06cfe56 (timeseries) - timeseries: the data node ip is incorrect
  • +
+

Maintenance

+
    +
  • 7f29f5a (controller) - resources: retrieve resource instance response add message (#112)
  • +
  • 4a84dcd (controller) - controller: add deploy default annotations (#113)
  • +
  • 829d7e5 (controller) - controller: modify url match service name (#114)
  • +
  • 30abf6d (controller) - controller: transfer app ownership in async
  • +
  • dc6f45e (controller) - controller: add channel for pod exec
  • +
  • af4f3a7 (controller) - controller: avoid error when secret no data field (#117)
  • +
  • ca27956 (controller) - controller: add pod default security
  • +
  • b2e9c64 (prometheus) - charts: node-exporter mount root (#2)
  • +
  • 3cdb2b6 (storage) - storage: bump seaweedfs 3.61
  • +
  • 00dd2fd (storage) - storage: add csi daemonset updateStrategy
  • +
  • 48e763c (storage) - storage: add drycc storage upgrade document
  • +
  • 841df90 (storage) - storage: bump seaweedfs 3.62
  • +
  • cefd52e (timeseries) - timeseries: add check data node exists
  • +
  • ad1c46e (workflow-cli) - resources: resources instance add message
  • +
  • 9f955c2 (workflow-cli) - workflow-cli: add short options cpu
  • +
  • 65399ef (workflow-cli) - workflow-cli: add tty resize support
  • +
+ + + +
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/blog/2024/02/27/drycc-workflow-v1.7.5/index.html b/blog/2024/02/27/drycc-workflow-v1.7.5/index.html new file mode 100644 index 000000000..f77685ef9 --- /dev/null +++ b/blog/2024/02/27/drycc-workflow-v1.7.5/index.html @@ -0,0 +1,316 @@ + + + + + + + + + + + + + + + + + + + +Drycc Workflow v1.7.5 | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + +
+

Drycc Workflow v1.7.5

+
New Drycc Workflow Release v1.7.5
+ + +

These release notes for Drycc Workflow v1.7.5 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.7.4, please refer to the following change summary.

+

Workflow ## v1.7.4 -> v1.7.5

+

Releases

+
    +
  • builder v1.5.0 -> v1.5.1
  • +
  • controller v1.6.3 -> v1.7.0
  • +
  • logger v1.3.2 -> v1.3.3
  • +
  • storage v0.0.3 -> v0.0.4
  • +
  • redis v1.3.1 -> v1.3.2
  • +
  • rabbitmq v1.2.0 -> v1.2.1
  • +
  • registry v1.2.1 -> v1.2.2
  • +
  • workflow-cli v1.5.1 -> v1.5.2
  • +
+

Features

+
    +
  • 95d130a (controller) - controller: volume support nfs
  • +
+

Fixes

+
    +
  • ee2ee15 (controller) - controller: container entrypoint error
  • +
  • 03ea4f8 (controller) - controller: class property have been deprecated in python 3.11
  • +
  • 5f04d17 (controller) - controller: miss err msg
  • +
  • 27972a3 (controller) - controller: load_db_state_to_k8s err
  • +
  • a005d62 (controller) - controller: volume repeat path no error
  • +
  • c7a5ba6 (rabbitmq) - rabbitmq: cpu usage to high
  • +
  • 45c2077 (workflow-cli) - workflow-cli: miss err msg
  • +
  • bc738bd (workflow-cli) - workflow-cli: volumes list format
  • +
+

Maintenance

+
    +
  • 35e1c06 (builder) - builder: bump golang 1.22
  • +
  • 26caa36 (controller) - deps: bump aiohttp from 3.9.0 to 3.9.2 in /rootfs (#118)
  • +
  • 3d938c4 (controller) - deps: bump django from 4.2.7 to 4.2.10
  • +
  • e625c2f (logger) - logger: bump golang 1.22
  • +
  • bfa500d (redis) - redis: headless svc does not require ports
  • +
  • 330209a (registry) - registry: headless svc does not require ports
  • +
  • 48c42eb (storage) - storage: change volume index to leveldb
  • +
  • f4fde9d (storage) - storage: add volume size limit
  • +
  • 33e3684 (workflow-cli) - workflow-cli: volume support nfs
  • +
  • 48d5950 (workflow-cli) - workflow-cli: bump golang 1.22
  • +
+ + + +
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/blog/2024/02/27/drycc-workflow-v1.7.6/index.html b/blog/2024/02/27/drycc-workflow-v1.7.6/index.html new file mode 100644 index 000000000..9a40d40c5 --- /dev/null +++ b/blog/2024/02/27/drycc-workflow-v1.7.6/index.html @@ -0,0 +1,284 @@ + + + + + + + + + + + + + + + + + + + +Drycc Workflow v1.7.6 | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + +
+

Drycc Workflow v1.7.6

+
New Drycc Workflow Release v1.7.6
+ + +

Workflow ## v1.7.5 -> v1.7.6

+

Releases

+
    +
  • storage v0.0.4 -> v0.0.5
  • +
+

Maintenance

+
    +
  • 6cb63b6 (storage) - seaweedfs: bump version 3.63
  • +
+ + + +
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/blog/2024/04/30/drycc-workflow-v1.7.7/index.html b/blog/2024/04/30/drycc-workflow-v1.7.7/index.html new file mode 100644 index 000000000..27e4b873e --- /dev/null +++ b/blog/2024/04/30/drycc-workflow-v1.7.7/index.html @@ -0,0 +1,436 @@ + + + + + + + + + + + + + + + + + + + +Drycc Workflow v1.7.7 | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + +
+

Drycc Workflow v1.7.7

+
New Drycc Workflow Release v1.7.7
+ + +

Workflow ## v1.7.6 -> v1.7.7

+

Releases

+
    +
  • builder v1.5.1 -> v1.6.0
  • +
  • controller v1.7.0 -> v1.8.0
  • +
  • database v1.2.1 -> v1.3.0
  • +
  • passport v1.2.0 -> v1.3.0
  • +
  • imagebuilder v1.1.1 -> v1.2.0
  • +
  • fluentbit v0.0.1 -> v0.0.2
  • +
  • logger v1.3.3 -> v1.3.4
  • +
  • storage v0.0.5 -> v0.1.0
  • +
  • gateway v0.0.2 -> v0.0.3
  • +
  • monitor v1.4.0 -> v1.4.1
  • +
  • redis v1.3.2 -> v1.4.0
  • +
  • timeseries v0.0.2 -> v0.1.0
  • +
  • prometheus v0.1.1 -> v0.1.2
  • +
  • rabbitmq v1.2.1 -> v1.3.0
  • +
  • registry v1.2.2 -> v1.3.0
  • +
  • registry-proxy v1.2.1 -> v1.2.2
  • +
  • workflow-cli v1.5.2 -> v1.6.0
  • +
+

Features

+
    +
  • 6c1cf5e (builder) - charts: reuses the value from an existing secret and config
  • +
  • 65ae63c (builder) - pipeline: add dryccfile support
  • +
  • bb7b11d (builder) - auth: add tokens api
  • +
  • 39d022f (controller) - ps: add pod logs support
  • +
  • 86056d0 (controller) - charts: reuses the value from an existing secret and config
  • +
  • 4cf005c (controller) - limits: add limits plan support
  • +
  • bf60e4b (controller) - controller: add init job
  • +
  • 98f77a8 (controller) - pipeline: add dryccfile support
  • +
  • 8ce9a83 (controller) - cert-manager: add tls events
  • +
  • 7034f5d (controller) - config: deploy according to procfile_type
  • +
  • 5554d8f (controller) - config: add typed_values
  • +
  • 2c5bbad (controller) - auth: add token api
  • +
  • 410d34e (database) - charts: reuses the value from an existing secret and config
  • +
  • 693e4d1 (imagebuilder) - pipeline: add dryccfile support
  • +
  • 7d9cc06 (imagebuilder) - config: add typed values
  • +
  • 854e171 (passport) - charts: reuses the value from an existing secret and config
  • +
  • 7ac9255 (passport) - oauth2: add authorization code for any grant type
  • +
  • 4517547 (rabbitmq) - charts: reuses the value from an existing secret and config
  • +
  • bccfcb4 (redis) - charts: reuses the value from an existing secret and config
  • +
  • d887605 (registry) - charts: reuses the value from an existing secret and config
  • +
  • ff09e5b (storage) - charts: reuses the value from an existing secret and config
  • +
  • c6e2ac8 (timeseries) - charts: reuses the value from an existing secret and config
  • +
  • 22c4c77 (workflow-cli) - apps: change drycc run to async
  • +
  • a9e6369 (workflow-cli) - ps: add pod logs support
  • +
  • 2bc31c8 (workflow-cli) - limits: add limits plan support
  • +
  • f40398a (workflow-cli) - pipeline: add dryccfile support
  • +
  • 03638ff (workflow-cli) - tls: add tls events
  • +
  • 9113627 (workflow-cli) - config: add typed values
  • +
  • 43ee760 (workflow-cli) - auth: add tokens api
  • +
+

Fixes

+
    +
  • 50dfe64 (builder) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • ab09b24 (controller) - healthcheck: delete outdated code
  • +
  • 52019b5 (controller) - services: default PORT change error
  • +
  • f57ae42 (controller) - certificate: failed to create certificate
  • +
  • 30c3f54 (controller) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • dbba43a (controller) - service: update port error
  • +
  • e0459c5 (controller) - copy: use deepcopy replace copy
  • +
  • 2122479 (controller) - charts: failed to call webhook
  • +
  • 53d9977 (controller) - signals: config limits handle error
  • +
  • afda287 (controller) - limits: always set default
  • +
  • b350cb8 (database) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • b48a422 (fluentbit) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 7cebca2 (gateway) - cert-manager: auto tls error
  • +
  • 190c19b (imagebuilder) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 2c6a6f9 (logger) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 10bb98d (monitor) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • f8225dc (passport) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 06db66c (prometheus) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • f4aff72 (rabbitmq) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 88c18ff (redis) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 5dcc19d (registry) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 092a939 (registry-proxy) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 3597ac9 (storage) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 5a49b35 (timeseries) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 0c4a48a (workflow-cli) - tls: change issuer options
  • +
  • 06a2511 (workflow-cli) - tls: info error
  • +
+

Maintenance

+
    +
  • 2f7617e (builder) - go: bump controller-sdk-go version
  • +
  • aae2f29 (builder) - charts: add diagnostic mode
  • +
  • 7304980 (builder) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 30b648b (builder) - charts: change canary app version
  • +
  • 2afa006 (builder) - controller-sdk-go: bump version
  • +
  • d127a90 (builder) - config: add typed values
  • +
  • 32fdfd0 (controller) - charts: add diagnostic mode
  • +
  • 0974942 (controller) - woodpecker: migrations woodpecker-ci to 2
  • +
  • f401e08 (controller) - python: bump python 3.12
  • +
  • c565959 (controller) - celery: remove retrieve_resource task
  • +
  • 47be1a1 (controller) - requirements: bump drf 3.15.1
  • +
  • 99f7468 (controller) - charts: add config to values.yaml
  • +
  • 7d17f5c (controller) - scale: prohibit scale when there is a running pipeline
  • +
  • f09e1c9 (controller) - resource: sort services and plans
  • +
  • e817505 (controller) - limits: change default cpu and gpu name
  • +
  • 5531b2f (controller) - auth: add password login
  • +
  • 27473f7 (controller) - deps: bump gunicorn from 21.2.0 to 22.0.0 in /rootfs
  • +
  • c1ee1c7 (controller) - deps: bump aiohttp from 3.9.3 to 3.9.4 in /rootfs
  • +
  • affbcb5 (database) - postgres: add patroni and postgres params (#15)
  • +
  • f9e4eda (database) - dockerfile: install vi
  • +
  • 008b7b6 (database) - dockerfile: install vim instand of vi
  • +
  • dbbfee1 (database) - charts: add diagnostic mode
  • +
  • 2e26c33 (database) - woodpecker: migrations woodpecker-ci to 2
  • +
  • a1b81f2 (database) - charts: change canary app version
  • +
  • bc725e8 (fluentbit) - charts: add diagnostic mode
  • +
  • 5d73886 (fluentbit) - woodpecker: migrations woodpecker-ci to 2
  • +
  • b85072d (fluentbit) - charts: change canary app version
  • +
  • 761174d (gateway) - gateway: change secrets name
  • +
  • 1c304da (gateway) - woodpecker: migrations woodpecker-ci to 2
  • +
  • b919a4c (gateway) - charts: change canary app version
  • +
  • 3cea298 (imagebuilder) - charts: allow all dns
  • +
  • 653bcbe (imagebuilder) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 59daeab (imagebuilder) - charts: change canary app version
  • +
  • 2834a5a (logger) - charts: add diagnostic mode
  • +
  • 6685492 (logger) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 191cdaf (logger) - charts: change canary app version
  • +
  • b3c3cfa (monitor) - charts: add diagnostic mode
  • +
  • 796799d (monitor) - grafana: add node metrics dashboard
  • +
  • ef2a222 (monitor) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 9c83090 (monitor) - charts: change canary app version
  • +
  • 1a97c2c (passport) - charts: add diagnostic mode
  • +
  • 353e1ae (passport) - logger: add oauth2_provider logger config
  • +
  • fe735c0 (passport) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 41d6144 (passport) - charts: change canary app version
  • +
  • 979d474 (passport) - python: bump python 3.12
  • +
  • e9f41a1 (passport) - requirements: bump drf 3.15.1
  • +
  • f479f4d (passport) - charts: add migrate job
  • +
  • ad9abf6 (passport) - passport: migrations add run_before
  • +
  • 95ac667 (passport) - passport: optimize the use of master and slave database rules
  • +
  • 204f7fc (passport) - deps: bump gunicorn from 21.2.0 to 22.0.0 in /rootfs
  • +
  • 90a6410 (prometheus) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 2d8eb44 (prometheus) - charts: change canary app version
  • +
  • 9687a17 (rabbitmq) - charts: add diagnostic mode
  • +
  • 35d3d5b (rabbitmq) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 6a6564d (rabbitmq) - charts: change canary app version
  • +
  • cb6722f (redis) - charts: add diagnostic mode
  • +
  • 9553497 (redis) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 1c8dc07 (redis) - charts: change canary app version
  • +
  • 9fa2a32 (registry) - charts: add diagnostic mode
  • +
  • 9b09e51 (registry) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 7dbd390 (registry) - charts: change canary app version
  • +
  • e1d2a33 (registry-proxy) - charts: add diagnostic mode
  • +
  • 3eabfdd (registry-proxy) - charts: remove default limits
  • +
  • f8754da (registry-proxy) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 7df7316 (registry-proxy) - charts: change canary app version
  • +
  • 861d3b8 (storage) - filer: modify the default parameters of the filer
  • +
  • 5fa08da (storage) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 22c4620 (storage) - charts: change canary app version
  • +
  • 6c1e29c (timeseries) - postgres: add patroni params
  • +
  • e280d3f (timeseries) - dockerfile: install vi
  • +
  • 5213617 (timeseries) - dockerfile: install vim instand of vi
  • +
  • a569a57 (timeseries) - charts: add diagnostic mode
  • +
  • b93ec70 (timeseries) - woodpecker: migrations woodpecker-ci to 2
  • +
  • ff3b870 (timeseries) - charts: change canary app version
  • +
  • e334f74 (workflow-cli) - healthcheck: delete outdated healthcheck style
  • +
  • 4f8b960 (workflow-cli) - auth: add password login
  • +
+ + + +
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/blog/2024/05/01/drycc-workflow-v1.7.8/index.html b/blog/2024/05/01/drycc-workflow-v1.7.8/index.html new file mode 100644 index 000000000..47ce0b6b2 --- /dev/null +++ b/blog/2024/05/01/drycc-workflow-v1.7.8/index.html @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + + + + +Drycc Workflow v1.7.8 | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + +
+

Drycc Workflow v1.7.8

+
New Drycc Workflow Release v1.7.8
+ + +

Workflow ## v1.7.7 -> v1.7.8

+

Releases

+
    +
  • builder v1.6.0 -> v1.7.0
  • +
  • controller v1.8.0 -> v1.9.0
  • +
  • workflow-cli v1.6.0 -> v1.7.0
  • +
+

Features

+
    +
  • 384c7ee (builder) - domain: add procfile_type
  • +
  • 26c8c7f (controller) - domain: add procfile_type
  • +
  • bd49789 (workflow-cli) - domain: add procfile_type
  • +
+ + + +
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/blog/_print/index.html b/blog/_print/index.html new file mode 100644 index 000000000..ea935eeea --- /dev/null +++ b/blog/_print/index.html @@ -0,0 +1,2411 @@ + + + + + + + + + + + + + + + + + + + + + +Blog | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + + +
+
+

+This is the multi-page printable view of this section. +Click here to print. +

+Return to the regular view of this page. +

+
+ + + +

Blog

+ + + + + + + + +
+

This is the blog section. It has two categories: News and Releases.

+

Files in these directories will be listed in reverse chronological order.

+ +
+
+ + + + + + + + + + + + + + + + + + + +
+

News

+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+

Welcome to Drycc

+
Drycc Workflow is A Open, Unified, Lightweight, Simpler Containers as a Service (CaaS).
+ +

Drycc Workflow is an open source Container as a Service (CaaS) that adds a developer-friendly layer to any Kubernetes cluster, making it easy to deploy and manage applications.

+

We welcome your input! If you have feedback, please submit an issue. If you’d like to participate in development, please read the “Working on Documentation” section below and submit a pull request.

+ +
+ + + + + + + + + + + + + + + + + + + + +
+

Release

+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+

Drycc Workflow v1.7.8

+
New Drycc Workflow Release v1.7.8
+ +

Workflow ## v1.7.7 -> v1.7.8

+

Releases

+
    +
  • builder v1.6.0 -> v1.7.0
  • +
  • controller v1.8.0 -> v1.9.0
  • +
  • workflow-cli v1.6.0 -> v1.7.0
  • +
+

Features

+
    +
  • 384c7ee (builder) - domain: add procfile_type
  • +
  • 26c8c7f (controller) - domain: add procfile_type
  • +
  • bd49789 (workflow-cli) - domain: add procfile_type
  • +
+ +
+ + + + + + + + + + + + + + + + +
+

Drycc Workflow v1.7.7

+
New Drycc Workflow Release v1.7.7
+ +

Workflow ## v1.7.6 -> v1.7.7

+

Releases

+
    +
  • builder v1.5.1 -> v1.6.0
  • +
  • controller v1.7.0 -> v1.8.0
  • +
  • database v1.2.1 -> v1.3.0
  • +
  • passport v1.2.0 -> v1.3.0
  • +
  • imagebuilder v1.1.1 -> v1.2.0
  • +
  • fluentbit v0.0.1 -> v0.0.2
  • +
  • logger v1.3.3 -> v1.3.4
  • +
  • storage v0.0.5 -> v0.1.0
  • +
  • gateway v0.0.2 -> v0.0.3
  • +
  • monitor v1.4.0 -> v1.4.1
  • +
  • redis v1.3.2 -> v1.4.0
  • +
  • timeseries v0.0.2 -> v0.1.0
  • +
  • prometheus v0.1.1 -> v0.1.2
  • +
  • rabbitmq v1.2.1 -> v1.3.0
  • +
  • registry v1.2.2 -> v1.3.0
  • +
  • registry-proxy v1.2.1 -> v1.2.2
  • +
  • workflow-cli v1.5.2 -> v1.6.0
  • +
+

Features

+
    +
  • 6c1cf5e (builder) - charts: reuses the value from an existing secret and config
  • +
  • 65ae63c (builder) - pipeline: add dryccfile support
  • +
  • bb7b11d (builder) - auth: add tokens api
  • +
  • 39d022f (controller) - ps: add pod logs support
  • +
  • 86056d0 (controller) - charts: reuses the value from an existing secret and config
  • +
  • 4cf005c (controller) - limits: add limits plan support
  • +
  • bf60e4b (controller) - controller: add init job
  • +
  • 98f77a8 (controller) - pipeline: add dryccfile support
  • +
  • 8ce9a83 (controller) - cert-manager: add tls events
  • +
  • 7034f5d (controller) - config: deploy according to procfile_type
  • +
  • 5554d8f (controller) - config: add typed_values
  • +
  • 2c5bbad (controller) - auth: add token api
  • +
  • 410d34e (database) - charts: reuses the value from an existing secret and config
  • +
  • 693e4d1 (imagebuilder) - pipeline: add dryccfile support
  • +
  • 7d9cc06 (imagebuilder) - config: add typed values
  • +
  • 854e171 (passport) - charts: reuses the value from an existing secret and config
  • +
  • 7ac9255 (passport) - oauth2: add authorization code for any grant type
  • +
  • 4517547 (rabbitmq) - charts: reuses the value from an existing secret and config
  • +
  • bccfcb4 (redis) - charts: reuses the value from an existing secret and config
  • +
  • d887605 (registry) - charts: reuses the value from an existing secret and config
  • +
  • ff09e5b (storage) - charts: reuses the value from an existing secret and config
  • +
  • c6e2ac8 (timeseries) - charts: reuses the value from an existing secret and config
  • +
  • 22c4c77 (workflow-cli) - apps: change drycc run to async
  • +
  • a9e6369 (workflow-cli) - ps: add pod logs support
  • +
  • 2bc31c8 (workflow-cli) - limits: add limits plan support
  • +
  • f40398a (workflow-cli) - pipeline: add dryccfile support
  • +
  • 03638ff (workflow-cli) - tls: add tls events
  • +
  • 9113627 (workflow-cli) - config: add typed values
  • +
  • 43ee760 (workflow-cli) - auth: add tokens api
  • +
+

Fixes

+
    +
  • 50dfe64 (builder) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • ab09b24 (controller) - healthcheck: delete outdated code
  • +
  • 52019b5 (controller) - services: default PORT change error
  • +
  • f57ae42 (controller) - certificate: failed to create certificate
  • +
  • 30c3f54 (controller) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • dbba43a (controller) - service: update port error
  • +
  • e0459c5 (controller) - copy: use deepcopy replace copy
  • +
  • 2122479 (controller) - charts: failed to call webhook
  • +
  • 53d9977 (controller) - signals: config limits handle error
  • +
  • afda287 (controller) - limits: always set default
  • +
  • b350cb8 (database) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • b48a422 (fluentbit) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 7cebca2 (gateway) - cert-manager: auto tls error
  • +
  • 190c19b (imagebuilder) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 2c6a6f9 (logger) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 10bb98d (monitor) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • f8225dc (passport) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 06db66c (prometheus) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • f4aff72 (rabbitmq) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 88c18ff (redis) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 5dcc19d (registry) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 092a939 (registry-proxy) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 3597ac9 (storage) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 5a49b35 (timeseries) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 0c4a48a (workflow-cli) - tls: change issuer options
  • +
  • 06a2511 (workflow-cli) - tls: info error
  • +
+

Maintenance

+
    +
  • 2f7617e (builder) - go: bump controller-sdk-go version
  • +
  • aae2f29 (builder) - charts: add diagnostic mode
  • +
  • 7304980 (builder) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 30b648b (builder) - charts: change canary app version
  • +
  • 2afa006 (builder) - controller-sdk-go: bump version
  • +
  • d127a90 (builder) - config: add typed values
  • +
  • 32fdfd0 (controller) - charts: add diagnostic mode
  • +
  • 0974942 (controller) - woodpecker: migrations woodpecker-ci to 2
  • +
  • f401e08 (controller) - python: bump python 3.12
  • +
  • c565959 (controller) - celery: remove retrieve_resource task
  • +
  • 47be1a1 (controller) - requirements: bump drf 3.15.1
  • +
  • 99f7468 (controller) - charts: add config to values.yaml
  • +
  • 7d17f5c (controller) - scale: prohibit scale when there is a running pipeline
  • +
  • f09e1c9 (controller) - resource: sort services and plans
  • +
  • e817505 (controller) - limits: change default cpu and gpu name
  • +
  • 5531b2f (controller) - auth: add password login
  • +
  • 27473f7 (controller) - deps: bump gunicorn from 21.2.0 to 22.0.0 in /rootfs
  • +
  • c1ee1c7 (controller) - deps: bump aiohttp from 3.9.3 to 3.9.4 in /rootfs
  • +
  • affbcb5 (database) - postgres: add patroni and postgres params (#15)
  • +
  • f9e4eda (database) - dockerfile: install vi
  • +
  • 008b7b6 (database) - dockerfile: install vim instand of vi
  • +
  • dbbfee1 (database) - charts: add diagnostic mode
  • +
  • 2e26c33 (database) - woodpecker: migrations woodpecker-ci to 2
  • +
  • a1b81f2 (database) - charts: change canary app version
  • +
  • bc725e8 (fluentbit) - charts: add diagnostic mode
  • +
  • 5d73886 (fluentbit) - woodpecker: migrations woodpecker-ci to 2
  • +
  • b85072d (fluentbit) - charts: change canary app version
  • +
  • 761174d (gateway) - gateway: change secrets name
  • +
  • 1c304da (gateway) - woodpecker: migrations woodpecker-ci to 2
  • +
  • b919a4c (gateway) - charts: change canary app version
  • +
  • 3cea298 (imagebuilder) - charts: allow all dns
  • +
  • 653bcbe (imagebuilder) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 59daeab (imagebuilder) - charts: change canary app version
  • +
  • 2834a5a (logger) - charts: add diagnostic mode
  • +
  • 6685492 (logger) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 191cdaf (logger) - charts: change canary app version
  • +
  • b3c3cfa (monitor) - charts: add diagnostic mode
  • +
  • 796799d (monitor) - grafana: add node metrics dashboard
  • +
  • ef2a222 (monitor) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 9c83090 (monitor) - charts: change canary app version
  • +
  • 1a97c2c (passport) - charts: add diagnostic mode
  • +
  • 353e1ae (passport) - logger: add oauth2_provider logger config
  • +
  • fe735c0 (passport) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 41d6144 (passport) - charts: change canary app version
  • +
  • 979d474 (passport) - python: bump python 3.12
  • +
  • e9f41a1 (passport) - requirements: bump drf 3.15.1
  • +
  • f479f4d (passport) - charts: add migrate job
  • +
  • ad9abf6 (passport) - passport: migrations add run_before
  • +
  • 95ac667 (passport) - passport: optimize the use of master and slave database rules
  • +
  • 204f7fc (passport) - deps: bump gunicorn from 21.2.0 to 22.0.0 in /rootfs
  • +
  • 90a6410 (prometheus) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 2d8eb44 (prometheus) - charts: change canary app version
  • +
  • 9687a17 (rabbitmq) - charts: add diagnostic mode
  • +
  • 35d3d5b (rabbitmq) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 6a6564d (rabbitmq) - charts: change canary app version
  • +
  • cb6722f (redis) - charts: add diagnostic mode
  • +
  • 9553497 (redis) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 1c8dc07 (redis) - charts: change canary app version
  • +
  • 9fa2a32 (registry) - charts: add diagnostic mode
  • +
  • 9b09e51 (registry) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 7dbd390 (registry) - charts: change canary app version
  • +
  • e1d2a33 (registry-proxy) - charts: add diagnostic mode
  • +
  • 3eabfdd (registry-proxy) - charts: remove default limits
  • +
  • f8754da (registry-proxy) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 7df7316 (registry-proxy) - charts: change canary app version
  • +
  • 861d3b8 (storage) - filer: modify the default parameters of the filer
  • +
  • 5fa08da (storage) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 22c4620 (storage) - charts: change canary app version
  • +
  • 6c1e29c (timeseries) - postgres: add patroni params
  • +
  • e280d3f (timeseries) - dockerfile: install vi
  • +
  • 5213617 (timeseries) - dockerfile: install vim instand of vi
  • +
  • a569a57 (timeseries) - charts: add diagnostic mode
  • +
  • b93ec70 (timeseries) - woodpecker: migrations woodpecker-ci to 2
  • +
  • ff3b870 (timeseries) - charts: change canary app version
  • +
  • e334f74 (workflow-cli) - healthcheck: delete outdated healthcheck style
  • +
  • 4f8b960 (workflow-cli) - auth: add password login
  • +
+ +
+ + + + + + + + + + + + + + + + +
+

Drycc Workflow v1.7.5

+
New Drycc Workflow Release v1.7.5
+ +

These release notes for Drycc Workflow v1.7.5 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.7.4, please refer to the following change summary.

+

Workflow ## v1.7.4 -> v1.7.5

+

Releases

+
    +
  • builder v1.5.0 -> v1.5.1
  • +
  • controller v1.6.3 -> v1.7.0
  • +
  • logger v1.3.2 -> v1.3.3
  • +
  • storage v0.0.3 -> v0.0.4
  • +
  • redis v1.3.1 -> v1.3.2
  • +
  • rabbitmq v1.2.0 -> v1.2.1
  • +
  • registry v1.2.1 -> v1.2.2
  • +
  • workflow-cli v1.5.1 -> v1.5.2
  • +
+

Features

+
    +
  • 95d130a (controller) - controller: volume support nfs
  • +
+

Fixes

+
    +
  • ee2ee15 (controller) - controller: container entrypoint error
  • +
  • 03ea4f8 (controller) - controller: class property have been deprecated in python 3.11
  • +
  • 5f04d17 (controller) - controller: miss err msg
  • +
  • 27972a3 (controller) - controller: load_db_state_to_k8s err
  • +
  • a005d62 (controller) - controller: volume repeat path no error
  • +
  • c7a5ba6 (rabbitmq) - rabbitmq: cpu usage to high
  • +
  • 45c2077 (workflow-cli) - workflow-cli: miss err msg
  • +
  • bc738bd (workflow-cli) - workflow-cli: volumes list format
  • +
+

Maintenance

+
    +
  • 35e1c06 (builder) - builder: bump golang 1.22
  • +
  • 26caa36 (controller) - deps: bump aiohttp from 3.9.0 to 3.9.2 in /rootfs (#118)
  • +
  • 3d938c4 (controller) - deps: bump django from 4.2.7 to 4.2.10
  • +
  • e625c2f (logger) - logger: bump golang 1.22
  • +
  • bfa500d (redis) - redis: headless svc does not require ports
  • +
  • 330209a (registry) - registry: headless svc does not require ports
  • +
  • 48c42eb (storage) - storage: change volume index to leveldb
  • +
  • f4fde9d (storage) - storage: add volume size limit
  • +
  • 33e3684 (workflow-cli) - workflow-cli: volume support nfs
  • +
  • 48d5950 (workflow-cli) - workflow-cli: bump golang 1.22
  • +
+ +
+ + + + + + + + + + + + + + + + +
+

Drycc Workflow v1.7.6

+
New Drycc Workflow Release v1.7.6
+ +

Workflow ## v1.7.5 -> v1.7.6

+

Releases

+
    +
  • storage v0.0.4 -> v0.0.5
  • +
+

Maintenance

+
    +
  • 6cb63b6 (storage) - seaweedfs: bump version 3.63
  • +
+ +
+ + + + + + + + + + + + + + + + +
+

Drycc Workflow v1.7.2

+
New Drycc Workflow Release v1.7.2
+ +

These release notes for Drycc Workflow v1.7.2 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.7.1, please refer to the following change summary.

+

Workflow ## v1.7.1 -> v1.7.2

+

Releases

+
    +
  • controller v1.6.0 -> v1.6.1
  • +
  • logger v1.3.1 -> v1.3.2
  • +
  • storage v0.0.1 -> v0.0.2
  • +
  • timeseries v0.0.1 -> v0.0.2
  • +
  • prometheus v0.1.0 -> v0.1.1
  • +
  • workflow-cli v1.5.0 -> v1.5.1
  • +
+

Fixes

+
    +
  • 2fe80a6 (controller) - resources: after resources instance update, could not delete (#111)
  • +
  • a4082ad (controller) - controller: resource status and binding
  • +
  • e9bfccc (controller) - controller: fix multiple volumes mount at one dir error (#116)
  • +
  • 58d2b4c (logger) - logger: redis conn error block
  • +
  • 7cb2700 (prometheus) - prometheus: prometheus config basic_auth
  • +
  • 7838c6b (storage) - storage: random accesskey secretkey
  • +
  • d9dcdfb (storage) - storage: pod restart loses data
  • +
  • 3cbdd29 (storage) - storage: tipd cannot start after deleting pod
  • +
  • be7e11f (storage) - storage: jq command not found
  • +
  • 878f674 (storage) - storage: charts updateStrategy error
  • +
  • 06cfe56 (timeseries) - timeseries: the data node ip is incorrect
  • +
+

Maintenance

+
    +
  • 7f29f5a (controller) - resources: retrieve resource instance response add message (#112)
  • +
  • 4a84dcd (controller) - controller: add deploy default annotations (#113)
  • +
  • 829d7e5 (controller) - controller: modify url match service name (#114)
  • +
  • 30abf6d (controller) - controller: transfer app ownership in async
  • +
  • dc6f45e (controller) - controller: add channel for pod exec
  • +
  • af4f3a7 (controller) - controller: avoid error when secret no data field (#117)
  • +
  • ca27956 (controller) - controller: add pod default security
  • +
  • b2e9c64 (prometheus) - charts: node-exporter mount root (#2)
  • +
  • 3cdb2b6 (storage) - storage: bump seaweedfs 3.61
  • +
  • 00dd2fd (storage) - storage: add csi daemonset updateStrategy
  • +
  • 48e763c (storage) - storage: add drycc storage upgrade document
  • +
  • 841df90 (storage) - storage: bump seaweedfs 3.62
  • +
  • cefd52e (timeseries) - timeseries: add check data node exists
  • +
  • ad1c46e (workflow-cli) - resources: resources instance add message
  • +
  • 9f955c2 (workflow-cli) - workflow-cli: add short options cpu
  • +
  • 65399ef (workflow-cli) - workflow-cli: add tty resize support
  • +
+ +
+ + + + + + + + + + + + + + + + +
+

Drycc Workflow v1.7.0

+
New Drycc Workflow Release v1.7.0
+ +

These release notes for Drycc Workflow v1.7.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.6.0, please refer to the following change summary.

+

Workflow ## v1.6.0 -> v1.7.0

+

Releases

+
    +
  • builder v1.4.0 -> v1.5.0
  • +
  • controller v1.5.1 -> v1.6.0
  • +
  • database v1.2.0 -> v1.2.1
  • +
  • passport v1.1.0 -> v1.2.0
  • +
  • imagebuilder v1.1.0 -> v1.1.1
  • +
  • fluentbit v0.0.0 -> v0.0.1
  • +
  • logger v1.3.0 -> v1.3.1
  • +
  • storage v0.0.0 -> v0.0.1
  • +
  • gateway v0.0.0 -> v0.0.1
  • +
  • monitor v1.3.0 -> v1.4.0
  • +
  • redis v1.3.0 -> v1.3.1
  • +
  • timeseries v0.0.0 -> v0.0.1
  • +
  • prometheus v0.0.0 -> v0.1.0
  • +
  • rabbitmq v1.1.0 -> v1.2.0
  • +
  • registry v1.2.0 -> v1.2.1
  • +
  • registry-proxy v1.2.0 -> v1.2.1
  • +
+

Features

+
    +
  • fcbebda (builder) - builder: use TCPRoute expose service
  • +
  • d02bb5d (controller) - controller: support app dns policy config
  • +
  • 9aa968e (controller) - controller: add svc type support
  • +
  • 62e2d34 (controller) - controller: improve the services api
  • +
  • 4393755 (controller) - controller: use gateway replace ingress
  • +
  • 323045d (controller) - controller: add canary support
  • +
  • 3f81c97 (controller) - gateways: add addresses field
  • +
  • 4e64aa7 (controller) - gateways: add addresses field
  • +
  • 02ad581 (monitor) - grafana: add pd tikv dashboard
  • +
  • 2a9e2b0 (monitor) - monitor: add storage monitor
  • +
  • 41d5057 (monitor) - grafana: data source change to prometheus
  • +
  • ec035d1 (monitor) - monitor: usegateway replace ingress
  • +
  • c694c98 (monitor) - grafana: add drycc storage seaweedfs dashboard
  • +
  • 1e1fdc8 (passport) - passport: use gateway replace ingress
  • +
  • ffdb408 (prometheus) - prometheus: use gateway replace ingress
  • +
  • 04152b9 (rabbitmq) - rabbitmq: use gateway replace ingress
  • +
+

Fixes

+
    +
  • 0499500 (builder) - builder: manifest error
  • +
  • 642491d (builder) - builder: no build log
  • +
  • 873d146 (controller) - controller: do not set entrypoint when no procfile
  • +
  • d9028c5 (controller) - controller: pip8 error
  • +
  • 3efcfb7 (controller) - controller: manifest error
  • +
  • 18a3a1a (controller) - controller: miss service error
  • +
  • 94f796c (controller) - controller: drycc run pod should not restart
  • +
  • 80f3161 (controller) - controller: monitor query error
  • +
  • b76f2c5 (controller) - controller: read websocket delay
  • +
  • b6e068e (controller) - controller: metrics sql tpl, gateway pod should not restart, cleanup old rs, update monitor datatbase config
  • +
  • ad9adc6 (controller) - controller: rabbitmq sharding err
  • +
  • 6773907 (controller) - controller: default k8s pod annotaions
  • +
  • ffcf1f9 (controller) - controller: under-indented for visual indent
  • +
  • 3afd0cf (controller) - controller: charts env error
  • +
  • 769bb8b (database) - database: manifest error
  • +
  • 769bb8b (database) - database: label conflict error
  • +
  • 6a321c5 (database) - database: link error
  • +
  • 558feae (fluentbit) - fluentbit: build charts error
  • +
  • 98d8a2a (gateway) - fixup
  • +
  • 8b5dde1 (gateway) - gateway: secretName
  • +
  • 702866d (gateway) - gateway: build status
  • +
  • f55dac1 (imagebuilder) - imagebuilder: manifest error
  • +
  • ac13b5f (imagebuilder) - imagebuilder: build svg
  • +
  • 6b7bbc5 (logger) - logger: manifest error
  • +
  • 0136b5c (monitor) - monitor: manifest error
  • +
  • f03d975 (passport) - passport: DRYCC_GRAFANA_DOMAIN error
  • +
  • b530ea8 (passport) - passport: manifest error
  • +
  • be5a0a7 (passport) - passport: change passport
  • +
  • 1596c7f (rabbitmq) - rabbitmq: manifest error
  • +
  • 0dc4f6f (rabbitmq) - rabbitmq: images-shard error
  • +
  • 43293ae (redis) - redis: manifest error
  • +
  • ca13b7d (registry) - registry: manifest error
  • +
  • ab5c793 (registry) - registry: garbage collect error
  • +
  • ab0fabc (registry-proxy) - registry-proxy: manifest error
  • +
  • dfc7236 (registry-proxy) - registry-proxy: daemon yaml format
  • +
  • 42c03be (storage) - storage: seaweedfs csi error
  • +
  • 453e41a (timeseries) - timeseries: could not register node
  • +
+

Docs

+
    +
  • 5433c89 (gateway) - gateway: add prerequisites
  • +
  • 2f0c5d8 (logger) - logger: change architecture
  • +
+

Maintenance

+
    +
  • bdd02eb (builder) - builder: use dynamic clusterrole name
  • +
  • 66b4b25 (builder) - builder: upgrade new controller-go-sdk
  • +
  • 219d86f (builder) - builder: upgrade go.mod
  • +
  • 91f2f14 (builder) - builder: use woodpecker replace drone
  • +
  • 9abca16 (builder) - woodpecker: use woodpecker ci build status
  • +
  • f43dd50 (builder) - deps: bump golang.org/x/net from 0.2.0 to 0.7.0
  • +
  • 0384c69 (builder) - builder: add chart appVersion
  • +
  • e3149b9 (builder) - builder: upgrade codename to bookworm
  • +
  • d88ea1b (builder) - builder: add codename build-arg
  • +
  • ba59030 (builder) - builder: upgrade go.mod
  • +
  • 1114dd7 (builder) - builder: bump common 1.1.2
  • +
  • fe50b62 (builder) - builder: change drycc gateway listener name
  • +
  • db3950c (builder) - builder: remove gateway route
  • +
  • 5a508bb (builder) - builder: use podman replace docker
  • +
  • bbb9029 (builder) - deps: bump golang.org/x/net from 0.12.0 to 0.17.0
  • +
  • f4e5d6c (builder) - builder: remove health url
  • +
  • 9111c8f (builder) - builder: remove io/ioutil
  • +
  • 1f36e3d (controller) - deps: bump django from 4.1.2 to 4.1.6 in /rootfs
  • +
  • e4ab434 (controller) - controller: use woodpecker replace drone
  • +
  • 9f0301e (controller) - deps: bump django from 4.1.6 to 4.1.7 in /rootfs
  • +
  • 3932423 (controller) - woodpecker: use woodpecker ci build status
  • +
  • ae8b6b4 (controller) - setting: support KUBERNETES_LIMITS env config
  • +
  • c10b9bc (controller) - controller: using the api_version instead of hard coding
  • +
  • e6908cd (controller) - controller: upgrade requirements
  • +
  • b0eba0c (controller) - controller: add route rules serializer
  • +
  • 2e4b6a4 (controller) - controller: add chart appVersion
  • +
  • 7d32b55 (controller) - controller: upgrade to bookworm
  • +
  • f2dc8dd (controller) - controller: add codename build-arg
  • +
  • 5739b83 (controller) - controller: use timescaledb replace influxdb
  • +
  • 53892cb (controller) - controller: add timeseries
  • +
  • 0fe0eae (controller) - controller: upgrade requirements
  • +
  • 18b2a91 (controller) - deps: bump aiohttp from 3.8.4 to 3.8.5 in /rootfs
  • +
  • f50874a (controller) - controller: bump common 1.1.2
  • +
  • 956cd08 (controller) - controller: change drycc gateway listener name
  • +
  • 9ab3ead (controller) - controller: remove passport url check
  • +
  • a24c7b0 (controller) - controller: remove gateway route
  • +
  • f7e539a (controller) - controller: change celery priority
  • +
  • ab77a52 (controller) - controller: use podman replace docker
  • +
  • 8e27501 (controller) - controller: dynamic app storage class
  • +
  • 385978b (controller) - controller: list_pods datetime format
  • +
  • b20362c (controller) - deps: bump django from 4.2.3 to 4.2.7 in /rootfs
  • +
  • e11ae1b (controller) - controller: add cluster migrate
  • +
  • ca6e9df (controller) - controller: async mount
  • +
  • 9a7fbfc (controller) - controller: remove FOSSA
  • +
  • 3d55279 (controller) - deps: bump aiohttp from 3.8.5 to 3.8.6 in /rootfs
  • +
  • d498a11 (controller) - controller: add measure loalancers
  • +
  • 249a985 (controller) - deps: bump aiohttp from 3.8.5 to 3.8.6 in /rootfs
  • +
  • b967f58 (controller) - deps: bump aiohttp from 3.8.6 to 3.9.0 in /rootfs (#107)
  • +
  • 8ca9ed6 (controller) - controller: no longer restrict reserved domain
  • +
  • 9ff6649 (database) - database: add init database configure
  • +
  • 9b4cd26 (database) - database: use dynamic clusterrole name
  • +
  • b59cde4 (database) - database: remove minio require
  • +
  • 86462f8 (database) - database: use woodpecker replace drone
  • +
  • 1e8555a (database) - database: add chart appVersion
  • +
  • 1b762d5 (database) - database: upgrade codename to bookworm
  • +
  • 9ffe1fd (database) - database: add codename build-arg
  • +
  • 69466d7 (database) - database: add database extension
  • +
  • beb4b62 (database) - database: bump common 1.1.2
  • +
  • 67e2714 (database) - database: use podman replace docker
  • +
  • 8f328f8 (fluentbit) - fluentbit: no limit buffer size for kube api
  • +
  • fc0552c (fluentbit) - fluentbit: use podman replace docker
  • +
  • 63a6cab (fluentbit) - fluentbit: change fluentbit match
  • +
  • 220f81a (fluentbit) - fluentbit: run as no-root
  • +
  • aec1393 (fluentbit) - fluentbit: change configmap name
  • +
  • 1af4fd2 (fluentbit) - fluentbit: change default stream name
  • +
  • bef90ad (gateway) - gateway: add route for gateway
  • +
  • d523ddb (gateway) - gateway: change drycc gateway listener name
  • +
  • d9137f4 (gateway) - gateway: add chart appVersion
  • +
  • 0425dd4 (gateway) - gateway: add customListeners
  • +
  • 3982b86 (imagebuilder) - imagebuilder: use woodpecker replace drone
  • +
  • 3e4e7a3 (imagebuilder) - imagebuilder: add chart appVersion
  • +
  • 8df6e8e (imagebuilder) - imagebuilder: upgrade stack version
  • +
  • a5601f7 (imagebuilder) - imagebuilder: add drycc_app env
  • +
  • 07465f8 (imagebuilder) - imagebuilder: upgrade to bookworm
  • +
  • 00d22d2 (imagebuilder) - imagebuilder: add codename build-arg
  • +
  • 0b7a24e (imagebuilder) - imagebuilder: upgrade podman/mc/caddy
  • +
  • a7d8be8 (imagebuilder) - imagebuilder: use podman replace docker
  • +
  • 6b2da83 (logger) - logger: use woodpecker replace drone
  • +
  • 8245b25 (logger) - woodpecker: use woodpecker ci build status
  • +
  • f811a74 (logger) - logger: add chart appVersion
  • +
  • 413f6f6 (logger) - logger: upgrade codename to bookworm
  • +
  • 2ac6b10 (logger) - logger: add codename build-arg
  • +
  • 2581426 (logger) - logger: bump redis to v9
  • +
  • 364b25a (logger) - logger: bump common 1.1.2
  • +
  • dc169a3 (logger) - logger: use fluentbit replace fluentd
  • +
  • d855d91 (logger) - logger: use podman replace docker
  • +
  • f767235 (monitor) - monitor: add off-cluster passport configure
  • +
  • ab23936 (monitor) - monitor: use dynamic clusterrole name
  • +
  • 47beee0 (monitor) - monitor: change tikv secret key
  • +
  • af7703f (monitor) - grafana: remove panel when component off-cluster
  • +
  • 1b870c2 (monitor) - monitor: use woodpecker replace drone
  • +
  • 4a5f1f1 (monitor) - grafana: up ldap api_url config
  • +
  • 143cabe (monitor) - monitor: add prometheus architecture diagram
  • +
  • 93091c2 (monitor) - woodpecker: use woodpecker ci build status
  • +
  • 0b7045a (monitor) - grafana: add dashboard kubernetes_deployment_metrics
  • +
  • 2fb1839 (monitor) - woodpecker: pipeline config VERSION, when build container image
  • +
  • e272416 (monitor) - monitor: add chart appVersion
  • +
  • abc0e53 (monitor) - monitor: upgrade codename to bookworm
  • +
  • 86cc01b (monitor) - monitor: add codename build-arg
  • +
  • 1cd849f (monitor) - monitor: add postgresql outputs
  • +
  • c3205c0 (monitor) - monitor: change default agent config
  • +
  • 8c802c0 (monitor) - monitor: add timeseries database
  • +
  • e9abc40 (monitor) - monitor: bump common 1.1.2
  • +
  • 6af66cd (monitor) - monitor: change drycc gateway listener name
  • +
  • d02d718 (monitor) - monitor: remove gateway route
  • +
  • 3509c29 (monitor) - monitor: use podman replace docker
  • +
  • ed7bfa2 (monitor) - monitor: optimize env PROMETHEUS_URL
  • +
  • da89bef (passport) - passport: charts codereview
  • +
  • 61c4a96 (passport) - passport: support init app config
  • +
  • 9101006 (passport) - passport: add initApplications to charts
  • +
  • 7dd7fa4 (passport) - passport: use woodpecker replace drone
  • +
  • 4400199 (passport) - woodpecker: use woodpecker ci build status
  • +
  • 6b2c546 (passport) - passport: change secret name to drycc-passport-auto-tls
  • +
  • c8bd824 (passport) - passport: upgrade requirements
  • +
  • aee5aef (passport) - passport: add chart appVersion
  • +
  • 2d81953 (passport) - passport: upgrade codename to bookworm
  • +
  • 9e66242 (passport) - passport: add codename build-arg
  • +
  • 0fca998 (passport) - passport: upgrade requirements
  • +
  • 3482528 (passport) - passport: bump common 1.1.2
  • +
  • 0c5ec93 (passport) - passport: change drycc gateway listener name
  • +
  • f7b8f53 (passport) - passport: remove gateway route
  • +
  • baf69da (passport) - passport: use podman replace docker
  • +
  • fcd45dd (passport) - passport: add cluster migrate
  • +
  • da6d32a (prometheus) - prometheus: add prometheus-config
  • +
  • 683de9e (prometheus) - prometheus: use podman replace docker
  • +
  • 3323300 (prometheus) - prometheus: remove gateway route
  • +
  • da1d356 (prometheus) - prometheus: change drycc gateway listener name
  • +
  • 4e7a936 (prometheus) - prometheus: bump common 1.1.2
  • +
  • 44c1c6f (prometheus) - prometheus: add codename build-arg
  • +
  • d1f1dda (prometheus) - prometheus: upgrade codename to bookworm
  • +
  • 0836fc1 (prometheus) - prometheus: add chart appVersion
  • +
  • 9e13232 (prometheus) - prometheus: add LICENSE
  • +
  • f53e14a (rabbitmq) - rabbitmq: remove auto user
  • +
  • 0ec7277 (rabbitmq) - rabbitmq: use woodpecker replace drone
  • +
  • f376a30 (rabbitmq) - woodpecker: use woodpecker ci build status
  • +
  • 51405d8 (rabbitmq) - rabbitmq: add chart appVersion
  • +
  • 463ca03 (rabbitmq) - rabbitmq: upgrade codename to bookworm
  • +
  • 1978a71 (rabbitmq) - rabbitmq: add codename build-arg
  • +
  • 139277f (rabbitmq) - rabbitmq: bump common 1.1.2
  • +
  • be49741 (rabbitmq) - rabbitmq: change drycc gateway listener name
  • +
  • 6d22518 (rabbitmq) - rabbitmq: remove gateway route
  • +
  • 0eb7833 (rabbitmq) - rabbitmq: add check shards
  • +
  • 9211063 (rabbitmq) - rabbitmq: erlang vm tuning optimization
  • +
  • 648a78d (rabbitmq) - rabbitmq: use podman replace docker
  • +
  • 0b43a4d (rabbitmq) - rabbitmq: add x-random exchange
  • +
  • ad1c4da (redis) - redis: use woodpecker replace drone
  • +
  • 3f37f92 (redis) - redis: add chart appVersion
  • +
  • e3bef7a (redis) - redis: upgrade codename to bookworm
  • +
  • 4e806d4 (redis) - redis: add codename build-arg
  • +
  • d5023be (redis) - redis: bump common 1.1.2
  • +
  • 98f5d6f (redis) - redis: use podman replace docker
  • +
  • 063f29e (registry) - registry: use woodpecker replace drone
  • +
  • 17bf8ae (registry) - woodpecker: use woodpecker ci build status
  • +
  • 7bbad15 (registry) - registry: add chart appVersion
  • +
  • 279154f (registry) - registry: upgrade codename to bookworm
  • +
  • 3e4ae84 (registry) - registry: add codename build-arg
  • +
  • fa322d6 (registry) - registry: bump common 1.1.2
  • +
  • 6c18fe0 (registry) - registry: use podman replace docker
  • +
  • 0bc8472 (registry) - registry: remove health url
  • +
  • 5dacd9f (registry) - registry: add wait-for-port check
  • +
  • fdeefc3 (registry) - registry: use headless
  • +
  • 08bf9f8 (registry) - registry: change registry port to 5000
  • +
  • 40bcea2 (registry) - registry: add registry push test
  • +
  • 871b8e7 (registry) - registry: add default env
  • +
  • 7f3b3ac (registry) - registry: bump registry 2.8.3
  • +
  • 569f15d (registry-proxy) - registry-proxy: use woodpecker replace drone
  • +
  • cc33caf (registry-proxy) - woodpecker: use woodpecker ci build status
  • +
  • 0002aab (registry-proxy) - registry-proxy: add chart appVersion
  • +
  • 40af10b (registry-proxy) - registry-proxy: upgrade codename to bookworm
  • +
  • c56b9df (registry-proxy) - registry-proxy: add codename build-arg
  • +
  • 9d5bfe0 (registry-proxy) - registry-proxy: use podman replace docker
  • +
  • e6a3350 (registry-proxy) - registry-proxy: change worker_processes to 1
  • +
  • 726f39d (storage) - storage: add volume compactionMBps
  • +
  • a5aa2d8 (storage) - storage: add threshold to vacuum and reclaim spaces
  • +
  • e687d04 (storage) - storage: delete disk type in single disk case
  • +
  • 75ee2e4 (storage) - storage: change datanode replicas to 4
  • +
  • c5fd7ba (storage) - storage: delete useless env
  • +
  • b3826ea (storage) - storage: add ssd hdd dir
  • +
  • 29881a0 (storage) - storage: add balance cronjob
  • +
  • c5a0f51 (storage) - storage: add defaultReplication for seaweedfs master
  • +
  • 543c7a2 (timeseries) - timeseries: use podman replace docker
  • +
  • 5376024 (timeseries) - timeseries: update timeseries-service-replica
  • +
  • 52e8520 (timeseries) - timeseries: bump common 1.1.2
  • +
  • f82657c (timeseries) - timeseries: add start script
  • +
+ +
+ + + + + + + + + + + + + + + + +
+

Drycc Workflow v1.6.0

+
New Drycc Workflow Release v1.6.0
+ +

These release notes for Drycc Workflow v1.6.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.5.0, please refer to the following change summary.

+

Workflow ## v1.5.0 -> v1.6.0

+

Releases

+
    +
  • builder v1.3.0 -> v1.4.0
  • +
  • controller v1.4.0 -> v1.5.0
  • +
  • passport v1.0.0 -> v1.1.0
  • +
  • database v1.1.0 -> v1.2.0
  • +
  • imagebuilder v1.0.1 -> v1.1.0
  • +
  • fluentd v1.2.0 -> v1.3.0
  • +
  • logger v1.2.0 -> v1.3.0
  • +
  • storage v1.2.0 -> v1.3.0
  • +
  • monitor v1.2.0 -> v1.3.0
  • +
  • redis v1.2.0 -> v1.3.0
  • +
  • influxdb v1.1.0 -> v1.2.0
  • +
  • rabbitmq v1.0.0 -> v1.1.0
  • +
  • registry v1.1.0 -> v1.2.0
  • +
  • registry-proxy v1.1.0 -> v1.2.0
  • +
+

Features

+
    +
  • 52517d9 (builder) - builder: update controller-sdk-go
  • +
  • 1d78ca0 (builder) - builder: add affinity
  • +
  • 26b6980 (builder) - builder: switch charts to oci
  • +
  • bfd4385 (controller) - controller: add get manager user status
  • +
  • 874208d (controller) - controller: unified measurement model
  • +
  • cadf98f (controller) - controller: add admission webhook
  • +
  • e0050c2 (controller) - controller: new measurement model
  • +
  • a11ba58 (controller) - controller: multi pod restart uses async
  • +
  • fb3c15d (controller) - controller: add check app owner status
  • +
  • 3d78b76 (controller) - controller: add resource services api
  • +
  • 3d6a201 (controller) - controller: add search apps api
  • +
  • 01c443a (controller) - controller: add KUBERNETES_CPU_MEMORY_RATIO parameter
  • +
  • 7c26232 (controller) - controller: add volume size limit
  • +
  • 3bee749 (controller) - controller: add annotations support
  • +
  • 23cd97c (controller) - controller: traefik v2 support
  • +
  • e37b7db (controller) - controller: add affinity
  • +
  • b3b367b (controller) - controller: add volume expand support
  • +
  • a4e154a (controller) - controller: add database replica support
  • +
  • 2f37216 (controller) - controller: switch wsgi to asgi
  • +
  • b3314a5 (controller) - controller: add pod exec api
  • +
  • 75df2dc (controller) - controller: add stream support for app logs
  • +
  • 4229bad (controller) - ccontroller: switch charts to oci
  • +
  • 89bb19b (database) - database: upgrade to pg14
  • +
  • 9f45a5d (database) - database: add hugepages support
  • +
  • c4008c9 (database) - database: add affinity
  • +
  • 411a7b2 (database) - postgres: use patroni
  • +
  • 64e5cb0 (database) - database: switch charts to oci
  • +
  • 2bab823 (fluentd) - fluentd: switch charts to oci
  • +
  • 337ba62 (imagebuilder) - imagebuilder: run podman as rootless
  • +
  • 4396ffa (imagebuilder) - imagebuilder: switch to oci charts
  • +
  • f37ae09 (influxdb) - influxdb: add affinity
  • +
  • 04503b2 (influxdb) - influxdb: add influxdb ha
  • +
  • 41ddad5 (influxdb) - influxdb: switch charts to oci
  • +
  • 2006480 (logger) - logger: use redis stream replace nsqd
  • +
  • ab23d17 (logger) - logger: add affinity
  • +
  • 81d4e9d (logger) - logger: switch charts to oci
  • +
  • c3d9796 (monitor) - monitor: add affinity
  • +
  • cd9de3c (monitor) - monitor: switch to oci charts
  • +
  • 318a73f (passport) - passport: add change user confirm
  • +
  • 79ef100 (passport) - passport: add re login at authorize
  • +
  • 6927bb5 (passport) - passport: add affinity
  • +
  • 3146a09 (passport) - passport: add google reCAPTCHA
  • +
  • 802abcd (passport) - passport: add replica database support
  • +
  • a0dcd1b (passport) - passport: switch wsgi to asgi
  • +
  • 4c9dbba (passport) - passport: switch charts to oci
  • +
  • 74825f7 (rabbitmq) - rabbitmq: add rabbitmq managentment ingress
  • +
  • 12cf7d6 (rabbitmq) - rabbitmq: add affinity
  • +
  • 103417d (rabbitmq) - rabbitmq: switch charts to oci
  • +
  • 5d428bb (redis) - redis: add affinity
  • +
  • a88c1a9 (redis) - redis: switch charts to oci
  • +
  • 541585d (registry) - registry: add affinity
  • +
  • e9ca9d4 (registry) - registry: add garbage-collect cronjob
  • +
  • ec62a59 (registry) - registry: switch charts to oci
  • +
  • fde0b07 (registry-proxy) - registry-proxy: switch charts to oci
  • +
  • be14eb4 (storage) - minio: add affinity
  • +
  • 51af696 (storage) - storage: add k8s csi support
  • +
  • 76a75d9 (storage) - storage: add cluster health checker
  • +
  • a17dc8c (storage) - storage: switch charts to oci
  • +
+

Fixes

+
    +
  • e4f44fb (builder) - builder: no error return
  • +
  • e38dfc7 (builder) - builderControllerHost/ControllerPort init error
  • +
  • ff9069f (controller) - controller: influxdb query error
  • +
  • f7f5069 (controller) - controller: authentication 500
  • +
  • 7e297a8 (controller) - controller: add check remote user status
  • +
  • 9db28e1 (controller) - controller: celery MaxRetriesExceededError
  • +
  • 4bcff08 (controller) - controller: wrong name
  • +
  • d69fde2 (controller) - controller: traefik ingress create error
  • +
  • a3ad743 (controller) - fixup(controller: user login error
  • +
  • 662c8dd (controller) - controller: change influxdb port
  • +
  • 957bdf6 (controller) - controller: validate rsa key pairing before storage
  • +
  • 419ec4c (controller) - controller: kubernetes pod/exec cluster role
  • +
  • a67edaa (controller) - controller: Cannot routing:disable
  • +
  • e09e214 (controller) - controller: allowlist cannot remove
  • +
  • 318b126 (controller) - controller: domains update error
  • +
  • 92855eb (database) - database: premission denied
  • +
  • bde945a (database) - fixup(postgres: support arm, fix Failed to build psutil
  • +
  • 7854d45 (database) - fixup(postgres: user name converted to lowercase letters
  • +
  • 57b2a07 (fluentd) - fluentd: ifconfig_path not found
  • +
  • 20e72b9 (imagebuilder) - imagebuilder: upgrade pack version
  • +
  • 651db8a (imagebuilder) - imagebuilder: chown uid gid order
  • +
  • d2e9164 (influxdb) - influxdb: proxy not running
  • +
  • 3a1d361 (monitor) - monitor: charts naming
  • +
  • d754ae0 (monitor) - monitor: telegraf init error
  • +
  • 63f9e34 (monitor) - monitor: affinity error
  • +
  • 95ae1e5 (passport) - passport: yarn build fail
  • +
  • 3f5365e (passport) - passport: wrong name
  • +
  • 907f17b (passport) - passport: change uid gid to 1001
  • +
  • e3911e0 (passport) - passport: ‘registration_done’ not found
  • +
  • 2ace5f0 (passport) - passport: ui style
  • +
  • b3ba1e1 (passport) - passport privacy policy link
  • +
  • 172e9c8 (passport) - passport: check databaseReplicaUrl error
  • +
  • a3aeb70 (rabbitmq) - passport: change uid gid to 1001
  • +
  • 5c73dcf (redis) - reids: DRYCC_REGISTY misspelling
  • +
  • d7e3baf (redis) - redis: env miss
  • +
  • cadaa91 (registry) - registry: set gid uid to 1001
  • +
  • d524217 (registry) - registry: storage run error
  • +
  • 854f912 (registry) - registry: chown uid gid order
  • +
  • e642bb7 (registry-proxy) - registry-proxy: containerPort error
  • +
  • 8dfd029 (registry-proxy) - registry-proxy: chown uid gid order
  • +
  • bbea364 (storage) - minio: premission denied
  • +
  • 97deba1 (storage) - storage: node unimplemented error
  • +
  • b9bdeff (storage) - storage: pd can not connect each other
  • +
+

Style

+
    +
  • 1edb10c (controller) - controller: database convention over configuration
  • +
  • 1960cc3 (database) - database: database name convention over configuration
  • +
  • 06d1f5d (imagebuilder) - imagebuilder: URL to Url
  • +
  • b8a8941 (passport) - passport: database convention over configuration
  • +
+

Maintenance

+
    +
  • 8e9a199 (builder) - builder: upgrade controller-sdk-go
  • +
  • 4840151 (builder) - builder: use exec runner replace docker runner
  • +
  • 68ccfb1 (builder) - builder: canonical charts naming
  • +
  • 8f971cb (builder) - builder: provide any additional service annotations
  • +
  • fe2c55d (builder) - dockerfile: use drycc/base image
  • +
  • 2b5e706 (builder) - dockerfile: change user and workdir
  • +
  • 7a6c8d3 (builder) - builder: set gid uid to 1001
  • +
  • fe494f7 (builder) - dockerfile: use uid gid
  • +
  • a7c8752 (builder) - builder: change nodes to pod affinity
  • +
  • eb2e94c (builder) - database: bump mc 2022.04.01.23.44.48
  • +
  • cfaae66 (builder) - builder: use registry.drycc.cc replace docker.io
  • +
  • d7d2890 (builder) - builder: change default imagebuilder registry
  • +
  • ecfdb19 (builder) - imagebuilder: change python-dev registry
  • +
  • 6da17f4 (builder) - builder: https://github.com/minio/minio/issues/14331
  • +
  • 1a57e5b (builder) - builder: https://github.com/minio/minio/issues/14331
  • +
  • f1464fa (builder) - builder: https://github.com/minio/minio/issues/13799
  • +
  • b1e1c4f (builder) - builder: use env replace creds volume
  • +
  • 71a4145 (builder) - builder: bump go.mod
  • +
  • 3567688 (builder) - builder: fine management affinity
  • +
  • 73ea38b (builder) - builder: change storage to minio
  • +
  • 1f91321 (builder) - builder: use testify replace assert
  • +
  • d148b9c (builder) - builder: add check storage health
  • +
  • b768101 (builder) - builder: change initContainers
  • +
  • 1b3bec3 (builder) - builder: add replicas
  • +
  • 5cb0d61 (builder) - builder: upgrade to latest controller-sdk-go
  • +
  • 98b9d58 (builder) - builder: upgrade new require
  • +
  • 65817c3 (builder) - builder: change drycc.cc to www.drycc.cc
  • +
  • 4e3f9d0 (controller) - controller: add celery retry mechanism
  • +
  • f6716fe (controller) - controller: change cronjob name
  • +
  • eb60693 (controller) - controller: refine celery task priority
  • +
  • 66905e9 (controller) - controller: change manager auth
  • +
  • ea20c41 (controller) - controller: remove start/stop api
  • +
  • 4c8fc80 (controller) - controller: improve tasks error handling
  • +
  • cf7402e (controller) - controller: add blocklist api
  • +
  • 80f14dd (controller) - controller: use get_user_model replace auth.User
  • +
  • ffc7bb7 (controller) - controller: use JSONField replace ArrayField
  • +
  • 370df8c (controller) - controller: add validate metric
  • +
  • 29084ce (controller) - controller: use user id request manager api
  • +
  • 718fe12 (controller) - controller change urlpatterns order
  • +
  • 71f4042 (controller) - controller: measurements uses lowercase letters
  • +
  • e5123ea (controller) - controller: change resource unit to number
  • +
  • 18fee9a (controller) - deps: bump celery from 5.1.2 to 5.2.2 in /rootfs
  • +
  • ffca6c1 (controller) - controller: use exec runner replace docker runner
  • +
  • 9ec12e1 (controller) - controller: simplify drone configuration
  • +
  • 4b4749e (controller) - controller: set default CSRF_COOKIE_SECURE false
  • +
  • 2ef6338 (controller) - deps: bump django from 3.2.5 to 3.2.10 in /rootfs
  • +
  • c7570d0 (controller) - deps: bump django from 3.2.10 to 3.2.11 in /rootfs
  • +
  • 8b17bc1 (controller) - controller: canonical charts naming
  • +
  • c928fb0 (controller) - controller: use rabbitmq cluster
  • +
  • f917185 (controller) - controller: provide any additional service annotations
  • +
  • 22a8f63 (controller) - deps: bump django from 3.2.11 to 3.2.12 in /rootfs
  • +
  • 3cc3b00 (controller) - dockerfile: use drycc/base image
  • +
  • ee274f6 (controller) - controller: set venv profile
  • +
  • ce6b069 (controller) - controller: set gid uid to 1001
  • +
  • 3a105d3 (controller) - dockerfile: use uid gid
  • +
  • 15f9b0e (controller) - controller: code review
  • +
  • 01e6fd9 (controller) - controller: use passport user id
  • +
  • 893ee31 (controller) - oauth2: update user info pipline
  • +
  • 3028fb4 (controller) - user: set AnonymousUser username
  • +
  • 5daf82d (controller) - controller: set worker_cancel_long_running_tasks_on_connection_loss
  • +
  • 61f2c53 (controller) - controller: change nodes to pod affinity
  • +
  • 88feb1d (controller) - imagebuilder: python=3.10.4 rabbitmq=3.9.14
  • +
  • 914e03f (controller) - controller: use registry.drycc.cc replace docker.io
  • +
  • a5bb548 (controller) - controller: change python-dev registry
  • +
  • 3ecdd7c (controller) - controller: add a separate rabbitmqUrl configuration
  • +
  • 967cb11 (controller) - controller: remove APP_STORAGE
  • +
  • 473d2b5 (controller) - controller: use env replace creds volume
  • +
  • e410d4c (controller) - deps: bump django from 3.2.12 to 3.2.13 in /rootfs
  • +
  • c6ef777 (controller) - controller: simplified passport config
  • +
  • 0fd3233 (controller) - controller: remove settings hardcode
  • +
  • a64e99c (controller) - controller: change passport config
  • +
  • 62aba25 (controller) - controller: set cronjob timezone to utc
  • +
  • 760b70b (controller) - controller: change default ratio
  • +
  • 8dffc3a (controller) - controller: fine management affinity
  • +
  • 26043c4 (controller) - controller: change default app storage
  • +
  • 608bd8d (controller) - deps: bump django from 3.2.13 to 3.2.14 in /rootfs
  • +
  • 18ed0c2 (controller) - controller: remove conjob affinity
  • +
  • add6712 (controller) - controller: add volume expand support use patch
  • +
  • cc1ad13 (controller) - controller: add startupProbe
  • +
  • 0e9a603 (controller) - controller: add clearsocial cronjob
  • +
  • eb6f05d (controller) - controller: change initContainers
  • +
  • 762c676 (controller) - controller: change replicas
  • +
  • abd7e8c (controller) - deps: bump django from 3.2.14 to 3.2.15 in /rootfs
  • +
  • 07fdf1b (controller) - controller: remove database conn_max_age
  • +
  • ef8e41f (controller) - controller: add database replica check
  • +
  • 79143f2 (controller) - controller: upgrade new require
  • +
  • a624048 (controller) - controller: add app.refresh func annotation
  • +
  • b22d367 (controller) - controller: optimize app refresh timing
  • +
  • fe98f0c (database) - database: use exec runner replace docker runner
  • +
  • 5e00c11 (database) - database: canonical charts naming
  • +
  • d2cb860 (database) - database: disable huge_pages
  • +
  • 197d80d (database) - database: add persistence
  • +
  • 1c3e645 (database) - database: provide any additional service annotations
  • +
  • 37730ab (database) - dockerfile: use drycc/base image
  • +
  • 5014112 (database) - dockerfile: change entrypoint
  • +
  • 29b538e (database) - database: change nodes to pod affinity
  • +
  • c2bb074 (database) - database: bump python 3.10.4 and mc 2022.04.01.23.44.48
  • +
  • 077a4e9 (database) - database: use registry.drycc.cc replace docker.io
  • +
  • 560bdb9 (database) - database: change python-dev registry
  • +
  • 1e54b55 (database) - database: https://github.com/minio/minio/issues/14331
  • +
  • d646672 (database) - database: https://github.com/minio/minio/issues/13799
  • +
  • a6ac4e3 (database) - database: use env replace creds volume
  • +
  • 9618d87 (database) - database: fine management affinity
  • +
  • b823273 (database) - database: change minio to storage
  • +
  • 7bd5a90 (database) - database: add check storage health
  • +
  • 20c6d96 (database) - database: fix storage run error
  • +
  • 8bde830 (database) - database: upgrade to pg 14.5
  • +
  • a33b5e5 (fluentd) - fluentd: update plugins
  • +
  • eed7a78 (fluentd) - fluentd: update filter kubernetes setting
  • +
  • cc83dd8 (fluentd) - fluentd: update elasticsearch store setting and support exclude specific container logs
  • +
  • ba2feb2 (fluentd) - fluentd: use exec runner replace docker runner
  • +
  • d528676 (fluentd) - fluentd: simplify drone configuration
  • +
  • dece82d (fluentd) - fluentd: canonical charts naming
  • +
  • 4e0a802 (fluentd) - fluend: replace nsqd with redis
  • +
  • 15ceca0 (fluentd) - dockerfile: use drycc/base image
  • +
  • a7f619f (fluentd) - dockerfile: change workdir
  • +
  • 9adf5ed (fluentd) - database: bump fluentd 1.14.6
  • +
  • 50c14c2 (fluentd) - fluentd: use registry.drycc.cc replace docker.io
  • +
  • 83171b1 (fluentd) - fluentd: change python-dev registry
  • +
  • ec83581 (fluentd) - fluentd: unified reids declaration
  • +
  • 07c63e2 (fluentd) - fluentd: upgrade fluentd 1.15.2
  • +
  • 65df9be (imagebuilder) - imagebuilder: update pack version
  • +
  • 66cab35 (imagebuilder) - imagebuilder: use dind replace go-dev
  • +
  • 0c82060 (imagebuilder) - imagebuilder: use exec runner replace docker runner
  • +
  • 8146da9 (imagebuilder) - imagebuilder: canonical charts naming
  • +
  • 7d97241 (imagebuilder) - dockerfile: use drycc/base image
  • +
  • 07e805c (imagebuilder) - imagebuilder: change default buildpack
  • +
  • 8d1038d (imagebuilder) - imagebuilder: upgrade podman to 4.0.1
  • +
  • 62d3687 (imagebuilder) - imagebuilder: change workdir to /workspace
  • +
  • da8bfb0 (imagebuilder) - imagebuilder: change uid gid to 1001
  • +
  • d44e3bc (imagebuilder) - imagebuilder: upgrade stack
  • +
  • 5b0c7e6 (imagebuilder) - imagebuilder: use registry.drycc.cc replace docker.io
  • +
  • f74cbf6 (imagebuilder) - imagebuilder: add defaultBuildpacksURL
  • +
  • 941d493 (imagebuilder) - imagebuilder: https://github.com/minio/minio/issues/14331
  • +
  • 449be91 (imagebuilder) - imagebuilder: https://github.com/minio/minio/issues/13799
  • +
  • 63b0523 (imagebuilder) - imagebuilder: use env replace creds volume
  • +
  • 4e8a6e5 (imagebuilder) - imagebuilder: add imagebuilder config
  • +
  • 2d891f5 (imagebuilder) - imagebuilder: change minio to storage
  • +
  • addceda (imagebuilder) - imagebuilder: upgrade new require
  • +
  • a6e569f (imagebuilder) - imagebuilder: pack_build add –env-file parameter
  • +
  • 6191ff5 (influxdb) - influxdb: use exec runner replace docker runner
  • +
  • dc3f8c7 (influxdb) - influxdb: canonical charts naming
  • +
  • 6b5c819 (influxdb) - influxdb: new ingress style
  • +
  • 68b381d (influxdb) - influxdb: provide any additional service annotations
  • +
  • ea20eb8 (influxdb) - dockerfile: use drycc/base image
  • +
  • 64c0a71 (influxdb) - influxdb: set gid uid to 1001
  • +
  • a709ca1 (influxdb) - influxdb: use DRYCC_UID DRYCC_GID env
  • +
  • 740dff0 (influxdb) - influxdb: use common affinity template
  • +
  • e035673 (influxdb) - influxdb: change nodes to pod affinity
  • +
  • f1cefbd (influxdb) - influxdb: use registry.drycc.cc replace docker.io
  • +
  • a00100e (influxdb) - influxdb: fine management affinity
  • +
  • 9d165ef (influxdb) - influxdb: add probe
  • +
  • bee7fff (influxdb) - influxdb: upgrade to influxdb 2.4.0
  • +
  • 254914c (logger) - logger: use exec runner replace docker runner
  • +
  • 8d91c68 (logger) - logger: canonical charts naming
  • +
  • b6d2182 (logger) - logger: provide any additional service annotations
  • +
  • c35e59a (logger) - dockerfile: use drycc/base image
  • +
  • a63c070 (logger) - logger: change workdir to /workspace
  • +
  • a594b28 (logger) - logger: set gid uid to 1001
  • +
  • 9a90e22 (logger) - dockerfile: use uid gid
  • +
  • 36493b4 (logger) - logger: use common affinity template
  • +
  • 897a3a5 (logger) - logger: change nodes to pod affinity
  • +
  • 03b32ab (logger) - logger: use registry.drycc.cc replace docker.io
  • +
  • a50ba5f (logger) - logger: change python-dev registry
  • +
  • 23187a3 (logger) - logger: unified reids declaration
  • +
  • aaa129a (logger) - logger: fine management affinity
  • +
  • be4f656 (logger) - logger: add replicas
  • +
  • 7c25459 (logger) - charts: add NetworkPolicy
  • +
  • 6810149 (logger) - logger: remove memory storage
  • +
  • a918c50 (logger) - logger: add .vscode to .gitignore
  • +
  • a415210 (logger) - logger: add log follow support
  • +
  • 59b1da3 (logger) - logger: upgrade new require
  • +
  • 27cc151 (monitor) - monitor: use exec runner replace docker runner
  • +
  • 07d6a9d (monitor) - monitor: canonical charts naming
  • +
  • 1054357 (monitor) - monitor: use redis default port
  • +
  • e3673df (monitor) - monitor: remove nsqd
  • +
  • fc9dd3e (monitor) - monitor: new ingress style
  • +
  • 856a898 (monitor) - monitor: add default user env
  • +
  • 9857535 (monitor) - monitor: add random user
  • +
  • 38b5a04 (monitor) - grafana: oauth auto login
  • +
  • 5dfc579 (monitor) - monitor: upgrade version
  • +
  • e121b5a (monitor) - monitor: provide any additional service annotations
  • +
  • 84462a0 (monitor) - dockerfile: use drycc/base image
  • +
  • b9e8ce8 (monitor) - monitor: chore(imagebuilder): change uid gid to 1001
  • +
  • 05ee8ab (monitor) - dockerfile: use uid gid
  • +
  • e1fa68e (monitor) - monitor: use common affinity template
  • +
  • b8f302b (monitor) - monitor: change nodes to pod affinity
  • +
  • 4fc991f (monitor) - database: bump telegraf 1.22.0 and grafana 8.4.5
  • +
  • 21a2f6a (monitor) - monitor: use registry.drycc.cc replace docker.io
  • +
  • acc976f (monitor) - monitor: change python-dev registry
  • +
  • 62d76c1 (monitor) - monitor: unified reids declaration
  • +
  • b3c57ad (monitor) - monitor: optimize oauth2 configuration
  • +
  • 70af6b0 (monitor) - monitor: change passport config
  • +
  • 69f9a88 (monitor) - monitor: fine management affinity
  • +
  • 2fb278f (monitor) - monitor: rename influxdb port
  • +
  • 17548ff (monitor) - grafana: update dashborad
  • +
  • 69d7bbd (monitor) - grafana: influx dashborad disk size
  • +
  • 75db1b0 (monitor) - monitor: upgrade new grafana/telegraf
  • +
  • 80504a1 (monitor) - grafana: update influx and redis dashboard
  • +
  • f7078cb (monitor) - monitor:chown use env
  • +
  • 91ae0dd (passport) - passport: optimize login display
  • +
  • 2d3bbbc (passport) - passport: change drycc logo
  • +
  • 59790a7 (passport) - passport: make user email unique
  • +
  • faea034 (passport) - passport: use strtobool
  • +
  • 1fbf2bc (passport) - passport: use yarn replace npm
  • +
  • 119cac8 (passport) - passport: use exec runner replace docker runner
  • +
  • cff5062 (passport) - passport: set default CSRF_COOKIE_SECURE false
  • +
  • 9cc0210 (passport) - passport: canonical charts naming
  • +
  • 9ab3896 (passport) - passport: new ingress style
  • +
  • 259ccc9 (passport) - passport: provide any additional service annotations
  • +
  • af1bbcd (passport) - dockerfile: use drycc/base image
  • +
  • 9ae5373 (passport) - passport: set venv profile
  • +
  • 8f61090 (passport) - dockerfile: use uid gid
  • +
  • fcaf72d (passport) - passport: upgrade npm package
  • +
  • 546dcd5 (passport) - passport: add license
  • +
  • 4bda2d6 (passport) - passport: use minify
  • +
  • 73b0fd1 (passport) - passport: use common affinity template
  • +
  • 278fe7a (passport) - passport: change nodes to pod affinity
  • +
  • 3cd93d3 (passport) - passport: add reactive
  • +
  • 370b493 (passport) - passport: add footer
  • +
  • 483cbd6 (passport) - passport: use h_captcha replace re_captcha
  • +
  • 3d1675e (passport) - database: bump python 3.10.4 and node 16.14.2
  • +
  • 86a7835 (passport) - passport: use registry.drycc.cc replace docker.io
  • +
  • 2d65355 (passport) - passport: change python-dev registry
  • +
  • 90c1444 (passport) - passport: unified reids declaration
  • +
  • 2e0e417 (passport) - passport: fix firefox footer
  • +
  • ad274be (passport) - passport: use bulecss
  • +
  • f986d8b (passport) - passport: add main footer
  • +
  • 3e52867 (passport) - passport: dynamic settings for vue
  • +
  • 38adabc (passport) - passport: change passport config
  • +
  • f8d6b60 (passport) - passport: fine management affinity
  • +
  • 2cbd79d (passport) - passport: remove database conn_max_age
  • +
  • 7122797 (passport) - passport: change drycc.cc to www.drycc.cc
  • +
  • 8cc84cd (rabbitmq) - rabbitmq: use exec runner replace docker runner
  • +
  • f35930f (rabbitmq) - rabbitmq: add rabbitmq cluster support
  • +
  • fbfa3ba (rabbitmq) - rabbitmq: canonical charts naming
  • +
  • ca60701 (rabbitmq) - rabbitmq: use volumeClaimTemplates
  • +
  • fe5d1b4 (rabbitmq) - rabbitmq: add sharding support
  • +
  • 9c4ab97 (rabbitmq) - rabbitmq: provide any additional service annotations
  • +
  • 348a88a (rabbitmq) - dockerfile: use drycc/base image
  • +
  • 2388be1 (rabbitmq) - rabbitmq: upgrade erlang to 24.2.2
  • +
  • db2eaa5 (rabbitmq) - dockerfile: use uid gid
  • +
  • 772afd1 (rabbitmq) - rabbitmq: change to wait pid file
  • +
  • 2bfc25e (rabbitmq) - rabbitmq: use common affinity template
  • +
  • 11d505e (rabbitmq) - rabbitmq: change nodes to pod affinity
  • +
  • 69d63f1 (rabbitmq) - database: bump erlang 24.3.3 and rabbitmq 3.9.14
  • +
  • 8380299 (rabbitmq) - rabbitmq: use registry.drycc.cc replace docker.io
  • +
  • b3f69f1 (rabbitmq) - rabbitmq: add check rabbitmqLocaltion
  • +
  • 5327c76 (rabbitmq) - rabbitmq: fine management affinity
  • +
  • 5c66b5a (rabbitmq) - rabbitmq: change probe
  • +
  • 27bebf9 (rabbitmq) - rabbitmq: add start-rabbitmq script
  • +
  • 86ee6a7 (rabbitmq) - rabbitmq: upgrade to rabbitmq 3.10.7
  • +
  • 1f29683 (redis) - redis: use exec runner replace docker runner
  • +
  • a5041fc (redis) - redis: canonical charts naming
  • +
  • 64468c2 (redis) - redis: add redis persistence
  • +
  • de5d753 (redis) - redis: provide any additional service annotations
  • +
  • f644639 (redis) - dockerfile: use drycc/base image
  • +
  • 98051d2 (redis) - redis: premission denied
  • +
  • bcb548e (redis) - dockerfile: use uid gid
  • +
  • 524aa41 (redis) - redis: use common affinity template
  • +
  • 26c9466 (redis) - redis: change nodes to pod affinity
  • +
  • b67d7a2 (redis) - redis: use registry.drycc.cc replace docker.io
  • +
  • 839ec50 (redis) - redis: use env replace creds volume
  • +
  • 237ca86 (redis) - redis: fine management affinity
  • +
  • bdd968d (redis) - redis: upgrade neew require
  • +
  • 8b2910f (registry) - registry: use exec runner replace docker runner
  • +
  • eedbe78 (registry) - registry: canonical charts naming
  • +
  • 0241615 (registry) - registry: provide any additional service annotations
  • +
  • 9b58da4 (registry) - dockerfile: use drycc/base image
  • +
  • ab6acb7 (registry) - registry: change workdir to /workspace
  • +
  • f368bf7 (registry) - registry: use DRYCC_UID DRYCC_GID env
  • +
  • f4b9041 (registry) - registry: use common affinity template
  • +
  • c2e87ca (registry) - registry: change nodes to pod affinity
  • +
  • feb6aba (registry) - database: bump mc 2022.04.01.23.44.48
  • +
  • 956932b (registry) - rregistry: use registry.drycc.cc replace docker.io
  • +
  • deda8d8 (registry) - registry: move registry-secret.yaml from workflow to registry
  • +
  • f52c7bf (registry) - registry: change python-dev registry
  • +
  • 007fe03 (registry) - registry: https://github.com/minio/minio/issues/14331
  • +
  • d620c6d (registry) - registry: https://github.com/minio/minio/issues/13799
  • +
  • 85e6b73 (registry) - registry: use env replace creds volume
  • +
  • 6a1155d (registry) - registry: fine management affinity
  • +
  • 7b8ebae (registry) - registry: change minio to storage
  • +
  • 1338951 (registry) - registry: add check storage health
  • +
  • 2fa769d (registry) - registry: change probe
  • +
  • f187cbf (registry) - registry: add replicas
  • +
  • 09d8a7b (registry) - registry: upgrade to mc 2022.08.28.20.08.11
  • +
  • 4b187b8 (registry-proxy) - registry-proxy: use exec runner replace docker runner
  • +
  • 29ffbbe (registry-proxy) - registry-proxy: canonical charts naming
  • +
  • 6d783ba (registry-proxy) - registry-proxy: remove use_cni
  • +
  • 8cf05cf (registry-proxy) - dockerfile: use drycc/base image
  • +
  • 090e286 (registry-proxy) - registry-proxy: chore(imagebuilder): change uid gid to 1001
  • +
  • 7cf6120 (registry-proxy) - registry-proxy: use DRYCC_UID DRYCC_GID env
  • +
  • 3a00697 (registry-proxy) - registry-proxy: use registry.drycc.cc replace docker.io
  • +
  • 30e69e8 (registry-proxy) - registry-proxy: add registry basic auth proxy
  • +
  • 942abce (registry-proxy) - registry-proxy: upgrade to nginx 1.23.1
  • +
  • 5ea3297 (storage) - minio: use exec runner replace docker runner
  • +
  • 8306add (storage) - minio: canonical charts naming
  • +
  • c917e9f (storage) - minio: provide any additional service annotations
  • +
  • 042c732 (storage) - dockerfile: use drycc/base image
  • +
  • 7b47b82 (storage) - minio: change workdir to /workspace
  • +
  • 6f3531e (storage) - minio: use DRYCC_UID DRYCC_GID env
  • +
  • 9795fb1 (storage) - minio: use common affinity template
  • +
  • a7b09c5 (storage) - minio: change nodes to pod affinity
  • +
  • 7607342 (storage) - database: bump mc 2022.04.01.23.44.48 and minio 2022.04.01.03.41.39
  • +
  • ea2b2f1 (storage) - minio: use registry.drycc.cc replace docker.io
  • +
  • 445b501 (storage) - minio: https://github.com/minio/minio/issues/14331
  • +
  • f19fbc7 (storage) - minio: use env replace creds volume
  • +
  • 8982e2e (storage) - minio: use minio to distributed
  • +
  • 06bec73 (storage) - minio: fine management affinity
  • +
  • 9b8f006 (storage) - storage: remove assert
  • +
  • 59d64b9 (storage) - storage: change listen to POD_IP
  • +
  • 60044ee (storage) - storage: add juicefs mount options
  • +
  • 189f944 (storage) - storage: remove volumeName
  • +
  • 302fe89 (storage) - storage: mv to minio dir
  • +
  • 6ec586d (storage) - storage: change readinessProbee andlivenessProbe
  • +
  • 0e028df (storage) - storage: add minio pdb
  • +
  • cf9bd2d (storage) - storage: add check storage health svc
  • +
  • 2dd5c9f (storage) - storage: add volumeBindingMode
  • +
  • fa2effc (storage) - storage: remove databaseBucket
  • +
  • d166cc7 (storage) - charts: format network-policy name
  • +
  • d06bcce (storage) - storage: upgrade to golang 1.19
  • +
  • c2ca05c (storage) - storage: upgrade new require
  • +
+ +
+ + + + + + + + + + + + + + + + +
+

Drycc Workflow v1.5.0

+
New Drycc Workflow Release v1.5.0
+ +

These release notes for Drycc Workflow v1.5.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.4.0, please refer to the following change summary.

+

Workflow ## v1.4.0 -> v1.5.0

+

Releases

+
    +
  • passport v1.0.0
  • +
  • rabbitmq v1.0.0
  • +
  • imagebuilder v1.0.0
  • +
  • builder v1.2.0 -> v1.3.0
  • +
  • controller v1.3.0 -> v1.4.0
  • +
  • database v1.0.2 -> v1.1.0
  • +
  • fluentd v1.1.0 -> v1.2.0
  • +
  • redis v1.1.0 -> v1.2.0
  • +
  • influxdb v1.0.1 -> v1.1.0
  • +
  • logger v1.1.0 -> v1.2.0
  • +
  • minio v1.1.0 -> v1.2.0
  • +
  • monitor v1.1.0 -> v1.2.0
  • +
  • nsqd v1.1.0 -> v1.2.0
  • +
  • registry v1.0.3 -> v1.1.0
  • +
  • registry-proxy v1.0.2 -> v1.1.0
  • +
+

Features

+
    +
  • 0f5f8e4 (builder) - builder: multi-platform support
  • +
  • f269d06 (builder) - build: add buildx supportjkjkk:q
  • +
  • 5e72fe8 (builder) - registry: use docker build
  • +
  • 25d8a4c (builder) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 7a3e1c5 (builder) - charts: set the default chart version
  • +
  • 46b75ff (builder) - builder: add cloud native buildpacks support
  • +
  • 2db2054 (builder) - builder: unified build model
  • +
  • 4b7f9d9 (builder) - builder: add initContainers
  • +
  • b78c936 (controller) - token: add get token api
  • +
  • bac52a5 (controller) - tasks: use celery replace nsqd
  • +
  • b9b0c58 (controller) - build: add buildx support
  • +
  • 205dcb3 (controller) - influxdb: add influxdb client
  • +
  • ff15849 (controller) - influxdb: upgrade to influxdb 2.x
  • +
  • 4016244 (controller) - controller: push data to influx
  • +
  • fcfce2e (controller) - workflow-manager: add workflow-manager support
  • +
  • 00e9bfb (controller) - influxdb: review influxdb code
  • +
  • dd644d5 (controller) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 118278b (controller) - charts: set the default chart version
  • +
  • 122a9cd (controller) - oauth2: add oauth2 support
  • +
  • 559a5b6 (controller) - controller: use cncf buildpacks replace slugrunner
  • +
  • 96130e6 (controller) - charts: database configuration optimization of passport and controller
  • +
  • 2ea8508 (controller) - oauth: using passport authentication
  • +
  • 868c437 (database) - database: multi-platform support
  • +
  • eadd5da (database) - build: add buildx support
  • +
  • b6eea4c (database) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 04a88db (database) - charts: set the default chart version
  • +
  • 92ed309 (database) - database: add initContainer
  • +
  • ee6b78f (fluentd) - build: add buildx support
  • +
  • f523e30 (fluentd) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • ee47b53 (fluentd) - charts: set the default chart version
  • +
  • 80a51af (influxdb) - influxdb: modify influxdb naming rules
  • +
  • fb10030 (influxdb) - influxdb: use influxdb v2
  • +
  • 0e87ad8 (influxdb) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 9d10801 (influxdb) - charts: set the default chart version
  • +
  • d825c9f (logger) - build: add buildx support
  • +
  • b139576 (logger) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 88f84ea (logger) - charts: set the default chart version
  • +
  • 5ccae3e (logger) - dockerfile: remove chmod cmd
  • +
  • 193aefc (logger) - logger: add initContainers
  • +
  • baee330 (minio) - minio: multi-platform support
  • +
  • ad5d055 (minio) - build: add buildx support
  • +
  • 19868d4 (minio) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 4bd84b8 (minio) - charts: set the default chart version
  • +
  • 79d1f2f (monitor) - database: multi-platform support
  • +
  • 88e5a7f (monitor) - build: add buildx support
  • +
  • 5672e99 (monitor) - influxdb: modify influxdb naming rules
  • +
  • 8672103 (monitor) - influxdb: use influxdb v2
  • +
  • 66cb4c8 (monitor) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 9576eb3 (monitor) - charts: set the default chart version
  • +
  • 30809c9 (monitor) - monitor: add initContainers
  • +
  • 70d140c (nsqd) - nsqd: using self compiled nsq binary
  • +
  • 1073d4f (nsqd) - nsqd: use GOPATH replace /go
  • +
  • e498480 (nsqd) - build: add buildx support
  • +
  • cf9b7d5 (nsqd) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • c335856 (nsqd) - charts: set the default chart version
  • +
  • efba713 (redis) - build: add buildx support
  • +
  • c7a3b53 (redis) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 4cdad7b (redis) - charts: set the default chart version
  • +
  • 652b443 (registry) - registry: multi-platform support
  • +
  • 4060176 (registry) - registry: use docker build
  • +
  • 7102a03 (registry) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 6c8600d (registry) - charts: set the default chart version
  • +
  • 33a51c9 (registry) - registry: add initContainers
  • +
  • bef70dc (registry-proxy) - build: add buildx support
  • +
  • d2319c1 (registry-proxy) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 02fafed (registry-proxy) - charts: set the default chart version
  • +
+

Fixes

+
    +
  • 5499c9a (controller) - gunicorn: gunicorn not running
  • +
  • 06e9e88 (controller) - controller: error loading shared library
  • +
  • 01b5bd0 (controller) - controller: upgrade celery config
  • +
  • 6e32d55 (controller) - controller: fix update resources bug
  • +
  • 0e0d53f (controller) - chart: set the domain depends certManagerEnabled
  • +
  • 2ac4ca8 (controller) - passport: error loading shared library libexpat.so.1
  • +
  • a0dd517 (fluentd) - fluentd: drone build
  • +
  • 6eca2a3 (logger) - logger: golang lint
  • +
  • 63b0aa0 (registry) - drone: charts url error
  • +
+

Docs

+
    +
  • 472cfcc (controller) - controller organize README.md document
  • +
  • d9d6e29 (redis) - redis: delete links that do not exist
  • +
+

Test case

+
    +
  • 1468f57 (controller) - controller: add command unittest
  • +
+

Maintenance

+
    +
  • 9999bfd (builder) - builder:replace the special words
  • +
  • cda8b58 (builder) - builder: remove docker keyword from charts
  • +
  • dc575dd (builder) - builder: use imagebuilder replace dockerbuilder
  • +
  • d3bb183 (builder) - docker: use the full name of registry
  • +
  • 5fe34d1 (builder) - travis: add DEV_REGISTRY
  • +
  • 7e36453 (builder) - CICD: use drone
  • +
  • 52b8d9d (builder) - drone: add image_registries volumes
  • +
  • 65963f4 (builder) - k8s: add privileged to dind
  • +
  • d345fcf (builder) - LICENSE: revert modifications to Apache license
  • +
  • 7975c99 (builder) - drone: always pull image
  • +
  • 59633dd (builder) - builder: modify launch imagebuild pod
  • +
  • 8d14e67 (builder) - builder: use Procfile in anywhere
  • +
  • 5357fa8 (builder) - go: bump go mod
  • +
  • 8d26ac0 (builder) - k8s: k8s deprecated api migration
  • +
  • 0af620d (builder) - chars: change org to imageTag
  • +
  • ae84303 (builder) - builder: run imagebuider replace pod with job
  • +
  • 3b2c496 (builder) - builder: change docs website
  • +
  • 5679a4c (builder) - builder: upgrade to golang1.17
  • +
  • a214503 (controller) - controller:replace whitelist with allowlist
  • +
  • 375ddcc (controller) - ps:drycc ps:list show autoscale num
  • +
  • c32e409 (controller) - ldap: canot register when ldap is enabled
  • +
  • c46580a (controller) - controller:modify redis config
  • +
  • fa9e87b (controller) - chart:modify controller charts
  • +
  • 6f9fd08 (controller) - nsq: remove nsq
  • +
  • 994b2dc (controller) - docker-buildx: add check-docker
  • +
  • a720c3a (controller) - controller: remove docker keyword from charts
  • +
  • e9a5c84 (controller) - docker: use the full name of registry
  • +
  • a26614a (controller) - controller: add rabbitmq env
  • +
  • 3df229d (controller) - controller: modify database config && remove redis port config && add env prefix with DRYCC
  • +
  • 257e94b (controller) - controller: CELERY_BROKER use rabbitmq and modify celery-deployment cronjob
  • +
  • f4d6ec3 (controller) - chart: pretty chart format
  • +
  • 63e6195 (controller) - influxdb: modify influxdb code
  • +
  • 0f6d408 (controller) - CICD: use drone
  • +
  • 87bad28 (controller) - python: upgrade to python3.9
  • +
  • e8f7560 (controller) - volumes: modify mount summary
  • +
  • 6cf6c6b (controller) - drone: add image_registries volumes
  • +
  • a9397e8 (controller) - oauth: modify token Authentication
  • +
  • c7f8c8b (controller) - deps: bump django from 2.2.14 to 2.2.18 in /rootfs
  • +
  • a1a08aa (controller) - deps: bump djangorestframework from 3.11.0 to 3.11.2 in /rootfs
  • +
  • efd78b4 (controller) - deps: bump django from 2.2.18 to 2.2.20 in /rootfs
  • +
  • 649b044 (controller) - deps: bump django from 2.2.20 to 2.2.22 in /rootfs
  • +
  • 41b742b (controller) - deps: bump django from 2.2.22 to 2.2.24 in /rootfs
  • +
  • 22ffe5d (controller) - LICENSE: revert modifications to Apache license
  • +
  • c98b468 (controller) - drone: always pull image
  • +
  • 20e6edb (controller) - chart: modify the problem of using buildpack
  • +
  • db16879 (controller) - controller: pretty pods list print
  • +
  • ba6f456 (controller) - test: pretty pods list print
  • +
  • 5fce4b7 (controller) - k8s: k8s deprecated api migration
  • +
  • e9e0bcb (controller) - oauth: using passport authentication
  • +
  • 0311172 (controller) - chars: change org to imageTag
  • +
  • 150eff1 (controller) - charts: update cert-manager api version
  • +
  • de8545a (controller) - controller: update requirements
  • +
  • 1442207 (controller) - controller: using django native JSONFiled
  • +
  • ab4e836 (controller) - oauth: modify passport api
  • +
  • 5c54e06 (controller) - controller: eliminate pip warnings
  • +
  • 870328d (controller) - controller: remove entrypoint
  • +
  • 5e5e6ae (controller) - controller: upgrade celery config
  • +
  • 607778f (controller) - controller: add initContainer
  • +
  • 23dc016 (controller) - chart: set the domain depends certManagerEnabled
  • +
  • f3cf20b (controller) - controller: remove default bash env
  • +
  • 73f2636 (controller) - controller: modify alpinelinux repositories
  • +
  • 498e9f2 (controller) - chart: change certManagerEnabled to boolean type
  • +
  • 27f5308 (controller) - passport: exclude cryptography
  • +
  • 370b75d (controller) - controller: use sh env
  • +
  • 07585b4 (database) - postgres:replace the special words
  • +
  • 20172dc (database) - database: remove docker keyword from charts
  • +
  • abb9b88 (database) - docker: use the full name of registry
  • +
  • e72f58f (database) - chart: modify the off-cluster database
  • +
  • a91f64f (database) - travis: add DEV_REGISTRY
  • +
  • 614fb76 (database) - tests: use add-host replace link
  • +
  • a3428f3 (database) - CICD: use drone
  • +
  • 239fef1 (database) - drone: add image_registries volumes
  • +
  • 42858e1 (database) - LICENSE: revert modifications to Apache license
  • +
  • d0fe850 (database) - drone: always pull image
  • +
  • 34a36ad (database) - charts: Nn secret is generated during off-cluster
  • +
  • 064ccf4 (database) - database: create database
  • +
  • 9228992 (database) - chars: change org to imageTag
  • +
  • 9f7810c (database) - database: upgrade to wal-g v1.1
  • +
  • 05783f4 (fluentd) - fluentd:replace the special words
  • +
  • 0739809 (fluentd) - influxdb:replace monitor-influx with influx
  • +
  • f02487c (fluentd) - fluentd: remove docker keyword from charts
  • +
  • 2c96cc0 (fluentd) - docker: use the full name of registry
  • +
  • b20c429 (fluentd) - charts: remove port config
  • +
  • 6dd0197 (fluentd) - travis: add DEV_REGISTRY
  • +
  • c5bec51 (fluentd) - CICD: use drone
  • +
  • f8524b7 (fluentd) - drone: add image_registries volumes
  • +
  • a50878a (fluentd) - LICENSE: revert modifications to Apache license
  • +
  • 14fe20e (fluentd) - drone: always pull image
  • +
  • 4a2f660 (fluentd) - k8s: k8s deprecated api migration
  • +
  • de2dd91 (fluentd) - chars: change org to imageTag
  • +
  • a9f1944 (fluentd) - fluentd: upgrade to fluentd1.14
  • +
  • 7cb4e95 (influxdb) - influxdb: change username to user
  • +
  • 0fdc21b (influxdb) - influxdb: remove docker keyword from charts
  • +
  • b2acddb (influxdb) - influxdb: change default path
  • +
  • ba88919 (influxdb) - influxdb: add check_env function
  • +
  • 9117401 (influxdb) - influxdb: modify init_influxdb has_bucket
  • +
  • 092a3e6 (influxdb) - chart: pod not readiness
  • +
  • 51de380 (influxdb) - travis: add DEV_REGISTRY
  • +
  • 66d7667 (influxdb) - docker: replace influxdb base image
  • +
  • 3aa3094 (influxdb) - CICD: use drone
  • +
  • 14b9c24 (influxdb) - drone: add image_registries volumes
  • +
  • 02b4cd1 (logger) - logger:replace the special words
  • +
  • 114b5d5 (logger) - reids: delete the logger prefix of redis
  • +
  • 639278a (logger) - redis: remove logger from redis conf
  • +
  • 90195e2 (logger) - go: remove GOOS and GOARCH
  • +
  • 31e2e27 (logger) - logger: remove docker keyword from charts
  • +
  • 8fbd9fa (logger) - docker: use the full name of registry
  • +
  • b39df2d (logger) - charts: remove redis\nsqd port config
  • +
  • 35d6d07 (logger) - travis: add DEV_REGISTRY
  • +
  • 69aabf5 (logger) - tests: remove docker link
  • +
  • e916644 (logger) - CICD: use drone
  • +
  • d6872b7 (logger) - drone: add image_registries volumes
  • +
  • 37801da (logger) - LICENSE: revert modifications to Apache license
  • +
  • cfb4b38 (logger) - drone: always pull image
  • +
  • 8bda3bf (logger) - go: bump go mod
  • +
  • e13ebfc (logger) - chars: change org to imageTag
  • +
  • 38e6d8d (minio) - minio:replace the special words
  • +
  • d6925dd (minio) - minio: remove docker keyword from charts
  • +
  • d56bc39 (minio) - docker: use the full name of registry
  • +
  • e4696cc (minio) - travis: add DEV_REGISTRY
  • +
  • 70c5c79 (minio) - minio: use latest version
  • +
  • 773cf6c (minio) - Makefile: remove DEV_REGISTRY ?=
  • +
  • 5ce5bc6 (minio) - CICD: use drone
  • +
  • 5da8be3 (minio) - drone: add image_registries volumes
  • +
  • c1f0611 (minio) - LICENSE: revert modifications to Apache license
  • +
  • b73f792 (minio) - drone: always pull image
  • +
  • 79d1c93 (minio) - go: bump go mod
  • +
  • c448899 (minio) - chars: change org to imageTag
  • +
  • 15ee49e (minio) - minio: migrate deprecated warning
  • +
  • 9968a1a (minio) - minio: upgrade to golang1.7
  • +
  • 14fedd2 (monitor) - monitor:replace the special works
  • +
  • 52c431a (monitor) - reids: delete the logger prefix of redis
  • +
  • 2c95b47 (monitor) - redis: remove logger from redis conf
  • +
  • da9bc56 (monitor) - monitor:remove influxdb
  • +
  • 53f47b9 (monitor) - grafana: use grafana docker image
  • +
  • 5bdb188 (monitor) - grafana: use grafana docker image
  • +
  • c0586dd (monitor) - monitor: remove docker keyword from charts
  • +
  • 87d02b6 (monitor) - charts: add nodes and persistentvolumes rule
  • +
  • 1b5598f (monitor) - monitor: modify grafana dashboard with FLUX and pretty config.toml
  • +
  • bcbc0d5 (monitor) - docker: use the full name of registry
  • +
  • 9418c9e (monitor) - monitor: fix upload dashboard error and modify INFLUXDB input
  • +
  • 589f29a (monitor) - travis: add DEV_REGISTRY
  • +
  • f776f8a (monitor) - CICD: use drone
  • +
  • 6ca3060 (monitor) - drone: add image_registries volumes
  • +
  • 6a9ffb2 (monitor) - LICENSE: revert modifications to Apache license
  • +
  • 45e41ed (monitor) - drone: always pull image
  • +
  • 654d407 (monitor) - k8s: k8s deprecated api migration
  • +
  • 41e9b9c (monitor) - chars: change org to imageTag
  • +
  • 99c10d3 (monitor) - charts: update cert-manager api version
  • +
  • 9bf83c4 (monitor) - oauth: user oauth passport
  • +
  • a128f6d (monitor) - chart: change certManagerEnabled to boolean type
  • +
  • 8f897fe (monitor) - chart: set the domain depends certManagerEnabled
  • +
  • ba6d793 (nsqd) - README:update travis build status
  • +
  • 49879c4 (nsqd) - nsqd: minimum git clone code
  • +
  • c5e2680 (nsqd) - nsqd: remove docker keyword from charts
  • +
  • 21dd17b (nsqd) - docker: use the full name of registry
  • +
  • 7d86b3c (nsqd) - charts: remove port config
  • +
  • c073d95 (nsqd) - travis: add DEV_REGISTRY
  • +
  • 55c297c (nsqd) - CICD: use drone
  • +
  • 165c2ae (nsqd) - drone: add image_registries volumes
  • +
  • 9c6a1f8 (nsqd) - LICENSE: revert modifications to Apache license
  • +
  • 9283098 (nsqd) - drone: always pull image
  • +
  • 46acf8a (nsqd) - k8s: k8s deprecated api migration
  • +
  • 43caf80 (nsqd) - chars: change org to imageTag
  • +
  • 6897471 (nsqd) - nsqd: use official image
  • +
  • 297bc05 (redis) - redis:replace the special words
  • +
  • f5f8b5e (redis) - reids: delete the logger prefix of redis
  • +
  • af7b657 (redis) - redis: change logger-redis to redis
  • +
  • 8dca154 (redis) - redis: remove logger from redis conf
  • +
  • eaeda2d (redis) - redis: remove docker keyword from charts
  • +
  • 53c6358 (redis) - docker: use the full name of registry
  • +
  • ae37416 (redis) - charts: remove port config
  • +
  • e985656 (redis) - travis: add DEV_REGISTRY
  • +
  • 423336a (redis) - CICD: use drone
  • +
  • be64ab4 (redis) - drone: add image_registries volumes
  • +
  • 3bec735 (redis) - LICENSE: revert modifications to Apache license
  • +
  • 4f934f6 (redis) - drone: always pull image
  • +
  • 359b878 (redis) - chars: change org to imageTag
  • +
  • 83b8ac2 (registry) - workflow:replace the special words
  • +
  • 869b280 (registry) - registry: remove docker keyword from charts
  • +
  • 999c1e9 (registry) - docker: use the full name of registry
  • +
  • 5652da9 (registry) - travis: add DEV_REGISTRY
  • +
  • cc8c6c2 (registry) - CICD: use drone
  • +
  • c7bdbd0 (registry) - CICD: pretty .drone.yaml format
  • +
  • 5c55a38 (registry) - test: use add-host replace link
  • +
  • f8866f3 (registry) - drone: add image_registries volumes
  • +
  • 6c8292f (registry) - LICENSE: revert modifications to Apache license
  • +
  • 1d50f2c (registry) - drone: always pull image
  • +
  • efbca6d (registry) - chars: change org to imageTag
  • +
  • 2eafc59 (registry-proxy) - registry-proxy: update nginx
  • +
  • 071bd86 (registry-proxy) - charts: upgrade k8s newer API versions
  • +
  • c72db96 (registry-proxy) - registry-proxy: change travis icon url
  • +
  • 63ffb92 (registry-proxy) - registry-proxy:replace the special works
  • +
  • 1d904a6 (registry-proxy) - registry-proxy: remove docker keyword from charts
  • +
  • c8200b1 (registry-proxy) - docker: use the full name of registry
  • +
  • d3fa939 (registry-proxy) - travis: add DEV_REGISTRY
  • +
  • 5a8b353 (registry-proxy) - CICD: use drone
  • +
  • 703d05a (registry-proxy) - drone: add image_registries volumes
  • +
  • aa71db1 (registry-proxy) - LICENSE: revert modifications to Apache license
  • +
  • 710c126 (registry-proxy) - drone: always pull image
  • +
  • 2dcc5e6 (registry-proxy) - chars: change org to imageTag
  • +
+ +
+ + + + + + + + + + + + + + + + +
+

Drycc Workflow v1.4.0

+
New Drycc Workflow Release v1.4.0
+ +

These release notes for Drycc Workflow v1.3.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.4.0, please refer to the following change summary.

+

Workflow ## v1.3.0 -> v1.4.0

+

Releases

+
    +
  • builder v1.1.0 -> v1.2.0
  • +
  • slugbuilder v1.1.1 -> v1.2.0
  • +
  • dockerbuilder v1.1.1 -> v1.1.2
  • +
  • controller v1.2.1 -> v1.3.0
  • +
  • slugrunner v1.1.1 -> v1.1.2
  • +
  • database v1.0.1 -> v1.0.2
  • +
  • fluentd v1.0.1 -> v1.1.0
  • +
  • redis v1.0.0 -> v1.1.0
  • +
  • logger v1.0.0 -> v1.1.0
  • +
  • minio v1.0.1 -> v1.1.0
  • +
  • monitor v1.0.1 -> v1.1.0
  • +
  • nsqd v1.0.0 -> v1.1.0
  • +
  • registry v1.0.2 -> v1.0.3
  • +
  • registry-proxy v1.0.0 -> v1.0.1
  • +
+

Features

+
    +
  • fc7d93f (builder) - builder: use go-dev
  • +
  • 0c2159e (builder) - builder: fmt code and add create_bucket script
  • +
  • 1b88340 (controller) - controller: remove deprecated api
  • +
  • a92fdeb (controller) - routable: ingress support routable
  • +
  • 1e3eab3 (controller) - maintenance: add maintenance support for ingress
  • +
  • 56b9dd0 (controller) - crt: support containerd-ctr
  • +
  • 5fc3b46 (controller) - controller: add ephemeral-storage restriction
  • +
  • d677e52 (controller) - controller: add a volume command
  • +
  • 5f1323a (controller) - controller:drycc run cmd add –mount para
  • +
  • 74c36a5 (controller) - tasks: add distributed async task
  • +
  • 139c3ca (controller) - tasks: change nsq reader to async
  • +
  • f237d74 (controller) - controller:add drycc resource cmd
  • +
  • 41b46d0 (controller) - controller:add drycc resource cmd improvement
  • +
  • c26f7d8 (controller) - controller: add LimitRanges support
  • +
  • 45b5d1b (controller) - users: add users status api
  • +
  • 4e16f9b (controller) - ps:add ps:stop/start command
  • +
  • c659fa9 (controller) - k8s: add k8s cluster domain
  • +
  • 31a625d (controller) - ps:add ps:stop/start command
  • +
  • 00a779a (fluentd) - fluentd: support containerd log format
  • +
  • f3f1bd4 (fluentd) - nsqd: add stateless nsqd cluster support
  • +
  • db7147c (fluentd) - mirrors: delete aliyun mirrors
  • +
  • 689c12e (logger) - nsqd: add stateless nsqd cluster support
  • +
  • 78ccc5d (logger) - redis: add redis client cluster support
  • +
  • 9843f2c (logger) - k8s: add k8s cluster domain
  • +
  • 6ba122e (minio) - minio: add pvc support
  • +
  • 6973550 (monitor) - monitor: add ingress for monitor
  • +
  • cd73305 (monitor) - charts: add volumeName support
  • +
  • 4769fe9 (monitor) - nsqd: add stateless nsqd cluster support
  • +
  • 87806df (monitor) - k8s: add k8s cluster domain
  • +
  • 4db40c4 (nsqd) - nsqd: add stateless nsqd cluster support
  • +
  • b6f3d4f (nsqd) - nsqd: add stateless nsqd cluster support
  • +
  • 74b85bb (redis) - redis: change redis to statefulset
  • +
  • ff98b50 (slugbuilder) - slugbuilder: delete build hook
  • +
  • b201c2f (slugbuilder) - buildpacks: use drycc buildpacks
  • +
+

Fixes

+
    +
  • 0ec042d (builder) - test: fix test case error
  • +
  • 4fb113b (builder) - build: base image replace by alpine
  • +
  • 443df48 (builder) - minio: fix not bucket error
  • +
  • 3dab5b0 (builder) - minio: create bucket error
  • +
  • 734fca6 (controller) - autoscale: Fix for autoscale on k8s-1.9+ without breaking manual scaling
  • +
  • a7dcd10 (controller) - controller: test pass
  • +
  • 93f0f2e (controller) - controller: fix migrations error
  • +
  • 4724375 (controller) - controller: fix test error
  • +
  • 7bacf29 (controller) - charts: fix clusterrole
  • +
  • 90957f7 (controller) - pod: sort events error
  • +
  • 440b13e (controller) - controller: review table structure
  • +
  • 0a470a6 (controller) - controller: bump tornado 5.1.1
  • +
  • e39218b (controller) - pynsq: no current event loop in thread
  • +
  • 1d8630e (controller) - tests: fix test_task.py run error
  • +
  • 1ff1202 (controller) - controller: fix test case
  • +
  • d8c0da3 (controller) - settings: fix env name
  • +
  • 6d8fd36 (database) - 003_restore_from_backup.sh: ignore script exit 1
  • +
  • e0394a9 (database) - minio: fix not bucket error
  • +
  • f35f252 (database) - mc: fix create_bucket error
  • +
  • 74d6886 (database) - postgres: recovery mode not run
  • +
  • e50d0c1 (dockerbuilder) - caddy: fix caddy not start
  • +
  • f3bec7a (fluentd) - influxdb: fix influxdb host and port
  • +
  • bc19f27 (fluentd) - charts: skipped value for daemon_environment: Not a table
  • +
  • 338d623 (logger) - logger: logger not run in alpine
  • +
  • 7788302 (minio) - minio: bump minio version
  • +
  • 619eed0 (minio) - fix: use go mod replace dep
  • +
  • 3b42122 (monitor) - monitor: fix host error
  • +
  • 67998ef (monitor) - influxdb: replace drycc-monitor-influxapi to drycc-monitor-influx-api
  • +
  • 2cc361c (registry) - registry: fix test case
  • +
  • 548297a (registry) - minio: fix not bucket error
  • +
  • 5412ddb (registry) - minio: create bucket error
  • +
  • d0d629e (slugbuilder) - slugbuilder:fix normalize_storage path
  • +
  • d76ecbe (slugbuilder) - slugbuilder: use v3 api
  • +
  • c505e18 (slugbuilder) - shellcheck: SC2039
  • +
+

Style

+
    +
  • c893a17 (builder) - builder: fmt code
  • +
  • bba5795 (controller) - controller: format code
  • +
  • d36082b (controller) - controller: fix pep8
  • +
  • 66026f2 (controller) - resource: standardize the naming of resource
  • +
  • 03d7e2c (controller) - servicecatalog: change servicecatalog to svcat
  • +
  • 49dbb6d (controller) - controller: flake8 upgrade
  • +
  • cbfc108 (monitor) - monitor: format charts and dashboard
  • +
  • ee85954 (slugbuilder) - slugbuilder: use shellcheck
  • +
  • 3afed2e (slugbuilder) - docker: simplify dockerfile
  • +
  • 36b7f68 (slugrunner) - docker: simplify dockerfile
  • +
+

Maintenance

+
    +
  • 61bb0ef (builder) - aws: upgrade aws sdk version
  • +
  • 0f2e074 (builder) - chore: use go mode replace dep
  • +
  • e9a2219 (builder) - builder: delete glide up
  • +
  • bb8c518 (builder) - registry: del quay.io
  • +
  • fa6d02f (builder) - builder: upgrade go.sum
  • +
  • 9d61e8d (builder) - build: upgrade go.mod
  • +
  • d763a98 (builder) - charts: upgrade k8s newer API versions
  • +
  • d1bc1aa (builder) - pkg: upgrade to new drycc/pkg
  • +
  • 02b1e98 (builder) - builder: update go mod
  • +
  • 8e17d65 (builder) - builder: change alpine repositories
  • +
  • f32b723 (builder) - mirrors: delete aliyun mirrors
  • +
  • e33dc61 (builder) - minio: use bin mc replace docker images
  • +
  • 3ab4f1c (builder) - builder: update controller-sdk-go
  • +
  • b2adfac (builder) - heroku: remove heroku-16 support
  • +
  • f429ac8 (builder) - builder: set GIT_LOCK_TIMEOUT to 30 minutes
  • +
  • 7197c83 (builder) - go.mod:upgrade require pkg controller-sdk-go
  • +
  • 5f3e22d (controller) - deps: bump django from 1.11.21 to 1.11.22 in /rootfs
  • +
  • 1db645a (controller) - deps: bump django from 1.11.22 to 1.11.23 in /rootfs
  • +
  • fbe8067 (controller) - deps: bump django from 1.11.23 to 1.11.29 in /rootfs
  • +
  • 537d667 (controller) - registry: del quay.io
  • +
  • a23c65b (controller) - deps: update all deps to the latest version
  • +
  • 546337e (controller) - charts: upgrade k8s newer API versions
  • +
  • 06023f8 (controller) - workflow-manager: del workflow-manager
  • +
  • bba5736 (controller) - controller: change cluster-issuer location
  • +
  • 6c43661 (controller) - Certificatechange cluster-issuer location
  • +
  • 39a4728 (controller) - controller:change cluster-issuer location del controller-cluster-issuer.yaml
  • +
  • 9e96d3f (controller) - Certificate:upgrade version cert-manager.io/v1alpha2
  • +
  • 8e68049 (controller) - docker: use INDEX_URL replace index.docker.io
  • +
  • 8fda205 (controller) - cert_manager: change cert_manager_enabled to global
  • +
  • 6fefb6d (controller) - charts: change platform_domain to global
  • +
  • 064b2ad (controller) - maintenance: remove maintenance support
  • +
  • b8797c9 (controller) - workflow: remove namespace
  • +
  • 1b20d76 (controller) - quota: add kube quota config
  • +
  • d780075 (controller) - pod: add pod default resources support
  • +
  • 3d72c08 (controller) - rename: rename ingress name
  • +
  • 0aa6ab9 (controller) - mirrors: delete aliyun mirrors
  • +
  • 7533a65 (controller) - heroku: remove heroku-16 support
  • +
  • e5a885d (controller) - controller:check mount volume path
  • +
  • 9014e74 (controller) - test: optimization Dockerfile.test
  • +
  • 0b6ebb2 (controller) - tasks: change apply_async parameters
  • +
  • 835f009 (controller) - wsgi: add tornado 6 support
  • +
  • 67a4ad7 (controller) - utils: use threads replace asyncio
  • +
  • a28949b (controller) - ldap: add AUTH_LDAP_USER_FLAGS_BY_GROUP
  • +
  • a903209 (controller) - charts: add custom controller environment variables support
  • +
  • e0e783e (controller) - ldap: change filter style
  • +
  • d760825 (controller) - scheduler: remove debug log
  • +
  • a25928e (controller) - wsgi: remove a wsgi.py file
  • +
  • 7b2696e (controller) - log: disable nsq.client info log
  • +
  • 8d5c07b (controller) - charts: add default environment
  • +
  • 025f4a2 (controller) - controller: change quota name
  • +
  • ebda60e (controller) - controller: review pvc code
  • +
  • 8832ba9 (controller) - controller: change status\binding model type and mount path check container_types
  • +
  • 7148d04 (controller) - controller: add overcommit cpu and ram support
  • +
  • 4d2087c (controller) - limits: modify limits unit verification
  • +
  • af36970 (controller) - api: check cpu/memory range for api
  • +
  • 329355b (controller) - volumes: modify the volume size
  • +
  • 9dfee09 (controller) - LimitRanges: modify the default limits
  • +
  • 5205bca (controller) - controller: improve the details of certificate
  • +
  • 7ebecdf (database) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z
  • +
  • 6415e2c (database) - postgres: upgrade to pg13
  • +
  • 12e6806 (database) - charts: upgrade k8s newer API versions
  • +
  • d294509 (database) - minio: use canary minio test
  • +
  • 1bad02e (database) - mirrors: delete aliyun mirrors
  • +
  • d51420b (database) - minio: use bin mc replace docker images
  • +
  • 4133d05 (dockerbuilder) - dockerbuilder: update caddy and kaniko
  • +
  • 6b4dd18 (dockerbuilder) - minio: use bin mc replace docker images
  • +
  • 6df9b7c (fluentd) - deps-dev: update rake requirement from ~> 10.0 to ~> 12.3
  • +
  • c2490f8 (fluentd) - fluentd: upgrade fluentd
  • +
  • be4a56a (fluentd) - fluentd: add Gemfile.lock
  • +
  • 2237f75 (fluentd) - charts: upgrade k8s newer API versions
  • +
  • c574065 (fluentd) - charts: upgrade k8s newer API versions
  • +
  • 52b8084 (fluentd) - router: delete obsolete router code
  • +
  • 3b3cceb (fluentd) - fluentd: remove manifests dir
  • +
  • 25c6702 (fluentd) - nsqd: change var name
  • +
  • bd571be (fluentd) - nsqd: change DRYCC_NSQD_ADDRESSES to DRYCC_NSQD_ADDRS
  • +
  • 72aa4e6 (fluentd) - influxdb: change influxdb service name
  • +
  • bd61903 (logger) - logger: use go mod replace dep
  • +
  • 69c63a1 (logger) - logger: update go.mod
  • +
  • 3aa9cd7 (logger) - registry: del quay.io
  • +
  • f058496 (logger) - nsqd: change var name
  • +
  • 6d9787c (logger) - nsqd: change DRYCC_NSQD_ADDRESSES to DRYCC_NSQD_ADDRS
  • +
  • 85ed307 (logger) - logger: standard naming
  • +
  • d88e7b6 (minio) - minio: update minio api to v7
  • +
  • 43715d2 (minio) - minio: upgrade minio
  • +
  • 0e1239b (minio) - minio: use docker.io replace quay.io
  • +
  • f7f047b (minio) - registry: del quay.io
  • +
  • afa7128 (minio) - build: upgrade go.mod
  • +
  • aff2db5 (minio) - charts: upgrade k8s newer API versions
  • +
  • 4547f14 (minio) - pkg: upgrade to new drycc/pkg
  • +
  • 2769b85 (minio) - minio: use bin mc replace docker images
  • +
  • 35dde8d (monitor) - monitor: update grafana influxdb telegraf
  • +
  • 9e3a949 (monitor) - charts: upgrade k8s newer API versions
  • +
  • 6af0432 (monitor) - workflow-manager: remove workflow-manager
  • +
  • 0611c07 (monitor) - router: delete obsolete router code
  • +
  • be04824 (monitor) - cert_manager: change cert_manager_enabled to global
  • +
  • 3780165 (monitor) - charts: change platform_domain to global
  • +
  • 50b04e1 (monitor) - influxdb: remove influxdb admin ui
  • +
  • 6ab4d68 (monitor) - influxdb: remove unuse port
  • +
  • f1510bd (monitor) - monitor: update grafana dashboard,telegraf inputs.kubernetes
  • +
  • f36de2c (monitor) - pvc: upgrade to new format
  • +
  • fc78a0a (monitor) - workflow: remove namespace
  • +
  • e85890f (monitor) - monitor: monitoring nsqd and redis separately
  • +
  • 694f6b1 (monitor) - mirrors: delete aliyun mirrors
  • +
  • 4aea36a (monitor) - grafana: add ldap support for grafana
  • +
  • 68fc30f (nsqd) - nsq: update nsq
  • +
  • 16f32aa (nsqd) - charts: upgrade k8s newer API versions
  • +
  • 04db389 (redis) - reids: update to redis 6
  • +
  • 3f01bab (redis) - charts: upgrade k8s newer API versions
  • +
  • 647e4be (registry) - registry: del quay.io
  • +
  • 0bbce99 (registry) - charts: upgrade k8s newer API versions
  • +
  • a982b50 (registry) - minio: use bin mc replace docker images
  • +
  • e088da3 (registry-proxy) - ingress: renmae use_native_ingress to use_ingress
  • +
  • 7e88337 (registry-proxy) - nginx: upgrade nginx to mainline
  • +
  • 7204d72 (registry-proxy) - registry: optimizing variable naming
  • +
  • 2eafc59 (registry-proxy) - registry-proxy: update nginx
  • +
  • 071bd86 (registry-proxy) - charts: upgrade k8s newer API versions
  • +
  • c72db96 (registry-proxy) - registry-proxy: change travis icon url
  • +
  • ca9f962 (slugbuilder) - slugbuilder: del BUILDPACK_URL support
  • +
  • 1b74dd5 (slugbuilder) - slugbuilder: add heroku-20 support
  • +
  • 54d4ad2 (slugbuilder) - slugbuilder: del quay.io
  • +
  • a78f37e (slugbuilder) - slugbuilder: add heroku-20 stack
  • +
  • 94ac94a (slugbuilder) - minio: use bin mc replace docker images
  • +
  • 53b4b8b (slugbuilder) - slugbuilder: modify stack priority
  • +
  • 58e2bd2 (slugbuilder) - dockerfile: add WORKDIR /tmp
  • +
  • b29cd04 (slugbuilder) - slugbuilder: add pre_build.sh
  • +
  • 9d319f6 (slugbuilder) - slugbuilder: silent mc command output
  • +
  • d1ec3c9 (slugbuilder) - heroku: remove heroku-16 support
  • +
  • 5048534 (slugbuilder) - slugbuilder: use drycc stack-images
  • +
  • a116537 (slugrunner) - slugrunner: add heroku-20 support
  • +
  • a1196bf (slugrunner) - slugrunner: del quay.io
  • +
  • 64c96d7 (slugrunner) - slugrunner: add heroku-20 stack
  • +
  • cc3e226 (slugrunner) - minio: use bin mc replace docker images
  • +
  • 9130bde (slugrunner) - shellcheck: shellcheck installer
  • +
  • 4ea33e1 (slugrunner) - slugrunner: modify stack priority
  • +
  • 5514e8b (slugrunner) - heroku: remove heroku-16 support
  • +
  • be829fb (slugrunner) - slugrunner: use drycc stack-images
  • +
  • e1e06be (slugrunner) - slugrunner: remove Dockerfile.heroku-16
  • +
+ +
+ + + + + + + + + + + + + + + + +
+

Drycc Workflow v1.3.0

+
New Drycc Workflow Release v1.3.0
+ +

These release notes for Drycc Workflow v1.3.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.2.0, please refer to the following change summary.

+

Workflow ## v1.2.0 -> v1.3.0

+

Releases

+
    +
  • builder v1.0.2 -> v1.1.0
  • +
  • slugbuilder v1.1.0 -> v1.1.1
  • +
  • dockerbuilder v1.1.0 -> v1.1.1
  • +
  • controller v1.2.0 -> v1.2.1
  • +
  • slugrunner v1.1.0 -> v1.1.1
  • +
  • database v1.0.0 -> v1.0.1
  • +
  • fluentd v1.0.0 -> v1.0.1
  • +
  • minio v1.0.0 -> v1.0.1
  • +
  • monitor v1.0.0 -> v1.0.1
  • +
  • registry v1.0.1 -> v1.0.2
  • +
  • workflow-manager v1.0.0 -> v1.0.1
  • +
+

Features

+
    +
  • 9c7cceb (builder) - builder: add app config to env
  • +
+

Fixes

+
    +
  • 7fe44fa (controller) - docker: docker timeout must be an int, float or None
  • +
  • b196550 (controller) - controller: revert release.check_image_access for now
  • +
  • cc3ec13 (workflow-manager) - glide: bump goautoneg
  • +
+

Maintenance

+
    +
  • ef932c4 (builder) - controller-sdk-go: upgrade controller-sdk-go
  • +
  • 4654cf6 (controller) - django-rest-framework: upgrade to 3.9.3
  • +
  • 14121f1 (controller) - deps: bump djangorestframework from 3.9.3 to 3.9.4 in /rootfs
  • +
  • 385acdc (controller) - deps: bump django from 1.11.20 to 1.11.21 in /rootfs
  • +
  • fa312bb (database) - postgres: set max_connections = 1024
  • +
  • 7ebecdf (database) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z
  • +
  • b8878f6 (dockerbuilder) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z
  • +
  • b097451 (fluentd) - fluent: upgrade fluent to v1.4
  • +
  • 4341f9a (minio) - mc: upgrade mc and minio
  • +
  • c1ee2a4 (monitor) - monitor: remove copyrights.tar.gz
  • +
  • 9854260 (registry) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z
  • +
  • acc5627 (slugbuilder) - slugbuilder: internal support for multi buildpack
  • +
  • d58907e (slugbuilder) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z
  • +
  • b39a0c2 (slugrunner) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z
  • +
+ +
+ + + + + + + + + + + + + + + + +
+

Drycc Workflow v1.2.0

+
New Drycc Workflow Release v1.2.0
+ +

These release notes for Drycc Workflow v1.2.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.1.0, please refer to the following change summary.

+

Workflow ## v1.1.0 -> v1.2.0

+

Releases

+
    +
  • builder v1.0.1 -> v1.0.2
  • +
  • slugbuilder v1.0.0 -> v1.1.0
  • +
  • dockerbuilder v1.0.0 -> v1.1.0
  • +
  • controller v1.1.0 -> v1.2.0
  • +
  • slugrunner v1.0.0 -> v1.1.0
  • +
  • registry v1.0.0 -> v1.0.1
  • +
  • registry-proxy v1.0.1 -> v1.0.2
  • +
+

Features

+
    +
  • e5584e3 (controller) - controller: add STACK support
  • +
  • ad34dc1 (dockerbuilder) - kaniko: use kaniko replace docker-py
  • +
  • b81430e (dockerbuilder) - dockerbuilder: change image to image.json format
  • +
  • 60dde96 (slugbuilder) - slugbuilder: add STACK support
  • +
  • fe8b6e5 (slugrunner) - slugrunner: add STACK support
  • +
+

Maintenance

+
    +
  • 942f050 (builder) - registry: remove env DRYCC_REGISTRY_PROXY_PORT
  • +
  • ff7a16f (builder) - registry: remove ecr and gcr registry
  • +
  • ad13683 (builder) - builder: change DRYCC_BUILD_TYPE to DRYCC_STACK
  • +
  • 6def637 (builder) - registry: rename DRYCC_REGISTRY_SERVICE to DRYCC_REGISTRY_PROXY
  • +
  • 5044e22 (builder) - registry: remove registry_secret_prefix
  • +
  • 2ea39cc (builder) - controller-go-sdk: upgrade controller-go-sdk
  • +
  • 6aee0d7 (builder) - registry: optimizing variable naming
  • +
  • f9c62d9 (controller) - domain: added reserved domain check
  • +
  • f5a135b (controller) - migrations: clean old migrations
  • +
  • 4369b2c (controller) - registry: rename DRYCC_REGISTRY_SERVICE to DRYCC_REGISTRY_PROXY
  • +
  • 1057ca5 (controller) - registry: remove registry_secret_prefix
  • +
  • d114b3e (controller) - docker: update docker client
  • +
  • edbe963 (dockerbuilder) - dockerfile: change base image to alpine
  • +
  • fb35baf (dockerbuilder) - registry: rename DRYCC_REGISTRY_SERVICE to DRYCC_REGISTRY_PROXY
  • +
  • 946dbf6 (dockerbuilder) - docker: remove insecure support
  • +
  • 628d853 (dockerbuilder) - proxy: add registry proxy
  • +
  • ff27cbd (registry) - env: remove unused env
  • +
  • 7204d72 (registry-proxy) - registry: optimizing variable naming
  • +
+ +
+ + + + + + + + + + + + + + + +
+
+
+ + +
+ + + + + + diff --git a/blog/index.html b/blog/index.html new file mode 100644 index 000000000..7c0a902ce --- /dev/null +++ b/blog/index.html @@ -0,0 +1,445 @@ + + + + + + + + + + + + + + + + + + + + + +Blog | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + +
+
Posts in 2024
+
    +
  • +
    +
    Drycc Workflow v1.7.8
    +

    01.05.2024 in Release

    + + + + + + +

    Workflow ## v1.7.7 -> v1.7.8 Releases builder v1.6.0 -> v1.7.0 controller v1.8.0 -> v1.9.0 workflow-cli v1.6.0 -> v1.7.0 Features 384c7ee (builder) - domain: add procfile_type 26c8c7f (controller) - domain: add procfile_type bd49789 …

    +

    Read more

    +
    +
  • +
  • +
    +
    Drycc Workflow v1.7.7
    +

    30.04.2024 in Release

    + + + + + + +

    Workflow ## v1.7.6 -> v1.7.7 Releases builder v1.5.1 -> v1.6.0 controller v1.7.0 -> v1.8.0 database v1.2.1 -> v1.3.0 passport v1.2.0 -> v1.3.0 imagebuilder v1.1.1 -> v1.2.0 fluentbit v0.0.1 -> v0.0.2 logger v1.3.3 -> v1.3.4 …

    +

    Read more

    +
    +
  • +
  • +
    +
    Drycc Workflow v1.7.6
    +

    27.02.2024 in Release

    + + + + + + +

    Workflow ## v1.7.5 -> v1.7.6 Releases storage v0.0.4 -> v0.0.5 Maintenance 6cb63b6 (storage) - seaweedfs: bump version 3.63

    +

    Read more

    +
    +
  • +
  • +
    +
    Drycc Workflow v1.7.5
    +

    27.02.2024 in Release

    + + + + + + +

    These release notes for Drycc Workflow v1.7.5 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.7.4, please refer to the following change summary. …

    +

    Read more

    +
    +
  • +
  • +
    +
    Drycc Workflow v1.7.2
    +

    29.01.2024 in Release

    + + + + + + +

    These release notes for Drycc Workflow v1.7.2 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.7.1, please refer to the following change summary. …

    +

    Read more

    +
    +
  • +
+
Posts in 2023
+
    +
  • +
    +
    Drycc Workflow v1.7.0
    +

    08.12.2023 in Release

    + + + + + + +

    These release notes for Drycc Workflow v1.7.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.6.0, please refer to the following change summary. …

    +

    Read more

    +
    +
  • +
+
Posts in 2022
+
    +
  • +
    +
    Drycc Workflow v1.6.0
    +

    21.10.2022 in Release

    + + + + + + +

    These release notes for Drycc Workflow v1.6.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.5.0, please refer to the following change summary. …

    +

    Read more

    +
    +
  • +
  • +
    +
    Drycc Workflow v1.5.0
    +

    06.10.2022 in Release

    + + + + + + +

    These release notes for Drycc Workflow v1.5.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.4.0, please refer to the following change summary. …

    +

    Read more

    +
    +
  • +
+
Posts in 2021
+
    +
  • +
    +
    Drycc Workflow v1.4.0
    +

    06.10.2021 in Release

    + + + + + + +

    These release notes for Drycc Workflow v1.3.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.4.0, please refer to the following change summary. …

    +

    Read more

    +
    +
  • +
+
Posts in 2020
+
    +
  • +
    +
    Drycc Workflow v1.3.0
    +

    06.10.2020 in Release

    + + + + + + +

    These release notes for Drycc Workflow v1.3.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.2.0, please refer to the following change summary. …

    +

    Read more

    +
    +
  • +
+ +
+
+ +
+ +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/blog/index.xml b/blog/index.xml new file mode 100644 index 000000000..dec202249 --- /dev/null +++ b/blog/index.xml @@ -0,0 +1,1818 @@ + + + Drycc – Blog + /blog/ + Recent content in Blog on Drycc + Hugo -- gohugo.io + en + + + + + + + + + + + Blog: Drycc Workflow v1.7.8 + /blog/2024/05/01/drycc-workflow-v1.7.8/ + Wed, 01 May 2024 00:00:00 +0000 + + /blog/2024/05/01/drycc-workflow-v1.7.8/ + + + + <h2 id="workflow--v177---v178">Workflow ## v1.7.7 -&gt; v1.7.8<a class="td-heading-self-link" href="#workflow--v177---v178" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>builder v1.6.0 -&gt; v1.7.0</li> +<li>controller v1.8.0 -&gt; v1.9.0</li> +<li>workflow-cli v1.6.0 -&gt; v1.7.0</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/384c7ee9c69201b4d3280bb1582e50ad40210b8f"><code>384c7ee</code></a> (builder) - domain: add procfile_type</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/26c8c7f1a2ed3445fc4a52a5f7b8e7cace8a12e8"><code>26c8c7f</code></a> (controller) - domain: add procfile_type</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/bd49789b2aa8bbb8da440d63c83e339fd69d4774"><code>bd49789</code></a> (workflow-cli) - domain: add procfile_type</li> +</ul> + + + + + + Blog: Drycc Workflow v1.7.7 + /blog/2024/04/30/drycc-workflow-v1.7.7/ + Tue, 30 Apr 2024 00:00:00 +0000 + + /blog/2024/04/30/drycc-workflow-v1.7.7/ + + + + <h2 id="workflow--v176---v177">Workflow ## v1.7.6 -&gt; v1.7.7<a class="td-heading-self-link" href="#workflow--v176---v177" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>builder v1.5.1 -&gt; v1.6.0</li> +<li>controller v1.7.0 -&gt; v1.8.0</li> +<li>database v1.2.1 -&gt; v1.3.0</li> +<li>passport v1.2.0 -&gt; v1.3.0</li> +<li>imagebuilder v1.1.1 -&gt; v1.2.0</li> +<li>fluentbit v0.0.1 -&gt; v0.0.2</li> +<li>logger v1.3.3 -&gt; v1.3.4</li> +<li>storage v0.0.5 -&gt; v0.1.0</li> +<li>gateway v0.0.2 -&gt; v0.0.3</li> +<li>monitor v1.4.0 -&gt; v1.4.1</li> +<li>redis v1.3.2 -&gt; v1.4.0</li> +<li>timeseries v0.0.2 -&gt; v0.1.0</li> +<li>prometheus v0.1.1 -&gt; v0.1.2</li> +<li>rabbitmq v1.2.1 -&gt; v1.3.0</li> +<li>registry v1.2.2 -&gt; v1.3.0</li> +<li>registry-proxy v1.2.1 -&gt; v1.2.2</li> +<li>workflow-cli v1.5.2 -&gt; v1.6.0</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/6c1cf5e514543737c38384596abffca1ac96af44"><code>6c1cf5e</code></a> (builder) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/65ae63c4d3aaff3354d162718ff07c0509b4e689"><code>65ae63c</code></a> (builder) - pipeline: add dryccfile support</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/bb7b11de75226c3a1cb9254dfec78a8edda0c864"><code>bb7b11d</code></a> (builder) - auth: add tokens api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/39d022fe0a4106c91ea461f73728490560f8d653"><code>39d022f</code></a> (controller) - ps: add pod logs support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/86056d06d8992172fe02240d7963aa416ec9c754"><code>86056d0</code></a> (controller) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4cf005c1cc4b361af80ef96597e291ebe3baec24"><code>4cf005c</code></a> (controller) - limits: add limits plan support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/bf60e4bdbebb3f3288e0fbd81566c264dd187faf"><code>bf60e4b</code></a> (controller) - controller: add init job</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/98f77a8ceeea6e8a098cd37d79115201c40133e1"><code>98f77a8</code></a> (controller) - pipeline: add dryccfile support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8ce9a83f4bcf46d6039910e052e6ebfa959fd0e8"><code>8ce9a83</code></a> (controller) - cert-manager: add tls events</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7034f5d8347f0c85b40651eaf239a554fd95ae76"><code>7034f5d</code></a> (controller) - config: deploy according to procfile_type</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5554d8f9f26790783d97d6d6128920ffa9b28713"><code>5554d8f</code></a> (controller) - config: add typed_values</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/2c5bbad2d74b1c40c61158477aac9103dac2eff4"><code>2c5bbad</code></a> (controller) - auth: add token api</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/410d34e8e639c973557104c3aee14a85324f3c0f"><code>410d34e</code></a> (database) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/693e4d199b18342e33c7ec68c3a651d29b7d9ad6"><code>693e4d1</code></a> (imagebuilder) - pipeline: add dryccfile support</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/7d9cc0679eac7dd873d8db8f9607e347830b2aa1"><code>7d9cc06</code></a> (imagebuilder) - config: add typed values</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/854e1711180de70bc83d3c65721910df013ef988"><code>854e171</code></a> (passport) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/7ac92557670d915c1e568c7297c5ec1b9620f1a1"><code>7ac9255</code></a> (passport) - oauth2: add authorization code for any grant type</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/4517547e21983dd7192ae8cc985c974ed2c64b51"><code>4517547</code></a> (rabbitmq) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/bccfcb43cd63e62974b55523a75fa994ed560453"><code>bccfcb4</code></a> (redis) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/d8876055c0732c470d17d9205a5188289fdac1ec"><code>d887605</code></a> (registry) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/ff09e5b8279cd3343370bfa58c3acba234621263"><code>ff09e5b</code></a> (storage) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/c6e2ac82c8adc75687dbc814cb2163b06820311e"><code>c6e2ac8</code></a> (timeseries) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/22c4c772e3c9cbfe4f686d2fbe161b6484cdcc12"><code>22c4c77</code></a> (workflow-cli) - apps: change drycc run to async</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/a9e6369153255a6cc84dc73e3095086a34d25ad1"><code>a9e6369</code></a> (workflow-cli) - ps: add pod logs support</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/2bc31c8a2010e147b92827a967238e88dca5b743"><code>2bc31c8</code></a> (workflow-cli) - limits: add limits plan support</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/f40398a555e67a942fbe465d29e1076516941d74"><code>f40398a</code></a> (workflow-cli) - pipeline: add dryccfile support</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/03638ffdaefab5e0c7020f6eb279ddeda99aeded"><code>03638ff</code></a> (workflow-cli) - tls: add tls events</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/91136274d87d2cf9e0d2a1dd313d9b948a5d0a81"><code>9113627</code></a> (workflow-cli) - config: add typed values</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/43ee760c4bc93bc5e5402536a09f05dfd6832b7d"><code>43ee760</code></a> (workflow-cli) - auth: add tokens api</li> +</ul> +<h4 id="fixes">Fixes<a class="td-heading-self-link" href="#fixes" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/50dfe6449cbf50bfcf55421f34f2195cb8d7e26c"><code>50dfe64</code></a> (builder) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ab09b243b8484d8a989327e8e3b41f2a23efa643"><code>ab09b24</code></a> (controller) - healthcheck: delete outdated code</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/52019b541aaaca98b2b6692fec1290d1231e21fe"><code>52019b5</code></a> (controller) - services: default PORT change error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f57ae429fa4d9dbd89c7cf81f805fe9127930219"><code>f57ae42</code></a> (controller) - certificate: failed to create certificate</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/30c3f548324dcfa571a86afbed64ba0d38b72e99"><code>30c3f54</code></a> (controller) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/dbba43ae315644e858eb2330d52cbf636a366a07"><code>dbba43a</code></a> (controller) - service: update port error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e0459c5d43a74c2c38aae6ebf3e207ad8cc9f283"><code>e0459c5</code></a> (controller) - copy: use deepcopy replace copy</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/2122479685d9ce83c986449e20a041de105a2d49"><code>2122479</code></a> (controller) - charts: failed to call webhook</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/53d99775d66648aca41b88992df4ee203cb8f675"><code>53d9977</code></a> (controller) - signals: config limits handle error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/afda287ead80e94a699b3548c01fdfdbd1a6f5a4"><code>afda287</code></a> (controller) - limits: always set default</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/b350cb89e4c313d776592e9e4706909ee72550b5"><code>b350cb8</code></a> (database) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/b48a42243e602637fb04f14cb74d23e23096e2e2"><code>b48a422</code></a> (fluentbit) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/7cebca2a2589c839efbe49cbec6becde85149a8e"><code>7cebca2</code></a> (gateway) - cert-manager: auto tls error</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/190c19bbac3386e277bd7918be5b7f7ad5a25566"><code>190c19b</code></a> (imagebuilder) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/2c6a6f9273a0f5e2c16744f6ac6e77d27a7234a2"><code>2c6a6f9</code></a> (logger) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/10bb98df862bebefcf4142e88c24e8f804e310ba"><code>10bb98d</code></a> (monitor) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/f8225dca4c4ceae7bc4d613e77ae4c8ebf71838c"><code>f8225dc</code></a> (passport) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/06db66c072006f79c10404812ad9f0902cfb52b7"><code>06db66c</code></a> (prometheus) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/f4aff727962b6afe99e89283ce14ebe8d571d9ab"><code>f4aff72</code></a> (rabbitmq) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/88c18ff452bdd478f49dd88f6595ea096e430f2d"><code>88c18ff</code></a> (redis) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/5dcc19d6d47ea30b799ae10e915ebd948b39fc4c"><code>5dcc19d</code></a> (registry) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/092a9398243f19e41ac14cc5fb4f76473848c585"><code>092a939</code></a> (registry-proxy) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/3597ac918db548f837b3262a033d836690378972"><code>3597ac9</code></a> (storage) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/5a49b35d2197c957e43a98e94d38ac8a8ebd894b"><code>5a49b35</code></a> (timeseries) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/0c4a48a84b998b8e7f57f09f307930630e8efd74"><code>0c4a48a</code></a> (workflow-cli) - tls: change issuer options</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/06a2511195bc1f2a3145a73269428200914b4694"><code>06a2511</code></a> (workflow-cli) - tls: info error</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/2f7617e164707830b52f2ca39c7f634ca53842ed"><code>2f7617e</code></a> (builder) - go: bump controller-sdk-go version</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/aae2f2911197e4643e7a999944401d2e5acd884d"><code>aae2f29</code></a> (builder) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/7304980fb22cd0d56e1fa5b1e573b4795ef2ddd9"><code>7304980</code></a> (builder) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/30b648b0d429ba08f89e1d3b49078e40eae2d897"><code>30b648b</code></a> (builder) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/2afa006867a3d4d4501578f0973ff759d87af87f"><code>2afa006</code></a> (builder) - controller-sdk-go: bump version</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/d127a9070a6dd0be1d96860c719d3b4a71eb7bb9"><code>d127a90</code></a> (builder) - config: add typed values</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/32fdfd0e7f54793d3ced05ff42b300173debe866"><code>32fdfd0</code></a> (controller) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0974942fb8a70d9165ef6524744850cf72629a0c"><code>0974942</code></a> (controller) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f401e08d3ffbfee5d84410ad8e31c18a3267513e"><code>f401e08</code></a> (controller) - python: bump python 3.12</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c565959af53e6ab7be7245faea09fd1a30972ac7"><code>c565959</code></a> (controller) - celery: remove retrieve_resource task</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/47be1a10b03d7522a9bc87b9973c8f126db95478"><code>47be1a1</code></a> (controller) - requirements: bump drf 3.15.1</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/99f7468e561d596121bc981294e6ca4baaed2728"><code>99f7468</code></a> (controller) - charts: add config to values.yaml</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7d17f5ca716596ef66046eb5f3606215feb87731"><code>7d17f5c</code></a> (controller) - scale: prohibit scale when there is a running pipeline</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f09e1c9475e64840ff02e23cee30f5911b507a58"><code>f09e1c9</code></a> (controller) - resource: sort services and plans</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e817505fc5dc6a2e9b959b9fd7d63c044f17fcf1"><code>e817505</code></a> (controller) - limits: change default cpu and gpu name</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5531b2ff4b15a6b9804cc0b146b69ee7308a1a83"><code>5531b2f</code></a> (controller) - auth: add password login</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/27473f72e8b7c1f1b6bb9c56493688f346bbcc9c"><code>27473f7</code></a> (controller) - deps: bump gunicorn from 21.2.0 to 22.0.0 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c1ee1c7a3103c938b8b81219da7b14cd30f3eceb"><code>c1ee1c7</code></a> (controller) - deps: bump aiohttp from 3.9.3 to 3.9.4 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/affbcb587360d7750f3faf4d022e36032f0b3266"><code>affbcb5</code></a> (database) - postgres: add patroni and postgres params (#15)</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/f9e4edaf9a2a22b974a2aced48a7890f767da0c0"><code>f9e4eda</code></a> (database) - dockerfile: install vi</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/008b7b675c244d2aff9b86947fe907dbb84185f4"><code>008b7b6</code></a> (database) - dockerfile: install vim instand of vi</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/dbbfee12b2fe9c773d32660a6bcf26674ae2cd61"><code>dbbfee1</code></a> (database) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/2e26c333df5aa90243cff8c5159a6c3a9b499a00"><code>2e26c33</code></a> (database) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/a1b81f20f517743d9f69ecda526095a4e9c3ee36"><code>a1b81f2</code></a> (database) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/bc725e8169b25eda4017012f72b5d970147f0d08"><code>bc725e8</code></a> (fluentbit) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/5d738865825bd083561972373a5dd8796a53be6c"><code>5d73886</code></a> (fluentbit) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/b85072d0177447ac3f05f1f4ccd4c9d7f4a56f99"><code>b85072d</code></a> (fluentbit) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/761174ddb5bc06643a02c145714587816ea06f8a"><code>761174d</code></a> (gateway) - gateway: change secrets name</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/1c304da25eef99568badf3ece29639dd6d8f8564"><code>1c304da</code></a> (gateway) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/b919a4c24b5abb776876df002cc9d4c15cf3d50d"><code>b919a4c</code></a> (gateway) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/3cea298be74856a2fba40b0a35824e0f3018dcab"><code>3cea298</code></a> (imagebuilder) - charts: allow all dns</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/653bcbeec95adcea209299751a3a94f3ebaf2d4f"><code>653bcbe</code></a> (imagebuilder) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/59daeab055610ce6cc584be73dba3767158b9747"><code>59daeab</code></a> (imagebuilder) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/2834a5acb914eecb7708ad3bd3efdcc38243d784"><code>2834a5a</code></a> (logger) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/6685492c2a8493bad3b59dedb201576f7508ff86"><code>6685492</code></a> (logger) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/191cdaf001ab5b916b0edf53aaa2a7558ef7f35a"><code>191cdaf</code></a> (logger) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/b3c3cfa319fe46d30696a2f4637f91636398ffff"><code>b3c3cfa</code></a> (monitor) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/796799db309de06ea54db56a1c0e5f397c858f47"><code>796799d</code></a> (monitor) - grafana: add node metrics dashboard</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/ef2a2228a27e4eddce1ff3b4b56755ab013c47cd"><code>ef2a222</code></a> (monitor) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/9c830909640fddca03329d4a72eb91ab1d913c86"><code>9c83090</code></a> (monitor) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/1a97c2cedd3ace5c567bf32dbd057bd215502662"><code>1a97c2c</code></a> (passport) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/353e1ae932ea4dae5112b8f8225ee502695b11ee"><code>353e1ae</code></a> (passport) - logger: add oauth2_provider logger config</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/fe735c0d8c5a2840349b27ceb081d02729ae50bf"><code>fe735c0</code></a> (passport) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/41d6144a20f24461e1a393d4b1957f5be19f4f3a"><code>41d6144</code></a> (passport) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/979d4740bdd50a12f5110144cf413c3972164c90"><code>979d474</code></a> (passport) - python: bump python 3.12</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/e9f41a121e11becd9dcd6b5422dcc6e209cbeedf"><code>e9f41a1</code></a> (passport) - requirements: bump drf 3.15.1</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/f479f4d5791ac2917679b70f376ec9bf24fa1fd4"><code>f479f4d</code></a> (passport) - charts: add migrate job</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/ad9abf64ad7e2b959d565eaa0016066183444cd0"><code>ad9abf6</code></a> (passport) - passport: migrations add run_before</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/95ac66705669bd4301af9d3ae812e0843eb6a37c"><code>95ac667</code></a> (passport) - passport: optimize the use of master and slave database rules</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/204f7fc62fd0cdf016cd5e95a4d2fd2e6c841b17"><code>204f7fc</code></a> (passport) - deps: bump gunicorn from 21.2.0 to 22.0.0 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/90a6410c0d0864a434b804cf80fe63960afd4493"><code>90a6410</code></a> (prometheus) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/2d8eb44ef28deae27ac54247a008a5351212eea0"><code>2d8eb44</code></a> (prometheus) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/9687a175b58aed22d314557d7254a82ff0a6d3dd"><code>9687a17</code></a> (rabbitmq) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/35d3d5b7e01bebbeeea5442a22f24d40fcbfdd93"><code>35d3d5b</code></a> (rabbitmq) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/6a6564ddef4f26bc81ea3eb9e965fb8e6180d092"><code>6a6564d</code></a> (rabbitmq) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/cb6722f0df93fae95d4480e1929b55e1e78a2a3a"><code>cb6722f</code></a> (redis) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/9553497d89e358022ab539cb3db658def17bc9cb"><code>9553497</code></a> (redis) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/1c8dc07b0167126d292e3db45f23db5d6ff111dc"><code>1c8dc07</code></a> (redis) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/9fa2a32f965d282940cd3f8489ce8959bb2e791f"><code>9fa2a32</code></a> (registry) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/9b09e51c1d548ba4d1c088aff761391092d746e3"><code>9b09e51</code></a> (registry) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/7dbd3902139c8430c18bfb83e4dbce79a6df16a5"><code>7dbd390</code></a> (registry) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/e1d2a33d8c9f20eddce510d79df050b0fe90a94c"><code>e1d2a33</code></a> (registry-proxy) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/3eabfdda5c2a78fc49e73dce382263faad29f5c3"><code>3eabfdd</code></a> (registry-proxy) - charts: remove default limits</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/f8754dad5de5f88bb0f20f46d73e1cbab2aff68e"><code>f8754da</code></a> (registry-proxy) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/7df73166e6ea521587eb2ba5b8e1626cc334d7f3"><code>7df7316</code></a> (registry-proxy) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/861d3b8f5ebc2ee32f11a600b26a14d79e0acdf1"><code>861d3b8</code></a> (storage) - filer: modify the default parameters of the filer</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/5fa08da71087503071fa780ac2469f4d55e7d0c5"><code>5fa08da</code></a> (storage) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/22c4620e0e724b26943260d58d749bb4efd0999b"><code>22c4620</code></a> (storage) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/6c1e29c1bf187e2b754d6f683014dba7a4ebe342"><code>6c1e29c</code></a> (timeseries) - postgres: add patroni params</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/e280d3ff2d799fa1e0738bf6e7585aaba0e72c58"><code>e280d3f</code></a> (timeseries) - dockerfile: install vi</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/5213617c4a5ace9225e1cad8348c736b943c5e25"><code>5213617</code></a> (timeseries) - dockerfile: install vim instand of vi</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/a569a57f06484738d5801651f9e253553347f928"><code>a569a57</code></a> (timeseries) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/b93ec702dcbd0e2306d0290cde2d104d4c5897f3"><code>b93ec70</code></a> (timeseries) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/ff3b8705e65a56f0da392519b54f9b060894ec8c"><code>ff3b870</code></a> (timeseries) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/e334f74a71ffbd5f10baa38da43248d92c051322"><code>e334f74</code></a> (workflow-cli) - healthcheck: delete outdated healthcheck style</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/4f8b960e9ddcd1351b4567935d0a8d98d2aa843d"><code>4f8b960</code></a> (workflow-cli) - auth: add password login</li> +</ul> + + + + + + Blog: Drycc Workflow v1.7.5 + /blog/2024/02/27/drycc-workflow-v1.7.5/ + Tue, 27 Feb 2024 00:00:00 +0000 + + /blog/2024/02/27/drycc-workflow-v1.7.5/ + + + + <p>These release notes for Drycc Workflow v1.7.5 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.7.4, please refer to the following change summary.</p> +<h2 id="workflow--v174---v175">Workflow ## v1.7.4 -&gt; v1.7.5<a class="td-heading-self-link" href="#workflow--v174---v175" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>builder v1.5.0 -&gt; v1.5.1</li> +<li>controller v1.6.3 -&gt; v1.7.0</li> +<li>logger v1.3.2 -&gt; v1.3.3</li> +<li>storage v0.0.3 -&gt; v0.0.4</li> +<li>redis v1.3.1 -&gt; v1.3.2</li> +<li>rabbitmq v1.2.0 -&gt; v1.2.1</li> +<li>registry v1.2.1 -&gt; v1.2.2</li> +<li>workflow-cli v1.5.1 -&gt; v1.5.2</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/95d130a19f63544defbf415d63ea44b650d07da7"><code>95d130a</code></a> (controller) - controller: volume support nfs</li> +</ul> +<h4 id="fixes">Fixes<a class="td-heading-self-link" href="#fixes" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ee2ee15992331922728aabcf03420fbad7b76a1d"><code>ee2ee15</code></a> (controller) - controller: container entrypoint error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/03ea4f87b58f2e3f12505ff0ba43ab655fdf0528"><code>03ea4f8</code></a> (controller) - controller: class property have been deprecated in python 3.11</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5f04d177fa399a7859d4f0d8e13b58e77983c2e9"><code>5f04d17</code></a> (controller) - controller: miss err msg</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/27972a3a48f5fb67283c50b95e58da7b7ef05458"><code>27972a3</code></a> (controller) - controller: load_db_state_to_k8s err</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a005d629bbdd9a5d68f5bb4c480fd9e6b51300c7"><code>a005d62</code></a> (controller) - controller: volume repeat path no error</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/c7a5ba62b8e513f43aad8143e507d23885558834"><code>c7a5ba6</code></a> (rabbitmq) - rabbitmq: cpu usage to high</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/45c20770d8203ae475c127fe82b00bd04334507d"><code>45c2077</code></a> (workflow-cli) - workflow-cli: miss err msg</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/bc738bd6ef19fa222e675058bc0af79b75026308"><code>bc738bd</code></a> (workflow-cli) - workflow-cli: volumes list format</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/35e1c063c5f40fc97f60ab2a0b9f66de37eef383"><code>35e1c06</code></a> (builder) - builder: bump golang 1.22</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/26caa36c197b968909da1a584dff686cd6bcd651"><code>26caa36</code></a> (controller) - deps: bump aiohttp from 3.9.0 to 3.9.2 in /rootfs (#118)</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3d938c4f00b4a972abe948dc814b2cbf41ea2b3b"><code>3d938c4</code></a> (controller) - deps: bump django from 4.2.7 to 4.2.10</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/e625c2f86176c0acff331f58f84da15d96041f21"><code>e625c2f</code></a> (logger) - logger: bump golang 1.22</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/bfa500dc9271bf0a475c50feb8e6be8574953bcd"><code>bfa500d</code></a> (redis) - redis: headless svc does not require ports</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/330209a5c329c0f34b47a07812e7282ad7890208"><code>330209a</code></a> (registry) - registry: headless svc does not require ports</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/48c42eb3d6ef09471d26a65c88f5cd88cd6684e8"><code>48c42eb</code></a> (storage) - storage: change volume index to leveldb</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/f4fde9d2c871162c14ecf0e993093211f49e7c66"><code>f4fde9d</code></a> (storage) - storage: add volume size limit</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/33e3684ec520a83bccdf7623d4b3d1317c10e9a0"><code>33e3684</code></a> (workflow-cli) - workflow-cli: volume support nfs</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/48d59507ab5f40e8a8cea9875b230e9e1b97644d"><code>48d5950</code></a> (workflow-cli) - workflow-cli: bump golang 1.22</li> +</ul> + + + + + + Blog: Drycc Workflow v1.7.6 + /blog/2024/02/27/drycc-workflow-v1.7.6/ + Tue, 27 Feb 2024 00:00:00 +0000 + + /blog/2024/02/27/drycc-workflow-v1.7.6/ + + + + <h2 id="workflow--v175---v176">Workflow ## v1.7.5 -&gt; v1.7.6<a class="td-heading-self-link" href="#workflow--v175---v176" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>storage v0.0.4 -&gt; v0.0.5</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/6cb63b632ab24cecda10e2e772f46e499d678aa5"><code>6cb63b6</code></a> (storage) - seaweedfs: bump version 3.63</li> +</ul> + + + + + + Blog: Drycc Workflow v1.7.2 + /blog/2024/01/29/drycc-workflow-v1.7.2/ + Mon, 29 Jan 2024 00:00:00 +0000 + + /blog/2024/01/29/drycc-workflow-v1.7.2/ + + + + <p>These release notes for Drycc Workflow v1.7.2 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.7.1, please refer to the following change summary.</p> +<h2 id="workflow--v171---v172">Workflow ## v1.7.1 -&gt; v1.7.2<a class="td-heading-self-link" href="#workflow--v171---v172" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>controller v1.6.0 -&gt; v1.6.1</li> +<li>logger v1.3.1 -&gt; v1.3.2</li> +<li>storage v0.0.1 -&gt; v0.0.2</li> +<li>timeseries v0.0.1 -&gt; v0.0.2</li> +<li>prometheus v0.1.0 -&gt; v0.1.1</li> +<li>workflow-cli v1.5.0 -&gt; v1.5.1</li> +</ul> +<h4 id="fixes">Fixes<a class="td-heading-self-link" href="#fixes" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/2fe80a65e2f564abe94a04a4018af101ca10d55d"><code>2fe80a6</code></a> (controller) - resources: after resources instance update, could not delete (#111)</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a4082ad0c4fca861bc713864ec4539249b707c0e"><code>a4082ad</code></a> (controller) - controller: resource status and binding</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e9bfccc307fd9631361eaedd1db0c98fb11f7a9b"><code>e9bfccc</code></a> (controller) - controller: fix multiple volumes mount at one dir error (#116)</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/58d2b4c35020c25e133f46bb48f7b512e41a0f91"><code>58d2b4c</code></a> (logger) - logger: redis conn error block</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/7cb2700c483040869f3fa5ff1af76cf68d8e8711"><code>7cb2700</code></a> (prometheus) - prometheus: prometheus config basic_auth</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/7838c6b63eec363ec0fccbc8a2b455477edb69db"><code>7838c6b</code></a> (storage) - storage: random accesskey secretkey</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/d9dcdfb7350c003a60883c9e70e3afca730d5419"><code>d9dcdfb</code></a> (storage) - storage: pod restart loses data</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/3cbdd29c8dd94d7bd046a3fe817dabbb59887225"><code>3cbdd29</code></a> (storage) - storage: tipd cannot start after deleting pod</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/be7e11fe5a8a861a976c27b69331779b4edd0a3a"><code>be7e11f</code></a> (storage) - storage: jq command not found</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/878f674be07b4aee660ec66830a9fe29473bdaba"><code>878f674</code></a> (storage) - storage: charts updateStrategy error</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/06cfe561e1327690dfcccd7151711053b8126a9a"><code>06cfe56</code></a> (timeseries) - timeseries: the data node ip is incorrect</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7f29f5a98049b0c256728dad38cf63026c45910e"><code>7f29f5a</code></a> (controller) - resources: retrieve resource instance response add message (#112)</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4a84dcdca75a3c1cd037c01777cf410c21c56225"><code>4a84dcd</code></a> (controller) - controller: add deploy default annotations (#113)</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/829d7e560317a0ac20081f6bd4c81f53b547aac4"><code>829d7e5</code></a> (controller) - controller: modify url match service name (#114)</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/30abf6dba46d215d7747b4443826e6e3fac1138a"><code>30abf6d</code></a> (controller) - controller: transfer app ownership in async</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/dc6f45e98ab77a776a620286465da106a8109ba6"><code>dc6f45e</code></a> (controller) - controller: add channel for pod exec</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/af4f3a771d8a7c6f1f99c17acb67704d9f3f921f"><code>af4f3a7</code></a> (controller) - controller: avoid error when secret no data field (#117)</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ca27956696aa6bd2e4adefcc6827f840eefd4b34"><code>ca27956</code></a> (controller) - controller: add pod default security</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/b2e9c647ff2a1e7828946d363b6cfc5bdca2deb7"><code>b2e9c64</code></a> (prometheus) - charts: node-exporter mount root (#2)</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/3cdb2b62fe9e2d6f7506c5215be9e3e7d27254b3"><code>3cdb2b6</code></a> (storage) - storage: bump seaweedfs 3.61</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/00dd2fd331104fd4f7ee58ca35a0906588318d16"><code>00dd2fd</code></a> (storage) - storage: add csi daemonset updateStrategy</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/48e763cb34c3e9b1004ad222a1e4670739e0b9ba"><code>48e763c</code></a> (storage) - storage: add drycc storage upgrade document</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/841df90682a121df819ea11ba8d2dc7843ffcd54"><code>841df90</code></a> (storage) - storage: bump seaweedfs 3.62</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/cefd52e7b031efc05f305a8d8f456229418556f8"><code>cefd52e</code></a> (timeseries) - timeseries: add check data node exists</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/ad1c46e39f392dd676a0f5c8e00b05ed1959cb95"><code>ad1c46e</code></a> (workflow-cli) - resources: resources instance add message</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/9f955c2c97a0a2875f7badadb4f868649cf44b2e"><code>9f955c2</code></a> (workflow-cli) - workflow-cli: add short options cpu</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/65399ef156b9fae2d2fe633cb6b4b63fb6263a1c"><code>65399ef</code></a> (workflow-cli) - workflow-cli: add tty resize support</li> +</ul> + + + + + + Blog: Drycc Workflow v1.7.0 + /blog/2023/12/08/drycc-workflow-v1.7.0/ + Fri, 08 Dec 2023 00:00:00 +0000 + + /blog/2023/12/08/drycc-workflow-v1.7.0/ + + + + <p>These release notes for Drycc Workflow v1.7.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.6.0, please refer to the following change summary.</p> +<h2 id="workflow--v160---v170">Workflow ## v1.6.0 -&gt; v1.7.0<a class="td-heading-self-link" href="#workflow--v160---v170" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>builder v1.4.0 -&gt; v1.5.0</li> +<li>controller v1.5.1 -&gt; v1.6.0</li> +<li>database v1.2.0 -&gt; v1.2.1</li> +<li>passport v1.1.0 -&gt; v1.2.0</li> +<li>imagebuilder v1.1.0 -&gt; v1.1.1</li> +<li>fluentbit v0.0.0 -&gt; v0.0.1</li> +<li>logger v1.3.0 -&gt; v1.3.1</li> +<li>storage v0.0.0 -&gt; v0.0.1</li> +<li>gateway v0.0.0 -&gt; v0.0.1</li> +<li>monitor v1.3.0 -&gt; v1.4.0</li> +<li>redis v1.3.0 -&gt; v1.3.1</li> +<li>timeseries v0.0.0 -&gt; v0.0.1</li> +<li>prometheus v0.0.0 -&gt; v0.1.0</li> +<li>rabbitmq v1.1.0 -&gt; v1.2.0</li> +<li>registry v1.2.0 -&gt; v1.2.1</li> +<li>registry-proxy v1.2.0 -&gt; v1.2.1</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/fcbebdae62029cf4308ffc0adeb8a90cf5550077"><code>fcbebda</code></a> (builder) - builder: use TCPRoute expose service</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d02bb5de832e50a281aa550c738b3eb653549806"><code>d02bb5d</code></a> (controller) - controller: support app dns policy config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9aa968ebccdebaf0971a6dbaa890320b9603a6a9"><code>9aa968e</code></a> (controller) - controller: add svc type support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/62e2d348e2987ebcdcaba993559dc1d30a8ffec6"><code>62e2d34</code></a> (controller) - controller: improve the services api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4393755b08a587e093b7603683ac8b5cdf654ac3"><code>4393755</code></a> (controller) - controller: use gateway replace ingress</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/323045d9ab1589c08a8090d7fe9c73ab6276281d"><code>323045d</code></a> (controller) - controller: add canary support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3f81c975baefd4018e6b3426965b4397456f0d0e"><code>3f81c97</code></a> (controller) - gateways: add addresses field</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4e64aa73d0fde9fe667064b420bd9375dbea8397"><code>4e64aa7</code></a> (controller) - gateways: add addresses field</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/02ad5811d9a8d3e031ce97f8ce85d0ce85be7619"><code>02ad581</code></a> (monitor) - grafana: add pd tikv dashboard</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/2a9e2b042941a911a31c846f71988d6eadeff811"><code>2a9e2b0</code></a> (monitor) - monitor: add storage monitor</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/41d5057b1d4067822edcf597e888b3f23e052d9d"><code>41d5057</code></a> (monitor) - grafana: data source change to prometheus</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/ec035d11f3fcf8486f4240aac8db4890e4520b53"><code>ec035d1</code></a> (monitor) - monitor: usegateway replace ingress</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/c694c98cfab10d8381fd70d7efbbdaedc26caf2d"><code>c694c98</code></a> (monitor) - grafana: add drycc storage seaweedfs dashboard</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/1e1fdc8a8f3ca0974ff5d06ade500afed29a16ed"><code>1e1fdc8</code></a> (passport) - passport: use gateway replace ingress</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/ffdb408776bfa42c80ba5df56730c689a26a821a"><code>ffdb408</code></a> (prometheus) - prometheus: use gateway replace ingress</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/04152b99ca9a8aacddc246af78968191e41ea9d7"><code>04152b9</code></a> (rabbitmq) - rabbitmq: use gateway replace ingress</li> +</ul> +<h4 id="fixes">Fixes<a class="td-heading-self-link" href="#fixes" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/0499500a1335791a89ffcab18e97b22d55ac232c"><code>0499500</code></a> (builder) - builder: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/642491d68a4958cdd6b9b78771ad512d7a462231"><code>642491d</code></a> (builder) - builder: no build log</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/873d146812f40de609100d9a2181d50e79695a54"><code>873d146</code></a> (controller) - controller: do not set entrypoint when no procfile</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d9028c53547b4d53d46d5cba508602ae31d0b391"><code>d9028c5</code></a> (controller) - controller: pip8 error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3efcfb764325255ff9ae4ca47ab82927e88ff9ab"><code>3efcfb7</code></a> (controller) - controller: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/18a3a1a3f777597966da8f8fb21545a18b44d887"><code>18a3a1a</code></a> (controller) - controller: miss service error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/94f796cd2ebd8dd76b4e8073cab039fed0211cae"><code>94f796c</code></a> (controller) - controller: drycc run pod should not restart</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/80f31614601daf30351033c3d9ce8610d4a41581"><code>80f3161</code></a> (controller) - controller: monitor query error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b76f2c5ee9c0e3461737ec7fc6cc73b73a0c043c"><code>b76f2c5</code></a> (controller) - controller: read websocket delay</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b6e068ee19354b98d613985c8c80ec6d42171cc0"><code>b6e068e</code></a> (controller) - controller: metrics sql tpl, gateway pod should not restart, cleanup old rs, update monitor datatbase config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ad9adc645759445702688b2a486ed5d6a1e6a5f7"><code>ad9adc6</code></a> (controller) - controller: rabbitmq sharding err</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/67739075a1134b817e9be97b7d594c1e3790f444"><code>6773907</code></a> (controller) - controller: default k8s pod annotaions</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ffcf1f931c395c3293d909f32a3bf35136b72776"><code>ffcf1f9</code></a> (controller) - controller: under-indented for visual indent</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3afd0cf8e36cec5bbfb59424d5ab036268287d3a"><code>3afd0cf</code></a> (controller) - controller: charts env error</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/769bb8b8dc47ef032377a61e6288c514bff16a9b"><code>769bb8b</code></a> (database) - database: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/769bb8b8dc47ef032377a61e6288c514bff16a9b"><code>769bb8b</code></a> (database) - database: label conflict error</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/6a321c5c802b3a0826bc283f2ffe429769f8753c"><code>6a321c5</code></a> (database) - database: link error</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/558feae9c0edfb4fa7f0dae08f09dc987f822c88"><code>558feae</code></a> (fluentbit) - fluentbit: build charts error</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/98d8a2a6046dffa3213f84fd5cb2f054727ca798"><code>98d8a2a</code></a> (gateway) - fixup</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/8b5dde1d5b0107913f3fca7c90703902fd9a360e"><code>8b5dde1</code></a> (gateway) - gateway: secretName</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/702866da3014497e303eb346be0f88c3c161586c"><code>702866d</code></a> (gateway) - gateway: build status</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/f55dac1cbab3214f60b33992f3e08e186bfa6198"><code>f55dac1</code></a> (imagebuilder) - imagebuilder: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/ac13b5f036e036073d39ddf2e34627be340df078"><code>ac13b5f</code></a> (imagebuilder) - imagebuilder: build svg</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/6b7bbc5a38a8550457585908ac7ce9858c19a034"><code>6b7bbc5</code></a> (logger) - logger: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/0136b5c3ac711f132be35d8382f9df9268145be6"><code>0136b5c</code></a> (monitor) - monitor: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/f03d975fe88a4419f58b54f8d1ac944f968b0bfe"><code>f03d975</code></a> (passport) - passport: DRYCC_GRAFANA_DOMAIN error</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/b530ea8960c173b16968dc5c4da5f8e5f783d9dd"><code>b530ea8</code></a> (passport) - passport: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/be5a0a77f5e037456676af5617cdcd01c2f868ea"><code>be5a0a7</code></a> (passport) - passport: change passport</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/1596c7f723d493b8f17e367999e0315d7f2bc205"><code>1596c7f</code></a> (rabbitmq) - rabbitmq: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/0dc4f6fef0bf147e2cec96cd26f490ae5799fa57"><code>0dc4f6f</code></a> (rabbitmq) - rabbitmq: images-shard error</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/43293ae792f0fc8fa932b7fac865f57510de793d"><code>43293ae</code></a> (redis) - redis: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/ca13b7d7592995b057f1075b3223074c7a9de54b"><code>ca13b7d</code></a> (registry) - registry: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/ab5c7937aac830c2b09b08777f39180248911442"><code>ab5c793</code></a> (registry) - registry: garbage collect error</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/ab0fabc77483f531acaeaa089afce1636200c20a"><code>ab0fabc</code></a> (registry-proxy) - registry-proxy: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/dfc72361f70380697d7090cb0e5bfa61c5264560"><code>dfc7236</code></a> (registry-proxy) - registry-proxy: daemon yaml format</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/42c03bee957cb46b5703cd163cea24c754b3cccc"><code>42c03be</code></a> (storage) - storage: seaweedfs csi error</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/453e41a13ecaedf256dc823c37de3233a2f60cab"><code>453e41a</code></a> (timeseries) - timeseries: could not register node</li> +</ul> +<h4 id="docs">Docs<a class="td-heading-self-link" href="#docs" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/5433c8907bdf4c0320566878a0cfc4f38730f3d4"><code>5433c89</code></a> (gateway) - gateway: add prerequisites</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/2f0c5d8ed5a227507f7848426824759db673eb20"><code>2f0c5d8</code></a> (logger) - logger: change architecture</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/bdd02ebf1178209cca08c0e94d76638405100083"><code>bdd02eb</code></a> (builder) - builder: use dynamic clusterrole name</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/66b4b25ec7c517152a37e375f9a7e86e05cceada"><code>66b4b25</code></a> (builder) - builder: upgrade new controller-go-sdk</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/219d86f6bebf11fce80e2535b724bf8ad94b204b"><code>219d86f</code></a> (builder) - builder: upgrade go.mod</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/91f2f14b0b02af099fe67d4a9be65432de0cb18d"><code>91f2f14</code></a> (builder) - builder: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/9abca168d6a8b26f45a3787c2a80bf5aa6354451"><code>9abca16</code></a> (builder) - woodpecker: use woodpecker ci build status</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/f43dd5030ac3715ab96cfb2a114bd0416b21110c"><code>f43dd50</code></a> (builder) - deps: bump golang.org/x/net from 0.2.0 to 0.7.0</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/0384c69ad46cdabeabb3ca23d01367d047eb0c84"><code>0384c69</code></a> (builder) - builder: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/e3149b95e8c64c1d01444d58de67aa4747c4ebf7"><code>e3149b9</code></a> (builder) - builder: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/d88ea1bd5538e5425cb4cbb856ab82bb5dfe47e8"><code>d88ea1b</code></a> (builder) - builder: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/ba590303b791ff954e41a64ef8babe54170aba3b"><code>ba59030</code></a> (builder) - builder: upgrade go.mod</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/1114dd7d951215c23a6fcefc75a5a71a85391561"><code>1114dd7</code></a> (builder) - builder: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/fe50b626d9edf4908f6c820fa2714e5bde0fbc0e"><code>fe50b62</code></a> (builder) - builder: change drycc gateway listener name</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/db3950cf47cd8f5f0c06c579eec1189c2bcdb0b3"><code>db3950c</code></a> (builder) - builder: remove gateway route</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/5a508bbc9e21852c4e47e598bb42a7c8c75e93ee"><code>5a508bb</code></a> (builder) - builder: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/bbb9029e773f24d2692afdd801e8d09ca75538a3"><code>bbb9029</code></a> (builder) - deps: bump golang.org/x/net from 0.12.0 to 0.17.0</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/f4e5d6ca78d597e020ce398fd9fd132c41591826"><code>f4e5d6c</code></a> (builder) - builder: remove health url</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/9111c8ffd87978db6734d405ef0362c34b9fe4ef"><code>9111c8f</code></a> (builder) - builder: remove io/ioutil</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1f36e3ddd67b29571707c57819bdd8148647359c"><code>1f36e3d</code></a> (controller) - deps: bump django from 4.1.2 to 4.1.6 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e4ab434db6fd84cd35a127c8414951df7e138503"><code>e4ab434</code></a> (controller) - controller: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9f0301e4a138d337d9530807b347775d25ee6525"><code>9f0301e</code></a> (controller) - deps: bump django from 4.1.6 to 4.1.7 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/39324238c251f982072b28fdbb79c04df6230889"><code>3932423</code></a> (controller) - woodpecker: use woodpecker ci build status</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ae8b6b464f3733bd0ca743bd419ecf806646909f"><code>ae8b6b4</code></a> (controller) - setting: support KUBERNETES_LIMITS env config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c10b9bc740f74ed820d36ba5cb6eb462bce3bb7c"><code>c10b9bc</code></a> (controller) - controller: using the api_version instead of hard coding</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e6908cd934ec0360344c2120bbd4bd9a27b6fe9d"><code>e6908cd</code></a> (controller) - controller: upgrade requirements</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b0eba0c0f03b3b74bf6b2d013a8e2fd69dd5fc6c"><code>b0eba0c</code></a> (controller) - controller: add route rules serializer</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/2e4b6a457f6ab66137badecaa0ce5a020e2208e2"><code>2e4b6a4</code></a> (controller) - controller: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7d32b55dad2a0da5a2d539c970608182dfd00c52"><code>7d32b55</code></a> (controller) - controller: upgrade to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f2dc8dd737e44d1297f6a6903bc17392f767a828"><code>f2dc8dd</code></a> (controller) - controller: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5739b8306921408b11b921515cd6dc7a818e6a1a"><code>5739b83</code></a> (controller) - controller: use timescaledb replace influxdb</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/53892cb796b69ba91b1520ee2b1e35bf6516fb57"><code>53892cb</code></a> (controller) - controller: add timeseries</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0fe0eae17d2af7e0a955d6e8041db22a66b64317"><code>0fe0eae</code></a> (controller) - controller: upgrade requirements</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/18b2a915d043cade51e0d4017d08e4ffa9f54dd6"><code>18b2a91</code></a> (controller) - deps: bump aiohttp from 3.8.4 to 3.8.5 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f50874a6e180d9a18fd3a9b9ad1ec1491acae114"><code>f50874a</code></a> (controller) - controller: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/956cd081922f8eeda637530e8397a40d9f7d9c3d"><code>956cd08</code></a> (controller) - controller: change drycc gateway listener name</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9ab3ead47263e0f00f5d31afdad028eedefd6a56"><code>9ab3ead</code></a> (controller) - controller: remove passport url check</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a24c7b011de56845fcc0ffaa78424d60e6cb8aac"><code>a24c7b0</code></a> (controller) - controller: remove gateway route</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f7e539acb9890593d5b3ba970221f333b81abff5"><code>f7e539a</code></a> (controller) - controller: change celery priority</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ab77a529bc9ac2e61a45af4676b8d8796789f014"><code>ab77a52</code></a> (controller) - controller: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8e27501fc6f024bd590508ad827d6a28ca871776"><code>8e27501</code></a> (controller) - controller: dynamic app storage class</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/385978b8f8a07696196974f7f021886448fbc31c"><code>385978b</code></a> (controller) - controller: list_pods datetime format</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b20362c09cf14cbb64148476948481bca11fcf99"><code>b20362c</code></a> (controller) - deps: bump django from 4.2.3 to 4.2.7 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e11ae1ba7d5ef0423b6a51874704739e6a3c86df"><code>e11ae1b</code></a> (controller) - controller: add cluster migrate</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ca6e9dfa4e90c613572faf449445cebabcf1a310"><code>ca6e9df</code></a> (controller) - controller: async mount</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9a7fbfc5e7037dbcd6f8415da1540fc0d0785bff"><code>9a7fbfc</code></a> (controller) - controller: remove FOSSA</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3d55279d81f93783dfdcf0af47c429094fd45019"><code>3d55279</code></a> (controller) - deps: bump aiohttp from 3.8.5 to 3.8.6 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d498a11d8c1179d9ef7e09d4638b10663fc3266d"><code>d498a11</code></a> (controller) - controller: add measure loalancers</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/249a985410e98ab0250af7eaf88c28735f2d7ef1"><code>249a985</code></a> (controller) - deps: bump aiohttp from 3.8.5 to 3.8.6 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b967f5846a006e03d41374266d689a34bd387ba8"><code>b967f58</code></a> (controller) - deps: bump aiohttp from 3.8.6 to 3.9.0 in /rootfs (#107)</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8ca9ed61477fe4c538b0eefbe08f42757f9ec527"><code>8ca9ed6</code></a> (controller) - controller: no longer restrict reserved domain</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/9ff6649b311185927398a12d55451897015ba491"><code>9ff6649</code></a> (database) - database: add init database configure</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/9b4cd26e827862bbcbd2f95eb9ff5aea3031ef80"><code>9b4cd26</code></a> (database) - database: use dynamic clusterrole name</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/b59cde4a41499b1739f51776524c969963706a1e"><code>b59cde4</code></a> (database) - database: remove minio require</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/86462f8e432c21ed691f17544313747a1a95bf2a"><code>86462f8</code></a> (database) - database: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/1e8555a4fa0aa4ab14e276af95eeadb11e7ea2f3"><code>1e8555a</code></a> (database) - database: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/1b762d54948614e8ff8179f91ba4087c1c24cd93"><code>1b762d5</code></a> (database) - database: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/9ffe1fdcc1d1fd33e1d5a69d38c6e2c044f7e002"><code>9ffe1fd</code></a> (database) - database: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/69466d71dfb0fac98f5e2372eae4923d2cb55dde"><code>69466d7</code></a> (database) - database: add database extension</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/beb4b628783f30b8dec35f0ee50d179a27781915"><code>beb4b62</code></a> (database) - database: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/67e27148766a6a16379bccbb160df881e8638cfa"><code>67e2714</code></a> (database) - database: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/8f328f85f28b51b0ea8ce4fe508701c2e875a668"><code>8f328f8</code></a> (fluentbit) - fluentbit: no limit buffer size for kube api</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/fc0552c72b83267e37d67766a0e1040c7d3d59d8"><code>fc0552c</code></a> (fluentbit) - fluentbit: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/63a6cab0c5004ade3c332f16d87f70daaebc12b0"><code>63a6cab</code></a> (fluentbit) - fluentbit: change fluentbit match</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/220f81adae775c21f6eac5fca0f16f2f96962e7d"><code>220f81a</code></a> (fluentbit) - fluentbit: run as no-root</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/aec1393d9e976f2ecb24281a3fc92f5f8bdcf563"><code>aec1393</code></a> (fluentbit) - fluentbit: change configmap name</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/1af4fd24c9e061cb74c3c09af75ad33262a74a19"><code>1af4fd2</code></a> (fluentbit) - fluentbit: change default stream name</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/bef90adfd96f4c713a7de261cb2c66e7cb9900af"><code>bef90ad</code></a> (gateway) - gateway: add route for gateway</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/d523ddb7f794774c5e237c10779fe43713cdc0b6"><code>d523ddb</code></a> (gateway) - gateway: change drycc gateway listener name</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/d9137f4c7681be9edacc2f1123660d0feb961601"><code>d9137f4</code></a> (gateway) - gateway: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/0425dd4e7a0399fd757a80880e67eda2e8c150fc"><code>0425dd4</code></a> (gateway) - gateway: add customListeners</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/3982b86cb7515d42ead064dee86b931f2f4c58a7"><code>3982b86</code></a> (imagebuilder) - imagebuilder: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/3e4e7a329c7532d8787c9c76eb71d938d12fad45"><code>3e4e7a3</code></a> (imagebuilder) - imagebuilder: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/8df6e8e0e6684a4c4a21bf477958b36eb6750e97"><code>8df6e8e</code></a> (imagebuilder) - imagebuilder: upgrade stack version</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/a5601f7588843698b336eccacbc12559dc915779"><code>a5601f7</code></a> (imagebuilder) - imagebuilder: add drycc_app env</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/07465f8bc16cbb15e12d02d522df94265d503c45"><code>07465f8</code></a> (imagebuilder) - imagebuilder: upgrade to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/00d22d2a3c3fa5dce5595fee94bfa8d5a5ca9b2c"><code>00d22d2</code></a> (imagebuilder) - imagebuilder: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/0b7a24e9211acef3252234e4ebce81353c2a8218"><code>0b7a24e</code></a> (imagebuilder) - imagebuilder: upgrade podman/mc/caddy</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/a7d8be869f0b128e9fc6a28ec5c45e5cdca0ea90"><code>a7d8be8</code></a> (imagebuilder) - imagebuilder: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/6b2da83d29e0210a9307e4c5ad1199ed7d7599ce"><code>6b2da83</code></a> (logger) - logger: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/8245b2588a3c350b9c1405c9e56664881534c4b4"><code>8245b25</code></a> (logger) - woodpecker: use woodpecker ci build status</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/f811a74710324fa3ac4ac1fbafc76fe38b042c33"><code>f811a74</code></a> (logger) - logger: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/413f6f60b255f43adbf98cfdbdf2a8325cf3327a"><code>413f6f6</code></a> (logger) - logger: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/2ac6b101d2a205cce7653dcbf635cf1afea8e47e"><code>2ac6b10</code></a> (logger) - logger: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/2581426b262362e04fc4906cfb7d4567ca58d40a"><code>2581426</code></a> (logger) - logger: bump redis to v9</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/364b25aebe91236be41b5974b3643fc1a2b6d352"><code>364b25a</code></a> (logger) - logger: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/dc169a303663ce319037fcf19d0b6bd164b8ee82"><code>dc169a3</code></a> (logger) - logger: use fluentbit replace fluentd</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/d855d91ba3b4651d2a384f3919a39a84f6794b95"><code>d855d91</code></a> (logger) - logger: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/f76723507196a4814dc98e8d9c6403157b6273c4"><code>f767235</code></a> (monitor) - monitor: add off-cluster passport configure</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/ab23936f8d8610f88c061996217b28a8da0ffe3d"><code>ab23936</code></a> (monitor) - monitor: use dynamic clusterrole name</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/47beee0619ee974ad702d813e4db39b187a0507b"><code>47beee0</code></a> (monitor) - monitor: change tikv secret key</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/af7703f7a646a074adf89f9e1d7681bc2a4a8cfb"><code>af7703f</code></a> (monitor) - grafana: remove panel when component off-cluster</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/1b870c2a5b5212d9aeae8dd720bab8190a2b8002"><code>1b870c2</code></a> (monitor) - monitor: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/4a5f1f164c48e93271e28e5a252eb9c87ce4e293"><code>4a5f1f1</code></a> (monitor) - grafana: up ldap api_url config</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/143cabe692cd9d80f909afbe91de0bb8b3c18dea"><code>143cabe</code></a> (monitor) - monitor: add prometheus architecture diagram</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/93091c2dcde35d1ca63450ba08cd2e92b532cdda"><code>93091c2</code></a> (monitor) - woodpecker: use woodpecker ci build status</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/0b7045a1ec3d0061a8434e7e8beed47183287b2c"><code>0b7045a</code></a> (monitor) - grafana: add dashboard kubernetes_deployment_metrics</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/2fb1839f48277724e394b04697d1eb1fb748bf3e"><code>2fb1839</code></a> (monitor) - woodpecker: pipeline config VERSION, when build container image</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/e2724164a3e2855d1f62e4bdcdcff99f6b10e48f"><code>e272416</code></a> (monitor) - monitor: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/abc0e5373a0aef065fd8887e9f8bee5fd13a5e92"><code>abc0e53</code></a> (monitor) - monitor: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/86cc01bd318becf9528feffcfd7c6080c3faafa2"><code>86cc01b</code></a> (monitor) - monitor: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/1cd849ff6f8367375f6d80430e9fe623ebe0162d"><code>1cd849f</code></a> (monitor) - monitor: add postgresql outputs</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/c3205c04418bbb794286eca1bcaa2bf37f26437c"><code>c3205c0</code></a> (monitor) - monitor: change default agent config</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/8c802c01af85fbf40b42c124cd6c72a7c3d8266d"><code>8c802c0</code></a> (monitor) - monitor: add timeseries database</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/e9abc40801c5d90934d19b5ca1b838dbdf9b2431"><code>e9abc40</code></a> (monitor) - monitor: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/6af66cd45685080c5242f6bc6758df35e0c7a69f"><code>6af66cd</code></a> (monitor) - monitor: change drycc gateway listener name</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/d02d718b64837e2869aea66f8a9205d0d3205feb"><code>d02d718</code></a> (monitor) - monitor: remove gateway route</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/3509c2916b9b6aabe709b0057afdacbdc747e462"><code>3509c29</code></a> (monitor) - monitor: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/ed7bfa2f0c17b3e2577f168af719a6c9b3adc436"><code>ed7bfa2</code></a> (monitor) - monitor: optimize env PROMETHEUS_URL</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/da89befad4be1c66ae33740c7a2567b8b83b6b46"><code>da89bef</code></a> (passport) - passport: charts codereview</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/61c4a964022e28f81727efdc858e5ec3a07a71fb"><code>61c4a96</code></a> (passport) - passport: support init app config</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/91010068522d524dfd6680d09915a5444e29a1ba"><code>9101006</code></a> (passport) - passport: add initApplications to charts</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/7dd7fa414f07cc61771cec2d3e98cc1a32d38a00"><code>7dd7fa4</code></a> (passport) - passport: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/4400199ac576b00e0e268ca74d18ff1da15f32bc"><code>4400199</code></a> (passport) - woodpecker: use woodpecker ci build status</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/6b2c546ec6a5dd0311667cab1ac322819ea71918"><code>6b2c546</code></a> (passport) - passport: change secret name to drycc-passport-auto-tls</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/c8bd824c567bfc68df8fd118ad5a9805242507bd"><code>c8bd824</code></a> (passport) - passport: upgrade requirements</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/aee5aefe0c074816b6ba99624f0e2e5fb6462516"><code>aee5aef</code></a> (passport) - passport: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/2d819533a0d6e10534e5a82fac370dd67ef96fc2"><code>2d81953</code></a> (passport) - passport: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/9e662428f39d73651a0c70bd613595c7205c4494"><code>9e66242</code></a> (passport) - passport: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/0fca9982e2ff45bbb5ebe7e3e91fcf0a6af52d94"><code>0fca998</code></a> (passport) - passport: upgrade requirements</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/348252849763e5e96b5908293bd78d84b52b6ad0"><code>3482528</code></a> (passport) - passport: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/0c5ec939da419910c9e98ea97cee9d66916ba14f"><code>0c5ec93</code></a> (passport) - passport: change drycc gateway listener name</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/f7b8f5312d0e9707d2f41b14fb1113e2dfa63dc3"><code>f7b8f53</code></a> (passport) - passport: remove gateway route</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/baf69da9f8b9e1858fa89418e12f3133ab567d88"><code>baf69da</code></a> (passport) - passport: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/fcd45dd063da8338c812d5d8af9c41c6d4405826"><code>fcd45dd</code></a> (passport) - passport: add cluster migrate</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/da6d32a3f09d43209fd1037cb1cff810ddcdcf68"><code>da6d32a</code></a> (prometheus) - prometheus: add prometheus-config</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/683de9e2c03941152196e4fb986cb9ce8e7c1a0f"><code>683de9e</code></a> (prometheus) - prometheus: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/3323300fa23d53bc09e3e70041f4a300aaace68b"><code>3323300</code></a> (prometheus) - prometheus: remove gateway route</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/da1d356e3f978a01fcbbd6b5996ff9272748ed87"><code>da1d356</code></a> (prometheus) - prometheus: change drycc gateway listener name</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/4e7a936edaf8446d48b80e69afd610af6d59a6a4"><code>4e7a936</code></a> (prometheus) - prometheus: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/44c1c6f6a3a11cd1792753c7ba94faf6675e8fa3"><code>44c1c6f</code></a> (prometheus) - prometheus: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/d1f1dda09da1cd0b82dd18854e196b206e27e931"><code>d1f1dda</code></a> (prometheus) - prometheus: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/0836fc1cea544fd928fb6727c99ca9369a1c2134"><code>0836fc1</code></a> (prometheus) - prometheus: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/9e132322c6c36fde1a6ce4f8fabce6ffdb73cb32"><code>9e13232</code></a> (prometheus) - prometheus: add LICENSE</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/f53e14a9e741122cef2a88976a4ccafc6ad6f6fd"><code>f53e14a</code></a> (rabbitmq) - rabbitmq: remove auto user</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/0ec7277c5624b35ea1ac9d5d88a9eddb75278794"><code>0ec7277</code></a> (rabbitmq) - rabbitmq: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/f376a30bdb6223f03b7d3e40eb3093616830291b"><code>f376a30</code></a> (rabbitmq) - woodpecker: use woodpecker ci build status</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/51405d8f429584fcf5d38a7b1422971304f3981c"><code>51405d8</code></a> (rabbitmq) - rabbitmq: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/463ca03544a31a0a6c98ceb4862e9cd15a47271b"><code>463ca03</code></a> (rabbitmq) - rabbitmq: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/1978a714c0f868de9d4dfc863be003c313d3db6f"><code>1978a71</code></a> (rabbitmq) - rabbitmq: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/139277f11035e0e548bfdc35272579806cd8bb0c"><code>139277f</code></a> (rabbitmq) - rabbitmq: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/be49741721134fd966c09ea44ef87b705668c8a2"><code>be49741</code></a> (rabbitmq) - rabbitmq: change drycc gateway listener name</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/6d22518f5bbb3883bc4bdc05b6c93ea6b40e3be9"><code>6d22518</code></a> (rabbitmq) - rabbitmq: remove gateway route</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/0eb7833ac8a01bbde78f3e0172e6d3d2948d6234"><code>0eb7833</code></a> (rabbitmq) - rabbitmq: add check shards</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/921106312dc679e79c8dc8ce226ae62fa68ce0ec"><code>9211063</code></a> (rabbitmq) - rabbitmq: erlang vm tuning optimization</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/648a78d9b886890e924250a198624972d28a2ad8"><code>648a78d</code></a> (rabbitmq) - rabbitmq: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/0b43a4d04556eb2bfa81cc8ed22d84d636ad45d1"><code>0b43a4d</code></a> (rabbitmq) - rabbitmq: add x-random exchange</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/ad1c4da3f11a1e690508c71a992a3bda86b56201"><code>ad1c4da</code></a> (redis) - redis: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/3f37f92a06db4b06c105718bec48aeaac2bf1a31"><code>3f37f92</code></a> (redis) - redis: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/e3bef7a15e73fb77ba76ac4f0140fa03ebd2a813"><code>e3bef7a</code></a> (redis) - redis: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/4e806d40f4a203db5c91dd184a712fba8ce55820"><code>4e806d4</code></a> (redis) - redis: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/d5023be85937f1f4cf4b625fb8250a63c4776f3b"><code>d5023be</code></a> (redis) - redis: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/98f5d6fa30d4fb28c89eb547a0e2631aa34a46ac"><code>98f5d6f</code></a> (redis) - redis: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/063f29e85bc565c29d19b900b96017161263cb88"><code>063f29e</code></a> (registry) - registry: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/17bf8ae8cc1a257ff978a6a8ee27d8988f3ed9c2"><code>17bf8ae</code></a> (registry) - woodpecker: use woodpecker ci build status</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/7bbad151b1d5c934f9d81a882ea6ebef16bf1723"><code>7bbad15</code></a> (registry) - registry: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/279154fdec97b5e0d28a5c27481928d433ac1369"><code>279154f</code></a> (registry) - registry: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/3e4ae840d5718521278051122c19b96b9dbf2791"><code>3e4ae84</code></a> (registry) - registry: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/fa322d6c372fd6d622a2054584bbcab934ff67f0"><code>fa322d6</code></a> (registry) - registry: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/6c18fe004f3431a59ecd5c874c3bd77af544c661"><code>6c18fe0</code></a> (registry) - registry: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/0bc8472a7baa4b8f982694b97528fa984c03639d"><code>0bc8472</code></a> (registry) - registry: remove health url</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/5dacd9f735816decc4b6af7c4994a75ce280d92b"><code>5dacd9f</code></a> (registry) - registry: add wait-for-port check</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/fdeefc3888d5ec0dbfff8db6c797621a90896531"><code>fdeefc3</code></a> (registry) - registry: use headless</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/08bf9f882de2d94f8c3bdefafe24fafa9b9870c4"><code>08bf9f8</code></a> (registry) - registry: change registry port to 5000</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/40bcea2ddf3a6e6316422e14a25df360fb4dcf81"><code>40bcea2</code></a> (registry) - registry: add registry push test</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/871b8e72735b0c17f4c692ea53495e1abb4497d1"><code>871b8e7</code></a> (registry) - registry: add default env</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/7f3b3aceea1cc28475f9cec0a3244f693eaf1e6a"><code>7f3b3ac</code></a> (registry) - registry: bump registry 2.8.3</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/569f15dca6d21c69f3ad3734e6509addf2caf913"><code>569f15d</code></a> (registry-proxy) - registry-proxy: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/cc33caf06d9aa2c4bec7a745aa233f8827695972"><code>cc33caf</code></a> (registry-proxy) - woodpecker: use woodpecker ci build status</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/0002aab36b2692250f8653db3505a0300275bea3"><code>0002aab</code></a> (registry-proxy) - registry-proxy: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/40af10ba90e5e0e6e050f5d97625a1294ab6f910"><code>40af10b</code></a> (registry-proxy) - registry-proxy: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/c56b9dff701130403d9d0ecc932069fa16d2e462"><code>c56b9df</code></a> (registry-proxy) - registry-proxy: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/9d5bfe091bddf0f6d7d0cd8995823540b084dc77"><code>9d5bfe0</code></a> (registry-proxy) - registry-proxy: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/e6a33500e5eba9a32baa3f2e9841e67546236965"><code>e6a3350</code></a> (registry-proxy) - registry-proxy: change worker_processes to 1</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/726f39d51f196a28effb917fbacb20db960cf5f3"><code>726f39d</code></a> (storage) - storage: add volume compactionMBps</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/a5aa2d87bd4d320e30833cbe3e3598f5199e7da5"><code>a5aa2d8</code></a> (storage) - storage: add threshold to vacuum and reclaim spaces</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/e687d044f2796dbfef23239df62337b2e658b797"><code>e687d04</code></a> (storage) - storage: delete disk type in single disk case</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/75ee2e4f4acfa1c4fd8f725252ffdc8a30495dda"><code>75ee2e4</code></a> (storage) - storage: change datanode replicas to 4</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/c5fd7bad70e239cd389fc92372305435e099d4ce"><code>c5fd7ba</code></a> (storage) - storage: delete useless env</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/b3826ea800b1fbde96178f590d25361560f3bc3a"><code>b3826ea</code></a> (storage) - storage: add ssd hdd dir</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/29881a0702b1e68e69c86e6ae96da8c4eda209a4"><code>29881a0</code></a> (storage) - storage: add balance cronjob</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/c5a0f512283eb2c32814f3b2f3c0e3ebfb57bd1f"><code>c5a0f51</code></a> (storage) - storage: add defaultReplication for seaweedfs master</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/543c7a273c2988d477782ba97462263c93068669"><code>543c7a2</code></a> (timeseries) - timeseries: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/5376024ea1489cf311fd18dd691ab5b80eb4e5e8"><code>5376024</code></a> (timeseries) - timeseries: update timeseries-service-replica</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/52e8520d0e2bb6b0625304a8e29d3b680bc44840"><code>52e8520</code></a> (timeseries) - timeseries: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/f82657ceb0cdf390fb07e721ce57e07081d43968"><code>f82657c</code></a> (timeseries) - timeseries: add start script</li> +</ul> + + + + + + Blog: Drycc Workflow v1.6.0 + /blog/2022/10/21/drycc-workflow-v1.6.0/ + Fri, 21 Oct 2022 00:00:00 +0000 + + /blog/2022/10/21/drycc-workflow-v1.6.0/ + + + + <p>These release notes for Drycc Workflow v1.6.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.5.0, please refer to the following change summary.</p> +<h2 id="workflow--v150---v160">Workflow ## v1.5.0 -&gt; v1.6.0<a class="td-heading-self-link" href="#workflow--v150---v160" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>builder v1.3.0 -&gt; v1.4.0</li> +<li>controller v1.4.0 -&gt; v1.5.0</li> +<li>passport v1.0.0 -&gt; v1.1.0</li> +<li>database v1.1.0 -&gt; v1.2.0</li> +<li>imagebuilder v1.0.1 -&gt; v1.1.0</li> +<li>fluentd v1.2.0 -&gt; v1.3.0</li> +<li>logger v1.2.0 -&gt; v1.3.0</li> +<li>storage v1.2.0 -&gt; v1.3.0</li> +<li>monitor v1.2.0 -&gt; v1.3.0</li> +<li>redis v1.2.0 -&gt; v1.3.0</li> +<li>influxdb v1.1.0 -&gt; v1.2.0</li> +<li>rabbitmq v1.0.0 -&gt; v1.1.0</li> +<li>registry v1.1.0 -&gt; v1.2.0</li> +<li>registry-proxy v1.1.0 -&gt; v1.2.0</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/52517d9323bfcd246e1fd8e13bdee2c45739136a"><code>52517d9</code></a> (builder) - builder: update controller-sdk-go</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/1d78ca01de03c80ac86687999d82dba0077df31a"><code>1d78ca0</code></a> (builder) - builder: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/26b69801c78321da8754c814b6503ec76e857a1b"><code>26b6980</code></a> (builder) - builder: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/bfd43851009116d6d4bceb4c46edc3cd21cf9d41"><code>bfd4385</code></a> (controller) - controller: add get manager user status</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/874208d8501198ed8780f2e820ab112d3b78eae2"><code>874208d</code></a> (controller) - controller: unified measurement model</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/cadf98f888c384890c529700c16208b17e17dff2"><code>cadf98f</code></a> (controller) - controller: add admission webhook</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e0050c23869dd3a1d5e8038859a7324484b227b2"><code>e0050c2</code></a> (controller) - controller: new measurement model</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a11ba587b73058c3af610fc9fc101e5d446eb43f"><code>a11ba58</code></a> (controller) - controller: multi pod restart uses async</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/fb3c15d70041d4b215c34b5625cb82ae52279d2b"><code>fb3c15d</code></a> (controller) - controller: add check app owner status</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3d78b764c874c30f23aa7e6db9a0d03cb09b6a24"><code>3d78b76</code></a> (controller) - controller: add resource services api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3d6a2012ab840dcde1be3c8f197df76eac9c5d88"><code>3d6a201</code></a> (controller) - controller: add search apps api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/01c443a3bf142d6497d20492e3ee7f534db64322"><code>01c443a</code></a> (controller) - controller: add KUBERNETES_CPU_MEMORY_RATIO parameter</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7c2623276991b46b7ac2b8e9d8ce2f84e8ebf26b"><code>7c26232</code></a> (controller) - controller: add volume size limit</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3bee749fc0c670d3ee371c7ffb031f47f0d45873"><code>3bee749</code></a> (controller) - controller: add annotations support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/23cd97c1f213ea9dcec45a4a40e9c3942904e55a"><code>23cd97c</code></a> (controller) - controller: traefik v2 support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e37b7db45049776d7d7455e01f5928986b24b043"><code>e37b7db</code></a> (controller) - controller: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b3b367b108bea56a5fa5ccc603f0dafc14bb5edb"><code>b3b367b</code></a> (controller) - controller: add volume expand support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a4e154aaf0f6cd3b01ebbab0a4af1a4b693a45a4"><code>a4e154a</code></a> (controller) - controller: add database replica support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/2f37216fbaed5fa707c76b44881b1f7507a75f49"><code>2f37216</code></a> (controller) - controller: switch wsgi to asgi</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b3314a50607e9d5383d0ce954811827acae8fa05"><code>b3314a5</code></a> (controller) - controller: add pod exec api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/75df2dce65591da4e1e56c7f56a1903749fa4e20"><code>75df2dc</code></a> (controller) - controller: add stream support for app logs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4229badbcd4e367cbe13bf13f2b5c62271b7b31e"><code>4229bad</code></a> (controller) - ccontroller: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/89bb19b20f2eb0d8918cdc7223fa3b117af620d5"><code>89bb19b</code></a> (database) - database: upgrade to pg14</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/9f45a5d5e9b7871c47acd73ce227856c1683f6a2"><code>9f45a5d</code></a> (database) - database: add hugepages support</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/c4008c9fbe0f99d1200a58466a15466d92840fa5"><code>c4008c9</code></a> (database) - database: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/411a7b269a3333caed809a1afac69578a7c5ad9b"><code>411a7b2</code></a> (database) - postgres: use patroni</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/64e5cb0aaaacfa2d9976e278583fa700c858ce92"><code>64e5cb0</code></a> (database) - database: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/2bab823194abea35c7a1ff4d59db6a88eb19fcad"><code>2bab823</code></a> (fluentd) - fluentd: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/337ba62d587a4f6c7321aa6ef843d5764692a09e"><code>337ba62</code></a> (imagebuilder) - imagebuilder: run podman as rootless</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/4396ffaeb6a2751e6f78907ac7c517966b5e3c08"><code>4396ffa</code></a> (imagebuilder) - imagebuilder: switch to oci charts</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/f37ae0927023685d88f9e594d8316d8c40cd5296"><code>f37ae09</code></a> (influxdb) - influxdb: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/04503b2c0d5c455c1a106c71be727d2b2b14a2f8"><code>04503b2</code></a> (influxdb) - influxdb: add influxdb ha</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/41ddad5e9acb54fa5bb2c35559615d1cc4fd3af5"><code>41ddad5</code></a> (influxdb) - influxdb: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/2006480f82ab4291efa75a69cad0080a29872110"><code>2006480</code></a> (logger) - logger: use redis stream replace nsqd</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/ab23d17f378ea1b740fb4c43dc06f4853d5c729f"><code>ab23d17</code></a> (logger) - logger: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/81d4e9dcde820ab8dc1df6fb99f82fdf39eb35ea"><code>81d4e9d</code></a> (logger) - logger: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/c3d9796e21c344d660bfd036d6154c28a3051995"><code>c3d9796</code></a> (monitor) - monitor: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/cd9de3c70c33236975b1d2547b75a66649fba93d"><code>cd9de3c</code></a> (monitor) - monitor: switch to oci charts</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/318a73f7f03c01faa23ce3a89b4b52d5cae4279d"><code>318a73f</code></a> (passport) - passport: add change user confirm</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/79ef1004687152d93a5e60058fd4f40a6273b55a"><code>79ef100</code></a> (passport) - passport: add re login at authorize</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/6927bb5884a7ee332a64afabfd6439467d7fee3c"><code>6927bb5</code></a> (passport) - passport: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/3146a0981b744962d68a75fab65e074ab61d4b1c"><code>3146a09</code></a> (passport) - passport: add google reCAPTCHA</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/802abcdd5f0768d75b4fc9f08f46c4b2a590be29"><code>802abcd</code></a> (passport) - passport: add replica database support</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/a0dcd1b7b2bdd3ba247d50fdf554a2918b065588"><code>a0dcd1b</code></a> (passport) - passport: switch wsgi to asgi</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/4c9dbba2b1e79cf9860e19529bd99f52f5588328"><code>4c9dbba</code></a> (passport) - passport: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/74825f7827e22b75938cbcc5bf81ad1a40c4ab37"><code>74825f7</code></a> (rabbitmq) - rabbitmq: add rabbitmq managentment ingress</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/12cf7d60e4e89e3396e786f4487cca55f1322887"><code>12cf7d6</code></a> (rabbitmq) - rabbitmq: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/103417de373246b4f1e0b9cdaf2eaae6ba704dea"><code>103417d</code></a> (rabbitmq) - rabbitmq: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/5d428bbd55c0ec12f6fcafe312b2cd3768fb51d1"><code>5d428bb</code></a> (redis) - redis: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/a88c1a9625757b901515682f39d40a7f5b877f95"><code>a88c1a9</code></a> (redis) - redis: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/541585d4060d6006b99fd3649718566a6ea3163b"><code>541585d</code></a> (registry) - registry: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/e9ca9d475dade575ae13c3b288148b8094faf3f6"><code>e9ca9d4</code></a> (registry) - registry: add garbage-collect cronjob</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/ec62a5969747738252132510923637c1b63b63d8"><code>ec62a59</code></a> (registry) - registry: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/fde0b07f243deabc0818efc4088583c6ca6aa5b8"><code>fde0b07</code></a> (registry-proxy) - registry-proxy: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/be14eb42fcda99f9160d21f437858e89337543a2"><code>be14eb4</code></a> (storage) - minio: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/51af6966183c496c9c1374cf4c4fa9b66f319a44"><code>51af696</code></a> (storage) - storage: add k8s csi support</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/76a75d922b965b8961f872b62c67569924e0cf49"><code>76a75d9</code></a> (storage) - storage: add cluster health checker</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/a17dc8cc37c2c2d96acdbcc08a6c2e52676cb777"><code>a17dc8c</code></a> (storage) - storage: switch charts to oci</li> +</ul> +<h4 id="fixes">Fixes<a class="td-heading-self-link" href="#fixes" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/e4f44fba4f4a71812b0a1b0d42668d8a6f3bbc65"><code>e4f44fb</code></a> (builder) - builder: no error return</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/e38dfc71c5dfa0edafc5603f274235048a3992d7"><code>e38dfc7</code></a> (builder) - builderControllerHost/ControllerPort init error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ff9069fee85633db4801a43d4fa70292099c94dc"><code>ff9069f</code></a> (controller) - controller: influxdb query error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f7f5069569e3f7325fc8fa5f90f8c19e95c0c6ce"><code>f7f5069</code></a> (controller) - controller: authentication 500</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7e297a8996c9fbf490fcbce364c0b4172bdc6388"><code>7e297a8</code></a> (controller) - controller: add check remote user status</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9db28e1ea4627f8f63dcc6f83db2962dc5b47451"><code>9db28e1</code></a> (controller) - controller: celery MaxRetriesExceededError</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4bcff08d38a01a4d7267fef00650395275e3203b"><code>4bcff08</code></a> (controller) - controller: wrong name</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d69fde2efc71b015ae2894fcc3efa0cf369457e5"><code>d69fde2</code></a> (controller) - controller: traefik ingress create error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a3ad743c2ecd0528c5c69915272dc68a90fd841a"><code>a3ad743</code></a> (controller) - fixup(controller: user login error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/662c8ddfbcb03d19f5ced769de21964ff5ed413e"><code>662c8dd</code></a> (controller) - controller: change influxdb port</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/957bdf67128b45abad43e8ee560fb6cb749b0783"><code>957bdf6</code></a> (controller) - controller: validate rsa key pairing before storage</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/419ec4c4de6ad77c9cc3f551260fdc35504ceb15"><code>419ec4c</code></a> (controller) - controller: kubernetes pod/exec cluster role</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a67edaae26c00a7ce806bde95b73041ec1c84734"><code>a67edaa</code></a> (controller) - controller: Cannot routing:disable</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e09e2144f1906b19d9b00f0883effe3491198ebf"><code>e09e214</code></a> (controller) - controller: allowlist cannot remove</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/318b1267f35bcf158fc21b20f8e367a3e23fa454"><code>318b126</code></a> (controller) - controller: domains update error</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/92855ebc7df34fb8cc5ea440db4f821681ae2408"><code>92855eb</code></a> (database) - database: premission denied</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/bde945ab972d9085009b291c0faac55d8942b014"><code>bde945a</code></a> (database) - fixup(postgres: support arm, fix Failed to build psutil</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/7854d45a2164a1db8ee37bc3ce39c8515bacae30"><code>7854d45</code></a> (database) - fixup(postgres: user name converted to lowercase letters</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/57b2a0708d5ab8fff913e97be09f132074d1ff56"><code>57b2a07</code></a> (fluentd) - fluentd: ifconfig_path not found</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/20e72b962a415773fd97919832c7a0bde9c55a28"><code>20e72b9</code></a> (imagebuilder) - imagebuilder: upgrade pack version</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/651db8a1d2f40f0fafb88f2da4b6fd20ee920715"><code>651db8a</code></a> (imagebuilder) - imagebuilder: chown uid gid order</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/d2e9164afe61fac362beb65ee9113453c2ecd970"><code>d2e9164</code></a> (influxdb) - influxdb: proxy not running</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/3a1d3618d881880abcd752c9c9184a570b38442e"><code>3a1d361</code></a> (monitor) - monitor: charts naming</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/d754ae0244e6e1e300062db24c8e4477b7522715"><code>d754ae0</code></a> (monitor) - monitor: telegraf init error</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/63f9e346a4ded75b7b4f8f0c6708bbe725ee6160"><code>63f9e34</code></a> (monitor) - monitor: affinity error</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/95ae1e5f51e528b75ccae36ad86e9abfbff52050"><code>95ae1e5</code></a> (passport) - passport: yarn build fail</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/3f5365e8e5be0b2a486651e87fb5b82fe4668bbc"><code>3f5365e</code></a> (passport) - passport: wrong name</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/907f17b95c1114a802781f2bbec3ba046464f1a8"><code>907f17b</code></a> (passport) - passport: change uid gid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/e3911e0f5e9174ab8e7542f60b8bd0c3ff7f85f6"><code>e3911e0</code></a> (passport) - passport: &lsquo;registration_done&rsquo; not found</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/2ace5f0a2a363d959a381bd3f759b4990bc13953"><code>2ace5f0</code></a> (passport) - passport: ui style</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/b3ba1e1545f07ee2322850ee6cfb6915ee26967d"><code>b3ba1e1</code></a> (passport) - passport privacy policy link</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/172e9c8b680a83d6c437292febf0418d35c99aa9"><code>172e9c8</code></a> (passport) - passport: check databaseReplicaUrl error</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/a3aeb7052d4ebdbc7bd020850f94921c253a8a38"><code>a3aeb70</code></a> (rabbitmq) - passport: change uid gid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/5c73dcf6a8692e83abd40f1d5e991714b3c51876"><code>5c73dcf</code></a> (redis) - reids: DRYCC_REGISTY misspelling</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/d7e3baf4600d87e4d4af2b3e581cb62c591a25b6"><code>d7e3baf</code></a> (redis) - redis: env miss</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/cadaa9151519a4efb52d5c5f779cc0aff0f8fe1e"><code>cadaa91</code></a> (registry) - registry: set gid uid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/d524217dccfc6dd80c86547d5f2f875b15a8054d"><code>d524217</code></a> (registry) - registry: storage run error</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/854f912bf746ac69d0117378888c1fe8334dd7fb"><code>854f912</code></a> (registry) - registry: chown uid gid order</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/e642bb7452fb62bbc7ce6f1b852e029b88a71488"><code>e642bb7</code></a> (registry-proxy) - registry-proxy: containerPort error</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/8dfd029b78d2dcd1b6bf31960d35234deb6bfc5b"><code>8dfd029</code></a> (registry-proxy) - registry-proxy: chown uid gid order</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/bbea3642114ac83e3c9cb56e7131146378bbf213"><code>bbea364</code></a> (storage) - minio: premission denied</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/97deba16553dd6dc8d2625d8747825692e8667bb"><code>97deba1</code></a> (storage) - storage: node unimplemented error</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/b9bdeff3ef47f43ec12dd16194297d63298fbd34"><code>b9bdeff</code></a> (storage) - storage: pd can not connect each other</li> +</ul> +<h4 id="style">Style<a class="td-heading-self-link" href="#style" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1edb10c23e5ae5654e6a7daf08b7a74fe9c86b74"><code>1edb10c</code></a> (controller) - controller: database convention over configuration</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/1960cc3367aa6b0e8f0db5f0117a271c884356a0"><code>1960cc3</code></a> (database) - database: database name convention over configuration</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/06d1f5dd3b7ff353ae26615695732f54dd09e5c7"><code>06d1f5d</code></a> (imagebuilder) - imagebuilder: URL to Url</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/b8a89412e7794fe9e16689d4e8902d34f68a6ce1"><code>b8a8941</code></a> (passport) - passport: database convention over configuration</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/8e9a199ac90382e67f64c757d9d207e7aa106c86"><code>8e9a199</code></a> (builder) - builder: upgrade controller-sdk-go</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/48401512b2eee6a608efe45c962809a4a388ed9a"><code>4840151</code></a> (builder) - builder: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/68ccfb12da3fdc35519b23fdb8212f7de377f8b5"><code>68ccfb1</code></a> (builder) - builder: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/8f971cbd509062f952e0b0fe2fdc9983891077ad"><code>8f971cb</code></a> (builder) - builder: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/fe2c55d0e5264818e482fcd71510d9a616689c79"><code>fe2c55d</code></a> (builder) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/2b5e70609f11eff1eb1e1d8a5591644799fa8982"><code>2b5e706</code></a> (builder) - dockerfile: change user and workdir</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/7a6c8d319bcc67e1cbe5a733de773860aa859765"><code>7a6c8d3</code></a> (builder) - builder: set gid uid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/fe494f75669f9e3a51ff32e330edb8c5a33efed7"><code>fe494f7</code></a> (builder) - dockerfile: use uid gid</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/a7c87525709c6903e4fb254740eac710c3e18385"><code>a7c8752</code></a> (builder) - builder: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/eb2e94c2ab4358e74a74c8d198eb6798e9bdeae7"><code>eb2e94c</code></a> (builder) - database: bump mc 2022.04.01.23.44.48</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/cfaae66aa31b4b7b28c7d4577e9bf9c7f17a6716"><code>cfaae66</code></a> (builder) - builder: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/d7d289060ddafcc94855bb46dc4fbc24cf1c3527"><code>d7d2890</code></a> (builder) - builder: change default imagebuilder registry</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/ecfdb19270198fc3f2b46cc0dc91151bd3ebf114"><code>ecfdb19</code></a> (builder) - imagebuilder: change python-dev registry</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/6da17f489543950af850ee3d5bb4e1cfbcc5cac1"><code>6da17f4</code></a> (builder) - builder: <a href="https://github.com/minio/minio/issues/14331">https://github.com/minio/minio/issues/14331</a></li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/1a57e5bd5e467b859e0d69e6b3775454132cb225"><code>1a57e5b</code></a> (builder) - builder: <a href="https://github.com/minio/minio/issues/14331">https://github.com/minio/minio/issues/14331</a></li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/f1464fa6065483d23b98f01a847b73e951f896ae"><code>f1464fa</code></a> (builder) - builder: <a href="https://github.com/minio/minio/issues/13799">https://github.com/minio/minio/issues/13799</a></li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/b1e1c4f5920ba82235a253f9980960ef9dca527d"><code>b1e1c4f</code></a> (builder) - builder: use env replace creds volume</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/71a41453660c6d731247a10e00f94121ae3a69a5"><code>71a4145</code></a> (builder) - builder: bump go.mod</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/3567688f8809e3805e47170d4b3109a31b1f883f"><code>3567688</code></a> (builder) - builder: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/73ea38b11c631415aa02c5ee43ff92ecfe48348d"><code>73ea38b</code></a> (builder) - builder: change storage to minio</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/1f913215ba18670fe83891bf84317b72985151dc"><code>1f91321</code></a> (builder) - builder: use testify replace assert</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/d148b9c998759b886ea5493d0e2aa94518d39dcb"><code>d148b9c</code></a> (builder) - builder: add check storage health</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/b768101f69233fa792f3240be47b71b24881e90c"><code>b768101</code></a> (builder) - builder: change initContainers</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/1b3bec3ea2783c5124f372c2874c3691b71489cd"><code>1b3bec3</code></a> (builder) - builder: add replicas</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/5cb0d618ff5bb1136501f4ba6359e5e5c46a7a63"><code>5cb0d61</code></a> (builder) - builder: upgrade to latest controller-sdk-go</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/98b9d581209eacabdb9e28c5eb6a7975f13bd454"><code>98b9d58</code></a> (builder) - builder: upgrade new require</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/65817c3e519df8368cd4427f5d366f9edde1fbd5"><code>65817c3</code></a> (builder) - builder: change drycc.cc to <a href="https://www.drycc.cc">www.drycc.cc</a></li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4e3f9d05bb8d00023e6f1927785b7c27d4801652"><code>4e3f9d0</code></a> (controller) - controller: add celery retry mechanism</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f6716fee7625ad8f0cad2b1cf5ad746beb847a65"><code>f6716fe</code></a> (controller) - controller: change cronjob name</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/eb606938533da2673ed2aa2986bcb0cdd2c9ee2c"><code>eb60693</code></a> (controller) - controller: refine celery task priority</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/66905e95bb3c9f71fb4c75038199d54c6b5a0edc"><code>66905e9</code></a> (controller) - controller: change manager auth</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ea20c415af0ee4e70f32873748cd979bd36f8240"><code>ea20c41</code></a> (controller) - controller: remove start/stop api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4c8fc807f950064d2cc98ebdd6a51ec86eabb20f"><code>4c8fc80</code></a> (controller) - controller: improve tasks error handling</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/cf7402eaff8373c956e6c0ffa1c7ff479cade8e2"><code>cf7402e</code></a> (controller) - controller: add blocklist api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/80f14dd5b8852c235e3de496261b416c8b59a043"><code>80f14dd</code></a> (controller) - controller: use get_user_model replace auth.User</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ffc7bb790f2257f5e5f9902400f78524d1f528e3"><code>ffc7bb7</code></a> (controller) - controller: use JSONField replace ArrayField</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/370df8c9d011e25785a06e5a4a737dcdb622f4f5"><code>370df8c</code></a> (controller) - controller: add validate metric</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/29084ce759bddd671de4441c6f8e6889774e4c80"><code>29084ce</code></a> (controller) - controller: use user id request manager api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/718fe123eafe5136ac08635c8cf1dbca3dcad4ab"><code>718fe12</code></a> (controller) - controller change urlpatterns order</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/71f40426a65bc6cdc90e6185b1487ae30a3c73de"><code>71f4042</code></a> (controller) - controller: measurements uses lowercase letters</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e5123ea55ae516d94b0cb54ec6ffb464c050ce87"><code>e5123ea</code></a> (controller) - controller: change resource unit to number</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/18fee9aeb1114ea8dbcc4d8eacea93148206e002"><code>18fee9a</code></a> (controller) - deps: bump celery from 5.1.2 to 5.2.2 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ffca6c11c67012e13540e06c12cf30dea5e5cde7"><code>ffca6c1</code></a> (controller) - controller: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9ec12e1ff7bcfb3b72953313484d3f605d97c73b"><code>9ec12e1</code></a> (controller) - controller: simplify drone configuration</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4b4749e2fd391a492fbf40fb7ee25c7b61b52f26"><code>4b4749e</code></a> (controller) - controller: set default CSRF_COOKIE_SECURE false</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/2ef6338c20c8625b2cc76c6021149bc07141fcd0"><code>2ef6338</code></a> (controller) - deps: bump django from 3.2.5 to 3.2.10 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c7570d0a40f7daa04de0a4fe1ecbb001e436ee41"><code>c7570d0</code></a> (controller) - deps: bump django from 3.2.10 to 3.2.11 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8b17bc16624fd9caddbbc462cc3487d3500a5216"><code>8b17bc1</code></a> (controller) - controller: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c928fb09f88ce210df7b495b80a005146320e2bf"><code>c928fb0</code></a> (controller) - controller: use rabbitmq cluster</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f9171852a8530c9bd385576517d24172917a1b33"><code>f917185</code></a> (controller) - controller: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/22a8f634a3574553132ecd53e8be467d84a255e9"><code>22a8f63</code></a> (controller) - deps: bump django from 3.2.11 to 3.2.12 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3cc3b00a705b9c7b0ff5d36fb2c0ab4139113dd9"><code>3cc3b00</code></a> (controller) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ee274f6d6728b3b9b3fd91b344be3f8a0d3f737f"><code>ee274f6</code></a> (controller) - controller: set venv profile</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ce6b069644ed3952a47bdd1bd728a395a9f1af05"><code>ce6b069</code></a> (controller) - controller: set gid uid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3a105d3628e40e2f53dfd2badeb7221555207227"><code>3a105d3</code></a> (controller) - dockerfile: use uid gid</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/15f9b0ea96630a818ec191dac15497a5dc99cadc"><code>15f9b0e</code></a> (controller) - controller: code review</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/01e6fd9ef5d730749a33986ff9d58dd854f50cb5"><code>01e6fd9</code></a> (controller) - controller: use passport user id</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/893ee31a1de6036136d0b813d5ff6575267e640a"><code>893ee31</code></a> (controller) - oauth2: update user info pipline</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3028fb470f23d858a5e36312e419dcdfbcc00be0"><code>3028fb4</code></a> (controller) - user: set AnonymousUser username</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5daf82d3bd17f2c653d2db52fb79d2a895ed1335"><code>5daf82d</code></a> (controller) - controller: set worker_cancel_long_running_tasks_on_connection_loss</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/61f2c53a7841099e33c8d5f8d25de311392ce317"><code>61f2c53</code></a> (controller) - controller: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/88feb1df0f3508c29a47ea291f225207a8a4c754"><code>88feb1d</code></a> (controller) - imagebuilder: python=3.10.4 rabbitmq=3.9.14</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/914e03fb8d6d6bff7ef9b5f91b0a3eeedac2ebeb"><code>914e03f</code></a> (controller) - controller: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a5bb548ee73cd201cafe797fdba4fe89e4bbb377"><code>a5bb548</code></a> (controller) - controller: change python-dev registry</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3ecdd7c05b7cddd640ffe92012b777a80cae1eec"><code>3ecdd7c</code></a> (controller) - controller: add a separate rabbitmqUrl configuration</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/967cb116bdbbf040c3c3c15579bb2d334666d3e8"><code>967cb11</code></a> (controller) - controller: remove APP_STORAGE</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/473d2b5f08c205240b5e081fcb9256d7ecd4cd45"><code>473d2b5</code></a> (controller) - controller: use env replace creds volume</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e410d4cba17662bad797fbd7288052b81e50df29"><code>e410d4c</code></a> (controller) - deps: bump django from 3.2.12 to 3.2.13 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c6ef777035d5e955984f9f4c84fac465943d8b74"><code>c6ef777</code></a> (controller) - controller: simplified passport config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0fd3233f1471b32c621149ac4ca5b5527741fda8"><code>0fd3233</code></a> (controller) - controller: remove settings hardcode</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a64e99cf099eba92c6df749c3c89f4245488b3e4"><code>a64e99c</code></a> (controller) - controller: change passport config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/62aba2594f1240c4368d95c61d75fa08343d05fb"><code>62aba25</code></a> (controller) - controller: set cronjob timezone to utc</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/760b70b635d6eecedfd3d40991740b13e587c1c5"><code>760b70b</code></a> (controller) - controller: change default ratio</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8dffc3afbce3871dc82fe4ce94c92b1fbbacc9b6"><code>8dffc3a</code></a> (controller) - controller: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/26043c40c89cb162b3ce322eba6a79f81a6b24cf"><code>26043c4</code></a> (controller) - controller: change default app storage</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/608bd8da7a7cb75d8fadfa965bcd9ea32e4a96ef"><code>608bd8d</code></a> (controller) - deps: bump django from 3.2.13 to 3.2.14 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/18ed0c2a656497108f98c5c8dbd3b27253dd7915"><code>18ed0c2</code></a> (controller) - controller: remove conjob affinity</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/add671288d5f4af68735a69771f024e4ed856196"><code>add6712</code></a> (controller) - controller: add volume expand support use patch</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/cc1ad1322ba638aa7f6acf45823047712a85e86f"><code>cc1ad13</code></a> (controller) - controller: add startupProbe</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0e9a6033b1a2b66f937010601df70e5625674a66"><code>0e9a603</code></a> (controller) - controller: add clearsocial cronjob</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/eb6f05d969102c008051ebd4c7e39a1300ed1b25"><code>eb6f05d</code></a> (controller) - controller: change initContainers</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/762c6767947b6407a7fb23ffbcb07dc46154b222"><code>762c676</code></a> (controller) - controller: change replicas</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/abd7e8c2210eb1f71c1d280383794af5fa786c98"><code>abd7e8c</code></a> (controller) - deps: bump django from 3.2.14 to 3.2.15 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/07fdf1b9938d868ef55c1d2067258a1eb6c59d23"><code>07fdf1b</code></a> (controller) - controller: remove database conn_max_age</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ef8e41f523aa0159831c95623b96fa74b3570d0c"><code>ef8e41f</code></a> (controller) - controller: add database replica check</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/79143f2301bfc52f8181fc0e0f07263645e065d8"><code>79143f2</code></a> (controller) - controller: upgrade new require</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a62404890973cb26c9360878e7625e15eb87d281"><code>a624048</code></a> (controller) - controller: add app.refresh func annotation</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b22d367d54aa2ab131c8e69491e084dc283826a4"><code>b22d367</code></a> (controller) - controller: optimize app refresh timing</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/fe98f0c8f3d2cfebc2b6ad13927627ebee96e39e"><code>fe98f0c</code></a> (database) - database: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/5e00c118e5830c43158417486b83602d1e9839ff"><code>5e00c11</code></a> (database) - database: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/d2cb8607a95e098fe0c50a82ebadd3393a52cd56"><code>d2cb860</code></a> (database) - database: disable huge_pages</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/197d80d95e42443351abbf1aae216d5f80073334"><code>197d80d</code></a> (database) - database: add persistence</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/1c3e64596ee5970c3ef7a1daeee86ced68ae3ec1"><code>1c3e645</code></a> (database) - database: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/37730ab6ca7ac86728f9fe0f1c41240402abb9bc"><code>37730ab</code></a> (database) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/5014112dd279d1e3a8d5b6fa23797d0996fb2047"><code>5014112</code></a> (database) - dockerfile: change entrypoint</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/29b538e8b33cd19bb3a781abb8335905fa7a533f"><code>29b538e</code></a> (database) - database: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/c2bb0746172d4dc764cd8543d98bb6cbd9205cf9"><code>c2bb074</code></a> (database) - database: bump python 3.10.4 and mc 2022.04.01.23.44.48</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/077a4e95b2ee3d772e030971218e880f31a55e4c"><code>077a4e9</code></a> (database) - database: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/560bdb97a46897ae0fd464ca6e2b54d129d91b37"><code>560bdb9</code></a> (database) - database: change python-dev registry</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/1e54b554f4a29df49ac42ba046f00f71a105f84e"><code>1e54b55</code></a> (database) - database: <a href="https://github.com/minio/minio/issues/14331">https://github.com/minio/minio/issues/14331</a></li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/d6466723b4f949a4771d7415f1a80924f398963d"><code>d646672</code></a> (database) - database: <a href="https://github.com/minio/minio/issues/13799">https://github.com/minio/minio/issues/13799</a></li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/a6ac4e350fec8e27c1bdc560130c585d3a7ab7d2"><code>a6ac4e3</code></a> (database) - database: use env replace creds volume</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/9618d87f3bc63c8933553278e88c7d6758b9e2af"><code>9618d87</code></a> (database) - database: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/b8232737ff893b064a558821da49b40905b4e83d"><code>b823273</code></a> (database) - database: change minio to storage</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/7bd5a90fe97b9b0ec20f5305431891f10a975c61"><code>7bd5a90</code></a> (database) - database: add check storage health</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/20c6d96e16b2dc7fc7d1bf75a8b44dd6ca459f6f"><code>20c6d96</code></a> (database) - database: fix storage run error</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/8bde83071df44a11b01ae13fbe2676567780170b"><code>8bde830</code></a> (database) - database: upgrade to pg 14.5</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/a33b5e5ef09bfc8cf5fbf79fd11dee4766a910e2"><code>a33b5e5</code></a> (fluentd) - fluentd: update plugins</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/eed7a7804b91dba5c31762adcf1245950365b4fe"><code>eed7a78</code></a> (fluentd) - fluentd: update filter kubernetes setting</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/cc83dd87809f1b71e18636240582c0a58eb73ad2"><code>cc83dd8</code></a> (fluentd) - fluentd: update elasticsearch store setting and support exclude specific container logs</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/ba2feb28bc7a96ec2a0632c5c4070d5300de3c37"><code>ba2feb2</code></a> (fluentd) - fluentd: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/d528676b75699d731ceba78ca7b207bd1472aed6"><code>d528676</code></a> (fluentd) - fluentd: simplify drone configuration</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/dece82d3a85c2b69d4315d324d03fd1f523e53fa"><code>dece82d</code></a> (fluentd) - fluentd: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/4e0a80244c190607f9e706fdeed0f3829c505a76"><code>4e0a802</code></a> (fluentd) - fluend: replace nsqd with redis</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/15ceca0cdbfb56e03b96cfd96e9b13909667f2e3"><code>15ceca0</code></a> (fluentd) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/a7f619f70d0fb77d08f544dc593d033396b984af"><code>a7f619f</code></a> (fluentd) - dockerfile: change workdir</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/9adf5ed9a2387c79a596a4e8fddcc099316e9fd8"><code>9adf5ed</code></a> (fluentd) - database: bump fluentd 1.14.6</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/50c14c28eb1f3c673787b1f59f6b713995cd1441"><code>50c14c2</code></a> (fluentd) - fluentd: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/83171b1e36a4fc787459ffdceb9a2573b518a287"><code>83171b1</code></a> (fluentd) - fluentd: change python-dev registry</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/ec8358165e029e7c82316877f629b128bb3a00f7"><code>ec83581</code></a> (fluentd) - fluentd: unified reids declaration</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/07c63e24a3760a0604d3c17936690f31380e7b8c"><code>07c63e2</code></a> (fluentd) - fluentd: upgrade fluentd 1.15.2</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/65df9be7b31a93f6ea30d259cb13cf0401d78234"><code>65df9be</code></a> (imagebuilder) - imagebuilder: update pack version</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/66cab351e53388cdb2bddf4f415240883c3217f9"><code>66cab35</code></a> (imagebuilder) - imagebuilder: use dind replace go-dev</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/0c8206098ba01f01039c1b563238a6612e6a1fed"><code>0c82060</code></a> (imagebuilder) - imagebuilder: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/8146da94bfef611398b03c70be316676aa49f626"><code>8146da9</code></a> (imagebuilder) - imagebuilder: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/7d97241d42a0282255d9c1d6a823159671f25fd4"><code>7d97241</code></a> (imagebuilder) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/07e805c48d9f9ccf44e23d91791995f38fa28345"><code>07e805c</code></a> (imagebuilder) - imagebuilder: change default buildpack</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/8d1038df7e714b72d43b491a3fddb36639736937"><code>8d1038d</code></a> (imagebuilder) - imagebuilder: upgrade podman to 4.0.1</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/62d3687a1edeefee68d5fedfb59eea38e791a3f7"><code>62d3687</code></a> (imagebuilder) - imagebuilder: change workdir to /workspace</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/da8bfb0f576bc292eb6427f7945271cc00fcb0ce"><code>da8bfb0</code></a> (imagebuilder) - imagebuilder: change uid gid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/d44e3bc2007f4e70c7dfa6d59279e7643345bd46"><code>d44e3bc</code></a> (imagebuilder) - imagebuilder: upgrade stack</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/5b0c7e69839ac408230bc142a2ba42953a068216"><code>5b0c7e6</code></a> (imagebuilder) - imagebuilder: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/f74cbf6113d99064c5b734da329980434c4f854a"><code>f74cbf6</code></a> (imagebuilder) - imagebuilder: add defaultBuildpacksURL</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/941d4939323573679841cc114669e1dec2154f94"><code>941d493</code></a> (imagebuilder) - imagebuilder: <a href="https://github.com/minio/minio/issues/14331">https://github.com/minio/minio/issues/14331</a></li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/449be91d0c64e4e7947de68c4e35fcfd8a944a14"><code>449be91</code></a> (imagebuilder) - imagebuilder: <a href="https://github.com/minio/minio/issues/13799">https://github.com/minio/minio/issues/13799</a></li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/63b052341db3e1dcd2458ded7be233ec9877a3bf"><code>63b0523</code></a> (imagebuilder) - imagebuilder: use env replace creds volume</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/4e8a6e570108c8db393c764bd6cfa8f66cb126c7"><code>4e8a6e5</code></a> (imagebuilder) - imagebuilder: add imagebuilder config</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/2d891f53998f135bc91c34ff1e80189e01969ab5"><code>2d891f5</code></a> (imagebuilder) - imagebuilder: change minio to storage</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/addceda27e7416c7e75d7502265448a95377ed4d"><code>addceda</code></a> (imagebuilder) - imagebuilder: upgrade new require</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/a6e569fdfaf379bb7c64c32e2406ecbb61ad890f"><code>a6e569f</code></a> (imagebuilder) - imagebuilder: pack_build add &ndash;env-file parameter</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/6191ff5c4cc132b0a5f9bf4bc227f8a64ed0c327"><code>6191ff5</code></a> (influxdb) - influxdb: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/dc3f8c7ed955953e4b576111edde4f05726a86cb"><code>dc3f8c7</code></a> (influxdb) - influxdb: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/6b5c81922dd498c0abb22e44ff85226881df187f"><code>6b5c819</code></a> (influxdb) - influxdb: new ingress style</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/68b381d1f377bdd805d4db86fb244ece080851bc"><code>68b381d</code></a> (influxdb) - influxdb: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/ea20eb81c27c90d8038872a9b5517ea1a7eafb8f"><code>ea20eb8</code></a> (influxdb) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/64c0a71ef6d0139d8c8df6b8823f53d444df1adf"><code>64c0a71</code></a> (influxdb) - influxdb: set gid uid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/a709ca19e2ee8a37f9f46263a714aea85e413391"><code>a709ca1</code></a> (influxdb) - influxdb: use DRYCC_UID DRYCC_GID env</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/740dff00afe4b6b207d3e64819745702861e7b8b"><code>740dff0</code></a> (influxdb) - influxdb: use common affinity template</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/e0356737f548edc85730aecbbf3ac402ef0fc3a0"><code>e035673</code></a> (influxdb) - influxdb: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/f1cefbd0b3107e5a4a228cce55e580eda0a6e849"><code>f1cefbd</code></a> (influxdb) - influxdb: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/a00100ebf6f1f8ee29d0341689823be68297a9f6"><code>a00100e</code></a> (influxdb) - influxdb: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/9d165ef2cf43f2abceba893a883e34285e694cb3"><code>9d165ef</code></a> (influxdb) - influxdb: add probe</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/bee7fff49a4c9410c5ccae1f3a2435ac0b505e82"><code>bee7fff</code></a> (influxdb) - influxdb: upgrade to influxdb 2.4.0</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/254914c02d7bd968e52586a52b8749d5b3fb6388"><code>254914c</code></a> (logger) - logger: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/8d91c68965c76c955300ec0f2e583020c14465e7"><code>8d91c68</code></a> (logger) - logger: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/b6d21828ed8355c658716f9684c7dee4c73a964f"><code>b6d2182</code></a> (logger) - logger: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/c35e59a79f6ccd9946db9979abb9f5125c899695"><code>c35e59a</code></a> (logger) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/a63c07029db0b5f7ec7dc38f4f60489956944475"><code>a63c070</code></a> (logger) - logger: change workdir to /workspace</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/a594b28985d601c0289deedef07ac09ccd58a1f4"><code>a594b28</code></a> (logger) - logger: set gid uid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/9a90e22cac7243e36d88d33f95369a7a5b0a5baf"><code>9a90e22</code></a> (logger) - dockerfile: use uid gid</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/36493b41b11e8847d578dd9563d581bf25adcb2e"><code>36493b4</code></a> (logger) - logger: use common affinity template</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/897a3a5a77ea96250b76bcf06274179c85549c86"><code>897a3a5</code></a> (logger) - logger: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/03b32ab19cd49ddeb966682fe5e7dd4c3b34235e"><code>03b32ab</code></a> (logger) - logger: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/a50ba5fcd9ef8205a1b5064789735241b5ece4b8"><code>a50ba5f</code></a> (logger) - logger: change python-dev registry</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/23187a3fe6e2ffe2d4fc38a705e72c14a85fbb67"><code>23187a3</code></a> (logger) - logger: unified reids declaration</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/aaa129ade36389917750e10389b3274331caf03a"><code>aaa129a</code></a> (logger) - logger: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/be4f65615f0735303f9be4f9d67158979741b395"><code>be4f656</code></a> (logger) - logger: add replicas</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/7c25459be3cb002ea933a47e9ec318d20d69616b"><code>7c25459</code></a> (logger) - charts: add NetworkPolicy</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/6810149b5d3d6199c69909374a72836287f66b9e"><code>6810149</code></a> (logger) - logger: remove memory storage</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/a918c50d5294d3ac8bd6d156d0a63ecd373ba72c"><code>a918c50</code></a> (logger) - logger: add .vscode to .gitignore</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/a41521029d715d227582cb00edc64953028f5983"><code>a415210</code></a> (logger) - logger: add log follow support</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/59b1da3a3172da80b3b16205a6dc420a79208450"><code>59b1da3</code></a> (logger) - logger: upgrade new require</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/27cc151c73ef774d4799e04431748bdd8ffbeea5"><code>27cc151</code></a> (monitor) - monitor: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/07d6a9dff96571e1445fb04da374935062fa18e0"><code>07d6a9d</code></a> (monitor) - monitor: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/105435759e1f9250aaf0e7c0ea8d5b34aa2e0a76"><code>1054357</code></a> (monitor) - monitor: use redis default port</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/e3673dfa93515ecd8507a00b2081ab7749091038"><code>e3673df</code></a> (monitor) - monitor: remove nsqd</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/fc9dd3ed61d7990e451af7b28d7691a6a0557e28"><code>fc9dd3e</code></a> (monitor) - monitor: new ingress style</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/856a898d34a21c18479f11c20926621bcb75894d"><code>856a898</code></a> (monitor) - monitor: add default user env</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/9857535c0cdb43253706d3f6d47d15fd0cc592cd"><code>9857535</code></a> (monitor) - monitor: add random user</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/38b5a040f4617782597abd1ed63f2ac732c64bb8"><code>38b5a04</code></a> (monitor) - grafana: oauth auto login</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/5dfc5797cc291d2a6387713989bc0eb5c130127b"><code>5dfc579</code></a> (monitor) - monitor: upgrade version</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/e121b5a7844ed76b7cca01a89c0cfdbc36438487"><code>e121b5a</code></a> (monitor) - monitor: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/84462a03ead9ebc1addf53ede3089f4abb0db1f0"><code>84462a0</code></a> (monitor) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/b9e8ce8c0775c6ce6725200ca8639b372a91bbe9"><code>b9e8ce8</code></a> (monitor) - monitor: chore(imagebuilder): change uid gid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/05ee8abd8e44a731e070c6417b00f9a777649c22"><code>05ee8ab</code></a> (monitor) - dockerfile: use uid gid</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/e1fa68e170a1b4c8a1fd6ee67d211cb023cb6963"><code>e1fa68e</code></a> (monitor) - monitor: use common affinity template</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/b8f302b73ef2f71f53d3c165db6ca0f9d446e294"><code>b8f302b</code></a> (monitor) - monitor: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/4fc991f9be7d47ea1a029d57bbc8c7fb3c80bd5d"><code>4fc991f</code></a> (monitor) - database: bump telegraf 1.22.0 and grafana 8.4.5</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/21a2f6a6b23f23308d50f97ad99b9164919ff5b8"><code>21a2f6a</code></a> (monitor) - monitor: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/acc976f8c3a834f511cb482de03b0e6473de855f"><code>acc976f</code></a> (monitor) - monitor: change python-dev registry</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/62d76c13d28d136aba544749a837426f3317a794"><code>62d76c1</code></a> (monitor) - monitor: unified reids declaration</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/b3c57ad982406161ef60f04442d4dd9cee91b5b1"><code>b3c57ad</code></a> (monitor) - monitor: optimize oauth2 configuration</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/70af6b07c4c724fbd3070776f4863bffb381d549"><code>70af6b0</code></a> (monitor) - monitor: change passport config</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/69f9a888501b560c698bc6781a80752180f86f04"><code>69f9a88</code></a> (monitor) - monitor: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/2fb278f0ce0d7b9d606b04a4afc297ce44c146f4"><code>2fb278f</code></a> (monitor) - monitor: rename influxdb port</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/17548ffc21f7e10499c535c55ffb413f28576727"><code>17548ff</code></a> (monitor) - grafana: update dashborad</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/69d7bbda0547bae588e01dbcf167d31dfc7debfe"><code>69d7bbd</code></a> (monitor) - grafana: influx dashborad disk size</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/75db1b021bdd974f23f769ae69c9e33aed420d6e"><code>75db1b0</code></a> (monitor) - monitor: upgrade new grafana/telegraf</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/80504a1bb18cfd20493406dccf01e0de1b83713e"><code>80504a1</code></a> (monitor) - grafana: update influx and redis dashboard</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/f7078cba8022651a395db8484be72ca8156556dd"><code>f7078cb</code></a> (monitor) - monitor:chown use env</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/91ae0ddb94a172421923af2b63918b051bc65695"><code>91ae0dd</code></a> (passport) - passport: optimize login display</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/2d3bbbca40f25656872268f3862f71047f861349"><code>2d3bbbc</code></a> (passport) - passport: change drycc logo</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/59790a747eb6bf83345b57dbd3b27d23b760d48e"><code>59790a7</code></a> (passport) - passport: make user email unique</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/faea034774c19cfac3e5858262600cf1842601ed"><code>faea034</code></a> (passport) - passport: use strtobool</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/1fbf2bc2ce25b003a4f424efeeb67a54408b7744"><code>1fbf2bc</code></a> (passport) - passport: use yarn replace npm</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/119cac8f95d371bc51803dd482d9195460e1ede3"><code>119cac8</code></a> (passport) - passport: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/cff5062a2d8acc931c7a88d3afb7b7b8effd2642"><code>cff5062</code></a> (passport) - passport: set default CSRF_COOKIE_SECURE false</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/9cc021077c3f4f3992727c6661ac758bc8f9e60d"><code>9cc0210</code></a> (passport) - passport: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/9ab38969eff6a8bc8b33166ccd5352b0158e5c17"><code>9ab3896</code></a> (passport) - passport: new ingress style</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/259ccc91b805ed463ff0b0889a58debd78214fc2"><code>259ccc9</code></a> (passport) - passport: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/af1bbcdce7c677597c9647b27e96a1e3fcde7f5e"><code>af1bbcd</code></a> (passport) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/9ae5373f0ce8d6ec3a3f2f2915c9e6b08ca1a025"><code>9ae5373</code></a> (passport) - passport: set venv profile</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/8f610901ad7f5aa175433c2c160076cd0bcc3a15"><code>8f61090</code></a> (passport) - dockerfile: use uid gid</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/fcaf72dc9e5f196dc671a8a887ac33dcc4e1b5e2"><code>fcaf72d</code></a> (passport) - passport: upgrade npm package</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/546dcd5b8d668635ada247c7f44d95c0a001bac9"><code>546dcd5</code></a> (passport) - passport: add license</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/4bda2d661883876248c0dd0211fe15551c888c56"><code>4bda2d6</code></a> (passport) - passport: use minify</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/73b0fd135a91bf0e5c6238a659b0e41a5603d179"><code>73b0fd1</code></a> (passport) - passport: use common affinity template</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/278fe7a321f4a8561094d0cd8789918a1fd9a5fa"><code>278fe7a</code></a> (passport) - passport: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/3cd93d36d49972d4c87fc6fc7cbf38c8b6bd8a1b"><code>3cd93d3</code></a> (passport) - passport: add reactive</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/370b493ccac77e04b1366b4037e9fa7f46d4fda1"><code>370b493</code></a> (passport) - passport: add footer</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/483cbd6ae503b4a3116b673272526a842cd1dcff"><code>483cbd6</code></a> (passport) - passport: use h_captcha replace re_captcha</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/3d1675e2af62a5c858b1ae28385af97257c140d8"><code>3d1675e</code></a> (passport) - database: bump python 3.10.4 and node 16.14.2</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/86a783592e559b0a13d2cffcbea6bb4dd7e33684"><code>86a7835</code></a> (passport) - passport: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/2d65355b89a12658a69fad874add357378aedf83"><code>2d65355</code></a> (passport) - passport: change python-dev registry</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/90c1444d2f1f45658fe5a51f406ca58485eb251c"><code>90c1444</code></a> (passport) - passport: unified reids declaration</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/2e0e417f1ce86eff2c4d4f35bf5c40e230382cb8"><code>2e0e417</code></a> (passport) - passport: fix firefox footer</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/ad274bed8c36be339d461c657403070abbb695c6"><code>ad274be</code></a> (passport) - passport: use bulecss</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/f986d8b3a47d9fd83831fece5000189b1ca82dfc"><code>f986d8b</code></a> (passport) - passport: add main footer</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/3e528676fed3aae01fedbc1be39bcab7e997f088"><code>3e52867</code></a> (passport) - passport: dynamic settings for vue</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/38adabc356280f02d3cc048bd00b8ec1be8d91a8"><code>38adabc</code></a> (passport) - passport: change passport config</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/f8d6b604a6009be7b04d4b97d3457dcc0ba1b697"><code>f8d6b60</code></a> (passport) - passport: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/2cbd79daaeb948f274552e897acd53d0bddefb69"><code>2cbd79d</code></a> (passport) - passport: remove database conn_max_age</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/712279768f9c4dee75e5f0f6f6a1ab0865d5e701"><code>7122797</code></a> (passport) - passport: change drycc.cc to <a href="https://www.drycc.cc">www.drycc.cc</a></li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/8cc84cdb7717cc5a50353f7c32e745725c4c5973"><code>8cc84cd</code></a> (rabbitmq) - rabbitmq: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/f35930fb57b5a0b15c82be2f09879de46bd027e7"><code>f35930f</code></a> (rabbitmq) - rabbitmq: add rabbitmq cluster support</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/fbfa3ba8ff88b80d736ae2dee02575d43754529e"><code>fbfa3ba</code></a> (rabbitmq) - rabbitmq: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/ca607015c53dbf68bcdfe636ff46ce17cb973a01"><code>ca60701</code></a> (rabbitmq) - rabbitmq: use volumeClaimTemplates</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/fe5d1b41f48a729f1ada17ddaec4fd738d2c5c26"><code>fe5d1b4</code></a> (rabbitmq) - rabbitmq: add sharding support</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/9c4ab976e148b46d7fb2ba218254bb4cb8789152"><code>9c4ab97</code></a> (rabbitmq) - rabbitmq: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/348a88a95bad2b93971805ae9563555bfbd4ab00"><code>348a88a</code></a> (rabbitmq) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/2388be18e4d23623cc5b461a31f4dbc13562762f"><code>2388be1</code></a> (rabbitmq) - rabbitmq: upgrade erlang to 24.2.2</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/db2eaa5fac326200594c9768a6e6ce85721a8cea"><code>db2eaa5</code></a> (rabbitmq) - dockerfile: use uid gid</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/772afd1f7ed5732355bb9af28018d542d0c6e837"><code>772afd1</code></a> (rabbitmq) - rabbitmq: change to wait pid file</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/2bfc25ec33619c1b10be7639c819c8c2f383bbaf"><code>2bfc25e</code></a> (rabbitmq) - rabbitmq: use common affinity template</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/11d505ea19d520d98f74457054dfdbe9e91a98fc"><code>11d505e</code></a> (rabbitmq) - rabbitmq: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/69d63f1c0ce2ed2a0a80945582db041e5dd7bb7e"><code>69d63f1</code></a> (rabbitmq) - database: bump erlang 24.3.3 and rabbitmq 3.9.14</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/838029926101907d9da255e2cbcabc97dd1b0dba"><code>8380299</code></a> (rabbitmq) - rabbitmq: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/b3f69f14a151124887f49a9c4740905221d8f65a"><code>b3f69f1</code></a> (rabbitmq) - rabbitmq: add check rabbitmqLocaltion</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/5327c76d66cb6339d68036aeff52f13f315ca4f0"><code>5327c76</code></a> (rabbitmq) - rabbitmq: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/5c66b5a74037aa530ed84203c153a7d83f2ba6cc"><code>5c66b5a</code></a> (rabbitmq) - rabbitmq: change probe</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/27bebf99a4fac504dc3e4a2a8d395cc5c23c9ff4"><code>27bebf9</code></a> (rabbitmq) - rabbitmq: add start-rabbitmq script</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/86ee6a780841f4f4927aa4dc6bbc50362fc5f5a0"><code>86ee6a7</code></a> (rabbitmq) - rabbitmq: upgrade to rabbitmq 3.10.7</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/1f29683eb9630822c50687276941bf10b2e1c014"><code>1f29683</code></a> (redis) - redis: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/a5041fc911aa86b277f3577949637f090d7d0488"><code>a5041fc</code></a> (redis) - redis: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/64468c2257c828e61d183d4680b632ea0a24021e"><code>64468c2</code></a> (redis) - redis: add redis persistence</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/de5d7538e64ec86c2d7393dfab922dfe66d29bde"><code>de5d753</code></a> (redis) - redis: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/f6446395fbf46fd644ce3b12a3b5996e7a5b66a2"><code>f644639</code></a> (redis) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/98051d20ecb8f946c8e5093b50791df77494da52"><code>98051d2</code></a> (redis) - redis: premission denied</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/bcb548eca8ae83d1f828bd47e190b6f78a919635"><code>bcb548e</code></a> (redis) - dockerfile: use uid gid</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/524aa412e589ed21c61e31ad03067f8b96a0e116"><code>524aa41</code></a> (redis) - redis: use common affinity template</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/26c946651e503cf3be26225010fcf67a646e8c27"><code>26c9466</code></a> (redis) - redis: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/b67d7a25db6484862676b57d89530f5de4cd254e"><code>b67d7a2</code></a> (redis) - redis: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/839ec50c7c473dcac3fc2fb7e0a51a3493b3db62"><code>839ec50</code></a> (redis) - redis: use env replace creds volume</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/237ca86c239a392e23ce9b7ce68bcf9d1d0da27f"><code>237ca86</code></a> (redis) - redis: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/bdd968d27a01a06110ac394fcb4f7893cfb0edc1"><code>bdd968d</code></a> (redis) - redis: upgrade neew require</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/8b2910f10b7f5b6da8828bf8558f4eb373fcc238"><code>8b2910f</code></a> (registry) - registry: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/eedbe78543bf04298134ee2900b21d9218fd99e5"><code>eedbe78</code></a> (registry) - registry: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/024161578b010ad70702ae9480cb07a9b210ca61"><code>0241615</code></a> (registry) - registry: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/9b58da4298fd28f3ca060ce2ffd11a0977b755e1"><code>9b58da4</code></a> (registry) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/ab6acb71f85990865cd4322ef21e3d2ae0903ac8"><code>ab6acb7</code></a> (registry) - registry: change workdir to /workspace</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/f368bf7d7dfb8357acc8bf5019d052057dba393e"><code>f368bf7</code></a> (registry) - registry: use DRYCC_UID DRYCC_GID env</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/f4b9041f9c18721dcfc71091a89145323c5fc092"><code>f4b9041</code></a> (registry) - registry: use common affinity template</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/c2e87ca32c58633e9f86b3422d48249b3c1d81a8"><code>c2e87ca</code></a> (registry) - registry: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/feb6aba75f16044ecd927e020372338cd6ddf519"><code>feb6aba</code></a> (registry) - database: bump mc 2022.04.01.23.44.48</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/956932b04720266b896c0ea150a595c77a513444"><code>956932b</code></a> (registry) - rregistry: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/deda8d8d7868938fa890b5e7a0f22911e7151837"><code>deda8d8</code></a> (registry) - registry: move registry-secret.yaml from workflow to registry</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/f52c7bf6e4bc23d4f7b4e78224ff2d8da81198bc"><code>f52c7bf</code></a> (registry) - registry: change python-dev registry</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/007fe03a89f5e3b6d9baeda0b3fea84041a46ea4"><code>007fe03</code></a> (registry) - registry: <a href="https://github.com/minio/minio/issues/14331">https://github.com/minio/minio/issues/14331</a></li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/d620c6db554f29b6c9b044c12b5dfd62194f274b"><code>d620c6d</code></a> (registry) - registry: <a href="https://github.com/minio/minio/issues/13799">https://github.com/minio/minio/issues/13799</a></li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/85e6b732126ea2dacb4db0d79b2fbb831b0d984a"><code>85e6b73</code></a> (registry) - registry: use env replace creds volume</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/6a1155d75f7d6007f7ef3fe2c947423567c20e65"><code>6a1155d</code></a> (registry) - registry: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/7b8ebae5738c401580391a631757fa4646a31f3c"><code>7b8ebae</code></a> (registry) - registry: change minio to storage</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/13389519866129557fe9e08b446eb3a3de163a71"><code>1338951</code></a> (registry) - registry: add check storage health</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/2fa769dcfb770b1f9789e3ab13f96380f3e708c6"><code>2fa769d</code></a> (registry) - registry: change probe</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/f187cbf22c9206693656df844e2f97007dd95574"><code>f187cbf</code></a> (registry) - registry: add replicas</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/09d8a7b3cc69d6e0f90ab19b727f54b7129a3ae5"><code>09d8a7b</code></a> (registry) - registry: upgrade to mc 2022.08.28.20.08.11</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/4b187b8d076ef387b667e0807081021184c1f55f"><code>4b187b8</code></a> (registry-proxy) - registry-proxy: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/29ffbbe58737a14432a69938c69ff54c056b7f85"><code>29ffbbe</code></a> (registry-proxy) - registry-proxy: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/6d783baa4be1de057980040830fd6d3b161347a8"><code>6d783ba</code></a> (registry-proxy) - registry-proxy: remove use_cni</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/8cf05cff7cb44bf0b0f5c94e76567607d2f9adef"><code>8cf05cf</code></a> (registry-proxy) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/090e28647345560182a8f21da8f9445d567e3c73"><code>090e286</code></a> (registry-proxy) - registry-proxy: chore(imagebuilder): change uid gid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/7cf6120e818b9a12799a305d8d17dfef8746a9b1"><code>7cf6120</code></a> (registry-proxy) - registry-proxy: use DRYCC_UID DRYCC_GID env</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/3a00697ed5de2230fc98971798d16de4ac6ceccd"><code>3a00697</code></a> (registry-proxy) - registry-proxy: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/30e69e8ca26894cc9efcd206665c5d96aa198085"><code>30e69e8</code></a> (registry-proxy) - registry-proxy: add registry basic auth proxy</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/942abce928797f2a77883f3a6a1a6720a6774c34"><code>942abce</code></a> (registry-proxy) - registry-proxy: upgrade to nginx 1.23.1</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/5ea3297285ab826c6686bcd20c34b1dd178615f6"><code>5ea3297</code></a> (storage) - minio: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/8306addad83bf486ae0d796d85b8f5593ca22ef7"><code>8306add</code></a> (storage) - minio: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/c917e9f3e1b03d0c9557f41f753c05f5d48f60df"><code>c917e9f</code></a> (storage) - minio: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/042c73208b255364db2cc08374a7b9ba39946edf"><code>042c732</code></a> (storage) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/7b47b82f903ecd1e6f6c1a30ed856f7153eaef20"><code>7b47b82</code></a> (storage) - minio: change workdir to /workspace</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/6f3531ef29ed032f3f0bcbc09211e9030a02340a"><code>6f3531e</code></a> (storage) - minio: use DRYCC_UID DRYCC_GID env</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/9795fb1c71641cd106dc06abeb355c8479b0a351"><code>9795fb1</code></a> (storage) - minio: use common affinity template</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/a7b09c5b264fa9ce068ae06b12ac5fec6e7a63d4"><code>a7b09c5</code></a> (storage) - minio: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/76073428fa40f6048482594720707c1e92ca17d5"><code>7607342</code></a> (storage) - database: bump mc 2022.04.01.23.44.48 and minio 2022.04.01.03.41.39</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/ea2b2f15ffc2c4d263e537aa14a74f9c71a450cc"><code>ea2b2f1</code></a> (storage) - minio: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/445b50100629f5799b4137fa5d71a4768836f8d2"><code>445b501</code></a> (storage) - minio: <a href="https://github.com/minio/minio/issues/14331">https://github.com/minio/minio/issues/14331</a></li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/f19fbc75f98c5f1349bdfe098c69bdf732a10886"><code>f19fbc7</code></a> (storage) - minio: use env replace creds volume</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/8982e2eab58a059040d483c4ac373e9ccced0765"><code>8982e2e</code></a> (storage) - minio: use minio to distributed</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/06bec7372476dec97304f51754a9c031498fd888"><code>06bec73</code></a> (storage) - minio: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/9b8f0062892bcd4f720014a142efde4ce6ed10c6"><code>9b8f006</code></a> (storage) - storage: remove assert</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/59d64b92e21603e86573699e5b1e2914672cfe3a"><code>59d64b9</code></a> (storage) - storage: change listen to POD_IP</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/60044ee012378c0c344518f5945ed6dace124535"><code>60044ee</code></a> (storage) - storage: add juicefs mount options</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/189f944175bd9c16d3a8d5347a9040143903e15a"><code>189f944</code></a> (storage) - storage: remove volumeName</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/302fe8964b3171bc6c7cdddd494d5e3ca62c5209"><code>302fe89</code></a> (storage) - storage: mv to minio dir</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/6ec586d742cf14f311e2ac097ad207c2b3fb65b4"><code>6ec586d</code></a> (storage) - storage: change readinessProbee andlivenessProbe</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/0e028dfee98c4cf8a54110101f1084b03cf75b8e"><code>0e028df</code></a> (storage) - storage: add minio pdb</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/cf9bd2de2b8138b6a75c1d804e919586d2d53eca"><code>cf9bd2d</code></a> (storage) - storage: add check storage health svc</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/2dd5c9f20dcbbdb184d3e0be19a9e93b41ac1019"><code>2dd5c9f</code></a> (storage) - storage: add volumeBindingMode</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/fa2effc313905bf8e7a0d41d6d09335ca1a70552"><code>fa2effc</code></a> (storage) - storage: remove databaseBucket</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/d166cc721e45bf1955a2d99b70187ee9b3d6970a"><code>d166cc7</code></a> (storage) - charts: format network-policy name</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/d06bcce9fe0e8de7720e5c93b5d87e742be7f5a7"><code>d06bcce</code></a> (storage) - storage: upgrade to golang 1.19</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/c2ca05cd4b92259d4454723ab25252e4f6e220ac"><code>c2ca05c</code></a> (storage) - storage: upgrade new require</li> +</ul> + + + + + + Blog: Drycc Workflow v1.5.0 + /blog/2022/10/06/drycc-workflow-v1.5.0/ + Thu, 06 Oct 2022 00:00:00 +0000 + + /blog/2022/10/06/drycc-workflow-v1.5.0/ + + + + <p>These release notes for Drycc Workflow v1.5.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.4.0, please refer to the following change summary.</p> +<h2 id="workflow--v140---v150">Workflow ## v1.4.0 -&gt; v1.5.0<a class="td-heading-self-link" href="#workflow--v140---v150" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>passport v1.0.0</li> +<li>rabbitmq v1.0.0</li> +<li>imagebuilder v1.0.0</li> +<li>builder v1.2.0 -&gt; v1.3.0</li> +<li>controller v1.3.0 -&gt; v1.4.0</li> +<li>database v1.0.2 -&gt; v1.1.0</li> +<li>fluentd v1.1.0 -&gt; v1.2.0</li> +<li>redis v1.1.0 -&gt; v1.2.0</li> +<li>influxdb v1.0.1 -&gt; v1.1.0</li> +<li>logger v1.1.0 -&gt; v1.2.0</li> +<li>minio v1.1.0 -&gt; v1.2.0</li> +<li>monitor v1.1.0 -&gt; v1.2.0</li> +<li>nsqd v1.1.0 -&gt; v1.2.0</li> +<li>registry v1.0.3 -&gt; v1.1.0</li> +<li>registry-proxy v1.0.2 -&gt; v1.1.0</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/0f5f8e4171313ea56de2d659d92458acd39a3201"><code>0f5f8e4</code></a> (builder) - builder: multi-platform support</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/f269d06ddc42464ba99ceeabc283645778034547"><code>f269d06</code></a> (builder) - build: add buildx supportjkjkk:q</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/5e72fe88f057c1814c6d8075638d124445c16157"><code>5e72fe8</code></a> (builder) - registry: use docker build</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/25d8a4cbc14ccfeccc0a33d17fc723149103a0d3"><code>25d8a4c</code></a> (builder) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/7a3e1c58942dfdfde474462f92a2a5bddf1c15a8"><code>7a3e1c5</code></a> (builder) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/46b75ff211da2985ce17737e7c6bb29ce73c8df3"><code>46b75ff</code></a> (builder) - builder: add cloud native buildpacks support</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/2db2054dd960f80ee76c442d3705490c5f70358a"><code>2db2054</code></a> (builder) - builder: unified build model</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/4b7f9d9bc38c65ca56e162701b4cbce43c1cbbbe"><code>4b7f9d9</code></a> (builder) - builder: add initContainers</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b78c936ec706cce8bd8e8676a411187fed658b23"><code>b78c936</code></a> (controller) - token: add get token api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/bac52a51b06872d48ecefabfb14b29b9f70d4357"><code>bac52a5</code></a> (controller) - tasks: use celery replace nsqd</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b9b0c58b1f877d077543efb202c71f5cec07b6fc"><code>b9b0c58</code></a> (controller) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/205dcb3b5b1003d704a0033d3a3b8b6761393df9"><code>205dcb3</code></a> (controller) - influxdb: add influxdb client</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ff15849bafddc47e06820ca89e8e95abc6c89311"><code>ff15849</code></a> (controller) - influxdb: upgrade to influxdb 2.x</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4016244757d764b553abd20ffb8ed79368c7caa1"><code>4016244</code></a> (controller) - controller: push data to influx</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/fcfce2ea7f6af657c46a1c53f0f78b7224b56ff6"><code>fcfce2e</code></a> (controller) - workflow-manager: add workflow-manager support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/00e9bfb627c11be35fd57c330d3127c84675b0f6"><code>00e9bfb</code></a> (controller) - influxdb: review influxdb code</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/dd644d5a5e626d51ddb6f4d6488691ac7f2f2804"><code>dd644d5</code></a> (controller) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/118278b332877428f09d13801432a8c7f51ebbee"><code>118278b</code></a> (controller) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/122a9cd267f8b80d4b922938b97a71032f174648"><code>122a9cd</code></a> (controller) - oauth2: add oauth2 support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/559a5b6c76a0b9925bdd7d027e5653b7d494d4ac"><code>559a5b6</code></a> (controller) - controller: use cncf buildpacks replace slugrunner</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/96130e6900dae2bc31899e3a06fec87c5c6684c9"><code>96130e6</code></a> (controller) - charts: database configuration optimization of passport and controller</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/2ea85089f9ef7814e7c504380929c09cd73fadb2"><code>2ea8508</code></a> (controller) - oauth: using passport authentication</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/868c437940b7cde4caaf0b4f81ab5265cd2f197c"><code>868c437</code></a> (database) - database: multi-platform support</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/eadd5da76c3a5979a90b52b245dc9041da861d6a"><code>eadd5da</code></a> (database) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/b6eea4c09dcd95d7f8f0540c2ffef63567146167"><code>b6eea4c</code></a> (database) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/04a88dbafe96027068badd9e65c30b832432c371"><code>04a88db</code></a> (database) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/92ed309894ef2d065d4dc20acf5cf44dfafa84d7"><code>92ed309</code></a> (database) - database: add initContainer</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/ee6b78ff78bfe978edf2e9a9789bdf58c2dc846f"><code>ee6b78f</code></a> (fluentd) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/f523e30c5e93d80e509232e7bb25f4de92267312"><code>f523e30</code></a> (fluentd) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/ee47b53b6f18bf4e2cdd41aaabf4dcd807d4b2d7"><code>ee47b53</code></a> (fluentd) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/80a51af1c0dbf689ead41a4b88d5e31861a7b0d0"><code>80a51af</code></a> (influxdb) - influxdb: modify influxdb naming rules</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/fb1003086e3819ada293e1792b46e966e509ee3a"><code>fb10030</code></a> (influxdb) - influxdb: use influxdb v2</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/0e87ad8c239a8cbb4ec02a584081ac1be0cb21af"><code>0e87ad8</code></a> (influxdb) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/9d108019d94ce2e653ec16482e89dff314810f9b"><code>9d10801</code></a> (influxdb) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/d825c9f7b4198c10e93abc7121af54f7af63f711"><code>d825c9f</code></a> (logger) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/b1395766670636ecbb42fb0b4ca1649186bfd4c5"><code>b139576</code></a> (logger) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/88f84ea95e334fcfef45ecd4f28c8bc468523574"><code>88f84ea</code></a> (logger) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/5ccae3ef8fa0894f08bf6ba552b17455a481a698"><code>5ccae3e</code></a> (logger) - dockerfile: remove chmod cmd</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/193aefc8c4106c7c6d5022c9183c68d6e604e735"><code>193aefc</code></a> (logger) - logger: add initContainers</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/baee3305a3b09a0fba83f33fb161400a7e7fd7fb"><code>baee330</code></a> (minio) - minio: multi-platform support</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/ad5d055e170977801a6951813e4896d1f854e14f"><code>ad5d055</code></a> (minio) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/19868d457852e423536d8ae8f426a2c3437f423d"><code>19868d4</code></a> (minio) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/4bd84b8bb8af65a0ab05eff3a4c227452c4a3a2f"><code>4bd84b8</code></a> (minio) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/79d1f2f85c17c71ec609e8e191e04e9de87deec0"><code>79d1f2f</code></a> (monitor) - database: multi-platform support</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/88e5a7f45886f5ca947e44052c5c52a2f8e17497"><code>88e5a7f</code></a> (monitor) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/5672e99a81ce856e4cd42a1b4e1083919e165272"><code>5672e99</code></a> (monitor) - influxdb: modify influxdb naming rules</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/867210310f29da9600bb2d052e05d5181cfe5a4f"><code>8672103</code></a> (monitor) - influxdb: use influxdb v2</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/66cb4c877ee0acfdcabab284da18b58266b61201"><code>66cb4c8</code></a> (monitor) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/9576eb38c61048d3d540303047c8690763d664e1"><code>9576eb3</code></a> (monitor) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/30809c9ce3f31f52ac10616dbe9a24135d74828d"><code>30809c9</code></a> (monitor) - monitor: add initContainers</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/70d140ce05b061462a990029b9fd7ac749c383c7"><code>70d140c</code></a> (nsqd) - nsqd: using self compiled nsq binary</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/1073d4f35b082ea6dd63570d8427d7e3d1c2fecf"><code>1073d4f</code></a> (nsqd) - nsqd: use GOPATH replace /go</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/e49848037b54362f83ee063adc6e954afe8fa84a"><code>e498480</code></a> (nsqd) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/cf9b7d5cd6ee63d77acadec5c3a410acb60df400"><code>cf9b7d5</code></a> (nsqd) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/c335856f1ca9c80b0dc23df3445d395a13b8b50b"><code>c335856</code></a> (nsqd) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/efba7134453bc730b968d909089564de3de3079a"><code>efba713</code></a> (redis) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/c7a3b53025faa393bf6e915ec71b96ef7a5da27f"><code>c7a3b53</code></a> (redis) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/4cdad7bab726dd11973c1dbc643a81eb6313ba1f"><code>4cdad7b</code></a> (redis) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/652b443a4e5c54765bb40cfeb38310eee455a3c2"><code>652b443</code></a> (registry) - registry: multi-platform support</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/4060176efaca5531faec4ecdd02eb30b6451e16e"><code>4060176</code></a> (registry) - registry: use docker build</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/7102a03677830beb4b0ad093b141cb48ba948dd7"><code>7102a03</code></a> (registry) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/6c8600d293589b36748acf7b4dfb913f2cefde8d"><code>6c8600d</code></a> (registry) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/33a51c99e3f278c7c36dfc27c124db3dec530914"><code>33a51c9</code></a> (registry) - registry: add initContainers</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/bef70dc98c4b044d1108f6b42f439b36d37270e1"><code>bef70dc</code></a> (registry-proxy) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/d2319c1fce4e57cd9257ec3978f4e5a8d0101a23"><code>d2319c1</code></a> (registry-proxy) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/02fafed2b1b5648274c3d44c3d113a0a025e4fca"><code>02fafed</code></a> (registry-proxy) - charts: set the default chart version</li> +</ul> +<h4 id="fixes">Fixes<a class="td-heading-self-link" href="#fixes" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5499c9a2844c192285d5afdbf6a08d803a70cf8d"><code>5499c9a</code></a> (controller) - gunicorn: gunicorn not running</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/06e9e8869fbf61b3db753ab211bd9d465afa9058"><code>06e9e88</code></a> (controller) - controller: error loading shared library</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/01b5bd04cf1848b876b2b5acbeae6c361bebf975"><code>01b5bd0</code></a> (controller) - controller: upgrade celery config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/6e32d55cf9de3dce1b7d470f850c2d155809cc07"><code>6e32d55</code></a> (controller) - controller: fix update resources bug</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0e0d53f3056dfbf427ad7a474786e723b87cb39c"><code>0e0d53f</code></a> (controller) - chart: set the domain depends certManagerEnabled</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/2ac4ca839d76a4b80205506938d63f25bb4abea0"><code>2ac4ca8</code></a> (controller) - passport: error loading shared library libexpat.so.1</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/a0dd517e189a2ba9472c0d320ba32d091520dcbe"><code>a0dd517</code></a> (fluentd) - fluentd: drone build</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/6eca2a3e17e2965816718963fe4d7f6ffeb15a42"><code>6eca2a3</code></a> (logger) - logger: golang lint</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/63b0aa0989db8f9e15daa415c5a0b56e9350c0a9"><code>63b0aa0</code></a> (registry) - drone: charts url error</li> +</ul> +<h4 id="docs">Docs<a class="td-heading-self-link" href="#docs" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/472cfcc226c98d2b9a74c367519d57ec31890b71"><code>472cfcc</code></a> (controller) - controller organize README.md document</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/d9d6e292c602c3538784de6755b40f4655710278"><code>d9d6e29</code></a> (redis) - redis: delete links that do not exist</li> +</ul> +<h4 id="test-case">Test case<a class="td-heading-self-link" href="#test-case" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1468f57465243709594b0d6472636ccc0d7b7f62"><code>1468f57</code></a> (controller) - controller: add command unittest</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/9999bfd30ab9550966eb70a6e52efbbb38f5cef1"><code>9999bfd</code></a> (builder) - builder:replace the special words</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/cda8b5814e507ab72a0ce7125eaa8d6bdd168a06"><code>cda8b58</code></a> (builder) - builder: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/dc575dde93ad1334be9d1337fbc1b0b66a06ebd9"><code>dc575dd</code></a> (builder) - builder: use imagebuilder replace dockerbuilder</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/d3bb183df646a7f2503c739633bb6d5d61778219"><code>d3bb183</code></a> (builder) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/5fe34d1fee978986729120af7d5732ed3759b88c"><code>5fe34d1</code></a> (builder) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/7e364532bf841109fe5e75c6a5c357ad46f7c4b7"><code>7e36453</code></a> (builder) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/52b8d9df26f28e562b4eca72e777106db86db9db"><code>52b8d9d</code></a> (builder) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/65963f4b35d2b60e376818d314cd203fb698eaba"><code>65963f4</code></a> (builder) - k8s: add privileged to dind</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/d345fcf23f1c3e755ec646d988c5d1e0e90d2eba"><code>d345fcf</code></a> (builder) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/7975c998252a66557bbfa774ac18f18e17a5ddbd"><code>7975c99</code></a> (builder) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/59633dd9197fed8400d8007cc93e7a62404e92b1"><code>59633dd</code></a> (builder) - builder: modify launch imagebuild pod</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/8d14e67e5e84c2d6b6254b7704219c9ed38aac67"><code>8d14e67</code></a> (builder) - builder: use Procfile in anywhere</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/5357fa88e56ef24fac7f8d3dc0bfa5d990c1be58"><code>5357fa8</code></a> (builder) - go: bump go mod</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/8d26ac054edeb67e4ce473507a96951dbda10db2"><code>8d26ac0</code></a> (builder) - k8s: k8s deprecated api migration</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/0af620def4db8473c799c9499a4a27ee4a278210"><code>0af620d</code></a> (builder) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/ae84303f6d15b22c525e62cf3ae2d1e314d9a67b"><code>ae84303</code></a> (builder) - builder: run imagebuider replace pod with job</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/3b2c496a00a8512731c18d79215ce9e279b60e19"><code>3b2c496</code></a> (builder) - builder: change docs website</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/5679a4cfefd214b7bb0014cde3f7c461bd70ca91"><code>5679a4c</code></a> (builder) - builder: upgrade to golang1.17</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a214503452b10f3e265d97954964d321480b007d"><code>a214503</code></a> (controller) - controller:replace whitelist with allowlist</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/375ddcc15761326b8c74f8cd78a239cfe9c14224"><code>375ddcc</code></a> (controller) - ps:drycc ps:list show autoscale num</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c32e409b6fe09c533bc5cfdbf35b47e633d2a644"><code>c32e409</code></a> (controller) - ldap: canot register when ldap is enabled</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c46580a6264cbe21ee5240fde5791c9c78ef2a19"><code>c46580a</code></a> (controller) - controller:modify redis config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/fa9e87b6131a9669eebafb4bfea26dc5f15bde64"><code>fa9e87b</code></a> (controller) - chart:modify controller charts</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/6f9fd081e6826fd89316ff4d064c9cf03501e1d3"><code>6f9fd08</code></a> (controller) - nsq: remove nsq</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/994b2dc68afdeaedc540525422183565bc1e3230"><code>994b2dc</code></a> (controller) - docker-buildx: add check-docker</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a720c3a9933aaaa15d5933143708fbcac2d5233a"><code>a720c3a</code></a> (controller) - controller: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e9a5c843d0abd85ae57d8cb87cbe7369364b07e6"><code>e9a5c84</code></a> (controller) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a26614acb4fb8cef5030e0e56681939977a7a266"><code>a26614a</code></a> (controller) - controller: add rabbitmq env</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3df229d2d31b6f8fc79a260e5088a86d00716459"><code>3df229d</code></a> (controller) - controller: modify database config &amp;&amp; remove redis port config &amp;&amp; add env prefix with DRYCC</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/257e94b429c8f7b0c636a083215d9709baaf5c8d"><code>257e94b</code></a> (controller) - controller: CELERY_BROKER use rabbitmq and modify celery-deployment cronjob</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f4d6ec343ec3fb618ef9ee8da09474294d49807e"><code>f4d6ec3</code></a> (controller) - chart: pretty chart format</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/63e61951cda276fe59a91a64a7b84f7feb66ce6d"><code>63e6195</code></a> (controller) - influxdb: modify influxdb code</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0f6d408734984e4ec9bbc56c0a4b68ba5783b680"><code>0f6d408</code></a> (controller) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/87bad28b65b773e6534c4cc8e2128045d3ffb7c3"><code>87bad28</code></a> (controller) - python: upgrade to python3.9</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e8f75603cd0cd38423d774f1b3220b64ef9eb6dd"><code>e8f7560</code></a> (controller) - volumes: modify mount summary</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/6cf6c6bdbf029b1e52a36d5148d5a025fb6d04c1"><code>6cf6c6b</code></a> (controller) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a9397e8c06a69d5539e8f5b67be242932e69c2c8"><code>a9397e8</code></a> (controller) - oauth: modify token Authentication</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c7f8c8b3b2294205603afd9ca4a7ba2e3f6cea02"><code>c7f8c8b</code></a> (controller) - deps: bump django from 2.2.14 to 2.2.18 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a1a08aa4165ba678e979d6ca4477694999d0e5b8"><code>a1a08aa</code></a> (controller) - deps: bump djangorestframework from 3.11.0 to 3.11.2 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/efd78b42038a404d53d06e92bb609cc7f97739db"><code>efd78b4</code></a> (controller) - deps: bump django from 2.2.18 to 2.2.20 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/649b044c644c9729b80e5f0e2663779bcc648ef2"><code>649b044</code></a> (controller) - deps: bump django from 2.2.20 to 2.2.22 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/41b742bbec9370490b0176fac407bcbd83abd2ed"><code>41b742b</code></a> (controller) - deps: bump django from 2.2.22 to 2.2.24 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/22ffe5d8dd51cffc38e5e3757ac97eba02861e2b"><code>22ffe5d</code></a> (controller) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c98b46837efa85a5daf46c6dc40d45606b7548bc"><code>c98b468</code></a> (controller) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/20e6edb1001fb709ea877349771404ee807ae36d"><code>20e6edb</code></a> (controller) - chart: modify the problem of using buildpack</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/db16879a4ce64c7020b7622603f53ef88898be0a"><code>db16879</code></a> (controller) - controller: pretty pods list print</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ba6f456ddb0a48a0e8c1f446330a838ba27b8f48"><code>ba6f456</code></a> (controller) - test: pretty pods list print</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5fce4b7a77c91836d921c6d1f4cb8cacb2ab953d"><code>5fce4b7</code></a> (controller) - k8s: k8s deprecated api migration</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e9e0bcb36d4b6b1169446c484357260aee7feba7"><code>e9e0bcb</code></a> (controller) - oauth: using passport authentication</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0311172bea0f1d28959ee528c0e50493d0c8d425"><code>0311172</code></a> (controller) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/150eff1c246b908e8f5521cc1e5e9ff4c765433d"><code>150eff1</code></a> (controller) - charts: update cert-manager api version</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/de8545a568984f52e5757806d9ce631864285fed"><code>de8545a</code></a> (controller) - controller: update requirements</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1442207889955cbf230bd1c87867acaab72256fb"><code>1442207</code></a> (controller) - controller: using django native JSONFiled</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ab4e836a55aa61cbdb222a8fc606b5619625337e"><code>ab4e836</code></a> (controller) - oauth: modify passport api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5c54e0642c76bfa1253397177b5aef2dc28dc611"><code>5c54e06</code></a> (controller) - controller: eliminate pip warnings</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/870328ddf06ab6b3004fd0e56516de6496c06e26"><code>870328d</code></a> (controller) - controller: remove entrypoint</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5e5e6ae5763333989e153119c6078c06788d0f78"><code>5e5e6ae</code></a> (controller) - controller: upgrade celery config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/607778ffb2f81b74457db2b34952a0cd01647eb3"><code>607778f</code></a> (controller) - controller: add initContainer</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/23dc016da2419237814a7d1ac54435adc99f0423"><code>23dc016</code></a> (controller) - chart: set the domain depends certManagerEnabled</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f3cf20b610a649d105e4889212272604615ddfa7"><code>f3cf20b</code></a> (controller) - controller: remove default bash env</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/73f26364110a1cdee5bdfe868e4fbf0be2cdbcf4"><code>73f2636</code></a> (controller) - controller: modify alpinelinux repositories</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/498e9f2fbd5470ff8079e09eacc04be4272d9601"><code>498e9f2</code></a> (controller) - chart: change certManagerEnabled to boolean type</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/27f5308938f972d078e78c539e9160cc2f3b3a1a"><code>27f5308</code></a> (controller) - passport: exclude cryptography</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/370b75dc9cbdcf24b3955b562ff276e3214eb5a2"><code>370b75d</code></a> (controller) - controller: use sh env</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/07585b4f45471b22e6942590dac51cf724e8bd57"><code>07585b4</code></a> (database) - postgres:replace the special words</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/20172dcfac8370b389aa26a30cc9e2f0a96f6a6d"><code>20172dc</code></a> (database) - database: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/abb9b88a96e0098d3fb1128d123825ca4faea3a4"><code>abb9b88</code></a> (database) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/e72f58ffa50be0f5170423529292872fcd53cfea"><code>e72f58f</code></a> (database) - chart: modify the off-cluster database</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/a91f64f694c15143b7210597ffdd7dacfa6668bf"><code>a91f64f</code></a> (database) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/614fb76a1c77b8f5697a87aadfd094d6eaa8c27b"><code>614fb76</code></a> (database) - tests: use add-host replace link</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/a3428f353c38f440381890fd80416ad302033352"><code>a3428f3</code></a> (database) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/239fef11f87655203f6090e55259cb09906fb253"><code>239fef1</code></a> (database) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/42858e1e2ae1a09e1bad75e1fabb7ec4115e7197"><code>42858e1</code></a> (database) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/d0fe85094eb305ce071f51bf40bdf2099b88ea13"><code>d0fe850</code></a> (database) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/34a36ad4f650d6eaf2320e55f4d80a06e0dd1675"><code>34a36ad</code></a> (database) - charts: Nn secret is generated during off-cluster</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/064ccf462a1bd2fe513809c39919fc1ccaba7801"><code>064ccf4</code></a> (database) - database: create database</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/9228992327543f008bf4158be8b8cd1777c3ba90"><code>9228992</code></a> (database) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/9f7810c6dcf6323bc6f75345f4c9fc25a5e11ef6"><code>9f7810c</code></a> (database) - database: upgrade to wal-g v1.1</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/05783f4118cd7e8cc80e41c20656f5b16961fa3d"><code>05783f4</code></a> (fluentd) - fluentd:replace the special words</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/0739809ba68d12ef8940f0f6addcfea7353885f5"><code>0739809</code></a> (fluentd) - influxdb:replace monitor-influx with influx</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/f02487cea73f20a2039fe6c1960950a3b73107b5"><code>f02487c</code></a> (fluentd) - fluentd: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/2c96cc089f7965286409cb4d710df5ab947b20b5"><code>2c96cc0</code></a> (fluentd) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/b20c429b9ace293c7add60fa350098b91285bf87"><code>b20c429</code></a> (fluentd) - charts: remove port config</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/6dd019721438cf32f2262bdb76d74da9ab5b37a3"><code>6dd0197</code></a> (fluentd) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/c5bec512a902662a8200639b3b574925c836e734"><code>c5bec51</code></a> (fluentd) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/f8524b78536b6d6cc1022e3cfa6ab61ac36fbca8"><code>f8524b7</code></a> (fluentd) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/a50878aabea91b3fbbafaf9c1f43c2eca7fe5a5c"><code>a50878a</code></a> (fluentd) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/14fe20e811ba3c8814188dcec18ed69c169c4b9d"><code>14fe20e</code></a> (fluentd) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/4a2f66070910abcc3068d0e03a8e52d1e5d2659d"><code>4a2f660</code></a> (fluentd) - k8s: k8s deprecated api migration</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/de2dd9178130101f4b0c5ed82d5e80a1ba4dd591"><code>de2dd91</code></a> (fluentd) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/a9f1944c3dcac5e8f0eb2f44d11ec81517735b8c"><code>a9f1944</code></a> (fluentd) - fluentd: upgrade to fluentd1.14</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/7cb4e954704cfa5ff37d3b95b5e9a231188f4264"><code>7cb4e95</code></a> (influxdb) - influxdb: change username to user</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/0fdc21b2a95003abd488cb05b640ec1fa1db3ff7"><code>0fdc21b</code></a> (influxdb) - influxdb: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/b2acddb8d72bd0e17fb0b543a8f98e2fa5d57735"><code>b2acddb</code></a> (influxdb) - influxdb: change default path</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/ba8891910d5ef9084f9dd9b7569d905e19f056ea"><code>ba88919</code></a> (influxdb) - influxdb: add check_env function</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/91174010ed68356d9b813b70e2def18af9ed5186"><code>9117401</code></a> (influxdb) - influxdb: modify init_influxdb has_bucket</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/092a3e6b96e9494f00e7a0627b2aa9ce1212c7d4"><code>092a3e6</code></a> (influxdb) - chart: pod not readiness</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/51de380cc83177be8bdb557894b9fd5c28ed0a3d"><code>51de380</code></a> (influxdb) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/66d76679cc55578d13274fa5bf0e653b258e57b4"><code>66d7667</code></a> (influxdb) - docker: replace influxdb base image</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/3aa30943cea519fff18c23264c99c226cfb43c80"><code>3aa3094</code></a> (influxdb) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/14b9c24f110297e5b6a632ce4ad94625f5663038"><code>14b9c24</code></a> (influxdb) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/02b4cd111c092393b0f2d3f1c1654d0476603b03"><code>02b4cd1</code></a> (logger) - logger:replace the special words</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/114b5d5392a1d82f8dc73b4b1527e742fcaf22f1"><code>114b5d5</code></a> (logger) - reids: delete the logger prefix of redis</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/639278a8f055d7872491db2240f4327d4f77114e"><code>639278a</code></a> (logger) - redis: remove logger from redis conf</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/90195e27521b44e0d43f8fb7ff9ab9a658f60676"><code>90195e2</code></a> (logger) - go: remove GOOS and GOARCH</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/31e2e27f9160e62b199c196972fe5c0097a78a22"><code>31e2e27</code></a> (logger) - logger: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/8fbd9fa7b119f112221be5fa5bdc21e3a891a6b9"><code>8fbd9fa</code></a> (logger) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/b39df2d46e0f625900f80d0103a5a35c4e7fbb0e"><code>b39df2d</code></a> (logger) - charts: remove redis\nsqd port config</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/35d6d0784df91dc1036928c83905052962a84ca0"><code>35d6d07</code></a> (logger) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/69aabf527a1bea60f6d7792a488ed074d138a27a"><code>69aabf5</code></a> (logger) - tests: remove docker link</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/e916644cd89379731f5a9990044e3f64d570b6dc"><code>e916644</code></a> (logger) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/d6872b7cfbd30d0be087270b581a0730961f4b8b"><code>d6872b7</code></a> (logger) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/37801daabfe98292c54ed2902aeb120069448b64"><code>37801da</code></a> (logger) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/cfb4b38897136e5c1b942433b52944cdccc9b195"><code>cfb4b38</code></a> (logger) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/8bda3bf9906424c9be8661ab0d6850ae6e3352ea"><code>8bda3bf</code></a> (logger) - go: bump go mod</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/e13ebfcd5fc940393e1d398623650bfcd31c24de"><code>e13ebfc</code></a> (logger) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/38e6d8d592ad42a176d08f0d7edbe38e55b39b72"><code>38e6d8d</code></a> (minio) - minio:replace the special words</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/d6925ddec232dd3b6187414f4a11327330baa95a"><code>d6925dd</code></a> (minio) - minio: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/d56bc39ba487c24e89a47e6c63375342ba3c3552"><code>d56bc39</code></a> (minio) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/e4696cc243711c53a1fe16051cd80209c8a3d281"><code>e4696cc</code></a> (minio) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/70c5c7988a513b5a39b92e442b0f9052d1507f67"><code>70c5c79</code></a> (minio) - minio: use latest version</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/773cf6c47a4ab539dcac29084980953bdd0e9e04"><code>773cf6c</code></a> (minio) - Makefile: remove DEV_REGISTRY ?=</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/5ce5bc696e7522107139cccfec37c6dc4b759059"><code>5ce5bc6</code></a> (minio) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/5da8be3ca9345e7a6c87ad61bf104b7345523691"><code>5da8be3</code></a> (minio) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/c1f0611fed4e73a5109f1d15901721fa968d6c34"><code>c1f0611</code></a> (minio) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/b73f7927c34fca39605e13930a06fad829658e7b"><code>b73f792</code></a> (minio) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/79d1c935ee59bf45af52a1265aa87e2ef3233f40"><code>79d1c93</code></a> (minio) - go: bump go mod</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/c448899edbaacf8d54cdbad53561733069c1020b"><code>c448899</code></a> (minio) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/15ee49ef85be819d3f6eed5dde4551ffa31f5fae"><code>15ee49e</code></a> (minio) - minio: migrate deprecated warning</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/9968a1a2095fecda1d3ba3fbd2263e83494d716e"><code>9968a1a</code></a> (minio) - minio: upgrade to golang1.7</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/14fedd29ba64e02c05b6cd5fb06bd261bf9f367b"><code>14fedd2</code></a> (monitor) - monitor:replace the special works</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/52c431ad1701cc15e03d55cbc436c5f4f7472522"><code>52c431a</code></a> (monitor) - reids: delete the logger prefix of redis</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/2c95b47a1f714a421be5860a78dd94c23ddcfdf3"><code>2c95b47</code></a> (monitor) - redis: remove logger from redis conf</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/da9bc5605eb4a118bca92fdff3cc49c2f208c040"><code>da9bc56</code></a> (monitor) - monitor:remove influxdb</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/53f47b9a3b8dec717d049b9be3961e4efd446381"><code>53f47b9</code></a> (monitor) - grafana: use grafana docker image</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/5bdb188a7255e845cda8a49806053f12032d196d"><code>5bdb188</code></a> (monitor) - grafana: use grafana docker image</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/c0586dda982c857e61b89964f34b57028cfaa29c"><code>c0586dd</code></a> (monitor) - monitor: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/87d02b6c80ef04c1170e848e9febdb723c9503c3"><code>87d02b6</code></a> (monitor) - charts: add nodes and persistentvolumes rule</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/1b5598fb479f85808bb33ef29b8cd21ab9d40bc6"><code>1b5598f</code></a> (monitor) - monitor: modify grafana dashboard with FLUX and pretty config.toml</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/bcbc0d5b3ef1b16a9e4b22208f5c628156a556cc"><code>bcbc0d5</code></a> (monitor) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/9418c9e13b4fb20f4174ee965044cf30ca12ae38"><code>9418c9e</code></a> (monitor) - monitor: fix upload dashboard error and modify INFLUXDB input</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/589f29a84eeab3f9fbc1cce1e49a601938a32987"><code>589f29a</code></a> (monitor) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/f776f8a650fd4c0c1e5f21dc9aa38ad36ca5be72"><code>f776f8a</code></a> (monitor) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/6ca306092ca874c666066dffce4f3f8fad11bbcb"><code>6ca3060</code></a> (monitor) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/6a9ffb24264ff8d7e5e9407f811e5b38b9e20a38"><code>6a9ffb2</code></a> (monitor) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/45e41ed8d104205a708fd82327e0fa3f3ac3d97e"><code>45e41ed</code></a> (monitor) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/654d407bea3cc3e686416cb2f6e1224990bab741"><code>654d407</code></a> (monitor) - k8s: k8s deprecated api migration</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/41e9b9c3c1b371ea815cd480e33c53779c2211a7"><code>41e9b9c</code></a> (monitor) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/99c10d38471587b09fb51ee65c8e602e443b44e7"><code>99c10d3</code></a> (monitor) - charts: update cert-manager api version</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/9bf83c40a846784e8375db884a2d417073324408"><code>9bf83c4</code></a> (monitor) - oauth: user oauth passport</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/a128f6d5f97fc060a80a2384f4a2dd2dc916dd12"><code>a128f6d</code></a> (monitor) - chart: change certManagerEnabled to boolean type</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/8f897fe306e15f4d528d0665171d634f0d9b93c4"><code>8f897fe</code></a> (monitor) - chart: set the domain depends certManagerEnabled</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/ba6d793c6110993b227246b8bf0bb861fc468975"><code>ba6d793</code></a> (nsqd) - README:update travis build status</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/49879c4baba2a6824b9f32bb2734aec21debefb0"><code>49879c4</code></a> (nsqd) - nsqd: minimum git clone code</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/c5e26805e49bd1be880fd4857b435359a0840992"><code>c5e2680</code></a> (nsqd) - nsqd: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/21dd17b886aad7e673fdb72fe4ccce3d9786a623"><code>21dd17b</code></a> (nsqd) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/7d86b3cbb2452da48abcc99f165dfa8954f103bb"><code>7d86b3c</code></a> (nsqd) - charts: remove port config</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/c073d952af18ffd83b6f86ce7a55140b36029a63"><code>c073d95</code></a> (nsqd) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/55c297ca70952986cb6a971593bbe0e64adea029"><code>55c297c</code></a> (nsqd) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/165c2aef05413585886651299c11dfb741469b0c"><code>165c2ae</code></a> (nsqd) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/9c6a1f8eb363e1d09eaef29c97eff7b60053103b"><code>9c6a1f8</code></a> (nsqd) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/92830984c4627f1a034f8fcfcb490a09576aa960"><code>9283098</code></a> (nsqd) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/46acf8a349c2d8462ee2ec0b592bde8a26e5f459"><code>46acf8a</code></a> (nsqd) - k8s: k8s deprecated api migration</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/43caf8058c5c9b129744c1a191f234d3b44c793f"><code>43caf80</code></a> (nsqd) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/689747119e18e2f1151404beb1729cad9d6ea5f6"><code>6897471</code></a> (nsqd) - nsqd: use official image</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/297bc05baf835ffe4d103bb6cb7613aa1286be68"><code>297bc05</code></a> (redis) - redis:replace the special words</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/f5f8b5e75b99f11e20a1b3210e4c4a42e342df92"><code>f5f8b5e</code></a> (redis) - reids: delete the logger prefix of redis</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/af7b657e76bbc1201391fe3915e081bd220b96a8"><code>af7b657</code></a> (redis) - redis: change logger-redis to redis</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/8dca154e5ae4a38b42e1eb6e16e01f3e78d5fee1"><code>8dca154</code></a> (redis) - redis: remove logger from redis conf</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/eaeda2d2650c61768092ea7f5846733328e47dc6"><code>eaeda2d</code></a> (redis) - redis: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/53c6358e7fbaf02ec15d0a01afa5e02769e3bfb4"><code>53c6358</code></a> (redis) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/ae37416efe8b6fcfdfabf2d444bd241e7128d889"><code>ae37416</code></a> (redis) - charts: remove port config</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/e985656354c17c1221d8ec35007710e0b9d4f6a3"><code>e985656</code></a> (redis) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/423336a645aa3b5091b76e88e58b501357cc733c"><code>423336a</code></a> (redis) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/be64ab4c2fd6e1edd33ca8c5a4458c74bf6fa372"><code>be64ab4</code></a> (redis) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/3bec735f6849b5649c5a2416e8fdb76fb6c780d7"><code>3bec735</code></a> (redis) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/4f934f6ee96925b70463c660416706eafc21fc3e"><code>4f934f6</code></a> (redis) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/359b8780f014c1627a1290e32231cd53caf6f762"><code>359b878</code></a> (redis) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/83b8ac299c215de85e85485c6c0546bc25a37ab1"><code>83b8ac2</code></a> (registry) - workflow:replace the special words</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/869b280b55534a7fbd2dfc9052044cb487d97730"><code>869b280</code></a> (registry) - registry: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/999c1e936026b79dc0462da166998f3fa4cebec3"><code>999c1e9</code></a> (registry) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/5652da941334dfdddbe2636d974e9d687b0d912d"><code>5652da9</code></a> (registry) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/cc8c6c2bc077bad277232d25bc536416dfa6c244"><code>cc8c6c2</code></a> (registry) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/c7bdbd0e67e6bcd35423db7d05aca99a511054ed"><code>c7bdbd0</code></a> (registry) - CICD: pretty .drone.yaml format</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/5c55a38592dfd1a7356992018f15f022c02fdfc6"><code>5c55a38</code></a> (registry) - test: use add-host replace link</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/f8866f3e6b4f94e15815e5f79b2adbebe3fd1ed1"><code>f8866f3</code></a> (registry) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/6c8292f9c65b38816fad79bf3f49ff54ad8760dc"><code>6c8292f</code></a> (registry) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/1d50f2ce75f708fd3b07b0c5d5dff2f4bdb8adc7"><code>1d50f2c</code></a> (registry) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/efbca6d2c99e2b170e945f050afa8fb139398a49"><code>efbca6d</code></a> (registry) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/2eafc592dc68c529a8a3a8077ef9d48916718079"><code>2eafc59</code></a> (registry-proxy) - registry-proxy: update nginx</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/071bd86ae3bef755f47e22aad54762a7f1e4c0f1"><code>071bd86</code></a> (registry-proxy) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/c72db9618ee6a73655b4b2c5e940ee9fc9447380"><code>c72db96</code></a> (registry-proxy) - registry-proxy: change travis icon url</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/63ffb920f62b692071fcbf825cbac55bbebe6598"><code>63ffb92</code></a> (registry-proxy) - registry-proxy:replace the special works</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/1d904a61de6cc38bfb071a965de09f5dea0d9996"><code>1d904a6</code></a> (registry-proxy) - registry-proxy: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/c8200b1f6f573dba0edb19509fdb56a8357828c7"><code>c8200b1</code></a> (registry-proxy) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/d3fa939d910c7b0c707f191b174d1fce89e4cdb6"><code>d3fa939</code></a> (registry-proxy) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/5a8b353fa642dbef5929d372ef4ce39657bd40fb"><code>5a8b353</code></a> (registry-proxy) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/703d05a7fa07fc8d5b4c5c4ca0fed8a1ee156536"><code>703d05a</code></a> (registry-proxy) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/aa71db189c6b489347d8f723bdf881bc0b0abf67"><code>aa71db1</code></a> (registry-proxy) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/710c1260065431acf427bdf7d6d6319024598852"><code>710c126</code></a> (registry-proxy) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/2dcc5e6c4b469cb74b56c8c1f0b69d1d5c58291a"><code>2dcc5e6</code></a> (registry-proxy) - chars: change org to imageTag</li> +</ul> + + + + + + Blog: Drycc Workflow v1.4.0 + /blog/2021/10/06/drycc-workflow-v1.4.0/ + Wed, 06 Oct 2021 00:00:00 +0000 + + /blog/2021/10/06/drycc-workflow-v1.4.0/ + + + + <p>These release notes for Drycc Workflow v1.3.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.4.0, please refer to the following change summary.</p> +<h2 id="workflow--v130---v140">Workflow ## v1.3.0 -&gt; v1.4.0<a class="td-heading-self-link" href="#workflow--v130---v140" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>builder v1.1.0 -&gt; v1.2.0</li> +<li>slugbuilder v1.1.1 -&gt; v1.2.0</li> +<li>dockerbuilder v1.1.1 -&gt; v1.1.2</li> +<li>controller v1.2.1 -&gt; v1.3.0</li> +<li>slugrunner v1.1.1 -&gt; v1.1.2</li> +<li>database v1.0.1 -&gt; v1.0.2</li> +<li>fluentd v1.0.1 -&gt; v1.1.0</li> +<li>redis v1.0.0 -&gt; v1.1.0</li> +<li>logger v1.0.0 -&gt; v1.1.0</li> +<li>minio v1.0.1 -&gt; v1.1.0</li> +<li>monitor v1.0.1 -&gt; v1.1.0</li> +<li>nsqd v1.0.0 -&gt; v1.1.0</li> +<li>registry v1.0.2 -&gt; v1.0.3</li> +<li>registry-proxy v1.0.0 -&gt; v1.0.1</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/fc7d93f718019cfae02b04c745470b4975c91a84"><code>fc7d93f</code></a> (builder) - builder: use go-dev</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/0c2159e4a44f0c3f635dcee1b95afdd741d1935c"><code>0c2159e</code></a> (builder) - builder: fmt code and add create_bucket script</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1b88340205ac77e84ebba7a42215d7d3d40578a0"><code>1b88340</code></a> (controller) - controller: remove deprecated api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a92fdebab64716e4194653a9a17f1c00f70c882d"><code>a92fdeb</code></a> (controller) - routable: ingress support routable</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1e3eab3602538f266305a78c9244be466d685c68"><code>1e3eab3</code></a> (controller) - maintenance: add maintenance support for ingress</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/56b9dd0691c904bd75df928bace98830879eb31d"><code>56b9dd0</code></a> (controller) - crt: support containerd-ctr</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5fc3b46b2acd67af89590f1c7dd85fbfa5e989a6"><code>5fc3b46</code></a> (controller) - controller: add ephemeral-storage restriction</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d677e52c288431517de9ae4bddaaadbd1c8b976c"><code>d677e52</code></a> (controller) - controller: add a volume command</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5f1323a837c71127bb99fd8631934c5bd0cab2a7"><code>5f1323a</code></a> (controller) - controller:drycc run cmd add &ndash;mount para</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/74c36a51eef46ea1c110ee53472be632079ce5e1"><code>74c36a5</code></a> (controller) - tasks: add distributed async task</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/139c3ca9d01d7188c1a499dfffad7b7697e5fd0f"><code>139c3ca</code></a> (controller) - tasks: change nsq reader to async</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f237d74ca6344a5929c9b5089dae07a38c13753b"><code>f237d74</code></a> (controller) - controller:add drycc resource cmd</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/41b46d0653d39d0bdfb42907f7a0b9863bc20992"><code>41b46d0</code></a> (controller) - controller:add drycc resource cmd improvement</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c26f7d82e8fa6fcf4b45ab16fcb0298cb2880f6a"><code>c26f7d8</code></a> (controller) - controller: add LimitRanges support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/45b5d1b904abe94819c3dd306117dcd4e09123ed"><code>45b5d1b</code></a> (controller) - users: add users status api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4e16f9b86ac24b4c62d7d6fddb33278d1880dfa7"><code>4e16f9b</code></a> (controller) - ps:add ps:stop/start command</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c659fa9e058620fd8ce0ba4fcfc48898f1219f2c"><code>c659fa9</code></a> (controller) - k8s: add k8s cluster domain</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/31a625d71733b47944876ac3fb58fe55cd9b746b"><code>31a625d</code></a> (controller) - ps:add ps:stop/start command</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/00a779a5dbb60a33b621fae13b30a24e39ac55f3"><code>00a779a</code></a> (fluentd) - fluentd: support containerd log format</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/f3f1bd42697f08340b6b6f5fbe161c5b6fbb31b6"><code>f3f1bd4</code></a> (fluentd) - nsqd: add stateless nsqd cluster support</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/db7147c0e7556a655e185c6f00419f99aff4ed29"><code>db7147c</code></a> (fluentd) - mirrors: delete aliyun mirrors</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/689c12eed60f53e1afbbcede91a5955360183fa7"><code>689c12e</code></a> (logger) - nsqd: add stateless nsqd cluster support</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/78ccc5de7718b8f6fb1caf701d1b4ef72fc64362"><code>78ccc5d</code></a> (logger) - redis: add redis client cluster support</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/9843f2cf9d1d03511296bf7731b59d547bc10387"><code>9843f2c</code></a> (logger) - k8s: add k8s cluster domain</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/6ba122e8b6cbdf7b73785d21961056e6b9fc91ee"><code>6ba122e</code></a> (minio) - minio: add pvc support</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/69735500c483f9144f461a2b8a3444e51ddd4dc4"><code>6973550</code></a> (monitor) - monitor: add ingress for monitor</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/cd733053287efbd12c29217cd47c6345c39457ce"><code>cd73305</code></a> (monitor) - charts: add volumeName support</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/4769fe9e8d14bdbdca9447f9df23c67c09db2a45"><code>4769fe9</code></a> (monitor) - nsqd: add stateless nsqd cluster support</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/87806df02cd84fc5feec304e9bc6e32996396b80"><code>87806df</code></a> (monitor) - k8s: add k8s cluster domain</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/4db40c4f129115019ef41c14df56a2d0092e9da1"><code>4db40c4</code></a> (nsqd) - nsqd: add stateless nsqd cluster support</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/b6f3d4fe0f6bc8d3467fdebf21374bed378edf9e"><code>b6f3d4f</code></a> (nsqd) - nsqd: add stateless nsqd cluster support</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/74b85bb9efdcba88a25a2734d512d07ef8068032"><code>74b85bb</code></a> (redis) - redis: change redis to statefulset</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/ff98b5018610d0e2be0ec5c03c7a11232199811a"><code>ff98b50</code></a> (slugbuilder) - slugbuilder: delete build hook</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/b201c2ff207eddac7327f75d698a77e89d4125a1"><code>b201c2f</code></a> (slugbuilder) - buildpacks: use drycc buildpacks</li> +</ul> +<h4 id="fixes">Fixes<a class="td-heading-self-link" href="#fixes" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/0ec042db3c8a4db39088ffe381f518abdb55287d"><code>0ec042d</code></a> (builder) - test: fix test case error</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/4fb113b7351f9f02612b3e14b4d0787b77abb3b2"><code>4fb113b</code></a> (builder) - build: base image replace by alpine</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/443df48c699846c176c1e4a12b5bb42abe790633"><code>443df48</code></a> (builder) - minio: fix not bucket error</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/3dab5b0ce203bcc03891122aca73da5c7342a40b"><code>3dab5b0</code></a> (builder) - minio: create bucket error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/734fca6f371bf73d79d35f1fcdc04ff66cb196fc"><code>734fca6</code></a> (controller) - autoscale: Fix for autoscale on k8s-1.9+ without breaking manual scaling</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a7dcd1000965fae97bad4dc4b908741f856e2d2b"><code>a7dcd10</code></a> (controller) - controller: test pass</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/93f0f2eaa361386bf7775edcbc27c143a71f0dc7"><code>93f0f2e</code></a> (controller) - controller: fix migrations error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4724375b4319e1cbfa1a587e0e856d9eb9b6ac00"><code>4724375</code></a> (controller) - controller: fix test error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7bacf298db4e431c58e86cef028f99fffb5b349e"><code>7bacf29</code></a> (controller) - charts: fix clusterrole</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/90957f727cc883084ff1a81deaada4d62419f0a9"><code>90957f7</code></a> (controller) - pod: sort events error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/440b13edb6e5b9c9fa69f8b6c72f10329a4087d2"><code>440b13e</code></a> (controller) - controller: review table structure</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0a470a6ecffa1fa9d5ef2bb0a71b00ddefb84a1f"><code>0a470a6</code></a> (controller) - controller: bump tornado 5.1.1</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e39218b2216591b7d412baeee5c8e85a7209996d"><code>e39218b</code></a> (controller) - pynsq: no current event loop in thread</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1d8630e250c65051df90b22f023f0f95034f0cc1"><code>1d8630e</code></a> (controller) - tests: fix test_task.py run error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1ff120213ee452a570a1e23dff85ab3032704a30"><code>1ff1202</code></a> (controller) - controller: fix test case</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d8c0da319db0b559eb8c8b0c28280d7e70613da2"><code>d8c0da3</code></a> (controller) - settings: fix env name</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/6d8fd3605f54c5a3c7ce0d4e5164f772fa22a8ec"><code>6d8fd36</code></a> (database) - 003_restore_from_backup.sh: ignore script exit 1</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/e0394a9a6aa44a066df18b8ad3ddd21e9c9fa1c2"><code>e0394a9</code></a> (database) - minio: fix not bucket error</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/f35f2525602c90dbe397f56005206ed6abf6eb39"><code>f35f252</code></a> (database) - mc: fix create_bucket error</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/74d68865fb7502d04e74418cc2b6ef8316c45778"><code>74d6886</code></a> (database) - postgres: recovery mode not run</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/e50d0c105151dac43b2bbc5f4e316a47dd55e925"><code>e50d0c1</code></a> (dockerbuilder) - caddy: fix caddy not start</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/f3bec7a8a63c586d19caa777b3fa4a7d0de112c7"><code>f3bec7a</code></a> (fluentd) - influxdb: fix influxdb host and port</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/bc19f27d1567281c5c1ae10b9072c9aad33e2013"><code>bc19f27</code></a> (fluentd) - charts: skipped value for daemon_environment: Not a table</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/338d6237ed76464fc47a6ca3d6f3d34927af6aa2"><code>338d623</code></a> (logger) - logger: logger not run in alpine</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/77883026f33f38aa9d01dd4d88298d162a9050e1"><code>7788302</code></a> (minio) - minio: bump minio version</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/619eed0426591646d5fa9e72b77391d6ac817946"><code>619eed0</code></a> (minio) - fix: use go mod replace dep</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/3b42122703b8bfa3203c8115b8d673f2081d2559"><code>3b42122</code></a> (monitor) - monitor: fix host error</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/67998eff2439c406db048a868f61ae9861268449"><code>67998ef</code></a> (monitor) - influxdb: replace drycc-monitor-influxapi to drycc-monitor-influx-api</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/2cc361cf42754562ffa5b6e7c2e14c065e2cd0f1"><code>2cc361c</code></a> (registry) - registry: fix test case</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/548297a7b97e8f28498fa51b50f9232d8c78053b"><code>548297a</code></a> (registry) - minio: fix not bucket error</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/5412ddb1b956fad53d0c59a87c2158b6e014b05f"><code>5412ddb</code></a> (registry) - minio: create bucket error</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/d0d629e5a58d7e91421f2cd344029474e5c630d4"><code>d0d629e</code></a> (slugbuilder) - slugbuilder:fix normalize_storage path</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/d76ecbe4d4d05aeb23a566b2d3c929cca4e63e63"><code>d76ecbe</code></a> (slugbuilder) - slugbuilder: use v3 api</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/c505e182006dd8a734efa14fc851f15340d05929"><code>c505e18</code></a> (slugbuilder) - shellcheck: SC2039</li> +</ul> +<h4 id="style">Style<a class="td-heading-self-link" href="#style" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/c893a1771550c7728f697216b17e38da0f18ec3f"><code>c893a17</code></a> (builder) - builder: fmt code</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/bba5795cd3f3f36bf2a4b6d37661254143f60328"><code>bba5795</code></a> (controller) - controller: format code</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d36082b6f0fbf46487e3fdc6aff0e7866f6462a7"><code>d36082b</code></a> (controller) - controller: fix pep8</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/66026f2f2110fca58f783b8844d9c5b7a794d1f4"><code>66026f2</code></a> (controller) - resource: standardize the naming of resource</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/03d7e2c8bfb120627ec13c4aa37ff7bc3074e88e"><code>03d7e2c</code></a> (controller) - servicecatalog: change servicecatalog to svcat</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/49dbb6d99655dd398978b273ce3fb29051a56cb7"><code>49dbb6d</code></a> (controller) - controller: flake8 upgrade</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/cbfc108b4f209dfbd088f260fe84399bdda5d502"><code>cbfc108</code></a> (monitor) - monitor: format charts and dashboard</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/ee85954d57ae9d19e6e2790090a6fcf1413e8b2d"><code>ee85954</code></a> (slugbuilder) - slugbuilder: use shellcheck</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/3afed2e3592173fcc3522d71dfdbdd45a8b70a01"><code>3afed2e</code></a> (slugbuilder) - docker: simplify dockerfile</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/36b7f688afcb9c8c81016fbbc7b8a3da9537911d"><code>36b7f68</code></a> (slugrunner) - docker: simplify dockerfile</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/61bb0ef367bdabdb3072473e1d639d723b2a8f08"><code>61bb0ef</code></a> (builder) - aws: upgrade aws sdk version</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/0f2e074b748b9f7067cadac63fb83684bc582272"><code>0f2e074</code></a> (builder) - chore: use go mode replace dep</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/e9a2219c2d1c9303cd1a60d2e9bdc9e676f07348"><code>e9a2219</code></a> (builder) - builder: delete glide up</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/bb8c518645bcee82e6ab7782496799b6b82b9fd4"><code>bb8c518</code></a> (builder) - registry: del quay.io</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/fa6d02f54af2daf51c1b08b4b7ad6a3be2425b45"><code>fa6d02f</code></a> (builder) - builder: upgrade go.sum</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/9d61e8da908fae47c33a77c8547e80d1d6d3d812"><code>9d61e8d</code></a> (builder) - build: upgrade go.mod</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/d763a984a800366eb2f6384fbf23c596342720fb"><code>d763a98</code></a> (builder) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/d1bc1aae69b9b16859e11bfa18b1fa2b602bc686"><code>d1bc1aa</code></a> (builder) - pkg: upgrade to new drycc/pkg</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/02b1e98a3b208be80326adb85307663ef931adf6"><code>02b1e98</code></a> (builder) - builder: update go mod</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/8e17d6579e022ce3574ee7582a1f48fc88bb5e95"><code>8e17d65</code></a> (builder) - builder: change alpine repositories</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/f32b723ef49069ffeee6f2419e87b5450617df1e"><code>f32b723</code></a> (builder) - mirrors: delete aliyun mirrors</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/e33dc612d4910ad3b0e56fbb797a7d1dd609bf6d"><code>e33dc61</code></a> (builder) - minio: use bin mc replace docker images</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/3ab4f1c4a587f58230c1c91670831a0927dc6dfb"><code>3ab4f1c</code></a> (builder) - builder: update controller-sdk-go</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/b2adfac62d24626a8dc5f2cf4d011c4610170e3a"><code>b2adfac</code></a> (builder) - heroku: remove heroku-16 support</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/f429ac8fa76a4b59ed36ab9b1dc2bfee19d0be3e"><code>f429ac8</code></a> (builder) - builder: set GIT_LOCK_TIMEOUT to 30 minutes</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/7197c833a68b1168ee4eba0ac16a6fb569f2066e"><code>7197c83</code></a> (builder) - go.mod:upgrade require pkg controller-sdk-go</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5f3e22dc87a55d9bd8fd3299f37be26b19c2350f"><code>5f3e22d</code></a> (controller) - deps: bump django from 1.11.21 to 1.11.22 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1db645af644946d8694234b0b7e1f22e762c5424"><code>1db645a</code></a> (controller) - deps: bump django from 1.11.22 to 1.11.23 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/fbe80677bc8fe7d19772a0bc002fb541106ef75d"><code>fbe8067</code></a> (controller) - deps: bump django from 1.11.23 to 1.11.29 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/537d667d5fd896eec054adda6185042d6492cbd1"><code>537d667</code></a> (controller) - registry: del quay.io</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a23c65b14ba90a60a6d57aa56a12f201ad7ba33b"><code>a23c65b</code></a> (controller) - deps: update all deps to the latest version</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/546337eced482db0b8e879ce8caaa322503f5f52"><code>546337e</code></a> (controller) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/06023f8b84897c4aeaa14fc45c6d35c16eeed1d7"><code>06023f8</code></a> (controller) - workflow-manager: del workflow-manager</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/bba573609e25e87875ca40ccdef6e4dd4c8cfd1a"><code>bba5736</code></a> (controller) - controller: change cluster-issuer location</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/6c436612923a18486982c268d1e23bbd42a3f9a7"><code>6c43661</code></a> (controller) - Certificatechange cluster-issuer location</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/39a47288e3e0bcf7bfa55768c6759ac94c416c33"><code>39a4728</code></a> (controller) - controller:change cluster-issuer location del controller-cluster-issuer.yaml</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9e96d3f9ccda7f8934628444e72e4959bafde91a"><code>9e96d3f</code></a> (controller) - Certificate:upgrade version cert-manager.io/v1alpha2</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8e68049a870b2277663bd0dc09430baa343a5881"><code>8e68049</code></a> (controller) - docker: use INDEX_URL replace index.docker.io</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8fda20583558fefcd239d5e2d6ae09c5c5f881a7"><code>8fda205</code></a> (controller) - cert_manager: change cert_manager_enabled to global</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/6fefb6d00f8909d7269a9171af9db7ba016533c4"><code>6fefb6d</code></a> (controller) - charts: change platform_domain to global</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/064b2ad886b7782598a7f68925d5275ebd88bfd4"><code>064b2ad</code></a> (controller) - maintenance: remove maintenance support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b8797c98a1b2e01f835169ca7493fff508a3cf95"><code>b8797c9</code></a> (controller) - workflow: remove namespace</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1b20d7632a8ca8e4e9f0f6b1c98826af1d846008"><code>1b20d76</code></a> (controller) - quota: add kube quota config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d780075077cf9f9843ecf79ae36e569eec59cd3d"><code>d780075</code></a> (controller) - pod: add pod default resources support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3d72c0817b582f050321396240bd4a6bad3bfb16"><code>3d72c08</code></a> (controller) - rename: rename ingress name</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0aa6ab9cd277231420b1404b922601debe0aa89b"><code>0aa6ab9</code></a> (controller) - mirrors: delete aliyun mirrors</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7533a65e78efd06ebe809712791c5399b85efcba"><code>7533a65</code></a> (controller) - heroku: remove heroku-16 support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e5a885d676f052ffdee6bc74e2fe0cffb85a1f86"><code>e5a885d</code></a> (controller) - controller:check mount volume path</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9014e74b5c0312014aa9d20cf9d6aff128f8022f"><code>9014e74</code></a> (controller) - test: optimization Dockerfile.test</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0b6ebb2f0e18f7e97ed2bb7b2c6008e3be7248f2"><code>0b6ebb2</code></a> (controller) - tasks: change apply_async parameters</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/835f009573d5643d271b6e558793b1c9ae1463da"><code>835f009</code></a> (controller) - wsgi: add tornado 6 support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/67a4ad7cbd50cd9de1214e8d4be27196e8077367"><code>67a4ad7</code></a> (controller) - utils: use threads replace asyncio</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a28949b093e9f4d73c798f24e41d1eaff0cc1cc2"><code>a28949b</code></a> (controller) - ldap: add AUTH_LDAP_USER_FLAGS_BY_GROUP</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a903209c062f3e275f97bc18dc1d2b9a17e1a826"><code>a903209</code></a> (controller) - charts: add custom controller environment variables support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e0e783ecb5e87bf68e83411cfd92f54916aa9931"><code>e0e783e</code></a> (controller) - ldap: change filter style</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d7608251c2f8938b8f5ee1edd0c7d0f371931826"><code>d760825</code></a> (controller) - scheduler: remove debug log</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a25928ee84e75a84c13c5402cc351e1ec6e3f151"><code>a25928e</code></a> (controller) - wsgi: remove a wsgi.py file</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7b2696e3ea066b59395b63d97fbad5a472d49b5b"><code>7b2696e</code></a> (controller) - log: disable nsq.client info log</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8d5c07b49ba4220ba7946a8bef1a22b1e8d78e47"><code>8d5c07b</code></a> (controller) - charts: add default environment</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/025f4a2ea96c883df3c35b961aaac2bdd9a5b4ea"><code>025f4a2</code></a> (controller) - controller: change quota name</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ebda60ed125f49524169cb320c79c37d5adc2e6c"><code>ebda60e</code></a> (controller) - controller: review pvc code</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8832ba952281c2a06dc98dfc6726e7f9e9207d81"><code>8832ba9</code></a> (controller) - controller: change status\binding model type and mount path check container_types</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7148d04c5f1223f06747fae9a33cb3787159ce9e"><code>7148d04</code></a> (controller) - controller: add overcommit cpu and ram support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4d2087cc9c783e5c2722fd446b64c7263b783001"><code>4d2087c</code></a> (controller) - limits: modify limits unit verification</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/af36970d90b9a8d95857052ab1c97b7727a01976"><code>af36970</code></a> (controller) - api: check cpu/memory range for api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/329355b6cdde8a382a5fe271f764cca747cd9444"><code>329355b</code></a> (controller) - volumes: modify the volume size</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9dfee0919449d13e11ec3cfe50a187ecd5de07b2"><code>9dfee09</code></a> (controller) - LimitRanges: modify the default limits</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5205bca582cd292fcfa7c0abb1bcc98c3dce05f1"><code>5205bca</code></a> (controller) - controller: improve the details of certificate</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/7ebecdfdca2de4936b67bc542053305f098db6d6"><code>7ebecdf</code></a> (database) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/6415e2ccacef3af313b4df2e7d0924797217238f"><code>6415e2c</code></a> (database) - postgres: upgrade to pg13</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/12e68062d48938c8619f94c30741af6fd2fee8e9"><code>12e6806</code></a> (database) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/d294509c192eb7e2f6f11aedad8aefff83fb8532"><code>d294509</code></a> (database) - minio: use canary minio test</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/1bad02e1768d4d54df61f7df3e54c81bd68e6c52"><code>1bad02e</code></a> (database) - mirrors: delete aliyun mirrors</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/d51420bbde24cada100f764288c9bd165dbc9f31"><code>d51420b</code></a> (database) - minio: use bin mc replace docker images</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/4133d05d8edec1f1ba2b995354dc98ae863a1da7"><code>4133d05</code></a> (dockerbuilder) - dockerbuilder: update caddy and kaniko</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/6b4dd18637b3a81a64c1be34a6d73832095c638d"><code>6b4dd18</code></a> (dockerbuilder) - minio: use bin mc replace docker images</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/6df9b7c0bc4a22bca7ed2588a070868680382f68"><code>6df9b7c</code></a> (fluentd) - deps-dev: update rake requirement from ~&gt; 10.0 to ~&gt; 12.3</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/c2490f84d991ddfc588bded7e6afe9706e82f090"><code>c2490f8</code></a> (fluentd) - fluentd: upgrade fluentd</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/be4a56a12ce0c8a812b8922630122225532ac3fa"><code>be4a56a</code></a> (fluentd) - fluentd: add Gemfile.lock</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/2237f755e0123eb4138289648b5a0ee64bbd4183"><code>2237f75</code></a> (fluentd) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/c5740650bcb218c59676733c20f5765ae4cb905d"><code>c574065</code></a> (fluentd) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/52b8084cbaa5d0b8c8ca7014f94b596dca911708"><code>52b8084</code></a> (fluentd) - router: delete obsolete router code</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/3b3ccebeced1c4257c0c3ed1a70b7f18a8c6aa85"><code>3b3cceb</code></a> (fluentd) - fluentd: remove manifests dir</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/25c6702f8c1e1c5916b0544ccda64eced3451448"><code>25c6702</code></a> (fluentd) - nsqd: change var name</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/bd571be4178f69cb4bd7ee233440ca889ec5c601"><code>bd571be</code></a> (fluentd) - nsqd: change DRYCC_NSQD_ADDRESSES to DRYCC_NSQD_ADDRS</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/72aa4e6b7fe5cb5ef784f894429e3f1e177e5c82"><code>72aa4e6</code></a> (fluentd) - influxdb: change influxdb service name</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/bd61903dd01aa61374a5f527f8ee85bc7820c042"><code>bd61903</code></a> (logger) - logger: use go mod replace dep</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/69c63a1bd602c9a5a68ef3b93d43b2dca161d495"><code>69c63a1</code></a> (logger) - logger: update go.mod</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/3aa9cd715568b46efa26025f25c73ce897436b4f"><code>3aa9cd7</code></a> (logger) - registry: del quay.io</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/f05849639ef8e34bacf9a55965ab3d7297df4cf7"><code>f058496</code></a> (logger) - nsqd: change var name</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/6d9787cebb2e992de9743ac0544201b012b21094"><code>6d9787c</code></a> (logger) - nsqd: change DRYCC_NSQD_ADDRESSES to DRYCC_NSQD_ADDRS</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/85ed307592a38ae80186f59bf31e504124013e07"><code>85ed307</code></a> (logger) - logger: standard naming</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/d88e7b65131e2fdaa7d4164a4d66793d89cc384d"><code>d88e7b6</code></a> (minio) - minio: update minio api to v7</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/43715d2dd30bc15f5564124e0e5e444ce7ca63c2"><code>43715d2</code></a> (minio) - minio: upgrade minio</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/0e1239b358ce3bde11a1401634f519b7e1c38156"><code>0e1239b</code></a> (minio) - minio: use docker.io replace quay.io</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/f7f047b506a0e6b30b7b88e916d67b1faaba8a52"><code>f7f047b</code></a> (minio) - registry: del quay.io</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/afa71289345ed311e603c8847188ccef40774869"><code>afa7128</code></a> (minio) - build: upgrade go.mod</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/aff2db5a41ae72b899f2fc9f70af96730ed16fdf"><code>aff2db5</code></a> (minio) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/4547f14617a76db897b71ef7451db92a832dff1e"><code>4547f14</code></a> (minio) - pkg: upgrade to new drycc/pkg</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/2769b85cbd316cb08da58753d6bae3946d32032a"><code>2769b85</code></a> (minio) - minio: use bin mc replace docker images</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/35dde8df07fb96c4996ef8410780da48e1170e4a"><code>35dde8d</code></a> (monitor) - monitor: update grafana influxdb telegraf</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/9e3a949734f326290dd752c636991cf2e1c962f9"><code>9e3a949</code></a> (monitor) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/6af0432fe174769e9d44c03c264ad4a9ea5cee5f"><code>6af0432</code></a> (monitor) - workflow-manager: remove workflow-manager</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/0611c07996da19eb1401278ad5cc5e46d3b1435c"><code>0611c07</code></a> (monitor) - router: delete obsolete router code</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/be048248577d97f8679863c179999ce843806c09"><code>be04824</code></a> (monitor) - cert_manager: change cert_manager_enabled to global</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/37801650414da8539390c4d7cad66f614b90ef6e"><code>3780165</code></a> (monitor) - charts: change platform_domain to global</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/50b04e15f9c3aa51751bb78250907fa22023a419"><code>50b04e1</code></a> (monitor) - influxdb: remove influxdb admin ui</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/6ab4d68b758904d12697b9a129835e6d0474cafb"><code>6ab4d68</code></a> (monitor) - influxdb: remove unuse port</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/f1510bd94e48ea41ff4c36ac2140688b5c2dde87"><code>f1510bd</code></a> (monitor) - monitor: update grafana dashboard,telegraf inputs.kubernetes</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/f36de2c251dc63b21a1fdc2c05413d6d50e9f8cb"><code>f36de2c</code></a> (monitor) - pvc: upgrade to new format</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/fc78a0a2627b51a28c730e19f2c8c1c16103829f"><code>fc78a0a</code></a> (monitor) - workflow: remove namespace</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/e85890f298dd68cf6c0e8af70d843e84da600361"><code>e85890f</code></a> (monitor) - monitor: monitoring nsqd and redis separately</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/694f6b1dc801769a8fe82b90ba26422747df6539"><code>694f6b1</code></a> (monitor) - mirrors: delete aliyun mirrors</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/4aea36a822079ba593a646683dba0e35e3e68416"><code>4aea36a</code></a> (monitor) - grafana: add ldap support for grafana</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/68fc30f0f05af759b80e07c4dcd3d2a57c7ffd6a"><code>68fc30f</code></a> (nsqd) - nsq: update nsq</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/16f32aaf7b984b24853044b6619dbe9f2b8613e2"><code>16f32aa</code></a> (nsqd) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/04db389e01f6832a6a105a73a0a02c9b7dd6623b"><code>04db389</code></a> (redis) - reids: update to redis 6</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/3f01bab0dbe89fa4094750bdb5c3f0ac503b8f00"><code>3f01bab</code></a> (redis) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/647e4bed5f617727fd50c5e0645fd27cc128461e"><code>647e4be</code></a> (registry) - registry: del quay.io</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/0bbce990d4ff5660ce79020e0bca346a0c716b3d"><code>0bbce99</code></a> (registry) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/a982b503350abfd584d33d0e088bc0a79714fb9c"><code>a982b50</code></a> (registry) - minio: use bin mc replace docker images</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/e088da3304147b568868e0546c321b57f84263b9"><code>e088da3</code></a> (registry-proxy) - ingress: renmae use_native_ingress to use_ingress</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/7e88337bbfbc73bc30bd0906f25027c5d266b1c2"><code>7e88337</code></a> (registry-proxy) - nginx: upgrade nginx to mainline</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/7204d72c00b2d7360a2d3a20833d701e303a9f62"><code>7204d72</code></a> (registry-proxy) - registry: optimizing variable naming</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/2eafc592dc68c529a8a3a8077ef9d48916718079"><code>2eafc59</code></a> (registry-proxy) - registry-proxy: update nginx</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/071bd86ae3bef755f47e22aad54762a7f1e4c0f1"><code>071bd86</code></a> (registry-proxy) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/c72db9618ee6a73655b4b2c5e940ee9fc9447380"><code>c72db96</code></a> (registry-proxy) - registry-proxy: change travis icon url</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/ca9f9623a6867f0c5f4ff973c06613deff9e5dd3"><code>ca9f962</code></a> (slugbuilder) - slugbuilder: del BUILDPACK_URL support</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/1b74dd57a7f19040577f8e55b6a9d993ef496c8d"><code>1b74dd5</code></a> (slugbuilder) - slugbuilder: add heroku-20 support</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/54d4ad2e97e9ff5c805ac985a0e5af0050677388"><code>54d4ad2</code></a> (slugbuilder) - slugbuilder: del quay.io</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/a78f37ee99cec1b7c3eb7cb7a803bf2a5ed7c45b"><code>a78f37e</code></a> (slugbuilder) - slugbuilder: add heroku-20 stack</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/94ac94ac5dd4a387c0e1aaef6638954e41e9983a"><code>94ac94a</code></a> (slugbuilder) - minio: use bin mc replace docker images</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/53b4b8b7ef9dece421a7893c5c3137ab0df8b960"><code>53b4b8b</code></a> (slugbuilder) - slugbuilder: modify stack priority</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/58e2bd28cf5fda8c618a2ba540d9e3acbf46fab5"><code>58e2bd2</code></a> (slugbuilder) - dockerfile: add WORKDIR /tmp</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/b29cd04c1769ef3481ff7c61c41a6e8722664469"><code>b29cd04</code></a> (slugbuilder) - slugbuilder: add pre_build.sh</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/9d319f60a1edd735bc5217054fe365047bd8795a"><code>9d319f6</code></a> (slugbuilder) - slugbuilder: silent mc command output</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/d1ec3c983be9934dd6b86fa51200489eb5555fa7"><code>d1ec3c9</code></a> (slugbuilder) - heroku: remove heroku-16 support</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/5048534c684b76f41ca12136cefd6e6da51ace3e"><code>5048534</code></a> (slugbuilder) - slugbuilder: use drycc stack-images</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/a1165373fc9ca369eec2715a2a49f166430cefa9"><code>a116537</code></a> (slugrunner) - slugrunner: add heroku-20 support</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/a1196bf153c21cefde2122aee5bf7dfa32ac5f0a"><code>a1196bf</code></a> (slugrunner) - slugrunner: del quay.io</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/64c96d720f4b5cdc54b66d349bac6de5567ab331"><code>64c96d7</code></a> (slugrunner) - slugrunner: add heroku-20 stack</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/cc3e2264b67f950fb888502aeea08d41d4c8ccf4"><code>cc3e226</code></a> (slugrunner) - minio: use bin mc replace docker images</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/9130bde01bcfa897ae5c4be6bc59b4a4fe7b92f3"><code>9130bde</code></a> (slugrunner) - shellcheck: shellcheck installer</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/4ea33e154ab4353de5bd5bf6afeb0157756224e8"><code>4ea33e1</code></a> (slugrunner) - slugrunner: modify stack priority</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/5514e8b393daa6f4cd8f3ebe0a619158e32945e6"><code>5514e8b</code></a> (slugrunner) - heroku: remove heroku-16 support</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/be829fb66e68bb9ccc2a1d49e1b364af09219fff"><code>be829fb</code></a> (slugrunner) - slugrunner: use drycc stack-images</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/e1e06be74f2f40740c8e72178ae6ba97233c5bbe"><code>e1e06be</code></a> (slugrunner) - slugrunner: remove Dockerfile.heroku-16</li> +</ul> + + + + + + Blog: Drycc Workflow v1.3.0 + /blog/2020/10/06/drycc-workflow-v1.3.0/ + Tue, 06 Oct 2020 00:00:00 +0000 + + /blog/2020/10/06/drycc-workflow-v1.3.0/ + + + + <p>These release notes for Drycc Workflow v1.3.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.2.0, please refer to the following change summary.</p> +<h2 id="workflow--v120---v130">Workflow ## v1.2.0 -&gt; v1.3.0<a class="td-heading-self-link" href="#workflow--v120---v130" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>builder v1.0.2 -&gt; v1.1.0</li> +<li>slugbuilder v1.1.0 -&gt; v1.1.1</li> +<li>dockerbuilder v1.1.0 -&gt; v1.1.1</li> +<li>controller v1.2.0 -&gt; v1.2.1</li> +<li>slugrunner v1.1.0 -&gt; v1.1.1</li> +<li>database v1.0.0 -&gt; v1.0.1</li> +<li>fluentd v1.0.0 -&gt; v1.0.1</li> +<li>minio v1.0.0 -&gt; v1.0.1</li> +<li>monitor v1.0.0 -&gt; v1.0.1</li> +<li>registry v1.0.1 -&gt; v1.0.2</li> +<li>workflow-manager v1.0.0 -&gt; v1.0.1</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/9c7cceb2b775850cbe30c6df7b03bdcf7a35d0d2"><code>9c7cceb</code></a> (builder) - builder: add app config to env</li> +</ul> +<h4 id="fixes">Fixes<a class="td-heading-self-link" href="#fixes" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7fe44faf2663b20e39b27221a8426cf332f2085b"><code>7fe44fa</code></a> (controller) - docker: docker timeout must be an int, float or None</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b196550f9ac51f22f422e29d6b1a7aa3708421c3"><code>b196550</code></a> (controller) - controller: revert release.check_image_access for now</li> +<li><a href="https://api.github.com/repos/drycc/workflow-manager/git/trees/cc3ec13a5d5173160f1f6b42726df81119cd69ae"><code>cc3ec13</code></a> (workflow-manager) - glide: bump goautoneg</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/ef932c4eb4ea0d592b57f0a4aebdbd6ad039c998"><code>ef932c4</code></a> (builder) - controller-sdk-go: upgrade controller-sdk-go</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4654cf64a919aa64b10253b080e0b6aae86edcb5"><code>4654cf6</code></a> (controller) - django-rest-framework: upgrade to 3.9.3</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/14121f1dae135b137f8ded451cfd1d8f8ca62543"><code>14121f1</code></a> (controller) - deps: bump djangorestframework from 3.9.3 to 3.9.4 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/385acdc7e0359eedb83e10e71877a9ff591bff15"><code>385acdc</code></a> (controller) - deps: bump django from 1.11.20 to 1.11.21 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/fa312bb7f57f5f8638484bc4d9825aa962031a25"><code>fa312bb</code></a> (database) - postgres: set max_connections = 1024</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/7ebecdfdca2de4936b67bc542053305f098db6d6"><code>7ebecdf</code></a> (database) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/b8878f6d4c32540bc864581a457aa6c996e7e50c"><code>b8878f6</code></a> (dockerbuilder) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/b097451f312c0386c466be3b638242535849def0"><code>b097451</code></a> (fluentd) - fluent: upgrade fluent to v1.4</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/4341f9ae71b5dc55c14984d9cacc8e48a3e6e089"><code>4341f9a</code></a> (minio) - mc: upgrade mc and minio</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/c1ee2a46808c6054ab1393cdd31bf861e01ebdfc"><code>c1ee2a4</code></a> (monitor) - monitor: remove copyrights.tar.gz</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/9854260ef4738be5d25e4a028ebd3125988fec34"><code>9854260</code></a> (registry) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/acc5627dd8f96d3f62e02cd8813cbd829321bd18"><code>acc5627</code></a> (slugbuilder) - slugbuilder: internal support for multi buildpack</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/d58907eb664185c25950953dae4fe4774a2f6310"><code>d58907e</code></a> (slugbuilder) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/b39a0c29fef7d76ae681ec7ba2f01e3605a33657"><code>b39a0c2</code></a> (slugrunner) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z</li> +</ul> + + + + + + Blog: Drycc Workflow v1.2.0 + /blog/2019/10/06/drycc-workflow-v1.2.0/ + Sun, 06 Oct 2019 00:00:00 +0000 + + /blog/2019/10/06/drycc-workflow-v1.2.0/ + + + + <p>These release notes for Drycc Workflow v1.2.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.1.0, please refer to the following change summary.</p> +<h2 id="workflow--v110---v120">Workflow ## v1.1.0 -&gt; v1.2.0<a class="td-heading-self-link" href="#workflow--v110---v120" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>builder v1.0.1 -&gt; v1.0.2</li> +<li>slugbuilder v1.0.0 -&gt; v1.1.0</li> +<li>dockerbuilder v1.0.0 -&gt; v1.1.0</li> +<li>controller v1.1.0 -&gt; v1.2.0</li> +<li>slugrunner v1.0.0 -&gt; v1.1.0</li> +<li>registry v1.0.0 -&gt; v1.0.1</li> +<li>registry-proxy v1.0.1 -&gt; v1.0.2</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e5584e32ef02329fd091a7a4d3f40bac9894d5a4"><code>e5584e3</code></a> (controller) - controller: add STACK support</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/ad34dc1a501aada4aa2f8ceeb7eefa9fed6baf75"><code>ad34dc1</code></a> (dockerbuilder) - kaniko: use kaniko replace docker-py</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/b81430e8d7ac10167450667cf41e2f9efada6cca"><code>b81430e</code></a> (dockerbuilder) - dockerbuilder: change image to image.json format</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/60dde96064c69aa7578476c2e4855680f5186706"><code>60dde96</code></a> (slugbuilder) - slugbuilder: add STACK support</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/fe8b6e56dd1a9334844581183bb16eb3d59df366"><code>fe8b6e5</code></a> (slugrunner) - slugrunner: add STACK support</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/942f050ec90f771262cbb5634f5df8d5a3818a5d"><code>942f050</code></a> (builder) - registry: remove env DRYCC_REGISTRY_PROXY_PORT</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/ff7a16f53ac78dac0c334a9718cdc76c65400732"><code>ff7a16f</code></a> (builder) - registry: remove ecr and gcr registry</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/ad13683ce634c9b4835f45d2b474bac16ca52baa"><code>ad13683</code></a> (builder) - builder: change DRYCC_BUILD_TYPE to DRYCC_STACK</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/6def637d5331330940d0a94cf6313a4bcb67fec0"><code>6def637</code></a> (builder) - registry: rename DRYCC_REGISTRY_SERVICE to DRYCC_REGISTRY_PROXY</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/5044e223a56ee6283ac8d68a1442a6430b18dd99"><code>5044e22</code></a> (builder) - registry: remove registry_secret_prefix</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/2ea39cc0a9dd68fa1baca4b3725a00b9bcf7f89a"><code>2ea39cc</code></a> (builder) - controller-go-sdk: upgrade controller-go-sdk</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/6aee0d7f092b53c37c70d05db076eaae1bbcff44"><code>6aee0d7</code></a> (builder) - registry: optimizing variable naming</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f9c62d9db809bfe03af33092e71a16e56fc35483"><code>f9c62d9</code></a> (controller) - domain: added reserved domain check</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f5a135be6aa2b319e623fd59bb711705d1cfe13f"><code>f5a135b</code></a> (controller) - migrations: clean old migrations</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4369b2c2fb6ef861978588a61efa1bfc6a4572ec"><code>4369b2c</code></a> (controller) - registry: rename DRYCC_REGISTRY_SERVICE to DRYCC_REGISTRY_PROXY</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1057ca59c3ae6bbd85d772f6b49b0c542d7d18c4"><code>1057ca5</code></a> (controller) - registry: remove registry_secret_prefix</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d114b3e93544624a5f01b1ca71db92d0b33f4e0d"><code>d114b3e</code></a> (controller) - docker: update docker client</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/edbe9631dcfb34ed50d9e931d36506fa262b6299"><code>edbe963</code></a> (dockerbuilder) - dockerfile: change base image to alpine</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/fb35baf913ff846e08ba79d9ad8195fca1411684"><code>fb35baf</code></a> (dockerbuilder) - registry: rename DRYCC_REGISTRY_SERVICE to DRYCC_REGISTRY_PROXY</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/946dbf688474933f821f641f6c027bab68cd9e79"><code>946dbf6</code></a> (dockerbuilder) - docker: remove insecure support</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/628d8532256e32a046268491f2a331dcb608b713"><code>628d853</code></a> (dockerbuilder) - proxy: add registry proxy</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/ff27cbdd27e9dc51ce29b6a68777888ed8737862"><code>ff27cbd</code></a> (registry) - env: remove unused env</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/7204d72c00b2d7360a2d3a20833d701e303a9f62"><code>7204d72</code></a> (registry-proxy) - registry: optimizing variable naming</li> +</ul> + + + + + + Blog: Welcome to Drycc + /blog/2018/10/06/welcome-to-drycc/ + Sat, 06 Oct 2018 00:00:00 +0000 + + /blog/2018/10/06/welcome-to-drycc/ + + + + <p><strong>Drycc Workflow</strong> is an open source Container as a Service (CaaS) that adds a developer-friendly layer to any <a href="http://kubernetes.io">Kubernetes</a> cluster, making it easy to deploy and manage applications.</p> +<p>We welcome your input! If you have feedback, please <a href="https://github.com/drycc/workflow/issues">submit an issue</a>. If you&rsquo;d like to participate in development, please read the &ldquo;Working on Documentation&rdquo; section below and <a href="https://github.com/drycc/workflow/pulls">submit a pull request</a>.</p> + + + + + + diff --git a/blog/news/_print/index.html b/blog/news/_print/index.html new file mode 100644 index 000000000..55eb7724a --- /dev/null +++ b/blog/news/_print/index.html @@ -0,0 +1,244 @@ + + + + + + + + + + + + + + + + + + + + + +News | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + + +
+
+

+This is the multi-page printable view of this section. +Click here to print. +

+Return to the regular view of this page. +

+
+ + + +

News

+ + + + + + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
+

Welcome to Drycc

+
Drycc Workflow is A Open, Unified, Lightweight, Simpler Containers as a Service (CaaS).
+ +

Drycc Workflow is an open source Container as a Service (CaaS) that adds a developer-friendly layer to any Kubernetes cluster, making it easy to deploy and manage applications.

+

We welcome your input! If you have feedback, please submit an issue. If you’d like to participate in development, please read the “Working on Documentation” section below and submit a pull request.

+ +
+ + + + + + + + + + + +
+
+
+ + +
+ + + + + + diff --git a/blog/news/index.html b/blog/news/index.html new file mode 100644 index 000000000..c80d55c24 --- /dev/null +++ b/blog/news/index.html @@ -0,0 +1,261 @@ + + + + + + + + + + + + + + + + + + + + + +News | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + +
+
Posts in 2018
+
    +
  • +
    +
    Welcome to Drycc
    +

    06.10.2018 in News

    + + + + + + +

    Drycc Workflow is an open source Container as a Service (CaaS) that adds a developer-friendly layer to any Kubernetes cluster, making it easy to deploy and manage applications. +We welcome your input! If you have feedback, please submit an issue. If …

    +

    Read more

    +
    +
  • +
+ +
+
+
+ +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/blog/news/index.xml b/blog/news/index.xml new file mode 100644 index 000000000..22aa7df7f --- /dev/null +++ b/blog/news/index.xml @@ -0,0 +1,33 @@ + + + Drycc – News + /blog/news/ + Recent content in News on Drycc + Hugo -- gohugo.io + en + + + + + + + + + + + Blog: Welcome to Drycc + /blog/2018/10/06/welcome-to-drycc/ + Sat, 06 Oct 2018 00:00:00 +0000 + + /blog/2018/10/06/welcome-to-drycc/ + + + + <p><strong>Drycc Workflow</strong> is an open source Container as a Service (CaaS) that adds a developer-friendly layer to any <a href="http://kubernetes.io">Kubernetes</a> cluster, making it easy to deploy and manage applications.</p> +<p>We welcome your input! If you have feedback, please <a href="https://github.com/drycc/workflow/issues">submit an issue</a>. If you&rsquo;d like to participate in development, please read the &ldquo;Working on Documentation&rdquo; section below and <a href="https://github.com/drycc/workflow/pulls">submit a pull request</a>.</p> + + + + + + diff --git a/blog/news/page/1/index.html b/blog/news/page/1/index.html new file mode 100644 index 000000000..ad9561b0a --- /dev/null +++ b/blog/news/page/1/index.html @@ -0,0 +1,10 @@ + + + + /blog/news/ + + + + + + diff --git a/blog/page/1/index.html b/blog/page/1/index.html new file mode 100644 index 000000000..d209a5087 --- /dev/null +++ b/blog/page/1/index.html @@ -0,0 +1,10 @@ + + + + /blog/ + + + + + + diff --git a/blog/page/2/index.html b/blog/page/2/index.html new file mode 100644 index 000000000..9f6fa531e --- /dev/null +++ b/blog/page/2/index.html @@ -0,0 +1,301 @@ + + + + + + + + + + + + + + + + + + + + + +Blog | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + +
+
Posts in 2019
+
    +
  • +
    +
    Drycc Workflow v1.2.0
    +

    06.10.2019 in Release

    + + + + + + +

    These release notes for Drycc Workflow v1.2.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.1.0, please refer to the following change summary. …

    +

    Read more

    +
    +
  • +
+
Posts in 2018
+
    +
  • +
    +
    Welcome to Drycc
    +

    06.10.2018 in News

    + + + + + + +

    Drycc Workflow is an open source Container as a Service (CaaS) that adds a developer-friendly layer to any Kubernetes cluster, making it easy to deploy and manage applications. +We welcome your input! If you have feedback, please submit an issue. If …

    +

    Read more

    +
    +
  • +
+ +
+
+ +
+ +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/blog/releases/_print/index.html b/blog/releases/_print/index.html new file mode 100644 index 000000000..9741b8b56 --- /dev/null +++ b/blog/releases/_print/index.html @@ -0,0 +1,2254 @@ + + + + + + + + + + + + + + + + + + + + + +Release | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + + +
+
+

+This is the multi-page printable view of this section. +Click here to print. +

+Return to the regular view of this page. +

+
+ + + +

Release

+ + + + + + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
+

Drycc Workflow v1.7.8

+
New Drycc Workflow Release v1.7.8
+ +

Workflow ## v1.7.7 -> v1.7.8

+

Releases

+
    +
  • builder v1.6.0 -> v1.7.0
  • +
  • controller v1.8.0 -> v1.9.0
  • +
  • workflow-cli v1.6.0 -> v1.7.0
  • +
+

Features

+
    +
  • 384c7ee (builder) - domain: add procfile_type
  • +
  • 26c8c7f (controller) - domain: add procfile_type
  • +
  • bd49789 (workflow-cli) - domain: add procfile_type
  • +
+ +
+ + + + + + + + + + + + + + + + +
+

Drycc Workflow v1.7.7

+
New Drycc Workflow Release v1.7.7
+ +

Workflow ## v1.7.6 -> v1.7.7

+

Releases

+
    +
  • builder v1.5.1 -> v1.6.0
  • +
  • controller v1.7.0 -> v1.8.0
  • +
  • database v1.2.1 -> v1.3.0
  • +
  • passport v1.2.0 -> v1.3.0
  • +
  • imagebuilder v1.1.1 -> v1.2.0
  • +
  • fluentbit v0.0.1 -> v0.0.2
  • +
  • logger v1.3.3 -> v1.3.4
  • +
  • storage v0.0.5 -> v0.1.0
  • +
  • gateway v0.0.2 -> v0.0.3
  • +
  • monitor v1.4.0 -> v1.4.1
  • +
  • redis v1.3.2 -> v1.4.0
  • +
  • timeseries v0.0.2 -> v0.1.0
  • +
  • prometheus v0.1.1 -> v0.1.2
  • +
  • rabbitmq v1.2.1 -> v1.3.0
  • +
  • registry v1.2.2 -> v1.3.0
  • +
  • registry-proxy v1.2.1 -> v1.2.2
  • +
  • workflow-cli v1.5.2 -> v1.6.0
  • +
+

Features

+
    +
  • 6c1cf5e (builder) - charts: reuses the value from an existing secret and config
  • +
  • 65ae63c (builder) - pipeline: add dryccfile support
  • +
  • bb7b11d (builder) - auth: add tokens api
  • +
  • 39d022f (controller) - ps: add pod logs support
  • +
  • 86056d0 (controller) - charts: reuses the value from an existing secret and config
  • +
  • 4cf005c (controller) - limits: add limits plan support
  • +
  • bf60e4b (controller) - controller: add init job
  • +
  • 98f77a8 (controller) - pipeline: add dryccfile support
  • +
  • 8ce9a83 (controller) - cert-manager: add tls events
  • +
  • 7034f5d (controller) - config: deploy according to procfile_type
  • +
  • 5554d8f (controller) - config: add typed_values
  • +
  • 2c5bbad (controller) - auth: add token api
  • +
  • 410d34e (database) - charts: reuses the value from an existing secret and config
  • +
  • 693e4d1 (imagebuilder) - pipeline: add dryccfile support
  • +
  • 7d9cc06 (imagebuilder) - config: add typed values
  • +
  • 854e171 (passport) - charts: reuses the value from an existing secret and config
  • +
  • 7ac9255 (passport) - oauth2: add authorization code for any grant type
  • +
  • 4517547 (rabbitmq) - charts: reuses the value from an existing secret and config
  • +
  • bccfcb4 (redis) - charts: reuses the value from an existing secret and config
  • +
  • d887605 (registry) - charts: reuses the value from an existing secret and config
  • +
  • ff09e5b (storage) - charts: reuses the value from an existing secret and config
  • +
  • c6e2ac8 (timeseries) - charts: reuses the value from an existing secret and config
  • +
  • 22c4c77 (workflow-cli) - apps: change drycc run to async
  • +
  • a9e6369 (workflow-cli) - ps: add pod logs support
  • +
  • 2bc31c8 (workflow-cli) - limits: add limits plan support
  • +
  • f40398a (workflow-cli) - pipeline: add dryccfile support
  • +
  • 03638ff (workflow-cli) - tls: add tls events
  • +
  • 9113627 (workflow-cli) - config: add typed values
  • +
  • 43ee760 (workflow-cli) - auth: add tokens api
  • +
+

Fixes

+
    +
  • 50dfe64 (builder) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • ab09b24 (controller) - healthcheck: delete outdated code
  • +
  • 52019b5 (controller) - services: default PORT change error
  • +
  • f57ae42 (controller) - certificate: failed to create certificate
  • +
  • 30c3f54 (controller) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • dbba43a (controller) - service: update port error
  • +
  • e0459c5 (controller) - copy: use deepcopy replace copy
  • +
  • 2122479 (controller) - charts: failed to call webhook
  • +
  • 53d9977 (controller) - signals: config limits handle error
  • +
  • afda287 (controller) - limits: always set default
  • +
  • b350cb8 (database) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • b48a422 (fluentbit) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 7cebca2 (gateway) - cert-manager: auto tls error
  • +
  • 190c19b (imagebuilder) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 2c6a6f9 (logger) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 10bb98d (monitor) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • f8225dc (passport) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 06db66c (prometheus) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • f4aff72 (rabbitmq) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 88c18ff (redis) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 5dcc19d (registry) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 092a939 (registry-proxy) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 3597ac9 (storage) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 5a49b35 (timeseries) - woodpecker: CI_SYSTEM_ARCH env removed
  • +
  • 0c4a48a (workflow-cli) - tls: change issuer options
  • +
  • 06a2511 (workflow-cli) - tls: info error
  • +
+

Maintenance

+
    +
  • 2f7617e (builder) - go: bump controller-sdk-go version
  • +
  • aae2f29 (builder) - charts: add diagnostic mode
  • +
  • 7304980 (builder) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 30b648b (builder) - charts: change canary app version
  • +
  • 2afa006 (builder) - controller-sdk-go: bump version
  • +
  • d127a90 (builder) - config: add typed values
  • +
  • 32fdfd0 (controller) - charts: add diagnostic mode
  • +
  • 0974942 (controller) - woodpecker: migrations woodpecker-ci to 2
  • +
  • f401e08 (controller) - python: bump python 3.12
  • +
  • c565959 (controller) - celery: remove retrieve_resource task
  • +
  • 47be1a1 (controller) - requirements: bump drf 3.15.1
  • +
  • 99f7468 (controller) - charts: add config to values.yaml
  • +
  • 7d17f5c (controller) - scale: prohibit scale when there is a running pipeline
  • +
  • f09e1c9 (controller) - resource: sort services and plans
  • +
  • e817505 (controller) - limits: change default cpu and gpu name
  • +
  • 5531b2f (controller) - auth: add password login
  • +
  • 27473f7 (controller) - deps: bump gunicorn from 21.2.0 to 22.0.0 in /rootfs
  • +
  • c1ee1c7 (controller) - deps: bump aiohttp from 3.9.3 to 3.9.4 in /rootfs
  • +
  • affbcb5 (database) - postgres: add patroni and postgres params (#15)
  • +
  • f9e4eda (database) - dockerfile: install vi
  • +
  • 008b7b6 (database) - dockerfile: install vim instand of vi
  • +
  • dbbfee1 (database) - charts: add diagnostic mode
  • +
  • 2e26c33 (database) - woodpecker: migrations woodpecker-ci to 2
  • +
  • a1b81f2 (database) - charts: change canary app version
  • +
  • bc725e8 (fluentbit) - charts: add diagnostic mode
  • +
  • 5d73886 (fluentbit) - woodpecker: migrations woodpecker-ci to 2
  • +
  • b85072d (fluentbit) - charts: change canary app version
  • +
  • 761174d (gateway) - gateway: change secrets name
  • +
  • 1c304da (gateway) - woodpecker: migrations woodpecker-ci to 2
  • +
  • b919a4c (gateway) - charts: change canary app version
  • +
  • 3cea298 (imagebuilder) - charts: allow all dns
  • +
  • 653bcbe (imagebuilder) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 59daeab (imagebuilder) - charts: change canary app version
  • +
  • 2834a5a (logger) - charts: add diagnostic mode
  • +
  • 6685492 (logger) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 191cdaf (logger) - charts: change canary app version
  • +
  • b3c3cfa (monitor) - charts: add diagnostic mode
  • +
  • 796799d (monitor) - grafana: add node metrics dashboard
  • +
  • ef2a222 (monitor) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 9c83090 (monitor) - charts: change canary app version
  • +
  • 1a97c2c (passport) - charts: add diagnostic mode
  • +
  • 353e1ae (passport) - logger: add oauth2_provider logger config
  • +
  • fe735c0 (passport) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 41d6144 (passport) - charts: change canary app version
  • +
  • 979d474 (passport) - python: bump python 3.12
  • +
  • e9f41a1 (passport) - requirements: bump drf 3.15.1
  • +
  • f479f4d (passport) - charts: add migrate job
  • +
  • ad9abf6 (passport) - passport: migrations add run_before
  • +
  • 95ac667 (passport) - passport: optimize the use of master and slave database rules
  • +
  • 204f7fc (passport) - deps: bump gunicorn from 21.2.0 to 22.0.0 in /rootfs
  • +
  • 90a6410 (prometheus) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 2d8eb44 (prometheus) - charts: change canary app version
  • +
  • 9687a17 (rabbitmq) - charts: add diagnostic mode
  • +
  • 35d3d5b (rabbitmq) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 6a6564d (rabbitmq) - charts: change canary app version
  • +
  • cb6722f (redis) - charts: add diagnostic mode
  • +
  • 9553497 (redis) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 1c8dc07 (redis) - charts: change canary app version
  • +
  • 9fa2a32 (registry) - charts: add diagnostic mode
  • +
  • 9b09e51 (registry) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 7dbd390 (registry) - charts: change canary app version
  • +
  • e1d2a33 (registry-proxy) - charts: add diagnostic mode
  • +
  • 3eabfdd (registry-proxy) - charts: remove default limits
  • +
  • f8754da (registry-proxy) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 7df7316 (registry-proxy) - charts: change canary app version
  • +
  • 861d3b8 (storage) - filer: modify the default parameters of the filer
  • +
  • 5fa08da (storage) - woodpecker: migrations woodpecker-ci to 2
  • +
  • 22c4620 (storage) - charts: change canary app version
  • +
  • 6c1e29c (timeseries) - postgres: add patroni params
  • +
  • e280d3f (timeseries) - dockerfile: install vi
  • +
  • 5213617 (timeseries) - dockerfile: install vim instand of vi
  • +
  • a569a57 (timeseries) - charts: add diagnostic mode
  • +
  • b93ec70 (timeseries) - woodpecker: migrations woodpecker-ci to 2
  • +
  • ff3b870 (timeseries) - charts: change canary app version
  • +
  • e334f74 (workflow-cli) - healthcheck: delete outdated healthcheck style
  • +
  • 4f8b960 (workflow-cli) - auth: add password login
  • +
+ +
+ + + + + + + + + + + + + + + + +
+

Drycc Workflow v1.7.5

+
New Drycc Workflow Release v1.7.5
+ +

These release notes for Drycc Workflow v1.7.5 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.7.4, please refer to the following change summary.

+

Workflow ## v1.7.4 -> v1.7.5

+

Releases

+
    +
  • builder v1.5.0 -> v1.5.1
  • +
  • controller v1.6.3 -> v1.7.0
  • +
  • logger v1.3.2 -> v1.3.3
  • +
  • storage v0.0.3 -> v0.0.4
  • +
  • redis v1.3.1 -> v1.3.2
  • +
  • rabbitmq v1.2.0 -> v1.2.1
  • +
  • registry v1.2.1 -> v1.2.2
  • +
  • workflow-cli v1.5.1 -> v1.5.2
  • +
+

Features

+
    +
  • 95d130a (controller) - controller: volume support nfs
  • +
+

Fixes

+
    +
  • ee2ee15 (controller) - controller: container entrypoint error
  • +
  • 03ea4f8 (controller) - controller: class property have been deprecated in python 3.11
  • +
  • 5f04d17 (controller) - controller: miss err msg
  • +
  • 27972a3 (controller) - controller: load_db_state_to_k8s err
  • +
  • a005d62 (controller) - controller: volume repeat path no error
  • +
  • c7a5ba6 (rabbitmq) - rabbitmq: cpu usage to high
  • +
  • 45c2077 (workflow-cli) - workflow-cli: miss err msg
  • +
  • bc738bd (workflow-cli) - workflow-cli: volumes list format
  • +
+

Maintenance

+
    +
  • 35e1c06 (builder) - builder: bump golang 1.22
  • +
  • 26caa36 (controller) - deps: bump aiohttp from 3.9.0 to 3.9.2 in /rootfs (#118)
  • +
  • 3d938c4 (controller) - deps: bump django from 4.2.7 to 4.2.10
  • +
  • e625c2f (logger) - logger: bump golang 1.22
  • +
  • bfa500d (redis) - redis: headless svc does not require ports
  • +
  • 330209a (registry) - registry: headless svc does not require ports
  • +
  • 48c42eb (storage) - storage: change volume index to leveldb
  • +
  • f4fde9d (storage) - storage: add volume size limit
  • +
  • 33e3684 (workflow-cli) - workflow-cli: volume support nfs
  • +
  • 48d5950 (workflow-cli) - workflow-cli: bump golang 1.22
  • +
+ +
+ + + + + + + + + + + + + + + + +
+

Drycc Workflow v1.7.6

+
New Drycc Workflow Release v1.7.6
+ +

Workflow ## v1.7.5 -> v1.7.6

+

Releases

+
    +
  • storage v0.0.4 -> v0.0.5
  • +
+

Maintenance

+
    +
  • 6cb63b6 (storage) - seaweedfs: bump version 3.63
  • +
+ +
+ + + + + + + + + + + + + + + + +
+

Drycc Workflow v1.7.2

+
New Drycc Workflow Release v1.7.2
+ +

These release notes for Drycc Workflow v1.7.2 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.7.1, please refer to the following change summary.

+

Workflow ## v1.7.1 -> v1.7.2

+

Releases

+
    +
  • controller v1.6.0 -> v1.6.1
  • +
  • logger v1.3.1 -> v1.3.2
  • +
  • storage v0.0.1 -> v0.0.2
  • +
  • timeseries v0.0.1 -> v0.0.2
  • +
  • prometheus v0.1.0 -> v0.1.1
  • +
  • workflow-cli v1.5.0 -> v1.5.1
  • +
+

Fixes

+
    +
  • 2fe80a6 (controller) - resources: after resources instance update, could not delete (#111)
  • +
  • a4082ad (controller) - controller: resource status and binding
  • +
  • e9bfccc (controller) - controller: fix multiple volumes mount at one dir error (#116)
  • +
  • 58d2b4c (logger) - logger: redis conn error block
  • +
  • 7cb2700 (prometheus) - prometheus: prometheus config basic_auth
  • +
  • 7838c6b (storage) - storage: random accesskey secretkey
  • +
  • d9dcdfb (storage) - storage: pod restart loses data
  • +
  • 3cbdd29 (storage) - storage: tipd cannot start after deleting pod
  • +
  • be7e11f (storage) - storage: jq command not found
  • +
  • 878f674 (storage) - storage: charts updateStrategy error
  • +
  • 06cfe56 (timeseries) - timeseries: the data node ip is incorrect
  • +
+

Maintenance

+
    +
  • 7f29f5a (controller) - resources: retrieve resource instance response add message (#112)
  • +
  • 4a84dcd (controller) - controller: add deploy default annotations (#113)
  • +
  • 829d7e5 (controller) - controller: modify url match service name (#114)
  • +
  • 30abf6d (controller) - controller: transfer app ownership in async
  • +
  • dc6f45e (controller) - controller: add channel for pod exec
  • +
  • af4f3a7 (controller) - controller: avoid error when secret no data field (#117)
  • +
  • ca27956 (controller) - controller: add pod default security
  • +
  • b2e9c64 (prometheus) - charts: node-exporter mount root (#2)
  • +
  • 3cdb2b6 (storage) - storage: bump seaweedfs 3.61
  • +
  • 00dd2fd (storage) - storage: add csi daemonset updateStrategy
  • +
  • 48e763c (storage) - storage: add drycc storage upgrade document
  • +
  • 841df90 (storage) - storage: bump seaweedfs 3.62
  • +
  • cefd52e (timeseries) - timeseries: add check data node exists
  • +
  • ad1c46e (workflow-cli) - resources: resources instance add message
  • +
  • 9f955c2 (workflow-cli) - workflow-cli: add short options cpu
  • +
  • 65399ef (workflow-cli) - workflow-cli: add tty resize support
  • +
+ +
+ + + + + + + + + + + + + + + + +
+

Drycc Workflow v1.7.0

+
New Drycc Workflow Release v1.7.0
+ +

These release notes for Drycc Workflow v1.7.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.6.0, please refer to the following change summary.

+

Workflow ## v1.6.0 -> v1.7.0

+

Releases

+
    +
  • builder v1.4.0 -> v1.5.0
  • +
  • controller v1.5.1 -> v1.6.0
  • +
  • database v1.2.0 -> v1.2.1
  • +
  • passport v1.1.0 -> v1.2.0
  • +
  • imagebuilder v1.1.0 -> v1.1.1
  • +
  • fluentbit v0.0.0 -> v0.0.1
  • +
  • logger v1.3.0 -> v1.3.1
  • +
  • storage v0.0.0 -> v0.0.1
  • +
  • gateway v0.0.0 -> v0.0.1
  • +
  • monitor v1.3.0 -> v1.4.0
  • +
  • redis v1.3.0 -> v1.3.1
  • +
  • timeseries v0.0.0 -> v0.0.1
  • +
  • prometheus v0.0.0 -> v0.1.0
  • +
  • rabbitmq v1.1.0 -> v1.2.0
  • +
  • registry v1.2.0 -> v1.2.1
  • +
  • registry-proxy v1.2.0 -> v1.2.1
  • +
+

Features

+
    +
  • fcbebda (builder) - builder: use TCPRoute expose service
  • +
  • d02bb5d (controller) - controller: support app dns policy config
  • +
  • 9aa968e (controller) - controller: add svc type support
  • +
  • 62e2d34 (controller) - controller: improve the services api
  • +
  • 4393755 (controller) - controller: use gateway replace ingress
  • +
  • 323045d (controller) - controller: add canary support
  • +
  • 3f81c97 (controller) - gateways: add addresses field
  • +
  • 4e64aa7 (controller) - gateways: add addresses field
  • +
  • 02ad581 (monitor) - grafana: add pd tikv dashboard
  • +
  • 2a9e2b0 (monitor) - monitor: add storage monitor
  • +
  • 41d5057 (monitor) - grafana: data source change to prometheus
  • +
  • ec035d1 (monitor) - monitor: usegateway replace ingress
  • +
  • c694c98 (monitor) - grafana: add drycc storage seaweedfs dashboard
  • +
  • 1e1fdc8 (passport) - passport: use gateway replace ingress
  • +
  • ffdb408 (prometheus) - prometheus: use gateway replace ingress
  • +
  • 04152b9 (rabbitmq) - rabbitmq: use gateway replace ingress
  • +
+

Fixes

+
    +
  • 0499500 (builder) - builder: manifest error
  • +
  • 642491d (builder) - builder: no build log
  • +
  • 873d146 (controller) - controller: do not set entrypoint when no procfile
  • +
  • d9028c5 (controller) - controller: pip8 error
  • +
  • 3efcfb7 (controller) - controller: manifest error
  • +
  • 18a3a1a (controller) - controller: miss service error
  • +
  • 94f796c (controller) - controller: drycc run pod should not restart
  • +
  • 80f3161 (controller) - controller: monitor query error
  • +
  • b76f2c5 (controller) - controller: read websocket delay
  • +
  • b6e068e (controller) - controller: metrics sql tpl, gateway pod should not restart, cleanup old rs, update monitor datatbase config
  • +
  • ad9adc6 (controller) - controller: rabbitmq sharding err
  • +
  • 6773907 (controller) - controller: default k8s pod annotaions
  • +
  • ffcf1f9 (controller) - controller: under-indented for visual indent
  • +
  • 3afd0cf (controller) - controller: charts env error
  • +
  • 769bb8b (database) - database: manifest error
  • +
  • 769bb8b (database) - database: label conflict error
  • +
  • 6a321c5 (database) - database: link error
  • +
  • 558feae (fluentbit) - fluentbit: build charts error
  • +
  • 98d8a2a (gateway) - fixup
  • +
  • 8b5dde1 (gateway) - gateway: secretName
  • +
  • 702866d (gateway) - gateway: build status
  • +
  • f55dac1 (imagebuilder) - imagebuilder: manifest error
  • +
  • ac13b5f (imagebuilder) - imagebuilder: build svg
  • +
  • 6b7bbc5 (logger) - logger: manifest error
  • +
  • 0136b5c (monitor) - monitor: manifest error
  • +
  • f03d975 (passport) - passport: DRYCC_GRAFANA_DOMAIN error
  • +
  • b530ea8 (passport) - passport: manifest error
  • +
  • be5a0a7 (passport) - passport: change passport
  • +
  • 1596c7f (rabbitmq) - rabbitmq: manifest error
  • +
  • 0dc4f6f (rabbitmq) - rabbitmq: images-shard error
  • +
  • 43293ae (redis) - redis: manifest error
  • +
  • ca13b7d (registry) - registry: manifest error
  • +
  • ab5c793 (registry) - registry: garbage collect error
  • +
  • ab0fabc (registry-proxy) - registry-proxy: manifest error
  • +
  • dfc7236 (registry-proxy) - registry-proxy: daemon yaml format
  • +
  • 42c03be (storage) - storage: seaweedfs csi error
  • +
  • 453e41a (timeseries) - timeseries: could not register node
  • +
+

Docs

+
    +
  • 5433c89 (gateway) - gateway: add prerequisites
  • +
  • 2f0c5d8 (logger) - logger: change architecture
  • +
+

Maintenance

+
    +
  • bdd02eb (builder) - builder: use dynamic clusterrole name
  • +
  • 66b4b25 (builder) - builder: upgrade new controller-go-sdk
  • +
  • 219d86f (builder) - builder: upgrade go.mod
  • +
  • 91f2f14 (builder) - builder: use woodpecker replace drone
  • +
  • 9abca16 (builder) - woodpecker: use woodpecker ci build status
  • +
  • f43dd50 (builder) - deps: bump golang.org/x/net from 0.2.0 to 0.7.0
  • +
  • 0384c69 (builder) - builder: add chart appVersion
  • +
  • e3149b9 (builder) - builder: upgrade codename to bookworm
  • +
  • d88ea1b (builder) - builder: add codename build-arg
  • +
  • ba59030 (builder) - builder: upgrade go.mod
  • +
  • 1114dd7 (builder) - builder: bump common 1.1.2
  • +
  • fe50b62 (builder) - builder: change drycc gateway listener name
  • +
  • db3950c (builder) - builder: remove gateway route
  • +
  • 5a508bb (builder) - builder: use podman replace docker
  • +
  • bbb9029 (builder) - deps: bump golang.org/x/net from 0.12.0 to 0.17.0
  • +
  • f4e5d6c (builder) - builder: remove health url
  • +
  • 9111c8f (builder) - builder: remove io/ioutil
  • +
  • 1f36e3d (controller) - deps: bump django from 4.1.2 to 4.1.6 in /rootfs
  • +
  • e4ab434 (controller) - controller: use woodpecker replace drone
  • +
  • 9f0301e (controller) - deps: bump django from 4.1.6 to 4.1.7 in /rootfs
  • +
  • 3932423 (controller) - woodpecker: use woodpecker ci build status
  • +
  • ae8b6b4 (controller) - setting: support KUBERNETES_LIMITS env config
  • +
  • c10b9bc (controller) - controller: using the api_version instead of hard coding
  • +
  • e6908cd (controller) - controller: upgrade requirements
  • +
  • b0eba0c (controller) - controller: add route rules serializer
  • +
  • 2e4b6a4 (controller) - controller: add chart appVersion
  • +
  • 7d32b55 (controller) - controller: upgrade to bookworm
  • +
  • f2dc8dd (controller) - controller: add codename build-arg
  • +
  • 5739b83 (controller) - controller: use timescaledb replace influxdb
  • +
  • 53892cb (controller) - controller: add timeseries
  • +
  • 0fe0eae (controller) - controller: upgrade requirements
  • +
  • 18b2a91 (controller) - deps: bump aiohttp from 3.8.4 to 3.8.5 in /rootfs
  • +
  • f50874a (controller) - controller: bump common 1.1.2
  • +
  • 956cd08 (controller) - controller: change drycc gateway listener name
  • +
  • 9ab3ead (controller) - controller: remove passport url check
  • +
  • a24c7b0 (controller) - controller: remove gateway route
  • +
  • f7e539a (controller) - controller: change celery priority
  • +
  • ab77a52 (controller) - controller: use podman replace docker
  • +
  • 8e27501 (controller) - controller: dynamic app storage class
  • +
  • 385978b (controller) - controller: list_pods datetime format
  • +
  • b20362c (controller) - deps: bump django from 4.2.3 to 4.2.7 in /rootfs
  • +
  • e11ae1b (controller) - controller: add cluster migrate
  • +
  • ca6e9df (controller) - controller: async mount
  • +
  • 9a7fbfc (controller) - controller: remove FOSSA
  • +
  • 3d55279 (controller) - deps: bump aiohttp from 3.8.5 to 3.8.6 in /rootfs
  • +
  • d498a11 (controller) - controller: add measure loalancers
  • +
  • 249a985 (controller) - deps: bump aiohttp from 3.8.5 to 3.8.6 in /rootfs
  • +
  • b967f58 (controller) - deps: bump aiohttp from 3.8.6 to 3.9.0 in /rootfs (#107)
  • +
  • 8ca9ed6 (controller) - controller: no longer restrict reserved domain
  • +
  • 9ff6649 (database) - database: add init database configure
  • +
  • 9b4cd26 (database) - database: use dynamic clusterrole name
  • +
  • b59cde4 (database) - database: remove minio require
  • +
  • 86462f8 (database) - database: use woodpecker replace drone
  • +
  • 1e8555a (database) - database: add chart appVersion
  • +
  • 1b762d5 (database) - database: upgrade codename to bookworm
  • +
  • 9ffe1fd (database) - database: add codename build-arg
  • +
  • 69466d7 (database) - database: add database extension
  • +
  • beb4b62 (database) - database: bump common 1.1.2
  • +
  • 67e2714 (database) - database: use podman replace docker
  • +
  • 8f328f8 (fluentbit) - fluentbit: no limit buffer size for kube api
  • +
  • fc0552c (fluentbit) - fluentbit: use podman replace docker
  • +
  • 63a6cab (fluentbit) - fluentbit: change fluentbit match
  • +
  • 220f81a (fluentbit) - fluentbit: run as no-root
  • +
  • aec1393 (fluentbit) - fluentbit: change configmap name
  • +
  • 1af4fd2 (fluentbit) - fluentbit: change default stream name
  • +
  • bef90ad (gateway) - gateway: add route for gateway
  • +
  • d523ddb (gateway) - gateway: change drycc gateway listener name
  • +
  • d9137f4 (gateway) - gateway: add chart appVersion
  • +
  • 0425dd4 (gateway) - gateway: add customListeners
  • +
  • 3982b86 (imagebuilder) - imagebuilder: use woodpecker replace drone
  • +
  • 3e4e7a3 (imagebuilder) - imagebuilder: add chart appVersion
  • +
  • 8df6e8e (imagebuilder) - imagebuilder: upgrade stack version
  • +
  • a5601f7 (imagebuilder) - imagebuilder: add drycc_app env
  • +
  • 07465f8 (imagebuilder) - imagebuilder: upgrade to bookworm
  • +
  • 00d22d2 (imagebuilder) - imagebuilder: add codename build-arg
  • +
  • 0b7a24e (imagebuilder) - imagebuilder: upgrade podman/mc/caddy
  • +
  • a7d8be8 (imagebuilder) - imagebuilder: use podman replace docker
  • +
  • 6b2da83 (logger) - logger: use woodpecker replace drone
  • +
  • 8245b25 (logger) - woodpecker: use woodpecker ci build status
  • +
  • f811a74 (logger) - logger: add chart appVersion
  • +
  • 413f6f6 (logger) - logger: upgrade codename to bookworm
  • +
  • 2ac6b10 (logger) - logger: add codename build-arg
  • +
  • 2581426 (logger) - logger: bump redis to v9
  • +
  • 364b25a (logger) - logger: bump common 1.1.2
  • +
  • dc169a3 (logger) - logger: use fluentbit replace fluentd
  • +
  • d855d91 (logger) - logger: use podman replace docker
  • +
  • f767235 (monitor) - monitor: add off-cluster passport configure
  • +
  • ab23936 (monitor) - monitor: use dynamic clusterrole name
  • +
  • 47beee0 (monitor) - monitor: change tikv secret key
  • +
  • af7703f (monitor) - grafana: remove panel when component off-cluster
  • +
  • 1b870c2 (monitor) - monitor: use woodpecker replace drone
  • +
  • 4a5f1f1 (monitor) - grafana: up ldap api_url config
  • +
  • 143cabe (monitor) - monitor: add prometheus architecture diagram
  • +
  • 93091c2 (monitor) - woodpecker: use woodpecker ci build status
  • +
  • 0b7045a (monitor) - grafana: add dashboard kubernetes_deployment_metrics
  • +
  • 2fb1839 (monitor) - woodpecker: pipeline config VERSION, when build container image
  • +
  • e272416 (monitor) - monitor: add chart appVersion
  • +
  • abc0e53 (monitor) - monitor: upgrade codename to bookworm
  • +
  • 86cc01b (monitor) - monitor: add codename build-arg
  • +
  • 1cd849f (monitor) - monitor: add postgresql outputs
  • +
  • c3205c0 (monitor) - monitor: change default agent config
  • +
  • 8c802c0 (monitor) - monitor: add timeseries database
  • +
  • e9abc40 (monitor) - monitor: bump common 1.1.2
  • +
  • 6af66cd (monitor) - monitor: change drycc gateway listener name
  • +
  • d02d718 (monitor) - monitor: remove gateway route
  • +
  • 3509c29 (monitor) - monitor: use podman replace docker
  • +
  • ed7bfa2 (monitor) - monitor: optimize env PROMETHEUS_URL
  • +
  • da89bef (passport) - passport: charts codereview
  • +
  • 61c4a96 (passport) - passport: support init app config
  • +
  • 9101006 (passport) - passport: add initApplications to charts
  • +
  • 7dd7fa4 (passport) - passport: use woodpecker replace drone
  • +
  • 4400199 (passport) - woodpecker: use woodpecker ci build status
  • +
  • 6b2c546 (passport) - passport: change secret name to drycc-passport-auto-tls
  • +
  • c8bd824 (passport) - passport: upgrade requirements
  • +
  • aee5aef (passport) - passport: add chart appVersion
  • +
  • 2d81953 (passport) - passport: upgrade codename to bookworm
  • +
  • 9e66242 (passport) - passport: add codename build-arg
  • +
  • 0fca998 (passport) - passport: upgrade requirements
  • +
  • 3482528 (passport) - passport: bump common 1.1.2
  • +
  • 0c5ec93 (passport) - passport: change drycc gateway listener name
  • +
  • f7b8f53 (passport) - passport: remove gateway route
  • +
  • baf69da (passport) - passport: use podman replace docker
  • +
  • fcd45dd (passport) - passport: add cluster migrate
  • +
  • da6d32a (prometheus) - prometheus: add prometheus-config
  • +
  • 683de9e (prometheus) - prometheus: use podman replace docker
  • +
  • 3323300 (prometheus) - prometheus: remove gateway route
  • +
  • da1d356 (prometheus) - prometheus: change drycc gateway listener name
  • +
  • 4e7a936 (prometheus) - prometheus: bump common 1.1.2
  • +
  • 44c1c6f (prometheus) - prometheus: add codename build-arg
  • +
  • d1f1dda (prometheus) - prometheus: upgrade codename to bookworm
  • +
  • 0836fc1 (prometheus) - prometheus: add chart appVersion
  • +
  • 9e13232 (prometheus) - prometheus: add LICENSE
  • +
  • f53e14a (rabbitmq) - rabbitmq: remove auto user
  • +
  • 0ec7277 (rabbitmq) - rabbitmq: use woodpecker replace drone
  • +
  • f376a30 (rabbitmq) - woodpecker: use woodpecker ci build status
  • +
  • 51405d8 (rabbitmq) - rabbitmq: add chart appVersion
  • +
  • 463ca03 (rabbitmq) - rabbitmq: upgrade codename to bookworm
  • +
  • 1978a71 (rabbitmq) - rabbitmq: add codename build-arg
  • +
  • 139277f (rabbitmq) - rabbitmq: bump common 1.1.2
  • +
  • be49741 (rabbitmq) - rabbitmq: change drycc gateway listener name
  • +
  • 6d22518 (rabbitmq) - rabbitmq: remove gateway route
  • +
  • 0eb7833 (rabbitmq) - rabbitmq: add check shards
  • +
  • 9211063 (rabbitmq) - rabbitmq: erlang vm tuning optimization
  • +
  • 648a78d (rabbitmq) - rabbitmq: use podman replace docker
  • +
  • 0b43a4d (rabbitmq) - rabbitmq: add x-random exchange
  • +
  • ad1c4da (redis) - redis: use woodpecker replace drone
  • +
  • 3f37f92 (redis) - redis: add chart appVersion
  • +
  • e3bef7a (redis) - redis: upgrade codename to bookworm
  • +
  • 4e806d4 (redis) - redis: add codename build-arg
  • +
  • d5023be (redis) - redis: bump common 1.1.2
  • +
  • 98f5d6f (redis) - redis: use podman replace docker
  • +
  • 063f29e (registry) - registry: use woodpecker replace drone
  • +
  • 17bf8ae (registry) - woodpecker: use woodpecker ci build status
  • +
  • 7bbad15 (registry) - registry: add chart appVersion
  • +
  • 279154f (registry) - registry: upgrade codename to bookworm
  • +
  • 3e4ae84 (registry) - registry: add codename build-arg
  • +
  • fa322d6 (registry) - registry: bump common 1.1.2
  • +
  • 6c18fe0 (registry) - registry: use podman replace docker
  • +
  • 0bc8472 (registry) - registry: remove health url
  • +
  • 5dacd9f (registry) - registry: add wait-for-port check
  • +
  • fdeefc3 (registry) - registry: use headless
  • +
  • 08bf9f8 (registry) - registry: change registry port to 5000
  • +
  • 40bcea2 (registry) - registry: add registry push test
  • +
  • 871b8e7 (registry) - registry: add default env
  • +
  • 7f3b3ac (registry) - registry: bump registry 2.8.3
  • +
  • 569f15d (registry-proxy) - registry-proxy: use woodpecker replace drone
  • +
  • cc33caf (registry-proxy) - woodpecker: use woodpecker ci build status
  • +
  • 0002aab (registry-proxy) - registry-proxy: add chart appVersion
  • +
  • 40af10b (registry-proxy) - registry-proxy: upgrade codename to bookworm
  • +
  • c56b9df (registry-proxy) - registry-proxy: add codename build-arg
  • +
  • 9d5bfe0 (registry-proxy) - registry-proxy: use podman replace docker
  • +
  • e6a3350 (registry-proxy) - registry-proxy: change worker_processes to 1
  • +
  • 726f39d (storage) - storage: add volume compactionMBps
  • +
  • a5aa2d8 (storage) - storage: add threshold to vacuum and reclaim spaces
  • +
  • e687d04 (storage) - storage: delete disk type in single disk case
  • +
  • 75ee2e4 (storage) - storage: change datanode replicas to 4
  • +
  • c5fd7ba (storage) - storage: delete useless env
  • +
  • b3826ea (storage) - storage: add ssd hdd dir
  • +
  • 29881a0 (storage) - storage: add balance cronjob
  • +
  • c5a0f51 (storage) - storage: add defaultReplication for seaweedfs master
  • +
  • 543c7a2 (timeseries) - timeseries: use podman replace docker
  • +
  • 5376024 (timeseries) - timeseries: update timeseries-service-replica
  • +
  • 52e8520 (timeseries) - timeseries: bump common 1.1.2
  • +
  • f82657c (timeseries) - timeseries: add start script
  • +
+ +
+ + + + + + + + + + + + + + + + +
+

Drycc Workflow v1.6.0

+
New Drycc Workflow Release v1.6.0
+ +

These release notes for Drycc Workflow v1.6.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.5.0, please refer to the following change summary.

+

Workflow ## v1.5.0 -> v1.6.0

+

Releases

+
    +
  • builder v1.3.0 -> v1.4.0
  • +
  • controller v1.4.0 -> v1.5.0
  • +
  • passport v1.0.0 -> v1.1.0
  • +
  • database v1.1.0 -> v1.2.0
  • +
  • imagebuilder v1.0.1 -> v1.1.0
  • +
  • fluentd v1.2.0 -> v1.3.0
  • +
  • logger v1.2.0 -> v1.3.0
  • +
  • storage v1.2.0 -> v1.3.0
  • +
  • monitor v1.2.0 -> v1.3.0
  • +
  • redis v1.2.0 -> v1.3.0
  • +
  • influxdb v1.1.0 -> v1.2.0
  • +
  • rabbitmq v1.0.0 -> v1.1.0
  • +
  • registry v1.1.0 -> v1.2.0
  • +
  • registry-proxy v1.1.0 -> v1.2.0
  • +
+

Features

+
    +
  • 52517d9 (builder) - builder: update controller-sdk-go
  • +
  • 1d78ca0 (builder) - builder: add affinity
  • +
  • 26b6980 (builder) - builder: switch charts to oci
  • +
  • bfd4385 (controller) - controller: add get manager user status
  • +
  • 874208d (controller) - controller: unified measurement model
  • +
  • cadf98f (controller) - controller: add admission webhook
  • +
  • e0050c2 (controller) - controller: new measurement model
  • +
  • a11ba58 (controller) - controller: multi pod restart uses async
  • +
  • fb3c15d (controller) - controller: add check app owner status
  • +
  • 3d78b76 (controller) - controller: add resource services api
  • +
  • 3d6a201 (controller) - controller: add search apps api
  • +
  • 01c443a (controller) - controller: add KUBERNETES_CPU_MEMORY_RATIO parameter
  • +
  • 7c26232 (controller) - controller: add volume size limit
  • +
  • 3bee749 (controller) - controller: add annotations support
  • +
  • 23cd97c (controller) - controller: traefik v2 support
  • +
  • e37b7db (controller) - controller: add affinity
  • +
  • b3b367b (controller) - controller: add volume expand support
  • +
  • a4e154a (controller) - controller: add database replica support
  • +
  • 2f37216 (controller) - controller: switch wsgi to asgi
  • +
  • b3314a5 (controller) - controller: add pod exec api
  • +
  • 75df2dc (controller) - controller: add stream support for app logs
  • +
  • 4229bad (controller) - ccontroller: switch charts to oci
  • +
  • 89bb19b (database) - database: upgrade to pg14
  • +
  • 9f45a5d (database) - database: add hugepages support
  • +
  • c4008c9 (database) - database: add affinity
  • +
  • 411a7b2 (database) - postgres: use patroni
  • +
  • 64e5cb0 (database) - database: switch charts to oci
  • +
  • 2bab823 (fluentd) - fluentd: switch charts to oci
  • +
  • 337ba62 (imagebuilder) - imagebuilder: run podman as rootless
  • +
  • 4396ffa (imagebuilder) - imagebuilder: switch to oci charts
  • +
  • f37ae09 (influxdb) - influxdb: add affinity
  • +
  • 04503b2 (influxdb) - influxdb: add influxdb ha
  • +
  • 41ddad5 (influxdb) - influxdb: switch charts to oci
  • +
  • 2006480 (logger) - logger: use redis stream replace nsqd
  • +
  • ab23d17 (logger) - logger: add affinity
  • +
  • 81d4e9d (logger) - logger: switch charts to oci
  • +
  • c3d9796 (monitor) - monitor: add affinity
  • +
  • cd9de3c (monitor) - monitor: switch to oci charts
  • +
  • 318a73f (passport) - passport: add change user confirm
  • +
  • 79ef100 (passport) - passport: add re login at authorize
  • +
  • 6927bb5 (passport) - passport: add affinity
  • +
  • 3146a09 (passport) - passport: add google reCAPTCHA
  • +
  • 802abcd (passport) - passport: add replica database support
  • +
  • a0dcd1b (passport) - passport: switch wsgi to asgi
  • +
  • 4c9dbba (passport) - passport: switch charts to oci
  • +
  • 74825f7 (rabbitmq) - rabbitmq: add rabbitmq managentment ingress
  • +
  • 12cf7d6 (rabbitmq) - rabbitmq: add affinity
  • +
  • 103417d (rabbitmq) - rabbitmq: switch charts to oci
  • +
  • 5d428bb (redis) - redis: add affinity
  • +
  • a88c1a9 (redis) - redis: switch charts to oci
  • +
  • 541585d (registry) - registry: add affinity
  • +
  • e9ca9d4 (registry) - registry: add garbage-collect cronjob
  • +
  • ec62a59 (registry) - registry: switch charts to oci
  • +
  • fde0b07 (registry-proxy) - registry-proxy: switch charts to oci
  • +
  • be14eb4 (storage) - minio: add affinity
  • +
  • 51af696 (storage) - storage: add k8s csi support
  • +
  • 76a75d9 (storage) - storage: add cluster health checker
  • +
  • a17dc8c (storage) - storage: switch charts to oci
  • +
+

Fixes

+
    +
  • e4f44fb (builder) - builder: no error return
  • +
  • e38dfc7 (builder) - builderControllerHost/ControllerPort init error
  • +
  • ff9069f (controller) - controller: influxdb query error
  • +
  • f7f5069 (controller) - controller: authentication 500
  • +
  • 7e297a8 (controller) - controller: add check remote user status
  • +
  • 9db28e1 (controller) - controller: celery MaxRetriesExceededError
  • +
  • 4bcff08 (controller) - controller: wrong name
  • +
  • d69fde2 (controller) - controller: traefik ingress create error
  • +
  • a3ad743 (controller) - fixup(controller: user login error
  • +
  • 662c8dd (controller) - controller: change influxdb port
  • +
  • 957bdf6 (controller) - controller: validate rsa key pairing before storage
  • +
  • 419ec4c (controller) - controller: kubernetes pod/exec cluster role
  • +
  • a67edaa (controller) - controller: Cannot routing:disable
  • +
  • e09e214 (controller) - controller: allowlist cannot remove
  • +
  • 318b126 (controller) - controller: domains update error
  • +
  • 92855eb (database) - database: premission denied
  • +
  • bde945a (database) - fixup(postgres: support arm, fix Failed to build psutil
  • +
  • 7854d45 (database) - fixup(postgres: user name converted to lowercase letters
  • +
  • 57b2a07 (fluentd) - fluentd: ifconfig_path not found
  • +
  • 20e72b9 (imagebuilder) - imagebuilder: upgrade pack version
  • +
  • 651db8a (imagebuilder) - imagebuilder: chown uid gid order
  • +
  • d2e9164 (influxdb) - influxdb: proxy not running
  • +
  • 3a1d361 (monitor) - monitor: charts naming
  • +
  • d754ae0 (monitor) - monitor: telegraf init error
  • +
  • 63f9e34 (monitor) - monitor: affinity error
  • +
  • 95ae1e5 (passport) - passport: yarn build fail
  • +
  • 3f5365e (passport) - passport: wrong name
  • +
  • 907f17b (passport) - passport: change uid gid to 1001
  • +
  • e3911e0 (passport) - passport: ‘registration_done’ not found
  • +
  • 2ace5f0 (passport) - passport: ui style
  • +
  • b3ba1e1 (passport) - passport privacy policy link
  • +
  • 172e9c8 (passport) - passport: check databaseReplicaUrl error
  • +
  • a3aeb70 (rabbitmq) - passport: change uid gid to 1001
  • +
  • 5c73dcf (redis) - reids: DRYCC_REGISTY misspelling
  • +
  • d7e3baf (redis) - redis: env miss
  • +
  • cadaa91 (registry) - registry: set gid uid to 1001
  • +
  • d524217 (registry) - registry: storage run error
  • +
  • 854f912 (registry) - registry: chown uid gid order
  • +
  • e642bb7 (registry-proxy) - registry-proxy: containerPort error
  • +
  • 8dfd029 (registry-proxy) - registry-proxy: chown uid gid order
  • +
  • bbea364 (storage) - minio: premission denied
  • +
  • 97deba1 (storage) - storage: node unimplemented error
  • +
  • b9bdeff (storage) - storage: pd can not connect each other
  • +
+

Style

+
    +
  • 1edb10c (controller) - controller: database convention over configuration
  • +
  • 1960cc3 (database) - database: database name convention over configuration
  • +
  • 06d1f5d (imagebuilder) - imagebuilder: URL to Url
  • +
  • b8a8941 (passport) - passport: database convention over configuration
  • +
+

Maintenance

+
    +
  • 8e9a199 (builder) - builder: upgrade controller-sdk-go
  • +
  • 4840151 (builder) - builder: use exec runner replace docker runner
  • +
  • 68ccfb1 (builder) - builder: canonical charts naming
  • +
  • 8f971cb (builder) - builder: provide any additional service annotations
  • +
  • fe2c55d (builder) - dockerfile: use drycc/base image
  • +
  • 2b5e706 (builder) - dockerfile: change user and workdir
  • +
  • 7a6c8d3 (builder) - builder: set gid uid to 1001
  • +
  • fe494f7 (builder) - dockerfile: use uid gid
  • +
  • a7c8752 (builder) - builder: change nodes to pod affinity
  • +
  • eb2e94c (builder) - database: bump mc 2022.04.01.23.44.48
  • +
  • cfaae66 (builder) - builder: use registry.drycc.cc replace docker.io
  • +
  • d7d2890 (builder) - builder: change default imagebuilder registry
  • +
  • ecfdb19 (builder) - imagebuilder: change python-dev registry
  • +
  • 6da17f4 (builder) - builder: https://github.com/minio/minio/issues/14331
  • +
  • 1a57e5b (builder) - builder: https://github.com/minio/minio/issues/14331
  • +
  • f1464fa (builder) - builder: https://github.com/minio/minio/issues/13799
  • +
  • b1e1c4f (builder) - builder: use env replace creds volume
  • +
  • 71a4145 (builder) - builder: bump go.mod
  • +
  • 3567688 (builder) - builder: fine management affinity
  • +
  • 73ea38b (builder) - builder: change storage to minio
  • +
  • 1f91321 (builder) - builder: use testify replace assert
  • +
  • d148b9c (builder) - builder: add check storage health
  • +
  • b768101 (builder) - builder: change initContainers
  • +
  • 1b3bec3 (builder) - builder: add replicas
  • +
  • 5cb0d61 (builder) - builder: upgrade to latest controller-sdk-go
  • +
  • 98b9d58 (builder) - builder: upgrade new require
  • +
  • 65817c3 (builder) - builder: change drycc.cc to www.drycc.cc
  • +
  • 4e3f9d0 (controller) - controller: add celery retry mechanism
  • +
  • f6716fe (controller) - controller: change cronjob name
  • +
  • eb60693 (controller) - controller: refine celery task priority
  • +
  • 66905e9 (controller) - controller: change manager auth
  • +
  • ea20c41 (controller) - controller: remove start/stop api
  • +
  • 4c8fc80 (controller) - controller: improve tasks error handling
  • +
  • cf7402e (controller) - controller: add blocklist api
  • +
  • 80f14dd (controller) - controller: use get_user_model replace auth.User
  • +
  • ffc7bb7 (controller) - controller: use JSONField replace ArrayField
  • +
  • 370df8c (controller) - controller: add validate metric
  • +
  • 29084ce (controller) - controller: use user id request manager api
  • +
  • 718fe12 (controller) - controller change urlpatterns order
  • +
  • 71f4042 (controller) - controller: measurements uses lowercase letters
  • +
  • e5123ea (controller) - controller: change resource unit to number
  • +
  • 18fee9a (controller) - deps: bump celery from 5.1.2 to 5.2.2 in /rootfs
  • +
  • ffca6c1 (controller) - controller: use exec runner replace docker runner
  • +
  • 9ec12e1 (controller) - controller: simplify drone configuration
  • +
  • 4b4749e (controller) - controller: set default CSRF_COOKIE_SECURE false
  • +
  • 2ef6338 (controller) - deps: bump django from 3.2.5 to 3.2.10 in /rootfs
  • +
  • c7570d0 (controller) - deps: bump django from 3.2.10 to 3.2.11 in /rootfs
  • +
  • 8b17bc1 (controller) - controller: canonical charts naming
  • +
  • c928fb0 (controller) - controller: use rabbitmq cluster
  • +
  • f917185 (controller) - controller: provide any additional service annotations
  • +
  • 22a8f63 (controller) - deps: bump django from 3.2.11 to 3.2.12 in /rootfs
  • +
  • 3cc3b00 (controller) - dockerfile: use drycc/base image
  • +
  • ee274f6 (controller) - controller: set venv profile
  • +
  • ce6b069 (controller) - controller: set gid uid to 1001
  • +
  • 3a105d3 (controller) - dockerfile: use uid gid
  • +
  • 15f9b0e (controller) - controller: code review
  • +
  • 01e6fd9 (controller) - controller: use passport user id
  • +
  • 893ee31 (controller) - oauth2: update user info pipline
  • +
  • 3028fb4 (controller) - user: set AnonymousUser username
  • +
  • 5daf82d (controller) - controller: set worker_cancel_long_running_tasks_on_connection_loss
  • +
  • 61f2c53 (controller) - controller: change nodes to pod affinity
  • +
  • 88feb1d (controller) - imagebuilder: python=3.10.4 rabbitmq=3.9.14
  • +
  • 914e03f (controller) - controller: use registry.drycc.cc replace docker.io
  • +
  • a5bb548 (controller) - controller: change python-dev registry
  • +
  • 3ecdd7c (controller) - controller: add a separate rabbitmqUrl configuration
  • +
  • 967cb11 (controller) - controller: remove APP_STORAGE
  • +
  • 473d2b5 (controller) - controller: use env replace creds volume
  • +
  • e410d4c (controller) - deps: bump django from 3.2.12 to 3.2.13 in /rootfs
  • +
  • c6ef777 (controller) - controller: simplified passport config
  • +
  • 0fd3233 (controller) - controller: remove settings hardcode
  • +
  • a64e99c (controller) - controller: change passport config
  • +
  • 62aba25 (controller) - controller: set cronjob timezone to utc
  • +
  • 760b70b (controller) - controller: change default ratio
  • +
  • 8dffc3a (controller) - controller: fine management affinity
  • +
  • 26043c4 (controller) - controller: change default app storage
  • +
  • 608bd8d (controller) - deps: bump django from 3.2.13 to 3.2.14 in /rootfs
  • +
  • 18ed0c2 (controller) - controller: remove conjob affinity
  • +
  • add6712 (controller) - controller: add volume expand support use patch
  • +
  • cc1ad13 (controller) - controller: add startupProbe
  • +
  • 0e9a603 (controller) - controller: add clearsocial cronjob
  • +
  • eb6f05d (controller) - controller: change initContainers
  • +
  • 762c676 (controller) - controller: change replicas
  • +
  • abd7e8c (controller) - deps: bump django from 3.2.14 to 3.2.15 in /rootfs
  • +
  • 07fdf1b (controller) - controller: remove database conn_max_age
  • +
  • ef8e41f (controller) - controller: add database replica check
  • +
  • 79143f2 (controller) - controller: upgrade new require
  • +
  • a624048 (controller) - controller: add app.refresh func annotation
  • +
  • b22d367 (controller) - controller: optimize app refresh timing
  • +
  • fe98f0c (database) - database: use exec runner replace docker runner
  • +
  • 5e00c11 (database) - database: canonical charts naming
  • +
  • d2cb860 (database) - database: disable huge_pages
  • +
  • 197d80d (database) - database: add persistence
  • +
  • 1c3e645 (database) - database: provide any additional service annotations
  • +
  • 37730ab (database) - dockerfile: use drycc/base image
  • +
  • 5014112 (database) - dockerfile: change entrypoint
  • +
  • 29b538e (database) - database: change nodes to pod affinity
  • +
  • c2bb074 (database) - database: bump python 3.10.4 and mc 2022.04.01.23.44.48
  • +
  • 077a4e9 (database) - database: use registry.drycc.cc replace docker.io
  • +
  • 560bdb9 (database) - database: change python-dev registry
  • +
  • 1e54b55 (database) - database: https://github.com/minio/minio/issues/14331
  • +
  • d646672 (database) - database: https://github.com/minio/minio/issues/13799
  • +
  • a6ac4e3 (database) - database: use env replace creds volume
  • +
  • 9618d87 (database) - database: fine management affinity
  • +
  • b823273 (database) - database: change minio to storage
  • +
  • 7bd5a90 (database) - database: add check storage health
  • +
  • 20c6d96 (database) - database: fix storage run error
  • +
  • 8bde830 (database) - database: upgrade to pg 14.5
  • +
  • a33b5e5 (fluentd) - fluentd: update plugins
  • +
  • eed7a78 (fluentd) - fluentd: update filter kubernetes setting
  • +
  • cc83dd8 (fluentd) - fluentd: update elasticsearch store setting and support exclude specific container logs
  • +
  • ba2feb2 (fluentd) - fluentd: use exec runner replace docker runner
  • +
  • d528676 (fluentd) - fluentd: simplify drone configuration
  • +
  • dece82d (fluentd) - fluentd: canonical charts naming
  • +
  • 4e0a802 (fluentd) - fluend: replace nsqd with redis
  • +
  • 15ceca0 (fluentd) - dockerfile: use drycc/base image
  • +
  • a7f619f (fluentd) - dockerfile: change workdir
  • +
  • 9adf5ed (fluentd) - database: bump fluentd 1.14.6
  • +
  • 50c14c2 (fluentd) - fluentd: use registry.drycc.cc replace docker.io
  • +
  • 83171b1 (fluentd) - fluentd: change python-dev registry
  • +
  • ec83581 (fluentd) - fluentd: unified reids declaration
  • +
  • 07c63e2 (fluentd) - fluentd: upgrade fluentd 1.15.2
  • +
  • 65df9be (imagebuilder) - imagebuilder: update pack version
  • +
  • 66cab35 (imagebuilder) - imagebuilder: use dind replace go-dev
  • +
  • 0c82060 (imagebuilder) - imagebuilder: use exec runner replace docker runner
  • +
  • 8146da9 (imagebuilder) - imagebuilder: canonical charts naming
  • +
  • 7d97241 (imagebuilder) - dockerfile: use drycc/base image
  • +
  • 07e805c (imagebuilder) - imagebuilder: change default buildpack
  • +
  • 8d1038d (imagebuilder) - imagebuilder: upgrade podman to 4.0.1
  • +
  • 62d3687 (imagebuilder) - imagebuilder: change workdir to /workspace
  • +
  • da8bfb0 (imagebuilder) - imagebuilder: change uid gid to 1001
  • +
  • d44e3bc (imagebuilder) - imagebuilder: upgrade stack
  • +
  • 5b0c7e6 (imagebuilder) - imagebuilder: use registry.drycc.cc replace docker.io
  • +
  • f74cbf6 (imagebuilder) - imagebuilder: add defaultBuildpacksURL
  • +
  • 941d493 (imagebuilder) - imagebuilder: https://github.com/minio/minio/issues/14331
  • +
  • 449be91 (imagebuilder) - imagebuilder: https://github.com/minio/minio/issues/13799
  • +
  • 63b0523 (imagebuilder) - imagebuilder: use env replace creds volume
  • +
  • 4e8a6e5 (imagebuilder) - imagebuilder: add imagebuilder config
  • +
  • 2d891f5 (imagebuilder) - imagebuilder: change minio to storage
  • +
  • addceda (imagebuilder) - imagebuilder: upgrade new require
  • +
  • a6e569f (imagebuilder) - imagebuilder: pack_build add –env-file parameter
  • +
  • 6191ff5 (influxdb) - influxdb: use exec runner replace docker runner
  • +
  • dc3f8c7 (influxdb) - influxdb: canonical charts naming
  • +
  • 6b5c819 (influxdb) - influxdb: new ingress style
  • +
  • 68b381d (influxdb) - influxdb: provide any additional service annotations
  • +
  • ea20eb8 (influxdb) - dockerfile: use drycc/base image
  • +
  • 64c0a71 (influxdb) - influxdb: set gid uid to 1001
  • +
  • a709ca1 (influxdb) - influxdb: use DRYCC_UID DRYCC_GID env
  • +
  • 740dff0 (influxdb) - influxdb: use common affinity template
  • +
  • e035673 (influxdb) - influxdb: change nodes to pod affinity
  • +
  • f1cefbd (influxdb) - influxdb: use registry.drycc.cc replace docker.io
  • +
  • a00100e (influxdb) - influxdb: fine management affinity
  • +
  • 9d165ef (influxdb) - influxdb: add probe
  • +
  • bee7fff (influxdb) - influxdb: upgrade to influxdb 2.4.0
  • +
  • 254914c (logger) - logger: use exec runner replace docker runner
  • +
  • 8d91c68 (logger) - logger: canonical charts naming
  • +
  • b6d2182 (logger) - logger: provide any additional service annotations
  • +
  • c35e59a (logger) - dockerfile: use drycc/base image
  • +
  • a63c070 (logger) - logger: change workdir to /workspace
  • +
  • a594b28 (logger) - logger: set gid uid to 1001
  • +
  • 9a90e22 (logger) - dockerfile: use uid gid
  • +
  • 36493b4 (logger) - logger: use common affinity template
  • +
  • 897a3a5 (logger) - logger: change nodes to pod affinity
  • +
  • 03b32ab (logger) - logger: use registry.drycc.cc replace docker.io
  • +
  • a50ba5f (logger) - logger: change python-dev registry
  • +
  • 23187a3 (logger) - logger: unified reids declaration
  • +
  • aaa129a (logger) - logger: fine management affinity
  • +
  • be4f656 (logger) - logger: add replicas
  • +
  • 7c25459 (logger) - charts: add NetworkPolicy
  • +
  • 6810149 (logger) - logger: remove memory storage
  • +
  • a918c50 (logger) - logger: add .vscode to .gitignore
  • +
  • a415210 (logger) - logger: add log follow support
  • +
  • 59b1da3 (logger) - logger: upgrade new require
  • +
  • 27cc151 (monitor) - monitor: use exec runner replace docker runner
  • +
  • 07d6a9d (monitor) - monitor: canonical charts naming
  • +
  • 1054357 (monitor) - monitor: use redis default port
  • +
  • e3673df (monitor) - monitor: remove nsqd
  • +
  • fc9dd3e (monitor) - monitor: new ingress style
  • +
  • 856a898 (monitor) - monitor: add default user env
  • +
  • 9857535 (monitor) - monitor: add random user
  • +
  • 38b5a04 (monitor) - grafana: oauth auto login
  • +
  • 5dfc579 (monitor) - monitor: upgrade version
  • +
  • e121b5a (monitor) - monitor: provide any additional service annotations
  • +
  • 84462a0 (monitor) - dockerfile: use drycc/base image
  • +
  • b9e8ce8 (monitor) - monitor: chore(imagebuilder): change uid gid to 1001
  • +
  • 05ee8ab (monitor) - dockerfile: use uid gid
  • +
  • e1fa68e (monitor) - monitor: use common affinity template
  • +
  • b8f302b (monitor) - monitor: change nodes to pod affinity
  • +
  • 4fc991f (monitor) - database: bump telegraf 1.22.0 and grafana 8.4.5
  • +
  • 21a2f6a (monitor) - monitor: use registry.drycc.cc replace docker.io
  • +
  • acc976f (monitor) - monitor: change python-dev registry
  • +
  • 62d76c1 (monitor) - monitor: unified reids declaration
  • +
  • b3c57ad (monitor) - monitor: optimize oauth2 configuration
  • +
  • 70af6b0 (monitor) - monitor: change passport config
  • +
  • 69f9a88 (monitor) - monitor: fine management affinity
  • +
  • 2fb278f (monitor) - monitor: rename influxdb port
  • +
  • 17548ff (monitor) - grafana: update dashborad
  • +
  • 69d7bbd (monitor) - grafana: influx dashborad disk size
  • +
  • 75db1b0 (monitor) - monitor: upgrade new grafana/telegraf
  • +
  • 80504a1 (monitor) - grafana: update influx and redis dashboard
  • +
  • f7078cb (monitor) - monitor:chown use env
  • +
  • 91ae0dd (passport) - passport: optimize login display
  • +
  • 2d3bbbc (passport) - passport: change drycc logo
  • +
  • 59790a7 (passport) - passport: make user email unique
  • +
  • faea034 (passport) - passport: use strtobool
  • +
  • 1fbf2bc (passport) - passport: use yarn replace npm
  • +
  • 119cac8 (passport) - passport: use exec runner replace docker runner
  • +
  • cff5062 (passport) - passport: set default CSRF_COOKIE_SECURE false
  • +
  • 9cc0210 (passport) - passport: canonical charts naming
  • +
  • 9ab3896 (passport) - passport: new ingress style
  • +
  • 259ccc9 (passport) - passport: provide any additional service annotations
  • +
  • af1bbcd (passport) - dockerfile: use drycc/base image
  • +
  • 9ae5373 (passport) - passport: set venv profile
  • +
  • 8f61090 (passport) - dockerfile: use uid gid
  • +
  • fcaf72d (passport) - passport: upgrade npm package
  • +
  • 546dcd5 (passport) - passport: add license
  • +
  • 4bda2d6 (passport) - passport: use minify
  • +
  • 73b0fd1 (passport) - passport: use common affinity template
  • +
  • 278fe7a (passport) - passport: change nodes to pod affinity
  • +
  • 3cd93d3 (passport) - passport: add reactive
  • +
  • 370b493 (passport) - passport: add footer
  • +
  • 483cbd6 (passport) - passport: use h_captcha replace re_captcha
  • +
  • 3d1675e (passport) - database: bump python 3.10.4 and node 16.14.2
  • +
  • 86a7835 (passport) - passport: use registry.drycc.cc replace docker.io
  • +
  • 2d65355 (passport) - passport: change python-dev registry
  • +
  • 90c1444 (passport) - passport: unified reids declaration
  • +
  • 2e0e417 (passport) - passport: fix firefox footer
  • +
  • ad274be (passport) - passport: use bulecss
  • +
  • f986d8b (passport) - passport: add main footer
  • +
  • 3e52867 (passport) - passport: dynamic settings for vue
  • +
  • 38adabc (passport) - passport: change passport config
  • +
  • f8d6b60 (passport) - passport: fine management affinity
  • +
  • 2cbd79d (passport) - passport: remove database conn_max_age
  • +
  • 7122797 (passport) - passport: change drycc.cc to www.drycc.cc
  • +
  • 8cc84cd (rabbitmq) - rabbitmq: use exec runner replace docker runner
  • +
  • f35930f (rabbitmq) - rabbitmq: add rabbitmq cluster support
  • +
  • fbfa3ba (rabbitmq) - rabbitmq: canonical charts naming
  • +
  • ca60701 (rabbitmq) - rabbitmq: use volumeClaimTemplates
  • +
  • fe5d1b4 (rabbitmq) - rabbitmq: add sharding support
  • +
  • 9c4ab97 (rabbitmq) - rabbitmq: provide any additional service annotations
  • +
  • 348a88a (rabbitmq) - dockerfile: use drycc/base image
  • +
  • 2388be1 (rabbitmq) - rabbitmq: upgrade erlang to 24.2.2
  • +
  • db2eaa5 (rabbitmq) - dockerfile: use uid gid
  • +
  • 772afd1 (rabbitmq) - rabbitmq: change to wait pid file
  • +
  • 2bfc25e (rabbitmq) - rabbitmq: use common affinity template
  • +
  • 11d505e (rabbitmq) - rabbitmq: change nodes to pod affinity
  • +
  • 69d63f1 (rabbitmq) - database: bump erlang 24.3.3 and rabbitmq 3.9.14
  • +
  • 8380299 (rabbitmq) - rabbitmq: use registry.drycc.cc replace docker.io
  • +
  • b3f69f1 (rabbitmq) - rabbitmq: add check rabbitmqLocaltion
  • +
  • 5327c76 (rabbitmq) - rabbitmq: fine management affinity
  • +
  • 5c66b5a (rabbitmq) - rabbitmq: change probe
  • +
  • 27bebf9 (rabbitmq) - rabbitmq: add start-rabbitmq script
  • +
  • 86ee6a7 (rabbitmq) - rabbitmq: upgrade to rabbitmq 3.10.7
  • +
  • 1f29683 (redis) - redis: use exec runner replace docker runner
  • +
  • a5041fc (redis) - redis: canonical charts naming
  • +
  • 64468c2 (redis) - redis: add redis persistence
  • +
  • de5d753 (redis) - redis: provide any additional service annotations
  • +
  • f644639 (redis) - dockerfile: use drycc/base image
  • +
  • 98051d2 (redis) - redis: premission denied
  • +
  • bcb548e (redis) - dockerfile: use uid gid
  • +
  • 524aa41 (redis) - redis: use common affinity template
  • +
  • 26c9466 (redis) - redis: change nodes to pod affinity
  • +
  • b67d7a2 (redis) - redis: use registry.drycc.cc replace docker.io
  • +
  • 839ec50 (redis) - redis: use env replace creds volume
  • +
  • 237ca86 (redis) - redis: fine management affinity
  • +
  • bdd968d (redis) - redis: upgrade neew require
  • +
  • 8b2910f (registry) - registry: use exec runner replace docker runner
  • +
  • eedbe78 (registry) - registry: canonical charts naming
  • +
  • 0241615 (registry) - registry: provide any additional service annotations
  • +
  • 9b58da4 (registry) - dockerfile: use drycc/base image
  • +
  • ab6acb7 (registry) - registry: change workdir to /workspace
  • +
  • f368bf7 (registry) - registry: use DRYCC_UID DRYCC_GID env
  • +
  • f4b9041 (registry) - registry: use common affinity template
  • +
  • c2e87ca (registry) - registry: change nodes to pod affinity
  • +
  • feb6aba (registry) - database: bump mc 2022.04.01.23.44.48
  • +
  • 956932b (registry) - rregistry: use registry.drycc.cc replace docker.io
  • +
  • deda8d8 (registry) - registry: move registry-secret.yaml from workflow to registry
  • +
  • f52c7bf (registry) - registry: change python-dev registry
  • +
  • 007fe03 (registry) - registry: https://github.com/minio/minio/issues/14331
  • +
  • d620c6d (registry) - registry: https://github.com/minio/minio/issues/13799
  • +
  • 85e6b73 (registry) - registry: use env replace creds volume
  • +
  • 6a1155d (registry) - registry: fine management affinity
  • +
  • 7b8ebae (registry) - registry: change minio to storage
  • +
  • 1338951 (registry) - registry: add check storage health
  • +
  • 2fa769d (registry) - registry: change probe
  • +
  • f187cbf (registry) - registry: add replicas
  • +
  • 09d8a7b (registry) - registry: upgrade to mc 2022.08.28.20.08.11
  • +
  • 4b187b8 (registry-proxy) - registry-proxy: use exec runner replace docker runner
  • +
  • 29ffbbe (registry-proxy) - registry-proxy: canonical charts naming
  • +
  • 6d783ba (registry-proxy) - registry-proxy: remove use_cni
  • +
  • 8cf05cf (registry-proxy) - dockerfile: use drycc/base image
  • +
  • 090e286 (registry-proxy) - registry-proxy: chore(imagebuilder): change uid gid to 1001
  • +
  • 7cf6120 (registry-proxy) - registry-proxy: use DRYCC_UID DRYCC_GID env
  • +
  • 3a00697 (registry-proxy) - registry-proxy: use registry.drycc.cc replace docker.io
  • +
  • 30e69e8 (registry-proxy) - registry-proxy: add registry basic auth proxy
  • +
  • 942abce (registry-proxy) - registry-proxy: upgrade to nginx 1.23.1
  • +
  • 5ea3297 (storage) - minio: use exec runner replace docker runner
  • +
  • 8306add (storage) - minio: canonical charts naming
  • +
  • c917e9f (storage) - minio: provide any additional service annotations
  • +
  • 042c732 (storage) - dockerfile: use drycc/base image
  • +
  • 7b47b82 (storage) - minio: change workdir to /workspace
  • +
  • 6f3531e (storage) - minio: use DRYCC_UID DRYCC_GID env
  • +
  • 9795fb1 (storage) - minio: use common affinity template
  • +
  • a7b09c5 (storage) - minio: change nodes to pod affinity
  • +
  • 7607342 (storage) - database: bump mc 2022.04.01.23.44.48 and minio 2022.04.01.03.41.39
  • +
  • ea2b2f1 (storage) - minio: use registry.drycc.cc replace docker.io
  • +
  • 445b501 (storage) - minio: https://github.com/minio/minio/issues/14331
  • +
  • f19fbc7 (storage) - minio: use env replace creds volume
  • +
  • 8982e2e (storage) - minio: use minio to distributed
  • +
  • 06bec73 (storage) - minio: fine management affinity
  • +
  • 9b8f006 (storage) - storage: remove assert
  • +
  • 59d64b9 (storage) - storage: change listen to POD_IP
  • +
  • 60044ee (storage) - storage: add juicefs mount options
  • +
  • 189f944 (storage) - storage: remove volumeName
  • +
  • 302fe89 (storage) - storage: mv to minio dir
  • +
  • 6ec586d (storage) - storage: change readinessProbee andlivenessProbe
  • +
  • 0e028df (storage) - storage: add minio pdb
  • +
  • cf9bd2d (storage) - storage: add check storage health svc
  • +
  • 2dd5c9f (storage) - storage: add volumeBindingMode
  • +
  • fa2effc (storage) - storage: remove databaseBucket
  • +
  • d166cc7 (storage) - charts: format network-policy name
  • +
  • d06bcce (storage) - storage: upgrade to golang 1.19
  • +
  • c2ca05c (storage) - storage: upgrade new require
  • +
+ +
+ + + + + + + + + + + + + + + + +
+

Drycc Workflow v1.5.0

+
New Drycc Workflow Release v1.5.0
+ +

These release notes for Drycc Workflow v1.5.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.4.0, please refer to the following change summary.

+

Workflow ## v1.4.0 -> v1.5.0

+

Releases

+
    +
  • passport v1.0.0
  • +
  • rabbitmq v1.0.0
  • +
  • imagebuilder v1.0.0
  • +
  • builder v1.2.0 -> v1.3.0
  • +
  • controller v1.3.0 -> v1.4.0
  • +
  • database v1.0.2 -> v1.1.0
  • +
  • fluentd v1.1.0 -> v1.2.0
  • +
  • redis v1.1.0 -> v1.2.0
  • +
  • influxdb v1.0.1 -> v1.1.0
  • +
  • logger v1.1.0 -> v1.2.0
  • +
  • minio v1.1.0 -> v1.2.0
  • +
  • monitor v1.1.0 -> v1.2.0
  • +
  • nsqd v1.1.0 -> v1.2.0
  • +
  • registry v1.0.3 -> v1.1.0
  • +
  • registry-proxy v1.0.2 -> v1.1.0
  • +
+

Features

+
    +
  • 0f5f8e4 (builder) - builder: multi-platform support
  • +
  • f269d06 (builder) - build: add buildx supportjkjkk:q
  • +
  • 5e72fe8 (builder) - registry: use docker build
  • +
  • 25d8a4c (builder) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 7a3e1c5 (builder) - charts: set the default chart version
  • +
  • 46b75ff (builder) - builder: add cloud native buildpacks support
  • +
  • 2db2054 (builder) - builder: unified build model
  • +
  • 4b7f9d9 (builder) - builder: add initContainers
  • +
  • b78c936 (controller) - token: add get token api
  • +
  • bac52a5 (controller) - tasks: use celery replace nsqd
  • +
  • b9b0c58 (controller) - build: add buildx support
  • +
  • 205dcb3 (controller) - influxdb: add influxdb client
  • +
  • ff15849 (controller) - influxdb: upgrade to influxdb 2.x
  • +
  • 4016244 (controller) - controller: push data to influx
  • +
  • fcfce2e (controller) - workflow-manager: add workflow-manager support
  • +
  • 00e9bfb (controller) - influxdb: review influxdb code
  • +
  • dd644d5 (controller) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 118278b (controller) - charts: set the default chart version
  • +
  • 122a9cd (controller) - oauth2: add oauth2 support
  • +
  • 559a5b6 (controller) - controller: use cncf buildpacks replace slugrunner
  • +
  • 96130e6 (controller) - charts: database configuration optimization of passport and controller
  • +
  • 2ea8508 (controller) - oauth: using passport authentication
  • +
  • 868c437 (database) - database: multi-platform support
  • +
  • eadd5da (database) - build: add buildx support
  • +
  • b6eea4c (database) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 04a88db (database) - charts: set the default chart version
  • +
  • 92ed309 (database) - database: add initContainer
  • +
  • ee6b78f (fluentd) - build: add buildx support
  • +
  • f523e30 (fluentd) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • ee47b53 (fluentd) - charts: set the default chart version
  • +
  • 80a51af (influxdb) - influxdb: modify influxdb naming rules
  • +
  • fb10030 (influxdb) - influxdb: use influxdb v2
  • +
  • 0e87ad8 (influxdb) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 9d10801 (influxdb) - charts: set the default chart version
  • +
  • d825c9f (logger) - build: add buildx support
  • +
  • b139576 (logger) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 88f84ea (logger) - charts: set the default chart version
  • +
  • 5ccae3e (logger) - dockerfile: remove chmod cmd
  • +
  • 193aefc (logger) - logger: add initContainers
  • +
  • baee330 (minio) - minio: multi-platform support
  • +
  • ad5d055 (minio) - build: add buildx support
  • +
  • 19868d4 (minio) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 4bd84b8 (minio) - charts: set the default chart version
  • +
  • 79d1f2f (monitor) - database: multi-platform support
  • +
  • 88e5a7f (monitor) - build: add buildx support
  • +
  • 5672e99 (monitor) - influxdb: modify influxdb naming rules
  • +
  • 8672103 (monitor) - influxdb: use influxdb v2
  • +
  • 66cb4c8 (monitor) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 9576eb3 (monitor) - charts: set the default chart version
  • +
  • 30809c9 (monitor) - monitor: add initContainers
  • +
  • 70d140c (nsqd) - nsqd: using self compiled nsq binary
  • +
  • 1073d4f (nsqd) - nsqd: use GOPATH replace /go
  • +
  • e498480 (nsqd) - build: add buildx support
  • +
  • cf9b7d5 (nsqd) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • c335856 (nsqd) - charts: set the default chart version
  • +
  • efba713 (redis) - build: add buildx support
  • +
  • c7a3b53 (redis) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 4cdad7b (redis) - charts: set the default chart version
  • +
  • 652b443 (registry) - registry: multi-platform support
  • +
  • 4060176 (registry) - registry: use docker build
  • +
  • 7102a03 (registry) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 6c8600d (registry) - charts: set the default chart version
  • +
  • 33a51c9 (registry) - registry: add initContainers
  • +
  • bef70dc (registry-proxy) - build: add buildx support
  • +
  • d2319c1 (registry-proxy) - docker: dealing with the change of docker in kubenetes 1.20
  • +
  • 02fafed (registry-proxy) - charts: set the default chart version
  • +
+

Fixes

+
    +
  • 5499c9a (controller) - gunicorn: gunicorn not running
  • +
  • 06e9e88 (controller) - controller: error loading shared library
  • +
  • 01b5bd0 (controller) - controller: upgrade celery config
  • +
  • 6e32d55 (controller) - controller: fix update resources bug
  • +
  • 0e0d53f (controller) - chart: set the domain depends certManagerEnabled
  • +
  • 2ac4ca8 (controller) - passport: error loading shared library libexpat.so.1
  • +
  • a0dd517 (fluentd) - fluentd: drone build
  • +
  • 6eca2a3 (logger) - logger: golang lint
  • +
  • 63b0aa0 (registry) - drone: charts url error
  • +
+

Docs

+
    +
  • 472cfcc (controller) - controller organize README.md document
  • +
  • d9d6e29 (redis) - redis: delete links that do not exist
  • +
+

Test case

+
    +
  • 1468f57 (controller) - controller: add command unittest
  • +
+

Maintenance

+
    +
  • 9999bfd (builder) - builder:replace the special words
  • +
  • cda8b58 (builder) - builder: remove docker keyword from charts
  • +
  • dc575dd (builder) - builder: use imagebuilder replace dockerbuilder
  • +
  • d3bb183 (builder) - docker: use the full name of registry
  • +
  • 5fe34d1 (builder) - travis: add DEV_REGISTRY
  • +
  • 7e36453 (builder) - CICD: use drone
  • +
  • 52b8d9d (builder) - drone: add image_registries volumes
  • +
  • 65963f4 (builder) - k8s: add privileged to dind
  • +
  • d345fcf (builder) - LICENSE: revert modifications to Apache license
  • +
  • 7975c99 (builder) - drone: always pull image
  • +
  • 59633dd (builder) - builder: modify launch imagebuild pod
  • +
  • 8d14e67 (builder) - builder: use Procfile in anywhere
  • +
  • 5357fa8 (builder) - go: bump go mod
  • +
  • 8d26ac0 (builder) - k8s: k8s deprecated api migration
  • +
  • 0af620d (builder) - chars: change org to imageTag
  • +
  • ae84303 (builder) - builder: run imagebuider replace pod with job
  • +
  • 3b2c496 (builder) - builder: change docs website
  • +
  • 5679a4c (builder) - builder: upgrade to golang1.17
  • +
  • a214503 (controller) - controller:replace whitelist with allowlist
  • +
  • 375ddcc (controller) - ps:drycc ps:list show autoscale num
  • +
  • c32e409 (controller) - ldap: canot register when ldap is enabled
  • +
  • c46580a (controller) - controller:modify redis config
  • +
  • fa9e87b (controller) - chart:modify controller charts
  • +
  • 6f9fd08 (controller) - nsq: remove nsq
  • +
  • 994b2dc (controller) - docker-buildx: add check-docker
  • +
  • a720c3a (controller) - controller: remove docker keyword from charts
  • +
  • e9a5c84 (controller) - docker: use the full name of registry
  • +
  • a26614a (controller) - controller: add rabbitmq env
  • +
  • 3df229d (controller) - controller: modify database config && remove redis port config && add env prefix with DRYCC
  • +
  • 257e94b (controller) - controller: CELERY_BROKER use rabbitmq and modify celery-deployment cronjob
  • +
  • f4d6ec3 (controller) - chart: pretty chart format
  • +
  • 63e6195 (controller) - influxdb: modify influxdb code
  • +
  • 0f6d408 (controller) - CICD: use drone
  • +
  • 87bad28 (controller) - python: upgrade to python3.9
  • +
  • e8f7560 (controller) - volumes: modify mount summary
  • +
  • 6cf6c6b (controller) - drone: add image_registries volumes
  • +
  • a9397e8 (controller) - oauth: modify token Authentication
  • +
  • c7f8c8b (controller) - deps: bump django from 2.2.14 to 2.2.18 in /rootfs
  • +
  • a1a08aa (controller) - deps: bump djangorestframework from 3.11.0 to 3.11.2 in /rootfs
  • +
  • efd78b4 (controller) - deps: bump django from 2.2.18 to 2.2.20 in /rootfs
  • +
  • 649b044 (controller) - deps: bump django from 2.2.20 to 2.2.22 in /rootfs
  • +
  • 41b742b (controller) - deps: bump django from 2.2.22 to 2.2.24 in /rootfs
  • +
  • 22ffe5d (controller) - LICENSE: revert modifications to Apache license
  • +
  • c98b468 (controller) - drone: always pull image
  • +
  • 20e6edb (controller) - chart: modify the problem of using buildpack
  • +
  • db16879 (controller) - controller: pretty pods list print
  • +
  • ba6f456 (controller) - test: pretty pods list print
  • +
  • 5fce4b7 (controller) - k8s: k8s deprecated api migration
  • +
  • e9e0bcb (controller) - oauth: using passport authentication
  • +
  • 0311172 (controller) - chars: change org to imageTag
  • +
  • 150eff1 (controller) - charts: update cert-manager api version
  • +
  • de8545a (controller) - controller: update requirements
  • +
  • 1442207 (controller) - controller: using django native JSONFiled
  • +
  • ab4e836 (controller) - oauth: modify passport api
  • +
  • 5c54e06 (controller) - controller: eliminate pip warnings
  • +
  • 870328d (controller) - controller: remove entrypoint
  • +
  • 5e5e6ae (controller) - controller: upgrade celery config
  • +
  • 607778f (controller) - controller: add initContainer
  • +
  • 23dc016 (controller) - chart: set the domain depends certManagerEnabled
  • +
  • f3cf20b (controller) - controller: remove default bash env
  • +
  • 73f2636 (controller) - controller: modify alpinelinux repositories
  • +
  • 498e9f2 (controller) - chart: change certManagerEnabled to boolean type
  • +
  • 27f5308 (controller) - passport: exclude cryptography
  • +
  • 370b75d (controller) - controller: use sh env
  • +
  • 07585b4 (database) - postgres:replace the special words
  • +
  • 20172dc (database) - database: remove docker keyword from charts
  • +
  • abb9b88 (database) - docker: use the full name of registry
  • +
  • e72f58f (database) - chart: modify the off-cluster database
  • +
  • a91f64f (database) - travis: add DEV_REGISTRY
  • +
  • 614fb76 (database) - tests: use add-host replace link
  • +
  • a3428f3 (database) - CICD: use drone
  • +
  • 239fef1 (database) - drone: add image_registries volumes
  • +
  • 42858e1 (database) - LICENSE: revert modifications to Apache license
  • +
  • d0fe850 (database) - drone: always pull image
  • +
  • 34a36ad (database) - charts: Nn secret is generated during off-cluster
  • +
  • 064ccf4 (database) - database: create database
  • +
  • 9228992 (database) - chars: change org to imageTag
  • +
  • 9f7810c (database) - database: upgrade to wal-g v1.1
  • +
  • 05783f4 (fluentd) - fluentd:replace the special words
  • +
  • 0739809 (fluentd) - influxdb:replace monitor-influx with influx
  • +
  • f02487c (fluentd) - fluentd: remove docker keyword from charts
  • +
  • 2c96cc0 (fluentd) - docker: use the full name of registry
  • +
  • b20c429 (fluentd) - charts: remove port config
  • +
  • 6dd0197 (fluentd) - travis: add DEV_REGISTRY
  • +
  • c5bec51 (fluentd) - CICD: use drone
  • +
  • f8524b7 (fluentd) - drone: add image_registries volumes
  • +
  • a50878a (fluentd) - LICENSE: revert modifications to Apache license
  • +
  • 14fe20e (fluentd) - drone: always pull image
  • +
  • 4a2f660 (fluentd) - k8s: k8s deprecated api migration
  • +
  • de2dd91 (fluentd) - chars: change org to imageTag
  • +
  • a9f1944 (fluentd) - fluentd: upgrade to fluentd1.14
  • +
  • 7cb4e95 (influxdb) - influxdb: change username to user
  • +
  • 0fdc21b (influxdb) - influxdb: remove docker keyword from charts
  • +
  • b2acddb (influxdb) - influxdb: change default path
  • +
  • ba88919 (influxdb) - influxdb: add check_env function
  • +
  • 9117401 (influxdb) - influxdb: modify init_influxdb has_bucket
  • +
  • 092a3e6 (influxdb) - chart: pod not readiness
  • +
  • 51de380 (influxdb) - travis: add DEV_REGISTRY
  • +
  • 66d7667 (influxdb) - docker: replace influxdb base image
  • +
  • 3aa3094 (influxdb) - CICD: use drone
  • +
  • 14b9c24 (influxdb) - drone: add image_registries volumes
  • +
  • 02b4cd1 (logger) - logger:replace the special words
  • +
  • 114b5d5 (logger) - reids: delete the logger prefix of redis
  • +
  • 639278a (logger) - redis: remove logger from redis conf
  • +
  • 90195e2 (logger) - go: remove GOOS and GOARCH
  • +
  • 31e2e27 (logger) - logger: remove docker keyword from charts
  • +
  • 8fbd9fa (logger) - docker: use the full name of registry
  • +
  • b39df2d (logger) - charts: remove redis\nsqd port config
  • +
  • 35d6d07 (logger) - travis: add DEV_REGISTRY
  • +
  • 69aabf5 (logger) - tests: remove docker link
  • +
  • e916644 (logger) - CICD: use drone
  • +
  • d6872b7 (logger) - drone: add image_registries volumes
  • +
  • 37801da (logger) - LICENSE: revert modifications to Apache license
  • +
  • cfb4b38 (logger) - drone: always pull image
  • +
  • 8bda3bf (logger) - go: bump go mod
  • +
  • e13ebfc (logger) - chars: change org to imageTag
  • +
  • 38e6d8d (minio) - minio:replace the special words
  • +
  • d6925dd (minio) - minio: remove docker keyword from charts
  • +
  • d56bc39 (minio) - docker: use the full name of registry
  • +
  • e4696cc (minio) - travis: add DEV_REGISTRY
  • +
  • 70c5c79 (minio) - minio: use latest version
  • +
  • 773cf6c (minio) - Makefile: remove DEV_REGISTRY ?=
  • +
  • 5ce5bc6 (minio) - CICD: use drone
  • +
  • 5da8be3 (minio) - drone: add image_registries volumes
  • +
  • c1f0611 (minio) - LICENSE: revert modifications to Apache license
  • +
  • b73f792 (minio) - drone: always pull image
  • +
  • 79d1c93 (minio) - go: bump go mod
  • +
  • c448899 (minio) - chars: change org to imageTag
  • +
  • 15ee49e (minio) - minio: migrate deprecated warning
  • +
  • 9968a1a (minio) - minio: upgrade to golang1.7
  • +
  • 14fedd2 (monitor) - monitor:replace the special works
  • +
  • 52c431a (monitor) - reids: delete the logger prefix of redis
  • +
  • 2c95b47 (monitor) - redis: remove logger from redis conf
  • +
  • da9bc56 (monitor) - monitor:remove influxdb
  • +
  • 53f47b9 (monitor) - grafana: use grafana docker image
  • +
  • 5bdb188 (monitor) - grafana: use grafana docker image
  • +
  • c0586dd (monitor) - monitor: remove docker keyword from charts
  • +
  • 87d02b6 (monitor) - charts: add nodes and persistentvolumes rule
  • +
  • 1b5598f (monitor) - monitor: modify grafana dashboard with FLUX and pretty config.toml
  • +
  • bcbc0d5 (monitor) - docker: use the full name of registry
  • +
  • 9418c9e (monitor) - monitor: fix upload dashboard error and modify INFLUXDB input
  • +
  • 589f29a (monitor) - travis: add DEV_REGISTRY
  • +
  • f776f8a (monitor) - CICD: use drone
  • +
  • 6ca3060 (monitor) - drone: add image_registries volumes
  • +
  • 6a9ffb2 (monitor) - LICENSE: revert modifications to Apache license
  • +
  • 45e41ed (monitor) - drone: always pull image
  • +
  • 654d407 (monitor) - k8s: k8s deprecated api migration
  • +
  • 41e9b9c (monitor) - chars: change org to imageTag
  • +
  • 99c10d3 (monitor) - charts: update cert-manager api version
  • +
  • 9bf83c4 (monitor) - oauth: user oauth passport
  • +
  • a128f6d (monitor) - chart: change certManagerEnabled to boolean type
  • +
  • 8f897fe (monitor) - chart: set the domain depends certManagerEnabled
  • +
  • ba6d793 (nsqd) - README:update travis build status
  • +
  • 49879c4 (nsqd) - nsqd: minimum git clone code
  • +
  • c5e2680 (nsqd) - nsqd: remove docker keyword from charts
  • +
  • 21dd17b (nsqd) - docker: use the full name of registry
  • +
  • 7d86b3c (nsqd) - charts: remove port config
  • +
  • c073d95 (nsqd) - travis: add DEV_REGISTRY
  • +
  • 55c297c (nsqd) - CICD: use drone
  • +
  • 165c2ae (nsqd) - drone: add image_registries volumes
  • +
  • 9c6a1f8 (nsqd) - LICENSE: revert modifications to Apache license
  • +
  • 9283098 (nsqd) - drone: always pull image
  • +
  • 46acf8a (nsqd) - k8s: k8s deprecated api migration
  • +
  • 43caf80 (nsqd) - chars: change org to imageTag
  • +
  • 6897471 (nsqd) - nsqd: use official image
  • +
  • 297bc05 (redis) - redis:replace the special words
  • +
  • f5f8b5e (redis) - reids: delete the logger prefix of redis
  • +
  • af7b657 (redis) - redis: change logger-redis to redis
  • +
  • 8dca154 (redis) - redis: remove logger from redis conf
  • +
  • eaeda2d (redis) - redis: remove docker keyword from charts
  • +
  • 53c6358 (redis) - docker: use the full name of registry
  • +
  • ae37416 (redis) - charts: remove port config
  • +
  • e985656 (redis) - travis: add DEV_REGISTRY
  • +
  • 423336a (redis) - CICD: use drone
  • +
  • be64ab4 (redis) - drone: add image_registries volumes
  • +
  • 3bec735 (redis) - LICENSE: revert modifications to Apache license
  • +
  • 4f934f6 (redis) - drone: always pull image
  • +
  • 359b878 (redis) - chars: change org to imageTag
  • +
  • 83b8ac2 (registry) - workflow:replace the special words
  • +
  • 869b280 (registry) - registry: remove docker keyword from charts
  • +
  • 999c1e9 (registry) - docker: use the full name of registry
  • +
  • 5652da9 (registry) - travis: add DEV_REGISTRY
  • +
  • cc8c6c2 (registry) - CICD: use drone
  • +
  • c7bdbd0 (registry) - CICD: pretty .drone.yaml format
  • +
  • 5c55a38 (registry) - test: use add-host replace link
  • +
  • f8866f3 (registry) - drone: add image_registries volumes
  • +
  • 6c8292f (registry) - LICENSE: revert modifications to Apache license
  • +
  • 1d50f2c (registry) - drone: always pull image
  • +
  • efbca6d (registry) - chars: change org to imageTag
  • +
  • 2eafc59 (registry-proxy) - registry-proxy: update nginx
  • +
  • 071bd86 (registry-proxy) - charts: upgrade k8s newer API versions
  • +
  • c72db96 (registry-proxy) - registry-proxy: change travis icon url
  • +
  • 63ffb92 (registry-proxy) - registry-proxy:replace the special works
  • +
  • 1d904a6 (registry-proxy) - registry-proxy: remove docker keyword from charts
  • +
  • c8200b1 (registry-proxy) - docker: use the full name of registry
  • +
  • d3fa939 (registry-proxy) - travis: add DEV_REGISTRY
  • +
  • 5a8b353 (registry-proxy) - CICD: use drone
  • +
  • 703d05a (registry-proxy) - drone: add image_registries volumes
  • +
  • aa71db1 (registry-proxy) - LICENSE: revert modifications to Apache license
  • +
  • 710c126 (registry-proxy) - drone: always pull image
  • +
  • 2dcc5e6 (registry-proxy) - chars: change org to imageTag
  • +
+ +
+ + + + + + + + + + + + + + + + +
+

Drycc Workflow v1.4.0

+
New Drycc Workflow Release v1.4.0
+ +

These release notes for Drycc Workflow v1.3.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.4.0, please refer to the following change summary.

+

Workflow ## v1.3.0 -> v1.4.0

+

Releases

+
    +
  • builder v1.1.0 -> v1.2.0
  • +
  • slugbuilder v1.1.1 -> v1.2.0
  • +
  • dockerbuilder v1.1.1 -> v1.1.2
  • +
  • controller v1.2.1 -> v1.3.0
  • +
  • slugrunner v1.1.1 -> v1.1.2
  • +
  • database v1.0.1 -> v1.0.2
  • +
  • fluentd v1.0.1 -> v1.1.0
  • +
  • redis v1.0.0 -> v1.1.0
  • +
  • logger v1.0.0 -> v1.1.0
  • +
  • minio v1.0.1 -> v1.1.0
  • +
  • monitor v1.0.1 -> v1.1.0
  • +
  • nsqd v1.0.0 -> v1.1.0
  • +
  • registry v1.0.2 -> v1.0.3
  • +
  • registry-proxy v1.0.0 -> v1.0.1
  • +
+

Features

+
    +
  • fc7d93f (builder) - builder: use go-dev
  • +
  • 0c2159e (builder) - builder: fmt code and add create_bucket script
  • +
  • 1b88340 (controller) - controller: remove deprecated api
  • +
  • a92fdeb (controller) - routable: ingress support routable
  • +
  • 1e3eab3 (controller) - maintenance: add maintenance support for ingress
  • +
  • 56b9dd0 (controller) - crt: support containerd-ctr
  • +
  • 5fc3b46 (controller) - controller: add ephemeral-storage restriction
  • +
  • d677e52 (controller) - controller: add a volume command
  • +
  • 5f1323a (controller) - controller:drycc run cmd add –mount para
  • +
  • 74c36a5 (controller) - tasks: add distributed async task
  • +
  • 139c3ca (controller) - tasks: change nsq reader to async
  • +
  • f237d74 (controller) - controller:add drycc resource cmd
  • +
  • 41b46d0 (controller) - controller:add drycc resource cmd improvement
  • +
  • c26f7d8 (controller) - controller: add LimitRanges support
  • +
  • 45b5d1b (controller) - users: add users status api
  • +
  • 4e16f9b (controller) - ps:add ps:stop/start command
  • +
  • c659fa9 (controller) - k8s: add k8s cluster domain
  • +
  • 31a625d (controller) - ps:add ps:stop/start command
  • +
  • 00a779a (fluentd) - fluentd: support containerd log format
  • +
  • f3f1bd4 (fluentd) - nsqd: add stateless nsqd cluster support
  • +
  • db7147c (fluentd) - mirrors: delete aliyun mirrors
  • +
  • 689c12e (logger) - nsqd: add stateless nsqd cluster support
  • +
  • 78ccc5d (logger) - redis: add redis client cluster support
  • +
  • 9843f2c (logger) - k8s: add k8s cluster domain
  • +
  • 6ba122e (minio) - minio: add pvc support
  • +
  • 6973550 (monitor) - monitor: add ingress for monitor
  • +
  • cd73305 (monitor) - charts: add volumeName support
  • +
  • 4769fe9 (monitor) - nsqd: add stateless nsqd cluster support
  • +
  • 87806df (monitor) - k8s: add k8s cluster domain
  • +
  • 4db40c4 (nsqd) - nsqd: add stateless nsqd cluster support
  • +
  • b6f3d4f (nsqd) - nsqd: add stateless nsqd cluster support
  • +
  • 74b85bb (redis) - redis: change redis to statefulset
  • +
  • ff98b50 (slugbuilder) - slugbuilder: delete build hook
  • +
  • b201c2f (slugbuilder) - buildpacks: use drycc buildpacks
  • +
+

Fixes

+
    +
  • 0ec042d (builder) - test: fix test case error
  • +
  • 4fb113b (builder) - build: base image replace by alpine
  • +
  • 443df48 (builder) - minio: fix not bucket error
  • +
  • 3dab5b0 (builder) - minio: create bucket error
  • +
  • 734fca6 (controller) - autoscale: Fix for autoscale on k8s-1.9+ without breaking manual scaling
  • +
  • a7dcd10 (controller) - controller: test pass
  • +
  • 93f0f2e (controller) - controller: fix migrations error
  • +
  • 4724375 (controller) - controller: fix test error
  • +
  • 7bacf29 (controller) - charts: fix clusterrole
  • +
  • 90957f7 (controller) - pod: sort events error
  • +
  • 440b13e (controller) - controller: review table structure
  • +
  • 0a470a6 (controller) - controller: bump tornado 5.1.1
  • +
  • e39218b (controller) - pynsq: no current event loop in thread
  • +
  • 1d8630e (controller) - tests: fix test_task.py run error
  • +
  • 1ff1202 (controller) - controller: fix test case
  • +
  • d8c0da3 (controller) - settings: fix env name
  • +
  • 6d8fd36 (database) - 003_restore_from_backup.sh: ignore script exit 1
  • +
  • e0394a9 (database) - minio: fix not bucket error
  • +
  • f35f252 (database) - mc: fix create_bucket error
  • +
  • 74d6886 (database) - postgres: recovery mode not run
  • +
  • e50d0c1 (dockerbuilder) - caddy: fix caddy not start
  • +
  • f3bec7a (fluentd) - influxdb: fix influxdb host and port
  • +
  • bc19f27 (fluentd) - charts: skipped value for daemon_environment: Not a table
  • +
  • 338d623 (logger) - logger: logger not run in alpine
  • +
  • 7788302 (minio) - minio: bump minio version
  • +
  • 619eed0 (minio) - fix: use go mod replace dep
  • +
  • 3b42122 (monitor) - monitor: fix host error
  • +
  • 67998ef (monitor) - influxdb: replace drycc-monitor-influxapi to drycc-monitor-influx-api
  • +
  • 2cc361c (registry) - registry: fix test case
  • +
  • 548297a (registry) - minio: fix not bucket error
  • +
  • 5412ddb (registry) - minio: create bucket error
  • +
  • d0d629e (slugbuilder) - slugbuilder:fix normalize_storage path
  • +
  • d76ecbe (slugbuilder) - slugbuilder: use v3 api
  • +
  • c505e18 (slugbuilder) - shellcheck: SC2039
  • +
+

Style

+
    +
  • c893a17 (builder) - builder: fmt code
  • +
  • bba5795 (controller) - controller: format code
  • +
  • d36082b (controller) - controller: fix pep8
  • +
  • 66026f2 (controller) - resource: standardize the naming of resource
  • +
  • 03d7e2c (controller) - servicecatalog: change servicecatalog to svcat
  • +
  • 49dbb6d (controller) - controller: flake8 upgrade
  • +
  • cbfc108 (monitor) - monitor: format charts and dashboard
  • +
  • ee85954 (slugbuilder) - slugbuilder: use shellcheck
  • +
  • 3afed2e (slugbuilder) - docker: simplify dockerfile
  • +
  • 36b7f68 (slugrunner) - docker: simplify dockerfile
  • +
+

Maintenance

+
    +
  • 61bb0ef (builder) - aws: upgrade aws sdk version
  • +
  • 0f2e074 (builder) - chore: use go mode replace dep
  • +
  • e9a2219 (builder) - builder: delete glide up
  • +
  • bb8c518 (builder) - registry: del quay.io
  • +
  • fa6d02f (builder) - builder: upgrade go.sum
  • +
  • 9d61e8d (builder) - build: upgrade go.mod
  • +
  • d763a98 (builder) - charts: upgrade k8s newer API versions
  • +
  • d1bc1aa (builder) - pkg: upgrade to new drycc/pkg
  • +
  • 02b1e98 (builder) - builder: update go mod
  • +
  • 8e17d65 (builder) - builder: change alpine repositories
  • +
  • f32b723 (builder) - mirrors: delete aliyun mirrors
  • +
  • e33dc61 (builder) - minio: use bin mc replace docker images
  • +
  • 3ab4f1c (builder) - builder: update controller-sdk-go
  • +
  • b2adfac (builder) - heroku: remove heroku-16 support
  • +
  • f429ac8 (builder) - builder: set GIT_LOCK_TIMEOUT to 30 minutes
  • +
  • 7197c83 (builder) - go.mod:upgrade require pkg controller-sdk-go
  • +
  • 5f3e22d (controller) - deps: bump django from 1.11.21 to 1.11.22 in /rootfs
  • +
  • 1db645a (controller) - deps: bump django from 1.11.22 to 1.11.23 in /rootfs
  • +
  • fbe8067 (controller) - deps: bump django from 1.11.23 to 1.11.29 in /rootfs
  • +
  • 537d667 (controller) - registry: del quay.io
  • +
  • a23c65b (controller) - deps: update all deps to the latest version
  • +
  • 546337e (controller) - charts: upgrade k8s newer API versions
  • +
  • 06023f8 (controller) - workflow-manager: del workflow-manager
  • +
  • bba5736 (controller) - controller: change cluster-issuer location
  • +
  • 6c43661 (controller) - Certificatechange cluster-issuer location
  • +
  • 39a4728 (controller) - controller:change cluster-issuer location del controller-cluster-issuer.yaml
  • +
  • 9e96d3f (controller) - Certificate:upgrade version cert-manager.io/v1alpha2
  • +
  • 8e68049 (controller) - docker: use INDEX_URL replace index.docker.io
  • +
  • 8fda205 (controller) - cert_manager: change cert_manager_enabled to global
  • +
  • 6fefb6d (controller) - charts: change platform_domain to global
  • +
  • 064b2ad (controller) - maintenance: remove maintenance support
  • +
  • b8797c9 (controller) - workflow: remove namespace
  • +
  • 1b20d76 (controller) - quota: add kube quota config
  • +
  • d780075 (controller) - pod: add pod default resources support
  • +
  • 3d72c08 (controller) - rename: rename ingress name
  • +
  • 0aa6ab9 (controller) - mirrors: delete aliyun mirrors
  • +
  • 7533a65 (controller) - heroku: remove heroku-16 support
  • +
  • e5a885d (controller) - controller:check mount volume path
  • +
  • 9014e74 (controller) - test: optimization Dockerfile.test
  • +
  • 0b6ebb2 (controller) - tasks: change apply_async parameters
  • +
  • 835f009 (controller) - wsgi: add tornado 6 support
  • +
  • 67a4ad7 (controller) - utils: use threads replace asyncio
  • +
  • a28949b (controller) - ldap: add AUTH_LDAP_USER_FLAGS_BY_GROUP
  • +
  • a903209 (controller) - charts: add custom controller environment variables support
  • +
  • e0e783e (controller) - ldap: change filter style
  • +
  • d760825 (controller) - scheduler: remove debug log
  • +
  • a25928e (controller) - wsgi: remove a wsgi.py file
  • +
  • 7b2696e (controller) - log: disable nsq.client info log
  • +
  • 8d5c07b (controller) - charts: add default environment
  • +
  • 025f4a2 (controller) - controller: change quota name
  • +
  • ebda60e (controller) - controller: review pvc code
  • +
  • 8832ba9 (controller) - controller: change status\binding model type and mount path check container_types
  • +
  • 7148d04 (controller) - controller: add overcommit cpu and ram support
  • +
  • 4d2087c (controller) - limits: modify limits unit verification
  • +
  • af36970 (controller) - api: check cpu/memory range for api
  • +
  • 329355b (controller) - volumes: modify the volume size
  • +
  • 9dfee09 (controller) - LimitRanges: modify the default limits
  • +
  • 5205bca (controller) - controller: improve the details of certificate
  • +
  • 7ebecdf (database) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z
  • +
  • 6415e2c (database) - postgres: upgrade to pg13
  • +
  • 12e6806 (database) - charts: upgrade k8s newer API versions
  • +
  • d294509 (database) - minio: use canary minio test
  • +
  • 1bad02e (database) - mirrors: delete aliyun mirrors
  • +
  • d51420b (database) - minio: use bin mc replace docker images
  • +
  • 4133d05 (dockerbuilder) - dockerbuilder: update caddy and kaniko
  • +
  • 6b4dd18 (dockerbuilder) - minio: use bin mc replace docker images
  • +
  • 6df9b7c (fluentd) - deps-dev: update rake requirement from ~> 10.0 to ~> 12.3
  • +
  • c2490f8 (fluentd) - fluentd: upgrade fluentd
  • +
  • be4a56a (fluentd) - fluentd: add Gemfile.lock
  • +
  • 2237f75 (fluentd) - charts: upgrade k8s newer API versions
  • +
  • c574065 (fluentd) - charts: upgrade k8s newer API versions
  • +
  • 52b8084 (fluentd) - router: delete obsolete router code
  • +
  • 3b3cceb (fluentd) - fluentd: remove manifests dir
  • +
  • 25c6702 (fluentd) - nsqd: change var name
  • +
  • bd571be (fluentd) - nsqd: change DRYCC_NSQD_ADDRESSES to DRYCC_NSQD_ADDRS
  • +
  • 72aa4e6 (fluentd) - influxdb: change influxdb service name
  • +
  • bd61903 (logger) - logger: use go mod replace dep
  • +
  • 69c63a1 (logger) - logger: update go.mod
  • +
  • 3aa9cd7 (logger) - registry: del quay.io
  • +
  • f058496 (logger) - nsqd: change var name
  • +
  • 6d9787c (logger) - nsqd: change DRYCC_NSQD_ADDRESSES to DRYCC_NSQD_ADDRS
  • +
  • 85ed307 (logger) - logger: standard naming
  • +
  • d88e7b6 (minio) - minio: update minio api to v7
  • +
  • 43715d2 (minio) - minio: upgrade minio
  • +
  • 0e1239b (minio) - minio: use docker.io replace quay.io
  • +
  • f7f047b (minio) - registry: del quay.io
  • +
  • afa7128 (minio) - build: upgrade go.mod
  • +
  • aff2db5 (minio) - charts: upgrade k8s newer API versions
  • +
  • 4547f14 (minio) - pkg: upgrade to new drycc/pkg
  • +
  • 2769b85 (minio) - minio: use bin mc replace docker images
  • +
  • 35dde8d (monitor) - monitor: update grafana influxdb telegraf
  • +
  • 9e3a949 (monitor) - charts: upgrade k8s newer API versions
  • +
  • 6af0432 (monitor) - workflow-manager: remove workflow-manager
  • +
  • 0611c07 (monitor) - router: delete obsolete router code
  • +
  • be04824 (monitor) - cert_manager: change cert_manager_enabled to global
  • +
  • 3780165 (monitor) - charts: change platform_domain to global
  • +
  • 50b04e1 (monitor) - influxdb: remove influxdb admin ui
  • +
  • 6ab4d68 (monitor) - influxdb: remove unuse port
  • +
  • f1510bd (monitor) - monitor: update grafana dashboard,telegraf inputs.kubernetes
  • +
  • f36de2c (monitor) - pvc: upgrade to new format
  • +
  • fc78a0a (monitor) - workflow: remove namespace
  • +
  • e85890f (monitor) - monitor: monitoring nsqd and redis separately
  • +
  • 694f6b1 (monitor) - mirrors: delete aliyun mirrors
  • +
  • 4aea36a (monitor) - grafana: add ldap support for grafana
  • +
  • 68fc30f (nsqd) - nsq: update nsq
  • +
  • 16f32aa (nsqd) - charts: upgrade k8s newer API versions
  • +
  • 04db389 (redis) - reids: update to redis 6
  • +
  • 3f01bab (redis) - charts: upgrade k8s newer API versions
  • +
  • 647e4be (registry) - registry: del quay.io
  • +
  • 0bbce99 (registry) - charts: upgrade k8s newer API versions
  • +
  • a982b50 (registry) - minio: use bin mc replace docker images
  • +
  • e088da3 (registry-proxy) - ingress: renmae use_native_ingress to use_ingress
  • +
  • 7e88337 (registry-proxy) - nginx: upgrade nginx to mainline
  • +
  • 7204d72 (registry-proxy) - registry: optimizing variable naming
  • +
  • 2eafc59 (registry-proxy) - registry-proxy: update nginx
  • +
  • 071bd86 (registry-proxy) - charts: upgrade k8s newer API versions
  • +
  • c72db96 (registry-proxy) - registry-proxy: change travis icon url
  • +
  • ca9f962 (slugbuilder) - slugbuilder: del BUILDPACK_URL support
  • +
  • 1b74dd5 (slugbuilder) - slugbuilder: add heroku-20 support
  • +
  • 54d4ad2 (slugbuilder) - slugbuilder: del quay.io
  • +
  • a78f37e (slugbuilder) - slugbuilder: add heroku-20 stack
  • +
  • 94ac94a (slugbuilder) - minio: use bin mc replace docker images
  • +
  • 53b4b8b (slugbuilder) - slugbuilder: modify stack priority
  • +
  • 58e2bd2 (slugbuilder) - dockerfile: add WORKDIR /tmp
  • +
  • b29cd04 (slugbuilder) - slugbuilder: add pre_build.sh
  • +
  • 9d319f6 (slugbuilder) - slugbuilder: silent mc command output
  • +
  • d1ec3c9 (slugbuilder) - heroku: remove heroku-16 support
  • +
  • 5048534 (slugbuilder) - slugbuilder: use drycc stack-images
  • +
  • a116537 (slugrunner) - slugrunner: add heroku-20 support
  • +
  • a1196bf (slugrunner) - slugrunner: del quay.io
  • +
  • 64c96d7 (slugrunner) - slugrunner: add heroku-20 stack
  • +
  • cc3e226 (slugrunner) - minio: use bin mc replace docker images
  • +
  • 9130bde (slugrunner) - shellcheck: shellcheck installer
  • +
  • 4ea33e1 (slugrunner) - slugrunner: modify stack priority
  • +
  • 5514e8b (slugrunner) - heroku: remove heroku-16 support
  • +
  • be829fb (slugrunner) - slugrunner: use drycc stack-images
  • +
  • e1e06be (slugrunner) - slugrunner: remove Dockerfile.heroku-16
  • +
+ +
+ + + + + + + + + + + + + + + + +
+

Drycc Workflow v1.3.0

+
New Drycc Workflow Release v1.3.0
+ +

These release notes for Drycc Workflow v1.3.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.2.0, please refer to the following change summary.

+

Workflow ## v1.2.0 -> v1.3.0

+

Releases

+
    +
  • builder v1.0.2 -> v1.1.0
  • +
  • slugbuilder v1.1.0 -> v1.1.1
  • +
  • dockerbuilder v1.1.0 -> v1.1.1
  • +
  • controller v1.2.0 -> v1.2.1
  • +
  • slugrunner v1.1.0 -> v1.1.1
  • +
  • database v1.0.0 -> v1.0.1
  • +
  • fluentd v1.0.0 -> v1.0.1
  • +
  • minio v1.0.0 -> v1.0.1
  • +
  • monitor v1.0.0 -> v1.0.1
  • +
  • registry v1.0.1 -> v1.0.2
  • +
  • workflow-manager v1.0.0 -> v1.0.1
  • +
+

Features

+
    +
  • 9c7cceb (builder) - builder: add app config to env
  • +
+

Fixes

+
    +
  • 7fe44fa (controller) - docker: docker timeout must be an int, float or None
  • +
  • b196550 (controller) - controller: revert release.check_image_access for now
  • +
  • cc3ec13 (workflow-manager) - glide: bump goautoneg
  • +
+

Maintenance

+
    +
  • ef932c4 (builder) - controller-sdk-go: upgrade controller-sdk-go
  • +
  • 4654cf6 (controller) - django-rest-framework: upgrade to 3.9.3
  • +
  • 14121f1 (controller) - deps: bump djangorestframework from 3.9.3 to 3.9.4 in /rootfs
  • +
  • 385acdc (controller) - deps: bump django from 1.11.20 to 1.11.21 in /rootfs
  • +
  • fa312bb (database) - postgres: set max_connections = 1024
  • +
  • 7ebecdf (database) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z
  • +
  • b8878f6 (dockerbuilder) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z
  • +
  • b097451 (fluentd) - fluent: upgrade fluent to v1.4
  • +
  • 4341f9a (minio) - mc: upgrade mc and minio
  • +
  • c1ee2a4 (monitor) - monitor: remove copyrights.tar.gz
  • +
  • 9854260 (registry) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z
  • +
  • acc5627 (slugbuilder) - slugbuilder: internal support for multi buildpack
  • +
  • d58907e (slugbuilder) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z
  • +
  • b39a0c2 (slugrunner) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z
  • +
+ +
+ + + + + + + + + + + + + + + + +
+

Drycc Workflow v1.2.0

+
New Drycc Workflow Release v1.2.0
+ +

These release notes for Drycc Workflow v1.2.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.1.0, please refer to the following change summary.

+

Workflow ## v1.1.0 -> v1.2.0

+

Releases

+
    +
  • builder v1.0.1 -> v1.0.2
  • +
  • slugbuilder v1.0.0 -> v1.1.0
  • +
  • dockerbuilder v1.0.0 -> v1.1.0
  • +
  • controller v1.1.0 -> v1.2.0
  • +
  • slugrunner v1.0.0 -> v1.1.0
  • +
  • registry v1.0.0 -> v1.0.1
  • +
  • registry-proxy v1.0.1 -> v1.0.2
  • +
+

Features

+
    +
  • e5584e3 (controller) - controller: add STACK support
  • +
  • ad34dc1 (dockerbuilder) - kaniko: use kaniko replace docker-py
  • +
  • b81430e (dockerbuilder) - dockerbuilder: change image to image.json format
  • +
  • 60dde96 (slugbuilder) - slugbuilder: add STACK support
  • +
  • fe8b6e5 (slugrunner) - slugrunner: add STACK support
  • +
+

Maintenance

+
    +
  • 942f050 (builder) - registry: remove env DRYCC_REGISTRY_PROXY_PORT
  • +
  • ff7a16f (builder) - registry: remove ecr and gcr registry
  • +
  • ad13683 (builder) - builder: change DRYCC_BUILD_TYPE to DRYCC_STACK
  • +
  • 6def637 (builder) - registry: rename DRYCC_REGISTRY_SERVICE to DRYCC_REGISTRY_PROXY
  • +
  • 5044e22 (builder) - registry: remove registry_secret_prefix
  • +
  • 2ea39cc (builder) - controller-go-sdk: upgrade controller-go-sdk
  • +
  • 6aee0d7 (builder) - registry: optimizing variable naming
  • +
  • f9c62d9 (controller) - domain: added reserved domain check
  • +
  • f5a135b (controller) - migrations: clean old migrations
  • +
  • 4369b2c (controller) - registry: rename DRYCC_REGISTRY_SERVICE to DRYCC_REGISTRY_PROXY
  • +
  • 1057ca5 (controller) - registry: remove registry_secret_prefix
  • +
  • d114b3e (controller) - docker: update docker client
  • +
  • edbe963 (dockerbuilder) - dockerfile: change base image to alpine
  • +
  • fb35baf (dockerbuilder) - registry: rename DRYCC_REGISTRY_SERVICE to DRYCC_REGISTRY_PROXY
  • +
  • 946dbf6 (dockerbuilder) - docker: remove insecure support
  • +
  • 628d853 (dockerbuilder) - proxy: add registry proxy
  • +
  • ff27cbd (registry) - env: remove unused env
  • +
  • 7204d72 (registry-proxy) - registry: optimizing variable naming
  • +
+ +
+ + + + + + + + + + + +
+
+
+ + +
+ + + + + + diff --git a/blog/releases/index.html b/blog/releases/index.html new file mode 100644 index 000000000..fd5d440a6 --- /dev/null +++ b/blog/releases/index.html @@ -0,0 +1,445 @@ + + + + + + + + + + + + + + + + + + + + + +Release | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + +
+
Posts in 2024
+
    +
  • +
    +
    Drycc Workflow v1.7.8
    +

    01.05.2024 in Release

    + + + + + + +

    Workflow ## v1.7.7 -> v1.7.8 Releases builder v1.6.0 -> v1.7.0 controller v1.8.0 -> v1.9.0 workflow-cli v1.6.0 -> v1.7.0 Features 384c7ee (builder) - domain: add procfile_type 26c8c7f (controller) - domain: add procfile_type bd49789 …

    +

    Read more

    +
    +
  • +
  • +
    +
    Drycc Workflow v1.7.7
    +

    30.04.2024 in Release

    + + + + + + +

    Workflow ## v1.7.6 -> v1.7.7 Releases builder v1.5.1 -> v1.6.0 controller v1.7.0 -> v1.8.0 database v1.2.1 -> v1.3.0 passport v1.2.0 -> v1.3.0 imagebuilder v1.1.1 -> v1.2.0 fluentbit v0.0.1 -> v0.0.2 logger v1.3.3 -> v1.3.4 …

    +

    Read more

    +
    +
  • +
  • +
    +
    Drycc Workflow v1.7.6
    +

    27.02.2024 in Release

    + + + + + + +

    Workflow ## v1.7.5 -> v1.7.6 Releases storage v0.0.4 -> v0.0.5 Maintenance 6cb63b6 (storage) - seaweedfs: bump version 3.63

    +

    Read more

    +
    +
  • +
  • +
    +
    Drycc Workflow v1.7.5
    +

    27.02.2024 in Release

    + + + + + + +

    These release notes for Drycc Workflow v1.7.5 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.7.4, please refer to the following change summary. …

    +

    Read more

    +
    +
  • +
  • +
    +
    Drycc Workflow v1.7.2
    +

    29.01.2024 in Release

    + + + + + + +

    These release notes for Drycc Workflow v1.7.2 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.7.1, please refer to the following change summary. …

    +

    Read more

    +
    +
  • +
+
Posts in 2023
+
    +
  • +
    +
    Drycc Workflow v1.7.0
    +

    08.12.2023 in Release

    + + + + + + +

    These release notes for Drycc Workflow v1.7.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.6.0, please refer to the following change summary. …

    +

    Read more

    +
    +
  • +
+
Posts in 2022
+
    +
  • +
    +
    Drycc Workflow v1.6.0
    +

    21.10.2022 in Release

    + + + + + + +

    These release notes for Drycc Workflow v1.6.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.5.0, please refer to the following change summary. …

    +

    Read more

    +
    +
  • +
  • +
    +
    Drycc Workflow v1.5.0
    +

    06.10.2022 in Release

    + + + + + + +

    These release notes for Drycc Workflow v1.5.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.4.0, please refer to the following change summary. …

    +

    Read more

    +
    +
  • +
+
Posts in 2021
+
    +
  • +
    +
    Drycc Workflow v1.4.0
    +

    06.10.2021 in Release

    + + + + + + +

    These release notes for Drycc Workflow v1.3.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.4.0, please refer to the following change summary. …

    +

    Read more

    +
    +
  • +
+
Posts in 2020
+
    +
  • +
    +
    Drycc Workflow v1.3.0
    +

    06.10.2020 in Release

    + + + + + + +

    These release notes for Drycc Workflow v1.3.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.2.0, please refer to the following change summary. …

    +

    Read more

    +
    +
  • +
+ +
+
+ +
+ +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/blog/releases/index.xml b/blog/releases/index.xml new file mode 100644 index 000000000..dba538ceb --- /dev/null +++ b/blog/releases/index.xml @@ -0,0 +1,1803 @@ + + + Drycc – Release + /blog/releases/ + Recent content in Release on Drycc + Hugo -- gohugo.io + en + + + + + + + + + + + Blog: Drycc Workflow v1.7.8 + /blog/2024/05/01/drycc-workflow-v1.7.8/ + Wed, 01 May 2024 00:00:00 +0000 + + /blog/2024/05/01/drycc-workflow-v1.7.8/ + + + + <h2 id="workflow--v177---v178">Workflow ## v1.7.7 -&gt; v1.7.8<a class="td-heading-self-link" href="#workflow--v177---v178" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>builder v1.6.0 -&gt; v1.7.0</li> +<li>controller v1.8.0 -&gt; v1.9.0</li> +<li>workflow-cli v1.6.0 -&gt; v1.7.0</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/384c7ee9c69201b4d3280bb1582e50ad40210b8f"><code>384c7ee</code></a> (builder) - domain: add procfile_type</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/26c8c7f1a2ed3445fc4a52a5f7b8e7cace8a12e8"><code>26c8c7f</code></a> (controller) - domain: add procfile_type</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/bd49789b2aa8bbb8da440d63c83e339fd69d4774"><code>bd49789</code></a> (workflow-cli) - domain: add procfile_type</li> +</ul> + + + + + + Blog: Drycc Workflow v1.7.7 + /blog/2024/04/30/drycc-workflow-v1.7.7/ + Tue, 30 Apr 2024 00:00:00 +0000 + + /blog/2024/04/30/drycc-workflow-v1.7.7/ + + + + <h2 id="workflow--v176---v177">Workflow ## v1.7.6 -&gt; v1.7.7<a class="td-heading-self-link" href="#workflow--v176---v177" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>builder v1.5.1 -&gt; v1.6.0</li> +<li>controller v1.7.0 -&gt; v1.8.0</li> +<li>database v1.2.1 -&gt; v1.3.0</li> +<li>passport v1.2.0 -&gt; v1.3.0</li> +<li>imagebuilder v1.1.1 -&gt; v1.2.0</li> +<li>fluentbit v0.0.1 -&gt; v0.0.2</li> +<li>logger v1.3.3 -&gt; v1.3.4</li> +<li>storage v0.0.5 -&gt; v0.1.0</li> +<li>gateway v0.0.2 -&gt; v0.0.3</li> +<li>monitor v1.4.0 -&gt; v1.4.1</li> +<li>redis v1.3.2 -&gt; v1.4.0</li> +<li>timeseries v0.0.2 -&gt; v0.1.0</li> +<li>prometheus v0.1.1 -&gt; v0.1.2</li> +<li>rabbitmq v1.2.1 -&gt; v1.3.0</li> +<li>registry v1.2.2 -&gt; v1.3.0</li> +<li>registry-proxy v1.2.1 -&gt; v1.2.2</li> +<li>workflow-cli v1.5.2 -&gt; v1.6.0</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/6c1cf5e514543737c38384596abffca1ac96af44"><code>6c1cf5e</code></a> (builder) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/65ae63c4d3aaff3354d162718ff07c0509b4e689"><code>65ae63c</code></a> (builder) - pipeline: add dryccfile support</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/bb7b11de75226c3a1cb9254dfec78a8edda0c864"><code>bb7b11d</code></a> (builder) - auth: add tokens api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/39d022fe0a4106c91ea461f73728490560f8d653"><code>39d022f</code></a> (controller) - ps: add pod logs support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/86056d06d8992172fe02240d7963aa416ec9c754"><code>86056d0</code></a> (controller) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4cf005c1cc4b361af80ef96597e291ebe3baec24"><code>4cf005c</code></a> (controller) - limits: add limits plan support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/bf60e4bdbebb3f3288e0fbd81566c264dd187faf"><code>bf60e4b</code></a> (controller) - controller: add init job</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/98f77a8ceeea6e8a098cd37d79115201c40133e1"><code>98f77a8</code></a> (controller) - pipeline: add dryccfile support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8ce9a83f4bcf46d6039910e052e6ebfa959fd0e8"><code>8ce9a83</code></a> (controller) - cert-manager: add tls events</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7034f5d8347f0c85b40651eaf239a554fd95ae76"><code>7034f5d</code></a> (controller) - config: deploy according to procfile_type</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5554d8f9f26790783d97d6d6128920ffa9b28713"><code>5554d8f</code></a> (controller) - config: add typed_values</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/2c5bbad2d74b1c40c61158477aac9103dac2eff4"><code>2c5bbad</code></a> (controller) - auth: add token api</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/410d34e8e639c973557104c3aee14a85324f3c0f"><code>410d34e</code></a> (database) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/693e4d199b18342e33c7ec68c3a651d29b7d9ad6"><code>693e4d1</code></a> (imagebuilder) - pipeline: add dryccfile support</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/7d9cc0679eac7dd873d8db8f9607e347830b2aa1"><code>7d9cc06</code></a> (imagebuilder) - config: add typed values</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/854e1711180de70bc83d3c65721910df013ef988"><code>854e171</code></a> (passport) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/7ac92557670d915c1e568c7297c5ec1b9620f1a1"><code>7ac9255</code></a> (passport) - oauth2: add authorization code for any grant type</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/4517547e21983dd7192ae8cc985c974ed2c64b51"><code>4517547</code></a> (rabbitmq) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/bccfcb43cd63e62974b55523a75fa994ed560453"><code>bccfcb4</code></a> (redis) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/d8876055c0732c470d17d9205a5188289fdac1ec"><code>d887605</code></a> (registry) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/ff09e5b8279cd3343370bfa58c3acba234621263"><code>ff09e5b</code></a> (storage) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/c6e2ac82c8adc75687dbc814cb2163b06820311e"><code>c6e2ac8</code></a> (timeseries) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/22c4c772e3c9cbfe4f686d2fbe161b6484cdcc12"><code>22c4c77</code></a> (workflow-cli) - apps: change drycc run to async</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/a9e6369153255a6cc84dc73e3095086a34d25ad1"><code>a9e6369</code></a> (workflow-cli) - ps: add pod logs support</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/2bc31c8a2010e147b92827a967238e88dca5b743"><code>2bc31c8</code></a> (workflow-cli) - limits: add limits plan support</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/f40398a555e67a942fbe465d29e1076516941d74"><code>f40398a</code></a> (workflow-cli) - pipeline: add dryccfile support</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/03638ffdaefab5e0c7020f6eb279ddeda99aeded"><code>03638ff</code></a> (workflow-cli) - tls: add tls events</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/91136274d87d2cf9e0d2a1dd313d9b948a5d0a81"><code>9113627</code></a> (workflow-cli) - config: add typed values</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/43ee760c4bc93bc5e5402536a09f05dfd6832b7d"><code>43ee760</code></a> (workflow-cli) - auth: add tokens api</li> +</ul> +<h4 id="fixes">Fixes<a class="td-heading-self-link" href="#fixes" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/50dfe6449cbf50bfcf55421f34f2195cb8d7e26c"><code>50dfe64</code></a> (builder) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ab09b243b8484d8a989327e8e3b41f2a23efa643"><code>ab09b24</code></a> (controller) - healthcheck: delete outdated code</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/52019b541aaaca98b2b6692fec1290d1231e21fe"><code>52019b5</code></a> (controller) - services: default PORT change error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f57ae429fa4d9dbd89c7cf81f805fe9127930219"><code>f57ae42</code></a> (controller) - certificate: failed to create certificate</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/30c3f548324dcfa571a86afbed64ba0d38b72e99"><code>30c3f54</code></a> (controller) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/dbba43ae315644e858eb2330d52cbf636a366a07"><code>dbba43a</code></a> (controller) - service: update port error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e0459c5d43a74c2c38aae6ebf3e207ad8cc9f283"><code>e0459c5</code></a> (controller) - copy: use deepcopy replace copy</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/2122479685d9ce83c986449e20a041de105a2d49"><code>2122479</code></a> (controller) - charts: failed to call webhook</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/53d99775d66648aca41b88992df4ee203cb8f675"><code>53d9977</code></a> (controller) - signals: config limits handle error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/afda287ead80e94a699b3548c01fdfdbd1a6f5a4"><code>afda287</code></a> (controller) - limits: always set default</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/b350cb89e4c313d776592e9e4706909ee72550b5"><code>b350cb8</code></a> (database) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/b48a42243e602637fb04f14cb74d23e23096e2e2"><code>b48a422</code></a> (fluentbit) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/7cebca2a2589c839efbe49cbec6becde85149a8e"><code>7cebca2</code></a> (gateway) - cert-manager: auto tls error</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/190c19bbac3386e277bd7918be5b7f7ad5a25566"><code>190c19b</code></a> (imagebuilder) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/2c6a6f9273a0f5e2c16744f6ac6e77d27a7234a2"><code>2c6a6f9</code></a> (logger) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/10bb98df862bebefcf4142e88c24e8f804e310ba"><code>10bb98d</code></a> (monitor) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/f8225dca4c4ceae7bc4d613e77ae4c8ebf71838c"><code>f8225dc</code></a> (passport) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/06db66c072006f79c10404812ad9f0902cfb52b7"><code>06db66c</code></a> (prometheus) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/f4aff727962b6afe99e89283ce14ebe8d571d9ab"><code>f4aff72</code></a> (rabbitmq) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/88c18ff452bdd478f49dd88f6595ea096e430f2d"><code>88c18ff</code></a> (redis) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/5dcc19d6d47ea30b799ae10e915ebd948b39fc4c"><code>5dcc19d</code></a> (registry) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/092a9398243f19e41ac14cc5fb4f76473848c585"><code>092a939</code></a> (registry-proxy) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/3597ac918db548f837b3262a033d836690378972"><code>3597ac9</code></a> (storage) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/5a49b35d2197c957e43a98e94d38ac8a8ebd894b"><code>5a49b35</code></a> (timeseries) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/0c4a48a84b998b8e7f57f09f307930630e8efd74"><code>0c4a48a</code></a> (workflow-cli) - tls: change issuer options</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/06a2511195bc1f2a3145a73269428200914b4694"><code>06a2511</code></a> (workflow-cli) - tls: info error</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/2f7617e164707830b52f2ca39c7f634ca53842ed"><code>2f7617e</code></a> (builder) - go: bump controller-sdk-go version</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/aae2f2911197e4643e7a999944401d2e5acd884d"><code>aae2f29</code></a> (builder) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/7304980fb22cd0d56e1fa5b1e573b4795ef2ddd9"><code>7304980</code></a> (builder) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/30b648b0d429ba08f89e1d3b49078e40eae2d897"><code>30b648b</code></a> (builder) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/2afa006867a3d4d4501578f0973ff759d87af87f"><code>2afa006</code></a> (builder) - controller-sdk-go: bump version</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/d127a9070a6dd0be1d96860c719d3b4a71eb7bb9"><code>d127a90</code></a> (builder) - config: add typed values</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/32fdfd0e7f54793d3ced05ff42b300173debe866"><code>32fdfd0</code></a> (controller) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0974942fb8a70d9165ef6524744850cf72629a0c"><code>0974942</code></a> (controller) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f401e08d3ffbfee5d84410ad8e31c18a3267513e"><code>f401e08</code></a> (controller) - python: bump python 3.12</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c565959af53e6ab7be7245faea09fd1a30972ac7"><code>c565959</code></a> (controller) - celery: remove retrieve_resource task</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/47be1a10b03d7522a9bc87b9973c8f126db95478"><code>47be1a1</code></a> (controller) - requirements: bump drf 3.15.1</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/99f7468e561d596121bc981294e6ca4baaed2728"><code>99f7468</code></a> (controller) - charts: add config to values.yaml</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7d17f5ca716596ef66046eb5f3606215feb87731"><code>7d17f5c</code></a> (controller) - scale: prohibit scale when there is a running pipeline</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f09e1c9475e64840ff02e23cee30f5911b507a58"><code>f09e1c9</code></a> (controller) - resource: sort services and plans</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e817505fc5dc6a2e9b959b9fd7d63c044f17fcf1"><code>e817505</code></a> (controller) - limits: change default cpu and gpu name</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5531b2ff4b15a6b9804cc0b146b69ee7308a1a83"><code>5531b2f</code></a> (controller) - auth: add password login</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/27473f72e8b7c1f1b6bb9c56493688f346bbcc9c"><code>27473f7</code></a> (controller) - deps: bump gunicorn from 21.2.0 to 22.0.0 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c1ee1c7a3103c938b8b81219da7b14cd30f3eceb"><code>c1ee1c7</code></a> (controller) - deps: bump aiohttp from 3.9.3 to 3.9.4 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/affbcb587360d7750f3faf4d022e36032f0b3266"><code>affbcb5</code></a> (database) - postgres: add patroni and postgres params (#15)</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/f9e4edaf9a2a22b974a2aced48a7890f767da0c0"><code>f9e4eda</code></a> (database) - dockerfile: install vi</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/008b7b675c244d2aff9b86947fe907dbb84185f4"><code>008b7b6</code></a> (database) - dockerfile: install vim instand of vi</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/dbbfee12b2fe9c773d32660a6bcf26674ae2cd61"><code>dbbfee1</code></a> (database) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/2e26c333df5aa90243cff8c5159a6c3a9b499a00"><code>2e26c33</code></a> (database) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/a1b81f20f517743d9f69ecda526095a4e9c3ee36"><code>a1b81f2</code></a> (database) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/bc725e8169b25eda4017012f72b5d970147f0d08"><code>bc725e8</code></a> (fluentbit) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/5d738865825bd083561972373a5dd8796a53be6c"><code>5d73886</code></a> (fluentbit) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/b85072d0177447ac3f05f1f4ccd4c9d7f4a56f99"><code>b85072d</code></a> (fluentbit) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/761174ddb5bc06643a02c145714587816ea06f8a"><code>761174d</code></a> (gateway) - gateway: change secrets name</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/1c304da25eef99568badf3ece29639dd6d8f8564"><code>1c304da</code></a> (gateway) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/b919a4c24b5abb776876df002cc9d4c15cf3d50d"><code>b919a4c</code></a> (gateway) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/3cea298be74856a2fba40b0a35824e0f3018dcab"><code>3cea298</code></a> (imagebuilder) - charts: allow all dns</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/653bcbeec95adcea209299751a3a94f3ebaf2d4f"><code>653bcbe</code></a> (imagebuilder) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/59daeab055610ce6cc584be73dba3767158b9747"><code>59daeab</code></a> (imagebuilder) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/2834a5acb914eecb7708ad3bd3efdcc38243d784"><code>2834a5a</code></a> (logger) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/6685492c2a8493bad3b59dedb201576f7508ff86"><code>6685492</code></a> (logger) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/191cdaf001ab5b916b0edf53aaa2a7558ef7f35a"><code>191cdaf</code></a> (logger) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/b3c3cfa319fe46d30696a2f4637f91636398ffff"><code>b3c3cfa</code></a> (monitor) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/796799db309de06ea54db56a1c0e5f397c858f47"><code>796799d</code></a> (monitor) - grafana: add node metrics dashboard</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/ef2a2228a27e4eddce1ff3b4b56755ab013c47cd"><code>ef2a222</code></a> (monitor) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/9c830909640fddca03329d4a72eb91ab1d913c86"><code>9c83090</code></a> (monitor) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/1a97c2cedd3ace5c567bf32dbd057bd215502662"><code>1a97c2c</code></a> (passport) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/353e1ae932ea4dae5112b8f8225ee502695b11ee"><code>353e1ae</code></a> (passport) - logger: add oauth2_provider logger config</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/fe735c0d8c5a2840349b27ceb081d02729ae50bf"><code>fe735c0</code></a> (passport) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/41d6144a20f24461e1a393d4b1957f5be19f4f3a"><code>41d6144</code></a> (passport) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/979d4740bdd50a12f5110144cf413c3972164c90"><code>979d474</code></a> (passport) - python: bump python 3.12</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/e9f41a121e11becd9dcd6b5422dcc6e209cbeedf"><code>e9f41a1</code></a> (passport) - requirements: bump drf 3.15.1</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/f479f4d5791ac2917679b70f376ec9bf24fa1fd4"><code>f479f4d</code></a> (passport) - charts: add migrate job</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/ad9abf64ad7e2b959d565eaa0016066183444cd0"><code>ad9abf6</code></a> (passport) - passport: migrations add run_before</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/95ac66705669bd4301af9d3ae812e0843eb6a37c"><code>95ac667</code></a> (passport) - passport: optimize the use of master and slave database rules</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/204f7fc62fd0cdf016cd5e95a4d2fd2e6c841b17"><code>204f7fc</code></a> (passport) - deps: bump gunicorn from 21.2.0 to 22.0.0 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/90a6410c0d0864a434b804cf80fe63960afd4493"><code>90a6410</code></a> (prometheus) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/2d8eb44ef28deae27ac54247a008a5351212eea0"><code>2d8eb44</code></a> (prometheus) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/9687a175b58aed22d314557d7254a82ff0a6d3dd"><code>9687a17</code></a> (rabbitmq) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/35d3d5b7e01bebbeeea5442a22f24d40fcbfdd93"><code>35d3d5b</code></a> (rabbitmq) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/6a6564ddef4f26bc81ea3eb9e965fb8e6180d092"><code>6a6564d</code></a> (rabbitmq) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/cb6722f0df93fae95d4480e1929b55e1e78a2a3a"><code>cb6722f</code></a> (redis) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/9553497d89e358022ab539cb3db658def17bc9cb"><code>9553497</code></a> (redis) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/1c8dc07b0167126d292e3db45f23db5d6ff111dc"><code>1c8dc07</code></a> (redis) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/9fa2a32f965d282940cd3f8489ce8959bb2e791f"><code>9fa2a32</code></a> (registry) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/9b09e51c1d548ba4d1c088aff761391092d746e3"><code>9b09e51</code></a> (registry) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/7dbd3902139c8430c18bfb83e4dbce79a6df16a5"><code>7dbd390</code></a> (registry) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/e1d2a33d8c9f20eddce510d79df050b0fe90a94c"><code>e1d2a33</code></a> (registry-proxy) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/3eabfdda5c2a78fc49e73dce382263faad29f5c3"><code>3eabfdd</code></a> (registry-proxy) - charts: remove default limits</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/f8754dad5de5f88bb0f20f46d73e1cbab2aff68e"><code>f8754da</code></a> (registry-proxy) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/7df73166e6ea521587eb2ba5b8e1626cc334d7f3"><code>7df7316</code></a> (registry-proxy) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/861d3b8f5ebc2ee32f11a600b26a14d79e0acdf1"><code>861d3b8</code></a> (storage) - filer: modify the default parameters of the filer</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/5fa08da71087503071fa780ac2469f4d55e7d0c5"><code>5fa08da</code></a> (storage) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/22c4620e0e724b26943260d58d749bb4efd0999b"><code>22c4620</code></a> (storage) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/6c1e29c1bf187e2b754d6f683014dba7a4ebe342"><code>6c1e29c</code></a> (timeseries) - postgres: add patroni params</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/e280d3ff2d799fa1e0738bf6e7585aaba0e72c58"><code>e280d3f</code></a> (timeseries) - dockerfile: install vi</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/5213617c4a5ace9225e1cad8348c736b943c5e25"><code>5213617</code></a> (timeseries) - dockerfile: install vim instand of vi</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/a569a57f06484738d5801651f9e253553347f928"><code>a569a57</code></a> (timeseries) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/b93ec702dcbd0e2306d0290cde2d104d4c5897f3"><code>b93ec70</code></a> (timeseries) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/ff3b8705e65a56f0da392519b54f9b060894ec8c"><code>ff3b870</code></a> (timeseries) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/e334f74a71ffbd5f10baa38da43248d92c051322"><code>e334f74</code></a> (workflow-cli) - healthcheck: delete outdated healthcheck style</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/4f8b960e9ddcd1351b4567935d0a8d98d2aa843d"><code>4f8b960</code></a> (workflow-cli) - auth: add password login</li> +</ul> + + + + + + Blog: Drycc Workflow v1.7.5 + /blog/2024/02/27/drycc-workflow-v1.7.5/ + Tue, 27 Feb 2024 00:00:00 +0000 + + /blog/2024/02/27/drycc-workflow-v1.7.5/ + + + + <p>These release notes for Drycc Workflow v1.7.5 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.7.4, please refer to the following change summary.</p> +<h2 id="workflow--v174---v175">Workflow ## v1.7.4 -&gt; v1.7.5<a class="td-heading-self-link" href="#workflow--v174---v175" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>builder v1.5.0 -&gt; v1.5.1</li> +<li>controller v1.6.3 -&gt; v1.7.0</li> +<li>logger v1.3.2 -&gt; v1.3.3</li> +<li>storage v0.0.3 -&gt; v0.0.4</li> +<li>redis v1.3.1 -&gt; v1.3.2</li> +<li>rabbitmq v1.2.0 -&gt; v1.2.1</li> +<li>registry v1.2.1 -&gt; v1.2.2</li> +<li>workflow-cli v1.5.1 -&gt; v1.5.2</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/95d130a19f63544defbf415d63ea44b650d07da7"><code>95d130a</code></a> (controller) - controller: volume support nfs</li> +</ul> +<h4 id="fixes">Fixes<a class="td-heading-self-link" href="#fixes" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ee2ee15992331922728aabcf03420fbad7b76a1d"><code>ee2ee15</code></a> (controller) - controller: container entrypoint error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/03ea4f87b58f2e3f12505ff0ba43ab655fdf0528"><code>03ea4f8</code></a> (controller) - controller: class property have been deprecated in python 3.11</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5f04d177fa399a7859d4f0d8e13b58e77983c2e9"><code>5f04d17</code></a> (controller) - controller: miss err msg</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/27972a3a48f5fb67283c50b95e58da7b7ef05458"><code>27972a3</code></a> (controller) - controller: load_db_state_to_k8s err</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a005d629bbdd9a5d68f5bb4c480fd9e6b51300c7"><code>a005d62</code></a> (controller) - controller: volume repeat path no error</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/c7a5ba62b8e513f43aad8143e507d23885558834"><code>c7a5ba6</code></a> (rabbitmq) - rabbitmq: cpu usage to high</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/45c20770d8203ae475c127fe82b00bd04334507d"><code>45c2077</code></a> (workflow-cli) - workflow-cli: miss err msg</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/bc738bd6ef19fa222e675058bc0af79b75026308"><code>bc738bd</code></a> (workflow-cli) - workflow-cli: volumes list format</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/35e1c063c5f40fc97f60ab2a0b9f66de37eef383"><code>35e1c06</code></a> (builder) - builder: bump golang 1.22</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/26caa36c197b968909da1a584dff686cd6bcd651"><code>26caa36</code></a> (controller) - deps: bump aiohttp from 3.9.0 to 3.9.2 in /rootfs (#118)</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3d938c4f00b4a972abe948dc814b2cbf41ea2b3b"><code>3d938c4</code></a> (controller) - deps: bump django from 4.2.7 to 4.2.10</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/e625c2f86176c0acff331f58f84da15d96041f21"><code>e625c2f</code></a> (logger) - logger: bump golang 1.22</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/bfa500dc9271bf0a475c50feb8e6be8574953bcd"><code>bfa500d</code></a> (redis) - redis: headless svc does not require ports</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/330209a5c329c0f34b47a07812e7282ad7890208"><code>330209a</code></a> (registry) - registry: headless svc does not require ports</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/48c42eb3d6ef09471d26a65c88f5cd88cd6684e8"><code>48c42eb</code></a> (storage) - storage: change volume index to leveldb</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/f4fde9d2c871162c14ecf0e993093211f49e7c66"><code>f4fde9d</code></a> (storage) - storage: add volume size limit</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/33e3684ec520a83bccdf7623d4b3d1317c10e9a0"><code>33e3684</code></a> (workflow-cli) - workflow-cli: volume support nfs</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/48d59507ab5f40e8a8cea9875b230e9e1b97644d"><code>48d5950</code></a> (workflow-cli) - workflow-cli: bump golang 1.22</li> +</ul> + + + + + + Blog: Drycc Workflow v1.7.6 + /blog/2024/02/27/drycc-workflow-v1.7.6/ + Tue, 27 Feb 2024 00:00:00 +0000 + + /blog/2024/02/27/drycc-workflow-v1.7.6/ + + + + <h2 id="workflow--v175---v176">Workflow ## v1.7.5 -&gt; v1.7.6<a class="td-heading-self-link" href="#workflow--v175---v176" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>storage v0.0.4 -&gt; v0.0.5</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/6cb63b632ab24cecda10e2e772f46e499d678aa5"><code>6cb63b6</code></a> (storage) - seaweedfs: bump version 3.63</li> +</ul> + + + + + + Blog: Drycc Workflow v1.7.2 + /blog/2024/01/29/drycc-workflow-v1.7.2/ + Mon, 29 Jan 2024 00:00:00 +0000 + + /blog/2024/01/29/drycc-workflow-v1.7.2/ + + + + <p>These release notes for Drycc Workflow v1.7.2 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.7.1, please refer to the following change summary.</p> +<h2 id="workflow--v171---v172">Workflow ## v1.7.1 -&gt; v1.7.2<a class="td-heading-self-link" href="#workflow--v171---v172" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>controller v1.6.0 -&gt; v1.6.1</li> +<li>logger v1.3.1 -&gt; v1.3.2</li> +<li>storage v0.0.1 -&gt; v0.0.2</li> +<li>timeseries v0.0.1 -&gt; v0.0.2</li> +<li>prometheus v0.1.0 -&gt; v0.1.1</li> +<li>workflow-cli v1.5.0 -&gt; v1.5.1</li> +</ul> +<h4 id="fixes">Fixes<a class="td-heading-self-link" href="#fixes" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/2fe80a65e2f564abe94a04a4018af101ca10d55d"><code>2fe80a6</code></a> (controller) - resources: after resources instance update, could not delete (#111)</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a4082ad0c4fca861bc713864ec4539249b707c0e"><code>a4082ad</code></a> (controller) - controller: resource status and binding</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e9bfccc307fd9631361eaedd1db0c98fb11f7a9b"><code>e9bfccc</code></a> (controller) - controller: fix multiple volumes mount at one dir error (#116)</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/58d2b4c35020c25e133f46bb48f7b512e41a0f91"><code>58d2b4c</code></a> (logger) - logger: redis conn error block</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/7cb2700c483040869f3fa5ff1af76cf68d8e8711"><code>7cb2700</code></a> (prometheus) - prometheus: prometheus config basic_auth</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/7838c6b63eec363ec0fccbc8a2b455477edb69db"><code>7838c6b</code></a> (storage) - storage: random accesskey secretkey</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/d9dcdfb7350c003a60883c9e70e3afca730d5419"><code>d9dcdfb</code></a> (storage) - storage: pod restart loses data</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/3cbdd29c8dd94d7bd046a3fe817dabbb59887225"><code>3cbdd29</code></a> (storage) - storage: tipd cannot start after deleting pod</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/be7e11fe5a8a861a976c27b69331779b4edd0a3a"><code>be7e11f</code></a> (storage) - storage: jq command not found</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/878f674be07b4aee660ec66830a9fe29473bdaba"><code>878f674</code></a> (storage) - storage: charts updateStrategy error</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/06cfe561e1327690dfcccd7151711053b8126a9a"><code>06cfe56</code></a> (timeseries) - timeseries: the data node ip is incorrect</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7f29f5a98049b0c256728dad38cf63026c45910e"><code>7f29f5a</code></a> (controller) - resources: retrieve resource instance response add message (#112)</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4a84dcdca75a3c1cd037c01777cf410c21c56225"><code>4a84dcd</code></a> (controller) - controller: add deploy default annotations (#113)</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/829d7e560317a0ac20081f6bd4c81f53b547aac4"><code>829d7e5</code></a> (controller) - controller: modify url match service name (#114)</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/30abf6dba46d215d7747b4443826e6e3fac1138a"><code>30abf6d</code></a> (controller) - controller: transfer app ownership in async</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/dc6f45e98ab77a776a620286465da106a8109ba6"><code>dc6f45e</code></a> (controller) - controller: add channel for pod exec</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/af4f3a771d8a7c6f1f99c17acb67704d9f3f921f"><code>af4f3a7</code></a> (controller) - controller: avoid error when secret no data field (#117)</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ca27956696aa6bd2e4adefcc6827f840eefd4b34"><code>ca27956</code></a> (controller) - controller: add pod default security</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/b2e9c647ff2a1e7828946d363b6cfc5bdca2deb7"><code>b2e9c64</code></a> (prometheus) - charts: node-exporter mount root (#2)</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/3cdb2b62fe9e2d6f7506c5215be9e3e7d27254b3"><code>3cdb2b6</code></a> (storage) - storage: bump seaweedfs 3.61</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/00dd2fd331104fd4f7ee58ca35a0906588318d16"><code>00dd2fd</code></a> (storage) - storage: add csi daemonset updateStrategy</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/48e763cb34c3e9b1004ad222a1e4670739e0b9ba"><code>48e763c</code></a> (storage) - storage: add drycc storage upgrade document</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/841df90682a121df819ea11ba8d2dc7843ffcd54"><code>841df90</code></a> (storage) - storage: bump seaweedfs 3.62</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/cefd52e7b031efc05f305a8d8f456229418556f8"><code>cefd52e</code></a> (timeseries) - timeseries: add check data node exists</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/ad1c46e39f392dd676a0f5c8e00b05ed1959cb95"><code>ad1c46e</code></a> (workflow-cli) - resources: resources instance add message</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/9f955c2c97a0a2875f7badadb4f868649cf44b2e"><code>9f955c2</code></a> (workflow-cli) - workflow-cli: add short options cpu</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/65399ef156b9fae2d2fe633cb6b4b63fb6263a1c"><code>65399ef</code></a> (workflow-cli) - workflow-cli: add tty resize support</li> +</ul> + + + + + + Blog: Drycc Workflow v1.7.0 + /blog/2023/12/08/drycc-workflow-v1.7.0/ + Fri, 08 Dec 2023 00:00:00 +0000 + + /blog/2023/12/08/drycc-workflow-v1.7.0/ + + + + <p>These release notes for Drycc Workflow v1.7.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.6.0, please refer to the following change summary.</p> +<h2 id="workflow--v160---v170">Workflow ## v1.6.0 -&gt; v1.7.0<a class="td-heading-self-link" href="#workflow--v160---v170" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>builder v1.4.0 -&gt; v1.5.0</li> +<li>controller v1.5.1 -&gt; v1.6.0</li> +<li>database v1.2.0 -&gt; v1.2.1</li> +<li>passport v1.1.0 -&gt; v1.2.0</li> +<li>imagebuilder v1.1.0 -&gt; v1.1.1</li> +<li>fluentbit v0.0.0 -&gt; v0.0.1</li> +<li>logger v1.3.0 -&gt; v1.3.1</li> +<li>storage v0.0.0 -&gt; v0.0.1</li> +<li>gateway v0.0.0 -&gt; v0.0.1</li> +<li>monitor v1.3.0 -&gt; v1.4.0</li> +<li>redis v1.3.0 -&gt; v1.3.1</li> +<li>timeseries v0.0.0 -&gt; v0.0.1</li> +<li>prometheus v0.0.0 -&gt; v0.1.0</li> +<li>rabbitmq v1.1.0 -&gt; v1.2.0</li> +<li>registry v1.2.0 -&gt; v1.2.1</li> +<li>registry-proxy v1.2.0 -&gt; v1.2.1</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/fcbebdae62029cf4308ffc0adeb8a90cf5550077"><code>fcbebda</code></a> (builder) - builder: use TCPRoute expose service</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d02bb5de832e50a281aa550c738b3eb653549806"><code>d02bb5d</code></a> (controller) - controller: support app dns policy config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9aa968ebccdebaf0971a6dbaa890320b9603a6a9"><code>9aa968e</code></a> (controller) - controller: add svc type support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/62e2d348e2987ebcdcaba993559dc1d30a8ffec6"><code>62e2d34</code></a> (controller) - controller: improve the services api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4393755b08a587e093b7603683ac8b5cdf654ac3"><code>4393755</code></a> (controller) - controller: use gateway replace ingress</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/323045d9ab1589c08a8090d7fe9c73ab6276281d"><code>323045d</code></a> (controller) - controller: add canary support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3f81c975baefd4018e6b3426965b4397456f0d0e"><code>3f81c97</code></a> (controller) - gateways: add addresses field</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4e64aa73d0fde9fe667064b420bd9375dbea8397"><code>4e64aa7</code></a> (controller) - gateways: add addresses field</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/02ad5811d9a8d3e031ce97f8ce85d0ce85be7619"><code>02ad581</code></a> (monitor) - grafana: add pd tikv dashboard</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/2a9e2b042941a911a31c846f71988d6eadeff811"><code>2a9e2b0</code></a> (monitor) - monitor: add storage monitor</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/41d5057b1d4067822edcf597e888b3f23e052d9d"><code>41d5057</code></a> (monitor) - grafana: data source change to prometheus</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/ec035d11f3fcf8486f4240aac8db4890e4520b53"><code>ec035d1</code></a> (monitor) - monitor: usegateway replace ingress</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/c694c98cfab10d8381fd70d7efbbdaedc26caf2d"><code>c694c98</code></a> (monitor) - grafana: add drycc storage seaweedfs dashboard</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/1e1fdc8a8f3ca0974ff5d06ade500afed29a16ed"><code>1e1fdc8</code></a> (passport) - passport: use gateway replace ingress</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/ffdb408776bfa42c80ba5df56730c689a26a821a"><code>ffdb408</code></a> (prometheus) - prometheus: use gateway replace ingress</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/04152b99ca9a8aacddc246af78968191e41ea9d7"><code>04152b9</code></a> (rabbitmq) - rabbitmq: use gateway replace ingress</li> +</ul> +<h4 id="fixes">Fixes<a class="td-heading-self-link" href="#fixes" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/0499500a1335791a89ffcab18e97b22d55ac232c"><code>0499500</code></a> (builder) - builder: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/642491d68a4958cdd6b9b78771ad512d7a462231"><code>642491d</code></a> (builder) - builder: no build log</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/873d146812f40de609100d9a2181d50e79695a54"><code>873d146</code></a> (controller) - controller: do not set entrypoint when no procfile</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d9028c53547b4d53d46d5cba508602ae31d0b391"><code>d9028c5</code></a> (controller) - controller: pip8 error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3efcfb764325255ff9ae4ca47ab82927e88ff9ab"><code>3efcfb7</code></a> (controller) - controller: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/18a3a1a3f777597966da8f8fb21545a18b44d887"><code>18a3a1a</code></a> (controller) - controller: miss service error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/94f796cd2ebd8dd76b4e8073cab039fed0211cae"><code>94f796c</code></a> (controller) - controller: drycc run pod should not restart</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/80f31614601daf30351033c3d9ce8610d4a41581"><code>80f3161</code></a> (controller) - controller: monitor query error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b76f2c5ee9c0e3461737ec7fc6cc73b73a0c043c"><code>b76f2c5</code></a> (controller) - controller: read websocket delay</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b6e068ee19354b98d613985c8c80ec6d42171cc0"><code>b6e068e</code></a> (controller) - controller: metrics sql tpl, gateway pod should not restart, cleanup old rs, update monitor datatbase config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ad9adc645759445702688b2a486ed5d6a1e6a5f7"><code>ad9adc6</code></a> (controller) - controller: rabbitmq sharding err</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/67739075a1134b817e9be97b7d594c1e3790f444"><code>6773907</code></a> (controller) - controller: default k8s pod annotaions</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ffcf1f931c395c3293d909f32a3bf35136b72776"><code>ffcf1f9</code></a> (controller) - controller: under-indented for visual indent</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3afd0cf8e36cec5bbfb59424d5ab036268287d3a"><code>3afd0cf</code></a> (controller) - controller: charts env error</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/769bb8b8dc47ef032377a61e6288c514bff16a9b"><code>769bb8b</code></a> (database) - database: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/769bb8b8dc47ef032377a61e6288c514bff16a9b"><code>769bb8b</code></a> (database) - database: label conflict error</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/6a321c5c802b3a0826bc283f2ffe429769f8753c"><code>6a321c5</code></a> (database) - database: link error</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/558feae9c0edfb4fa7f0dae08f09dc987f822c88"><code>558feae</code></a> (fluentbit) - fluentbit: build charts error</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/98d8a2a6046dffa3213f84fd5cb2f054727ca798"><code>98d8a2a</code></a> (gateway) - fixup</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/8b5dde1d5b0107913f3fca7c90703902fd9a360e"><code>8b5dde1</code></a> (gateway) - gateway: secretName</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/702866da3014497e303eb346be0f88c3c161586c"><code>702866d</code></a> (gateway) - gateway: build status</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/f55dac1cbab3214f60b33992f3e08e186bfa6198"><code>f55dac1</code></a> (imagebuilder) - imagebuilder: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/ac13b5f036e036073d39ddf2e34627be340df078"><code>ac13b5f</code></a> (imagebuilder) - imagebuilder: build svg</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/6b7bbc5a38a8550457585908ac7ce9858c19a034"><code>6b7bbc5</code></a> (logger) - logger: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/0136b5c3ac711f132be35d8382f9df9268145be6"><code>0136b5c</code></a> (monitor) - monitor: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/f03d975fe88a4419f58b54f8d1ac944f968b0bfe"><code>f03d975</code></a> (passport) - passport: DRYCC_GRAFANA_DOMAIN error</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/b530ea8960c173b16968dc5c4da5f8e5f783d9dd"><code>b530ea8</code></a> (passport) - passport: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/be5a0a77f5e037456676af5617cdcd01c2f868ea"><code>be5a0a7</code></a> (passport) - passport: change passport</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/1596c7f723d493b8f17e367999e0315d7f2bc205"><code>1596c7f</code></a> (rabbitmq) - rabbitmq: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/0dc4f6fef0bf147e2cec96cd26f490ae5799fa57"><code>0dc4f6f</code></a> (rabbitmq) - rabbitmq: images-shard error</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/43293ae792f0fc8fa932b7fac865f57510de793d"><code>43293ae</code></a> (redis) - redis: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/ca13b7d7592995b057f1075b3223074c7a9de54b"><code>ca13b7d</code></a> (registry) - registry: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/ab5c7937aac830c2b09b08777f39180248911442"><code>ab5c793</code></a> (registry) - registry: garbage collect error</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/ab0fabc77483f531acaeaa089afce1636200c20a"><code>ab0fabc</code></a> (registry-proxy) - registry-proxy: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/dfc72361f70380697d7090cb0e5bfa61c5264560"><code>dfc7236</code></a> (registry-proxy) - registry-proxy: daemon yaml format</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/42c03bee957cb46b5703cd163cea24c754b3cccc"><code>42c03be</code></a> (storage) - storage: seaweedfs csi error</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/453e41a13ecaedf256dc823c37de3233a2f60cab"><code>453e41a</code></a> (timeseries) - timeseries: could not register node</li> +</ul> +<h4 id="docs">Docs<a class="td-heading-self-link" href="#docs" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/5433c8907bdf4c0320566878a0cfc4f38730f3d4"><code>5433c89</code></a> (gateway) - gateway: add prerequisites</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/2f0c5d8ed5a227507f7848426824759db673eb20"><code>2f0c5d8</code></a> (logger) - logger: change architecture</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/bdd02ebf1178209cca08c0e94d76638405100083"><code>bdd02eb</code></a> (builder) - builder: use dynamic clusterrole name</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/66b4b25ec7c517152a37e375f9a7e86e05cceada"><code>66b4b25</code></a> (builder) - builder: upgrade new controller-go-sdk</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/219d86f6bebf11fce80e2535b724bf8ad94b204b"><code>219d86f</code></a> (builder) - builder: upgrade go.mod</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/91f2f14b0b02af099fe67d4a9be65432de0cb18d"><code>91f2f14</code></a> (builder) - builder: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/9abca168d6a8b26f45a3787c2a80bf5aa6354451"><code>9abca16</code></a> (builder) - woodpecker: use woodpecker ci build status</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/f43dd5030ac3715ab96cfb2a114bd0416b21110c"><code>f43dd50</code></a> (builder) - deps: bump golang.org/x/net from 0.2.0 to 0.7.0</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/0384c69ad46cdabeabb3ca23d01367d047eb0c84"><code>0384c69</code></a> (builder) - builder: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/e3149b95e8c64c1d01444d58de67aa4747c4ebf7"><code>e3149b9</code></a> (builder) - builder: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/d88ea1bd5538e5425cb4cbb856ab82bb5dfe47e8"><code>d88ea1b</code></a> (builder) - builder: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/ba590303b791ff954e41a64ef8babe54170aba3b"><code>ba59030</code></a> (builder) - builder: upgrade go.mod</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/1114dd7d951215c23a6fcefc75a5a71a85391561"><code>1114dd7</code></a> (builder) - builder: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/fe50b626d9edf4908f6c820fa2714e5bde0fbc0e"><code>fe50b62</code></a> (builder) - builder: change drycc gateway listener name</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/db3950cf47cd8f5f0c06c579eec1189c2bcdb0b3"><code>db3950c</code></a> (builder) - builder: remove gateway route</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/5a508bbc9e21852c4e47e598bb42a7c8c75e93ee"><code>5a508bb</code></a> (builder) - builder: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/bbb9029e773f24d2692afdd801e8d09ca75538a3"><code>bbb9029</code></a> (builder) - deps: bump golang.org/x/net from 0.12.0 to 0.17.0</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/f4e5d6ca78d597e020ce398fd9fd132c41591826"><code>f4e5d6c</code></a> (builder) - builder: remove health url</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/9111c8ffd87978db6734d405ef0362c34b9fe4ef"><code>9111c8f</code></a> (builder) - builder: remove io/ioutil</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1f36e3ddd67b29571707c57819bdd8148647359c"><code>1f36e3d</code></a> (controller) - deps: bump django from 4.1.2 to 4.1.6 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e4ab434db6fd84cd35a127c8414951df7e138503"><code>e4ab434</code></a> (controller) - controller: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9f0301e4a138d337d9530807b347775d25ee6525"><code>9f0301e</code></a> (controller) - deps: bump django from 4.1.6 to 4.1.7 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/39324238c251f982072b28fdbb79c04df6230889"><code>3932423</code></a> (controller) - woodpecker: use woodpecker ci build status</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ae8b6b464f3733bd0ca743bd419ecf806646909f"><code>ae8b6b4</code></a> (controller) - setting: support KUBERNETES_LIMITS env config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c10b9bc740f74ed820d36ba5cb6eb462bce3bb7c"><code>c10b9bc</code></a> (controller) - controller: using the api_version instead of hard coding</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e6908cd934ec0360344c2120bbd4bd9a27b6fe9d"><code>e6908cd</code></a> (controller) - controller: upgrade requirements</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b0eba0c0f03b3b74bf6b2d013a8e2fd69dd5fc6c"><code>b0eba0c</code></a> (controller) - controller: add route rules serializer</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/2e4b6a457f6ab66137badecaa0ce5a020e2208e2"><code>2e4b6a4</code></a> (controller) - controller: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7d32b55dad2a0da5a2d539c970608182dfd00c52"><code>7d32b55</code></a> (controller) - controller: upgrade to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f2dc8dd737e44d1297f6a6903bc17392f767a828"><code>f2dc8dd</code></a> (controller) - controller: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5739b8306921408b11b921515cd6dc7a818e6a1a"><code>5739b83</code></a> (controller) - controller: use timescaledb replace influxdb</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/53892cb796b69ba91b1520ee2b1e35bf6516fb57"><code>53892cb</code></a> (controller) - controller: add timeseries</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0fe0eae17d2af7e0a955d6e8041db22a66b64317"><code>0fe0eae</code></a> (controller) - controller: upgrade requirements</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/18b2a915d043cade51e0d4017d08e4ffa9f54dd6"><code>18b2a91</code></a> (controller) - deps: bump aiohttp from 3.8.4 to 3.8.5 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f50874a6e180d9a18fd3a9b9ad1ec1491acae114"><code>f50874a</code></a> (controller) - controller: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/956cd081922f8eeda637530e8397a40d9f7d9c3d"><code>956cd08</code></a> (controller) - controller: change drycc gateway listener name</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9ab3ead47263e0f00f5d31afdad028eedefd6a56"><code>9ab3ead</code></a> (controller) - controller: remove passport url check</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a24c7b011de56845fcc0ffaa78424d60e6cb8aac"><code>a24c7b0</code></a> (controller) - controller: remove gateway route</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f7e539acb9890593d5b3ba970221f333b81abff5"><code>f7e539a</code></a> (controller) - controller: change celery priority</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ab77a529bc9ac2e61a45af4676b8d8796789f014"><code>ab77a52</code></a> (controller) - controller: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8e27501fc6f024bd590508ad827d6a28ca871776"><code>8e27501</code></a> (controller) - controller: dynamic app storage class</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/385978b8f8a07696196974f7f021886448fbc31c"><code>385978b</code></a> (controller) - controller: list_pods datetime format</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b20362c09cf14cbb64148476948481bca11fcf99"><code>b20362c</code></a> (controller) - deps: bump django from 4.2.3 to 4.2.7 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e11ae1ba7d5ef0423b6a51874704739e6a3c86df"><code>e11ae1b</code></a> (controller) - controller: add cluster migrate</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ca6e9dfa4e90c613572faf449445cebabcf1a310"><code>ca6e9df</code></a> (controller) - controller: async mount</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9a7fbfc5e7037dbcd6f8415da1540fc0d0785bff"><code>9a7fbfc</code></a> (controller) - controller: remove FOSSA</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3d55279d81f93783dfdcf0af47c429094fd45019"><code>3d55279</code></a> (controller) - deps: bump aiohttp from 3.8.5 to 3.8.6 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d498a11d8c1179d9ef7e09d4638b10663fc3266d"><code>d498a11</code></a> (controller) - controller: add measure loalancers</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/249a985410e98ab0250af7eaf88c28735f2d7ef1"><code>249a985</code></a> (controller) - deps: bump aiohttp from 3.8.5 to 3.8.6 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b967f5846a006e03d41374266d689a34bd387ba8"><code>b967f58</code></a> (controller) - deps: bump aiohttp from 3.8.6 to 3.9.0 in /rootfs (#107)</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8ca9ed61477fe4c538b0eefbe08f42757f9ec527"><code>8ca9ed6</code></a> (controller) - controller: no longer restrict reserved domain</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/9ff6649b311185927398a12d55451897015ba491"><code>9ff6649</code></a> (database) - database: add init database configure</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/9b4cd26e827862bbcbd2f95eb9ff5aea3031ef80"><code>9b4cd26</code></a> (database) - database: use dynamic clusterrole name</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/b59cde4a41499b1739f51776524c969963706a1e"><code>b59cde4</code></a> (database) - database: remove minio require</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/86462f8e432c21ed691f17544313747a1a95bf2a"><code>86462f8</code></a> (database) - database: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/1e8555a4fa0aa4ab14e276af95eeadb11e7ea2f3"><code>1e8555a</code></a> (database) - database: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/1b762d54948614e8ff8179f91ba4087c1c24cd93"><code>1b762d5</code></a> (database) - database: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/9ffe1fdcc1d1fd33e1d5a69d38c6e2c044f7e002"><code>9ffe1fd</code></a> (database) - database: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/69466d71dfb0fac98f5e2372eae4923d2cb55dde"><code>69466d7</code></a> (database) - database: add database extension</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/beb4b628783f30b8dec35f0ee50d179a27781915"><code>beb4b62</code></a> (database) - database: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/67e27148766a6a16379bccbb160df881e8638cfa"><code>67e2714</code></a> (database) - database: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/8f328f85f28b51b0ea8ce4fe508701c2e875a668"><code>8f328f8</code></a> (fluentbit) - fluentbit: no limit buffer size for kube api</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/fc0552c72b83267e37d67766a0e1040c7d3d59d8"><code>fc0552c</code></a> (fluentbit) - fluentbit: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/63a6cab0c5004ade3c332f16d87f70daaebc12b0"><code>63a6cab</code></a> (fluentbit) - fluentbit: change fluentbit match</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/220f81adae775c21f6eac5fca0f16f2f96962e7d"><code>220f81a</code></a> (fluentbit) - fluentbit: run as no-root</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/aec1393d9e976f2ecb24281a3fc92f5f8bdcf563"><code>aec1393</code></a> (fluentbit) - fluentbit: change configmap name</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/1af4fd24c9e061cb74c3c09af75ad33262a74a19"><code>1af4fd2</code></a> (fluentbit) - fluentbit: change default stream name</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/bef90adfd96f4c713a7de261cb2c66e7cb9900af"><code>bef90ad</code></a> (gateway) - gateway: add route for gateway</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/d523ddb7f794774c5e237c10779fe43713cdc0b6"><code>d523ddb</code></a> (gateway) - gateway: change drycc gateway listener name</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/d9137f4c7681be9edacc2f1123660d0feb961601"><code>d9137f4</code></a> (gateway) - gateway: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/0425dd4e7a0399fd757a80880e67eda2e8c150fc"><code>0425dd4</code></a> (gateway) - gateway: add customListeners</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/3982b86cb7515d42ead064dee86b931f2f4c58a7"><code>3982b86</code></a> (imagebuilder) - imagebuilder: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/3e4e7a329c7532d8787c9c76eb71d938d12fad45"><code>3e4e7a3</code></a> (imagebuilder) - imagebuilder: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/8df6e8e0e6684a4c4a21bf477958b36eb6750e97"><code>8df6e8e</code></a> (imagebuilder) - imagebuilder: upgrade stack version</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/a5601f7588843698b336eccacbc12559dc915779"><code>a5601f7</code></a> (imagebuilder) - imagebuilder: add drycc_app env</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/07465f8bc16cbb15e12d02d522df94265d503c45"><code>07465f8</code></a> (imagebuilder) - imagebuilder: upgrade to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/00d22d2a3c3fa5dce5595fee94bfa8d5a5ca9b2c"><code>00d22d2</code></a> (imagebuilder) - imagebuilder: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/0b7a24e9211acef3252234e4ebce81353c2a8218"><code>0b7a24e</code></a> (imagebuilder) - imagebuilder: upgrade podman/mc/caddy</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/a7d8be869f0b128e9fc6a28ec5c45e5cdca0ea90"><code>a7d8be8</code></a> (imagebuilder) - imagebuilder: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/6b2da83d29e0210a9307e4c5ad1199ed7d7599ce"><code>6b2da83</code></a> (logger) - logger: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/8245b2588a3c350b9c1405c9e56664881534c4b4"><code>8245b25</code></a> (logger) - woodpecker: use woodpecker ci build status</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/f811a74710324fa3ac4ac1fbafc76fe38b042c33"><code>f811a74</code></a> (logger) - logger: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/413f6f60b255f43adbf98cfdbdf2a8325cf3327a"><code>413f6f6</code></a> (logger) - logger: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/2ac6b101d2a205cce7653dcbf635cf1afea8e47e"><code>2ac6b10</code></a> (logger) - logger: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/2581426b262362e04fc4906cfb7d4567ca58d40a"><code>2581426</code></a> (logger) - logger: bump redis to v9</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/364b25aebe91236be41b5974b3643fc1a2b6d352"><code>364b25a</code></a> (logger) - logger: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/dc169a303663ce319037fcf19d0b6bd164b8ee82"><code>dc169a3</code></a> (logger) - logger: use fluentbit replace fluentd</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/d855d91ba3b4651d2a384f3919a39a84f6794b95"><code>d855d91</code></a> (logger) - logger: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/f76723507196a4814dc98e8d9c6403157b6273c4"><code>f767235</code></a> (monitor) - monitor: add off-cluster passport configure</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/ab23936f8d8610f88c061996217b28a8da0ffe3d"><code>ab23936</code></a> (monitor) - monitor: use dynamic clusterrole name</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/47beee0619ee974ad702d813e4db39b187a0507b"><code>47beee0</code></a> (monitor) - monitor: change tikv secret key</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/af7703f7a646a074adf89f9e1d7681bc2a4a8cfb"><code>af7703f</code></a> (monitor) - grafana: remove panel when component off-cluster</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/1b870c2a5b5212d9aeae8dd720bab8190a2b8002"><code>1b870c2</code></a> (monitor) - monitor: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/4a5f1f164c48e93271e28e5a252eb9c87ce4e293"><code>4a5f1f1</code></a> (monitor) - grafana: up ldap api_url config</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/143cabe692cd9d80f909afbe91de0bb8b3c18dea"><code>143cabe</code></a> (monitor) - monitor: add prometheus architecture diagram</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/93091c2dcde35d1ca63450ba08cd2e92b532cdda"><code>93091c2</code></a> (monitor) - woodpecker: use woodpecker ci build status</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/0b7045a1ec3d0061a8434e7e8beed47183287b2c"><code>0b7045a</code></a> (monitor) - grafana: add dashboard kubernetes_deployment_metrics</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/2fb1839f48277724e394b04697d1eb1fb748bf3e"><code>2fb1839</code></a> (monitor) - woodpecker: pipeline config VERSION, when build container image</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/e2724164a3e2855d1f62e4bdcdcff99f6b10e48f"><code>e272416</code></a> (monitor) - monitor: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/abc0e5373a0aef065fd8887e9f8bee5fd13a5e92"><code>abc0e53</code></a> (monitor) - monitor: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/86cc01bd318becf9528feffcfd7c6080c3faafa2"><code>86cc01b</code></a> (monitor) - monitor: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/1cd849ff6f8367375f6d80430e9fe623ebe0162d"><code>1cd849f</code></a> (monitor) - monitor: add postgresql outputs</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/c3205c04418bbb794286eca1bcaa2bf37f26437c"><code>c3205c0</code></a> (monitor) - monitor: change default agent config</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/8c802c01af85fbf40b42c124cd6c72a7c3d8266d"><code>8c802c0</code></a> (monitor) - monitor: add timeseries database</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/e9abc40801c5d90934d19b5ca1b838dbdf9b2431"><code>e9abc40</code></a> (monitor) - monitor: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/6af66cd45685080c5242f6bc6758df35e0c7a69f"><code>6af66cd</code></a> (monitor) - monitor: change drycc gateway listener name</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/d02d718b64837e2869aea66f8a9205d0d3205feb"><code>d02d718</code></a> (monitor) - monitor: remove gateway route</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/3509c2916b9b6aabe709b0057afdacbdc747e462"><code>3509c29</code></a> (monitor) - monitor: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/ed7bfa2f0c17b3e2577f168af719a6c9b3adc436"><code>ed7bfa2</code></a> (monitor) - monitor: optimize env PROMETHEUS_URL</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/da89befad4be1c66ae33740c7a2567b8b83b6b46"><code>da89bef</code></a> (passport) - passport: charts codereview</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/61c4a964022e28f81727efdc858e5ec3a07a71fb"><code>61c4a96</code></a> (passport) - passport: support init app config</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/91010068522d524dfd6680d09915a5444e29a1ba"><code>9101006</code></a> (passport) - passport: add initApplications to charts</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/7dd7fa414f07cc61771cec2d3e98cc1a32d38a00"><code>7dd7fa4</code></a> (passport) - passport: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/4400199ac576b00e0e268ca74d18ff1da15f32bc"><code>4400199</code></a> (passport) - woodpecker: use woodpecker ci build status</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/6b2c546ec6a5dd0311667cab1ac322819ea71918"><code>6b2c546</code></a> (passport) - passport: change secret name to drycc-passport-auto-tls</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/c8bd824c567bfc68df8fd118ad5a9805242507bd"><code>c8bd824</code></a> (passport) - passport: upgrade requirements</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/aee5aefe0c074816b6ba99624f0e2e5fb6462516"><code>aee5aef</code></a> (passport) - passport: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/2d819533a0d6e10534e5a82fac370dd67ef96fc2"><code>2d81953</code></a> (passport) - passport: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/9e662428f39d73651a0c70bd613595c7205c4494"><code>9e66242</code></a> (passport) - passport: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/0fca9982e2ff45bbb5ebe7e3e91fcf0a6af52d94"><code>0fca998</code></a> (passport) - passport: upgrade requirements</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/348252849763e5e96b5908293bd78d84b52b6ad0"><code>3482528</code></a> (passport) - passport: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/0c5ec939da419910c9e98ea97cee9d66916ba14f"><code>0c5ec93</code></a> (passport) - passport: change drycc gateway listener name</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/f7b8f5312d0e9707d2f41b14fb1113e2dfa63dc3"><code>f7b8f53</code></a> (passport) - passport: remove gateway route</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/baf69da9f8b9e1858fa89418e12f3133ab567d88"><code>baf69da</code></a> (passport) - passport: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/fcd45dd063da8338c812d5d8af9c41c6d4405826"><code>fcd45dd</code></a> (passport) - passport: add cluster migrate</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/da6d32a3f09d43209fd1037cb1cff810ddcdcf68"><code>da6d32a</code></a> (prometheus) - prometheus: add prometheus-config</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/683de9e2c03941152196e4fb986cb9ce8e7c1a0f"><code>683de9e</code></a> (prometheus) - prometheus: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/3323300fa23d53bc09e3e70041f4a300aaace68b"><code>3323300</code></a> (prometheus) - prometheus: remove gateway route</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/da1d356e3f978a01fcbbd6b5996ff9272748ed87"><code>da1d356</code></a> (prometheus) - prometheus: change drycc gateway listener name</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/4e7a936edaf8446d48b80e69afd610af6d59a6a4"><code>4e7a936</code></a> (prometheus) - prometheus: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/44c1c6f6a3a11cd1792753c7ba94faf6675e8fa3"><code>44c1c6f</code></a> (prometheus) - prometheus: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/d1f1dda09da1cd0b82dd18854e196b206e27e931"><code>d1f1dda</code></a> (prometheus) - prometheus: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/0836fc1cea544fd928fb6727c99ca9369a1c2134"><code>0836fc1</code></a> (prometheus) - prometheus: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/9e132322c6c36fde1a6ce4f8fabce6ffdb73cb32"><code>9e13232</code></a> (prometheus) - prometheus: add LICENSE</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/f53e14a9e741122cef2a88976a4ccafc6ad6f6fd"><code>f53e14a</code></a> (rabbitmq) - rabbitmq: remove auto user</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/0ec7277c5624b35ea1ac9d5d88a9eddb75278794"><code>0ec7277</code></a> (rabbitmq) - rabbitmq: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/f376a30bdb6223f03b7d3e40eb3093616830291b"><code>f376a30</code></a> (rabbitmq) - woodpecker: use woodpecker ci build status</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/51405d8f429584fcf5d38a7b1422971304f3981c"><code>51405d8</code></a> (rabbitmq) - rabbitmq: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/463ca03544a31a0a6c98ceb4862e9cd15a47271b"><code>463ca03</code></a> (rabbitmq) - rabbitmq: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/1978a714c0f868de9d4dfc863be003c313d3db6f"><code>1978a71</code></a> (rabbitmq) - rabbitmq: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/139277f11035e0e548bfdc35272579806cd8bb0c"><code>139277f</code></a> (rabbitmq) - rabbitmq: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/be49741721134fd966c09ea44ef87b705668c8a2"><code>be49741</code></a> (rabbitmq) - rabbitmq: change drycc gateway listener name</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/6d22518f5bbb3883bc4bdc05b6c93ea6b40e3be9"><code>6d22518</code></a> (rabbitmq) - rabbitmq: remove gateway route</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/0eb7833ac8a01bbde78f3e0172e6d3d2948d6234"><code>0eb7833</code></a> (rabbitmq) - rabbitmq: add check shards</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/921106312dc679e79c8dc8ce226ae62fa68ce0ec"><code>9211063</code></a> (rabbitmq) - rabbitmq: erlang vm tuning optimization</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/648a78d9b886890e924250a198624972d28a2ad8"><code>648a78d</code></a> (rabbitmq) - rabbitmq: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/0b43a4d04556eb2bfa81cc8ed22d84d636ad45d1"><code>0b43a4d</code></a> (rabbitmq) - rabbitmq: add x-random exchange</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/ad1c4da3f11a1e690508c71a992a3bda86b56201"><code>ad1c4da</code></a> (redis) - redis: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/3f37f92a06db4b06c105718bec48aeaac2bf1a31"><code>3f37f92</code></a> (redis) - redis: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/e3bef7a15e73fb77ba76ac4f0140fa03ebd2a813"><code>e3bef7a</code></a> (redis) - redis: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/4e806d40f4a203db5c91dd184a712fba8ce55820"><code>4e806d4</code></a> (redis) - redis: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/d5023be85937f1f4cf4b625fb8250a63c4776f3b"><code>d5023be</code></a> (redis) - redis: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/98f5d6fa30d4fb28c89eb547a0e2631aa34a46ac"><code>98f5d6f</code></a> (redis) - redis: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/063f29e85bc565c29d19b900b96017161263cb88"><code>063f29e</code></a> (registry) - registry: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/17bf8ae8cc1a257ff978a6a8ee27d8988f3ed9c2"><code>17bf8ae</code></a> (registry) - woodpecker: use woodpecker ci build status</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/7bbad151b1d5c934f9d81a882ea6ebef16bf1723"><code>7bbad15</code></a> (registry) - registry: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/279154fdec97b5e0d28a5c27481928d433ac1369"><code>279154f</code></a> (registry) - registry: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/3e4ae840d5718521278051122c19b96b9dbf2791"><code>3e4ae84</code></a> (registry) - registry: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/fa322d6c372fd6d622a2054584bbcab934ff67f0"><code>fa322d6</code></a> (registry) - registry: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/6c18fe004f3431a59ecd5c874c3bd77af544c661"><code>6c18fe0</code></a> (registry) - registry: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/0bc8472a7baa4b8f982694b97528fa984c03639d"><code>0bc8472</code></a> (registry) - registry: remove health url</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/5dacd9f735816decc4b6af7c4994a75ce280d92b"><code>5dacd9f</code></a> (registry) - registry: add wait-for-port check</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/fdeefc3888d5ec0dbfff8db6c797621a90896531"><code>fdeefc3</code></a> (registry) - registry: use headless</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/08bf9f882de2d94f8c3bdefafe24fafa9b9870c4"><code>08bf9f8</code></a> (registry) - registry: change registry port to 5000</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/40bcea2ddf3a6e6316422e14a25df360fb4dcf81"><code>40bcea2</code></a> (registry) - registry: add registry push test</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/871b8e72735b0c17f4c692ea53495e1abb4497d1"><code>871b8e7</code></a> (registry) - registry: add default env</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/7f3b3aceea1cc28475f9cec0a3244f693eaf1e6a"><code>7f3b3ac</code></a> (registry) - registry: bump registry 2.8.3</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/569f15dca6d21c69f3ad3734e6509addf2caf913"><code>569f15d</code></a> (registry-proxy) - registry-proxy: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/cc33caf06d9aa2c4bec7a745aa233f8827695972"><code>cc33caf</code></a> (registry-proxy) - woodpecker: use woodpecker ci build status</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/0002aab36b2692250f8653db3505a0300275bea3"><code>0002aab</code></a> (registry-proxy) - registry-proxy: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/40af10ba90e5e0e6e050f5d97625a1294ab6f910"><code>40af10b</code></a> (registry-proxy) - registry-proxy: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/c56b9dff701130403d9d0ecc932069fa16d2e462"><code>c56b9df</code></a> (registry-proxy) - registry-proxy: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/9d5bfe091bddf0f6d7d0cd8995823540b084dc77"><code>9d5bfe0</code></a> (registry-proxy) - registry-proxy: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/e6a33500e5eba9a32baa3f2e9841e67546236965"><code>e6a3350</code></a> (registry-proxy) - registry-proxy: change worker_processes to 1</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/726f39d51f196a28effb917fbacb20db960cf5f3"><code>726f39d</code></a> (storage) - storage: add volume compactionMBps</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/a5aa2d87bd4d320e30833cbe3e3598f5199e7da5"><code>a5aa2d8</code></a> (storage) - storage: add threshold to vacuum and reclaim spaces</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/e687d044f2796dbfef23239df62337b2e658b797"><code>e687d04</code></a> (storage) - storage: delete disk type in single disk case</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/75ee2e4f4acfa1c4fd8f725252ffdc8a30495dda"><code>75ee2e4</code></a> (storage) - storage: change datanode replicas to 4</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/c5fd7bad70e239cd389fc92372305435e099d4ce"><code>c5fd7ba</code></a> (storage) - storage: delete useless env</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/b3826ea800b1fbde96178f590d25361560f3bc3a"><code>b3826ea</code></a> (storage) - storage: add ssd hdd dir</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/29881a0702b1e68e69c86e6ae96da8c4eda209a4"><code>29881a0</code></a> (storage) - storage: add balance cronjob</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/c5a0f512283eb2c32814f3b2f3c0e3ebfb57bd1f"><code>c5a0f51</code></a> (storage) - storage: add defaultReplication for seaweedfs master</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/543c7a273c2988d477782ba97462263c93068669"><code>543c7a2</code></a> (timeseries) - timeseries: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/5376024ea1489cf311fd18dd691ab5b80eb4e5e8"><code>5376024</code></a> (timeseries) - timeseries: update timeseries-service-replica</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/52e8520d0e2bb6b0625304a8e29d3b680bc44840"><code>52e8520</code></a> (timeseries) - timeseries: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/f82657ceb0cdf390fb07e721ce57e07081d43968"><code>f82657c</code></a> (timeseries) - timeseries: add start script</li> +</ul> + + + + + + Blog: Drycc Workflow v1.6.0 + /blog/2022/10/21/drycc-workflow-v1.6.0/ + Fri, 21 Oct 2022 00:00:00 +0000 + + /blog/2022/10/21/drycc-workflow-v1.6.0/ + + + + <p>These release notes for Drycc Workflow v1.6.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.5.0, please refer to the following change summary.</p> +<h2 id="workflow--v150---v160">Workflow ## v1.5.0 -&gt; v1.6.0<a class="td-heading-self-link" href="#workflow--v150---v160" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>builder v1.3.0 -&gt; v1.4.0</li> +<li>controller v1.4.0 -&gt; v1.5.0</li> +<li>passport v1.0.0 -&gt; v1.1.0</li> +<li>database v1.1.0 -&gt; v1.2.0</li> +<li>imagebuilder v1.0.1 -&gt; v1.1.0</li> +<li>fluentd v1.2.0 -&gt; v1.3.0</li> +<li>logger v1.2.0 -&gt; v1.3.0</li> +<li>storage v1.2.0 -&gt; v1.3.0</li> +<li>monitor v1.2.0 -&gt; v1.3.0</li> +<li>redis v1.2.0 -&gt; v1.3.0</li> +<li>influxdb v1.1.0 -&gt; v1.2.0</li> +<li>rabbitmq v1.0.0 -&gt; v1.1.0</li> +<li>registry v1.1.0 -&gt; v1.2.0</li> +<li>registry-proxy v1.1.0 -&gt; v1.2.0</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/52517d9323bfcd246e1fd8e13bdee2c45739136a"><code>52517d9</code></a> (builder) - builder: update controller-sdk-go</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/1d78ca01de03c80ac86687999d82dba0077df31a"><code>1d78ca0</code></a> (builder) - builder: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/26b69801c78321da8754c814b6503ec76e857a1b"><code>26b6980</code></a> (builder) - builder: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/bfd43851009116d6d4bceb4c46edc3cd21cf9d41"><code>bfd4385</code></a> (controller) - controller: add get manager user status</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/874208d8501198ed8780f2e820ab112d3b78eae2"><code>874208d</code></a> (controller) - controller: unified measurement model</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/cadf98f888c384890c529700c16208b17e17dff2"><code>cadf98f</code></a> (controller) - controller: add admission webhook</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e0050c23869dd3a1d5e8038859a7324484b227b2"><code>e0050c2</code></a> (controller) - controller: new measurement model</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a11ba587b73058c3af610fc9fc101e5d446eb43f"><code>a11ba58</code></a> (controller) - controller: multi pod restart uses async</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/fb3c15d70041d4b215c34b5625cb82ae52279d2b"><code>fb3c15d</code></a> (controller) - controller: add check app owner status</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3d78b764c874c30f23aa7e6db9a0d03cb09b6a24"><code>3d78b76</code></a> (controller) - controller: add resource services api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3d6a2012ab840dcde1be3c8f197df76eac9c5d88"><code>3d6a201</code></a> (controller) - controller: add search apps api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/01c443a3bf142d6497d20492e3ee7f534db64322"><code>01c443a</code></a> (controller) - controller: add KUBERNETES_CPU_MEMORY_RATIO parameter</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7c2623276991b46b7ac2b8e9d8ce2f84e8ebf26b"><code>7c26232</code></a> (controller) - controller: add volume size limit</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3bee749fc0c670d3ee371c7ffb031f47f0d45873"><code>3bee749</code></a> (controller) - controller: add annotations support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/23cd97c1f213ea9dcec45a4a40e9c3942904e55a"><code>23cd97c</code></a> (controller) - controller: traefik v2 support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e37b7db45049776d7d7455e01f5928986b24b043"><code>e37b7db</code></a> (controller) - controller: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b3b367b108bea56a5fa5ccc603f0dafc14bb5edb"><code>b3b367b</code></a> (controller) - controller: add volume expand support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a4e154aaf0f6cd3b01ebbab0a4af1a4b693a45a4"><code>a4e154a</code></a> (controller) - controller: add database replica support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/2f37216fbaed5fa707c76b44881b1f7507a75f49"><code>2f37216</code></a> (controller) - controller: switch wsgi to asgi</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b3314a50607e9d5383d0ce954811827acae8fa05"><code>b3314a5</code></a> (controller) - controller: add pod exec api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/75df2dce65591da4e1e56c7f56a1903749fa4e20"><code>75df2dc</code></a> (controller) - controller: add stream support for app logs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4229badbcd4e367cbe13bf13f2b5c62271b7b31e"><code>4229bad</code></a> (controller) - ccontroller: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/89bb19b20f2eb0d8918cdc7223fa3b117af620d5"><code>89bb19b</code></a> (database) - database: upgrade to pg14</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/9f45a5d5e9b7871c47acd73ce227856c1683f6a2"><code>9f45a5d</code></a> (database) - database: add hugepages support</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/c4008c9fbe0f99d1200a58466a15466d92840fa5"><code>c4008c9</code></a> (database) - database: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/411a7b269a3333caed809a1afac69578a7c5ad9b"><code>411a7b2</code></a> (database) - postgres: use patroni</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/64e5cb0aaaacfa2d9976e278583fa700c858ce92"><code>64e5cb0</code></a> (database) - database: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/2bab823194abea35c7a1ff4d59db6a88eb19fcad"><code>2bab823</code></a> (fluentd) - fluentd: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/337ba62d587a4f6c7321aa6ef843d5764692a09e"><code>337ba62</code></a> (imagebuilder) - imagebuilder: run podman as rootless</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/4396ffaeb6a2751e6f78907ac7c517966b5e3c08"><code>4396ffa</code></a> (imagebuilder) - imagebuilder: switch to oci charts</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/f37ae0927023685d88f9e594d8316d8c40cd5296"><code>f37ae09</code></a> (influxdb) - influxdb: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/04503b2c0d5c455c1a106c71be727d2b2b14a2f8"><code>04503b2</code></a> (influxdb) - influxdb: add influxdb ha</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/41ddad5e9acb54fa5bb2c35559615d1cc4fd3af5"><code>41ddad5</code></a> (influxdb) - influxdb: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/2006480f82ab4291efa75a69cad0080a29872110"><code>2006480</code></a> (logger) - logger: use redis stream replace nsqd</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/ab23d17f378ea1b740fb4c43dc06f4853d5c729f"><code>ab23d17</code></a> (logger) - logger: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/81d4e9dcde820ab8dc1df6fb99f82fdf39eb35ea"><code>81d4e9d</code></a> (logger) - logger: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/c3d9796e21c344d660bfd036d6154c28a3051995"><code>c3d9796</code></a> (monitor) - monitor: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/cd9de3c70c33236975b1d2547b75a66649fba93d"><code>cd9de3c</code></a> (monitor) - monitor: switch to oci charts</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/318a73f7f03c01faa23ce3a89b4b52d5cae4279d"><code>318a73f</code></a> (passport) - passport: add change user confirm</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/79ef1004687152d93a5e60058fd4f40a6273b55a"><code>79ef100</code></a> (passport) - passport: add re login at authorize</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/6927bb5884a7ee332a64afabfd6439467d7fee3c"><code>6927bb5</code></a> (passport) - passport: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/3146a0981b744962d68a75fab65e074ab61d4b1c"><code>3146a09</code></a> (passport) - passport: add google reCAPTCHA</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/802abcdd5f0768d75b4fc9f08f46c4b2a590be29"><code>802abcd</code></a> (passport) - passport: add replica database support</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/a0dcd1b7b2bdd3ba247d50fdf554a2918b065588"><code>a0dcd1b</code></a> (passport) - passport: switch wsgi to asgi</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/4c9dbba2b1e79cf9860e19529bd99f52f5588328"><code>4c9dbba</code></a> (passport) - passport: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/74825f7827e22b75938cbcc5bf81ad1a40c4ab37"><code>74825f7</code></a> (rabbitmq) - rabbitmq: add rabbitmq managentment ingress</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/12cf7d60e4e89e3396e786f4487cca55f1322887"><code>12cf7d6</code></a> (rabbitmq) - rabbitmq: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/103417de373246b4f1e0b9cdaf2eaae6ba704dea"><code>103417d</code></a> (rabbitmq) - rabbitmq: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/5d428bbd55c0ec12f6fcafe312b2cd3768fb51d1"><code>5d428bb</code></a> (redis) - redis: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/a88c1a9625757b901515682f39d40a7f5b877f95"><code>a88c1a9</code></a> (redis) - redis: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/541585d4060d6006b99fd3649718566a6ea3163b"><code>541585d</code></a> (registry) - registry: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/e9ca9d475dade575ae13c3b288148b8094faf3f6"><code>e9ca9d4</code></a> (registry) - registry: add garbage-collect cronjob</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/ec62a5969747738252132510923637c1b63b63d8"><code>ec62a59</code></a> (registry) - registry: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/fde0b07f243deabc0818efc4088583c6ca6aa5b8"><code>fde0b07</code></a> (registry-proxy) - registry-proxy: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/be14eb42fcda99f9160d21f437858e89337543a2"><code>be14eb4</code></a> (storage) - minio: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/51af6966183c496c9c1374cf4c4fa9b66f319a44"><code>51af696</code></a> (storage) - storage: add k8s csi support</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/76a75d922b965b8961f872b62c67569924e0cf49"><code>76a75d9</code></a> (storage) - storage: add cluster health checker</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/a17dc8cc37c2c2d96acdbcc08a6c2e52676cb777"><code>a17dc8c</code></a> (storage) - storage: switch charts to oci</li> +</ul> +<h4 id="fixes">Fixes<a class="td-heading-self-link" href="#fixes" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/e4f44fba4f4a71812b0a1b0d42668d8a6f3bbc65"><code>e4f44fb</code></a> (builder) - builder: no error return</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/e38dfc71c5dfa0edafc5603f274235048a3992d7"><code>e38dfc7</code></a> (builder) - builderControllerHost/ControllerPort init error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ff9069fee85633db4801a43d4fa70292099c94dc"><code>ff9069f</code></a> (controller) - controller: influxdb query error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f7f5069569e3f7325fc8fa5f90f8c19e95c0c6ce"><code>f7f5069</code></a> (controller) - controller: authentication 500</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7e297a8996c9fbf490fcbce364c0b4172bdc6388"><code>7e297a8</code></a> (controller) - controller: add check remote user status</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9db28e1ea4627f8f63dcc6f83db2962dc5b47451"><code>9db28e1</code></a> (controller) - controller: celery MaxRetriesExceededError</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4bcff08d38a01a4d7267fef00650395275e3203b"><code>4bcff08</code></a> (controller) - controller: wrong name</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d69fde2efc71b015ae2894fcc3efa0cf369457e5"><code>d69fde2</code></a> (controller) - controller: traefik ingress create error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a3ad743c2ecd0528c5c69915272dc68a90fd841a"><code>a3ad743</code></a> (controller) - fixup(controller: user login error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/662c8ddfbcb03d19f5ced769de21964ff5ed413e"><code>662c8dd</code></a> (controller) - controller: change influxdb port</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/957bdf67128b45abad43e8ee560fb6cb749b0783"><code>957bdf6</code></a> (controller) - controller: validate rsa key pairing before storage</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/419ec4c4de6ad77c9cc3f551260fdc35504ceb15"><code>419ec4c</code></a> (controller) - controller: kubernetes pod/exec cluster role</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a67edaae26c00a7ce806bde95b73041ec1c84734"><code>a67edaa</code></a> (controller) - controller: Cannot routing:disable</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e09e2144f1906b19d9b00f0883effe3491198ebf"><code>e09e214</code></a> (controller) - controller: allowlist cannot remove</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/318b1267f35bcf158fc21b20f8e367a3e23fa454"><code>318b126</code></a> (controller) - controller: domains update error</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/92855ebc7df34fb8cc5ea440db4f821681ae2408"><code>92855eb</code></a> (database) - database: premission denied</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/bde945ab972d9085009b291c0faac55d8942b014"><code>bde945a</code></a> (database) - fixup(postgres: support arm, fix Failed to build psutil</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/7854d45a2164a1db8ee37bc3ce39c8515bacae30"><code>7854d45</code></a> (database) - fixup(postgres: user name converted to lowercase letters</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/57b2a0708d5ab8fff913e97be09f132074d1ff56"><code>57b2a07</code></a> (fluentd) - fluentd: ifconfig_path not found</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/20e72b962a415773fd97919832c7a0bde9c55a28"><code>20e72b9</code></a> (imagebuilder) - imagebuilder: upgrade pack version</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/651db8a1d2f40f0fafb88f2da4b6fd20ee920715"><code>651db8a</code></a> (imagebuilder) - imagebuilder: chown uid gid order</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/d2e9164afe61fac362beb65ee9113453c2ecd970"><code>d2e9164</code></a> (influxdb) - influxdb: proxy not running</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/3a1d3618d881880abcd752c9c9184a570b38442e"><code>3a1d361</code></a> (monitor) - monitor: charts naming</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/d754ae0244e6e1e300062db24c8e4477b7522715"><code>d754ae0</code></a> (monitor) - monitor: telegraf init error</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/63f9e346a4ded75b7b4f8f0c6708bbe725ee6160"><code>63f9e34</code></a> (monitor) - monitor: affinity error</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/95ae1e5f51e528b75ccae36ad86e9abfbff52050"><code>95ae1e5</code></a> (passport) - passport: yarn build fail</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/3f5365e8e5be0b2a486651e87fb5b82fe4668bbc"><code>3f5365e</code></a> (passport) - passport: wrong name</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/907f17b95c1114a802781f2bbec3ba046464f1a8"><code>907f17b</code></a> (passport) - passport: change uid gid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/e3911e0f5e9174ab8e7542f60b8bd0c3ff7f85f6"><code>e3911e0</code></a> (passport) - passport: &lsquo;registration_done&rsquo; not found</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/2ace5f0a2a363d959a381bd3f759b4990bc13953"><code>2ace5f0</code></a> (passport) - passport: ui style</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/b3ba1e1545f07ee2322850ee6cfb6915ee26967d"><code>b3ba1e1</code></a> (passport) - passport privacy policy link</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/172e9c8b680a83d6c437292febf0418d35c99aa9"><code>172e9c8</code></a> (passport) - passport: check databaseReplicaUrl error</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/a3aeb7052d4ebdbc7bd020850f94921c253a8a38"><code>a3aeb70</code></a> (rabbitmq) - passport: change uid gid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/5c73dcf6a8692e83abd40f1d5e991714b3c51876"><code>5c73dcf</code></a> (redis) - reids: DRYCC_REGISTY misspelling</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/d7e3baf4600d87e4d4af2b3e581cb62c591a25b6"><code>d7e3baf</code></a> (redis) - redis: env miss</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/cadaa9151519a4efb52d5c5f779cc0aff0f8fe1e"><code>cadaa91</code></a> (registry) - registry: set gid uid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/d524217dccfc6dd80c86547d5f2f875b15a8054d"><code>d524217</code></a> (registry) - registry: storage run error</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/854f912bf746ac69d0117378888c1fe8334dd7fb"><code>854f912</code></a> (registry) - registry: chown uid gid order</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/e642bb7452fb62bbc7ce6f1b852e029b88a71488"><code>e642bb7</code></a> (registry-proxy) - registry-proxy: containerPort error</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/8dfd029b78d2dcd1b6bf31960d35234deb6bfc5b"><code>8dfd029</code></a> (registry-proxy) - registry-proxy: chown uid gid order</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/bbea3642114ac83e3c9cb56e7131146378bbf213"><code>bbea364</code></a> (storage) - minio: premission denied</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/97deba16553dd6dc8d2625d8747825692e8667bb"><code>97deba1</code></a> (storage) - storage: node unimplemented error</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/b9bdeff3ef47f43ec12dd16194297d63298fbd34"><code>b9bdeff</code></a> (storage) - storage: pd can not connect each other</li> +</ul> +<h4 id="style">Style<a class="td-heading-self-link" href="#style" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1edb10c23e5ae5654e6a7daf08b7a74fe9c86b74"><code>1edb10c</code></a> (controller) - controller: database convention over configuration</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/1960cc3367aa6b0e8f0db5f0117a271c884356a0"><code>1960cc3</code></a> (database) - database: database name convention over configuration</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/06d1f5dd3b7ff353ae26615695732f54dd09e5c7"><code>06d1f5d</code></a> (imagebuilder) - imagebuilder: URL to Url</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/b8a89412e7794fe9e16689d4e8902d34f68a6ce1"><code>b8a8941</code></a> (passport) - passport: database convention over configuration</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/8e9a199ac90382e67f64c757d9d207e7aa106c86"><code>8e9a199</code></a> (builder) - builder: upgrade controller-sdk-go</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/48401512b2eee6a608efe45c962809a4a388ed9a"><code>4840151</code></a> (builder) - builder: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/68ccfb12da3fdc35519b23fdb8212f7de377f8b5"><code>68ccfb1</code></a> (builder) - builder: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/8f971cbd509062f952e0b0fe2fdc9983891077ad"><code>8f971cb</code></a> (builder) - builder: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/fe2c55d0e5264818e482fcd71510d9a616689c79"><code>fe2c55d</code></a> (builder) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/2b5e70609f11eff1eb1e1d8a5591644799fa8982"><code>2b5e706</code></a> (builder) - dockerfile: change user and workdir</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/7a6c8d319bcc67e1cbe5a733de773860aa859765"><code>7a6c8d3</code></a> (builder) - builder: set gid uid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/fe494f75669f9e3a51ff32e330edb8c5a33efed7"><code>fe494f7</code></a> (builder) - dockerfile: use uid gid</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/a7c87525709c6903e4fb254740eac710c3e18385"><code>a7c8752</code></a> (builder) - builder: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/eb2e94c2ab4358e74a74c8d198eb6798e9bdeae7"><code>eb2e94c</code></a> (builder) - database: bump mc 2022.04.01.23.44.48</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/cfaae66aa31b4b7b28c7d4577e9bf9c7f17a6716"><code>cfaae66</code></a> (builder) - builder: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/d7d289060ddafcc94855bb46dc4fbc24cf1c3527"><code>d7d2890</code></a> (builder) - builder: change default imagebuilder registry</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/ecfdb19270198fc3f2b46cc0dc91151bd3ebf114"><code>ecfdb19</code></a> (builder) - imagebuilder: change python-dev registry</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/6da17f489543950af850ee3d5bb4e1cfbcc5cac1"><code>6da17f4</code></a> (builder) - builder: <a href="https://github.com/minio/minio/issues/14331">https://github.com/minio/minio/issues/14331</a></li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/1a57e5bd5e467b859e0d69e6b3775454132cb225"><code>1a57e5b</code></a> (builder) - builder: <a href="https://github.com/minio/minio/issues/14331">https://github.com/minio/minio/issues/14331</a></li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/f1464fa6065483d23b98f01a847b73e951f896ae"><code>f1464fa</code></a> (builder) - builder: <a href="https://github.com/minio/minio/issues/13799">https://github.com/minio/minio/issues/13799</a></li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/b1e1c4f5920ba82235a253f9980960ef9dca527d"><code>b1e1c4f</code></a> (builder) - builder: use env replace creds volume</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/71a41453660c6d731247a10e00f94121ae3a69a5"><code>71a4145</code></a> (builder) - builder: bump go.mod</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/3567688f8809e3805e47170d4b3109a31b1f883f"><code>3567688</code></a> (builder) - builder: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/73ea38b11c631415aa02c5ee43ff92ecfe48348d"><code>73ea38b</code></a> (builder) - builder: change storage to minio</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/1f913215ba18670fe83891bf84317b72985151dc"><code>1f91321</code></a> (builder) - builder: use testify replace assert</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/d148b9c998759b886ea5493d0e2aa94518d39dcb"><code>d148b9c</code></a> (builder) - builder: add check storage health</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/b768101f69233fa792f3240be47b71b24881e90c"><code>b768101</code></a> (builder) - builder: change initContainers</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/1b3bec3ea2783c5124f372c2874c3691b71489cd"><code>1b3bec3</code></a> (builder) - builder: add replicas</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/5cb0d618ff5bb1136501f4ba6359e5e5c46a7a63"><code>5cb0d61</code></a> (builder) - builder: upgrade to latest controller-sdk-go</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/98b9d581209eacabdb9e28c5eb6a7975f13bd454"><code>98b9d58</code></a> (builder) - builder: upgrade new require</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/65817c3e519df8368cd4427f5d366f9edde1fbd5"><code>65817c3</code></a> (builder) - builder: change drycc.cc to <a href="https://www.drycc.cc">www.drycc.cc</a></li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4e3f9d05bb8d00023e6f1927785b7c27d4801652"><code>4e3f9d0</code></a> (controller) - controller: add celery retry mechanism</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f6716fee7625ad8f0cad2b1cf5ad746beb847a65"><code>f6716fe</code></a> (controller) - controller: change cronjob name</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/eb606938533da2673ed2aa2986bcb0cdd2c9ee2c"><code>eb60693</code></a> (controller) - controller: refine celery task priority</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/66905e95bb3c9f71fb4c75038199d54c6b5a0edc"><code>66905e9</code></a> (controller) - controller: change manager auth</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ea20c415af0ee4e70f32873748cd979bd36f8240"><code>ea20c41</code></a> (controller) - controller: remove start/stop api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4c8fc807f950064d2cc98ebdd6a51ec86eabb20f"><code>4c8fc80</code></a> (controller) - controller: improve tasks error handling</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/cf7402eaff8373c956e6c0ffa1c7ff479cade8e2"><code>cf7402e</code></a> (controller) - controller: add blocklist api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/80f14dd5b8852c235e3de496261b416c8b59a043"><code>80f14dd</code></a> (controller) - controller: use get_user_model replace auth.User</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ffc7bb790f2257f5e5f9902400f78524d1f528e3"><code>ffc7bb7</code></a> (controller) - controller: use JSONField replace ArrayField</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/370df8c9d011e25785a06e5a4a737dcdb622f4f5"><code>370df8c</code></a> (controller) - controller: add validate metric</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/29084ce759bddd671de4441c6f8e6889774e4c80"><code>29084ce</code></a> (controller) - controller: use user id request manager api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/718fe123eafe5136ac08635c8cf1dbca3dcad4ab"><code>718fe12</code></a> (controller) - controller change urlpatterns order</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/71f40426a65bc6cdc90e6185b1487ae30a3c73de"><code>71f4042</code></a> (controller) - controller: measurements uses lowercase letters</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e5123ea55ae516d94b0cb54ec6ffb464c050ce87"><code>e5123ea</code></a> (controller) - controller: change resource unit to number</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/18fee9aeb1114ea8dbcc4d8eacea93148206e002"><code>18fee9a</code></a> (controller) - deps: bump celery from 5.1.2 to 5.2.2 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ffca6c11c67012e13540e06c12cf30dea5e5cde7"><code>ffca6c1</code></a> (controller) - controller: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9ec12e1ff7bcfb3b72953313484d3f605d97c73b"><code>9ec12e1</code></a> (controller) - controller: simplify drone configuration</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4b4749e2fd391a492fbf40fb7ee25c7b61b52f26"><code>4b4749e</code></a> (controller) - controller: set default CSRF_COOKIE_SECURE false</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/2ef6338c20c8625b2cc76c6021149bc07141fcd0"><code>2ef6338</code></a> (controller) - deps: bump django from 3.2.5 to 3.2.10 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c7570d0a40f7daa04de0a4fe1ecbb001e436ee41"><code>c7570d0</code></a> (controller) - deps: bump django from 3.2.10 to 3.2.11 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8b17bc16624fd9caddbbc462cc3487d3500a5216"><code>8b17bc1</code></a> (controller) - controller: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c928fb09f88ce210df7b495b80a005146320e2bf"><code>c928fb0</code></a> (controller) - controller: use rabbitmq cluster</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f9171852a8530c9bd385576517d24172917a1b33"><code>f917185</code></a> (controller) - controller: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/22a8f634a3574553132ecd53e8be467d84a255e9"><code>22a8f63</code></a> (controller) - deps: bump django from 3.2.11 to 3.2.12 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3cc3b00a705b9c7b0ff5d36fb2c0ab4139113dd9"><code>3cc3b00</code></a> (controller) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ee274f6d6728b3b9b3fd91b344be3f8a0d3f737f"><code>ee274f6</code></a> (controller) - controller: set venv profile</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ce6b069644ed3952a47bdd1bd728a395a9f1af05"><code>ce6b069</code></a> (controller) - controller: set gid uid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3a105d3628e40e2f53dfd2badeb7221555207227"><code>3a105d3</code></a> (controller) - dockerfile: use uid gid</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/15f9b0ea96630a818ec191dac15497a5dc99cadc"><code>15f9b0e</code></a> (controller) - controller: code review</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/01e6fd9ef5d730749a33986ff9d58dd854f50cb5"><code>01e6fd9</code></a> (controller) - controller: use passport user id</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/893ee31a1de6036136d0b813d5ff6575267e640a"><code>893ee31</code></a> (controller) - oauth2: update user info pipline</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3028fb470f23d858a5e36312e419dcdfbcc00be0"><code>3028fb4</code></a> (controller) - user: set AnonymousUser username</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5daf82d3bd17f2c653d2db52fb79d2a895ed1335"><code>5daf82d</code></a> (controller) - controller: set worker_cancel_long_running_tasks_on_connection_loss</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/61f2c53a7841099e33c8d5f8d25de311392ce317"><code>61f2c53</code></a> (controller) - controller: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/88feb1df0f3508c29a47ea291f225207a8a4c754"><code>88feb1d</code></a> (controller) - imagebuilder: python=3.10.4 rabbitmq=3.9.14</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/914e03fb8d6d6bff7ef9b5f91b0a3eeedac2ebeb"><code>914e03f</code></a> (controller) - controller: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a5bb548ee73cd201cafe797fdba4fe89e4bbb377"><code>a5bb548</code></a> (controller) - controller: change python-dev registry</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3ecdd7c05b7cddd640ffe92012b777a80cae1eec"><code>3ecdd7c</code></a> (controller) - controller: add a separate rabbitmqUrl configuration</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/967cb116bdbbf040c3c3c15579bb2d334666d3e8"><code>967cb11</code></a> (controller) - controller: remove APP_STORAGE</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/473d2b5f08c205240b5e081fcb9256d7ecd4cd45"><code>473d2b5</code></a> (controller) - controller: use env replace creds volume</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e410d4cba17662bad797fbd7288052b81e50df29"><code>e410d4c</code></a> (controller) - deps: bump django from 3.2.12 to 3.2.13 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c6ef777035d5e955984f9f4c84fac465943d8b74"><code>c6ef777</code></a> (controller) - controller: simplified passport config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0fd3233f1471b32c621149ac4ca5b5527741fda8"><code>0fd3233</code></a> (controller) - controller: remove settings hardcode</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a64e99cf099eba92c6df749c3c89f4245488b3e4"><code>a64e99c</code></a> (controller) - controller: change passport config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/62aba2594f1240c4368d95c61d75fa08343d05fb"><code>62aba25</code></a> (controller) - controller: set cronjob timezone to utc</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/760b70b635d6eecedfd3d40991740b13e587c1c5"><code>760b70b</code></a> (controller) - controller: change default ratio</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8dffc3afbce3871dc82fe4ce94c92b1fbbacc9b6"><code>8dffc3a</code></a> (controller) - controller: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/26043c40c89cb162b3ce322eba6a79f81a6b24cf"><code>26043c4</code></a> (controller) - controller: change default app storage</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/608bd8da7a7cb75d8fadfa965bcd9ea32e4a96ef"><code>608bd8d</code></a> (controller) - deps: bump django from 3.2.13 to 3.2.14 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/18ed0c2a656497108f98c5c8dbd3b27253dd7915"><code>18ed0c2</code></a> (controller) - controller: remove conjob affinity</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/add671288d5f4af68735a69771f024e4ed856196"><code>add6712</code></a> (controller) - controller: add volume expand support use patch</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/cc1ad1322ba638aa7f6acf45823047712a85e86f"><code>cc1ad13</code></a> (controller) - controller: add startupProbe</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0e9a6033b1a2b66f937010601df70e5625674a66"><code>0e9a603</code></a> (controller) - controller: add clearsocial cronjob</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/eb6f05d969102c008051ebd4c7e39a1300ed1b25"><code>eb6f05d</code></a> (controller) - controller: change initContainers</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/762c6767947b6407a7fb23ffbcb07dc46154b222"><code>762c676</code></a> (controller) - controller: change replicas</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/abd7e8c2210eb1f71c1d280383794af5fa786c98"><code>abd7e8c</code></a> (controller) - deps: bump django from 3.2.14 to 3.2.15 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/07fdf1b9938d868ef55c1d2067258a1eb6c59d23"><code>07fdf1b</code></a> (controller) - controller: remove database conn_max_age</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ef8e41f523aa0159831c95623b96fa74b3570d0c"><code>ef8e41f</code></a> (controller) - controller: add database replica check</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/79143f2301bfc52f8181fc0e0f07263645e065d8"><code>79143f2</code></a> (controller) - controller: upgrade new require</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a62404890973cb26c9360878e7625e15eb87d281"><code>a624048</code></a> (controller) - controller: add app.refresh func annotation</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b22d367d54aa2ab131c8e69491e084dc283826a4"><code>b22d367</code></a> (controller) - controller: optimize app refresh timing</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/fe98f0c8f3d2cfebc2b6ad13927627ebee96e39e"><code>fe98f0c</code></a> (database) - database: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/5e00c118e5830c43158417486b83602d1e9839ff"><code>5e00c11</code></a> (database) - database: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/d2cb8607a95e098fe0c50a82ebadd3393a52cd56"><code>d2cb860</code></a> (database) - database: disable huge_pages</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/197d80d95e42443351abbf1aae216d5f80073334"><code>197d80d</code></a> (database) - database: add persistence</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/1c3e64596ee5970c3ef7a1daeee86ced68ae3ec1"><code>1c3e645</code></a> (database) - database: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/37730ab6ca7ac86728f9fe0f1c41240402abb9bc"><code>37730ab</code></a> (database) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/5014112dd279d1e3a8d5b6fa23797d0996fb2047"><code>5014112</code></a> (database) - dockerfile: change entrypoint</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/29b538e8b33cd19bb3a781abb8335905fa7a533f"><code>29b538e</code></a> (database) - database: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/c2bb0746172d4dc764cd8543d98bb6cbd9205cf9"><code>c2bb074</code></a> (database) - database: bump python 3.10.4 and mc 2022.04.01.23.44.48</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/077a4e95b2ee3d772e030971218e880f31a55e4c"><code>077a4e9</code></a> (database) - database: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/560bdb97a46897ae0fd464ca6e2b54d129d91b37"><code>560bdb9</code></a> (database) - database: change python-dev registry</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/1e54b554f4a29df49ac42ba046f00f71a105f84e"><code>1e54b55</code></a> (database) - database: <a href="https://github.com/minio/minio/issues/14331">https://github.com/minio/minio/issues/14331</a></li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/d6466723b4f949a4771d7415f1a80924f398963d"><code>d646672</code></a> (database) - database: <a href="https://github.com/minio/minio/issues/13799">https://github.com/minio/minio/issues/13799</a></li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/a6ac4e350fec8e27c1bdc560130c585d3a7ab7d2"><code>a6ac4e3</code></a> (database) - database: use env replace creds volume</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/9618d87f3bc63c8933553278e88c7d6758b9e2af"><code>9618d87</code></a> (database) - database: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/b8232737ff893b064a558821da49b40905b4e83d"><code>b823273</code></a> (database) - database: change minio to storage</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/7bd5a90fe97b9b0ec20f5305431891f10a975c61"><code>7bd5a90</code></a> (database) - database: add check storage health</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/20c6d96e16b2dc7fc7d1bf75a8b44dd6ca459f6f"><code>20c6d96</code></a> (database) - database: fix storage run error</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/8bde83071df44a11b01ae13fbe2676567780170b"><code>8bde830</code></a> (database) - database: upgrade to pg 14.5</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/a33b5e5ef09bfc8cf5fbf79fd11dee4766a910e2"><code>a33b5e5</code></a> (fluentd) - fluentd: update plugins</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/eed7a7804b91dba5c31762adcf1245950365b4fe"><code>eed7a78</code></a> (fluentd) - fluentd: update filter kubernetes setting</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/cc83dd87809f1b71e18636240582c0a58eb73ad2"><code>cc83dd8</code></a> (fluentd) - fluentd: update elasticsearch store setting and support exclude specific container logs</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/ba2feb28bc7a96ec2a0632c5c4070d5300de3c37"><code>ba2feb2</code></a> (fluentd) - fluentd: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/d528676b75699d731ceba78ca7b207bd1472aed6"><code>d528676</code></a> (fluentd) - fluentd: simplify drone configuration</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/dece82d3a85c2b69d4315d324d03fd1f523e53fa"><code>dece82d</code></a> (fluentd) - fluentd: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/4e0a80244c190607f9e706fdeed0f3829c505a76"><code>4e0a802</code></a> (fluentd) - fluend: replace nsqd with redis</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/15ceca0cdbfb56e03b96cfd96e9b13909667f2e3"><code>15ceca0</code></a> (fluentd) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/a7f619f70d0fb77d08f544dc593d033396b984af"><code>a7f619f</code></a> (fluentd) - dockerfile: change workdir</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/9adf5ed9a2387c79a596a4e8fddcc099316e9fd8"><code>9adf5ed</code></a> (fluentd) - database: bump fluentd 1.14.6</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/50c14c28eb1f3c673787b1f59f6b713995cd1441"><code>50c14c2</code></a> (fluentd) - fluentd: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/83171b1e36a4fc787459ffdceb9a2573b518a287"><code>83171b1</code></a> (fluentd) - fluentd: change python-dev registry</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/ec8358165e029e7c82316877f629b128bb3a00f7"><code>ec83581</code></a> (fluentd) - fluentd: unified reids declaration</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/07c63e24a3760a0604d3c17936690f31380e7b8c"><code>07c63e2</code></a> (fluentd) - fluentd: upgrade fluentd 1.15.2</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/65df9be7b31a93f6ea30d259cb13cf0401d78234"><code>65df9be</code></a> (imagebuilder) - imagebuilder: update pack version</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/66cab351e53388cdb2bddf4f415240883c3217f9"><code>66cab35</code></a> (imagebuilder) - imagebuilder: use dind replace go-dev</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/0c8206098ba01f01039c1b563238a6612e6a1fed"><code>0c82060</code></a> (imagebuilder) - imagebuilder: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/8146da94bfef611398b03c70be316676aa49f626"><code>8146da9</code></a> (imagebuilder) - imagebuilder: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/7d97241d42a0282255d9c1d6a823159671f25fd4"><code>7d97241</code></a> (imagebuilder) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/07e805c48d9f9ccf44e23d91791995f38fa28345"><code>07e805c</code></a> (imagebuilder) - imagebuilder: change default buildpack</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/8d1038df7e714b72d43b491a3fddb36639736937"><code>8d1038d</code></a> (imagebuilder) - imagebuilder: upgrade podman to 4.0.1</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/62d3687a1edeefee68d5fedfb59eea38e791a3f7"><code>62d3687</code></a> (imagebuilder) - imagebuilder: change workdir to /workspace</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/da8bfb0f576bc292eb6427f7945271cc00fcb0ce"><code>da8bfb0</code></a> (imagebuilder) - imagebuilder: change uid gid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/d44e3bc2007f4e70c7dfa6d59279e7643345bd46"><code>d44e3bc</code></a> (imagebuilder) - imagebuilder: upgrade stack</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/5b0c7e69839ac408230bc142a2ba42953a068216"><code>5b0c7e6</code></a> (imagebuilder) - imagebuilder: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/f74cbf6113d99064c5b734da329980434c4f854a"><code>f74cbf6</code></a> (imagebuilder) - imagebuilder: add defaultBuildpacksURL</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/941d4939323573679841cc114669e1dec2154f94"><code>941d493</code></a> (imagebuilder) - imagebuilder: <a href="https://github.com/minio/minio/issues/14331">https://github.com/minio/minio/issues/14331</a></li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/449be91d0c64e4e7947de68c4e35fcfd8a944a14"><code>449be91</code></a> (imagebuilder) - imagebuilder: <a href="https://github.com/minio/minio/issues/13799">https://github.com/minio/minio/issues/13799</a></li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/63b052341db3e1dcd2458ded7be233ec9877a3bf"><code>63b0523</code></a> (imagebuilder) - imagebuilder: use env replace creds volume</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/4e8a6e570108c8db393c764bd6cfa8f66cb126c7"><code>4e8a6e5</code></a> (imagebuilder) - imagebuilder: add imagebuilder config</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/2d891f53998f135bc91c34ff1e80189e01969ab5"><code>2d891f5</code></a> (imagebuilder) - imagebuilder: change minio to storage</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/addceda27e7416c7e75d7502265448a95377ed4d"><code>addceda</code></a> (imagebuilder) - imagebuilder: upgrade new require</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/a6e569fdfaf379bb7c64c32e2406ecbb61ad890f"><code>a6e569f</code></a> (imagebuilder) - imagebuilder: pack_build add &ndash;env-file parameter</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/6191ff5c4cc132b0a5f9bf4bc227f8a64ed0c327"><code>6191ff5</code></a> (influxdb) - influxdb: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/dc3f8c7ed955953e4b576111edde4f05726a86cb"><code>dc3f8c7</code></a> (influxdb) - influxdb: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/6b5c81922dd498c0abb22e44ff85226881df187f"><code>6b5c819</code></a> (influxdb) - influxdb: new ingress style</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/68b381d1f377bdd805d4db86fb244ece080851bc"><code>68b381d</code></a> (influxdb) - influxdb: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/ea20eb81c27c90d8038872a9b5517ea1a7eafb8f"><code>ea20eb8</code></a> (influxdb) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/64c0a71ef6d0139d8c8df6b8823f53d444df1adf"><code>64c0a71</code></a> (influxdb) - influxdb: set gid uid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/a709ca19e2ee8a37f9f46263a714aea85e413391"><code>a709ca1</code></a> (influxdb) - influxdb: use DRYCC_UID DRYCC_GID env</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/740dff00afe4b6b207d3e64819745702861e7b8b"><code>740dff0</code></a> (influxdb) - influxdb: use common affinity template</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/e0356737f548edc85730aecbbf3ac402ef0fc3a0"><code>e035673</code></a> (influxdb) - influxdb: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/f1cefbd0b3107e5a4a228cce55e580eda0a6e849"><code>f1cefbd</code></a> (influxdb) - influxdb: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/a00100ebf6f1f8ee29d0341689823be68297a9f6"><code>a00100e</code></a> (influxdb) - influxdb: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/9d165ef2cf43f2abceba893a883e34285e694cb3"><code>9d165ef</code></a> (influxdb) - influxdb: add probe</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/bee7fff49a4c9410c5ccae1f3a2435ac0b505e82"><code>bee7fff</code></a> (influxdb) - influxdb: upgrade to influxdb 2.4.0</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/254914c02d7bd968e52586a52b8749d5b3fb6388"><code>254914c</code></a> (logger) - logger: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/8d91c68965c76c955300ec0f2e583020c14465e7"><code>8d91c68</code></a> (logger) - logger: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/b6d21828ed8355c658716f9684c7dee4c73a964f"><code>b6d2182</code></a> (logger) - logger: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/c35e59a79f6ccd9946db9979abb9f5125c899695"><code>c35e59a</code></a> (logger) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/a63c07029db0b5f7ec7dc38f4f60489956944475"><code>a63c070</code></a> (logger) - logger: change workdir to /workspace</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/a594b28985d601c0289deedef07ac09ccd58a1f4"><code>a594b28</code></a> (logger) - logger: set gid uid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/9a90e22cac7243e36d88d33f95369a7a5b0a5baf"><code>9a90e22</code></a> (logger) - dockerfile: use uid gid</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/36493b41b11e8847d578dd9563d581bf25adcb2e"><code>36493b4</code></a> (logger) - logger: use common affinity template</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/897a3a5a77ea96250b76bcf06274179c85549c86"><code>897a3a5</code></a> (logger) - logger: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/03b32ab19cd49ddeb966682fe5e7dd4c3b34235e"><code>03b32ab</code></a> (logger) - logger: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/a50ba5fcd9ef8205a1b5064789735241b5ece4b8"><code>a50ba5f</code></a> (logger) - logger: change python-dev registry</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/23187a3fe6e2ffe2d4fc38a705e72c14a85fbb67"><code>23187a3</code></a> (logger) - logger: unified reids declaration</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/aaa129ade36389917750e10389b3274331caf03a"><code>aaa129a</code></a> (logger) - logger: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/be4f65615f0735303f9be4f9d67158979741b395"><code>be4f656</code></a> (logger) - logger: add replicas</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/7c25459be3cb002ea933a47e9ec318d20d69616b"><code>7c25459</code></a> (logger) - charts: add NetworkPolicy</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/6810149b5d3d6199c69909374a72836287f66b9e"><code>6810149</code></a> (logger) - logger: remove memory storage</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/a918c50d5294d3ac8bd6d156d0a63ecd373ba72c"><code>a918c50</code></a> (logger) - logger: add .vscode to .gitignore</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/a41521029d715d227582cb00edc64953028f5983"><code>a415210</code></a> (logger) - logger: add log follow support</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/59b1da3a3172da80b3b16205a6dc420a79208450"><code>59b1da3</code></a> (logger) - logger: upgrade new require</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/27cc151c73ef774d4799e04431748bdd8ffbeea5"><code>27cc151</code></a> (monitor) - monitor: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/07d6a9dff96571e1445fb04da374935062fa18e0"><code>07d6a9d</code></a> (monitor) - monitor: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/105435759e1f9250aaf0e7c0ea8d5b34aa2e0a76"><code>1054357</code></a> (monitor) - monitor: use redis default port</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/e3673dfa93515ecd8507a00b2081ab7749091038"><code>e3673df</code></a> (monitor) - monitor: remove nsqd</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/fc9dd3ed61d7990e451af7b28d7691a6a0557e28"><code>fc9dd3e</code></a> (monitor) - monitor: new ingress style</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/856a898d34a21c18479f11c20926621bcb75894d"><code>856a898</code></a> (monitor) - monitor: add default user env</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/9857535c0cdb43253706d3f6d47d15fd0cc592cd"><code>9857535</code></a> (monitor) - monitor: add random user</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/38b5a040f4617782597abd1ed63f2ac732c64bb8"><code>38b5a04</code></a> (monitor) - grafana: oauth auto login</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/5dfc5797cc291d2a6387713989bc0eb5c130127b"><code>5dfc579</code></a> (monitor) - monitor: upgrade version</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/e121b5a7844ed76b7cca01a89c0cfdbc36438487"><code>e121b5a</code></a> (monitor) - monitor: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/84462a03ead9ebc1addf53ede3089f4abb0db1f0"><code>84462a0</code></a> (monitor) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/b9e8ce8c0775c6ce6725200ca8639b372a91bbe9"><code>b9e8ce8</code></a> (monitor) - monitor: chore(imagebuilder): change uid gid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/05ee8abd8e44a731e070c6417b00f9a777649c22"><code>05ee8ab</code></a> (monitor) - dockerfile: use uid gid</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/e1fa68e170a1b4c8a1fd6ee67d211cb023cb6963"><code>e1fa68e</code></a> (monitor) - monitor: use common affinity template</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/b8f302b73ef2f71f53d3c165db6ca0f9d446e294"><code>b8f302b</code></a> (monitor) - monitor: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/4fc991f9be7d47ea1a029d57bbc8c7fb3c80bd5d"><code>4fc991f</code></a> (monitor) - database: bump telegraf 1.22.0 and grafana 8.4.5</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/21a2f6a6b23f23308d50f97ad99b9164919ff5b8"><code>21a2f6a</code></a> (monitor) - monitor: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/acc976f8c3a834f511cb482de03b0e6473de855f"><code>acc976f</code></a> (monitor) - monitor: change python-dev registry</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/62d76c13d28d136aba544749a837426f3317a794"><code>62d76c1</code></a> (monitor) - monitor: unified reids declaration</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/b3c57ad982406161ef60f04442d4dd9cee91b5b1"><code>b3c57ad</code></a> (monitor) - monitor: optimize oauth2 configuration</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/70af6b07c4c724fbd3070776f4863bffb381d549"><code>70af6b0</code></a> (monitor) - monitor: change passport config</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/69f9a888501b560c698bc6781a80752180f86f04"><code>69f9a88</code></a> (monitor) - monitor: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/2fb278f0ce0d7b9d606b04a4afc297ce44c146f4"><code>2fb278f</code></a> (monitor) - monitor: rename influxdb port</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/17548ffc21f7e10499c535c55ffb413f28576727"><code>17548ff</code></a> (monitor) - grafana: update dashborad</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/69d7bbda0547bae588e01dbcf167d31dfc7debfe"><code>69d7bbd</code></a> (monitor) - grafana: influx dashborad disk size</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/75db1b021bdd974f23f769ae69c9e33aed420d6e"><code>75db1b0</code></a> (monitor) - monitor: upgrade new grafana/telegraf</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/80504a1bb18cfd20493406dccf01e0de1b83713e"><code>80504a1</code></a> (monitor) - grafana: update influx and redis dashboard</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/f7078cba8022651a395db8484be72ca8156556dd"><code>f7078cb</code></a> (monitor) - monitor:chown use env</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/91ae0ddb94a172421923af2b63918b051bc65695"><code>91ae0dd</code></a> (passport) - passport: optimize login display</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/2d3bbbca40f25656872268f3862f71047f861349"><code>2d3bbbc</code></a> (passport) - passport: change drycc logo</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/59790a747eb6bf83345b57dbd3b27d23b760d48e"><code>59790a7</code></a> (passport) - passport: make user email unique</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/faea034774c19cfac3e5858262600cf1842601ed"><code>faea034</code></a> (passport) - passport: use strtobool</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/1fbf2bc2ce25b003a4f424efeeb67a54408b7744"><code>1fbf2bc</code></a> (passport) - passport: use yarn replace npm</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/119cac8f95d371bc51803dd482d9195460e1ede3"><code>119cac8</code></a> (passport) - passport: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/cff5062a2d8acc931c7a88d3afb7b7b8effd2642"><code>cff5062</code></a> (passport) - passport: set default CSRF_COOKIE_SECURE false</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/9cc021077c3f4f3992727c6661ac758bc8f9e60d"><code>9cc0210</code></a> (passport) - passport: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/9ab38969eff6a8bc8b33166ccd5352b0158e5c17"><code>9ab3896</code></a> (passport) - passport: new ingress style</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/259ccc91b805ed463ff0b0889a58debd78214fc2"><code>259ccc9</code></a> (passport) - passport: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/af1bbcdce7c677597c9647b27e96a1e3fcde7f5e"><code>af1bbcd</code></a> (passport) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/9ae5373f0ce8d6ec3a3f2f2915c9e6b08ca1a025"><code>9ae5373</code></a> (passport) - passport: set venv profile</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/8f610901ad7f5aa175433c2c160076cd0bcc3a15"><code>8f61090</code></a> (passport) - dockerfile: use uid gid</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/fcaf72dc9e5f196dc671a8a887ac33dcc4e1b5e2"><code>fcaf72d</code></a> (passport) - passport: upgrade npm package</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/546dcd5b8d668635ada247c7f44d95c0a001bac9"><code>546dcd5</code></a> (passport) - passport: add license</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/4bda2d661883876248c0dd0211fe15551c888c56"><code>4bda2d6</code></a> (passport) - passport: use minify</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/73b0fd135a91bf0e5c6238a659b0e41a5603d179"><code>73b0fd1</code></a> (passport) - passport: use common affinity template</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/278fe7a321f4a8561094d0cd8789918a1fd9a5fa"><code>278fe7a</code></a> (passport) - passport: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/3cd93d36d49972d4c87fc6fc7cbf38c8b6bd8a1b"><code>3cd93d3</code></a> (passport) - passport: add reactive</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/370b493ccac77e04b1366b4037e9fa7f46d4fda1"><code>370b493</code></a> (passport) - passport: add footer</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/483cbd6ae503b4a3116b673272526a842cd1dcff"><code>483cbd6</code></a> (passport) - passport: use h_captcha replace re_captcha</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/3d1675e2af62a5c858b1ae28385af97257c140d8"><code>3d1675e</code></a> (passport) - database: bump python 3.10.4 and node 16.14.2</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/86a783592e559b0a13d2cffcbea6bb4dd7e33684"><code>86a7835</code></a> (passport) - passport: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/2d65355b89a12658a69fad874add357378aedf83"><code>2d65355</code></a> (passport) - passport: change python-dev registry</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/90c1444d2f1f45658fe5a51f406ca58485eb251c"><code>90c1444</code></a> (passport) - passport: unified reids declaration</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/2e0e417f1ce86eff2c4d4f35bf5c40e230382cb8"><code>2e0e417</code></a> (passport) - passport: fix firefox footer</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/ad274bed8c36be339d461c657403070abbb695c6"><code>ad274be</code></a> (passport) - passport: use bulecss</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/f986d8b3a47d9fd83831fece5000189b1ca82dfc"><code>f986d8b</code></a> (passport) - passport: add main footer</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/3e528676fed3aae01fedbc1be39bcab7e997f088"><code>3e52867</code></a> (passport) - passport: dynamic settings for vue</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/38adabc356280f02d3cc048bd00b8ec1be8d91a8"><code>38adabc</code></a> (passport) - passport: change passport config</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/f8d6b604a6009be7b04d4b97d3457dcc0ba1b697"><code>f8d6b60</code></a> (passport) - passport: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/2cbd79daaeb948f274552e897acd53d0bddefb69"><code>2cbd79d</code></a> (passport) - passport: remove database conn_max_age</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/712279768f9c4dee75e5f0f6f6a1ab0865d5e701"><code>7122797</code></a> (passport) - passport: change drycc.cc to <a href="https://www.drycc.cc">www.drycc.cc</a></li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/8cc84cdb7717cc5a50353f7c32e745725c4c5973"><code>8cc84cd</code></a> (rabbitmq) - rabbitmq: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/f35930fb57b5a0b15c82be2f09879de46bd027e7"><code>f35930f</code></a> (rabbitmq) - rabbitmq: add rabbitmq cluster support</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/fbfa3ba8ff88b80d736ae2dee02575d43754529e"><code>fbfa3ba</code></a> (rabbitmq) - rabbitmq: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/ca607015c53dbf68bcdfe636ff46ce17cb973a01"><code>ca60701</code></a> (rabbitmq) - rabbitmq: use volumeClaimTemplates</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/fe5d1b41f48a729f1ada17ddaec4fd738d2c5c26"><code>fe5d1b4</code></a> (rabbitmq) - rabbitmq: add sharding support</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/9c4ab976e148b46d7fb2ba218254bb4cb8789152"><code>9c4ab97</code></a> (rabbitmq) - rabbitmq: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/348a88a95bad2b93971805ae9563555bfbd4ab00"><code>348a88a</code></a> (rabbitmq) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/2388be18e4d23623cc5b461a31f4dbc13562762f"><code>2388be1</code></a> (rabbitmq) - rabbitmq: upgrade erlang to 24.2.2</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/db2eaa5fac326200594c9768a6e6ce85721a8cea"><code>db2eaa5</code></a> (rabbitmq) - dockerfile: use uid gid</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/772afd1f7ed5732355bb9af28018d542d0c6e837"><code>772afd1</code></a> (rabbitmq) - rabbitmq: change to wait pid file</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/2bfc25ec33619c1b10be7639c819c8c2f383bbaf"><code>2bfc25e</code></a> (rabbitmq) - rabbitmq: use common affinity template</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/11d505ea19d520d98f74457054dfdbe9e91a98fc"><code>11d505e</code></a> (rabbitmq) - rabbitmq: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/69d63f1c0ce2ed2a0a80945582db041e5dd7bb7e"><code>69d63f1</code></a> (rabbitmq) - database: bump erlang 24.3.3 and rabbitmq 3.9.14</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/838029926101907d9da255e2cbcabc97dd1b0dba"><code>8380299</code></a> (rabbitmq) - rabbitmq: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/b3f69f14a151124887f49a9c4740905221d8f65a"><code>b3f69f1</code></a> (rabbitmq) - rabbitmq: add check rabbitmqLocaltion</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/5327c76d66cb6339d68036aeff52f13f315ca4f0"><code>5327c76</code></a> (rabbitmq) - rabbitmq: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/5c66b5a74037aa530ed84203c153a7d83f2ba6cc"><code>5c66b5a</code></a> (rabbitmq) - rabbitmq: change probe</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/27bebf99a4fac504dc3e4a2a8d395cc5c23c9ff4"><code>27bebf9</code></a> (rabbitmq) - rabbitmq: add start-rabbitmq script</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/86ee6a780841f4f4927aa4dc6bbc50362fc5f5a0"><code>86ee6a7</code></a> (rabbitmq) - rabbitmq: upgrade to rabbitmq 3.10.7</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/1f29683eb9630822c50687276941bf10b2e1c014"><code>1f29683</code></a> (redis) - redis: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/a5041fc911aa86b277f3577949637f090d7d0488"><code>a5041fc</code></a> (redis) - redis: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/64468c2257c828e61d183d4680b632ea0a24021e"><code>64468c2</code></a> (redis) - redis: add redis persistence</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/de5d7538e64ec86c2d7393dfab922dfe66d29bde"><code>de5d753</code></a> (redis) - redis: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/f6446395fbf46fd644ce3b12a3b5996e7a5b66a2"><code>f644639</code></a> (redis) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/98051d20ecb8f946c8e5093b50791df77494da52"><code>98051d2</code></a> (redis) - redis: premission denied</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/bcb548eca8ae83d1f828bd47e190b6f78a919635"><code>bcb548e</code></a> (redis) - dockerfile: use uid gid</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/524aa412e589ed21c61e31ad03067f8b96a0e116"><code>524aa41</code></a> (redis) - redis: use common affinity template</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/26c946651e503cf3be26225010fcf67a646e8c27"><code>26c9466</code></a> (redis) - redis: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/b67d7a25db6484862676b57d89530f5de4cd254e"><code>b67d7a2</code></a> (redis) - redis: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/839ec50c7c473dcac3fc2fb7e0a51a3493b3db62"><code>839ec50</code></a> (redis) - redis: use env replace creds volume</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/237ca86c239a392e23ce9b7ce68bcf9d1d0da27f"><code>237ca86</code></a> (redis) - redis: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/bdd968d27a01a06110ac394fcb4f7893cfb0edc1"><code>bdd968d</code></a> (redis) - redis: upgrade neew require</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/8b2910f10b7f5b6da8828bf8558f4eb373fcc238"><code>8b2910f</code></a> (registry) - registry: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/eedbe78543bf04298134ee2900b21d9218fd99e5"><code>eedbe78</code></a> (registry) - registry: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/024161578b010ad70702ae9480cb07a9b210ca61"><code>0241615</code></a> (registry) - registry: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/9b58da4298fd28f3ca060ce2ffd11a0977b755e1"><code>9b58da4</code></a> (registry) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/ab6acb71f85990865cd4322ef21e3d2ae0903ac8"><code>ab6acb7</code></a> (registry) - registry: change workdir to /workspace</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/f368bf7d7dfb8357acc8bf5019d052057dba393e"><code>f368bf7</code></a> (registry) - registry: use DRYCC_UID DRYCC_GID env</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/f4b9041f9c18721dcfc71091a89145323c5fc092"><code>f4b9041</code></a> (registry) - registry: use common affinity template</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/c2e87ca32c58633e9f86b3422d48249b3c1d81a8"><code>c2e87ca</code></a> (registry) - registry: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/feb6aba75f16044ecd927e020372338cd6ddf519"><code>feb6aba</code></a> (registry) - database: bump mc 2022.04.01.23.44.48</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/956932b04720266b896c0ea150a595c77a513444"><code>956932b</code></a> (registry) - rregistry: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/deda8d8d7868938fa890b5e7a0f22911e7151837"><code>deda8d8</code></a> (registry) - registry: move registry-secret.yaml from workflow to registry</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/f52c7bf6e4bc23d4f7b4e78224ff2d8da81198bc"><code>f52c7bf</code></a> (registry) - registry: change python-dev registry</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/007fe03a89f5e3b6d9baeda0b3fea84041a46ea4"><code>007fe03</code></a> (registry) - registry: <a href="https://github.com/minio/minio/issues/14331">https://github.com/minio/minio/issues/14331</a></li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/d620c6db554f29b6c9b044c12b5dfd62194f274b"><code>d620c6d</code></a> (registry) - registry: <a href="https://github.com/minio/minio/issues/13799">https://github.com/minio/minio/issues/13799</a></li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/85e6b732126ea2dacb4db0d79b2fbb831b0d984a"><code>85e6b73</code></a> (registry) - registry: use env replace creds volume</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/6a1155d75f7d6007f7ef3fe2c947423567c20e65"><code>6a1155d</code></a> (registry) - registry: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/7b8ebae5738c401580391a631757fa4646a31f3c"><code>7b8ebae</code></a> (registry) - registry: change minio to storage</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/13389519866129557fe9e08b446eb3a3de163a71"><code>1338951</code></a> (registry) - registry: add check storage health</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/2fa769dcfb770b1f9789e3ab13f96380f3e708c6"><code>2fa769d</code></a> (registry) - registry: change probe</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/f187cbf22c9206693656df844e2f97007dd95574"><code>f187cbf</code></a> (registry) - registry: add replicas</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/09d8a7b3cc69d6e0f90ab19b727f54b7129a3ae5"><code>09d8a7b</code></a> (registry) - registry: upgrade to mc 2022.08.28.20.08.11</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/4b187b8d076ef387b667e0807081021184c1f55f"><code>4b187b8</code></a> (registry-proxy) - registry-proxy: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/29ffbbe58737a14432a69938c69ff54c056b7f85"><code>29ffbbe</code></a> (registry-proxy) - registry-proxy: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/6d783baa4be1de057980040830fd6d3b161347a8"><code>6d783ba</code></a> (registry-proxy) - registry-proxy: remove use_cni</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/8cf05cff7cb44bf0b0f5c94e76567607d2f9adef"><code>8cf05cf</code></a> (registry-proxy) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/090e28647345560182a8f21da8f9445d567e3c73"><code>090e286</code></a> (registry-proxy) - registry-proxy: chore(imagebuilder): change uid gid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/7cf6120e818b9a12799a305d8d17dfef8746a9b1"><code>7cf6120</code></a> (registry-proxy) - registry-proxy: use DRYCC_UID DRYCC_GID env</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/3a00697ed5de2230fc98971798d16de4ac6ceccd"><code>3a00697</code></a> (registry-proxy) - registry-proxy: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/30e69e8ca26894cc9efcd206665c5d96aa198085"><code>30e69e8</code></a> (registry-proxy) - registry-proxy: add registry basic auth proxy</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/942abce928797f2a77883f3a6a1a6720a6774c34"><code>942abce</code></a> (registry-proxy) - registry-proxy: upgrade to nginx 1.23.1</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/5ea3297285ab826c6686bcd20c34b1dd178615f6"><code>5ea3297</code></a> (storage) - minio: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/8306addad83bf486ae0d796d85b8f5593ca22ef7"><code>8306add</code></a> (storage) - minio: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/c917e9f3e1b03d0c9557f41f753c05f5d48f60df"><code>c917e9f</code></a> (storage) - minio: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/042c73208b255364db2cc08374a7b9ba39946edf"><code>042c732</code></a> (storage) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/7b47b82f903ecd1e6f6c1a30ed856f7153eaef20"><code>7b47b82</code></a> (storage) - minio: change workdir to /workspace</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/6f3531ef29ed032f3f0bcbc09211e9030a02340a"><code>6f3531e</code></a> (storage) - minio: use DRYCC_UID DRYCC_GID env</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/9795fb1c71641cd106dc06abeb355c8479b0a351"><code>9795fb1</code></a> (storage) - minio: use common affinity template</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/a7b09c5b264fa9ce068ae06b12ac5fec6e7a63d4"><code>a7b09c5</code></a> (storage) - minio: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/76073428fa40f6048482594720707c1e92ca17d5"><code>7607342</code></a> (storage) - database: bump mc 2022.04.01.23.44.48 and minio 2022.04.01.03.41.39</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/ea2b2f15ffc2c4d263e537aa14a74f9c71a450cc"><code>ea2b2f1</code></a> (storage) - minio: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/445b50100629f5799b4137fa5d71a4768836f8d2"><code>445b501</code></a> (storage) - minio: <a href="https://github.com/minio/minio/issues/14331">https://github.com/minio/minio/issues/14331</a></li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/f19fbc75f98c5f1349bdfe098c69bdf732a10886"><code>f19fbc7</code></a> (storage) - minio: use env replace creds volume</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/8982e2eab58a059040d483c4ac373e9ccced0765"><code>8982e2e</code></a> (storage) - minio: use minio to distributed</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/06bec7372476dec97304f51754a9c031498fd888"><code>06bec73</code></a> (storage) - minio: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/9b8f0062892bcd4f720014a142efde4ce6ed10c6"><code>9b8f006</code></a> (storage) - storage: remove assert</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/59d64b92e21603e86573699e5b1e2914672cfe3a"><code>59d64b9</code></a> (storage) - storage: change listen to POD_IP</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/60044ee012378c0c344518f5945ed6dace124535"><code>60044ee</code></a> (storage) - storage: add juicefs mount options</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/189f944175bd9c16d3a8d5347a9040143903e15a"><code>189f944</code></a> (storage) - storage: remove volumeName</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/302fe8964b3171bc6c7cdddd494d5e3ca62c5209"><code>302fe89</code></a> (storage) - storage: mv to minio dir</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/6ec586d742cf14f311e2ac097ad207c2b3fb65b4"><code>6ec586d</code></a> (storage) - storage: change readinessProbee andlivenessProbe</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/0e028dfee98c4cf8a54110101f1084b03cf75b8e"><code>0e028df</code></a> (storage) - storage: add minio pdb</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/cf9bd2de2b8138b6a75c1d804e919586d2d53eca"><code>cf9bd2d</code></a> (storage) - storage: add check storage health svc</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/2dd5c9f20dcbbdb184d3e0be19a9e93b41ac1019"><code>2dd5c9f</code></a> (storage) - storage: add volumeBindingMode</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/fa2effc313905bf8e7a0d41d6d09335ca1a70552"><code>fa2effc</code></a> (storage) - storage: remove databaseBucket</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/d166cc721e45bf1955a2d99b70187ee9b3d6970a"><code>d166cc7</code></a> (storage) - charts: format network-policy name</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/d06bcce9fe0e8de7720e5c93b5d87e742be7f5a7"><code>d06bcce</code></a> (storage) - storage: upgrade to golang 1.19</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/c2ca05cd4b92259d4454723ab25252e4f6e220ac"><code>c2ca05c</code></a> (storage) - storage: upgrade new require</li> +</ul> + + + + + + Blog: Drycc Workflow v1.5.0 + /blog/2022/10/06/drycc-workflow-v1.5.0/ + Thu, 06 Oct 2022 00:00:00 +0000 + + /blog/2022/10/06/drycc-workflow-v1.5.0/ + + + + <p>These release notes for Drycc Workflow v1.5.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.4.0, please refer to the following change summary.</p> +<h2 id="workflow--v140---v150">Workflow ## v1.4.0 -&gt; v1.5.0<a class="td-heading-self-link" href="#workflow--v140---v150" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>passport v1.0.0</li> +<li>rabbitmq v1.0.0</li> +<li>imagebuilder v1.0.0</li> +<li>builder v1.2.0 -&gt; v1.3.0</li> +<li>controller v1.3.0 -&gt; v1.4.0</li> +<li>database v1.0.2 -&gt; v1.1.0</li> +<li>fluentd v1.1.0 -&gt; v1.2.0</li> +<li>redis v1.1.0 -&gt; v1.2.0</li> +<li>influxdb v1.0.1 -&gt; v1.1.0</li> +<li>logger v1.1.0 -&gt; v1.2.0</li> +<li>minio v1.1.0 -&gt; v1.2.0</li> +<li>monitor v1.1.0 -&gt; v1.2.0</li> +<li>nsqd v1.1.0 -&gt; v1.2.0</li> +<li>registry v1.0.3 -&gt; v1.1.0</li> +<li>registry-proxy v1.0.2 -&gt; v1.1.0</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/0f5f8e4171313ea56de2d659d92458acd39a3201"><code>0f5f8e4</code></a> (builder) - builder: multi-platform support</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/f269d06ddc42464ba99ceeabc283645778034547"><code>f269d06</code></a> (builder) - build: add buildx supportjkjkk:q</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/5e72fe88f057c1814c6d8075638d124445c16157"><code>5e72fe8</code></a> (builder) - registry: use docker build</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/25d8a4cbc14ccfeccc0a33d17fc723149103a0d3"><code>25d8a4c</code></a> (builder) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/7a3e1c58942dfdfde474462f92a2a5bddf1c15a8"><code>7a3e1c5</code></a> (builder) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/46b75ff211da2985ce17737e7c6bb29ce73c8df3"><code>46b75ff</code></a> (builder) - builder: add cloud native buildpacks support</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/2db2054dd960f80ee76c442d3705490c5f70358a"><code>2db2054</code></a> (builder) - builder: unified build model</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/4b7f9d9bc38c65ca56e162701b4cbce43c1cbbbe"><code>4b7f9d9</code></a> (builder) - builder: add initContainers</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b78c936ec706cce8bd8e8676a411187fed658b23"><code>b78c936</code></a> (controller) - token: add get token api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/bac52a51b06872d48ecefabfb14b29b9f70d4357"><code>bac52a5</code></a> (controller) - tasks: use celery replace nsqd</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b9b0c58b1f877d077543efb202c71f5cec07b6fc"><code>b9b0c58</code></a> (controller) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/205dcb3b5b1003d704a0033d3a3b8b6761393df9"><code>205dcb3</code></a> (controller) - influxdb: add influxdb client</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ff15849bafddc47e06820ca89e8e95abc6c89311"><code>ff15849</code></a> (controller) - influxdb: upgrade to influxdb 2.x</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4016244757d764b553abd20ffb8ed79368c7caa1"><code>4016244</code></a> (controller) - controller: push data to influx</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/fcfce2ea7f6af657c46a1c53f0f78b7224b56ff6"><code>fcfce2e</code></a> (controller) - workflow-manager: add workflow-manager support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/00e9bfb627c11be35fd57c330d3127c84675b0f6"><code>00e9bfb</code></a> (controller) - influxdb: review influxdb code</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/dd644d5a5e626d51ddb6f4d6488691ac7f2f2804"><code>dd644d5</code></a> (controller) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/118278b332877428f09d13801432a8c7f51ebbee"><code>118278b</code></a> (controller) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/122a9cd267f8b80d4b922938b97a71032f174648"><code>122a9cd</code></a> (controller) - oauth2: add oauth2 support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/559a5b6c76a0b9925bdd7d027e5653b7d494d4ac"><code>559a5b6</code></a> (controller) - controller: use cncf buildpacks replace slugrunner</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/96130e6900dae2bc31899e3a06fec87c5c6684c9"><code>96130e6</code></a> (controller) - charts: database configuration optimization of passport and controller</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/2ea85089f9ef7814e7c504380929c09cd73fadb2"><code>2ea8508</code></a> (controller) - oauth: using passport authentication</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/868c437940b7cde4caaf0b4f81ab5265cd2f197c"><code>868c437</code></a> (database) - database: multi-platform support</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/eadd5da76c3a5979a90b52b245dc9041da861d6a"><code>eadd5da</code></a> (database) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/b6eea4c09dcd95d7f8f0540c2ffef63567146167"><code>b6eea4c</code></a> (database) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/04a88dbafe96027068badd9e65c30b832432c371"><code>04a88db</code></a> (database) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/92ed309894ef2d065d4dc20acf5cf44dfafa84d7"><code>92ed309</code></a> (database) - database: add initContainer</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/ee6b78ff78bfe978edf2e9a9789bdf58c2dc846f"><code>ee6b78f</code></a> (fluentd) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/f523e30c5e93d80e509232e7bb25f4de92267312"><code>f523e30</code></a> (fluentd) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/ee47b53b6f18bf4e2cdd41aaabf4dcd807d4b2d7"><code>ee47b53</code></a> (fluentd) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/80a51af1c0dbf689ead41a4b88d5e31861a7b0d0"><code>80a51af</code></a> (influxdb) - influxdb: modify influxdb naming rules</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/fb1003086e3819ada293e1792b46e966e509ee3a"><code>fb10030</code></a> (influxdb) - influxdb: use influxdb v2</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/0e87ad8c239a8cbb4ec02a584081ac1be0cb21af"><code>0e87ad8</code></a> (influxdb) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/9d108019d94ce2e653ec16482e89dff314810f9b"><code>9d10801</code></a> (influxdb) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/d825c9f7b4198c10e93abc7121af54f7af63f711"><code>d825c9f</code></a> (logger) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/b1395766670636ecbb42fb0b4ca1649186bfd4c5"><code>b139576</code></a> (logger) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/88f84ea95e334fcfef45ecd4f28c8bc468523574"><code>88f84ea</code></a> (logger) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/5ccae3ef8fa0894f08bf6ba552b17455a481a698"><code>5ccae3e</code></a> (logger) - dockerfile: remove chmod cmd</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/193aefc8c4106c7c6d5022c9183c68d6e604e735"><code>193aefc</code></a> (logger) - logger: add initContainers</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/baee3305a3b09a0fba83f33fb161400a7e7fd7fb"><code>baee330</code></a> (minio) - minio: multi-platform support</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/ad5d055e170977801a6951813e4896d1f854e14f"><code>ad5d055</code></a> (minio) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/19868d457852e423536d8ae8f426a2c3437f423d"><code>19868d4</code></a> (minio) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/4bd84b8bb8af65a0ab05eff3a4c227452c4a3a2f"><code>4bd84b8</code></a> (minio) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/79d1f2f85c17c71ec609e8e191e04e9de87deec0"><code>79d1f2f</code></a> (monitor) - database: multi-platform support</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/88e5a7f45886f5ca947e44052c5c52a2f8e17497"><code>88e5a7f</code></a> (monitor) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/5672e99a81ce856e4cd42a1b4e1083919e165272"><code>5672e99</code></a> (monitor) - influxdb: modify influxdb naming rules</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/867210310f29da9600bb2d052e05d5181cfe5a4f"><code>8672103</code></a> (monitor) - influxdb: use influxdb v2</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/66cb4c877ee0acfdcabab284da18b58266b61201"><code>66cb4c8</code></a> (monitor) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/9576eb38c61048d3d540303047c8690763d664e1"><code>9576eb3</code></a> (monitor) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/30809c9ce3f31f52ac10616dbe9a24135d74828d"><code>30809c9</code></a> (monitor) - monitor: add initContainers</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/70d140ce05b061462a990029b9fd7ac749c383c7"><code>70d140c</code></a> (nsqd) - nsqd: using self compiled nsq binary</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/1073d4f35b082ea6dd63570d8427d7e3d1c2fecf"><code>1073d4f</code></a> (nsqd) - nsqd: use GOPATH replace /go</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/e49848037b54362f83ee063adc6e954afe8fa84a"><code>e498480</code></a> (nsqd) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/cf9b7d5cd6ee63d77acadec5c3a410acb60df400"><code>cf9b7d5</code></a> (nsqd) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/c335856f1ca9c80b0dc23df3445d395a13b8b50b"><code>c335856</code></a> (nsqd) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/efba7134453bc730b968d909089564de3de3079a"><code>efba713</code></a> (redis) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/c7a3b53025faa393bf6e915ec71b96ef7a5da27f"><code>c7a3b53</code></a> (redis) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/4cdad7bab726dd11973c1dbc643a81eb6313ba1f"><code>4cdad7b</code></a> (redis) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/652b443a4e5c54765bb40cfeb38310eee455a3c2"><code>652b443</code></a> (registry) - registry: multi-platform support</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/4060176efaca5531faec4ecdd02eb30b6451e16e"><code>4060176</code></a> (registry) - registry: use docker build</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/7102a03677830beb4b0ad093b141cb48ba948dd7"><code>7102a03</code></a> (registry) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/6c8600d293589b36748acf7b4dfb913f2cefde8d"><code>6c8600d</code></a> (registry) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/33a51c99e3f278c7c36dfc27c124db3dec530914"><code>33a51c9</code></a> (registry) - registry: add initContainers</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/bef70dc98c4b044d1108f6b42f439b36d37270e1"><code>bef70dc</code></a> (registry-proxy) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/d2319c1fce4e57cd9257ec3978f4e5a8d0101a23"><code>d2319c1</code></a> (registry-proxy) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/02fafed2b1b5648274c3d44c3d113a0a025e4fca"><code>02fafed</code></a> (registry-proxy) - charts: set the default chart version</li> +</ul> +<h4 id="fixes">Fixes<a class="td-heading-self-link" href="#fixes" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5499c9a2844c192285d5afdbf6a08d803a70cf8d"><code>5499c9a</code></a> (controller) - gunicorn: gunicorn not running</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/06e9e8869fbf61b3db753ab211bd9d465afa9058"><code>06e9e88</code></a> (controller) - controller: error loading shared library</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/01b5bd04cf1848b876b2b5acbeae6c361bebf975"><code>01b5bd0</code></a> (controller) - controller: upgrade celery config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/6e32d55cf9de3dce1b7d470f850c2d155809cc07"><code>6e32d55</code></a> (controller) - controller: fix update resources bug</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0e0d53f3056dfbf427ad7a474786e723b87cb39c"><code>0e0d53f</code></a> (controller) - chart: set the domain depends certManagerEnabled</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/2ac4ca839d76a4b80205506938d63f25bb4abea0"><code>2ac4ca8</code></a> (controller) - passport: error loading shared library libexpat.so.1</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/a0dd517e189a2ba9472c0d320ba32d091520dcbe"><code>a0dd517</code></a> (fluentd) - fluentd: drone build</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/6eca2a3e17e2965816718963fe4d7f6ffeb15a42"><code>6eca2a3</code></a> (logger) - logger: golang lint</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/63b0aa0989db8f9e15daa415c5a0b56e9350c0a9"><code>63b0aa0</code></a> (registry) - drone: charts url error</li> +</ul> +<h4 id="docs">Docs<a class="td-heading-self-link" href="#docs" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/472cfcc226c98d2b9a74c367519d57ec31890b71"><code>472cfcc</code></a> (controller) - controller organize README.md document</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/d9d6e292c602c3538784de6755b40f4655710278"><code>d9d6e29</code></a> (redis) - redis: delete links that do not exist</li> +</ul> +<h4 id="test-case">Test case<a class="td-heading-self-link" href="#test-case" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1468f57465243709594b0d6472636ccc0d7b7f62"><code>1468f57</code></a> (controller) - controller: add command unittest</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/9999bfd30ab9550966eb70a6e52efbbb38f5cef1"><code>9999bfd</code></a> (builder) - builder:replace the special words</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/cda8b5814e507ab72a0ce7125eaa8d6bdd168a06"><code>cda8b58</code></a> (builder) - builder: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/dc575dde93ad1334be9d1337fbc1b0b66a06ebd9"><code>dc575dd</code></a> (builder) - builder: use imagebuilder replace dockerbuilder</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/d3bb183df646a7f2503c739633bb6d5d61778219"><code>d3bb183</code></a> (builder) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/5fe34d1fee978986729120af7d5732ed3759b88c"><code>5fe34d1</code></a> (builder) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/7e364532bf841109fe5e75c6a5c357ad46f7c4b7"><code>7e36453</code></a> (builder) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/52b8d9df26f28e562b4eca72e777106db86db9db"><code>52b8d9d</code></a> (builder) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/65963f4b35d2b60e376818d314cd203fb698eaba"><code>65963f4</code></a> (builder) - k8s: add privileged to dind</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/d345fcf23f1c3e755ec646d988c5d1e0e90d2eba"><code>d345fcf</code></a> (builder) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/7975c998252a66557bbfa774ac18f18e17a5ddbd"><code>7975c99</code></a> (builder) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/59633dd9197fed8400d8007cc93e7a62404e92b1"><code>59633dd</code></a> (builder) - builder: modify launch imagebuild pod</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/8d14e67e5e84c2d6b6254b7704219c9ed38aac67"><code>8d14e67</code></a> (builder) - builder: use Procfile in anywhere</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/5357fa88e56ef24fac7f8d3dc0bfa5d990c1be58"><code>5357fa8</code></a> (builder) - go: bump go mod</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/8d26ac054edeb67e4ce473507a96951dbda10db2"><code>8d26ac0</code></a> (builder) - k8s: k8s deprecated api migration</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/0af620def4db8473c799c9499a4a27ee4a278210"><code>0af620d</code></a> (builder) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/ae84303f6d15b22c525e62cf3ae2d1e314d9a67b"><code>ae84303</code></a> (builder) - builder: run imagebuider replace pod with job</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/3b2c496a00a8512731c18d79215ce9e279b60e19"><code>3b2c496</code></a> (builder) - builder: change docs website</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/5679a4cfefd214b7bb0014cde3f7c461bd70ca91"><code>5679a4c</code></a> (builder) - builder: upgrade to golang1.17</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a214503452b10f3e265d97954964d321480b007d"><code>a214503</code></a> (controller) - controller:replace whitelist with allowlist</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/375ddcc15761326b8c74f8cd78a239cfe9c14224"><code>375ddcc</code></a> (controller) - ps:drycc ps:list show autoscale num</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c32e409b6fe09c533bc5cfdbf35b47e633d2a644"><code>c32e409</code></a> (controller) - ldap: canot register when ldap is enabled</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c46580a6264cbe21ee5240fde5791c9c78ef2a19"><code>c46580a</code></a> (controller) - controller:modify redis config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/fa9e87b6131a9669eebafb4bfea26dc5f15bde64"><code>fa9e87b</code></a> (controller) - chart:modify controller charts</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/6f9fd081e6826fd89316ff4d064c9cf03501e1d3"><code>6f9fd08</code></a> (controller) - nsq: remove nsq</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/994b2dc68afdeaedc540525422183565bc1e3230"><code>994b2dc</code></a> (controller) - docker-buildx: add check-docker</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a720c3a9933aaaa15d5933143708fbcac2d5233a"><code>a720c3a</code></a> (controller) - controller: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e9a5c843d0abd85ae57d8cb87cbe7369364b07e6"><code>e9a5c84</code></a> (controller) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a26614acb4fb8cef5030e0e56681939977a7a266"><code>a26614a</code></a> (controller) - controller: add rabbitmq env</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3df229d2d31b6f8fc79a260e5088a86d00716459"><code>3df229d</code></a> (controller) - controller: modify database config &amp;&amp; remove redis port config &amp;&amp; add env prefix with DRYCC</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/257e94b429c8f7b0c636a083215d9709baaf5c8d"><code>257e94b</code></a> (controller) - controller: CELERY_BROKER use rabbitmq and modify celery-deployment cronjob</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f4d6ec343ec3fb618ef9ee8da09474294d49807e"><code>f4d6ec3</code></a> (controller) - chart: pretty chart format</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/63e61951cda276fe59a91a64a7b84f7feb66ce6d"><code>63e6195</code></a> (controller) - influxdb: modify influxdb code</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0f6d408734984e4ec9bbc56c0a4b68ba5783b680"><code>0f6d408</code></a> (controller) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/87bad28b65b773e6534c4cc8e2128045d3ffb7c3"><code>87bad28</code></a> (controller) - python: upgrade to python3.9</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e8f75603cd0cd38423d774f1b3220b64ef9eb6dd"><code>e8f7560</code></a> (controller) - volumes: modify mount summary</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/6cf6c6bdbf029b1e52a36d5148d5a025fb6d04c1"><code>6cf6c6b</code></a> (controller) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a9397e8c06a69d5539e8f5b67be242932e69c2c8"><code>a9397e8</code></a> (controller) - oauth: modify token Authentication</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c7f8c8b3b2294205603afd9ca4a7ba2e3f6cea02"><code>c7f8c8b</code></a> (controller) - deps: bump django from 2.2.14 to 2.2.18 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a1a08aa4165ba678e979d6ca4477694999d0e5b8"><code>a1a08aa</code></a> (controller) - deps: bump djangorestframework from 3.11.0 to 3.11.2 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/efd78b42038a404d53d06e92bb609cc7f97739db"><code>efd78b4</code></a> (controller) - deps: bump django from 2.2.18 to 2.2.20 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/649b044c644c9729b80e5f0e2663779bcc648ef2"><code>649b044</code></a> (controller) - deps: bump django from 2.2.20 to 2.2.22 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/41b742bbec9370490b0176fac407bcbd83abd2ed"><code>41b742b</code></a> (controller) - deps: bump django from 2.2.22 to 2.2.24 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/22ffe5d8dd51cffc38e5e3757ac97eba02861e2b"><code>22ffe5d</code></a> (controller) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c98b46837efa85a5daf46c6dc40d45606b7548bc"><code>c98b468</code></a> (controller) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/20e6edb1001fb709ea877349771404ee807ae36d"><code>20e6edb</code></a> (controller) - chart: modify the problem of using buildpack</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/db16879a4ce64c7020b7622603f53ef88898be0a"><code>db16879</code></a> (controller) - controller: pretty pods list print</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ba6f456ddb0a48a0e8c1f446330a838ba27b8f48"><code>ba6f456</code></a> (controller) - test: pretty pods list print</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5fce4b7a77c91836d921c6d1f4cb8cacb2ab953d"><code>5fce4b7</code></a> (controller) - k8s: k8s deprecated api migration</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e9e0bcb36d4b6b1169446c484357260aee7feba7"><code>e9e0bcb</code></a> (controller) - oauth: using passport authentication</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0311172bea0f1d28959ee528c0e50493d0c8d425"><code>0311172</code></a> (controller) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/150eff1c246b908e8f5521cc1e5e9ff4c765433d"><code>150eff1</code></a> (controller) - charts: update cert-manager api version</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/de8545a568984f52e5757806d9ce631864285fed"><code>de8545a</code></a> (controller) - controller: update requirements</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1442207889955cbf230bd1c87867acaab72256fb"><code>1442207</code></a> (controller) - controller: using django native JSONFiled</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ab4e836a55aa61cbdb222a8fc606b5619625337e"><code>ab4e836</code></a> (controller) - oauth: modify passport api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5c54e0642c76bfa1253397177b5aef2dc28dc611"><code>5c54e06</code></a> (controller) - controller: eliminate pip warnings</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/870328ddf06ab6b3004fd0e56516de6496c06e26"><code>870328d</code></a> (controller) - controller: remove entrypoint</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5e5e6ae5763333989e153119c6078c06788d0f78"><code>5e5e6ae</code></a> (controller) - controller: upgrade celery config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/607778ffb2f81b74457db2b34952a0cd01647eb3"><code>607778f</code></a> (controller) - controller: add initContainer</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/23dc016da2419237814a7d1ac54435adc99f0423"><code>23dc016</code></a> (controller) - chart: set the domain depends certManagerEnabled</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f3cf20b610a649d105e4889212272604615ddfa7"><code>f3cf20b</code></a> (controller) - controller: remove default bash env</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/73f26364110a1cdee5bdfe868e4fbf0be2cdbcf4"><code>73f2636</code></a> (controller) - controller: modify alpinelinux repositories</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/498e9f2fbd5470ff8079e09eacc04be4272d9601"><code>498e9f2</code></a> (controller) - chart: change certManagerEnabled to boolean type</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/27f5308938f972d078e78c539e9160cc2f3b3a1a"><code>27f5308</code></a> (controller) - passport: exclude cryptography</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/370b75dc9cbdcf24b3955b562ff276e3214eb5a2"><code>370b75d</code></a> (controller) - controller: use sh env</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/07585b4f45471b22e6942590dac51cf724e8bd57"><code>07585b4</code></a> (database) - postgres:replace the special words</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/20172dcfac8370b389aa26a30cc9e2f0a96f6a6d"><code>20172dc</code></a> (database) - database: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/abb9b88a96e0098d3fb1128d123825ca4faea3a4"><code>abb9b88</code></a> (database) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/e72f58ffa50be0f5170423529292872fcd53cfea"><code>e72f58f</code></a> (database) - chart: modify the off-cluster database</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/a91f64f694c15143b7210597ffdd7dacfa6668bf"><code>a91f64f</code></a> (database) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/614fb76a1c77b8f5697a87aadfd094d6eaa8c27b"><code>614fb76</code></a> (database) - tests: use add-host replace link</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/a3428f353c38f440381890fd80416ad302033352"><code>a3428f3</code></a> (database) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/239fef11f87655203f6090e55259cb09906fb253"><code>239fef1</code></a> (database) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/42858e1e2ae1a09e1bad75e1fabb7ec4115e7197"><code>42858e1</code></a> (database) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/d0fe85094eb305ce071f51bf40bdf2099b88ea13"><code>d0fe850</code></a> (database) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/34a36ad4f650d6eaf2320e55f4d80a06e0dd1675"><code>34a36ad</code></a> (database) - charts: Nn secret is generated during off-cluster</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/064ccf462a1bd2fe513809c39919fc1ccaba7801"><code>064ccf4</code></a> (database) - database: create database</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/9228992327543f008bf4158be8b8cd1777c3ba90"><code>9228992</code></a> (database) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/9f7810c6dcf6323bc6f75345f4c9fc25a5e11ef6"><code>9f7810c</code></a> (database) - database: upgrade to wal-g v1.1</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/05783f4118cd7e8cc80e41c20656f5b16961fa3d"><code>05783f4</code></a> (fluentd) - fluentd:replace the special words</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/0739809ba68d12ef8940f0f6addcfea7353885f5"><code>0739809</code></a> (fluentd) - influxdb:replace monitor-influx with influx</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/f02487cea73f20a2039fe6c1960950a3b73107b5"><code>f02487c</code></a> (fluentd) - fluentd: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/2c96cc089f7965286409cb4d710df5ab947b20b5"><code>2c96cc0</code></a> (fluentd) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/b20c429b9ace293c7add60fa350098b91285bf87"><code>b20c429</code></a> (fluentd) - charts: remove port config</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/6dd019721438cf32f2262bdb76d74da9ab5b37a3"><code>6dd0197</code></a> (fluentd) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/c5bec512a902662a8200639b3b574925c836e734"><code>c5bec51</code></a> (fluentd) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/f8524b78536b6d6cc1022e3cfa6ab61ac36fbca8"><code>f8524b7</code></a> (fluentd) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/a50878aabea91b3fbbafaf9c1f43c2eca7fe5a5c"><code>a50878a</code></a> (fluentd) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/14fe20e811ba3c8814188dcec18ed69c169c4b9d"><code>14fe20e</code></a> (fluentd) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/4a2f66070910abcc3068d0e03a8e52d1e5d2659d"><code>4a2f660</code></a> (fluentd) - k8s: k8s deprecated api migration</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/de2dd9178130101f4b0c5ed82d5e80a1ba4dd591"><code>de2dd91</code></a> (fluentd) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/a9f1944c3dcac5e8f0eb2f44d11ec81517735b8c"><code>a9f1944</code></a> (fluentd) - fluentd: upgrade to fluentd1.14</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/7cb4e954704cfa5ff37d3b95b5e9a231188f4264"><code>7cb4e95</code></a> (influxdb) - influxdb: change username to user</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/0fdc21b2a95003abd488cb05b640ec1fa1db3ff7"><code>0fdc21b</code></a> (influxdb) - influxdb: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/b2acddb8d72bd0e17fb0b543a8f98e2fa5d57735"><code>b2acddb</code></a> (influxdb) - influxdb: change default path</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/ba8891910d5ef9084f9dd9b7569d905e19f056ea"><code>ba88919</code></a> (influxdb) - influxdb: add check_env function</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/91174010ed68356d9b813b70e2def18af9ed5186"><code>9117401</code></a> (influxdb) - influxdb: modify init_influxdb has_bucket</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/092a3e6b96e9494f00e7a0627b2aa9ce1212c7d4"><code>092a3e6</code></a> (influxdb) - chart: pod not readiness</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/51de380cc83177be8bdb557894b9fd5c28ed0a3d"><code>51de380</code></a> (influxdb) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/66d76679cc55578d13274fa5bf0e653b258e57b4"><code>66d7667</code></a> (influxdb) - docker: replace influxdb base image</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/3aa30943cea519fff18c23264c99c226cfb43c80"><code>3aa3094</code></a> (influxdb) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/14b9c24f110297e5b6a632ce4ad94625f5663038"><code>14b9c24</code></a> (influxdb) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/02b4cd111c092393b0f2d3f1c1654d0476603b03"><code>02b4cd1</code></a> (logger) - logger:replace the special words</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/114b5d5392a1d82f8dc73b4b1527e742fcaf22f1"><code>114b5d5</code></a> (logger) - reids: delete the logger prefix of redis</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/639278a8f055d7872491db2240f4327d4f77114e"><code>639278a</code></a> (logger) - redis: remove logger from redis conf</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/90195e27521b44e0d43f8fb7ff9ab9a658f60676"><code>90195e2</code></a> (logger) - go: remove GOOS and GOARCH</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/31e2e27f9160e62b199c196972fe5c0097a78a22"><code>31e2e27</code></a> (logger) - logger: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/8fbd9fa7b119f112221be5fa5bdc21e3a891a6b9"><code>8fbd9fa</code></a> (logger) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/b39df2d46e0f625900f80d0103a5a35c4e7fbb0e"><code>b39df2d</code></a> (logger) - charts: remove redis\nsqd port config</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/35d6d0784df91dc1036928c83905052962a84ca0"><code>35d6d07</code></a> (logger) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/69aabf527a1bea60f6d7792a488ed074d138a27a"><code>69aabf5</code></a> (logger) - tests: remove docker link</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/e916644cd89379731f5a9990044e3f64d570b6dc"><code>e916644</code></a> (logger) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/d6872b7cfbd30d0be087270b581a0730961f4b8b"><code>d6872b7</code></a> (logger) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/37801daabfe98292c54ed2902aeb120069448b64"><code>37801da</code></a> (logger) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/cfb4b38897136e5c1b942433b52944cdccc9b195"><code>cfb4b38</code></a> (logger) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/8bda3bf9906424c9be8661ab0d6850ae6e3352ea"><code>8bda3bf</code></a> (logger) - go: bump go mod</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/e13ebfcd5fc940393e1d398623650bfcd31c24de"><code>e13ebfc</code></a> (logger) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/38e6d8d592ad42a176d08f0d7edbe38e55b39b72"><code>38e6d8d</code></a> (minio) - minio:replace the special words</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/d6925ddec232dd3b6187414f4a11327330baa95a"><code>d6925dd</code></a> (minio) - minio: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/d56bc39ba487c24e89a47e6c63375342ba3c3552"><code>d56bc39</code></a> (minio) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/e4696cc243711c53a1fe16051cd80209c8a3d281"><code>e4696cc</code></a> (minio) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/70c5c7988a513b5a39b92e442b0f9052d1507f67"><code>70c5c79</code></a> (minio) - minio: use latest version</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/773cf6c47a4ab539dcac29084980953bdd0e9e04"><code>773cf6c</code></a> (minio) - Makefile: remove DEV_REGISTRY ?=</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/5ce5bc696e7522107139cccfec37c6dc4b759059"><code>5ce5bc6</code></a> (minio) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/5da8be3ca9345e7a6c87ad61bf104b7345523691"><code>5da8be3</code></a> (minio) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/c1f0611fed4e73a5109f1d15901721fa968d6c34"><code>c1f0611</code></a> (minio) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/b73f7927c34fca39605e13930a06fad829658e7b"><code>b73f792</code></a> (minio) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/79d1c935ee59bf45af52a1265aa87e2ef3233f40"><code>79d1c93</code></a> (minio) - go: bump go mod</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/c448899edbaacf8d54cdbad53561733069c1020b"><code>c448899</code></a> (minio) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/15ee49ef85be819d3f6eed5dde4551ffa31f5fae"><code>15ee49e</code></a> (minio) - minio: migrate deprecated warning</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/9968a1a2095fecda1d3ba3fbd2263e83494d716e"><code>9968a1a</code></a> (minio) - minio: upgrade to golang1.7</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/14fedd29ba64e02c05b6cd5fb06bd261bf9f367b"><code>14fedd2</code></a> (monitor) - monitor:replace the special works</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/52c431ad1701cc15e03d55cbc436c5f4f7472522"><code>52c431a</code></a> (monitor) - reids: delete the logger prefix of redis</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/2c95b47a1f714a421be5860a78dd94c23ddcfdf3"><code>2c95b47</code></a> (monitor) - redis: remove logger from redis conf</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/da9bc5605eb4a118bca92fdff3cc49c2f208c040"><code>da9bc56</code></a> (monitor) - monitor:remove influxdb</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/53f47b9a3b8dec717d049b9be3961e4efd446381"><code>53f47b9</code></a> (monitor) - grafana: use grafana docker image</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/5bdb188a7255e845cda8a49806053f12032d196d"><code>5bdb188</code></a> (monitor) - grafana: use grafana docker image</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/c0586dda982c857e61b89964f34b57028cfaa29c"><code>c0586dd</code></a> (monitor) - monitor: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/87d02b6c80ef04c1170e848e9febdb723c9503c3"><code>87d02b6</code></a> (monitor) - charts: add nodes and persistentvolumes rule</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/1b5598fb479f85808bb33ef29b8cd21ab9d40bc6"><code>1b5598f</code></a> (monitor) - monitor: modify grafana dashboard with FLUX and pretty config.toml</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/bcbc0d5b3ef1b16a9e4b22208f5c628156a556cc"><code>bcbc0d5</code></a> (monitor) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/9418c9e13b4fb20f4174ee965044cf30ca12ae38"><code>9418c9e</code></a> (monitor) - monitor: fix upload dashboard error and modify INFLUXDB input</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/589f29a84eeab3f9fbc1cce1e49a601938a32987"><code>589f29a</code></a> (monitor) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/f776f8a650fd4c0c1e5f21dc9aa38ad36ca5be72"><code>f776f8a</code></a> (monitor) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/6ca306092ca874c666066dffce4f3f8fad11bbcb"><code>6ca3060</code></a> (monitor) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/6a9ffb24264ff8d7e5e9407f811e5b38b9e20a38"><code>6a9ffb2</code></a> (monitor) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/45e41ed8d104205a708fd82327e0fa3f3ac3d97e"><code>45e41ed</code></a> (monitor) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/654d407bea3cc3e686416cb2f6e1224990bab741"><code>654d407</code></a> (monitor) - k8s: k8s deprecated api migration</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/41e9b9c3c1b371ea815cd480e33c53779c2211a7"><code>41e9b9c</code></a> (monitor) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/99c10d38471587b09fb51ee65c8e602e443b44e7"><code>99c10d3</code></a> (monitor) - charts: update cert-manager api version</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/9bf83c40a846784e8375db884a2d417073324408"><code>9bf83c4</code></a> (monitor) - oauth: user oauth passport</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/a128f6d5f97fc060a80a2384f4a2dd2dc916dd12"><code>a128f6d</code></a> (monitor) - chart: change certManagerEnabled to boolean type</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/8f897fe306e15f4d528d0665171d634f0d9b93c4"><code>8f897fe</code></a> (monitor) - chart: set the domain depends certManagerEnabled</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/ba6d793c6110993b227246b8bf0bb861fc468975"><code>ba6d793</code></a> (nsqd) - README:update travis build status</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/49879c4baba2a6824b9f32bb2734aec21debefb0"><code>49879c4</code></a> (nsqd) - nsqd: minimum git clone code</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/c5e26805e49bd1be880fd4857b435359a0840992"><code>c5e2680</code></a> (nsqd) - nsqd: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/21dd17b886aad7e673fdb72fe4ccce3d9786a623"><code>21dd17b</code></a> (nsqd) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/7d86b3cbb2452da48abcc99f165dfa8954f103bb"><code>7d86b3c</code></a> (nsqd) - charts: remove port config</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/c073d952af18ffd83b6f86ce7a55140b36029a63"><code>c073d95</code></a> (nsqd) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/55c297ca70952986cb6a971593bbe0e64adea029"><code>55c297c</code></a> (nsqd) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/165c2aef05413585886651299c11dfb741469b0c"><code>165c2ae</code></a> (nsqd) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/9c6a1f8eb363e1d09eaef29c97eff7b60053103b"><code>9c6a1f8</code></a> (nsqd) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/92830984c4627f1a034f8fcfcb490a09576aa960"><code>9283098</code></a> (nsqd) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/46acf8a349c2d8462ee2ec0b592bde8a26e5f459"><code>46acf8a</code></a> (nsqd) - k8s: k8s deprecated api migration</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/43caf8058c5c9b129744c1a191f234d3b44c793f"><code>43caf80</code></a> (nsqd) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/689747119e18e2f1151404beb1729cad9d6ea5f6"><code>6897471</code></a> (nsqd) - nsqd: use official image</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/297bc05baf835ffe4d103bb6cb7613aa1286be68"><code>297bc05</code></a> (redis) - redis:replace the special words</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/f5f8b5e75b99f11e20a1b3210e4c4a42e342df92"><code>f5f8b5e</code></a> (redis) - reids: delete the logger prefix of redis</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/af7b657e76bbc1201391fe3915e081bd220b96a8"><code>af7b657</code></a> (redis) - redis: change logger-redis to redis</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/8dca154e5ae4a38b42e1eb6e16e01f3e78d5fee1"><code>8dca154</code></a> (redis) - redis: remove logger from redis conf</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/eaeda2d2650c61768092ea7f5846733328e47dc6"><code>eaeda2d</code></a> (redis) - redis: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/53c6358e7fbaf02ec15d0a01afa5e02769e3bfb4"><code>53c6358</code></a> (redis) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/ae37416efe8b6fcfdfabf2d444bd241e7128d889"><code>ae37416</code></a> (redis) - charts: remove port config</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/e985656354c17c1221d8ec35007710e0b9d4f6a3"><code>e985656</code></a> (redis) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/423336a645aa3b5091b76e88e58b501357cc733c"><code>423336a</code></a> (redis) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/be64ab4c2fd6e1edd33ca8c5a4458c74bf6fa372"><code>be64ab4</code></a> (redis) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/3bec735f6849b5649c5a2416e8fdb76fb6c780d7"><code>3bec735</code></a> (redis) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/4f934f6ee96925b70463c660416706eafc21fc3e"><code>4f934f6</code></a> (redis) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/359b8780f014c1627a1290e32231cd53caf6f762"><code>359b878</code></a> (redis) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/83b8ac299c215de85e85485c6c0546bc25a37ab1"><code>83b8ac2</code></a> (registry) - workflow:replace the special words</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/869b280b55534a7fbd2dfc9052044cb487d97730"><code>869b280</code></a> (registry) - registry: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/999c1e936026b79dc0462da166998f3fa4cebec3"><code>999c1e9</code></a> (registry) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/5652da941334dfdddbe2636d974e9d687b0d912d"><code>5652da9</code></a> (registry) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/cc8c6c2bc077bad277232d25bc536416dfa6c244"><code>cc8c6c2</code></a> (registry) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/c7bdbd0e67e6bcd35423db7d05aca99a511054ed"><code>c7bdbd0</code></a> (registry) - CICD: pretty .drone.yaml format</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/5c55a38592dfd1a7356992018f15f022c02fdfc6"><code>5c55a38</code></a> (registry) - test: use add-host replace link</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/f8866f3e6b4f94e15815e5f79b2adbebe3fd1ed1"><code>f8866f3</code></a> (registry) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/6c8292f9c65b38816fad79bf3f49ff54ad8760dc"><code>6c8292f</code></a> (registry) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/1d50f2ce75f708fd3b07b0c5d5dff2f4bdb8adc7"><code>1d50f2c</code></a> (registry) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/efbca6d2c99e2b170e945f050afa8fb139398a49"><code>efbca6d</code></a> (registry) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/2eafc592dc68c529a8a3a8077ef9d48916718079"><code>2eafc59</code></a> (registry-proxy) - registry-proxy: update nginx</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/071bd86ae3bef755f47e22aad54762a7f1e4c0f1"><code>071bd86</code></a> (registry-proxy) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/c72db9618ee6a73655b4b2c5e940ee9fc9447380"><code>c72db96</code></a> (registry-proxy) - registry-proxy: change travis icon url</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/63ffb920f62b692071fcbf825cbac55bbebe6598"><code>63ffb92</code></a> (registry-proxy) - registry-proxy:replace the special works</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/1d904a61de6cc38bfb071a965de09f5dea0d9996"><code>1d904a6</code></a> (registry-proxy) - registry-proxy: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/c8200b1f6f573dba0edb19509fdb56a8357828c7"><code>c8200b1</code></a> (registry-proxy) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/d3fa939d910c7b0c707f191b174d1fce89e4cdb6"><code>d3fa939</code></a> (registry-proxy) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/5a8b353fa642dbef5929d372ef4ce39657bd40fb"><code>5a8b353</code></a> (registry-proxy) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/703d05a7fa07fc8d5b4c5c4ca0fed8a1ee156536"><code>703d05a</code></a> (registry-proxy) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/aa71db189c6b489347d8f723bdf881bc0b0abf67"><code>aa71db1</code></a> (registry-proxy) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/710c1260065431acf427bdf7d6d6319024598852"><code>710c126</code></a> (registry-proxy) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/2dcc5e6c4b469cb74b56c8c1f0b69d1d5c58291a"><code>2dcc5e6</code></a> (registry-proxy) - chars: change org to imageTag</li> +</ul> + + + + + + Blog: Drycc Workflow v1.4.0 + /blog/2021/10/06/drycc-workflow-v1.4.0/ + Wed, 06 Oct 2021 00:00:00 +0000 + + /blog/2021/10/06/drycc-workflow-v1.4.0/ + + + + <p>These release notes for Drycc Workflow v1.3.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.4.0, please refer to the following change summary.</p> +<h2 id="workflow--v130---v140">Workflow ## v1.3.0 -&gt; v1.4.0<a class="td-heading-self-link" href="#workflow--v130---v140" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>builder v1.1.0 -&gt; v1.2.0</li> +<li>slugbuilder v1.1.1 -&gt; v1.2.0</li> +<li>dockerbuilder v1.1.1 -&gt; v1.1.2</li> +<li>controller v1.2.1 -&gt; v1.3.0</li> +<li>slugrunner v1.1.1 -&gt; v1.1.2</li> +<li>database v1.0.1 -&gt; v1.0.2</li> +<li>fluentd v1.0.1 -&gt; v1.1.0</li> +<li>redis v1.0.0 -&gt; v1.1.0</li> +<li>logger v1.0.0 -&gt; v1.1.0</li> +<li>minio v1.0.1 -&gt; v1.1.0</li> +<li>monitor v1.0.1 -&gt; v1.1.0</li> +<li>nsqd v1.0.0 -&gt; v1.1.0</li> +<li>registry v1.0.2 -&gt; v1.0.3</li> +<li>registry-proxy v1.0.0 -&gt; v1.0.1</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/fc7d93f718019cfae02b04c745470b4975c91a84"><code>fc7d93f</code></a> (builder) - builder: use go-dev</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/0c2159e4a44f0c3f635dcee1b95afdd741d1935c"><code>0c2159e</code></a> (builder) - builder: fmt code and add create_bucket script</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1b88340205ac77e84ebba7a42215d7d3d40578a0"><code>1b88340</code></a> (controller) - controller: remove deprecated api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a92fdebab64716e4194653a9a17f1c00f70c882d"><code>a92fdeb</code></a> (controller) - routable: ingress support routable</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1e3eab3602538f266305a78c9244be466d685c68"><code>1e3eab3</code></a> (controller) - maintenance: add maintenance support for ingress</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/56b9dd0691c904bd75df928bace98830879eb31d"><code>56b9dd0</code></a> (controller) - crt: support containerd-ctr</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5fc3b46b2acd67af89590f1c7dd85fbfa5e989a6"><code>5fc3b46</code></a> (controller) - controller: add ephemeral-storage restriction</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d677e52c288431517de9ae4bddaaadbd1c8b976c"><code>d677e52</code></a> (controller) - controller: add a volume command</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5f1323a837c71127bb99fd8631934c5bd0cab2a7"><code>5f1323a</code></a> (controller) - controller:drycc run cmd add &ndash;mount para</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/74c36a51eef46ea1c110ee53472be632079ce5e1"><code>74c36a5</code></a> (controller) - tasks: add distributed async task</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/139c3ca9d01d7188c1a499dfffad7b7697e5fd0f"><code>139c3ca</code></a> (controller) - tasks: change nsq reader to async</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f237d74ca6344a5929c9b5089dae07a38c13753b"><code>f237d74</code></a> (controller) - controller:add drycc resource cmd</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/41b46d0653d39d0bdfb42907f7a0b9863bc20992"><code>41b46d0</code></a> (controller) - controller:add drycc resource cmd improvement</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c26f7d82e8fa6fcf4b45ab16fcb0298cb2880f6a"><code>c26f7d8</code></a> (controller) - controller: add LimitRanges support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/45b5d1b904abe94819c3dd306117dcd4e09123ed"><code>45b5d1b</code></a> (controller) - users: add users status api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4e16f9b86ac24b4c62d7d6fddb33278d1880dfa7"><code>4e16f9b</code></a> (controller) - ps:add ps:stop/start command</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c659fa9e058620fd8ce0ba4fcfc48898f1219f2c"><code>c659fa9</code></a> (controller) - k8s: add k8s cluster domain</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/31a625d71733b47944876ac3fb58fe55cd9b746b"><code>31a625d</code></a> (controller) - ps:add ps:stop/start command</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/00a779a5dbb60a33b621fae13b30a24e39ac55f3"><code>00a779a</code></a> (fluentd) - fluentd: support containerd log format</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/f3f1bd42697f08340b6b6f5fbe161c5b6fbb31b6"><code>f3f1bd4</code></a> (fluentd) - nsqd: add stateless nsqd cluster support</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/db7147c0e7556a655e185c6f00419f99aff4ed29"><code>db7147c</code></a> (fluentd) - mirrors: delete aliyun mirrors</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/689c12eed60f53e1afbbcede91a5955360183fa7"><code>689c12e</code></a> (logger) - nsqd: add stateless nsqd cluster support</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/78ccc5de7718b8f6fb1caf701d1b4ef72fc64362"><code>78ccc5d</code></a> (logger) - redis: add redis client cluster support</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/9843f2cf9d1d03511296bf7731b59d547bc10387"><code>9843f2c</code></a> (logger) - k8s: add k8s cluster domain</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/6ba122e8b6cbdf7b73785d21961056e6b9fc91ee"><code>6ba122e</code></a> (minio) - minio: add pvc support</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/69735500c483f9144f461a2b8a3444e51ddd4dc4"><code>6973550</code></a> (monitor) - monitor: add ingress for monitor</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/cd733053287efbd12c29217cd47c6345c39457ce"><code>cd73305</code></a> (monitor) - charts: add volumeName support</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/4769fe9e8d14bdbdca9447f9df23c67c09db2a45"><code>4769fe9</code></a> (monitor) - nsqd: add stateless nsqd cluster support</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/87806df02cd84fc5feec304e9bc6e32996396b80"><code>87806df</code></a> (monitor) - k8s: add k8s cluster domain</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/4db40c4f129115019ef41c14df56a2d0092e9da1"><code>4db40c4</code></a> (nsqd) - nsqd: add stateless nsqd cluster support</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/b6f3d4fe0f6bc8d3467fdebf21374bed378edf9e"><code>b6f3d4f</code></a> (nsqd) - nsqd: add stateless nsqd cluster support</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/74b85bb9efdcba88a25a2734d512d07ef8068032"><code>74b85bb</code></a> (redis) - redis: change redis to statefulset</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/ff98b5018610d0e2be0ec5c03c7a11232199811a"><code>ff98b50</code></a> (slugbuilder) - slugbuilder: delete build hook</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/b201c2ff207eddac7327f75d698a77e89d4125a1"><code>b201c2f</code></a> (slugbuilder) - buildpacks: use drycc buildpacks</li> +</ul> +<h4 id="fixes">Fixes<a class="td-heading-self-link" href="#fixes" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/0ec042db3c8a4db39088ffe381f518abdb55287d"><code>0ec042d</code></a> (builder) - test: fix test case error</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/4fb113b7351f9f02612b3e14b4d0787b77abb3b2"><code>4fb113b</code></a> (builder) - build: base image replace by alpine</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/443df48c699846c176c1e4a12b5bb42abe790633"><code>443df48</code></a> (builder) - minio: fix not bucket error</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/3dab5b0ce203bcc03891122aca73da5c7342a40b"><code>3dab5b0</code></a> (builder) - minio: create bucket error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/734fca6f371bf73d79d35f1fcdc04ff66cb196fc"><code>734fca6</code></a> (controller) - autoscale: Fix for autoscale on k8s-1.9+ without breaking manual scaling</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a7dcd1000965fae97bad4dc4b908741f856e2d2b"><code>a7dcd10</code></a> (controller) - controller: test pass</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/93f0f2eaa361386bf7775edcbc27c143a71f0dc7"><code>93f0f2e</code></a> (controller) - controller: fix migrations error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4724375b4319e1cbfa1a587e0e856d9eb9b6ac00"><code>4724375</code></a> (controller) - controller: fix test error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7bacf298db4e431c58e86cef028f99fffb5b349e"><code>7bacf29</code></a> (controller) - charts: fix clusterrole</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/90957f727cc883084ff1a81deaada4d62419f0a9"><code>90957f7</code></a> (controller) - pod: sort events error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/440b13edb6e5b9c9fa69f8b6c72f10329a4087d2"><code>440b13e</code></a> (controller) - controller: review table structure</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0a470a6ecffa1fa9d5ef2bb0a71b00ddefb84a1f"><code>0a470a6</code></a> (controller) - controller: bump tornado 5.1.1</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e39218b2216591b7d412baeee5c8e85a7209996d"><code>e39218b</code></a> (controller) - pynsq: no current event loop in thread</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1d8630e250c65051df90b22f023f0f95034f0cc1"><code>1d8630e</code></a> (controller) - tests: fix test_task.py run error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1ff120213ee452a570a1e23dff85ab3032704a30"><code>1ff1202</code></a> (controller) - controller: fix test case</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d8c0da319db0b559eb8c8b0c28280d7e70613da2"><code>d8c0da3</code></a> (controller) - settings: fix env name</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/6d8fd3605f54c5a3c7ce0d4e5164f772fa22a8ec"><code>6d8fd36</code></a> (database) - 003_restore_from_backup.sh: ignore script exit 1</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/e0394a9a6aa44a066df18b8ad3ddd21e9c9fa1c2"><code>e0394a9</code></a> (database) - minio: fix not bucket error</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/f35f2525602c90dbe397f56005206ed6abf6eb39"><code>f35f252</code></a> (database) - mc: fix create_bucket error</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/74d68865fb7502d04e74418cc2b6ef8316c45778"><code>74d6886</code></a> (database) - postgres: recovery mode not run</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/e50d0c105151dac43b2bbc5f4e316a47dd55e925"><code>e50d0c1</code></a> (dockerbuilder) - caddy: fix caddy not start</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/f3bec7a8a63c586d19caa777b3fa4a7d0de112c7"><code>f3bec7a</code></a> (fluentd) - influxdb: fix influxdb host and port</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/bc19f27d1567281c5c1ae10b9072c9aad33e2013"><code>bc19f27</code></a> (fluentd) - charts: skipped value for daemon_environment: Not a table</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/338d6237ed76464fc47a6ca3d6f3d34927af6aa2"><code>338d623</code></a> (logger) - logger: logger not run in alpine</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/77883026f33f38aa9d01dd4d88298d162a9050e1"><code>7788302</code></a> (minio) - minio: bump minio version</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/619eed0426591646d5fa9e72b77391d6ac817946"><code>619eed0</code></a> (minio) - fix: use go mod replace dep</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/3b42122703b8bfa3203c8115b8d673f2081d2559"><code>3b42122</code></a> (monitor) - monitor: fix host error</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/67998eff2439c406db048a868f61ae9861268449"><code>67998ef</code></a> (monitor) - influxdb: replace drycc-monitor-influxapi to drycc-monitor-influx-api</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/2cc361cf42754562ffa5b6e7c2e14c065e2cd0f1"><code>2cc361c</code></a> (registry) - registry: fix test case</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/548297a7b97e8f28498fa51b50f9232d8c78053b"><code>548297a</code></a> (registry) - minio: fix not bucket error</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/5412ddb1b956fad53d0c59a87c2158b6e014b05f"><code>5412ddb</code></a> (registry) - minio: create bucket error</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/d0d629e5a58d7e91421f2cd344029474e5c630d4"><code>d0d629e</code></a> (slugbuilder) - slugbuilder:fix normalize_storage path</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/d76ecbe4d4d05aeb23a566b2d3c929cca4e63e63"><code>d76ecbe</code></a> (slugbuilder) - slugbuilder: use v3 api</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/c505e182006dd8a734efa14fc851f15340d05929"><code>c505e18</code></a> (slugbuilder) - shellcheck: SC2039</li> +</ul> +<h4 id="style">Style<a class="td-heading-self-link" href="#style" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/c893a1771550c7728f697216b17e38da0f18ec3f"><code>c893a17</code></a> (builder) - builder: fmt code</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/bba5795cd3f3f36bf2a4b6d37661254143f60328"><code>bba5795</code></a> (controller) - controller: format code</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d36082b6f0fbf46487e3fdc6aff0e7866f6462a7"><code>d36082b</code></a> (controller) - controller: fix pep8</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/66026f2f2110fca58f783b8844d9c5b7a794d1f4"><code>66026f2</code></a> (controller) - resource: standardize the naming of resource</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/03d7e2c8bfb120627ec13c4aa37ff7bc3074e88e"><code>03d7e2c</code></a> (controller) - servicecatalog: change servicecatalog to svcat</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/49dbb6d99655dd398978b273ce3fb29051a56cb7"><code>49dbb6d</code></a> (controller) - controller: flake8 upgrade</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/cbfc108b4f209dfbd088f260fe84399bdda5d502"><code>cbfc108</code></a> (monitor) - monitor: format charts and dashboard</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/ee85954d57ae9d19e6e2790090a6fcf1413e8b2d"><code>ee85954</code></a> (slugbuilder) - slugbuilder: use shellcheck</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/3afed2e3592173fcc3522d71dfdbdd45a8b70a01"><code>3afed2e</code></a> (slugbuilder) - docker: simplify dockerfile</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/36b7f688afcb9c8c81016fbbc7b8a3da9537911d"><code>36b7f68</code></a> (slugrunner) - docker: simplify dockerfile</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/61bb0ef367bdabdb3072473e1d639d723b2a8f08"><code>61bb0ef</code></a> (builder) - aws: upgrade aws sdk version</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/0f2e074b748b9f7067cadac63fb83684bc582272"><code>0f2e074</code></a> (builder) - chore: use go mode replace dep</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/e9a2219c2d1c9303cd1a60d2e9bdc9e676f07348"><code>e9a2219</code></a> (builder) - builder: delete glide up</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/bb8c518645bcee82e6ab7782496799b6b82b9fd4"><code>bb8c518</code></a> (builder) - registry: del quay.io</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/fa6d02f54af2daf51c1b08b4b7ad6a3be2425b45"><code>fa6d02f</code></a> (builder) - builder: upgrade go.sum</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/9d61e8da908fae47c33a77c8547e80d1d6d3d812"><code>9d61e8d</code></a> (builder) - build: upgrade go.mod</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/d763a984a800366eb2f6384fbf23c596342720fb"><code>d763a98</code></a> (builder) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/d1bc1aae69b9b16859e11bfa18b1fa2b602bc686"><code>d1bc1aa</code></a> (builder) - pkg: upgrade to new drycc/pkg</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/02b1e98a3b208be80326adb85307663ef931adf6"><code>02b1e98</code></a> (builder) - builder: update go mod</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/8e17d6579e022ce3574ee7582a1f48fc88bb5e95"><code>8e17d65</code></a> (builder) - builder: change alpine repositories</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/f32b723ef49069ffeee6f2419e87b5450617df1e"><code>f32b723</code></a> (builder) - mirrors: delete aliyun mirrors</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/e33dc612d4910ad3b0e56fbb797a7d1dd609bf6d"><code>e33dc61</code></a> (builder) - minio: use bin mc replace docker images</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/3ab4f1c4a587f58230c1c91670831a0927dc6dfb"><code>3ab4f1c</code></a> (builder) - builder: update controller-sdk-go</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/b2adfac62d24626a8dc5f2cf4d011c4610170e3a"><code>b2adfac</code></a> (builder) - heroku: remove heroku-16 support</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/f429ac8fa76a4b59ed36ab9b1dc2bfee19d0be3e"><code>f429ac8</code></a> (builder) - builder: set GIT_LOCK_TIMEOUT to 30 minutes</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/7197c833a68b1168ee4eba0ac16a6fb569f2066e"><code>7197c83</code></a> (builder) - go.mod:upgrade require pkg controller-sdk-go</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5f3e22dc87a55d9bd8fd3299f37be26b19c2350f"><code>5f3e22d</code></a> (controller) - deps: bump django from 1.11.21 to 1.11.22 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1db645af644946d8694234b0b7e1f22e762c5424"><code>1db645a</code></a> (controller) - deps: bump django from 1.11.22 to 1.11.23 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/fbe80677bc8fe7d19772a0bc002fb541106ef75d"><code>fbe8067</code></a> (controller) - deps: bump django from 1.11.23 to 1.11.29 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/537d667d5fd896eec054adda6185042d6492cbd1"><code>537d667</code></a> (controller) - registry: del quay.io</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a23c65b14ba90a60a6d57aa56a12f201ad7ba33b"><code>a23c65b</code></a> (controller) - deps: update all deps to the latest version</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/546337eced482db0b8e879ce8caaa322503f5f52"><code>546337e</code></a> (controller) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/06023f8b84897c4aeaa14fc45c6d35c16eeed1d7"><code>06023f8</code></a> (controller) - workflow-manager: del workflow-manager</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/bba573609e25e87875ca40ccdef6e4dd4c8cfd1a"><code>bba5736</code></a> (controller) - controller: change cluster-issuer location</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/6c436612923a18486982c268d1e23bbd42a3f9a7"><code>6c43661</code></a> (controller) - Certificatechange cluster-issuer location</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/39a47288e3e0bcf7bfa55768c6759ac94c416c33"><code>39a4728</code></a> (controller) - controller:change cluster-issuer location del controller-cluster-issuer.yaml</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9e96d3f9ccda7f8934628444e72e4959bafde91a"><code>9e96d3f</code></a> (controller) - Certificate:upgrade version cert-manager.io/v1alpha2</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8e68049a870b2277663bd0dc09430baa343a5881"><code>8e68049</code></a> (controller) - docker: use INDEX_URL replace index.docker.io</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8fda20583558fefcd239d5e2d6ae09c5c5f881a7"><code>8fda205</code></a> (controller) - cert_manager: change cert_manager_enabled to global</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/6fefb6d00f8909d7269a9171af9db7ba016533c4"><code>6fefb6d</code></a> (controller) - charts: change platform_domain to global</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/064b2ad886b7782598a7f68925d5275ebd88bfd4"><code>064b2ad</code></a> (controller) - maintenance: remove maintenance support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b8797c98a1b2e01f835169ca7493fff508a3cf95"><code>b8797c9</code></a> (controller) - workflow: remove namespace</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1b20d7632a8ca8e4e9f0f6b1c98826af1d846008"><code>1b20d76</code></a> (controller) - quota: add kube quota config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d780075077cf9f9843ecf79ae36e569eec59cd3d"><code>d780075</code></a> (controller) - pod: add pod default resources support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3d72c0817b582f050321396240bd4a6bad3bfb16"><code>3d72c08</code></a> (controller) - rename: rename ingress name</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0aa6ab9cd277231420b1404b922601debe0aa89b"><code>0aa6ab9</code></a> (controller) - mirrors: delete aliyun mirrors</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7533a65e78efd06ebe809712791c5399b85efcba"><code>7533a65</code></a> (controller) - heroku: remove heroku-16 support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e5a885d676f052ffdee6bc74e2fe0cffb85a1f86"><code>e5a885d</code></a> (controller) - controller:check mount volume path</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9014e74b5c0312014aa9d20cf9d6aff128f8022f"><code>9014e74</code></a> (controller) - test: optimization Dockerfile.test</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0b6ebb2f0e18f7e97ed2bb7b2c6008e3be7248f2"><code>0b6ebb2</code></a> (controller) - tasks: change apply_async parameters</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/835f009573d5643d271b6e558793b1c9ae1463da"><code>835f009</code></a> (controller) - wsgi: add tornado 6 support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/67a4ad7cbd50cd9de1214e8d4be27196e8077367"><code>67a4ad7</code></a> (controller) - utils: use threads replace asyncio</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a28949b093e9f4d73c798f24e41d1eaff0cc1cc2"><code>a28949b</code></a> (controller) - ldap: add AUTH_LDAP_USER_FLAGS_BY_GROUP</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a903209c062f3e275f97bc18dc1d2b9a17e1a826"><code>a903209</code></a> (controller) - charts: add custom controller environment variables support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e0e783ecb5e87bf68e83411cfd92f54916aa9931"><code>e0e783e</code></a> (controller) - ldap: change filter style</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d7608251c2f8938b8f5ee1edd0c7d0f371931826"><code>d760825</code></a> (controller) - scheduler: remove debug log</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a25928ee84e75a84c13c5402cc351e1ec6e3f151"><code>a25928e</code></a> (controller) - wsgi: remove a wsgi.py file</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7b2696e3ea066b59395b63d97fbad5a472d49b5b"><code>7b2696e</code></a> (controller) - log: disable nsq.client info log</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8d5c07b49ba4220ba7946a8bef1a22b1e8d78e47"><code>8d5c07b</code></a> (controller) - charts: add default environment</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/025f4a2ea96c883df3c35b961aaac2bdd9a5b4ea"><code>025f4a2</code></a> (controller) - controller: change quota name</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ebda60ed125f49524169cb320c79c37d5adc2e6c"><code>ebda60e</code></a> (controller) - controller: review pvc code</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8832ba952281c2a06dc98dfc6726e7f9e9207d81"><code>8832ba9</code></a> (controller) - controller: change status\binding model type and mount path check container_types</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7148d04c5f1223f06747fae9a33cb3787159ce9e"><code>7148d04</code></a> (controller) - controller: add overcommit cpu and ram support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4d2087cc9c783e5c2722fd446b64c7263b783001"><code>4d2087c</code></a> (controller) - limits: modify limits unit verification</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/af36970d90b9a8d95857052ab1c97b7727a01976"><code>af36970</code></a> (controller) - api: check cpu/memory range for api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/329355b6cdde8a382a5fe271f764cca747cd9444"><code>329355b</code></a> (controller) - volumes: modify the volume size</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9dfee0919449d13e11ec3cfe50a187ecd5de07b2"><code>9dfee09</code></a> (controller) - LimitRanges: modify the default limits</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5205bca582cd292fcfa7c0abb1bcc98c3dce05f1"><code>5205bca</code></a> (controller) - controller: improve the details of certificate</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/7ebecdfdca2de4936b67bc542053305f098db6d6"><code>7ebecdf</code></a> (database) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/6415e2ccacef3af313b4df2e7d0924797217238f"><code>6415e2c</code></a> (database) - postgres: upgrade to pg13</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/12e68062d48938c8619f94c30741af6fd2fee8e9"><code>12e6806</code></a> (database) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/d294509c192eb7e2f6f11aedad8aefff83fb8532"><code>d294509</code></a> (database) - minio: use canary minio test</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/1bad02e1768d4d54df61f7df3e54c81bd68e6c52"><code>1bad02e</code></a> (database) - mirrors: delete aliyun mirrors</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/d51420bbde24cada100f764288c9bd165dbc9f31"><code>d51420b</code></a> (database) - minio: use bin mc replace docker images</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/4133d05d8edec1f1ba2b995354dc98ae863a1da7"><code>4133d05</code></a> (dockerbuilder) - dockerbuilder: update caddy and kaniko</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/6b4dd18637b3a81a64c1be34a6d73832095c638d"><code>6b4dd18</code></a> (dockerbuilder) - minio: use bin mc replace docker images</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/6df9b7c0bc4a22bca7ed2588a070868680382f68"><code>6df9b7c</code></a> (fluentd) - deps-dev: update rake requirement from ~&gt; 10.0 to ~&gt; 12.3</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/c2490f84d991ddfc588bded7e6afe9706e82f090"><code>c2490f8</code></a> (fluentd) - fluentd: upgrade fluentd</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/be4a56a12ce0c8a812b8922630122225532ac3fa"><code>be4a56a</code></a> (fluentd) - fluentd: add Gemfile.lock</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/2237f755e0123eb4138289648b5a0ee64bbd4183"><code>2237f75</code></a> (fluentd) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/c5740650bcb218c59676733c20f5765ae4cb905d"><code>c574065</code></a> (fluentd) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/52b8084cbaa5d0b8c8ca7014f94b596dca911708"><code>52b8084</code></a> (fluentd) - router: delete obsolete router code</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/3b3ccebeced1c4257c0c3ed1a70b7f18a8c6aa85"><code>3b3cceb</code></a> (fluentd) - fluentd: remove manifests dir</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/25c6702f8c1e1c5916b0544ccda64eced3451448"><code>25c6702</code></a> (fluentd) - nsqd: change var name</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/bd571be4178f69cb4bd7ee233440ca889ec5c601"><code>bd571be</code></a> (fluentd) - nsqd: change DRYCC_NSQD_ADDRESSES to DRYCC_NSQD_ADDRS</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/72aa4e6b7fe5cb5ef784f894429e3f1e177e5c82"><code>72aa4e6</code></a> (fluentd) - influxdb: change influxdb service name</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/bd61903dd01aa61374a5f527f8ee85bc7820c042"><code>bd61903</code></a> (logger) - logger: use go mod replace dep</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/69c63a1bd602c9a5a68ef3b93d43b2dca161d495"><code>69c63a1</code></a> (logger) - logger: update go.mod</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/3aa9cd715568b46efa26025f25c73ce897436b4f"><code>3aa9cd7</code></a> (logger) - registry: del quay.io</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/f05849639ef8e34bacf9a55965ab3d7297df4cf7"><code>f058496</code></a> (logger) - nsqd: change var name</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/6d9787cebb2e992de9743ac0544201b012b21094"><code>6d9787c</code></a> (logger) - nsqd: change DRYCC_NSQD_ADDRESSES to DRYCC_NSQD_ADDRS</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/85ed307592a38ae80186f59bf31e504124013e07"><code>85ed307</code></a> (logger) - logger: standard naming</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/d88e7b65131e2fdaa7d4164a4d66793d89cc384d"><code>d88e7b6</code></a> (minio) - minio: update minio api to v7</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/43715d2dd30bc15f5564124e0e5e444ce7ca63c2"><code>43715d2</code></a> (minio) - minio: upgrade minio</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/0e1239b358ce3bde11a1401634f519b7e1c38156"><code>0e1239b</code></a> (minio) - minio: use docker.io replace quay.io</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/f7f047b506a0e6b30b7b88e916d67b1faaba8a52"><code>f7f047b</code></a> (minio) - registry: del quay.io</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/afa71289345ed311e603c8847188ccef40774869"><code>afa7128</code></a> (minio) - build: upgrade go.mod</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/aff2db5a41ae72b899f2fc9f70af96730ed16fdf"><code>aff2db5</code></a> (minio) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/4547f14617a76db897b71ef7451db92a832dff1e"><code>4547f14</code></a> (minio) - pkg: upgrade to new drycc/pkg</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/2769b85cbd316cb08da58753d6bae3946d32032a"><code>2769b85</code></a> (minio) - minio: use bin mc replace docker images</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/35dde8df07fb96c4996ef8410780da48e1170e4a"><code>35dde8d</code></a> (monitor) - monitor: update grafana influxdb telegraf</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/9e3a949734f326290dd752c636991cf2e1c962f9"><code>9e3a949</code></a> (monitor) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/6af0432fe174769e9d44c03c264ad4a9ea5cee5f"><code>6af0432</code></a> (monitor) - workflow-manager: remove workflow-manager</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/0611c07996da19eb1401278ad5cc5e46d3b1435c"><code>0611c07</code></a> (monitor) - router: delete obsolete router code</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/be048248577d97f8679863c179999ce843806c09"><code>be04824</code></a> (monitor) - cert_manager: change cert_manager_enabled to global</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/37801650414da8539390c4d7cad66f614b90ef6e"><code>3780165</code></a> (monitor) - charts: change platform_domain to global</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/50b04e15f9c3aa51751bb78250907fa22023a419"><code>50b04e1</code></a> (monitor) - influxdb: remove influxdb admin ui</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/6ab4d68b758904d12697b9a129835e6d0474cafb"><code>6ab4d68</code></a> (monitor) - influxdb: remove unuse port</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/f1510bd94e48ea41ff4c36ac2140688b5c2dde87"><code>f1510bd</code></a> (monitor) - monitor: update grafana dashboard,telegraf inputs.kubernetes</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/f36de2c251dc63b21a1fdc2c05413d6d50e9f8cb"><code>f36de2c</code></a> (monitor) - pvc: upgrade to new format</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/fc78a0a2627b51a28c730e19f2c8c1c16103829f"><code>fc78a0a</code></a> (monitor) - workflow: remove namespace</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/e85890f298dd68cf6c0e8af70d843e84da600361"><code>e85890f</code></a> (monitor) - monitor: monitoring nsqd and redis separately</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/694f6b1dc801769a8fe82b90ba26422747df6539"><code>694f6b1</code></a> (monitor) - mirrors: delete aliyun mirrors</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/4aea36a822079ba593a646683dba0e35e3e68416"><code>4aea36a</code></a> (monitor) - grafana: add ldap support for grafana</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/68fc30f0f05af759b80e07c4dcd3d2a57c7ffd6a"><code>68fc30f</code></a> (nsqd) - nsq: update nsq</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/16f32aaf7b984b24853044b6619dbe9f2b8613e2"><code>16f32aa</code></a> (nsqd) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/04db389e01f6832a6a105a73a0a02c9b7dd6623b"><code>04db389</code></a> (redis) - reids: update to redis 6</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/3f01bab0dbe89fa4094750bdb5c3f0ac503b8f00"><code>3f01bab</code></a> (redis) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/647e4bed5f617727fd50c5e0645fd27cc128461e"><code>647e4be</code></a> (registry) - registry: del quay.io</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/0bbce990d4ff5660ce79020e0bca346a0c716b3d"><code>0bbce99</code></a> (registry) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/a982b503350abfd584d33d0e088bc0a79714fb9c"><code>a982b50</code></a> (registry) - minio: use bin mc replace docker images</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/e088da3304147b568868e0546c321b57f84263b9"><code>e088da3</code></a> (registry-proxy) - ingress: renmae use_native_ingress to use_ingress</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/7e88337bbfbc73bc30bd0906f25027c5d266b1c2"><code>7e88337</code></a> (registry-proxy) - nginx: upgrade nginx to mainline</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/7204d72c00b2d7360a2d3a20833d701e303a9f62"><code>7204d72</code></a> (registry-proxy) - registry: optimizing variable naming</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/2eafc592dc68c529a8a3a8077ef9d48916718079"><code>2eafc59</code></a> (registry-proxy) - registry-proxy: update nginx</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/071bd86ae3bef755f47e22aad54762a7f1e4c0f1"><code>071bd86</code></a> (registry-proxy) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/c72db9618ee6a73655b4b2c5e940ee9fc9447380"><code>c72db96</code></a> (registry-proxy) - registry-proxy: change travis icon url</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/ca9f9623a6867f0c5f4ff973c06613deff9e5dd3"><code>ca9f962</code></a> (slugbuilder) - slugbuilder: del BUILDPACK_URL support</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/1b74dd57a7f19040577f8e55b6a9d993ef496c8d"><code>1b74dd5</code></a> (slugbuilder) - slugbuilder: add heroku-20 support</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/54d4ad2e97e9ff5c805ac985a0e5af0050677388"><code>54d4ad2</code></a> (slugbuilder) - slugbuilder: del quay.io</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/a78f37ee99cec1b7c3eb7cb7a803bf2a5ed7c45b"><code>a78f37e</code></a> (slugbuilder) - slugbuilder: add heroku-20 stack</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/94ac94ac5dd4a387c0e1aaef6638954e41e9983a"><code>94ac94a</code></a> (slugbuilder) - minio: use bin mc replace docker images</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/53b4b8b7ef9dece421a7893c5c3137ab0df8b960"><code>53b4b8b</code></a> (slugbuilder) - slugbuilder: modify stack priority</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/58e2bd28cf5fda8c618a2ba540d9e3acbf46fab5"><code>58e2bd2</code></a> (slugbuilder) - dockerfile: add WORKDIR /tmp</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/b29cd04c1769ef3481ff7c61c41a6e8722664469"><code>b29cd04</code></a> (slugbuilder) - slugbuilder: add pre_build.sh</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/9d319f60a1edd735bc5217054fe365047bd8795a"><code>9d319f6</code></a> (slugbuilder) - slugbuilder: silent mc command output</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/d1ec3c983be9934dd6b86fa51200489eb5555fa7"><code>d1ec3c9</code></a> (slugbuilder) - heroku: remove heroku-16 support</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/5048534c684b76f41ca12136cefd6e6da51ace3e"><code>5048534</code></a> (slugbuilder) - slugbuilder: use drycc stack-images</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/a1165373fc9ca369eec2715a2a49f166430cefa9"><code>a116537</code></a> (slugrunner) - slugrunner: add heroku-20 support</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/a1196bf153c21cefde2122aee5bf7dfa32ac5f0a"><code>a1196bf</code></a> (slugrunner) - slugrunner: del quay.io</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/64c96d720f4b5cdc54b66d349bac6de5567ab331"><code>64c96d7</code></a> (slugrunner) - slugrunner: add heroku-20 stack</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/cc3e2264b67f950fb888502aeea08d41d4c8ccf4"><code>cc3e226</code></a> (slugrunner) - minio: use bin mc replace docker images</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/9130bde01bcfa897ae5c4be6bc59b4a4fe7b92f3"><code>9130bde</code></a> (slugrunner) - shellcheck: shellcheck installer</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/4ea33e154ab4353de5bd5bf6afeb0157756224e8"><code>4ea33e1</code></a> (slugrunner) - slugrunner: modify stack priority</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/5514e8b393daa6f4cd8f3ebe0a619158e32945e6"><code>5514e8b</code></a> (slugrunner) - heroku: remove heroku-16 support</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/be829fb66e68bb9ccc2a1d49e1b364af09219fff"><code>be829fb</code></a> (slugrunner) - slugrunner: use drycc stack-images</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/e1e06be74f2f40740c8e72178ae6ba97233c5bbe"><code>e1e06be</code></a> (slugrunner) - slugrunner: remove Dockerfile.heroku-16</li> +</ul> + + + + + + Blog: Drycc Workflow v1.3.0 + /blog/2020/10/06/drycc-workflow-v1.3.0/ + Tue, 06 Oct 2020 00:00:00 +0000 + + /blog/2020/10/06/drycc-workflow-v1.3.0/ + + + + <p>These release notes for Drycc Workflow v1.3.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.2.0, please refer to the following change summary.</p> +<h2 id="workflow--v120---v130">Workflow ## v1.2.0 -&gt; v1.3.0<a class="td-heading-self-link" href="#workflow--v120---v130" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>builder v1.0.2 -&gt; v1.1.0</li> +<li>slugbuilder v1.1.0 -&gt; v1.1.1</li> +<li>dockerbuilder v1.1.0 -&gt; v1.1.1</li> +<li>controller v1.2.0 -&gt; v1.2.1</li> +<li>slugrunner v1.1.0 -&gt; v1.1.1</li> +<li>database v1.0.0 -&gt; v1.0.1</li> +<li>fluentd v1.0.0 -&gt; v1.0.1</li> +<li>minio v1.0.0 -&gt; v1.0.1</li> +<li>monitor v1.0.0 -&gt; v1.0.1</li> +<li>registry v1.0.1 -&gt; v1.0.2</li> +<li>workflow-manager v1.0.0 -&gt; v1.0.1</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/9c7cceb2b775850cbe30c6df7b03bdcf7a35d0d2"><code>9c7cceb</code></a> (builder) - builder: add app config to env</li> +</ul> +<h4 id="fixes">Fixes<a class="td-heading-self-link" href="#fixes" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7fe44faf2663b20e39b27221a8426cf332f2085b"><code>7fe44fa</code></a> (controller) - docker: docker timeout must be an int, float or None</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b196550f9ac51f22f422e29d6b1a7aa3708421c3"><code>b196550</code></a> (controller) - controller: revert release.check_image_access for now</li> +<li><a href="https://api.github.com/repos/drycc/workflow-manager/git/trees/cc3ec13a5d5173160f1f6b42726df81119cd69ae"><code>cc3ec13</code></a> (workflow-manager) - glide: bump goautoneg</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/ef932c4eb4ea0d592b57f0a4aebdbd6ad039c998"><code>ef932c4</code></a> (builder) - controller-sdk-go: upgrade controller-sdk-go</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4654cf64a919aa64b10253b080e0b6aae86edcb5"><code>4654cf6</code></a> (controller) - django-rest-framework: upgrade to 3.9.3</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/14121f1dae135b137f8ded451cfd1d8f8ca62543"><code>14121f1</code></a> (controller) - deps: bump djangorestframework from 3.9.3 to 3.9.4 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/385acdc7e0359eedb83e10e71877a9ff591bff15"><code>385acdc</code></a> (controller) - deps: bump django from 1.11.20 to 1.11.21 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/fa312bb7f57f5f8638484bc4d9825aa962031a25"><code>fa312bb</code></a> (database) - postgres: set max_connections = 1024</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/7ebecdfdca2de4936b67bc542053305f098db6d6"><code>7ebecdf</code></a> (database) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/b8878f6d4c32540bc864581a457aa6c996e7e50c"><code>b8878f6</code></a> (dockerbuilder) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/b097451f312c0386c466be3b638242535849def0"><code>b097451</code></a> (fluentd) - fluent: upgrade fluent to v1.4</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/4341f9ae71b5dc55c14984d9cacc8e48a3e6e089"><code>4341f9a</code></a> (minio) - mc: upgrade mc and minio</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/c1ee2a46808c6054ab1393cdd31bf861e01ebdfc"><code>c1ee2a4</code></a> (monitor) - monitor: remove copyrights.tar.gz</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/9854260ef4738be5d25e4a028ebd3125988fec34"><code>9854260</code></a> (registry) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/acc5627dd8f96d3f62e02cd8813cbd829321bd18"><code>acc5627</code></a> (slugbuilder) - slugbuilder: internal support for multi buildpack</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/d58907eb664185c25950953dae4fe4774a2f6310"><code>d58907e</code></a> (slugbuilder) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/b39a0c29fef7d76ae681ec7ba2f01e3605a33657"><code>b39a0c2</code></a> (slugrunner) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z</li> +</ul> + + + + + + Blog: Drycc Workflow v1.2.0 + /blog/2019/10/06/drycc-workflow-v1.2.0/ + Sun, 06 Oct 2019 00:00:00 +0000 + + /blog/2019/10/06/drycc-workflow-v1.2.0/ + + + + <p>These release notes for Drycc Workflow v1.2.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.1.0, please refer to the following change summary.</p> +<h2 id="workflow--v110---v120">Workflow ## v1.1.0 -&gt; v1.2.0<a class="td-heading-self-link" href="#workflow--v110---v120" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>builder v1.0.1 -&gt; v1.0.2</li> +<li>slugbuilder v1.0.0 -&gt; v1.1.0</li> +<li>dockerbuilder v1.0.0 -&gt; v1.1.0</li> +<li>controller v1.1.0 -&gt; v1.2.0</li> +<li>slugrunner v1.0.0 -&gt; v1.1.0</li> +<li>registry v1.0.0 -&gt; v1.0.1</li> +<li>registry-proxy v1.0.1 -&gt; v1.0.2</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e5584e32ef02329fd091a7a4d3f40bac9894d5a4"><code>e5584e3</code></a> (controller) - controller: add STACK support</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/ad34dc1a501aada4aa2f8ceeb7eefa9fed6baf75"><code>ad34dc1</code></a> (dockerbuilder) - kaniko: use kaniko replace docker-py</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/b81430e8d7ac10167450667cf41e2f9efada6cca"><code>b81430e</code></a> (dockerbuilder) - dockerbuilder: change image to image.json format</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/60dde96064c69aa7578476c2e4855680f5186706"><code>60dde96</code></a> (slugbuilder) - slugbuilder: add STACK support</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/fe8b6e56dd1a9334844581183bb16eb3d59df366"><code>fe8b6e5</code></a> (slugrunner) - slugrunner: add STACK support</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/942f050ec90f771262cbb5634f5df8d5a3818a5d"><code>942f050</code></a> (builder) - registry: remove env DRYCC_REGISTRY_PROXY_PORT</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/ff7a16f53ac78dac0c334a9718cdc76c65400732"><code>ff7a16f</code></a> (builder) - registry: remove ecr and gcr registry</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/ad13683ce634c9b4835f45d2b474bac16ca52baa"><code>ad13683</code></a> (builder) - builder: change DRYCC_BUILD_TYPE to DRYCC_STACK</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/6def637d5331330940d0a94cf6313a4bcb67fec0"><code>6def637</code></a> (builder) - registry: rename DRYCC_REGISTRY_SERVICE to DRYCC_REGISTRY_PROXY</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/5044e223a56ee6283ac8d68a1442a6430b18dd99"><code>5044e22</code></a> (builder) - registry: remove registry_secret_prefix</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/2ea39cc0a9dd68fa1baca4b3725a00b9bcf7f89a"><code>2ea39cc</code></a> (builder) - controller-go-sdk: upgrade controller-go-sdk</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/6aee0d7f092b53c37c70d05db076eaae1bbcff44"><code>6aee0d7</code></a> (builder) - registry: optimizing variable naming</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f9c62d9db809bfe03af33092e71a16e56fc35483"><code>f9c62d9</code></a> (controller) - domain: added reserved domain check</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f5a135be6aa2b319e623fd59bb711705d1cfe13f"><code>f5a135b</code></a> (controller) - migrations: clean old migrations</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4369b2c2fb6ef861978588a61efa1bfc6a4572ec"><code>4369b2c</code></a> (controller) - registry: rename DRYCC_REGISTRY_SERVICE to DRYCC_REGISTRY_PROXY</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1057ca59c3ae6bbd85d772f6b49b0c542d7d18c4"><code>1057ca5</code></a> (controller) - registry: remove registry_secret_prefix</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d114b3e93544624a5f01b1ca71db92d0b33f4e0d"><code>d114b3e</code></a> (controller) - docker: update docker client</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/edbe9631dcfb34ed50d9e931d36506fa262b6299"><code>edbe963</code></a> (dockerbuilder) - dockerfile: change base image to alpine</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/fb35baf913ff846e08ba79d9ad8195fca1411684"><code>fb35baf</code></a> (dockerbuilder) - registry: rename DRYCC_REGISTRY_SERVICE to DRYCC_REGISTRY_PROXY</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/946dbf688474933f821f641f6c027bab68cd9e79"><code>946dbf6</code></a> (dockerbuilder) - docker: remove insecure support</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/628d8532256e32a046268491f2a331dcb608b713"><code>628d853</code></a> (dockerbuilder) - proxy: add registry proxy</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/ff27cbdd27e9dc51ce29b6a68777888ed8737862"><code>ff27cbd</code></a> (registry) - env: remove unused env</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/7204d72c00b2d7360a2d3a20833d701e303a9f62"><code>7204d72</code></a> (registry-proxy) - registry: optimizing variable naming</li> +</ul> + + + + + + diff --git a/blog/releases/page/1/index.html b/blog/releases/page/1/index.html new file mode 100644 index 000000000..cc7d3d782 --- /dev/null +++ b/blog/releases/page/1/index.html @@ -0,0 +1,10 @@ + + + + /blog/releases/ + + + + + + diff --git a/blog/releases/page/2/index.html b/blog/releases/page/2/index.html new file mode 100644 index 000000000..c85b0bb5b --- /dev/null +++ b/blog/releases/page/2/index.html @@ -0,0 +1,280 @@ + + + + + + + + + + + + + + + + + + + + + +Release | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + +
+
Posts in 2019
+
    +
  • +
    +
    Drycc Workflow v1.2.0
    +

    06.10.2019 in Release

    + + + + + + +

    These release notes for Drycc Workflow v1.2.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.1.0, please refer to the following change summary. …

    +

    Read more

    +
    +
  • +
+ +
+
+ +
+ +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/categories/index.html b/categories/index.html new file mode 100644 index 000000000..0a1c1fba0 --- /dev/null +++ b/categories/index.html @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + +Categories | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+

Categories

+
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/categories/index.xml b/categories/index.xml new file mode 100644 index 000000000..1399e112a --- /dev/null +++ b/categories/index.xml @@ -0,0 +1,18 @@ + + + Drycc – Categories + /categories/ + Recent content in Categories on Drycc + Hugo -- gohugo.io + en + + + + + + + + + + + diff --git a/community/_print/index.html b/community/_print/index.html new file mode 100644 index 000000000..5440f63da --- /dev/null +++ b/community/_print/index.html @@ -0,0 +1,199 @@ + + + + + + + + + + + + + + + + + + + + + +Community | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+
+
+ +

Join the Drycc community

+

Drycc is an open source project that anyone in the community can use, improve, and enjoy. We'd love you to join us! Here's a few ways to find out what's happening and get involved.

+
+
+
+
+ + + +
+ + +
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/community/index.html b/community/index.html new file mode 100644 index 000000000..7819ed8f4 --- /dev/null +++ b/community/index.html @@ -0,0 +1,199 @@ + + + + + + + + + + + + + + + + + + + + + +Community | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+
+
+ +

Join the Drycc community

+

Drycc is an open source project that anyone in the community can use, improve, and enjoy. We'd love you to join us! Here's a few ways to find out what's happening and get involved.

+
+
+
+
+ + + +
+ + +
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/community/index.xml b/community/index.xml new file mode 100644 index 000000000..78e6f84bc --- /dev/null +++ b/community/index.xml @@ -0,0 +1,18 @@ + + + Drycc – Community + /community/ + Recent content in Community on Drycc + Hugo -- gohugo.io + en + + + + + + + + + + + diff --git a/css/prism.css b/css/prism.css new file mode 100644 index 000000000..716b70d6c --- /dev/null +++ b/css/prism.css @@ -0,0 +1,4 @@ +/* PrismJS 1.28.0 +https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+bash+c+csharp+cpp+go+java+markdown+python+scss+sql+toml+yaml&plugins=toolbar+copy-to-clipboard */ +code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help} +div.code-toolbar{position:relative}div.code-toolbar>.toolbar{position:absolute;z-index:10;top:.3em;right:.2em;transition:opacity .3s ease-in-out;opacity:0}div.code-toolbar:hover>.toolbar{opacity:1}div.code-toolbar:focus-within>.toolbar{opacity:1}div.code-toolbar>.toolbar>.toolbar-item{display:inline-block}div.code-toolbar>.toolbar>.toolbar-item>a{cursor:pointer}div.code-toolbar>.toolbar>.toolbar-item>button{background:0 0;border:0;color:inherit;font:inherit;line-height:normal;overflow:visible;padding:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}div.code-toolbar>.toolbar>.toolbar-item>a,div.code-toolbar>.toolbar>.toolbar-item>button,div.code-toolbar>.toolbar>.toolbar-item>span{color:#bbb;font-size:.8em;padding:0 .5em;background:#f5f2f0;background:rgba(224,224,224,.2);box-shadow:0 2px 0 0 rgba(0,0,0,.2);border-radius:.5em}div.code-toolbar>.toolbar>.toolbar-item>a:focus,div.code-toolbar>.toolbar>.toolbar-item>a:hover,div.code-toolbar>.toolbar>.toolbar-item>button:focus,div.code-toolbar>.toolbar>.toolbar-item>button:hover,div.code-toolbar>.toolbar>.toolbar-item>span:focus,div.code-toolbar>.toolbar>.toolbar-item>span:hover{color:inherit;text-decoration:none} diff --git a/docs/_print/index.html b/docs/_print/index.html new file mode 100644 index 000000000..2f43c15d0 --- /dev/null +++ b/docs/_print/index.html @@ -0,0 +1,10064 @@ + + + + + + + + + + + + + + + + + + + + + +Docs | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+ + + + + +
+
+

+This is the multi-page printable view of this section. +Click here to print. +

+Return to the regular view of this page. +

+
+ + + +

Docs

+ + + + + + + + +
+ + +
+

A Open, Unified, Lightweight, Simpler Containers as a Service (CaaS).

+ +
+ +

Welcome to Drycc

+

Drycc Workflow is an open source container cloud platform.

+

Usually we also call it Container as a Service(CaaS) that adds a developer-friendly layer +to any Kubernetes cluster, making it easy to deploy and manage applications.

+

Drycc Workflow includes capabilities for building and deploying from source via git push, simple +application configuration, creating and rolling back releases, managing domain names and SSL +certificates, providing seamless edge routing, aggregating logs, and sharing applications with +teams. All of this is exposed through a simple REST API and command line interface.

+

Getting Started

+

To get started with Workflow, follow our Quick Start guide.

+

Take a deep dive into Drycc Workflow in our Concepts, Architecture, and +Components sections.

+

Feel like contibuting some code or want to get started as a maintainer? Pick an issue tagged as an +easy fix or help wanted and start contributing!

+ +
+
+ + + + + + + + + + + + + + + + +
+ +

1 - Quick Start

+
Step-by-step guides for deploying your first app and mastering the basics of Drycc.
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +

1.1 - Quick Start

+
This guide helps you set up the Drycc workflow.
+

Get started with Drycc Workflow in three easy steps.

+
    +
  1. Install CLI tools for Helm and Drycc Workflow
  2. +
  3. Boot a Kubernetes and install Drycc Workflow
  4. +
  5. Deploy your first application
  6. +
+

This guide will help you set up a cluster suitable for evaluation, development and testing. When you are ready for staging and production, view our production checklist.

+

Step 1: Install Workflow

+

For the quickstart we will install Drycc Workflow.

+

Step 2: Install CLI tools

+

For the quickstart we will install Drycc Workflow CLI.

+

Step 3: Deploy your first app

+

Last but not least, login and deploy your first application.

+ +
+ + + + + + + + + + + +
+ +

1.2 - Install Workflow

+
Install Workflow in pure host, it can be a cloud server, bare metal server, virtual machine, or even your laptop.
+

If you have a pure host, it can be a cloud server, bare metal server, virtual machine, or even your laptop. Then this chapter is very suitable for you.

+

Operating Systems

+

Drycc is expected to work on most modern Linux systems. Some OSS have specific requirements:

+
    +
  • (Red Hat/CentOS) Enterprise Linux, they usually use RPM package management.
  • +
  • Ubuntu (Desktop/Server/Cloud) Linux, a very popular distribution.
  • +
  • Debian GNU Linux, a very pure distribution of opensource software.
  • +
+

If you want to add more Linux distribution support, please submit a issue on github or submit PR directly.

+

System Software

+

Some basic software needs to be installed before installing drycc workflow.

+

OS configuration

+

K8s requires a large number of ports. If you are not sure what they are, please close the local firewall or open these ports. +At the same time, because k8s you need system time, you need to ensure that the system time is correct.

+

Installing NFSv4 client

+

The command used to install a NFSv4 client differs depending on the Linux distribution.

+

For Debian and Ubuntu, use this command:

+
$ apt-get install nfs-common
+

For RHEL, CentOS, and EKS with EKS Kubernetes Worker AMI with AmazonLinux2 image, use this command:

+
$ yum install nfs-utils
+

Installing curl

+

For Debian and Ubuntu, use this command:

+
$ apt-get install curl
+

For RHEL, CentOS, and EKS with EKS Kubernetes Worker AMI with AmazonLinux2 image, use this command:

+
$ yum install curl
+

Hardware

+

Hardware requirements scale based on the size of your deployments. Minimum recommendations are outlined here.

+
    +
  • RAM: 1G Minimum (we recommend at least 2GB)
  • +
  • CPU: 1 Minimum
  • +
+

This configuration only contains the minimum requirements that can meet the operation.

+

Disk

+

Drycc performance depends on the performance of the database. To ensure optimal speed, we recommend using an SSD when possible. Disk performance will vary on ARM devices utilizing an SD card or eMMC.

+

Domain Name

+

Drycc needs a root domain name under your full control and points this domain name to the server to be installed. +Suppose there is a wildcard domain pointing to the current server to install drycc, which is the name *.dryccdoman.com. +We need to set the PLATFORM_DOMAIN environment variables before installation.

+
$ export PLATFORM_DOMAIN=dryccdoman.co
+

Of course, if it is a test environment, we can also use nip.io, an IP to domain name service. +For example, your host IP is 59.46.3.190, we will get the following domain name 59.46.3.190.nip.io

+
$ export PLATFORM_DOMAIN=59.46.3.190.nip.io
+

Install

+

Before installation, please make sure whether your installation environment is a public network. +If it is an intranet environment and there is no public IP, you need to disable the automatic certificate.

+
$ export CERT_MANAGER_ENABLED=false
+

Then you can use the installation script available at https://www.drycc.cc/install.sh to install drycc as a service on systemd and openrc based systems.

+
$ curl -sfL https://www.drycc.cc/install.sh | bash -
+

!!! important +If you are in China, you need to use mirror acceleration:

+
```
+$ curl -sfL https://www.drycc.cc/install.sh | INSTALL_DRYCC_MIRROR=cn bash -
+```
+
+

Install Node

+

Node can be a simple agent or a server; Server has the function of agent. Multiple servers have high availability, but the number of servers should not +exceed 7 at most. There is no limit to the number of agents.

+
    +
  • First, check the cluster token of the master.
  • +
+
$ cat /var/lib/rancher/k3s/server/node-token
+K1078e7213ca32bdaabb44536f14b9ce7926bb201f41c3f3edd39975c16ff4901ea::server:33bde27f-ac49-4483-b6ac-f4eec2c6dbfa
+

We assume that the IP address of the cluster master is 192.168.6.240, in that way.

+
    +
  • Then, Set the environment variable:
  • +
+
$ export K3S_URL=https://192.168.6.240:6443
+$ export K3S_TOKEN="K1078e7213ca32bdaabb44536f14b9ce7926bb201f41c3f3edd39975c16ff4901ea::server:33bde27f-ac49-4483-b6ac-f4eec2c6dbfa"
+

!!! important +If you are in China, you need to use mirror acceleration:

+
```
+$ export INSTALL_DRYCC_MIRROR=cn
+```
+
+
    +
  • Join the cluster as server:
  • +
+
$ curl -sfL https://www.drycc.cc/install.sh | bash -s - install_k3s_server
+
    +
  • Join the cluster as agent:
  • +
+
$ curl -sfL https://www.drycc.cc/install.sh | bash -s - install_k3s_agent
+

Install Options

+

When using this method to install drycc, the following environment variables can be used to configure the installation:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ENVIRONMENT VARIABLEDESCRIPTION
PLATFORM_DOMAINRequired item, specify drycc’s domain name
DRYCC_ADMIN_USERNAMERequired item, specify drycc’s admin username
DRYCC_ADMIN_PASSWORDRequired item, specify drycc’s admin password
CERT_MANAGER_ENABLEDWhether to use automatic certificate. It is false by default
CHANNELBy default, stable channel will be installed. You can also specify testing
REGISTRY_FILEThe config.yaml file path used by k3s containers registry
KUBERNETES_SERVICE_HOSTSet with the HOST of the loadbalancer that was in front of kube-apiserver
KUBERNETES_SERVICE_PORTSet with the PORT of the loadbalancer that was in front of kube-apiserver
METALLB_CONFIG_FILEThe metallb config file path, layer 2 network is used by default
INSTALL_DRYCC_MIRRORSpecify the accelerated mirror location. Currently, only cn is supported
BUILDER_REPLICASNumber of builder replicas to deploy
CONTROLLER_API_REPLICASNumber of controller api replicas to deploy
CONTROLLER_CELERY_REPLICASNumber of controller celery replicas to deploy
CONTROLLER_WEBHOOK_REPLICASNumber of controller webhook replicas to deploy
CONTROLLER_APP_RUNTIME_CLASSRuntimeClass is a feature for selecting the container runtime configuration.
CONTROLLER_APP_STORAGE_CLASSStorageClass allocated by drycc volumes; default storageClass is used by default
REDIS_REPLICASNumber of redis replicas to deploy
REDIS_PERSISTENCE_SIZEThe size of the persistence space allocated to redis, which is 5Gi by default
REDIS_PERSISTENCE_STORAGE_CLASSStorangeClass of redis; default storangeclass is used by default
STORAGE_CSI_STATEFULSET_REPLICASNumber of storage csi controller replicas to deploy
STORAGE_MAINNODE_TIPD_REPLICASNumber of storage mainode tipd replicas to deploy
STORAGE_MAINNODE_TIPD_PERSISTENCE_SIZEThe size of the persistence space allocated to mainnode tipd, which is 10Gi by default
STORAGE_MAINNODE_TIPD_PERSISTENCE_STORAGE_CLASSStorangeClass of mainnode tipd; default storangeclass is used by default
STORAGE_MAINNODE_WEED_REPLICASNumber of storage mainode weed replicas to deploy
STORAGE_MAINNODE_WEED_PREALLOCATEPreallocate disk space for volumes, false is used by default
STORAGE_MAINNODE_WEED_SIZE_LIMIT_MBMaster stops directing writes to oversized volumes, 30000 is used by default
STORAGE_MAINNODE_WEED_DEFAULT_REPLICATIONdefault replication type if not specified, which is 000 by default
STORAGE_MAINNODE_WEED_PERSISTENCE_SIZEThe size of the persistence space allocated to mainnode weed, which is 10Gi by default
STORAGE_MAINNODE_WEED_PERSISTENCE_STORAGE_CLASSStorangeClass of mainnode weed; default storangeclass is used by default
STORAGE_METANODE_TIKV_REPLICASNumber of storage metanode tikv replicas to deploy
STORAGE_METANODE_TIKV_PERSISTENCE_SIZEThe size of the persistence space allocated to metanode tikv, which is 10Gi by default
STORAGE_METANODE_TIKV_PERSISTENCE_STORAGE_CLASSStorangeClass of mainnode tikv; default storangeclass is used by default
STORAGE_METANODE_WEED_REPLICASNumber of storage metanode weed replicas to deploy
STORAGE_METANODE_WEED_PERSISTENCE_SIZEThe size of the persistence space allocated to metanode weed, which is 10Gi by default
STORAGE_METANODE_WEED_PERSISTENCE_STORAGE_CLASSStorangeClass of mainnode weed; default storangeclass is used by default
STORAGE_DATANODE_WEED_REPLICASNumber of storage datanode weed replicas to deploy
STORAGE_DATANODE_WEED_PERSISTENCE_SIZEThe size of the persistence space allocated to datanode weed, which is 20Gi by default
STORAGE_DATANODE_WEED_PERSISTENCE_STORAGE_CLASSStorangeClass of datanode weed; default storangeclass is used by default
MONITOR_GRAFANA_PERSISTENCE_SIZEThe size of the persistence space allocated to monitor.grafana, which is 5Gi by default
MONITOR_GRAFANA_PERSISTENCE_STORAGE_CLASSStorangeClass of monitor grafana; default storangeclass is used by default
LOGGER_REPLICASNumber of logger replicas to deploy
RABBITMQ_REPLICASNumber of rabbitmq replicas to deploy
RABBITMQ_PERSISTENCE_SIZEThe size of the persistence space allocated to rabbitmq, which is 5Gi by default
RABBITMQ_PERSISTENCE_STORAGE_CLASSStorangeClass of rabbitmq; default storangeclass is used by default
DATABASE_REPLICASNumber of database replicas to deploy
DATABASE_PERSISTENCE_SIZEThe size of the persistence space allocated to database, which is 5Gi by default
DATABASE_PERSISTENCE_STORAGE_CLASSStorangeClass of database; default storangeclass is used by default
TIMESERIES_REPLICASNumber of timeseries replicas to deploy
TIMESERIES_PERSISTENCE_SIZEThe size of the persistence space allocated to timeseries, which is 5Gi by default
TIMESERIES_PERSISTENCE_STORAGE_CLASSStorangeClass of timeseries; default storangeclass is used by default
PASSPORT_REPLICASNumber of passport replicas to deploy
REGISTRY_REPLICASNumber of registry replicas to deploy
HELMBROKER_REPLICASNumber of helmbroker api replicas to deploy
HELMBROKER_CELERY_REPLICASNumber of helmbroker celery replicas to deploy
HELMBROKER_PERSISTENCE_SIZEThe size of the persistence space allocated to helmbroker, which is 5Gi by default
HELMBROKER_PERSISTENCE_STORAGE_CLASSStorangeClass of helmbroker; default storangeclass is used by default
PROMETHEUS_SERVER_RETENTIONPrometheus data retention period (default if not specified is 15 days)
PROMETHEUS_SERVER_PERSISTENCE_SIZEThe size of the persistence space allocated to prometheus-server, which is 10Gi by default
PROMETHEUS_SERVER_PERSISTENCE_STORAGE_CLASSStorangeClass of prometheus-server; default storangeclass is used by default
K3S_DATA_DIRThe config of k3s data dir; If not set, the default path is used
ACME_SERVERACME Server url, default use letsencrypt
ACME_EAB_KEY_IDThe key ID of which your external account binding is indexed by the external account
ACME_EAB_KEY_SECRETThe key Secret of which your external account symmetric MAC key
+

Since the installation script will install k3s, other environment variables can refer to k3s installation environment variables.

+

Uninstall

+

If you installed drycc using an installation script, you can uninstall the entire drycc using this script.

+
$ curl -sfL https://www.drycc.cc/uninstall.sh | bash -
+
+
+ + + + + + + + + + + +
+ +

1.3 - Drycc Workflow Client CLI

+
How to download, install Drycc CLI tools.
+

Drycc Workflow Client CLI

+

The Drycc command-line interface (CLI), lets you interact with Drycc Workflow. +Use the CLI to create and configure and manage applications.

+

Install the drycc client for Linux or Mac OS X with:

+
$ curl -sfL https://www.drycc.cc/install-cli.sh | bash -
+

!!! important +Users in Chinese mainland can use the following methods to speed up installation:

+
```
+$ curl -sfL https://www.drycc.cc/install-cli.sh | INSTALL_DRYCC_MIRROR=cn bash -
+```
+
+

Others please visit: https://github.com/drycc/workflow-cli/releases

+

The installer places the drycc binary in your current directory, but you +should move it somewhere in your $PATH:

+
$ sudo ln -fs $PWD/drycc /usr/local/bin/drycc
+

or:

+
$ sudo mv $PWD/drycc /usr/local/bin/drycc
+

Check your work by running drycc version:

+
$ drycc version
+v1.1.0
+

Update workflow cli to latest release.

+
drycc update
+

!!! note +Note that version numbers may vary as new releases become available

+ +
+ + + + + + + + + + + +
+ +

1.4 - Deploy Your First App

+
Deploy an application using drycc cli.
+

Determine Your Host and Hostname Values

+

Drycc workflow requires a wildcard DNS record to dynamically map app names to the router.

+

User should already have DNS set up pointing to their known host. The $hostname value can be calculated by prepending drycc. to the value set in global.platformDomain.

+

Login to Workflow

+

Workflow use the passport component to create and authorize users. +If you already have an account, use drycc login to authenticate against the Drycc Workflow API.

+
$ drycc login http://drycc.example.com
+Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71
+Waiting for login... .o.Logged in as admin
+Configuration file written to /root/.drycc/client.json
+

Or you can login with username and password

+
$ drycc login http://drycc.example.com --username=demo --password=demo
+Configuration file written to /root/.drycc/client.json
+

Deploy an Application

+

Drycc Workflow supports three different types of applications, Buildpacks, +Dockerfiles and Container Images. Our first application will be a simple Container +Image-based application, so you don’t have to wrestle with checking out code.

+

Run drycc create to create a new application on Drycc Workflow. If you do not +specify a name for your application, Workflow automatically generates a +friendly (and sometimes funny) name.

+
$ drycc create --no-remote
+Creating Application... done, created proper-barbecue
+If you want to add a git remote for this app later, use `drycc git:remote -a proper-barbecue`
+

Our application has been created and named proper-barbecue. As with the +drycc hostname, any HTTP traffic to proper-barbecue will be automatically +routed to your application pods by the edge router.

+

Let’s use the CLI to tell the platform to deploy an application and then use curl to send a request to the app:

+
$ drycc pull drycc/example-go -a proper-barbecue
+Creating build... done
+$ curl http://proper-barbecue.$hostname
+Powered by Drycc
+

!!! note +If you see a 404 error, make sure you specified your application name with -a <appname>!

+

Workflow’s edge router knows all about application names and automatically +sends traffic to the right application. The router sends traffic for +proper-barbecue.104.197.125.75.nip.io to your app, just like +drycc.104.197.125.75.nip.io was sent to the Workflow API service.

+

Change Application Configuration

+

Next, let’s change some configuration using the CLI. Our example app is built +to read configuration from the environment. By using drycc config:set we can +change how the application behaves:

+
$ drycc config:set POWERED_BY="Container Images + Kubernetes" -a proper-barbecue
+Creating config... done
+
+UUID                                    OWNER    NAME                 VALUE
+04bb6e45-9221-4843-a1f9-acc7fded3b06    dev      POWERED_BY           Container Images + Kubernetes
+

Behind the scenes, Workflow creates a new release for your application and uses +Kubernetes to provide a zero-downtime rolling deploy to the new release!

+

Validate that our configuration change has worked:

+
$ curl http://proper-barbecue.104.197.125.75.nip.io
+Powered by Container Images + Kubernetes
+

Scale Your Application

+

Last, let’s scale our application by adding more application processes. Using the CLI you can easily add and remove +additional processes to service requests:

+
$ drycc scale web=2 -a proper-barbecue
+Scaling processes... but first, coffee!
+done in 36s
+
+NAME                                RELEASE    STATE    PTYPE       STARTED
+proper-barbecue-v18-web-rk644       v18        up       web         2023-12-08T03:09:25UTC
+proper-barbecue-v18-web-0ag04       v18        up       web         2023-12-08T03:09:25UTC
+

Congratulations! You have deployed, configured, and scaled your first application using Drycc Workflow.

+

Going Further

+

There is a lot more you can do with Drycc Workflow, play around with the CLI:

+

!!! important +In order to have permission to push an app you must add a SSH key to your user on the Drycc Workflow. +For more information, please check Users and SSH Keys and Troubleshooting Workflow.

+ + +
+ + + + + + + + + + + + + + + +
+ +

2 - Understanding Workflow

+
Understanding the architecture design of workflow.
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +

2.1 - Concepts

+
Drycc Workflow is a lightweight application platform that deploys and scales Twelve-Factor apps as containers across a Kubernetes cluster.
+

Twelve-Factor Applications

+

The Twelve-Factor App is a methodology for building modern +applications that can be scaled across a distributed system.

+

Twelve-factor is a valuable synthesis of years of experience with +software-as-a-service apps in the wild, particularly on the +Heroku platform.

+

Workflow is designed to run applications that adhere to the Twelve-Factor App +methodology and best practices.

+

Kubernetes

+

Kubernetes is an open-source cluster manager developed by Google and +donated to the Cloud Native Compute Foundation. Kubernetes manages all +the activity on your cluster, including: desired state convergence, stable +service addresses, health monitoring, service discovery, and DNS resolution.

+

Workflow builds upon Kubernetes abstractions like Services, +Deployments and Pods to provide a developer-friendly experience. +Building containers directly from application source code, aggregating logs, +and managing deployment configurations and app releases are just some of the +features Workflow adds.

+

Drycc Workflow is a set of Kubernetes-native components, installable via +Helm. Systems engineers who are familiar with Kubernetes will feel right +at home running Workflow.

+

See the components overview for more detail.

+

Container

+

[Container][] is an open source project to build, ship and run any +application as a lightweight, portable, self-sufficient container.

+

If you have not yet converted your application to containers, Workflow provides +a simple and straightforward “source to Container image” capability. Supporting +multiple language runtimes via community buildpacks, building your application +in a container can be as easy as git push drycc master.

+

Applications which use either a Dockerfile or reference external Container +images are launched unmodified.

+

Applications

+

Workflow is designed around the concept of an application, or app.

+

Applications come in one of three forms:

+
    +
  1. a collection of source files stored in a git repository
  2. +
  3. a Dockerfile and associated source files stored in a git repository
  4. +
  5. a reference to an existing image at a Container repository
  6. +
+

Applications are identified by a unique name for easy reference. If you do not +specify a name when creating your application, Workflow generates one for you. +Workflow also manages related information, including domain names, SSL +certificates, and developer-provided configuration.

+

Build, Release, Run

+

Git Push Workflow

+

Build Stage

+

The builder component processes incoming git push drycc master requests +and manages your application packaging.

+

If your application is using a buildpack, builder will launch an ephemeral +job to extract and execute the packaging instructions. The resulting +application artifact is stored by the platform for execution during the run +stage.

+

If instead builder finds a Dockerfile, it follows those instructions to +create a Container image. The resulting artifact is stored in a Drycc-managed registry which +will be referenced during the run stage.

+

If another system already builds and packages your application, that container +artifact can be used directly. When referencing an external Container +image, the builder component doesn’t attempt to repackage your +app.

+

Release Stage

+

During the release stage, a build is combined with application configuration +to create a new, numbered release. New releases are created any time a new +build is created or application configuration is changed. Tracking releases as a +“write-only ledger” this way makes it easy to rollback to any previous release.

+

Run Stage

+

The run stage deploys the new release to the underlying Kubernetes cluster by +changing the Deployment object which references the new release. +By managing the desired replica count, Workflow +orchestrates a zero-downtime, rolling update of your application. Once +successfully updated, Workflow removes the last reference to the old release. +Note that during the deploy, your application will be running in a mixed mode.

+

Backing Services

+

Workflow treats all persistent services such as databases, caches, storage, +messaging systems, and other backing services as resources managed +separately from your application. This philosophy aligns with Twelve-Factor +best practices.

+

Applications attach to backing services using environment variables. +Because apps are decoupled from backing services, they are free to +scale up independently, to use services provided by other apps, or to switch +to external or third-party vendor services.

+

See Also

+ + +
+ + + + + + + + + + + +
+ +

2.2 - Architecture

+
Drycc Workflow is built using a service oriented architecture.
+

All components are published as a set of container images which can be deployed to any +compliant Kubernetes cluster.

+

Overview

+

System Overview

+

Operators use Helm to configure and install the Workflow components which +interface directly with the underlying Kubernetes cluster. Service discovery, +container availability and networking are all delegated to Kubernetes, while +Workflow provides a clean and simple developer experience.

+

Platform Services

+

Workflow Overview

+

Drycc Workflow provides additional functionality to your Kubernetes cluster, including:

+ +

Kubernetes-Native

+

All platform components and applications deployed via Workflow expect to be +running on an existing Kubernetes cluster. This means that you can happily run +your Kubernetes-native workloads next to applications that are managed through +Drycc Workflow.

+

Workflow and Kubernetes

+

Application Layout and Edge Routing

+

By default Workflow creates per-application Namespaces and Services so you can +easily connect your applications to other on-cluster services through standard +Kubernetes mechanisms.

+

Application Configuration

+

The router component is responsible for routing HTTP/s traffic to your +Applications as well as proxying git push and platform API traffic.

+

By default, the router component is deployed as a Kubernetes service with type +LoadBalancer; which, depending on your configuration, will provision a +cloud-native load balancer automatically.

+

The router automatically discovers routable Applications, SSL/TLS certificates +and application-specific configurations through the use of Kubernetes +annotations. Any changes to router configuration or certificates are applied +within seconds.

+

Topologies

+

Drycc Workflow no longer dictates a specific topology or server count for your +deployment. The platform components will happily run on single-server +configurations as well as multi-server production clusters.

+ +
+ + + + + + + + + + + +
+ +

2.3 - Components

+
Workflow is comprised of a number of small, independent services that combine to create a distributed CaaS.
+

All Workflow components are deployed as services (and associated controllers) in your Kubernetes cluster. +If you are interested we have a more detailed exploration of the Workflow architecture.

+

All of the componentry for Workflow is built with composability in mind. If you +need to customize one of the components for your specific deployment or need +the functionality in your own project we invite you to give it a shot!

+

Controller

+

Project Location: drycc/controller

+

The controller component is an HTTP API server which serves as the endpoint for +the drycc CLI. The controller provides all of the platform functionality as +well as interfacing with your Kubernetes cluster. The controller persists all +of its data to the database component.

+

Passport

+

Project Location: drycc/passport

+

The passport component exposes a web API and provide OAuth2 authentication.

+

Database

+

Project Location: drycc/postgres

+

The database component is a managed instance of PostgreSQL which holds a +majority of the platforms state. Backups and WAL files are pushed to object +storage via WAL-E. When the database is restarted, backups are fetched and +replayed from object storage so no data is lost.

+

Builder

+

Project Location: drycc/builder

+

The builder component is responsible for accepting code pushes via Git and +managing the build process of your Application. The builder process is:

+
    +
  1. Receives incoming git push requests over SSH
  2. +
  3. Authenticates the user via SSH key fingerprint
  4. +
  5. Authorizes the user’s access to push code to the Application
  6. +
  7. Starts the Application Build phase (see below)
  8. +
  9. Triggers a new Release via the Controller
  10. +
+

Builder currently supports both buildpack and Dockerfile based builds.

+

Project Location: drycc/imagebuilder

+

For Buildpack-based deploys, the builder component will launch a one-shot Job +in the drycc namespace. This job runs imagebuilder component which handles +default and custom buildpacks (specified by .packbuilder). The completed image +is pushed to the managed Container registry on cluster. For more information +about buildpacks see using buildpacks.

+

Unlike buildpack-based, For Applications which contain a Dockerfile in the root +of the repository, it generates a Container image (using the underlying Container engine). +For more information see using Dockerfiles.

+

Object Storage

+

Project Location: drycc/storage

+

All of the Workflow components that need to persist data will ship them to the +object storage that was configured for the cluster.For example, database ships +its WAL files, registry stores Container images, and slugbuilder stores slugs.

+

Workflow supports either on or off-cluster storage. For production deployments +we highly recommend that you configure off-cluster object storage.

+

To facilitate experimentation, development and test environments, the default charts for +Workflow include on-cluster storage via storage.

+

If you also feel comfortable using Kubernetes persistent volumes you may +configure storage to use persistent storage available in your environment.

+

Registry

+

Project Location: drycc/registry

+

The registry component is a managed container registry which holds application +images generated from the builder component. Registry persists the Container image +images to either local storage (in development mode) or to object storage +configured for the cluster.

+

Logger: fluentbit, logger

+

The logging subsystem consists of two components. Fluentbit handles log shipping +and logger maintains a ring-buffer of application logs.

+

Project Location: drycc/fluentbit

+

Fluentbit is deployed to your Kubernetes cluster via Daemon Sets. Fluentbit +subscribes to all container logs, decorates the output with Kubernetes metadata +and can be configured to drain logs to multiple destinations. By default, +Fluentbit ships logs to the logger component, which powers drycc logs.

+

Project Location: drycc/logger

+

The logger component receives log streams from fluentbit, collating by +Application name. Logger does not persist logs to disk, instead maintaining an +in-memory ring buffer. For more information on logger see the project +documentation.

+

Monitor

+

Project Location: drycc/monitor

+

The monitoring subsystem consists of two components: Telegraf and Grafana.

+

Telegraf is the is the metrics collection agent that runs using the daemon set API. It runs on +every worker node in the cluster, fetches information about the pods currently running and ships it +to Prometheus.

+

Grafana is a standalone graphing application. It natively supports Prometheus as a datasource and +provides a robust engine for creating dashboards on top of timeseries data. Workflow provides a few +dashboards out of the box for monitoring Drycc Workflow and Kubernetes. The dashboards can be used +as a starting point for creating more custom dashboards to suit a user’s needs.

+

Prometheus

+

Project Location: drycc/prometheus

+

Prometheus is a system monitoring and alerting system. It was opensourced by SoundCloud in 2012 and is +the second project both to join and to graduate within Cloud Native Computing Foundation after Kubernetes. +Prometheus stores all metrics data as time series, i.e metrics information is stored along with the +timestamp at which it was recorded, optional key-value pairs called as labels can also be stored along +with metrics.

+

Rabbitmq

+

Project Location: drycc/rabbitmq

+

RabbitMQ is the most widely deployed open source message broker. +Controller use celery with rabbitMQ to execute the asynchronous task.

+

HelmBroker

+

Project Location: drycc/rabbitmq

+

Helm Broker is a Service Broker that exposes Helm charts as Service Classes in Service Catalog. +To do so, Helm Broker uses the concept of addons. An addon is an abstraction layer over a Helm chart +which provides all information required to convert the chart into a Service Class.

+

Prometheus

+

Project Location: drycc/rabbitmq

+

Prometheus is an open-source systemsmonitoring and alerting toolkit originally built atSoundCloud.

+

See Also

+ + +
+ + + + + + + + + + + + + + + +
+ +

3 - Installing To Kubenetes

+
Deploying Drycc on a Kubernetes Cluster.
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +

3.1 - Requirements

+
To run Drycc Workflow on a Kubernetes cluster, there are a few requirements to keep in mind.
+

Kubernetes Versions

+

Drycc Workflow requires Kubernetes v1.16.15 or later.

+

Components Requirements

+

Drycc uses gateway as a routing implementation, so you have to choose an gateway. We recommend using istio or kong.

+

Workflow supports the use of ACME to manage automatic certificates, cert-manager is also one of the necessary components, if you use cert-manager EAB, you need to set the clusterResourceNamespace to the namespace of drycc.

+

Workflow supports stateful apps. You can create and use them through the ‘drycc volumes’ command. If you want to use this feature, you must have a StorageClass that supports ReadWriteMany.

+

Workflow also supports the OSB API through the ‘drycc resources’ command. If you want to use this function, you need to install service-catalog.

+

Storage Requirements

+

A variety of Drycc Workflow components rely on an object storage system to do their work, including storing application +slugs, Container images and database logs.

+

Drycc Workflow ships with drycc storage by default, which provides in-cluster.

+

Workflow supports Amazon Simple Storage Service (S3), Google Cloud Storage (GCS), OpenShift Swift, and Azure Blob +Storage. See configuring object storage for setup instructions.

+

Resource Requirements

+

When deploying Drycc Workflow, it’s important to provision machines with adequate resources. Drycc is a highly-available +distributed system, which means that Drycc components and your deployed applications will move around the cluster onto +healthy hosts as hosts leave the cluster for various reasons (failures, reboots, autoscalers, etc.). Because of this, +you should have ample spare resources on any machine in your cluster to withstand the additional load of running +services for failed machines.

+

Drycc Workflow components use about 2.5GB of memory across the cluster, and require approximately 30GB of hard disk +space. Because it may need to handle additional load if another one fails, each machine has minimum requirements of:

+
    +
  • At least 4GB of RAM (more is better)
  • +
  • At least 40GB of hard disk space
  • +
+

Note that these estimates are for Drycc Workflow and Kubernetes only. Be sure to leave enough spare capacity for your +application footprint as well.

+

Running smaller machines will likely result in increased system load and has been known to result in component failures +and instability.

+ +
+ + + + + + + + + + + +
+ +

3.2 - Specify Gateway

+
Choose the gateway provider that best suits your needs and platform.
+

Install Drycc Workflow (Specify gateway)

+

Now that Helm is installed and the repository has been added, install Workflow with a native gateway by running:

+
$ helm install drycc oci://registry.drycc.cc/charts/workflow \
+    --namespace drycc \
+    --set global.gatewayClass=istio \
+    --set global.platformDomain=drycc.cc \
+    --set builder.service.type=LoadBalancer
+

Of course, if you deploy it on a bare machine, you probably do not have Load Balancer. You need to use NodePort:

+
$ helm install drycc oci://registry.drycc.cc/charts/workflow \
+    --namespace drycc \
+    --set global.gatewayClass=istio \
+    --set global.platformDomain=drycc.cc \
+    --set builder.service.type=NodePort \
+    --set builder.service.nodePort=32222
+

If you want to use Load Balancer on a bare machine, you can look at metallb

+

Where global.platformDomain is a required parameter that is traditionally not required for Workflow that is explained in the next section. In this example we are using drycc.cc for $hostname.

+

Helm will install a variety of Kubernetes resources in the drycc namespace. +Wait for the pods that Helm launched to be ready. Monitor their status by running:

+
$ kubectl --namespace=drycc get pods
+

You should also notice that several Kubernetes gatewayclass has been installed on your cluster. You can view it by running:

+
$ kubectl get gatewayclass --namespace drycc
+

Depending on the order in which the Workflow components initialize, some pods may restart. This is common during the +installation: if a component’s dependencies are not yet available, that component will exit and Kubernetes will +automatically restart it.

+

Here, it can be seen that the controller, builder and registry all took a few loops waiting for storage before they were able to start:

+
$ kubectl --namespace=drycc get pods
+NAME                          READY     STATUS    RESTARTS   AGE
+drycc-builder-hy3xv            1/1       Running   5          5m
+drycc-controller-g3cu8         1/1       Running   5          5m
+drycc-controller-celery-cmxxn  3/3       Running   0          5m
+drycc-database-rad1o           1/1       Running   0          5m
+drycc-logger-fluentbit-1v8uk   1/1       Running   0          5m
+drycc-logger-fluentbit-esm60   1/1       Running   0          5m
+drycc-logger-sm8b3             1/1       Running   0          5m
+drycc-storage-4ww3t            1/1       Running   0          5m
+drycc-registry-asozo           1/1       Running   1          5m
+drycc-rabbitmq-0               1/1       Running   0          5m
+

Install a Kubernetes Gateway

+

Now that Workflow has been deployed with the global.gatewayClass , we will need a Kubernetes gateway in place to begin routing traffic.

+

Here is an example of how to use istio as an gateway for Workflow. Of course, you are welcome to use any controller you wish.

+
$ helm repo add istio https://istio-release.storage.googleapis.com/charts
+$ helm repo update
+$ kubectl create namespace istio-system
+$ helm install istio-base istio/base -n istio-system
+$ helm install istiod istio/istiod -n istio-system --wait
+$ kubectl create namespace istio-ingress
+$ helm install istio-ingress istio/gateway -n istio-ingress --wait
+

Configure DNS

+

User must install drycc and then set up a hostname, and assumes the *.$host convention.

+

We need to point the *.$host record to the public IP address of your gateway. You can get the public IP using the following command. A wildcard entry is necessary here as apps will use the same rule after they are deployed.

+
$ kubectl get gateway --namespace drycc
+NAME      CLASS   ADDRESS         PROGRAMMED   AGE
+gateway   istio   138.91.243.152  True         36d
+

If we were using drycc.cc as a hostname, we would need to create the following A DNS records.

+ + + + + + + + + + + + + + + +
NameTypeValue
*.drycc.ccA138.91.243.152
+

Once all of the pods are in the READY state, and *.$host resolves to the external IP found above, the preparation of gateway has been completed!

+

After installing Workflow, register a user and deploy an application.

+

If your k8s does not provide public network loadblance, you need to install TCP proxy services such as haproxy on machines that can +access both internal and external networks, and then expose 80 and 443.

+ +
+ + + + + + + + + + + +
+ +

3.3 - Installing Drycc Workflow

+
This document is aimed at those who have already provisioned a Kubernetes cluster and want to install Drycc Workflow.
+

If help is required getting started with Kubernetes and +Drycc Workflow, follow the quickstart guide for assistance.

+

Prerequisites

+
    +
  1. Verify the Kubernetes system requirements
  2. +
  3. Install Helm and Drycc Workflow CLI tools
  4. +
+

Check Your Setup

+

Check that the helm command is available and the version is v2.5.0 or newer.

+
$ helm version
+Client: &version.Version{SemVer:"v2.5.0", GitCommit:"012cb0ac1a1b2f888144ef5a67b8dab6c2d45be6", GitTreeState:"clean"}
+Server: &version.Version{SemVer:"v2.5.0", GitCommit:"012cb0ac1a1b2f888144ef5a67b8dab6c2d45be6", GitTreeState:"clean"}
+

Choose Your Deployment Strategy

+

Drycc Workflow includes everything it needs to run out of the box. However, these defaults are aimed at simplicity rather than +production readiness. Production and staging deployments of Workflow should, at a minimum, use off-cluster storage +which is used by Workflow components to store and backup critical data. Should an operator need to completely re-install +Workflow, the required components can recover from off-cluster storage. See the documentation for configuring object +storage for more details.

+

More rigorous installations would benefit from using outside sources for the following things:

+ +

Gateway

+

Now, workflow requires that gateway and cert-manager must be installed. Any compatible Kubernetes entry controller can be used.

+

Install Drycc Workflow

+

If the version of helm is 3.0 +; you need to create the namespace in advance:

+
kubectl create ns drycc
+

If you want to change it, set the variable when using helm.

+
$ helm install drycc oci://registry.drycc.cc/charts/workflow \
+    --namespace drycc \
+    --set builder.imageRegistry=quay.io \
+    --set imagebuilder.imageRegistry=quay.io \
+    --set controller.imageRegistry=quay.io \
+    --set database.imageRegistry=quay.io \
+    --set fluentbit.imageRegistry=quay.io \
+    --set redis.imageRegistry=quay.io \
+    --set rabbitmq.imageRegistry=quay.io \
+    --set logger.imageRegistry=quay.io \
+    --set storage.imageRegistry=quay.io \
+    --set monitor.imageRegistry=quay.io \
+    --set registry.imageRegistry=quay.io \
+    --set registry-proxy.imageRegistry=quay.io \
+    --set global.platformDomain=drycc.cc
+

Helm will install a variety of Kubernetes resources in the drycc namespace. +Wait for the pods that Helm launched to be ready. Monitor their status by running:

+
$ kubectl --namespace=drycc get pods
+

If it’s preferred to have kubectl automatically update as the pod states change, run (type Ctrl-C to stop the watch):

+
$ kubectl --namespace=drycc get pods -w
+

Depending on the order in which the Workflow components initialize, some pods may restart. This is common during the +installation: if a component’s dependencies are not yet available, that component will exit and Kubernetes will +automatically restart it.

+

Here, it can be seen that the controller, builder and registry all took a few loops before they were able to start:

+
$ kubectl --namespace=drycc get pods
+NAME                                     READY     STATUS    RESTARTS   AGE
+drycc-builder-574483744-l15zj             1/1       Running   0          4m
+drycc-controller-3953262871-pncgq         1/1       Running   2          4m
+drycc-controller-celery-cmxxn             3/3       Running   0          4m
+drycc-database-83844344-47ld6             1/1       Running   0          4m
+drycc-logger-176328999-wjckx              1/1       Running   4          4m
+drycc-logger-fluentbit-zxnqb              1/1       Running   0          4m
+drycc-redis-304849759-1f35p               1/1       Running   0          4m
+drycc-storage-676004970-nxqgt             1/1       Running   0          4m
+drycc-monitor-grafana-432627134-lnl2h     1/1       Running   0          4m
+drycc-monitor-telegraf-wmcmn              1/1       Running   1          4m
+drycc-registry-756475849-lwc6b            1/1       Running   1          4m
+drycc-registry-proxy-96c4p                1/1       Running   0          4m
+drycc-rabbitmq-0                          1/1       Running   0          4m
+

Once all of the pods are in the READY state, Drycc Workflow is up and running!

+

For more installation parameters, please check the values.yaml file of workflow.

+

After installing Workflow, register a user and deploy an application.

+

Configure DNS

+

User must to set up a hostname, and assumes the drycc-builder.$host convention.

+

We need to point the drycc-builder.$host record to the public IP address of your builder. You can get the public IP using the following command. A wildcard entry is necessary here as apps will use the same rule after they are deployed.

+
$ kubectl get svc drycc-builder --namespace drycc
+NAME              CLUSTER-IP   EXTERNAL-IP      PORT(S)                      AGE
+drycc-builder     10.0.25.3    138.91.243.152   2222:31625/TCP               33m
+

If we were using drycc.cc as a hostname, we would need to create the following A DNS records.

+ + + + + + + + + + + + + + + +
NameTypeValue
drycc-builder.drycc.ccA138.91.243.152
+

Once all of the pods are in the READY state, and drycc-builder.$host resolves to the external IP found above, Workflow is up and running!

+

After installing Workflow, register a user and deploy an application.

+

If your k8s does not provide public network loadblance, you need to install TCP proxy services such as haproxy on machines that can +access both internal and external networks, and then expose 80 and 443.

+ +
+ + + + + + + + + + + +
+ +

3.4 - Configuring Object Storage

+
A variety of Drycc Workflow components rely on an object storage system to do their work including storing application slugs, Container images and database logs.
+

Drycc Workflow ships with Storage by default, which provides in-cluster.

+

Configuring off-cluster Object Storage

+

Every component that relies on object storage uses two inputs for configuration:

+
    +
  1. You must use object storage services that are compatible with S3 API
  2. +
  3. Access credentials stored as a Kubernetes secret named storage-creds
  4. +
+

The helm chart for Drycc Workflow can be easily configured to connect Workflow components to off-cluster object storage. Drycc Workflow currently supports Google Compute Storage, Amazon S3, Azure Blob Storage and OpenStack Swift Storage.

+

Step 1: Create storage buckets

+

Create storage buckets for each of the Workflow subsystems: builder, registry, and database.

+

Depending on your chosen object storage you may need to provide globally unique bucket names. If you are using S3, use hyphens instead of periods in the bucket names. Using periods in the bucket name will cause an ssl certificate validation issue with S3.

+

If you provide credentials with sufficient access to the underlying storage, Workflow components will create the buckets if they do not exist.

+

Step 2: Generate storage credentials

+

If applicable, generate credentials that have create and write access to the storage buckets created in Step 1.

+

If you are using AWS S3 and your Kubernetes nodes are configured with appropriate IAM API keys via InstanceRoles, you do not need to create API credentials. Do, however, validate that the InstanceRole has appropriate permissions to the configured buckets!

+

Step 3: Configure Workflow Chart

+

Operators should configure object storage by editing the Helm values file before running helm install. To do so:

+
    +
  • Fetch the Helm values by running helm inspect values oci://registry.drycc.cc/charts/workflow > values.yaml
  • +
  • Update the global/storage parameter to reference the platform you are using, e.g. s3, azure, gcs, or swift
  • +
  • Find the corresponding section for your storage type and provide appropriate values including region, bucket names, and access credentials.
  • +
  • Save your changes.
  • +
+

!!! note +All values will be automatically (base64) encoded except the key_json values under gcs/gcr. These must be base64-encoded. This is to support cleanly passing said encoded text via helm --set cli functionality rather than attempting to pass the raw JSON data. For example:

+
	$ helm install drycc oci://registry.drycc.cc/charts/workflow \
+	    --namespace drycc \
+		--set global.platformDomain=youdomain.com
+		--set global.storage=gcs,gcs.key_json="$(cat /path/to/gcs_creds.json | base64 -w 0)"
+
+

You are now ready to run helm install drycc oci://registry.drycc.cc/charts/workflow --namespace drycc -f values.yaml using your desired object storage.

+ +
+ + + + + + + + + + + +
+ +

3.5 - Configuring Postgres

+
Drycc Workflow’s controller and passport component rely on a PostgreSQL database to store platform state.
+

Configuring Postgres

+

By default, Drycc Workflow ships with the database component, which provides an in-cluster PostgreSQL database backed up to in-cluster or off-cluster object storage. Currently, for object storage, which is utilized by several Workflow components, only off-cluster solutions such as S3 or GCS are recommended in production environments. Experience has shown that many operators already opting for off-cluster object storage similarly prefer to host Postgres off-cluster as well, using Amazon RDS or similar. When excercising both options, a Workflow installation becomes entirely stateless, and is thus restored or rebuilt with greater ease should the need ever arise.

+

Provisioning off-cluster Postgres

+

First, provision a PostgreSQL RDBMS using the cloud provider or other infrastructure of your choice. Take care to ensure that security groups or other firewall rules will permit connectivity from your Kubernetes worker nodes, any of which may play host to the Workflow controller component.

+

Take note of the following:

+
    +
  1. The hostname or public IP of your PostgreSQL RDBMS
  2. +
  3. The port on which your PostgreSQL RDBMS runs– typically 5432
  4. +
+

Within the off-cluster RDBMS, manually provision the following:

+
    +
  1. A database user (take note of the username and password)
  2. +
  3. A database owned by that user (take note of its name)
  4. +
+

If you are able to log into the RDBMS as a superuser or a user with appropriate permissions, this process will typically look like this:

+
$ psql -h <host> -p <port> -d postgres -U <"postgres" or your own username>
+> create user <drycc username; typically "drycc"> with password '<password>';
+> create database <database name; typically "drycc"> with owner <drycc username>;
+> \q
+

Configuring Workflow

+

The Helm chart for Drycc Workflow can be easily configured to connect the Workflow controller component to an off-cluster PostgreSQL database.

+
    +
  • Step 1: If you haven’t already fetched the values, do so with helm inspect values drycc/workflow > values.yaml
  • +
  • Step 2: Update database connection details by modifying values.yaml: +
      +
    • Update the databaseLocation parameter to off-cluster.
    • +
    • Update the values in the [database] configuration section to properly reflect all connection details.
    • +
    • Update the values in the [controller] configuration section to properly reflect platformDomain details.
    • +
    • Save your changes.
    • +
    • Note: you do not need to (and must not) base64 encode any values, as the Helm chart will automatically handle encoding as necessary.
    • +
    +
  • +
+

You are now ready to helm install drycc oci://registry.drycc.cc/charts/workflow --namespace drycc -f values.yaml as usual.

+ +
+ + + + + + + + + + + +
+ +

3.6 - Configuring Registry

+
Drycc Workflow’s builder component relies on a registry for storing application container images.
+

Drycc Workflow ships with a registry component by default, which provides an in-cluster Container registry backed by the platform-configured object storage. Operators might want to use an off-cluster registry for performance or security reasons.

+

Configuring Off-Cluster Private Registry

+

Every component that relies on a registry uses two inputs for configuration:

+
    +
  1. Registry Location environment variable named DRYCC_REGISTRY_LOCATION
  2. +
  3. Access credentials stored as a Kubernetes secret named registry-secret
  4. +
+

The Helm chart for Drycc Workflow can be easily configured to connect Workflow components to off-cluster registry. Drycc Workflow supports external registries which provide either short-lived tokens that are valid only for a specified amount of time or long-lived tokens (basic username/password) which are valid forever for authenticating to them. For those registries which provide short lived tokens for authentication, Drycc Workflow will generate and refresh them such that the deployed apps will only have access to the short-lived tokens and not to the actual credentials for the registries.

+

When using a private registry the container images are no longer pulled by Drycc Workflow Controller but rather are managed by Kubernetes. This will increase security and overall speed, however the port information can no longer be discovered. Instead the port information can be set via drycc config:set PORT=<port> prior to deploying the application.

+

Drycc Workflow currently supports:

+
    +
  1. off-cluster: Any provider which supports long-lived username/password authentication, such as Azure Container Registry, Docker Hub, quay.io, or a self-hosted Container registry.
  2. +
+

Configuration

+
    +
  1. If you haven’t already fetched the values file, do so with helm inspect values drycc/workflow > values.yaml
  2. +
  3. Update registry location details by modifying the values file: +* Update the registryLocation parameter to reference the registry location you are using: off-cluster, ecr, gcr +* Update the values in the section which corresponds to your registry location type.
  4. +
+

You are now ready to helm install drycc oci://registry.drycc.cc/charts/workflow --namespace drycc -f values.yaml using your desired registry.

+

Examples

+

Here we show how the relevant parts of the fetched values.yaml file might look like after configuring for a particular off-cluster registry:

+

Azure Container Registry (ACR)

+

After following the docs and creating a registry, e.g. myregistry, with its corresponding login server of myregistry.azurecr.io, the following values should be supplied:

+
global:
+...
+  registryLocation: "off-cluster"
+...
+registry-token-refresher:
+...
+  registry:
+    hostname: "myregistry.azurecr.io"
+    organization: "myorg"
+    username: "myusername"
+    password: "mypassword"
+...
+

Note: The mandatory organization field (here myorg) will be created as an ACR repository if it does not already exist.

+

Quay.io

+
global:
+...
+  registryLocation: "off-cluster"
+...
+registry-token-refresher:
+...
+  registry:
+    hostname: "quay.io"
+    organization: "myorg"
+    username: "myusername"
+    password: "mypassword"
+...
+
+
+ + + + + + + + + + + + + + + +
+ +

4 - Users

+
In this tutorial, you’ll learn how to manage users.
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +

4.1 - Drycc Workflow CLI

+
How to download, install, and start using the Drycc CLI. The Drycc CLI used to be part of the Drycc Toolbelt.
+

The Drycc Workflow command-line interface (CLI), or client, allows you to interact +with Drycc Workflow.

+

Installation

+

Install the latest drycc client for Linux or Mac OS X with: +$ curl -sfL https://www.drycc.cc/install-cli.sh | bash -

+

The installer puts drycc in your current directory, but you should move it +somewhere in your $PATH:

+
$ ln -fs $PWD/drycc /usr/local/bin/drycc
+
+

Getting Help

+

The Drycc client comes with comprehensive documentation for every command. +Use drycc help to explore the commands available to you:

+
$ drycc help
+The Drycc command-line client issues API calls to a Drycc controller.
+
+Usage: drycc <command> [<args>...]
+
+Auth commands::
+
+  login         login to a controller
+  logout        logout from the current controller
+
+Subcommands, use `drycc help [subcommand]` to learn more::
+...
+
+

To get help on subcommands, use drycc help [subcommand]:

+
$ drycc help apps
+Valid commands for apps:
+
+apps:create        create a new application
+apps:list          list accessible applications
+apps:info          view info about an application
+apps:open          open the application in a browser
+apps:logs          view aggregated application logs
+apps:run           run a command in an ephemeral app container
+apps:destroy       destroy an application
+apps:transfer      transfer app ownership to another user
+
+Use `drycc help [command]` to learn more
+
+

Support for Multiple Profiles

+

The CLI reads from the default client profile, which is located on your +workstation at $HOME/.drycc/client.json.

+

Easily switch between multiple Drycc Workflow installations or users by setting +the $DRYCC_PROFILE environment variable or by using the -c flag.

+

There are two ways to set the $DRYCC_PROFILE option.

+
    +
  1. Path to a json configuration file.
  2. +
  3. Profile name. If you set profile to just a name, it will be saved alongside the default profile, +in $HOME/.drycc/<name>.json.
  4. +
+

Examples:

+
$ DRYCC_PROFILE=production drycc login drycc.production.com
+...
+Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71
+Waiting for login... .o.Logged in as drycc
+Configuration saved to /home/testuser/.drycc/production.json
+$ DRYCC_PROFILE=~/config.json drycc login drycc.example.com
+...
+Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71
+Waiting for login... .o.Logged in as drycc
+Configuration saved to /home/testuser/config.json
+
+

The configuration flag works identically to and overrides $DRYCC_PROFILE:

+
$ drycc whoami -c ~/config.json
+You are drycc at drycc.example.com
+
+

Proxy Support

+

If your workstation uses a proxy to reach the network where the cluster lies, +set the http_proxy or https_proxy environment variable to enable proxy support:

+
$ export http_proxy="http://proxyip:port"
+$ export https_proxy="http://proxyip:port"
+
+

!!! note +Configuring a proxy is generally not necessary for local Minikube clusters.

+

CLI Plugins

+

Plugins allow developers to extend the functionality of the Drycc Client, adding new commands or features.

+

If an unknown command is specified, the client will attempt to execute the command as a dash-separated command. In this case, drycc resource:command will execute drycc-resource with the argument list command. In full form:

+
$ # these two are identical
+$ drycc accounts:list
+$ drycc-accounts list
+
+

Any flags after the command will also be sent to the plugin as an argument:

+
$ # these two are identical
+$ drycc accounts:list --debug
+$ drycc-accounts list --debug
+
+

But flags preceding the command will not:

+
$ # these two are identical
+$ drycc --debug accounts:list
+$ drycc-accounts list
+
+ +
+ + + + + + + + + + + +
+ +

4.2 - Users and Registration

+
Get started on Drycc today
+

Workflow use the passport component to create and authorize users, it can config options for LDAP authentication or browse passport web site to register users.

+

Login to Workflow

+

If you already have an account, use drycc login to authenticate against the Drycc Workflow API.

+
$ drycc login http://drycc.example.com
+Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71
+Waiting for login... .o.Logged in as drycc
+Configuration file written to /root/.drycc/client.json
+
+

Or you can login with username and password +$ drycc login http://drycc.example.com –username=demo –password=demo +Configuration file written to /root/.drycc/client.json

+

Logout from Workflow

+

Logout of an existing controller session using drycc logout.

+
$ drycc logout
+Logged out as drycc
+
+

Verify Your Session

+

You can verify your client configuration by running drycc whoami.

+
$ drycc whoami
+You are drycc at http://drycc.example.com
+
+

!!! note +Session and client configuration is stored in the ~/.drycc/client.json file.

+ +
+ + + + + + + + + + + +
+ +

4.3 - Users and SSH Keys

+
Create, manage, and upload SSH keys to Drycc for use in deploying and connecting to applications.
+

For Dockerfile and Buildpack based application deploys via git push, Drycc Workflow identifies users via SSH +keys. SSH keys are pushed to the platform and must be unique to each user. Users may have multiple SSH keys as needed.

+

Generate an SSH Key

+

If you do not already have an SSH key or would like to create a new key for Drycc Workflow, generate a new key using +ssh-keygen:

+
$ ssh-keygen -f ~/.ssh/id_drycc -t rsa
+Generating public/private rsa key pair.
+Enter passphrase (empty for no passphrase):
+Enter same passphrase again:
+Your identification has been saved in /Users/admin/.ssh/id_drycc.
+Your public key has been saved in /Users/admin/.ssh/id_drycc.pub.
+The key fingerprint is:
+3d:ac:1f:f4:83:f7:64:51:c1:7e:7f:80:b6:70:36:c9 admin@plinth-23437.local
+The key's randomart image is:
++--[ RSA 2048]----+
+|              .. |
+|               ..|
+|           . o. .|
+|         o. E .o.|
+|        S == o..o|
+|         o +.  .o|
+|        . o + o .|
+|         . o =   |
+|          .   .  |
++-----------------+
+$ ssh-add ~/.ssh/id_drycc
+Identity added: /Users/admin/.ssh/id_drycc (/Users/admin/.ssh/id_drycc)
+

Adding and Removing SSH Keys

+

By publishing the public half of your SSH key to Drycc Workflow the component responsible for receiving git push +will be able to authenticate the user and ensure that they have access to the destination application.

+
$ drycc keys:add ~/.ssh/id_drycc.pub
+Uploading id_drycc.pub to drycc... done
+

You can always view the keys associated with your user as well:

+
$ drycc keys:list
+ID                              OWNER    KEY                           
+admin@plinth-23437.local        admin    ssh-rsa abc AAAAB3Nz...3437.local
+admin@subgenius.local           admin    ssh-rsa 123 AAAAB3Nz...nius.local
+

Remove keys by their name:

+
$ drycc keys:remove admin@plinth-23437.local
+Removing admin@plinth-23437.local SSH Key... don
+
+
+ + + + + + + + + + + + + + + +
+ +

5 - Applications

+
A simple and scalable cloud platform for all developer needs.
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +

5.1 - Deploying an Application

+
Learn how to deploy the application to drycc.
+

An Application is deployed to Drycc using git push or the drycc client.

+

Supported Applications

+

Drycc Workflow can deploy any application or service that can run inside a container. In order to be scaled +horizontally, applications must follow the Twelve-Factor App methodology and store any application state in external +backing services.

+

For example, if your application persists state to the local filesystem – common with content management systems like +Wordpress and Drupal – it cannot be scaled horizontally using drycc scale.

+

Fortunately, most modern applications feature a stateless application tier that can scale horizontally inside Drycc.

+

Login to the Controller

+

!!! important +if you haven’t yet, now is a good time to install the client and register.

+

Before deploying an application, users must first authenticate against the Drycc Controller +using the URL supplied by their Drycc administrator.

+
$ drycc login http://drycc.example.com
+Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71
+Waiting for login... .o.Logged in as admin
+Configuration file written to /root/.drycc/client.json
+

Or you can login with username and password

+
$ drycc login http://drycc.example.com --username=demo --password=demo
+Configuration file written to /root/.drycc/client.json
+

Select a Build Process

+

Drycc Workflow supports three different ways of building applications:

+

Buildpacks

+

Cloud Native Buildpacks are useful if you want to follow cnb’s docs for building applications.

+

Learn how to deploy applications using Buildpacks.

+

Dockerfiles

+

Dockerfiles are a powerful way to define a portable execution environment built on a base OS of your choosing.

+

Learn how to deploy applications using Dockerfiles.

+

Container Image

+

Deploying a Container image onto Drycc allows you to take a Container image from either a public +or a private registry and copy it over bit-for-bit, ensuring that you are running the same +image in development or in your CI pipeline as you are in production.

+

Learn how to deploy applications using Container images.

+

Tuning Application Settings

+

It is possible to configure a few of the globally tunable settings on per application basis using config:set.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SettingDescription
DRYCC_DISABLE_CACHEif set, this will disable the [imagebuilder cache][] (default: not set)
DRYCC_DEPLOY_BATCHESthe number of pods to bring up and take down sequentially during a scale (default: number of available nodes)
DRYCC_DEPLOY_TIMEOUTdeploy timeout in seconds per deploy batch (default: 120)
IMAGE_PULL_POLICYthe kubernetes [image pull policy][pull-policy] for application images (default: “IfNotPresent”) (allowed values: “Always”, “IfNotPresent”)
KUBERNETES_DEPLOYMENTS_REVISION_HISTORY_LIMIThow many revisions Kubernetes keeps around of a given Deployment (default: all revisions)
KUBERNETES_POD_TERMINATION_GRACE_PERIOD_SECONDShow many seconds kubernetes waits for a pod to finish work after a SIGTERM before sending SIGKILL (default: 30)
+

Deploy Timeout

+

Deploy timeout in seconds - There are 2 deploy methods, Deployments (see below) and RC (versions prior to 2.4) and this setting affects those a bit differently.

+

Deployments

+

Deployments behave a little bit differently from the RC based deployment strategy.

+

Kubernetes takes care of the entire deploy, doing rolling updates in the background. As a result, there is only an overall deployment timeout instead of a configurable per-batch timeout.

+

The base timeout is multiplied with DRYCC_DEPLOY_BATCHES to create an overall timeout. This would be 240 (timeout) * 4 (batches) = 960 second overall timeout.

+

RC deploy

+

This deploy timeout defines how long to wait for each batch to complete in DRYCC_DEPLOY_BATCHES.

+

Additions to the base timeout

+

The base timeout is extended as well with healthchecks using initialDelaySeconds on liveness and readiness where the bigger of those two is applied. +Additionally the timeout system accounts for slow image pulls by adding an additional 10 minutes when it has seen an image pull take over 1 minute. This allows the timeout values to be reasonable without having to account for image pull slowness in the base deploy timeout.

+

Deployments

+

Workflow uses Deployments for deploys. In prior versions ReplicationControllers were used with the ability to turn on Deployments via DRYCC_KUBERNETES_DEPLOYMENTS=1.

+

The advantage of Deployments is that rolling-updates will happen server-side in Kubernetes instead of in Drycc Workflow Controller, +along with a few other Pod management related functionality. This allows a deploy to continue even when the CLI connection is interrupted.

+

Behind the scenes your application deploy will be built up of a Deployment object per process type, +each having multiple ReplicaSets (one per release) which in turn manage the Pods running your application.

+

Drycc Workflow will behave the same way with DRYCC_KUBERNETES_DEPLOYMENTS enabled or disabled (only applicable to versions prior to 2.4). +The changes are behind the scenes. Where you will see differences while using the CLI is drycc ps:list will output Pod names differently.

+ +
+ + + + + + + + + + + +
+ +

5.2 - Using Buildpacks

+
An overview of buildpacks, which are responsible for transforming deployed code into a slug, which can then be executed on a container.
+

Drycc supports deploying applications via Cloud Native Buildpacks. Cloud Native Buildpacks are useful if you want to follow cnb’s docs for building applications.

+

Add SSH Key

+

For Buildpack based application deploys via git push, Drycc Workflow identifies users via SSH keys. SSH keys are pushed to the platform and must be unique to each user.

+
    +
  • +

    See this document for instructions on how to generate an SSH key.

    +
  • +
  • +

    Run drycc keys:add to upload your SSH key to Drycc Workflow.

    +
  • +
+
$ drycc keys:add ~/.ssh/id_drycc.pub
+Uploading id_drycc.pub to drycc... done
+

Read more about adding/removing SSH Keys here.

+

Prepare an Application

+

If you do not have an existing application, you can clone an example application that demonstrates the Heroku Buildpack workflow.

+
$ git clone https://github.com/drycc/example-go.git
+$ cd example-go
+
+

Create an Application

+

Use drycc create to create an application on the Controller.

+
$ drycc create
+Creating application... done, created skiing-keypunch
+Git remote drycc added
+
+

Push to Deploy

+

Use git push drycc master to deploy your application.

+
$ git push drycc master
+Counting objects: 75, done.
+Delta compression using up to 8 threads.
+Compressing objects: 100% (48/48), done.
+Writing objects: 100% (75/75), 18.28 KiB | 0 bytes/s, done.
+Total 75 (delta 30), reused 58 (delta 22)
+remote: --->
+Starting build... but first, coffee!
+---> Waiting podman running.
+---> Process podman started.
+---> Waiting caddy running.
+---> Process caddy started.
+---> Building pack
+---> Using builder registry.drycc.cc/drycc/buildpacks:bookworm
+Builder 'registry.drycc.cc/drycc/buildpacks:bookworm' is trusted
+Pulling image 'registry.drycc.cc/drycc/buildpacks:bookworm'
+Resolving "drycc/buildpacks" using unqualified-search registries (/etc/containers/registries.conf)
+Trying to pull registry.drycc.cc/drycc/buildpacks:bookworm...
+Getting image source signatures
+...
+---> Skip generate base layer
+---> Python Buildpack
+---> Downloading and extracting Python 3.10.0
+---> Installing requirements with pip
+Collecting Django==3.2.8
+Downloading Django-3.2.8-py3-none-any.whl (7.9 MB)
+Collecting gunicorn==20.1.0
+Downloading gunicorn-20.1.0-py3-none-any.whl (79 kB)
+Collecting sqlparse>=0.2.2
+Downloading sqlparse-0.4.2-py3-none-any.whl (42 kB)
+Collecting pytz
+Downloading pytz-2021.3-py2.py3-none-any.whl (503 kB)
+Collecting asgiref<4,>=3.3.2
+Downloading asgiref-3.4.1-py3-none-any.whl (25 kB)
+Requirement already satisfied: setuptools>=3.0 in /layers/drycc_python/python/lib/python3.10/site-packages (from gunicorn==20.1.0->-r requirements.txt (line 2)) (57.5.0)
+Installing collected packages: sqlparse, pytz, asgiref, gunicorn, Django
+Successfully installed Django-3.2.8 asgiref-3.4.1 gunicorn-20.1.0 pytz-2021.3 sqlparse-0.4.2
+---> Generate Launcher
+...
+Build complete.
+Launching App...
+...
+Done, skiing-keypunch:v2 deployed to Workflow
+
+Use 'drycc open' to view this application in your browser
+
+To learn more, use 'drycc help' or visit https://www.drycc.cc
+
+To ssh://git@drycc.staging-2.drycc.cc:2222/skiing-keypunch.git
+ * [new branch]      master -> master
+
+$ curl -s http://skiing-keypunch.example.com
+Powered by Drycc
+Release v2 on skiing-keypunch-v2-web-02zb9
+
+

Because a Buildpacks-style application is detected, the web process type is automatically scaled to 1 on first deploy.

+

Use drycc scale web=3 to increase web processes to 3, for example. Scaling a +process type directly changes the number of pods running that process.

+

Included Buildpacks

+

For convenience, a number of buildpacks come bundled with Drycc:

+ +

Drycc will cycle through the bin/detect script of each buildpack to match the code you +are pushing.

+

!!! note +If you’re testing against the [Scala Buildpack][], the Builder requires at least +512MB of free memory to execute the Scala Build Tool.

+

Using a Custom Buildpack

+

To use a custom buildpack, you need create a .pack_builder file in your root path app.

+
$  tee > .pack_builder << EOF
+   > registry.drycc.cc/drycc/buildpacks:bookworm
+   > EOF
+
+

On your next git push, the custom buildpack will be used.

+

Using Private Repositories

+

To pull code from private repositories, set the SSH_KEY environment variable to a private key +which has access. Use either the path of a private key file or the raw key material:

+
$ drycc config:set SSH_KEY=/home/user/.ssh/id_rsa
+$ drycc config:set SSH_KEY="""-----BEGIN RSA PRIVATE KEY-----
+(...)
+-----END RSA PRIVATE KEY-----"""
+
+

For example, to use a custom buildpack hosted at a private GitHub URL, ensure that an SSH public +key exists in your GitHub settings. Then set SSH_KEY to the corresponding SSH private key +and set .pack_builder to the builder image:

+
$  tee > .pack_builder << EOF
+   > registry.drycc.cc/drycc/buildpacks:bookworm
+   > EOF
+$ git add .buildpack
+$ git commit -m "chore(buildpack): modify the pack_builder"
+$ git push drycc master
+
+

Builder selector

+

Which way to build a project conforms to the following principles:

+
    +
  • If Dockerfile exists in the project, the stack uses container
  • +
  • If Procfile exists in the project, the stack uses buildpack
  • +
  • If both exist, container is used by default
  • +
  • You can also set the DRYCC_STACK to container or buildpack determine which stack to use.
  • +
+ +
+ + + + + + + + + + + +
+ +

5.3 - Using Dockerfiles

+
Drycc Container Registry allows you to deploy your Docker-based app to Drycc. Both Common Runtime and Private Spaces are supported.
+

Drycc supports deploying applications via Dockerfiles. A Dockerfile automates the steps for crafting a [Container Image][]. +Dockerfiles are incredibly powerful but require some extra work to define your exact application runtime environment.

+

Add SSH Key

+

For Dockerfile based application deploys via git push, Drycc Workflow identifies users via SSH keys. SSH keys are pushed to the platform and must be unique to each user.

+
    +
  • +

    See this document for instructions on how to generate an SSH key.

    +
  • +
  • +

    Run drycc keys:add to upload your SSH key to Drycc Workflow.

    +
  • +
+
$ drycc keys:add ~/.ssh/id_drycc.pub
+Uploading id_drycc.pub to drycc... done
+

Read more about adding/removing SSH Keys here.

+

Prepare an Application

+

If you do not have an existing application, you can clone an example application that demonstrates the Dockerfile workflow.

+
$ git clone https://github.com/drycc/helloworld.git
+$ cd helloworld
+
+

Dockerfile Requirements

+

In order to deploy Dockerfile applications, they must conform to the following requirements:

+
    +
  • The Dockerfile must use the EXPOSE directive to expose exactly one port.
  • +
  • That port must be listening for an HTTP connection.
  • +
  • The Dockerfile must use the CMD directive to define the default process that will run within the container.
  • +
  • The Container image must contain bash to run processes.
  • +
+

!!! note +Note that if you are using a private registry of any kind (gcr or other) the application environment must include a $PORT config variable that matches the EXPOSE’d port, example: drycc config:set PORT=5000. See Configuring Registry for more info.

+

Create an Application

+

Use drycc create to create an application on the Controller.

+
$ drycc create
+Creating application... done, created folksy-offshoot
+Git remote drycc added
+
+

Push to Deploy

+

Use git push drycc master to deploy your application.

+
$ git push drycc master
+Counting objects: 13, done.
+Delta compression using up to 8 threads.
+Compressing objects: 100% (13/13), done.
+Writing objects: 100% (13/13), 1.99 KiB | 0 bytes/s, done.
+Total 13 (delta 2), reused 0 (delta 0)
+-----> Building Docker image
+Uploading context 4.096 kB
+Uploading context
+Step 0 : FROM drycc/base:latest
+ ---> 60024338bc63
+Step 1 : RUN wget -O /tmp/go1.2.1.linux-amd64.tar.gz -q https://go.googlecode.com/files/go1.2.1.linux-amd64.tar.gz
+ ---> Using cache
+ ---> cf9ef8c5caa7
+Step 2 : RUN tar -C /usr/local -xzf /tmp/go1.2.1.linux-amd64.tar.gz
+ ---> Using cache
+ ---> 515b1faf3bd8
+Step 3 : RUN mkdir -p /go
+ ---> Using cache
+ ---> ebf4927a00e9
+Step 4 : ENV GOPATH /go
+ ---> Using cache
+ ---> c6a276eded37
+Step 5 : ENV PATH /usr/local/go/bin:/go/bin:$PATH
+ ---> Using cache
+ ---> 2ba6f6c9f108
+Step 6 : ADD . /go/src/github.com/drycc/helloworld
+ ---> 94ab7f4b977b
+Removing intermediate container 171b7d9fdb34
+Step 7 : RUN cd /go/src/github.com/drycc/helloworld && go install -v .
+ ---> Running in 0c8fbb2d2812
+github.com/drycc/helloworld
+ ---> 13b5af931393
+Removing intermediate container 0c8fbb2d2812
+Step 8 : ENV PORT 80
+ ---> Running in 9b07da36a272
+ ---> 2dce83167874
+Removing intermediate container 9b07da36a272
+Step 9 : CMD ["/go/bin/helloworld"]
+ ---> Running in f7b215199940
+ ---> b1e55ce5195a
+Removing intermediate container f7b215199940
+Step 10 : EXPOSE 80
+ ---> Running in 7eb8ec45dcb0
+ ---> ea1a8cc93ca3
+Removing intermediate container 7eb8ec45dcb0
+Successfully built ea1a8cc93ca3
+-----> Pushing image to private registry
+
+       Launching... done, v2
+
+-----> folksy-offshoot deployed to Drycc
+       http://folksy-offshoot.local3.dryccapp.com
+
+       To learn more, use `drycc help` or visit https://www.drycc.cc
+
+To ssh://git@local3.dryccapp.com:2222/folksy-offshoot.git
+ * [new branch]      master -> master
+
+$ curl -s http://folksy-offshoot.local3.dryccapp.com
+Welcome to Drycc!
+See the documentation at http://docs.drycc.cc/ for more information.
+
+

Because a Dockerfile application is detected, the web process type is automatically scaled to 1 on first deploy.

+

Use drycc scale web=3 to increase web processes to 3, for example. Scaling a +process type directly changes the number of containers +running that process.

+

Container Build Arguments

+

As of Workflow v2.13.0, users can inject their application config into the Container image using +Container build arguments. To opt into this, users must add a new environment variable +to their application:

+
$ drycc config:set DRYCC_DOCKER_BUILD_ARGS_ENABLED=1
+

Every environment variable set with drycc config:set will then be available for use inside the +user’s Dockerfile. For example, if a user runs drycc config:set POWERED_BY=Workflow, +the user can utilize that build argument in their Dockerfile:

+
ARG POWERED_BY
+RUN echo "Powered by $POWERED_BY" > /etc/motd
+
+
+ + + + + + + + + + + +
+ +

5.4 - Using Docker Images

+
Deploy an application using a container image stored in your Drycc Container Registry.
+

Drycc supports deploying applications via an existing Docker Image. +This is useful for integrating Drycc into Docker-based CI/CD pipelines.

+

Prepare an Application

+

Start by cloning an example application:

+
$ git clone https://github.com/drycc/example-dockerfile-http.git
+$ cd example-dockerfile-http
+
+

Next use your local docker client to build the image and push +it to DockerHub.

+
$ docker build -t <username>/example-dockerfile-http .
+$ docker push <username>/example-dockerfile-http
+
+

Docker Image Requirements

+

In order to deploy Docker images, they must conform to the following requirements:

+
    +
  • The Dockerfile must use the EXPOSE directive to expose exactly one port.
  • +
  • That port must be listening for an HTTP connection.
  • +
  • The Dockerfile must use the CMD directive to define the default process that will run within the container.
  • +
  • The Docker image must contain bash to run processes.
  • +
+

!!! note +Note that if you are using a private registry of any kind (gcr or other) the application environment must include a $PORT config variable that matches the EXPOSE’d port, example: drycc config:set PORT=5000. See Configuring Registry for more info.

+

Create an Application

+

Use drycc create to create an application on the controller.

+
$ mkdir -p /tmp/example-dockerfile-http && cd /tmp/example-dockerfile-http
+$ drycc create example-dockerfile-http --no-remote
+Creating application... done, created example-dockerfile-http
+
+

!!! note +For all commands except for drycc create, the drycc client uses the name of the current directory +as the app name if you don’t specify it explicitly with --app.

+

Deploy the Application

+

Use drycc pull to deploy your application from DockerHub or +a public registry.

+
$ drycc pull <username>/example-dockerfile-http:latest
+Creating build...  done, v2
+
+$ curl -s http://example-dockerfile-http.local3.dryccapp.com
+Powered by Drycc
+
+

Because you are deploying a Docker image, the web process type is automatically scaled to 1 on first deploy.

+

Use drycc scale web=3 to increase web processes to 3, for example. Scaling a +process type directly changes the number of Containers +running that process.

+

Private Registry

+

To deploy Docker images from a private registry or from a private repository, use drycc registry +to attach credentials to your application. These credentials are the same as you’d use when running +docker login at your private registry.

+

To deploy private Docker images, take the following steps:

+
    +
  • Gather the username and password for the registry, such as a Quay.io Robot Account or a GCR.io Long Lived Token
  • +
  • Run drycc registry:set username=<the-user> password=<secret> -a <application-name>
  • +
  • Now perform drycc pull as normal, against an image in the private registry
  • +
+

When using a GCR.io Long Lived Token, the JSON blob will have to be compacted first using a +tool like jq and then used in the password field in drycc registry:set. For the username, use +_json_key. For example:

+
drycc registry:set username=_json_key password="$(cat google_cloud_cred.json | jq -c .)"
+

When using a private registry the docker images are no longer pulled into the Drycc Internal Registry via +the Drycc Workflow Controller but rather is managed by Kubernetes. This will increase security and overall speed, +however the application port information can no longer be discovered. Instead the application port information can be set via +drycc config:set PORT=80 prior to setting the registry information.

+

!!! note +Currently GCR.io and ECR in short lived auth token mode are not supported.

+ +
+ + + + + + + + + + + +
+ +

5.5 - Managing Application Processes

+
A Procfile is a list of process types in an app. Each process type declares a command that is executed when a container of that process type is started.
+

Drycc Workflow manages your application as a set of processes that can be named, scaled and configured according to their +role. This gives you the flexibility to easily manage the different facets of your application. For example, you may have +web-facing processes that handle HTTP traffic, background worker processes that do async work, and a helper process that +streams from the Twitter API.

+

By using a Procfile, either checked in to your application or provided via the CLI you can specify the name of the type +and the application command that should run. To spawn other process types, use drycc scale <ptype>=<n> to scale those +types accordingly.

+

Default Process Types

+

In the absence of a Procfile, a single, default process type is assumed for each application.

+

Applications built using Buildpacks via git push implicitly receive a web process type, which starts +the application server. Rails 4, for example, has the following process type:

+
web: bundle exec rails server -p $PORT
+
+

All applications utilizing Dockerfiles have an implied web process type, which runs the +Dockerfile’s CMD directive unmodified:

+
$ cat Dockerfile
+FROM centos:latest
+COPY . /app
+WORKDIR /app
+CMD python -m SimpleHTTPServer 5000
+EXPOSE 5000
+
+

For the above Dockerfile-based application, the web process type would run the Container CMD of python -m SimpleHTTPServer 5000.

+

Applications utilizing remote Container images, a web process type is also implied, and runs the CMD +specified in the Container image.

+

!!! note +The web process type is special as they’is the default process type that will +receive HTTP traffic from Workflow’s routers. Other process types can be named arbitrarily.

+

Declaring Process Types

+

If you use Buildpack or Dockerfile builds and want to override or specify additional process +types, simply include a file named Procfile in the root of your application’s source tree.

+

The format of a Procfile is one process type per line, with each line containing the command to invoke:

+
<process type>: <command>
+
+

The syntax is defined as:

+
    +
  • <process type> – a lowercase alphanumeric string, is a name for your command, such as web, worker, urgentworker, clock, etc.
  • +
  • <command> – a command line to launch the process, such as rake jobs:work.
  • +
+

This example Procfile specifies two types, web and sleeper. The web process launches a web server on port 5000 and +a simple process which sleeps for 900 seconds and exits.

+
$ cat Procfile
+web: bundle exec ruby web.rb -p ${PORT:-5000}
+sleeper: sleep 900
+

If you are using remote Container images, you may define process types by either running drycc pull with a +Procfile in your working directory, or by passing a stringified Procfile to the --procfile CLI option.

+

For example, passing process types inline:

+
$ drycc pull drycc/example-go:latest --procfile="web: /app/bin/boot"
+

Read a Procfile in another directory:

+
$ drycc pull drycc/example-go:latest --procfile="$(cat deploy/Procfile)"
+

Or via a Procfile located in your current, working directory:

+
$ cat Procfile
+web: /bin/boot
+sleeper: echo "sleeping"; sleep 900
+
+
+$ drycc pull -a steely-mainsail drycc/example-go
+Creating build... done
+
+$ drycc scale sleeper=1 -a steely-mainsail
+Scaling processes... but first, coffee!
+done in 0s
+
+NAME                                        RELEASE    STATE    PTYPE      READY    RESTARTS     STARTED
+steely-mainsail-sleeper-76c45b967c-4qm6w    v3         up       sleeper    1/1      0            2023-12-08T02:25:00UTC
+steely-mainsail-web-c4f44c4b4-7p7dh         v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+

!!! note +Only process types of web will be scaled to 1 automatically. If you have additional process types +remember to scale the process counts after creation.

+

To remove a process type simply scale it to 0:

+
$ drycc scale sleeper=0 -a steely-mainsail
+Scaling processes... but first, coffee!
+done in 3s
+
+NAME                                        RELEASE    STATE    PTYPE      READY    RESTARTS     STARTED
+steely-mainsail-web-c4f44c4b4-7p7dh         v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+

Scaling Processes

+

Applications deployed on Drycc Workflow scale out via the process model. Use drycc scale to control the number of +containers that power your app.

+
$ drycc scale web=5 -a iciest-waggoner
+Scaling processes... but first, coffee!
+done in 3s
+
+NAME                                        RELEASE    STATE    PTYPE      READY    RESTARTS     STARTED
+iciest-waggoner-web-c4f44c4b4-7p7dh         v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+iciest-waggoner-web-c4f44c4b4-8p7dh         v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+iciest-waggoner-web-c4f44c4b4-9p7dh         v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+iciest-waggoner-web-c4f44c4b4-1p7dh         v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+iciest-waggoner-web-c4f44c4b4-2p7dh         v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+

If you have multiple process types for your application you may scale the process count for each type separately. For +example, this allows you to manage web process independently from background workers. For more information on process +types see our documentation for Managing App Processes.

+

In this example, we are scaling the process type web to 5 but leaving the process type background with one worker.

+
$ drycc scale web=5
+Scaling processes... but first, coffee!
+done in 4s
+
+NAME                                                RELEASE    STATE    PTYPE      READY    RESTARTS     STARTED
+scenic-icehouse-web-3291896318-7lord                v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-jn957                v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-rsekj                v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-vwhnh                v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-vokg7                v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-vokg7                v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-background-3291896318-yf8kh         v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+

Scaling a process down, by reducing the process count, sends a TERM signal to the processes, followed by a SIGKILL +if they have not exited within 30 seconds. Depending on your application, scaling down may interrupt long-running HTTP +client connections.

+

For example, scaling from 5 processes to 3:

+
$ drycc scale web=3
+Scaling processes... but first, coffee!
+done in 1s
+
+NAME                                                RELEASE    STATE    PTYPE     READY    RESTARTS     STARTED
+scenic-icehouse-web-3291896318-vwhnh                v2         up       web       1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-vokg7                v2         up       web       1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-vokg9                v2         up       web       1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-background-3291896318-yf8kh         v2         up       web       1/1      0            2023-12-08T02:25:00UTC
+

Autoscale

+

Autoscale allows adding a minimum and maximum number of pods on a per process type basis. This is accomplished by specifying a target CPU usage across all available pods.

+

This feature is built on top of Horizontal Pod Autoscaling in Kubernetes or HPA for short.

+

!!! note +This is an alpha feature. It is recommended to be on the latest Kubernetes when using this feature.

+
$ drycc autoscale:set web --min=3 --max=8 --cpu-percent=75
+Applying autoscale settings for process type web on scenic-icehouse... done
+

And then review the scaling rule that was created for web

+
$ drycc autoscale:list
+PTYPE    PERCENT    MIN    MAX
+web      75         3      8
+

Remove scaling rule

+
$ drycc autoscale:unset web
+Removing autoscale for process type web on scenic-icehouse... done
+

For autoscaling to work CPU requests have to be specified on each application Pod (can be done via drycc limits --cpu). This allows the autoscale policies to do the appropriate calculations and make decisions on when to scale up and down.

+

Scale up can only happen if there was no rescaling within the last 3 minutes. Scale down will wait for 5 minutes from the last rescaling. That information and more can be found at HPA algorithm page.

+

Fetch a container logs of the application

+

List the containers:

+
$ drycc ps
+NAME                                                RELEASE    STATE    PTYPEE     READY    RESTARTS     STARTED
+python-getting-started-web-69b7d4bfdc-kl4xf         v2         up       web        1/1      0             2023-12-08T02:25:00UTC
+
+=== python-getting-started Processes
+--- web:
+python-getting-started-web-69b7d4bfdc-kl4xf up (v2)
+

fetch the container logs:

+
$ drycc ps:logs -f python-getting-started-web-69b7d4bfdc-kl4xf
+[2024-05-24 07:14:39 +0000] [1] [INFO] Starting gunicorn 20.1.0
+[2024-05-24 07:14:39 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1)
+[2024-05-24 07:14:39 +0000] [1] [INFO] Using worker: gevent
+[2024-05-24 07:14:39 +0000] [8] [INFO] Booting worker with pid: 8
+[2024-05-24 07:14:39 +0000] [9] [INFO] Booting worker with pid: 9
+[2024-05-24 07:14:39 +0000] [10] [INFO] Booting worker with pid: 10
+[2024-05-24 07:14:39 +0000] [11] [INFO] Booting worker with pid: 11
+

Get a container info of the application

+

List the containers:

+
$ drycc ps:describe python-getting-started-web-69b7d4bfdc-kl4xf
+Container:        python-getting-started-web                   
+Image:            drycc/python-getting-started:latest          
+Command:          
+Args:             
+                  - gunicorn                                   
+                  - -c                                         
+                  - gunicorn_config.py                         
+                  - helloworld.wsgi:application                
+State:            running                                      
+  startedAt:      "2024-05-24T07:14:39Z"                       
+Ready:            true                                         
+Restart Count:    0                 
+

delete a container of the application

+

Delete the containers. +Due to the set number of replicas, a new container will be launched to meet the quantity requirement.

+
$ drycc ps:delete python-getting-started-web-69b7d4bfdc-kl4xf
+Deleting python-getting-started-web-69b7d4bfdc-kl4xf from python-getting-started... done
+

Get a Shell to a Running Container

+

Verify that the container is running:

+
$ drycc ps
+NAME                                                RELEASE    STATE    PTYPEE     READY    RESTARTS     STARTED
+python-getting-started-web-69b7d4bfdc-kl4xf         v2         up       web        1/1      0             2023-12-08T02:25:00UTC
+
+=== python-getting-started Processes
+--- web:
+python-getting-started-web-69b7d4bfdc-kl4xf up (v2)
+

Get a shell to the running container:

+
$ drycc ps:exec python-getting-started-web-69b7d4bfdc-kl4xf -it -- bash
+

In your shell, list the root directory:

+
# Run this inside the container
+ls /
+

Running individual commands in a container

+
$ drycc ps:exec python-getting-started-web-69b7d4bfdc-kl4xf -- date
+

Use “drycc ps –help” for a list of global command-line (applies to all commands).

+

Restarting an Application Processes

+

If you need to restart an application process, you may use drycc pts:restart. Behind the scenes, Drycc Workflow instructs +Kubernetes to terminate the old process and launch a new one in its place.

+
$ drycc ps
+NAME                                               RELEASE    STATE       PTYPE      READY    RESTARTS     STARTED
+scenic-icehouse-web-3291896318-vokg7               v2         up          web        1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-rsekj               v2         up          web        1/1      0            2023-12-08T02:50:21UTC
+scenic-icehouse-web-3291896318-vokg7               v2         up          web        1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-background-3291896318-yf8kh        v2         up          web        1/1      0            2023-12-08T02:25:00UTC
+
+$ drycc pts:restart scenic-icehouse-background
+NAME                                               RELEASE    STATE       PTYPE      READY    RESTARTS    STARTED
+scenic-icehouse-web-3291896318-vokg7               v2         up          web        1/1      0           2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-rsekj               v2         up          web        1/1      0           2023-12-08T02:50:21UTC
+scenic-icehouse-web-3291896318-vokg7               v2         up          web        1/1      0           2023-12-08T02:25:00UTC
+scenic-icehouse-background-3291896318-yf8kh        v2         starting    web        1/1      0           2023-12-08T02:25:00UTC
+

Notice that the process name has changed from scenic-icehouse-background-3291896318-yf8kh to +scenic-icehouse-background-3291896318-yd87g. In a multi-node Kubernetes cluster, this may also have the effect of scheduling +the Pod to a new node.

+

Use “drycc pts –help” for a list of pts command-line (process types info).

+

List an Application Process Types

+
$ drycc pts
+NAME          RELEASE    READY    UP-TO-DATE    AVAILABLE    STARTED                   
+web           v2         3/3      1             1            2023-12-08T02:25:00UTC    
+background    v2         1/1      1             1            2023-12-08T02:25:00UTC    
+

Get deployment info of the application process type

+
$ drycc pts:describe web
+Container:    python-getting-started-web                   
+Image:        drycc/python-getting-started:latest          
+Command:      
+Args:         
+              - gunicorn                                   
+              - -c                                         
+              - gunicorn_config.py                         
+              - helloworld.wsgi:application                
+Limits:       
+              cpu 1                                                                                               
+              ephemeral-storage 2Gi                                                                               
+              memory 1Gi                                                                                          
+Liveness:     http-get headers=[] path=/geo/ port=8000 delay=120s timeout=10s period=20s #success=1 #failure=3    
+Readiness:    http-get headers=[] path=/geo/ port=8000 delay=120s timeout=10s period=20s #success=1 #failure=3  
+
+
+ + + + + + + + + + + +
+ +

5.6 - Configuring an Application

+
How to store configuration of a Drycc app in the environment, keeping config out of code, making it easy to maintain app or deployment specific configs.
+

Configuring an Application

+

A Drycc application stores config in environment variables.

+

Setting Environment Variables

+

Use drycc config to modify environment variables for a deployed application.

+
$ drycc help config
+Valid commands for config:
+
+config:list        list environment variables for an app
+config:set         set environment variables for an app
+config:unset       unset environment variables for an app
+config:pull        extract environment variables to .env
+config:push        set environment variables from .env
+
+Use `drycc help [command]` to learn more.
+
+

When config is changed, a new release is created and deployed automatically.

+

You can set multiple environment variables with one drycc config:set command, +or with drycc config:push and a local .env file.

+
$ drycc config:set FOO=1 BAR=baz && drycc config:pull
+$ cat .env
+FOO=1
+BAR=baz
+$ echo "TIDE=high" >> .env
+$ drycc config:push
+Creating config... done, v4
+
+=== yuppie-earthman
+DRYCC_APP: yuppie-earthman
+FOO: 1
+BAR: baz
+TIDE: high
+
+

It can also modify environment variables for a process type of application.

+
$ drycc config:set FOO=1 BAR=baz --ptype=web
+
+

Attach to Backing Services

+

Drycc treats backing services like databases, caches and queues as attached resources. +Attachments are performed using environment variables.

+

For example, use drycc config to set a DATABASE_URL that attaches +the application to an external PostgreSQL database.

+
$ drycc config:set DATABASE_URL=postgres://user:pass@example.com:5432/db
+=== peachy-waxworks
+DATABASE_URL: postgres://user:pass@example.com:5432/db
+
+

Detachments can be performed with drycc config:unset.

+

Buildpacks Cache

+

By default, apps using the [Imagebuilder][] will reuse the latest image data. +When deploying applications that depend on third-party libraries that have to be fetched, +this could speed up deployments a lot. In order to make use of this, the buildpack must implement +the cache by writing to the cache directory. Most buildpacks already implement this, but when using +custom buildpacks, it might need to be changed to make full use of the cache.

+

Disabling and re-enabling the cache

+

In some cases, cache might not speed up your application. To disable caching, you can set the +DRYCC_DISABLE_CACHE variable with drycc config:set DRYCC_DISABLE_CACHE=1. When you disable the +cache, Drycc will clear up files it created to store the cache. After having it turned off, run +drycc config:unset DRYCC_DISABLE_CACHE to re-enable the cache.

+

Clearing the cache

+

Use the following procedure to clear the cache:

+
$ drycc config:set DRYCC_DISABLE_CACHE=1
+$ git commit --allow-empty -m "Clearing Drycc cache"
+$ git push drycc # (if you use a different remote, you should use your remote name)
+$ drycc config:unset DRYCC_DISABLE_CACHE
+
+

Custom Health Checks

+

By default, Workflow only checks that the application starts in their Container. If it is preferred +to have Kubernetes respond to application health, a health check may be added by configuring a +health check probe for the application.

+

The health checks are implemented as Kubernetes container probes. A liveness +and a readiness probe can be configured, and each probe can be of type httpGet, exec, or +tcpSocket depending on the type of probe the container requires.

+

A liveness probe is useful for applications running for long periods of time, eventually +transitioning to broken states and cannot recover except by restarting them.

+

Other times, a readiness probe is useful when the container is only temporarily unable to serve, +and will recover on its own. In this case, if a container fails its readiness probe, the container +will not be shut down, but rather the container will stop receiving incoming requests.

+

httpGet probes are just as it sounds: it performs a HTTP GET operation on the Container. A +response code inside the 200-399 range is considered a pass.

+

exec probes run a command inside the Container to determine its health, such as +cat /var/run/myapp.pid or a script that determines when the application is ready. An exit code of +zero is considered a pass, while a non-zero status code is considered a fail.

+

tcpSocket probes attempt to open a socket in the Container. The Container is only considered +healthy if the check can establish a connection. tcpSocket probes accept a port number to perform +the socket connection on the Container.

+

Health checks can be configured on a per-proctype basis for each application using drycc healthchecks:set. If no type is mentioned then the health checks are applied to default proc type web, whichever is present. To +configure a httpGet liveness probe:

+
$ drycc healthchecks:set liveness httpGet 80 --ptype web
+Applying livenessProbe healthcheck... done
+
+App:             peachy-waxworks
+UUID:            afd84067-29e9-4a5f-9f3a-60d91e938812
+Owner:           dev
+Created:         2023-12-08T10:25:00Z
+Updated:         2023-12-08T10:25:00Z
+Healthchecks:
+                 liveness web http-get headers=[] path=/ port=80 delay=50s timeout=50s period=10s #success=1 #failure=3
+

If the application relies on certain headers being set (such as the Host header) or a specific +URL path relative to the root, you can also send specific HTTP headers:

+
$ drycc healthchecks:set liveness httpGet 80 \
+    --path /welcome/index.html \
+    --headers "X-Client-Version:v1.0,X-Foo:bar"
+Applying livenessProbe healthcheck... done
+
+App:             peachy-waxworks
+UUID:            afd84067-29e9-4a5f-9f3a-60d91e938812
+Owner:           dev
+Created:         2023-12-08T10:25:00Z
+Updated:         2023-12-08T10:25:00Z
+Healthchecks:
+                 liveness web http-get headers=[X-Client-Version=v1.0] path=/welcome/index.html port=80 delay=50s timeout=50s period=10s #success=1 #failure=3
+

To configure an exec readiness probe:

+
$ drycc healthchecks:set readiness exec -- /bin/echo -n hello --ptype web
+Applying readinessProbe healthcheck... done
+
+App:             peachy-waxworks
+UUID:            afd84067-29e9-4a5f-9f3a-60d91e938812
+Owner:           dev
+Created:         2023-12-08T10:25:00Z
+Updated:         2023-12-08T10:25:00Z
+Healthchecks:
+                 readiness web exec /bin/echo -n hello delay=50s timeout=50s period=10s #success=1 #failure=3
+

You can overwrite a probe by running drycc healthchecks:set again:

+
$ drycc healthchecks:set readiness httpGet 80 --ptype web
+Applying livenessProbe healthcheck... done
+
+App:             peachy-waxworks
+UUID:            afd84067-29e9-4a5f-9f3a-60d91e938812
+Owner:           dev
+Created:         2023-12-08T10:25:00Z
+Updated:         2023-12-08T10:25:00Z
+Healthchecks:
+                 liveness web http-get headers=[] path=/ port=80 delay=50s timeout=50s period=10s #success=1 #failure=3
+

Configured health checks also modify the default application deploy behavior. When starting a new +Pod, Workflow will wait for the health check to pass before moving onto the next Pod.

+

Autodeploy

+

By default, Changes the config, limits or healthchecks and so on will trigger deploy. +If you don’t want deploy, you can disable.

+
$ drycc autodeploy:disable
+

To re-enable autodeploy.

+
drycc autodeploy:enable
+

you can deploy by executing the following command. +deploy all ptypes

+
drycc releases:deploy
+

deploy web process type, and support --force option to force deploy.

+
drycc releases:deploy web --force
+

Autorollback

+

By default, deployment failures will roll back to the previous successful version. +If you don’t want this to happen, you can disable.

+
$ drycc autorollback:disable
+

To re-enable autorollback.

+
drycc autorollback:enable
+

Isolate the Application

+

Workflow supports isolating applications onto a set of nodes using drycc tags.

+

!!! note +In order to use tags, you must first launch your cluster with the proper node labels. If you do +not, tag commands will fail. Learn more by reading “Assigning Pods to Nodes”.

+

Once your nodes are configured with appropriate label selectors, use drycc tags:set to restrict +the application ptype to those nodes:

+
$ drycc tags:set web environ=prod
+Applying tags...  done, v4
+
+environ  prod
+
+
+ + + + + + + + + + + +
+ +

5.7 - Managing Application Metrics

+
Metrics supports basic monitoring capabilities for Pod, providing various monitoring indicators such as CPU, memory, disk, network, etc., to meet the basic monitoring requirements for Pod resources.
+

Create an authentication token

+

Create an authentication token using the drycc client.

+
# drycc tokens:add prometheus --password admin --username admin
+ !    WARNING: Make sure to copy your token now.
+ !    You won't be able to see it again, please confirm whether to continue.
+ !    To proceed, type "yes" !
+
+> yes
+UUID                                  USERNAME    TOKEN                                                                                              
+58176cf1-37a8-4c52-9b27-4c7a47269dfb  admin       1F2c7A802aF640fd9F31dD846AdDf56BcMsay
+

Add scrape configurations for prometheus

+

A valid example file can be found here.

+

The global configuration specifies parameters that are valid in all other configuration contexts. They also serve as defaults for other configuration sections.

+
global:
+  scrape_interval:   60s
+  evaluation_interval: 60s
+scrape_configs:
+- job_name: 'drycc'
+  scheme: https
+  metrics_path: /v2/apps/<appname>/metrics
+  authorization:
+    type: Token
+    credentials: 1F2c7A802aF640fd9F31dD846AdDf56BcMsay
+  static_configs:
+  - targets: ['drycc.domain.com']
+
+
+ + + + + + + + + + + +
+ +

5.8 - Managing an Application

+
This is a high-level, technical description of how Drycc works. It ties together many of the concepts you’ll encounter while writing, configuring, deploying and running applications on the Drycc platform.
+

Track Application Changes

+

Drycc Workflow tracks all changes to your application. Application changes are the result of either new application code +pushed to the platform (via git push drycc master), or an update to application configuration (via drycc config:set KEY=VAL).

+

Each time a build or config change is made to your application a new release is created. These release numbers +increase monotonically.

+

You can see a record of changes to your application using drycc releases:

+
$ drycc releases
+OWNER    STATE      VERSION    CREATED                 SUMMARY
+dev      succeed    v3         2023-12-04T10:17:46Z    dev deleted PIP_INDEX_URL, DISABLE_COLLECTSTATIC
+dev      succeed    v2         2023-12-01T10:20:22Z    dev added IMAGE_PULL_POLICY, PIP_INDEX_URL, PORT, DISABLE_COLLEC[...]
+dev      succeed    v1         2023-11-30T17:54:57Z    dev created initial release
+

Rollback a Release

+

Drycc Workflow also supports rolling back go previous releases. If buggy code or an errant configuration change is pushed +to your application, you may rollback to a previously known, good release.

+

!!! note +All rollbacks create a new, numbered release. But will reference the build/code and configuration from the desired rollback point.

+

In this example, the application is currently running release v4. Using drycc rollback v2 tells Workflow to deploy the +build and configuration that was used for release v2. This creates a new release named v5 whose contents are the source +and configuration from release v2:

+
$ drycc releases
+OWNER    STATE      VERSION    CREATED                 SUMMARY
+dev      succeed    v3         2023-12-04T10:17:46Z    dev deleted PIP_INDEX_URL, DISABLE_COLLECTSTATIC
+dev      succeed    v2         2023-12-01T10:20:22Z    dev added IMAGE_PULL_POLICY, PIP_INDEX_URL, PORT, DISABLE_COLLEC[...]
+dev      succeed    v1         2023-11-30T17:54:57Z    dev created initial release
+
+$ drycc rollback v2
+Rolled back to v2
+
+$ drycc releases
+OWNER    STATE      VERSION    CREATED                 SUMMARY
+dev      succeed    v4         2023-12-04T10:20:46Z    dev rolled back to v2
+dev      succeed    v3         2023-12-04T10:17:46Z    dev deleted PIP_INDEX_URL, DISABLE_COLLECTSTATIC
+dev      succeed    v2         2023-12-01T10:20:22Z    dev added IMAGE_PULL_POLICY, PIP_INDEX_URL, PORT, DISABLE_COLLEC[...]
+dev      succeed    v1         2023-11-30T17:54:57Z    dev created initial release
+

Only rollback web process type:

+
$ drycc rollback v3 web
+Rolled back to v3
+
+$ drycc releases
+OWNER    STATE      VERSION    CREATED                 SUMMARY
+dev      succeed    v5         2023-12-04T10:23:49Z    dev rolled back to v3
+dev      succeed    v4         2023-12-04T10:20:46Z    dev rolled back to v2
+dev      succeed    v3         2023-12-04T10:17:46Z    dev deleted PIP_INDEX_URL, DISABLE_COLLECTSTATIC
+dev      succeed    v2         2023-12-01T10:20:22Z    dev added IMAGE_PULL_POLICY, PIP_INDEX_URL, PORT, DISABLE_COLLEC[...]
+dev      succeed    v1         2023-11-30T17:54:57Z    dev created initial release
+

Run One-off Administration Tasks

+

Drycc applications use one-off processes for admin tasks like database migrations and other commands that must run against the live application.

+

Use drycc run to execute commands on the deployed application.

+
$ drycc run 'ls -l'
+Running `ls -l`...
+
+total 28
+-rw-r--r-- 1 root root  553 Dec  2 23:59 LICENSE
+-rw-r--r-- 1 root root   60 Dec  2 23:59 Procfile
+-rw-r--r-- 1 root root   33 Dec  2 23:59 README.md
+-rw-r--r-- 1 root root 1622 Dec  2 23:59 pom.xml
+drwxr-xr-x 3 root root 4096 Dec  2 23:59 src
+-rw-r--r-- 1 root root   25 Dec  2 23:59 system.properties
+drwxr-xr-x 6 root root 4096 Dec  3 00:00 target
+
+

Share an Application

+

Use drycc perms:add to allow another Drycc user to collaborate on your application.

+
$ drycc perms:add otheruser view,change,delete
+Adding user otheruser as a collaborator for view,change,delete peachy-waxwork... done
+

Use drycc perms to see who an application is currently shared with, and drycc perms:remove to remove a collaborator.

+

!!! note +Collaborators can do anything with an application that its owner can do, except delete the application.

+

When working with an application that has been shared with you, clone the original repository and add Drycc’ git remote +entry before attempting to git push any changes to Drycc.

+
$ git clone https://github.com/drycc/example-java-jetty.git
+Cloning into 'example-java-jetty'... done
+$ cd example-java-jetty
+$ git remote add -f drycc ssh://git@local3.dryccapp.com:2222/peachy-waxworks.git
+Updating drycc
+From drycc-controller.local:peachy-waxworks
+ * [new branch]      master     -> drycc/master
+

Application Troubleshooting

+

Applications deployed on Drycc Workflow treat logs as event streams. Drycc Workflow aggregates stdout and stderr +from every Container making it easy to troubleshoot problems with your application.

+

Use drycc logs to view the log output from your deployed application.

+
$ drycc logs -f
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.5]: INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null}
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.8]: INFO:oejs.Server:jetty-7.6.0.v20120127
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.5]: INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:10005
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.6]: INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null}
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.7]: INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null}
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.6]: INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:10006
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.8]: INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null}
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.7]: INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:10007
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.8]: INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:10008
+
+ +
+ + + + + + + + + + + +
+ +

5.9 - Mounting volumes for an Application

+
Drycc supports many types of volumes. A container can use any number of volume types simultaneously.
+

We can use the blow command to create volumes and mount the created volumes. +Drycc create volume support ReadWriteMany, so before deploying drycc, you need to have a StorageClass ready which can support ReadWriteMany. +Deploying drycc, set controller.appStorageClass to this StorageClass.

+

Use drycc volumes to mount a volume for a deployed application’s processes.

+
$ drycc help volumes
+Valid commands for volumes:
+
+volumes:create           create a volume for the application
+volumes:list             list volumes in the application
+volumes:delete           delete a volume from the application
+volumes:client           the client used to manage volume files
+volumes:mount            mount a volume to process of the application
+volumes:unmount          unmount a volume from process of the application
+
+Use 'drycc help [command]' to learn more.
+
+

Create a volume for the application

+

You can create a csi volume with the drycc volumes:create command.

+
$ drycc volumes:create myvolume 200M
+Creating myvolumes to scenic-icehouse... done
+
+

Or use an existing nfs server

+
$ drycc volumes:create myvolume 200M -t nfs --nfs-server=nfs.drycc.com --nfs-path=/
+Creating myvolumes to scenic-icehouse... done
+
+

List volumes in the application

+

After volume is created, you can list the volumes in this application.

+
$ drycc volumes:list
+=== scenic-icehouse volumes
+--- myvolumes     200M
+
+

Mount a volume

+

The volume which is named myvolumes is created, you can mount the volume with process of the application, +use the command of drycc volumes:mount. When volume is mounted, a new release will be created and deployed automatically.

+
$ drycc volumes:mount myvolumes web=/data/web
+Mounting volume... done
+
+

And use drycc volumes:list show mount detail.

+
$ drycc volumes:list
+=== scenic-icehouse volumes
+--- myvolumes     200M
+web               /data/web
+
+

If you don’t need the volume, use drycc volumes:unmount to unmount the volume and then use drycc volumes:delete to delete the volume from the application. +Before deleting volume, the volume has to be unmounted.

+
$ drycc volumes:unmount myvolumes web
+Unmounting volume... done
+
+$ drycc volumes:delete myvolumes
+Deleting myvolumes from scenic-icehouse... done
+
+

Use volume client to manage volume files.

+

Assume the volume which is named myvolumes is created and mounted.

+

Prepare a file named testfile.

+
$ echo "testtext" > testfile
+
+

Upload. +$ drycc volumes:client cp testfile vol://myvolume/ +[↑] testfile 100% [==================================================] (5/ 5 B, 355 B/s)

+

List files in myvolume.

+
$ drycc volumes:client ls vol://myvolume/
+[2024-07-22T15:32:28+08:00]    5    testfile
+
+

Delete testfle in myvolume.

+
$ drycc volumes:client rm vol://myvolume/testfile
+ +
+ + + + + + + + + + + +
+ +

5.10 - About gateway for an Application

+
A Gateway describes how traffic can be translated to Services within the cluster.
+

A Gateway describes how traffic can be translated to Services within the cluster. That is, it defines a request for a way to translate traffic from somewhere that does not know about Kubernetes to somewhere that does. For example, traffic sent to a Kubernetes Service by a cloud load balancer, an in-cluster proxy, or an external hardware load balancer. While many use cases have client traffic originating “outside” the cluster, this is not a requirement.

+

Create Gateway for an Application

+

Gateway is a way of exposing services externally, which generates an external IP address to connect route and service. +After deploy, the gateway has been created.

+

List the containers:

+
# drycc gateways
+NAME                      LISENTER       PORT     PROTOCOL    ADDRESSES      
+python-getting-started    tcp-80-0       80       HTTP        101.65.132.51     
+

You can also add a port in this gateway or create a one.

+
# drycc gateways:add python-getting-started --port=443 --protocol=HTTPS
+Adding gateway python-getting-started to python-getting-started... done     
+

Create service for an Application

+

Service is a way of exposing services internally, creating a service generates an internal DNS that can access ptype. +the web process type has been created, for others types, you should add as needed.

+

List the services:

+
$ drycc services
+PTYPE      PORT    PROTOCOL    TARGET-PORT    DOMAIN                                    
+web        80      TCP         8000           python-getting-started.python-getting-started.svc.cluster.local  
+

Add a new service for process type

+
# drycc services:add --help
+# drycc services:add sleep 8001:8001
+

Create Route for an Application

+

A Gateway may be attached to one or more Route references which serve to direct traffic for a subset of traffic to a specific service. +Same as the above, the web process type already bind the gateway and servies.

+
# drycc routes
+NAME                           OWNER        PTYPE      KIND         SERVICE-PORT    GATEWAY                           LISTENER-PORT             
+python-getting-started         demo         web        HTTPRoute    80              python-getting-started            80  
+

create a new route and attach gateway.

+
drycc routes:create sleep --ptype=sleep --kind=HTTPRoute --port=8001
+drycc routes:attach sleep --gateway=python-getting-started --port=80
+
+
+ + + + + + + + + + + +
+ +

5.11 - Managing resources for an Application

+
Tools and services for developing, extending, and operating your app.
+

We can use blow command to create resources and bind which resource is created. +This command depend on service-catalog.

+

Use drycc resources to create and bind a resource for a deployed application.

+
$ drycc help resources
+
+Valid commands for resources:
+
+resources:services         list all available resource services
+resources:plans            list all available plans for an resource services
+resources:create           create a resource for the application
+resources:list             list resources in the application
+resources:describe         get a resource detail info in the application
+resources:update           update a resource from the application
+resources:destroy          delete a resource from the applicationa
+resources:bind             bind a resource to servicebroker
+resources:unbind           unbind a resource from servicebroker
+
+Use 'drycc help [command]' to learn more.
+
+

List all available resource services

+

You can list available resource services with one drycc resources:services command

+
$ drycc resources:services
+ID                                      NAME                  UPDATEABLE 
+15032a52-33c2-4b40-97aa-ceb972f51509    airflow               true          
+b7cb26a4-b258-445c-860b-a664239a67f8    cloudbeaver           true          
+9ce3c3ba-33b5-4e4e-a5e9-a338a83d5070    flink                 true          
+b80c51a1-957c-4d93-b3d5-efde84cd8031    fluentbit             true          
+fff5b6c7-ed85-429b-8265-493e40cc53c7    grafana               true          
+412e368f-bf78-4798-92cc-43343119a57d    kafka                 true          
+ea2a9b87-fbc4-4e2a-adee-161c1f91d98d    minio                 true          
+383f7316-84f3-4955-8491-1d4b02b749c8    mongodb               true          
+fbee746b-f3a7-4bef-8b55-cbecfd4c8ac3    mysql-cluster         true          
+5975094d-45cc-4e85-8573-f93937d026c7    opensearch            true          
+1db95161-7193-4544-8c76-e5ad5f6c03f6    pmm                   true          
+5cfb0abf-276c-445b-9060-9aa964ede87d    postgresql-cluster    true          
+b8f70264-eafc-4b2f-848e-2ec0d059032b    prometheus            true          
+f8186d36-f334-4094-8e02-d21a61da657b    rabbitmq              true          
+e1fd0d37-9046-4152-a29b-d155c5657c8b    redis                 true          
+7d2b64c6-0b59-4f08-a2f5-7b17cea6e5ee    redis-cluster         true          
+2e6877df-86e7-4bcc-a869-2a9b6847a465    seaweedfs             true          
+4aea5c0f-9495-420d-896a-ffc61a3eced5    spark                 true          
+b50db3b5-8d5f-4be9-b8bd-467ecd6cc11d    zookeeper             true
+
+

List all available plans for an resource services

+

You can list all available plans for an resource services with one drycc resources:plans command

+
$ drycc resources:plans redis
+ID                                      NAME              DESCRIPTION                                                       
+8d659058-a3b4-4058-b039-cc03a31b9442    standard-128      Redis standard-128 plan which limit resources memory size 128Mi.     
+36e3dbec-fc51-4f6b-9baa-e31e316858be    standard-256      Redis standard-256 plan which limit resources memory size 256Mi.     
+560817c2-5aa1-41c4-9ee6-a77e3ee552d5    standard-512      Redis standard-512 plan which limit resources memory size 512Mi.     
+d544d989-9fb8-43e9-a74e-0840ce1b8f0f    standard-1024     Redis standard-1024 plan which limit resources memory size 1Gi.      
+ad51b7bb-9b12-4ffd-8e49-010c0141b263    standard-2048     Redis standard-2048 plan which limit resources memory size 2Gi.      
+5097d76e-557c-453f-bdb1-54009e0df78d    standard-4096     Redis standard-4096 plan which limit resources memory size 4Gi.      
+be3fa2d0-36d2-47c5-9561-9deffe5ba373    standard-8192     Redis standard-8192 plan which limit resources memory size 8Gi.      
+4ca812a8-d7c3-439f-96cd-26523e88400e    standard-16384    Redis standard-16384 plan which limit resources memory size 16Gi.    
+b7f2a71f-0d97-48fd-8eed-aab24a7822f3    standard-32768    Redis standard-32768 plan which limit resources memory size 32Gi.    
+25c6b5d5-7505-47c8-95b1-dc9bdc698063    standard-65536    Redis standard-65536 plan which limit resources memory size 64Gi.
+
+

Create resource in application

+

You can create a resource with one drycc resources:create command

+
$ drycc resources:create redis:1000 redis
+Creating redis to scenic-icehouse... done
+
+

After resources are created, you can list the resources in this application.

+
$ drycc resources:list
+UUID                                    NAME     OWNER    PLAN                  UPDATED              
+07220e9e-d54d-4d74-a88c-f464aa374386    redis    admin    redis:standard-128    2024-05-08T01:01:00Z   
+
+

Bind resources

+

The resource which is named redis is created, you can bind the redis to the application, +use the command of drycc resources:bind redis.

+
$ drycc resources:bind redis
+Binding resource... done
+
+

Describe resources

+

And use drycc resources:describe show the binding detail. If the binding is successful, this command will show the information of connect to the resource.

+
$ drycc resources:describe redis
+=== scenic-icehouse resource redis
+plan:               redis:1000
+status:             Ready
+binding:            Ready
+
+REDISPORT:          6379
+REDIS_PASSWORD:     RzG87SJWG1
+SENTINELHOST:       172.16.0.2
+SENTINELPORT:       26379
+
+

Update resources

+

You can use the drycc resources:update command to upgrade a new plan. +An example of how to upgrade the plan’s capacity to 100MB:

+
$ drycc resources:update redis:10000 redis
+Updating redis to scenic-icehouse... done
+
+

Remove the resource

+

If you don’t need resources, use drycc resources:unbind to unbind the resource and then use drycc resources:destroy to delete the resource from the application. +Before deleting the resource, the resource must be unbinded.

+
$ drycc resources:unbind redis
+Unbinding resource... done
+
+$ drycc resources:destroy redis
+Deleting redis from scenic-icehouse... done
+
+ +
+ + + + + + + + + + + +
+ +

5.12 - Inter-app Communication

+
The Communication Solution between Drycc Applicatios.
+

A common architecture pattern of multi-process applications is to have one process serve public requests while having multiple other processes supporting the public one to, for example, perform actions on a schedule or process work items from a queue. To implement this system of apps in Drycc Workflow, set up the apps to communicate using DNS resolution, as shown above, and hide the supporting processes from public view by removing them from the Drycc Workflow router.

+

DNS Service Discovery

+

Drycc Workflow supports deploying a single app composed of a system of processes. Each Drycc Workflow app communicates on a single port, so communicating with another Workflow app means finding that app’s address and port. All Workflow apps are mapped to port 80 externally, so finding its IP address is the only challenge. Workflow creates a Kubernetes Service for each app, which effectively assigns a name and one cluster-internal IP address to an app. The DNS service running in the cluster adds and removes DNS records which point from the app name to its IP address as services are added and removed. Drycc Workflow apps, then, can simply send requests to the domain name given to the service, which is “app-name.app-namespace”.

+ +
+ + + + + + + + + + + +
+ +

5.13 - Resource Limits

+
Drycc Workflow supports restricting memory and CPU shares of each process.
+

+

Managing Application Resource Limits

+

Drycc Workflow supports restricting memory and CPU shares of each process. Requests/Limits set on a per-process type are given to +Kubernetes as a requests and limits. Which means you guarantee <requests> amount of resource for a process as well as limit +the process from using more than <limits>. +By default, Kubernetes will set <requests> equal to <limit> if we don’t explicitly set <requests> value. Please keep in mind that 0 <= requests <= limits.

+

Limiting

+

If you set a requests/limits that is out of range for your cluster, Kubernetes will be unable to schedule your application +processes into the cluster!

+
$ drycc limits:plans
+
+ID                    SPEC    CPU              VCPUS    MEMORY     FEATURES                      
+std1.large.c1m1       std1    Universal CPU    1        1 GiB      Integrated GPU shared    
+std1.large.c1m2       std1    Universal CPU    1        2 GiB      Integrated GPU shared    
+std1.large.c1m4       std1    Universal CPU    1        4 GiB      Integrated GPU shared    
+std1.large.c1m8       std1    Universal CPU    1        8 GiB      Integrated GPU shared    
+std1.large.c2m2       std1    Universal CPU    2        2 GiB      Integrated GPU shared    
+std1.large.c2m4       std1    Universal CPU    2        4 GiB      Integrated GPU shared    
+std1.large.c2m8       std1    Universal CPU    2        8 GiB      Integrated GPU shared    
+std1.large.c2m16      std1    Universal CPU    2        16 GiB     Integrated GPU shared    
+
+$ drycc limits:set web=std1.large.c1m1
+Applying limits... done
+
+
+ + + + + + + + + + + +
+ +

5.14 - Domains and Routing

+
Make your apps accessible via custom domain names.
+

You can use drycc domains to add or remove custom domains to the application:

+
$ drycc domains:add hello.bacongobbler.com --ptype=web
+Adding hello.bacongobbler.com to finest-woodshed... done
+
+

Once that’s done, you can go into a DNS registrar and set up a CNAME from the new +appname to the old one:

+
$ dig hello.dryccapp.com
+[...]
+;; ANSWER SECTION:
+hello.bacongobbler.com.         1759    IN    CNAME    finest-woodshed.dryccapp.com.
+finest-woodshed.dryccapp.com.    270     IN    A        172.17.8.100
+
+

!!! note +Setting a CNAME for a root domain can cause issues. Setting an @ record +to be a CNAME causes all traffic to go to the other domain, including mail and the SOA +(“start-of-authority”) records. It is highly recommended that you bind a subdomain to +an application, however you can work around this by pointing the @ record to the +address of the load balancer (if any).

+

To add or remove the application from the routing mesh, use drycc routing:

+
$ drycc routing:disable
+Disabling routing for finest-woodshed... done
+
+

This will make the application unreachable through the Router, but the application is still +reachable internally through its Kubernetes Service. To re-enable routing:

+
$ drycc routing:enable
+Enabling routing for finest-woodshed... done
+
+ +
+ + + + + + + + + + + +
+ +

5.15 - Application SSL Certificates

+
SSL is a cryptographic protocol that provides end-to-end encryption and integrity for all web requests.
+

Application SSL Certificates

+

SSL is a cryptographic protocol that provides end-to-end encryption and integrity for all web +requests. Apps that transmit sensitive data should enable SSL to ensure all information is +transmitted securely.

+

To enable SSL on a custom domain, e.g., www.example.com, use the SSL endpoint.

+

!!! note +drycc certs is only useful for custom domains. Default application domains are +SSL-enabled already and can be accessed simply by using https, +e.g. https://foo.dryccapp.com (provided that you have installed your wildcard +certificate on the routers or on the load balancer).

+

Overview

+

Because of the unique nature of SSL validation, provisioning SSL for your domain is a multi-step +process that involves several third-parties. You will need to:

+
    +
  1. Purchase an SSL certificate from your SSL provider
  2. +
  3. Upload the cert to Drycc
  4. +
+

Acquire SSL Certificate

+

Purchasing an SSL cert varies in cost and process depending on the vendor. RapidSSL offers a +simple way to purchase a certificate and is a recommended solution. If you’re able to use this +provider, see buy an SSL certificate with RapidSSL for instructions.

+

DNS and Domain Configuration

+

Once the SSL certificate is provisioned and your cert is confirmed, you must route requests for +your domain through Drycc. Unless you’ve already done so, add the domain specified when generating +the CSR to your app with:

+
$ drycc domains:add www.example.com --ptype==web -a foo
+Adding www.example.com to foo... done
+
+

Add a Certificate

+

Add your certificate, any intermediate certificates, and private key to the endpoint with the +certs:add command.

+
$ drycc certs:add example-com server.crt server.key -a foo
+Adding SSL endpoint... done
+www.example.com
+
+

!!! note +The name given to the certificate can only contain a-z (lowercase), 0-9 and hyphens

+

The Drycc platform will investigate the certificate and extract any relevant information from it +such as the Common Name, Subject Alt Names (SAN), fingerprint and more.

+

This allows for wildcard certificates and multiple domains in the SAN without uploading duplicates.

+

Add a Certificate Chain

+

Sometimes, your certificates (such as a self-signed or a cheap certificate) need additional +certificates to establish the chain of trust. What you need to do is bundle all the certificates +into one file and give that to Drycc. Importantly, your site’s certificate must be the first one:

+
$ cat server.crt server.ca > server.bundle
+
+

After that, you can add them to Drycc with the certs:add command:

+
$ drycc certs:add example-com server.bundle server.key -a foo
+Adding SSL endpoint... done
+www.example.com
+
+

Attach SSL certificate to a domain

+

Certificates are not automagically connected up to domains, instead you will have to attach a +certificate to a domain

+
$ drycc certs:attach example-com example.com -a foo
+
+

Each certificate can be connected to many domains. There is no need to upload duplicates.

+

To remove an association

+
$ drycc certs:detach example-com example.com -a foo
+
+

Endpoint overview

+

You can verify the details of your domain’s SSL configuration with drycc certs.

+
$ drycc certs
+
+     Name     |    Common Name    | SubjectAltName    |         Expires         |   Fingerprint   |   Domains    |   Updated   |   Created
++-------------+-------------------+-------------------+-------------------------+-----------------+--------------+-------------+-------------+
+  example-com |     example.com   | blog.example.com  | 31 Dec 2017 (in 1 year) | 8F:8E[...]CD:EB |  example.com | 30 Jan 2016 | 29 Jan 2016
+
+

or by looking at at each certificates detailed information

+
$ drycc certs:info example-com -a foo
+
+=== bar-com Certificate
+Common Name(s):     example.com
+Expires At:         2017-01-14 23:57:57 +0000 UTC
+Starts At:          2016-01-15 23:57:57 +0000 UTC
+Fingerprint:        7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0
+Subject Alt Name:   blog.example.com
+Issuer:             /C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=example.com/emailAddress=engineering@drycc.cc
+Subject:            /C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=example.com/emailAddress=engineering@drycc.cc
+
+Connected Domains:  example.com
+Owner:              admin-user
+Created:            2016-01-28 19:07:41 +0000 UTC
+Updated:            2016-01-30 00:10:02 +0000 UTC
+
+

Testing SSL

+

Use a command line utility like curl to test that everything is configured correctly for your +secure domain.

+

!!! note +The -k option flag tells curl to ignore untrusted certificates.

+

Pay attention to the output. It should print SSL certificate verify ok. If it prints something +like common name: www.example.com (does not match 'www.somedomain.com') then something is not +configured correctly.

+

Enforcing SSL at the Router

+

To enforce all HTTP requests be redirected to HTTPS, TLS can be enforced at the router level by +running

+
$ drycc tls:force:enable -a foo
+Enabling https-only requests for foo... done
+
+

Users hitting the HTTP endpoint for the application will now receive a 301 redirect to the HTTPS +endpoint.

+

To disable enforced TLS, run

+
$ drycc tls:force:disable -a foo
+Disabling https-only requests for foo... done
+
+

Automated Certificate Management

+

With Automated Certificate Management (ACM), Drycc automatically manages TLS certificates for apps with Hobby and Professional dynos on the Common Runtime, and for apps in Private Spaces that enable the feature. +Certificates handled by ACM automatically renew one month before they expire, and new certificates are created automatically whenever you add or remove a custom domain. All applications with paid dynos include ACM for free. +Automated Certificate Management uses Let’s Encrypt, the free, automated, and open certificate authority for managing your application’s TLS certificates. Let’s Encrypt is run for the public benefit by the Internet Security Research Group (ISRG).

+

To enable ACM with the following command: +$ drycc tls:auto:enable -a foo

+

To disable ACM with the following command: +$ drycc tls:auto:disable -a foo

+

Remove Certificate

+

You can remove a certificate using the certs:remove command:

+
$ drycc certs:remove my-cert -a foo
+Removing www.example.com... Done.
+
+

Swapping out certificates

+

Over the lifetime of an application an operator will have to acquire certificates with new expire +dates and apply it to all relevant applications, below is the recommended way to swap out certificates.

+

Be intentional with certificate names, name them example-com-2017 when possible, where the year +signifies the expiry year. This allows for example-com-2018 when a new certificate is purchased.

+

Assuming all applications are already using example-com-2017 the following commands can be ran, +chained together or otherwise:

+
$ drycc certs:detach example-com-2017 example.com -a foo
+$ drycc certs:attach example-com-2018 example.com -a foo
+
+

This will take care of a singular domain which allows the operator to verify everything went +as planned and slowly roll it out to any other application using the same method.

+

Troubleshooting

+

Here are some steps you can follow if your SSL endpoint is not working as you’d expect.

+

Untrusted Certificate

+

In some cases when accessing the SSL endpoint, it may list your certificate as untrusted.

+

If this occurs, it may be because it is not trusted by Mozilla’s list of root CAs. If this is +the case, your certificate may be considered untrusted for many browsers.

+

If you have uploaded a certificate that was signed by a root authority but you get the message that +it is not trusted, then something is wrong with the certificate. For example, it may be missing +intermediary certificates. If so, download the intermediary certificates from your SSL provider, +remove the certificate from Drycc and re-run the certs:add command.

+ +
+ + + + + + + + + + + +
+ +

5.16 - Using drycc.yaml

+
Drycc Container Registry allows you to deploy your Docker-based app to Drycc. Both Common Runtime and Private Spaces are supported.
+

The Drycc stack is intended for advanced use cases only. Unless you have a specific need for custom Docker images, we recommend using Drycc’s default buildpack-powered build system. It offers automatic base image security updates and language-specific optimizations. It also avoids the need to maintain a .containerDockerfile

+

drycc.yaml Overview

+

A manifest has three top-level sections.

+
    +
  • build – Specifies the to build Dockerfile
  • +
  • run – Specifies the release phase tasks to execute
  • +
  • deploy – Specifies process types and the commands to run for each type
  • +
+

Here’s an example that illustrates using a manifest to build Docker images.

+
build:
+  docker:
+    web: Dockerfile
+    worker: worker/Dockerfile
+  config:
+    web:
+      FOO: bar
+    worker:
+      RAILS_ENV: development
+run:
+- command:
+  - ./deployment-tasks.sh
+  image: worker
+  # If the field is empty, it means it will be executed forever
+  when:
+    ptypes:
+    - web
+    - webbbsbs
+  # Maximum execution time
+  timeout: 100
+deploy:
+  web:
+    command:
+    - bash
+    - -ec
+    args:
+    - bundle exec puma -C config/puma.rb
+  worker:
+    command:
+    - bash
+    - -ec
+    args:
+    - python myworker.py
+  asset-syncer:
+    command:
+    - bash
+    - -ec
+    args:
+    - python asset-syncer.py
+    image: worker
+

For more deployment information, please refer to the drycc examples.

+ +
+ + + + + + + + + + + + + + + +
+ +

6 - Managing Workflow

+
Managing Workflow using the kubectl.
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +

6.1 - Tuning Component Settings

+
Helm Charts are a set of Kubernetes manifests that reflect best practices for deploying an application or service on Kubernetes.
+

After you add the Drycc Chart Repository, you can customize the chart using +helm inspect values drycc/workflow > values.yaml before using helm install to complete the +installation.

+

There are a few ways to customize the respective component:

+
    +
  • +

    If the value is exposed in the values.yaml file as derived above, one may modify the section of the component to tune these settings. The modified value(s) will then take effect at chart installation or release upgrade time via either of the two respective commands:

    +
     $ helm install drycc oci://registry.drycc.cc/charts/workflow \
    +     -n drycc \
    +     --namespace drycc \
    +     -f values.yaml
    + $ helm upgrade drycc oci://registry.drycc.cc/charts/workflow \
    +     -n drycc \
    +     --namespace drycc \
    +     -f values.yaml
    +
    +
  • +
  • +

    If the value hasn’t yet been exposed in the values.yaml file, one may edit the component deployment with the tuned setting. Here we edit the drycc-controller deployment:

    +
     $ kubectl --namespace drycc edit deployment drycc-controller
    +
    +

    Add/edit the setting via the appropriate environment variable and value under the env section and save. The updated deployment will recreate the component pod with the new/modified setting.

    +
  • +
  • +

    Lastly, one may also fetch and edit the chart as served by version control/the chart repository itself:

    +
     $ helm fetch oci://registry.drycc.cc/charts/workflow --untar
    + $ $EDITOR workflow/charts/controller/templates/controller-deployment.yaml
    +
    +

    Then run helm install ./workflow --namespace drycc --name drycc to apply the changes, or helm upgrade drycc ./workflow if the cluster is already running.

    +
  • +
+

Setting Resource limits

+

You can set resource limits to Workflow components by modifying the values.yaml file fetched +earlier. This file has a section for each Workflow component. To set a limit to any Workflow +component just add limitsCpu, limitsMemory in the section and set them to the appropriate +values.

+

Below is an example of how the builder section of values.yaml might look with CPU and memory +limits set:

+
builder:
+  imageOrg: "drycc"
+  imagePullPolicy: "Always"
+  imageTag: "canary"
+  limitsCpu: "100m"
+  limitsMemory: "50Mi"
+

Customizing the Builder

+

The following environment variables are tunable for the Builder component:

+ + + + + + + + + + + + + + + + + +
SettingDescription
DEBUGEnable debug log output (default: false)
BUILDER_POD_NODE_SELECTORA node selector setting for builder job. As it may sometimes consume a lot of node resources, one may want a given builder job to run in a specific node only, so it won’t affect critical nodes. for example pool:testing,disk:magnetic
+

Customizing the Controller

+

The following environment variables are tunable for the Controller component:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SettingDescription
REGISTRATION_MODEset registration to “enabled”, “disabled”, or “admin_only” (default: “admin_only”)
GUNICORN_WORKERSnumber of gunicorn workers spawned to process requests (default: CPU cores * 4 + 1)
RESERVED_NAMESa comma-separated list of names which applications cannot reserve for routing (default: “drycc, drycc-builder”)
DRYCC_DEPLOY_HOOK_URLSa comma-separated list of URLs to send deploy hooks to.
DRYCC_DEPLOY_HOOK_SECRET_KEYa private key used to compute the HMAC signature for deploy hooks.
DRYCC_DEPLOY_REJECT_IF_PROCFILE_MISSINGrejects a deploy if the previous build had a Procfile but the current deploy is missing it. A 409 is thrown in the API. Prevents accidental process types removal. (default: “false”, allowed values: “true”, “false”)
DRYCC_DEPLOY_PROCFILE_MISSING_REMOVEwhen turned on (default) any missing process type in a Procfile compared to the previous deploy is removed. When set to false will allow an empty Procfile to go through without removing missing process types, note that new images, configs and so on will get updated on all proc types. (default: “true”, allowed values: “true”, “false”)
DRYCC_DEFAULT_CONFIG_TAGSset tags for all applications by default, for example: ‘{“role”: “worker”}’. (default: ‘’)
KUBERNETES_NAMESPACE_DEFAULT_QUOTA_SPECset resource quota to application namespace by setting ResourceQuota spec, for example: {"spec":{"hard":{"pods":"10"}}}, restrict app owner to spawn more then 10 pods (default: “”, no quota will be applied to namespace)
+

LDAP authentication settings

+

Configuration options for LDAP authentication are detailed here.

+

The following environment variables are available for enabling LDAP +authentication of user accounts in the Passport component:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SettingDescription
LDAP_ENDPOINTThe URI of the LDAP server. If not specified, LDAP authentication is not enabled (default: “”, example: ldap://hostname).
LDAP_BIND_DNThe distinguished name to use when binding to the LDAP server (default: “”)
LDAP_BIND_PASSWORDThe password to use with LDAP_BIND_DN (default: “”)
LDAP_USER_BASEDNThe distinguished name of the search base for user names (default: “”)
LDAP_USER_FILTERThe name of the login field in the users search base (default: “username”)
LDAP_GROUP_BASEDNThe distinguished name of the search base for user’s groups names (default: “”)
LDAP_GROUP_FILTERThe filter for user’s groups (default: “”, example: objectClass=person)
+

Global and per application settings

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SettingDescription
DRYCC_DEPLOY_BATCHESthe number of pods to bring up and take down sequentially during a scale (default: number of available nodes)
DRYCC_DEPLOY_TIMEOUTdeploy timeout in seconds per deploy batch (default: 120)
IMAGE_PULL_POLICYthe kubernetes image pull policy for application images (default: “IfNotPresent”) (allowed values: “Always”, “IfNotPresent”)
KUBERNETES_DEPLOYMENTS_REVISION_HISTORY_LIMIThow many revisions Kubernetes keeps around of a given Deployment (default: all revisions)
KUBERNETES_POD_TERMINATION_GRACE_PERIOD_SECONDShow many seconds kubernetes waits for a pod to finish work after a SIGTERM before sending SIGKILL (default: 30)
+

See the Deploying Apps guide for more detailed information on those.

+

Customizing the Database

+

The following environment variables are tunable for the Database component:

+ + + + + + + + + + + + + + + + + +
SettingDescription
BACKUP_FREQUENCYhow often the database should perform a base backup (default: “12h”)
BACKUPS_TO_RETAINnumber of base backups the backing store should retain (default: 5)
+

Customizing Fluentbit

+

The following values can be changed in the values.yaml file or by using the --values flag with the Helm CLI.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
KeyDescription
config.serviceThe service section defines the global properties of the service.
config.inputsAn input section defines a source (related to an input plugin).
config.filtersA filter section defines a filter (related to a filter plugin)
config.outputsThe outputs section specify a destination that certain records should follow after a Tag match.
+

For more information about the various variables that can be set please see the fluentbit.

+

Customizing the Logger

+

The following environment variables are tunable for the Logger component:

+ + + + + + + + + + + + + + + + + +
SettingDescription
STORAGE_ADAPTERHow to store logs that are sent to the logger. Legal values are “file”, “memory”, and “redis”. (default: “redis”)
NUMBER_OF_LINESHow many lines to store in the ring buffer (default: 1000)
+

Customizing the Monitor

+

Grafana

+

We have exposed some of the more useful configuration values directly in the chart. This allows them to be set using either the values.yaml file or by using the --set flag with the Helm CLI. You can see these options below:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
SettingDefault ValueDescription
user“admin”The first user created in the database (this user has admin privileges)
password“admin”Password for the first user.
allow_sign_up“true”Allows users to sign up for an account.
+

For a list of other options you can set by using environment variables please see the configuration file in Github.

+

Telegraf

+

For a list of configuration values that can be set by using environment variables please see the following configuration file.

+

Prometheus

+

You can find a list of values that can be set using environment variables here.

+

Customizing the Registry

+

The Registry component can be tuned by following the +drycc/distribution config doc.

+

Customizing the Router

+

The majority of router settings are tunable through annotations, which allows the router to be +re-configured with zero downtime post-installation. You can find the list of annotations to tune +here.

+

The following environment variables are tunable for the [Router][] component:

+ + + + + + + + + + + + + +
SettingDescription
POD_NAMESPACEThe pod namespace the router resides in. This is set by the Kubernetes downward API.
+

Customizing Workflow Manager

+

The following environment variables are tunable for [Workflow Manager][]:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SettingDescription
CHECK_VERSIONSEnables the external version check at https://versions.drycc.info/ (default: “true”)
POLL_INTERVAL_SECThe interval when Workflow Manager performs a version check, in seconds (default: 43200, or 12 hours)
VERSIONS_API_URLThe versions API URL (default: “https://versions-staging.drycc.info”)
DOCTOR_API_URLThe doctor API URL (default: “https://doctor-staging.drycc.info”)
API_VERSIONThe version number Workflow Manager sends to the versions API (default: “v2”)
+ +
+ + + + + + + + + + + +
+ +

6.2 - Configure DNS

+
The Drycc Workflow controller and all applications deployed via Workflow are intended (by default) to be accessible as subdomains of the Workflow cluster’s domain.
+

For example, assuming example.com were a cluster’s domain:

+
    +
  • The controller should be accessible at drycc.example.com
  • +
  • Applications should be accessible (by default) at <application name>.example.com
  • +
+

Given that this is the case, the primary objective in configuring DNS is that traffic for all subdomains of a cluster’s domain be directed to the cluster node(s) hosting the platform’s router component, which is capable of directing traffic within the cluster to the correct endpoints.

+

With a Load Balancer

+

Generally, it is recommended that a [load balancer][] be used to direct inbound traffic to one or more routers. In such a case, configuring DNS is as simple as defining a wildcard record in DNS that points to the load balancer.

+

For example, assuming a domain of example.com:

+
    +
  • An A record enumerating each of your load balancer(s) IPs (i.e. DNS round-robining)
  • +
  • A CNAME record referencing an existing fully-qualified domain name for the load balancer +
      +
    • Per AWS’ own documentation, this is the recommended strategy when using AWS Elastic Load Balancers, as ELB IPs may change over time.
    • +
    +
  • +
+

DNS for any applications using a “custom domain” (a fully-qualified domain name that is not a subdomain of the cluster’s own domain) can be configured by creating a CNAME record that references the wildcard record described above.

+

Although it is dependent upon your distribution of Kubernetes and your underlying infrastructure, in many cases, the IP(s) or existing fully-qualified domain name of a load balancer can be determined directly using the kubectl tool:

+
$ kubectl --namespace=istio-nginx describe service | grep "LoadBalancer"
+LoadBalancer Ingress:	a493e4e58ea0511e5bb390686bc85da3-1558404688.us-west-2.elb.amazonaws.com
+

The LoadBalancer Ingress field typically describes an existing domain name or public IP(s). Note that if Kubernetes is able to automatically provision a load balancer for you, it does so asynchronously. If the command shown above is issued very soon after Workflow installation, the load balancer may not exist yet.

+

Without a Load Balancer

+

On some platforms (Minikube, for instance), a load balancer is not an easy or practical thing to provision. In these cases, one can directly identify the public IP of a Kubernetes node that is hosting a router pod and use that information to configure the local /etc/hosts file.

+

Because wildcard entries do not work in a local /etc/hosts file, using this strategy may result in frequent editing of that file to add fully-qualified subdomains of a cluster for each application added to that cluster. Because of this a more viable option may be to utilize the xip.io service.

+

In general, for any IP, a.b.c.d, the fully-qualified domain name any-subdomain.a.b.c.d.xip.io will resolve to the IP a.b.c.d. This can be enormously useful.

+

To begin, find the node(s) hosting router instances using kubectl:

+
$ kubectl --namespace=istio-ingress describe pod | grep Node:
+Node:       ip-10-0-0-199.us-west-2.compute.internal/10.0.0.199
+Node:       ip-10-0-0-198.us-west-2.compute.internal/10.0.0.198
+

The command will display information for every router pod. For each, a node name and IP are displayed in the Node field. If the IPs appearing in these fields are public, any of these may be used to configure your local /etc/hosts file or may be used with xip.io. If the IPs shown are not public, further investigation may be needed.

+

You can list the IP addresses of a node using kubectl:

+
$ kubectl describe node ip-10-0-0-199.us-west-2.compute.internal
+# ...
+Addresses:	10.0.0.199,10.0.0.199,54.218.85.175
+# ...
+

Here, the Addresses field lists all the node’s IPs. If any of them are public, again, they may be used to configure your local /etc/hosts file or may be used with xip.io.

+

Tutorial: Configuring DNS with Google Cloud DNS

+

In this section, we’ll describe how to configure Google Cloud DNS for routing your domain name to your Drycc cluster.

+

We’ll assume the following in this section:

+
    +
  • Your Ingress service has a load balancer in front of it. +
      +
    • The load balancer need not be cloud based, it just needs to provide a stable IP address or a stable domain name
    • +
    +
  • +
  • You have the mystuff.com domain name registered with a registrar +
      +
    • Replace your domain name with mystuff.com in the instructions to follow
    • +
    +
  • +
  • Your registrar lets you alter the nameservers for your domain name (most registrars do)
  • +
+

Here are the steps for configuring cloud DNS to route to your drycc cluster:

+
    +
  1. Get the load balancer IP or domain name
  2. +
+
    +
  • If you are on Google Container Engine, you can run kubectl get svc -n istio-ingress and look for the LoadBalancer Ingress column to get the IP address
  • +
+
    +
  1. Create a new Cloud DNS Zone (on the console: Networking => Cloud DNS, then click on Create Zone)
  2. +
  3. Name your zone, and set the DNS name to mystuff.com. (note the . at the end
  4. +
  5. Click on the Create button
  6. +
  7. Click on the Add Record Set button on the resulting page
  8. +
  9. If your load balancer provides a stable IP address, enter the following fields in the resulting form:
  10. +
  11. DNS Name: *
  12. +
  13. Resource Record Type: A
  14. +
  15. TTL: the DNS TTL of your choosing. If you’re testing or you anticipate that you’ll tear down and rebuild many drycc clusters over time, we recommend a low TTL
  16. +
  17. IPv4 Address: The IP that you got in the very first step
  18. +
  19. Click the Create button
  20. +
  21. If your load balancer provides the stable domain name lbdomain.com, enter the following fields in the resulting form:
  22. +
  23. DNS Name: *
  24. +
  25. Resource Record Type: CNAME
  26. +
  27. TTL: the DNS TTL of your choosing. If you’re testing or you anticipate that you’ll tear down and rebuild many drycc clusters over time, we recommend a low TTL
  28. +
  29. Canonical name: lbdomain.com. (note the . a the end)
  30. +
  31. Click on the Create button
  32. +
  33. In your domain registrar, set the nameservers for your mystuff.com domain to the ones under the data column in the NS record on the same page. They’ll often be something like the below (note the trailing . characters).
  34. +
+
ns-cloud-b1.googledomains.com.
+ns-cloud-b2.googledomains.com.
+ns-cloud-b3.googledomains.com.
+ns-cloud-b4.googledomains.com.
+

Note: If you ever have to re-create your drycc cluster, simply go back to step 6.4 or 7.4 (depending on your load balancer) and change the IP address or domain name to the new value. You may have to wait for the TTL you set to expire.

+

Testing

+

To test that traffic reaches its intended destination, a request can be +sent to the Drycc controller like so (do not forget the trailing slash!):

+
curl http://drycc.example.com/v2/
+

Or:

+
curl http://drycc.54.218.85.175.xip.io/v2/
+

Since such requests require authentication, a response such as the following should be considered an indicator of success:

+
{"detail":"Authentication credentials were not provided."}
+
+
+ + + + + + + + + + + +
+ +

6.3 - Deploy Hooks

+
Deploy hooks allow an external service to receive a notification whenever a new version of your app is pushed to Workflow.
+

It’s useful to help keep the development team informed about deploys, while +it can also be used to integrate different systems together.

+

After one or more hooks are setup, hook output and errors appear in your application’s logs:

+
$ drycc logs
+...
+2011-03-15T15:07:29-07:00 drycc[api]: Deploy hook sent to http://drycc.rocks
+

Deploy hooks are a generic HTTP hook. An administrator can create and configure multiple deploy +hooks by tuning the controller settings via the Helm chart.

+

HTTP POST Hook

+

The HTTP deploy hook performs an HTTP POST to a URL. The parameters included in the request are the +same as the variables available in the hook message: app, release, release_summary, sha and +user. See below for their descriptions:

+
app=secure-woodland&release=v4&release_summary=gabrtv%20deployed%35b3726&sha=35b3726&user=gabrtv
+

Optionally, if a deploy hook secret key is added to the controller through +tuning the controller settings, a new Authorization header will be +present in the POST request. The value of this header is computed as the HMAC hex digest of the +request URL, using the secret as the key.

+

In order to authenticate that this request came from Workflow, use the secret key, the full URL and +the HMAC-SHA1 hashing algorithm to compute the signature. In Python, that would look something like +this:

+
import hashlib
+import hmac
+
+hmac.new("my_secret_key", "http://drycc.rocks?app=secure-woodland&release=v4&release_summary=gabrtv%20deployed%35b3726&sha=35b3726&user=gabrtv", digestmod=hashlib.sha1).hexdigest()
+

If the value of the computed HMAC hex digest and the value in the Authorization header are +identical, then the request came from Workflow.

+

!!! important +When computing the signature, ensure that the URL parameters are in alphabetic order. This is +critical when computing the cryptographic signature as most web applications don’t care about +the order of the HTTP parameters, but the cryptographic signature will not be the same.

+ +
+ + + + + + + + + + + +
+ +

6.4 - Platform Logging

+
Logs are a stream of time-stamped events aggregated from the output streams of all your app’s running processes. Retrieve, filter, or use syslog drains.
+

The logging platform is made up of 2 components - Fluentbit and Logger.

+

Fluentbit runs on every worker node of the cluster and is deployed as a Daemon Set. The Fluentbit pods capture all of the stderr and stdout streams of every container running on the host (even those not hosted directly by kubernetes). Once the log message arrives in our custom fluentbit plugin we determine where the message originated.

+

If the message was from the Workflow Controller or from an application deployed via workflow we send it to the logs topic on the local Redis Stream instance.

+

Logger then acts as a consumer reading messages off of the Redis Stream logs topic storing those messages in a local Redis instance. When a user wants to retrieve log entries using the drycc logs command we make an HTTP request from Controller to Logger which then fetches the appropriate data from Redis.

+

Configuring Off Cluster Redis

+

Even though we provide a redis instance with the default Workflow install, it is recommended that operators use a third-party source like Elasticache or similar offering. This way your data is durable across upgrades or outages. If you have a third-party Redis installation you would like to use all you need to do is set the following values in your helm chart:

+
    +
  • db = “0”
  • +
  • host = “my.host.redis”
  • +
  • port = “6379”
  • +
  • password = ""
  • +
+

These can be changed by running helm inspect values drycc/workflow > values.yaml before using +helm install to complete the installation. To customize the redis credentials, edit values.yaml +and modify the redis section of the file to tune these settings.

+

Debugging Logger

+

If the drycc logs command encounters an error it will return the following message:

+
Error: There are currently no log messages. Please check the following things:
+1) Logger and fluentbit pods are running.
+2) The application is writing logs to the logger component by checking that an entry in the ring buffer was created: kubectl  --namespace=drycc logs <logger pod>
+3) Making sure that the container logs were mounted properly into the fluentbit pod: kubectl --namespace=drycc exec <fluentbit pod> ls /var/log/containers
+

Architecture Diagram

+
                        ┌────────┐                                        
+                        │ Router │                  ┌────────┐     ┌─────┐
+                        └────────┘                  │ Logger │◀───▶│Redis│
+                            │                       └────────┘     └─────┘
+                        Log file                        ▲                
+                            │                           │                
+                            ▼                           │                
+┌────────┐             ┌─────────┐    logs/metrics   ┌──────────────┐     
+│App Logs│──Log File──▶│Fluentbit│───────topics─────▶│ Redis Stream │     
+└────────┘             └─────────┘                   └──────────────┘     
+                                                                          
+

Default Configuration

+

Fluent Bit is based in a pluggable architecture where different plugins plays a major role in the data pipeline, more than 70 built-in plugins available. +Please refer to charts values.yaml for specific configurations.

+ +
+ + + + + + + + + + + +
+ +

6.5 - Platform Monitoring

+
Platform monitoring to your apps to spot issues in advance and respond to incidents quickly.
+

Description

+

We now include a monitoring stack for introspection on a running Kubernetes cluster. The stack includes 4 components:

+ +

Architecture Diagram

+
┌────────────────┐                                                        
+│ HOST           │                                                        
+│  node-exporter │◀──┐                       ┌──────────────────┐         
+└────────────────┘   │                       │kube-state-metrics│         
+                     │                       └──────────────────┘         
+┌────────────────┐   │                               ▲                    
+│ HOST           │   │    ┌────────────┐             │                    
+│  node-exporter │◀──┼────│ Prometheus │─────────────┘                    
+└────────────────┘   │    └────────────┘                                  
+                     │          ▲                                         
+┌───────────────┐    │          │                                         
+│ HOST          │    │          ▼                                         
+│  node-exporter│◀───┘    ┌──────────┐                                    
+└───────────────┘         │ Grafana  │                                    
+                          └──────────┘                                    
+

Grafana

+

Grafana allows users to create custom dashboards that visualize the data captured to the running Prometheus component. By default Grafana is exposed using a service annotation through the router at the following URL: http://grafana.mydomain.com. The default login is admin/admin. If you are interested in changing these values please see [Tuning Component Settings][].

+

Grafana will preload several dashboards to help operators get started with monitoring Kubernetes and Drycc Workflow. +These dashboards are meant as starting points and don’t include every item that might be desirable to monitor in a +production installation.

+

Drycc Workflow monitoring by default does not write data to the host filesystem or to long-term storage. If the Grafana instance fails, modified dashboards are lost.

+

Production Configuration

+

A production install of Grafana should have the following configuration values changed if possible:

+
    +
  • Change the default username and password from admin/admin. The value for the password is passed in plain text so it is best to set this value on the command line instead of checking it into version control.
  • +
  • Enable persistence
  • +
  • Use a supported external database such as mysql or postgres. You can find more information here
  • +
+

On Cluster Persistence

+

Enabling persistence will allow your custom configuration to persist across pod restarts. This means that the default sqllite database (which stores things like sessions and user data) will not disappear if you upgrade the Workflow installation.

+

If you wish to have persistence for Grafana you can set enabled to true in the values.yaml file before running helm install.

+
 grafana:
+   # Configure the following ONLY if you want persistence for on-cluster grafana
+   # GCP PDs and EBS volumes are supported only
+   persistence:
+     enabled: true # Set to true to enable persistence
+     size: 5Gi # PVC size
+

Off Cluster Grafana

+

If you wish to provide your own Grafana instance you can set grafanaLocation in the values.yaml file before running helm install.

+

Prometheus

+

Prometheus writes data to the host disk; however, if the prometheus pod dies and comes back on another host, the data will not be recovered. The prometheus graph UI is also exposed through the router allowing users to access the query engine by going to prometheus.mydomain.com.

+

On Cluster Persistence

+

You can set node-exporter and kube-state-metrics to true or false in the values.yaml. +If you wish to have persistence for Prometheus you can set enabled to true in the values.yaml file before running helm install.

+
prometheus:
+  prometheus-server:
+    persistence:
+      enabled: true # Set to true to enable persistence
+      size: 10Gi # PVC size
+node-exporter:
+  enabled: true
+kube-state-metrics:
+  enabled: true
+

Off Cluster Prometheus

+

To use off-cluster Prometheus, please provide the following values in the values.yaml file before running helm install.

+
    +
  • global.prometheusLocation=off-cluster
  • +
  • url = "http://my.prometheus.url:9090"
  • +
+ +
+ + + + + + + + + + + +
+ +

6.6 - Production Deployments

+
When readying a Workflow deployment for production workloads, there are some additional recommendations.
+

Running Workflow without drycc storage

+

In production, persistent storage can be achieved by running an external object store. +For users on AWS, GCE/GKE or Azure, the convenience of Amazon S3, Google GCS or Microsoft Azure Storage +makes the prospect of running a Storage-less Workflow cluster quite reasonable. For users who have restriction +on using external object storage using swift object storage can be an option.

+

Running a Workflow cluster without Storage provides several advantages:

+
    +
  • Removal of state from the worker nodes
  • +
  • Reduced resource usage
  • +
  • Reduced complexity and operational burden of managing Workflow
  • +
+

See Configuring Object Storage for details on removing this operational complexity.

+

Review Security Considerations

+

There are some additional security-related considerations when running Workflow in production. +See [Security Considerations][] for details.

+

Registration is Admin-Only

+

By default, registration with the Workflow controller is in “admin_only” mode. The first user +to run a drycc register command becomes the initial “admin” user, and registrations after that +are disallowed unless requested by an admin.

+

Please see the following documentation to learn about changing registration mode:

+ +

Disable Grafana Signups

+

It is also recommended to disable signups for the Grafana dashboards.

+

Please see the following documentation to learn about disabling Grafana signups:

+ +

Running Workflow with RBAC

+

If your cluster has RBAC amongst your authorization modes ($ kubectl api-versions should contains rbac.authorization.k8s.io) it may be necessary to enable RBAC in Workflow. +This can be achieved by setting use_rbac in the global section of values.yaml to true, or by adding --set=global.use_rbac=true to the $ helm install/upgrade command. +RBAC support was announced in Kubernetes-1.5 and is enabled by default if:

+
    +
  • your Kubernetes cluster is in GKE
  • +
  • your Kubernetes cluster built with kubeadm
  • +
+

Note: helm may need to be given specific permissions under RBAC if not already done.

+

Attention: Azure ACS Kubernetes clusters are not RBAC-enabled for today due to lack in authentication strategy. Feel free to watch this PR for more details.

+ +
+ + + + + + + + + + + +
+ +

6.7 - Upgrading Workflow

+
Drycc Workflow releases may be upgraded in-place with minimal downtime.
+

This upgrade process requires:

+ +

Upgrade Process

+

!!! note +If upgrading from a Helm Classic install, you’ll need to ‘migrate’ the cluster to a Kubernetes Helm installation. See Workflow-Migration for steps.

+

Step 1: Apply the Workflow upgrade

+

Helm will remove all components from the previous release. Traffic to applications deployed through +Workflow will continue to flow during the upgrade. No service interruptions should occur.

+

If Workflow is not configured to use off-cluster Postgres, the Workflow API will experience a brief +period of downtime while the database recovers from backup.

+

First, find the name of the release helm gave to your deployment with helm ls, then run

+
$ helm upgrade <release-name> oci://registry.drycc.cc/charts/workflow
+

Note: If using off-cluster object storage on gcs and/or off-cluster registry using gcr and intending to upgrade from a pre-v2.10.0 chart to v2.10.0 or greater, the key_json values will now need to be pre-base64-encoded. Therefore, assuming the rest of the custom/off-cluster values are defined in the existing values.yaml used for previous installs, the following may be run:

+
$ B64_KEY_JSON="$(cat ~/path/to/key.json | base64 -w 0)"
+$ helm upgrade <release_name> drycc/workflow -f values.yaml --set gcs.key_json="${B64_KEY_JSON}",registry-token-refresher.gcr.key_json="${B64_KEY_JSON}"
+

Alternatively, simply replace the appropriate values in values.yaml and do without the --set +parameter. Make sure to wrap it in single quotes as double quotes will give a parser error when +upgrading.

+

Step 2: Verify Upgrade

+

Verify that all components have started and passed their readiness checks:

+
$ kubectl --namespace=drycc get pods
+NAME                                     READY     STATUS    RESTARTS   AGE
+drycc-builder-2448122224-3cibz            1/1       Running   0          5m
+drycc-controller-1410285775-ipc34         1/1       Running   3          5m
+drycc-controller-celery-694f75749b-cmxxn  3/3       Running   0          5m
+drycc-database-e7c5z                      1/1       Running   0          5m
+drycc-logger-cgjup                        1/1       Running   3          5m
+drycc-logger-fluentbit-45h7j              1/1       Running   0          5m
+drycc-logger-fluentbit-4z7lw              1/1       Running   0          5m
+drycc-logger-fluentbit-k2wsw              1/1       Running   0          5m
+drycc-logger-fluentbit-skdw4              1/1       Running   0          5m
+drycc-redis-8nazu                         1/1       Running   0          5m
+drycc-monitor-grafana-tm266               1/1       Running   0          5m
+drycc-monitor-telegraf-51zel              1/1       Running   1          5m
+drycc-monitor-telegraf-cdasg              1/1       Running   0          5m
+drycc-monitor-telegraf-hea6x              1/1       Running   0          5m
+drycc-monitor-telegraf-r7lsg              1/1       Running   0          5m
+drycc-registry-1814324048-yomz5           1/1       Running   0          5m
+drycc-registry-proxy-4m3o4                1/1       Running   0          5m
+drycc-registry-proxy-no3r1                1/1       Running   0          5m
+drycc-registry-proxy-ou8is                1/1       Running   0          5m
+drycc-registry-proxy-zyajl                1/1       Running   0          5m
+drycc-rabbitmq-0                          1/1       Running   0          5m
+

Step 3: Upgrade the Drycc Client

+

Users of Drycc Workflow should now upgrade their drycc client to avoid getting WARNING: Client and server API versions do not match. Please consider upgrading. warnings.

+
curl -sfL https://www.drycc.cc/install-cli.sh | bash - && sudo mv drycc $(which drycc)
+
+
+ + + + + + + + + + + + + + + +
+ +

7 - Troubleshooting

+
Troubleshooting is systematic approach to problem-solving.
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +

7.1 - Troubleshooting Workflow

+
Common issues that users have run into when provisioning Workflow are detailed below.
+

A Component Fails to Start

+

For information on troubleshooting a failing component, see +Troubleshooting with Kubectl.

+

An Application Fails to Start

+

For information on troubleshooting application deployment issues, see +Troubleshooting Applications.

+

Permission denied (publickey)

+

The most common problem for this issue is the user forgetting to run drycc keys:add or add their +private key to their SSH agent. To do so, run ssh-add ~/.ssh/id_rsa and try running +git push drycc master again.

+

If you happen get a Could not open a connection to your authentication agent +error after trying to run ssh-add command above, you may need to load the SSH +agent environment variables issuing the eval "$(ssh-agent)" command before.

+

Other Issues

+

Running into something not detailed here? Please open an issue or hop into +#community on Slack for help!

+ +
+ + + + + + + + + + + +
+ +

7.2 - Troubleshooting using Kubectl

+
Kubernetes provides a command line tool for communicating with a Kubernetes cluster’s control plane, using the Kubernetes API.
+

This document describes how one can use kubectl to debug any issues with the cluster.

+

Diving into the Components

+

Using kubectl, one can inspect the cluster’s current state. When Workflow is installed +with helm, Workflow is installed into the drycc namespace. To inspect if Workflow is +running, run:

+
$ kubectl --namespace=drycc get pods
+NAME                          READY     STATUS              RESTARTS   AGE
+drycc-builder-gqum7            0/1       ContainerCreating   0          4s
+drycc-controller-h6lk6         0/1       ContainerCreating   0          4s
+drycc-controller-celery-cmxxn  0/3       ContainerCreating   0          4s
+drycc-database-56v39           0/1       ContainerCreating   0          4s
+drycc-logger-fluentbit-xihr1   0/1       Pending             0          2s
+drycc-logger-grupg             0/1       ContainerCreating   0          3s
+drycc-storage-c2exb            0/1       Pending             0          3s
+drycc-monitor-grafana-9ccur    0/1       Pending             0          3s
+drycc-monitor-telegraf-dc3y3   0/1       Pending             0          2s
+drycc-registry-5bor6           0/1       Pending             0          3s
+drycc-rabbitmq-0               0/1       ContainerCreating   0          3s
+
+

!!! tip +To save precious keystrokes, alias kubectl --namespace=drycc to kd so it is easier to type +in the future.

+

To fetch the logs of a specific component, use kubectl logs:

+
$ kubectl --namespace=drycc logs drycc-controller-h6lk6
+system information:
+Django Version: 1.9.6
+Python 3.5.1
+addgroup: gid '0' in use
+Django checks:
+System check identified no issues (2 silenced).
+[...]
+
+

To dive into a running container to inspect its environment, use kubectl exec:

+
$ kubectl --namespace=drycc exec -it drycc-database-56v39 gosu postgres psql
+psql (13.4 (Debian 13.4-1.pgdg100+1))
+Type "help" for help.
+
+postgres=# \l
+                                                List of databases
+     Name          |  Owner   | Encoding |  Collate   |   Ctype    |   Access privileges
+-------------------+----------+----------+------------+------------+-----------------------
+ drycc_controller  | postgres | UTF8     | en_US.utf8 | en_US.utf8 |
+ drycc_passport    | postgres | UTF8     | en_US.utf8 | en_US.utf8 |
+ postgres          | postgres | UTF8     | en_US.utf8 | en_US.utf8 |
+ template0         | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
+                   |          |          |            |            | postgres=CTc/postgres
+ template1         | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
+                   |          |          |            |            | postgres=CTc/postgres
+(4 rows)
+postgres=# \connect drycc_controller
+You are now connected to database "drycc_controller" as user "postgres".
+drycc_controller=# \dt
+                                 List of relations
+ Schema |              Name              | Type  |      Owner
+--------+--------------------------------+-------+-------------------
+ public | api_app                        | table | drycc_controller
+ public | api_build                      | table | drycc_controller
+ public | api_certificate                | table | drycc_controller
+ public | api_config                     | table | drycc_controller
+ public | api_domain                     | table | drycc_controller
+ public | api_key                        | table | drycc_controller
+ public | api_push                       | table | drycc_controller
+ public | api_release                    | table | drycc_controller
+ public | auth_group                     | table | drycc_controller
+ --More--
+ drycc_controller=# SELECT COUNT(*) from api_app;
+ count
+-------
+     0
+(1 row)
+
+ +
+ + + + + + + + + + + +
+ +

7.3 - Troubleshooting Applications

+
This document describes how one can troubleshoot common issues when deploying or debugging an application that fails to start or deploy.
+

Application has a Dockerfile, but a Buildpack Deployment Occurs

+

When you deploy an application to Workflow using git push drycc master and the Builder +attempts to deploy using the Buildpack workflow, check the following steps:

+
    +
  1. Are you deploying the correct project?
  2. +
  3. Are you pushing the correct git branch (git push drycc <branch>)?
  4. +
  5. Is the Dockerfile in the project’s root directory?
  6. +
  7. Have you committed the Dockerfile to the project?
  8. +
+

Application was Deployed, but is Failing to Start

+

If you deployed your application but it is failing to start, you can use drycc logs to check +why the application fails to boot. Sometimes, the application container may fail to boot without +logging any information about the error. This typically occurs when the healthcheck configured for +the application fails. In this case, you can start by +troubleshooting using kubectl. You can inspect the application’s current +state by examining the pod deployed in the application’s namespace. To do that, run

+
$ kubectl --namespace=myapp get pods
+NAME                          READY     STATUS                RESTARTS   AGE
+myapp-web-1585713350-3brbo    0/1       CrashLoopBackOff      2          43s
+
+

We can then describe the pod and determine why it is failing to boot:

+
Events:
+  FirstSeen     LastSeen        Count   From                            SubobjectPath                           Type            Reason          Message
+  ---------     --------        -----   ----                            -------------                           --------        ------          -------
+  43s           43s             1       {default-scheduler }                                                    Normal          Scheduled       Successfully assigned myapp-web-1585713350-3brbo to kubernetes-node-1
+  41s           41s             1       {kubelet kubernetes-node-1}     spec.containers{myapp-web}              Normal          Created         Created container with container id b86bd851a61f
+  41s           41s             1       {kubelet kubernetes-node-1}     spec.containers{myapp-web}              Normal          Started         Started container with container id b86bd851a61f
+  37s           35s             1       {kubelet kubernetes-node-1}     spec.containers{myapp-web}              Warning         Unhealthy       Liveness probe failed: Get http://10.246.39.13:8000/healthz: dial tcp 10.246.39.13:8000: getsockopt: connection refused
+
+

In this instance, we set the healthcheck initial delay timeout for the application at 1 second, +which is too aggressive. The application needs some time to set up the API server after the +container has booted. By increasing the healthcheck initial delay timeout to 10 seconds, the +application is able to boot and is responding correctly.

+

See Custom Health Checks for more information on how to customize the application’s +health checks to better suit the application’s needs.

+ +
+ + + + + + + + + + + + + + + +
+ +

8 - Roadmap

+
Browse the ever-growing list of up-to-date, community driven roadmaps.
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +

8.1 - Planning Process

+
Drycc features a lightweight process that emphasizes openness and ensures every community member can be an integral part of planning for the future.
+

The Role of Maintainers

+

Maintainers lead the Drycc projects. Their duties include proposing the Roadmap, reviewing and integrating contributions and maintaining the vision of the project.

+

Open Roadmap

+

The Drycc Roadmap is a community document. While Maintainers propose the Roadmap, it gets discussed and refined in Release Planning Meetings.

+

Contributing to the Roadmap

+

Proposals and issues can be opened by anyone. Every member of the community is welcome to participate in the discussion by providing feedback and/or offering counter-proposals.

+

Release Milestones

+

The Roadmap gets delivered progressively via the Release Schedule. Releases are defined during Release Planning Meetings and managed using GitHub Milestones which track specific deliverables and work-in-progress.

+

Release Planning Meetings

+

Major decisions affecting the Roadmap are discussed during Release Planning Meetings on the first Thursday of each month, aligned with the Release Schedule.

+

Release Planning Meetings are open to the public with access coordinated via the Drycc #community Slack channel. +Notes from past meetings are below, along with links to a recording of the entire meeting on YouTube.

+

Credits

+

Thanks to Amy Lindburg and our friends at Podman for their inspiration.

+ +
+ + + + + + + + + + + +
+ +

8.2 - Drycc Workflow Roadmap

+
Drycc roadmap is community driven and managed through GitHub.
+

Drycc Workflow Roadmap

+

The Drycc Workflow Roadmap is a community document created as part of the open +Planning Process. Each roadmap item describes a high-level capability or +grouping of features that are deemed important to the future of Drycc.

+

Given the project’s rapid Release Schedule, roadmap +items are designed to provide a sense of direction over many releases.

+

Interactive drycc run /bin/bash

+

Provide the ability for developers to launch an interactive terminal session in +their application environment.

+

Related issues:

+ +

Log Streaming

+

Stream application logs via drycc logs -f https://github.com/drycc/drycc/issues/465

+

Teams and Permissions

+

Teams and Permissions represents a more flexible permissions model to allow +more nuanced control to applications, capabilities and resources on the +platform. There have been a number of proposals in this area which need to be +reconciled for Drycc Workflow before we begin implementation.

+

Related issues:

+ +

Monitoring

+ +

Workflow Addons/Services

+

Developers should be able to quickly and easily provision application +dependencies using a services or addon abstraction. +https://github.com/drycc/drycc/issues/231

+

Inbound/Outbound Webhooks

+

Drycc Workflow should be able to send and receive webhooks from external +systems. Facilitating integration with third party services like GitHub, +Gitlab, Slack, Hipchat.

+ + +
+ + + + + + + + + + + +
+ +

8.3 - Releases

+
Drycc’s release model allows applications to record and roll back to previous versions.
+

Drycc uses a continuous delivery approach for creating releases. Every merged commit that passes +testing results in a deliverable that can be given a semantic version tag and shipped.

+

The master git branch of a project should always work. Only changes considered ready to be +released publicly are merged.

+

Components Release as Needed

+

Drycc components release new versions as often as needed. Fixing a high priority bug requires the +project maintainer to create a new patch release. Merging a backward-compatible feature implies +a minor release.

+

By releasing often, each component release becomes a safe and routine event. This makes it faster +and easier for users to obtain specific fixes. Continuous delivery also reduces the work +necessary to release a product such as Drycc Workflow, which integrates several components.

+

“Components” applies not just to Drycc Workflow projects, but also to development and release +tools, to Container base images, and to other Drycc projects that do semantic version releases.

+

See “How to Release a Component” for more detail.

+

Workflow Releases Each Month

+

Drycc Workflow has a regular, public release cadence. From v2.8.0 onward, new Workflow feature +releases arrive on the first Thursday of each month. Patch releases are created at any time, +as needed. GitHub milestones are used to communicate the content and timing of major and minor +releases, and longer-term planning is visible at the Roadmap.

+

Workflow release timing is not linked to specific features. If a feature is merged before the +release date, it is included in the next release.

+

See “How to Release Workflow” for more detail.

+

Semantic Versioning

+

Drycc releases comply with semantic versioning, with the “public API” broadly +defined as:

+
    +
  • REST, gRPC, or other API that is network-accessible
  • +
  • Library or framework API intended for public use
  • +
  • “Pluggable” socket-level protocols users can redirect
  • +
  • CLI commands and output formats
  • +
+

In general, changes to anything a user might reasonably link to, customize, or integrate with +should be backward-compatible, or else require a major release. Drycc users can be confident that +upgrading to a patch or to a minor release will not break anything.

+

How to Release a Component

+

Most Drycc projects are “components” which produce a Container image or binary executable as a +deliverable. This section leads a maintainer through creating a component release.

+

Step 1: Update Code and Run the Release Tool

+

Major or minor releases should happen on the master branch. Patch releases +should check out the previous release tag and cherry-pick specific commits from master.

+

Note: if a patch release, the release artifact will have to be manually promoted by triggering +the component-promote job with the following values:

+
COMPONENT_NAME=<component name>
+COMPONENT_SHA=<patch commit sha>
+

Make sure you have the dryccrel release tool in your search $PATH.

+

Run dryccrel release once with a fake semver tag to proofread the changelog content. (If HEAD +of master is not what is intended for the release, add the --sha flag as described +in dryccrel release --help.)

+
$ dryccrel release controller v0.0.0
+Doing a dry run of the component release...
+skipping commit 943a49267eeb28546819a266654806cfcbae0e38
+
+Creating changelog for controller with tag v2.8.1 through commit 943a49267eeb28546819a266654806cfcbae0e38
+
+### v2.8.1 -> v0.0.0
+
+#### Fixes
+
+- [`615b834`](https://github.com/drycc/controller/commit/615b834f39cb68a854cc1f1e2f0f82d862ea2731) boot: Ensure DRYCC_DEBUG==true for debug output
+

Based on the changelog content, determine whether the component deserves a minor or patch +release. Run the command again with that semver tag and --dry-run=false. You will still be +asked for confirmation before the release is created:

+
$ dryccrel release controller v2.8.2 --dry-run=false
+skipping commit 943a49267eeb28546819a266654806cfcbae0e38
+
+Creating changelog for controller with tag v2.8.1 through commit 943a49267eeb28546819a266654806cfcbae0e38
+
+### v2.8.1 -> v2.8.2
+
+
+#### Fixes
+
+- [`615b834`](https://github.com/drycc/controller/commit/615b834f39cb68a854cc1f1e2f0f82d862ea2731) boot: Ensure DRYCC_DEBUG==true for debug output
+
+
+Please review the above changelog contents and ensure:
+  1. All intended commits are mentioned
+  2. The changes agree with the semver release tag (major, minor, or patch)
+
+Create release for Drycc Controller v2.8.2? [y/n]: y
+New release is available at https://github.com/drycc/controller/releases/tag/v2.8.2
+

Step 2: Verify the Component is Available

+

Tagging the component (see Step 1) +starts a CI job that eventually results in an artifact being made available for public download. +Please see the CI flow diagrams for details.

+

Double-check that the artifact is available, either by a podman pull command or by running the +appropriate installer script.

+

If the artifact can’t be downloaded, ensure that its CI release jobs are still in progress, or +fix whatever issue arose in the pipeline. For example, the +master merge pipeline +may have failed to promote the :git-abc1d23 candidate image and needs to be restarted with +that component and commit.

+

If the component has a correlating Kubernetes Helm chart, +this chart will also be packaged, signed and uploaded to its production chart repo. Please +verify it can be fetched (and verified):

+
$ helm fetch oci://registry.drycc.cc/charts/controller --version 1.0.0
+Verification: &{0xc4207ec870 sha256:026e766e918ff28d2a7041bc3d560d149ee7eb0cb84165c9d9d00a3045ff45c3 controller-v1.0.1.tgz}
+

How to Release Workflow

+

Drycc Workflow integrates multiple component releases together with a Kubernetes Helm chart +deliverable. This section leads a maintainer through creating a Workflow release.

+

Step 1: Set Environment Variables

+

Export two environment variables that will be used in later steps:

+
export WORKFLOW_RELEASE=v2.17.0 WORKFLOW_PREV_RELEASE=v2.16.0  # for example
+

Step 2: Tag Supporting Repositories

+

Some Workflow components not in the Helm chart must also be tagged in sync with the release. +Follow the component release process above and ensure that +these components are tagged:

+ +

The version number for drycc/workflow-cli should always match the overall Workflow version +number.

+

Step 3: Create Helm Chart

+

To create and stage a release candidate chart for Workflow, we will build the workflow-chart-stage job with the following parameters:

+

RELEASE_TAG=$WORKFLOW_RELEASE

+

This job will gather all of the latest component release tags and use these to specify the versions of all component charts. +It will then package the Workflow chart, upload it to the staging chart repo and kick off an e2e run against said chart.

+

Step 4: Manual Testing

+

Now it’s time to go above and beyond current CI tests. Create a testing matrix spreadsheet (copying +from the previous document is a good start) and sign up testers to cover all permutations.

+

Testers should pay special attention to the overall user experience, make sure upgrading from +earlier versions is smooth, and cover various storage configurations and Kubernetes versions and +infrastructure providers.

+

When showstopper-level bugs are found, the process is as follows:

+
    +
  1. Create a component PR that fixes the bug.
  2. +
  3. Once the PR passes and is reviewed, merge it and do a new +component release
  4. +
  5. Trigger the same workflow-chart-stage job as mentioned in Step 3 to upload the newly-generated Workflow release candidate chart to staging.
  6. +
+

Step 5: Release the Chart

+

When testing has completed without uncovering any new showstopper bugs, kick off the workflow-chart-release job with the following parameter:

+

RELEASE_TAG=$WORKFLOW_RELEASE

+

This job will copy the release candidate chart (now approved by CI and manual testing) from the staging repo to the production repo, signing +it if it has not done so already.

+

Step 6: Assemble Master Changelog

+

Each component already updated its release notes on GitHub with CHANGELOG content. We’ll now +generate the master changelog for the Workflow chart, consisting of all component and auxilliary repo changes.

+

We’ll employ the requirements.lock file from the WORKFLOW_PREV_RELEASE chart, as well as a repo-to-chart-name mapping file, this time invoking dryccrel changelog global to get all component changes between +the chart versions existing in the WORKFLOW_PREV_RELEASE chart and the most recent releases existing in GitHub. +(Therefore, if there are any unreleased commits in a component repo, they will not appear here):

+
helm fetch --untar oci://registry.drycc.cc/charts/workflow --version $WORKFLOW_PREV_RELEASE
+dryccrel changelog global workflow/requirements.lock map.json > changelog-$WORKFLOW_RELEASE.md
+

This master changelog should then be placed into a single gist. The file will also be added to the documentation +update PR created in the next step.

+

Step 7: Update Documentation

+

Create a new pull request at drycc/workflow that updates version references to the new release. +Use git grep $WORKFLOW_PREV_RELEASE to find any references, but be careful not to change +CHANGELOG.md.

+

Place the $WORKFLOW_RELEASE master changelog generated in Step 7 in the changelogs directory. +Make sure to add a header to the page to make it clear that this is for a Workflow release, e.g.:

+
## Workflow v2.16.0 -> v2.17.0
+

Once the PR has been reviewed and merged, do a component release of +drycc/workflow itself. The version number for drycc/workflow should always match the +overall Workflow version number.

+

Step 8: Close GitHub Milestones

+

Create a pull request at seed-repo to close the release +milestone and create the next one. When changes are merged to seed-repo, milestones on all +relevant projects will be updated. If there are open issues attached to the milestone, move them +to the next upcoming milestone before merging the pull request.

+

Milestones map to Drycc Workflow releases in drycc/workflow. These milestones do not correspond +to individual component release tags.

+

Step 9: Release Workflow CLI Stable

+

Now that the $WORKFLOW_RELEASE version of Workflow CLI has been vetted, we can push stable artifacts based on this version.

+

Kick off https://ci.drycc.info/job/workflow-cli-build-stable/ with the TAG build parameter of $WORKFLOW_RELEASE +and then verify stable artifacts are available and appropriately updated after the job completes:

+
$ curl -sfL https://www.drycc.cc/install-cli.sh | bash -
+$ ./drycc version
+# (Should show $WORKFLOW_RELEASE)
+

Step 10: Let Everyone Know

+

Let the rest of the team know they can start blogging and tweeting about the new Workflow release. +Post a message to the #company channel on Slack. Include a link to the released chart and to the +master CHANGELOG:

+
@here Drycc Workflow v2.17.0 is now live!
+Master CHANGELOG: https://drycc.info/docs/workflow/changelogs/v2.17.0/
+

You’re done with the release. Nice job!

+ +
+ + + + + + + + + + + + + + + +
+ +

9 - Contribution Guidelines

+
This HowTo is for project maintainers who need a Contributing Guide for their project.
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +

9.1 - Contributor Overview

+
Interested in contributing to a Drycc project? There are lots of ways to help.
+

File Bugs & Enhancements

+

Find a bug? Want to see a new feature? Have a request for the maintainers? Open a Github issue in the applicable repository and we’ll get the conversation started.

+

Our official support channel is the Drycc #community Slack channel.

+

Don’t know what the applicable repository for an issue is? Open up in issue in workflow or chat with a maintainer in the Drycc #community Slack channel and we’ll make sure it gets to the right place.

+

Additionally, take a look at the troubleshooting documentation for common issues.

+

Before opening a new issue, it’s helpful to search and see if anyone else has already reported the problem. You can search through a list of issues for all Drycc projects here.

+

Write Documentation

+

We are always looking to improve and expand our documentation. Most docs reside in the drycc/workflow repository. Simply fork the project, update docs and send us a pull request.

+

Contribute Code

+

We are always looking for help improving the core platform, other workloads, tooling, and test coverage. Interested in contributing code? Let’s chat in the Drycc #community Slack channel. Make sure to check out issues tagged easy fix or help wanted.

+

When you’re ready to begin writing code, review Design Documents and get your Development Environment set up.

+

By contributing to any Drycc project you agree to its Developer Certificate of Origin (DCO). This document was created by the Linux Kernel community and is a simple statement that you, as a contributor, have the legal right to make the contribution.

+

Triage Issues

+

If you don’t have time to code, consider helping with triage. The community will thank you for saving them time by spending some of yours. See Triaging Issues for more info.

+

Share your Experience

+

Interact with the community on our user mailing list or live in our Drycc #community Slack channel, where you can chat with other Drycc Workflow users any time of day.

+ +
+ + + + + + + + + + + +
+ +

9.2 - Design Documents

+
Before submitting a pull request which will significantly alter the behavior of any Drycc component.
+

Before submitting a pull request which will significantly alter the behavior of any Drycc component, such as a new feature or major refactoring, contributors should first open an issue representing a design document.

+

Goals

+

Design documents help ensure project contributors:

+
    +
  • Involve stakeholders as early as possible in a feature’s development
  • +
  • Ensure code changes accomplish the original motivations and design goals
  • +
  • Establish clear acceptance criteria for a feature or change
  • +
  • Enforce test-driven design methodology and automated test coverage
  • +
+

Contents

+

Design document issues should be named Design Doc: <change description> and contain the following sections:

+

Goal

+

This section should briefly describe the proposed change and the motivations behind it. Tests will be written to ensure this design goal is met by the change.

+

This section should also reference a separate GitHub issue tracking the feature or change, which will typically be assigned to a release milestone.

+

Code Changes

+

This section should detail the code changes necessary to accomplish the change, as well as the proposed implementation. This should be as detailed as necessary to help reviewers understand the change.

+

Tests

+

All changes should be covered by automated tests, either unit or integration tests (ideally both). This section should detail how tests will be written to validate that the change accomplishes the design goals and doesn’t introduce any regressions.

+

If a change cannot be sufficiently covered by automated testing, the design should be reconsidered. If there is no test coverage whatsoever for an affected section of code, a separate issue should be filed to integrate automated testing with that section of the codebase.

+

The tests described here also form the acceptance criteria for the change, so that when it’s completed maintainers can merge the pull request after confirming the tests pass CI.

+

Approval

+

A design document follows the same merge approval review process as final pull requests do, and maintainers will take extra care to ensure that any stakeholders for the change are included in the discussion and review of the design document.

+

Once the design is accepted, the author can complete the change and submit a pull request for review. The pull request should close both the design document for the change as well as any issues that either track the issue or are closed as a result of the change.

+

See Submitting a Pull Request for more information on pull request and commit message formatting.

+ +
+ + + + + + + + + + + +
+ +

9.3 - Development Environment

+
This document is for developers who are interested in working directly on the Drycc codebase.
+

In this guide, we walk you through the process of setting up a development environment that is suitable for hacking on most Drycc components.

+

We try to make it simple to hack on Drycc components. However, there are necessarily several moving pieces and some setup required. We welcome any suggestions for automating or simplifying this process.

+

!!! note +The Drycc team is actively engaged in containerizing Go and Python based development environments tailored specifically for Drycc development in order to minimize the setup required. This work is ongoing. Refer to the drycc/router project for a working example of a fully containerized development environment.

+

If you’re just getting into the Drycc codebase, look for GitHub issues with the label easy-fix. These are more straightforward or low-risk issues and are a great way to become more familiar with Drycc.

+

Prerequisites

+

In order to successfully compile and test Drycc binaries and build Container images of Drycc components, the following are required:

+
    +
  • git
  • +
  • Go 1.5 or later, with support for compiling to linux/amd64
  • +
  • glide
  • +
  • golint
  • +
  • shellcheck
  • +
  • Podman (in a non-Linux environment, you will additionally want [Podman Machine][machine])
  • +
+

For drycc/controller, in particular, you will also need:

+
    +
  • Python 2.7 or later (with pip)
  • +
  • virtualenv (sudo pip install virtualenv)
  • +
+

In most cases, you should simply install according to the instructions. There are a few special cases, though. We cover these below.

+

Configuring Go

+

If your local workstation does not support the linux/amd64 target environment, you will have to install Go from source with cross-compile support for that environment. This is because some of the components are built on your local machine and then injected into a container.

+

Homebrew users can just install with cross compiling support:

+
$ brew install go --with-cc-common
+

It is also straightforward to build Go from source:

+
$ sudo su
+$ curl -sSL https://golang.org/dl/go1.5.src.tar.gz | tar -v -C /usr/local -xz
+$ cd /usr/local/go/src
+$ # compile Go for our default platform first, then add cross-compile support
+$ ./make.bash --no-clean
+$ GOOS=linux GOARCH=amd64 ./make.bash --no-clean
+

Once you can compile to linux/amd64, you should be able to compile Drycc components as normal.

+

Fork the Repository

+

Once the prerequisites have been met, we can begin to work with Drycc components.

+

Begin at Github by forking whichever Drycc project you would like to contribute to, then clone that fork locally. Since Drycc is predominantly written in Go, the best place to put it is under $GOPATH/src/github.com/drycc/.

+
$ mkdir -p  $GOPATH/src/github.com/drycc
+$ cd $GOPATH/src/github.com/drycc
+$ git clone git@github.com:<username>/<component>.git
+$ cd <component>
+

!!! note +By checking out the forked copy into the namespace github.com/drycc/<component>, we are tricking the Go toolchain into seeing our fork as the “official” source tree.

+

If you are going to be issuing pull requests to the upstream repository from which you forked, we suggest configuring Git such that you can easily rebase your code to the upstream repository’s main branch. There are various strategies for doing this, but the most common is to add an upstream remote:

+
$ git remote add upstream https://github.com/drycc/<component>.git
+

For the sake of simplicity, you may want to point an environment variable to your Drycc code - the directory containing one or more Drycc components:

+
$ export DRYCC=$GOPATH/src/github.com/drycc
+

Throughout the rest of this document, $DRYCC refers to that location.

+

Alternative: Forking with a Pushurl

+

A number of Drycc contributors prefer to pull directly from drycc/<component>, but push to <username>/<component>. If that workflow suits you better, you can set it up this way:

+
$ git clone git@github.com:drycc/<component>.git
+$ cd drycc
+$ git config remote.origin.pushurl git@github.com:<username>/<component>.git
+

In this setup, fetching and pulling code will work directly with the upstream repository, while pushing code will send changes to your fork. This makes it easy to stay up to date, but also make changes and then issue pull requests.

+

Make Your Changes

+

With your development environment set up and the code you wish to work on forked and cloned, you can begin making your changes.

+

Test Your Changes

+

Drycc components each include a comprehensive suite of automated tests, mostly written in Go. See testing for instructions on running the tests.

+

Deploying Your Changes

+

Although writing and executing tests are critical to ensuring code quality, most contributors will also want to deploy their changes to a live environment, whether to make use of those changes or to test them further. The remainder of this section documents the procedure for running officially released Drycc components in a development cluster and replacing any one of those with your customizations.

+

Running a Kubernetes Cluster for Development

+

To run a Kubernetes cluster locally or elsewhere to support your development activities, refer to Drycc installation instructions here.

+

Using a Development Registry

+

To facilitate deploying Container images containing your changes to your Kubernetes cluster, you will need to make use of a Container registry. This is a location to where you can push your custom-built images and from where your Kubernetes cluster can retrieve those same images.

+

If your development cluster runs locally (in Minikube, for instance), the most efficient and economical means of achieving this is to run a Container registry locally as a Container container.

+

To facilitate this, most Drycc components provide a make target to create such a registry:

+
$ make dev-registry
+

In a Linux environment, to begin using the registry:

+
export DRYCC_REGISTRY=<IP of the host machine>:5000
+

In non-Linux environments:

+
export DRYCC_REGISTRY=<IP of the drycc Container Machine VM>:5000
+

If your development cluster runs on a cloud provider such as Google Container Engine, a local registry such as the one above will not be accessible to your Kubernetes nodes. In such cases, a public registry such as [DockerHub][dh] or quay.io will suffice.

+

To use DockerHub for this purpose, for instance:

+
$ export DRYCC_REGISTRY="registry.drycc.cc"
+$ export IMAGE_PREFIX=<your DockerHub username>
+

To use quay.io:

+
$ export DRYCC_REGISTRY=quay.io
+$ export IMAGE_PREFIX=<your quay.io username>
+

Note the importance of the trailing slash.

+

Dev / Deployment Workflow

+

With a functioning Kubernetes cluster and the officially released Drycc components installed onto it, deployment and further testing of any Drycc component you have made changes to is facilitated by replacing the officially released component with a custom built image that contains your changes. Most Drycc components include Makefiles with targets specifically intended to facilitate this workflow with minimal friction.

+

In the general case, this workflow looks like this:

+
    +
  1. Update source code and commit your changes using git
  2. +
  3. Use make build to build a new Container image
  4. +
  5. Use make dev-release to generate Kubernetes manifest(s)
  6. +
  7. Use make deploy to restart the component using the updated manifest
  8. +
+

This can be shortened to a one-liner using just the deploy target:

+
$ make deploy
+

Useful Commands

+

Once your customized Drycc component has been deployed, here are some helpful commands that will allow you to inspect your cluster and to troubleshoot, if necessary:

+

See All Drycc Pods

+
$ kubectl --namespace=drycc get pods
+

Describe a Pod

+

This is often useful for troubleshooting pods that are in pending or crashed states:

+
$ kubectl --namespace=drycc describe -f <pod name>
+

Tail Logs

+
$ kubectl --namespace=drycc logs -f <pod name>
+

Django Shell

+

Specific to drycc/controller

+
$ kubectl --namespace=drycc exec -it <pod name> -- python manage.py shell
+

Have commands other Drycc contributors might find useful? Send us a PR!

+

Pull Requests

+

Satisfied with your changes? Share them!

+

Please read Submitting a Pull Request. It contains a checklist of +things you should do when proposing a change to any Drycc component.

+ +
+ + + + + + + + + + + +
+ +

9.4 - Testing Drycc

+
Each Drycc component is one among an ecosystem of such components - many of which integrate with one another - which makes testing each component thoroughly a matter of paramount importance.
+

Each Drycc component includes its own suite of style checks, unit tests, and black-box type functional tests.

+

Integration tests verify the behavior of the Drycc components together as a system and are provided separately by the drycc/workflow-e2e project.

+

GitHub pull requests for all Drycc components are tested automatically by the Travis CI continuous integration system. Contributors should run the same tests locally before proposing any changes to the Drycc codebase.

+

Set Up the Environment

+

Successfully executing the unit and functional tests for any Drycc component requires that the Development Environment is set up first.

+

Run the Tests

+

The style checks, unit tests, and functional tests for each component can all be executed via make targets:

+

To execute style checks:

+
$ make test-style
+

To execute unit tests:

+
$ make test-unit
+

To execute functional tests:

+
$ make test-functional
+

To execute style checks, unit tests, and functional tests all in one shot:

+
$ make test
+

To execute integration tests, refer to drycc/workflow-e2e documentation.

+ +
+ + + + + + + + + + + +
+ +

9.5 - Submitting a Pull Request

+
Proposed changes to Drycc projects are made as GitHub pull requests.
+

Design Document

+

Before opening a pull request, ensure your change also references a design document if the contribution is substantial. For more information, see Design Documents.

+

Single Issue

+

It’s hard to reach agreement on the merit of a PR when it isn’t focused. When fixing an issue or implementing a new feature, resist the temptation to refactor nearby code or to fix that potential bug you noticed. Instead, open a separate issue or pull request. Keeping concerns separated allows pull requests to be tested, reviewed, and merged more quickly.

+

Squash and rebase the commit or commits in your pull request into logical units of work with git. Include tests and documentation changes in the same commit, so that a revert would remove all traces of the feature or fix.

+

Most pull requests will reference a GitHub issue. In the PR description - not in the commit itself - include a line such as “closes #1234”. The issue referenced will automatically be closed when your PR is merged.

+

Include Tests

+

If you significantly alter or add functionality to a component that impacts the broader Drycc Workflow PaaS, you should submit a complementary PR to modify or amend end-to-end integration tests. These integration tests can be found in the drycc/workflow-e2e repository.

+

See testing for more information.

+

Include Docs

+

Changes to any Drycc Workflow component that could affect a user’s experience also require a change or addition to the relevant documentation. For most Drycc components, this involves updating the component’s own documentation. In some cases where a component is tightly integrated into drycc/workflow, its documentation must also be updated.

+

Cross-repo commits

+

If a pull request is part of a larger piece of work involving one or more additional commits in other Workflow repositories, these commits can be referenced in the last PR to be submitted. The downstream e2e test job will then supply every referenced commit (derived from PR issue number supplied) to the test runner so it can source the necessary Container images for inclusion in the generated Workflow chart to be tested.

+

For example, consider paired commits in drycc/controller and drycc/workflow-e2e. The commit body for the first PR in drycc/workflow-e2e would look like:

+
feat(foo_test): add e2e test for feature foo
+
+[skip e2e] test for controller#42
+

Adding [skip e2e] forgoes the e2e tests on this commit. This and any other required PRs aside from the final PR should be submitted first, so that their respective build and image push jobs run.

+

Lastly, the final PR in drycc/controller should be created with the required PR number(s) listed, in the form of [Rr]equires <repoName>#<pullRequestNumber>, for use by the downstream e2e run.

+
feat(foo): add feature foo
+
+Requires workflow-e2e#42
+

Code Standards

+

Drycc components are implemented in Go and Python. For both languages, we agree with The Zen of Python, which emphasizes simple over clever. Readability counts.

+

Go code should always be run through gofmt on the default settings. Lines of code may be up to 99 characters long. Documentation strings and tests are required for all exported functions. Use of third-party go packages should be minimal, but when doing so, such dependencies should be managed via the glide tool.

+

Python code should always adhere to PEP8, the python code style guide, with the exception that lines of code may be up to 99 characters long. Docstrings and tests are required for all public methods, although the flake8 tool used by Drycc does not enforce this.

+

Commit Style

+

We follow a convention for commit messages borrowed from CoreOS, who borrowed theirs +from AngularJS. This is an example of a commit:

+
feat(scripts/test-cluster): add a cluster test command
+
+this uses tmux to setup a test cluster that you can easily kill and
+start for debugging.
+

To make it more formal, it looks something like this:

+
{type}({scope}): {subject}
+<BLANK LINE>
+{body}
+<BLANK LINE>
+{footer}
+

The allowed {types} are as follows:

+
    +
  • feat -> feature
  • +
  • fix -> bug fix
  • +
  • docs -> documentation
  • +
  • style -> formatting
  • +
  • ref -> refactoring code
  • +
  • test -> adding missing tests
  • +
  • chore -> maintenance
  • +
+

The {scope} can be anything specifying the location(s) of the commit change(s).

+

The {subject} needs to be an imperative, present tense verb: “change”, not “changed” nor +“changes”. The first letter should not be capitalized, and there is no dot (.) at the end.

+

Just like the {subject}, the message {body} needs to be in the present tense, and includes +the motivation for the change, as well as a contrast with the previous behavior. The first +letter in a paragraph must be capitalized.

+

All breaking changes need to be mentioned in the {footer} with the description of the +change, the justification behind the change and any migration notes required.

+

Any line of the commit message cannot be longer than 72 characters, with the subject line +limited to 50 characters. This allows the message to be easier to read on GitHub as well +as in various git tools.

+

Merge Approval

+

Any code change - other than a simple typo fix or one-line documentation change - requires at least two Drycc maintainers to accept it. Maintainers tag pull requests with “LGTM1” and “LGTM2” (Looks Good To Me) labels to indicate acceptance.

+

No pull requests can be merged until at least one core maintainer signs off with an LGTM. The other LGTM can come from either a core maintainer or contributing maintainer.

+

If the PR is from a Drycc maintainer, then he or she should be the one to close it. This keeps the commit stream clean and gives the maintainer the benefit of revisiting the PR before deciding whether or not to merge the changes.

+

An exception to this is when an errant commit needs to be reverted urgently. If necessary, a PR that only reverts a previous commit can be merged without waiting for LGTM approval.

+ +
+ + + + + + + + + + + +
+ +

9.6 - Community

+
Drycc is an open source project that anyone in the community can use, improve, and enjoy. We’d love you to join us! Here’s a few ways to find out what’s happening and get involved.
+

Drycc software is fully open source. As such, the “Drycc community” consists of anyone who uses the Drycc software and participates in its evolution, whether by answering questions, finding bugs, suggesting enhancements, or writing documentation or code.

+

Drycc development is coordinated through numerous project repositories on GitHub. Anyone can check out the source code for any Drycc component, fork it, make improvements, and create a pull request to offer those changes back to the Drycc community.

+

Engine Yard maintains the numerous Drycc projects, and as such, decides what ends up in the official GitHub repositories. Drycc depends on the contributions of the community; the maintainers will not ignore pull requests or issues.

+

Drycc uses the timeless, highly efficient, and totally unfair system known as “Benevolent Dictator for Life” (BDFL). Gabriel Monroy, the creator of Drycc, is our BDFL and has final say over all decisions related to Drycc.

+

Open Source Bounties

+

Drycc projects are bounty-friendly. We believe open source bounty sites can be constructive tools in the development of open source software. Community members are encouraged to a) offer bounties and b) receive bounties for open source contributions that benefit everyone. The Drycc maintainers, however, will not accept bounties on this project but are more than happy to help community members attempting bounties.

+ +
+ + + + + + + + + + + +
+ +

9.7 - Triaging Issues

+
Issue triage provides an important way to contribute to an open source project.
+

Triage helps ensure issues resolve quickly by:

+
    +
  • Describing the issue’s intent and purpose is conveyed precisely. This is necessary because it can be difficult for an issue to explain how an end user experiences an problem and what actions they took.
  • +
  • Giving a contributor the information they need before they commit to resolving an issue.
  • +
  • Lowering the issue count by preventing duplicate issues.
  • +
  • Streamlining the development process by preventing duplicate discussions.
  • +
+

If you don’t have time to code, consider helping with triage. The community will thank you for saving them time by spending some of yours.

+

Ensure the Issue Contains Basic Information

+

Before triaging an issue very far, make sure that the issue’s author provided the standard issue information. This will help you make an educated recommendation on how this to categorize the issue. Standard information that should be included in most issues are things such as:

+
    +
  • the version(s) of Drycc this issue affects
  • +
  • a reproducible case if this is a bug
  • +
  • page URL if this is a docs issue or the name of a man page
  • +
+

Depending on the issue, you might not feel all this information is needed. Use your best judgment. If you cannot triage an issue using what its author provided, explain kindly to the author that they must provide the above information to clarify the problem.

+

If the author provides the recommended information but you are still unable to triage the issue, request additional information. Do this kindly and politely because you are asking for more of the author’s time.

+

If the author does not respond requested information within the timespan of a week, close the issue with a kind note stating that the author can request for the issue to be reopened when the necessary information is provided.

+

Classifying the Issue

+

An issue can have multiple of the following labels:

+

Issue Kind

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KindDescription
bugBugs are bugs. The cause may or may not be known at triage time so debugging should be taken account into the time estimate.
docsWriting documentation, man pages, articles, blogs, or other significant word-driven task.
enhancementEnhancements can drastically improve usability or performance of a component.
questionContains a user or contributor question requiring a response.
securitySecurity-related issues such as TLS encryption, network segregation, authn/authz features, etc.
+

Functional Area

+
    +
  • builder
  • +
  • cache
  • +
  • contrib and provisioning
  • +
  • client
  • +
  • controller
  • +
  • database
  • +
  • docs
  • +
  • kubernetes
  • +
  • registry
  • +
  • router
  • +
  • store (Ceph)
  • +
  • tests
  • +
+

Easy Fix

+

“Easy Fix” issues are a way for a new contributor to find issues that are fit for their experience level. These issues are typically for users who are new to Drycc, and possibly Go, and is looking to help while learning the basics.

+

Prioritizing issues

+

When attached to a specific milestone, an issue can be attributed one of the following labels to indicate their degree of priority.

+ + + + + + + + + + + + + + + + + +
PriorityDescription
priority 0Urgent: Security, critical bugs, blocking issues. Drop everything and fix this today, then consider creating a patch release.
priority 1Serious: Impedes user actions or is a regression. Fix this before the next planned release.
+

And that’s it. That should be all the information required for a new or existing contributor to come in an resolve an issue.

+ +
+ + + + + + + + + + + +
+ +

9.8 - Conduct

+
The Drycc community welcomes and encourages participation by everyone.
+

Conduct

+

The Drycc community welcomes and encourages participation by everyone.

+

No matter how you identify yourself or how others perceive you: we welcome you. We welcome contributions from everyone as long as they interact constructively with our community.

+

The Drycc developer community continues to grow, and it is inevitable that disagreements and conflict will arise. We ask that participants conduct themselves according to these principles:

+
    +
  1. +

    Be welcoming, friendly, and patient.

    +
  2. +
  3. +

    Be considerate.

    +
  4. +
+

Your work will be used by other people, and you in turn will depend on the work of others. Any decision you take will affect users and colleagues, and you should take those consequences into account when making decisions. Remember that we’re a world-wide community, so you might not be communicating in someone else’s primary language.

+
    +
  1. Be respectful.
  2. +
+

Not all of us will agree all the time, but disagreement is no excuse for poor behavior and bad manners. We might all experience some frustration now and then, but we cannot allow that frustration to turn into a personal attack. It’s important to remember that a community where people feel uncomfortable or threatened is not a productive one.

+
    +
  1. Be careful in the words that you choose.
  2. +
+

Be kind to others. Do not insult or put down other participants. Behave professionally. Remember that harassment and sexist, racist, or exclusionary jokes are never appropriate for the community.

+

(Thanks to the Debian and Django communities for their text and +their inspiration.)

+ +
+ + + + + + + + + + + +
+ +

9.9 - Drycc Maintainers

+
This document serves to describe the leadership structure of the Drycc project, and list the current project maintainers.
+

What is a maintainer?

+

(Unabashedly stolen from the Podman project)

+

There are different types of maintainers, with different responsibilities, but +all maintainers have 3 things in common:

+
    +
  1. They share responsibility in the project’s success.
  2. +
  3. They have made a long-term, recurring time investment to improve the project.
  4. +
  5. They spend that time doing whatever needs to be done, not necessarily what +is the most interesting or fun.
  6. +
+

Maintainers are often under-appreciated, because their work is harder to appreciate. +It’s easy to appreciate a really cool and technically advanced feature. It’s harder +to appreciate the absence of bugs, the slow but steady improvement in stability, +or the reliability of a release process. But those things distinguish a good +project from a great one.

+

Drycc maintainers

+

Drycc has two groups of maintainers in addition to our beloved Benevolent Dictator for Life.

+

BDFL

+

Drycc follows the timeless, highly efficient and totally unfair system known as Benevolent dictator +for life.

+

Gabriel Monroy (@gabrtv), as creator of the Drycc project, serves as our +project’s BDFL. While the day-to-day project management is carried out by the maintainers, Gabriel +serves as the final arbiter of any disputes and has the final say on project direction.

+

Core maintainers

+

Core maintainers are exceptionally knowledgeable about all areas of Drycc. Some maintainers work on Drycc +full-time, although this is not a requirement.

+

The duties of a core maintainer include:

+
    +
  • Classify and respond to GitHub issues and review pull requests
  • +
  • Help to shape the Drycc roadmap and lead efforts to accomplish roadmap milestones
  • +
  • Participate actively in feature development and bug fixing
  • +
  • Answer questions and help users in the Drycc #community Slack channel
  • +
+

The current list of core maintainers can be seen here.

+

No pull requests can be merged until at least one core maintainer signs off with an +LGTM. The other LGTM can +come from either a core maintainer or contributing maintainer.

+

Contributing maintainers

+

Contributing maintainers are exceptionally knowledgeable about some but not necessarily all areas +of Drycc, and are often selected due to specific domain knowledge that complements the project (but +a willingness to continually contribute to the project is most important!). Often, +core maintainers will ask a contributing maintainer to weigh in on issues, pull requests, or +conversations where the contributing maintainer is knowledgeable.

+

The duties of a contributing maintainer are very similar to those of a core maintainer, but they are limited to areas of the Drycc project where the contributing maintainer is knowledgeable.

+

Contributing maintainers are defined in practice as those who have write access to the Drycc repository. All maintainers can review pull requests and add LGTM labels as appropriate.

+

Becoming a maintainer

+

The Drycc project wouldn’t be where it is today without its community. Many of the project’s +community members embody the spirit of maintainership, and have contributed substantially to +the project.

+

The contributing maintainers group was created in part so that exceptional members of the community +who have an interest in the continued success of the project have the opportunity to join the +core maintainers in guiding the future of Drycc.

+

Generally, potential contributing maintainers are selected by the Drycc core maintainers based in +part on the following criteria:

+
    +
  • Sustained contributions to the project over a period of time (usually months)
  • +
  • A willingness to help Drycc users on GitHub and in the Drycc #community Slack channel
  • +
  • A friendly attitude :)
  • +
+

The Drycc core maintainers must unanimously agree before inviting a community member to join as a +contributing maintainer, although in many cases the candidate has already been acting in the +capacity of a contributing maintainer for some time, and has been consulted on issues, pull requests, +etc.

+ +
+ + + + + + + + + + + + + + + +
+ +

10 - Reference Guide

+
Reference gxwuide definition and meaning.
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +

10.1 - Creating a Self-Signed SSL Certificate

+
A self-signed TLS/SSL certificate is not signed by a publicly trusted certificate authority (CA) but instead by the developer or company that is responsible for the website.
+

When using the app ssl feature for non-production applications or when installing SSL for the platform, you can avoid the costs associated with the SSL certificate by using a self-signed SSL certificate. Though the certificate implements full encryption, visitors to your site will see a browser warning indicating that the certificate should not be trusted.

+

Prerequisites

+

The openssl library is required to generate your own certificate. Run the following command in your local environment to see if you already have openssl installed.

+
$ which openssl
+/usr/bin/openssl
+
+

If the which command does not return a path then you will need to install openssl yourself:

+ + + + + + + + + + + + + + + + + + + + + +
If you have…Install with…
Mac OS XHomebrew: brew install openssl
Windowscomplete package .exe installed
Ubuntu Linuxapt-get install openssl
+

Generate Private Key and Certificate Signing Request

+

A private key and certificate signing request are required to create an SSL certificate. These can be generated with a few simple commands. When the openssl req command asks for a “challenge password”, just press return, leaving the password empty.

+
$ openssl genrsa -des3 -passout pass:x -out server.pass.key 2048
+...
+$ openssl rsa -passin pass:x -in server.pass.key -out server.key
+writing RSA key
+$ rm server.pass.key
+$ openssl req -new -key server.key -out server.csr
+...
+Country Name (2 letter code) [AU]:US
+State or Province Name (full name) [Some-State]:California
+...
+A challenge password []:
+...
+
+

Generate SSL Certificate

+

The self-signed SSL certificate is generated from the server.key private key and server.csr files.

+
$ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
+
+

The server.crt file is your site certificate suitable for use with Drycc’s SSL endpoint along with the server.key private key.

+ +
+ + + + + + + + + + + +
+ +

10.2 - Controller API v2.0

+
This is the v2.0 REST API for the Controller.
+

What’s New

+

New! format of POST /v2/apps/<app id>/run has changed.

+

Authentication

+

Register a New User

+

Example Request:

+
POST /v2/auth/register/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+
+{
+    "username": "test",
+    "password": "opensesame",
+    "email": "test@example.com"
+}
+

Optional Parameters:

+
{
+    "first_name": "test",
+    "last_name": "testerson"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "id": 1,
+    "last_login": "2014-10-19T22:01:00.601Z",
+    "is_superuser": true,
+    "username": "test",
+    "first_name": "test",
+    "last_name": "testerson",
+    "email": "test@example.com",
+    "is_staff": true,
+    "is_active": true,
+    "date_joined": "2014-10-19T22:01:00.601Z",
+    "groups": [],
+    "user_permissions": []
+}
+

Log in

+

Example Request:

+
POST /v2/auth/login/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+
+{"username": "test", "password": "opensesame"}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{"token": "abc123"}
+

Cancel Account

+

Example Request:

+
DELETE /v2/auth/cancel/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Regenerate Token

+
+

note

+

This command could require administrative privileges

+
+

Example Request:

+
POST /v2/auth/tokens/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional Parameters:

+
{
+    "username" : "test"
+    "all" : "true"
+}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{"token": "abc123"}
+

Change Password

+

Example Request:

+
POST /v2/auth/passwd/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "password": "foo",
+    "new_password": "bar"
+}
+

Optional parameters:

+
{"username": "testuser"}
+
+

note

+

Using the username parameter requires administrative privileges and makes the password parameter optional.

+
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Applications

+

List all Applications

+

Example Request:

+
GET /v2/apps HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "created": "2014-01-01T00:00:00UTC",
+            "id": "example-go",
+            "owner": "test",
+            "structure": {},
+            "updated": "2014-01-01T00:00:00UTC",
+            "url": "example-go.example.com",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+        }
+    ]
+}
+

Create an Application

+

Example Request:

+
POST /v2/apps/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+

Optional parameters:

+
{"id": "example-go"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example-go",
+    "owner": "test",
+    "structure": {},
+    "updated": "2014-01-01T00:00:00UTC",
+    "url": "example-go.example.com",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Destroy an Application

+

Example Request:

+
DELETE /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

List Application Details

+

Example Request:

+
GET /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example-go",
+    "owner": "test",
+    "structure": {},
+    "updated": "2014-01-01T00:00:00UTC",
+    "url": "example-go.example.com",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Update Application Details

+

Example Request:

+
POST /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional parameters:

+
{
+  "owner": "test"
+}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 1.8.0
+Content-Type: application/json
+

Retrieve Application Logs

+

Example Request:

+
GET /v2/apps/example-go/logs/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional URL Query Parameters:

+
?log_lines=
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: text/plain
+
+"16:51:14 drycc[api]: test created initial release\n"
+

Run one-off Commands

+
POST /v2/apps/example-go/run/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"command": "echo hi"}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{"exit_code": 0, "output": "hi\n"}
+

Certificates

+

List all Certificates

+

Example Request:

+
GET /v2/certs HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+  "count": 1,
+  "next": null,
+  "previous": null,
+  "results": [
+    {
+      "id": 22,
+      "owner": "test",
+      "san": [],
+      "domains": [],
+      "created": "2016-06-22T22:24:20Z",
+      "updated": "2016-06-22T22:24:20Z",
+      "name": "foo",
+      "common_name": "bar.com",
+      "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+      "expires": "2017-01-14T23:57:57Z",
+      "starts": "2016-01-15T23:57:57Z",
+      "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+      "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+    }
+  ]
+}
+

Get Certificate Details

+

Example Request:

+
GET /v2/certs/foo HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+  "id": 22,
+  "owner": "test",
+  "san": [],
+  "domains": [],
+  "created": "2016-06-22T22:24:20Z",
+  "updated": "2016-06-22T22:24:20Z",
+  "name": "foo",
+  "common_name": "bar.com",
+  "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+  "expires": "2017-01-14T23:57:57Z",
+  "starts": "2016-01-15T23:57:57Z",
+  "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+  "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+}
+

Create Certificate

+

Example Request:

+
POST /v2/certs/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{
+    "name": "foo"
+    "certificate": "-----BEGIN CERTIFICATE-----",
+    "key": "-----BEGIN RSA PRIVATE KEY-----"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+  "id": 22,
+  "owner": "test",
+  "san": [],
+  "domains": [],
+  "created": "2016-06-22T22:24:20Z",
+  "updated": "2016-06-22T22:24:20Z",
+  "name": "foo",
+  "common_name": "bar.com",
+  "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+  "expires": "2017-01-14T23:57:57Z",
+  "starts": "2016-01-15T23:57:57Z",
+  "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+  "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+}
+

Destroy a Certificate

+

Example Request:

+
DELETE /v2/certs/foo HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Attach a Domain to a Certificate

+

Example Request:

+
POST /v2/certs/foo/domain/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "domain": "test.com"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Remove a Domain from a Certificate

+

Example Request:

+
DELETE /v2/certs/foo/domain/test.com/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Pods

+

List all Pods

+

Example Request:

+
GET /v2/apps/example-go/pods/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "results": [
+        {
+            "name": "go-v2-web-e7dej",
+            "release": "v2",
+            "started": "2014-01-01T00:00:00Z",
+            "state": "up",
+            "type": "web"
+        }
+    ]
+}
+

List all Pods by Type

+

Example Request:

+
GET /v2/apps/example-go/pods/web/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "results": [
+        {
+            "name": "go-v2-web-e7dej",
+            "release": "v2",
+            "started": "2014-01-01T00:00:00Z",
+            "state": "up",
+            "type": "web"
+        }
+    ]
+}
+

Restart All Pods

+

Example Request:

+
POST /v2/apps/example-go/pods/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Restart Pods by Type

+

Example Request:

+
POST /v2/apps/example-go/pods/web/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Restart Pods by Type and Name

+

Example Request:

+
POST /v2/apps/example-go/pods/go-v2-web-atots/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Scale Pods

+

Example Request:

+
POST /v2/apps/example-go/scale/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"web": 3}
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Configuration

+

List Application Configuration

+

Example Request:

+
GET /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+      "PLATFORM": "drycc"
+    },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Create new Config

+

Example Request:

+
POST /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"values": {"HELLO": "world", "PLATFORM": "drycc"}}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+X-Drycc-Release: 3
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+        "DRYCC_APP": "example-go",
+        "DRYCC_RELEASE": "v3",
+        "HELLO": "world",
+        "PLATFORM": "drycc"
+
+    },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Unset Config Variable

+

Example Request:

+
POST /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"values": {"HELLO": null}}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+X-Drycc-Release: 4
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+        "DRYCC_APP": "example-go",
+        "DRYCC_RELEASE": "v4",
+        "PLATFORM": "drycc"
+   },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Domains

+

List Application Domains

+

Example Request:

+
GET /v2/apps/example-go/domains/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "app": "example-go",
+            "created": "2014-01-01T00:00:00UTC",
+            "domain": "example.example.com",
+            "owner": "test",
+            "updated": "2014-01-01T00:00:00UTC"
+        }
+    ]
+}
+

Add Domain

+

Example Request:

+
POST /v2/apps/example-go/domains/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{'domain': 'example.example.com'}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "domain": "example.example.com",
+    "owner": "test",
+    "updated": "2014-01-01T00:00:00UTC"
+}
+

Remove Domain

+

Example Request:

+
DELETE /v2/apps/example-go/domains/example.example.com HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Builds

+

List Application Builds

+

Example Request:

+
GET /v2/apps/example-go/build/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "dockerfile": "FROM drycc/slugrunner RUN mkdir -p /app WORKDIR /app ENTRYPOINT [\"/runner/init\"] ADD slug.tgz /app ENV GIT_SHA 060da68f654e75fac06dbedd1995d5f8ad9084db",
+    "image": "example-go",
+    "owner": "test",
+    "procfile": {
+        "web": "example-go"
+    },
+    "sha": "060da68f",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Create Application Build

+

Example Request:

+
POST /v2/apps/example-go/build/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"image": "drycc/example-go:latest"}
+

Optional Parameters:

+
{
+    "procfile": {
+      "web": "./cmd"
+    }
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+X-Drycc-Release: 4
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "dockerfile": "",
+    "image": "drycc/example-go:latest",
+    "owner": "test",
+    "procfile": {},
+    "sha": "",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Releases

+

List Application Releases

+

Example Request:

+
GET /v2/apps/example-go/releases/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 3,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "app": "example-go",
+            "build": "202d8e4b-600e-4425-a85c-ffc7ea607f61",
+            "config": "ed637ceb-5d32-44bd-9406-d326a777a513",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test changed nothing",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 3
+        },
+        {
+            "app": "example-go",
+            "build": "202d8e4b-600e-4425-a85c-ffc7ea607f61",
+            "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test deployed 060da68",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 2
+        },
+        {
+            "app": "example-go",
+            "build": null,
+            "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test created initial release",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 1
+        }
+    ]
+}
+

List Release Details

+

Example Request:

+
GET /v2/apps/example-go/releases/v2/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "build": null,
+    "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+    "created": "2014-01-01T00:00:00UTC",
+    "owner": "test",
+    "summary": "test created initial release",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+    "version": 1
+}
+

Rollback Release

+

Example Request:

+
POST /v2/apps/example-go/releases/rollback/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"version": 1}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{"version": 5}
+

Keys

+

List Keys

+

Example Request:

+
GET /v2/keys/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "created": "2014-01-01T00:00:00UTC",
+            "id": "test@example.com",
+            "owner": "test",
+            "public": "ssh-rsa <...>",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+        }
+    ]
+}
+

Add Key to User

+

Example Request:

+
POST /v2/keys/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "id": "example",
+    "public": "ssh-rsa <...>"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example",
+    "owner": "example",
+    "public": "ssh-rsa <...>",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Remove Key from User

+

Example Request:

+
DELETE /v2/keys/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Permissions

+

List Application Permissions

+
+

note

+

This does not include the app owner.

+
+

Example Request:

+
GET /v2/apps/example-go/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "users": [
+        "test",
+        "foo"
+    ]
+}
+

Create Application Permission

+

Example Request:

+
POST /v2/apps/example-go/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{"username": "example"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Remove Application Permission

+

Example Request:

+
DELETE /v2/apps/example-go/perms/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

List Administrators

+

Example Request:

+
GET /v2/admin/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 2,
+    "next": null
+    "previous": null,
+    "results": [
+        {
+            "username": "test",
+            "is_superuser": true
+        },
+        {
+            "username": "foo",
+            "is_superuser": true
+        }
+    ]
+}
+

Grant User Administrative Privileges

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
POST /v2/admin/perms HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{"username": "example"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Remove User’s Administrative Privileges

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
DELETE /v2/admin/perms/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Users

+

List all users

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
GET /v2/users HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "id": 1,
+            "last_login": "2014-10-19T22:01:00.601Z",
+            "is_superuser": true,
+            "username": "test",
+            "first_name": "test",
+            "last_name": "testerson",
+            "email": "test@example.com",
+            "is_staff": true,
+            "is_active": true,
+            "date_joined": "2014-10-19T22:01:00.601Z",
+            "groups": [],
+            "user_permissions": []
+        }
+    ]
+}
+
+
+ + + + + + + + + + + +
+ +

10.3 - Controller API v2.1

+
This is the v2.1 REST API for the Controller.
+

What’s New

+

New! healthcheck field in configuration, deprecates the HEALTHCHECK_* environment variables.

+

New! Unsetting a configuration variable that does not exist will return a 422.

+

New! Creating an identical sequential release returns a 409 rather than create a no-op release.

+

Authentication

+

Register a New User

+

Example Request:

+
POST /v2/auth/register/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+
+{
+    "username": "test",
+    "password": "opensesame",
+    "email": "test@example.com"
+}
+

Optional Parameters:

+
{
+    "first_name": "test",
+    "last_name": "testerson"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "id": 1,
+    "last_login": "2014-10-19T22:01:00.601Z",
+    "is_superuser": true,
+    "username": "test",
+    "first_name": "test",
+    "last_name": "testerson",
+    "email": "test@example.com",
+    "is_staff": true,
+    "is_active": true,
+    "date_joined": "2014-10-19T22:01:00.601Z",
+    "groups": [],
+    "user_permissions": []
+}
+

Log in

+

Example Request:

+
POST /v2/auth/login/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+
+{"username": "test", "password": "opensesame"}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{"token": "abc123"}
+

Cancel Account

+

Example Request:

+
DELETE /v2/auth/cancel/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Regenerate Token

+
+

note

+

This command could require administrative privileges

+
+

Example Request:

+
POST /v2/auth/tokens/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional Parameters:

+
{
+    "username" : "test"
+    "all" : "true"
+}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{"token": "abc123"}
+

Change Password

+

Example Request:

+
POST /v2/auth/passwd/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "password": "foo",
+    "new_password": "bar"
+}
+

Optional parameters:

+
{"username": "testuser"}
+
+

note

+

Using the username parameter requires administrative privileges and makes the password parameter optional.

+
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Applications

+

List all Applications

+

Example Request:

+
GET /v2/apps HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "created": "2014-01-01T00:00:00UTC",
+            "id": "example-go",
+            "owner": "test",
+            "structure": {},
+            "updated": "2014-01-01T00:00:00UTC",
+            "url": "example-go.example.com",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+        }
+    ]
+}
+

Create an Application

+

Example Request:

+
POST /v2/apps/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+

Optional parameters:

+
{"id": "example-go"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example-go",
+    "owner": "test",
+    "structure": {},
+    "updated": "2014-01-01T00:00:00UTC",
+    "url": "example-go.example.com",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Destroy an Application

+

Example Request:

+
DELETE /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

List Application Details

+

Example Request:

+
GET /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example-go",
+    "owner": "test",
+    "structure": {},
+    "updated": "2014-01-01T00:00:00UTC",
+    "url": "example-go.example.com",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Update Application Details

+

Example Request:

+
POST /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional parameters:

+
{
+  "owner": "test"
+}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 1.8.0
+Content-Type: application/json
+

Retrieve Application Logs

+

Example Request:

+
GET /v2/apps/example-go/logs/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional URL Query Parameters:

+
?log_lines=
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: text/plain
+
+"16:51:14 drycc[api]: test created initial release\n"
+

Run one-off Commands

+
POST /v2/apps/example-go/run/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"command": "echo hi"}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{"exit_code": 0, "output": "hi\n"}
+

Certificates

+

List all Certificates

+

Example Request:

+
GET /v2/certs HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+  "count": 1,
+  "next": null,
+  "previous": null,
+  "results": [
+    {
+      "id": 22,
+      "owner": "test",
+      "san": [],
+      "domains": [],
+      "created": "2016-06-22T22:24:20Z",
+      "updated": "2016-06-22T22:24:20Z",
+      "name": "foo",
+      "common_name": "bar.com",
+      "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+      "expires": "2017-01-14T23:57:57Z",
+      "starts": "2016-01-15T23:57:57Z",
+      "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+      "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+    }
+  ]
+}
+

Get Certificate Details

+

Example Request:

+
GET /v2/certs/foo HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+  "id": 22,
+  "owner": "test",
+  "san": [],
+  "domains": [],
+  "created": "2016-06-22T22:24:20Z",
+  "updated": "2016-06-22T22:24:20Z",
+  "name": "foo",
+  "common_name": "bar.com",
+  "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+  "expires": "2017-01-14T23:57:57Z",
+  "starts": "2016-01-15T23:57:57Z",
+  "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+  "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+}
+

Create Certificate

+

Example Request:

+
POST /v2/certs/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{
+    "name": "foo"
+    "certificate": "-----BEGIN CERTIFICATE-----",
+    "key": "-----BEGIN RSA PRIVATE KEY-----"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+  "id": 22,
+  "owner": "test",
+  "san": [],
+  "domains": [],
+  "created": "2016-06-22T22:24:20Z",
+  "updated": "2016-06-22T22:24:20Z",
+  "name": "foo",
+  "common_name": "bar.com",
+  "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+  "expires": "2017-01-14T23:57:57Z",
+  "starts": "2016-01-15T23:57:57Z",
+  "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+  "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+}
+

Destroy a Certificate

+

Example Request:

+
DELETE /v2/certs/foo HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Attach a Domain to a Certificate

+

Example Request:

+
POST /v2/certs/foo/domain/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "domain": "test.com"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Remove a Domain from a Certificate

+

Example Request:

+
DELETE /v2/certs/foo/domain/test.com/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Pods

+

List all Pods

+

Example Request:

+
GET /v2/apps/example-go/pods/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "results": [
+        {
+            "name": "go-v2-web-e7dej",
+            "release": "v2",
+            "started": "2014-01-01T00:00:00Z",
+            "state": "up",
+            "type": "web"
+        }
+    ]
+}
+

List all Pods by Type

+

Example Request:

+
GET /v2/apps/example-go/pods/web/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "results": [
+        {
+            "name": "go-v2-web-e7dej",
+            "release": "v2",
+            "started": "2014-01-01T00:00:00Z",
+            "state": "up",
+            "type": "web"
+        }
+    ]
+}
+

Restart All Pods

+

Example Request:

+
POST /v2/apps/example-go/pods/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Restart Pods by Type

+

Example Request:

+
POST /v2/apps/example-go/pods/web/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Restart Pods by Type and Name

+

Example Request:

+
POST /v2/apps/example-go/pods/go-v2-web-atots/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Scale Pods

+

Example Request:

+
POST /v2/apps/example-go/scale/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"web": 3}
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Configuration

+

List Application Configuration

+

Example Request:

+
GET /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+      "PLATFORM": "drycc"
+    },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Create new Config

+

Example Request:

+
POST /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"values": {"HELLO": "world", "PLATFORM": "drycc"}}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+        "DRYCC_APP": "example-go",
+        "DRYCC_RELEASE": "v3",
+        "HELLO": "world",
+        "PLATFORM": "drycc"
+
+    },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Unset Config Variable

+

Example Request:

+
POST /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"values": {"HELLO": null}}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+        "DRYCC_APP": "example-go",
+        "DRYCC_RELEASE": "v4",
+        "PLATFORM": "drycc"
+   },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Domains

+

List Application Domains

+

Example Request:

+
GET /v2/apps/example-go/domains/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "app": "example-go",
+            "created": "2014-01-01T00:00:00UTC",
+            "domain": "example.example.com",
+            "owner": "test",
+            "updated": "2014-01-01T00:00:00UTC"
+        }
+    ]
+}
+

Add Domain

+

Example Request:

+
POST /v2/apps/example-go/domains/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{'domain': 'example.example.com'}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "domain": "example.example.com",
+    "owner": "test",
+    "updated": "2014-01-01T00:00:00UTC"
+}
+

Remove Domain

+

Example Request:

+
DELETE /v2/apps/example-go/domains/example.example.com HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Builds

+

List Application Builds

+

Example Request:

+
GET /v2/apps/example-go/build/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "dockerfile": "FROM drycc/slugrunner RUN mkdir -p /app WORKDIR /app ENTRYPOINT [\"/runner/init\"] ADD slug.tgz /app ENV GIT_SHA 060da68f654e75fac06dbedd1995d5f8ad9084db",
+    "image": "example-go",
+    "owner": "test",
+    "procfile": {
+        "web": "example-go"
+    },
+    "sha": "060da68f",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Create Application Build

+

Example Request:

+
POST /v2/apps/example-go/build/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"image": "drycc/example-go:latest"}
+

Optional Parameters:

+
{
+    "procfile": {
+      "web": "./cmd"
+    }
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "dockerfile": "",
+    "image": "drycc/example-go:latest",
+    "owner": "test",
+    "procfile": {},
+    "sha": "",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Releases

+

List Application Releases

+

Example Request:

+
GET /v2/apps/example-go/releases/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 3,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "app": "example-go",
+            "build": "202d8e4b-600e-4425-a85c-ffc7ea607f61",
+            "config": "ed637ceb-5d32-44bd-9406-d326a777a513",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test changed nothing",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 3
+        },
+        {
+            "app": "example-go",
+            "build": "202d8e4b-600e-4425-a85c-ffc7ea607f61",
+            "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test deployed 060da68",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 2
+        },
+        {
+            "app": "example-go",
+            "build": null,
+            "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test created initial release",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 1
+        }
+    ]
+}
+

List Release Details

+

Example Request:

+
GET /v2/apps/example-go/releases/v2/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "build": null,
+    "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+    "created": "2014-01-01T00:00:00UTC",
+    "owner": "test",
+    "summary": "test created initial release",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+    "version": 1
+}
+

Rollback Release

+

Example Request:

+
POST /v2/apps/example-go/releases/rollback/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"version": 1}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{"version": 5}
+

Keys

+

List Keys

+

Example Request:

+
GET /v2/keys/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "created": "2014-01-01T00:00:00UTC",
+            "id": "test@example.com",
+            "owner": "test",
+            "public": "ssh-rsa <...>",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+        }
+    ]
+}
+

Add Key to User

+

Example Request:

+
POST /v2/keys/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "id": "example",
+    "public": "ssh-rsa <...>"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example",
+    "owner": "example",
+    "public": "ssh-rsa <...>",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Remove Key from User

+

Example Request:

+
DELETE /v2/keys/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Permissions

+

List Application Permissions

+
+

note

+

This does not include the app owner.

+
+

Example Request:

+
GET /v2/apps/example-go/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "users": [
+        "test",
+        "foo"
+    ]
+}
+

Create Application Permission

+

Example Request:

+
POST /v2/apps/example-go/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{"username": "example"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Remove Application Permission

+

Example Request:

+
DELETE /v2/apps/example-go/perms/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

List Administrators

+

Example Request:

+
GET /v2/admin/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 2,
+    "next": null
+    "previous": null,
+    "results": [
+        {
+            "username": "test",
+            "is_superuser": true
+        },
+        {
+            "username": "foo",
+            "is_superuser": true
+        }
+    ]
+}
+

Grant User Administrative Privileges

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
POST /v2/admin/perms HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{"username": "example"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Remove User’s Administrative Privileges

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
DELETE /v2/admin/perms/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Users

+

List all users

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
GET /v2/users HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "id": 1,
+            "last_login": "2014-10-19T22:01:00.601Z",
+            "is_superuser": true,
+            "username": "test",
+            "first_name": "test",
+            "last_name": "testerson",
+            "email": "test@example.com",
+            "is_staff": true,
+            "is_active": true,
+            "date_joined": "2014-10-19T22:01:00.601Z",
+            "groups": [],
+            "user_permissions": []
+        }
+    ]
+}
+
+
+ + + + + + + + + + + +
+ +

10.4 - Controller API v2.2

+
This is the v2.2 REST API for the Controller.
+

What’s New

+

New! /v2/auth/whoami endpoint

+

Authentication

+

Register a New User

+

Example Request:

+
POST /v2/auth/register/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+
+{
+    "username": "test",
+    "password": "opensesame",
+    "email": "test@example.com"
+}
+

Optional Parameters:

+
{
+    "first_name": "test",
+    "last_name": "testerson"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "id": 1,
+    "last_login": "2014-10-19T22:01:00.601Z",
+    "is_superuser": true,
+    "username": "test",
+    "first_name": "test",
+    "last_name": "testerson",
+    "email": "test@example.com",
+    "is_staff": true,
+    "is_active": true,
+    "date_joined": "2014-10-19T22:01:00.601Z",
+    "groups": [],
+    "user_permissions": []
+}
+

Log in

+

Example Request:

+
POST /v2/auth/login/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+
+{"username": "test", "password": "opensesame"}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{"token": "abc123"}
+

Cancel Account

+

Example Request:

+
DELETE /v2/auth/cancel/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Who Am I

+

Example Request:

+
GET /v2/auth/whoami/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "id": 1,
+    "last_login": "2014-10-19T22:01:00.601Z",
+    "is_superuser": true,
+    "username": "test",
+    "first_name": "test",
+    "last_name": "testerson",
+    "email": "test@example.com",
+    "is_staff": true,
+    "is_active": true,
+    "date_joined": "2014-10-19T22:01:00.601Z",
+    "groups": [],
+    "user_permissions": []
+}
+

Regenerate Token

+
+

note

+

This command could require administrative privileges

+
+

Example Request:

+
POST /v2/auth/tokens/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional Parameters:

+
{
+    "username" : "test"
+    "all" : "true"
+}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{"token": "abc123"}
+

Change Password

+

Example Request:

+
POST /v2/auth/passwd/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "password": "foo",
+    "new_password": "bar"
+}
+

Optional parameters:

+
{"username": "testuser"}
+
+

note

+

Using the username parameter requires administrative privileges and makes the password parameter optional.

+
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Applications

+

List all Applications

+

Example Request:

+
GET /v2/apps HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "created": "2014-01-01T00:00:00UTC",
+            "id": "example-go",
+            "owner": "test",
+            "structure": {},
+            "updated": "2014-01-01T00:00:00UTC",
+            "url": "example-go.example.com",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+        }
+    ]
+}
+

Create an Application

+

Example Request:

+
POST /v2/apps/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+

Optional parameters:

+
{"id": "example-go"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example-go",
+    "owner": "test",
+    "structure": {},
+    "updated": "2014-01-01T00:00:00UTC",
+    "url": "example-go.example.com",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Destroy an Application

+

Example Request:

+
DELETE /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

List Application Details

+

Example Request:

+
GET /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example-go",
+    "owner": "test",
+    "structure": {},
+    "updated": "2014-01-01T00:00:00UTC",
+    "url": "example-go.example.com",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Update Application Details

+

Example Request:

+
POST /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional parameters:

+
{
+  "owner": "test"
+}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 1.8.0
+Content-Type: application/json
+

Retrieve Application Logs

+

Example Request:

+
GET /v2/apps/example-go/logs/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional URL Query Parameters:

+
?log_lines=
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: text/plain
+
+"16:51:14 drycc[api]: test created initial release\n"
+

Run one-off Commands

+
POST /v2/apps/example-go/run/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"command": "echo hi"}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{"exit_code": 0, "output": "hi\n"}
+

Certificates

+

List all Certificates

+

Example Request:

+
GET /v2/certs HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+  "count": 1,
+  "next": null,
+  "previous": null,
+  "results": [
+    {
+      "id": 22,
+      "owner": "test",
+      "san": [],
+      "domains": [],
+      "created": "2016-06-22T22:24:20Z",
+      "updated": "2016-06-22T22:24:20Z",
+      "name": "foo",
+      "common_name": "bar.com",
+      "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+      "expires": "2017-01-14T23:57:57Z",
+      "starts": "2016-01-15T23:57:57Z",
+      "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+      "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+    }
+  ]
+}
+

Get Certificate Details

+

Example Request:

+
GET /v2/certs/foo HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+  "id": 22,
+  "owner": "test",
+  "san": [],
+  "domains": [],
+  "created": "2016-06-22T22:24:20Z",
+  "updated": "2016-06-22T22:24:20Z",
+  "name": "foo",
+  "common_name": "bar.com",
+  "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+  "expires": "2017-01-14T23:57:57Z",
+  "starts": "2016-01-15T23:57:57Z",
+  "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+  "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+}
+

Create Certificate

+

Example Request:

+
POST /v2/certs/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{
+    "name": "foo"
+    "certificate": "-----BEGIN CERTIFICATE-----",
+    "key": "-----BEGIN RSA PRIVATE KEY-----"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+  "id": 22,
+  "owner": "test",
+  "san": [],
+  "domains": [],
+  "created": "2016-06-22T22:24:20Z",
+  "updated": "2016-06-22T22:24:20Z",
+  "name": "foo",
+  "common_name": "bar.com",
+  "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+  "expires": "2017-01-14T23:57:57Z",
+  "starts": "2016-01-15T23:57:57Z",
+  "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+  "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+}
+

Destroy a Certificate

+

Example Request:

+
DELETE /v2/certs/foo HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Attach a Domain to a Certificate

+

Example Request:

+
POST /v2/certs/foo/domain/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "domain": "test.com"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Remove a Domain from a Certificate

+

Example Request:

+
DELETE /v2/certs/foo/domain/test.com/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Pods

+

List all Pods

+

Example Request:

+
GET /v2/apps/example-go/pods/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "results": [
+        {
+            "name": "go-v2-web-e7dej",
+            "release": "v2",
+            "started": "2014-01-01T00:00:00Z",
+            "state": "up",
+            "type": "web"
+        }
+    ]
+}
+

List all Pods by Type

+

Example Request:

+
GET /v2/apps/example-go/pods/web/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "results": [
+        {
+            "name": "go-v2-web-e7dej",
+            "release": "v2",
+            "started": "2014-01-01T00:00:00Z",
+            "state": "up",
+            "type": "web"
+        }
+    ]
+}
+

Restart All Pods

+

Example Request:

+
POST /v2/apps/example-go/pods/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Restart Pods by Type

+

Example Request:

+
POST /v2/apps/example-go/pods/web/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Restart Pods by Type and Name

+

Example Request:

+
POST /v2/apps/example-go/pods/go-v2-web-atots/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Scale Pods

+

Example Request:

+
POST /v2/apps/example-go/scale/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"web": 3}
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Configuration

+

List Application Configuration

+

Example Request:

+
GET /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+      "PLATFORM": "drycc"
+    },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Create new Config

+

Example Request:

+
POST /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"values": {"HELLO": "world", "PLATFORM": "drycc"}}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+        "DRYCC_APP": "example-go",
+        "DRYCC_RELEASE": "v3",
+        "HELLO": "world",
+        "PLATFORM": "drycc"
+
+    },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Unset Config Variable

+

Example Request:

+
POST /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"values": {"HELLO": null}}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+        "DRYCC_APP": "example-go",
+        "DRYCC_RELEASE": "v4",
+        "PLATFORM": "drycc"
+   },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Domains

+

List Application Domains

+

Example Request:

+
GET /v2/apps/example-go/domains/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "app": "example-go",
+            "created": "2014-01-01T00:00:00UTC",
+            "domain": "example.example.com",
+            "owner": "test",
+            "updated": "2014-01-01T00:00:00UTC"
+        }
+    ]
+}
+

Add Domain

+

Example Request:

+
POST /v2/apps/example-go/domains/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{'domain': 'example.example.com'}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "domain": "example.example.com",
+    "owner": "test",
+    "updated": "2014-01-01T00:00:00UTC"
+}
+

Remove Domain

+

Example Request:

+
DELETE /v2/apps/example-go/domains/example.example.com HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Builds

+

List Application Builds

+

Example Request:

+
GET /v2/apps/example-go/build/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "dockerfile": "FROM drycc/slugrunner RUN mkdir -p /app WORKDIR /app ENTRYPOINT [\"/runner/init\"] ADD slug.tgz /app ENV GIT_SHA 060da68f654e75fac06dbedd1995d5f8ad9084db",
+    "image": "example-go",
+    "owner": "test",
+    "procfile": {
+        "web": "example-go"
+    },
+    "sha": "060da68f",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Create Application Build

+

Example Request:

+
POST /v2/apps/example-go/build/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"image": "drycc/example-go:latest"}
+

Optional Parameters:

+
{
+    "procfile": {
+      "web": "./cmd"
+    }
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "dockerfile": "",
+    "image": "drycc/example-go:latest",
+    "owner": "test",
+    "procfile": {},
+    "sha": "",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Releases

+

List Application Releases

+

Example Request:

+
GET /v2/apps/example-go/releases/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "count": 3,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "app": "example-go",
+            "build": "202d8e4b-600e-4425-a85c-ffc7ea607f61",
+            "config": "ed637ceb-5d32-44bd-9406-d326a777a513",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test changed nothing",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 3
+        },
+        {
+            "app": "example-go",
+            "build": "202d8e4b-600e-4425-a85c-ffc7ea607f61",
+            "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test deployed 060da68",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 2
+        },
+        {
+            "app": "example-go",
+            "build": null,
+            "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test created initial release",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 1
+        }
+    ]
+}
+

List Release Details

+

Example Request:

+
GET /v2/apps/example-go/releases/v2/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "build": null,
+    "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+    "created": "2014-01-01T00:00:00UTC",
+    "owner": "test",
+    "summary": "test created initial release",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+    "version": 1
+}
+

Rollback Release

+

Example Request:

+
POST /v2/apps/example-go/releases/rollback/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"version": 1}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{"version": 5}
+

Keys

+

List Keys

+

Example Request:

+
GET /v2/keys/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "created": "2014-01-01T00:00:00UTC",
+            "id": "test@example.com",
+            "owner": "test",
+            "public": "ssh-rsa <...>",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+        }
+    ]
+}
+

Add Key to User

+

Example Request:

+
POST /v2/keys/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "id": "example",
+    "public": "ssh-rsa <...>"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example",
+    "owner": "example",
+    "public": "ssh-rsa <...>",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Remove Key from User

+

Example Request:

+
DELETE /v2/keys/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Permissions

+

List Application Permissions

+
+

note

+

This does not include the app owner.

+
+

Example Request:

+
GET /v2/apps/example-go/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "users": [
+        "test",
+        "foo"
+    ]
+}
+

Create Application Permission

+

Example Request:

+
POST /v2/apps/example-go/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{"username": "example"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Remove Application Permission

+

Example Request:

+
DELETE /v2/apps/example-go/perms/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

List Administrators

+

Example Request:

+
GET /v2/admin/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "count": 2,
+    "next": null
+    "previous": null,
+    "results": [
+        {
+            "username": "test",
+            "is_superuser": true
+        },
+        {
+            "username": "foo",
+            "is_superuser": true
+        }
+    ]
+}
+

Grant User Administrative Privileges

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
POST /v2/admin/perms HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{"username": "example"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Remove User’s Administrative Privileges

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
DELETE /v2/admin/perms/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Users

+

List all users

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
GET /v2/users HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "id": 1,
+            "last_login": "2014-10-19T22:01:00.601Z",
+            "is_superuser": true,
+            "username": "test",
+            "first_name": "test",
+            "last_name": "testerson",
+            "email": "test@example.com",
+            "is_staff": true,
+            "is_active": true,
+            "date_joined": "2014-10-19T22:01:00.601Z",
+            "groups": [],
+            "user_permissions": []
+        }
+    ]
+}
+
+
+ + + + + + + + + + + +
+ +

10.5 - Controller API v2.3

+
This is the v2.3 REST API for the Controller.
+

What’s New

+

New! /v2/apps/{name}/logs endpoint was fixed and no longer returns b'log data' and instead returns a normal string log data

+

Authentication

+

Register a New User

+

Example Request:

+
POST /v2/auth/register/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+
+{
+    "username": "test",
+    "password": "opensesame",
+    "email": "test@example.com"
+}
+

Optional Parameters:

+
{
+    "first_name": "test",
+    "last_name": "testerson"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "id": 1,
+    "last_login": "2014-10-19T22:01:00.601Z",
+    "is_superuser": true,
+    "username": "test",
+    "first_name": "test",
+    "last_name": "testerson",
+    "email": "test@example.com",
+    "is_staff": true,
+    "is_active": true,
+    "date_joined": "2014-10-19T22:01:00.601Z",
+    "groups": [],
+    "user_permissions": []
+}
+

Log in

+

Example Request:

+
POST /v2/auth/login/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+
+{"username": "test", "password": "opensesame"}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{"token": "abc123"}
+

Cancel Account

+

Example Request:

+
DELETE /v2/auth/cancel/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Who Am I

+

Example Request:

+
GET /v2/auth/whoami/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "id": 1,
+    "last_login": "2014-10-19T22:01:00.601Z",
+    "is_superuser": true,
+    "username": "test",
+    "first_name": "test",
+    "last_name": "testerson",
+    "email": "test@example.com",
+    "is_staff": true,
+    "is_active": true,
+    "date_joined": "2014-10-19T22:01:00.601Z",
+    "groups": [],
+    "user_permissions": []
+}
+

Regenerate Token

+
+

note

+

This command could require administrative privileges

+
+

Example Request:

+
POST /v2/auth/tokens/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional Parameters:

+
{
+    "username" : "test"
+    "all" : "true"
+}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{"token": "abc123"}
+

Change Password

+

Example Request:

+
POST /v2/auth/passwd/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "password": "foo",
+    "new_password": "bar"
+}
+

Optional parameters:

+
{"username": "testuser"}
+
+

note

+

Using the username parameter requires administrative privileges and makes the password parameter optional.

+
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Applications

+

List all Applications

+

Example Request:

+
GET /v2/apps HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "created": "2014-01-01T00:00:00UTC",
+            "id": "example-go",
+            "owner": "test",
+            "structure": {},
+            "updated": "2014-01-01T00:00:00UTC",
+            "url": "example-go.example.com",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+        }
+    ]
+}
+

Create an Application

+

Example Request:

+
POST /v2/apps/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+

Optional parameters:

+
{"id": "example-go"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example-go",
+    "owner": "test",
+    "structure": {},
+    "updated": "2014-01-01T00:00:00UTC",
+    "url": "example-go.example.com",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Destroy an Application

+

Example Request:

+
DELETE /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

List Application Details

+

Example Request:

+
GET /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example-go",
+    "owner": "test",
+    "structure": {},
+    "updated": "2014-01-01T00:00:00UTC",
+    "url": "example-go.example.com",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Update Application Details

+

Example Request:

+
POST /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional parameters:

+
{
+  "owner": "test"
+}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 1.8.0
+Content-Type: application/json
+

Retrieve Application Logs

+

Example Request:

+
GET /v2/apps/example-go/logs/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional URL Query Parameters:

+
?log_lines=
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: text/plain
+
+"16:51:14 drycc[api]: test created initial release\n"
+

Run one-off Commands

+
POST /v2/apps/example-go/run/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"command": "echo hi"}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{"exit_code": 0, "output": "hi\n"}
+

Certificates

+

List all Certificates

+

Example Request:

+
GET /v2/certs HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+  "count": 1,
+  "next": null,
+  "previous": null,
+  "results": [
+    {
+      "id": 22,
+      "owner": "test",
+      "san": [],
+      "domains": [],
+      "created": "2016-06-22.32.34:20Z",
+      "updated": "2016-06-22.32.34:20Z",
+      "name": "foo",
+      "common_name": "bar.com",
+      "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+      "expires": "2017-01-14T23:57:57Z",
+      "starts": "2016-01-15T23:57:57Z",
+      "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+      "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+    }
+  ]
+}
+

Get Certificate Details

+

Example Request:

+
GET /v2/certs/foo HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+  "id": 22,
+  "owner": "test",
+  "san": [],
+  "domains": [],
+  "created": "2016-06-22.32.34:20Z",
+  "updated": "2016-06-22.32.34:20Z",
+  "name": "foo",
+  "common_name": "bar.com",
+  "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+  "expires": "2017-01-14T23:57:57Z",
+  "starts": "2016-01-15T23:57:57Z",
+  "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+  "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+}
+

Create Certificate

+

Example Request:

+
POST /v2/certs/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{
+    "name": "foo"
+    "certificate": "-----BEGIN CERTIFICATE-----",
+    "key": "-----BEGIN RSA PRIVATE KEY-----"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+  "id": 22,
+  "owner": "test",
+  "san": [],
+  "domains": [],
+  "created": "2016-06-22.32.34:20Z",
+  "updated": "2016-06-22.32.34:20Z",
+  "name": "foo",
+  "common_name": "bar.com",
+  "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+  "expires": "2017-01-14T23:57:57Z",
+  "starts": "2016-01-15T23:57:57Z",
+  "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+  "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+}
+

Destroy a Certificate

+

Example Request:

+
DELETE /v2/certs/foo HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Attach a Domain to a Certificate

+

Example Request:

+
POST /v2/certs/foo/domain/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "domain": "test.com"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Remove a Domain from a Certificate

+

Example Request:

+
DELETE /v2/certs/foo/domain/test.com/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Enable or disable TLS

+

Example Request:

+
POST /v2/apps/example-go/tls/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{
+  "https_enforced": true
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "app": "example-go",
+    "owner": "test",
+    "https_enforced": true,
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Get TLS status

+

Example Request:

+
GET /v2/apps/example-go/tls/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "app": "example-go",
+    "owner": "test",
+    "https_enforced": false,
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Pods

+

List all Pods

+

Example Request:

+
GET /v2/apps/example-go/pods/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "results": [
+        {
+            "name": "go-v2-web-e7dej",
+            "release": "v2",
+            "started": "2014-01-01T00:00:00Z",
+            "state": "up",
+            "type": "web"
+        }
+    ]
+}
+

List all Pods by Type

+

Example Request:

+
GET /v2/apps/example-go/pods/web/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "results": [
+        {
+            "name": "go-v2-web-e7dej",
+            "release": "v2",
+            "started": "2014-01-01T00:00:00Z",
+            "state": "up",
+            "type": "web"
+        }
+    ]
+}
+

Restart All Pods

+

Example Request:

+
POST /v2/apps/example-go/pods/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Restart Pods by Type

+

Example Request:

+
POST /v2/apps/example-go/pods/web/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Restart Pods by Type and Name

+

Example Request:

+
POST /v2/apps/example-go/pods/go-v2-web-atots/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Scale Pods

+

Example Request:

+
POST /v2/apps/example-go/scale/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"web": 3}
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Configuration

+

List Application Configuration

+

Example Request:

+
GET /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+      "PLATFORM": "drycc"
+    },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Create new Config

+

Example Request:

+
POST /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"values": {"HELLO": "world", "PLATFORM": "drycc"}}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+        "DRYCC_APP": "example-go",
+        "DRYCC_RELEASE": "v3",
+        "HELLO": "world",
+        "PLATFORM": "drycc"
+
+    },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Unset Config Variable

+

Example Request:

+
POST /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"values": {"HELLO": null}}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+        "DRYCC_APP": "example-go",
+        "DRYCC_RELEASE": "v4",
+        "PLATFORM": "drycc"
+   },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Domains

+

List Application Domains

+

Example Request:

+
GET /v2/apps/example-go/domains/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "app": "example-go",
+            "created": "2014-01-01T00:00:00UTC",
+            "domain": "example.example.com",
+            "owner": "test",
+            "updated": "2014-01-01T00:00:00UTC"
+        }
+    ]
+}
+

Add Domain

+

Example Request:

+
POST /v2/apps/example-go/domains/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{'domain': 'example.example.com'}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "domain": "example.example.com",
+    "owner": "test",
+    "updated": "2014-01-01T00:00:00UTC"
+}
+

Remove Domain

+

Example Request:

+
DELETE /v2/apps/example-go/domains/example.example.com HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Builds

+

List Application Builds

+

Example Request:

+
GET /v2/apps/example-go/build/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "dockerfile": "FROM drycc/slugrunner RUN mkdir -p /app WORKDIR /app ENTRYPOINT [\"/runner/init\"] ADD slug.tgz /app ENV GIT_SHA 060da68f654e75fac06dbedd1995d5f8ad9084db",
+    "image": "example-go",
+    "owner": "test",
+    "procfile": {
+        "web": "example-go"
+    },
+    "sha": "060da68f",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Create Application Build

+

Example Request:

+
POST /v2/apps/example-go/build/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"image": "drycc/example-go:latest"}
+

Optional Parameters:

+
{
+    "procfile": {
+      "web": "./cmd"
+    }
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "dockerfile": "",
+    "image": "drycc/example-go:latest",
+    "owner": "test",
+    "procfile": {},
+    "sha": "",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Releases

+

List Application Releases

+

Example Request:

+
GET /v2/apps/example-go/releases/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "count": 3,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "app": "example-go",
+            "build": "2.3d8e4b-600e-4425-a85c-ffc7ea607f61",
+            "config": "ed637ceb-5d32-44bd-9406-d326a777a513",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test changed nothing",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 3
+        },
+        {
+            "app": "example-go",
+            "build": "2.3d8e4b-600e-4425-a85c-ffc7ea607f61",
+            "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test deployed 060da68",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 2
+        },
+        {
+            "app": "example-go",
+            "build": null,
+            "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test created initial release",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 1
+        }
+    ]
+}
+

List Release Details

+

Example Request:

+
GET /v2/apps/example-go/releases/v2/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "build": null,
+    "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+    "created": "2014-01-01T00:00:00UTC",
+    "owner": "test",
+    "summary": "test created initial release",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+    "version": 1
+}
+

Rollback Release

+

Example Request:

+
POST /v2/apps/example-go/releases/rollback/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"version": 1}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{"version": 5}
+

Keys

+

List Keys

+

Example Request:

+
GET /v2/keys/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "created": "2014-01-01T00:00:00UTC",
+            "id": "test@example.com",
+            "owner": "test",
+            "public": "ssh-rsa <...>",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+        }
+    ]
+}
+

Add Key to User

+

Example Request:

+
POST /v2/keys/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "id": "example",
+    "public": "ssh-rsa <...>"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example",
+    "owner": "example",
+    "public": "ssh-rsa <...>",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Remove Key from User

+

Example Request:

+
DELETE /v2/keys/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Permissions

+

List Application Permissions

+
+

note

+

This does not include the app owner.

+
+

Example Request:

+
GET /v2/apps/example-go/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "users": [
+        "test",
+        "foo"
+    ]
+}
+

Create Application Permission

+

Example Request:

+
POST /v2/apps/example-go/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{"username": "example"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Remove Application Permission

+

Example Request:

+
DELETE /v2/apps/example-go/perms/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

List Administrators

+

Example Request:

+
GET /v2/admin/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "count": 2,
+    "next": null
+    "previous": null,
+    "results": [
+        {
+            "username": "test",
+            "is_superuser": true
+        },
+        {
+            "username": "foo",
+            "is_superuser": true
+        }
+    ]
+}
+

Grant User Administrative Privileges

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
POST /v2/admin/perms HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{"username": "example"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Remove User’s Administrative Privileges

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
DELETE /v2/admin/perms/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Users

+

List all users

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
GET /v2/users HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "id": 1,
+            "last_login": "2014-10-19T22:01:00.601Z",
+            "is_superuser": true,
+            "username": "test",
+            "first_name": "test",
+            "last_name": "testerson",
+            "email": "test@example.com",
+            "is_staff": true,
+            "is_active": true,
+            "date_joined": "2014-10-19T22:01:00.601Z",
+            "groups": [],
+            "user_permissions": []
+        }
+    ]
+}
+
+
+ + + + + + + + + + + + + +
+
+
+ + +
+ + + + + + diff --git a/docs/applications/_print/index.html b/docs/applications/_print/index.html new file mode 100644 index 000000000..332054523 --- /dev/null +++ b/docs/applications/_print/index.html @@ -0,0 +1,1953 @@ + + + + + + + + + + + + + + + + + + + + + +Applications | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+ + + + + +
+
+

+This is the multi-page printable view of this section. +Click here to print. +

+Return to the regular view of this page. +

+
+ + + +

Applications

+
A simple and scalable cloud platform for all developer needs.
+ + + + + + + +
+ +
+
+ + + + + + + + + + + + + + + + +
+ +

1 - Deploying an Application

+
Learn how to deploy the application to drycc.
+

An Application is deployed to Drycc using git push or the drycc client.

+

Supported Applications

+

Drycc Workflow can deploy any application or service that can run inside a container. In order to be scaled +horizontally, applications must follow the Twelve-Factor App methodology and store any application state in external +backing services.

+

For example, if your application persists state to the local filesystem – common with content management systems like +Wordpress and Drupal – it cannot be scaled horizontally using drycc scale.

+

Fortunately, most modern applications feature a stateless application tier that can scale horizontally inside Drycc.

+

Login to the Controller

+

!!! important +if you haven’t yet, now is a good time to install the client and register.

+

Before deploying an application, users must first authenticate against the Drycc Controller +using the URL supplied by their Drycc administrator.

+
$ drycc login http://drycc.example.com
+Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71
+Waiting for login... .o.Logged in as admin
+Configuration file written to /root/.drycc/client.json
+

Or you can login with username and password

+
$ drycc login http://drycc.example.com --username=demo --password=demo
+Configuration file written to /root/.drycc/client.json
+

Select a Build Process

+

Drycc Workflow supports three different ways of building applications:

+

Buildpacks

+

Cloud Native Buildpacks are useful if you want to follow cnb’s docs for building applications.

+

Learn how to deploy applications using Buildpacks.

+

Dockerfiles

+

Dockerfiles are a powerful way to define a portable execution environment built on a base OS of your choosing.

+

Learn how to deploy applications using Dockerfiles.

+

Container Image

+

Deploying a Container image onto Drycc allows you to take a Container image from either a public +or a private registry and copy it over bit-for-bit, ensuring that you are running the same +image in development or in your CI pipeline as you are in production.

+

Learn how to deploy applications using Container images.

+

Tuning Application Settings

+

It is possible to configure a few of the globally tunable settings on per application basis using config:set.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SettingDescription
DRYCC_DISABLE_CACHEif set, this will disable the [imagebuilder cache][] (default: not set)
DRYCC_DEPLOY_BATCHESthe number of pods to bring up and take down sequentially during a scale (default: number of available nodes)
DRYCC_DEPLOY_TIMEOUTdeploy timeout in seconds per deploy batch (default: 120)
IMAGE_PULL_POLICYthe kubernetes [image pull policy][pull-policy] for application images (default: “IfNotPresent”) (allowed values: “Always”, “IfNotPresent”)
KUBERNETES_DEPLOYMENTS_REVISION_HISTORY_LIMIThow many revisions Kubernetes keeps around of a given Deployment (default: all revisions)
KUBERNETES_POD_TERMINATION_GRACE_PERIOD_SECONDShow many seconds kubernetes waits for a pod to finish work after a SIGTERM before sending SIGKILL (default: 30)
+

Deploy Timeout

+

Deploy timeout in seconds - There are 2 deploy methods, Deployments (see below) and RC (versions prior to 2.4) and this setting affects those a bit differently.

+

Deployments

+

Deployments behave a little bit differently from the RC based deployment strategy.

+

Kubernetes takes care of the entire deploy, doing rolling updates in the background. As a result, there is only an overall deployment timeout instead of a configurable per-batch timeout.

+

The base timeout is multiplied with DRYCC_DEPLOY_BATCHES to create an overall timeout. This would be 240 (timeout) * 4 (batches) = 960 second overall timeout.

+

RC deploy

+

This deploy timeout defines how long to wait for each batch to complete in DRYCC_DEPLOY_BATCHES.

+

Additions to the base timeout

+

The base timeout is extended as well with healthchecks using initialDelaySeconds on liveness and readiness where the bigger of those two is applied. +Additionally the timeout system accounts for slow image pulls by adding an additional 10 minutes when it has seen an image pull take over 1 minute. This allows the timeout values to be reasonable without having to account for image pull slowness in the base deploy timeout.

+

Deployments

+

Workflow uses Deployments for deploys. In prior versions ReplicationControllers were used with the ability to turn on Deployments via DRYCC_KUBERNETES_DEPLOYMENTS=1.

+

The advantage of Deployments is that rolling-updates will happen server-side in Kubernetes instead of in Drycc Workflow Controller, +along with a few other Pod management related functionality. This allows a deploy to continue even when the CLI connection is interrupted.

+

Behind the scenes your application deploy will be built up of a Deployment object per process type, +each having multiple ReplicaSets (one per release) which in turn manage the Pods running your application.

+

Drycc Workflow will behave the same way with DRYCC_KUBERNETES_DEPLOYMENTS enabled or disabled (only applicable to versions prior to 2.4). +The changes are behind the scenes. Where you will see differences while using the CLI is drycc ps:list will output Pod names differently.

+ +
+ + + + + + + + + + + +
+ +

2 - Using Buildpacks

+
An overview of buildpacks, which are responsible for transforming deployed code into a slug, which can then be executed on a container.
+

Drycc supports deploying applications via Cloud Native Buildpacks. Cloud Native Buildpacks are useful if you want to follow cnb’s docs for building applications.

+

Add SSH Key

+

For Buildpack based application deploys via git push, Drycc Workflow identifies users via SSH keys. SSH keys are pushed to the platform and must be unique to each user.

+
    +
  • +

    See this document for instructions on how to generate an SSH key.

    +
  • +
  • +

    Run drycc keys:add to upload your SSH key to Drycc Workflow.

    +
  • +
+
$ drycc keys:add ~/.ssh/id_drycc.pub
+Uploading id_drycc.pub to drycc... done
+

Read more about adding/removing SSH Keys here.

+

Prepare an Application

+

If you do not have an existing application, you can clone an example application that demonstrates the Heroku Buildpack workflow.

+
$ git clone https://github.com/drycc/example-go.git
+$ cd example-go
+
+

Create an Application

+

Use drycc create to create an application on the Controller.

+
$ drycc create
+Creating application... done, created skiing-keypunch
+Git remote drycc added
+
+

Push to Deploy

+

Use git push drycc master to deploy your application.

+
$ git push drycc master
+Counting objects: 75, done.
+Delta compression using up to 8 threads.
+Compressing objects: 100% (48/48), done.
+Writing objects: 100% (75/75), 18.28 KiB | 0 bytes/s, done.
+Total 75 (delta 30), reused 58 (delta 22)
+remote: --->
+Starting build... but first, coffee!
+---> Waiting podman running.
+---> Process podman started.
+---> Waiting caddy running.
+---> Process caddy started.
+---> Building pack
+---> Using builder registry.drycc.cc/drycc/buildpacks:bookworm
+Builder 'registry.drycc.cc/drycc/buildpacks:bookworm' is trusted
+Pulling image 'registry.drycc.cc/drycc/buildpacks:bookworm'
+Resolving "drycc/buildpacks" using unqualified-search registries (/etc/containers/registries.conf)
+Trying to pull registry.drycc.cc/drycc/buildpacks:bookworm...
+Getting image source signatures
+...
+---> Skip generate base layer
+---> Python Buildpack
+---> Downloading and extracting Python 3.10.0
+---> Installing requirements with pip
+Collecting Django==3.2.8
+Downloading Django-3.2.8-py3-none-any.whl (7.9 MB)
+Collecting gunicorn==20.1.0
+Downloading gunicorn-20.1.0-py3-none-any.whl (79 kB)
+Collecting sqlparse>=0.2.2
+Downloading sqlparse-0.4.2-py3-none-any.whl (42 kB)
+Collecting pytz
+Downloading pytz-2021.3-py2.py3-none-any.whl (503 kB)
+Collecting asgiref<4,>=3.3.2
+Downloading asgiref-3.4.1-py3-none-any.whl (25 kB)
+Requirement already satisfied: setuptools>=3.0 in /layers/drycc_python/python/lib/python3.10/site-packages (from gunicorn==20.1.0->-r requirements.txt (line 2)) (57.5.0)
+Installing collected packages: sqlparse, pytz, asgiref, gunicorn, Django
+Successfully installed Django-3.2.8 asgiref-3.4.1 gunicorn-20.1.0 pytz-2021.3 sqlparse-0.4.2
+---> Generate Launcher
+...
+Build complete.
+Launching App...
+...
+Done, skiing-keypunch:v2 deployed to Workflow
+
+Use 'drycc open' to view this application in your browser
+
+To learn more, use 'drycc help' or visit https://www.drycc.cc
+
+To ssh://git@drycc.staging-2.drycc.cc:2222/skiing-keypunch.git
+ * [new branch]      master -> master
+
+$ curl -s http://skiing-keypunch.example.com
+Powered by Drycc
+Release v2 on skiing-keypunch-v2-web-02zb9
+
+

Because a Buildpacks-style application is detected, the web process type is automatically scaled to 1 on first deploy.

+

Use drycc scale web=3 to increase web processes to 3, for example. Scaling a +process type directly changes the number of pods running that process.

+

Included Buildpacks

+

For convenience, a number of buildpacks come bundled with Drycc:

+ +

Drycc will cycle through the bin/detect script of each buildpack to match the code you +are pushing.

+

!!! note +If you’re testing against the [Scala Buildpack][], the Builder requires at least +512MB of free memory to execute the Scala Build Tool.

+

Using a Custom Buildpack

+

To use a custom buildpack, you need create a .pack_builder file in your root path app.

+
$  tee > .pack_builder << EOF
+   > registry.drycc.cc/drycc/buildpacks:bookworm
+   > EOF
+
+

On your next git push, the custom buildpack will be used.

+

Using Private Repositories

+

To pull code from private repositories, set the SSH_KEY environment variable to a private key +which has access. Use either the path of a private key file or the raw key material:

+
$ drycc config:set SSH_KEY=/home/user/.ssh/id_rsa
+$ drycc config:set SSH_KEY="""-----BEGIN RSA PRIVATE KEY-----
+(...)
+-----END RSA PRIVATE KEY-----"""
+
+

For example, to use a custom buildpack hosted at a private GitHub URL, ensure that an SSH public +key exists in your GitHub settings. Then set SSH_KEY to the corresponding SSH private key +and set .pack_builder to the builder image:

+
$  tee > .pack_builder << EOF
+   > registry.drycc.cc/drycc/buildpacks:bookworm
+   > EOF
+$ git add .buildpack
+$ git commit -m "chore(buildpack): modify the pack_builder"
+$ git push drycc master
+
+

Builder selector

+

Which way to build a project conforms to the following principles:

+
    +
  • If Dockerfile exists in the project, the stack uses container
  • +
  • If Procfile exists in the project, the stack uses buildpack
  • +
  • If both exist, container is used by default
  • +
  • You can also set the DRYCC_STACK to container or buildpack determine which stack to use.
  • +
+ +
+ + + + + + + + + + + +
+ +

3 - Using Dockerfiles

+
Drycc Container Registry allows you to deploy your Docker-based app to Drycc. Both Common Runtime and Private Spaces are supported.
+

Drycc supports deploying applications via Dockerfiles. A Dockerfile automates the steps for crafting a [Container Image][]. +Dockerfiles are incredibly powerful but require some extra work to define your exact application runtime environment.

+

Add SSH Key

+

For Dockerfile based application deploys via git push, Drycc Workflow identifies users via SSH keys. SSH keys are pushed to the platform and must be unique to each user.

+
    +
  • +

    See this document for instructions on how to generate an SSH key.

    +
  • +
  • +

    Run drycc keys:add to upload your SSH key to Drycc Workflow.

    +
  • +
+
$ drycc keys:add ~/.ssh/id_drycc.pub
+Uploading id_drycc.pub to drycc... done
+

Read more about adding/removing SSH Keys here.

+

Prepare an Application

+

If you do not have an existing application, you can clone an example application that demonstrates the Dockerfile workflow.

+
$ git clone https://github.com/drycc/helloworld.git
+$ cd helloworld
+
+

Dockerfile Requirements

+

In order to deploy Dockerfile applications, they must conform to the following requirements:

+
    +
  • The Dockerfile must use the EXPOSE directive to expose exactly one port.
  • +
  • That port must be listening for an HTTP connection.
  • +
  • The Dockerfile must use the CMD directive to define the default process that will run within the container.
  • +
  • The Container image must contain bash to run processes.
  • +
+

!!! note +Note that if you are using a private registry of any kind (gcr or other) the application environment must include a $PORT config variable that matches the EXPOSE’d port, example: drycc config:set PORT=5000. See Configuring Registry for more info.

+

Create an Application

+

Use drycc create to create an application on the Controller.

+
$ drycc create
+Creating application... done, created folksy-offshoot
+Git remote drycc added
+
+

Push to Deploy

+

Use git push drycc master to deploy your application.

+
$ git push drycc master
+Counting objects: 13, done.
+Delta compression using up to 8 threads.
+Compressing objects: 100% (13/13), done.
+Writing objects: 100% (13/13), 1.99 KiB | 0 bytes/s, done.
+Total 13 (delta 2), reused 0 (delta 0)
+-----> Building Docker image
+Uploading context 4.096 kB
+Uploading context
+Step 0 : FROM drycc/base:latest
+ ---> 60024338bc63
+Step 1 : RUN wget -O /tmp/go1.2.1.linux-amd64.tar.gz -q https://go.googlecode.com/files/go1.2.1.linux-amd64.tar.gz
+ ---> Using cache
+ ---> cf9ef8c5caa7
+Step 2 : RUN tar -C /usr/local -xzf /tmp/go1.2.1.linux-amd64.tar.gz
+ ---> Using cache
+ ---> 515b1faf3bd8
+Step 3 : RUN mkdir -p /go
+ ---> Using cache
+ ---> ebf4927a00e9
+Step 4 : ENV GOPATH /go
+ ---> Using cache
+ ---> c6a276eded37
+Step 5 : ENV PATH /usr/local/go/bin:/go/bin:$PATH
+ ---> Using cache
+ ---> 2ba6f6c9f108
+Step 6 : ADD . /go/src/github.com/drycc/helloworld
+ ---> 94ab7f4b977b
+Removing intermediate container 171b7d9fdb34
+Step 7 : RUN cd /go/src/github.com/drycc/helloworld && go install -v .
+ ---> Running in 0c8fbb2d2812
+github.com/drycc/helloworld
+ ---> 13b5af931393
+Removing intermediate container 0c8fbb2d2812
+Step 8 : ENV PORT 80
+ ---> Running in 9b07da36a272
+ ---> 2dce83167874
+Removing intermediate container 9b07da36a272
+Step 9 : CMD ["/go/bin/helloworld"]
+ ---> Running in f7b215199940
+ ---> b1e55ce5195a
+Removing intermediate container f7b215199940
+Step 10 : EXPOSE 80
+ ---> Running in 7eb8ec45dcb0
+ ---> ea1a8cc93ca3
+Removing intermediate container 7eb8ec45dcb0
+Successfully built ea1a8cc93ca3
+-----> Pushing image to private registry
+
+       Launching... done, v2
+
+-----> folksy-offshoot deployed to Drycc
+       http://folksy-offshoot.local3.dryccapp.com
+
+       To learn more, use `drycc help` or visit https://www.drycc.cc
+
+To ssh://git@local3.dryccapp.com:2222/folksy-offshoot.git
+ * [new branch]      master -> master
+
+$ curl -s http://folksy-offshoot.local3.dryccapp.com
+Welcome to Drycc!
+See the documentation at http://docs.drycc.cc/ for more information.
+
+

Because a Dockerfile application is detected, the web process type is automatically scaled to 1 on first deploy.

+

Use drycc scale web=3 to increase web processes to 3, for example. Scaling a +process type directly changes the number of containers +running that process.

+

Container Build Arguments

+

As of Workflow v2.13.0, users can inject their application config into the Container image using +Container build arguments. To opt into this, users must add a new environment variable +to their application:

+
$ drycc config:set DRYCC_DOCKER_BUILD_ARGS_ENABLED=1
+

Every environment variable set with drycc config:set will then be available for use inside the +user’s Dockerfile. For example, if a user runs drycc config:set POWERED_BY=Workflow, +the user can utilize that build argument in their Dockerfile:

+
ARG POWERED_BY
+RUN echo "Powered by $POWERED_BY" > /etc/motd
+
+
+ + + + + + + + + + + +
+ +

4 - Using Docker Images

+
Deploy an application using a container image stored in your Drycc Container Registry.
+

Drycc supports deploying applications via an existing Docker Image. +This is useful for integrating Drycc into Docker-based CI/CD pipelines.

+

Prepare an Application

+

Start by cloning an example application:

+
$ git clone https://github.com/drycc/example-dockerfile-http.git
+$ cd example-dockerfile-http
+
+

Next use your local docker client to build the image and push +it to DockerHub.

+
$ docker build -t <username>/example-dockerfile-http .
+$ docker push <username>/example-dockerfile-http
+
+

Docker Image Requirements

+

In order to deploy Docker images, they must conform to the following requirements:

+
    +
  • The Dockerfile must use the EXPOSE directive to expose exactly one port.
  • +
  • That port must be listening for an HTTP connection.
  • +
  • The Dockerfile must use the CMD directive to define the default process that will run within the container.
  • +
  • The Docker image must contain bash to run processes.
  • +
+

!!! note +Note that if you are using a private registry of any kind (gcr or other) the application environment must include a $PORT config variable that matches the EXPOSE’d port, example: drycc config:set PORT=5000. See Configuring Registry for more info.

+

Create an Application

+

Use drycc create to create an application on the controller.

+
$ mkdir -p /tmp/example-dockerfile-http && cd /tmp/example-dockerfile-http
+$ drycc create example-dockerfile-http --no-remote
+Creating application... done, created example-dockerfile-http
+
+

!!! note +For all commands except for drycc create, the drycc client uses the name of the current directory +as the app name if you don’t specify it explicitly with --app.

+

Deploy the Application

+

Use drycc pull to deploy your application from DockerHub or +a public registry.

+
$ drycc pull <username>/example-dockerfile-http:latest
+Creating build...  done, v2
+
+$ curl -s http://example-dockerfile-http.local3.dryccapp.com
+Powered by Drycc
+
+

Because you are deploying a Docker image, the web process type is automatically scaled to 1 on first deploy.

+

Use drycc scale web=3 to increase web processes to 3, for example. Scaling a +process type directly changes the number of Containers +running that process.

+

Private Registry

+

To deploy Docker images from a private registry or from a private repository, use drycc registry +to attach credentials to your application. These credentials are the same as you’d use when running +docker login at your private registry.

+

To deploy private Docker images, take the following steps:

+
    +
  • Gather the username and password for the registry, such as a Quay.io Robot Account or a GCR.io Long Lived Token
  • +
  • Run drycc registry:set username=<the-user> password=<secret> -a <application-name>
  • +
  • Now perform drycc pull as normal, against an image in the private registry
  • +
+

When using a GCR.io Long Lived Token, the JSON blob will have to be compacted first using a +tool like jq and then used in the password field in drycc registry:set. For the username, use +_json_key. For example:

+
drycc registry:set username=_json_key password="$(cat google_cloud_cred.json | jq -c .)"
+

When using a private registry the docker images are no longer pulled into the Drycc Internal Registry via +the Drycc Workflow Controller but rather is managed by Kubernetes. This will increase security and overall speed, +however the application port information can no longer be discovered. Instead the application port information can be set via +drycc config:set PORT=80 prior to setting the registry information.

+

!!! note +Currently GCR.io and ECR in short lived auth token mode are not supported.

+ +
+ + + + + + + + + + + +
+ +

5 - Managing Application Processes

+
A Procfile is a list of process types in an app. Each process type declares a command that is executed when a container of that process type is started.
+

Drycc Workflow manages your application as a set of processes that can be named, scaled and configured according to their +role. This gives you the flexibility to easily manage the different facets of your application. For example, you may have +web-facing processes that handle HTTP traffic, background worker processes that do async work, and a helper process that +streams from the Twitter API.

+

By using a Procfile, either checked in to your application or provided via the CLI you can specify the name of the type +and the application command that should run. To spawn other process types, use drycc scale <ptype>=<n> to scale those +types accordingly.

+

Default Process Types

+

In the absence of a Procfile, a single, default process type is assumed for each application.

+

Applications built using Buildpacks via git push implicitly receive a web process type, which starts +the application server. Rails 4, for example, has the following process type:

+
web: bundle exec rails server -p $PORT
+
+

All applications utilizing Dockerfiles have an implied web process type, which runs the +Dockerfile’s CMD directive unmodified:

+
$ cat Dockerfile
+FROM centos:latest
+COPY . /app
+WORKDIR /app
+CMD python -m SimpleHTTPServer 5000
+EXPOSE 5000
+
+

For the above Dockerfile-based application, the web process type would run the Container CMD of python -m SimpleHTTPServer 5000.

+

Applications utilizing remote Container images, a web process type is also implied, and runs the CMD +specified in the Container image.

+

!!! note +The web process type is special as they’is the default process type that will +receive HTTP traffic from Workflow’s routers. Other process types can be named arbitrarily.

+

Declaring Process Types

+

If you use Buildpack or Dockerfile builds and want to override or specify additional process +types, simply include a file named Procfile in the root of your application’s source tree.

+

The format of a Procfile is one process type per line, with each line containing the command to invoke:

+
<process type>: <command>
+
+

The syntax is defined as:

+
    +
  • <process type> – a lowercase alphanumeric string, is a name for your command, such as web, worker, urgentworker, clock, etc.
  • +
  • <command> – a command line to launch the process, such as rake jobs:work.
  • +
+

This example Procfile specifies two types, web and sleeper. The web process launches a web server on port 5000 and +a simple process which sleeps for 900 seconds and exits.

+
$ cat Procfile
+web: bundle exec ruby web.rb -p ${PORT:-5000}
+sleeper: sleep 900
+

If you are using remote Container images, you may define process types by either running drycc pull with a +Procfile in your working directory, or by passing a stringified Procfile to the --procfile CLI option.

+

For example, passing process types inline:

+
$ drycc pull drycc/example-go:latest --procfile="web: /app/bin/boot"
+

Read a Procfile in another directory:

+
$ drycc pull drycc/example-go:latest --procfile="$(cat deploy/Procfile)"
+

Or via a Procfile located in your current, working directory:

+
$ cat Procfile
+web: /bin/boot
+sleeper: echo "sleeping"; sleep 900
+
+
+$ drycc pull -a steely-mainsail drycc/example-go
+Creating build... done
+
+$ drycc scale sleeper=1 -a steely-mainsail
+Scaling processes... but first, coffee!
+done in 0s
+
+NAME                                        RELEASE    STATE    PTYPE      READY    RESTARTS     STARTED
+steely-mainsail-sleeper-76c45b967c-4qm6w    v3         up       sleeper    1/1      0            2023-12-08T02:25:00UTC
+steely-mainsail-web-c4f44c4b4-7p7dh         v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+

!!! note +Only process types of web will be scaled to 1 automatically. If you have additional process types +remember to scale the process counts after creation.

+

To remove a process type simply scale it to 0:

+
$ drycc scale sleeper=0 -a steely-mainsail
+Scaling processes... but first, coffee!
+done in 3s
+
+NAME                                        RELEASE    STATE    PTYPE      READY    RESTARTS     STARTED
+steely-mainsail-web-c4f44c4b4-7p7dh         v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+

Scaling Processes

+

Applications deployed on Drycc Workflow scale out via the process model. Use drycc scale to control the number of +containers that power your app.

+
$ drycc scale web=5 -a iciest-waggoner
+Scaling processes... but first, coffee!
+done in 3s
+
+NAME                                        RELEASE    STATE    PTYPE      READY    RESTARTS     STARTED
+iciest-waggoner-web-c4f44c4b4-7p7dh         v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+iciest-waggoner-web-c4f44c4b4-8p7dh         v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+iciest-waggoner-web-c4f44c4b4-9p7dh         v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+iciest-waggoner-web-c4f44c4b4-1p7dh         v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+iciest-waggoner-web-c4f44c4b4-2p7dh         v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+

If you have multiple process types for your application you may scale the process count for each type separately. For +example, this allows you to manage web process independently from background workers. For more information on process +types see our documentation for Managing App Processes.

+

In this example, we are scaling the process type web to 5 but leaving the process type background with one worker.

+
$ drycc scale web=5
+Scaling processes... but first, coffee!
+done in 4s
+
+NAME                                                RELEASE    STATE    PTYPE      READY    RESTARTS     STARTED
+scenic-icehouse-web-3291896318-7lord                v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-jn957                v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-rsekj                v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-vwhnh                v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-vokg7                v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-vokg7                v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-background-3291896318-yf8kh         v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+

Scaling a process down, by reducing the process count, sends a TERM signal to the processes, followed by a SIGKILL +if they have not exited within 30 seconds. Depending on your application, scaling down may interrupt long-running HTTP +client connections.

+

For example, scaling from 5 processes to 3:

+
$ drycc scale web=3
+Scaling processes... but first, coffee!
+done in 1s
+
+NAME                                                RELEASE    STATE    PTYPE     READY    RESTARTS     STARTED
+scenic-icehouse-web-3291896318-vwhnh                v2         up       web       1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-vokg7                v2         up       web       1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-vokg9                v2         up       web       1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-background-3291896318-yf8kh         v2         up       web       1/1      0            2023-12-08T02:25:00UTC
+

Autoscale

+

Autoscale allows adding a minimum and maximum number of pods on a per process type basis. This is accomplished by specifying a target CPU usage across all available pods.

+

This feature is built on top of Horizontal Pod Autoscaling in Kubernetes or HPA for short.

+

!!! note +This is an alpha feature. It is recommended to be on the latest Kubernetes when using this feature.

+
$ drycc autoscale:set web --min=3 --max=8 --cpu-percent=75
+Applying autoscale settings for process type web on scenic-icehouse... done
+

And then review the scaling rule that was created for web

+
$ drycc autoscale:list
+PTYPE    PERCENT    MIN    MAX
+web      75         3      8
+

Remove scaling rule

+
$ drycc autoscale:unset web
+Removing autoscale for process type web on scenic-icehouse... done
+

For autoscaling to work CPU requests have to be specified on each application Pod (can be done via drycc limits --cpu). This allows the autoscale policies to do the appropriate calculations and make decisions on when to scale up and down.

+

Scale up can only happen if there was no rescaling within the last 3 minutes. Scale down will wait for 5 minutes from the last rescaling. That information and more can be found at HPA algorithm page.

+

Fetch a container logs of the application

+

List the containers:

+
$ drycc ps
+NAME                                                RELEASE    STATE    PTYPEE     READY    RESTARTS     STARTED
+python-getting-started-web-69b7d4bfdc-kl4xf         v2         up       web        1/1      0             2023-12-08T02:25:00UTC
+
+=== python-getting-started Processes
+--- web:
+python-getting-started-web-69b7d4bfdc-kl4xf up (v2)
+

fetch the container logs:

+
$ drycc ps:logs -f python-getting-started-web-69b7d4bfdc-kl4xf
+[2024-05-24 07:14:39 +0000] [1] [INFO] Starting gunicorn 20.1.0
+[2024-05-24 07:14:39 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1)
+[2024-05-24 07:14:39 +0000] [1] [INFO] Using worker: gevent
+[2024-05-24 07:14:39 +0000] [8] [INFO] Booting worker with pid: 8
+[2024-05-24 07:14:39 +0000] [9] [INFO] Booting worker with pid: 9
+[2024-05-24 07:14:39 +0000] [10] [INFO] Booting worker with pid: 10
+[2024-05-24 07:14:39 +0000] [11] [INFO] Booting worker with pid: 11
+

Get a container info of the application

+

List the containers:

+
$ drycc ps:describe python-getting-started-web-69b7d4bfdc-kl4xf
+Container:        python-getting-started-web                   
+Image:            drycc/python-getting-started:latest          
+Command:          
+Args:             
+                  - gunicorn                                   
+                  - -c                                         
+                  - gunicorn_config.py                         
+                  - helloworld.wsgi:application                
+State:            running                                      
+  startedAt:      "2024-05-24T07:14:39Z"                       
+Ready:            true                                         
+Restart Count:    0                 
+

delete a container of the application

+

Delete the containers. +Due to the set number of replicas, a new container will be launched to meet the quantity requirement.

+
$ drycc ps:delete python-getting-started-web-69b7d4bfdc-kl4xf
+Deleting python-getting-started-web-69b7d4bfdc-kl4xf from python-getting-started... done
+

Get a Shell to a Running Container

+

Verify that the container is running:

+
$ drycc ps
+NAME                                                RELEASE    STATE    PTYPEE     READY    RESTARTS     STARTED
+python-getting-started-web-69b7d4bfdc-kl4xf         v2         up       web        1/1      0             2023-12-08T02:25:00UTC
+
+=== python-getting-started Processes
+--- web:
+python-getting-started-web-69b7d4bfdc-kl4xf up (v2)
+

Get a shell to the running container:

+
$ drycc ps:exec python-getting-started-web-69b7d4bfdc-kl4xf -it -- bash
+

In your shell, list the root directory:

+
# Run this inside the container
+ls /
+

Running individual commands in a container

+
$ drycc ps:exec python-getting-started-web-69b7d4bfdc-kl4xf -- date
+

Use “drycc ps –help” for a list of global command-line (applies to all commands).

+

Restarting an Application Processes

+

If you need to restart an application process, you may use drycc pts:restart. Behind the scenes, Drycc Workflow instructs +Kubernetes to terminate the old process and launch a new one in its place.

+
$ drycc ps
+NAME                                               RELEASE    STATE       PTYPE      READY    RESTARTS     STARTED
+scenic-icehouse-web-3291896318-vokg7               v2         up          web        1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-rsekj               v2         up          web        1/1      0            2023-12-08T02:50:21UTC
+scenic-icehouse-web-3291896318-vokg7               v2         up          web        1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-background-3291896318-yf8kh        v2         up          web        1/1      0            2023-12-08T02:25:00UTC
+
+$ drycc pts:restart scenic-icehouse-background
+NAME                                               RELEASE    STATE       PTYPE      READY    RESTARTS    STARTED
+scenic-icehouse-web-3291896318-vokg7               v2         up          web        1/1      0           2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-rsekj               v2         up          web        1/1      0           2023-12-08T02:50:21UTC
+scenic-icehouse-web-3291896318-vokg7               v2         up          web        1/1      0           2023-12-08T02:25:00UTC
+scenic-icehouse-background-3291896318-yf8kh        v2         starting    web        1/1      0           2023-12-08T02:25:00UTC
+

Notice that the process name has changed from scenic-icehouse-background-3291896318-yf8kh to +scenic-icehouse-background-3291896318-yd87g. In a multi-node Kubernetes cluster, this may also have the effect of scheduling +the Pod to a new node.

+

Use “drycc pts –help” for a list of pts command-line (process types info).

+

List an Application Process Types

+
$ drycc pts
+NAME          RELEASE    READY    UP-TO-DATE    AVAILABLE    STARTED                   
+web           v2         3/3      1             1            2023-12-08T02:25:00UTC    
+background    v2         1/1      1             1            2023-12-08T02:25:00UTC    
+

Get deployment info of the application process type

+
$ drycc pts:describe web
+Container:    python-getting-started-web                   
+Image:        drycc/python-getting-started:latest          
+Command:      
+Args:         
+              - gunicorn                                   
+              - -c                                         
+              - gunicorn_config.py                         
+              - helloworld.wsgi:application                
+Limits:       
+              cpu 1                                                                                               
+              ephemeral-storage 2Gi                                                                               
+              memory 1Gi                                                                                          
+Liveness:     http-get headers=[] path=/geo/ port=8000 delay=120s timeout=10s period=20s #success=1 #failure=3    
+Readiness:    http-get headers=[] path=/geo/ port=8000 delay=120s timeout=10s period=20s #success=1 #failure=3  
+
+
+ + + + + + + + + + + +
+ +

6 - Configuring an Application

+
How to store configuration of a Drycc app in the environment, keeping config out of code, making it easy to maintain app or deployment specific configs.
+

Configuring an Application

+

A Drycc application stores config in environment variables.

+

Setting Environment Variables

+

Use drycc config to modify environment variables for a deployed application.

+
$ drycc help config
+Valid commands for config:
+
+config:list        list environment variables for an app
+config:set         set environment variables for an app
+config:unset       unset environment variables for an app
+config:pull        extract environment variables to .env
+config:push        set environment variables from .env
+
+Use `drycc help [command]` to learn more.
+
+

When config is changed, a new release is created and deployed automatically.

+

You can set multiple environment variables with one drycc config:set command, +or with drycc config:push and a local .env file.

+
$ drycc config:set FOO=1 BAR=baz && drycc config:pull
+$ cat .env
+FOO=1
+BAR=baz
+$ echo "TIDE=high" >> .env
+$ drycc config:push
+Creating config... done, v4
+
+=== yuppie-earthman
+DRYCC_APP: yuppie-earthman
+FOO: 1
+BAR: baz
+TIDE: high
+
+

It can also modify environment variables for a process type of application.

+
$ drycc config:set FOO=1 BAR=baz --ptype=web
+
+

Attach to Backing Services

+

Drycc treats backing services like databases, caches and queues as attached resources. +Attachments are performed using environment variables.

+

For example, use drycc config to set a DATABASE_URL that attaches +the application to an external PostgreSQL database.

+
$ drycc config:set DATABASE_URL=postgres://user:pass@example.com:5432/db
+=== peachy-waxworks
+DATABASE_URL: postgres://user:pass@example.com:5432/db
+
+

Detachments can be performed with drycc config:unset.

+

Buildpacks Cache

+

By default, apps using the [Imagebuilder][] will reuse the latest image data. +When deploying applications that depend on third-party libraries that have to be fetched, +this could speed up deployments a lot. In order to make use of this, the buildpack must implement +the cache by writing to the cache directory. Most buildpacks already implement this, but when using +custom buildpacks, it might need to be changed to make full use of the cache.

+

Disabling and re-enabling the cache

+

In some cases, cache might not speed up your application. To disable caching, you can set the +DRYCC_DISABLE_CACHE variable with drycc config:set DRYCC_DISABLE_CACHE=1. When you disable the +cache, Drycc will clear up files it created to store the cache. After having it turned off, run +drycc config:unset DRYCC_DISABLE_CACHE to re-enable the cache.

+

Clearing the cache

+

Use the following procedure to clear the cache:

+
$ drycc config:set DRYCC_DISABLE_CACHE=1
+$ git commit --allow-empty -m "Clearing Drycc cache"
+$ git push drycc # (if you use a different remote, you should use your remote name)
+$ drycc config:unset DRYCC_DISABLE_CACHE
+
+

Custom Health Checks

+

By default, Workflow only checks that the application starts in their Container. If it is preferred +to have Kubernetes respond to application health, a health check may be added by configuring a +health check probe for the application.

+

The health checks are implemented as Kubernetes container probes. A liveness +and a readiness probe can be configured, and each probe can be of type httpGet, exec, or +tcpSocket depending on the type of probe the container requires.

+

A liveness probe is useful for applications running for long periods of time, eventually +transitioning to broken states and cannot recover except by restarting them.

+

Other times, a readiness probe is useful when the container is only temporarily unable to serve, +and will recover on its own. In this case, if a container fails its readiness probe, the container +will not be shut down, but rather the container will stop receiving incoming requests.

+

httpGet probes are just as it sounds: it performs a HTTP GET operation on the Container. A +response code inside the 200-399 range is considered a pass.

+

exec probes run a command inside the Container to determine its health, such as +cat /var/run/myapp.pid or a script that determines when the application is ready. An exit code of +zero is considered a pass, while a non-zero status code is considered a fail.

+

tcpSocket probes attempt to open a socket in the Container. The Container is only considered +healthy if the check can establish a connection. tcpSocket probes accept a port number to perform +the socket connection on the Container.

+

Health checks can be configured on a per-proctype basis for each application using drycc healthchecks:set. If no type is mentioned then the health checks are applied to default proc type web, whichever is present. To +configure a httpGet liveness probe:

+
$ drycc healthchecks:set liveness httpGet 80 --ptype web
+Applying livenessProbe healthcheck... done
+
+App:             peachy-waxworks
+UUID:            afd84067-29e9-4a5f-9f3a-60d91e938812
+Owner:           dev
+Created:         2023-12-08T10:25:00Z
+Updated:         2023-12-08T10:25:00Z
+Healthchecks:
+                 liveness web http-get headers=[] path=/ port=80 delay=50s timeout=50s period=10s #success=1 #failure=3
+

If the application relies on certain headers being set (such as the Host header) or a specific +URL path relative to the root, you can also send specific HTTP headers:

+
$ drycc healthchecks:set liveness httpGet 80 \
+    --path /welcome/index.html \
+    --headers "X-Client-Version:v1.0,X-Foo:bar"
+Applying livenessProbe healthcheck... done
+
+App:             peachy-waxworks
+UUID:            afd84067-29e9-4a5f-9f3a-60d91e938812
+Owner:           dev
+Created:         2023-12-08T10:25:00Z
+Updated:         2023-12-08T10:25:00Z
+Healthchecks:
+                 liveness web http-get headers=[X-Client-Version=v1.0] path=/welcome/index.html port=80 delay=50s timeout=50s period=10s #success=1 #failure=3
+

To configure an exec readiness probe:

+
$ drycc healthchecks:set readiness exec -- /bin/echo -n hello --ptype web
+Applying readinessProbe healthcheck... done
+
+App:             peachy-waxworks
+UUID:            afd84067-29e9-4a5f-9f3a-60d91e938812
+Owner:           dev
+Created:         2023-12-08T10:25:00Z
+Updated:         2023-12-08T10:25:00Z
+Healthchecks:
+                 readiness web exec /bin/echo -n hello delay=50s timeout=50s period=10s #success=1 #failure=3
+

You can overwrite a probe by running drycc healthchecks:set again:

+
$ drycc healthchecks:set readiness httpGet 80 --ptype web
+Applying livenessProbe healthcheck... done
+
+App:             peachy-waxworks
+UUID:            afd84067-29e9-4a5f-9f3a-60d91e938812
+Owner:           dev
+Created:         2023-12-08T10:25:00Z
+Updated:         2023-12-08T10:25:00Z
+Healthchecks:
+                 liveness web http-get headers=[] path=/ port=80 delay=50s timeout=50s period=10s #success=1 #failure=3
+

Configured health checks also modify the default application deploy behavior. When starting a new +Pod, Workflow will wait for the health check to pass before moving onto the next Pod.

+

Autodeploy

+

By default, Changes the config, limits or healthchecks and so on will trigger deploy. +If you don’t want deploy, you can disable.

+
$ drycc autodeploy:disable
+

To re-enable autodeploy.

+
drycc autodeploy:enable
+

you can deploy by executing the following command. +deploy all ptypes

+
drycc releases:deploy
+

deploy web process type, and support --force option to force deploy.

+
drycc releases:deploy web --force
+

Autorollback

+

By default, deployment failures will roll back to the previous successful version. +If you don’t want this to happen, you can disable.

+
$ drycc autorollback:disable
+

To re-enable autorollback.

+
drycc autorollback:enable
+

Isolate the Application

+

Workflow supports isolating applications onto a set of nodes using drycc tags.

+

!!! note +In order to use tags, you must first launch your cluster with the proper node labels. If you do +not, tag commands will fail. Learn more by reading “Assigning Pods to Nodes”.

+

Once your nodes are configured with appropriate label selectors, use drycc tags:set to restrict +the application ptype to those nodes:

+
$ drycc tags:set web environ=prod
+Applying tags...  done, v4
+
+environ  prod
+
+
+ + + + + + + + + + + +
+ +

7 - Managing Application Metrics

+
Metrics supports basic monitoring capabilities for Pod, providing various monitoring indicators such as CPU, memory, disk, network, etc., to meet the basic monitoring requirements for Pod resources.
+

Create an authentication token

+

Create an authentication token using the drycc client.

+
# drycc tokens:add prometheus --password admin --username admin
+ !    WARNING: Make sure to copy your token now.
+ !    You won't be able to see it again, please confirm whether to continue.
+ !    To proceed, type "yes" !
+
+> yes
+UUID                                  USERNAME    TOKEN                                                                                              
+58176cf1-37a8-4c52-9b27-4c7a47269dfb  admin       1F2c7A802aF640fd9F31dD846AdDf56BcMsay
+

Add scrape configurations for prometheus

+

A valid example file can be found here.

+

The global configuration specifies parameters that are valid in all other configuration contexts. They also serve as defaults for other configuration sections.

+
global:
+  scrape_interval:   60s
+  evaluation_interval: 60s
+scrape_configs:
+- job_name: 'drycc'
+  scheme: https
+  metrics_path: /v2/apps/<appname>/metrics
+  authorization:
+    type: Token
+    credentials: 1F2c7A802aF640fd9F31dD846AdDf56BcMsay
+  static_configs:
+  - targets: ['drycc.domain.com']
+
+
+ + + + + + + + + + + +
+ +

8 - Managing an Application

+
This is a high-level, technical description of how Drycc works. It ties together many of the concepts you’ll encounter while writing, configuring, deploying and running applications on the Drycc platform.
+

Track Application Changes

+

Drycc Workflow tracks all changes to your application. Application changes are the result of either new application code +pushed to the platform (via git push drycc master), or an update to application configuration (via drycc config:set KEY=VAL).

+

Each time a build or config change is made to your application a new release is created. These release numbers +increase monotonically.

+

You can see a record of changes to your application using drycc releases:

+
$ drycc releases
+OWNER    STATE      VERSION    CREATED                 SUMMARY
+dev      succeed    v3         2023-12-04T10:17:46Z    dev deleted PIP_INDEX_URL, DISABLE_COLLECTSTATIC
+dev      succeed    v2         2023-12-01T10:20:22Z    dev added IMAGE_PULL_POLICY, PIP_INDEX_URL, PORT, DISABLE_COLLEC[...]
+dev      succeed    v1         2023-11-30T17:54:57Z    dev created initial release
+

Rollback a Release

+

Drycc Workflow also supports rolling back go previous releases. If buggy code or an errant configuration change is pushed +to your application, you may rollback to a previously known, good release.

+

!!! note +All rollbacks create a new, numbered release. But will reference the build/code and configuration from the desired rollback point.

+

In this example, the application is currently running release v4. Using drycc rollback v2 tells Workflow to deploy the +build and configuration that was used for release v2. This creates a new release named v5 whose contents are the source +and configuration from release v2:

+
$ drycc releases
+OWNER    STATE      VERSION    CREATED                 SUMMARY
+dev      succeed    v3         2023-12-04T10:17:46Z    dev deleted PIP_INDEX_URL, DISABLE_COLLECTSTATIC
+dev      succeed    v2         2023-12-01T10:20:22Z    dev added IMAGE_PULL_POLICY, PIP_INDEX_URL, PORT, DISABLE_COLLEC[...]
+dev      succeed    v1         2023-11-30T17:54:57Z    dev created initial release
+
+$ drycc rollback v2
+Rolled back to v2
+
+$ drycc releases
+OWNER    STATE      VERSION    CREATED                 SUMMARY
+dev      succeed    v4         2023-12-04T10:20:46Z    dev rolled back to v2
+dev      succeed    v3         2023-12-04T10:17:46Z    dev deleted PIP_INDEX_URL, DISABLE_COLLECTSTATIC
+dev      succeed    v2         2023-12-01T10:20:22Z    dev added IMAGE_PULL_POLICY, PIP_INDEX_URL, PORT, DISABLE_COLLEC[...]
+dev      succeed    v1         2023-11-30T17:54:57Z    dev created initial release
+

Only rollback web process type:

+
$ drycc rollback v3 web
+Rolled back to v3
+
+$ drycc releases
+OWNER    STATE      VERSION    CREATED                 SUMMARY
+dev      succeed    v5         2023-12-04T10:23:49Z    dev rolled back to v3
+dev      succeed    v4         2023-12-04T10:20:46Z    dev rolled back to v2
+dev      succeed    v3         2023-12-04T10:17:46Z    dev deleted PIP_INDEX_URL, DISABLE_COLLECTSTATIC
+dev      succeed    v2         2023-12-01T10:20:22Z    dev added IMAGE_PULL_POLICY, PIP_INDEX_URL, PORT, DISABLE_COLLEC[...]
+dev      succeed    v1         2023-11-30T17:54:57Z    dev created initial release
+

Run One-off Administration Tasks

+

Drycc applications use one-off processes for admin tasks like database migrations and other commands that must run against the live application.

+

Use drycc run to execute commands on the deployed application.

+
$ drycc run 'ls -l'
+Running `ls -l`...
+
+total 28
+-rw-r--r-- 1 root root  553 Dec  2 23:59 LICENSE
+-rw-r--r-- 1 root root   60 Dec  2 23:59 Procfile
+-rw-r--r-- 1 root root   33 Dec  2 23:59 README.md
+-rw-r--r-- 1 root root 1622 Dec  2 23:59 pom.xml
+drwxr-xr-x 3 root root 4096 Dec  2 23:59 src
+-rw-r--r-- 1 root root   25 Dec  2 23:59 system.properties
+drwxr-xr-x 6 root root 4096 Dec  3 00:00 target
+
+

Share an Application

+

Use drycc perms:add to allow another Drycc user to collaborate on your application.

+
$ drycc perms:add otheruser view,change,delete
+Adding user otheruser as a collaborator for view,change,delete peachy-waxwork... done
+

Use drycc perms to see who an application is currently shared with, and drycc perms:remove to remove a collaborator.

+

!!! note +Collaborators can do anything with an application that its owner can do, except delete the application.

+

When working with an application that has been shared with you, clone the original repository and add Drycc’ git remote +entry before attempting to git push any changes to Drycc.

+
$ git clone https://github.com/drycc/example-java-jetty.git
+Cloning into 'example-java-jetty'... done
+$ cd example-java-jetty
+$ git remote add -f drycc ssh://git@local3.dryccapp.com:2222/peachy-waxworks.git
+Updating drycc
+From drycc-controller.local:peachy-waxworks
+ * [new branch]      master     -> drycc/master
+

Application Troubleshooting

+

Applications deployed on Drycc Workflow treat logs as event streams. Drycc Workflow aggregates stdout and stderr +from every Container making it easy to troubleshoot problems with your application.

+

Use drycc logs to view the log output from your deployed application.

+
$ drycc logs -f
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.5]: INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null}
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.8]: INFO:oejs.Server:jetty-7.6.0.v20120127
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.5]: INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:10005
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.6]: INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null}
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.7]: INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null}
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.6]: INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:10006
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.8]: INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null}
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.7]: INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:10007
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.8]: INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:10008
+
+ +
+ + + + + + + + + + + +
+ +

9 - Mounting volumes for an Application

+
Drycc supports many types of volumes. A container can use any number of volume types simultaneously.
+

We can use the blow command to create volumes and mount the created volumes. +Drycc create volume support ReadWriteMany, so before deploying drycc, you need to have a StorageClass ready which can support ReadWriteMany. +Deploying drycc, set controller.appStorageClass to this StorageClass.

+

Use drycc volumes to mount a volume for a deployed application’s processes.

+
$ drycc help volumes
+Valid commands for volumes:
+
+volumes:create           create a volume for the application
+volumes:list             list volumes in the application
+volumes:delete           delete a volume from the application
+volumes:client           the client used to manage volume files
+volumes:mount            mount a volume to process of the application
+volumes:unmount          unmount a volume from process of the application
+
+Use 'drycc help [command]' to learn more.
+
+

Create a volume for the application

+

You can create a csi volume with the drycc volumes:create command.

+
$ drycc volumes:create myvolume 200M
+Creating myvolumes to scenic-icehouse... done
+
+

Or use an existing nfs server

+
$ drycc volumes:create myvolume 200M -t nfs --nfs-server=nfs.drycc.com --nfs-path=/
+Creating myvolumes to scenic-icehouse... done
+
+

List volumes in the application

+

After volume is created, you can list the volumes in this application.

+
$ drycc volumes:list
+=== scenic-icehouse volumes
+--- myvolumes     200M
+
+

Mount a volume

+

The volume which is named myvolumes is created, you can mount the volume with process of the application, +use the command of drycc volumes:mount. When volume is mounted, a new release will be created and deployed automatically.

+
$ drycc volumes:mount myvolumes web=/data/web
+Mounting volume... done
+
+

And use drycc volumes:list show mount detail.

+
$ drycc volumes:list
+=== scenic-icehouse volumes
+--- myvolumes     200M
+web               /data/web
+
+

If you don’t need the volume, use drycc volumes:unmount to unmount the volume and then use drycc volumes:delete to delete the volume from the application. +Before deleting volume, the volume has to be unmounted.

+
$ drycc volumes:unmount myvolumes web
+Unmounting volume... done
+
+$ drycc volumes:delete myvolumes
+Deleting myvolumes from scenic-icehouse... done
+
+

Use volume client to manage volume files.

+

Assume the volume which is named myvolumes is created and mounted.

+

Prepare a file named testfile.

+
$ echo "testtext" > testfile
+
+

Upload. +$ drycc volumes:client cp testfile vol://myvolume/ +[↑] testfile 100% [==================================================] (5/ 5 B, 355 B/s)

+

List files in myvolume.

+
$ drycc volumes:client ls vol://myvolume/
+[2024-07-22T15:32:28+08:00]    5    testfile
+
+

Delete testfle in myvolume.

+
$ drycc volumes:client rm vol://myvolume/testfile
+ +
+ + + + + + + + + + + +
+ +

10 - About gateway for an Application

+
A Gateway describes how traffic can be translated to Services within the cluster.
+

A Gateway describes how traffic can be translated to Services within the cluster. That is, it defines a request for a way to translate traffic from somewhere that does not know about Kubernetes to somewhere that does. For example, traffic sent to a Kubernetes Service by a cloud load balancer, an in-cluster proxy, or an external hardware load balancer. While many use cases have client traffic originating “outside” the cluster, this is not a requirement.

+

Create Gateway for an Application

+

Gateway is a way of exposing services externally, which generates an external IP address to connect route and service. +After deploy, the gateway has been created.

+

List the containers:

+
# drycc gateways
+NAME                      LISENTER       PORT     PROTOCOL    ADDRESSES      
+python-getting-started    tcp-80-0       80       HTTP        101.65.132.51     
+

You can also add a port in this gateway or create a one.

+
# drycc gateways:add python-getting-started --port=443 --protocol=HTTPS
+Adding gateway python-getting-started to python-getting-started... done     
+

Create service for an Application

+

Service is a way of exposing services internally, creating a service generates an internal DNS that can access ptype. +the web process type has been created, for others types, you should add as needed.

+

List the services:

+
$ drycc services
+PTYPE      PORT    PROTOCOL    TARGET-PORT    DOMAIN                                    
+web        80      TCP         8000           python-getting-started.python-getting-started.svc.cluster.local  
+

Add a new service for process type

+
# drycc services:add --help
+# drycc services:add sleep 8001:8001
+

Create Route for an Application

+

A Gateway may be attached to one or more Route references which serve to direct traffic for a subset of traffic to a specific service. +Same as the above, the web process type already bind the gateway and servies.

+
# drycc routes
+NAME                           OWNER        PTYPE      KIND         SERVICE-PORT    GATEWAY                           LISTENER-PORT             
+python-getting-started         demo         web        HTTPRoute    80              python-getting-started            80  
+

create a new route and attach gateway.

+
drycc routes:create sleep --ptype=sleep --kind=HTTPRoute --port=8001
+drycc routes:attach sleep --gateway=python-getting-started --port=80
+
+
+ + + + + + + + + + + +
+ +

11 - Managing resources for an Application

+
Tools and services for developing, extending, and operating your app.
+

We can use blow command to create resources and bind which resource is created. +This command depend on service-catalog.

+

Use drycc resources to create and bind a resource for a deployed application.

+
$ drycc help resources
+
+Valid commands for resources:
+
+resources:services         list all available resource services
+resources:plans            list all available plans for an resource services
+resources:create           create a resource for the application
+resources:list             list resources in the application
+resources:describe         get a resource detail info in the application
+resources:update           update a resource from the application
+resources:destroy          delete a resource from the applicationa
+resources:bind             bind a resource to servicebroker
+resources:unbind           unbind a resource from servicebroker
+
+Use 'drycc help [command]' to learn more.
+
+

List all available resource services

+

You can list available resource services with one drycc resources:services command

+
$ drycc resources:services
+ID                                      NAME                  UPDATEABLE 
+15032a52-33c2-4b40-97aa-ceb972f51509    airflow               true          
+b7cb26a4-b258-445c-860b-a664239a67f8    cloudbeaver           true          
+9ce3c3ba-33b5-4e4e-a5e9-a338a83d5070    flink                 true          
+b80c51a1-957c-4d93-b3d5-efde84cd8031    fluentbit             true          
+fff5b6c7-ed85-429b-8265-493e40cc53c7    grafana               true          
+412e368f-bf78-4798-92cc-43343119a57d    kafka                 true          
+ea2a9b87-fbc4-4e2a-adee-161c1f91d98d    minio                 true          
+383f7316-84f3-4955-8491-1d4b02b749c8    mongodb               true          
+fbee746b-f3a7-4bef-8b55-cbecfd4c8ac3    mysql-cluster         true          
+5975094d-45cc-4e85-8573-f93937d026c7    opensearch            true          
+1db95161-7193-4544-8c76-e5ad5f6c03f6    pmm                   true          
+5cfb0abf-276c-445b-9060-9aa964ede87d    postgresql-cluster    true          
+b8f70264-eafc-4b2f-848e-2ec0d059032b    prometheus            true          
+f8186d36-f334-4094-8e02-d21a61da657b    rabbitmq              true          
+e1fd0d37-9046-4152-a29b-d155c5657c8b    redis                 true          
+7d2b64c6-0b59-4f08-a2f5-7b17cea6e5ee    redis-cluster         true          
+2e6877df-86e7-4bcc-a869-2a9b6847a465    seaweedfs             true          
+4aea5c0f-9495-420d-896a-ffc61a3eced5    spark                 true          
+b50db3b5-8d5f-4be9-b8bd-467ecd6cc11d    zookeeper             true
+
+

List all available plans for an resource services

+

You can list all available plans for an resource services with one drycc resources:plans command

+
$ drycc resources:plans redis
+ID                                      NAME              DESCRIPTION                                                       
+8d659058-a3b4-4058-b039-cc03a31b9442    standard-128      Redis standard-128 plan which limit resources memory size 128Mi.     
+36e3dbec-fc51-4f6b-9baa-e31e316858be    standard-256      Redis standard-256 plan which limit resources memory size 256Mi.     
+560817c2-5aa1-41c4-9ee6-a77e3ee552d5    standard-512      Redis standard-512 plan which limit resources memory size 512Mi.     
+d544d989-9fb8-43e9-a74e-0840ce1b8f0f    standard-1024     Redis standard-1024 plan which limit resources memory size 1Gi.      
+ad51b7bb-9b12-4ffd-8e49-010c0141b263    standard-2048     Redis standard-2048 plan which limit resources memory size 2Gi.      
+5097d76e-557c-453f-bdb1-54009e0df78d    standard-4096     Redis standard-4096 plan which limit resources memory size 4Gi.      
+be3fa2d0-36d2-47c5-9561-9deffe5ba373    standard-8192     Redis standard-8192 plan which limit resources memory size 8Gi.      
+4ca812a8-d7c3-439f-96cd-26523e88400e    standard-16384    Redis standard-16384 plan which limit resources memory size 16Gi.    
+b7f2a71f-0d97-48fd-8eed-aab24a7822f3    standard-32768    Redis standard-32768 plan which limit resources memory size 32Gi.    
+25c6b5d5-7505-47c8-95b1-dc9bdc698063    standard-65536    Redis standard-65536 plan which limit resources memory size 64Gi.
+
+

Create resource in application

+

You can create a resource with one drycc resources:create command

+
$ drycc resources:create redis:1000 redis
+Creating redis to scenic-icehouse... done
+
+

After resources are created, you can list the resources in this application.

+
$ drycc resources:list
+UUID                                    NAME     OWNER    PLAN                  UPDATED              
+07220e9e-d54d-4d74-a88c-f464aa374386    redis    admin    redis:standard-128    2024-05-08T01:01:00Z   
+
+

Bind resources

+

The resource which is named redis is created, you can bind the redis to the application, +use the command of drycc resources:bind redis.

+
$ drycc resources:bind redis
+Binding resource... done
+
+

Describe resources

+

And use drycc resources:describe show the binding detail. If the binding is successful, this command will show the information of connect to the resource.

+
$ drycc resources:describe redis
+=== scenic-icehouse resource redis
+plan:               redis:1000
+status:             Ready
+binding:            Ready
+
+REDISPORT:          6379
+REDIS_PASSWORD:     RzG87SJWG1
+SENTINELHOST:       172.16.0.2
+SENTINELPORT:       26379
+
+

Update resources

+

You can use the drycc resources:update command to upgrade a new plan. +An example of how to upgrade the plan’s capacity to 100MB:

+
$ drycc resources:update redis:10000 redis
+Updating redis to scenic-icehouse... done
+
+

Remove the resource

+

If you don’t need resources, use drycc resources:unbind to unbind the resource and then use drycc resources:destroy to delete the resource from the application. +Before deleting the resource, the resource must be unbinded.

+
$ drycc resources:unbind redis
+Unbinding resource... done
+
+$ drycc resources:destroy redis
+Deleting redis from scenic-icehouse... done
+
+ +
+ + + + + + + + + + + +
+ +

12 - Inter-app Communication

+
The Communication Solution between Drycc Applicatios.
+

A common architecture pattern of multi-process applications is to have one process serve public requests while having multiple other processes supporting the public one to, for example, perform actions on a schedule or process work items from a queue. To implement this system of apps in Drycc Workflow, set up the apps to communicate using DNS resolution, as shown above, and hide the supporting processes from public view by removing them from the Drycc Workflow router.

+

DNS Service Discovery

+

Drycc Workflow supports deploying a single app composed of a system of processes. Each Drycc Workflow app communicates on a single port, so communicating with another Workflow app means finding that app’s address and port. All Workflow apps are mapped to port 80 externally, so finding its IP address is the only challenge. Workflow creates a Kubernetes Service for each app, which effectively assigns a name and one cluster-internal IP address to an app. The DNS service running in the cluster adds and removes DNS records which point from the app name to its IP address as services are added and removed. Drycc Workflow apps, then, can simply send requests to the domain name given to the service, which is “app-name.app-namespace”.

+ +
+ + + + + + + + + + + +
+ +

13 - Resource Limits

+
Drycc Workflow supports restricting memory and CPU shares of each process.
+

+

Managing Application Resource Limits

+

Drycc Workflow supports restricting memory and CPU shares of each process. Requests/Limits set on a per-process type are given to +Kubernetes as a requests and limits. Which means you guarantee <requests> amount of resource for a process as well as limit +the process from using more than <limits>. +By default, Kubernetes will set <requests> equal to <limit> if we don’t explicitly set <requests> value. Please keep in mind that 0 <= requests <= limits.

+

Limiting

+

If you set a requests/limits that is out of range for your cluster, Kubernetes will be unable to schedule your application +processes into the cluster!

+
$ drycc limits:plans
+
+ID                    SPEC    CPU              VCPUS    MEMORY     FEATURES                      
+std1.large.c1m1       std1    Universal CPU    1        1 GiB      Integrated GPU shared    
+std1.large.c1m2       std1    Universal CPU    1        2 GiB      Integrated GPU shared    
+std1.large.c1m4       std1    Universal CPU    1        4 GiB      Integrated GPU shared    
+std1.large.c1m8       std1    Universal CPU    1        8 GiB      Integrated GPU shared    
+std1.large.c2m2       std1    Universal CPU    2        2 GiB      Integrated GPU shared    
+std1.large.c2m4       std1    Universal CPU    2        4 GiB      Integrated GPU shared    
+std1.large.c2m8       std1    Universal CPU    2        8 GiB      Integrated GPU shared    
+std1.large.c2m16      std1    Universal CPU    2        16 GiB     Integrated GPU shared    
+
+$ drycc limits:set web=std1.large.c1m1
+Applying limits... done
+
+
+ + + + + + + + + + + +
+ +

14 - Domains and Routing

+
Make your apps accessible via custom domain names.
+

You can use drycc domains to add or remove custom domains to the application:

+
$ drycc domains:add hello.bacongobbler.com --ptype=web
+Adding hello.bacongobbler.com to finest-woodshed... done
+
+

Once that’s done, you can go into a DNS registrar and set up a CNAME from the new +appname to the old one:

+
$ dig hello.dryccapp.com
+[...]
+;; ANSWER SECTION:
+hello.bacongobbler.com.         1759    IN    CNAME    finest-woodshed.dryccapp.com.
+finest-woodshed.dryccapp.com.    270     IN    A        172.17.8.100
+
+

!!! note +Setting a CNAME for a root domain can cause issues. Setting an @ record +to be a CNAME causes all traffic to go to the other domain, including mail and the SOA +(“start-of-authority”) records. It is highly recommended that you bind a subdomain to +an application, however you can work around this by pointing the @ record to the +address of the load balancer (if any).

+

To add or remove the application from the routing mesh, use drycc routing:

+
$ drycc routing:disable
+Disabling routing for finest-woodshed... done
+
+

This will make the application unreachable through the Router, but the application is still +reachable internally through its Kubernetes Service. To re-enable routing:

+
$ drycc routing:enable
+Enabling routing for finest-woodshed... done
+
+ +
+ + + + + + + + + + + +
+ +

15 - Application SSL Certificates

+
SSL is a cryptographic protocol that provides end-to-end encryption and integrity for all web requests.
+

Application SSL Certificates

+

SSL is a cryptographic protocol that provides end-to-end encryption and integrity for all web +requests. Apps that transmit sensitive data should enable SSL to ensure all information is +transmitted securely.

+

To enable SSL on a custom domain, e.g., www.example.com, use the SSL endpoint.

+

!!! note +drycc certs is only useful for custom domains. Default application domains are +SSL-enabled already and can be accessed simply by using https, +e.g. https://foo.dryccapp.com (provided that you have installed your wildcard +certificate on the routers or on the load balancer).

+

Overview

+

Because of the unique nature of SSL validation, provisioning SSL for your domain is a multi-step +process that involves several third-parties. You will need to:

+
    +
  1. Purchase an SSL certificate from your SSL provider
  2. +
  3. Upload the cert to Drycc
  4. +
+

Acquire SSL Certificate

+

Purchasing an SSL cert varies in cost and process depending on the vendor. RapidSSL offers a +simple way to purchase a certificate and is a recommended solution. If you’re able to use this +provider, see buy an SSL certificate with RapidSSL for instructions.

+

DNS and Domain Configuration

+

Once the SSL certificate is provisioned and your cert is confirmed, you must route requests for +your domain through Drycc. Unless you’ve already done so, add the domain specified when generating +the CSR to your app with:

+
$ drycc domains:add www.example.com --ptype==web -a foo
+Adding www.example.com to foo... done
+
+

Add a Certificate

+

Add your certificate, any intermediate certificates, and private key to the endpoint with the +certs:add command.

+
$ drycc certs:add example-com server.crt server.key -a foo
+Adding SSL endpoint... done
+www.example.com
+
+

!!! note +The name given to the certificate can only contain a-z (lowercase), 0-9 and hyphens

+

The Drycc platform will investigate the certificate and extract any relevant information from it +such as the Common Name, Subject Alt Names (SAN), fingerprint and more.

+

This allows for wildcard certificates and multiple domains in the SAN without uploading duplicates.

+

Add a Certificate Chain

+

Sometimes, your certificates (such as a self-signed or a cheap certificate) need additional +certificates to establish the chain of trust. What you need to do is bundle all the certificates +into one file and give that to Drycc. Importantly, your site’s certificate must be the first one:

+
$ cat server.crt server.ca > server.bundle
+
+

After that, you can add them to Drycc with the certs:add command:

+
$ drycc certs:add example-com server.bundle server.key -a foo
+Adding SSL endpoint... done
+www.example.com
+
+

Attach SSL certificate to a domain

+

Certificates are not automagically connected up to domains, instead you will have to attach a +certificate to a domain

+
$ drycc certs:attach example-com example.com -a foo
+
+

Each certificate can be connected to many domains. There is no need to upload duplicates.

+

To remove an association

+
$ drycc certs:detach example-com example.com -a foo
+
+

Endpoint overview

+

You can verify the details of your domain’s SSL configuration with drycc certs.

+
$ drycc certs
+
+     Name     |    Common Name    | SubjectAltName    |         Expires         |   Fingerprint   |   Domains    |   Updated   |   Created
++-------------+-------------------+-------------------+-------------------------+-----------------+--------------+-------------+-------------+
+  example-com |     example.com   | blog.example.com  | 31 Dec 2017 (in 1 year) | 8F:8E[...]CD:EB |  example.com | 30 Jan 2016 | 29 Jan 2016
+
+

or by looking at at each certificates detailed information

+
$ drycc certs:info example-com -a foo
+
+=== bar-com Certificate
+Common Name(s):     example.com
+Expires At:         2017-01-14 23:57:57 +0000 UTC
+Starts At:          2016-01-15 23:57:57 +0000 UTC
+Fingerprint:        7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0
+Subject Alt Name:   blog.example.com
+Issuer:             /C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=example.com/emailAddress=engineering@drycc.cc
+Subject:            /C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=example.com/emailAddress=engineering@drycc.cc
+
+Connected Domains:  example.com
+Owner:              admin-user
+Created:            2016-01-28 19:07:41 +0000 UTC
+Updated:            2016-01-30 00:10:02 +0000 UTC
+
+

Testing SSL

+

Use a command line utility like curl to test that everything is configured correctly for your +secure domain.

+

!!! note +The -k option flag tells curl to ignore untrusted certificates.

+

Pay attention to the output. It should print SSL certificate verify ok. If it prints something +like common name: www.example.com (does not match 'www.somedomain.com') then something is not +configured correctly.

+

Enforcing SSL at the Router

+

To enforce all HTTP requests be redirected to HTTPS, TLS can be enforced at the router level by +running

+
$ drycc tls:force:enable -a foo
+Enabling https-only requests for foo... done
+
+

Users hitting the HTTP endpoint for the application will now receive a 301 redirect to the HTTPS +endpoint.

+

To disable enforced TLS, run

+
$ drycc tls:force:disable -a foo
+Disabling https-only requests for foo... done
+
+

Automated Certificate Management

+

With Automated Certificate Management (ACM), Drycc automatically manages TLS certificates for apps with Hobby and Professional dynos on the Common Runtime, and for apps in Private Spaces that enable the feature. +Certificates handled by ACM automatically renew one month before they expire, and new certificates are created automatically whenever you add or remove a custom domain. All applications with paid dynos include ACM for free. +Automated Certificate Management uses Let’s Encrypt, the free, automated, and open certificate authority for managing your application’s TLS certificates. Let’s Encrypt is run for the public benefit by the Internet Security Research Group (ISRG).

+

To enable ACM with the following command: +$ drycc tls:auto:enable -a foo

+

To disable ACM with the following command: +$ drycc tls:auto:disable -a foo

+

Remove Certificate

+

You can remove a certificate using the certs:remove command:

+
$ drycc certs:remove my-cert -a foo
+Removing www.example.com... Done.
+
+

Swapping out certificates

+

Over the lifetime of an application an operator will have to acquire certificates with new expire +dates and apply it to all relevant applications, below is the recommended way to swap out certificates.

+

Be intentional with certificate names, name them example-com-2017 when possible, where the year +signifies the expiry year. This allows for example-com-2018 when a new certificate is purchased.

+

Assuming all applications are already using example-com-2017 the following commands can be ran, +chained together or otherwise:

+
$ drycc certs:detach example-com-2017 example.com -a foo
+$ drycc certs:attach example-com-2018 example.com -a foo
+
+

This will take care of a singular domain which allows the operator to verify everything went +as planned and slowly roll it out to any other application using the same method.

+

Troubleshooting

+

Here are some steps you can follow if your SSL endpoint is not working as you’d expect.

+

Untrusted Certificate

+

In some cases when accessing the SSL endpoint, it may list your certificate as untrusted.

+

If this occurs, it may be because it is not trusted by Mozilla’s list of root CAs. If this is +the case, your certificate may be considered untrusted for many browsers.

+

If you have uploaded a certificate that was signed by a root authority but you get the message that +it is not trusted, then something is wrong with the certificate. For example, it may be missing +intermediary certificates. If so, download the intermediary certificates from your SSL provider, +remove the certificate from Drycc and re-run the certs:add command.

+ +
+ + + + + + + + + + + +
+ +

16 - Using drycc.yaml

+
Drycc Container Registry allows you to deploy your Docker-based app to Drycc. Both Common Runtime and Private Spaces are supported.
+

The Drycc stack is intended for advanced use cases only. Unless you have a specific need for custom Docker images, we recommend using Drycc’s default buildpack-powered build system. It offers automatic base image security updates and language-specific optimizations. It also avoids the need to maintain a .containerDockerfile

+

drycc.yaml Overview

+

A manifest has three top-level sections.

+
    +
  • build – Specifies the to build Dockerfile
  • +
  • run – Specifies the release phase tasks to execute
  • +
  • deploy – Specifies process types and the commands to run for each type
  • +
+

Here’s an example that illustrates using a manifest to build Docker images.

+
build:
+  docker:
+    web: Dockerfile
+    worker: worker/Dockerfile
+  config:
+    web:
+      FOO: bar
+    worker:
+      RAILS_ENV: development
+run:
+- command:
+  - ./deployment-tasks.sh
+  image: worker
+  # If the field is empty, it means it will be executed forever
+  when:
+    ptypes:
+    - web
+    - webbbsbs
+  # Maximum execution time
+  timeout: 100
+deploy:
+  web:
+    command:
+    - bash
+    - -ec
+    args:
+    - bundle exec puma -C config/puma.rb
+  worker:
+    command:
+    - bash
+    - -ec
+    args:
+    - python myworker.py
+  asset-syncer:
+    command:
+    - bash
+    - -ec
+    args:
+    - python asset-syncer.py
+    image: worker
+

For more deployment information, please refer to the drycc examples.

+ +
+ + + + + + + + + +
+
+
+ + +
+ + + + + + diff --git a/docs/applications/deploying-apps/index.html b/docs/applications/deploying-apps/index.html new file mode 100644 index 000000000..82f7e752f --- /dev/null +++ b/docs/applications/deploying-apps/index.html @@ -0,0 +1,561 @@ + + + + + + + + + + + + + + + + + + + +Deploying an Application | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Deploying an Application

+
Learn how to deploy the application to drycc.
+ +

An Application is deployed to Drycc using git push or the drycc client.

+

Supported Applications

+

Drycc Workflow can deploy any application or service that can run inside a container. In order to be scaled +horizontally, applications must follow the Twelve-Factor App methodology and store any application state in external +backing services.

+

For example, if your application persists state to the local filesystem – common with content management systems like +Wordpress and Drupal – it cannot be scaled horizontally using drycc scale.

+

Fortunately, most modern applications feature a stateless application tier that can scale horizontally inside Drycc.

+

Login to the Controller

+

!!! important +if you haven’t yet, now is a good time to install the client and register.

+

Before deploying an application, users must first authenticate against the Drycc Controller +using the URL supplied by their Drycc administrator.

+
$ drycc login http://drycc.example.com
+Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71
+Waiting for login... .o.Logged in as admin
+Configuration file written to /root/.drycc/client.json
+

Or you can login with username and password

+
$ drycc login http://drycc.example.com --username=demo --password=demo
+Configuration file written to /root/.drycc/client.json
+

Select a Build Process

+

Drycc Workflow supports three different ways of building applications:

+

Buildpacks

+

Cloud Native Buildpacks are useful if you want to follow cnb’s docs for building applications.

+

Learn how to deploy applications using Buildpacks.

+

Dockerfiles

+

Dockerfiles are a powerful way to define a portable execution environment built on a base OS of your choosing.

+

Learn how to deploy applications using Dockerfiles.

+

Container Image

+

Deploying a Container image onto Drycc allows you to take a Container image from either a public +or a private registry and copy it over bit-for-bit, ensuring that you are running the same +image in development or in your CI pipeline as you are in production.

+

Learn how to deploy applications using Container images.

+

Tuning Application Settings

+

It is possible to configure a few of the globally tunable settings on per application basis using config:set.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SettingDescription
DRYCC_DISABLE_CACHEif set, this will disable the [imagebuilder cache][] (default: not set)
DRYCC_DEPLOY_BATCHESthe number of pods to bring up and take down sequentially during a scale (default: number of available nodes)
DRYCC_DEPLOY_TIMEOUTdeploy timeout in seconds per deploy batch (default: 120)
IMAGE_PULL_POLICYthe kubernetes [image pull policy][pull-policy] for application images (default: “IfNotPresent”) (allowed values: “Always”, “IfNotPresent”)
KUBERNETES_DEPLOYMENTS_REVISION_HISTORY_LIMIThow many revisions Kubernetes keeps around of a given Deployment (default: all revisions)
KUBERNETES_POD_TERMINATION_GRACE_PERIOD_SECONDShow many seconds kubernetes waits for a pod to finish work after a SIGTERM before sending SIGKILL (default: 30)
+

Deploy Timeout

+

Deploy timeout in seconds - There are 2 deploy methods, Deployments (see below) and RC (versions prior to 2.4) and this setting affects those a bit differently.

+

Deployments

+

Deployments behave a little bit differently from the RC based deployment strategy.

+

Kubernetes takes care of the entire deploy, doing rolling updates in the background. As a result, there is only an overall deployment timeout instead of a configurable per-batch timeout.

+

The base timeout is multiplied with DRYCC_DEPLOY_BATCHES to create an overall timeout. This would be 240 (timeout) * 4 (batches) = 960 second overall timeout.

+

RC deploy

+

This deploy timeout defines how long to wait for each batch to complete in DRYCC_DEPLOY_BATCHES.

+

Additions to the base timeout

+

The base timeout is extended as well with healthchecks using initialDelaySeconds on liveness and readiness where the bigger of those two is applied. +Additionally the timeout system accounts for slow image pulls by adding an additional 10 minutes when it has seen an image pull take over 1 minute. This allows the timeout values to be reasonable without having to account for image pull slowness in the base deploy timeout.

+

Deployments

+

Workflow uses Deployments for deploys. In prior versions ReplicationControllers were used with the ability to turn on Deployments via DRYCC_KUBERNETES_DEPLOYMENTS=1.

+

The advantage of Deployments is that rolling-updates will happen server-side in Kubernetes instead of in Drycc Workflow Controller, +along with a few other Pod management related functionality. This allows a deploy to continue even when the CLI connection is interrupted.

+

Behind the scenes your application deploy will be built up of a Deployment object per process type, +each having multiple ReplicaSets (one per release) which in turn manage the Pods running your application.

+

Drycc Workflow will behave the same way with DRYCC_KUBERNETES_DEPLOYMENTS enabled or disabled (only applicable to versions prior to 2.4). +The changes are behind the scenes. Where you will see differences while using the CLI is drycc ps:list will output Pod names differently.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/applications/domains-and-routing/index.html b/docs/applications/domains-and-routing/index.html new file mode 100644 index 000000000..e788a8560 --- /dev/null +++ b/docs/applications/domains-and-routing/index.html @@ -0,0 +1,479 @@ + + + + + + + + + + + + + + + + + + + +Domains and Routing | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Domains and Routing

+
Make your apps accessible via custom domain names.
+ +

You can use drycc domains to add or remove custom domains to the application:

+
$ drycc domains:add hello.bacongobbler.com --ptype=web
+Adding hello.bacongobbler.com to finest-woodshed... done
+
+

Once that’s done, you can go into a DNS registrar and set up a CNAME from the new +appname to the old one:

+
$ dig hello.dryccapp.com
+[...]
+;; ANSWER SECTION:
+hello.bacongobbler.com.         1759    IN    CNAME    finest-woodshed.dryccapp.com.
+finest-woodshed.dryccapp.com.    270     IN    A        172.17.8.100
+
+

!!! note +Setting a CNAME for a root domain can cause issues. Setting an @ record +to be a CNAME causes all traffic to go to the other domain, including mail and the SOA +(“start-of-authority”) records. It is highly recommended that you bind a subdomain to +an application, however you can work around this by pointing the @ record to the +address of the load balancer (if any).

+

To add or remove the application from the routing mesh, use drycc routing:

+
$ drycc routing:disable
+Disabling routing for finest-woodshed... done
+
+

This will make the application unreachable through the Router, but the application is still +reachable internally through its Kubernetes Service. To re-enable routing:

+
$ drycc routing:enable
+Enabling routing for finest-woodshed... done
+
+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/applications/index.html b/docs/applications/index.html new file mode 100644 index 000000000..780bdd1db --- /dev/null +++ b/docs/applications/index.html @@ -0,0 +1,550 @@ + + + + + + + + + + + + + + + + + + + + + +Applications | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Applications

+
A simple and scalable cloud platform for all developer needs.
+ + +
+ + +
+
+
+ Deploying an Application +
+

Learn how to deploy the application to drycc.

+
+
+
+ Using Buildpacks +
+

An overview of buildpacks, which are responsible for transforming deployed code into a slug, which can then be executed on a container.

+
+
+
+ Using Dockerfiles +
+

Drycc Container Registry allows you to deploy your Docker-based app to Drycc. Both Common Runtime and Private Spaces are supported.

+
+
+
+ Using Docker Images +
+

Deploy an application using a container image stored in your Drycc Container Registry.

+
+
+
+ Managing Application Processes +
+

A Procfile is a list of process types in an app. Each process type declares a command that is executed when a container of that process type is started.

+
+
+
+ Configuring an Application +
+

How to store configuration of a Drycc app in the environment, keeping config out of code, making it easy to maintain app or deployment specific configs.

+
+
+
+ Managing Application Metrics +
+

Metrics supports basic monitoring capabilities for Pod, providing various monitoring indicators such as CPU, memory, disk, network, etc., to meet the basic monitoring requirements for Pod resources.

+
+
+
+ Managing an Application +
+

This is a high-level, technical description of how Drycc works. It ties together many of the concepts you’ll encounter while writing, configuring, deploying and running applications on the Drycc platform.

+
+
+
+ Mounting volumes for an Application +
+

Drycc supports many types of volumes. A container can use any number of volume types simultaneously.

+
+
+
+ About gateway for an Application +
+

A Gateway describes how traffic can be translated to Services within the cluster.

+
+
+
+ Managing resources for an Application +
+

Tools and services for developing, extending, and operating your app.

+
+
+
+ Inter-app Communication +
+

The Communication Solution between Drycc Applicatios.

+
+
+
+ Resource Limits +
+

Drycc Workflow supports restricting memory and CPU shares of each process.

+
+
+
+ Domains and Routing +
+

Make your apps accessible via custom domain names.

+
+
+
+ Application SSL Certificates +
+

SSL is a cryptographic protocol that provides end-to-end encryption and integrity for all web requests.

+
+
+
+ Using drycc.yaml +
+

Drycc Container Registry allows you to deploy your Docker-based app to Drycc. Both Common Runtime and Private Spaces are supported.

+
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+
+ +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/applications/index.xml b/docs/applications/index.xml new file mode 100644 index 000000000..4c27c55bb --- /dev/null +++ b/docs/applications/index.xml @@ -0,0 +1,1574 @@ + + + Drycc – Applications + /docs/applications/ + Recent content in Applications on Drycc + Hugo -- gohugo.io + en + + + + + + + + + + + Docs: Deploying an Application + /docs/applications/deploying-apps/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/applications/deploying-apps/ + + + + <p>An <a href="../reference-guide/terms.md#application">Application</a> is deployed to Drycc using <code>git push</code> or the <code>drycc</code> client.</p> +<h2 id="supported-applications">Supported Applications<a class="td-heading-self-link" href="#supported-applications" aria-label="Heading self-link"></a></h2> +<p>Drycc Workflow can deploy any application or service that can run inside a container. In order to be scaled +horizontally, applications must follow the <a href="http://12factor.net/">Twelve-Factor App</a> methodology and store any application state in external +backing services.</p> +<p>For example, if your application persists state to the local filesystem &ndash; common with content management systems like +Wordpress and Drupal &ndash; it cannot be scaled horizontally using <code>drycc scale</code>.</p> +<p>Fortunately, most modern applications feature a stateless application tier that can scale horizontally inside Drycc.</p> +<h2 id="login-to-the-controller">Login to the Controller<a class="td-heading-self-link" href="#login-to-the-controller" aria-label="Heading self-link"></a></h2> +<p>!!! important +if you haven&rsquo;t yet, now is a good time to <a href="/docs/users/cli/#installation">install the client</a> and <a href="/docs/users/registration/">register</a>.</p> +<p>Before deploying an application, users must first authenticate against the Drycc <a href="/docs/understanding-workflow/components/#controller">Controller</a> +using the URL supplied by their Drycc administrator.</p> +<pre tabindex="0"><code>$ drycc login http://drycc.example.com +Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71 +Waiting for login... .o.Logged in as admin +Configuration file written to /root/.drycc/client.json +</code></pre><p>Or you can login with username and password</p> +<pre tabindex="0"><code>$ drycc login http://drycc.example.com --username=demo --password=demo +Configuration file written to /root/.drycc/client.json +</code></pre><h2 id="select-a-build-process">Select a Build Process<a class="td-heading-self-link" href="#select-a-build-process" aria-label="Heading self-link"></a></h2> +<p>Drycc Workflow supports three different ways of building applications:</p> +<h3 id="buildpacks">Buildpacks<a class="td-heading-self-link" href="#buildpacks" aria-label="Heading self-link"></a></h3> +<p>Cloud Native Buildpacks are useful if you want to follow <a href="https://buildpacks.io/docs/">cnb&rsquo;s docs</a> for building applications.</p> +<p>Learn how to deploy applications <a href="/docs/applications/using-buildpacks/">using Buildpacks</a>.</p> +<h3 id="dockerfiles">Dockerfiles<a class="td-heading-self-link" href="#dockerfiles" aria-label="Heading self-link"></a></h3> +<p>Dockerfiles are a powerful way to define a portable execution environment built on a base OS of your choosing.</p> +<p>Learn how to deploy applications <a href="/docs/applications/using-dockerfiles/">using Dockerfiles</a>.</p> +<h3 id="container-image">Container Image<a class="td-heading-self-link" href="#container-image" aria-label="Heading self-link"></a></h3> +<p>Deploying a Container image onto Drycc allows you to take a Container image from either a public +or a private registry and copy it over bit-for-bit, ensuring that you are running the same +image in development or in your CI pipeline as you are in production.</p> +<p>Learn how to deploy applications <a href="/docs/applications/using-container-images/">using Container images</a>.</p> +<h2 id="tuning-application-settings">Tuning Application Settings<a class="td-heading-self-link" href="#tuning-application-settings" aria-label="Heading self-link"></a></h2> +<p>It is possible to configure a few of the <a href="/docs/applications/managing-app-configuration/">globally tunable</a> settings on per application basis using <code>config:set</code>.</p> +<table> +<thead> +<tr> +<th>Setting</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>DRYCC_DISABLE_CACHE</td> +<td>if set, this will disable the [imagebuilder cache][] (default: not set)</td> +</tr> +<tr> +<td>DRYCC_DEPLOY_BATCHES</td> +<td>the number of pods to bring up and take down sequentially during a scale (default: number of available nodes)</td> +</tr> +<tr> +<td>DRYCC_DEPLOY_TIMEOUT</td> +<td>deploy timeout in seconds per deploy batch (default: 120)</td> +</tr> +<tr> +<td>IMAGE_PULL_POLICY</td> +<td>the kubernetes [image pull policy][pull-policy] for application images (default: &ldquo;IfNotPresent&rdquo;) (allowed values: &ldquo;Always&rdquo;, &ldquo;IfNotPresent&rdquo;)</td> +</tr> +<tr> +<td>KUBERNETES_DEPLOYMENTS_REVISION_HISTORY_LIMIT</td> +<td>how many <a href="http://kubernetes.io/docs/user-guide/deployments/#revision-history-limit">revisions</a> Kubernetes keeps around of a given Deployment (default: all revisions)</td> +</tr> +<tr> +<td>KUBERNETES_POD_TERMINATION_GRACE_PERIOD_SECONDS</td> +<td>how many seconds kubernetes waits for a pod to finish work after a SIGTERM before sending SIGKILL (default: 30)</td> +</tr> +</tbody> +</table> +<h3 id="deploy-timeout">Deploy Timeout<a class="td-heading-self-link" href="#deploy-timeout" aria-label="Heading self-link"></a></h3> +<p>Deploy timeout in seconds - There are 2 deploy methods, Deployments (see below) and RC (versions prior to 2.4) and this setting affects those a bit differently.</p> +<h4 id="deployments">Deployments<a class="td-heading-self-link" href="#deployments" aria-label="Heading self-link"></a></h4> +<p>Deployments behave a little bit differently from the RC based deployment strategy.</p> +<p>Kubernetes takes care of the entire deploy, doing rolling updates in the background. As a result, there is only an overall deployment timeout instead of a configurable per-batch timeout.</p> +<p>The base timeout is multiplied with <code>DRYCC_DEPLOY_BATCHES</code> to create an overall timeout. This would be 240 (timeout) * 4 (batches) = 960 second overall timeout.</p> +<h4 id="rc-deploy">RC deploy<a class="td-heading-self-link" href="#rc-deploy" aria-label="Heading self-link"></a></h4> +<p>This deploy timeout defines how long to wait for each batch to complete in <code>DRYCC_DEPLOY_BATCHES</code>.</p> +<h4 id="additions-to-the-base-timeout">Additions to the base timeout<a class="td-heading-self-link" href="#additions-to-the-base-timeout" aria-label="Heading self-link"></a></h4> +<p>The base timeout is extended as well with healthchecks using <code>initialDelaySeconds</code> on <code>liveness</code> and <code>readiness</code> where the bigger of those two is applied. +Additionally the timeout system accounts for slow image pulls by adding an additional 10 minutes when it has seen an image pull take over 1 minute. This allows the timeout values to be reasonable without having to account for image pull slowness in the base deploy timeout.</p> +<h3 id="deployments-1">Deployments<a class="td-heading-self-link" href="#deployments-1" aria-label="Heading self-link"></a></h3> +<p>Workflow uses <a href="http://kubernetes.io/docs/user-guide/deployments/">Deployments</a> for deploys. In prior versions <a href="http://kubernetes.io/docs/user-guide/replication-controller/">ReplicationControllers</a> were used with the ability to turn on Deployments via <code>DRYCC_KUBERNETES_DEPLOYMENTS=1</code>.</p> +<p>The advantage of <a href="http://kubernetes.io/docs/user-guide/deployments/">Deployments</a> is that rolling-updates will happen server-side in Kubernetes instead of in Drycc Workflow Controller, +along with a few other Pod management related functionality. This allows a deploy to continue even when the CLI connection is interrupted.</p> +<p>Behind the scenes your application deploy will be built up of a Deployment object per process type, +each having multiple ReplicaSets (one per release) which in turn manage the Pods running your application.</p> +<p>Drycc Workflow will behave the same way with <code>DRYCC_KUBERNETES_DEPLOYMENTS</code> enabled or disabled (only applicable to versions prior to 2.4). +The changes are behind the scenes. Where you will see differences while using the CLI is <code>drycc ps:list</code> will output Pod names differently.</p> + + + + + + Docs: Using Buildpacks + /docs/applications/using-buildpacks/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/applications/using-buildpacks/ + + + + <p>Drycc supports deploying applications via <a href="https://buildpacks.io/">Cloud Native Buildpacks</a>. Cloud Native Buildpacks are useful if you want to follow <a href="https://buildpacks.io/docs/">cnb&rsquo;s docs</a> for building applications.</p> +<h2 id="add-ssh-key">Add SSH Key<a class="td-heading-self-link" href="#add-ssh-key" aria-label="Heading self-link"></a></h2> +<p>For <strong>Buildpack</strong> based application deploys via <code>git push</code>, Drycc Workflow identifies users via SSH keys. SSH keys are pushed to the platform and must be unique to each user.</p> +<ul> +<li> +<p>See <a href="/docs/users/ssh-keys/#generate-an-ssh-key">this document</a> for instructions on how to generate an SSH key.</p> +</li> +<li> +<p>Run <code>drycc keys:add</code> to upload your SSH key to Drycc Workflow.</p> +</li> +</ul> +<pre tabindex="0"><code>$ drycc keys:add ~/.ssh/id_drycc.pub +Uploading id_drycc.pub to drycc... done +</code></pre><p>Read more about adding/removing SSH Keys <a href="/docs/users/ssh-keys/#adding-and-removing-ssh-keys">here</a>.</p> +<h2 id="prepare-an-application">Prepare an Application<a class="td-heading-self-link" href="#prepare-an-application" aria-label="Heading self-link"></a></h2> +<p>If you do not have an existing application, you can clone an example application that demonstrates the Heroku Buildpack workflow.</p> +<pre><code>$ git clone https://github.com/drycc/example-go.git +$ cd example-go +</code></pre> +<h2 id="create-an-application">Create an Application<a class="td-heading-self-link" href="#create-an-application" aria-label="Heading self-link"></a></h2> +<p>Use <code>drycc create</code> to create an application on the <a href="/docs/understanding-workflow/components/#controller">Controller</a>.</p> +<pre><code>$ drycc create +Creating application... done, created skiing-keypunch +Git remote drycc added +</code></pre> +<h2 id="push-to-deploy">Push to Deploy<a class="td-heading-self-link" href="#push-to-deploy" aria-label="Heading self-link"></a></h2> +<p>Use <code>git push drycc master</code> to deploy your application.</p> +<pre><code>$ git push drycc master +Counting objects: 75, done. +Delta compression using up to 8 threads. +Compressing objects: 100% (48/48), done. +Writing objects: 100% (75/75), 18.28 KiB | 0 bytes/s, done. +Total 75 (delta 30), reused 58 (delta 22) +remote: ---&gt; +Starting build... but first, coffee! +---&gt; Waiting podman running. +---&gt; Process podman started. +---&gt; Waiting caddy running. +---&gt; Process caddy started. +---&gt; Building pack +---&gt; Using builder registry.drycc.cc/drycc/buildpacks:bookworm +Builder 'registry.drycc.cc/drycc/buildpacks:bookworm' is trusted +Pulling image 'registry.drycc.cc/drycc/buildpacks:bookworm' +Resolving &quot;drycc/buildpacks&quot; using unqualified-search registries (/etc/containers/registries.conf) +Trying to pull registry.drycc.cc/drycc/buildpacks:bookworm... +Getting image source signatures +... +---&gt; Skip generate base layer +---&gt; Python Buildpack +---&gt; Downloading and extracting Python 3.10.0 +---&gt; Installing requirements with pip +Collecting Django==3.2.8 +Downloading Django-3.2.8-py3-none-any.whl (7.9 MB) +Collecting gunicorn==20.1.0 +Downloading gunicorn-20.1.0-py3-none-any.whl (79 kB) +Collecting sqlparse&gt;=0.2.2 +Downloading sqlparse-0.4.2-py3-none-any.whl (42 kB) +Collecting pytz +Downloading pytz-2021.3-py2.py3-none-any.whl (503 kB) +Collecting asgiref&lt;4,&gt;=3.3.2 +Downloading asgiref-3.4.1-py3-none-any.whl (25 kB) +Requirement already satisfied: setuptools&gt;=3.0 in /layers/drycc_python/python/lib/python3.10/site-packages (from gunicorn==20.1.0-&gt;-r requirements.txt (line 2)) (57.5.0) +Installing collected packages: sqlparse, pytz, asgiref, gunicorn, Django +Successfully installed Django-3.2.8 asgiref-3.4.1 gunicorn-20.1.0 pytz-2021.3 sqlparse-0.4.2 +---&gt; Generate Launcher +... +Build complete. +Launching App... +... +Done, skiing-keypunch:v2 deployed to Workflow + +Use 'drycc open' to view this application in your browser + +To learn more, use 'drycc help' or visit https://www.drycc.cc + +To ssh://git@drycc.staging-2.drycc.cc:2222/skiing-keypunch.git + * [new branch] master -&gt; master + +$ curl -s http://skiing-keypunch.example.com +Powered by Drycc +Release v2 on skiing-keypunch-v2-web-02zb9 +</code></pre> +<p>Because a Buildpacks-style application is detected, the <code>web</code> process type is automatically scaled to 1 on first deploy.</p> +<p>Use <code>drycc scale web=3</code> to increase <code>web</code> processes to 3, for example. Scaling a +process type directly changes the number of <a href="http://kubernetes.io/v1.1/docs/user-guide/pods.html">pods</a> running that process.</p> +<h2 id="included-buildpacks">Included Buildpacks<a class="td-heading-self-link" href="#included-buildpacks" aria-label="Heading self-link"></a></h2> +<p>For convenience, a number of buildpacks come bundled with Drycc:</p> +<ul> +<li><a href="https://github.com/drycc/pack-images/tree/main/buildpacks/go">Go Buildpack</a></li> +<li><a href="https://github.com/drycc/pack-images/tree/main/buildpacks/java">Java Buildpack</a></li> +<li><a href="https://github.com/drycc/pack-images/tree/main/buildpacks/nodejs">Nodejs Buildpack</a></li> +<li><a href="https://github.com/drycc/pack-images/tree/main/buildpacks/php">PHP Buildpack</a></li> +<li><a href="https://github.com/drycc/pack-images/tree/main/buildpacks/python">Python Buildpack</a></li> +<li><a href="https://github.com/drycc/pack-images/tree/main/buildpacks/ruby">Ruby Buildpack</a></li> +<li><a href="https://github.com/drycc/pack-images/tree/main/buildpacks/rust">Rust Buildpack</a></li> +</ul> +<p>Drycc will cycle through the <code>bin/detect</code> script of each buildpack to match the code you +are pushing.</p> +<p>!!! note +If you&rsquo;re testing against the [Scala Buildpack][], the <a href="/docs/understanding-workflow/components/#builder">Builder</a> requires at least +512MB of free memory to execute the Scala Build Tool.</p> +<h2 id="using-a-custom-buildpack">Using a Custom Buildpack<a class="td-heading-self-link" href="#using-a-custom-buildpack" aria-label="Heading self-link"></a></h2> +<p>To use a custom buildpack, you need create a <code>.pack_builder</code> file in your root path app.</p> +<pre><code>$ tee &gt; .pack_builder &lt;&lt; EOF + &gt; registry.drycc.cc/drycc/buildpacks:bookworm + &gt; EOF +</code></pre> +<p>On your next <code>git push</code>, the custom buildpack will be used.</p> +<h2 id="using-private-repositories">Using Private Repositories<a class="td-heading-self-link" href="#using-private-repositories" aria-label="Heading self-link"></a></h2> +<p>To pull code from private repositories, set the <code>SSH_KEY</code> environment variable to a private key +which has access. Use either the path of a private key file or the raw key material:</p> +<pre><code>$ drycc config:set SSH_KEY=/home/user/.ssh/id_rsa +$ drycc config:set SSH_KEY=&quot;&quot;&quot;-----BEGIN RSA PRIVATE KEY----- +(...) +-----END RSA PRIVATE KEY-----&quot;&quot;&quot; +</code></pre> +<p>For example, to use a custom buildpack hosted at a private GitHub URL, ensure that an SSH public +key exists in your <a href="https://github.com/settings/ssh">GitHub settings</a>. Then set <code>SSH_KEY</code> to the corresponding SSH private key +and set <code>.pack_builder</code> to the builder image:</p> +<pre><code>$ tee &gt; .pack_builder &lt;&lt; EOF + &gt; registry.drycc.cc/drycc/buildpacks:bookworm + &gt; EOF +$ git add .buildpack +$ git commit -m &quot;chore(buildpack): modify the pack_builder&quot; +$ git push drycc master +</code></pre> +<h2 id="builder-selector">Builder selector<a class="td-heading-self-link" href="#builder-selector" aria-label="Heading self-link"></a></h2> +<p>Which way to build a project conforms to the following principles:</p> +<ul> +<li>If Dockerfile exists in the project, the stack uses <code>container</code></li> +<li>If Procfile exists in the project, the stack uses <code>buildpack</code></li> +<li>If both exist, <code>container</code> is used by default</li> +<li>You can also set the <code>DRYCC_STACK</code> to <code>container</code> or <code>buildpack</code> determine which stack to use.</li> +</ul> + + + + + + Docs: Using Dockerfiles + /docs/applications/using-dockerfiles/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/applications/using-dockerfiles/ + + + + <p>Drycc supports deploying applications via Dockerfiles. A <a href="https://docs.docker.com/reference/builder/">Dockerfile</a> automates the steps for crafting a [Container Image][]. +Dockerfiles are incredibly powerful but require some extra work to define your exact application runtime environment.</p> +<h2 id="add-ssh-key">Add SSH Key<a class="td-heading-self-link" href="#add-ssh-key" aria-label="Heading self-link"></a></h2> +<p>For <strong>Dockerfile</strong> based application deploys via <code>git push</code>, Drycc Workflow identifies users via SSH keys. SSH keys are pushed to the platform and must be unique to each user.</p> +<ul> +<li> +<p>See <a href="/docs/users/ssh-keys/#generate-an-ssh-key">this document</a> for instructions on how to generate an SSH key.</p> +</li> +<li> +<p>Run <code>drycc keys:add</code> to upload your SSH key to Drycc Workflow.</p> +</li> +</ul> +<pre tabindex="0"><code>$ drycc keys:add ~/.ssh/id_drycc.pub +Uploading id_drycc.pub to drycc... done +</code></pre><p>Read more about adding/removing SSH Keys <a href="/docs/users/ssh-keys/#adding-and-removing-ssh-keys">here</a>.</p> +<h2 id="prepare-an-application">Prepare an Application<a class="td-heading-self-link" href="#prepare-an-application" aria-label="Heading self-link"></a></h2> +<p>If you do not have an existing application, you can clone an example application that demonstrates the Dockerfile workflow.</p> +<pre><code>$ git clone https://github.com/drycc/helloworld.git +$ cd helloworld +</code></pre> +<h3 id="dockerfile-requirements">Dockerfile Requirements<a class="td-heading-self-link" href="#dockerfile-requirements" aria-label="Heading self-link"></a></h3> +<p>In order to deploy Dockerfile applications, they must conform to the following requirements:</p> +<ul> +<li>The Dockerfile must use the <code>EXPOSE</code> directive to expose exactly one port.</li> +<li>That port must be listening for an HTTP connection.</li> +<li>The Dockerfile must use the <code>CMD</code> directive to define the default process that will run within the container.</li> +<li>The Container image must contain <a href="https://www.gnu.org/software/bash/">bash</a> to run processes.</li> +</ul> +<p>!!! note +Note that if you are using a private registry of any kind (<code>gcr</code> or other) the application environment must include a <code>$PORT</code> config variable that matches the <code>EXPOSE</code>&rsquo;d port, example: <code>drycc config:set PORT=5000</code>. See <a href="/docs/installing-workflow/configuring-registry/#configuring-off-cluster-private-registry">Configuring Registry</a> for more info.</p> +<h2 id="create-an-application">Create an Application<a class="td-heading-self-link" href="#create-an-application" aria-label="Heading self-link"></a></h2> +<p>Use <code>drycc create</code> to create an application on the <a href="/docs/understanding-workflow/components/#controller">Controller</a>.</p> +<pre><code>$ drycc create +Creating application... done, created folksy-offshoot +Git remote drycc added +</code></pre> +<h2 id="push-to-deploy">Push to Deploy<a class="td-heading-self-link" href="#push-to-deploy" aria-label="Heading self-link"></a></h2> +<p>Use <code>git push drycc master</code> to deploy your application.</p> +<pre><code>$ git push drycc master +Counting objects: 13, done. +Delta compression using up to 8 threads. +Compressing objects: 100% (13/13), done. +Writing objects: 100% (13/13), 1.99 KiB | 0 bytes/s, done. +Total 13 (delta 2), reused 0 (delta 0) +-----&gt; Building Docker image +Uploading context 4.096 kB +Uploading context +Step 0 : FROM drycc/base:latest + ---&gt; 60024338bc63 +Step 1 : RUN wget -O /tmp/go1.2.1.linux-amd64.tar.gz -q https://go.googlecode.com/files/go1.2.1.linux-amd64.tar.gz + ---&gt; Using cache + ---&gt; cf9ef8c5caa7 +Step 2 : RUN tar -C /usr/local -xzf /tmp/go1.2.1.linux-amd64.tar.gz + ---&gt; Using cache + ---&gt; 515b1faf3bd8 +Step 3 : RUN mkdir -p /go + ---&gt; Using cache + ---&gt; ebf4927a00e9 +Step 4 : ENV GOPATH /go + ---&gt; Using cache + ---&gt; c6a276eded37 +Step 5 : ENV PATH /usr/local/go/bin:/go/bin:$PATH + ---&gt; Using cache + ---&gt; 2ba6f6c9f108 +Step 6 : ADD . /go/src/github.com/drycc/helloworld + ---&gt; 94ab7f4b977b +Removing intermediate container 171b7d9fdb34 +Step 7 : RUN cd /go/src/github.com/drycc/helloworld &amp;&amp; go install -v . + ---&gt; Running in 0c8fbb2d2812 +github.com/drycc/helloworld + ---&gt; 13b5af931393 +Removing intermediate container 0c8fbb2d2812 +Step 8 : ENV PORT 80 + ---&gt; Running in 9b07da36a272 + ---&gt; 2dce83167874 +Removing intermediate container 9b07da36a272 +Step 9 : CMD [&quot;/go/bin/helloworld&quot;] + ---&gt; Running in f7b215199940 + ---&gt; b1e55ce5195a +Removing intermediate container f7b215199940 +Step 10 : EXPOSE 80 + ---&gt; Running in 7eb8ec45dcb0 + ---&gt; ea1a8cc93ca3 +Removing intermediate container 7eb8ec45dcb0 +Successfully built ea1a8cc93ca3 +-----&gt; Pushing image to private registry + + Launching... done, v2 + +-----&gt; folksy-offshoot deployed to Drycc + http://folksy-offshoot.local3.dryccapp.com + + To learn more, use `drycc help` or visit https://www.drycc.cc + +To ssh://git@local3.dryccapp.com:2222/folksy-offshoot.git + * [new branch] master -&gt; master + +$ curl -s http://folksy-offshoot.local3.dryccapp.com +Welcome to Drycc! +See the documentation at http://docs.drycc.cc/ for more information. +</code></pre> +<p>Because a Dockerfile application is detected, the <code>web</code> process type is automatically scaled to 1 on first deploy.</p> +<p>Use <code>drycc scale web=3</code> to increase <code>web</code> processes to 3, for example. Scaling a +process type directly changes the number of <a href="../reference-guide/terms.md#container">containers</a> +running that process.</p> +<h2 id="container-build-arguments">Container Build Arguments<a class="td-heading-self-link" href="#container-build-arguments" aria-label="Heading self-link"></a></h2> +<p>As of Workflow v2.13.0, users can inject their application config into the Container image using +<a href="https://docs.docker.com/engine/reference/commandline/build/#set-build-time-variables---build-arg">Container build arguments</a>. To opt into this, users must add a new environment variable +to their application:</p> +<pre tabindex="0"><code>$ drycc config:set DRYCC_DOCKER_BUILD_ARGS_ENABLED=1 +</code></pre><p>Every environment variable set with <code>drycc config:set</code> will then be available for use inside the +user&rsquo;s Dockerfile. For example, if a user runs <code>drycc config:set POWERED_BY=Workflow</code>, +the user can utilize that build argument in their Dockerfile:</p> +<pre tabindex="0"><code>ARG POWERED_BY +RUN echo &#34;Powered by $POWERED_BY&#34; &gt; /etc/motd +</code></pre> + + + + + Docs: Using Docker Images + /docs/applications/using-container-images/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/applications/using-container-images/ + + + + <p>Drycc supports deploying applications via an existing <a href="https://docs.docker.com/introduction/understanding-docker/">Docker Image</a>. +This is useful for integrating Drycc into Docker-based CI/CD pipelines.</p> +<h2 id="prepare-an-application">Prepare an Application<a class="td-heading-self-link" href="#prepare-an-application" aria-label="Heading self-link"></a></h2> +<p>Start by cloning an example application:</p> +<pre><code>$ git clone https://github.com/drycc/example-dockerfile-http.git +$ cd example-dockerfile-http +</code></pre> +<p>Next use your local <code>docker</code> client to build the image and push +it to <a href="https://registry.hub.docker.com/">DockerHub</a>.</p> +<pre><code>$ docker build -t &lt;username&gt;/example-dockerfile-http . +$ docker push &lt;username&gt;/example-dockerfile-http +</code></pre> +<h3 id="docker-image-requirements">Docker Image Requirements<a class="td-heading-self-link" href="#docker-image-requirements" aria-label="Heading self-link"></a></h3> +<p>In order to deploy Docker images, they must conform to the following requirements:</p> +<ul> +<li>The Dockerfile must use the <code>EXPOSE</code> directive to expose exactly one port.</li> +<li>That port must be listening for an HTTP connection.</li> +<li>The Dockerfile must use the <code>CMD</code> directive to define the default process that will run within the container.</li> +<li>The Docker image must contain <a href="https://www.gnu.org/software/bash/">bash</a> to run processes.</li> +</ul> +<p>!!! note +Note that if you are using a private registry of any kind (<code>gcr</code> or other) the application environment must include a <code>$PORT</code> config variable that matches the <code>EXPOSE</code>&rsquo;d port, example: <code>drycc config:set PORT=5000</code>. See <a href="/docs/installing-workflow/configuring-registry/#configuring-off-cluster-private-registry">Configuring Registry</a> for more info.</p> +<h2 id="create-an-application">Create an Application<a class="td-heading-self-link" href="#create-an-application" aria-label="Heading self-link"></a></h2> +<p>Use <code>drycc create</code> to create an application on the <a href="/docs/understanding-workflow/components/#controller">controller</a>.</p> +<pre><code>$ mkdir -p /tmp/example-dockerfile-http &amp;&amp; cd /tmp/example-dockerfile-http +$ drycc create example-dockerfile-http --no-remote +Creating application... done, created example-dockerfile-http +</code></pre> +<p>!!! note +For all commands except for <code>drycc create</code>, the <code>drycc</code> client uses the name of the current directory +as the app name if you don&rsquo;t specify it explicitly with <code>--app</code>.</p> +<h2 id="deploy-the-application">Deploy the Application<a class="td-heading-self-link" href="#deploy-the-application" aria-label="Heading self-link"></a></h2> +<p>Use <code>drycc pull</code> to deploy your application from <a href="https://registry.hub.docker.com/">DockerHub</a> or +a public registry.</p> +<pre><code>$ drycc pull &lt;username&gt;/example-dockerfile-http:latest +Creating build... done, v2 + +$ curl -s http://example-dockerfile-http.local3.dryccapp.com +Powered by Drycc +</code></pre> +<p>Because you are deploying a Docker image, the <code>web</code> process type is automatically scaled to 1 on first deploy.</p> +<p>Use <code>drycc scale web=3</code> to increase <code>web</code> processes to 3, for example. Scaling a +process type directly changes the number of <a href="../reference-guide/terms.md#container">Containers</a> +running that process.</p> +<h2 id="private-registry">Private Registry<a class="td-heading-self-link" href="#private-registry" aria-label="Heading self-link"></a></h2> +<p>To deploy Docker images from a private registry or from a private repository, use <code>drycc registry</code> +to attach credentials to your application. These credentials are the same as you&rsquo;d use when running +<code>docker login</code> at your private registry.</p> +<p>To deploy private Docker images, take the following steps:</p> +<ul> +<li>Gather the username and password for the registry, such as a <a href="https://docs.quay.io/glossary/robot-accounts.html">Quay.io Robot Account</a> or a <a href="https://cloud.google.com/container-registry/docs/auth#using_a_json_key_file">GCR.io Long Lived Token</a></li> +<li>Run <code>drycc registry:set username=&lt;the-user&gt; password=&lt;secret&gt; -a &lt;application-name&gt;</code></li> +<li>Now perform <code>drycc pull</code> as normal, against an image in the private registry</li> +</ul> +<p>When using a <a href="https://cloud.google.com/container-registry/docs/auth#using_a_json_key_file">GCR.io Long Lived Token</a>, the JSON blob will have to be compacted first using a +tool like <a href="https://stedolan.github.io/jq/">jq</a> and then used in the password field in <code>drycc registry:set</code>. For the username, use +<code>_json_key</code>. For example:</p> +<pre tabindex="0"><code>drycc registry:set username=_json_key password=&#34;$(cat google_cloud_cred.json | jq -c .)&#34; +</code></pre><p>When using a private registry the docker images are no longer pulled into the Drycc Internal Registry via +the Drycc Workflow Controller but rather is managed by Kubernetes. This will increase security and overall speed, +however the application <code>port</code> information can no longer be discovered. Instead the application <code>port</code> information can be set via +<code>drycc config:set PORT=80</code> prior to setting the registry information.</p> +<p>!!! note +Currently <a href="https://gcr.io">GCR.io</a> and <a href="https://aws.amazon.com/ecr/">ECR</a> in short lived auth token mode are not supported.</p> + + + + + + Docs: Managing Application Processes + /docs/applications/managing-app-processes/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/applications/managing-app-processes/ + + + + <p>Drycc Workflow manages your application as a set of processes that can be named, scaled and configured according to their +role. This gives you the flexibility to easily manage the different facets of your application. For example, you may have +web-facing processes that handle HTTP traffic, background worker processes that do async work, and a helper process that +streams from the Twitter API.</p> +<p>By using a Procfile, either checked in to your application or provided via the CLI you can specify the name of the type +and the application command that should run. To spawn other process types, use <code>drycc scale &lt;ptype&gt;=&lt;n&gt;</code> to scale those +types accordingly.</p> +<h2 id="default-process-types">Default Process Types<a class="td-heading-self-link" href="#default-process-types" aria-label="Heading self-link"></a></h2> +<p>In the absence of a Procfile, a single, default process type is assumed for each application.</p> +<p>Applications built using <a href="/docs/applications/using-buildpacks/">Buildpacks</a> via <code>git push</code> implicitly receive a <code>web</code> process type, which starts +the application server. Rails 4, for example, has the following process type:</p> +<pre><code>web: bundle exec rails server -p $PORT +</code></pre> +<p>All applications utilizing <a href="/docs/applications/using-dockerfiles/">Dockerfiles</a> have an implied <code>web</code> process type, which runs the +Dockerfile&rsquo;s <code>CMD</code> directive unmodified:</p> +<pre><code>$ cat Dockerfile +FROM centos:latest +COPY . /app +WORKDIR /app +CMD python -m SimpleHTTPServer 5000 +EXPOSE 5000 +</code></pre> +<p>For the above Dockerfile-based application, the <code>web</code> process type would run the Container <code>CMD</code> of <code>python -m SimpleHTTPServer 5000</code>.</p> +<p>Applications utilizing <a href="/docs/applications/using-container-images/">remote Container images</a>, a <code>web</code> process type is also implied, and runs the <code>CMD</code> +specified in the Container image.</p> +<p>!!! note +The <code>web</code> process type is special as they’is the default process type that will +receive HTTP traffic from Workflow’s routers. Other process types can be named arbitrarily.</p> +<h2 id="declaring-process-types">Declaring Process Types<a class="td-heading-self-link" href="#declaring-process-types" aria-label="Heading self-link"></a></h2> +<p>If you use <a href="/docs/applications/using-buildpacks/">Buildpack</a> or <a href="/docs/applications/using-dockerfiles/">Dockerfile</a> builds and want to override or specify additional process +types, simply include a file named <code>Procfile</code> in the root of your application&rsquo;s source tree.</p> +<p>The format of a <code>Procfile</code> is one process type per line, with each line containing the command to invoke:</p> +<pre><code>&lt;process type&gt;: &lt;command&gt; +</code></pre> +<p>The syntax is defined as:</p> +<ul> +<li><code>&lt;process type&gt;</code> – a lowercase alphanumeric string, is a name for your command, such as web, worker, urgentworker, clock, etc.</li> +<li><code>&lt;command&gt;</code> – a command line to launch the process, such as <code>rake jobs:work</code>.</li> +</ul> +<p>This example Procfile specifies two types, <code>web</code> and <code>sleeper</code>. The <code>web</code> process launches a web server on port 5000 and +a simple process which sleeps for 900 seconds and exits.</p> +<pre tabindex="0"><code>$ cat Procfile +web: bundle exec ruby web.rb -p ${PORT:-5000} +sleeper: sleep 900 +</code></pre><p>If you are using <a href="/docs/applications/using-container-images/">remote Container images</a>, you may define process types by either running <code>drycc pull</code> with a +<code>Procfile</code> in your working directory, or by passing a stringified Procfile to the <code>--procfile</code> CLI option.</p> +<p>For example, passing process types inline:</p> +<pre tabindex="0"><code>$ drycc pull drycc/example-go:latest --procfile=&#34;web: /app/bin/boot&#34; +</code></pre><p>Read a <code>Procfile</code> in another directory:</p> +<pre tabindex="0"><code>$ drycc pull drycc/example-go:latest --procfile=&#34;$(cat deploy/Procfile)&#34; +</code></pre><p>Or via a Procfile located in your current, working directory:</p> +<pre tabindex="0"><code>$ cat Procfile +web: /bin/boot +sleeper: echo &#34;sleeping&#34;; sleep 900 + + +$ drycc pull -a steely-mainsail drycc/example-go +Creating build... done + +$ drycc scale sleeper=1 -a steely-mainsail +Scaling processes... but first, coffee! +done in 0s + +NAME RELEASE STATE PTYPE READY RESTARTS STARTED +steely-mainsail-sleeper-76c45b967c-4qm6w v3 up sleeper 1/1 0 2023-12-08T02:25:00UTC +steely-mainsail-web-c4f44c4b4-7p7dh v3 up web 1/1 0 2023-12-08T02:25:00UTC +</code></pre><p>!!! note +Only process types of <code>web</code> will be scaled to 1 automatically. If you have additional process types +remember to scale the process counts after creation.</p> +<p>To remove a process type simply scale it to 0:</p> +<pre tabindex="0"><code>$ drycc scale sleeper=0 -a steely-mainsail +Scaling processes... but first, coffee! +done in 3s + +NAME RELEASE STATE PTYPE READY RESTARTS STARTED +steely-mainsail-web-c4f44c4b4-7p7dh v3 up web 1/1 0 2023-12-08T02:25:00UTC +</code></pre><h2 id="scaling-processes">Scaling Processes<a class="td-heading-self-link" href="#scaling-processes" aria-label="Heading self-link"></a></h2> +<p>Applications deployed on Drycc Workflow scale out via the <a href="https://devcenter.heroku.com/articles/process-model">process model</a>. Use <code>drycc scale</code> to control the number of +<a href="../reference-guide/terms.md#container">containers</a> that power your app.</p> +<pre tabindex="0"><code>$ drycc scale web=5 -a iciest-waggoner +Scaling processes... but first, coffee! +done in 3s + +NAME RELEASE STATE PTYPE READY RESTARTS STARTED +iciest-waggoner-web-c4f44c4b4-7p7dh v3 up web 1/1 0 2023-12-08T02:25:00UTC +iciest-waggoner-web-c4f44c4b4-8p7dh v3 up web 1/1 0 2023-12-08T02:25:00UTC +iciest-waggoner-web-c4f44c4b4-9p7dh v3 up web 1/1 0 2023-12-08T02:25:00UTC +iciest-waggoner-web-c4f44c4b4-1p7dh v3 up web 1/1 0 2023-12-08T02:25:00UTC +iciest-waggoner-web-c4f44c4b4-2p7dh v3 up web 1/1 0 2023-12-08T02:25:00UTC +</code></pre><p>If you have multiple process types for your application you may scale the process count for each type separately. For +example, this allows you to manage web process independently from background workers. For more information on process +types see our documentation for <a href="/docs/applications/managing-app-processes/">Managing App Processes</a>.</p> +<p>In this example, we are scaling the process type <code>web</code> to 5 but leaving the process type <code>background</code> with one worker.</p> +<pre tabindex="0"><code>$ drycc scale web=5 +Scaling processes... but first, coffee! +done in 4s + +NAME RELEASE STATE PTYPE READY RESTARTS STARTED +scenic-icehouse-web-3291896318-7lord v3 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-web-3291896318-jn957 v3 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-web-3291896318-rsekj v3 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-web-3291896318-vwhnh v3 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-web-3291896318-vokg7 v3 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-web-3291896318-vokg7 v3 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-background-3291896318-yf8kh v3 up web 1/1 0 2023-12-08T02:25:00UTC +</code></pre><p>Scaling a process down, by reducing the process count, sends a <code>TERM</code> signal to the processes, followed by a <code>SIGKILL</code> +if they have not exited within 30 seconds. Depending on your application, scaling down may interrupt long-running HTTP +client connections.</p> +<p>For example, scaling from 5 processes to 3:</p> +<pre tabindex="0"><code>$ drycc scale web=3 +Scaling processes... but first, coffee! +done in 1s + +NAME RELEASE STATE PTYPE READY RESTARTS STARTED +scenic-icehouse-web-3291896318-vwhnh v2 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-web-3291896318-vokg7 v2 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-web-3291896318-vokg9 v2 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-background-3291896318-yf8kh v2 up web 1/1 0 2023-12-08T02:25:00UTC +</code></pre><h2 id="autoscale">Autoscale<a class="td-heading-self-link" href="#autoscale" aria-label="Heading self-link"></a></h2> +<p>Autoscale allows adding a minimum and maximum number of pods on a per process type basis. This is accomplished by specifying a target CPU usage across all available pods.</p> +<p>This feature is built on top of <a href="https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/">Horizontal Pod Autoscaling</a> in Kubernetes or <a href="https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/">HPA</a> for short.</p> +<p>!!! note +This is an alpha feature. It is recommended to be on the latest Kubernetes when using this feature.</p> +<pre tabindex="0"><code>$ drycc autoscale:set web --min=3 --max=8 --cpu-percent=75 +Applying autoscale settings for process type web on scenic-icehouse... done +</code></pre><p>And then review the scaling rule that was created for <code>web</code></p> +<pre tabindex="0"><code>$ drycc autoscale:list +PTYPE PERCENT MIN MAX +web 75 3 8 +</code></pre><p>Remove scaling rule</p> +<pre tabindex="0"><code>$ drycc autoscale:unset web +Removing autoscale for process type web on scenic-icehouse... done +</code></pre><p>For autoscaling to work CPU requests have to be specified on each application Pod (can be done via <code>drycc limits --cpu</code>). This allows the autoscale policies to do the <a href="https://github.com/kubernetes/community/blob/master/contributors/design-proposals/horizontal-pod-autoscaler.md#autoscaling-algorithm">appropriate calculations</a> and make decisions on when to scale up and down.</p> +<p>Scale up can only happen if there was no rescaling within the last 3 minutes. Scale down will wait for 5 minutes from the last rescaling. That information and more can be found at <a href="https://github.com/kubernetes/community/blob/master/contributors/design-proposals/horizontal-pod-autoscaler.md#autoscaling-algorithm">HPA algorithm page</a>.</p> +<h2 id="fetch-a-container-logs-of-the-application">Fetch a container logs of the application<a class="td-heading-self-link" href="#fetch-a-container-logs-of-the-application" aria-label="Heading self-link"></a></h2> +<p>List the containers:</p> +<pre tabindex="0"><code>$ drycc ps +NAME RELEASE STATE PTYPEE READY RESTARTS STARTED +python-getting-started-web-69b7d4bfdc-kl4xf v2 up web 1/1 0 2023-12-08T02:25:00UTC + +=== python-getting-started Processes +--- web: +python-getting-started-web-69b7d4bfdc-kl4xf up (v2) +</code></pre><p>fetch the container logs:</p> +<pre tabindex="0"><code>$ drycc ps:logs -f python-getting-started-web-69b7d4bfdc-kl4xf +[2024-05-24 07:14:39 +0000] [1] [INFO] Starting gunicorn 20.1.0 +[2024-05-24 07:14:39 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1) +[2024-05-24 07:14:39 +0000] [1] [INFO] Using worker: gevent +[2024-05-24 07:14:39 +0000] [8] [INFO] Booting worker with pid: 8 +[2024-05-24 07:14:39 +0000] [9] [INFO] Booting worker with pid: 9 +[2024-05-24 07:14:39 +0000] [10] [INFO] Booting worker with pid: 10 +[2024-05-24 07:14:39 +0000] [11] [INFO] Booting worker with pid: 11 +</code></pre><h2 id="get-a-container-info-of-the-application">Get a container info of the application<a class="td-heading-self-link" href="#get-a-container-info-of-the-application" aria-label="Heading self-link"></a></h2> +<p>List the containers:</p> +<pre tabindex="0"><code>$ drycc ps:describe python-getting-started-web-69b7d4bfdc-kl4xf +Container: python-getting-started-web +Image: drycc/python-getting-started:latest +Command: +Args: + - gunicorn + - -c + - gunicorn_config.py + - helloworld.wsgi:application +State: running + startedAt: &#34;2024-05-24T07:14:39Z&#34; +Ready: true +Restart Count: 0 +</code></pre><h2 id="delete-a-container-of-the-application">delete a container of the application<a class="td-heading-self-link" href="#delete-a-container-of-the-application" aria-label="Heading self-link"></a></h2> +<p>Delete the containers. +Due to the set number of replicas, a new container will be launched to meet the quantity requirement.</p> +<pre tabindex="0"><code>$ drycc ps:delete python-getting-started-web-69b7d4bfdc-kl4xf +Deleting python-getting-started-web-69b7d4bfdc-kl4xf from python-getting-started... done +</code></pre><h2 id="get-a-shell-to-a-running-container">Get a Shell to a Running Container<a class="td-heading-self-link" href="#get-a-shell-to-a-running-container" aria-label="Heading self-link"></a></h2> +<p>Verify that the container is running:</p> +<pre tabindex="0"><code>$ drycc ps +NAME RELEASE STATE PTYPEE READY RESTARTS STARTED +python-getting-started-web-69b7d4bfdc-kl4xf v2 up web 1/1 0 2023-12-08T02:25:00UTC + +=== python-getting-started Processes +--- web: +python-getting-started-web-69b7d4bfdc-kl4xf up (v2) +</code></pre><p>Get a shell to the running container:</p> +<pre tabindex="0"><code>$ drycc ps:exec python-getting-started-web-69b7d4bfdc-kl4xf -it -- bash +</code></pre><p>In your shell, list the root directory:</p> +<pre tabindex="0"><code># Run this inside the container +ls / +</code></pre><p>Running individual commands in a container</p> +<pre tabindex="0"><code>$ drycc ps:exec python-getting-started-web-69b7d4bfdc-kl4xf -- date +</code></pre><p>Use &ldquo;drycc ps &ndash;help&rdquo; for a list of global command-line (applies to all commands).</p> +<h2 id="restarting-an-application-processes">Restarting an Application Processes<a class="td-heading-self-link" href="#restarting-an-application-processes" aria-label="Heading self-link"></a></h2> +<p>If you need to restart an application process, you may use <code>drycc pts:restart</code>. Behind the scenes, Drycc Workflow instructs +Kubernetes to terminate the old process and launch a new one in its place.</p> +<pre tabindex="0"><code>$ drycc ps +NAME RELEASE STATE PTYPE READY RESTARTS STARTED +scenic-icehouse-web-3291896318-vokg7 v2 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-web-3291896318-rsekj v2 up web 1/1 0 2023-12-08T02:50:21UTC +scenic-icehouse-web-3291896318-vokg7 v2 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-background-3291896318-yf8kh v2 up web 1/1 0 2023-12-08T02:25:00UTC + +$ drycc pts:restart scenic-icehouse-background +NAME RELEASE STATE PTYPE READY RESTARTS STARTED +scenic-icehouse-web-3291896318-vokg7 v2 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-web-3291896318-rsekj v2 up web 1/1 0 2023-12-08T02:50:21UTC +scenic-icehouse-web-3291896318-vokg7 v2 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-background-3291896318-yf8kh v2 starting web 1/1 0 2023-12-08T02:25:00UTC +</code></pre><p>Notice that the process name has changed from <code>scenic-icehouse-background-3291896318-yf8kh</code> to +<code>scenic-icehouse-background-3291896318-yd87g</code>. In a multi-node Kubernetes cluster, this may also have the effect of scheduling +the Pod to a new node.</p> +<p>Use &ldquo;drycc pts &ndash;help&rdquo; for a list of pts command-line (process types info).</p> +<h2 id="list-an-application-process-types">List an Application Process Types<a class="td-heading-self-link" href="#list-an-application-process-types" aria-label="Heading self-link"></a></h2> +<pre tabindex="0"><code>$ drycc pts +NAME RELEASE READY UP-TO-DATE AVAILABLE STARTED +web v2 3/3 1 1 2023-12-08T02:25:00UTC +background v2 1/1 1 1 2023-12-08T02:25:00UTC +</code></pre><h2 id="get-deployment-info-of-the-application-process-type">Get deployment info of the application process type<a class="td-heading-self-link" href="#get-deployment-info-of-the-application-process-type" aria-label="Heading self-link"></a></h2> +<pre tabindex="0"><code>$ drycc pts:describe web +Container: python-getting-started-web +Image: drycc/python-getting-started:latest +Command: +Args: + - gunicorn + - -c + - gunicorn_config.py + - helloworld.wsgi:application +Limits: + cpu 1 + ephemeral-storage 2Gi + memory 1Gi +Liveness: http-get headers=[] path=/geo/ port=8000 delay=120s timeout=10s period=20s #success=1 #failure=3 +Readiness: http-get headers=[] path=/geo/ port=8000 delay=120s timeout=10s period=20s #success=1 #failure=3 +</code></pre> + + + + + Docs: Configuring an Application + /docs/applications/managing-app-configuration/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/applications/managing-app-configuration/ + + + + <h1 id="configuring-an-application">Configuring an Application<a class="td-heading-self-link" href="#configuring-an-application" aria-label="Heading self-link"></a></h1> +<p>A Drycc application <a href="http://12factor.net/config">stores config in environment variables</a>.</p> +<h2 id="setting-environment-variables">Setting Environment Variables<a class="td-heading-self-link" href="#setting-environment-variables" aria-label="Heading self-link"></a></h2> +<p>Use <code>drycc config</code> to modify environment variables for a deployed application.</p> +<pre><code>$ drycc help config +Valid commands for config: + +config:list list environment variables for an app +config:set set environment variables for an app +config:unset unset environment variables for an app +config:pull extract environment variables to .env +config:push set environment variables from .env + +Use `drycc help [command]` to learn more. +</code></pre> +<p>When config is changed, a new release is created and deployed automatically.</p> +<p>You can set multiple environment variables with one <code>drycc config:set</code> command, +or with <code>drycc config:push</code> and a local .env file.</p> +<pre><code>$ drycc config:set FOO=1 BAR=baz &amp;&amp; drycc config:pull +$ cat .env +FOO=1 +BAR=baz +$ echo &quot;TIDE=high&quot; &gt;&gt; .env +$ drycc config:push +Creating config... done, v4 + +=== yuppie-earthman +DRYCC_APP: yuppie-earthman +FOO: 1 +BAR: baz +TIDE: high +</code></pre> +<p>It can also modify environment variables for a process type of application.</p> +<pre><code>$ drycc config:set FOO=1 BAR=baz --ptype=web +</code></pre> +<h2 id="attach-to-backing-services">Attach to Backing Services<a class="td-heading-self-link" href="#attach-to-backing-services" aria-label="Heading self-link"></a></h2> +<p>Drycc treats backing services like databases, caches and queues as <a href="http://12factor.net/backing-services">attached resources</a>. +Attachments are performed using environment variables.</p> +<p>For example, use <code>drycc config</code> to set a <code>DATABASE_URL</code> that attaches +the application to an external PostgreSQL database.</p> +<pre><code>$ drycc config:set DATABASE_URL=postgres://user:pass@example.com:5432/db +=== peachy-waxworks +DATABASE_URL: postgres://user:pass@example.com:5432/db +</code></pre> +<p>Detachments can be performed with <code>drycc config:unset</code>.</p> +<h2 id="buildpacks-cache">Buildpacks Cache<a class="td-heading-self-link" href="#buildpacks-cache" aria-label="Heading self-link"></a></h2> +<p>By default, apps using the [Imagebuilder][] will reuse the latest image data. +When deploying applications that depend on third-party libraries that have to be fetched, +this could speed up deployments a lot. In order to make use of this, the buildpack must implement +the cache by writing to the cache directory. Most buildpacks already implement this, but when using +custom buildpacks, it might need to be changed to make full use of the cache.</p> +<h3 id="disabling-and-re-enabling-the-cache">Disabling and re-enabling the cache<a class="td-heading-self-link" href="#disabling-and-re-enabling-the-cache" aria-label="Heading self-link"></a></h3> +<p>In some cases, cache might not speed up your application. To disable caching, you can set the +<code>DRYCC_DISABLE_CACHE</code> variable with <code>drycc config:set DRYCC_DISABLE_CACHE=1</code>. When you disable the +cache, Drycc will clear up files it created to store the cache. After having it turned off, run +<code>drycc config:unset DRYCC_DISABLE_CACHE</code> to re-enable the cache.</p> +<h3 id="clearing-the-cache">Clearing the cache<a class="td-heading-self-link" href="#clearing-the-cache" aria-label="Heading self-link"></a></h3> +<p>Use the following procedure to clear the cache:</p> +<pre><code>$ drycc config:set DRYCC_DISABLE_CACHE=1 +$ git commit --allow-empty -m &quot;Clearing Drycc cache&quot; +$ git push drycc # (if you use a different remote, you should use your remote name) +$ drycc config:unset DRYCC_DISABLE_CACHE +</code></pre> +<h2 id="custom-health-checks">Custom Health Checks<a class="td-heading-self-link" href="#custom-health-checks" aria-label="Heading self-link"></a></h2> +<p>By default, Workflow only checks that the application starts in their Container. If it is preferred +to have Kubernetes respond to application health, a health check may be added by configuring a +health check probe for the application.</p> +<p>The health checks are implemented as <a href="https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes">Kubernetes container probes</a>. A <code>liveness</code> +and a <code>readiness</code> probe can be configured, and each probe can be of type <code>httpGet</code>, <code>exec</code>, or +<code>tcpSocket</code> depending on the type of probe the container requires.</p> +<p>A liveness probe is useful for applications running for long periods of time, eventually +transitioning to broken states and cannot recover except by restarting them.</p> +<p>Other times, a readiness probe is useful when the container is only temporarily unable to serve, +and will recover on its own. In this case, if a container fails its readiness probe, the container +will not be shut down, but rather the container will stop receiving incoming requests.</p> +<p><code>httpGet</code> probes are just as it sounds: it performs a HTTP GET operation on the Container. A +response code inside the 200-399 range is considered a pass.</p> +<p><code>exec</code> probes run a command inside the Container to determine its health, such as +<code>cat /var/run/myapp.pid</code> or a script that determines when the application is ready. An exit code of +zero is considered a pass, while a non-zero status code is considered a fail.</p> +<p><code>tcpSocket</code> probes attempt to open a socket in the Container. The Container is only considered +healthy if the check can establish a connection. <code>tcpSocket</code> probes accept a port number to perform +the socket connection on the Container.</p> +<p>Health checks can be configured on a per-proctype basis for each application using <code>drycc healthchecks:set</code>. If no type is mentioned then the health checks are applied to default proc type web, whichever is present. To +configure a <code>httpGet</code> liveness probe:</p> +<pre tabindex="0"><code>$ drycc healthchecks:set liveness httpGet 80 --ptype web +Applying livenessProbe healthcheck... done + +App: peachy-waxworks +UUID: afd84067-29e9-4a5f-9f3a-60d91e938812 +Owner: dev +Created: 2023-12-08T10:25:00Z +Updated: 2023-12-08T10:25:00Z +Healthchecks: + liveness web http-get headers=[] path=/ port=80 delay=50s timeout=50s period=10s #success=1 #failure=3 +</code></pre><p>If the application relies on certain headers being set (such as the <code>Host</code> header) or a specific +URL path relative to the root, you can also send specific HTTP headers:</p> +<pre tabindex="0"><code>$ drycc healthchecks:set liveness httpGet 80 \ + --path /welcome/index.html \ + --headers &#34;X-Client-Version:v1.0,X-Foo:bar&#34; +Applying livenessProbe healthcheck... done + +App: peachy-waxworks +UUID: afd84067-29e9-4a5f-9f3a-60d91e938812 +Owner: dev +Created: 2023-12-08T10:25:00Z +Updated: 2023-12-08T10:25:00Z +Healthchecks: + liveness web http-get headers=[X-Client-Version=v1.0] path=/welcome/index.html port=80 delay=50s timeout=50s period=10s #success=1 #failure=3 +</code></pre><p>To configure an <code>exec</code> readiness probe:</p> +<pre tabindex="0"><code>$ drycc healthchecks:set readiness exec -- /bin/echo -n hello --ptype web +Applying readinessProbe healthcheck... done + +App: peachy-waxworks +UUID: afd84067-29e9-4a5f-9f3a-60d91e938812 +Owner: dev +Created: 2023-12-08T10:25:00Z +Updated: 2023-12-08T10:25:00Z +Healthchecks: + readiness web exec /bin/echo -n hello delay=50s timeout=50s period=10s #success=1 #failure=3 +</code></pre><p>You can overwrite a probe by running <code>drycc healthchecks:set</code> again:</p> +<pre tabindex="0"><code>$ drycc healthchecks:set readiness httpGet 80 --ptype web +Applying livenessProbe healthcheck... done + +App: peachy-waxworks +UUID: afd84067-29e9-4a5f-9f3a-60d91e938812 +Owner: dev +Created: 2023-12-08T10:25:00Z +Updated: 2023-12-08T10:25:00Z +Healthchecks: + liveness web http-get headers=[] path=/ port=80 delay=50s timeout=50s period=10s #success=1 #failure=3 +</code></pre><p>Configured health checks also modify the default application deploy behavior. When starting a new +Pod, Workflow will wait for the health check to pass before moving onto the next Pod.</p> +<h2 id="autodeploy">Autodeploy<a class="td-heading-self-link" href="#autodeploy" aria-label="Heading self-link"></a></h2> +<p>By default, Changes the config, limits or healthchecks and so on will trigger deploy. +If you don&rsquo;t want deploy, you can disable.</p> +<pre tabindex="0"><code>$ drycc autodeploy:disable +</code></pre><p>To re-enable autodeploy.</p> +<pre tabindex="0"><code>drycc autodeploy:enable +</code></pre><p>you can deploy by executing the following command. +deploy all ptypes</p> +<pre tabindex="0"><code>drycc releases:deploy +</code></pre><p>deploy web process type, and support <code>--force</code> option to force deploy.</p> +<pre tabindex="0"><code>drycc releases:deploy web --force +</code></pre><h2 id="autorollback">Autorollback<a class="td-heading-self-link" href="#autorollback" aria-label="Heading self-link"></a></h2> +<p>By default, deployment failures will roll back to the previous successful version. +If you don&rsquo;t want this to happen, you can disable.</p> +<pre tabindex="0"><code>$ drycc autorollback:disable +</code></pre><p>To re-enable autorollback.</p> +<pre tabindex="0"><code>drycc autorollback:enable +</code></pre><h2 id="isolate-the-application">Isolate the Application<a class="td-heading-self-link" href="#isolate-the-application" aria-label="Heading self-link"></a></h2> +<p>Workflow supports isolating applications onto a set of nodes using <code>drycc tags</code>.</p> +<p>!!! note +In order to use tags, you must first launch your cluster with the proper node labels. If you do +not, tag commands will fail. Learn more by reading <a href="http://kubernetes.io/docs/user-guide/node-selection/">&ldquo;Assigning Pods to Nodes&rdquo;</a>.</p> +<p>Once your nodes are configured with appropriate label selectors, use <code>drycc tags:set</code> to restrict +the application ptype to those nodes:</p> +<pre tabindex="0"><code>$ drycc tags:set web environ=prod +Applying tags... done, v4 + +environ prod +</code></pre> + + + + + Docs: Managing Application Metrics + /docs/applications/managing-app-metrics/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/applications/managing-app-metrics/ + + + + <h2 id="create-an-authentication-token">Create an authentication token<a class="td-heading-self-link" href="#create-an-authentication-token" aria-label="Heading self-link"></a></h2> +<p>Create an authentication token using the drycc client.</p> +<pre tabindex="0"><code># drycc tokens:add prometheus --password admin --username admin + ! WARNING: Make sure to copy your token now. + ! You won&#39;t be able to see it again, please confirm whether to continue. + ! To proceed, type &#34;yes&#34; ! + +&gt; yes +UUID USERNAME TOKEN +58176cf1-37a8-4c52-9b27-4c7a47269dfb admin 1F2c7A802aF640fd9F31dD846AdDf56BcMsay +</code></pre><h2 id="add-scrape-configurations-for-prometheus">Add scrape configurations for prometheus<a class="td-heading-self-link" href="#add-scrape-configurations-for-prometheus" aria-label="Heading self-link"></a></h2> +<p>A valid example file can be found here.</p> +<p>The global configuration specifies parameters that are valid in all other configuration contexts. They also serve as defaults for other configuration sections.</p> +<pre tabindex="0"><code>global: + scrape_interval: 60s + evaluation_interval: 60s +scrape_configs: +- job_name: &#39;drycc&#39; + scheme: https + metrics_path: /v2/apps/&lt;appname&gt;/metrics + authorization: + type: Token + credentials: 1F2c7A802aF640fd9F31dD846AdDf56BcMsay + static_configs: + - targets: [&#39;drycc.domain.com&#39;] +</code></pre> + + + + + Docs: Managing an Application + /docs/applications/managing-app-lifecycle/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/applications/managing-app-lifecycle/ + + + + <h2 id="track-application-changes">Track Application Changes<a class="td-heading-self-link" href="#track-application-changes" aria-label="Heading self-link"></a></h2> +<p>Drycc Workflow tracks all changes to your application. Application changes are the result of either new application code +pushed to the platform (via <code>git push drycc master</code>), or an update to application configuration (via <code>drycc config:set KEY=VAL</code>).</p> +<p>Each time a build or config change is made to your application a new <a href="../reference-guide/terms.md#release">release</a> is created. These release numbers +increase monotonically.</p> +<p>You can see a record of changes to your application using <code>drycc releases</code>:</p> +<pre tabindex="0"><code>$ drycc releases +OWNER STATE VERSION CREATED SUMMARY +dev succeed v3 2023-12-04T10:17:46Z dev deleted PIP_INDEX_URL, DISABLE_COLLECTSTATIC +dev succeed v2 2023-12-01T10:20:22Z dev added IMAGE_PULL_POLICY, PIP_INDEX_URL, PORT, DISABLE_COLLEC[...] +dev succeed v1 2023-11-30T17:54:57Z dev created initial release +</code></pre><h2 id="rollback-a-release">Rollback a Release<a class="td-heading-self-link" href="#rollback-a-release" aria-label="Heading self-link"></a></h2> +<p>Drycc Workflow also supports rolling back go previous releases. If buggy code or an errant configuration change is pushed +to your application, you may rollback to a previously known, good release.</p> +<p>!!! note +All rollbacks create a new, numbered release. But will reference the build/code and configuration from the desired rollback point.</p> +<p>In this example, the application is currently running release v4. Using <code>drycc rollback v2</code> tells Workflow to deploy the +build and configuration that was used for release v2. This creates a new release named v5 whose contents are the source +and configuration from release v2:</p> +<pre tabindex="0"><code>$ drycc releases +OWNER STATE VERSION CREATED SUMMARY +dev succeed v3 2023-12-04T10:17:46Z dev deleted PIP_INDEX_URL, DISABLE_COLLECTSTATIC +dev succeed v2 2023-12-01T10:20:22Z dev added IMAGE_PULL_POLICY, PIP_INDEX_URL, PORT, DISABLE_COLLEC[...] +dev succeed v1 2023-11-30T17:54:57Z dev created initial release + +$ drycc rollback v2 +Rolled back to v2 + +$ drycc releases +OWNER STATE VERSION CREATED SUMMARY +dev succeed v4 2023-12-04T10:20:46Z dev rolled back to v2 +dev succeed v3 2023-12-04T10:17:46Z dev deleted PIP_INDEX_URL, DISABLE_COLLECTSTATIC +dev succeed v2 2023-12-01T10:20:22Z dev added IMAGE_PULL_POLICY, PIP_INDEX_URL, PORT, DISABLE_COLLEC[...] +dev succeed v1 2023-11-30T17:54:57Z dev created initial release +</code></pre><p>Only rollback web process type:</p> +<pre tabindex="0"><code>$ drycc rollback v3 web +Rolled back to v3 + +$ drycc releases +OWNER STATE VERSION CREATED SUMMARY +dev succeed v5 2023-12-04T10:23:49Z dev rolled back to v3 +dev succeed v4 2023-12-04T10:20:46Z dev rolled back to v2 +dev succeed v3 2023-12-04T10:17:46Z dev deleted PIP_INDEX_URL, DISABLE_COLLECTSTATIC +dev succeed v2 2023-12-01T10:20:22Z dev added IMAGE_PULL_POLICY, PIP_INDEX_URL, PORT, DISABLE_COLLEC[...] +dev succeed v1 2023-11-30T17:54:57Z dev created initial release +</code></pre><h2 id="run-one-off-administration-tasks">Run One-off Administration Tasks<a class="td-heading-self-link" href="#run-one-off-administration-tasks" aria-label="Heading self-link"></a></h2> +<p>Drycc applications <a href="http://12factor.net/admin-processes">use one-off processes for admin tasks</a> like database migrations and other commands that must run against the live application.</p> +<p>Use <code>drycc run</code> to execute commands on the deployed application.</p> +<pre><code>$ drycc run 'ls -l' +Running `ls -l`... + +total 28 +-rw-r--r-- 1 root root 553 Dec 2 23:59 LICENSE +-rw-r--r-- 1 root root 60 Dec 2 23:59 Procfile +-rw-r--r-- 1 root root 33 Dec 2 23:59 README.md +-rw-r--r-- 1 root root 1622 Dec 2 23:59 pom.xml +drwxr-xr-x 3 root root 4096 Dec 2 23:59 src +-rw-r--r-- 1 root root 25 Dec 2 23:59 system.properties +drwxr-xr-x 6 root root 4096 Dec 3 00:00 target +</code></pre> +<h2 id="share-an-application">Share an Application<a class="td-heading-self-link" href="#share-an-application" aria-label="Heading self-link"></a></h2> +<p>Use <code>drycc perms:add</code> to allow another Drycc user to collaborate on your application.</p> +<pre tabindex="0"><code>$ drycc perms:add otheruser view,change,delete +Adding user otheruser as a collaborator for view,change,delete peachy-waxwork... done +</code></pre><p>Use <code>drycc perms</code> to see who an application is currently shared with, and <code>drycc perms:remove</code> to remove a collaborator.</p> +<p>!!! note +Collaborators can do anything with an application that its owner can do, except delete the application.</p> +<p>When working with an application that has been shared with you, clone the original repository and add Drycc&rsquo; git remote +entry before attempting to <code>git push</code> any changes to Drycc.</p> +<pre tabindex="0"><code>$ git clone https://github.com/drycc/example-java-jetty.git +Cloning into &#39;example-java-jetty&#39;... done +$ cd example-java-jetty +$ git remote add -f drycc ssh://git@local3.dryccapp.com:2222/peachy-waxworks.git +Updating drycc +From drycc-controller.local:peachy-waxworks + * [new branch] master -&gt; drycc/master +</code></pre><h2 id="application-troubleshooting">Application Troubleshooting<a class="td-heading-self-link" href="#application-troubleshooting" aria-label="Heading self-link"></a></h2> +<p>Applications deployed on Drycc Workflow <a href="http://12factor.net/logs">treat logs as event streams</a>. Drycc Workflow aggregates <code>stdout</code> and <code>stderr</code> +from every <a href="../reference-guide/terms.md#container">Container</a> making it easy to troubleshoot problems with your application.</p> +<p>Use <code>drycc logs</code> to view the log output from your deployed application.</p> +<pre><code>$ drycc logs -f +Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.5]: INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null} +Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.8]: INFO:oejs.Server:jetty-7.6.0.v20120127 +Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.5]: INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:10005 +Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.6]: INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null} +Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.7]: INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null} +Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.6]: INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:10006 +Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.8]: INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null} +Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.7]: INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:10007 +Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.8]: INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:10008 +</code></pre> + + + + + + Docs: Mounting volumes for an Application + /docs/applications/managing-app-volumes/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/applications/managing-app-volumes/ + + + + <p>We can use the blow command to create volumes and mount the created volumes. +Drycc create volume support <a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes">ReadWriteMany</a>, so before deploying drycc, you need to have a StorageClass ready which can support ReadWriteMany. +Deploying drycc, set controller.appStorageClass to this StorageClass.</p> +<p>Use <code>drycc volumes</code> to mount a volume for a deployed application&rsquo;s processes.</p> +<pre><code>$ drycc help volumes +Valid commands for volumes: + +volumes:create create a volume for the application +volumes:list list volumes in the application +volumes:delete delete a volume from the application +volumes:client the client used to manage volume files +volumes:mount mount a volume to process of the application +volumes:unmount unmount a volume from process of the application + +Use 'drycc help [command]' to learn more. +</code></pre> +<h2 id="create-a-volume-for-the-application">Create a volume for the application<a class="td-heading-self-link" href="#create-a-volume-for-the-application" aria-label="Heading self-link"></a></h2> +<p>You can create a csi volume with the <code>drycc volumes:create</code> command.</p> +<pre><code>$ drycc volumes:create myvolume 200M +Creating myvolumes to scenic-icehouse... done +</code></pre> +<p>Or use an existing nfs server</p> +<pre><code>$ drycc volumes:create myvolume 200M -t nfs --nfs-server=nfs.drycc.com --nfs-path=/ +Creating myvolumes to scenic-icehouse... done +</code></pre> +<h2 id="list-volumes-in-the-application">List volumes in the application<a class="td-heading-self-link" href="#list-volumes-in-the-application" aria-label="Heading self-link"></a></h2> +<p>After volume is created, you can list the volumes in this application.</p> +<pre><code>$ drycc volumes:list +=== scenic-icehouse volumes +--- myvolumes 200M +</code></pre> +<h2 id="mount-a-volume">Mount a volume<a class="td-heading-self-link" href="#mount-a-volume" aria-label="Heading self-link"></a></h2> +<p>The volume which is named myvolumes is created, you can mount the volume with process of the application, +use the command of <code>drycc volumes:mount</code>. When volume is mounted, a new release will be created and deployed automatically.</p> +<pre><code>$ drycc volumes:mount myvolumes web=/data/web +Mounting volume... done +</code></pre> +<p>And use <code>drycc volumes:list</code> show mount detail.</p> +<pre><code>$ drycc volumes:list +=== scenic-icehouse volumes +--- myvolumes 200M +web /data/web +</code></pre> +<p>If you don&rsquo;t need the volume, use <code>drycc volumes:unmount</code> to unmount the volume and then use <code>drycc volumes:delete</code> to delete the volume from the application. +Before deleting volume, the volume has to be unmounted.</p> +<pre><code>$ drycc volumes:unmount myvolumes web +Unmounting volume... done + +$ drycc volumes:delete myvolumes +Deleting myvolumes from scenic-icehouse... done +</code></pre> +<h2 id="use-volume-client-to-manage-volume-files">Use volume client to manage volume files.<a class="td-heading-self-link" href="#use-volume-client-to-manage-volume-files" aria-label="Heading self-link"></a></h2> +<p>Assume the volume which is named myvolumes is created and mounted.</p> +<p>Prepare a file named testfile.</p> +<pre><code>$ echo &quot;testtext&quot; &gt; testfile +</code></pre> +<p>Upload. +$ drycc volumes:client cp testfile vol://myvolume/ +[↑] testfile 100% [==================================================] (5/ 5 B, 355 B/s)</p> +<p>List files in myvolume.</p> +<pre><code>$ drycc volumes:client ls vol://myvolume/ +[2024-07-22T15:32:28+08:00] 5 testfile +</code></pre> +<p>Delete testfle in myvolume.</p> +<pre><code>$ drycc volumes:client rm vol://myvolume/testfile</code></pre> + + + + + + Docs: About gateway for an Application + /docs/applications/managing-app-gateway/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/applications/managing-app-gateway/ + + + + <p>A <a href="https://gateway-api.sigs.k8s.io/">Gateway</a> describes how traffic can be translated to Services within the cluster. That is, it defines a request for a way to translate traffic from somewhere that does not know about Kubernetes to somewhere that does. For example, traffic sent to a Kubernetes Service by a cloud load balancer, an in-cluster proxy, or an external hardware load balancer. While many use cases have client traffic originating “outside” the cluster, this is not a requirement.</p> +<h2 id="create-gateway-for-an-application">Create Gateway for an Application<a class="td-heading-self-link" href="#create-gateway-for-an-application" aria-label="Heading self-link"></a></h2> +<p>Gateway is a way of exposing services externally, which generates an external IP address to connect route and service. +After deploy, the gateway has been created.</p> +<p>List the containers:</p> +<pre tabindex="0"><code># drycc gateways +NAME LISENTER PORT PROTOCOL ADDRESSES +python-getting-started tcp-80-0 80 HTTP 101.65.132.51 +</code></pre><p>You can also add a port in this gateway or create a one.</p> +<pre tabindex="0"><code># drycc gateways:add python-getting-started --port=443 --protocol=HTTPS +Adding gateway python-getting-started to python-getting-started... done +</code></pre><h2 id="create-service-for-an-application">Create service for an Application<a class="td-heading-self-link" href="#create-service-for-an-application" aria-label="Heading self-link"></a></h2> +<p>Service is a way of exposing services internally, creating a service generates an internal DNS that can access <code>ptype</code>. +the web process type has been created, for others types, you should add as needed.</p> +<p>List the services:</p> +<pre tabindex="0"><code>$ drycc services +PTYPE PORT PROTOCOL TARGET-PORT DOMAIN +web 80 TCP 8000 python-getting-started.python-getting-started.svc.cluster.local +</code></pre><p>Add a new service for process type</p> +<pre tabindex="0"><code># drycc services:add --help +# drycc services:add sleep 8001:8001 +</code></pre><h2 id="create-route-for-an-application">Create Route for an Application<a class="td-heading-self-link" href="#create-route-for-an-application" aria-label="Heading self-link"></a></h2> +<p>A Gateway may be attached to one or more Route references which serve to direct traffic for a subset of traffic to a specific service. +Same as the above, the web process type already bind the gateway and servies.</p> +<pre tabindex="0"><code># drycc routes +NAME OWNER PTYPE KIND SERVICE-PORT GATEWAY LISTENER-PORT +python-getting-started demo web HTTPRoute 80 python-getting-started 80 +</code></pre><p>create a new route and attach gateway.</p> +<pre tabindex="0"><code>drycc routes:create sleep --ptype=sleep --kind=HTTPRoute --port=8001 +drycc routes:attach sleep --gateway=python-getting-started --port=80 +</code></pre> + + + + + Docs: Managing resources for an Application + /docs/applications/managing-app-resources/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/applications/managing-app-resources/ + + + + <p>We can use blow command to create resources and bind which resource is created. +This command depend on <a href="https://service-catalog.drycc.cc">service-catalog</a>.</p> +<p>Use <code>drycc resources</code> to create and bind a resource for a deployed application.</p> +<pre><code>$ drycc help resources + +Valid commands for resources: + +resources:services list all available resource services +resources:plans list all available plans for an resource services +resources:create create a resource for the application +resources:list list resources in the application +resources:describe get a resource detail info in the application +resources:update update a resource from the application +resources:destroy delete a resource from the applicationa +resources:bind bind a resource to servicebroker +resources:unbind unbind a resource from servicebroker + +Use 'drycc help [command]' to learn more. +</code></pre> +<h2 id="list-all-available-resource-services">List all available resource services<a class="td-heading-self-link" href="#list-all-available-resource-services" aria-label="Heading self-link"></a></h2> +<p>You can list available resource services with one <code>drycc resources:services</code> command</p> +<pre><code>$ drycc resources:services +ID NAME UPDATEABLE +15032a52-33c2-4b40-97aa-ceb972f51509 airflow true +b7cb26a4-b258-445c-860b-a664239a67f8 cloudbeaver true +9ce3c3ba-33b5-4e4e-a5e9-a338a83d5070 flink true +b80c51a1-957c-4d93-b3d5-efde84cd8031 fluentbit true +fff5b6c7-ed85-429b-8265-493e40cc53c7 grafana true +412e368f-bf78-4798-92cc-43343119a57d kafka true +ea2a9b87-fbc4-4e2a-adee-161c1f91d98d minio true +383f7316-84f3-4955-8491-1d4b02b749c8 mongodb true +fbee746b-f3a7-4bef-8b55-cbecfd4c8ac3 mysql-cluster true +5975094d-45cc-4e85-8573-f93937d026c7 opensearch true +1db95161-7193-4544-8c76-e5ad5f6c03f6 pmm true +5cfb0abf-276c-445b-9060-9aa964ede87d postgresql-cluster true +b8f70264-eafc-4b2f-848e-2ec0d059032b prometheus true +f8186d36-f334-4094-8e02-d21a61da657b rabbitmq true +e1fd0d37-9046-4152-a29b-d155c5657c8b redis true +7d2b64c6-0b59-4f08-a2f5-7b17cea6e5ee redis-cluster true +2e6877df-86e7-4bcc-a869-2a9b6847a465 seaweedfs true +4aea5c0f-9495-420d-896a-ffc61a3eced5 spark true +b50db3b5-8d5f-4be9-b8bd-467ecd6cc11d zookeeper true +</code></pre> +<h2 id="list-all-available-plans-for-an-resource-services">List all available plans for an resource services<a class="td-heading-self-link" href="#list-all-available-plans-for-an-resource-services" aria-label="Heading self-link"></a></h2> +<p>You can list all available plans for an resource services with one <code>drycc resources:plans</code> command</p> +<pre><code>$ drycc resources:plans redis +ID NAME DESCRIPTION +8d659058-a3b4-4058-b039-cc03a31b9442 standard-128 Redis standard-128 plan which limit resources memory size 128Mi. +36e3dbec-fc51-4f6b-9baa-e31e316858be standard-256 Redis standard-256 plan which limit resources memory size 256Mi. +560817c2-5aa1-41c4-9ee6-a77e3ee552d5 standard-512 Redis standard-512 plan which limit resources memory size 512Mi. +d544d989-9fb8-43e9-a74e-0840ce1b8f0f standard-1024 Redis standard-1024 plan which limit resources memory size 1Gi. +ad51b7bb-9b12-4ffd-8e49-010c0141b263 standard-2048 Redis standard-2048 plan which limit resources memory size 2Gi. +5097d76e-557c-453f-bdb1-54009e0df78d standard-4096 Redis standard-4096 plan which limit resources memory size 4Gi. +be3fa2d0-36d2-47c5-9561-9deffe5ba373 standard-8192 Redis standard-8192 plan which limit resources memory size 8Gi. +4ca812a8-d7c3-439f-96cd-26523e88400e standard-16384 Redis standard-16384 plan which limit resources memory size 16Gi. +b7f2a71f-0d97-48fd-8eed-aab24a7822f3 standard-32768 Redis standard-32768 plan which limit resources memory size 32Gi. +25c6b5d5-7505-47c8-95b1-dc9bdc698063 standard-65536 Redis standard-65536 plan which limit resources memory size 64Gi. +</code></pre> +<h2 id="create-resource-in-application">Create resource in application<a class="td-heading-self-link" href="#create-resource-in-application" aria-label="Heading self-link"></a></h2> +<p>You can create a resource with one <code>drycc resources:create</code> command</p> +<pre><code>$ drycc resources:create redis:1000 redis +Creating redis to scenic-icehouse... done +</code></pre> +<p>After resources are created, you can list the resources in this application.</p> +<pre><code>$ drycc resources:list +UUID NAME OWNER PLAN UPDATED +07220e9e-d54d-4d74-a88c-f464aa374386 redis admin redis:standard-128 2024-05-08T01:01:00Z +</code></pre> +<h2 id="bind-resources">Bind resources<a class="td-heading-self-link" href="#bind-resources" aria-label="Heading self-link"></a></h2> +<p>The resource which is named redis is created, you can bind the redis to the application, +use the command of <code>drycc resources:bind redis</code>.</p> +<pre><code>$ drycc resources:bind redis +Binding resource... done +</code></pre> +<h2 id="describe-resources">Describe resources<a class="td-heading-self-link" href="#describe-resources" aria-label="Heading self-link"></a></h2> +<p>And use <code>drycc resources:describe</code> show the binding detail. If the binding is successful, this command will show the information of connect to the resource.</p> +<pre><code>$ drycc resources:describe redis +=== scenic-icehouse resource redis +plan: redis:1000 +status: Ready +binding: Ready + +REDISPORT: 6379 +REDIS_PASSWORD: RzG87SJWG1 +SENTINELHOST: 172.16.0.2 +SENTINELPORT: 26379 +</code></pre> +<h2 id="update-resources">Update resources<a class="td-heading-self-link" href="#update-resources" aria-label="Heading self-link"></a></h2> +<p>You can use the <code>drycc resources:update</code> command to upgrade a new plan. +An example of how to upgrade the plan&rsquo;s capacity to 100MB:</p> +<pre><code>$ drycc resources:update redis:10000 redis +Updating redis to scenic-icehouse... done +</code></pre> +<h2 id="remove-the-resource">Remove the resource<a class="td-heading-self-link" href="#remove-the-resource" aria-label="Heading self-link"></a></h2> +<p>If you don&rsquo;t need resources, use <code>drycc resources:unbind</code> to unbind the resource and then use <code>drycc resources:destroy</code> to delete the resource from the application. +Before deleting the resource, the resource must be unbinded.</p> +<pre><code>$ drycc resources:unbind redis +Unbinding resource... done + +$ drycc resources:destroy redis +Deleting redis from scenic-icehouse... done +</code></pre> + + + + + + Docs: Inter-app Communication + /docs/applications/inter-app-communication/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/applications/inter-app-communication/ + + + + <p>A common architecture pattern of multi-process applications is to have one process serve public requests while having multiple other processes supporting the public one to, for example, perform actions on a schedule or process work items from a queue. To implement this system of apps in Drycc Workflow, set up the apps to communicate using DNS resolution, as shown above, and hide the supporting processes from public view by removing them from the Drycc Workflow router.</p> +<h3 id="dns-service-discovery">DNS Service Discovery<a class="td-heading-self-link" href="#dns-service-discovery" aria-label="Heading self-link"></a></h3> +<p>Drycc Workflow supports deploying a single app composed of a system of processes. Each Drycc Workflow app communicates on a single port, so communicating with another Workflow app means finding that app&rsquo;s address and port. All Workflow apps are mapped to port 80 externally, so finding its IP address is the only challenge. Workflow creates a <a href="https://kubernetes.io/docs/user-guide/services/">Kubernetes Service</a> for each app, which effectively assigns a name and one cluster-internal IP address to an app. The DNS service running in the cluster adds and removes DNS records which point from the app name to its IP address as services are added and removed. Drycc Workflow apps, then, can simply send requests to the domain name given to the service, which is &ldquo;app-name.app-namespace&rdquo;.</p> + + + + + + Docs: Resource Limits + /docs/applications/managing-resource-limits/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/applications/managing-resource-limits/ + + + + <h2 id="heading"><a class="td-heading-self-link" href="#heading" aria-label="Heading self-link"></a></h2> +<h2 id="managing-application-resource-limits">Managing Application Resource Limits<a class="td-heading-self-link" href="#managing-application-resource-limits" aria-label="Heading self-link"></a></h2> +<p>Drycc Workflow supports restricting memory and CPU shares of each process. Requests/Limits set on a per-process type are given to +Kubernetes as a requests and limits. Which means you guarantee &lt;requests&gt; amount of resource for a process as well as limit +the process from using more than &lt;limits&gt;. +By default, Kubernetes will set &lt;requests&gt; equal to &lt;limit&gt; if we don&rsquo;t explicitly set &lt;requests&gt; value. Please keep in mind that <code>0 &lt;= requests &lt;= limits</code>.</p> +<h2 id="limiting">Limiting<a class="td-heading-self-link" href="#limiting" aria-label="Heading self-link"></a></h2> +<p>If you set a requests/limits that is out of range for your cluster, Kubernetes will be unable to schedule your application +processes into the cluster!</p> +<pre tabindex="0"><code>$ drycc limits:plans + +ID SPEC CPU VCPUS MEMORY FEATURES +std1.large.c1m1 std1 Universal CPU 1 1 GiB Integrated GPU shared +std1.large.c1m2 std1 Universal CPU 1 2 GiB Integrated GPU shared +std1.large.c1m4 std1 Universal CPU 1 4 GiB Integrated GPU shared +std1.large.c1m8 std1 Universal CPU 1 8 GiB Integrated GPU shared +std1.large.c2m2 std1 Universal CPU 2 2 GiB Integrated GPU shared +std1.large.c2m4 std1 Universal CPU 2 4 GiB Integrated GPU shared +std1.large.c2m8 std1 Universal CPU 2 8 GiB Integrated GPU shared +std1.large.c2m16 std1 Universal CPU 2 16 GiB Integrated GPU shared + +$ drycc limits:set web=std1.large.c1m1 +Applying limits... done +</code></pre> + + + + + Docs: Domains and Routing + /docs/applications/domains-and-routing/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/applications/domains-and-routing/ + + + + <p>You can use <code>drycc domains</code> to add or remove custom domains to the application:</p> +<pre><code>$ drycc domains:add hello.bacongobbler.com --ptype=web +Adding hello.bacongobbler.com to finest-woodshed... done +</code></pre> +<p>Once that&rsquo;s done, you can go into a DNS registrar and set up a CNAME from the new +appname to the old one:</p> +<pre><code>$ dig hello.dryccapp.com +[...] +;; ANSWER SECTION: +hello.bacongobbler.com. 1759 IN CNAME finest-woodshed.dryccapp.com. +finest-woodshed.dryccapp.com. 270 IN A 172.17.8.100 +</code></pre> +<p>!!! note +Setting a CNAME for a root domain can cause issues. Setting an @ record +to be a CNAME causes all traffic to go to the other domain, including mail and the SOA +(&ldquo;start-of-authority&rdquo;) records. It is highly recommended that you bind a subdomain to +an application, however you can work around this by pointing the @ record to the +address of the load balancer (if any).</p> +<p>To add or remove the application from the routing mesh, use <code>drycc routing</code>:</p> +<pre><code>$ drycc routing:disable +Disabling routing for finest-woodshed... done +</code></pre> +<p>This will make the application unreachable through the <a href="/docs/understanding-workflow/components/#router">Router</a>, but the application is still +reachable internally through its <a href="../reference-guide/terms.md#service">Kubernetes Service</a>. To re-enable routing:</p> +<pre><code>$ drycc routing:enable +Enabling routing for finest-woodshed... done +</code></pre> + + + + + + Docs: Application SSL Certificates + /docs/applications/ssl-certificates/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/applications/ssl-certificates/ + + + + <h1 id="application-ssl-certificates">Application SSL Certificates<a class="td-heading-self-link" href="#application-ssl-certificates" aria-label="Heading self-link"></a></h1> +<p>SSL is a cryptographic protocol that provides end-to-end encryption and integrity for all web +requests. Apps that transmit sensitive data should enable SSL to ensure all information is +transmitted securely.</p> +<p>To enable SSL on a custom domain, e.g., <code>www.example.com</code>, use the SSL endpoint.</p> +<p>!!! note +<code>drycc certs</code> is only useful for custom domains. Default application domains are +SSL-enabled already and can be accessed simply by using https, +e.g. <code>https://foo.dryccapp.com</code> (provided that you have <a href="https://gateway-api.sigs.k8s.io/guides/tls/">installed your wildcard +certificate</a> on the routers or on the load balancer).</p> +<h2 id="overview">Overview<a class="td-heading-self-link" href="#overview" aria-label="Heading self-link"></a></h2> +<p>Because of the unique nature of SSL validation, provisioning SSL for your domain is a multi-step +process that involves several third-parties. You will need to:</p> +<ol> +<li>Purchase an SSL certificate from your SSL provider</li> +<li>Upload the cert to Drycc</li> +</ol> +<h2 id="acquire-ssl-certificate">Acquire SSL Certificate<a class="td-heading-self-link" href="#acquire-ssl-certificate" aria-label="Heading self-link"></a></h2> +<p>Purchasing an SSL cert varies in cost and process depending on the vendor. <a href="https://www.rapidssl.com/">RapidSSL</a> offers a +simple way to purchase a certificate and is a recommended solution. If you’re able to use this +provider, see <a href="https://www.rapidssl.com/buy-ssl/">buy an SSL certificate with RapidSSL</a> for instructions.</p> +<h2 id="dns-and-domain-configuration">DNS and Domain Configuration<a class="td-heading-self-link" href="#dns-and-domain-configuration" aria-label="Heading self-link"></a></h2> +<p>Once the SSL certificate is provisioned and your cert is confirmed, you must route requests for +your domain through Drycc. Unless you&rsquo;ve already done so, add the domain specified when generating +the CSR to your app with:</p> +<pre><code>$ drycc domains:add www.example.com --ptype==web -a foo +Adding www.example.com to foo... done +</code></pre> +<h2 id="add-a-certificate">Add a Certificate<a class="td-heading-self-link" href="#add-a-certificate" aria-label="Heading self-link"></a></h2> +<p>Add your certificate, any intermediate certificates, and private key to the endpoint with the +<code>certs:add</code> command.</p> +<pre><code>$ drycc certs:add example-com server.crt server.key -a foo +Adding SSL endpoint... done +www.example.com +</code></pre> +<p>!!! note +The name given to the certificate can only contain a-z (lowercase), 0-9 and hyphens</p> +<p>The Drycc platform will investigate the certificate and extract any relevant information from it +such as the Common Name, Subject Alt Names (SAN), fingerprint and more.</p> +<p>This allows for wildcard certificates and multiple domains in the SAN without uploading duplicates.</p> +<h3 id="add-a-certificate-chain">Add a Certificate Chain<a class="td-heading-self-link" href="#add-a-certificate-chain" aria-label="Heading self-link"></a></h3> +<p>Sometimes, your certificates (such as a self-signed or a cheap certificate) need additional +certificates to establish the chain of trust. What you need to do is bundle all the certificates +into one file and give that to Drycc. Importantly, your site’s certificate must be the first one:</p> +<pre><code>$ cat server.crt server.ca &gt; server.bundle +</code></pre> +<p>After that, you can add them to Drycc with the <code>certs:add</code> command:</p> +<pre><code>$ drycc certs:add example-com server.bundle server.key -a foo +Adding SSL endpoint... done +www.example.com +</code></pre> +<h2 id="attach-ssl-certificate-to-a-domain">Attach SSL certificate to a domain<a class="td-heading-self-link" href="#attach-ssl-certificate-to-a-domain" aria-label="Heading self-link"></a></h2> +<p>Certificates are not automagically connected up to domains, instead you will have to attach a +certificate to a domain</p> +<pre><code>$ drycc certs:attach example-com example.com -a foo +</code></pre> +<p>Each certificate can be connected to many domains. There is no need to upload duplicates.</p> +<p>To remove an association</p> +<pre><code>$ drycc certs:detach example-com example.com -a foo +</code></pre> +<h2 id="endpoint-overview">Endpoint overview<a class="td-heading-self-link" href="#endpoint-overview" aria-label="Heading self-link"></a></h2> +<p>You can verify the details of your domain&rsquo;s SSL configuration with <code>drycc certs</code>.</p> +<pre><code>$ drycc certs + + Name | Common Name | SubjectAltName | Expires | Fingerprint | Domains | Updated | Created ++-------------+-------------------+-------------------+-------------------------+-----------------+--------------+-------------+-------------+ + example-com | example.com | blog.example.com | 31 Dec 2017 (in 1 year) | 8F:8E[...]CD:EB | example.com | 30 Jan 2016 | 29 Jan 2016 +</code></pre> +<p>or by looking at at each certificates detailed information</p> +<pre><code>$ drycc certs:info example-com -a foo + +=== bar-com Certificate +Common Name(s): example.com +Expires At: 2017-01-14 23:57:57 +0000 UTC +Starts At: 2016-01-15 23:57:57 +0000 UTC +Fingerprint: 7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0 +Subject Alt Name: blog.example.com +Issuer: /C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=example.com/emailAddress=engineering@drycc.cc +Subject: /C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=example.com/emailAddress=engineering@drycc.cc + +Connected Domains: example.com +Owner: admin-user +Created: 2016-01-28 19:07:41 +0000 UTC +Updated: 2016-01-30 00:10:02 +0000 UTC +</code></pre> +<h2 id="testing-ssl">Testing SSL<a class="td-heading-self-link" href="#testing-ssl" aria-label="Heading self-link"></a></h2> +<p>Use a command line utility like <code>curl</code> to test that everything is configured correctly for your +secure domain.</p> +<p>!!! note +The -k option flag tells curl to ignore untrusted certificates.</p> +<p>Pay attention to the output. It should print <code>SSL certificate verify ok</code>. If it prints something +like <code>common name: www.example.com (does not match 'www.somedomain.com')</code> then something is not +configured correctly.</p> +<h2 id="enforcing-ssl-at-the-router">Enforcing SSL at the Router<a class="td-heading-self-link" href="#enforcing-ssl-at-the-router" aria-label="Heading self-link"></a></h2> +<p>To enforce all HTTP requests be redirected to HTTPS, TLS can be enforced at the router level by +running</p> +<pre><code>$ drycc tls:force:enable -a foo +Enabling https-only requests for foo... done +</code></pre> +<p>Users hitting the HTTP endpoint for the application will now receive a 301 redirect to the HTTPS +endpoint.</p> +<p>To disable enforced TLS, run</p> +<pre><code>$ drycc tls:force:disable -a foo +Disabling https-only requests for foo... done +</code></pre> +<h2 id="automated-certificate-management">Automated Certificate Management<a class="td-heading-self-link" href="#automated-certificate-management" aria-label="Heading self-link"></a></h2> +<p>With Automated Certificate Management (ACM), Drycc automatically manages TLS certificates for apps with Hobby and Professional dynos on the Common Runtime, and for apps in Private Spaces that enable the feature. +Certificates handled by ACM automatically renew one month before they expire, and new certificates are created automatically whenever you add or remove a custom domain. All applications with paid dynos include ACM for free. +Automated Certificate Management uses Let’s Encrypt, the free, automated, and open certificate authority for managing your application’s TLS certificates. Let’s Encrypt is run for the public benefit by the Internet Security Research Group (ISRG).</p> +<p>To enable ACM with the following command: +$ drycc tls:auto:enable -a foo</p> +<p>To disable ACM with the following command: +$ drycc tls:auto:disable -a foo</p> +<h2 id="remove-certificate">Remove Certificate<a class="td-heading-self-link" href="#remove-certificate" aria-label="Heading self-link"></a></h2> +<p>You can remove a certificate using the <code>certs:remove</code> command:</p> +<pre><code>$ drycc certs:remove my-cert -a foo +Removing www.example.com... Done. +</code></pre> +<h2 id="swapping-out-certificates">Swapping out certificates<a class="td-heading-self-link" href="#swapping-out-certificates" aria-label="Heading self-link"></a></h2> +<p>Over the lifetime of an application an operator will have to acquire certificates with new expire +dates and apply it to all relevant applications, below is the recommended way to swap out certificates.</p> +<p>Be intentional with certificate names, name them <code>example-com-2017</code> when possible, where the year +signifies the expiry year. This allows for <code>example-com-2018</code> when a new certificate is purchased.</p> +<p>Assuming all applications are already using <code>example-com-2017</code> the following commands can be ran, +chained together or otherwise:</p> +<pre><code>$ drycc certs:detach example-com-2017 example.com -a foo +$ drycc certs:attach example-com-2018 example.com -a foo +</code></pre> +<p>This will take care of a singular domain which allows the operator to verify everything went +as planned and slowly roll it out to any other application using the same method.</p> +<h2 id="troubleshooting">Troubleshooting<a class="td-heading-self-link" href="#troubleshooting" aria-label="Heading self-link"></a></h2> +<p>Here are some steps you can follow if your SSL endpoint is not working as you&rsquo;d expect.</p> +<h3 id="untrusted-certificate">Untrusted Certificate<a class="td-heading-self-link" href="#untrusted-certificate" aria-label="Heading self-link"></a></h3> +<p>In some cases when accessing the SSL endpoint, it may list your certificate as untrusted.</p> +<p>If this occurs, it may be because it is not trusted by Mozilla’s list of <a href="https://www.mozilla.org/en-US/about/governance/policies/security-group/certs/included/">root CAs</a>. If this is +the case, your certificate may be considered untrusted for many browsers.</p> +<p>If you have uploaded a certificate that was signed by a root authority but you get the message that +it is not trusted, then something is wrong with the certificate. For example, it may be missing +<a href="http://en.wikipedia.org/wiki/Intermediate_certificate_authorities">intermediary certificates</a>. If so, download the intermediary certificates from your SSL provider, +remove the certificate from Drycc and re-run the <code>certs:add</code> command.</p> + + + + + + Docs: Using drycc.yaml + /docs/applications/using-dryccfile/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/applications/using-dryccfile/ + + + + <p>The Drycc stack is intended for advanced use cases only. Unless you have a specific need for custom Docker images, we recommend using Drycc’s default buildpack-powered build system. It offers automatic base image security updates and language-specific optimizations. It also avoids the need to maintain a .containerDockerfile</p> +<h2 id="dryccyaml-overview">drycc.yaml Overview<a class="td-heading-self-link" href="#dryccyaml-overview" aria-label="Heading self-link"></a></h2> +<p>A manifest has three top-level sections.</p> +<ul> +<li>build – Specifies the to build Dockerfile</li> +<li>run – Specifies the release phase tasks to execute</li> +<li>deploy – Specifies process types and the commands to run for each type</li> +</ul> +<p>Here’s an example that illustrates using a manifest to build Docker images.</p> +<pre tabindex="0"><code>build: + docker: + web: Dockerfile + worker: worker/Dockerfile + config: + web: + FOO: bar + worker: + RAILS_ENV: development +run: +- command: + - ./deployment-tasks.sh + image: worker + # If the field is empty, it means it will be executed forever + when: + ptypes: + - web + - webbbsbs + # Maximum execution time + timeout: 100 +deploy: + web: + command: + - bash + - -ec + args: + - bundle exec puma -C config/puma.rb + worker: + command: + - bash + - -ec + args: + - python myworker.py + asset-syncer: + command: + - bash + - -ec + args: + - python asset-syncer.py + image: worker +</code></pre><p>For more deployment information, please refer to the drycc <a href="https://github.com/drycc/samples">examples</a>.</p> + + + + + + diff --git a/docs/applications/inter-app-communication/index.html b/docs/applications/inter-app-communication/index.html new file mode 100644 index 000000000..80632ec6e --- /dev/null +++ b/docs/applications/inter-app-communication/index.html @@ -0,0 +1,466 @@ + + + + + + + + + + + + + + + + + + + +Inter-app Communication | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Inter-app Communication

+
The Communication Solution between Drycc Applicatios.
+ +

A common architecture pattern of multi-process applications is to have one process serve public requests while having multiple other processes supporting the public one to, for example, perform actions on a schedule or process work items from a queue. To implement this system of apps in Drycc Workflow, set up the apps to communicate using DNS resolution, as shown above, and hide the supporting processes from public view by removing them from the Drycc Workflow router.

+

DNS Service Discovery

+

Drycc Workflow supports deploying a single app composed of a system of processes. Each Drycc Workflow app communicates on a single port, so communicating with another Workflow app means finding that app’s address and port. All Workflow apps are mapped to port 80 externally, so finding its IP address is the only challenge. Workflow creates a Kubernetes Service for each app, which effectively assigns a name and one cluster-internal IP address to an app. The DNS service running in the cluster adds and removes DNS records which point from the app name to its IP address as services are added and removed. Drycc Workflow apps, then, can simply send requests to the domain name given to the service, which is “app-name.app-namespace”.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/applications/managing-app-configuration/index.html b/docs/applications/managing-app-configuration/index.html new file mode 100644 index 000000000..b1c12424e --- /dev/null +++ b/docs/applications/managing-app-configuration/index.html @@ -0,0 +1,631 @@ + + + + + + + + + + + + + + + + + + + +Configuring an Application | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Configuring an Application

+
How to store configuration of a Drycc app in the environment, keeping config out of code, making it easy to maintain app or deployment specific configs.
+ +

Configuring an Application

+

A Drycc application stores config in environment variables.

+

Setting Environment Variables

+

Use drycc config to modify environment variables for a deployed application.

+
$ drycc help config
+Valid commands for config:
+
+config:list        list environment variables for an app
+config:set         set environment variables for an app
+config:unset       unset environment variables for an app
+config:pull        extract environment variables to .env
+config:push        set environment variables from .env
+
+Use `drycc help [command]` to learn more.
+
+

When config is changed, a new release is created and deployed automatically.

+

You can set multiple environment variables with one drycc config:set command, +or with drycc config:push and a local .env file.

+
$ drycc config:set FOO=1 BAR=baz && drycc config:pull
+$ cat .env
+FOO=1
+BAR=baz
+$ echo "TIDE=high" >> .env
+$ drycc config:push
+Creating config... done, v4
+
+=== yuppie-earthman
+DRYCC_APP: yuppie-earthman
+FOO: 1
+BAR: baz
+TIDE: high
+
+

It can also modify environment variables for a process type of application.

+
$ drycc config:set FOO=1 BAR=baz --ptype=web
+
+

Attach to Backing Services

+

Drycc treats backing services like databases, caches and queues as attached resources. +Attachments are performed using environment variables.

+

For example, use drycc config to set a DATABASE_URL that attaches +the application to an external PostgreSQL database.

+
$ drycc config:set DATABASE_URL=postgres://user:pass@example.com:5432/db
+=== peachy-waxworks
+DATABASE_URL: postgres://user:pass@example.com:5432/db
+
+

Detachments can be performed with drycc config:unset.

+

Buildpacks Cache

+

By default, apps using the [Imagebuilder][] will reuse the latest image data. +When deploying applications that depend on third-party libraries that have to be fetched, +this could speed up deployments a lot. In order to make use of this, the buildpack must implement +the cache by writing to the cache directory. Most buildpacks already implement this, but when using +custom buildpacks, it might need to be changed to make full use of the cache.

+

Disabling and re-enabling the cache

+

In some cases, cache might not speed up your application. To disable caching, you can set the +DRYCC_DISABLE_CACHE variable with drycc config:set DRYCC_DISABLE_CACHE=1. When you disable the +cache, Drycc will clear up files it created to store the cache. After having it turned off, run +drycc config:unset DRYCC_DISABLE_CACHE to re-enable the cache.

+

Clearing the cache

+

Use the following procedure to clear the cache:

+
$ drycc config:set DRYCC_DISABLE_CACHE=1
+$ git commit --allow-empty -m "Clearing Drycc cache"
+$ git push drycc # (if you use a different remote, you should use your remote name)
+$ drycc config:unset DRYCC_DISABLE_CACHE
+
+

Custom Health Checks

+

By default, Workflow only checks that the application starts in their Container. If it is preferred +to have Kubernetes respond to application health, a health check may be added by configuring a +health check probe for the application.

+

The health checks are implemented as Kubernetes container probes. A liveness +and a readiness probe can be configured, and each probe can be of type httpGet, exec, or +tcpSocket depending on the type of probe the container requires.

+

A liveness probe is useful for applications running for long periods of time, eventually +transitioning to broken states and cannot recover except by restarting them.

+

Other times, a readiness probe is useful when the container is only temporarily unable to serve, +and will recover on its own. In this case, if a container fails its readiness probe, the container +will not be shut down, but rather the container will stop receiving incoming requests.

+

httpGet probes are just as it sounds: it performs a HTTP GET operation on the Container. A +response code inside the 200-399 range is considered a pass.

+

exec probes run a command inside the Container to determine its health, such as +cat /var/run/myapp.pid or a script that determines when the application is ready. An exit code of +zero is considered a pass, while a non-zero status code is considered a fail.

+

tcpSocket probes attempt to open a socket in the Container. The Container is only considered +healthy if the check can establish a connection. tcpSocket probes accept a port number to perform +the socket connection on the Container.

+

Health checks can be configured on a per-proctype basis for each application using drycc healthchecks:set. If no type is mentioned then the health checks are applied to default proc type web, whichever is present. To +configure a httpGet liveness probe:

+
$ drycc healthchecks:set liveness httpGet 80 --ptype web
+Applying livenessProbe healthcheck... done
+
+App:             peachy-waxworks
+UUID:            afd84067-29e9-4a5f-9f3a-60d91e938812
+Owner:           dev
+Created:         2023-12-08T10:25:00Z
+Updated:         2023-12-08T10:25:00Z
+Healthchecks:
+                 liveness web http-get headers=[] path=/ port=80 delay=50s timeout=50s period=10s #success=1 #failure=3
+

If the application relies on certain headers being set (such as the Host header) or a specific +URL path relative to the root, you can also send specific HTTP headers:

+
$ drycc healthchecks:set liveness httpGet 80 \
+    --path /welcome/index.html \
+    --headers "X-Client-Version:v1.0,X-Foo:bar"
+Applying livenessProbe healthcheck... done
+
+App:             peachy-waxworks
+UUID:            afd84067-29e9-4a5f-9f3a-60d91e938812
+Owner:           dev
+Created:         2023-12-08T10:25:00Z
+Updated:         2023-12-08T10:25:00Z
+Healthchecks:
+                 liveness web http-get headers=[X-Client-Version=v1.0] path=/welcome/index.html port=80 delay=50s timeout=50s period=10s #success=1 #failure=3
+

To configure an exec readiness probe:

+
$ drycc healthchecks:set readiness exec -- /bin/echo -n hello --ptype web
+Applying readinessProbe healthcheck... done
+
+App:             peachy-waxworks
+UUID:            afd84067-29e9-4a5f-9f3a-60d91e938812
+Owner:           dev
+Created:         2023-12-08T10:25:00Z
+Updated:         2023-12-08T10:25:00Z
+Healthchecks:
+                 readiness web exec /bin/echo -n hello delay=50s timeout=50s period=10s #success=1 #failure=3
+

You can overwrite a probe by running drycc healthchecks:set again:

+
$ drycc healthchecks:set readiness httpGet 80 --ptype web
+Applying livenessProbe healthcheck... done
+
+App:             peachy-waxworks
+UUID:            afd84067-29e9-4a5f-9f3a-60d91e938812
+Owner:           dev
+Created:         2023-12-08T10:25:00Z
+Updated:         2023-12-08T10:25:00Z
+Healthchecks:
+                 liveness web http-get headers=[] path=/ port=80 delay=50s timeout=50s period=10s #success=1 #failure=3
+

Configured health checks also modify the default application deploy behavior. When starting a new +Pod, Workflow will wait for the health check to pass before moving onto the next Pod.

+

Autodeploy

+

By default, Changes the config, limits or healthchecks and so on will trigger deploy. +If you don’t want deploy, you can disable.

+
$ drycc autodeploy:disable
+

To re-enable autodeploy.

+
drycc autodeploy:enable
+

you can deploy by executing the following command. +deploy all ptypes

+
drycc releases:deploy
+

deploy web process type, and support --force option to force deploy.

+
drycc releases:deploy web --force
+

Autorollback

+

By default, deployment failures will roll back to the previous successful version. +If you don’t want this to happen, you can disable.

+
$ drycc autorollback:disable
+

To re-enable autorollback.

+
drycc autorollback:enable
+

Isolate the Application

+

Workflow supports isolating applications onto a set of nodes using drycc tags.

+

!!! note +In order to use tags, you must first launch your cluster with the proper node labels. If you do +not, tag commands will fail. Learn more by reading “Assigning Pods to Nodes”.

+

Once your nodes are configured with appropriate label selectors, use drycc tags:set to restrict +the application ptype to those nodes:

+
$ drycc tags:set web environ=prod
+Applying tags...  done, v4
+
+environ  prod
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/applications/managing-app-gateway/index.html b/docs/applications/managing-app-gateway/index.html new file mode 100644 index 000000000..82ffe291f --- /dev/null +++ b/docs/applications/managing-app-gateway/index.html @@ -0,0 +1,491 @@ + + + + + + + + + + + + + + + + + + + +About gateway for an Application | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

About gateway for an Application

+
A Gateway describes how traffic can be translated to Services within the cluster.
+ +

A Gateway describes how traffic can be translated to Services within the cluster. That is, it defines a request for a way to translate traffic from somewhere that does not know about Kubernetes to somewhere that does. For example, traffic sent to a Kubernetes Service by a cloud load balancer, an in-cluster proxy, or an external hardware load balancer. While many use cases have client traffic originating “outside” the cluster, this is not a requirement.

+

Create Gateway for an Application

+

Gateway is a way of exposing services externally, which generates an external IP address to connect route and service. +After deploy, the gateway has been created.

+

List the containers:

+
# drycc gateways
+NAME                      LISENTER       PORT     PROTOCOL    ADDRESSES      
+python-getting-started    tcp-80-0       80       HTTP        101.65.132.51     
+

You can also add a port in this gateway or create a one.

+
# drycc gateways:add python-getting-started --port=443 --protocol=HTTPS
+Adding gateway python-getting-started to python-getting-started... done     
+

Create service for an Application

+

Service is a way of exposing services internally, creating a service generates an internal DNS that can access ptype. +the web process type has been created, for others types, you should add as needed.

+

List the services:

+
$ drycc services
+PTYPE      PORT    PROTOCOL    TARGET-PORT    DOMAIN                                    
+web        80      TCP         8000           python-getting-started.python-getting-started.svc.cluster.local  
+

Add a new service for process type

+
# drycc services:add --help
+# drycc services:add sleep 8001:8001
+

Create Route for an Application

+

A Gateway may be attached to one or more Route references which serve to direct traffic for a subset of traffic to a specific service. +Same as the above, the web process type already bind the gateway and servies.

+
# drycc routes
+NAME                           OWNER        PTYPE      KIND         SERVICE-PORT    GATEWAY                           LISTENER-PORT             
+python-getting-started         demo         web        HTTPRoute    80              python-getting-started            80  
+

create a new route and attach gateway.

+
drycc routes:create sleep --ptype=sleep --kind=HTTPRoute --port=8001
+drycc routes:attach sleep --gateway=python-getting-started --port=80
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/applications/managing-app-lifecycle/index.html b/docs/applications/managing-app-lifecycle/index.html new file mode 100644 index 000000000..23db406ac --- /dev/null +++ b/docs/applications/managing-app-lifecycle/index.html @@ -0,0 +1,554 @@ + + + + + + + + + + + + + + + + + + + +Managing an Application | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Managing an Application

+
This is a high-level, technical description of how Drycc works. It ties together many of the concepts you’ll encounter while writing, configuring, deploying and running applications on the Drycc platform.
+ +

Track Application Changes

+

Drycc Workflow tracks all changes to your application. Application changes are the result of either new application code +pushed to the platform (via git push drycc master), or an update to application configuration (via drycc config:set KEY=VAL).

+

Each time a build or config change is made to your application a new release is created. These release numbers +increase monotonically.

+

You can see a record of changes to your application using drycc releases:

+
$ drycc releases
+OWNER    STATE      VERSION    CREATED                 SUMMARY
+dev      succeed    v3         2023-12-04T10:17:46Z    dev deleted PIP_INDEX_URL, DISABLE_COLLECTSTATIC
+dev      succeed    v2         2023-12-01T10:20:22Z    dev added IMAGE_PULL_POLICY, PIP_INDEX_URL, PORT, DISABLE_COLLEC[...]
+dev      succeed    v1         2023-11-30T17:54:57Z    dev created initial release
+

Rollback a Release

+

Drycc Workflow also supports rolling back go previous releases. If buggy code or an errant configuration change is pushed +to your application, you may rollback to a previously known, good release.

+

!!! note +All rollbacks create a new, numbered release. But will reference the build/code and configuration from the desired rollback point.

+

In this example, the application is currently running release v4. Using drycc rollback v2 tells Workflow to deploy the +build and configuration that was used for release v2. This creates a new release named v5 whose contents are the source +and configuration from release v2:

+
$ drycc releases
+OWNER    STATE      VERSION    CREATED                 SUMMARY
+dev      succeed    v3         2023-12-04T10:17:46Z    dev deleted PIP_INDEX_URL, DISABLE_COLLECTSTATIC
+dev      succeed    v2         2023-12-01T10:20:22Z    dev added IMAGE_PULL_POLICY, PIP_INDEX_URL, PORT, DISABLE_COLLEC[...]
+dev      succeed    v1         2023-11-30T17:54:57Z    dev created initial release
+
+$ drycc rollback v2
+Rolled back to v2
+
+$ drycc releases
+OWNER    STATE      VERSION    CREATED                 SUMMARY
+dev      succeed    v4         2023-12-04T10:20:46Z    dev rolled back to v2
+dev      succeed    v3         2023-12-04T10:17:46Z    dev deleted PIP_INDEX_URL, DISABLE_COLLECTSTATIC
+dev      succeed    v2         2023-12-01T10:20:22Z    dev added IMAGE_PULL_POLICY, PIP_INDEX_URL, PORT, DISABLE_COLLEC[...]
+dev      succeed    v1         2023-11-30T17:54:57Z    dev created initial release
+

Only rollback web process type:

+
$ drycc rollback v3 web
+Rolled back to v3
+
+$ drycc releases
+OWNER    STATE      VERSION    CREATED                 SUMMARY
+dev      succeed    v5         2023-12-04T10:23:49Z    dev rolled back to v3
+dev      succeed    v4         2023-12-04T10:20:46Z    dev rolled back to v2
+dev      succeed    v3         2023-12-04T10:17:46Z    dev deleted PIP_INDEX_URL, DISABLE_COLLECTSTATIC
+dev      succeed    v2         2023-12-01T10:20:22Z    dev added IMAGE_PULL_POLICY, PIP_INDEX_URL, PORT, DISABLE_COLLEC[...]
+dev      succeed    v1         2023-11-30T17:54:57Z    dev created initial release
+

Run One-off Administration Tasks

+

Drycc applications use one-off processes for admin tasks like database migrations and other commands that must run against the live application.

+

Use drycc run to execute commands on the deployed application.

+
$ drycc run 'ls -l'
+Running `ls -l`...
+
+total 28
+-rw-r--r-- 1 root root  553 Dec  2 23:59 LICENSE
+-rw-r--r-- 1 root root   60 Dec  2 23:59 Procfile
+-rw-r--r-- 1 root root   33 Dec  2 23:59 README.md
+-rw-r--r-- 1 root root 1622 Dec  2 23:59 pom.xml
+drwxr-xr-x 3 root root 4096 Dec  2 23:59 src
+-rw-r--r-- 1 root root   25 Dec  2 23:59 system.properties
+drwxr-xr-x 6 root root 4096 Dec  3 00:00 target
+
+

Share an Application

+

Use drycc perms:add to allow another Drycc user to collaborate on your application.

+
$ drycc perms:add otheruser view,change,delete
+Adding user otheruser as a collaborator for view,change,delete peachy-waxwork... done
+

Use drycc perms to see who an application is currently shared with, and drycc perms:remove to remove a collaborator.

+

!!! note +Collaborators can do anything with an application that its owner can do, except delete the application.

+

When working with an application that has been shared with you, clone the original repository and add Drycc’ git remote +entry before attempting to git push any changes to Drycc.

+
$ git clone https://github.com/drycc/example-java-jetty.git
+Cloning into 'example-java-jetty'... done
+$ cd example-java-jetty
+$ git remote add -f drycc ssh://git@local3.dryccapp.com:2222/peachy-waxworks.git
+Updating drycc
+From drycc-controller.local:peachy-waxworks
+ * [new branch]      master     -> drycc/master
+

Application Troubleshooting

+

Applications deployed on Drycc Workflow treat logs as event streams. Drycc Workflow aggregates stdout and stderr +from every Container making it easy to troubleshoot problems with your application.

+

Use drycc logs to view the log output from your deployed application.

+
$ drycc logs -f
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.5]: INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null}
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.8]: INFO:oejs.Server:jetty-7.6.0.v20120127
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.5]: INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:10005
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.6]: INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null}
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.7]: INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null}
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.6]: INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:10006
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.8]: INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null}
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.7]: INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:10007
+Dec  3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.8]: INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:10008
+
+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/applications/managing-app-metrics/index.html b/docs/applications/managing-app-metrics/index.html new file mode 100644 index 000000000..f128f8df2 --- /dev/null +++ b/docs/applications/managing-app-metrics/index.html @@ -0,0 +1,485 @@ + + + + + + + + + + + + + + + + + + + +Managing Application Metrics | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Managing Application Metrics

+
Metrics supports basic monitoring capabilities for Pod, providing various monitoring indicators such as CPU, memory, disk, network, etc., to meet the basic monitoring requirements for Pod resources.
+ +

Create an authentication token

+

Create an authentication token using the drycc client.

+
# drycc tokens:add prometheus --password admin --username admin
+ !    WARNING: Make sure to copy your token now.
+ !    You won't be able to see it again, please confirm whether to continue.
+ !    To proceed, type "yes" !
+
+> yes
+UUID                                  USERNAME    TOKEN                                                                                              
+58176cf1-37a8-4c52-9b27-4c7a47269dfb  admin       1F2c7A802aF640fd9F31dD846AdDf56BcMsay
+

Add scrape configurations for prometheus

+

A valid example file can be found here.

+

The global configuration specifies parameters that are valid in all other configuration contexts. They also serve as defaults for other configuration sections.

+
global:
+  scrape_interval:   60s
+  evaluation_interval: 60s
+scrape_configs:
+- job_name: 'drycc'
+  scheme: https
+  metrics_path: /v2/apps/<appname>/metrics
+  authorization:
+    type: Token
+    credentials: 1F2c7A802aF640fd9F31dD846AdDf56BcMsay
+  static_configs:
+  - targets: ['drycc.domain.com']
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/applications/managing-app-processes/index.html b/docs/applications/managing-app-processes/index.html new file mode 100644 index 000000000..2696bb96d --- /dev/null +++ b/docs/applications/managing-app-processes/index.html @@ -0,0 +1,699 @@ + + + + + + + + + + + + + + + + + + + +Managing Application Processes | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Managing Application Processes

+
A Procfile is a list of process types in an app. Each process type declares a command that is executed when a container of that process type is started.
+ +

Drycc Workflow manages your application as a set of processes that can be named, scaled and configured according to their +role. This gives you the flexibility to easily manage the different facets of your application. For example, you may have +web-facing processes that handle HTTP traffic, background worker processes that do async work, and a helper process that +streams from the Twitter API.

+

By using a Procfile, either checked in to your application or provided via the CLI you can specify the name of the type +and the application command that should run. To spawn other process types, use drycc scale <ptype>=<n> to scale those +types accordingly.

+

Default Process Types

+

In the absence of a Procfile, a single, default process type is assumed for each application.

+

Applications built using Buildpacks via git push implicitly receive a web process type, which starts +the application server. Rails 4, for example, has the following process type:

+
web: bundle exec rails server -p $PORT
+
+

All applications utilizing Dockerfiles have an implied web process type, which runs the +Dockerfile’s CMD directive unmodified:

+
$ cat Dockerfile
+FROM centos:latest
+COPY . /app
+WORKDIR /app
+CMD python -m SimpleHTTPServer 5000
+EXPOSE 5000
+
+

For the above Dockerfile-based application, the web process type would run the Container CMD of python -m SimpleHTTPServer 5000.

+

Applications utilizing remote Container images, a web process type is also implied, and runs the CMD +specified in the Container image.

+

!!! note +The web process type is special as they’is the default process type that will +receive HTTP traffic from Workflow’s routers. Other process types can be named arbitrarily.

+

Declaring Process Types

+

If you use Buildpack or Dockerfile builds and want to override or specify additional process +types, simply include a file named Procfile in the root of your application’s source tree.

+

The format of a Procfile is one process type per line, with each line containing the command to invoke:

+
<process type>: <command>
+
+

The syntax is defined as:

+
    +
  • <process type> – a lowercase alphanumeric string, is a name for your command, such as web, worker, urgentworker, clock, etc.
  • +
  • <command> – a command line to launch the process, such as rake jobs:work.
  • +
+

This example Procfile specifies two types, web and sleeper. The web process launches a web server on port 5000 and +a simple process which sleeps for 900 seconds and exits.

+
$ cat Procfile
+web: bundle exec ruby web.rb -p ${PORT:-5000}
+sleeper: sleep 900
+

If you are using remote Container images, you may define process types by either running drycc pull with a +Procfile in your working directory, or by passing a stringified Procfile to the --procfile CLI option.

+

For example, passing process types inline:

+
$ drycc pull drycc/example-go:latest --procfile="web: /app/bin/boot"
+

Read a Procfile in another directory:

+
$ drycc pull drycc/example-go:latest --procfile="$(cat deploy/Procfile)"
+

Or via a Procfile located in your current, working directory:

+
$ cat Procfile
+web: /bin/boot
+sleeper: echo "sleeping"; sleep 900
+
+
+$ drycc pull -a steely-mainsail drycc/example-go
+Creating build... done
+
+$ drycc scale sleeper=1 -a steely-mainsail
+Scaling processes... but first, coffee!
+done in 0s
+
+NAME                                        RELEASE    STATE    PTYPE      READY    RESTARTS     STARTED
+steely-mainsail-sleeper-76c45b967c-4qm6w    v3         up       sleeper    1/1      0            2023-12-08T02:25:00UTC
+steely-mainsail-web-c4f44c4b4-7p7dh         v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+

!!! note +Only process types of web will be scaled to 1 automatically. If you have additional process types +remember to scale the process counts after creation.

+

To remove a process type simply scale it to 0:

+
$ drycc scale sleeper=0 -a steely-mainsail
+Scaling processes... but first, coffee!
+done in 3s
+
+NAME                                        RELEASE    STATE    PTYPE      READY    RESTARTS     STARTED
+steely-mainsail-web-c4f44c4b4-7p7dh         v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+

Scaling Processes

+

Applications deployed on Drycc Workflow scale out via the process model. Use drycc scale to control the number of +containers that power your app.

+
$ drycc scale web=5 -a iciest-waggoner
+Scaling processes... but first, coffee!
+done in 3s
+
+NAME                                        RELEASE    STATE    PTYPE      READY    RESTARTS     STARTED
+iciest-waggoner-web-c4f44c4b4-7p7dh         v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+iciest-waggoner-web-c4f44c4b4-8p7dh         v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+iciest-waggoner-web-c4f44c4b4-9p7dh         v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+iciest-waggoner-web-c4f44c4b4-1p7dh         v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+iciest-waggoner-web-c4f44c4b4-2p7dh         v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+

If you have multiple process types for your application you may scale the process count for each type separately. For +example, this allows you to manage web process independently from background workers. For more information on process +types see our documentation for Managing App Processes.

+

In this example, we are scaling the process type web to 5 but leaving the process type background with one worker.

+
$ drycc scale web=5
+Scaling processes... but first, coffee!
+done in 4s
+
+NAME                                                RELEASE    STATE    PTYPE      READY    RESTARTS     STARTED
+scenic-icehouse-web-3291896318-7lord                v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-jn957                v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-rsekj                v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-vwhnh                v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-vokg7                v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-vokg7                v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-background-3291896318-yf8kh         v3         up       web        1/1      0            2023-12-08T02:25:00UTC
+

Scaling a process down, by reducing the process count, sends a TERM signal to the processes, followed by a SIGKILL +if they have not exited within 30 seconds. Depending on your application, scaling down may interrupt long-running HTTP +client connections.

+

For example, scaling from 5 processes to 3:

+
$ drycc scale web=3
+Scaling processes... but first, coffee!
+done in 1s
+
+NAME                                                RELEASE    STATE    PTYPE     READY    RESTARTS     STARTED
+scenic-icehouse-web-3291896318-vwhnh                v2         up       web       1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-vokg7                v2         up       web       1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-vokg9                v2         up       web       1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-background-3291896318-yf8kh         v2         up       web       1/1      0            2023-12-08T02:25:00UTC
+

Autoscale

+

Autoscale allows adding a minimum and maximum number of pods on a per process type basis. This is accomplished by specifying a target CPU usage across all available pods.

+

This feature is built on top of Horizontal Pod Autoscaling in Kubernetes or HPA for short.

+

!!! note +This is an alpha feature. It is recommended to be on the latest Kubernetes when using this feature.

+
$ drycc autoscale:set web --min=3 --max=8 --cpu-percent=75
+Applying autoscale settings for process type web on scenic-icehouse... done
+

And then review the scaling rule that was created for web

+
$ drycc autoscale:list
+PTYPE    PERCENT    MIN    MAX
+web      75         3      8
+

Remove scaling rule

+
$ drycc autoscale:unset web
+Removing autoscale for process type web on scenic-icehouse... done
+

For autoscaling to work CPU requests have to be specified on each application Pod (can be done via drycc limits --cpu). This allows the autoscale policies to do the appropriate calculations and make decisions on when to scale up and down.

+

Scale up can only happen if there was no rescaling within the last 3 minutes. Scale down will wait for 5 minutes from the last rescaling. That information and more can be found at HPA algorithm page.

+

Fetch a container logs of the application

+

List the containers:

+
$ drycc ps
+NAME                                                RELEASE    STATE    PTYPEE     READY    RESTARTS     STARTED
+python-getting-started-web-69b7d4bfdc-kl4xf         v2         up       web        1/1      0             2023-12-08T02:25:00UTC
+
+=== python-getting-started Processes
+--- web:
+python-getting-started-web-69b7d4bfdc-kl4xf up (v2)
+

fetch the container logs:

+
$ drycc ps:logs -f python-getting-started-web-69b7d4bfdc-kl4xf
+[2024-05-24 07:14:39 +0000] [1] [INFO] Starting gunicorn 20.1.0
+[2024-05-24 07:14:39 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1)
+[2024-05-24 07:14:39 +0000] [1] [INFO] Using worker: gevent
+[2024-05-24 07:14:39 +0000] [8] [INFO] Booting worker with pid: 8
+[2024-05-24 07:14:39 +0000] [9] [INFO] Booting worker with pid: 9
+[2024-05-24 07:14:39 +0000] [10] [INFO] Booting worker with pid: 10
+[2024-05-24 07:14:39 +0000] [11] [INFO] Booting worker with pid: 11
+

Get a container info of the application

+

List the containers:

+
$ drycc ps:describe python-getting-started-web-69b7d4bfdc-kl4xf
+Container:        python-getting-started-web                   
+Image:            drycc/python-getting-started:latest          
+Command:          
+Args:             
+                  - gunicorn                                   
+                  - -c                                         
+                  - gunicorn_config.py                         
+                  - helloworld.wsgi:application                
+State:            running                                      
+  startedAt:      "2024-05-24T07:14:39Z"                       
+Ready:            true                                         
+Restart Count:    0                 
+

delete a container of the application

+

Delete the containers. +Due to the set number of replicas, a new container will be launched to meet the quantity requirement.

+
$ drycc ps:delete python-getting-started-web-69b7d4bfdc-kl4xf
+Deleting python-getting-started-web-69b7d4bfdc-kl4xf from python-getting-started... done
+

Get a Shell to a Running Container

+

Verify that the container is running:

+
$ drycc ps
+NAME                                                RELEASE    STATE    PTYPEE     READY    RESTARTS     STARTED
+python-getting-started-web-69b7d4bfdc-kl4xf         v2         up       web        1/1      0             2023-12-08T02:25:00UTC
+
+=== python-getting-started Processes
+--- web:
+python-getting-started-web-69b7d4bfdc-kl4xf up (v2)
+

Get a shell to the running container:

+
$ drycc ps:exec python-getting-started-web-69b7d4bfdc-kl4xf -it -- bash
+

In your shell, list the root directory:

+
# Run this inside the container
+ls /
+

Running individual commands in a container

+
$ drycc ps:exec python-getting-started-web-69b7d4bfdc-kl4xf -- date
+

Use “drycc ps –help” for a list of global command-line (applies to all commands).

+

Restarting an Application Processes

+

If you need to restart an application process, you may use drycc pts:restart. Behind the scenes, Drycc Workflow instructs +Kubernetes to terminate the old process and launch a new one in its place.

+
$ drycc ps
+NAME                                               RELEASE    STATE       PTYPE      READY    RESTARTS     STARTED
+scenic-icehouse-web-3291896318-vokg7               v2         up          web        1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-rsekj               v2         up          web        1/1      0            2023-12-08T02:50:21UTC
+scenic-icehouse-web-3291896318-vokg7               v2         up          web        1/1      0            2023-12-08T02:25:00UTC
+scenic-icehouse-background-3291896318-yf8kh        v2         up          web        1/1      0            2023-12-08T02:25:00UTC
+
+$ drycc pts:restart scenic-icehouse-background
+NAME                                               RELEASE    STATE       PTYPE      READY    RESTARTS    STARTED
+scenic-icehouse-web-3291896318-vokg7               v2         up          web        1/1      0           2023-12-08T02:25:00UTC
+scenic-icehouse-web-3291896318-rsekj               v2         up          web        1/1      0           2023-12-08T02:50:21UTC
+scenic-icehouse-web-3291896318-vokg7               v2         up          web        1/1      0           2023-12-08T02:25:00UTC
+scenic-icehouse-background-3291896318-yf8kh        v2         starting    web        1/1      0           2023-12-08T02:25:00UTC
+

Notice that the process name has changed from scenic-icehouse-background-3291896318-yf8kh to +scenic-icehouse-background-3291896318-yd87g. In a multi-node Kubernetes cluster, this may also have the effect of scheduling +the Pod to a new node.

+

Use “drycc pts –help” for a list of pts command-line (process types info).

+

List an Application Process Types

+
$ drycc pts
+NAME          RELEASE    READY    UP-TO-DATE    AVAILABLE    STARTED                   
+web           v2         3/3      1             1            2023-12-08T02:25:00UTC    
+background    v2         1/1      1             1            2023-12-08T02:25:00UTC    
+

Get deployment info of the application process type

+
$ drycc pts:describe web
+Container:    python-getting-started-web                   
+Image:        drycc/python-getting-started:latest          
+Command:      
+Args:         
+              - gunicorn                                   
+              - -c                                         
+              - gunicorn_config.py                         
+              - helloworld.wsgi:application                
+Limits:       
+              cpu 1                                                                                               
+              ephemeral-storage 2Gi                                                                               
+              memory 1Gi                                                                                          
+Liveness:     http-get headers=[] path=/geo/ port=8000 delay=120s timeout=10s period=20s #success=1 #failure=3    
+Readiness:    http-get headers=[] path=/geo/ port=8000 delay=120s timeout=10s period=20s #success=1 #failure=3  
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/applications/managing-app-resources/index.html b/docs/applications/managing-app-resources/index.html new file mode 100644 index 000000000..5cf487e4b --- /dev/null +++ b/docs/applications/managing-app-resources/index.html @@ -0,0 +1,567 @@ + + + + + + + + + + + + + + + + + + + +Managing resources for an Application | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Managing resources for an Application

+
Tools and services for developing, extending, and operating your app.
+ +

We can use blow command to create resources and bind which resource is created. +This command depend on service-catalog.

+

Use drycc resources to create and bind a resource for a deployed application.

+
$ drycc help resources
+
+Valid commands for resources:
+
+resources:services         list all available resource services
+resources:plans            list all available plans for an resource services
+resources:create           create a resource for the application
+resources:list             list resources in the application
+resources:describe         get a resource detail info in the application
+resources:update           update a resource from the application
+resources:destroy          delete a resource from the applicationa
+resources:bind             bind a resource to servicebroker
+resources:unbind           unbind a resource from servicebroker
+
+Use 'drycc help [command]' to learn more.
+
+

List all available resource services

+

You can list available resource services with one drycc resources:services command

+
$ drycc resources:services
+ID                                      NAME                  UPDATEABLE 
+15032a52-33c2-4b40-97aa-ceb972f51509    airflow               true          
+b7cb26a4-b258-445c-860b-a664239a67f8    cloudbeaver           true          
+9ce3c3ba-33b5-4e4e-a5e9-a338a83d5070    flink                 true          
+b80c51a1-957c-4d93-b3d5-efde84cd8031    fluentbit             true          
+fff5b6c7-ed85-429b-8265-493e40cc53c7    grafana               true          
+412e368f-bf78-4798-92cc-43343119a57d    kafka                 true          
+ea2a9b87-fbc4-4e2a-adee-161c1f91d98d    minio                 true          
+383f7316-84f3-4955-8491-1d4b02b749c8    mongodb               true          
+fbee746b-f3a7-4bef-8b55-cbecfd4c8ac3    mysql-cluster         true          
+5975094d-45cc-4e85-8573-f93937d026c7    opensearch            true          
+1db95161-7193-4544-8c76-e5ad5f6c03f6    pmm                   true          
+5cfb0abf-276c-445b-9060-9aa964ede87d    postgresql-cluster    true          
+b8f70264-eafc-4b2f-848e-2ec0d059032b    prometheus            true          
+f8186d36-f334-4094-8e02-d21a61da657b    rabbitmq              true          
+e1fd0d37-9046-4152-a29b-d155c5657c8b    redis                 true          
+7d2b64c6-0b59-4f08-a2f5-7b17cea6e5ee    redis-cluster         true          
+2e6877df-86e7-4bcc-a869-2a9b6847a465    seaweedfs             true          
+4aea5c0f-9495-420d-896a-ffc61a3eced5    spark                 true          
+b50db3b5-8d5f-4be9-b8bd-467ecd6cc11d    zookeeper             true
+
+

List all available plans for an resource services

+

You can list all available plans for an resource services with one drycc resources:plans command

+
$ drycc resources:plans redis
+ID                                      NAME              DESCRIPTION                                                       
+8d659058-a3b4-4058-b039-cc03a31b9442    standard-128      Redis standard-128 plan which limit resources memory size 128Mi.     
+36e3dbec-fc51-4f6b-9baa-e31e316858be    standard-256      Redis standard-256 plan which limit resources memory size 256Mi.     
+560817c2-5aa1-41c4-9ee6-a77e3ee552d5    standard-512      Redis standard-512 plan which limit resources memory size 512Mi.     
+d544d989-9fb8-43e9-a74e-0840ce1b8f0f    standard-1024     Redis standard-1024 plan which limit resources memory size 1Gi.      
+ad51b7bb-9b12-4ffd-8e49-010c0141b263    standard-2048     Redis standard-2048 plan which limit resources memory size 2Gi.      
+5097d76e-557c-453f-bdb1-54009e0df78d    standard-4096     Redis standard-4096 plan which limit resources memory size 4Gi.      
+be3fa2d0-36d2-47c5-9561-9deffe5ba373    standard-8192     Redis standard-8192 plan which limit resources memory size 8Gi.      
+4ca812a8-d7c3-439f-96cd-26523e88400e    standard-16384    Redis standard-16384 plan which limit resources memory size 16Gi.    
+b7f2a71f-0d97-48fd-8eed-aab24a7822f3    standard-32768    Redis standard-32768 plan which limit resources memory size 32Gi.    
+25c6b5d5-7505-47c8-95b1-dc9bdc698063    standard-65536    Redis standard-65536 plan which limit resources memory size 64Gi.
+
+

Create resource in application

+

You can create a resource with one drycc resources:create command

+
$ drycc resources:create redis:1000 redis
+Creating redis to scenic-icehouse... done
+
+

After resources are created, you can list the resources in this application.

+
$ drycc resources:list
+UUID                                    NAME     OWNER    PLAN                  UPDATED              
+07220e9e-d54d-4d74-a88c-f464aa374386    redis    admin    redis:standard-128    2024-05-08T01:01:00Z   
+
+

Bind resources

+

The resource which is named redis is created, you can bind the redis to the application, +use the command of drycc resources:bind redis.

+
$ drycc resources:bind redis
+Binding resource... done
+
+

Describe resources

+

And use drycc resources:describe show the binding detail. If the binding is successful, this command will show the information of connect to the resource.

+
$ drycc resources:describe redis
+=== scenic-icehouse resource redis
+plan:               redis:1000
+status:             Ready
+binding:            Ready
+
+REDISPORT:          6379
+REDIS_PASSWORD:     RzG87SJWG1
+SENTINELHOST:       172.16.0.2
+SENTINELPORT:       26379
+
+

Update resources

+

You can use the drycc resources:update command to upgrade a new plan. +An example of how to upgrade the plan’s capacity to 100MB:

+
$ drycc resources:update redis:10000 redis
+Updating redis to scenic-icehouse... done
+
+

Remove the resource

+

If you don’t need resources, use drycc resources:unbind to unbind the resource and then use drycc resources:destroy to delete the resource from the application. +Before deleting the resource, the resource must be unbinded.

+
$ drycc resources:unbind redis
+Unbinding resource... done
+
+$ drycc resources:destroy redis
+Deleting redis from scenic-icehouse... done
+
+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/applications/managing-app-volumes/index.html b/docs/applications/managing-app-volumes/index.html new file mode 100644 index 000000000..4413a6683 --- /dev/null +++ b/docs/applications/managing-app-volumes/index.html @@ -0,0 +1,527 @@ + + + + + + + + + + + + + + + + + + + +Mounting volumes for an Application | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Mounting volumes for an Application

+
Drycc supports many types of volumes. A container can use any number of volume types simultaneously.
+ +

We can use the blow command to create volumes and mount the created volumes. +Drycc create volume support ReadWriteMany, so before deploying drycc, you need to have a StorageClass ready which can support ReadWriteMany. +Deploying drycc, set controller.appStorageClass to this StorageClass.

+

Use drycc volumes to mount a volume for a deployed application’s processes.

+
$ drycc help volumes
+Valid commands for volumes:
+
+volumes:create           create a volume for the application
+volumes:list             list volumes in the application
+volumes:delete           delete a volume from the application
+volumes:client           the client used to manage volume files
+volumes:mount            mount a volume to process of the application
+volumes:unmount          unmount a volume from process of the application
+
+Use 'drycc help [command]' to learn more.
+
+

Create a volume for the application

+

You can create a csi volume with the drycc volumes:create command.

+
$ drycc volumes:create myvolume 200M
+Creating myvolumes to scenic-icehouse... done
+
+

Or use an existing nfs server

+
$ drycc volumes:create myvolume 200M -t nfs --nfs-server=nfs.drycc.com --nfs-path=/
+Creating myvolumes to scenic-icehouse... done
+
+

List volumes in the application

+

After volume is created, you can list the volumes in this application.

+
$ drycc volumes:list
+=== scenic-icehouse volumes
+--- myvolumes     200M
+
+

Mount a volume

+

The volume which is named myvolumes is created, you can mount the volume with process of the application, +use the command of drycc volumes:mount. When volume is mounted, a new release will be created and deployed automatically.

+
$ drycc volumes:mount myvolumes web=/data/web
+Mounting volume... done
+
+

And use drycc volumes:list show mount detail.

+
$ drycc volumes:list
+=== scenic-icehouse volumes
+--- myvolumes     200M
+web               /data/web
+
+

If you don’t need the volume, use drycc volumes:unmount to unmount the volume and then use drycc volumes:delete to delete the volume from the application. +Before deleting volume, the volume has to be unmounted.

+
$ drycc volumes:unmount myvolumes web
+Unmounting volume... done
+
+$ drycc volumes:delete myvolumes
+Deleting myvolumes from scenic-icehouse... done
+
+

Use volume client to manage volume files.

+

Assume the volume which is named myvolumes is created and mounted.

+

Prepare a file named testfile.

+
$ echo "testtext" > testfile
+
+

Upload. +$ drycc volumes:client cp testfile vol://myvolume/ +[↑] testfile 100% [==================================================] (5/ 5 B, 355 B/s)

+

List files in myvolume.

+
$ drycc volumes:client ls vol://myvolume/
+[2024-07-22T15:32:28+08:00]    5    testfile
+
+

Delete testfle in myvolume.

+
$ drycc volumes:client rm vol://myvolume/testfile
+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/applications/managing-resource-limits/index.html b/docs/applications/managing-resource-limits/index.html new file mode 100644 index 000000000..56b621117 --- /dev/null +++ b/docs/applications/managing-resource-limits/index.html @@ -0,0 +1,484 @@ + + + + + + + + + + + + + + + + + + + +Resource Limits | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Resource Limits

+
Drycc Workflow supports restricting memory and CPU shares of each process.
+ +

+

Managing Application Resource Limits

+

Drycc Workflow supports restricting memory and CPU shares of each process. Requests/Limits set on a per-process type are given to +Kubernetes as a requests and limits. Which means you guarantee <requests> amount of resource for a process as well as limit +the process from using more than <limits>. +By default, Kubernetes will set <requests> equal to <limit> if we don’t explicitly set <requests> value. Please keep in mind that 0 <= requests <= limits.

+

Limiting

+

If you set a requests/limits that is out of range for your cluster, Kubernetes will be unable to schedule your application +processes into the cluster!

+
$ drycc limits:plans
+
+ID                    SPEC    CPU              VCPUS    MEMORY     FEATURES                      
+std1.large.c1m1       std1    Universal CPU    1        1 GiB      Integrated GPU shared    
+std1.large.c1m2       std1    Universal CPU    1        2 GiB      Integrated GPU shared    
+std1.large.c1m4       std1    Universal CPU    1        4 GiB      Integrated GPU shared    
+std1.large.c1m8       std1    Universal CPU    1        8 GiB      Integrated GPU shared    
+std1.large.c2m2       std1    Universal CPU    2        2 GiB      Integrated GPU shared    
+std1.large.c2m4       std1    Universal CPU    2        4 GiB      Integrated GPU shared    
+std1.large.c2m8       std1    Universal CPU    2        8 GiB      Integrated GPU shared    
+std1.large.c2m16      std1    Universal CPU    2        16 GiB     Integrated GPU shared    
+
+$ drycc limits:set web=std1.large.c1m1
+Applying limits... done
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/applications/ssl-certificates/index.html b/docs/applications/ssl-certificates/index.html new file mode 100644 index 000000000..7301d0300 --- /dev/null +++ b/docs/applications/ssl-certificates/index.html @@ -0,0 +1,618 @@ + + + + + + + + + + + + + + + + + + + +Application SSL Certificates | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Application SSL Certificates

+
SSL is a cryptographic protocol that provides end-to-end encryption and integrity for all web requests.
+ +

Application SSL Certificates

+

SSL is a cryptographic protocol that provides end-to-end encryption and integrity for all web +requests. Apps that transmit sensitive data should enable SSL to ensure all information is +transmitted securely.

+

To enable SSL on a custom domain, e.g., www.example.com, use the SSL endpoint.

+

!!! note +drycc certs is only useful for custom domains. Default application domains are +SSL-enabled already and can be accessed simply by using https, +e.g. https://foo.dryccapp.com (provided that you have installed your wildcard +certificate on the routers or on the load balancer).

+

Overview

+

Because of the unique nature of SSL validation, provisioning SSL for your domain is a multi-step +process that involves several third-parties. You will need to:

+
    +
  1. Purchase an SSL certificate from your SSL provider
  2. +
  3. Upload the cert to Drycc
  4. +
+

Acquire SSL Certificate

+

Purchasing an SSL cert varies in cost and process depending on the vendor. RapidSSL offers a +simple way to purchase a certificate and is a recommended solution. If you’re able to use this +provider, see buy an SSL certificate with RapidSSL for instructions.

+

DNS and Domain Configuration

+

Once the SSL certificate is provisioned and your cert is confirmed, you must route requests for +your domain through Drycc. Unless you’ve already done so, add the domain specified when generating +the CSR to your app with:

+
$ drycc domains:add www.example.com --ptype==web -a foo
+Adding www.example.com to foo... done
+
+

Add a Certificate

+

Add your certificate, any intermediate certificates, and private key to the endpoint with the +certs:add command.

+
$ drycc certs:add example-com server.crt server.key -a foo
+Adding SSL endpoint... done
+www.example.com
+
+

!!! note +The name given to the certificate can only contain a-z (lowercase), 0-9 and hyphens

+

The Drycc platform will investigate the certificate and extract any relevant information from it +such as the Common Name, Subject Alt Names (SAN), fingerprint and more.

+

This allows for wildcard certificates and multiple domains in the SAN without uploading duplicates.

+

Add a Certificate Chain

+

Sometimes, your certificates (such as a self-signed or a cheap certificate) need additional +certificates to establish the chain of trust. What you need to do is bundle all the certificates +into one file and give that to Drycc. Importantly, your site’s certificate must be the first one:

+
$ cat server.crt server.ca > server.bundle
+
+

After that, you can add them to Drycc with the certs:add command:

+
$ drycc certs:add example-com server.bundle server.key -a foo
+Adding SSL endpoint... done
+www.example.com
+
+

Attach SSL certificate to a domain

+

Certificates are not automagically connected up to domains, instead you will have to attach a +certificate to a domain

+
$ drycc certs:attach example-com example.com -a foo
+
+

Each certificate can be connected to many domains. There is no need to upload duplicates.

+

To remove an association

+
$ drycc certs:detach example-com example.com -a foo
+
+

Endpoint overview

+

You can verify the details of your domain’s SSL configuration with drycc certs.

+
$ drycc certs
+
+     Name     |    Common Name    | SubjectAltName    |         Expires         |   Fingerprint   |   Domains    |   Updated   |   Created
++-------------+-------------------+-------------------+-------------------------+-----------------+--------------+-------------+-------------+
+  example-com |     example.com   | blog.example.com  | 31 Dec 2017 (in 1 year) | 8F:8E[...]CD:EB |  example.com | 30 Jan 2016 | 29 Jan 2016
+
+

or by looking at at each certificates detailed information

+
$ drycc certs:info example-com -a foo
+
+=== bar-com Certificate
+Common Name(s):     example.com
+Expires At:         2017-01-14 23:57:57 +0000 UTC
+Starts At:          2016-01-15 23:57:57 +0000 UTC
+Fingerprint:        7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0
+Subject Alt Name:   blog.example.com
+Issuer:             /C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=example.com/emailAddress=engineering@drycc.cc
+Subject:            /C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=example.com/emailAddress=engineering@drycc.cc
+
+Connected Domains:  example.com
+Owner:              admin-user
+Created:            2016-01-28 19:07:41 +0000 UTC
+Updated:            2016-01-30 00:10:02 +0000 UTC
+
+

Testing SSL

+

Use a command line utility like curl to test that everything is configured correctly for your +secure domain.

+

!!! note +The -k option flag tells curl to ignore untrusted certificates.

+

Pay attention to the output. It should print SSL certificate verify ok. If it prints something +like common name: www.example.com (does not match 'www.somedomain.com') then something is not +configured correctly.

+

Enforcing SSL at the Router

+

To enforce all HTTP requests be redirected to HTTPS, TLS can be enforced at the router level by +running

+
$ drycc tls:force:enable -a foo
+Enabling https-only requests for foo... done
+
+

Users hitting the HTTP endpoint for the application will now receive a 301 redirect to the HTTPS +endpoint.

+

To disable enforced TLS, run

+
$ drycc tls:force:disable -a foo
+Disabling https-only requests for foo... done
+
+

Automated Certificate Management

+

With Automated Certificate Management (ACM), Drycc automatically manages TLS certificates for apps with Hobby and Professional dynos on the Common Runtime, and for apps in Private Spaces that enable the feature. +Certificates handled by ACM automatically renew one month before they expire, and new certificates are created automatically whenever you add or remove a custom domain. All applications with paid dynos include ACM for free. +Automated Certificate Management uses Let’s Encrypt, the free, automated, and open certificate authority for managing your application’s TLS certificates. Let’s Encrypt is run for the public benefit by the Internet Security Research Group (ISRG).

+

To enable ACM with the following command: +$ drycc tls:auto:enable -a foo

+

To disable ACM with the following command: +$ drycc tls:auto:disable -a foo

+

Remove Certificate

+

You can remove a certificate using the certs:remove command:

+
$ drycc certs:remove my-cert -a foo
+Removing www.example.com... Done.
+
+

Swapping out certificates

+

Over the lifetime of an application an operator will have to acquire certificates with new expire +dates and apply it to all relevant applications, below is the recommended way to swap out certificates.

+

Be intentional with certificate names, name them example-com-2017 when possible, where the year +signifies the expiry year. This allows for example-com-2018 when a new certificate is purchased.

+

Assuming all applications are already using example-com-2017 the following commands can be ran, +chained together or otherwise:

+
$ drycc certs:detach example-com-2017 example.com -a foo
+$ drycc certs:attach example-com-2018 example.com -a foo
+
+

This will take care of a singular domain which allows the operator to verify everything went +as planned and slowly roll it out to any other application using the same method.

+

Troubleshooting

+

Here are some steps you can follow if your SSL endpoint is not working as you’d expect.

+

Untrusted Certificate

+

In some cases when accessing the SSL endpoint, it may list your certificate as untrusted.

+

If this occurs, it may be because it is not trusted by Mozilla’s list of root CAs. If this is +the case, your certificate may be considered untrusted for many browsers.

+

If you have uploaded a certificate that was signed by a root authority but you get the message that +it is not trusted, then something is wrong with the certificate. For example, it may be missing +intermediary certificates. If so, download the intermediary certificates from your SSL provider, +remove the certificate from Drycc and re-run the certs:add command.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/applications/using-buildpacks/index.html b/docs/applications/using-buildpacks/index.html new file mode 100644 index 000000000..9d2b419f9 --- /dev/null +++ b/docs/applications/using-buildpacks/index.html @@ -0,0 +1,600 @@ + + + + + + + + + + + + + + + + + + + +Using Buildpacks | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Using Buildpacks

+
An overview of buildpacks, which are responsible for transforming deployed code into a slug, which can then be executed on a container.
+ +

Drycc supports deploying applications via Cloud Native Buildpacks. Cloud Native Buildpacks are useful if you want to follow cnb’s docs for building applications.

+

Add SSH Key

+

For Buildpack based application deploys via git push, Drycc Workflow identifies users via SSH keys. SSH keys are pushed to the platform and must be unique to each user.

+
    +
  • +

    See this document for instructions on how to generate an SSH key.

    +
  • +
  • +

    Run drycc keys:add to upload your SSH key to Drycc Workflow.

    +
  • +
+
$ drycc keys:add ~/.ssh/id_drycc.pub
+Uploading id_drycc.pub to drycc... done
+

Read more about adding/removing SSH Keys here.

+

Prepare an Application

+

If you do not have an existing application, you can clone an example application that demonstrates the Heroku Buildpack workflow.

+
$ git clone https://github.com/drycc/example-go.git
+$ cd example-go
+
+

Create an Application

+

Use drycc create to create an application on the Controller.

+
$ drycc create
+Creating application... done, created skiing-keypunch
+Git remote drycc added
+
+

Push to Deploy

+

Use git push drycc master to deploy your application.

+
$ git push drycc master
+Counting objects: 75, done.
+Delta compression using up to 8 threads.
+Compressing objects: 100% (48/48), done.
+Writing objects: 100% (75/75), 18.28 KiB | 0 bytes/s, done.
+Total 75 (delta 30), reused 58 (delta 22)
+remote: --->
+Starting build... but first, coffee!
+---> Waiting podman running.
+---> Process podman started.
+---> Waiting caddy running.
+---> Process caddy started.
+---> Building pack
+---> Using builder registry.drycc.cc/drycc/buildpacks:bookworm
+Builder 'registry.drycc.cc/drycc/buildpacks:bookworm' is trusted
+Pulling image 'registry.drycc.cc/drycc/buildpacks:bookworm'
+Resolving "drycc/buildpacks" using unqualified-search registries (/etc/containers/registries.conf)
+Trying to pull registry.drycc.cc/drycc/buildpacks:bookworm...
+Getting image source signatures
+...
+---> Skip generate base layer
+---> Python Buildpack
+---> Downloading and extracting Python 3.10.0
+---> Installing requirements with pip
+Collecting Django==3.2.8
+Downloading Django-3.2.8-py3-none-any.whl (7.9 MB)
+Collecting gunicorn==20.1.0
+Downloading gunicorn-20.1.0-py3-none-any.whl (79 kB)
+Collecting sqlparse>=0.2.2
+Downloading sqlparse-0.4.2-py3-none-any.whl (42 kB)
+Collecting pytz
+Downloading pytz-2021.3-py2.py3-none-any.whl (503 kB)
+Collecting asgiref<4,>=3.3.2
+Downloading asgiref-3.4.1-py3-none-any.whl (25 kB)
+Requirement already satisfied: setuptools>=3.0 in /layers/drycc_python/python/lib/python3.10/site-packages (from gunicorn==20.1.0->-r requirements.txt (line 2)) (57.5.0)
+Installing collected packages: sqlparse, pytz, asgiref, gunicorn, Django
+Successfully installed Django-3.2.8 asgiref-3.4.1 gunicorn-20.1.0 pytz-2021.3 sqlparse-0.4.2
+---> Generate Launcher
+...
+Build complete.
+Launching App...
+...
+Done, skiing-keypunch:v2 deployed to Workflow
+
+Use 'drycc open' to view this application in your browser
+
+To learn more, use 'drycc help' or visit https://www.drycc.cc
+
+To ssh://git@drycc.staging-2.drycc.cc:2222/skiing-keypunch.git
+ * [new branch]      master -> master
+
+$ curl -s http://skiing-keypunch.example.com
+Powered by Drycc
+Release v2 on skiing-keypunch-v2-web-02zb9
+
+

Because a Buildpacks-style application is detected, the web process type is automatically scaled to 1 on first deploy.

+

Use drycc scale web=3 to increase web processes to 3, for example. Scaling a +process type directly changes the number of pods running that process.

+

Included Buildpacks

+

For convenience, a number of buildpacks come bundled with Drycc:

+ +

Drycc will cycle through the bin/detect script of each buildpack to match the code you +are pushing.

+

!!! note +If you’re testing against the [Scala Buildpack][], the Builder requires at least +512MB of free memory to execute the Scala Build Tool.

+

Using a Custom Buildpack

+

To use a custom buildpack, you need create a .pack_builder file in your root path app.

+
$  tee > .pack_builder << EOF
+   > registry.drycc.cc/drycc/buildpacks:bookworm
+   > EOF
+
+

On your next git push, the custom buildpack will be used.

+

Using Private Repositories

+

To pull code from private repositories, set the SSH_KEY environment variable to a private key +which has access. Use either the path of a private key file or the raw key material:

+
$ drycc config:set SSH_KEY=/home/user/.ssh/id_rsa
+$ drycc config:set SSH_KEY="""-----BEGIN RSA PRIVATE KEY-----
+(...)
+-----END RSA PRIVATE KEY-----"""
+
+

For example, to use a custom buildpack hosted at a private GitHub URL, ensure that an SSH public +key exists in your GitHub settings. Then set SSH_KEY to the corresponding SSH private key +and set .pack_builder to the builder image:

+
$  tee > .pack_builder << EOF
+   > registry.drycc.cc/drycc/buildpacks:bookworm
+   > EOF
+$ git add .buildpack
+$ git commit -m "chore(buildpack): modify the pack_builder"
+$ git push drycc master
+
+

Builder selector

+

Which way to build a project conforms to the following principles:

+
    +
  • If Dockerfile exists in the project, the stack uses container
  • +
  • If Procfile exists in the project, the stack uses buildpack
  • +
  • If both exist, container is used by default
  • +
  • You can also set the DRYCC_STACK to container or buildpack determine which stack to use.
  • +
+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/applications/using-container-images/index.html b/docs/applications/using-container-images/index.html new file mode 100644 index 000000000..c536734f9 --- /dev/null +++ b/docs/applications/using-container-images/index.html @@ -0,0 +1,530 @@ + + + + + + + + + + + + + + + + + + + +Using Docker Images | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Using Docker Images

+
Deploy an application using a container image stored in your Drycc Container Registry.
+ +

Drycc supports deploying applications via an existing Docker Image. +This is useful for integrating Drycc into Docker-based CI/CD pipelines.

+

Prepare an Application

+

Start by cloning an example application:

+
$ git clone https://github.com/drycc/example-dockerfile-http.git
+$ cd example-dockerfile-http
+
+

Next use your local docker client to build the image and push +it to DockerHub.

+
$ docker build -t <username>/example-dockerfile-http .
+$ docker push <username>/example-dockerfile-http
+
+

Docker Image Requirements

+

In order to deploy Docker images, they must conform to the following requirements:

+
    +
  • The Dockerfile must use the EXPOSE directive to expose exactly one port.
  • +
  • That port must be listening for an HTTP connection.
  • +
  • The Dockerfile must use the CMD directive to define the default process that will run within the container.
  • +
  • The Docker image must contain bash to run processes.
  • +
+

!!! note +Note that if you are using a private registry of any kind (gcr or other) the application environment must include a $PORT config variable that matches the EXPOSE’d port, example: drycc config:set PORT=5000. See Configuring Registry for more info.

+

Create an Application

+

Use drycc create to create an application on the controller.

+
$ mkdir -p /tmp/example-dockerfile-http && cd /tmp/example-dockerfile-http
+$ drycc create example-dockerfile-http --no-remote
+Creating application... done, created example-dockerfile-http
+
+

!!! note +For all commands except for drycc create, the drycc client uses the name of the current directory +as the app name if you don’t specify it explicitly with --app.

+

Deploy the Application

+

Use drycc pull to deploy your application from DockerHub or +a public registry.

+
$ drycc pull <username>/example-dockerfile-http:latest
+Creating build...  done, v2
+
+$ curl -s http://example-dockerfile-http.local3.dryccapp.com
+Powered by Drycc
+
+

Because you are deploying a Docker image, the web process type is automatically scaled to 1 on first deploy.

+

Use drycc scale web=3 to increase web processes to 3, for example. Scaling a +process type directly changes the number of Containers +running that process.

+

Private Registry

+

To deploy Docker images from a private registry or from a private repository, use drycc registry +to attach credentials to your application. These credentials are the same as you’d use when running +docker login at your private registry.

+

To deploy private Docker images, take the following steps:

+
    +
  • Gather the username and password for the registry, such as a Quay.io Robot Account or a GCR.io Long Lived Token
  • +
  • Run drycc registry:set username=<the-user> password=<secret> -a <application-name>
  • +
  • Now perform drycc pull as normal, against an image in the private registry
  • +
+

When using a GCR.io Long Lived Token, the JSON blob will have to be compacted first using a +tool like jq and then used in the password field in drycc registry:set. For the username, use +_json_key. For example:

+
drycc registry:set username=_json_key password="$(cat google_cloud_cred.json | jq -c .)"
+

When using a private registry the docker images are no longer pulled into the Drycc Internal Registry via +the Drycc Workflow Controller but rather is managed by Kubernetes. This will increase security and overall speed, +however the application port information can no longer be discovered. Instead the application port information can be set via +drycc config:set PORT=80 prior to setting the registry information.

+

!!! note +Currently GCR.io and ECR in short lived auth token mode are not supported.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/applications/using-dockerfiles/index.html b/docs/applications/using-dockerfiles/index.html new file mode 100644 index 000000000..2a6be19d0 --- /dev/null +++ b/docs/applications/using-dockerfiles/index.html @@ -0,0 +1,582 @@ + + + + + + + + + + + + + + + + + + + +Using Dockerfiles | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Using Dockerfiles

+
Drycc Container Registry allows you to deploy your Docker-based app to Drycc. Both Common Runtime and Private Spaces are supported.
+ +

Drycc supports deploying applications via Dockerfiles. A Dockerfile automates the steps for crafting a [Container Image][]. +Dockerfiles are incredibly powerful but require some extra work to define your exact application runtime environment.

+

Add SSH Key

+

For Dockerfile based application deploys via git push, Drycc Workflow identifies users via SSH keys. SSH keys are pushed to the platform and must be unique to each user.

+
    +
  • +

    See this document for instructions on how to generate an SSH key.

    +
  • +
  • +

    Run drycc keys:add to upload your SSH key to Drycc Workflow.

    +
  • +
+
$ drycc keys:add ~/.ssh/id_drycc.pub
+Uploading id_drycc.pub to drycc... done
+

Read more about adding/removing SSH Keys here.

+

Prepare an Application

+

If you do not have an existing application, you can clone an example application that demonstrates the Dockerfile workflow.

+
$ git clone https://github.com/drycc/helloworld.git
+$ cd helloworld
+
+

Dockerfile Requirements

+

In order to deploy Dockerfile applications, they must conform to the following requirements:

+
    +
  • The Dockerfile must use the EXPOSE directive to expose exactly one port.
  • +
  • That port must be listening for an HTTP connection.
  • +
  • The Dockerfile must use the CMD directive to define the default process that will run within the container.
  • +
  • The Container image must contain bash to run processes.
  • +
+

!!! note +Note that if you are using a private registry of any kind (gcr or other) the application environment must include a $PORT config variable that matches the EXPOSE’d port, example: drycc config:set PORT=5000. See Configuring Registry for more info.

+

Create an Application

+

Use drycc create to create an application on the Controller.

+
$ drycc create
+Creating application... done, created folksy-offshoot
+Git remote drycc added
+
+

Push to Deploy

+

Use git push drycc master to deploy your application.

+
$ git push drycc master
+Counting objects: 13, done.
+Delta compression using up to 8 threads.
+Compressing objects: 100% (13/13), done.
+Writing objects: 100% (13/13), 1.99 KiB | 0 bytes/s, done.
+Total 13 (delta 2), reused 0 (delta 0)
+-----> Building Docker image
+Uploading context 4.096 kB
+Uploading context
+Step 0 : FROM drycc/base:latest
+ ---> 60024338bc63
+Step 1 : RUN wget -O /tmp/go1.2.1.linux-amd64.tar.gz -q https://go.googlecode.com/files/go1.2.1.linux-amd64.tar.gz
+ ---> Using cache
+ ---> cf9ef8c5caa7
+Step 2 : RUN tar -C /usr/local -xzf /tmp/go1.2.1.linux-amd64.tar.gz
+ ---> Using cache
+ ---> 515b1faf3bd8
+Step 3 : RUN mkdir -p /go
+ ---> Using cache
+ ---> ebf4927a00e9
+Step 4 : ENV GOPATH /go
+ ---> Using cache
+ ---> c6a276eded37
+Step 5 : ENV PATH /usr/local/go/bin:/go/bin:$PATH
+ ---> Using cache
+ ---> 2ba6f6c9f108
+Step 6 : ADD . /go/src/github.com/drycc/helloworld
+ ---> 94ab7f4b977b
+Removing intermediate container 171b7d9fdb34
+Step 7 : RUN cd /go/src/github.com/drycc/helloworld && go install -v .
+ ---> Running in 0c8fbb2d2812
+github.com/drycc/helloworld
+ ---> 13b5af931393
+Removing intermediate container 0c8fbb2d2812
+Step 8 : ENV PORT 80
+ ---> Running in 9b07da36a272
+ ---> 2dce83167874
+Removing intermediate container 9b07da36a272
+Step 9 : CMD ["/go/bin/helloworld"]
+ ---> Running in f7b215199940
+ ---> b1e55ce5195a
+Removing intermediate container f7b215199940
+Step 10 : EXPOSE 80
+ ---> Running in 7eb8ec45dcb0
+ ---> ea1a8cc93ca3
+Removing intermediate container 7eb8ec45dcb0
+Successfully built ea1a8cc93ca3
+-----> Pushing image to private registry
+
+       Launching... done, v2
+
+-----> folksy-offshoot deployed to Drycc
+       http://folksy-offshoot.local3.dryccapp.com
+
+       To learn more, use `drycc help` or visit https://www.drycc.cc
+
+To ssh://git@local3.dryccapp.com:2222/folksy-offshoot.git
+ * [new branch]      master -> master
+
+$ curl -s http://folksy-offshoot.local3.dryccapp.com
+Welcome to Drycc!
+See the documentation at http://docs.drycc.cc/ for more information.
+
+

Because a Dockerfile application is detected, the web process type is automatically scaled to 1 on first deploy.

+

Use drycc scale web=3 to increase web processes to 3, for example. Scaling a +process type directly changes the number of containers +running that process.

+

Container Build Arguments

+

As of Workflow v2.13.0, users can inject their application config into the Container image using +Container build arguments. To opt into this, users must add a new environment variable +to their application:

+
$ drycc config:set DRYCC_DOCKER_BUILD_ARGS_ENABLED=1
+

Every environment variable set with drycc config:set will then be available for use inside the +user’s Dockerfile. For example, if a user runs drycc config:set POWERED_BY=Workflow, +the user can utilize that build argument in their Dockerfile:

+
ARG POWERED_BY
+RUN echo "Powered by $POWERED_BY" > /etc/motd
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/applications/using-dryccfile/index.html b/docs/applications/using-dryccfile/index.html new file mode 100644 index 000000000..b12da0432 --- /dev/null +++ b/docs/applications/using-dryccfile/index.html @@ -0,0 +1,509 @@ + + + + + + + + + + + + + + + + + + + +Using drycc.yaml | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Using drycc.yaml

+
Drycc Container Registry allows you to deploy your Docker-based app to Drycc. Both Common Runtime and Private Spaces are supported.
+ +

The Drycc stack is intended for advanced use cases only. Unless you have a specific need for custom Docker images, we recommend using Drycc’s default buildpack-powered build system. It offers automatic base image security updates and language-specific optimizations. It also avoids the need to maintain a .containerDockerfile

+

drycc.yaml Overview

+

A manifest has three top-level sections.

+
    +
  • build – Specifies the to build Dockerfile
  • +
  • run – Specifies the release phase tasks to execute
  • +
  • deploy – Specifies process types and the commands to run for each type
  • +
+

Here’s an example that illustrates using a manifest to build Docker images.

+
build:
+  docker:
+    web: Dockerfile
+    worker: worker/Dockerfile
+  config:
+    web:
+      FOO: bar
+    worker:
+      RAILS_ENV: development
+run:
+- command:
+  - ./deployment-tasks.sh
+  image: worker
+  # If the field is empty, it means it will be executed forever
+  when:
+    ptypes:
+    - web
+    - webbbsbs
+  # Maximum execution time
+  timeout: 100
+deploy:
+  web:
+    command:
+    - bash
+    - -ec
+    args:
+    - bundle exec puma -C config/puma.rb
+  worker:
+    command:
+    - bash
+    - -ec
+    args:
+    - python myworker.py
+  asset-syncer:
+    command:
+    - bash
+    - -ec
+    args:
+    - python asset-syncer.py
+    image: worker
+

For more deployment information, please refer to the drycc examples.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/contribution-guidelines/_print/index.html b/docs/contribution-guidelines/_print/index.html new file mode 100644 index 000000000..67900ffa3 --- /dev/null +++ b/docs/contribution-guidelines/_print/index.html @@ -0,0 +1,838 @@ + + + + + + + + + + + + + + + + + + + + + +Contribution Guidelines | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+ + + + + +
+
+

+This is the multi-page printable view of this section. +Click here to print. +

+Return to the regular view of this page. +

+
+ + + +

Contribution Guidelines

+
This HowTo is for project maintainers who need a Contributing Guide for their project.
+ + + + + + + +
+ +
+
+ + + + + + + + + + + + + + + + +
+ +

1 - Contributor Overview

+
Interested in contributing to a Drycc project? There are lots of ways to help.
+

File Bugs & Enhancements

+

Find a bug? Want to see a new feature? Have a request for the maintainers? Open a Github issue in the applicable repository and we’ll get the conversation started.

+

Our official support channel is the Drycc #community Slack channel.

+

Don’t know what the applicable repository for an issue is? Open up in issue in workflow or chat with a maintainer in the Drycc #community Slack channel and we’ll make sure it gets to the right place.

+

Additionally, take a look at the troubleshooting documentation for common issues.

+

Before opening a new issue, it’s helpful to search and see if anyone else has already reported the problem. You can search through a list of issues for all Drycc projects here.

+

Write Documentation

+

We are always looking to improve and expand our documentation. Most docs reside in the drycc/workflow repository. Simply fork the project, update docs and send us a pull request.

+

Contribute Code

+

We are always looking for help improving the core platform, other workloads, tooling, and test coverage. Interested in contributing code? Let’s chat in the Drycc #community Slack channel. Make sure to check out issues tagged easy fix or help wanted.

+

When you’re ready to begin writing code, review Design Documents and get your Development Environment set up.

+

By contributing to any Drycc project you agree to its Developer Certificate of Origin (DCO). This document was created by the Linux Kernel community and is a simple statement that you, as a contributor, have the legal right to make the contribution.

+

Triage Issues

+

If you don’t have time to code, consider helping with triage. The community will thank you for saving them time by spending some of yours. See Triaging Issues for more info.

+

Share your Experience

+

Interact with the community on our user mailing list or live in our Drycc #community Slack channel, where you can chat with other Drycc Workflow users any time of day.

+ +
+ + + + + + + + + + + +
+ +

2 - Design Documents

+
Before submitting a pull request which will significantly alter the behavior of any Drycc component.
+

Before submitting a pull request which will significantly alter the behavior of any Drycc component, such as a new feature or major refactoring, contributors should first open an issue representing a design document.

+

Goals

+

Design documents help ensure project contributors:

+
    +
  • Involve stakeholders as early as possible in a feature’s development
  • +
  • Ensure code changes accomplish the original motivations and design goals
  • +
  • Establish clear acceptance criteria for a feature or change
  • +
  • Enforce test-driven design methodology and automated test coverage
  • +
+

Contents

+

Design document issues should be named Design Doc: <change description> and contain the following sections:

+

Goal

+

This section should briefly describe the proposed change and the motivations behind it. Tests will be written to ensure this design goal is met by the change.

+

This section should also reference a separate GitHub issue tracking the feature or change, which will typically be assigned to a release milestone.

+

Code Changes

+

This section should detail the code changes necessary to accomplish the change, as well as the proposed implementation. This should be as detailed as necessary to help reviewers understand the change.

+

Tests

+

All changes should be covered by automated tests, either unit or integration tests (ideally both). This section should detail how tests will be written to validate that the change accomplishes the design goals and doesn’t introduce any regressions.

+

If a change cannot be sufficiently covered by automated testing, the design should be reconsidered. If there is no test coverage whatsoever for an affected section of code, a separate issue should be filed to integrate automated testing with that section of the codebase.

+

The tests described here also form the acceptance criteria for the change, so that when it’s completed maintainers can merge the pull request after confirming the tests pass CI.

+

Approval

+

A design document follows the same merge approval review process as final pull requests do, and maintainers will take extra care to ensure that any stakeholders for the change are included in the discussion and review of the design document.

+

Once the design is accepted, the author can complete the change and submit a pull request for review. The pull request should close both the design document for the change as well as any issues that either track the issue or are closed as a result of the change.

+

See Submitting a Pull Request for more information on pull request and commit message formatting.

+ +
+ + + + + + + + + + + +
+ +

3 - Development Environment

+
This document is for developers who are interested in working directly on the Drycc codebase.
+

In this guide, we walk you through the process of setting up a development environment that is suitable for hacking on most Drycc components.

+

We try to make it simple to hack on Drycc components. However, there are necessarily several moving pieces and some setup required. We welcome any suggestions for automating or simplifying this process.

+

!!! note +The Drycc team is actively engaged in containerizing Go and Python based development environments tailored specifically for Drycc development in order to minimize the setup required. This work is ongoing. Refer to the drycc/router project for a working example of a fully containerized development environment.

+

If you’re just getting into the Drycc codebase, look for GitHub issues with the label easy-fix. These are more straightforward or low-risk issues and are a great way to become more familiar with Drycc.

+

Prerequisites

+

In order to successfully compile and test Drycc binaries and build Container images of Drycc components, the following are required:

+
    +
  • git
  • +
  • Go 1.5 or later, with support for compiling to linux/amd64
  • +
  • glide
  • +
  • golint
  • +
  • shellcheck
  • +
  • Podman (in a non-Linux environment, you will additionally want [Podman Machine][machine])
  • +
+

For drycc/controller, in particular, you will also need:

+
    +
  • Python 2.7 or later (with pip)
  • +
  • virtualenv (sudo pip install virtualenv)
  • +
+

In most cases, you should simply install according to the instructions. There are a few special cases, though. We cover these below.

+

Configuring Go

+

If your local workstation does not support the linux/amd64 target environment, you will have to install Go from source with cross-compile support for that environment. This is because some of the components are built on your local machine and then injected into a container.

+

Homebrew users can just install with cross compiling support:

+
$ brew install go --with-cc-common
+

It is also straightforward to build Go from source:

+
$ sudo su
+$ curl -sSL https://golang.org/dl/go1.5.src.tar.gz | tar -v -C /usr/local -xz
+$ cd /usr/local/go/src
+$ # compile Go for our default platform first, then add cross-compile support
+$ ./make.bash --no-clean
+$ GOOS=linux GOARCH=amd64 ./make.bash --no-clean
+

Once you can compile to linux/amd64, you should be able to compile Drycc components as normal.

+

Fork the Repository

+

Once the prerequisites have been met, we can begin to work with Drycc components.

+

Begin at Github by forking whichever Drycc project you would like to contribute to, then clone that fork locally. Since Drycc is predominantly written in Go, the best place to put it is under $GOPATH/src/github.com/drycc/.

+
$ mkdir -p  $GOPATH/src/github.com/drycc
+$ cd $GOPATH/src/github.com/drycc
+$ git clone git@github.com:<username>/<component>.git
+$ cd <component>
+

!!! note +By checking out the forked copy into the namespace github.com/drycc/<component>, we are tricking the Go toolchain into seeing our fork as the “official” source tree.

+

If you are going to be issuing pull requests to the upstream repository from which you forked, we suggest configuring Git such that you can easily rebase your code to the upstream repository’s main branch. There are various strategies for doing this, but the most common is to add an upstream remote:

+
$ git remote add upstream https://github.com/drycc/<component>.git
+

For the sake of simplicity, you may want to point an environment variable to your Drycc code - the directory containing one or more Drycc components:

+
$ export DRYCC=$GOPATH/src/github.com/drycc
+

Throughout the rest of this document, $DRYCC refers to that location.

+

Alternative: Forking with a Pushurl

+

A number of Drycc contributors prefer to pull directly from drycc/<component>, but push to <username>/<component>. If that workflow suits you better, you can set it up this way:

+
$ git clone git@github.com:drycc/<component>.git
+$ cd drycc
+$ git config remote.origin.pushurl git@github.com:<username>/<component>.git
+

In this setup, fetching and pulling code will work directly with the upstream repository, while pushing code will send changes to your fork. This makes it easy to stay up to date, but also make changes and then issue pull requests.

+

Make Your Changes

+

With your development environment set up and the code you wish to work on forked and cloned, you can begin making your changes.

+

Test Your Changes

+

Drycc components each include a comprehensive suite of automated tests, mostly written in Go. See testing for instructions on running the tests.

+

Deploying Your Changes

+

Although writing and executing tests are critical to ensuring code quality, most contributors will also want to deploy their changes to a live environment, whether to make use of those changes or to test them further. The remainder of this section documents the procedure for running officially released Drycc components in a development cluster and replacing any one of those with your customizations.

+

Running a Kubernetes Cluster for Development

+

To run a Kubernetes cluster locally or elsewhere to support your development activities, refer to Drycc installation instructions here.

+

Using a Development Registry

+

To facilitate deploying Container images containing your changes to your Kubernetes cluster, you will need to make use of a Container registry. This is a location to where you can push your custom-built images and from where your Kubernetes cluster can retrieve those same images.

+

If your development cluster runs locally (in Minikube, for instance), the most efficient and economical means of achieving this is to run a Container registry locally as a Container container.

+

To facilitate this, most Drycc components provide a make target to create such a registry:

+
$ make dev-registry
+

In a Linux environment, to begin using the registry:

+
export DRYCC_REGISTRY=<IP of the host machine>:5000
+

In non-Linux environments:

+
export DRYCC_REGISTRY=<IP of the drycc Container Machine VM>:5000
+

If your development cluster runs on a cloud provider such as Google Container Engine, a local registry such as the one above will not be accessible to your Kubernetes nodes. In such cases, a public registry such as [DockerHub][dh] or quay.io will suffice.

+

To use DockerHub for this purpose, for instance:

+
$ export DRYCC_REGISTRY="registry.drycc.cc"
+$ export IMAGE_PREFIX=<your DockerHub username>
+

To use quay.io:

+
$ export DRYCC_REGISTRY=quay.io
+$ export IMAGE_PREFIX=<your quay.io username>
+

Note the importance of the trailing slash.

+

Dev / Deployment Workflow

+

With a functioning Kubernetes cluster and the officially released Drycc components installed onto it, deployment and further testing of any Drycc component you have made changes to is facilitated by replacing the officially released component with a custom built image that contains your changes. Most Drycc components include Makefiles with targets specifically intended to facilitate this workflow with minimal friction.

+

In the general case, this workflow looks like this:

+
    +
  1. Update source code and commit your changes using git
  2. +
  3. Use make build to build a new Container image
  4. +
  5. Use make dev-release to generate Kubernetes manifest(s)
  6. +
  7. Use make deploy to restart the component using the updated manifest
  8. +
+

This can be shortened to a one-liner using just the deploy target:

+
$ make deploy
+

Useful Commands

+

Once your customized Drycc component has been deployed, here are some helpful commands that will allow you to inspect your cluster and to troubleshoot, if necessary:

+

See All Drycc Pods

+
$ kubectl --namespace=drycc get pods
+

Describe a Pod

+

This is often useful for troubleshooting pods that are in pending or crashed states:

+
$ kubectl --namespace=drycc describe -f <pod name>
+

Tail Logs

+
$ kubectl --namespace=drycc logs -f <pod name>
+

Django Shell

+

Specific to drycc/controller

+
$ kubectl --namespace=drycc exec -it <pod name> -- python manage.py shell
+

Have commands other Drycc contributors might find useful? Send us a PR!

+

Pull Requests

+

Satisfied with your changes? Share them!

+

Please read Submitting a Pull Request. It contains a checklist of +things you should do when proposing a change to any Drycc component.

+ +
+ + + + + + + + + + + +
+ +

4 - Testing Drycc

+
Each Drycc component is one among an ecosystem of such components - many of which integrate with one another - which makes testing each component thoroughly a matter of paramount importance.
+

Each Drycc component includes its own suite of style checks, unit tests, and black-box type functional tests.

+

Integration tests verify the behavior of the Drycc components together as a system and are provided separately by the drycc/workflow-e2e project.

+

GitHub pull requests for all Drycc components are tested automatically by the Travis CI continuous integration system. Contributors should run the same tests locally before proposing any changes to the Drycc codebase.

+

Set Up the Environment

+

Successfully executing the unit and functional tests for any Drycc component requires that the Development Environment is set up first.

+

Run the Tests

+

The style checks, unit tests, and functional tests for each component can all be executed via make targets:

+

To execute style checks:

+
$ make test-style
+

To execute unit tests:

+
$ make test-unit
+

To execute functional tests:

+
$ make test-functional
+

To execute style checks, unit tests, and functional tests all in one shot:

+
$ make test
+

To execute integration tests, refer to drycc/workflow-e2e documentation.

+ +
+ + + + + + + + + + + +
+ +

5 - Submitting a Pull Request

+
Proposed changes to Drycc projects are made as GitHub pull requests.
+

Design Document

+

Before opening a pull request, ensure your change also references a design document if the contribution is substantial. For more information, see Design Documents.

+

Single Issue

+

It’s hard to reach agreement on the merit of a PR when it isn’t focused. When fixing an issue or implementing a new feature, resist the temptation to refactor nearby code or to fix that potential bug you noticed. Instead, open a separate issue or pull request. Keeping concerns separated allows pull requests to be tested, reviewed, and merged more quickly.

+

Squash and rebase the commit or commits in your pull request into logical units of work with git. Include tests and documentation changes in the same commit, so that a revert would remove all traces of the feature or fix.

+

Most pull requests will reference a GitHub issue. In the PR description - not in the commit itself - include a line such as “closes #1234”. The issue referenced will automatically be closed when your PR is merged.

+

Include Tests

+

If you significantly alter or add functionality to a component that impacts the broader Drycc Workflow PaaS, you should submit a complementary PR to modify or amend end-to-end integration tests. These integration tests can be found in the drycc/workflow-e2e repository.

+

See testing for more information.

+

Include Docs

+

Changes to any Drycc Workflow component that could affect a user’s experience also require a change or addition to the relevant documentation. For most Drycc components, this involves updating the component’s own documentation. In some cases where a component is tightly integrated into drycc/workflow, its documentation must also be updated.

+

Cross-repo commits

+

If a pull request is part of a larger piece of work involving one or more additional commits in other Workflow repositories, these commits can be referenced in the last PR to be submitted. The downstream e2e test job will then supply every referenced commit (derived from PR issue number supplied) to the test runner so it can source the necessary Container images for inclusion in the generated Workflow chart to be tested.

+

For example, consider paired commits in drycc/controller and drycc/workflow-e2e. The commit body for the first PR in drycc/workflow-e2e would look like:

+
feat(foo_test): add e2e test for feature foo
+
+[skip e2e] test for controller#42
+

Adding [skip e2e] forgoes the e2e tests on this commit. This and any other required PRs aside from the final PR should be submitted first, so that their respective build and image push jobs run.

+

Lastly, the final PR in drycc/controller should be created with the required PR number(s) listed, in the form of [Rr]equires <repoName>#<pullRequestNumber>, for use by the downstream e2e run.

+
feat(foo): add feature foo
+
+Requires workflow-e2e#42
+

Code Standards

+

Drycc components are implemented in Go and Python. For both languages, we agree with The Zen of Python, which emphasizes simple over clever. Readability counts.

+

Go code should always be run through gofmt on the default settings. Lines of code may be up to 99 characters long. Documentation strings and tests are required for all exported functions. Use of third-party go packages should be minimal, but when doing so, such dependencies should be managed via the glide tool.

+

Python code should always adhere to PEP8, the python code style guide, with the exception that lines of code may be up to 99 characters long. Docstrings and tests are required for all public methods, although the flake8 tool used by Drycc does not enforce this.

+

Commit Style

+

We follow a convention for commit messages borrowed from CoreOS, who borrowed theirs +from AngularJS. This is an example of a commit:

+
feat(scripts/test-cluster): add a cluster test command
+
+this uses tmux to setup a test cluster that you can easily kill and
+start for debugging.
+

To make it more formal, it looks something like this:

+
{type}({scope}): {subject}
+<BLANK LINE>
+{body}
+<BLANK LINE>
+{footer}
+

The allowed {types} are as follows:

+
    +
  • feat -> feature
  • +
  • fix -> bug fix
  • +
  • docs -> documentation
  • +
  • style -> formatting
  • +
  • ref -> refactoring code
  • +
  • test -> adding missing tests
  • +
  • chore -> maintenance
  • +
+

The {scope} can be anything specifying the location(s) of the commit change(s).

+

The {subject} needs to be an imperative, present tense verb: “change”, not “changed” nor +“changes”. The first letter should not be capitalized, and there is no dot (.) at the end.

+

Just like the {subject}, the message {body} needs to be in the present tense, and includes +the motivation for the change, as well as a contrast with the previous behavior. The first +letter in a paragraph must be capitalized.

+

All breaking changes need to be mentioned in the {footer} with the description of the +change, the justification behind the change and any migration notes required.

+

Any line of the commit message cannot be longer than 72 characters, with the subject line +limited to 50 characters. This allows the message to be easier to read on GitHub as well +as in various git tools.

+

Merge Approval

+

Any code change - other than a simple typo fix or one-line documentation change - requires at least two Drycc maintainers to accept it. Maintainers tag pull requests with “LGTM1” and “LGTM2” (Looks Good To Me) labels to indicate acceptance.

+

No pull requests can be merged until at least one core maintainer signs off with an LGTM. The other LGTM can come from either a core maintainer or contributing maintainer.

+

If the PR is from a Drycc maintainer, then he or she should be the one to close it. This keeps the commit stream clean and gives the maintainer the benefit of revisiting the PR before deciding whether or not to merge the changes.

+

An exception to this is when an errant commit needs to be reverted urgently. If necessary, a PR that only reverts a previous commit can be merged without waiting for LGTM approval.

+ +
+ + + + + + + + + + + +
+ +

6 - Community

+
Drycc is an open source project that anyone in the community can use, improve, and enjoy. We’d love you to join us! Here’s a few ways to find out what’s happening and get involved.
+

Drycc software is fully open source. As such, the “Drycc community” consists of anyone who uses the Drycc software and participates in its evolution, whether by answering questions, finding bugs, suggesting enhancements, or writing documentation or code.

+

Drycc development is coordinated through numerous project repositories on GitHub. Anyone can check out the source code for any Drycc component, fork it, make improvements, and create a pull request to offer those changes back to the Drycc community.

+

Engine Yard maintains the numerous Drycc projects, and as such, decides what ends up in the official GitHub repositories. Drycc depends on the contributions of the community; the maintainers will not ignore pull requests or issues.

+

Drycc uses the timeless, highly efficient, and totally unfair system known as “Benevolent Dictator for Life” (BDFL). Gabriel Monroy, the creator of Drycc, is our BDFL and has final say over all decisions related to Drycc.

+

Open Source Bounties

+

Drycc projects are bounty-friendly. We believe open source bounty sites can be constructive tools in the development of open source software. Community members are encouraged to a) offer bounties and b) receive bounties for open source contributions that benefit everyone. The Drycc maintainers, however, will not accept bounties on this project but are more than happy to help community members attempting bounties.

+ +
+ + + + + + + + + + + +
+ +

7 - Triaging Issues

+
Issue triage provides an important way to contribute to an open source project.
+

Triage helps ensure issues resolve quickly by:

+
    +
  • Describing the issue’s intent and purpose is conveyed precisely. This is necessary because it can be difficult for an issue to explain how an end user experiences an problem and what actions they took.
  • +
  • Giving a contributor the information they need before they commit to resolving an issue.
  • +
  • Lowering the issue count by preventing duplicate issues.
  • +
  • Streamlining the development process by preventing duplicate discussions.
  • +
+

If you don’t have time to code, consider helping with triage. The community will thank you for saving them time by spending some of yours.

+

Ensure the Issue Contains Basic Information

+

Before triaging an issue very far, make sure that the issue’s author provided the standard issue information. This will help you make an educated recommendation on how this to categorize the issue. Standard information that should be included in most issues are things such as:

+
    +
  • the version(s) of Drycc this issue affects
  • +
  • a reproducible case if this is a bug
  • +
  • page URL if this is a docs issue or the name of a man page
  • +
+

Depending on the issue, you might not feel all this information is needed. Use your best judgment. If you cannot triage an issue using what its author provided, explain kindly to the author that they must provide the above information to clarify the problem.

+

If the author provides the recommended information but you are still unable to triage the issue, request additional information. Do this kindly and politely because you are asking for more of the author’s time.

+

If the author does not respond requested information within the timespan of a week, close the issue with a kind note stating that the author can request for the issue to be reopened when the necessary information is provided.

+

Classifying the Issue

+

An issue can have multiple of the following labels:

+

Issue Kind

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KindDescription
bugBugs are bugs. The cause may or may not be known at triage time so debugging should be taken account into the time estimate.
docsWriting documentation, man pages, articles, blogs, or other significant word-driven task.
enhancementEnhancements can drastically improve usability or performance of a component.
questionContains a user or contributor question requiring a response.
securitySecurity-related issues such as TLS encryption, network segregation, authn/authz features, etc.
+

Functional Area

+
    +
  • builder
  • +
  • cache
  • +
  • contrib and provisioning
  • +
  • client
  • +
  • controller
  • +
  • database
  • +
  • docs
  • +
  • kubernetes
  • +
  • registry
  • +
  • router
  • +
  • store (Ceph)
  • +
  • tests
  • +
+

Easy Fix

+

“Easy Fix” issues are a way for a new contributor to find issues that are fit for their experience level. These issues are typically for users who are new to Drycc, and possibly Go, and is looking to help while learning the basics.

+

Prioritizing issues

+

When attached to a specific milestone, an issue can be attributed one of the following labels to indicate their degree of priority.

+ + + + + + + + + + + + + + + + + +
PriorityDescription
priority 0Urgent: Security, critical bugs, blocking issues. Drop everything and fix this today, then consider creating a patch release.
priority 1Serious: Impedes user actions or is a regression. Fix this before the next planned release.
+

And that’s it. That should be all the information required for a new or existing contributor to come in an resolve an issue.

+ +
+ + + + + + + + + + + +
+ +

8 - Conduct

+
The Drycc community welcomes and encourages participation by everyone.
+

Conduct

+

The Drycc community welcomes and encourages participation by everyone.

+

No matter how you identify yourself or how others perceive you: we welcome you. We welcome contributions from everyone as long as they interact constructively with our community.

+

The Drycc developer community continues to grow, and it is inevitable that disagreements and conflict will arise. We ask that participants conduct themselves according to these principles:

+
    +
  1. +

    Be welcoming, friendly, and patient.

    +
  2. +
  3. +

    Be considerate.

    +
  4. +
+

Your work will be used by other people, and you in turn will depend on the work of others. Any decision you take will affect users and colleagues, and you should take those consequences into account when making decisions. Remember that we’re a world-wide community, so you might not be communicating in someone else’s primary language.

+
    +
  1. Be respectful.
  2. +
+

Not all of us will agree all the time, but disagreement is no excuse for poor behavior and bad manners. We might all experience some frustration now and then, but we cannot allow that frustration to turn into a personal attack. It’s important to remember that a community where people feel uncomfortable or threatened is not a productive one.

+
    +
  1. Be careful in the words that you choose.
  2. +
+

Be kind to others. Do not insult or put down other participants. Behave professionally. Remember that harassment and sexist, racist, or exclusionary jokes are never appropriate for the community.

+

(Thanks to the Debian and Django communities for their text and +their inspiration.)

+ +
+ + + + + + + + + + + +
+ +

9 - Drycc Maintainers

+
This document serves to describe the leadership structure of the Drycc project, and list the current project maintainers.
+

What is a maintainer?

+

(Unabashedly stolen from the Podman project)

+

There are different types of maintainers, with different responsibilities, but +all maintainers have 3 things in common:

+
    +
  1. They share responsibility in the project’s success.
  2. +
  3. They have made a long-term, recurring time investment to improve the project.
  4. +
  5. They spend that time doing whatever needs to be done, not necessarily what +is the most interesting or fun.
  6. +
+

Maintainers are often under-appreciated, because their work is harder to appreciate. +It’s easy to appreciate a really cool and technically advanced feature. It’s harder +to appreciate the absence of bugs, the slow but steady improvement in stability, +or the reliability of a release process. But those things distinguish a good +project from a great one.

+

Drycc maintainers

+

Drycc has two groups of maintainers in addition to our beloved Benevolent Dictator for Life.

+

BDFL

+

Drycc follows the timeless, highly efficient and totally unfair system known as Benevolent dictator +for life.

+

Gabriel Monroy (@gabrtv), as creator of the Drycc project, serves as our +project’s BDFL. While the day-to-day project management is carried out by the maintainers, Gabriel +serves as the final arbiter of any disputes and has the final say on project direction.

+

Core maintainers

+

Core maintainers are exceptionally knowledgeable about all areas of Drycc. Some maintainers work on Drycc +full-time, although this is not a requirement.

+

The duties of a core maintainer include:

+
    +
  • Classify and respond to GitHub issues and review pull requests
  • +
  • Help to shape the Drycc roadmap and lead efforts to accomplish roadmap milestones
  • +
  • Participate actively in feature development and bug fixing
  • +
  • Answer questions and help users in the Drycc #community Slack channel
  • +
+

The current list of core maintainers can be seen here.

+

No pull requests can be merged until at least one core maintainer signs off with an +LGTM. The other LGTM can +come from either a core maintainer or contributing maintainer.

+

Contributing maintainers

+

Contributing maintainers are exceptionally knowledgeable about some but not necessarily all areas +of Drycc, and are often selected due to specific domain knowledge that complements the project (but +a willingness to continually contribute to the project is most important!). Often, +core maintainers will ask a contributing maintainer to weigh in on issues, pull requests, or +conversations where the contributing maintainer is knowledgeable.

+

The duties of a contributing maintainer are very similar to those of a core maintainer, but they are limited to areas of the Drycc project where the contributing maintainer is knowledgeable.

+

Contributing maintainers are defined in practice as those who have write access to the Drycc repository. All maintainers can review pull requests and add LGTM labels as appropriate.

+

Becoming a maintainer

+

The Drycc project wouldn’t be where it is today without its community. Many of the project’s +community members embody the spirit of maintainership, and have contributed substantially to +the project.

+

The contributing maintainers group was created in part so that exceptional members of the community +who have an interest in the continued success of the project have the opportunity to join the +core maintainers in guiding the future of Drycc.

+

Generally, potential contributing maintainers are selected by the Drycc core maintainers based in +part on the following criteria:

+
    +
  • Sustained contributions to the project over a period of time (usually months)
  • +
  • A willingness to help Drycc users on GitHub and in the Drycc #community Slack channel
  • +
  • A friendly attitude :)
  • +
+

The Drycc core maintainers must unanimously agree before inviting a community member to join as a +contributing maintainer, although in many cases the candidate has already been acting in the +capacity of a contributing maintainer for some time, and has been consulted on issues, pull requests, +etc.

+ +
+ + + + + + + + + +
+
+
+ + +
+ + + + + + diff --git a/docs/contribution-guidelines/community/index.html b/docs/contribution-guidelines/community/index.html new file mode 100644 index 000000000..54a6ec496 --- /dev/null +++ b/docs/contribution-guidelines/community/index.html @@ -0,0 +1,465 @@ + + + + + + + + + + + + + + + + + + + +Community | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Community

+
Drycc is an open source project that anyone in the community can use, improve, and enjoy. We’d love you to join us! Here’s a few ways to find out what’s happening and get involved.
+ +

Drycc software is fully open source. As such, the “Drycc community” consists of anyone who uses the Drycc software and participates in its evolution, whether by answering questions, finding bugs, suggesting enhancements, or writing documentation or code.

+

Drycc development is coordinated through numerous project repositories on GitHub. Anyone can check out the source code for any Drycc component, fork it, make improvements, and create a pull request to offer those changes back to the Drycc community.

+

Engine Yard maintains the numerous Drycc projects, and as such, decides what ends up in the official GitHub repositories. Drycc depends on the contributions of the community; the maintainers will not ignore pull requests or issues.

+

Drycc uses the timeless, highly efficient, and totally unfair system known as “Benevolent Dictator for Life” (BDFL). Gabriel Monroy, the creator of Drycc, is our BDFL and has final say over all decisions related to Drycc.

+

Open Source Bounties

+

Drycc projects are bounty-friendly. We believe open source bounty sites can be constructive tools in the development of open source software. Community members are encouraged to a) offer bounties and b) receive bounties for open source contributions that benefit everyone. The Drycc maintainers, however, will not accept bounties on this project but are more than happy to help community members attempting bounties.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/contribution-guidelines/conduct/index.html b/docs/contribution-guidelines/conduct/index.html new file mode 100644 index 000000000..3e4002182 --- /dev/null +++ b/docs/contribution-guidelines/conduct/index.html @@ -0,0 +1,475 @@ + + + + + + + + + + + + + + + + + + + +Conduct | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Conduct

+
The Drycc community welcomes and encourages participation by everyone.
+ +

Conduct

+

The Drycc community welcomes and encourages participation by everyone.

+

No matter how you identify yourself or how others perceive you: we welcome you. We welcome contributions from everyone as long as they interact constructively with our community.

+

The Drycc developer community continues to grow, and it is inevitable that disagreements and conflict will arise. We ask that participants conduct themselves according to these principles:

+
    +
  1. +

    Be welcoming, friendly, and patient.

    +
  2. +
  3. +

    Be considerate.

    +
  4. +
+

Your work will be used by other people, and you in turn will depend on the work of others. Any decision you take will affect users and colleagues, and you should take those consequences into account when making decisions. Remember that we’re a world-wide community, so you might not be communicating in someone else’s primary language.

+
    +
  1. Be respectful.
  2. +
+

Not all of us will agree all the time, but disagreement is no excuse for poor behavior and bad manners. We might all experience some frustration now and then, but we cannot allow that frustration to turn into a personal attack. It’s important to remember that a community where people feel uncomfortable or threatened is not a productive one.

+
    +
  1. Be careful in the words that you choose.
  2. +
+

Be kind to others. Do not insult or put down other participants. Behave professionally. Remember that harassment and sexist, racist, or exclusionary jokes are never appropriate for the community.

+

(Thanks to the Debian and Django communities for their text and +their inspiration.)

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/contribution-guidelines/design-documents/index.html b/docs/contribution-guidelines/design-documents/index.html new file mode 100644 index 000000000..4efd9aacc --- /dev/null +++ b/docs/contribution-guidelines/design-documents/index.html @@ -0,0 +1,491 @@ + + + + + + + + + + + + + + + + + + + +Design Documents | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Design Documents

+
Before submitting a pull request which will significantly alter the behavior of any Drycc component.
+ +

Before submitting a pull request which will significantly alter the behavior of any Drycc component, such as a new feature or major refactoring, contributors should first open an issue representing a design document.

+

Goals

+

Design documents help ensure project contributors:

+
    +
  • Involve stakeholders as early as possible in a feature’s development
  • +
  • Ensure code changes accomplish the original motivations and design goals
  • +
  • Establish clear acceptance criteria for a feature or change
  • +
  • Enforce test-driven design methodology and automated test coverage
  • +
+

Contents

+

Design document issues should be named Design Doc: <change description> and contain the following sections:

+

Goal

+

This section should briefly describe the proposed change and the motivations behind it. Tests will be written to ensure this design goal is met by the change.

+

This section should also reference a separate GitHub issue tracking the feature or change, which will typically be assigned to a release milestone.

+

Code Changes

+

This section should detail the code changes necessary to accomplish the change, as well as the proposed implementation. This should be as detailed as necessary to help reviewers understand the change.

+

Tests

+

All changes should be covered by automated tests, either unit or integration tests (ideally both). This section should detail how tests will be written to validate that the change accomplishes the design goals and doesn’t introduce any regressions.

+

If a change cannot be sufficiently covered by automated testing, the design should be reconsidered. If there is no test coverage whatsoever for an affected section of code, a separate issue should be filed to integrate automated testing with that section of the codebase.

+

The tests described here also form the acceptance criteria for the change, so that when it’s completed maintainers can merge the pull request after confirming the tests pass CI.

+

Approval

+

A design document follows the same merge approval review process as final pull requests do, and maintainers will take extra care to ensure that any stakeholders for the change are included in the discussion and review of the design document.

+

Once the design is accepted, the author can complete the change and submit a pull request for review. The pull request should close both the design document for the change as well as any issues that either track the issue or are closed as a result of the change.

+

See Submitting a Pull Request for more information on pull request and commit message formatting.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/contribution-guidelines/development-environment/index.html b/docs/contribution-guidelines/development-environment/index.html new file mode 100644 index 000000000..209174160 --- /dev/null +++ b/docs/contribution-guidelines/development-environment/index.html @@ -0,0 +1,592 @@ + + + + + + + + + + + + + + + + + + + +Development Environment | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Development Environment

+
This document is for developers who are interested in working directly on the Drycc codebase.
+ +

In this guide, we walk you through the process of setting up a development environment that is suitable for hacking on most Drycc components.

+

We try to make it simple to hack on Drycc components. However, there are necessarily several moving pieces and some setup required. We welcome any suggestions for automating or simplifying this process.

+

!!! note +The Drycc team is actively engaged in containerizing Go and Python based development environments tailored specifically for Drycc development in order to minimize the setup required. This work is ongoing. Refer to the drycc/router project for a working example of a fully containerized development environment.

+

If you’re just getting into the Drycc codebase, look for GitHub issues with the label easy-fix. These are more straightforward or low-risk issues and are a great way to become more familiar with Drycc.

+

Prerequisites

+

In order to successfully compile and test Drycc binaries and build Container images of Drycc components, the following are required:

+
    +
  • git
  • +
  • Go 1.5 or later, with support for compiling to linux/amd64
  • +
  • glide
  • +
  • golint
  • +
  • shellcheck
  • +
  • Podman (in a non-Linux environment, you will additionally want [Podman Machine][machine])
  • +
+

For drycc/controller, in particular, you will also need:

+
    +
  • Python 2.7 or later (with pip)
  • +
  • virtualenv (sudo pip install virtualenv)
  • +
+

In most cases, you should simply install according to the instructions. There are a few special cases, though. We cover these below.

+

Configuring Go

+

If your local workstation does not support the linux/amd64 target environment, you will have to install Go from source with cross-compile support for that environment. This is because some of the components are built on your local machine and then injected into a container.

+

Homebrew users can just install with cross compiling support:

+
$ brew install go --with-cc-common
+

It is also straightforward to build Go from source:

+
$ sudo su
+$ curl -sSL https://golang.org/dl/go1.5.src.tar.gz | tar -v -C /usr/local -xz
+$ cd /usr/local/go/src
+$ # compile Go for our default platform first, then add cross-compile support
+$ ./make.bash --no-clean
+$ GOOS=linux GOARCH=amd64 ./make.bash --no-clean
+

Once you can compile to linux/amd64, you should be able to compile Drycc components as normal.

+

Fork the Repository

+

Once the prerequisites have been met, we can begin to work with Drycc components.

+

Begin at Github by forking whichever Drycc project you would like to contribute to, then clone that fork locally. Since Drycc is predominantly written in Go, the best place to put it is under $GOPATH/src/github.com/drycc/.

+
$ mkdir -p  $GOPATH/src/github.com/drycc
+$ cd $GOPATH/src/github.com/drycc
+$ git clone git@github.com:<username>/<component>.git
+$ cd <component>
+

!!! note +By checking out the forked copy into the namespace github.com/drycc/<component>, we are tricking the Go toolchain into seeing our fork as the “official” source tree.

+

If you are going to be issuing pull requests to the upstream repository from which you forked, we suggest configuring Git such that you can easily rebase your code to the upstream repository’s main branch. There are various strategies for doing this, but the most common is to add an upstream remote:

+
$ git remote add upstream https://github.com/drycc/<component>.git
+

For the sake of simplicity, you may want to point an environment variable to your Drycc code - the directory containing one or more Drycc components:

+
$ export DRYCC=$GOPATH/src/github.com/drycc
+

Throughout the rest of this document, $DRYCC refers to that location.

+

Alternative: Forking with a Pushurl

+

A number of Drycc contributors prefer to pull directly from drycc/<component>, but push to <username>/<component>. If that workflow suits you better, you can set it up this way:

+
$ git clone git@github.com:drycc/<component>.git
+$ cd drycc
+$ git config remote.origin.pushurl git@github.com:<username>/<component>.git
+

In this setup, fetching and pulling code will work directly with the upstream repository, while pushing code will send changes to your fork. This makes it easy to stay up to date, but also make changes and then issue pull requests.

+

Make Your Changes

+

With your development environment set up and the code you wish to work on forked and cloned, you can begin making your changes.

+

Test Your Changes

+

Drycc components each include a comprehensive suite of automated tests, mostly written in Go. See testing for instructions on running the tests.

+

Deploying Your Changes

+

Although writing and executing tests are critical to ensuring code quality, most contributors will also want to deploy their changes to a live environment, whether to make use of those changes or to test them further. The remainder of this section documents the procedure for running officially released Drycc components in a development cluster and replacing any one of those with your customizations.

+

Running a Kubernetes Cluster for Development

+

To run a Kubernetes cluster locally or elsewhere to support your development activities, refer to Drycc installation instructions here.

+

Using a Development Registry

+

To facilitate deploying Container images containing your changes to your Kubernetes cluster, you will need to make use of a Container registry. This is a location to where you can push your custom-built images and from where your Kubernetes cluster can retrieve those same images.

+

If your development cluster runs locally (in Minikube, for instance), the most efficient and economical means of achieving this is to run a Container registry locally as a Container container.

+

To facilitate this, most Drycc components provide a make target to create such a registry:

+
$ make dev-registry
+

In a Linux environment, to begin using the registry:

+
export DRYCC_REGISTRY=<IP of the host machine>:5000
+

In non-Linux environments:

+
export DRYCC_REGISTRY=<IP of the drycc Container Machine VM>:5000
+

If your development cluster runs on a cloud provider such as Google Container Engine, a local registry such as the one above will not be accessible to your Kubernetes nodes. In such cases, a public registry such as [DockerHub][dh] or quay.io will suffice.

+

To use DockerHub for this purpose, for instance:

+
$ export DRYCC_REGISTRY="registry.drycc.cc"
+$ export IMAGE_PREFIX=<your DockerHub username>
+

To use quay.io:

+
$ export DRYCC_REGISTRY=quay.io
+$ export IMAGE_PREFIX=<your quay.io username>
+

Note the importance of the trailing slash.

+

Dev / Deployment Workflow

+

With a functioning Kubernetes cluster and the officially released Drycc components installed onto it, deployment and further testing of any Drycc component you have made changes to is facilitated by replacing the officially released component with a custom built image that contains your changes. Most Drycc components include Makefiles with targets specifically intended to facilitate this workflow with minimal friction.

+

In the general case, this workflow looks like this:

+
    +
  1. Update source code and commit your changes using git
  2. +
  3. Use make build to build a new Container image
  4. +
  5. Use make dev-release to generate Kubernetes manifest(s)
  6. +
  7. Use make deploy to restart the component using the updated manifest
  8. +
+

This can be shortened to a one-liner using just the deploy target:

+
$ make deploy
+

Useful Commands

+

Once your customized Drycc component has been deployed, here are some helpful commands that will allow you to inspect your cluster and to troubleshoot, if necessary:

+

See All Drycc Pods

+
$ kubectl --namespace=drycc get pods
+

Describe a Pod

+

This is often useful for troubleshooting pods that are in pending or crashed states:

+
$ kubectl --namespace=drycc describe -f <pod name>
+

Tail Logs

+
$ kubectl --namespace=drycc logs -f <pod name>
+

Django Shell

+

Specific to drycc/controller

+
$ kubectl --namespace=drycc exec -it <pod name> -- python manage.py shell
+

Have commands other Drycc contributors might find useful? Send us a PR!

+

Pull Requests

+

Satisfied with your changes? Share them!

+

Please read Submitting a Pull Request. It contains a checklist of +things you should do when proposing a change to any Drycc component.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/contribution-guidelines/index.html b/docs/contribution-guidelines/index.html new file mode 100644 index 000000000..2a79523cd --- /dev/null +++ b/docs/contribution-guidelines/index.html @@ -0,0 +1,508 @@ + + + + + + + + + + + + + + + + + + + + + +Contribution Guidelines | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Contribution Guidelines

+
This HowTo is for project maintainers who need a Contributing Guide for their project.
+ + +
+ + +
+
+
+ Contributor Overview +
+

Interested in contributing to a Drycc project? There are lots of ways to help.

+
+
+
+ Design Documents +
+

Before submitting a pull request which will significantly alter the behavior of any Drycc component.

+
+
+
+ Development Environment +
+

This document is for developers who are interested in working directly on the Drycc codebase.

+
+
+
+ Testing Drycc +
+

Each Drycc component is one among an ecosystem of such components - many of which integrate with one another - which makes testing each component thoroughly a matter of paramount importance.

+
+
+
+ Submitting a Pull Request +
+

Proposed changes to Drycc projects are made as GitHub pull requests.

+
+
+
+ Community +
+

Drycc is an open source project that anyone in the community can use, improve, and enjoy. We’d love you to join us! Here’s a few ways to find out what’s happening and get involved.

+
+
+
+ Triaging Issues +
+

Issue triage provides an important way to contribute to an open source project.

+
+
+
+ Conduct +
+

The Drycc community welcomes and encourages participation by everyone.

+
+
+
+ Drycc Maintainers +
+

This document serves to describe the leadership structure of the Drycc project, and list the current project maintainers.

+
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+
+ +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/contribution-guidelines/index.xml b/docs/contribution-guidelines/index.xml new file mode 100644 index 000000000..90443418f --- /dev/null +++ b/docs/contribution-guidelines/index.xml @@ -0,0 +1,543 @@ + + + Drycc – Contribution Guidelines + /docs/contribution-guidelines/ + Recent content in Contribution Guidelines on Drycc + Hugo -- gohugo.io + en + + + + + + + + + + + Docs: Contributor Overview + /docs/contribution-guidelines/overview/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/contribution-guidelines/overview/ + + + + <h2 id="file-bugs--enhancements">File Bugs &amp; Enhancements<a class="td-heading-self-link" href="#file-bugs--enhancements" aria-label="Heading self-link"></a></h2> +<p>Find a bug? Want to see a new feature? Have a request for the maintainers? Open a Github issue in the applicable repository and we’ll get the conversation started.</p> +<p>Our official support channel is the <a href="https://slack.drycc.cc">Drycc #community Slack channel</a>.</p> +<p>Don&rsquo;t know what the applicable repository for an issue is? Open up in issue in <a href="https://github.com/drycc/workflow">workflow</a> or chat with a maintainer in the <a href="https://slack.drycc.cc">Drycc #community Slack channel</a> and we&rsquo;ll make sure it gets to the right place.</p> +<p>Additionally, take a look at the <a href="/docs/troubleshooting/">troubleshooting</a> documentation for common issues.</p> +<p>Before opening a new issue, it&rsquo;s helpful to search and see if anyone else has already reported the problem. You can search through a list of issues for all Drycc projects <a href="https://github.com/pulls?utf8=%E2%9C%93&q=user%3Adrycc+user%3Ahelm">here</a>.</p> +<h2 id="write-documentation">Write Documentation<a class="td-heading-self-link" href="#write-documentation" aria-label="Heading self-link"></a></h2> +<p>We are always looking to improve and expand our documentation. Most docs reside in the <a href="https://github.com/drycc/workflow">drycc/workflow</a> repository. Simply fork the project, update docs and send us a pull request.</p> +<h2 id="contribute-code">Contribute Code<a class="td-heading-self-link" href="#contribute-code" aria-label="Heading self-link"></a></h2> +<p>We are always looking for help improving the core platform, other workloads, tooling, and test coverage. Interested in contributing code? Let’s chat in the <a href="https://slack.drycc.cc">Drycc #community Slack channel</a>. Make sure to check out issues tagged <a href="https://github.com/pulls?utf8=%E2%9C%93&q=user%3Adrycc+label%3A%22easy+fix%22+is%3Aopen">easy fix</a> or <a href="https://github.com/pulls?utf8=%E2%9C%93&q=user%3Adrycc+label%3A%22help+wanted%22+is%3Aopen">help wanted</a>.</p> +<p>When you&rsquo;re ready to begin writing code, review <a href="/docs/contribution-guidelines/design-documents/">Design Documents</a> and get your <a href="/docs/contribution-guidelines/development-environment/">Development Environment</a> set up.</p> +<p>By contributing to any Drycc project you agree to its <a href="https://github.com/drycc/workflow/blob/main/DCO">Developer Certificate of Origin (DCO)</a>. This document was created by the Linux Kernel community and is a simple statement that you, as a contributor, have the legal right to make the contribution.</p> +<h2 id="triage-issues">Triage Issues<a class="td-heading-self-link" href="#triage-issues" aria-label="Heading self-link"></a></h2> +<p>If you don&rsquo;t have time to code, consider helping with triage. The community will thank you for saving them time by spending some of yours. See <a href="/docs/contribution-guidelines/triaging-issues/">Triaging Issues</a> for more info.</p> +<h2 id="share-your-experience">Share your Experience<a class="td-heading-self-link" href="#share-your-experience" aria-label="Heading self-link"></a></h2> +<p>Interact with the community on our user mailing list or live in our <a href="https://slack.drycc.cc">Drycc #community Slack channel</a>, where you can chat with other Drycc Workflow users any time of day.</p> + + + + + + Docs: Design Documents + /docs/contribution-guidelines/design-documents/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/contribution-guidelines/design-documents/ + + + + <p>Before submitting a pull request which will significantly alter the behavior of any Drycc component, such as a new feature or major refactoring, contributors should first open an issue representing a design document.</p> +<h2 id="goals">Goals<a class="td-heading-self-link" href="#goals" aria-label="Heading self-link"></a></h2> +<p>Design documents help ensure project contributors:</p> +<ul> +<li>Involve stakeholders as early as possible in a feature&rsquo;s development</li> +<li>Ensure code changes accomplish the original motivations and design goals</li> +<li>Establish clear acceptance criteria for a feature or change</li> +<li>Enforce test-driven design methodology and automated test coverage</li> +</ul> +<h2 id="contents">Contents<a class="td-heading-self-link" href="#contents" aria-label="Heading self-link"></a></h2> +<p>Design document issues should be named <code>Design Doc: &lt;change description&gt;</code> and contain the following sections:</p> +<h3 id="goal">Goal<a class="td-heading-self-link" href="#goal" aria-label="Heading self-link"></a></h3> +<p>This section should briefly describe the proposed change and the motivations behind it. Tests will be written to ensure this design goal is met by the change.</p> +<p>This section should also reference a separate GitHub issue tracking the feature or change, which will typically be assigned to a release milestone.</p> +<h3 id="code-changes">Code Changes<a class="td-heading-self-link" href="#code-changes" aria-label="Heading self-link"></a></h3> +<p>This section should detail the code changes necessary to accomplish the change, as well as the proposed implementation. This should be as detailed as necessary to help reviewers understand the change.</p> +<h3 id="tests">Tests<a class="td-heading-self-link" href="#tests" aria-label="Heading self-link"></a></h3> +<p>All changes should be covered by automated tests, either unit or integration tests (ideally both). This section should detail how tests will be written to validate that the change accomplishes the design goals and doesn&rsquo;t introduce any regressions.</p> +<p>If a change cannot be sufficiently covered by automated testing, the design should be reconsidered. If there is no test coverage whatsoever for an affected section of code, a separate issue should be filed to integrate automated testing with that section of the codebase.</p> +<p>The tests described here also form the acceptance criteria for the change, so that when it&rsquo;s completed maintainers can merge the pull request after confirming the tests pass CI.</p> +<h3 id="approval">Approval<a class="td-heading-self-link" href="#approval" aria-label="Heading self-link"></a></h3> +<p>A design document follows the same <a href="/docs/contribution-guidelines/submitting-a-pull-request/#merge-approval">merge approval</a> review process as final pull requests do, and maintainers will take extra care to ensure that any stakeholders for the change are included in the discussion and review of the design document.</p> +<p>Once the design is accepted, the author can complete the change and submit a pull request for review. The pull request should close both the design document for the change as well as any issues that either track the issue or are closed as a result of the change.</p> +<p>See <a href="/docs/contribution-guidelines/submitting-a-pull-request/">Submitting a Pull Request</a> for more information on pull request and commit message formatting.</p> + + + + + + Docs: Development Environment + /docs/contribution-guidelines/development-environment/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/contribution-guidelines/development-environment/ + + + + <p>In this guide, we walk you through the process of setting up a development environment that is suitable for hacking on most Drycc components.</p> +<p>We try to make it simple to hack on Drycc components. However, there are necessarily several moving pieces and some setup required. We welcome any suggestions for automating or simplifying this process.</p> +<p>!!! note +The Drycc team is actively engaged in containerizing Go and Python based development environments tailored specifically for Drycc development in order to minimize the setup required. This work is ongoing. Refer to the <a href="https://github.com/drycc/router">drycc/router</a> project for a working example of a fully containerized development environment.</p> +<p>If you&rsquo;re just getting into the Drycc codebase, look for GitHub issues with the label <a href="https://github.com/issues?q=user%3Adrycc+label%3Aeasy-fix+is%3Aopen">easy-fix</a>. These are more straightforward or low-risk issues and are a great way to become more familiar with Drycc.</p> +<h2 id="prerequisites">Prerequisites<a class="td-heading-self-link" href="#prerequisites" aria-label="Heading self-link"></a></h2> +<p>In order to successfully compile and test Drycc binaries and build Container images of Drycc components, the following are required:</p> +<ul> +<li><a href="https://git-scm.com/">git</a></li> +<li>Go 1.5 or later, with support for compiling to <code>linux/amd64</code></li> +<li><a href="https://github.com/Masterminds/glide">glide</a></li> +<li><a href="https://github.com/golang/lint">golint</a></li> +<li><a href="https://github.com/koalaman/shellcheck">shellcheck</a></li> +<li><a href="https://podman.io/">Podman</a> (in a non-Linux environment, you will additionally want [Podman Machine][machine])</li> +</ul> +<p>For <a href="https://github.com/drycc/controller">drycc/controller</a>, in particular, you will also need:</p> +<ul> +<li>Python 2.7 or later (with <code>pip</code>)</li> +<li>virtualenv (<code>sudo pip install virtualenv</code>)</li> +</ul> +<p>In most cases, you should simply install according to the instructions. There are a few special cases, though. We cover these below.</p> +<h3 id="configuring-go">Configuring Go<a class="td-heading-self-link" href="#configuring-go" aria-label="Heading self-link"></a></h3> +<p>If your local workstation does not support the <code>linux/amd64</code> target environment, you will have to install Go from source with cross-compile support for that environment. This is because some of the components are built on your local machine and then injected into a container.</p> +<p>Homebrew users can just install with cross compiling support:</p> +<pre tabindex="0"><code>$ brew install go --with-cc-common +</code></pre><p>It is also straightforward to build Go from source:</p> +<pre tabindex="0"><code>$ sudo su +$ curl -sSL https://golang.org/dl/go1.5.src.tar.gz | tar -v -C /usr/local -xz +$ cd /usr/local/go/src +$ # compile Go for our default platform first, then add cross-compile support +$ ./make.bash --no-clean +$ GOOS=linux GOARCH=amd64 ./make.bash --no-clean +</code></pre><p>Once you can compile to <code>linux/amd64</code>, you should be able to compile Drycc components as normal.</p> +<h2 id="fork-the-repository">Fork the Repository<a class="td-heading-self-link" href="#fork-the-repository" aria-label="Heading self-link"></a></h2> +<p>Once the prerequisites have been met, we can begin to work with Drycc components.</p> +<p>Begin at Github by forking whichever Drycc project you would like to contribute to, then clone that fork locally. Since Drycc is predominantly written in Go, the best place to put it is under <code>$GOPATH/src/github.com/drycc/</code>.</p> +<pre tabindex="0"><code>$ mkdir -p $GOPATH/src/github.com/drycc +$ cd $GOPATH/src/github.com/drycc +$ git clone git@github.com:&lt;username&gt;/&lt;component&gt;.git +$ cd &lt;component&gt; +</code></pre><p>!!! note +By checking out the forked copy into the namespace <code>github.com/drycc/&lt;component&gt;</code>, we are tricking the Go toolchain into seeing our fork as the &ldquo;official&rdquo; source tree.</p> +<p>If you are going to be issuing pull requests to the upstream repository from which you forked, we suggest configuring Git such that you can easily rebase your code to the upstream repository&rsquo;s main branch. There are various strategies for doing this, but the <a href="https://help.github.com/articles/fork-a-repo/">most common</a> is to add an <code>upstream</code> remote:</p> +<pre tabindex="0"><code>$ git remote add upstream https://github.com/drycc/&lt;component&gt;.git +</code></pre><p>For the sake of simplicity, you may want to point an environment variable to your Drycc code - the directory containing one or more Drycc components:</p> +<pre tabindex="0"><code>$ export DRYCC=$GOPATH/src/github.com/drycc +</code></pre><p>Throughout the rest of this document, <code>$DRYCC</code> refers to that location.</p> +<h3 id="alternative-forking-with-a-pushurl">Alternative: Forking with a Pushurl<a class="td-heading-self-link" href="#alternative-forking-with-a-pushurl" aria-label="Heading self-link"></a></h3> +<p>A number of Drycc contributors prefer to pull directly from <code>drycc/&lt;component&gt;</code>, but push to <code>&lt;username&gt;/&lt;component&gt;</code>. If that workflow suits you better, you can set it up this way:</p> +<pre tabindex="0"><code>$ git clone git@github.com:drycc/&lt;component&gt;.git +$ cd drycc +$ git config remote.origin.pushurl git@github.com:&lt;username&gt;/&lt;component&gt;.git +</code></pre><p>In this setup, fetching and pulling code will work directly with the upstream repository, while pushing code will send changes to your fork. This makes it easy to stay up to date, but also make changes and then issue pull requests.</p> +<h2 id="make-your-changes">Make Your Changes<a class="td-heading-self-link" href="#make-your-changes" aria-label="Heading self-link"></a></h2> +<p>With your development environment set up and the code you wish to work on forked and cloned, you can begin making your changes.</p> +<h2 id="test-your-changes">Test Your Changes<a class="td-heading-self-link" href="#test-your-changes" aria-label="Heading self-link"></a></h2> +<p>Drycc components each include a comprehensive suite of automated tests, mostly written in Go. See <a href="/docs/contribution-guidelines/testing/">testing</a> for instructions on running the tests.</p> +<h2 id="deploying-your-changes">Deploying Your Changes<a class="td-heading-self-link" href="#deploying-your-changes" aria-label="Heading self-link"></a></h2> +<p>Although writing and executing tests are critical to ensuring code quality, most contributors will also want to deploy their changes to a live environment, whether to make use of those changes or to test them further. The remainder of this section documents the procedure for running officially released Drycc components in a development cluster and replacing any one of those with your customizations.</p> +<h3 id="running-a-kubernetes-cluster-for-development">Running a Kubernetes Cluster for Development<a class="td-heading-self-link" href="#running-a-kubernetes-cluster-for-development" aria-label="Heading self-link"></a></h3> +<p>To run a Kubernetes cluster locally or elsewhere to support your development activities, refer to Drycc installation instructions <a href="/docs/quickstart/">here</a>.</p> +<h3 id="using-a-development-registry">Using a Development Registry<a class="td-heading-self-link" href="#using-a-development-registry" aria-label="Heading self-link"></a></h3> +<p>To facilitate deploying Container images containing your changes to your Kubernetes cluster, you will need to make use of a Container registry. This is a location to where you can push your custom-built images and from where your Kubernetes cluster can retrieve those same images.</p> +<p>If your development cluster runs locally (in Minikube, for instance), the most efficient and economical means of achieving this is to run a Container registry locally <em>as</em> a Container container.</p> +<p>To facilitate this, most Drycc components provide a make target to create such a registry:</p> +<pre tabindex="0"><code>$ make dev-registry +</code></pre><p>In a Linux environment, to begin using the registry:</p> +<pre tabindex="0"><code>export DRYCC_REGISTRY=&lt;IP of the host machine&gt;:5000 +</code></pre><p>In non-Linux environments:</p> +<pre tabindex="0"><code>export DRYCC_REGISTRY=&lt;IP of the drycc Container Machine VM&gt;:5000 +</code></pre><p>If your development cluster runs on a cloud provider such as Google Container Engine, a local registry such as the one above will not be accessible to your Kubernetes nodes. In such cases, a public registry such as [DockerHub][dh] or <a href="https://quay.io/">quay.io</a> will suffice.</p> +<p>To use DockerHub for this purpose, for instance:</p> +<pre tabindex="0"><code>$ export DRYCC_REGISTRY=&#34;registry.drycc.cc&#34; +$ export IMAGE_PREFIX=&lt;your DockerHub username&gt; +</code></pre><p>To use quay.io:</p> +<pre tabindex="0"><code>$ export DRYCC_REGISTRY=quay.io +$ export IMAGE_PREFIX=&lt;your quay.io username&gt; +</code></pre><p>Note the importance of the trailing slash.</p> +<h3 id="dev--deployment-workflow">Dev / Deployment Workflow<a class="td-heading-self-link" href="#dev--deployment-workflow" aria-label="Heading self-link"></a></h3> +<p>With a functioning Kubernetes cluster and the officially released Drycc components installed onto it, deployment and further testing of any Drycc component you have made changes to is facilitated by replacing the officially released component with a custom built image that contains your changes. Most Drycc components include Makefiles with targets specifically intended to facilitate this workflow with minimal friction.</p> +<p>In the general case, this workflow looks like this:</p> +<ol> +<li>Update source code and commit your changes using <code>git</code></li> +<li>Use <code>make build</code> to build a new Container image</li> +<li>Use <code>make dev-release</code> to generate Kubernetes manifest(s)</li> +<li>Use <code>make deploy</code> to restart the component using the updated manifest</li> +</ol> +<p>This can be shortened to a one-liner using just the <code>deploy</code> target:</p> +<pre tabindex="0"><code>$ make deploy +</code></pre><h2 id="useful-commands">Useful Commands<a class="td-heading-self-link" href="#useful-commands" aria-label="Heading self-link"></a></h2> +<p>Once your customized Drycc component has been deployed, here are some helpful commands that will allow you to inspect your cluster and to troubleshoot, if necessary:</p> +<h3 id="see-all-drycc-pods">See All Drycc Pods<a class="td-heading-self-link" href="#see-all-drycc-pods" aria-label="Heading self-link"></a></h3> +<pre tabindex="0"><code>$ kubectl --namespace=drycc get pods +</code></pre><h3 id="describe-a-pod">Describe a Pod<a class="td-heading-self-link" href="#describe-a-pod" aria-label="Heading self-link"></a></h3> +<p>This is often useful for troubleshooting pods that are in pending or crashed states:</p> +<pre tabindex="0"><code>$ kubectl --namespace=drycc describe -f &lt;pod name&gt; +</code></pre><h3 id="tail-logs">Tail Logs<a class="td-heading-self-link" href="#tail-logs" aria-label="Heading self-link"></a></h3> +<pre tabindex="0"><code>$ kubectl --namespace=drycc logs -f &lt;pod name&gt; +</code></pre><h3 id="django-shell">Django Shell<a class="td-heading-self-link" href="#django-shell" aria-label="Heading self-link"></a></h3> +<p>Specific to <a href="https://github.com/drycc/controller">drycc/controller</a></p> +<pre tabindex="0"><code>$ kubectl --namespace=drycc exec -it &lt;pod name&gt; -- python manage.py shell +</code></pre><p>Have commands other Drycc contributors might find useful? Send us a PR!</p> +<h2 id="pull-requests">Pull Requests<a class="td-heading-self-link" href="#pull-requests" aria-label="Heading self-link"></a></h2> +<p>Satisfied with your changes? Share them!</p> +<p>Please read <a href="/docs/contribution-guidelines/submitting-a-pull-request/">Submitting a Pull Request</a>. It contains a checklist of +things you should do when proposing a change to any Drycc component.</p> + + + + + + Docs: Testing Drycc + /docs/contribution-guidelines/testing/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/contribution-guidelines/testing/ + + + + <p>Each Drycc component includes its own suite of style checks, <a href="http://en.wikipedia.org/wiki/Unit_testing">unit tests</a>, and black-box type <a href="http://en.wikipedia.org/wiki/Functional_testing">functional tests</a>.</p> +<p><a href="http://en.wikipedia.org/wiki/Integration_testing">Integration tests</a> verify the behavior of the Drycc components together as a system and are provided separately by the <a href="https://github.com/drycc/workflow-e2e">drycc/workflow-e2e</a> project.</p> +<p>GitHub pull requests for all Drycc components are tested automatically by the <a href="https://travis-ci.org/drycc">Travis CI</a> <a href="http://en.wikipedia.org/wiki/Continuous_integration">continuous integration</a> system. Contributors should run the same tests locally before proposing any changes to the Drycc codebase.</p> +<h2 id="set-up-the-environment">Set Up the Environment<a class="td-heading-self-link" href="#set-up-the-environment" aria-label="Heading self-link"></a></h2> +<p>Successfully executing the unit and functional tests for any Drycc component requires that the <a href="/docs/contribution-guidelines/development-environment/">Development Environment</a> is set up first.</p> +<h2 id="run-the-tests">Run the Tests<a class="td-heading-self-link" href="#run-the-tests" aria-label="Heading self-link"></a></h2> +<p>The style checks, unit tests, and functional tests for each component can all be executed via make targets:</p> +<p>To execute style checks:</p> +<pre tabindex="0"><code>$ make test-style +</code></pre><p>To execute unit tests:</p> +<pre tabindex="0"><code>$ make test-unit +</code></pre><p>To execute functional tests:</p> +<pre tabindex="0"><code>$ make test-functional +</code></pre><p>To execute style checks, unit tests, and functional tests all in one shot:</p> +<pre tabindex="0"><code>$ make test +</code></pre><p>To execute integration tests, refer to <a href="https://github.com/drycc/workflow-e2e">drycc/workflow-e2e</a> documentation.</p> + + + + + + Docs: Submitting a Pull Request + /docs/contribution-guidelines/submitting-a-pull-request/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/contribution-guidelines/submitting-a-pull-request/ + + + + <h2 id="design-document">Design Document<a class="td-heading-self-link" href="#design-document" aria-label="Heading self-link"></a></h2> +<p>Before opening a pull request, ensure your change also references a design document if the contribution is substantial. For more information, see <a href="/docs/contribution-guidelines/design-documents/">Design Documents</a>.</p> +<h2 id="single-issue">Single Issue<a class="td-heading-self-link" href="#single-issue" aria-label="Heading self-link"></a></h2> +<p>It&rsquo;s hard to reach agreement on the merit of a PR when it isn&rsquo;t focused. When fixing an issue or implementing a new feature, resist the temptation to refactor nearby code or to fix that potential bug you noticed. Instead, open a separate issue or pull request. Keeping concerns separated allows pull requests to be tested, reviewed, and merged more quickly.</p> +<p>Squash and rebase the commit or commits in your pull request into logical units of work with <code>git</code>. Include tests and documentation changes in the same commit, so that a revert would remove all traces of the feature or fix.</p> +<p>Most pull requests will reference a GitHub issue. In the PR description - not in the commit itself - include a line such as &ldquo;closes #1234&rdquo;. The issue referenced will automatically be closed when your PR is merged.</p> +<h2 id="include-tests">Include Tests<a class="td-heading-self-link" href="#include-tests" aria-label="Heading self-link"></a></h2> +<p>If you significantly alter or add functionality to a component that impacts the broader Drycc Workflow PaaS, you should submit a complementary PR to modify or amend end-to-end integration tests. These integration tests can be found in the <a href="https://github.com/drycc/workflow-e2e">drycc/workflow-e2e</a> repository.</p> +<p>See <a href="/docs/contribution-guidelines/testing/">testing</a> for more information.</p> +<h2 id="include-docs">Include Docs<a class="td-heading-self-link" href="#include-docs" aria-label="Heading self-link"></a></h2> +<p>Changes to any Drycc Workflow component that could affect a user&rsquo;s experience also require a change or addition to the relevant documentation. For most Drycc components, this involves updating the component&rsquo;s <em>own</em> documentation. In some cases where a component is tightly integrated into <a href="https://github.com/drycc/workflow">drycc/workflow</a>, its documentation must also be updated.</p> +<h2 id="cross-repo-commits">Cross-repo commits<a class="td-heading-self-link" href="#cross-repo-commits" aria-label="Heading self-link"></a></h2> +<p>If a pull request is part of a larger piece of work involving one or more additional commits in other Workflow repositories, these commits can be referenced in the last PR to be submitted. The downstream <a href="https://ci.drycc.info/job/workflow-e2e-pr/">e2e test job</a> will then supply every referenced commit (derived from PR issue number supplied) to the test runner so it can source the necessary Container images for inclusion in the generated Workflow chart to be tested.</p> +<p>For example, consider paired commits in <a href="https://github.com/drycc/controller">drycc/controller</a> and <a href="https://github.com/drycc/workflow-e2e">drycc/workflow-e2e</a>. The commit body for the first PR in <code>drycc/workflow-e2e</code> would look like:</p> +<pre tabindex="0"><code>feat(foo_test): add e2e test for feature foo + +[skip e2e] test for controller#42 +</code></pre><p>Adding <code>[skip e2e]</code> forgoes the e2e tests on this commit. This and any other required PRs aside from the final PR should be submitted first, so that their respective build and image push jobs run.</p> +<p>Lastly, the final PR in <code>drycc/controller</code> should be created with the required PR number(s) listed, in the form of <code>[Rr]equires &lt;repoName&gt;#&lt;pullRequestNumber&gt;</code>, for use by the downstream e2e run.</p> +<pre tabindex="0"><code>feat(foo): add feature foo + +Requires workflow-e2e#42 +</code></pre><h2 id="code-standards">Code Standards<a class="td-heading-self-link" href="#code-standards" aria-label="Heading self-link"></a></h2> +<p>Drycc components are implemented in <a href="http://golang.org/">Go</a> and <a href="http://www.python.org/">Python</a>. For both languages, we agree with <a href="http://www.python.org/dev/peps/pep-0020/">The Zen of Python</a>, which emphasizes simple over clever. Readability counts.</p> +<p>Go code should always be run through <code>gofmt</code> on the default settings. Lines of code may be up to 99 characters long. Documentation strings and tests are required for all exported functions. Use of third-party go packages should be minimal, but when doing so, such dependencies should be managed via the <a href="https://github.com/Masterminds/glide">glide</a> tool.</p> +<p>Python code should always adhere to <a href="http://www.python.org/dev/peps/pep-0008/">PEP8</a>, the python code style guide, with the exception that lines of code may be up to 99 characters long. Docstrings and tests are required for all public methods, although the <a href="https://pypi.python.org/pypi/flake8/">flake8</a> tool used by Drycc does not enforce this.</p> +<h2 id="commit-style">Commit Style<a class="td-heading-self-link" href="#commit-style" aria-label="Heading self-link"></a></h2> +<p>We follow a convention for commit messages borrowed from CoreOS, who borrowed theirs +from AngularJS. This is an example of a commit:</p> +<pre tabindex="0"><code>feat(scripts/test-cluster): add a cluster test command + +this uses tmux to setup a test cluster that you can easily kill and +start for debugging. +</code></pre><p>To make it more formal, it looks something like this:</p> +<pre tabindex="0"><code>{type}({scope}): {subject} +&lt;BLANK LINE&gt; +{body} +&lt;BLANK LINE&gt; +{footer} +</code></pre><p>The allowed <code>{types}</code> are as follows:</p> +<ul> +<li><code>feat</code> -&gt; feature</li> +<li><code>fix</code> -&gt; bug fix</li> +<li><code>docs</code> -&gt; documentation</li> +<li><code>style</code> -&gt; formatting</li> +<li><code>ref</code> -&gt; refactoring code</li> +<li><code>test</code> -&gt; adding missing tests</li> +<li><code>chore</code> -&gt; maintenance</li> +</ul> +<p>The <code>{scope}</code> can be anything specifying the location(s) of the commit change(s).</p> +<p>The <code>{subject}</code> needs to be an imperative, present tense verb: “change”, not “changed” nor +“changes”. The first letter should not be capitalized, and there is no dot (.) at the end.</p> +<p>Just like the <code>{subject}</code>, the message <code>{body}</code> needs to be in the present tense, and includes +the motivation for the change, as well as a contrast with the previous behavior. The first +letter in a paragraph must be capitalized.</p> +<p>All breaking changes need to be mentioned in the <code>{footer}</code> with the description of the +change, the justification behind the change and any migration notes required.</p> +<p>Any line of the commit message cannot be longer than 72 characters, with the subject line +limited to 50 characters. This allows the message to be easier to read on GitHub as well +as in various git tools.</p> +<h2 id="merge-approval">Merge Approval<a class="td-heading-self-link" href="#merge-approval" aria-label="Heading self-link"></a></h2> +<p>Any code change - other than a simple typo fix or one-line documentation change - requires at least two <a href="/docs/contribution-guidelines/maintainers/">Drycc maintainers</a> to accept it. Maintainers tag pull requests with &ldquo;<strong>LGTM1</strong>&rdquo; and &ldquo;<strong>LGTM2</strong>&rdquo; (Looks Good To Me) labels to indicate acceptance.</p> +<p>No pull requests can be merged until at least one core maintainer signs off with an LGTM. The other LGTM can come from either a core maintainer or contributing maintainer.</p> +<p>If the PR is from a Drycc maintainer, then he or she should be the one to close it. This keeps the commit stream clean and gives the maintainer the benefit of revisiting the PR before deciding whether or not to merge the changes.</p> +<p>An exception to this is when an errant commit needs to be reverted urgently. If necessary, a PR that only reverts a previous commit can be merged without waiting for LGTM approval.</p> + + + + + + Docs: Community + /docs/contribution-guidelines/community/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/contribution-guidelines/community/ + + + + <p>Drycc software is fully open source. As such, the &ldquo;Drycc community&rdquo; consists of anyone who uses the Drycc software and participates in its evolution, whether by answering questions, finding bugs, suggesting enhancements, or writing documentation or code.</p> +<p>Drycc development is coordinated through numerous project repositories <a href="https://github.com/drycc">on GitHub</a>. Anyone can check out the source code for any Drycc component, fork it, make improvements, and create a pull request to offer those changes back to the Drycc community.</p> +<p><a href="https://www.drycc.cc/community">Engine Yard</a> maintains the numerous Drycc projects, and as such, decides what ends up in the official GitHub repositories. Drycc depends on the contributions of the community; the maintainers will not ignore pull requests or issues.</p> +<p>Drycc uses the timeless, highly efficient, and totally unfair system known as &ldquo;Benevolent Dictator for Life&rdquo; (<a href="http://en.wikipedia.org/wiki/Benevolent_Dictator_for_Life">BDFL</a>). <a href="https://github.com/gabrtv">Gabriel Monroy</a>, the creator of Drycc, is our BDFL and has final say over all decisions related to Drycc.</p> +<h2 id="open-source-bounties">Open Source Bounties<a class="td-heading-self-link" href="#open-source-bounties" aria-label="Heading self-link"></a></h2> +<p>Drycc projects are bounty-friendly. We believe open source bounty sites can be constructive tools in the development of open source software. Community members are encouraged to a) offer bounties and b) receive bounties for open source contributions that benefit everyone. The Drycc maintainers, however, will not accept bounties on this project but are more than happy to help community members attempting bounties.</p> + + + + + + Docs: Triaging Issues + /docs/contribution-guidelines/triaging-issues/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/contribution-guidelines/triaging-issues/ + + + + <p>Triage helps ensure issues resolve quickly by:</p> +<ul> +<li>Describing the issue&rsquo;s intent and purpose is conveyed precisely. This is necessary because it can be difficult for an issue to explain how an end user experiences an problem and what actions they took.</li> +<li>Giving a contributor the information they need before they commit to resolving an issue.</li> +<li>Lowering the issue count by preventing duplicate issues.</li> +<li>Streamlining the development process by preventing duplicate discussions.</li> +</ul> +<p>If you don&rsquo;t have time to code, consider helping with triage. The community will thank you for saving them time by spending some of yours.</p> +<h2 id="ensure-the-issue-contains-basic-information">Ensure the Issue Contains Basic Information<a class="td-heading-self-link" href="#ensure-the-issue-contains-basic-information" aria-label="Heading self-link"></a></h2> +<p>Before triaging an issue very far, make sure that the issue&rsquo;s author provided the standard issue information. This will help you make an educated recommendation on how this to categorize the issue. Standard information that should be included in most issues are things such as:</p> +<ul> +<li>the version(s) of Drycc this issue affects</li> +<li>a reproducible case if this is a bug</li> +<li>page URL if this is a docs issue or the name of a man page</li> +</ul> +<p>Depending on the issue, you might not feel all this information is needed. Use your best judgment. If you cannot triage an issue using what its author provided, explain kindly to the author that they must provide the above information to clarify the problem.</p> +<p>If the author provides the recommended information but you are still unable to triage the issue, request additional information. Do this kindly and politely because you are asking for more of the author&rsquo;s time.</p> +<p>If the author does not respond requested information within the timespan of a week, close the issue with a kind note stating that the author can request for the issue to be reopened when the necessary information is provided.</p> +<h2 id="classifying-the-issue">Classifying the Issue<a class="td-heading-self-link" href="#classifying-the-issue" aria-label="Heading self-link"></a></h2> +<p>An issue can have multiple of the following labels:</p> +<h3 id="issue-kind">Issue Kind<a class="td-heading-self-link" href="#issue-kind" aria-label="Heading self-link"></a></h3> +<table> +<thead> +<tr> +<th>Kind</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>bug</td> +<td>Bugs are bugs. The cause may or may not be known at triage time so debugging should be taken account into the time estimate.</td> +</tr> +<tr> +<td>docs</td> +<td>Writing documentation, man pages, articles, blogs, or other significant word-driven task.</td> +</tr> +<tr> +<td>enhancement</td> +<td>Enhancements can drastically improve usability or performance of a component.</td> +</tr> +<tr> +<td>question</td> +<td>Contains a user or contributor question requiring a response.</td> +</tr> +<tr> +<td>security</td> +<td>Security-related issues such as TLS encryption, network segregation, authn/authz features, etc.</td> +</tr> +</tbody> +</table> +<h3 id="functional-area">Functional Area<a class="td-heading-self-link" href="#functional-area" aria-label="Heading self-link"></a></h3> +<ul> +<li>builder</li> +<li>cache</li> +<li>contrib and provisioning</li> +<li>client</li> +<li>controller</li> +<li>database</li> +<li>docs</li> +<li>kubernetes</li> +<li>registry</li> +<li>router</li> +<li>store (Ceph)</li> +<li>tests</li> +</ul> +<h2 id="easy-fix">Easy Fix<a class="td-heading-self-link" href="#easy-fix" aria-label="Heading self-link"></a></h2> +<p>&ldquo;Easy Fix&rdquo; issues are a way for a new contributor to find issues that are fit for their experience level. These issues are typically for users who are new to Drycc, and possibly Go, and is looking to help while learning the basics.</p> +<h2 id="prioritizing-issues">Prioritizing issues<a class="td-heading-self-link" href="#prioritizing-issues" aria-label="Heading self-link"></a></h2> +<p>When attached to a specific milestone, an issue can be attributed one of the following labels to indicate their degree of priority.</p> +<table> +<thead> +<tr> +<th>Priority</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>priority 0</td> +<td>Urgent: Security, critical bugs, blocking issues. Drop everything and fix this today, then consider creating a patch release.</td> +</tr> +<tr> +<td>priority 1</td> +<td>Serious: Impedes user actions or is a regression. Fix this before the next planned release.</td> +</tr> +</tbody> +</table> +<p>And that&rsquo;s it. That should be all the information required for a new or existing contributor to come in an resolve an issue.</p> + + + + + + Docs: Conduct + /docs/contribution-guidelines/conduct/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/contribution-guidelines/conduct/ + + + + <h1 id="conduct">Conduct<a class="td-heading-self-link" href="#conduct" aria-label="Heading self-link"></a></h1> +<p>The Drycc community welcomes and encourages participation by <strong>everyone</strong>.</p> +<p>No matter how you identify yourself or how others perceive you: we welcome you. We welcome contributions from everyone as long as they interact constructively with our community.</p> +<p>The Drycc developer community continues to grow, and it is inevitable that disagreements and conflict will arise. We ask that participants conduct themselves according to these principles:</p> +<ol> +<li> +<p><strong>Be welcoming, friendly, and patient.</strong></p> +</li> +<li> +<p><strong>Be considerate.</strong></p> +</li> +</ol> +<p>Your work will be used by other people, and you in turn will depend on the work of others. Any decision you take will affect users and colleagues, and you should take those consequences into account when making decisions. Remember that we&rsquo;re a world-wide community, so you might not be communicating in someone else&rsquo;s primary language.</p> +<ol start="3"> +<li><strong>Be respectful.</strong></li> +</ol> +<p>Not all of us will agree all the time, but disagreement is no excuse for poor behavior and bad manners. We might all experience some frustration now and then, but we cannot allow that frustration to turn into a personal attack. It’s important to remember that a community where people feel uncomfortable or threatened is not a productive one.</p> +<ol start="4"> +<li><strong>Be careful in the words that you choose.</strong></li> +</ol> +<p>Be kind to others. Do not insult or put down other participants. Behave professionally. Remember that harassment and sexist, racist, or exclusionary jokes are never appropriate for the community.</p> +<p>(Thanks to the <a href="http://www.debian.org/intro/diversity">Debian</a> and <a href="https://www.djangoproject.com/conduct/">Django</a> communities for their text and +their inspiration.)</p> + + + + + + Docs: Drycc Maintainers + /docs/contribution-guidelines/maintainers/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/contribution-guidelines/maintainers/ + + + + <h1 id="what-is-a-maintainer">What is a maintainer?<a class="td-heading-self-link" href="#what-is-a-maintainer" aria-label="Heading self-link"></a></h1> +<p>(Unabashedly stolen from the <a href="https://github.com/containers/podman/blob/master/MAINTAINERS">Podman</a> project)</p> +<p>There are different types of maintainers, with different responsibilities, but +all maintainers have 3 things in common:</p> +<ol> +<li>They share responsibility in the project&rsquo;s success.</li> +<li>They have made a long-term, recurring time investment to improve the project.</li> +<li>They spend that time doing whatever needs to be done, not necessarily what +is the most interesting or fun.</li> +</ol> +<p>Maintainers are often under-appreciated, because their work is harder to appreciate. +It&rsquo;s easy to appreciate a really cool and technically advanced feature. It&rsquo;s harder +to appreciate the absence of bugs, the slow but steady improvement in stability, +or the reliability of a release process. But those things distinguish a good +project from a great one.</p> +<h1 id="drycc-maintainers">Drycc maintainers<a class="td-heading-self-link" href="#drycc-maintainers" aria-label="Heading self-link"></a></h1> +<p>Drycc has two groups of maintainers in addition to our beloved Benevolent Dictator for Life.</p> +<h2 id="bdfl">BDFL<a class="td-heading-self-link" href="#bdfl" aria-label="Heading self-link"></a></h2> +<p>Drycc follows the timeless, highly efficient and totally unfair system known as <a href="http://en.wikipedia.org/wiki/Benevolent_Dictator_for_Life">Benevolent dictator +for life</a>.</p> +<p>Gabriel Monroy (<a href="https://github.com/gabrtv">@gabrtv</a>), as creator of the Drycc project, serves as our +project&rsquo;s BDFL. While the day-to-day project management is carried out by the maintainers, Gabriel +serves as the final arbiter of any disputes and has the final say on project direction.</p> +<h2 id="core-maintainers">Core maintainers<a class="td-heading-self-link" href="#core-maintainers" aria-label="Heading self-link"></a></h2> +<p>Core maintainers are exceptionally knowledgeable about all areas of Drycc. Some maintainers work on Drycc +full-time, although this is not a requirement.</p> +<p>The duties of a core maintainer include:</p> +<ul> +<li>Classify and respond to GitHub issues and review pull requests</li> +<li>Help to shape the Drycc roadmap and lead efforts to accomplish roadmap milestones</li> +<li>Participate actively in feature development and bug fixing</li> +<li>Answer questions and help users in the <a href="https://slack.drycc.cc">Drycc #community Slack channel</a></li> +</ul> +<p>The current list of core maintainers can be seen <a href="https://github.com/orgs/drycc/teams/core-maintainers">here</a>.</p> +<p>No pull requests can be merged until at least one core maintainer signs off with an +<a href="http://docs.drycc.cc/en/latest/contributing/standards/#merge-approval">LGTM</a>. The other LGTM can +come from either a core maintainer or contributing maintainer.</p> +<h2 id="contributing-maintainers">Contributing maintainers<a class="td-heading-self-link" href="#contributing-maintainers" aria-label="Heading self-link"></a></h2> +<p>Contributing maintainers are exceptionally knowledgeable about some but not necessarily all areas +of Drycc, and are often selected due to specific domain knowledge that complements the project (but +a willingness to continually contribute to the project is most important!). Often, +core maintainers will ask a contributing maintainer to weigh in on issues, pull requests, or +conversations where the contributing maintainer is knowledgeable.</p> +<p>The duties of a contributing maintainer are very similar to those of a core maintainer, but they are limited to areas of the Drycc project where the contributing maintainer is knowledgeable.</p> +<p>Contributing maintainers are defined in practice as those who have write access to the Drycc repository. All maintainers can review pull requests and add LGTM labels as appropriate.</p> +<h2 id="becoming-a-maintainer">Becoming a maintainer<a class="td-heading-self-link" href="#becoming-a-maintainer" aria-label="Heading self-link"></a></h2> +<p>The Drycc project wouldn&rsquo;t be where it is today without its community. Many of the project&rsquo;s +community members embody the spirit of maintainership, and have contributed substantially to +the project.</p> +<p>The contributing maintainers group was created in part so that exceptional members of the community +who have an interest in the continued success of the project have the opportunity to join the +core maintainers in guiding the future of Drycc.</p> +<p>Generally, potential contributing maintainers are selected by the Drycc core maintainers based in +part on the following criteria:</p> +<ul> +<li>Sustained contributions to the project over a period of time (usually months)</li> +<li>A willingness to help Drycc users on GitHub and in the <a href="https://slack.drycc.cc">Drycc #community Slack channel</a></li> +<li>A friendly attitude :)</li> +</ul> +<p>The Drycc core maintainers must unanimously agree before inviting a community member to join as a +contributing maintainer, although in many cases the candidate has already been acting in the +capacity of a contributing maintainer for some time, and has been consulted on issues, pull requests, +etc.</p> + + + + + + diff --git a/docs/contribution-guidelines/maintainers/index.html b/docs/contribution-guidelines/maintainers/index.html new file mode 100644 index 000000000..60cb7872c --- /dev/null +++ b/docs/contribution-guidelines/maintainers/index.html @@ -0,0 +1,525 @@ + + + + + + + + + + + + + + + + + + + +Drycc Maintainers | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Drycc Maintainers

+
This document serves to describe the leadership structure of the Drycc project, and list the current project maintainers.
+ +

What is a maintainer?

+

(Unabashedly stolen from the Podman project)

+

There are different types of maintainers, with different responsibilities, but +all maintainers have 3 things in common:

+
    +
  1. They share responsibility in the project’s success.
  2. +
  3. They have made a long-term, recurring time investment to improve the project.
  4. +
  5. They spend that time doing whatever needs to be done, not necessarily what +is the most interesting or fun.
  6. +
+

Maintainers are often under-appreciated, because their work is harder to appreciate. +It’s easy to appreciate a really cool and technically advanced feature. It’s harder +to appreciate the absence of bugs, the slow but steady improvement in stability, +or the reliability of a release process. But those things distinguish a good +project from a great one.

+

Drycc maintainers

+

Drycc has two groups of maintainers in addition to our beloved Benevolent Dictator for Life.

+

BDFL

+

Drycc follows the timeless, highly efficient and totally unfair system known as Benevolent dictator +for life.

+

Gabriel Monroy (@gabrtv), as creator of the Drycc project, serves as our +project’s BDFL. While the day-to-day project management is carried out by the maintainers, Gabriel +serves as the final arbiter of any disputes and has the final say on project direction.

+

Core maintainers

+

Core maintainers are exceptionally knowledgeable about all areas of Drycc. Some maintainers work on Drycc +full-time, although this is not a requirement.

+

The duties of a core maintainer include:

+
    +
  • Classify and respond to GitHub issues and review pull requests
  • +
  • Help to shape the Drycc roadmap and lead efforts to accomplish roadmap milestones
  • +
  • Participate actively in feature development and bug fixing
  • +
  • Answer questions and help users in the Drycc #community Slack channel
  • +
+

The current list of core maintainers can be seen here.

+

No pull requests can be merged until at least one core maintainer signs off with an +LGTM. The other LGTM can +come from either a core maintainer or contributing maintainer.

+

Contributing maintainers

+

Contributing maintainers are exceptionally knowledgeable about some but not necessarily all areas +of Drycc, and are often selected due to specific domain knowledge that complements the project (but +a willingness to continually contribute to the project is most important!). Often, +core maintainers will ask a contributing maintainer to weigh in on issues, pull requests, or +conversations where the contributing maintainer is knowledgeable.

+

The duties of a contributing maintainer are very similar to those of a core maintainer, but they are limited to areas of the Drycc project where the contributing maintainer is knowledgeable.

+

Contributing maintainers are defined in practice as those who have write access to the Drycc repository. All maintainers can review pull requests and add LGTM labels as appropriate.

+

Becoming a maintainer

+

The Drycc project wouldn’t be where it is today without its community. Many of the project’s +community members embody the spirit of maintainership, and have contributed substantially to +the project.

+

The contributing maintainers group was created in part so that exceptional members of the community +who have an interest in the continued success of the project have the opportunity to join the +core maintainers in guiding the future of Drycc.

+

Generally, potential contributing maintainers are selected by the Drycc core maintainers based in +part on the following criteria:

+
    +
  • Sustained contributions to the project over a period of time (usually months)
  • +
  • A willingness to help Drycc users on GitHub and in the Drycc #community Slack channel
  • +
  • A friendly attitude :)
  • +
+

The Drycc core maintainers must unanimously agree before inviting a community member to join as a +contributing maintainer, although in many cases the candidate has already been acting in the +capacity of a contributing maintainer for some time, and has been consulted on issues, pull requests, +etc.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/contribution-guidelines/overview/index.html b/docs/contribution-guidelines/overview/index.html new file mode 100644 index 000000000..3dd943572 --- /dev/null +++ b/docs/contribution-guidelines/overview/index.html @@ -0,0 +1,479 @@ + + + + + + + + + + + + + + + + + + + +Contributor Overview | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Contributor Overview

+
Interested in contributing to a Drycc project? There are lots of ways to help.
+ +

File Bugs & Enhancements

+

Find a bug? Want to see a new feature? Have a request for the maintainers? Open a Github issue in the applicable repository and we’ll get the conversation started.

+

Our official support channel is the Drycc #community Slack channel.

+

Don’t know what the applicable repository for an issue is? Open up in issue in workflow or chat with a maintainer in the Drycc #community Slack channel and we’ll make sure it gets to the right place.

+

Additionally, take a look at the troubleshooting documentation for common issues.

+

Before opening a new issue, it’s helpful to search and see if anyone else has already reported the problem. You can search through a list of issues for all Drycc projects here.

+

Write Documentation

+

We are always looking to improve and expand our documentation. Most docs reside in the drycc/workflow repository. Simply fork the project, update docs and send us a pull request.

+

Contribute Code

+

We are always looking for help improving the core platform, other workloads, tooling, and test coverage. Interested in contributing code? Let’s chat in the Drycc #community Slack channel. Make sure to check out issues tagged easy fix or help wanted.

+

When you’re ready to begin writing code, review Design Documents and get your Development Environment set up.

+

By contributing to any Drycc project you agree to its Developer Certificate of Origin (DCO). This document was created by the Linux Kernel community and is a simple statement that you, as a contributor, have the legal right to make the contribution.

+

Triage Issues

+

If you don’t have time to code, consider helping with triage. The community will thank you for saving them time by spending some of yours. See Triaging Issues for more info.

+

Share your Experience

+

Interact with the community on our user mailing list or live in our Drycc #community Slack channel, where you can chat with other Drycc Workflow users any time of day.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/contribution-guidelines/submitting-a-pull-request/index.html b/docs/contribution-guidelines/submitting-a-pull-request/index.html new file mode 100644 index 000000000..c6dd29985 --- /dev/null +++ b/docs/contribution-guidelines/submitting-a-pull-request/index.html @@ -0,0 +1,531 @@ + + + + + + + + + + + + + + + + + + + +Submitting a Pull Request | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Submitting a Pull Request

+
Proposed changes to Drycc projects are made as GitHub pull requests.
+ +

Design Document

+

Before opening a pull request, ensure your change also references a design document if the contribution is substantial. For more information, see Design Documents.

+

Single Issue

+

It’s hard to reach agreement on the merit of a PR when it isn’t focused. When fixing an issue or implementing a new feature, resist the temptation to refactor nearby code or to fix that potential bug you noticed. Instead, open a separate issue or pull request. Keeping concerns separated allows pull requests to be tested, reviewed, and merged more quickly.

+

Squash and rebase the commit or commits in your pull request into logical units of work with git. Include tests and documentation changes in the same commit, so that a revert would remove all traces of the feature or fix.

+

Most pull requests will reference a GitHub issue. In the PR description - not in the commit itself - include a line such as “closes #1234”. The issue referenced will automatically be closed when your PR is merged.

+

Include Tests

+

If you significantly alter or add functionality to a component that impacts the broader Drycc Workflow PaaS, you should submit a complementary PR to modify or amend end-to-end integration tests. These integration tests can be found in the drycc/workflow-e2e repository.

+

See testing for more information.

+

Include Docs

+

Changes to any Drycc Workflow component that could affect a user’s experience also require a change or addition to the relevant documentation. For most Drycc components, this involves updating the component’s own documentation. In some cases where a component is tightly integrated into drycc/workflow, its documentation must also be updated.

+

Cross-repo commits

+

If a pull request is part of a larger piece of work involving one or more additional commits in other Workflow repositories, these commits can be referenced in the last PR to be submitted. The downstream e2e test job will then supply every referenced commit (derived from PR issue number supplied) to the test runner so it can source the necessary Container images for inclusion in the generated Workflow chart to be tested.

+

For example, consider paired commits in drycc/controller and drycc/workflow-e2e. The commit body for the first PR in drycc/workflow-e2e would look like:

+
feat(foo_test): add e2e test for feature foo
+
+[skip e2e] test for controller#42
+

Adding [skip e2e] forgoes the e2e tests on this commit. This and any other required PRs aside from the final PR should be submitted first, so that their respective build and image push jobs run.

+

Lastly, the final PR in drycc/controller should be created with the required PR number(s) listed, in the form of [Rr]equires <repoName>#<pullRequestNumber>, for use by the downstream e2e run.

+
feat(foo): add feature foo
+
+Requires workflow-e2e#42
+

Code Standards

+

Drycc components are implemented in Go and Python. For both languages, we agree with The Zen of Python, which emphasizes simple over clever. Readability counts.

+

Go code should always be run through gofmt on the default settings. Lines of code may be up to 99 characters long. Documentation strings and tests are required for all exported functions. Use of third-party go packages should be minimal, but when doing so, such dependencies should be managed via the glide tool.

+

Python code should always adhere to PEP8, the python code style guide, with the exception that lines of code may be up to 99 characters long. Docstrings and tests are required for all public methods, although the flake8 tool used by Drycc does not enforce this.

+

Commit Style

+

We follow a convention for commit messages borrowed from CoreOS, who borrowed theirs +from AngularJS. This is an example of a commit:

+
feat(scripts/test-cluster): add a cluster test command
+
+this uses tmux to setup a test cluster that you can easily kill and
+start for debugging.
+

To make it more formal, it looks something like this:

+
{type}({scope}): {subject}
+<BLANK LINE>
+{body}
+<BLANK LINE>
+{footer}
+

The allowed {types} are as follows:

+
    +
  • feat -> feature
  • +
  • fix -> bug fix
  • +
  • docs -> documentation
  • +
  • style -> formatting
  • +
  • ref -> refactoring code
  • +
  • test -> adding missing tests
  • +
  • chore -> maintenance
  • +
+

The {scope} can be anything specifying the location(s) of the commit change(s).

+

The {subject} needs to be an imperative, present tense verb: “change”, not “changed” nor +“changes”. The first letter should not be capitalized, and there is no dot (.) at the end.

+

Just like the {subject}, the message {body} needs to be in the present tense, and includes +the motivation for the change, as well as a contrast with the previous behavior. The first +letter in a paragraph must be capitalized.

+

All breaking changes need to be mentioned in the {footer} with the description of the +change, the justification behind the change and any migration notes required.

+

Any line of the commit message cannot be longer than 72 characters, with the subject line +limited to 50 characters. This allows the message to be easier to read on GitHub as well +as in various git tools.

+

Merge Approval

+

Any code change - other than a simple typo fix or one-line documentation change - requires at least two Drycc maintainers to accept it. Maintainers tag pull requests with “LGTM1” and “LGTM2” (Looks Good To Me) labels to indicate acceptance.

+

No pull requests can be merged until at least one core maintainer signs off with an LGTM. The other LGTM can come from either a core maintainer or contributing maintainer.

+

If the PR is from a Drycc maintainer, then he or she should be the one to close it. This keeps the commit stream clean and gives the maintainer the benefit of revisiting the PR before deciding whether or not to merge the changes.

+

An exception to this is when an errant commit needs to be reverted urgently. If necessary, a PR that only reverts a previous commit can be merged without waiting for LGTM approval.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/contribution-guidelines/testing/index.html b/docs/contribution-guidelines/testing/index.html new file mode 100644 index 000000000..914e30675 --- /dev/null +++ b/docs/contribution-guidelines/testing/index.html @@ -0,0 +1,476 @@ + + + + + + + + + + + + + + + + + + + +Testing Drycc | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Testing Drycc

+
Each Drycc component is one among an ecosystem of such components - many of which integrate with one another - which makes testing each component thoroughly a matter of paramount importance.
+ +

Each Drycc component includes its own suite of style checks, unit tests, and black-box type functional tests.

+

Integration tests verify the behavior of the Drycc components together as a system and are provided separately by the drycc/workflow-e2e project.

+

GitHub pull requests for all Drycc components are tested automatically by the Travis CI continuous integration system. Contributors should run the same tests locally before proposing any changes to the Drycc codebase.

+

Set Up the Environment

+

Successfully executing the unit and functional tests for any Drycc component requires that the Development Environment is set up first.

+

Run the Tests

+

The style checks, unit tests, and functional tests for each component can all be executed via make targets:

+

To execute style checks:

+
$ make test-style
+

To execute unit tests:

+
$ make test-unit
+

To execute functional tests:

+
$ make test-functional
+

To execute style checks, unit tests, and functional tests all in one shot:

+
$ make test
+

To execute integration tests, refer to drycc/workflow-e2e documentation.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/contribution-guidelines/triaging-issues/index.html b/docs/contribution-guidelines/triaging-issues/index.html new file mode 100644 index 000000000..da124e739 --- /dev/null +++ b/docs/contribution-guidelines/triaging-issues/index.html @@ -0,0 +1,556 @@ + + + + + + + + + + + + + + + + + + + +Triaging Issues | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Triaging Issues

+
Issue triage provides an important way to contribute to an open source project.
+ +

Triage helps ensure issues resolve quickly by:

+
    +
  • Describing the issue’s intent and purpose is conveyed precisely. This is necessary because it can be difficult for an issue to explain how an end user experiences an problem and what actions they took.
  • +
  • Giving a contributor the information they need before they commit to resolving an issue.
  • +
  • Lowering the issue count by preventing duplicate issues.
  • +
  • Streamlining the development process by preventing duplicate discussions.
  • +
+

If you don’t have time to code, consider helping with triage. The community will thank you for saving them time by spending some of yours.

+

Ensure the Issue Contains Basic Information

+

Before triaging an issue very far, make sure that the issue’s author provided the standard issue information. This will help you make an educated recommendation on how this to categorize the issue. Standard information that should be included in most issues are things such as:

+
    +
  • the version(s) of Drycc this issue affects
  • +
  • a reproducible case if this is a bug
  • +
  • page URL if this is a docs issue or the name of a man page
  • +
+

Depending on the issue, you might not feel all this information is needed. Use your best judgment. If you cannot triage an issue using what its author provided, explain kindly to the author that they must provide the above information to clarify the problem.

+

If the author provides the recommended information but you are still unable to triage the issue, request additional information. Do this kindly and politely because you are asking for more of the author’s time.

+

If the author does not respond requested information within the timespan of a week, close the issue with a kind note stating that the author can request for the issue to be reopened when the necessary information is provided.

+

Classifying the Issue

+

An issue can have multiple of the following labels:

+

Issue Kind

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KindDescription
bugBugs are bugs. The cause may or may not be known at triage time so debugging should be taken account into the time estimate.
docsWriting documentation, man pages, articles, blogs, or other significant word-driven task.
enhancementEnhancements can drastically improve usability or performance of a component.
questionContains a user or contributor question requiring a response.
securitySecurity-related issues such as TLS encryption, network segregation, authn/authz features, etc.
+

Functional Area

+
    +
  • builder
  • +
  • cache
  • +
  • contrib and provisioning
  • +
  • client
  • +
  • controller
  • +
  • database
  • +
  • docs
  • +
  • kubernetes
  • +
  • registry
  • +
  • router
  • +
  • store (Ceph)
  • +
  • tests
  • +
+

Easy Fix

+

“Easy Fix” issues are a way for a new contributor to find issues that are fit for their experience level. These issues are typically for users who are new to Drycc, and possibly Go, and is looking to help while learning the basics.

+

Prioritizing issues

+

When attached to a specific milestone, an issue can be attributed one of the following labels to indicate their degree of priority.

+ + + + + + + + + + + + + + + + + +
PriorityDescription
priority 0Urgent: Security, critical bugs, blocking issues. Drop everything and fix this today, then consider creating a patch release.
priority 1Serious: Impedes user actions or is a regression. Fix this before the next planned release.
+

And that’s it. That should be all the information required for a new or existing contributor to come in an resolve an issue.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/diagrams/Application_Layout.png b/docs/diagrams/Application_Layout.png new file mode 100644 index 0000000000000000000000000000000000000000..c52cd7cc575b69ad709022dc65b3b80d4d18a04a GIT binary patch literal 74455 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 ^(AfQMtVLN{3YT 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%0AxvBLfwzZr(h>Jo7RgSoz3ae)N49LX}z+=j# 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 o5O-1gSH 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®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�- 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

#f7OIgX}^mGs+jp}W_vtr_pY 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 literal 0 HcmV?d00001 diff --git a/docs/diagrams/Workflow_Detail.png b/docs/diagrams/Workflow_Detail.png new file mode 100644 index 0000000000000000000000000000000000000000..fe4980009407a1db9d089c0e0912a6d36b00889e GIT binary patch literal 45357 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 QE_i6DYG2H|a5L!t0n>cgxBvhE literal 0 HcmV?d00001 diff --git a/docs/diagrams/Workflow_Overview.jpg b/docs/diagrams/Workflow_Overview.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fe37885eaa3edd700a7d7445f6ae63cfc3057e10 GIT binary patch literal 96949 zcmeFZcUV*3)-D=BM3gEZMKDTL10o0FKjiG7JFv6G8wwjuZ48CyrYHK-wo6PW;vW4Eobf z(9xe{IK_CH>C9Q$fHHOf-3fYnx|8$_3@2%qKH*0@4miodaPG47?NgivPZ@>WxMcjJ zznm7nQ`E?9*hdhNefIJ#)0y);ynOtkV&Ye>Ub`tLub`-;eD|KZhUR@OZ6jk7Q|Kcz zbL;0ews!Uoj_$8KJiWYqUI)B;9~cxI5*ia57oU*$F)2AcBQxu3c24fM;*!#`@`}o; z>ZazF*0%N^9Y6aA28V`6M#si+_}RJng~g@i72?+R&hFkm>EQ5>T(nvF?_$v&|EXLY zG`Z+bo}@p?_(!f2bY6c1=Qzo5S^Ctu+XjqJ-8hA0{7-Y;iT+a5$RsRlNZ@|cKD(>$u z#zU5EffJnbf7Oq_q^048n2F_JpJP%Cu$(;B}BzNN9+0T*I1Kdspm|ta-)^X8lyN zc-v@?OZnt6fGD?K8-G`O$eL&LppwY-&3E+mxm4dZbXHHfJtpKBfYYM(!gf?pbL&0F z08UNvRmk{RYLE;0Q`Ip5?|`zQP3-4jswm0{k6Jnpdkr2QE57<+*qa2+26Q7DYL!Nn~5E)u+&PZfZ_&L0gUi|2T@ugixOVn}565Wl9C@#y*?*Egd}zC87V*u%=kbXY7*aF`#1tO%;n;`v%$J0JcENiIAPM zQgy%=1~ATJz&{Kk8KO#gD6G>5D(=UCmOe_nCiSf_DQIs>oa%40pRpba!lV9S%rW4M z{@&YTz?X?*fVeY?lng1(IR^CJL$OmQXwvjb)bIEesU!6N^SFPQ(>)X5;pr$maKamX z$dEV{Ret4vJMs3^pBcx1+Z^P(M=msBZWSN(?X_|fA^&lC?Elk3j2WYrgdoBHUafzx z*1x}7|H7#K`@8jTOZacU^>4rR|MMs#!*>QUuG09S90SLn8u|s14zY`IW;~L4!y*@F z_*$dZWt+1H-fH>C!D6nbDhGoGGb8Md0q^#^dgVy(zgF3UZI(pnbLoo&Tm2Xcbf#vV*^V>-TzaB|UUexheF@XS#pdL8(MYSgq_#myE7mt8%!qQ|etYtrS5u zMkCT02ZeM_2T(~yI##I`bqrt-AX(#%lJZqAe4SkFZ@F(qD4M`lidGy0X3MtMH_2R! z?dM`7YJoO@HQnYSieU{dek2Bab-}pXmFW2rV!MQCqbN|%c;Q>3IgJT6nbC_2_8X7o z)dCwJ=7%U8hRk(#W;4PW-%q|(aZ#W;mfr7YzzOS7ne#5c&X~yjBtqS;CAb8o6i4qz zaHGFERy&v3oX^OdZ1;lSV2-)h7#FYsx>L!oCi3^fvK{yRD`4{Fo1>?>{3rKsD~9>! z%cDzUe*EUp)_P32BHZ^^nN@tMKNk=Z&#j`keyT z^c0t4CwEn${?JjIQ3h?*eo|CGm%EZ_Y&fhM%bp$z8dPS64 z?YOBZ7vcT$p;s^o;9oSo0sLbJ&AW{E7*&=Kz-XJZ9D=)39gI2ZQxF4~@yHKs**-b+ zH4g<@K@F8#os-t*(WB5nK_lKr?#;Imm%;t%Ky!wuAOu_HqfreG^C_iA{+&0&YGZtN z3-@Rkh3OdZBQFCr5|5>ZnJ=Y{8?%7nJei<%5>KGaCh06^OMX_IyO^uaO`deD$Go(mVv+L6N>Xk&W=m^9)%X$vXr z9c9wHEBc66I^l;E-BZSsKtmbO7+91PdenqGIgC*MI`jKcW4&6lu;+{tc@-nmIM}4s zR9vFH*nx9T=KkKptvhw?7!bJVu8!0`1~kLSR>uHz4rH?hMb>@o(%3U@jfaKT3olLa z4KD`jfEGPINZijpd*Mdo88!o$luj^VJLYZOboACo{d2`DLr*o%Kx4HWru7z=*0~HU ziH86Kb*}%*t}a2iRkINN@O4ouU`�$i{;;=+chRr&|nM2DccvnG@v+$AE%pqm^6P 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 literal 0 HcmV?d00001 diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 000000000..03c0d9b49 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,537 @@ + + + + + + + + + + + + + + + + + + + + + +Docs | Drycc + + + + + + + + + + + + + + + + + + + + + +

+ +
+
+
+
+ + +
+ + + + + +
+

Docs

+ + + + +
+

A Open, Unified, Lightweight, Simpler Containers as a Service (CaaS).

+ +
+ +

Welcome to Drycc

+

Drycc Workflow is an open source container cloud platform.

+

Usually we also call it Container as a Service(CaaS) that adds a developer-friendly layer +to any Kubernetes cluster, making it easy to deploy and manage applications.

+

Drycc Workflow includes capabilities for building and deploying from source via git push, simple +application configuration, creating and rolling back releases, managing domain names and SSL +certificates, providing seamless edge routing, aggregating logs, and sharing applications with +teams. All of this is exposed through a simple REST API and command line interface.

+

Getting Started

+

To get started with Workflow, follow our Quick Start guide.

+

Take a deep dive into Drycc Workflow in our Concepts, Architecture, and +Components sections.

+

Feel like contibuting some code or want to get started as a maintainer? Pick an issue tagged as an +easy fix or help wanted and start contributing!

+ +
+ + +
+
+
+ Quick Start +
+

Step-by-step guides for deploying your first app and mastering the basics of Drycc.

+
+
+
+ Understanding Workflow +
+

Understanding the architecture design of workflow.

+
+
+
+ Installing To Kubenetes +
+

Deploying Drycc on a Kubernetes Cluster.

+
+
+
+ Users +
+

In this tutorial, you’ll learn how to manage users.

+
+
+
+ Applications +
+

A simple and scalable cloud platform for all developer needs.

+
+
+
+ Managing Workflow +
+

Managing Workflow using the kubectl.

+
+
+
+ Troubleshooting +
+

Troubleshooting is systematic approach to problem-solving.

+
+
+
+ Roadmap +
+

Browse the ever-growing list of up-to-date, community driven roadmaps.

+
+
+
+ Contribution Guidelines +
+

This HowTo is for project maintainers who need a Contributing Guide for their project.

+
+
+
+ Reference Guide +
+

Reference gxwuide definition and meaning.

+
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+
+ +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/index.xml b/docs/index.xml new file mode 100644 index 000000000..51fd5534a --- /dev/null +++ b/docs/index.xml @@ -0,0 +1,8052 @@ + + + Drycc – Docs + /docs/ + Recent content in Docs on Drycc + Hugo -- gohugo.io + en + + + + + + + + + + + Docs: Drycc Workflow CLI + /docs/users/cli/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/users/cli/ + + + + <p>The Drycc Workflow command-line interface (CLI), or client, allows you to interact +with Drycc Workflow.</p> +<h2 id="installation">Installation<a class="td-heading-self-link" href="#installation" aria-label="Heading self-link"></a></h2> +<p>Install the latest <code>drycc</code> client for Linux or Mac OS X with: +$ curl -sfL <a href="https://www.drycc.cc/install-cli.sh">https://www.drycc.cc/install-cli.sh</a> | bash -</p> +<p>The installer puts <code>drycc</code> in your current directory, but you should move it +somewhere in your $PATH:</p> +<pre><code>$ ln -fs $PWD/drycc /usr/local/bin/drycc +</code></pre> +<h2 id="getting-help">Getting Help<a class="td-heading-self-link" href="#getting-help" aria-label="Heading self-link"></a></h2> +<p>The Drycc client comes with comprehensive documentation for every command. +Use <code>drycc help</code> to explore the commands available to you:</p> +<pre><code>$ drycc help +The Drycc command-line client issues API calls to a Drycc controller. + +Usage: drycc &lt;command&gt; [&lt;args&gt;...] + +Auth commands:: + + login login to a controller + logout logout from the current controller + +Subcommands, use `drycc help [subcommand]` to learn more:: +... +</code></pre> +<p>To get help on subcommands, use <code>drycc help [subcommand]</code>:</p> +<pre><code>$ drycc help apps +Valid commands for apps: + +apps:create create a new application +apps:list list accessible applications +apps:info view info about an application +apps:open open the application in a browser +apps:logs view aggregated application logs +apps:run run a command in an ephemeral app container +apps:destroy destroy an application +apps:transfer transfer app ownership to another user + +Use `drycc help [command]` to learn more +</code></pre> +<h2 id="support-for-multiple-profiles">Support for Multiple Profiles<a class="td-heading-self-link" href="#support-for-multiple-profiles" aria-label="Heading self-link"></a></h2> +<p>The CLI reads from the default <code>client</code> profile, which is located on your +workstation at <code>$HOME/.drycc/client.json</code>.</p> +<p>Easily switch between multiple Drycc Workflow installations or users by setting +the <code>$DRYCC_PROFILE</code> environment variable or by using the <code>-c</code> flag.</p> +<p>There are two ways to set the <code>$DRYCC_PROFILE</code> option.</p> +<ol> +<li>Path to a json configuration file.</li> +<li>Profile name. If you set profile to just a name, it will be saved alongside the default profile, +in <code>$HOME/.drycc/&lt;name&gt;.json</code>.</li> +</ol> +<p>Examples:</p> +<pre><code>$ DRYCC_PROFILE=production drycc login drycc.production.com +... +Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71 +Waiting for login... .o.Logged in as drycc +Configuration saved to /home/testuser/.drycc/production.json +$ DRYCC_PROFILE=~/config.json drycc login drycc.example.com +... +Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71 +Waiting for login... .o.Logged in as drycc +Configuration saved to /home/testuser/config.json +</code></pre> +<p>The configuration flag works identically to and overrides <code>$DRYCC_PROFILE</code>:</p> +<pre><code>$ drycc whoami -c ~/config.json +You are drycc at drycc.example.com +</code></pre> +<h2 id="proxy-support">Proxy Support<a class="td-heading-self-link" href="#proxy-support" aria-label="Heading self-link"></a></h2> +<p>If your workstation uses a proxy to reach the network where the cluster lies, +set the <code>http_proxy</code> or <code>https_proxy</code> environment variable to enable proxy support:</p> +<pre><code>$ export http_proxy=&quot;http://proxyip:port&quot; +$ export https_proxy=&quot;http://proxyip:port&quot; +</code></pre> +<p>!!! note +Configuring a proxy is generally not necessary for local Minikube clusters.</p> +<h2 id="cli-plugins">CLI Plugins<a class="td-heading-self-link" href="#cli-plugins" aria-label="Heading self-link"></a></h2> +<p>Plugins allow developers to extend the functionality of the Drycc Client, adding new commands or features.</p> +<p>If an unknown command is specified, the client will attempt to execute the command as a dash-separated command. In this case, <code>drycc resource:command</code> will execute <code>drycc-resource</code> with the argument list <code>command</code>. In full form:</p> +<pre><code>$ # these two are identical +$ drycc accounts:list +$ drycc-accounts list +</code></pre> +<p>Any flags after the command will also be sent to the plugin as an argument:</p> +<pre><code>$ # these two are identical +$ drycc accounts:list --debug +$ drycc-accounts list --debug +</code></pre> +<p>But flags preceding the command will not:</p> +<pre><code>$ # these two are identical +$ drycc --debug accounts:list +$ drycc-accounts list +</code></pre> + + + + + + Docs: Concepts + /docs/understanding-workflow/concepts/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/understanding-workflow/concepts/ + + + + <h2 id="twelve-factor-applications">Twelve-Factor Applications<a class="td-heading-self-link" href="#twelve-factor-applications" aria-label="Heading self-link"></a></h2> +<p>The <a href="http://12factor.net/">Twelve-Factor App</a> is a methodology for building modern +applications that can be scaled across a distributed system.</p> +<p>Twelve-factor is a valuable synthesis of years of experience with +software-as-a-service apps in the wild, particularly on the +Heroku platform.</p> +<p>Workflow is designed to run applications that adhere to the <a href="http://12factor.net/">Twelve-Factor App</a> +methodology and best practices.</p> +<h2 id="kubernetes">Kubernetes<a class="td-heading-self-link" href="#kubernetes" aria-label="Heading self-link"></a></h2> +<p><a href="https://kubernetes.io">Kubernetes</a> is an open-source cluster manager developed by Google and +donated to the <a href="https://cncf.io/">Cloud Native Compute Foundation</a>. Kubernetes manages all +the activity on your cluster, including: desired state convergence, stable +service addresses, health monitoring, service discovery, and DNS resolution.</p> +<p>Workflow builds upon Kubernetes abstractions like Services, +Deployments and Pods to provide a developer-friendly experience. +Building containers directly from application source code, aggregating logs, +and managing deployment configurations and app releases are just some of the +features Workflow adds.</p> +<p>Drycc Workflow is a set of Kubernetes-native components, installable via +<a href="https://github.com/kubernetes/helm">Helm</a>. Systems engineers who are familiar with Kubernetes will feel right +at home running Workflow.</p> +<p>See the <a href="/docs/understanding-workflow/components/">components</a> overview for more detail.</p> +<h2 id="container">Container<a class="td-heading-self-link" href="#container" aria-label="Heading self-link"></a></h2> +<p>[Container][] is an open source project to build, ship and run any +application as a lightweight, portable, self-sufficient container.</p> +<p>If you have not yet converted your application to containers, Workflow provides +a simple and straightforward &ldquo;source to Container image&rdquo; capability. Supporting +multiple language runtimes via community <a href="/docs/applications/using-buildpacks/">buildpacks</a>, building your application +in a container can be as easy as <code>git push drycc master</code>.</p> +<p>Applications which use either a Dockerfile or reference external Container +images are launched unmodified.</p> +<h2 id="applications">Applications<a class="td-heading-self-link" href="#applications" aria-label="Heading self-link"></a></h2> +<p>Workflow is designed around the concept of an <a href="../reference-guide/terms.md#application">application</a>, or app.</p> +<p>Applications come in one of three forms:</p> +<ol> +<li>a collection of source files stored in a <code>git</code> repository</li> +<li>a Dockerfile and associated source files stored in a <code>git</code> repository</li> +<li>a reference to an existing image at a Container repository</li> +</ol> +<p>Applications are identified by a unique name for easy reference. If you do not +specify a name when creating your application, Workflow generates one for you. +Workflow also manages related information, including domain names, SSL +certificates, and developer-provided configuration.</p> +<h2 id="build-release-run">Build, Release, Run<a class="td-heading-self-link" href="#build-release-run" aria-label="Heading self-link"></a></h2> +<p><img alt="Git Push Workflow" src="../../diagrams/Git_Push_Flow.png"></p> +<h3 id="build-stage">Build Stage<a class="td-heading-self-link" href="#build-stage" aria-label="Heading self-link"></a></h3> +<p>The <a href="/docs/understanding-workflow/components/#builder">builder</a> component processes incoming <code>git push drycc master</code> requests +and manages your application packaging.</p> +<p>If your application is using a <a href="/docs/applications/using-buildpacks/">buildpack</a>, builder will launch an ephemeral +job to extract and execute the packaging instructions. The resulting +application artifact is stored by the platform for execution during the run +stage.</p> +<p>If instead builder finds a <a href="/docs/applications/using-dockerfiles/">Dockerfile</a>, it follows those instructions to +create a Container image. The resulting artifact is stored in a Drycc-managed registry which +will be referenced during the run stage.</p> +<p>If another system already builds and packages your application, that container +artifact can be used directly. When referencing an <a href="/docs/applications/using-container-images/">external Container +image</a>, the builder component doesn&rsquo;t attempt to repackage your +app.</p> +<h3 id="release-stage">Release Stage<a class="td-heading-self-link" href="#release-stage" aria-label="Heading self-link"></a></h3> +<p>During the release stage, a <a href="../reference-guide/terms.md#build">build</a> is combined with <a href="../reference-guide/terms.md#config">application configuration</a> +to create a new, numbered <a href="../reference-guide/terms.md#release">release</a>. New releases are created any time a new +build is created or application configuration is changed. Tracking releases as a +&ldquo;write-only ledger&rdquo; this way makes it easy to rollback to any previous release.</p> +<h3 id="run-stage">Run Stage<a class="td-heading-self-link" href="#run-stage" aria-label="Heading self-link"></a></h3> +<p>The run stage deploys the new release to the underlying Kubernetes cluster by +changing the Deployment object which references the new release. +By managing the desired replica count, Workflow +orchestrates a zero-downtime, rolling update of your application. Once +successfully updated, Workflow removes the last reference to the old release. +Note that during the deploy, your application will be running in a mixed mode.</p> +<h2 id="backing-services">Backing Services<a class="td-heading-self-link" href="#backing-services" aria-label="Heading self-link"></a></h2> +<p>Workflow treats all persistent services such as databases, caches, storage, +messaging systems, and other <a href="http://12factor.net/backing-services">backing services</a> as resources managed +separately from your application. This philosophy aligns with Twelve-Factor +best practices.</p> +<p>Applications attach to backing services using <a href="http://12factor.net/config">environment variables</a>. +Because apps are decoupled from backing services, they are free to +scale up independently, to use services provided by other apps, or to switch +to external or third-party vendor services.</p> +<h2 id="see-also">See Also<a class="td-heading-self-link" href="#see-also" aria-label="Heading self-link"></a></h2> +<ul> +<li><a href="/docs/understanding-workflow/architecture/">Workflow Architecture</a></li> +<li><a href="/docs/understanding-workflow/components/">Workflow Components</a></li> +</ul> + + + + + + Docs: Creating a Self-Signed SSL Certificate + /docs/reference-guide/creating-a-self-signed-ssl-certificate/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/reference-guide/creating-a-self-signed-ssl-certificate/ + + + + <p>When <a href="/docs/applications/ssl-certificates/">using the app ssl</a> feature for non-production applications or when <a href="https://gateway-api.sigs.k8s.io/guides/tls/">installing SSL for the platform</a>, you can avoid the costs associated with the SSL certificate by using a self-signed SSL certificate. Though the certificate implements full encryption, visitors to your site will see a browser warning indicating that the certificate should not be trusted.</p> +<h2 id="prerequisites">Prerequisites<a class="td-heading-self-link" href="#prerequisites" aria-label="Heading self-link"></a></h2> +<p>The openssl library is required to generate your own certificate. Run the following command in your local environment to see if you already have openssl installed.</p> +<pre><code>$ which openssl +/usr/bin/openssl +</code></pre> +<p>If the which command does not return a path then you will need to install openssl yourself:</p> +<table> +<thead> +<tr> +<th>If you have&hellip;</th> +<th>Install with&hellip;</th> +</tr> +</thead> +<tbody> +<tr> +<td>Mac OS X</td> +<td>Homebrew: <code>brew install openssl</code></td> +</tr> +<tr> +<td>Windows</td> +<td>complete package .exe installed</td> +</tr> +<tr> +<td>Ubuntu Linux</td> +<td><code>apt-get install openssl</code></td> +</tr> +</tbody> +</table> +<h2 id="generate-private-key-and-certificate-signing-request">Generate Private Key and Certificate Signing Request<a class="td-heading-self-link" href="#generate-private-key-and-certificate-signing-request" aria-label="Heading self-link"></a></h2> +<p>A private key and certificate signing request are required to create an SSL certificate. These can be generated with a few simple commands. When the openssl req command asks for a “challenge password”, just press return, leaving the password empty.</p> +<pre><code>$ openssl genrsa -des3 -passout pass:x -out server.pass.key 2048 +... +$ openssl rsa -passin pass:x -in server.pass.key -out server.key +writing RSA key +$ rm server.pass.key +$ openssl req -new -key server.key -out server.csr +... +Country Name (2 letter code) [AU]:US +State or Province Name (full name) [Some-State]:California +... +A challenge password []: +... +</code></pre> +<h2 id="generate-ssl-certificate">Generate SSL Certificate<a class="td-heading-self-link" href="#generate-ssl-certificate" aria-label="Heading self-link"></a></h2> +<p>The self-signed SSL certificate is generated from the server.key private key and server.csr files.</p> +<pre><code>$ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt +</code></pre> +<p>The server.crt file is your site certificate suitable for use with <a href="/docs/applications/ssl-certificates/">Drycc&rsquo;s SSL endpoint</a> along with the server.key private key.</p> + + + + + + Docs: Deploying an Application + /docs/applications/deploying-apps/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/applications/deploying-apps/ + + + + <p>An <a href="../reference-guide/terms.md#application">Application</a> is deployed to Drycc using <code>git push</code> or the <code>drycc</code> client.</p> +<h2 id="supported-applications">Supported Applications<a class="td-heading-self-link" href="#supported-applications" aria-label="Heading self-link"></a></h2> +<p>Drycc Workflow can deploy any application or service that can run inside a container. In order to be scaled +horizontally, applications must follow the <a href="http://12factor.net/">Twelve-Factor App</a> methodology and store any application state in external +backing services.</p> +<p>For example, if your application persists state to the local filesystem &ndash; common with content management systems like +Wordpress and Drupal &ndash; it cannot be scaled horizontally using <code>drycc scale</code>.</p> +<p>Fortunately, most modern applications feature a stateless application tier that can scale horizontally inside Drycc.</p> +<h2 id="login-to-the-controller">Login to the Controller<a class="td-heading-self-link" href="#login-to-the-controller" aria-label="Heading self-link"></a></h2> +<p>!!! important +if you haven&rsquo;t yet, now is a good time to <a href="/docs/users/cli/#installation">install the client</a> and <a href="/docs/users/registration/">register</a>.</p> +<p>Before deploying an application, users must first authenticate against the Drycc <a href="/docs/understanding-workflow/components/#controller">Controller</a> +using the URL supplied by their Drycc administrator.</p> +<pre tabindex="0"><code>$ drycc login http://drycc.example.com +Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71 +Waiting for login... .o.Logged in as admin +Configuration file written to /root/.drycc/client.json +</code></pre><p>Or you can login with username and password</p> +<pre tabindex="0"><code>$ drycc login http://drycc.example.com --username=demo --password=demo +Configuration file written to /root/.drycc/client.json +</code></pre><h2 id="select-a-build-process">Select a Build Process<a class="td-heading-self-link" href="#select-a-build-process" aria-label="Heading self-link"></a></h2> +<p>Drycc Workflow supports three different ways of building applications:</p> +<h3 id="buildpacks">Buildpacks<a class="td-heading-self-link" href="#buildpacks" aria-label="Heading self-link"></a></h3> +<p>Cloud Native Buildpacks are useful if you want to follow <a href="https://buildpacks.io/docs/">cnb&rsquo;s docs</a> for building applications.</p> +<p>Learn how to deploy applications <a href="/docs/applications/using-buildpacks/">using Buildpacks</a>.</p> +<h3 id="dockerfiles">Dockerfiles<a class="td-heading-self-link" href="#dockerfiles" aria-label="Heading self-link"></a></h3> +<p>Dockerfiles are a powerful way to define a portable execution environment built on a base OS of your choosing.</p> +<p>Learn how to deploy applications <a href="/docs/applications/using-dockerfiles/">using Dockerfiles</a>.</p> +<h3 id="container-image">Container Image<a class="td-heading-self-link" href="#container-image" aria-label="Heading self-link"></a></h3> +<p>Deploying a Container image onto Drycc allows you to take a Container image from either a public +or a private registry and copy it over bit-for-bit, ensuring that you are running the same +image in development or in your CI pipeline as you are in production.</p> +<p>Learn how to deploy applications <a href="/docs/applications/using-container-images/">using Container images</a>.</p> +<h2 id="tuning-application-settings">Tuning Application Settings<a class="td-heading-self-link" href="#tuning-application-settings" aria-label="Heading self-link"></a></h2> +<p>It is possible to configure a few of the <a href="/docs/applications/managing-app-configuration/">globally tunable</a> settings on per application basis using <code>config:set</code>.</p> +<table> +<thead> +<tr> +<th>Setting</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>DRYCC_DISABLE_CACHE</td> +<td>if set, this will disable the [imagebuilder cache][] (default: not set)</td> +</tr> +<tr> +<td>DRYCC_DEPLOY_BATCHES</td> +<td>the number of pods to bring up and take down sequentially during a scale (default: number of available nodes)</td> +</tr> +<tr> +<td>DRYCC_DEPLOY_TIMEOUT</td> +<td>deploy timeout in seconds per deploy batch (default: 120)</td> +</tr> +<tr> +<td>IMAGE_PULL_POLICY</td> +<td>the kubernetes [image pull policy][pull-policy] for application images (default: &ldquo;IfNotPresent&rdquo;) (allowed values: &ldquo;Always&rdquo;, &ldquo;IfNotPresent&rdquo;)</td> +</tr> +<tr> +<td>KUBERNETES_DEPLOYMENTS_REVISION_HISTORY_LIMIT</td> +<td>how many <a href="http://kubernetes.io/docs/user-guide/deployments/#revision-history-limit">revisions</a> Kubernetes keeps around of a given Deployment (default: all revisions)</td> +</tr> +<tr> +<td>KUBERNETES_POD_TERMINATION_GRACE_PERIOD_SECONDS</td> +<td>how many seconds kubernetes waits for a pod to finish work after a SIGTERM before sending SIGKILL (default: 30)</td> +</tr> +</tbody> +</table> +<h3 id="deploy-timeout">Deploy Timeout<a class="td-heading-self-link" href="#deploy-timeout" aria-label="Heading self-link"></a></h3> +<p>Deploy timeout in seconds - There are 2 deploy methods, Deployments (see below) and RC (versions prior to 2.4) and this setting affects those a bit differently.</p> +<h4 id="deployments">Deployments<a class="td-heading-self-link" href="#deployments" aria-label="Heading self-link"></a></h4> +<p>Deployments behave a little bit differently from the RC based deployment strategy.</p> +<p>Kubernetes takes care of the entire deploy, doing rolling updates in the background. As a result, there is only an overall deployment timeout instead of a configurable per-batch timeout.</p> +<p>The base timeout is multiplied with <code>DRYCC_DEPLOY_BATCHES</code> to create an overall timeout. This would be 240 (timeout) * 4 (batches) = 960 second overall timeout.</p> +<h4 id="rc-deploy">RC deploy<a class="td-heading-self-link" href="#rc-deploy" aria-label="Heading self-link"></a></h4> +<p>This deploy timeout defines how long to wait for each batch to complete in <code>DRYCC_DEPLOY_BATCHES</code>.</p> +<h4 id="additions-to-the-base-timeout">Additions to the base timeout<a class="td-heading-self-link" href="#additions-to-the-base-timeout" aria-label="Heading self-link"></a></h4> +<p>The base timeout is extended as well with healthchecks using <code>initialDelaySeconds</code> on <code>liveness</code> and <code>readiness</code> where the bigger of those two is applied. +Additionally the timeout system accounts for slow image pulls by adding an additional 10 minutes when it has seen an image pull take over 1 minute. This allows the timeout values to be reasonable without having to account for image pull slowness in the base deploy timeout.</p> +<h3 id="deployments-1">Deployments<a class="td-heading-self-link" href="#deployments-1" aria-label="Heading self-link"></a></h3> +<p>Workflow uses <a href="http://kubernetes.io/docs/user-guide/deployments/">Deployments</a> for deploys. In prior versions <a href="http://kubernetes.io/docs/user-guide/replication-controller/">ReplicationControllers</a> were used with the ability to turn on Deployments via <code>DRYCC_KUBERNETES_DEPLOYMENTS=1</code>.</p> +<p>The advantage of <a href="http://kubernetes.io/docs/user-guide/deployments/">Deployments</a> is that rolling-updates will happen server-side in Kubernetes instead of in Drycc Workflow Controller, +along with a few other Pod management related functionality. This allows a deploy to continue even when the CLI connection is interrupted.</p> +<p>Behind the scenes your application deploy will be built up of a Deployment object per process type, +each having multiple ReplicaSets (one per release) which in turn manage the Pods running your application.</p> +<p>Drycc Workflow will behave the same way with <code>DRYCC_KUBERNETES_DEPLOYMENTS</code> enabled or disabled (only applicable to versions prior to 2.4). +The changes are behind the scenes. Where you will see differences while using the CLI is <code>drycc ps:list</code> will output Pod names differently.</p> + + + + + + Docs: Quick Start + /docs/quickstart/overview/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/quickstart/overview/ + + + + <p>Get started with Drycc Workflow in three easy steps.</p> +<ol> +<li>Install CLI tools for Helm and Drycc Workflow</li> +<li>Boot a Kubernetes and install Drycc Workflow</li> +<li>Deploy your first application</li> +</ol> +<p>This guide will help you set up a cluster suitable for evaluation, development and testing. When you are ready for staging and production, view our <a href="/docs/managing-workflow/production-deployments/">production checklist</a>.</p> +<h2 id="step-1-install-workflow">Step 1: Install Workflow<a class="td-heading-self-link" href="#step-1-install-workflow" aria-label="Heading self-link"></a></h2> +<p>For the quickstart we will <a href="/docs/quickstart/install-workflow/">install Drycc Workflow</a>.</p> +<h2 id="step-2-install-cli-tools">Step 2: Install CLI tools<a class="td-heading-self-link" href="#step-2-install-cli-tools" aria-label="Heading self-link"></a></h2> +<p>For the quickstart we will <a href="/docs/quickstart/install-cli-tools/">install Drycc Workflow CLI</a>.</p> +<h2 id="step-3-deploy-your-first-app">Step 3: Deploy your first app<a class="td-heading-self-link" href="#step-3-deploy-your-first-app" aria-label="Heading self-link"></a></h2> +<p>Last but not least, <a href="/docs/quickstart/deploy-an-app/">login and deploy your first application</a>.</p> + + + + + + Docs: Contributor Overview + /docs/contribution-guidelines/overview/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/contribution-guidelines/overview/ + + + + <h2 id="file-bugs--enhancements">File Bugs &amp; Enhancements<a class="td-heading-self-link" href="#file-bugs--enhancements" aria-label="Heading self-link"></a></h2> +<p>Find a bug? Want to see a new feature? Have a request for the maintainers? Open a Github issue in the applicable repository and we’ll get the conversation started.</p> +<p>Our official support channel is the <a href="https://slack.drycc.cc">Drycc #community Slack channel</a>.</p> +<p>Don&rsquo;t know what the applicable repository for an issue is? Open up in issue in <a href="https://github.com/drycc/workflow">workflow</a> or chat with a maintainer in the <a href="https://slack.drycc.cc">Drycc #community Slack channel</a> and we&rsquo;ll make sure it gets to the right place.</p> +<p>Additionally, take a look at the <a href="/docs/troubleshooting/">troubleshooting</a> documentation for common issues.</p> +<p>Before opening a new issue, it&rsquo;s helpful to search and see if anyone else has already reported the problem. You can search through a list of issues for all Drycc projects <a href="https://github.com/pulls?utf8=%E2%9C%93&q=user%3Adrycc+user%3Ahelm">here</a>.</p> +<h2 id="write-documentation">Write Documentation<a class="td-heading-self-link" href="#write-documentation" aria-label="Heading self-link"></a></h2> +<p>We are always looking to improve and expand our documentation. Most docs reside in the <a href="https://github.com/drycc/workflow">drycc/workflow</a> repository. Simply fork the project, update docs and send us a pull request.</p> +<h2 id="contribute-code">Contribute Code<a class="td-heading-self-link" href="#contribute-code" aria-label="Heading self-link"></a></h2> +<p>We are always looking for help improving the core platform, other workloads, tooling, and test coverage. Interested in contributing code? Let’s chat in the <a href="https://slack.drycc.cc">Drycc #community Slack channel</a>. Make sure to check out issues tagged <a href="https://github.com/pulls?utf8=%E2%9C%93&q=user%3Adrycc+label%3A%22easy+fix%22+is%3Aopen">easy fix</a> or <a href="https://github.com/pulls?utf8=%E2%9C%93&q=user%3Adrycc+label%3A%22help+wanted%22+is%3Aopen">help wanted</a>.</p> +<p>When you&rsquo;re ready to begin writing code, review <a href="/docs/contribution-guidelines/design-documents/">Design Documents</a> and get your <a href="/docs/contribution-guidelines/development-environment/">Development Environment</a> set up.</p> +<p>By contributing to any Drycc project you agree to its <a href="https://github.com/drycc/workflow/blob/main/DCO">Developer Certificate of Origin (DCO)</a>. This document was created by the Linux Kernel community and is a simple statement that you, as a contributor, have the legal right to make the contribution.</p> +<h2 id="triage-issues">Triage Issues<a class="td-heading-self-link" href="#triage-issues" aria-label="Heading self-link"></a></h2> +<p>If you don&rsquo;t have time to code, consider helping with triage. The community will thank you for saving them time by spending some of yours. See <a href="/docs/contribution-guidelines/triaging-issues/">Triaging Issues</a> for more info.</p> +<h2 id="share-your-experience">Share your Experience<a class="td-heading-self-link" href="#share-your-experience" aria-label="Heading self-link"></a></h2> +<p>Interact with the community on our user mailing list or live in our <a href="https://slack.drycc.cc">Drycc #community Slack channel</a>, where you can chat with other Drycc Workflow users any time of day.</p> + + + + + + Docs: Planning Process + /docs/roadmap/planning-process/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/roadmap/planning-process/ + + + + <h2 id="the-role-of-maintainers">The Role of Maintainers<a class="td-heading-self-link" href="#the-role-of-maintainers" aria-label="Heading self-link"></a></h2> +<p><a href="../contributing/maintainers.md">Maintainers</a> lead the Drycc projects. Their duties include proposing the Roadmap, reviewing and integrating contributions and maintaining the vision of the project.</p> +<h2 id="open-roadmap">Open Roadmap<a class="td-heading-self-link" href="#open-roadmap" aria-label="Heading self-link"></a></h2> +<p>The <a href="/docs/roadmap/roadmap/">Drycc Roadmap</a> is a community document. While Maintainers propose the Roadmap, it gets discussed and refined in Release Planning Meetings.</p> +<h2 id="contributing-to-the-roadmap">Contributing to the Roadmap<a class="td-heading-self-link" href="#contributing-to-the-roadmap" aria-label="Heading self-link"></a></h2> +<p>Proposals and issues can be opened by anyone. Every member of the <a href="../contributing/community.md">community</a> is welcome to participate in the discussion by providing feedback and/or offering counter-proposals.</p> +<h2 id="release-milestones">Release Milestones<a class="td-heading-self-link" href="#release-milestones" aria-label="Heading self-link"></a></h2> +<p>The Roadmap gets delivered progressively via the <a href="/docs/roadmap/releases/">Release Schedule</a>. Releases are defined during Release Planning Meetings and managed using GitHub Milestones which track specific deliverables and work-in-progress.</p> +<h2 id="release-planning-meetings">Release Planning Meetings<a class="td-heading-self-link" href="#release-planning-meetings" aria-label="Heading self-link"></a></h2> +<p>Major decisions affecting the Roadmap are discussed during Release Planning Meetings on the first Thursday of each month, aligned with the <a href="/docs/roadmap/releases/">Release Schedule</a>.</p> +<p>Release Planning Meetings are open to the public with access coordinated via the <a href="https://slack.drycc.cc">Drycc #community Slack channel</a>. +Notes from past meetings are below, along with links to a recording of the entire meeting on YouTube.</p> +<h2 id="credits">Credits<a class="td-heading-self-link" href="#credits" aria-label="Heading self-link"></a></h2> +<p>Thanks to <a href="https://twitter.com/amylindburg">Amy Lindburg</a> and our friends at <a href="https://podman.io/">Podman</a> for their inspiration.</p> + + + + + + Docs: Requirements + /docs/installing-workflow/system-requirements/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/installing-workflow/system-requirements/ + + + + <h2 id="kubernetes-versions">Kubernetes Versions<a class="td-heading-self-link" href="#kubernetes-versions" aria-label="Heading self-link"></a></h2> +<p>Drycc Workflow requires Kubernetes v1.16.15 or later.</p> +<h2 id="components-requirements">Components Requirements<a class="td-heading-self-link" href="#components-requirements" aria-label="Heading self-link"></a></h2> +<p>Drycc uses gateway as a routing implementation, so you have to choose an gateway. We recommend using <a href="https://istio.io/">istio</a> or <a href="https://konghq.com/">kong</a>.</p> +<p>Workflow supports the use of ACME to manage automatic certificates, <a href="https://github.com/helm/charts/tree/master/stable/cert-manager">cert-manager</a> is also one of the necessary components, if you use cert-manager EAB, you need to set the <code>clusterResourceNamespace</code> to the namespace of drycc.</p> +<p>Workflow supports stateful apps. You can create and use them through the &lsquo;drycc volumes&rsquo; command. If you want to use this feature, you must have a <code>StorageClass</code> that supports <code>ReadWriteMany</code>.</p> +<p>Workflow also supports the <a href="https://github.com/openservicebrokerapi/servicebroker">OSB</a> API through the &lsquo;drycc resources&rsquo; command. If you want to use this function, you need to install <a href="https://service-catalog.drycc.cc">service-catalog</a>.</p> +<h2 id="storage-requirements">Storage Requirements<a class="td-heading-self-link" href="#storage-requirements" aria-label="Heading self-link"></a></h2> +<p>A variety of Drycc Workflow components rely on an object storage system to do their work, including storing application +slugs, Container images and database logs.</p> +<p>Drycc Workflow ships with drycc storage by default, which provides in-cluster.</p> +<p>Workflow supports Amazon Simple Storage Service (S3), Google Cloud Storage (GCS), OpenShift Swift, and Azure Blob +Storage. See <a href="/docs/installing-workflow/configuring-object-storage/">configuring object storage</a> for setup instructions.</p> +<h2 id="resource-requirements">Resource Requirements<a class="td-heading-self-link" href="#resource-requirements" aria-label="Heading self-link"></a></h2> +<p>When deploying Drycc Workflow, it&rsquo;s important to provision machines with adequate resources. Drycc is a highly-available +distributed system, which means that Drycc components and your deployed applications will move around the cluster onto +healthy hosts as hosts leave the cluster for various reasons (failures, reboots, autoscalers, etc.). Because of this, +you should have ample spare resources on any machine in your cluster to withstand the additional load of running +services for failed machines.</p> +<p>Drycc Workflow components use about 2.5GB of memory across the cluster, and require approximately 30GB of hard disk +space. Because it may need to handle additional load if another one fails, each machine has minimum requirements of:</p> +<ul> +<li>At least 4GB of RAM (more is better)</li> +<li>At least 40GB of hard disk space</li> +</ul> +<p>Note that these estimates are for Drycc Workflow and Kubernetes only. Be sure to leave enough spare capacity for your +application footprint as well.</p> +<p>Running smaller machines will likely result in increased system load and has been known to result in component failures +and instability.</p> + + + + + + Docs: Troubleshooting Workflow + /docs/troubleshooting/workflow/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/troubleshooting/workflow/ + + + + <h2 id="a-component-fails-to-start">A Component Fails to Start<a class="td-heading-self-link" href="#a-component-fails-to-start" aria-label="Heading self-link"></a></h2> +<p>For information on troubleshooting a failing component, see +<a href="/docs/troubleshooting/kubectl/">Troubleshooting with Kubectl</a>.</p> +<h2 id="an-application-fails-to-start">An Application Fails to Start<a class="td-heading-self-link" href="#an-application-fails-to-start" aria-label="Heading self-link"></a></h2> +<p>For information on troubleshooting application deployment issues, see +<a href="/docs/troubleshooting/applications/">Troubleshooting Applications</a>.</p> +<h2 id="permission-denied-publickey">Permission denied (publickey)<a class="td-heading-self-link" href="#permission-denied-publickey" aria-label="Heading self-link"></a></h2> +<p>The most common problem for this issue is the user forgetting to run <code>drycc keys:add</code> or add their +private key to their SSH agent. To do so, run <code>ssh-add ~/.ssh/id_rsa</code> and try running +<code>git push drycc master</code> again.</p> +<p>If you happen get a <code>Could not open a connection to your authentication agent</code> +error after trying to run <code>ssh-add</code> command above, you may need to load the SSH +agent environment variables issuing the <code>eval &quot;$(ssh-agent)&quot;</code> command before.</p> +<h2 id="other-issues">Other Issues<a class="td-heading-self-link" href="#other-issues" aria-label="Heading self-link"></a></h2> +<p>Running into something not detailed here? Please <a href="https://github.com/drycc/workflow/issues/new">open an issue</a> or hop into +<a href="http://slack.drycc.cc/">#community on Slack</a> for help!</p> + + + + + + Docs: Tuning Component Settings + /docs/managing-workflow/tuning-component-settings/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/managing-workflow/tuning-component-settings/ + + + + <p>After you add the Drycc Chart Repository, you can customize the chart using +<code>helm inspect values drycc/workflow &gt; values.yaml</code> before using <code>helm install</code> to complete the +installation.</p> +<p>There are a few ways to customize the respective component:</p> +<ul> +<li> +<p>If the value is exposed in the <code>values.yaml</code> file as derived above, one may modify the section of the component to tune these settings. The modified value(s) will then take effect at chart installation or release upgrade time via either of the two respective commands:</p> +<pre><code> $ helm install drycc oci://registry.drycc.cc/charts/workflow \ + -n drycc \ + --namespace drycc \ + -f values.yaml + $ helm upgrade drycc oci://registry.drycc.cc/charts/workflow \ + -n drycc \ + --namespace drycc \ + -f values.yaml +</code></pre> +</li> +<li> +<p>If the value hasn&rsquo;t yet been exposed in the <code>values.yaml</code> file, one may edit the component deployment with the tuned setting. Here we edit the <code>drycc-controller</code> deployment:</p> +<pre><code> $ kubectl --namespace drycc edit deployment drycc-controller +</code></pre> +<p>Add/edit the setting via the appropriate environment variable and value under the <code>env</code> section and save. The updated deployment will recreate the component pod with the new/modified setting.</p> +</li> +<li> +<p>Lastly, one may also fetch and edit the chart as served by version control/the chart repository itself:</p> +<pre><code> $ helm fetch oci://registry.drycc.cc/charts/workflow --untar + $ $EDITOR workflow/charts/controller/templates/controller-deployment.yaml +</code></pre> +<p>Then run <code>helm install ./workflow --namespace drycc --name drycc</code> to apply the changes, or <code>helm upgrade drycc ./workflow</code> if the cluster is already running.</p> +</li> +</ul> +<h2 id="setting-resource-limits">Setting Resource limits<a class="td-heading-self-link" href="#setting-resource-limits" aria-label="Heading self-link"></a></h2> +<p>You can set resource limits to Workflow components by modifying the values.yaml file fetched +earlier. This file has a section for each Workflow component. To set a limit to any Workflow +component just add <code>limitsCpu</code>, <code>limitsMemory</code> in the section and set them to the appropriate +values.</p> +<p>Below is an example of how the builder section of <code>values.yaml</code> might look with CPU and memory +limits set:</p> +<pre tabindex="0"><code>builder: + imageOrg: &#34;drycc&#34; + imagePullPolicy: &#34;Always&#34; + imageTag: &#34;canary&#34; + limitsCpu: &#34;100m&#34; + limitsMemory: &#34;50Mi&#34; +</code></pre><h2 id="customizing-the-builder">Customizing the Builder<a class="td-heading-self-link" href="#customizing-the-builder" aria-label="Heading self-link"></a></h2> +<p>The following environment variables are tunable for the <a href="/docs/understanding-workflow/components/#builder">Builder</a> component:</p> +<table> +<thead> +<tr> +<th>Setting</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>DEBUG</td> +<td>Enable debug log output (default: false)</td> +</tr> +<tr> +<td>BUILDER_POD_NODE_SELECTOR</td> +<td>A node selector setting for builder job. As it may sometimes consume a lot of node resources, one may want a given builder job to run in a specific node only, so it won&rsquo;t affect critical nodes. for example <code>pool:testing,disk:magnetic</code></td> +</tr> +</tbody> +</table> +<h2 id="customizing-the-controller">Customizing the Controller<a class="td-heading-self-link" href="#customizing-the-controller" aria-label="Heading self-link"></a></h2> +<p>The following environment variables are tunable for the <a href="/docs/understanding-workflow/components/#controller">Controller</a> component:</p> +<table> +<thead> +<tr> +<th>Setting</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>REGISTRATION_MODE</td> +<td>set registration to &ldquo;enabled&rdquo;, &ldquo;disabled&rdquo;, or &ldquo;admin_only&rdquo; (default: &ldquo;admin_only&rdquo;)</td> +</tr> +<tr> +<td>GUNICORN_WORKERS</td> +<td>number of <a href="http://gunicorn.org/">gunicorn</a> workers spawned to process requests (default: CPU cores * 4 + 1)</td> +</tr> +<tr> +<td>RESERVED_NAMES</td> +<td>a comma-separated list of names which applications cannot reserve for routing (default: &ldquo;drycc, drycc-builder&rdquo;)</td> +</tr> +<tr> +<td>DRYCC_DEPLOY_HOOK_URLS</td> +<td>a comma-separated list of URLs to send <a href="/docs/managing-workflow/deploy-hooks/#http-post-hook">deploy hooks</a> to.</td> +</tr> +<tr> +<td>DRYCC_DEPLOY_HOOK_SECRET_KEY</td> +<td>a private key used to compute the HMAC signature for deploy hooks.</td> +</tr> +<tr> +<td>DRYCC_DEPLOY_REJECT_IF_PROCFILE_MISSING</td> +<td>rejects a deploy if the previous build had a Procfile but the current deploy is missing it. A 409 is thrown in the API. Prevents accidental process types removal. (default: &ldquo;false&rdquo;, allowed values: &ldquo;true&rdquo;, &ldquo;false&rdquo;)</td> +</tr> +<tr> +<td>DRYCC_DEPLOY_PROCFILE_MISSING_REMOVE</td> +<td>when turned on (default) any missing process type in a Procfile compared to the previous deploy is removed. When set to false will allow an empty Procfile to go through without removing missing process types, note that new images, configs and so on will get updated on all proc types. (default: &ldquo;true&rdquo;, allowed values: &ldquo;true&rdquo;, &ldquo;false&rdquo;)</td> +</tr> +<tr> +<td>DRYCC_DEFAULT_CONFIG_TAGS</td> +<td>set tags for all applications by default, for example: &lsquo;{&ldquo;role&rdquo;: &ldquo;worker&rdquo;}&rsquo;. (default: &lsquo;&rsquo;)</td> +</tr> +<tr> +<td>KUBERNETES_NAMESPACE_DEFAULT_QUOTA_SPEC</td> +<td>set resource quota to application namespace by setting <a href="http://kubernetes.io/docs/admin/resourcequota/">ResourceQuota</a> spec, for example: <code>{&quot;spec&quot;:{&quot;hard&quot;:{&quot;pods&quot;:&quot;10&quot;}}}</code>, restrict app owner to spawn more then 10 pods (default: &ldquo;&rdquo;, no quota will be applied to namespace)</td> +</tr> +</tbody> +</table> +<h3 id="ldap-authentication-settings">LDAP authentication settings<a class="td-heading-self-link" href="#ldap-authentication-settings" aria-label="Heading self-link"></a></h3> +<p>Configuration options for LDAP authentication are detailed <a href="https://pythonhosted.org/django-auth-ldap/reference.html">here</a>.</p> +<p>The following environment variables are available for enabling LDAP +authentication of user accounts in the <a href="/docs/understanding-workflow/components/#passport">Passport</a> component:</p> +<table> +<thead> +<tr> +<th>Setting</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>LDAP_ENDPOINT</td> +<td>The URI of the LDAP server. If not specified, LDAP authentication is not enabled (default: &ldquo;&rdquo;, example: <code>ldap://hostname</code>).</td> +</tr> +<tr> +<td>LDAP_BIND_DN</td> +<td>The distinguished name to use when binding to the LDAP server (default: &ldquo;&rdquo;)</td> +</tr> +<tr> +<td>LDAP_BIND_PASSWORD</td> +<td>The password to use with LDAP_BIND_DN (default: &ldquo;&rdquo;)</td> +</tr> +<tr> +<td>LDAP_USER_BASEDN</td> +<td>The distinguished name of the search base for user names (default: &ldquo;&rdquo;)</td> +</tr> +<tr> +<td>LDAP_USER_FILTER</td> +<td>The name of the login field in the users search base (default: &ldquo;username&rdquo;)</td> +</tr> +<tr> +<td>LDAP_GROUP_BASEDN</td> +<td>The distinguished name of the search base for user&rsquo;s groups names (default: &ldquo;&rdquo;)</td> +</tr> +<tr> +<td>LDAP_GROUP_FILTER</td> +<td>The filter for user&rsquo;s groups (default: &ldquo;&rdquo;, example: <code>objectClass=person</code>)</td> +</tr> +</tbody> +</table> +<h3 id="global-and-per-application-settings">Global and per application settings<a class="td-heading-self-link" href="#global-and-per-application-settings" aria-label="Heading self-link"></a></h3> +<table> +<thead> +<tr> +<th>Setting</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>DRYCC_DEPLOY_BATCHES</td> +<td>the number of pods to bring up and take down sequentially during a scale (default: number of available nodes)</td> +</tr> +<tr> +<td>DRYCC_DEPLOY_TIMEOUT</td> +<td>deploy timeout in seconds per deploy batch (default: 120)</td> +</tr> +<tr> +<td>IMAGE_PULL_POLICY</td> +<td>the kubernetes <a href="http://kubernetes.io/docs/user-guide/images/">image pull policy</a> for application images (default: &ldquo;IfNotPresent&rdquo;) (allowed values: &ldquo;Always&rdquo;, &ldquo;IfNotPresent&rdquo;)</td> +</tr> +<tr> +<td>KUBERNETES_DEPLOYMENTS_REVISION_HISTORY_LIMIT</td> +<td>how many <a href="http://kubernetes.io/docs/user-guide/deployments/#revision-history-limit">revisions</a> Kubernetes keeps around of a given Deployment (default: all revisions)</td> +</tr> +<tr> +<td>KUBERNETES_POD_TERMINATION_GRACE_PERIOD_SECONDS</td> +<td>how many seconds kubernetes waits for a pod to finish work after a SIGTERM before sending SIGKILL (default: 30)</td> +</tr> +</tbody> +</table> +<p>See the <a href="/docs/applications/deploying-apps/">Deploying Apps</a> guide for more detailed information on those.</p> +<h2 id="customizing-the-database">Customizing the Database<a class="td-heading-self-link" href="#customizing-the-database" aria-label="Heading self-link"></a></h2> +<p>The following environment variables are tunable for the <a href="/docs/understanding-workflow/components/#database">Database</a> component:</p> +<table> +<thead> +<tr> +<th>Setting</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>BACKUP_FREQUENCY</td> +<td>how often the database should perform a base backup (default: &ldquo;12h&rdquo;)</td> +</tr> +<tr> +<td>BACKUPS_TO_RETAIN</td> +<td>number of base backups the backing store should retain (default: 5)</td> +</tr> +</tbody> +</table> +<h2 id="customizing-fluentbit">Customizing Fluentbit<a class="td-heading-self-link" href="#customizing-fluentbit" aria-label="Heading self-link"></a></h2> +<p>The following values can be changed in the <code>values.yaml</code> file or by using the <code>--values</code> flag with the Helm CLI.</p> +<table> +<thead> +<tr> +<th>Key</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>config.service</td> +<td>The service section defines the global properties of the service.</td> +</tr> +<tr> +<td>config.inputs</td> +<td>An input section defines a source (related to an input plugin).</td> +</tr> +<tr> +<td>config.filters</td> +<td>A filter section defines a filter (related to a filter plugin)</td> +</tr> +<tr> +<td>config.outputs</td> +<td>The outputs section specify a destination that certain records should follow after a Tag match.</td> +</tr> +</tbody> +</table> +<p>For more information about the various variables that can be set please see the <a href="https://github.com/drycc/fluentbit">fluentbit</a>.</p> +<h2 id="customizing-the-logger">Customizing the Logger<a class="td-heading-self-link" href="#customizing-the-logger" aria-label="Heading self-link"></a></h2> +<p>The following environment variables are tunable for the <a href="/docs/understanding-workflow/components/#logger-fluentbit-logger">Logger</a> component:</p> +<table> +<thead> +<tr> +<th>Setting</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>STORAGE_ADAPTER</td> +<td>How to store logs that are sent to the logger. Legal values are &ldquo;file&rdquo;, &ldquo;memory&rdquo;, and &ldquo;redis&rdquo;. (default: &ldquo;redis&rdquo;)</td> +</tr> +<tr> +<td>NUMBER_OF_LINES</td> +<td>How many lines to store in the ring buffer (default: 1000)</td> +</tr> +</tbody> +</table> +<h2 id="customizing-the-monitor">Customizing the Monitor<a class="td-heading-self-link" href="#customizing-the-monitor" aria-label="Heading self-link"></a></h2> +<h3 id="grafanahttpsgrafanacom"><a href="https://grafana.com/">Grafana</a><a class="td-heading-self-link" href="#grafanahttpsgrafanacom" aria-label="Heading self-link"></a></h3> +<p>We have exposed some of the more useful configuration values directly in the chart. This allows them to be set using either the <code>values.yaml</code> file or by using the <code>--set</code> flag with the Helm CLI. You can see these options below:</p> +<table> +<thead> +<tr> +<th>Setting</th> +<th>Default Value</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>user</td> +<td>&ldquo;admin&rdquo;</td> +<td>The first user created in the database (this user has admin privileges)</td> +</tr> +<tr> +<td>password</td> +<td>&ldquo;admin&rdquo;</td> +<td>Password for the first user.</td> +</tr> +<tr> +<td>allow_sign_up</td> +<td>&ldquo;true&rdquo;</td> +<td>Allows users to sign up for an account.</td> +</tr> +</tbody> +</table> +<p>For a list of other options you can set by using environment variables please see the <a href="https://github.com/drycc/monitor/blob/main/grafana/rootfs/usr/share/grafana/grafana.ini.tpl">configuration file</a> in Github.</p> +<h3 id="telegrafhttpsdocsinfluxdatacomtelegraf"><a href="https://docs.influxdata.com/telegraf">Telegraf</a><a class="td-heading-self-link" href="#telegrafhttpsdocsinfluxdatacomtelegraf" aria-label="Heading self-link"></a></h3> +<p>For a list of configuration values that can be set by using environment variables please see the following <a href="https://github.com/drycc/monitor/blob/main/telegraf/rootfs/config.toml.tpl">configuration file</a>.</p> +<h3 id="prometheushttpsprometheusio"><a href="https://prometheus.io">Prometheus</a><a class="td-heading-self-link" href="#prometheushttpsprometheusio" aria-label="Heading self-link"></a></h3> +<p>You can find a list of values that can be set using environment variables <a href="https://github.com/drycc/prometheus">here</a>.</p> +<h2 id="customizing-the-registry">Customizing the Registry<a class="td-heading-self-link" href="#customizing-the-registry" aria-label="Heading self-link"></a></h2> +<p>The <a href="/docs/understanding-workflow/components/#registry">Registry</a> component can be tuned by following the +<a href="https://github.com/drycc/distribution/blob/main/docs/configuration.md">drycc/distribution config doc</a>.</p> +<h2 id="customizing-the-router">Customizing the Router<a class="td-heading-self-link" href="#customizing-the-router" aria-label="Heading self-link"></a></h2> +<p>The majority of router settings are tunable through annotations, which allows the router to be +re-configured with zero downtime post-installation. You can find the list of annotations to tune +<a href="https://github.com/drycc/router#annotations">here</a>.</p> +<p>The following environment variables are tunable for the [Router][] component:</p> +<table> +<thead> +<tr> +<th>Setting</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>POD_NAMESPACE</td> +<td>The pod namespace the router resides in. This is set by the <a href="http://kubernetes.io/docs/user-guide/downward-api/">Kubernetes downward API</a>.</td> +</tr> +</tbody> +</table> +<h2 id="customizing-workflow-manager">Customizing Workflow Manager<a class="td-heading-self-link" href="#customizing-workflow-manager" aria-label="Heading self-link"></a></h2> +<p>The following environment variables are tunable for [Workflow Manager][]:</p> +<table> +<thead> +<tr> +<th>Setting</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>CHECK_VERSIONS</td> +<td>Enables the external version check at <a href="https://versions.drycc.info/">https://versions.drycc.info/</a> (default: &ldquo;true&rdquo;)</td> +</tr> +<tr> +<td>POLL_INTERVAL_SEC</td> +<td>The interval when Workflow Manager performs a version check, in seconds (default: 43200, or 12 hours)</td> +</tr> +<tr> +<td>VERSIONS_API_URL</td> +<td>The versions API URL (default: &ldquo;<a href="https://versions-staging.drycc.info">https://versions-staging.drycc.info</a>&rdquo;)</td> +</tr> +<tr> +<td>DOCTOR_API_URL</td> +<td>The doctor API URL (default: &ldquo;<a href="https://doctor-staging.drycc.info">https://doctor-staging.drycc.info</a>&rdquo;)</td> +</tr> +<tr> +<td>API_VERSION</td> +<td>The version number Workflow Manager sends to the versions API (default: &ldquo;v2&rdquo;)</td> +</tr> +</tbody> +</table> + + + + + + Docs: Architecture + /docs/understanding-workflow/architecture/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/understanding-workflow/architecture/ + + + + <p>All components are published as a set of container images which can be deployed to any +compliant Kubernetes cluster.</p> +<h2 id="overview">Overview<a class="td-heading-self-link" href="#overview" aria-label="Heading self-link"></a></h2> +<p><img alt="System Overview" src="../../diagrams/Ecosystem_Basic.jpg"></p> +<p>Operators use <a href="https://github.com/kubernetes/helm">Helm</a> to configure and install the Workflow components which +interface directly with the underlying Kubernetes cluster. Service discovery, +container availability and networking are all delegated to Kubernetes, while +Workflow provides a clean and simple developer experience.</p> +<h2 id="platform-services">Platform Services<a class="td-heading-self-link" href="#platform-services" aria-label="Heading self-link"></a></h2> +<p><img alt="Workflow Overview" src="../../diagrams/Workflow_Overview.jpg"></p> +<p>Drycc Workflow provides additional functionality to your Kubernetes cluster, including:</p> +<ul> +<li><a href="/docs/understanding-workflow/components/#builder">Source to Image Builder</a> which compiles your Application code via Buildpacks or Dockerfiles</li> +<li><a href="/docs/understanding-workflow/components/#logger">Cross-Pod Log Aggregation</a> which gathers logs from all of your Application processes</li> +<li><a href="/docs/understanding-workflow/components/#controller">Simple REST API</a> which powers the CLI and any external integrations</li> +<li>Application release and rollback</li> +<li>Authentication and Authorization to Application resources</li> +<li><a href="/docs/understanding-workflow/components/#router">HTTP/HTTPS edge routing</a> for your Applications</li> +</ul> +<h2 id="kubernetes-native">Kubernetes-Native<a class="td-heading-self-link" href="#kubernetes-native" aria-label="Heading self-link"></a></h2> +<p>All platform components and applications deployed via Workflow expect to be +running on an existing Kubernetes cluster. This means that you can happily run +your Kubernetes-native workloads next to applications that are managed through +Drycc Workflow.</p> +<p><img alt="Workflow and Kubernetes" src="../../diagrams/Workflow_Detail.png"></p> +<h2 id="application-layout-and-edge-routing">Application Layout and Edge Routing<a class="td-heading-self-link" href="#application-layout-and-edge-routing" aria-label="Heading self-link"></a></h2> +<p>By default Workflow creates per-application Namespaces and Services so you can +easily connect your applications to other on-cluster services through standard +Kubernetes mechanisms.</p> +<p><img alt="Application Configuration" src="../../diagrams/Application_Layout.png"></p> +<p>The router component is responsible for routing HTTP/s traffic to your +Applications as well as proxying <code>git push</code> and platform API traffic.</p> +<p>By default, the router component is deployed as a Kubernetes service with type +<code>LoadBalancer</code>; which, depending on your configuration, will provision a +cloud-native load balancer automatically.</p> +<p>The router automatically discovers routable Applications, SSL/TLS certificates +and application-specific configurations through the use of Kubernetes +annotations. Any changes to router configuration or certificates are applied +within seconds.</p> +<h2 id="topologies">Topologies<a class="td-heading-self-link" href="#topologies" aria-label="Heading self-link"></a></h2> +<p>Drycc Workflow no longer dictates a specific topology or server count for your +deployment. The platform components will happily run on single-server +configurations as well as multi-server production clusters.</p> + + + + + + Docs: Using Buildpacks + /docs/applications/using-buildpacks/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/applications/using-buildpacks/ + + + + <p>Drycc supports deploying applications via <a href="https://buildpacks.io/">Cloud Native Buildpacks</a>. Cloud Native Buildpacks are useful if you want to follow <a href="https://buildpacks.io/docs/">cnb&rsquo;s docs</a> for building applications.</p> +<h2 id="add-ssh-key">Add SSH Key<a class="td-heading-self-link" href="#add-ssh-key" aria-label="Heading self-link"></a></h2> +<p>For <strong>Buildpack</strong> based application deploys via <code>git push</code>, Drycc Workflow identifies users via SSH keys. SSH keys are pushed to the platform and must be unique to each user.</p> +<ul> +<li> +<p>See <a href="/docs/users/ssh-keys/#generate-an-ssh-key">this document</a> for instructions on how to generate an SSH key.</p> +</li> +<li> +<p>Run <code>drycc keys:add</code> to upload your SSH key to Drycc Workflow.</p> +</li> +</ul> +<pre tabindex="0"><code>$ drycc keys:add ~/.ssh/id_drycc.pub +Uploading id_drycc.pub to drycc... done +</code></pre><p>Read more about adding/removing SSH Keys <a href="/docs/users/ssh-keys/#adding-and-removing-ssh-keys">here</a>.</p> +<h2 id="prepare-an-application">Prepare an Application<a class="td-heading-self-link" href="#prepare-an-application" aria-label="Heading self-link"></a></h2> +<p>If you do not have an existing application, you can clone an example application that demonstrates the Heroku Buildpack workflow.</p> +<pre><code>$ git clone https://github.com/drycc/example-go.git +$ cd example-go +</code></pre> +<h2 id="create-an-application">Create an Application<a class="td-heading-self-link" href="#create-an-application" aria-label="Heading self-link"></a></h2> +<p>Use <code>drycc create</code> to create an application on the <a href="/docs/understanding-workflow/components/#controller">Controller</a>.</p> +<pre><code>$ drycc create +Creating application... done, created skiing-keypunch +Git remote drycc added +</code></pre> +<h2 id="push-to-deploy">Push to Deploy<a class="td-heading-self-link" href="#push-to-deploy" aria-label="Heading self-link"></a></h2> +<p>Use <code>git push drycc master</code> to deploy your application.</p> +<pre><code>$ git push drycc master +Counting objects: 75, done. +Delta compression using up to 8 threads. +Compressing objects: 100% (48/48), done. +Writing objects: 100% (75/75), 18.28 KiB | 0 bytes/s, done. +Total 75 (delta 30), reused 58 (delta 22) +remote: ---&gt; +Starting build... but first, coffee! +---&gt; Waiting podman running. +---&gt; Process podman started. +---&gt; Waiting caddy running. +---&gt; Process caddy started. +---&gt; Building pack +---&gt; Using builder registry.drycc.cc/drycc/buildpacks:bookworm +Builder 'registry.drycc.cc/drycc/buildpacks:bookworm' is trusted +Pulling image 'registry.drycc.cc/drycc/buildpacks:bookworm' +Resolving &quot;drycc/buildpacks&quot; using unqualified-search registries (/etc/containers/registries.conf) +Trying to pull registry.drycc.cc/drycc/buildpacks:bookworm... +Getting image source signatures +... +---&gt; Skip generate base layer +---&gt; Python Buildpack +---&gt; Downloading and extracting Python 3.10.0 +---&gt; Installing requirements with pip +Collecting Django==3.2.8 +Downloading Django-3.2.8-py3-none-any.whl (7.9 MB) +Collecting gunicorn==20.1.0 +Downloading gunicorn-20.1.0-py3-none-any.whl (79 kB) +Collecting sqlparse&gt;=0.2.2 +Downloading sqlparse-0.4.2-py3-none-any.whl (42 kB) +Collecting pytz +Downloading pytz-2021.3-py2.py3-none-any.whl (503 kB) +Collecting asgiref&lt;4,&gt;=3.3.2 +Downloading asgiref-3.4.1-py3-none-any.whl (25 kB) +Requirement already satisfied: setuptools&gt;=3.0 in /layers/drycc_python/python/lib/python3.10/site-packages (from gunicorn==20.1.0-&gt;-r requirements.txt (line 2)) (57.5.0) +Installing collected packages: sqlparse, pytz, asgiref, gunicorn, Django +Successfully installed Django-3.2.8 asgiref-3.4.1 gunicorn-20.1.0 pytz-2021.3 sqlparse-0.4.2 +---&gt; Generate Launcher +... +Build complete. +Launching App... +... +Done, skiing-keypunch:v2 deployed to Workflow + +Use 'drycc open' to view this application in your browser + +To learn more, use 'drycc help' or visit https://www.drycc.cc + +To ssh://git@drycc.staging-2.drycc.cc:2222/skiing-keypunch.git + * [new branch] master -&gt; master + +$ curl -s http://skiing-keypunch.example.com +Powered by Drycc +Release v2 on skiing-keypunch-v2-web-02zb9 +</code></pre> +<p>Because a Buildpacks-style application is detected, the <code>web</code> process type is automatically scaled to 1 on first deploy.</p> +<p>Use <code>drycc scale web=3</code> to increase <code>web</code> processes to 3, for example. Scaling a +process type directly changes the number of <a href="http://kubernetes.io/v1.1/docs/user-guide/pods.html">pods</a> running that process.</p> +<h2 id="included-buildpacks">Included Buildpacks<a class="td-heading-self-link" href="#included-buildpacks" aria-label="Heading self-link"></a></h2> +<p>For convenience, a number of buildpacks come bundled with Drycc:</p> +<ul> +<li><a href="https://github.com/drycc/pack-images/tree/main/buildpacks/go">Go Buildpack</a></li> +<li><a href="https://github.com/drycc/pack-images/tree/main/buildpacks/java">Java Buildpack</a></li> +<li><a href="https://github.com/drycc/pack-images/tree/main/buildpacks/nodejs">Nodejs Buildpack</a></li> +<li><a href="https://github.com/drycc/pack-images/tree/main/buildpacks/php">PHP Buildpack</a></li> +<li><a href="https://github.com/drycc/pack-images/tree/main/buildpacks/python">Python Buildpack</a></li> +<li><a href="https://github.com/drycc/pack-images/tree/main/buildpacks/ruby">Ruby Buildpack</a></li> +<li><a href="https://github.com/drycc/pack-images/tree/main/buildpacks/rust">Rust Buildpack</a></li> +</ul> +<p>Drycc will cycle through the <code>bin/detect</code> script of each buildpack to match the code you +are pushing.</p> +<p>!!! note +If you&rsquo;re testing against the [Scala Buildpack][], the <a href="/docs/understanding-workflow/components/#builder">Builder</a> requires at least +512MB of free memory to execute the Scala Build Tool.</p> +<h2 id="using-a-custom-buildpack">Using a Custom Buildpack<a class="td-heading-self-link" href="#using-a-custom-buildpack" aria-label="Heading self-link"></a></h2> +<p>To use a custom buildpack, you need create a <code>.pack_builder</code> file in your root path app.</p> +<pre><code>$ tee &gt; .pack_builder &lt;&lt; EOF + &gt; registry.drycc.cc/drycc/buildpacks:bookworm + &gt; EOF +</code></pre> +<p>On your next <code>git push</code>, the custom buildpack will be used.</p> +<h2 id="using-private-repositories">Using Private Repositories<a class="td-heading-self-link" href="#using-private-repositories" aria-label="Heading self-link"></a></h2> +<p>To pull code from private repositories, set the <code>SSH_KEY</code> environment variable to a private key +which has access. Use either the path of a private key file or the raw key material:</p> +<pre><code>$ drycc config:set SSH_KEY=/home/user/.ssh/id_rsa +$ drycc config:set SSH_KEY=&quot;&quot;&quot;-----BEGIN RSA PRIVATE KEY----- +(...) +-----END RSA PRIVATE KEY-----&quot;&quot;&quot; +</code></pre> +<p>For example, to use a custom buildpack hosted at a private GitHub URL, ensure that an SSH public +key exists in your <a href="https://github.com/settings/ssh">GitHub settings</a>. Then set <code>SSH_KEY</code> to the corresponding SSH private key +and set <code>.pack_builder</code> to the builder image:</p> +<pre><code>$ tee &gt; .pack_builder &lt;&lt; EOF + &gt; registry.drycc.cc/drycc/buildpacks:bookworm + &gt; EOF +$ git add .buildpack +$ git commit -m &quot;chore(buildpack): modify the pack_builder&quot; +$ git push drycc master +</code></pre> +<h2 id="builder-selector">Builder selector<a class="td-heading-self-link" href="#builder-selector" aria-label="Heading self-link"></a></h2> +<p>Which way to build a project conforms to the following principles:</p> +<ul> +<li>If Dockerfile exists in the project, the stack uses <code>container</code></li> +<li>If Procfile exists in the project, the stack uses <code>buildpack</code></li> +<li>If both exist, <code>container</code> is used by default</li> +<li>You can also set the <code>DRYCC_STACK</code> to <code>container</code> or <code>buildpack</code> determine which stack to use.</li> +</ul> + + + + + + Docs: Configure DNS + /docs/managing-workflow/configuring-dns/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/managing-workflow/configuring-dns/ + + + + <p>For example, assuming <code>example.com</code> were a cluster&rsquo;s domain:</p> +<ul> +<li>The controller should be accessible at <code>drycc.example.com</code></li> +<li>Applications should be accessible (by default) at <code>&lt;application name&gt;.example.com</code></li> +</ul> +<p>Given that this is the case, the primary objective in configuring DNS is that traffic for all subdomains of a cluster&rsquo;s domain be directed to the cluster node(s) hosting the platform&rsquo;s router component, which is capable of directing traffic within the cluster to the correct endpoints.</p> +<h2 id="with-a-load-balancer">With a Load Balancer<a class="td-heading-self-link" href="#with-a-load-balancer" aria-label="Heading self-link"></a></h2> +<p>Generally, it is recommended that a [load balancer][] be used to direct inbound traffic to one or more routers. In such a case, configuring DNS is as simple as defining a wildcard record in DNS that points to the load balancer.</p> +<p>For example, assuming a domain of <code>example.com</code>:</p> +<ul> +<li>An <code>A</code> record enumerating each of your load balancer(s) IPs (i.e. DNS round-robining)</li> +<li>A <code>CNAME</code> record referencing an existing fully-qualified domain name for the load balancer +<ul> +<li>Per <a href="https://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/using-domain-names-with-elb.html">AWS&rsquo; own documentation</a>, this is the recommended strategy when using AWS Elastic Load Balancers, as ELB IPs may change over time.</li> +</ul> +</li> +</ul> +<p>DNS for any applications using a &ldquo;custom domain&rdquo; (a fully-qualified domain name that is not a subdomain of the cluster&rsquo;s own domain) can be configured by creating a <code>CNAME</code> record that references the wildcard record described above.</p> +<p>Although it is dependent upon your distribution of Kubernetes and your underlying infrastructure, in many cases, the IP(s) or existing fully-qualified domain name of a load balancer can be determined directly using the <code>kubectl</code> tool:</p> +<pre tabindex="0"><code>$ kubectl --namespace=istio-nginx describe service | grep &#34;LoadBalancer&#34; +LoadBalancer Ingress: a493e4e58ea0511e5bb390686bc85da3-1558404688.us-west-2.elb.amazonaws.com +</code></pre><p>The <code>LoadBalancer Ingress</code> field typically describes an existing domain name or public IP(s). Note that if Kubernetes is able to automatically provision a load balancer for you, it does so asynchronously. If the command shown above is issued very soon after Workflow installation, the load balancer may not exist yet.</p> +<h2 id="without-a-load-balancer">Without a Load Balancer<a class="td-heading-self-link" href="#without-a-load-balancer" aria-label="Heading self-link"></a></h2> +<p>On some platforms (Minikube, for instance), a load balancer is not an easy or practical thing to provision. In these cases, one can directly identify the public IP of a Kubernetes node that is hosting a router pod and use that information to configure the local <code>/etc/hosts</code> file.</p> +<p>Because wildcard entries do not work in a local <code>/etc/hosts</code> file, using this strategy may result in frequent editing of that file to add fully-qualified subdomains of a cluster for each application added to that cluster. Because of this a more viable option may be to utilize the <a href="http://xip.io/">xip.io</a> service.</p> +<p>In general, for any IP, <code>a.b.c.d</code>, the fully-qualified domain name <code>any-subdomain.a.b.c.d.xip.io</code> will resolve to the IP <code>a.b.c.d</code>. This can be enormously useful.</p> +<p>To begin, find the node(s) hosting router instances using <code>kubectl</code>:</p> +<pre tabindex="0"><code>$ kubectl --namespace=istio-ingress describe pod | grep Node: +Node: ip-10-0-0-199.us-west-2.compute.internal/10.0.0.199 +Node: ip-10-0-0-198.us-west-2.compute.internal/10.0.0.198 +</code></pre><p>The command will display information for every router pod. For each, a node name and IP are displayed in the <code>Node</code> field. If the IPs appearing in these fields are public, any of these may be used to configure your local <code>/etc/hosts</code> file or may be used with <a href="http://xip.io/">xip.io</a>. If the IPs shown are not public, further investigation may be needed.</p> +<p>You can list the IP addresses of a node using <code>kubectl</code>:</p> +<pre tabindex="0"><code>$ kubectl describe node ip-10-0-0-199.us-west-2.compute.internal +# ... +Addresses: 10.0.0.199,10.0.0.199,54.218.85.175 +# ... +</code></pre><p>Here, the <code>Addresses</code> field lists all the node&rsquo;s IPs. If any of them are public, again, they may be used to configure your local <code>/etc/hosts</code> file or may be used with <a href="http://xip.io/">xip.io</a>.</p> +<h2 id="tutorial-configuring-dns-with-google-cloud-dnscloud-dns">Tutorial: Configuring DNS with <a href="https://cloud.google.com/dns/docs">Google Cloud DNS</a><a class="td-heading-self-link" href="#tutorial-configuring-dns-with-google-cloud-dnscloud-dns" aria-label="Heading self-link"></a></h2> +<p>In this section, we&rsquo;ll describe how to configure Google Cloud DNS for routing your domain name to your Drycc cluster.</p> +<p>We&rsquo;ll assume the following in this section:</p> +<ul> +<li>Your Ingress service has a load balancer in front of it. +<ul> +<li>The load balancer need not be cloud based, it just needs to provide a stable IP address or a stable domain name</li> +</ul> +</li> +<li>You have the <code>mystuff.com</code> domain name registered with a registrar +<ul> +<li>Replace your domain name with <code>mystuff.com</code> in the instructions to follow</li> +</ul> +</li> +<li>Your registrar lets you alter the nameservers for your domain name (most registrars do)</li> +</ul> +<p>Here are the steps for configuring cloud DNS to route to your drycc cluster:</p> +<ol> +<li>Get the load balancer IP or domain name</li> +</ol> +<ul> +<li>If you are on Google Container Engine, you can run <code>kubectl get svc -n istio-ingress</code> and look for the <code>LoadBalancer Ingress</code> column to get the IP address</li> +</ul> +<ol start="2"> +<li>Create a new Cloud DNS Zone (on the console: <code>Networking</code> =&gt; <code>Cloud DNS</code>, then click on <code>Create Zone</code>)</li> +<li>Name your zone, and set the DNS name to <code>mystuff.com.</code> (note the <code>.</code> at the end</li> +<li>Click on the <code>Create</code> button</li> +<li>Click on the <code>Add Record Set</code> button on the resulting page</li> +<li>If your load balancer provides a stable IP address, enter the following fields in the resulting form:</li> +<li><code>DNS Name</code>: <code>*</code></li> +<li><code>Resource Record Type</code>: <code>A</code></li> +<li><code>TTL</code>: the DNS TTL of your choosing. If you&rsquo;re testing or you anticipate that you&rsquo;ll tear down and rebuild many drycc clusters over time, we recommend a low TTL</li> +<li><code>IPv4 Address</code>: The IP that you got in the very first step</li> +<li>Click the <code>Create</code> button</li> +<li>If your load balancer provides the stable domain name <code>lbdomain.com</code>, enter the following fields in the resulting form:</li> +<li><code>DNS Name</code>: <code>*</code></li> +<li><code>Resource Record Type</code>: <code>CNAME</code></li> +<li><code>TTL</code>: the DNS TTL of your choosing. If you&rsquo;re testing or you anticipate that you&rsquo;ll tear down and rebuild many drycc clusters over time, we recommend a low TTL</li> +<li><code>Canonical name</code>: <code>lbdomain.com.</code> (note the <code>.</code> a the end)</li> +<li>Click on the <code>Create</code> button</li> +<li>In your domain registrar, set the nameservers for your <code>mystuff.com</code> domain to the ones under the <code>data</code> column in the <code>NS</code> record on the same page. They&rsquo;ll often be something like the below (note the trailing <code>.</code> characters).</li> +</ol> +<pre tabindex="0"><code>ns-cloud-b1.googledomains.com. +ns-cloud-b2.googledomains.com. +ns-cloud-b3.googledomains.com. +ns-cloud-b4.googledomains.com. +</code></pre><p>Note: If you ever have to re-create your drycc cluster, simply go back to step 6.4 or 7.4 (depending on your load balancer) and change the IP address or domain name to the new value. You may have to wait for the TTL you set to expire.</p> +<h2 id="testing">Testing<a class="td-heading-self-link" href="#testing" aria-label="Heading self-link"></a></h2> +<p>To test that traffic reaches its intended destination, a request can be +sent to the Drycc controller like so (do not forget the trailing slash!):</p> +<pre tabindex="0"><code>curl http://drycc.example.com/v2/ +</code></pre><p>Or:</p> +<pre tabindex="0"><code>curl http://drycc.54.218.85.175.xip.io/v2/ +</code></pre><p>Since such requests require authentication, a response such as the following should be considered an indicator of success:</p> +<pre tabindex="0"><code>{&#34;detail&#34;:&#34;Authentication credentials were not provided.&#34;} +</code></pre> + + + + + Docs: Design Documents + /docs/contribution-guidelines/design-documents/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/contribution-guidelines/design-documents/ + + + + <p>Before submitting a pull request which will significantly alter the behavior of any Drycc component, such as a new feature or major refactoring, contributors should first open an issue representing a design document.</p> +<h2 id="goals">Goals<a class="td-heading-self-link" href="#goals" aria-label="Heading self-link"></a></h2> +<p>Design documents help ensure project contributors:</p> +<ul> +<li>Involve stakeholders as early as possible in a feature&rsquo;s development</li> +<li>Ensure code changes accomplish the original motivations and design goals</li> +<li>Establish clear acceptance criteria for a feature or change</li> +<li>Enforce test-driven design methodology and automated test coverage</li> +</ul> +<h2 id="contents">Contents<a class="td-heading-self-link" href="#contents" aria-label="Heading self-link"></a></h2> +<p>Design document issues should be named <code>Design Doc: &lt;change description&gt;</code> and contain the following sections:</p> +<h3 id="goal">Goal<a class="td-heading-self-link" href="#goal" aria-label="Heading self-link"></a></h3> +<p>This section should briefly describe the proposed change and the motivations behind it. Tests will be written to ensure this design goal is met by the change.</p> +<p>This section should also reference a separate GitHub issue tracking the feature or change, which will typically be assigned to a release milestone.</p> +<h3 id="code-changes">Code Changes<a class="td-heading-self-link" href="#code-changes" aria-label="Heading self-link"></a></h3> +<p>This section should detail the code changes necessary to accomplish the change, as well as the proposed implementation. This should be as detailed as necessary to help reviewers understand the change.</p> +<h3 id="tests">Tests<a class="td-heading-self-link" href="#tests" aria-label="Heading self-link"></a></h3> +<p>All changes should be covered by automated tests, either unit or integration tests (ideally both). This section should detail how tests will be written to validate that the change accomplishes the design goals and doesn&rsquo;t introduce any regressions.</p> +<p>If a change cannot be sufficiently covered by automated testing, the design should be reconsidered. If there is no test coverage whatsoever for an affected section of code, a separate issue should be filed to integrate automated testing with that section of the codebase.</p> +<p>The tests described here also form the acceptance criteria for the change, so that when it&rsquo;s completed maintainers can merge the pull request after confirming the tests pass CI.</p> +<h3 id="approval">Approval<a class="td-heading-self-link" href="#approval" aria-label="Heading self-link"></a></h3> +<p>A design document follows the same <a href="/docs/contribution-guidelines/submitting-a-pull-request/#merge-approval">merge approval</a> review process as final pull requests do, and maintainers will take extra care to ensure that any stakeholders for the change are included in the discussion and review of the design document.</p> +<p>Once the design is accepted, the author can complete the change and submit a pull request for review. The pull request should close both the design document for the change as well as any issues that either track the issue or are closed as a result of the change.</p> +<p>See <a href="/docs/contribution-guidelines/submitting-a-pull-request/">Submitting a Pull Request</a> for more information on pull request and commit message formatting.</p> + + + + + + Docs: Install Workflow + /docs/quickstart/install-workflow/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/quickstart/install-workflow/ + + + + <p>If you have a pure host, it can be a cloud server, bare metal server, virtual machine, or even your laptop. Then this chapter is very suitable for you.</p> +<h2 id="operating-systems">Operating Systems<a class="td-heading-self-link" href="#operating-systems" aria-label="Heading self-link"></a></h2> +<p>Drycc is expected to work on most modern Linux systems. Some OSS have specific requirements:</p> +<ul> +<li>(Red Hat/CentOS) Enterprise Linux, they usually use RPM package management.</li> +<li>Ubuntu (Desktop/Server/Cloud) Linux, a very popular distribution.</li> +<li>Debian GNU Linux, a very pure distribution of opensource software.</li> +</ul> +<p>If you want to add more Linux distribution support, please submit a issue on github or submit PR directly.</p> +<h2 id="system-software">System Software<a class="td-heading-self-link" href="#system-software" aria-label="Heading self-link"></a></h2> +<p>Some basic software needs to be installed before installing drycc workflow.</p> +<h3 id="os-configuration">OS configuration<a class="td-heading-self-link" href="#os-configuration" aria-label="Heading self-link"></a></h3> +<p>K8s requires a large number of ports. If you are not sure what they are, please close the local firewall or open these ports. +At the same time, because k8s you need system time, you need to ensure that the system time is correct.</p> +<h3 id="installing-nfsv4-client">Installing NFSv4 client<a class="td-heading-self-link" href="#installing-nfsv4-client" aria-label="Heading self-link"></a></h3> +<p>The command used to install a NFSv4 client differs depending on the Linux distribution.</p> +<p>For Debian and Ubuntu, use this command:</p> +<pre tabindex="0"><code>$ apt-get install nfs-common +</code></pre><p>For RHEL, CentOS, and EKS with EKS Kubernetes Worker AMI with AmazonLinux2 image, use this command:</p> +<pre tabindex="0"><code>$ yum install nfs-utils +</code></pre><h3 id="installing-curl">Installing curl<a class="td-heading-self-link" href="#installing-curl" aria-label="Heading self-link"></a></h3> +<p>For Debian and Ubuntu, use this command:</p> +<pre tabindex="0"><code>$ apt-get install curl +</code></pre><p>For RHEL, CentOS, and EKS with EKS Kubernetes Worker AMI with AmazonLinux2 image, use this command:</p> +<pre tabindex="0"><code>$ yum install curl +</code></pre><h2 id="hardware">Hardware<a class="td-heading-self-link" href="#hardware" aria-label="Heading self-link"></a></h2> +<p>Hardware requirements scale based on the size of your deployments. Minimum recommendations are outlined here.</p> +<ul> +<li>RAM: 1G Minimum (we recommend at least 2GB)</li> +<li>CPU: 1 Minimum</li> +</ul> +<p>This configuration only contains the minimum requirements that can meet the operation.</p> +<h2 id="disk">Disk<a class="td-heading-self-link" href="#disk" aria-label="Heading self-link"></a></h2> +<p>Drycc performance depends on the performance of the database. To ensure optimal speed, we recommend using an SSD when possible. Disk performance will vary on ARM devices utilizing an SD card or eMMC.</p> +<h2 id="domain-name">Domain Name<a class="td-heading-self-link" href="#domain-name" aria-label="Heading self-link"></a></h2> +<p>Drycc needs a root domain name under your full control and points this domain name to the server to be installed. +Suppose there is a wildcard domain pointing to the current server to install drycc, which is the name <code>*.dryccdoman.com</code>. +We need to set the <code>PLATFORM_DOMAIN</code> environment variables before installation.</p> +<pre tabindex="0"><code>$ export PLATFORM_DOMAIN=dryccdoman.co +</code></pre><p>Of course, if it is a test environment, we can also use <code>nip.io</code>, an IP to domain name service. +For example, your host IP is <code>59.46.3.190</code>, we will get the following domain name <code>59.46.3.190.nip.io</code></p> +<pre tabindex="0"><code>$ export PLATFORM_DOMAIN=59.46.3.190.nip.io +</code></pre><h2 id="install">Install<a class="td-heading-self-link" href="#install" aria-label="Heading self-link"></a></h2> +<p>Before installation, please make sure whether your installation environment is a public network. +If it is an intranet environment and there is no public IP, you need to disable the automatic certificate.</p> +<pre tabindex="0"><code>$ export CERT_MANAGER_ENABLED=false +</code></pre><p>Then you can use the installation script available at <a href="https://www.drycc.cc/install.sh">https://www.drycc.cc/install.sh</a> to install drycc as a service on systemd and openrc based systems.</p> +<pre tabindex="0"><code>$ curl -sfL https://www.drycc.cc/install.sh | bash - +</code></pre><p>!!! important +If you are in China, you need to use mirror acceleration:</p> +<pre><code>``` +$ curl -sfL https://www.drycc.cc/install.sh | INSTALL_DRYCC_MIRROR=cn bash - +``` +</code></pre> +<h3 id="install-node">Install Node<a class="td-heading-self-link" href="#install-node" aria-label="Heading self-link"></a></h3> +<p>Node can be a simple agent or a server; Server has the function of agent. Multiple servers have high availability, but the number of servers should not +exceed 7 at most. There is no limit to the number of agents.</p> +<ul> +<li>First, check the cluster token of the master.</li> +</ul> +<pre tabindex="0"><code>$ cat /var/lib/rancher/k3s/server/node-token +K1078e7213ca32bdaabb44536f14b9ce7926bb201f41c3f3edd39975c16ff4901ea::server:33bde27f-ac49-4483-b6ac-f4eec2c6dbfa +</code></pre><p>We assume that the IP address of the cluster master is <code>192.168.6.240</code>, in that way.</p> +<ul> +<li>Then, Set the environment variable:</li> +</ul> +<pre tabindex="0"><code>$ export K3S_URL=https://192.168.6.240:6443 +$ export K3S_TOKEN=&#34;K1078e7213ca32bdaabb44536f14b9ce7926bb201f41c3f3edd39975c16ff4901ea::server:33bde27f-ac49-4483-b6ac-f4eec2c6dbfa&#34; +</code></pre><p>!!! important +If you are in China, you need to use mirror acceleration:</p> +<pre><code>``` +$ export INSTALL_DRYCC_MIRROR=cn +``` +</code></pre> +<ul> +<li>Join the cluster as server:</li> +</ul> +<pre tabindex="0"><code>$ curl -sfL https://www.drycc.cc/install.sh | bash -s - install_k3s_server +</code></pre><ul> +<li>Join the cluster as agent:</li> +</ul> +<pre tabindex="0"><code>$ curl -sfL https://www.drycc.cc/install.sh | bash -s - install_k3s_agent +</code></pre><h3 id="install-options">Install Options<a class="td-heading-self-link" href="#install-options" aria-label="Heading self-link"></a></h3> +<p>When using this method to install drycc, the following environment variables can be used to configure the installation:</p> +<table> +<thead> +<tr> +<th>ENVIRONMENT VARIABLE</th> +<th>DESCRIPTION</th> +</tr> +</thead> +<tbody> +<tr> +<td>PLATFORM_DOMAIN</td> +<td>Required item, specify drycc&rsquo;s domain name</td> +</tr> +<tr> +<td>DRYCC_ADMIN_USERNAME</td> +<td>Required item, specify drycc&rsquo;s admin username</td> +</tr> +<tr> +<td>DRYCC_ADMIN_PASSWORD</td> +<td>Required item, specify drycc&rsquo;s admin password</td> +</tr> +<tr> +<td>CERT_MANAGER_ENABLED</td> +<td>Whether to use automatic certificate. It is <code>false</code> by default</td> +</tr> +<tr> +<td>CHANNEL</td> +<td>By default, <code>stable</code> channel will be installed. You can also specify <code>testing</code></td> +</tr> +<tr> +<td>REGISTRY_FILE</td> +<td>The <code>config.yaml</code> file path used by k3s containers registry</td> +</tr> +<tr> +<td>KUBERNETES_SERVICE_HOST</td> +<td>Set with the HOST of the loadbalancer that was in front of kube-apiserver</td> +</tr> +<tr> +<td>KUBERNETES_SERVICE_PORT</td> +<td>Set with the PORT of the loadbalancer that was in front of kube-apiserver</td> +</tr> +<tr> +<td>METALLB_CONFIG_FILE</td> +<td>The metallb config file path, layer 2 network is used by default</td> +</tr> +<tr> +<td>INSTALL_DRYCC_MIRROR</td> +<td>Specify the accelerated mirror location. Currently, only <code>cn</code> is supported</td> +</tr> +<tr> +<td>BUILDER_REPLICAS</td> +<td>Number of builder replicas to deploy</td> +</tr> +<tr> +<td>CONTROLLER_API_REPLICAS</td> +<td>Number of controller api replicas to deploy</td> +</tr> +<tr> +<td>CONTROLLER_CELERY_REPLICAS</td> +<td>Number of controller celery replicas to deploy</td> +</tr> +<tr> +<td>CONTROLLER_WEBHOOK_REPLICAS</td> +<td>Number of controller webhook replicas to deploy</td> +</tr> +<tr> +<td>CONTROLLER_APP_RUNTIME_CLASS</td> +<td>RuntimeClass is a feature for selecting the container runtime configuration.</td> +</tr> +<tr> +<td>CONTROLLER_APP_STORAGE_CLASS</td> +<td>StorageClass allocated by <code>drycc volumes</code>; default storageClass is used by default</td> +</tr> +<tr> +<td>REDIS_REPLICAS</td> +<td>Number of redis replicas to deploy</td> +</tr> +<tr> +<td>REDIS_PERSISTENCE_SIZE</td> +<td>The size of the persistence space allocated to <code>redis</code>, which is <code>5Gi</code> by default</td> +</tr> +<tr> +<td>REDIS_PERSISTENCE_STORAGE_CLASS</td> +<td>StorangeClass of <code>redis</code>; default storangeclass is used by default</td> +</tr> +<tr> +<td>STORAGE_CSI_STATEFULSET_REPLICAS</td> +<td>Number of storage csi controller replicas to deploy</td> +</tr> +<tr> +<td>STORAGE_MAINNODE_TIPD_REPLICAS</td> +<td>Number of storage mainode tipd replicas to deploy</td> +</tr> +<tr> +<td>STORAGE_MAINNODE_TIPD_PERSISTENCE_SIZE</td> +<td>The size of the persistence space allocated to <code>mainnode tipd</code>, which is <code>10Gi</code> by default</td> +</tr> +<tr> +<td>STORAGE_MAINNODE_TIPD_PERSISTENCE_STORAGE_CLASS</td> +<td>StorangeClass of <code>mainnode tipd</code>; default storangeclass is used by default</td> +</tr> +<tr> +<td>STORAGE_MAINNODE_WEED_REPLICAS</td> +<td>Number of storage mainode weed replicas to deploy</td> +</tr> +<tr> +<td>STORAGE_MAINNODE_WEED_PREALLOCATE</td> +<td>Preallocate disk space for volumes, <code>false</code> is used by default</td> +</tr> +<tr> +<td>STORAGE_MAINNODE_WEED_SIZE_LIMIT_MB</td> +<td>Master stops directing writes to oversized volumes, <code>30000</code> is used by default</td> +</tr> +<tr> +<td>STORAGE_MAINNODE_WEED_DEFAULT_REPLICATION</td> +<td>default replication type if not specified, which is <code>000</code> by default</td> +</tr> +<tr> +<td>STORAGE_MAINNODE_WEED_PERSISTENCE_SIZE</td> +<td>The size of the persistence space allocated to <code>mainnode weed</code>, which is <code>10Gi</code> by default</td> +</tr> +<tr> +<td>STORAGE_MAINNODE_WEED_PERSISTENCE_STORAGE_CLASS</td> +<td>StorangeClass of <code>mainnode weed</code>; default storangeclass is used by default</td> +</tr> +<tr> +<td>STORAGE_METANODE_TIKV_REPLICAS</td> +<td>Number of storage metanode tikv replicas to deploy</td> +</tr> +<tr> +<td>STORAGE_METANODE_TIKV_PERSISTENCE_SIZE</td> +<td>The size of the persistence space allocated to <code>metanode tikv</code>, which is <code>10Gi</code> by default</td> +</tr> +<tr> +<td>STORAGE_METANODE_TIKV_PERSISTENCE_STORAGE_CLASS</td> +<td>StorangeClass of <code>mainnode tikv</code>; default storangeclass is used by default</td> +</tr> +<tr> +<td>STORAGE_METANODE_WEED_REPLICAS</td> +<td>Number of storage metanode weed replicas to deploy</td> +</tr> +<tr> +<td>STORAGE_METANODE_WEED_PERSISTENCE_SIZE</td> +<td>The size of the persistence space allocated to <code>metanode weed</code>, which is <code>10Gi</code> by default</td> +</tr> +<tr> +<td>STORAGE_METANODE_WEED_PERSISTENCE_STORAGE_CLASS</td> +<td>StorangeClass of <code>mainnode weed</code>; default storangeclass is used by default</td> +</tr> +<tr> +<td>STORAGE_DATANODE_WEED_REPLICAS</td> +<td>Number of storage datanode weed replicas to deploy</td> +</tr> +<tr> +<td>STORAGE_DATANODE_WEED_PERSISTENCE_SIZE</td> +<td>The size of the persistence space allocated to <code>datanode weed</code>, which is <code>20Gi</code> by default</td> +</tr> +<tr> +<td>STORAGE_DATANODE_WEED_PERSISTENCE_STORAGE_CLASS</td> +<td>StorangeClass of <code>datanode weed</code>; default storangeclass is used by default</td> +</tr> +<tr> +<td>MONITOR_GRAFANA_PERSISTENCE_SIZE</td> +<td>The size of the persistence space allocated to <code>monitor.grafana</code>, which is <code>5Gi</code> by default</td> +</tr> +<tr> +<td>MONITOR_GRAFANA_PERSISTENCE_STORAGE_CLASS</td> +<td>StorangeClass of <code>monitor</code> grafana; default storangeclass is used by default</td> +</tr> +<tr> +<td>LOGGER_REPLICAS</td> +<td>Number of logger replicas to deploy</td> +</tr> +<tr> +<td>RABBITMQ_REPLICAS</td> +<td>Number of rabbitmq replicas to deploy</td> +</tr> +<tr> +<td>RABBITMQ_PERSISTENCE_SIZE</td> +<td>The size of the persistence space allocated to <code>rabbitmq</code>, which is <code>5Gi</code> by default</td> +</tr> +<tr> +<td>RABBITMQ_PERSISTENCE_STORAGE_CLASS</td> +<td>StorangeClass of <code>rabbitmq</code>; default storangeclass is used by default</td> +</tr> +<tr> +<td>DATABASE_REPLICAS</td> +<td>Number of database replicas to deploy</td> +</tr> +<tr> +<td>DATABASE_PERSISTENCE_SIZE</td> +<td>The size of the persistence space allocated to <code>database</code>, which is <code>5Gi</code> by default</td> +</tr> +<tr> +<td>DATABASE_PERSISTENCE_STORAGE_CLASS</td> +<td>StorangeClass of <code>database</code>; default storangeclass is used by default</td> +</tr> +<tr> +<td>TIMESERIES_REPLICAS</td> +<td>Number of timeseries replicas to deploy</td> +</tr> +<tr> +<td>TIMESERIES_PERSISTENCE_SIZE</td> +<td>The size of the persistence space allocated to <code>timeseries</code>, which is <code>5Gi</code> by default</td> +</tr> +<tr> +<td>TIMESERIES_PERSISTENCE_STORAGE_CLASS</td> +<td>StorangeClass of <code>timeseries</code>; default storangeclass is used by default</td> +</tr> +<tr> +<td>PASSPORT_REPLICAS</td> +<td>Number of passport replicas to deploy</td> +</tr> +<tr> +<td>REGISTRY_REPLICAS</td> +<td>Number of registry replicas to deploy</td> +</tr> +<tr> +<td>HELMBROKER_REPLICAS</td> +<td>Number of helmbroker api replicas to deploy</td> +</tr> +<tr> +<td>HELMBROKER_CELERY_REPLICAS</td> +<td>Number of helmbroker celery replicas to deploy</td> +</tr> +<tr> +<td>HELMBROKER_PERSISTENCE_SIZE</td> +<td>The size of the persistence space allocated to <code>helmbroker</code>, which is <code>5Gi</code> by default</td> +</tr> +<tr> +<td>HELMBROKER_PERSISTENCE_STORAGE_CLASS</td> +<td>StorangeClass of <code>helmbroker</code>; default storangeclass is used by default</td> +</tr> +<tr> +<td>PROMETHEUS_SERVER_RETENTION</td> +<td>Prometheus data retention period (default if not specified is 15 days)</td> +</tr> +<tr> +<td>PROMETHEUS_SERVER_PERSISTENCE_SIZE</td> +<td>The size of the persistence space allocated to <code>prometheus-server</code>, which is <code>10Gi</code> by default</td> +</tr> +<tr> +<td>PROMETHEUS_SERVER_PERSISTENCE_STORAGE_CLASS</td> +<td>StorangeClass of <code>prometheus-server</code>; default storangeclass is used by default</td> +</tr> +<tr> +<td>K3S_DATA_DIR</td> +<td>The config of k3s data dir; If not set, the default path is used</td> +</tr> +<tr> +<td>ACME_SERVER</td> +<td>ACME Server url, default use letsencrypt</td> +</tr> +<tr> +<td>ACME_EAB_KEY_ID</td> +<td>The key ID of which your external account binding is indexed by the external account</td> +</tr> +<tr> +<td>ACME_EAB_KEY_SECRET</td> +<td>The key Secret of which your external account symmetric MAC key</td> +</tr> +</tbody> +</table> +<p>Since the installation script will install k3s, other environment variables can refer to k3s installation <a href="https://rancher.com/docs/k3s/latest/en/installation/install-options/">environment variables</a>.</p> +<h2 id="uninstall">Uninstall<a class="td-heading-self-link" href="#uninstall" aria-label="Heading self-link"></a></h2> +<p>If you installed drycc using an installation script, you can uninstall the entire drycc using this script.</p> +<pre tabindex="0"><code>$ curl -sfL https://www.drycc.cc/uninstall.sh | bash - +</code></pre> + + + + + Docs: Specify Gateway + /docs/installing-workflow/gateway/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/installing-workflow/gateway/ + + + + <h2 id="install-drycc-workflow-specify-gateway">Install Drycc Workflow (Specify gateway)<a class="td-heading-self-link" href="#install-drycc-workflow-specify-gateway" aria-label="Heading self-link"></a></h2> +<p>Now that Helm is installed and the repository has been added, install Workflow with a native gateway by running:</p> +<pre tabindex="0"><code>$ helm install drycc oci://registry.drycc.cc/charts/workflow \ + --namespace drycc \ + --set global.gatewayClass=istio \ + --set global.platformDomain=drycc.cc \ + --set builder.service.type=LoadBalancer +</code></pre><p>Of course, if you deploy it on a bare machine, you probably do not have Load Balancer. You need to use NodePort:</p> +<pre tabindex="0"><code>$ helm install drycc oci://registry.drycc.cc/charts/workflow \ + --namespace drycc \ + --set global.gatewayClass=istio \ + --set global.platformDomain=drycc.cc \ + --set builder.service.type=NodePort \ + --set builder.service.nodePort=32222 +</code></pre><p>If you want to use Load Balancer on a bare machine, you can look at <a href="https://github.com/metallb/metallb">metallb</a></p> +<p>Where <code>global.platformDomain</code> is a <strong>required</strong> parameter that is traditionally not required for Workflow that is explained in the next section. In this example we are using <code>drycc.cc</code> for <code>$hostname</code>.</p> +<p>Helm will install a variety of Kubernetes resources in the <code>drycc</code> namespace. +Wait for the pods that Helm launched to be ready. Monitor their status by running:</p> +<pre tabindex="0"><code>$ kubectl --namespace=drycc get pods +</code></pre><p>You should also notice that several Kubernetes gatewayclass has been installed on your cluster. You can view it by running:</p> +<pre tabindex="0"><code>$ kubectl get gatewayclass --namespace drycc +</code></pre><p>Depending on the order in which the Workflow components initialize, some pods may restart. This is common during the +installation: if a component&rsquo;s dependencies are not yet available, that component will exit and Kubernetes will +automatically restart it.</p> +<p>Here, it can be seen that the controller, builder and registry all took a few loops waiting for storage before they were able to start:</p> +<pre tabindex="0"><code>$ kubectl --namespace=drycc get pods +NAME READY STATUS RESTARTS AGE +drycc-builder-hy3xv 1/1 Running 5 5m +drycc-controller-g3cu8 1/1 Running 5 5m +drycc-controller-celery-cmxxn 3/3 Running 0 5m +drycc-database-rad1o 1/1 Running 0 5m +drycc-logger-fluentbit-1v8uk 1/1 Running 0 5m +drycc-logger-fluentbit-esm60 1/1 Running 0 5m +drycc-logger-sm8b3 1/1 Running 0 5m +drycc-storage-4ww3t 1/1 Running 0 5m +drycc-registry-asozo 1/1 Running 1 5m +drycc-rabbitmq-0 1/1 Running 0 5m +</code></pre><h2 id="install-a-kubernetes-gateway">Install a Kubernetes Gateway<a class="td-heading-self-link" href="#install-a-kubernetes-gateway" aria-label="Heading self-link"></a></h2> +<p>Now that Workflow has been deployed with the <code>global.gatewayClass</code> , we will need a Kubernetes gateway in place to begin routing traffic.</p> +<p>Here is an example of how to use <a href="https://istio.io/">istio</a> as an gateway for Workflow. Of course, you are welcome to use any controller you wish.</p> +<pre tabindex="0"><code>$ helm repo add istio https://istio-release.storage.googleapis.com/charts +$ helm repo update +$ kubectl create namespace istio-system +$ helm install istio-base istio/base -n istio-system +$ helm install istiod istio/istiod -n istio-system --wait +$ kubectl create namespace istio-ingress +$ helm install istio-ingress istio/gateway -n istio-ingress --wait +</code></pre><h2 id="configure-dns">Configure DNS<a class="td-heading-self-link" href="#configure-dns" aria-label="Heading self-link"></a></h2> +<p>User must install <a href="/docs/quickstart/install-workflow/">drycc</a> and then set up a hostname, and assumes the <code>*.$host</code> convention.</p> +<p>We need to point the <code>*.$host</code> record to the public IP address of your gateway. You can get the public IP using the following command. A wildcard entry is necessary here as apps will use the same rule after they are deployed.</p> +<pre tabindex="0"><code>$ kubectl get gateway --namespace drycc +NAME CLASS ADDRESS PROGRAMMED AGE +gateway istio 138.91.243.152 True 36d +</code></pre><p>If we were using <code>drycc.cc</code> as a hostname, we would need to create the following A DNS records.</p> +<table> +<thead> +<tr> +<th>Name</th> +<th style="text-align:center">Type</th> +<th style="text-align:right">Value</th> +</tr> +</thead> +<tbody> +<tr> +<td>*.drycc.cc</td> +<td style="text-align:center">A</td> +<td style="text-align:right">138.91.243.152</td> +</tr> +</tbody> +</table> +<p>Once all of the pods are in the <code>READY</code> state, and <code>*.$host</code> resolves to the external IP found above, the preparation of gateway has been completed!</p> +<p>After installing Workflow, <a href="/docs/quickstart/deploy-an-app/">register a user and deploy an application</a>.</p> +<p>If your k8s does not provide public network loadblance, you need to install TCP proxy services such as haproxy on machines that can +access both internal and external networks, and then expose <code>80</code> and <code>443</code>.</p> + + + + + + Docs: Installing Drycc Workflow + /docs/installing-workflow/workflow/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/installing-workflow/workflow/ + + + + <p>If help is required getting started with Kubernetes and +Drycc Workflow, follow the <a href="/docs/quickstart/">quickstart guide</a> for assistance.</p> +<h2 id="prerequisites">Prerequisites<a class="td-heading-self-link" href="#prerequisites" aria-label="Heading self-link"></a></h2> +<ol> +<li>Verify the <a href="/docs/installing-workflow/system-requirements/">Kubernetes system requirements</a></li> +<li>Install <a href="/docs/quickstart/install-cli-tools/">Helm and Drycc Workflow CLI</a> tools</li> +</ol> +<h2 id="check-your-setup">Check Your Setup<a class="td-heading-self-link" href="#check-your-setup" aria-label="Heading self-link"></a></h2> +<p>Check that the <code>helm</code> command is available and the version is v2.5.0 or newer.</p> +<pre tabindex="0"><code>$ helm version +Client: &amp;version.Version{SemVer:&#34;v2.5.0&#34;, GitCommit:&#34;012cb0ac1a1b2f888144ef5a67b8dab6c2d45be6&#34;, GitTreeState:&#34;clean&#34;} +Server: &amp;version.Version{SemVer:&#34;v2.5.0&#34;, GitCommit:&#34;012cb0ac1a1b2f888144ef5a67b8dab6c2d45be6&#34;, GitTreeState:&#34;clean&#34;} +</code></pre><h2 id="choose-your-deployment-strategy">Choose Your Deployment Strategy<a class="td-heading-self-link" href="#choose-your-deployment-strategy" aria-label="Heading self-link"></a></h2> +<p>Drycc Workflow includes everything it needs to run out of the box. However, these defaults are aimed at simplicity rather than +production readiness. Production and staging deployments of Workflow should, at a minimum, use off-cluster storage +which is used by Workflow components to store and backup critical data. Should an operator need to completely re-install +Workflow, the required components can recover from off-cluster storage. See the documentation for <a href="/docs/installing-workflow/configuring-object-storage/">configuring object +storage</a> for more details.</p> +<p>More rigorous installations would benefit from using outside sources for the following things:</p> +<ul> +<li><a href="/docs/installing-workflow/configuring-postgres/">Postgres</a> - For example AWS RDS.</li> +<li><a href="/docs/installing-workflow/configuring-registry/">Registry</a> - This includes <a href="https://quay.io">quay.io</a>, <a href="https://hub.docker.com">dockerhub</a>, <a href="https://aws.amazon.com/ecr/">Amazon ECR</a>, and <a href="https://cloud.google.com/container-registry/">Google GCR</a>.</li> +<li><a href="/docs/managing-workflow/platform-logging/#configuring-off-cluster-redis">Redis</a> - Such as AWS Elasticache</li> +<li><a href="/docs/managing-workflow/platform-monitoring/#off-cluster-grafana">Grafana</a></li> +</ul> +<h4 id="gateway">Gateway<a class="td-heading-self-link" href="#gateway" aria-label="Heading self-link"></a></h4> +<p>Now, workflow requires that gateway and cert-manager must be installed. Any compatible Kubernetes entry controller can be used.</p> +<h2 id="install-drycc-workflow">Install Drycc Workflow<a class="td-heading-self-link" href="#install-drycc-workflow" aria-label="Heading self-link"></a></h2> +<p>If the version of helm is 3.0 +; you need to create the namespace in advance:</p> +<pre tabindex="0"><code>kubectl create ns drycc +</code></pre><p>If you want to change it, set the variable when using helm.</p> +<pre tabindex="0"><code>$ helm install drycc oci://registry.drycc.cc/charts/workflow \ + --namespace drycc \ + --set builder.imageRegistry=quay.io \ + --set imagebuilder.imageRegistry=quay.io \ + --set controller.imageRegistry=quay.io \ + --set database.imageRegistry=quay.io \ + --set fluentbit.imageRegistry=quay.io \ + --set redis.imageRegistry=quay.io \ + --set rabbitmq.imageRegistry=quay.io \ + --set logger.imageRegistry=quay.io \ + --set storage.imageRegistry=quay.io \ + --set monitor.imageRegistry=quay.io \ + --set registry.imageRegistry=quay.io \ + --set registry-proxy.imageRegistry=quay.io \ + --set global.platformDomain=drycc.cc +</code></pre><p>Helm will install a variety of Kubernetes resources in the <code>drycc</code> namespace. +Wait for the pods that Helm launched to be ready. Monitor their status by running:</p> +<pre tabindex="0"><code>$ kubectl --namespace=drycc get pods +</code></pre><p>If it&rsquo;s preferred to have <code>kubectl</code> automatically update as the pod states change, run (type Ctrl-C to stop the watch):</p> +<pre tabindex="0"><code>$ kubectl --namespace=drycc get pods -w +</code></pre><p>Depending on the order in which the Workflow components initialize, some pods may restart. This is common during the +installation: if a component&rsquo;s dependencies are not yet available, that component will exit and Kubernetes will +automatically restart it.</p> +<p>Here, it can be seen that the controller, builder and registry all took a few loops before they were able to start:</p> +<pre tabindex="0"><code>$ kubectl --namespace=drycc get pods +NAME READY STATUS RESTARTS AGE +drycc-builder-574483744-l15zj 1/1 Running 0 4m +drycc-controller-3953262871-pncgq 1/1 Running 2 4m +drycc-controller-celery-cmxxn 3/3 Running 0 4m +drycc-database-83844344-47ld6 1/1 Running 0 4m +drycc-logger-176328999-wjckx 1/1 Running 4 4m +drycc-logger-fluentbit-zxnqb 1/1 Running 0 4m +drycc-redis-304849759-1f35p 1/1 Running 0 4m +drycc-storage-676004970-nxqgt 1/1 Running 0 4m +drycc-monitor-grafana-432627134-lnl2h 1/1 Running 0 4m +drycc-monitor-telegraf-wmcmn 1/1 Running 1 4m +drycc-registry-756475849-lwc6b 1/1 Running 1 4m +drycc-registry-proxy-96c4p 1/1 Running 0 4m +drycc-rabbitmq-0 1/1 Running 0 4m +</code></pre><p>Once all of the pods are in the <code>READY</code> state, Drycc Workflow is up and running!</p> +<p>For more installation parameters, please check the <a href="https://github.com/drycc/workflow/blob/main/charts/workflow/values.yaml">values.yaml</a> file of workflow.</p> +<p>After installing Workflow, <a href="/docs/quickstart/deploy-an-app/">register a user and deploy an application</a>.</p> +<h2 id="configure-dns">Configure DNS<a class="td-heading-self-link" href="#configure-dns" aria-label="Heading self-link"></a></h2> +<p>User must to set up a hostname, and assumes the <code>drycc-builder.$host</code> convention.</p> +<p>We need to point the <code>drycc-builder.$host</code> record to the public IP address of your builder. You can get the public IP using the following command. A wildcard entry is necessary here as apps will use the same rule after they are deployed.</p> +<pre tabindex="0"><code>$ kubectl get svc drycc-builder --namespace drycc +NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE +drycc-builder 10.0.25.3 138.91.243.152 2222:31625/TCP 33m +</code></pre><p>If we were using <code>drycc.cc</code> as a hostname, we would need to create the following A DNS records.</p> +<table> +<thead> +<tr> +<th>Name</th> +<th style="text-align:center">Type</th> +<th style="text-align:right">Value</th> +</tr> +</thead> +<tbody> +<tr> +<td>drycc-builder.drycc.cc</td> +<td style="text-align:center">A</td> +<td style="text-align:right">138.91.243.152</td> +</tr> +</tbody> +</table> +<p>Once all of the pods are in the <code>READY</code> state, and <code>drycc-builder.$host</code> resolves to the external IP found above, Workflow is up and running!</p> +<p>After installing Workflow, <a href="/docs/quickstart/deploy-an-app/">register a user and deploy an application</a>.</p> +<p>If your k8s does not provide public network loadblance, you need to install TCP proxy services such as haproxy on machines that can +access both internal and external networks, and then expose <code>80</code> and <code>443</code>.</p> + + + + + + Docs: Drycc Workflow Roadmap + /docs/roadmap/roadmap/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/roadmap/roadmap/ + + + + <h1 id="drycc-workflow-roadmap">Drycc Workflow Roadmap<a class="td-heading-self-link" href="#drycc-workflow-roadmap" aria-label="Heading self-link"></a></h1> +<p>The Drycc Workflow Roadmap is a community document created as part of the open +<a href="/docs/roadmap/planning-process/">Planning Process</a>. Each roadmap item describes a high-level capability or +grouping of features that are deemed important to the future of Drycc.</p> +<p>Given the project&rsquo;s rapid <a href="/docs/roadmap/releases/">Release Schedule</a>, roadmap +items are designed to provide a sense of direction over many releases.</p> +<h2 id="interactive-drycc-run-binbash">Interactive <code>drycc run /bin/bash</code><a class="td-heading-self-link" href="#interactive-drycc-run-binbash" aria-label="Heading self-link"></a></h2> +<p>Provide the ability for developers to launch an interactive terminal session in +their application environment.</p> +<p>Related issues:</p> +<ul> +<li><a href="https://github.com/drycc/workflow-cli/issues/28">https://github.com/drycc/workflow-cli/issues/28</a></li> +<li><a href="https://github.com/drycc/drycc/issues/117">https://github.com/drycc/drycc/issues/117</a></li> +</ul> +<h2 id="log-streaming">Log Streaming<a class="td-heading-self-link" href="#log-streaming" aria-label="Heading self-link"></a></h2> +<p>Stream application logs via <code>drycc logs -f</code> <a href="https://github.com/drycc/drycc/issues/465">https://github.com/drycc/drycc/issues/465</a></p> +<h2 id="teams-and-permissions">Teams and Permissions<a class="td-heading-self-link" href="#teams-and-permissions" aria-label="Heading self-link"></a></h2> +<p>Teams and Permissions represents a more flexible permissions model to allow +more nuanced control to applications, capabilities and resources on the +platform. There have been a number of proposals in this area which need to be +reconciled for Drycc Workflow before we begin implementation.</p> +<p>Related issues:</p> +<ul> +<li>Deploy Keys: <a href="https://github.com/drycc/drycc/issues/3875">https://github.com/drycc/drycc/issues/3875</a></li> +<li>Teams: <a href="https://github.com/drycc/drycc/issues/4173">https://github.com/drycc/drycc/issues/4173</a></li> +<li>Fine grained permissions: <a href="https://github.com/drycc/drycc/issues/4150">https://github.com/drycc/drycc/issues/4150</a></li> +<li>Admins create apps only: <a href="https://github.com/drycc/drycc/issues/4052">https://github.com/drycc/drycc/issues/4052</a></li> +<li>Admin Certificate Permissions: <a href="https://github.com/drycc/drycc/issues/4576#issuecomment-170987223">https://github.com/drycc/drycc/issues/4576#issuecomment-170987223</a></li> +</ul> +<h2 id="monitoring">Monitoring<a class="td-heading-self-link" href="#monitoring" aria-label="Heading self-link"></a></h2> +<ul> +<li><input disabled="" type="checkbox"> Define and deliver alerts with Kapacitor: <a href="https://github.com/drycc/monitor/issues/44">https://github.com/drycc/monitor/issues/44</a></li> +</ul> +<h2 id="workflow-addonsservices">Workflow Addons/Services<a class="td-heading-self-link" href="#workflow-addonsservices" aria-label="Heading self-link"></a></h2> +<p>Developers should be able to quickly and easily provision application +dependencies using a services or addon abstraction. +<a href="https://github.com/drycc/drycc/issues/231">https://github.com/drycc/drycc/issues/231</a></p> +<h2 id="inboundoutbound-webhooks">Inbound/Outbound Webhooks<a class="td-heading-self-link" href="#inboundoutbound-webhooks" aria-label="Heading self-link"></a></h2> +<p>Drycc Workflow should be able to send and receive webhooks from external +systems. Facilitating integration with third party services like GitHub, +Gitlab, Slack, Hipchat.</p> +<ul> +<li><input checked="" disabled="" type="checkbox"> Send webhook on platform events: <a href="https://github.com/drycc/drycc/issues/1486">https://github.com/drycc/drycc/issues/1486</a> (Workflow v2.10)</li> +</ul> + + + + + + Docs: Troubleshooting using Kubectl + /docs/troubleshooting/kubectl/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/troubleshooting/kubectl/ + + + + <p>This document describes how one can use <code>kubectl</code> to debug any issues with the cluster.</p> +<h2 id="diving-into-the-components">Diving into the Components<a class="td-heading-self-link" href="#diving-into-the-components" aria-label="Heading self-link"></a></h2> +<p>Using <code>kubectl</code>, one can inspect the cluster&rsquo;s current state. When Workflow is installed +with <code>helm</code>, Workflow is installed into the <code>drycc</code> namespace. To inspect if Workflow is +running, run:</p> +<pre><code>$ kubectl --namespace=drycc get pods +NAME READY STATUS RESTARTS AGE +drycc-builder-gqum7 0/1 ContainerCreating 0 4s +drycc-controller-h6lk6 0/1 ContainerCreating 0 4s +drycc-controller-celery-cmxxn 0/3 ContainerCreating 0 4s +drycc-database-56v39 0/1 ContainerCreating 0 4s +drycc-logger-fluentbit-xihr1 0/1 Pending 0 2s +drycc-logger-grupg 0/1 ContainerCreating 0 3s +drycc-storage-c2exb 0/1 Pending 0 3s +drycc-monitor-grafana-9ccur 0/1 Pending 0 3s +drycc-monitor-telegraf-dc3y3 0/1 Pending 0 2s +drycc-registry-5bor6 0/1 Pending 0 3s +drycc-rabbitmq-0 0/1 ContainerCreating 0 3s +</code></pre> +<p>!!! tip +To save precious keystrokes, alias <code>kubectl --namespace=drycc</code> to <code>kd</code> so it is easier to type +in the future.</p> +<p>To fetch the logs of a specific component, use <code>kubectl logs</code>:</p> +<pre><code>$ kubectl --namespace=drycc logs drycc-controller-h6lk6 +system information: +Django Version: 1.9.6 +Python 3.5.1 +addgroup: gid '0' in use +Django checks: +System check identified no issues (2 silenced). +[...] +</code></pre> +<p>To dive into a running container to inspect its environment, use <code>kubectl exec</code>:</p> +<pre><code>$ kubectl --namespace=drycc exec -it drycc-database-56v39 gosu postgres psql +psql (13.4 (Debian 13.4-1.pgdg100+1)) +Type &quot;help&quot; for help. + +postgres=# \l + List of databases + Name | Owner | Encoding | Collate | Ctype | Access privileges +-------------------+----------+----------+------------+------------+----------------------- + drycc_controller | postgres | UTF8 | en_US.utf8 | en_US.utf8 | + drycc_passport | postgres | UTF8 | en_US.utf8 | en_US.utf8 | + postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 | + template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres + + | | | | | postgres=CTc/postgres + template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres + + | | | | | postgres=CTc/postgres +(4 rows) +postgres=# \connect drycc_controller +You are now connected to database &quot;drycc_controller&quot; as user &quot;postgres&quot;. +drycc_controller=# \dt + List of relations + Schema | Name | Type | Owner +--------+--------------------------------+-------+------------------- + public | api_app | table | drycc_controller + public | api_build | table | drycc_controller + public | api_certificate | table | drycc_controller + public | api_config | table | drycc_controller + public | api_domain | table | drycc_controller + public | api_key | table | drycc_controller + public | api_push | table | drycc_controller + public | api_release | table | drycc_controller + public | auth_group | table | drycc_controller + --More-- + drycc_controller=# SELECT COUNT(*) from api_app; + count +------- + 0 +(1 row) +</code></pre> + + + + + + Docs: Users and Registration + /docs/users/registration/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/users/registration/ + + + + <p>Workflow use the passport component to create and authorize users, it can config options for LDAP authentication or browse passport web site to register users.</p> +<h2 id="login-to-workflow">Login to Workflow<a class="td-heading-self-link" href="#login-to-workflow" aria-label="Heading self-link"></a></h2> +<p>If you already have an account, use <code>drycc login</code> to authenticate against the Drycc Workflow API.</p> +<pre><code>$ drycc login http://drycc.example.com +Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71 +Waiting for login... .o.Logged in as drycc +Configuration file written to /root/.drycc/client.json +</code></pre> +<p>Or you can login with username and password +$ drycc login <a href="http://drycc.example.com">http://drycc.example.com</a> &ndash;username=demo &ndash;password=demo +Configuration file written to /root/.drycc/client.json</p> +<h2 id="logout-from-workflow">Logout from Workflow<a class="td-heading-self-link" href="#logout-from-workflow" aria-label="Heading self-link"></a></h2> +<p>Logout of an existing controller session using <code>drycc logout</code>.</p> +<pre><code>$ drycc logout +Logged out as drycc +</code></pre> +<h2 id="verify-your-session">Verify Your Session<a class="td-heading-self-link" href="#verify-your-session" aria-label="Heading self-link"></a></h2> +<p>You can verify your client configuration by running <code>drycc whoami</code>.</p> +<pre><code>$ drycc whoami +You are drycc at http://drycc.example.com +</code></pre> +<p>!!! note +Session and client configuration is stored in the <code>~/.drycc/client.json</code> file.</p> + + + + + + Docs: Components + /docs/understanding-workflow/components/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/understanding-workflow/components/ + + + + <p>All Workflow components are deployed as services (and associated controllers) in your Kubernetes cluster. +If you are interested we have a more detailed exploration of the <a href="/docs/understanding-workflow/architecture/">Workflow architecture</a>.</p> +<p>All of the componentry for Workflow is built with composability in mind. If you +need to customize one of the components for your specific deployment or need +the functionality in your own project we invite you to give it a shot!</p> +<h2 id="controller">Controller<a class="td-heading-self-link" href="#controller" aria-label="Heading self-link"></a></h2> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/controller">drycc/controller</a></p> +<p>The controller component is an HTTP API server which serves as the endpoint for +the <code>drycc</code> CLI. The controller provides all of the platform functionality as +well as interfacing with your Kubernetes cluster. The controller persists all +of its data to the database component.</p> +<h2 id="passport">Passport<a class="td-heading-self-link" href="#passport" aria-label="Heading self-link"></a></h2> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/passport">drycc/passport</a></p> +<p>The passport component exposes a web API and provide OAuth2 authentication.</p> +<h2 id="database">Database<a class="td-heading-self-link" href="#database" aria-label="Heading self-link"></a></h2> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/postgres">drycc/postgres</a></p> +<p>The database component is a managed instance of <a href="http://www.postgresql.org/">PostgreSQL</a> which holds a +majority of the platforms state. Backups and WAL files are pushed to object +storage via <a href="https://github.com/wal-e/wal-e">WAL-E</a>. When the database is restarted, backups are fetched and +replayed from object storage so no data is lost.</p> +<h2 id="builder">Builder<a class="td-heading-self-link" href="#builder" aria-label="Heading self-link"></a></h2> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/builder">drycc/builder</a></p> +<p>The builder component is responsible for accepting code pushes via <a href="http://git-scm.com/">Git</a> and +managing the build process of your <a href="../reference-guide/terms.md#application">Application</a>. The builder process is:</p> +<ol> +<li>Receives incoming <code>git push</code> requests over SSH</li> +<li>Authenticates the user via SSH key fingerprint</li> +<li>Authorizes the user&rsquo;s access to push code to the Application</li> +<li>Starts the Application Build phase (see below)</li> +<li>Triggers a new <a href="../reference-guide/terms.md#release">Release</a> via the Controller</li> +</ol> +<p>Builder currently supports both buildpack and Dockerfile based builds.</p> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/imagebuilder">drycc/imagebuilder</a></p> +<p>For Buildpack-based deploys, the builder component will launch a one-shot Job +in the <code>drycc</code> namespace. This job runs <code>imagebuilder</code> component which handles +default and custom buildpacks (specified by <code>.packbuilder</code>). The completed image +is pushed to the managed Container registry on cluster. For more information +about buildpacks see <a href="/docs/applications/using-buildpacks/">using buildpacks</a>.</p> +<p>Unlike buildpack-based, For Applications which contain a <code>Dockerfile</code> in the root +of the repository, it generates a Container image (using the underlying Container engine). +For more information see <a href="/docs/applications/using-dockerfiles/">using Dockerfiles</a>.</p> +<h2 id="object-storage">Object Storage<a class="td-heading-self-link" href="#object-storage" aria-label="Heading self-link"></a></h2> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/storage">drycc/storage</a></p> +<p>All of the Workflow components that need to persist data will ship them to the +object storage that was configured for the cluster.For example, database ships +its WAL files, registry stores Container images, and slugbuilder stores slugs.</p> +<p>Workflow supports either on or off-cluster storage. For production deployments +we highly recommend that you configure <a href="/docs/installing-workflow/configuring-object-storage/">off-cluster object storage</a>.</p> +<p>To facilitate experimentation, development and test environments, the default charts for +Workflow include on-cluster storage via <a href="https://github.com/drycc/storage">storage</a>.</p> +<p>If you also feel comfortable using Kubernetes persistent volumes you may +configure storage to use persistent storage available in your environment.</p> +<h2 id="registry">Registry<a class="td-heading-self-link" href="#registry" aria-label="Heading self-link"></a></h2> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/registry">drycc/registry</a></p> +<p>The registry component is a managed container registry which holds application +images generated from the builder component. Registry persists the Container image +images to either local storage (in development mode) or to object storage +configured for the cluster.</p> +<h2 id="logger-fluentbit-logger">Logger: fluentbit, logger<a class="td-heading-self-link" href="#logger-fluentbit-logger" aria-label="Heading self-link"></a></h2> +<p>The logging subsystem consists of two components. Fluentbit handles log shipping +and logger maintains a ring-buffer of application logs.</p> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/fluentbit">drycc/fluentbit</a></p> +<p>Fluentbit is deployed to your Kubernetes cluster via Daemon Sets. Fluentbit +subscribes to all container logs, decorates the output with Kubernetes metadata +and can be configured to drain logs to multiple destinations. By default, +Fluentbit ships logs to the logger component, which powers <code>drycc logs</code>.</p> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/logger">drycc/logger</a></p> +<p>The <code>logger</code> component receives log streams from <code>fluentbit</code>, collating by +Application name. Logger does not persist logs to disk, instead maintaining an +in-memory ring buffer. For more information on logger see the <a href="https://github.com/drycc/logger">project +documentation</a>.</p> +<h2 id="monitor">Monitor<a class="td-heading-self-link" href="#monitor" aria-label="Heading self-link"></a></h2> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/monitor">drycc/monitor</a></p> +<p>The monitoring subsystem consists of two components: Telegraf and Grafana.</p> +<p>Telegraf is the is the metrics collection agent that runs using the daemon set API. It runs on +every worker node in the cluster, fetches information about the pods currently running and ships it +to Prometheus.</p> +<p>Grafana is a standalone graphing application. It natively supports Prometheus as a datasource and +provides a robust engine for creating dashboards on top of timeseries data. Workflow provides a few +dashboards out of the box for monitoring Drycc Workflow and Kubernetes. The dashboards can be used +as a starting point for creating more custom dashboards to suit a user&rsquo;s needs.</p> +<h2 id="prometheus">Prometheus<a class="td-heading-self-link" href="#prometheus" aria-label="Heading self-link"></a></h2> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/prometheus">drycc/prometheus</a></p> +<p>Prometheus is a system monitoring and alerting system. It was opensourced by SoundCloud in 2012 and is +the second project both to join and to graduate within Cloud Native Computing Foundation after Kubernetes. +Prometheus stores all metrics data as time series, i.e metrics information is stored along with the +timestamp at which it was recorded, optional key-value pairs called as labels can also be stored along +with metrics.</p> +<h2 id="rabbitmq">Rabbitmq<a class="td-heading-self-link" href="#rabbitmq" aria-label="Heading self-link"></a></h2> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/rabbitmq">drycc/rabbitmq</a></p> +<p>RabbitMQ is the most widely deployed open source message broker. +Controller use celery with rabbitMQ to execute the asynchronous task.</p> +<h2 id="helmbroker">HelmBroker<a class="td-heading-self-link" href="#helmbroker" aria-label="Heading self-link"></a></h2> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/helmbroker">drycc/rabbitmq</a></p> +<p>Helm Broker is a Service Broker that exposes Helm charts as Service Classes in Service Catalog. +To do so, Helm Broker uses the concept of addons. An addon is an abstraction layer over a Helm chart +which provides all information required to convert the chart into a Service Class.</p> +<h2 id="prometheus-1">Prometheus<a class="td-heading-self-link" href="#prometheus-1" aria-label="Heading self-link"></a></h2> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/prometheus">drycc/rabbitmq</a></p> +<p>Prometheus is an open-source systemsmonitoring and alerting toolkit originally built atSoundCloud.</p> +<h2 id="see-also">See Also<a class="td-heading-self-link" href="#see-also" aria-label="Heading self-link"></a></h2> +<ul> +<li><a href="/docs/understanding-workflow/concepts/">Workflow Concepts</a></li> +<li><a href="/docs/understanding-workflow/architecture/">Workflow Architecture</a></li> +</ul> + + + + + + Docs: Controller API v2.0 + /docs/reference-guide/controller-api-v2-0/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/reference-guide/controller-api-v2-0/ + + + + <h2 id="whats-new">What&rsquo;s New<a class="td-heading-self-link" href="#whats-new" aria-label="Heading self-link"></a></h2> +<p><strong>New!</strong> format of <code>POST /v2/apps/&lt;app id&gt;/run</code> has changed.</p> +<h2 id="authentication">Authentication<a class="td-heading-self-link" href="#authentication" aria-label="Heading self-link"></a></h2> +<h3 id="register-a-new-user">Register a New User<a class="td-heading-self-link" href="#register-a-new-user" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/register/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json + +{ + &#34;username&#34;: &#34;test&#34;, + &#34;password&#34;: &#34;opensesame&#34;, + &#34;email&#34;: &#34;test@example.com&#34; +} +</code></pre><p>Optional Parameters:</p> +<pre tabindex="0"><code>{ + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;id&#34;: 1, + &#34;last_login&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;is_superuser&#34;: true, + &#34;username&#34;: &#34;test&#34;, + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34;, + &#34;email&#34;: &#34;test@example.com&#34;, + &#34;is_staff&#34;: true, + &#34;is_active&#34;: true, + &#34;date_joined&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;groups&#34;: [], + &#34;user_permissions&#34;: [] +} +</code></pre><h3 id="log-in">Log in<a class="td-heading-self-link" href="#log-in" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/login/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json + +{&#34;username&#34;: &#34;test&#34;, &#34;password&#34;: &#34;opensesame&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{&#34;token&#34;: &#34;abc123&#34;} +</code></pre><h3 id="cancel-account">Cancel Account<a class="td-heading-self-link" href="#cancel-account" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/auth/cancel/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="regenerate-token">Regenerate Token<a class="td-heading-self-link" href="#regenerate-token" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command could require administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/tokens/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Optional Parameters:</p> +<pre tabindex="0"><code>{ + &#34;username&#34; : &#34;test&#34; + &#34;all&#34; : &#34;true&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{&#34;token&#34;: &#34;abc123&#34;} +</code></pre><h3 id="change-password">Change Password<a class="td-heading-self-link" href="#change-password" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/passwd/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{ + &#34;password&#34;: &#34;foo&#34;, + &#34;new_password&#34;: &#34;bar&#34; +} +</code></pre><p>Optional parameters:</p> +<pre tabindex="0"><code>{&#34;username&#34;: &#34;testuser&#34;} +</code></pre><blockquote> +<p><strong>note</strong></p> +<p>Using the <code>username</code> parameter requires administrative privileges and makes the <code>password</code> parameter optional.</p> +</blockquote> +<p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h2 id="applications">Applications<a class="td-heading-self-link" href="#applications" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-applications">List all Applications<a class="td-heading-self-link" href="#list-all-applications" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;structure&#34;: {}, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;url&#34;: &#34;example-go.example.com&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; + } + ] +} +</code></pre><h3 id="create-an-application">Create an Application<a class="td-heading-self-link" href="#create-an-application" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 +</code></pre><p>Optional parameters:</p> +<pre tabindex="0"><code>{&#34;id&#34;: &#34;example-go&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;structure&#34;: {}, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;url&#34;: &#34;example-go.example.com&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="destroy-an-application">Destroy an Application<a class="td-heading-self-link" href="#destroy-an-application" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/apps/example-go/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="list-application-details">List Application Details<a class="td-heading-self-link" href="#list-application-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;structure&#34;: {}, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;url&#34;: &#34;example-go.example.com&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="update-application-details">Update Application Details<a class="td-heading-self-link" href="#update-application-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Optional parameters:</p> +<pre tabindex="0"><code>{ + &#34;owner&#34;: &#34;test&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 1.8.0 +Content-Type: application/json +</code></pre><h3 id="retrieve-application-logs">Retrieve Application Logs<a class="td-heading-self-link" href="#retrieve-application-logs" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/logs/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Optional URL Query Parameters:</p> +<pre tabindex="0"><code>?log_lines= +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: text/plain + +&#34;16:51:14 drycc[api]: test created initial release\n&#34; +</code></pre><h3 id="run-one-off-commands">Run one-off Commands<a class="td-heading-self-link" href="#run-one-off-commands" aria-label="Heading self-link"></a></h3> +<pre tabindex="0"><code>POST /v2/apps/example-go/run/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;command&#34;: &#34;echo hi&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{&#34;exit_code&#34;: 0, &#34;output&#34;: &#34;hi\n&#34;} +</code></pre><h2 id="certificates">Certificates<a class="td-heading-self-link" href="#certificates" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-certificates">List all Certificates<a class="td-heading-self-link" href="#list-all-certificates" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/certs HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;id&#34;: 22, + &#34;owner&#34;: &#34;test&#34;, + &#34;san&#34;: [], + &#34;domains&#34;: [], + &#34;created&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;updated&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;name&#34;: &#34;foo&#34;, + &#34;common_name&#34;: &#34;bar.com&#34;, + &#34;fingerprint&#34;: &#34;7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0&#34;, + &#34;expires&#34;: &#34;2017-01-14T23:57:57Z&#34;, + &#34;starts&#34;: &#34;2016-01-15T23:57:57Z&#34;, + &#34;issuer&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34;, + &#34;subject&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34; + } + ] +} +</code></pre><h3 id="get-certificate-details">Get Certificate Details<a class="td-heading-self-link" href="#get-certificate-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/certs/foo HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;id&#34;: 22, + &#34;owner&#34;: &#34;test&#34;, + &#34;san&#34;: [], + &#34;domains&#34;: [], + &#34;created&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;updated&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;name&#34;: &#34;foo&#34;, + &#34;common_name&#34;: &#34;bar.com&#34;, + &#34;fingerprint&#34;: &#34;7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0&#34;, + &#34;expires&#34;: &#34;2017-01-14T23:57:57Z&#34;, + &#34;starts&#34;: &#34;2016-01-15T23:57:57Z&#34;, + &#34;issuer&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34;, + &#34;subject&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34; +} +</code></pre><h3 id="create-certificate">Create Certificate<a class="td-heading-self-link" href="#create-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/certs/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{ + &#34;name&#34;: &#34;foo&#34; + &#34;certificate&#34;: &#34;-----BEGIN CERTIFICATE-----&#34;, + &#34;key&#34;: &#34;-----BEGIN RSA PRIVATE KEY-----&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;id&#34;: 22, + &#34;owner&#34;: &#34;test&#34;, + &#34;san&#34;: [], + &#34;domains&#34;: [], + &#34;created&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;updated&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;name&#34;: &#34;foo&#34;, + &#34;common_name&#34;: &#34;bar.com&#34;, + &#34;fingerprint&#34;: &#34;7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0&#34;, + &#34;expires&#34;: &#34;2017-01-14T23:57:57Z&#34;, + &#34;starts&#34;: &#34;2016-01-15T23:57:57Z&#34;, + &#34;issuer&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34;, + &#34;subject&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34; +} +</code></pre><h3 id="destroy-a-certificate">Destroy a Certificate<a class="td-heading-self-link" href="#destroy-a-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/certs/foo HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="attach-a-domain-to-a-certificate">Attach a Domain to a Certificate<a class="td-heading-self-link" href="#attach-a-domain-to-a-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/certs/foo/domain/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{ + &#34;domain&#34;: &#34;test.com&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="remove-a-domain-from-a-certificate">Remove a Domain from a Certificate<a class="td-heading-self-link" href="#remove-a-domain-from-a-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/certs/foo/domain/test.com/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h2 id="pods">Pods<a class="td-heading-self-link" href="#pods" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-pods">List all Pods<a class="td-heading-self-link" href="#list-all-pods" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/pods/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;results&#34;: [ + { + &#34;name&#34;: &#34;go-v2-web-e7dej&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2014-01-01T00:00:00Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } + ] +} +</code></pre><h3 id="list-all-pods-by-type">List all Pods by Type<a class="td-heading-self-link" href="#list-all-pods-by-type" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/pods/web/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;results&#34;: [ + { + &#34;name&#34;: &#34;go-v2-web-e7dej&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2014-01-01T00:00:00Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } + ] +} +</code></pre><h3 id="restart-all-pods">Restart All Pods<a class="td-heading-self-link" href="#restart-all-pods" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/pods/restart/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +[ + { + &#34;name&#34;: &#34;go-v2-web-atots&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2016-04-11T21:07:54Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } +] +</code></pre><h3 id="restart-pods-by-type">Restart Pods by Type<a class="td-heading-self-link" href="#restart-pods-by-type" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/pods/web/restart/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +[ + { + &#34;name&#34;: &#34;go-v2-web-atots&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2016-04-11T21:07:54Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } +] +</code></pre><h3 id="restart-pods-by-type-and-name">Restart Pods by Type and Name<a class="td-heading-self-link" href="#restart-pods-by-type-and-name" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/pods/go-v2-web-atots/restart/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +[ + { + &#34;name&#34;: &#34;go-v2-web-atots&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2016-04-11T21:07:54Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } +] +</code></pre><h3 id="scale-pods">Scale Pods<a class="td-heading-self-link" href="#scale-pods" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/scale/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;web&#34;: 3} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h2 id="configuration">Configuration<a class="td-heading-self-link" href="#configuration" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-configuration">List Application Configuration<a class="td-heading-self-link" href="#list-application-configuration" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/config/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;owner&#34;: &#34;test&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;values&#34;: { + &#34;PLATFORM&#34;: &#34;drycc&#34; + }, + &#34;memory&#34;: {}, + &#34;cpu&#34;: {}, + &#34;tags&#34;: {}, + &#34;healthcheck&#34;: {}, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="create-new-config">Create new Config<a class="td-heading-self-link" href="#create-new-config" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/config/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;values&#34;: {&#34;HELLO&#34;: &#34;world&#34;, &#34;PLATFORM&#34;: &#34;drycc&#34;}} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json +X-Drycc-Release: 3 + +{ + &#34;owner&#34;: &#34;test&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;values&#34;: { + &#34;DRYCC_APP&#34;: &#34;example-go&#34;, + &#34;DRYCC_RELEASE&#34;: &#34;v3&#34;, + &#34;HELLO&#34;: &#34;world&#34;, + &#34;PLATFORM&#34;: &#34;drycc&#34; + + }, + &#34;memory&#34;: {}, + &#34;cpu&#34;: {}, + &#34;tags&#34;: {}, + &#34;healthcheck&#34;: {}, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="unset-config-variable">Unset Config Variable<a class="td-heading-self-link" href="#unset-config-variable" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/config/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;values&#34;: {&#34;HELLO&#34;: null}} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json +X-Drycc-Release: 4 + +{ + &#34;owner&#34;: &#34;test&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;values&#34;: { + &#34;DRYCC_APP&#34;: &#34;example-go&#34;, + &#34;DRYCC_RELEASE&#34;: &#34;v4&#34;, + &#34;PLATFORM&#34;: &#34;drycc&#34; + }, + &#34;memory&#34;: {}, + &#34;cpu&#34;: {}, + &#34;tags&#34;: {}, + &#34;healthcheck&#34;: {}, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h2 id="domains">Domains<a class="td-heading-self-link" href="#domains" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-domains">List Application Domains<a class="td-heading-self-link" href="#list-application-domains" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/domains/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;domain&#34;: &#34;example.example.com&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34; + } + ] +} +</code></pre><h3 id="add-domain">Add Domain<a class="td-heading-self-link" href="#add-domain" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/domains/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{&#39;domain&#39;: &#39;example.example.com&#39;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;domain&#34;: &#34;example.example.com&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34; +} +</code></pre><h3 id="remove-domain">Remove Domain<a class="td-heading-self-link" href="#remove-domain" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/apps/example-go/domains/example.example.com HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h2 id="builds">Builds<a class="td-heading-self-link" href="#builds" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-builds">List Application Builds<a class="td-heading-self-link" href="#list-application-builds" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/build/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;dockerfile&#34;: &#34;FROM drycc/slugrunner RUN mkdir -p /app WORKDIR /app ENTRYPOINT [\&#34;/runner/init\&#34;] ADD slug.tgz /app ENV GIT_SHA 060da68f654e75fac06dbedd1995d5f8ad9084db&#34;, + &#34;image&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;procfile&#34;: { + &#34;web&#34;: &#34;example-go&#34; + }, + &#34;sha&#34;: &#34;060da68f&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="create-application-build">Create Application Build<a class="td-heading-self-link" href="#create-application-build" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/build/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;image&#34;: &#34;drycc/example-go:latest&#34;} +</code></pre><p>Optional Parameters:</p> +<pre tabindex="0"><code>{ + &#34;procfile&#34;: { + &#34;web&#34;: &#34;./cmd&#34; + } +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json +X-Drycc-Release: 4 + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;dockerfile&#34;: &#34;&#34;, + &#34;image&#34;: &#34;drycc/example-go:latest&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;procfile&#34;: {}, + &#34;sha&#34;: &#34;&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h2 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-releases">List Application Releases<a class="td-heading-self-link" href="#list-application-releases" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/releases/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 3, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: &#34;202d8e4b-600e-4425-a85c-ffc7ea607f61&#34;, + &#34;config&#34;: &#34;ed637ceb-5d32-44bd-9406-d326a777a513&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test changed nothing&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 3 + }, + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: &#34;202d8e4b-600e-4425-a85c-ffc7ea607f61&#34;, + &#34;config&#34;: &#34;95bd6dea-1685-4f78-a03d-fd7270b058d1&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test deployed 060da68&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 2 + }, + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: null, + &#34;config&#34;: &#34;95bd6dea-1685-4f78-a03d-fd7270b058d1&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test created initial release&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 1 + } + ] +} +</code></pre><h3 id="list-release-details">List Release Details<a class="td-heading-self-link" href="#list-release-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/releases/v2/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: null, + &#34;config&#34;: &#34;95bd6dea-1685-4f78-a03d-fd7270b058d1&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test created initial release&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 1 +} +</code></pre><h3 id="rollback-release">Rollback Release<a class="td-heading-self-link" href="#rollback-release" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/releases/rollback/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;version&#34;: 1} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{&#34;version&#34;: 5} +</code></pre><h2 id="keys">Keys<a class="td-heading-self-link" href="#keys" aria-label="Heading self-link"></a></h2> +<h3 id="list-keys">List Keys<a class="td-heading-self-link" href="#list-keys" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/keys/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;test@example.com&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;public&#34;: &#34;ssh-rsa &lt;...&gt;&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; + } + ] +} +</code></pre><h3 id="add-key-to-user">Add Key to User<a class="td-heading-self-link" href="#add-key-to-user" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/keys/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{ + &#34;id&#34;: &#34;example&#34;, + &#34;public&#34;: &#34;ssh-rsa &lt;...&gt;&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example&#34;, + &#34;owner&#34;: &#34;example&#34;, + &#34;public&#34;: &#34;ssh-rsa &lt;...&gt;&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="remove-key-from-user">Remove Key from User<a class="td-heading-self-link" href="#remove-key-from-user" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/keys/example HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h2 id="permissions">Permissions<a class="td-heading-self-link" href="#permissions" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-permissions">List Application Permissions<a class="td-heading-self-link" href="#list-application-permissions" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This does not include the app owner.</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/perms/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;users&#34;: [ + &#34;test&#34;, + &#34;foo&#34; + ] +} +</code></pre><h3 id="create-application-permission">Create Application Permission<a class="td-heading-self-link" href="#create-application-permission" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/perms/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{&#34;username&#34;: &#34;example&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="remove-application-permission">Remove Application Permission<a class="td-heading-self-link" href="#remove-application-permission" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/apps/example-go/perms/example HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="list-administrators">List Administrators<a class="td-heading-self-link" href="#list-administrators" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/admin/perms/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 2, + &#34;next&#34;: null + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;username&#34;: &#34;test&#34;, + &#34;is_superuser&#34;: true + }, + { + &#34;username&#34;: &#34;foo&#34;, + &#34;is_superuser&#34;: true + } + ] +} +</code></pre><h3 id="grant-user-administrative-privileges">Grant User Administrative Privileges<a class="td-heading-self-link" href="#grant-user-administrative-privileges" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command requires administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/admin/perms HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{&#34;username&#34;: &#34;example&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="remove-users-administrative-privileges">Remove User&rsquo;s Administrative Privileges<a class="td-heading-self-link" href="#remove-users-administrative-privileges" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command requires administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/admin/perms/example HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h2 id="users">Users<a class="td-heading-self-link" href="#users" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-users">List all users<a class="td-heading-self-link" href="#list-all-users" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command requires administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/users HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;id&#34;: 1, + &#34;last_login&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;is_superuser&#34;: true, + &#34;username&#34;: &#34;test&#34;, + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34;, + &#34;email&#34;: &#34;test@example.com&#34;, + &#34;is_staff&#34;: true, + &#34;is_active&#34;: true, + &#34;date_joined&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;groups&#34;: [], + &#34;user_permissions&#34;: [] + } + ] +} +</code></pre> + + + + + Docs: Deploy Hooks + /docs/managing-workflow/deploy-hooks/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/managing-workflow/deploy-hooks/ + + + + <p>It’s useful to help keep the development team informed about deploys, while +it can also be used to integrate different systems together.</p> +<p>After one or more hooks are setup, hook output and errors appear in your application’s logs:</p> +<pre tabindex="0"><code>$ drycc logs +... +2011-03-15T15:07:29-07:00 drycc[api]: Deploy hook sent to http://drycc.rocks +</code></pre><p>Deploy hooks are a generic HTTP hook. An administrator can create and configure multiple deploy +hooks by <a href="/docs/managing-workflow/tuning-component-settings/#customizing-the-controller">tuning the controller settings</a> via the Helm chart.</p> +<h2 id="http-post-hook">HTTP POST Hook<a class="td-heading-self-link" href="#http-post-hook" aria-label="Heading self-link"></a></h2> +<p>The HTTP deploy hook performs an HTTP POST to a URL. The parameters included in the request are the +same as the variables available in the hook message: <code>app</code>, <code>release</code>, <code>release_summary</code>, <code>sha</code> and +<code>user</code>. See below for their descriptions:</p> +<pre tabindex="0"><code>app=secure-woodland&amp;release=v4&amp;release_summary=gabrtv%20deployed%35b3726&amp;sha=35b3726&amp;user=gabrtv +</code></pre><p>Optionally, if a deploy hook secret key is added to the controller through +<a href="/docs/managing-workflow/tuning-component-settings/#customizing-the-controller">tuning the controller settings</a>, a new <code>Authorization</code> header will be +present in the POST request. The value of this header is computed as the <a href="https://en.wikipedia.org/wiki/Hash-based_message_authentication_code">HMAC</a> hex digest of the +request URL, using the secret as the key.</p> +<p>In order to authenticate that this request came from Workflow, use the secret key, the full URL and +the HMAC-SHA1 hashing algorithm to compute the signature. In Python, that would look something like +this:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#204a87;font-weight:bold">import</span> <span style="color:#000">hashlib</span> +</span></span><span style="display:flex;"><span><span style="color:#204a87;font-weight:bold">import</span> <span style="color:#000">hmac</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#000">hmac</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#000">new</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;my_secret_key&#34;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#4e9a06">&#34;http://drycc.rocks?app=secure-woodland&amp;release=v4&amp;release_summary=gabrtv</span><span style="color:#4e9a06">%20d</span><span style="color:#4e9a06">eployed%35b3726&amp;sha=35b3726&amp;user=gabrtv&#34;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">digestmod</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#000">hashlib</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#000">sha1</span><span style="color:#000;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#000">hexdigest</span><span style="color:#000;font-weight:bold">()</span> +</span></span></code></pre></div><p>If the value of the computed HMAC hex digest and the value in the <code>Authorization</code> header are +identical, then the request came from Workflow.</p> +<p>!!! important +When computing the signature, ensure that the URL parameters are in alphabetic order. This is +critical when computing the cryptographic signature as most web applications don&rsquo;t care about +the order of the HTTP parameters, but the cryptographic signature will not be the same.</p> + + + + + + Docs: Using Dockerfiles + /docs/applications/using-dockerfiles/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/applications/using-dockerfiles/ + + + + <p>Drycc supports deploying applications via Dockerfiles. A <a href="https://docs.docker.com/reference/builder/">Dockerfile</a> automates the steps for crafting a [Container Image][]. +Dockerfiles are incredibly powerful but require some extra work to define your exact application runtime environment.</p> +<h2 id="add-ssh-key">Add SSH Key<a class="td-heading-self-link" href="#add-ssh-key" aria-label="Heading self-link"></a></h2> +<p>For <strong>Dockerfile</strong> based application deploys via <code>git push</code>, Drycc Workflow identifies users via SSH keys. SSH keys are pushed to the platform and must be unique to each user.</p> +<ul> +<li> +<p>See <a href="/docs/users/ssh-keys/#generate-an-ssh-key">this document</a> for instructions on how to generate an SSH key.</p> +</li> +<li> +<p>Run <code>drycc keys:add</code> to upload your SSH key to Drycc Workflow.</p> +</li> +</ul> +<pre tabindex="0"><code>$ drycc keys:add ~/.ssh/id_drycc.pub +Uploading id_drycc.pub to drycc... done +</code></pre><p>Read more about adding/removing SSH Keys <a href="/docs/users/ssh-keys/#adding-and-removing-ssh-keys">here</a>.</p> +<h2 id="prepare-an-application">Prepare an Application<a class="td-heading-self-link" href="#prepare-an-application" aria-label="Heading self-link"></a></h2> +<p>If you do not have an existing application, you can clone an example application that demonstrates the Dockerfile workflow.</p> +<pre><code>$ git clone https://github.com/drycc/helloworld.git +$ cd helloworld +</code></pre> +<h3 id="dockerfile-requirements">Dockerfile Requirements<a class="td-heading-self-link" href="#dockerfile-requirements" aria-label="Heading self-link"></a></h3> +<p>In order to deploy Dockerfile applications, they must conform to the following requirements:</p> +<ul> +<li>The Dockerfile must use the <code>EXPOSE</code> directive to expose exactly one port.</li> +<li>That port must be listening for an HTTP connection.</li> +<li>The Dockerfile must use the <code>CMD</code> directive to define the default process that will run within the container.</li> +<li>The Container image must contain <a href="https://www.gnu.org/software/bash/">bash</a> to run processes.</li> +</ul> +<p>!!! note +Note that if you are using a private registry of any kind (<code>gcr</code> or other) the application environment must include a <code>$PORT</code> config variable that matches the <code>EXPOSE</code>&rsquo;d port, example: <code>drycc config:set PORT=5000</code>. See <a href="/docs/installing-workflow/configuring-registry/#configuring-off-cluster-private-registry">Configuring Registry</a> for more info.</p> +<h2 id="create-an-application">Create an Application<a class="td-heading-self-link" href="#create-an-application" aria-label="Heading self-link"></a></h2> +<p>Use <code>drycc create</code> to create an application on the <a href="/docs/understanding-workflow/components/#controller">Controller</a>.</p> +<pre><code>$ drycc create +Creating application... done, created folksy-offshoot +Git remote drycc added +</code></pre> +<h2 id="push-to-deploy">Push to Deploy<a class="td-heading-self-link" href="#push-to-deploy" aria-label="Heading self-link"></a></h2> +<p>Use <code>git push drycc master</code> to deploy your application.</p> +<pre><code>$ git push drycc master +Counting objects: 13, done. +Delta compression using up to 8 threads. +Compressing objects: 100% (13/13), done. +Writing objects: 100% (13/13), 1.99 KiB | 0 bytes/s, done. +Total 13 (delta 2), reused 0 (delta 0) +-----&gt; Building Docker image +Uploading context 4.096 kB +Uploading context +Step 0 : FROM drycc/base:latest + ---&gt; 60024338bc63 +Step 1 : RUN wget -O /tmp/go1.2.1.linux-amd64.tar.gz -q https://go.googlecode.com/files/go1.2.1.linux-amd64.tar.gz + ---&gt; Using cache + ---&gt; cf9ef8c5caa7 +Step 2 : RUN tar -C /usr/local -xzf /tmp/go1.2.1.linux-amd64.tar.gz + ---&gt; Using cache + ---&gt; 515b1faf3bd8 +Step 3 : RUN mkdir -p /go + ---&gt; Using cache + ---&gt; ebf4927a00e9 +Step 4 : ENV GOPATH /go + ---&gt; Using cache + ---&gt; c6a276eded37 +Step 5 : ENV PATH /usr/local/go/bin:/go/bin:$PATH + ---&gt; Using cache + ---&gt; 2ba6f6c9f108 +Step 6 : ADD . /go/src/github.com/drycc/helloworld + ---&gt; 94ab7f4b977b +Removing intermediate container 171b7d9fdb34 +Step 7 : RUN cd /go/src/github.com/drycc/helloworld &amp;&amp; go install -v . + ---&gt; Running in 0c8fbb2d2812 +github.com/drycc/helloworld + ---&gt; 13b5af931393 +Removing intermediate container 0c8fbb2d2812 +Step 8 : ENV PORT 80 + ---&gt; Running in 9b07da36a272 + ---&gt; 2dce83167874 +Removing intermediate container 9b07da36a272 +Step 9 : CMD [&quot;/go/bin/helloworld&quot;] + ---&gt; Running in f7b215199940 + ---&gt; b1e55ce5195a +Removing intermediate container f7b215199940 +Step 10 : EXPOSE 80 + ---&gt; Running in 7eb8ec45dcb0 + ---&gt; ea1a8cc93ca3 +Removing intermediate container 7eb8ec45dcb0 +Successfully built ea1a8cc93ca3 +-----&gt; Pushing image to private registry + + Launching... done, v2 + +-----&gt; folksy-offshoot deployed to Drycc + http://folksy-offshoot.local3.dryccapp.com + + To learn more, use `drycc help` or visit https://www.drycc.cc + +To ssh://git@local3.dryccapp.com:2222/folksy-offshoot.git + * [new branch] master -&gt; master + +$ curl -s http://folksy-offshoot.local3.dryccapp.com +Welcome to Drycc! +See the documentation at http://docs.drycc.cc/ for more information. +</code></pre> +<p>Because a Dockerfile application is detected, the <code>web</code> process type is automatically scaled to 1 on first deploy.</p> +<p>Use <code>drycc scale web=3</code> to increase <code>web</code> processes to 3, for example. Scaling a +process type directly changes the number of <a href="../reference-guide/terms.md#container">containers</a> +running that process.</p> +<h2 id="container-build-arguments">Container Build Arguments<a class="td-heading-self-link" href="#container-build-arguments" aria-label="Heading self-link"></a></h2> +<p>As of Workflow v2.13.0, users can inject their application config into the Container image using +<a href="https://docs.docker.com/engine/reference/commandline/build/#set-build-time-variables---build-arg">Container build arguments</a>. To opt into this, users must add a new environment variable +to their application:</p> +<pre tabindex="0"><code>$ drycc config:set DRYCC_DOCKER_BUILD_ARGS_ENABLED=1 +</code></pre><p>Every environment variable set with <code>drycc config:set</code> will then be available for use inside the +user&rsquo;s Dockerfile. For example, if a user runs <code>drycc config:set POWERED_BY=Workflow</code>, +the user can utilize that build argument in their Dockerfile:</p> +<pre tabindex="0"><code>ARG POWERED_BY +RUN echo &#34;Powered by $POWERED_BY&#34; &gt; /etc/motd +</code></pre> + + + + + Docs: Development Environment + /docs/contribution-guidelines/development-environment/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/contribution-guidelines/development-environment/ + + + + <p>In this guide, we walk you through the process of setting up a development environment that is suitable for hacking on most Drycc components.</p> +<p>We try to make it simple to hack on Drycc components. However, there are necessarily several moving pieces and some setup required. We welcome any suggestions for automating or simplifying this process.</p> +<p>!!! note +The Drycc team is actively engaged in containerizing Go and Python based development environments tailored specifically for Drycc development in order to minimize the setup required. This work is ongoing. Refer to the <a href="https://github.com/drycc/router">drycc/router</a> project for a working example of a fully containerized development environment.</p> +<p>If you&rsquo;re just getting into the Drycc codebase, look for GitHub issues with the label <a href="https://github.com/issues?q=user%3Adrycc+label%3Aeasy-fix+is%3Aopen">easy-fix</a>. These are more straightforward or low-risk issues and are a great way to become more familiar with Drycc.</p> +<h2 id="prerequisites">Prerequisites<a class="td-heading-self-link" href="#prerequisites" aria-label="Heading self-link"></a></h2> +<p>In order to successfully compile and test Drycc binaries and build Container images of Drycc components, the following are required:</p> +<ul> +<li><a href="https://git-scm.com/">git</a></li> +<li>Go 1.5 or later, with support for compiling to <code>linux/amd64</code></li> +<li><a href="https://github.com/Masterminds/glide">glide</a></li> +<li><a href="https://github.com/golang/lint">golint</a></li> +<li><a href="https://github.com/koalaman/shellcheck">shellcheck</a></li> +<li><a href="https://podman.io/">Podman</a> (in a non-Linux environment, you will additionally want [Podman Machine][machine])</li> +</ul> +<p>For <a href="https://github.com/drycc/controller">drycc/controller</a>, in particular, you will also need:</p> +<ul> +<li>Python 2.7 or later (with <code>pip</code>)</li> +<li>virtualenv (<code>sudo pip install virtualenv</code>)</li> +</ul> +<p>In most cases, you should simply install according to the instructions. There are a few special cases, though. We cover these below.</p> +<h3 id="configuring-go">Configuring Go<a class="td-heading-self-link" href="#configuring-go" aria-label="Heading self-link"></a></h3> +<p>If your local workstation does not support the <code>linux/amd64</code> target environment, you will have to install Go from source with cross-compile support for that environment. This is because some of the components are built on your local machine and then injected into a container.</p> +<p>Homebrew users can just install with cross compiling support:</p> +<pre tabindex="0"><code>$ brew install go --with-cc-common +</code></pre><p>It is also straightforward to build Go from source:</p> +<pre tabindex="0"><code>$ sudo su +$ curl -sSL https://golang.org/dl/go1.5.src.tar.gz | tar -v -C /usr/local -xz +$ cd /usr/local/go/src +$ # compile Go for our default platform first, then add cross-compile support +$ ./make.bash --no-clean +$ GOOS=linux GOARCH=amd64 ./make.bash --no-clean +</code></pre><p>Once you can compile to <code>linux/amd64</code>, you should be able to compile Drycc components as normal.</p> +<h2 id="fork-the-repository">Fork the Repository<a class="td-heading-self-link" href="#fork-the-repository" aria-label="Heading self-link"></a></h2> +<p>Once the prerequisites have been met, we can begin to work with Drycc components.</p> +<p>Begin at Github by forking whichever Drycc project you would like to contribute to, then clone that fork locally. Since Drycc is predominantly written in Go, the best place to put it is under <code>$GOPATH/src/github.com/drycc/</code>.</p> +<pre tabindex="0"><code>$ mkdir -p $GOPATH/src/github.com/drycc +$ cd $GOPATH/src/github.com/drycc +$ git clone git@github.com:&lt;username&gt;/&lt;component&gt;.git +$ cd &lt;component&gt; +</code></pre><p>!!! note +By checking out the forked copy into the namespace <code>github.com/drycc/&lt;component&gt;</code>, we are tricking the Go toolchain into seeing our fork as the &ldquo;official&rdquo; source tree.</p> +<p>If you are going to be issuing pull requests to the upstream repository from which you forked, we suggest configuring Git such that you can easily rebase your code to the upstream repository&rsquo;s main branch. There are various strategies for doing this, but the <a href="https://help.github.com/articles/fork-a-repo/">most common</a> is to add an <code>upstream</code> remote:</p> +<pre tabindex="0"><code>$ git remote add upstream https://github.com/drycc/&lt;component&gt;.git +</code></pre><p>For the sake of simplicity, you may want to point an environment variable to your Drycc code - the directory containing one or more Drycc components:</p> +<pre tabindex="0"><code>$ export DRYCC=$GOPATH/src/github.com/drycc +</code></pre><p>Throughout the rest of this document, <code>$DRYCC</code> refers to that location.</p> +<h3 id="alternative-forking-with-a-pushurl">Alternative: Forking with a Pushurl<a class="td-heading-self-link" href="#alternative-forking-with-a-pushurl" aria-label="Heading self-link"></a></h3> +<p>A number of Drycc contributors prefer to pull directly from <code>drycc/&lt;component&gt;</code>, but push to <code>&lt;username&gt;/&lt;component&gt;</code>. If that workflow suits you better, you can set it up this way:</p> +<pre tabindex="0"><code>$ git clone git@github.com:drycc/&lt;component&gt;.git +$ cd drycc +$ git config remote.origin.pushurl git@github.com:&lt;username&gt;/&lt;component&gt;.git +</code></pre><p>In this setup, fetching and pulling code will work directly with the upstream repository, while pushing code will send changes to your fork. This makes it easy to stay up to date, but also make changes and then issue pull requests.</p> +<h2 id="make-your-changes">Make Your Changes<a class="td-heading-self-link" href="#make-your-changes" aria-label="Heading self-link"></a></h2> +<p>With your development environment set up and the code you wish to work on forked and cloned, you can begin making your changes.</p> +<h2 id="test-your-changes">Test Your Changes<a class="td-heading-self-link" href="#test-your-changes" aria-label="Heading self-link"></a></h2> +<p>Drycc components each include a comprehensive suite of automated tests, mostly written in Go. See <a href="/docs/contribution-guidelines/testing/">testing</a> for instructions on running the tests.</p> +<h2 id="deploying-your-changes">Deploying Your Changes<a class="td-heading-self-link" href="#deploying-your-changes" aria-label="Heading self-link"></a></h2> +<p>Although writing and executing tests are critical to ensuring code quality, most contributors will also want to deploy their changes to a live environment, whether to make use of those changes or to test them further. The remainder of this section documents the procedure for running officially released Drycc components in a development cluster and replacing any one of those with your customizations.</p> +<h3 id="running-a-kubernetes-cluster-for-development">Running a Kubernetes Cluster for Development<a class="td-heading-self-link" href="#running-a-kubernetes-cluster-for-development" aria-label="Heading self-link"></a></h3> +<p>To run a Kubernetes cluster locally or elsewhere to support your development activities, refer to Drycc installation instructions <a href="/docs/quickstart/">here</a>.</p> +<h3 id="using-a-development-registry">Using a Development Registry<a class="td-heading-self-link" href="#using-a-development-registry" aria-label="Heading self-link"></a></h3> +<p>To facilitate deploying Container images containing your changes to your Kubernetes cluster, you will need to make use of a Container registry. This is a location to where you can push your custom-built images and from where your Kubernetes cluster can retrieve those same images.</p> +<p>If your development cluster runs locally (in Minikube, for instance), the most efficient and economical means of achieving this is to run a Container registry locally <em>as</em> a Container container.</p> +<p>To facilitate this, most Drycc components provide a make target to create such a registry:</p> +<pre tabindex="0"><code>$ make dev-registry +</code></pre><p>In a Linux environment, to begin using the registry:</p> +<pre tabindex="0"><code>export DRYCC_REGISTRY=&lt;IP of the host machine&gt;:5000 +</code></pre><p>In non-Linux environments:</p> +<pre tabindex="0"><code>export DRYCC_REGISTRY=&lt;IP of the drycc Container Machine VM&gt;:5000 +</code></pre><p>If your development cluster runs on a cloud provider such as Google Container Engine, a local registry such as the one above will not be accessible to your Kubernetes nodes. In such cases, a public registry such as [DockerHub][dh] or <a href="https://quay.io/">quay.io</a> will suffice.</p> +<p>To use DockerHub for this purpose, for instance:</p> +<pre tabindex="0"><code>$ export DRYCC_REGISTRY=&#34;registry.drycc.cc&#34; +$ export IMAGE_PREFIX=&lt;your DockerHub username&gt; +</code></pre><p>To use quay.io:</p> +<pre tabindex="0"><code>$ export DRYCC_REGISTRY=quay.io +$ export IMAGE_PREFIX=&lt;your quay.io username&gt; +</code></pre><p>Note the importance of the trailing slash.</p> +<h3 id="dev--deployment-workflow">Dev / Deployment Workflow<a class="td-heading-self-link" href="#dev--deployment-workflow" aria-label="Heading self-link"></a></h3> +<p>With a functioning Kubernetes cluster and the officially released Drycc components installed onto it, deployment and further testing of any Drycc component you have made changes to is facilitated by replacing the officially released component with a custom built image that contains your changes. Most Drycc components include Makefiles with targets specifically intended to facilitate this workflow with minimal friction.</p> +<p>In the general case, this workflow looks like this:</p> +<ol> +<li>Update source code and commit your changes using <code>git</code></li> +<li>Use <code>make build</code> to build a new Container image</li> +<li>Use <code>make dev-release</code> to generate Kubernetes manifest(s)</li> +<li>Use <code>make deploy</code> to restart the component using the updated manifest</li> +</ol> +<p>This can be shortened to a one-liner using just the <code>deploy</code> target:</p> +<pre tabindex="0"><code>$ make deploy +</code></pre><h2 id="useful-commands">Useful Commands<a class="td-heading-self-link" href="#useful-commands" aria-label="Heading self-link"></a></h2> +<p>Once your customized Drycc component has been deployed, here are some helpful commands that will allow you to inspect your cluster and to troubleshoot, if necessary:</p> +<h3 id="see-all-drycc-pods">See All Drycc Pods<a class="td-heading-self-link" href="#see-all-drycc-pods" aria-label="Heading self-link"></a></h3> +<pre tabindex="0"><code>$ kubectl --namespace=drycc get pods +</code></pre><h3 id="describe-a-pod">Describe a Pod<a class="td-heading-self-link" href="#describe-a-pod" aria-label="Heading self-link"></a></h3> +<p>This is often useful for troubleshooting pods that are in pending or crashed states:</p> +<pre tabindex="0"><code>$ kubectl --namespace=drycc describe -f &lt;pod name&gt; +</code></pre><h3 id="tail-logs">Tail Logs<a class="td-heading-self-link" href="#tail-logs" aria-label="Heading self-link"></a></h3> +<pre tabindex="0"><code>$ kubectl --namespace=drycc logs -f &lt;pod name&gt; +</code></pre><h3 id="django-shell">Django Shell<a class="td-heading-self-link" href="#django-shell" aria-label="Heading self-link"></a></h3> +<p>Specific to <a href="https://github.com/drycc/controller">drycc/controller</a></p> +<pre tabindex="0"><code>$ kubectl --namespace=drycc exec -it &lt;pod name&gt; -- python manage.py shell +</code></pre><p>Have commands other Drycc contributors might find useful? Send us a PR!</p> +<h2 id="pull-requests">Pull Requests<a class="td-heading-self-link" href="#pull-requests" aria-label="Heading self-link"></a></h2> +<p>Satisfied with your changes? Share them!</p> +<p>Please read <a href="/docs/contribution-guidelines/submitting-a-pull-request/">Submitting a Pull Request</a>. It contains a checklist of +things you should do when proposing a change to any Drycc component.</p> + + + + + + Docs: Drycc Workflow Client CLI + /docs/quickstart/install-cli-tools/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/quickstart/install-cli-tools/ + + + + <h2 id="drycc-workflow-client-cli">Drycc Workflow Client CLI<a class="td-heading-self-link" href="#drycc-workflow-client-cli" aria-label="Heading self-link"></a></h2> +<p>The Drycc command-line interface (CLI), lets you interact with Drycc Workflow. +Use the CLI to create and configure and manage applications.</p> +<p>Install the <code>drycc</code> client for Linux or Mac OS X with:</p> +<pre tabindex="0"><code>$ curl -sfL https://www.drycc.cc/install-cli.sh | bash - +</code></pre><p>!!! important +Users in Chinese mainland can use the following methods to speed up installation:</p> +<pre><code>``` +$ curl -sfL https://www.drycc.cc/install-cli.sh | INSTALL_DRYCC_MIRROR=cn bash - +``` +</code></pre> +<p>Others please visit: <a href="https://github.com/drycc/workflow-cli/releases">https://github.com/drycc/workflow-cli/releases</a></p> +<p>The installer places the <code>drycc</code> binary in your current directory, but you +should move it somewhere in your $PATH:</p> +<pre tabindex="0"><code>$ sudo ln -fs $PWD/drycc /usr/local/bin/drycc +</code></pre><p><em>or</em>:</p> +<pre tabindex="0"><code>$ sudo mv $PWD/drycc /usr/local/bin/drycc +</code></pre><p>Check your work by running <code>drycc version</code>:</p> +<pre tabindex="0"><code>$ drycc version +v1.1.0 +</code></pre><p>Update workflow cli to latest release.</p> +<pre tabindex="0"><code>drycc update +</code></pre><p>!!! note +Note that version numbers may vary as new releases become available</p> + + + + + + Docs: Releases + /docs/roadmap/releases/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/roadmap/releases/ + + + + <p>Drycc uses a <a href="https://en.wikipedia.org/wiki/Continuous_delivery">continuous delivery</a> approach for creating releases. Every merged commit that passes +testing results in a deliverable that can be given a <a href="http://semver.org">semantic version</a> tag and shipped.</p> +<p>The master <code>git</code> branch of a project should always work. Only changes considered ready to be +released publicly are merged.</p> +<h2 id="components-release-as-needed">Components Release as Needed<a class="td-heading-self-link" href="#components-release-as-needed" aria-label="Heading self-link"></a></h2> +<p>Drycc components release new versions as often as needed. Fixing a high priority bug requires the +project maintainer to create a new patch release. Merging a backward-compatible feature implies +a minor release.</p> +<p>By releasing often, each component release becomes a safe and routine event. This makes it faster +and easier for users to obtain specific fixes. Continuous delivery also reduces the work +necessary to release a product such as Drycc Workflow, which integrates several components.</p> +<p>&ldquo;Components&rdquo; applies not just to Drycc Workflow projects, but also to development and release +tools, to Container base images, and to other Drycc projects that do <a href="http://semver.org">semantic version</a> releases.</p> +<p>See &ldquo;<a href="/docs/roadmap/releases/#how-to-release-a-component">How to Release a Component</a>&rdquo; for more detail.</p> +<h2 id="workflow-releases-each-month">Workflow Releases Each Month<a class="td-heading-self-link" href="#workflow-releases-each-month" aria-label="Heading self-link"></a></h2> +<p>Drycc Workflow has a regular, public release cadence. From v2.8.0 onward, new Workflow feature +releases arrive on the first Thursday of each month. Patch releases are created at any time, +as needed. GitHub milestones are used to communicate the content and timing of major and minor +releases, and longer-term planning is visible at <a href="/docs/roadmap/roadmap/">the Roadmap</a>.</p> +<p>Workflow release timing is not linked to specific features. If a feature is merged before the +release date, it is included in the next release.</p> +<p>See &ldquo;<a href="/docs/roadmap/releases/#how-to-release-workflow">How to Release Workflow</a>&rdquo; for more detail.</p> +<h2 id="semantic-versioning">Semantic Versioning<a class="td-heading-self-link" href="#semantic-versioning" aria-label="Heading self-link"></a></h2> +<p>Drycc releases comply with <a href="http://semver.org">semantic versioning</a>, with the &ldquo;public API&rdquo; broadly +defined as:</p> +<ul> +<li>REST, gRPC, or other API that is network-accessible</li> +<li>Library or framework API intended for public use</li> +<li>&ldquo;Pluggable&rdquo; socket-level protocols users can redirect</li> +<li>CLI commands and output formats</li> +</ul> +<p>In general, changes to anything a user might reasonably link to, customize, or integrate with +should be backward-compatible, or else require a major release. Drycc users can be confident that +upgrading to a patch or to a minor release will not break anything.</p> +<h2 id="how-to-release-a-component">How to Release a Component<a class="td-heading-self-link" href="#how-to-release-a-component" aria-label="Heading self-link"></a></h2> +<p>Most Drycc projects are &ldquo;components&rdquo; which produce a Container image or binary executable as a +deliverable. This section leads a maintainer through creating a component release.</p> +<h3 id="step-1-update-code-and-run-the-release-tool">Step 1: Update Code and Run the Release Tool<a class="td-heading-self-link" href="#step-1-update-code-and-run-the-release-tool" aria-label="Heading self-link"></a></h3> +<p>Major or minor releases should happen on the master branch. Patch releases +should check out the previous release tag and cherry-pick specific commits from master.</p> +<p><strong>Note:</strong> if a patch release, the release artifact will have to be manually promoted by triggering +the <a href="https://ci.drycc.info/job/component-promote">component-promote</a> job with the following values:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#000">COMPONENT_NAME</span><span style="color:#ce5c00;font-weight:bold">=</span>&lt;component name&gt; +</span></span><span style="display:flex;"><span><span style="color:#000">COMPONENT_SHA</span><span style="color:#ce5c00;font-weight:bold">=</span>&lt;patch commit sha&gt; +</span></span></code></pre></div><p>Make sure you have the <a href="https://github.com/drycc/dryccrel">dryccrel</a> release tool in your search <code>$PATH</code>.</p> +<p>Run <code>dryccrel release</code> once with a fake semver tag to proofread the changelog content. (If <code>HEAD</code> +of master is not what is intended for the release, add the <code>--sha</code> flag as described +in <code>dryccrel release --help</code>.)</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ dryccrel release controller v0.0.0 +</span></span><span style="display:flex;"><span>Doing a dry run of the component release... +</span></span><span style="display:flex;"><span>skipping commit 943a49267eeb28546819a266654806cfcbae0e38 +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span>Creating changelog <span style="color:#204a87;font-weight:bold">for</span> controller with tag v2.8.1 through commit 943a49267eeb28546819a266654806cfcbae0e38 +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">### v2.8.1 -&gt; v0.0.0</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">#### Fixes</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span>- <span style="color:#ce5c00;font-weight:bold">[</span><span style="color:#4e9a06">`</span>615b834<span style="color:#4e9a06">`</span><span style="color:#ce5c00;font-weight:bold">](</span>https://github.com/drycc/controller/commit/615b834f39cb68a854cc1f1e2f0f82d862ea2731<span style="color:#ce5c00;font-weight:bold">)</span> boot: Ensure <span style="color:#000">DRYCC_DEBUG</span><span style="color:#ce5c00;font-weight:bold">==</span><span style="color:#204a87">true</span> <span style="color:#204a87;font-weight:bold">for</span> debug output +</span></span></code></pre></div><p>Based on the changelog content, determine whether the component deserves a minor or patch +release. Run the command again with that semver tag and <code>--dry-run=false</code>. You will still be +asked for confirmation before the release is created:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ dryccrel release controller v2.8.2 --dry-run<span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#204a87">false</span> +</span></span><span style="display:flex;"><span>skipping commit 943a49267eeb28546819a266654806cfcbae0e38 +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span>Creating changelog <span style="color:#204a87;font-weight:bold">for</span> controller with tag v2.8.1 through commit 943a49267eeb28546819a266654806cfcbae0e38 +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">### v2.8.1 -&gt; v2.8.2</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">#### Fixes</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span>- <span style="color:#ce5c00;font-weight:bold">[</span><span style="color:#4e9a06">`</span>615b834<span style="color:#4e9a06">`</span><span style="color:#ce5c00;font-weight:bold">](</span>https://github.com/drycc/controller/commit/615b834f39cb68a854cc1f1e2f0f82d862ea2731<span style="color:#ce5c00;font-weight:bold">)</span> boot: Ensure <span style="color:#000">DRYCC_DEBUG</span><span style="color:#ce5c00;font-weight:bold">==</span><span style="color:#204a87">true</span> <span style="color:#204a87;font-weight:bold">for</span> debug output +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span>Please review the above changelog contents and ensure: +</span></span><span style="display:flex;"><span> 1. All intended commits are mentioned +</span></span><span style="display:flex;"><span> 2. The changes agree with the semver release tag <span style="color:#ce5c00;font-weight:bold">(</span>major, minor, or patch<span style="color:#ce5c00;font-weight:bold">)</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span>Create release <span style="color:#204a87;font-weight:bold">for</span> Drycc Controller v2.8.2? <span style="color:#ce5c00;font-weight:bold">[</span>y/n<span style="color:#ce5c00;font-weight:bold">]</span>: y +</span></span><span style="display:flex;"><span>New release is available at https://github.com/drycc/controller/releases/tag/v2.8.2 +</span></span></code></pre></div><h3 id="step-2-verify-the-component-is-available">Step 2: Verify the Component is Available<a class="td-heading-self-link" href="#step-2-verify-the-component-is-available" aria-label="Heading self-link"></a></h3> +<p>Tagging the component (see <a href="/roadmap/releases/#step-1-update-code-and-run-the-release-tool">Step 1</a>) +starts a CI job that eventually results in an artifact being made available for public download. +Please see the <a href="https://github.com/drycc/jenkins-jobs/#flow">CI flow diagrams</a> for details.</p> +<p>Double-check that the artifact is available, either by a <code>podman pull</code> command or by running the +appropriate installer script.</p> +<p>If the artifact can&rsquo;t be downloaded, ensure that its CI release jobs are still in progress, or +fix whatever issue arose in the pipeline. For example, the +<a href="https://github.com/drycc/jenkins-jobs/#when-a-component-pr-is-merged-to-master">master merge pipeline</a> +may have failed to promote the <code>:git-abc1d23</code> candidate image and needs to be restarted with +that component and commit.</p> +<p>If the component has a correlating <a href="https://github.com/kubernetes/helm">Kubernetes Helm</a> chart, +this chart will also be packaged, signed and uploaded to its production chart repo. Please +verify it can be fetched (and verified):</p> +<pre tabindex="0"><code>$ helm fetch oci://registry.drycc.cc/charts/controller --version 1.0.0 +Verification: &amp;{0xc4207ec870 sha256:026e766e918ff28d2a7041bc3d560d149ee7eb0cb84165c9d9d00a3045ff45c3 controller-v1.0.1.tgz} +</code></pre><h2 id="how-to-release-workflow">How to Release Workflow<a class="td-heading-self-link" href="#how-to-release-workflow" aria-label="Heading self-link"></a></h2> +<p>Drycc Workflow integrates multiple component releases together with a <a href="https://github.com/kubernetes/helm">Kubernetes Helm</a> chart +deliverable. This section leads a maintainer through creating a Workflow release.</p> +<h3 id="step-1-set-environment-variables">Step 1: Set Environment Variables<a class="td-heading-self-link" href="#step-1-set-environment-variables" aria-label="Heading self-link"></a></h3> +<p>Export two environment variables that will be used in later steps:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#204a87">export</span> <span style="color:#000">WORKFLOW_RELEASE</span><span style="color:#ce5c00;font-weight:bold">=</span>v2.17.0 <span style="color:#000">WORKFLOW_PREV_RELEASE</span><span style="color:#ce5c00;font-weight:bold">=</span>v2.16.0 <span style="color:#8f5902;font-style:italic"># for example</span> +</span></span></code></pre></div><h3 id="step-2-tag-supporting-repositories">Step 2: Tag Supporting Repositories<a class="td-heading-self-link" href="#step-2-tag-supporting-repositories" aria-label="Heading self-link"></a></h3> +<p>Some Workflow components not in the Helm chart must also be tagged in sync with the release. +Follow the <a href="/docs/roadmap/releases/#how-to-release-a-component">component release process</a> above and ensure that +these components are tagged:</p> +<ul> +<li><a href="https://github.com/drycc/workflow-cli">drycc/workflow-cli</a></li> +<li><a href="https://github.com/drycc/workflow-e2e">drycc/workflow-e2e</a></li> +</ul> +<p>The version number for <a href="https://github.com/drycc/workflow-cli">drycc/workflow-cli</a> should always match the overall Workflow version +number.</p> +<h3 id="step-3-create-helm-chart">Step 3: Create Helm Chart<a class="td-heading-self-link" href="#step-3-create-helm-chart" aria-label="Heading self-link"></a></h3> +<p>To create and stage a release candidate chart for Workflow, we will build the <a href="https://ci.drycc.info/job/workflow-chart-stage">workflow-chart-stage</a> job with the following parameters:</p> +<p><code>RELEASE_TAG=$WORKFLOW_RELEASE</code></p> +<p>This job will gather all of the latest component release tags and use these to specify the versions of all component charts. +It will then package the Workflow chart, upload it to the staging chart repo and kick off an e2e run against said chart.</p> +<h3 id="step-4-manual-testing">Step 4: Manual Testing<a class="td-heading-self-link" href="#step-4-manual-testing" aria-label="Heading self-link"></a></h3> +<p>Now it&rsquo;s time to go above and beyond current CI tests. Create a testing matrix spreadsheet (copying +from the previous document is a good start) and sign up testers to cover all permutations.</p> +<p>Testers should pay special attention to the overall user experience, make sure upgrading from +earlier versions is smooth, and cover various storage configurations and Kubernetes versions and +infrastructure providers.</p> +<p>When showstopper-level bugs are found, the process is as follows:</p> +<ol> +<li>Create a component PR that fixes the bug.</li> +<li>Once the PR passes and is reviewed, merge it and do a new +<a href="/docs/roadmap/releases/#how-to-release-a-component">component release</a></li> +<li>Trigger the same <code>workflow-chart-stage</code> job as mentioned in Step 3 to upload the newly-generated Workflow release candidate chart to staging.</li> +</ol> +<h3 id="step-5-release-the-chart">Step 5: Release the Chart<a class="td-heading-self-link" href="#step-5-release-the-chart" aria-label="Heading self-link"></a></h3> +<p>When testing has completed without uncovering any new showstopper bugs, kick off the <a href="https://ci.drycc.info/job/workflow-chart-release">workflow-chart-release</a> job with the following parameter:</p> +<p><code>RELEASE_TAG=$WORKFLOW_RELEASE</code></p> +<p>This job will copy the release candidate chart (now approved by CI and manual testing) from the staging repo to the production repo, signing +it if it has not done so already.</p> +<h3 id="step-6-assemble-master-changelog">Step 6: Assemble Master Changelog<a class="td-heading-self-link" href="#step-6-assemble-master-changelog" aria-label="Heading self-link"></a></h3> +<p>Each component already updated its release notes on GitHub with CHANGELOG content. We&rsquo;ll now +generate the master changelog for the Workflow chart, consisting of all component and auxilliary repo changes.</p> +<p>We&rsquo;ll employ the <code>requirements.lock</code> file from the <code>WORKFLOW_PREV_RELEASE</code> chart, as well as a repo-to-chart-name <a href="https://github.com/drycc/dryccrel/blob/main/map.json">mapping file</a>, this time invoking <code>dryccrel changelog global</code> to get all component changes between +the chart versions existing in the <code>WORKFLOW_PREV_RELEASE</code> chart and the <em>most recent</em> releases existing in GitHub. +(Therefore, if there are any unreleased commits in a component repo, they will not appear here):</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>helm fetch --untar oci://registry.drycc.cc/charts/workflow --version <span style="color:#000">$WORKFLOW_PREV_RELEASE</span> +</span></span><span style="display:flex;"><span>dryccrel changelog global workflow/requirements.lock map.json &gt; changelog-<span style="color:#000">$WORKFLOW_RELEASE</span>.md +</span></span></code></pre></div><p>This master changelog should then be placed into a single gist. The file will also be added to the documentation +update PR created in the next step.</p> +<h3 id="step-7-update-documentation">Step 7: Update Documentation<a class="td-heading-self-link" href="#step-7-update-documentation" aria-label="Heading self-link"></a></h3> +<p>Create a new pull request at <a href="https://github.com/drycc/workflow">drycc/workflow</a> that updates version references to the new release. +Use <code>git grep $WORKFLOW_PREV_RELEASE</code> to find any references, but be careful not to change +<code>CHANGELOG.md</code>.</p> +<p>Place the <code>$WORKFLOW_RELEASE</code> master changelog generated in Step 7 in the <code>changelogs</code> directory. +Make sure to add a header to the page to make it clear that this is for a Workflow release, e.g.:</p> +<pre tabindex="0"><code>## Workflow v2.16.0 -&gt; v2.17.0 +</code></pre><p>Once the PR has been reviewed and merged, do a <a href="/docs/roadmap/releases/#how-to-release-a-component">component release</a> of +<a href="https://github.com/drycc/workflow">drycc/workflow</a> itself. The version number for <a href="https://github.com/drycc/workflow">drycc/workflow</a> should always match the +overall Workflow version number.</p> +<h3 id="step-8-close-github-milestones">Step 8: Close GitHub Milestones<a class="td-heading-self-link" href="#step-8-close-github-milestones" aria-label="Heading self-link"></a></h3> +<p>Create a pull request at <a href="https://github.com/drycc/seed-repo">seed-repo</a> to close the release +milestone and create the next one. When changes are merged to seed-repo, milestones on all +relevant projects will be updated. If there are open issues attached to the milestone, move them +to the next upcoming milestone before merging the pull request.</p> +<p>Milestones map to Drycc Workflow releases in <a href="https://github.com/drycc/workflow">drycc/workflow</a>. These milestones do not correspond +to individual component release tags.</p> +<h3 id="step-9-release-workflow-cli-stable">Step 9: Release Workflow CLI Stable<a class="td-heading-self-link" href="#step-9-release-workflow-cli-stable" aria-label="Heading self-link"></a></h3> +<p>Now that the <code>$WORKFLOW_RELEASE</code> version of Workflow CLI has been vetted, we can push <code>stable</code> artifacts based on this version.</p> +<p>Kick off <a href="https://ci.drycc.info/job/workflow-cli-build-stable/">https://ci.drycc.info/job/workflow-cli-build-stable/</a> with the <code>TAG</code> build parameter of <code>$WORKFLOW_RELEASE</code> +and then verify <code>stable</code> artifacts are available and appropriately updated after the job completes:</p> +<pre tabindex="0"><code>$ curl -sfL https://www.drycc.cc/install-cli.sh | bash - +$ ./drycc version +# (Should show $WORKFLOW_RELEASE) +</code></pre><h3 id="step-10-let-everyone-know">Step 10: Let Everyone Know<a class="td-heading-self-link" href="#step-10-let-everyone-know" aria-label="Heading self-link"></a></h3> +<p>Let the rest of the team know they can start blogging and tweeting about the new Workflow release. +Post a message to the #company channel on Slack. Include a link to the released chart and to the +master CHANGELOG:</p> +<pre tabindex="0"><code>@here Drycc Workflow v2.17.0 is now live! +Master CHANGELOG: https://drycc.info/docs/workflow/changelogs/v2.17.0/ +</code></pre><p>You&rsquo;re done with the release. Nice job!</p> + + + + + + Docs: Users and SSH Keys + /docs/users/ssh-keys/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/users/ssh-keys/ + + + + <p>For <strong>Dockerfile</strong> and <strong>Buildpack</strong> based application deploys via <code>git push</code>, Drycc Workflow identifies users via SSH +keys. SSH keys are pushed to the platform and must be unique to each user. Users may have multiple SSH keys as needed.</p> +<h2 id="generate-an-ssh-key">Generate an SSH Key<a class="td-heading-self-link" href="#generate-an-ssh-key" aria-label="Heading self-link"></a></h2> +<p>If you do not already have an SSH key or would like to create a new key for Drycc Workflow, generate a new key using +<code>ssh-keygen</code>:</p> +<pre tabindex="0"><code>$ ssh-keygen -f ~/.ssh/id_drycc -t rsa +Generating public/private rsa key pair. +Enter passphrase (empty for no passphrase): +Enter same passphrase again: +Your identification has been saved in /Users/admin/.ssh/id_drycc. +Your public key has been saved in /Users/admin/.ssh/id_drycc.pub. +The key fingerprint is: +3d:ac:1f:f4:83:f7:64:51:c1:7e:7f:80:b6:70:36:c9 admin@plinth-23437.local +The key&#39;s randomart image is: ++--[ RSA 2048]----+ +| .. | +| ..| +| . o. .| +| o. E .o.| +| S == o..o| +| o +. .o| +| . o + o .| +| . o = | +| . . | ++-----------------+ +$ ssh-add ~/.ssh/id_drycc +Identity added: /Users/admin/.ssh/id_drycc (/Users/admin/.ssh/id_drycc) +</code></pre><h2 id="adding-and-removing-ssh-keys">Adding and Removing SSH Keys<a class="td-heading-self-link" href="#adding-and-removing-ssh-keys" aria-label="Heading self-link"></a></h2> +<p>By publishing the <strong>public</strong> half of your SSH key to Drycc Workflow the component responsible for receiving <code>git push</code> +will be able to authenticate the user and ensure that they have access to the destination application.</p> +<pre tabindex="0"><code>$ drycc keys:add ~/.ssh/id_drycc.pub +Uploading id_drycc.pub to drycc... done +</code></pre><p>You can always view the keys associated with your user as well:</p> +<pre tabindex="0"><code>$ drycc keys:list +ID OWNER KEY +admin@plinth-23437.local admin ssh-rsa abc AAAAB3Nz...3437.local +admin@subgenius.local admin ssh-rsa 123 AAAAB3Nz...nius.local +</code></pre><p>Remove keys by their name:</p> +<pre tabindex="0"><code>$ drycc keys:remove admin@plinth-23437.local +Removing admin@plinth-23437.local SSH Key... don +</code></pre> + + + + + Docs: Troubleshooting Applications + /docs/troubleshooting/applications/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/troubleshooting/applications/ + + + + <h2 id="application-has-a-dockerfile-but-a-buildpack-deployment-occurs">Application has a Dockerfile, but a Buildpack Deployment Occurs<a class="td-heading-self-link" href="#application-has-a-dockerfile-but-a-buildpack-deployment-occurs" aria-label="Heading self-link"></a></h2> +<p>When you deploy an application to Workflow using <code>git push drycc master</code> and the <a href="/docs/understanding-workflow/components/#builder">Builder</a> +attempts to deploy using the Buildpack workflow, check the following steps:</p> +<ol> +<li>Are you deploying the correct project?</li> +<li>Are you pushing the correct git branch (<code>git push drycc &lt;branch&gt;</code>)?</li> +<li>Is the <code>Dockerfile</code> in the project&rsquo;s root directory?</li> +<li>Have you committed the <code>Dockerfile</code> to the project?</li> +</ol> +<h2 id="application-was-deployed-but-is-failing-to-start">Application was Deployed, but is Failing to Start<a class="td-heading-self-link" href="#application-was-deployed-but-is-failing-to-start" aria-label="Heading self-link"></a></h2> +<p>If you deployed your application but it is failing to start, you can use <code>drycc logs</code> to check +why the application fails to boot. Sometimes, the application container may fail to boot without +logging any information about the error. This typically occurs when the healthcheck configured for +the application fails. In this case, you can start by +<a href="/docs/troubleshooting/kubectl/">troubleshooting using kubectl</a>. You can inspect the application&rsquo;s current +state by examining the pod deployed in the application&rsquo;s namespace. To do that, run</p> +<pre><code>$ kubectl --namespace=myapp get pods +NAME READY STATUS RESTARTS AGE +myapp-web-1585713350-3brbo 0/1 CrashLoopBackOff 2 43s +</code></pre> +<p>We can then describe the pod and determine why it is failing to boot:</p> +<pre><code>Events: + FirstSeen LastSeen Count From SubobjectPath Type Reason Message + --------- -------- ----- ---- ------------- -------- ------ ------- + 43s 43s 1 {default-scheduler } Normal Scheduled Successfully assigned myapp-web-1585713350-3brbo to kubernetes-node-1 + 41s 41s 1 {kubelet kubernetes-node-1} spec.containers{myapp-web} Normal Created Created container with container id b86bd851a61f + 41s 41s 1 {kubelet kubernetes-node-1} spec.containers{myapp-web} Normal Started Started container with container id b86bd851a61f + 37s 35s 1 {kubelet kubernetes-node-1} spec.containers{myapp-web} Warning Unhealthy Liveness probe failed: Get http://10.246.39.13:8000/healthz: dial tcp 10.246.39.13:8000: getsockopt: connection refused +</code></pre> +<p>In this instance, we set the healthcheck initial delay timeout for the application at 1 second, +which is too aggressive. The application needs some time to set up the API server after the +container has booted. By increasing the healthcheck initial delay timeout to 10 seconds, the +application is able to boot and is responding correctly.</p> +<p>See <a href="/docs/applications/managing-app-configuration/#custom-health-checks">Custom Health Checks</a> for more information on how to customize the application&rsquo;s +health checks to better suit the application&rsquo;s needs.</p> + + + + + + Docs: Configuring Object Storage + /docs/installing-workflow/configuring-object-storage/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/installing-workflow/configuring-object-storage/ + + + + <p>Drycc Workflow ships with <a href="/docs/understanding-workflow/components/#object-storage">Storage</a> by default, which provides in-cluster.</p> +<h2 id="configuring-off-cluster-object-storage">Configuring off-cluster Object Storage<a class="td-heading-self-link" href="#configuring-off-cluster-object-storage" aria-label="Heading self-link"></a></h2> +<p>Every component that relies on object storage uses two inputs for configuration:</p> +<ol> +<li>You must use object storage services that are compatible with S3 API</li> +<li>Access credentials stored as a Kubernetes secret named <code>storage-creds</code></li> +</ol> +<p>The helm chart for Drycc Workflow can be easily configured to connect Workflow components to off-cluster object storage. Drycc Workflow currently supports Google Compute Storage, Amazon S3, <a href="https://azure.microsoft.com/en-us/services/storage/blobs/">Azure Blob Storage</a> and OpenStack Swift Storage.</p> +<h3 id="step-1-create-storage-buckets">Step 1: Create storage buckets<a class="td-heading-self-link" href="#step-1-create-storage-buckets" aria-label="Heading self-link"></a></h3> +<p>Create storage buckets for each of the Workflow subsystems: <code>builder</code>, <code>registry</code>, and <code>database</code>.</p> +<p>Depending on your chosen object storage you may need to provide globally unique bucket names. If you are using S3, use hyphens instead of periods in the bucket names. Using periods in the bucket name will cause an <a href="https://forums.aws.amazon.com/thread.jspa?threadID=105357">ssl certificate validation issue with S3</a>.</p> +<p>If you provide credentials with sufficient access to the underlying storage, Workflow components will create the buckets if they do not exist.</p> +<h3 id="step-2-generate-storage-credentials">Step 2: Generate storage credentials<a class="td-heading-self-link" href="#step-2-generate-storage-credentials" aria-label="Heading self-link"></a></h3> +<p>If applicable, generate credentials that have create and write access to the storage buckets created in Step 1.</p> +<p>If you are using AWS S3 and your Kubernetes nodes are configured with appropriate <a href="http://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html">IAM</a> API keys via InstanceRoles, you do not need to create API credentials. Do, however, validate that the InstanceRole has appropriate permissions to the configured buckets!</p> +<h3 id="step-3-configure-workflow-chart">Step 3: Configure Workflow Chart<a class="td-heading-self-link" href="#step-3-configure-workflow-chart" aria-label="Heading self-link"></a></h3> +<p>Operators should configure object storage by editing the Helm values file before running <code>helm install</code>. To do so:</p> +<ul> +<li>Fetch the Helm values by running <code>helm inspect values oci://registry.drycc.cc/charts/workflow &gt; values.yaml</code></li> +<li>Update the <code>global/storage</code> parameter to reference the platform you are using, e.g. <code>s3</code>, <code>azure</code>, <code>gcs</code>, or <code>swift</code></li> +<li>Find the corresponding section for your storage type and provide appropriate values including region, bucket names, and access credentials.</li> +<li>Save your changes.</li> +</ul> +<p>!!! note +All values will be automatically (base64) encoded <em>except</em> the <code>key_json</code> values under <code>gcs</code>/<code>gcr</code>. These must be base64-encoded. This is to support cleanly passing said encoded text via <code>helm --set</code> cli functionality rather than attempting to pass the raw JSON data. For example:</p> +<pre><code> $ helm install drycc oci://registry.drycc.cc/charts/workflow \ + --namespace drycc \ + --set global.platformDomain=youdomain.com + --set global.storage=gcs,gcs.key_json=&quot;$(cat /path/to/gcs_creds.json | base64 -w 0)&quot; +</code></pre> +<p>You are now ready to run <code>helm install drycc oci://registry.drycc.cc/charts/workflow --namespace drycc -f values.yaml</code> using your desired object storage.</p> + + + + + + Docs: Using Docker Images + /docs/applications/using-container-images/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/applications/using-container-images/ + + + + <p>Drycc supports deploying applications via an existing <a href="https://docs.docker.com/introduction/understanding-docker/">Docker Image</a>. +This is useful for integrating Drycc into Docker-based CI/CD pipelines.</p> +<h2 id="prepare-an-application">Prepare an Application<a class="td-heading-self-link" href="#prepare-an-application" aria-label="Heading self-link"></a></h2> +<p>Start by cloning an example application:</p> +<pre><code>$ git clone https://github.com/drycc/example-dockerfile-http.git +$ cd example-dockerfile-http +</code></pre> +<p>Next use your local <code>docker</code> client to build the image and push +it to <a href="https://registry.hub.docker.com/">DockerHub</a>.</p> +<pre><code>$ docker build -t &lt;username&gt;/example-dockerfile-http . +$ docker push &lt;username&gt;/example-dockerfile-http +</code></pre> +<h3 id="docker-image-requirements">Docker Image Requirements<a class="td-heading-self-link" href="#docker-image-requirements" aria-label="Heading self-link"></a></h3> +<p>In order to deploy Docker images, they must conform to the following requirements:</p> +<ul> +<li>The Dockerfile must use the <code>EXPOSE</code> directive to expose exactly one port.</li> +<li>That port must be listening for an HTTP connection.</li> +<li>The Dockerfile must use the <code>CMD</code> directive to define the default process that will run within the container.</li> +<li>The Docker image must contain <a href="https://www.gnu.org/software/bash/">bash</a> to run processes.</li> +</ul> +<p>!!! note +Note that if you are using a private registry of any kind (<code>gcr</code> or other) the application environment must include a <code>$PORT</code> config variable that matches the <code>EXPOSE</code>&rsquo;d port, example: <code>drycc config:set PORT=5000</code>. See <a href="/docs/installing-workflow/configuring-registry/#configuring-off-cluster-private-registry">Configuring Registry</a> for more info.</p> +<h2 id="create-an-application">Create an Application<a class="td-heading-self-link" href="#create-an-application" aria-label="Heading self-link"></a></h2> +<p>Use <code>drycc create</code> to create an application on the <a href="/docs/understanding-workflow/components/#controller">controller</a>.</p> +<pre><code>$ mkdir -p /tmp/example-dockerfile-http &amp;&amp; cd /tmp/example-dockerfile-http +$ drycc create example-dockerfile-http --no-remote +Creating application... done, created example-dockerfile-http +</code></pre> +<p>!!! note +For all commands except for <code>drycc create</code>, the <code>drycc</code> client uses the name of the current directory +as the app name if you don&rsquo;t specify it explicitly with <code>--app</code>.</p> +<h2 id="deploy-the-application">Deploy the Application<a class="td-heading-self-link" href="#deploy-the-application" aria-label="Heading self-link"></a></h2> +<p>Use <code>drycc pull</code> to deploy your application from <a href="https://registry.hub.docker.com/">DockerHub</a> or +a public registry.</p> +<pre><code>$ drycc pull &lt;username&gt;/example-dockerfile-http:latest +Creating build... done, v2 + +$ curl -s http://example-dockerfile-http.local3.dryccapp.com +Powered by Drycc +</code></pre> +<p>Because you are deploying a Docker image, the <code>web</code> process type is automatically scaled to 1 on first deploy.</p> +<p>Use <code>drycc scale web=3</code> to increase <code>web</code> processes to 3, for example. Scaling a +process type directly changes the number of <a href="../reference-guide/terms.md#container">Containers</a> +running that process.</p> +<h2 id="private-registry">Private Registry<a class="td-heading-self-link" href="#private-registry" aria-label="Heading self-link"></a></h2> +<p>To deploy Docker images from a private registry or from a private repository, use <code>drycc registry</code> +to attach credentials to your application. These credentials are the same as you&rsquo;d use when running +<code>docker login</code> at your private registry.</p> +<p>To deploy private Docker images, take the following steps:</p> +<ul> +<li>Gather the username and password for the registry, such as a <a href="https://docs.quay.io/glossary/robot-accounts.html">Quay.io Robot Account</a> or a <a href="https://cloud.google.com/container-registry/docs/auth#using_a_json_key_file">GCR.io Long Lived Token</a></li> +<li>Run <code>drycc registry:set username=&lt;the-user&gt; password=&lt;secret&gt; -a &lt;application-name&gt;</code></li> +<li>Now perform <code>drycc pull</code> as normal, against an image in the private registry</li> +</ul> +<p>When using a <a href="https://cloud.google.com/container-registry/docs/auth#using_a_json_key_file">GCR.io Long Lived Token</a>, the JSON blob will have to be compacted first using a +tool like <a href="https://stedolan.github.io/jq/">jq</a> and then used in the password field in <code>drycc registry:set</code>. For the username, use +<code>_json_key</code>. For example:</p> +<pre tabindex="0"><code>drycc registry:set username=_json_key password=&#34;$(cat google_cloud_cred.json | jq -c .)&#34; +</code></pre><p>When using a private registry the docker images are no longer pulled into the Drycc Internal Registry via +the Drycc Workflow Controller but rather is managed by Kubernetes. This will increase security and overall speed, +however the application <code>port</code> information can no longer be discovered. Instead the application <code>port</code> information can be set via +<code>drycc config:set PORT=80</code> prior to setting the registry information.</p> +<p>!!! note +Currently <a href="https://gcr.io">GCR.io</a> and <a href="https://aws.amazon.com/ecr/">ECR</a> in short lived auth token mode are not supported.</p> + + + + + + Docs: Controller API v2.1 + /docs/reference-guide/controller-api-v2-1/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/reference-guide/controller-api-v2-1/ + + + + <h2 id="whats-new">What&rsquo;s New<a class="td-heading-self-link" href="#whats-new" aria-label="Heading self-link"></a></h2> +<p><strong>New!</strong> <code>healthcheck</code> field in configuration, deprecates the <code>HEALTHCHECK_*</code> environment variables.</p> +<p><strong>New!</strong> Unsetting a configuration variable that does not exist will return a 422.</p> +<p><strong>New!</strong> Creating an identical sequential release returns a 409 rather than create a no-op release.</p> +<h2 id="authentication">Authentication<a class="td-heading-self-link" href="#authentication" aria-label="Heading self-link"></a></h2> +<h3 id="register-a-new-user">Register a New User<a class="td-heading-self-link" href="#register-a-new-user" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/register/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json + +{ + &#34;username&#34;: &#34;test&#34;, + &#34;password&#34;: &#34;opensesame&#34;, + &#34;email&#34;: &#34;test@example.com&#34; +} +</code></pre><p>Optional Parameters:</p> +<pre tabindex="0"><code>{ + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;id&#34;: 1, + &#34;last_login&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;is_superuser&#34;: true, + &#34;username&#34;: &#34;test&#34;, + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34;, + &#34;email&#34;: &#34;test@example.com&#34;, + &#34;is_staff&#34;: true, + &#34;is_active&#34;: true, + &#34;date_joined&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;groups&#34;: [], + &#34;user_permissions&#34;: [] +} +</code></pre><h3 id="log-in">Log in<a class="td-heading-self-link" href="#log-in" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/login/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json + +{&#34;username&#34;: &#34;test&#34;, &#34;password&#34;: &#34;opensesame&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{&#34;token&#34;: &#34;abc123&#34;} +</code></pre><h3 id="cancel-account">Cancel Account<a class="td-heading-self-link" href="#cancel-account" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/auth/cancel/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="regenerate-token">Regenerate Token<a class="td-heading-self-link" href="#regenerate-token" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command could require administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/tokens/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Optional Parameters:</p> +<pre tabindex="0"><code>{ + &#34;username&#34; : &#34;test&#34; + &#34;all&#34; : &#34;true&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{&#34;token&#34;: &#34;abc123&#34;} +</code></pre><h3 id="change-password">Change Password<a class="td-heading-self-link" href="#change-password" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/passwd/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{ + &#34;password&#34;: &#34;foo&#34;, + &#34;new_password&#34;: &#34;bar&#34; +} +</code></pre><p>Optional parameters:</p> +<pre tabindex="0"><code>{&#34;username&#34;: &#34;testuser&#34;} +</code></pre><blockquote> +<p><strong>note</strong></p> +<p>Using the <code>username</code> parameter requires administrative privileges and makes the <code>password</code> parameter optional.</p> +</blockquote> +<p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h2 id="applications">Applications<a class="td-heading-self-link" href="#applications" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-applications">List all Applications<a class="td-heading-self-link" href="#list-all-applications" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;structure&#34;: {}, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;url&#34;: &#34;example-go.example.com&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; + } + ] +} +</code></pre><h3 id="create-an-application">Create an Application<a class="td-heading-self-link" href="#create-an-application" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 +</code></pre><p>Optional parameters:</p> +<pre tabindex="0"><code>{&#34;id&#34;: &#34;example-go&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;structure&#34;: {}, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;url&#34;: &#34;example-go.example.com&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="destroy-an-application">Destroy an Application<a class="td-heading-self-link" href="#destroy-an-application" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/apps/example-go/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="list-application-details">List Application Details<a class="td-heading-self-link" href="#list-application-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;structure&#34;: {}, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;url&#34;: &#34;example-go.example.com&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="update-application-details">Update Application Details<a class="td-heading-self-link" href="#update-application-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Optional parameters:</p> +<pre tabindex="0"><code>{ + &#34;owner&#34;: &#34;test&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 1.8.0 +Content-Type: application/json +</code></pre><h3 id="retrieve-application-logs">Retrieve Application Logs<a class="td-heading-self-link" href="#retrieve-application-logs" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/logs/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Optional URL Query Parameters:</p> +<pre tabindex="0"><code>?log_lines= +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: text/plain + +&#34;16:51:14 drycc[api]: test created initial release\n&#34; +</code></pre><h3 id="run-one-off-commands">Run one-off Commands<a class="td-heading-self-link" href="#run-one-off-commands" aria-label="Heading self-link"></a></h3> +<pre tabindex="0"><code>POST /v2/apps/example-go/run/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;command&#34;: &#34;echo hi&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{&#34;exit_code&#34;: 0, &#34;output&#34;: &#34;hi\n&#34;} +</code></pre><h2 id="certificates">Certificates<a class="td-heading-self-link" href="#certificates" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-certificates">List all Certificates<a class="td-heading-self-link" href="#list-all-certificates" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/certs HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;id&#34;: 22, + &#34;owner&#34;: &#34;test&#34;, + &#34;san&#34;: [], + &#34;domains&#34;: [], + &#34;created&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;updated&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;name&#34;: &#34;foo&#34;, + &#34;common_name&#34;: &#34;bar.com&#34;, + &#34;fingerprint&#34;: &#34;7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0&#34;, + &#34;expires&#34;: &#34;2017-01-14T23:57:57Z&#34;, + &#34;starts&#34;: &#34;2016-01-15T23:57:57Z&#34;, + &#34;issuer&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34;, + &#34;subject&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34; + } + ] +} +</code></pre><h3 id="get-certificate-details">Get Certificate Details<a class="td-heading-self-link" href="#get-certificate-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/certs/foo HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;id&#34;: 22, + &#34;owner&#34;: &#34;test&#34;, + &#34;san&#34;: [], + &#34;domains&#34;: [], + &#34;created&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;updated&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;name&#34;: &#34;foo&#34;, + &#34;common_name&#34;: &#34;bar.com&#34;, + &#34;fingerprint&#34;: &#34;7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0&#34;, + &#34;expires&#34;: &#34;2017-01-14T23:57:57Z&#34;, + &#34;starts&#34;: &#34;2016-01-15T23:57:57Z&#34;, + &#34;issuer&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34;, + &#34;subject&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34; +} +</code></pre><h3 id="create-certificate">Create Certificate<a class="td-heading-self-link" href="#create-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/certs/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{ + &#34;name&#34;: &#34;foo&#34; + &#34;certificate&#34;: &#34;-----BEGIN CERTIFICATE-----&#34;, + &#34;key&#34;: &#34;-----BEGIN RSA PRIVATE KEY-----&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;id&#34;: 22, + &#34;owner&#34;: &#34;test&#34;, + &#34;san&#34;: [], + &#34;domains&#34;: [], + &#34;created&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;updated&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;name&#34;: &#34;foo&#34;, + &#34;common_name&#34;: &#34;bar.com&#34;, + &#34;fingerprint&#34;: &#34;7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0&#34;, + &#34;expires&#34;: &#34;2017-01-14T23:57:57Z&#34;, + &#34;starts&#34;: &#34;2016-01-15T23:57:57Z&#34;, + &#34;issuer&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34;, + &#34;subject&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34; +} +</code></pre><h3 id="destroy-a-certificate">Destroy a Certificate<a class="td-heading-self-link" href="#destroy-a-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/certs/foo HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="attach-a-domain-to-a-certificate">Attach a Domain to a Certificate<a class="td-heading-self-link" href="#attach-a-domain-to-a-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/certs/foo/domain/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{ + &#34;domain&#34;: &#34;test.com&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="remove-a-domain-from-a-certificate">Remove a Domain from a Certificate<a class="td-heading-self-link" href="#remove-a-domain-from-a-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/certs/foo/domain/test.com/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h2 id="pods">Pods<a class="td-heading-self-link" href="#pods" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-pods">List all Pods<a class="td-heading-self-link" href="#list-all-pods" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/pods/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;results&#34;: [ + { + &#34;name&#34;: &#34;go-v2-web-e7dej&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2014-01-01T00:00:00Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } + ] +} +</code></pre><h3 id="list-all-pods-by-type">List all Pods by Type<a class="td-heading-self-link" href="#list-all-pods-by-type" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/pods/web/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;results&#34;: [ + { + &#34;name&#34;: &#34;go-v2-web-e7dej&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2014-01-01T00:00:00Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } + ] +} +</code></pre><h3 id="restart-all-pods">Restart All Pods<a class="td-heading-self-link" href="#restart-all-pods" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/pods/restart/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +[ + { + &#34;name&#34;: &#34;go-v2-web-atots&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2016-04-11T21:07:54Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } +] +</code></pre><h3 id="restart-pods-by-type">Restart Pods by Type<a class="td-heading-self-link" href="#restart-pods-by-type" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/pods/web/restart/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +[ + { + &#34;name&#34;: &#34;go-v2-web-atots&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2016-04-11T21:07:54Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } +] +</code></pre><h3 id="restart-pods-by-type-and-name">Restart Pods by Type and Name<a class="td-heading-self-link" href="#restart-pods-by-type-and-name" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/pods/go-v2-web-atots/restart/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +[ + { + &#34;name&#34;: &#34;go-v2-web-atots&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2016-04-11T21:07:54Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } +] +</code></pre><h3 id="scale-pods">Scale Pods<a class="td-heading-self-link" href="#scale-pods" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/scale/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;web&#34;: 3} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h2 id="configuration">Configuration<a class="td-heading-self-link" href="#configuration" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-configuration">List Application Configuration<a class="td-heading-self-link" href="#list-application-configuration" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/config/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;owner&#34;: &#34;test&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;values&#34;: { + &#34;PLATFORM&#34;: &#34;drycc&#34; + }, + &#34;memory&#34;: {}, + &#34;cpu&#34;: {}, + &#34;tags&#34;: {}, + &#34;healthcheck&#34;: {}, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="create-new-config">Create new Config<a class="td-heading-self-link" href="#create-new-config" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/config/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;values&#34;: {&#34;HELLO&#34;: &#34;world&#34;, &#34;PLATFORM&#34;: &#34;drycc&#34;}} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;owner&#34;: &#34;test&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;values&#34;: { + &#34;DRYCC_APP&#34;: &#34;example-go&#34;, + &#34;DRYCC_RELEASE&#34;: &#34;v3&#34;, + &#34;HELLO&#34;: &#34;world&#34;, + &#34;PLATFORM&#34;: &#34;drycc&#34; + + }, + &#34;memory&#34;: {}, + &#34;cpu&#34;: {}, + &#34;tags&#34;: {}, + &#34;healthcheck&#34;: {}, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="unset-config-variable">Unset Config Variable<a class="td-heading-self-link" href="#unset-config-variable" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/config/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;values&#34;: {&#34;HELLO&#34;: null}} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;owner&#34;: &#34;test&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;values&#34;: { + &#34;DRYCC_APP&#34;: &#34;example-go&#34;, + &#34;DRYCC_RELEASE&#34;: &#34;v4&#34;, + &#34;PLATFORM&#34;: &#34;drycc&#34; + }, + &#34;memory&#34;: {}, + &#34;cpu&#34;: {}, + &#34;tags&#34;: {}, + &#34;healthcheck&#34;: {}, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h2 id="domains">Domains<a class="td-heading-self-link" href="#domains" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-domains">List Application Domains<a class="td-heading-self-link" href="#list-application-domains" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/domains/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;domain&#34;: &#34;example.example.com&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34; + } + ] +} +</code></pre><h3 id="add-domain">Add Domain<a class="td-heading-self-link" href="#add-domain" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/domains/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{&#39;domain&#39;: &#39;example.example.com&#39;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;domain&#34;: &#34;example.example.com&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34; +} +</code></pre><h3 id="remove-domain">Remove Domain<a class="td-heading-self-link" href="#remove-domain" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/apps/example-go/domains/example.example.com HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h2 id="builds">Builds<a class="td-heading-self-link" href="#builds" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-builds">List Application Builds<a class="td-heading-self-link" href="#list-application-builds" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/build/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;dockerfile&#34;: &#34;FROM drycc/slugrunner RUN mkdir -p /app WORKDIR /app ENTRYPOINT [\&#34;/runner/init\&#34;] ADD slug.tgz /app ENV GIT_SHA 060da68f654e75fac06dbedd1995d5f8ad9084db&#34;, + &#34;image&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;procfile&#34;: { + &#34;web&#34;: &#34;example-go&#34; + }, + &#34;sha&#34;: &#34;060da68f&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="create-application-build">Create Application Build<a class="td-heading-self-link" href="#create-application-build" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/build/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;image&#34;: &#34;drycc/example-go:latest&#34;} +</code></pre><p>Optional Parameters:</p> +<pre tabindex="0"><code>{ + &#34;procfile&#34;: { + &#34;web&#34;: &#34;./cmd&#34; + } +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;dockerfile&#34;: &#34;&#34;, + &#34;image&#34;: &#34;drycc/example-go:latest&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;procfile&#34;: {}, + &#34;sha&#34;: &#34;&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h2 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-releases">List Application Releases<a class="td-heading-self-link" href="#list-application-releases" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/releases/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 3, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: &#34;202d8e4b-600e-4425-a85c-ffc7ea607f61&#34;, + &#34;config&#34;: &#34;ed637ceb-5d32-44bd-9406-d326a777a513&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test changed nothing&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 3 + }, + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: &#34;202d8e4b-600e-4425-a85c-ffc7ea607f61&#34;, + &#34;config&#34;: &#34;95bd6dea-1685-4f78-a03d-fd7270b058d1&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test deployed 060da68&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 2 + }, + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: null, + &#34;config&#34;: &#34;95bd6dea-1685-4f78-a03d-fd7270b058d1&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test created initial release&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 1 + } + ] +} +</code></pre><h3 id="list-release-details">List Release Details<a class="td-heading-self-link" href="#list-release-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/releases/v2/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: null, + &#34;config&#34;: &#34;95bd6dea-1685-4f78-a03d-fd7270b058d1&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test created initial release&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 1 +} +</code></pre><h3 id="rollback-release">Rollback Release<a class="td-heading-self-link" href="#rollback-release" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/releases/rollback/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;version&#34;: 1} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{&#34;version&#34;: 5} +</code></pre><h2 id="keys">Keys<a class="td-heading-self-link" href="#keys" aria-label="Heading self-link"></a></h2> +<h3 id="list-keys">List Keys<a class="td-heading-self-link" href="#list-keys" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/keys/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;test@example.com&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;public&#34;: &#34;ssh-rsa &lt;...&gt;&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; + } + ] +} +</code></pre><h3 id="add-key-to-user">Add Key to User<a class="td-heading-self-link" href="#add-key-to-user" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/keys/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{ + &#34;id&#34;: &#34;example&#34;, + &#34;public&#34;: &#34;ssh-rsa &lt;...&gt;&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example&#34;, + &#34;owner&#34;: &#34;example&#34;, + &#34;public&#34;: &#34;ssh-rsa &lt;...&gt;&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="remove-key-from-user">Remove Key from User<a class="td-heading-self-link" href="#remove-key-from-user" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/keys/example HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h2 id="permissions">Permissions<a class="td-heading-self-link" href="#permissions" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-permissions">List Application Permissions<a class="td-heading-self-link" href="#list-application-permissions" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This does not include the app owner.</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/perms/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;users&#34;: [ + &#34;test&#34;, + &#34;foo&#34; + ] +} +</code></pre><h3 id="create-application-permission">Create Application Permission<a class="td-heading-self-link" href="#create-application-permission" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/perms/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{&#34;username&#34;: &#34;example&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="remove-application-permission">Remove Application Permission<a class="td-heading-self-link" href="#remove-application-permission" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/apps/example-go/perms/example HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="list-administrators">List Administrators<a class="td-heading-self-link" href="#list-administrators" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/admin/perms/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 2, + &#34;next&#34;: null + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;username&#34;: &#34;test&#34;, + &#34;is_superuser&#34;: true + }, + { + &#34;username&#34;: &#34;foo&#34;, + &#34;is_superuser&#34;: true + } + ] +} +</code></pre><h3 id="grant-user-administrative-privileges">Grant User Administrative Privileges<a class="td-heading-self-link" href="#grant-user-administrative-privileges" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command requires administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/admin/perms HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{&#34;username&#34;: &#34;example&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="remove-users-administrative-privileges">Remove User&rsquo;s Administrative Privileges<a class="td-heading-self-link" href="#remove-users-administrative-privileges" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command requires administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/admin/perms/example HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h2 id="users">Users<a class="td-heading-self-link" href="#users" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-users">List all users<a class="td-heading-self-link" href="#list-all-users" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command requires administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/users HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;id&#34;: 1, + &#34;last_login&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;is_superuser&#34;: true, + &#34;username&#34;: &#34;test&#34;, + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34;, + &#34;email&#34;: &#34;test@example.com&#34;, + &#34;is_staff&#34;: true, + &#34;is_active&#34;: true, + &#34;date_joined&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;groups&#34;: [], + &#34;user_permissions&#34;: [] + } + ] +} +</code></pre> + + + + + Docs: Deploy Your First App + /docs/quickstart/deploy-an-app/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/quickstart/deploy-an-app/ + + + + <h2 id="determine-your-host-and-hostname-values">Determine Your Host and Hostname Values<a class="td-heading-self-link" href="#determine-your-host-and-hostname-values" aria-label="Heading self-link"></a></h2> +<p>Drycc workflow requires a wildcard DNS record to dynamically map app names to the router.</p> +<p>User should already have DNS set up pointing to their known host. The <code>$hostname</code> value can be calculated by prepending <code>drycc.</code> to the value set in <code>global.platformDomain</code>.</p> +<h2 id="login-to-workflow">Login to Workflow<a class="td-heading-self-link" href="#login-to-workflow" aria-label="Heading self-link"></a></h2> +<p>Workflow use the passport component to create and authorize users. +If you already have an account, use <code>drycc login</code> to authenticate against the Drycc Workflow API.</p> +<pre tabindex="0"><code>$ drycc login http://drycc.example.com +Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71 +Waiting for login... .o.Logged in as admin +Configuration file written to /root/.drycc/client.json +</code></pre><p>Or you can login with username and password</p> +<pre tabindex="0"><code>$ drycc login http://drycc.example.com --username=demo --password=demo +Configuration file written to /root/.drycc/client.json +</code></pre><h2 id="deploy-an-application">Deploy an Application<a class="td-heading-self-link" href="#deploy-an-application" aria-label="Heading self-link"></a></h2> +<p>Drycc Workflow supports three different types of applications, Buildpacks, +Dockerfiles and Container Images. Our first application will be a simple Container +Image-based application, so you don&rsquo;t have to wrestle with checking out code.</p> +<p>Run <code>drycc create</code> to create a new application on Drycc Workflow. If you do not +specify a name for your application, Workflow automatically generates a +friendly (and sometimes funny) name.</p> +<pre tabindex="0"><code>$ drycc create --no-remote +Creating Application... done, created proper-barbecue +If you want to add a git remote for this app later, use `drycc git:remote -a proper-barbecue` +</code></pre><p>Our application has been created and named <code>proper-barbecue</code>. As with the +<code>drycc</code> hostname, any HTTP traffic to <code>proper-barbecue</code> will be automatically +routed to your application pods by the edge router.</p> +<p>Let&rsquo;s use the CLI to tell the platform to deploy an application and then use curl to send a request to the app:</p> +<pre tabindex="0"><code>$ drycc pull drycc/example-go -a proper-barbecue +Creating build... done +$ curl http://proper-barbecue.$hostname +Powered by Drycc +</code></pre><p>!!! note +If you see a 404 error, make sure you specified your application name with <code>-a &lt;appname&gt;</code>!</p> +<p>Workflow&rsquo;s edge router knows all about application names and automatically +sends traffic to the right application. The router sends traffic for +<code>proper-barbecue.104.197.125.75.nip.io</code> to your app, just like +<code>drycc.104.197.125.75.nip.io</code> was sent to the Workflow API service.</p> +<h2 id="change-application-configuration">Change Application Configuration<a class="td-heading-self-link" href="#change-application-configuration" aria-label="Heading self-link"></a></h2> +<p>Next, let&rsquo;s change some configuration using the CLI. Our example app is built +to read configuration from the environment. By using <code>drycc config:set</code> we can +change how the application behaves:</p> +<pre tabindex="0"><code>$ drycc config:set POWERED_BY=&#34;Container Images + Kubernetes&#34; -a proper-barbecue +Creating config... done + +UUID OWNER NAME VALUE +04bb6e45-9221-4843-a1f9-acc7fded3b06 dev POWERED_BY Container Images + Kubernetes +</code></pre><p>Behind the scenes, Workflow creates a new release for your application and uses +Kubernetes to provide a zero-downtime rolling deploy to the new release!</p> +<p>Validate that our configuration change has worked:</p> +<pre tabindex="0"><code>$ curl http://proper-barbecue.104.197.125.75.nip.io +Powered by Container Images + Kubernetes +</code></pre><h2 id="scale-your-application">Scale Your Application<a class="td-heading-self-link" href="#scale-your-application" aria-label="Heading self-link"></a></h2> +<p>Last, let&rsquo;s scale our application by adding more application processes. Using the CLI you can easily add and remove +additional processes to service requests:</p> +<pre tabindex="0"><code>$ drycc scale web=2 -a proper-barbecue +Scaling processes... but first, coffee! +done in 36s + +NAME RELEASE STATE PTYPE STARTED +proper-barbecue-v18-web-rk644 v18 up web 2023-12-08T03:09:25UTC +proper-barbecue-v18-web-0ag04 v18 up web 2023-12-08T03:09:25UTC +</code></pre><p>Congratulations! You have deployed, configured, and scaled your first application using Drycc Workflow.</p> +<h2 id="going-further">Going Further<a class="td-heading-self-link" href="#going-further" aria-label="Heading self-link"></a></h2> +<p>There is a lot more you can do with Drycc Workflow, play around with the CLI:</p> +<p>!!! important +In order to have permission to push an app you must add a SSH key to your user on the Drycc Workflow. +For more information, please check <a href="/docs/users/ssh-keys/">Users and SSH Keys</a> and <a href="/docs/troubleshooting/">Troubleshooting Workflow</a>.</p> +<ul> +<li>Roll back to a previous release with <code>drycc rollback -a proper-barbecue</code></li> +<li>See application logs with <code>drycc logs -a proper-barbecue</code></li> +<li>Try one of our other example applications like: +<ul> +<li><a href="https://github.com/drycc/ruby-getting-started">drycc/ruby-getting-started</a></li> +<li><a href="https://github.com/drycc/python-getting-started">drycc/python-getting-started</a></li> +<li><a href="https://github.com/drycc/php-getting-started">drycc/php-getting-started</a></li> +</ul> +</li> +<li>Read about using application <a href="/docs/applications/using-buildpacks/">Buildpacks</a> or <a href="/docs/applications/using-dockerfiles/">Dockerfiles</a></li> +<li>Join our <a href="https://drycc.slack.com/">#community slack channel</a> and meet the team!</li> +</ul> + + + + + + Docs: Platform Logging + /docs/managing-workflow/platform-logging/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/managing-workflow/platform-logging/ + + + + <p>The logging platform is made up of 2 components - <a href="https://github.com/drycc/fluentbit">Fluentbit</a> and <a href="https://github.com/drycc/logger">Logger</a>.</p> +<p><a href="https://github.com/drycc/fluentbit">Fluentbit</a> runs on every worker node of the cluster and is deployed as a <a href="http://kubernetes.io/v1.1/docs/admin/daemons.html">Daemon Set</a>. The Fluentbit pods capture all of the stderr and stdout streams of every container running on the host (even those not hosted directly by kubernetes). Once the log message arrives in our <a href="https://github.com/drycc/fluentbit/tree/main/plugin">custom fluentbit plugin</a> we determine where the message originated.</p> +<p>If the message was from the <a href="https://github.com/drycc/controller">Workflow Controller</a> or from an application deployed via workflow we send it to the logs topic on the local <a href="http://redis.io">Redis Stream</a> instance.</p> +<p>Logger then acts as a consumer reading messages off of the Redis Stream logs topic storing those messages in a local Redis instance. When a user wants to retrieve log entries using the <code>drycc logs</code> command we make an HTTP request from Controller to Logger which then fetches the appropriate data from Redis.</p> +<h2 id="configuring-off-cluster-redis">Configuring Off Cluster Redis<a class="td-heading-self-link" href="#configuring-off-cluster-redis" aria-label="Heading self-link"></a></h2> +<p>Even though we provide a redis instance with the default Workflow install, it is recommended that operators use a third-party source like Elasticache or similar offering. This way your data is durable across upgrades or outages. If you have a third-party Redis installation you would like to use all you need to do is set the following values in your helm chart:</p> +<ul> +<li>db = &ldquo;0&rdquo;</li> +<li>host = &ldquo;my.host.redis&rdquo;</li> +<li>port = &ldquo;6379&rdquo;</li> +<li>password = &quot;&quot;</li> +</ul> +<p>These can be changed by running <code>helm inspect values drycc/workflow &gt; values.yaml</code> before using +<code>helm install</code> to complete the installation. To customize the redis credentials, edit <code>values.yaml</code> +and modify the <code>redis</code> section of the file to tune these settings.</p> +<h2 id="debugging-logger">Debugging Logger<a class="td-heading-self-link" href="#debugging-logger" aria-label="Heading self-link"></a></h2> +<p>If the <code>drycc logs</code> command encounters an error it will return the following message:</p> +<pre tabindex="0"><code>Error: There are currently no log messages. Please check the following things: +1) Logger and fluentbit pods are running. +2) The application is writing logs to the logger component by checking that an entry in the ring buffer was created: kubectl --namespace=drycc logs &lt;logger pod&gt; +3) Making sure that the container logs were mounted properly into the fluentbit pod: kubectl --namespace=drycc exec &lt;fluentbit pod&gt; ls /var/log/containers +</code></pre><h2 id="architecture-diagram">Architecture Diagram<a class="td-heading-self-link" href="#architecture-diagram" aria-label="Heading self-link"></a></h2> +<pre tabindex="0"><code> ┌────────┐ + │ Router │ ┌────────┐ ┌─────┐ + └────────┘ │ Logger │◀───▶│Redis│ + │ └────────┘ └─────┘ + Log file ▲ + │ │ + ▼ │ +┌────────┐ ┌─────────┐ logs/metrics ┌──────────────┐ +│App Logs│──Log File──▶│Fluentbit│───────topics─────▶│ Redis Stream │ +└────────┘ └─────────┘ └──────────────┘ + +</code></pre><h2 id="default-configuration">Default Configuration<a class="td-heading-self-link" href="#default-configuration" aria-label="Heading self-link"></a></h2> +<p>Fluent Bit is based in a pluggable architecture where different plugins plays a major role in the data pipeline, more than 70 built-in plugins available. +Please refer to charts <a href="https://github.com/drycc/fluentbit/blob/main/charts/fluentbit/values.yaml">values.yaml</a> for specific configurations.</p> + + + + + + Docs: Testing Drycc + /docs/contribution-guidelines/testing/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/contribution-guidelines/testing/ + + + + <p>Each Drycc component includes its own suite of style checks, <a href="http://en.wikipedia.org/wiki/Unit_testing">unit tests</a>, and black-box type <a href="http://en.wikipedia.org/wiki/Functional_testing">functional tests</a>.</p> +<p><a href="http://en.wikipedia.org/wiki/Integration_testing">Integration tests</a> verify the behavior of the Drycc components together as a system and are provided separately by the <a href="https://github.com/drycc/workflow-e2e">drycc/workflow-e2e</a> project.</p> +<p>GitHub pull requests for all Drycc components are tested automatically by the <a href="https://travis-ci.org/drycc">Travis CI</a> <a href="http://en.wikipedia.org/wiki/Continuous_integration">continuous integration</a> system. Contributors should run the same tests locally before proposing any changes to the Drycc codebase.</p> +<h2 id="set-up-the-environment">Set Up the Environment<a class="td-heading-self-link" href="#set-up-the-environment" aria-label="Heading self-link"></a></h2> +<p>Successfully executing the unit and functional tests for any Drycc component requires that the <a href="/docs/contribution-guidelines/development-environment/">Development Environment</a> is set up first.</p> +<h2 id="run-the-tests">Run the Tests<a class="td-heading-self-link" href="#run-the-tests" aria-label="Heading self-link"></a></h2> +<p>The style checks, unit tests, and functional tests for each component can all be executed via make targets:</p> +<p>To execute style checks:</p> +<pre tabindex="0"><code>$ make test-style +</code></pre><p>To execute unit tests:</p> +<pre tabindex="0"><code>$ make test-unit +</code></pre><p>To execute functional tests:</p> +<pre tabindex="0"><code>$ make test-functional +</code></pre><p>To execute style checks, unit tests, and functional tests all in one shot:</p> +<pre tabindex="0"><code>$ make test +</code></pre><p>To execute integration tests, refer to <a href="https://github.com/drycc/workflow-e2e">drycc/workflow-e2e</a> documentation.</p> + + + + + + Docs: Configuring Postgres + /docs/installing-workflow/configuring-postgres/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/installing-workflow/configuring-postgres/ + + + + <h1 id="configuring-postgres">Configuring Postgres<a class="td-heading-self-link" href="#configuring-postgres" aria-label="Heading self-link"></a></h1> +<p>By default, Drycc Workflow ships with the <a href="/docs/understanding-workflow/components/#database">database</a> component, which provides an in-cluster PostgreSQL database backed up to in-cluster or off-cluster <a href="/docs/installing-workflow/configuring-object-storage/">object storage</a>. Currently, for object storage, which is utilized by <em>several</em> Workflow components, only off-cluster solutions such as S3 or GCS are recommended in production environments. Experience has shown that many operators already opting for off-cluster object storage similarly prefer to host Postgres off-cluster as well, using Amazon RDS or similar. When excercising both options, a Workflow installation becomes entirely stateless, and is thus restored or rebuilt with greater ease should the need ever arise.</p> +<h2 id="provisioning-off-cluster-postgres">Provisioning off-cluster Postgres<a class="td-heading-self-link" href="#provisioning-off-cluster-postgres" aria-label="Heading self-link"></a></h2> +<p>First, provision a PostgreSQL RDBMS using the cloud provider or other infrastructure of your choice. Take care to ensure that security groups or other firewall rules will permit connectivity from your Kubernetes worker nodes, any of which may play host to the Workflow controller component.</p> +<p>Take note of the following:</p> +<ol> +<li>The hostname or public IP of your PostgreSQL RDBMS</li> +<li>The port on which your PostgreSQL RDBMS runs&ndash; typically 5432</li> +</ol> +<p>Within the off-cluster RDBMS, manually provision the following:</p> +<ol> +<li>A database user (take note of the username and password)</li> +<li>A database owned by that user (take note of its name)</li> +</ol> +<p>If you are able to log into the RDBMS as a superuser or a user with appropriate permissions, this process will <em>typically</em> look like this:</p> +<pre tabindex="0"><code>$ psql -h &lt;host&gt; -p &lt;port&gt; -d postgres -U &lt;&#34;postgres&#34; or your own username&gt; +&gt; create user &lt;drycc username; typically &#34;drycc&#34;&gt; with password &#39;&lt;password&gt;&#39;; +&gt; create database &lt;database name; typically &#34;drycc&#34;&gt; with owner &lt;drycc username&gt;; +&gt; \q +</code></pre><h2 id="configuring-workflow">Configuring Workflow<a class="td-heading-self-link" href="#configuring-workflow" aria-label="Heading self-link"></a></h2> +<p>The Helm chart for Drycc Workflow can be easily configured to connect the Workflow controller component to an off-cluster PostgreSQL database.</p> +<ul> +<li><strong>Step 1:</strong> If you haven&rsquo;t already fetched the values, do so with <code>helm inspect values drycc/workflow &gt; values.yaml</code></li> +<li><strong>Step 2:</strong> Update database connection details by modifying <code>values.yaml</code>: +<ul> +<li>Update the <code>databaseLocation</code> parameter to <code>off-cluster</code>.</li> +<li>Update the values in the <code>[database]</code> configuration section to properly reflect all connection details.</li> +<li>Update the values in the <code>[controller]</code> configuration section to properly reflect platformDomain details.</li> +<li>Save your changes.</li> +<li>Note: you do not need to (and must not) base64 encode any values, as the Helm chart will automatically handle encoding as necessary.</li> +</ul> +</li> +</ul> +<p>You are now ready to <code>helm install drycc oci://registry.drycc.cc/charts/workflow --namespace drycc -f values.yaml</code> <a href="/docs/installing-workflow/">as usual</a>.</p> + + + + + + Docs: Configuring Registry + /docs/installing-workflow/configuring-registry/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/installing-workflow/configuring-registry/ + + + + <p>Drycc Workflow ships with a <a href="/docs/understanding-workflow/components/#registry">registry</a> component by default, which provides an in-cluster Container registry backed by the platform-configured <a href="/docs/installing-workflow/configuring-object-storage/">object storage</a>. Operators might want to use an off-cluster registry for performance or security reasons.</p> +<h2 id="configuring-off-cluster-private-registry">Configuring Off-Cluster Private Registry<a class="td-heading-self-link" href="#configuring-off-cluster-private-registry" aria-label="Heading self-link"></a></h2> +<p>Every component that relies on a registry uses two inputs for configuration:</p> +<ol> +<li>Registry Location environment variable named <code>DRYCC_REGISTRY_LOCATION</code></li> +<li>Access credentials stored as a Kubernetes secret named <code>registry-secret</code></li> +</ol> +<p>The Helm chart for Drycc Workflow can be easily configured to connect Workflow components to off-cluster registry. Drycc Workflow supports external registries which provide either short-lived tokens that are valid only for a specified amount of time or long-lived tokens (basic username/password) which are valid forever for authenticating to them. For those registries which provide short lived tokens for authentication, Drycc Workflow will generate and refresh them such that the deployed apps will only have access to the short-lived tokens and not to the actual credentials for the registries.</p> +<p>When using a private registry the container images are no longer pulled by Drycc Workflow Controller but rather are managed by <a href="https://kubernetes.io">Kubernetes</a>. This will increase security and overall speed, however the <code>port</code> information can no longer be discovered. Instead the <code>port</code> information can be set via <code>drycc config:set PORT=&lt;port&gt;</code> prior to deploying the application.</p> +<p>Drycc Workflow currently supports:</p> +<ol> +<li>off-cluster: Any provider which supports long-lived username/password authentication, such as <a href="https://docs.microsoft.com/en-us/azure/container-registry/">Azure Container Registry</a>, <a href="https://hub.docker.com/">Docker Hub</a>, <a href="https://quay.io/">quay.io</a>, or a self-hosted Container registry.</li> +</ol> +<h2 id="configuration">Configuration<a class="td-heading-self-link" href="#configuration" aria-label="Heading self-link"></a></h2> +<ol> +<li>If you haven&rsquo;t already fetched the values file, do so with <code>helm inspect values drycc/workflow &gt; values.yaml</code></li> +<li>Update registry location details by modifying the values file: +* Update the <code>registryLocation</code> parameter to reference the registry location you are using: <code>off-cluster</code>, <code>ecr</code>, <code>gcr</code> +* Update the values in the section which corresponds to your registry location type.</li> +</ol> +<p>You are now ready to <code>helm install drycc oci://registry.drycc.cc/charts/workflow --namespace drycc -f values.yaml</code> using your desired registry.</p> +<h2 id="examples">Examples<a class="td-heading-self-link" href="#examples" aria-label="Heading self-link"></a></h2> +<p>Here we show how the relevant parts of the fetched <code>values.yaml</code> file might look like after configuring for a particular off-cluster registry:</p> +<h3 id="azure-container-registryhttpsazuremicrosoftcomen-usservicescontainer-registry-acr"><a href="https://azure.microsoft.com/en-us/services/container-registry/">Azure Container Registry</a> (ACR)<a class="td-heading-self-link" href="#azure-container-registryhttpsazuremicrosoftcomen-usservicescontainer-registry-acr" aria-label="Heading self-link"></a></h3> +<p>After following the <a href="https://docs.microsoft.com/en-us/azure/container-registry/container-registry-get-started-azure-cli">docs</a> and creating a registry, e.g. <code>myregistry</code>, with its corresponding login server of <code>myregistry.azurecr.io</code>, the following values should be supplied:</p> +<pre tabindex="0"><code>global: +... + registryLocation: &#34;off-cluster&#34; +... +registry-token-refresher: +... + registry: + hostname: &#34;myregistry.azurecr.io&#34; + organization: &#34;myorg&#34; + username: &#34;myusername&#34; + password: &#34;mypassword&#34; +... +</code></pre><p><strong>Note:</strong> The mandatory organization field (here <code>myorg</code>) will be created as an ACR repository if it does not already exist.</p> +<h3 id="quayio">Quay.io<a class="td-heading-self-link" href="#quayio" aria-label="Heading self-link"></a></h3> +<pre tabindex="0"><code>global: +... + registryLocation: &#34;off-cluster&#34; +... +registry-token-refresher: +... + registry: + hostname: &#34;quay.io&#34; + organization: &#34;myorg&#34; + username: &#34;myusername&#34; + password: &#34;mypassword&#34; +... +</code></pre> + + + + + Docs: Controller API v2.2 + /docs/reference-guide/controller-api-v2-2/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/reference-guide/controller-api-v2-2/ + + + + <h2 id="whats-new">What&rsquo;s New<a class="td-heading-self-link" href="#whats-new" aria-label="Heading self-link"></a></h2> +<p><strong>New!</strong> <code>/v2/auth/whoami</code> endpoint</p> +<h2 id="authentication">Authentication<a class="td-heading-self-link" href="#authentication" aria-label="Heading self-link"></a></h2> +<h3 id="register-a-new-user">Register a New User<a class="td-heading-self-link" href="#register-a-new-user" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/register/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json + +{ + &#34;username&#34;: &#34;test&#34;, + &#34;password&#34;: &#34;opensesame&#34;, + &#34;email&#34;: &#34;test@example.com&#34; +} +</code></pre><p>Optional Parameters:</p> +<pre tabindex="0"><code>{ + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;id&#34;: 1, + &#34;last_login&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;is_superuser&#34;: true, + &#34;username&#34;: &#34;test&#34;, + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34;, + &#34;email&#34;: &#34;test@example.com&#34;, + &#34;is_staff&#34;: true, + &#34;is_active&#34;: true, + &#34;date_joined&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;groups&#34;: [], + &#34;user_permissions&#34;: [] +} +</code></pre><h3 id="log-in">Log in<a class="td-heading-self-link" href="#log-in" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/login/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json + +{&#34;username&#34;: &#34;test&#34;, &#34;password&#34;: &#34;opensesame&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{&#34;token&#34;: &#34;abc123&#34;} +</code></pre><h3 id="cancel-account">Cancel Account<a class="td-heading-self-link" href="#cancel-account" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/auth/cancel/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h3 id="who-am-i">Who Am I<a class="td-heading-self-link" href="#who-am-i" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/auth/whoami/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;id&#34;: 1, + &#34;last_login&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;is_superuser&#34;: true, + &#34;username&#34;: &#34;test&#34;, + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34;, + &#34;email&#34;: &#34;test@example.com&#34;, + &#34;is_staff&#34;: true, + &#34;is_active&#34;: true, + &#34;date_joined&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;groups&#34;: [], + &#34;user_permissions&#34;: [] +} +</code></pre><h3 id="regenerate-token">Regenerate Token<a class="td-heading-self-link" href="#regenerate-token" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command could require administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/tokens/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Optional Parameters:</p> +<pre tabindex="0"><code>{ + &#34;username&#34; : &#34;test&#34; + &#34;all&#34; : &#34;true&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{&#34;token&#34;: &#34;abc123&#34;} +</code></pre><h3 id="change-password">Change Password<a class="td-heading-self-link" href="#change-password" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/passwd/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{ + &#34;password&#34;: &#34;foo&#34;, + &#34;new_password&#34;: &#34;bar&#34; +} +</code></pre><p>Optional parameters:</p> +<pre tabindex="0"><code>{&#34;username&#34;: &#34;testuser&#34;} +</code></pre><blockquote> +<p><strong>note</strong></p> +<p>Using the <code>username</code> parameter requires administrative privileges and makes the <code>password</code> parameter optional.</p> +</blockquote> +<p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h2 id="applications">Applications<a class="td-heading-self-link" href="#applications" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-applications">List all Applications<a class="td-heading-self-link" href="#list-all-applications" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;structure&#34;: {}, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;url&#34;: &#34;example-go.example.com&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; + } + ] +} +</code></pre><h3 id="create-an-application">Create an Application<a class="td-heading-self-link" href="#create-an-application" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 +</code></pre><p>Optional parameters:</p> +<pre tabindex="0"><code>{&#34;id&#34;: &#34;example-go&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;structure&#34;: {}, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;url&#34;: &#34;example-go.example.com&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="destroy-an-application">Destroy an Application<a class="td-heading-self-link" href="#destroy-an-application" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/apps/example-go/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h3 id="list-application-details">List Application Details<a class="td-heading-self-link" href="#list-application-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;structure&#34;: {}, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;url&#34;: &#34;example-go.example.com&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="update-application-details">Update Application Details<a class="td-heading-self-link" href="#update-application-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Optional parameters:</p> +<pre tabindex="0"><code>{ + &#34;owner&#34;: &#34;test&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 1.8.0 +Content-Type: application/json +</code></pre><h3 id="retrieve-application-logs">Retrieve Application Logs<a class="td-heading-self-link" href="#retrieve-application-logs" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/logs/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Optional URL Query Parameters:</p> +<pre tabindex="0"><code>?log_lines= +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: text/plain + +&#34;16:51:14 drycc[api]: test created initial release\n&#34; +</code></pre><h3 id="run-one-off-commands">Run one-off Commands<a class="td-heading-self-link" href="#run-one-off-commands" aria-label="Heading self-link"></a></h3> +<pre tabindex="0"><code>POST /v2/apps/example-go/run/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;command&#34;: &#34;echo hi&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{&#34;exit_code&#34;: 0, &#34;output&#34;: &#34;hi\n&#34;} +</code></pre><h2 id="certificates">Certificates<a class="td-heading-self-link" href="#certificates" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-certificates">List all Certificates<a class="td-heading-self-link" href="#list-all-certificates" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/certs HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;id&#34;: 22, + &#34;owner&#34;: &#34;test&#34;, + &#34;san&#34;: [], + &#34;domains&#34;: [], + &#34;created&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;updated&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;name&#34;: &#34;foo&#34;, + &#34;common_name&#34;: &#34;bar.com&#34;, + &#34;fingerprint&#34;: &#34;7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0&#34;, + &#34;expires&#34;: &#34;2017-01-14T23:57:57Z&#34;, + &#34;starts&#34;: &#34;2016-01-15T23:57:57Z&#34;, + &#34;issuer&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34;, + &#34;subject&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34; + } + ] +} +</code></pre><h3 id="get-certificate-details">Get Certificate Details<a class="td-heading-self-link" href="#get-certificate-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/certs/foo HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;id&#34;: 22, + &#34;owner&#34;: &#34;test&#34;, + &#34;san&#34;: [], + &#34;domains&#34;: [], + &#34;created&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;updated&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;name&#34;: &#34;foo&#34;, + &#34;common_name&#34;: &#34;bar.com&#34;, + &#34;fingerprint&#34;: &#34;7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0&#34;, + &#34;expires&#34;: &#34;2017-01-14T23:57:57Z&#34;, + &#34;starts&#34;: &#34;2016-01-15T23:57:57Z&#34;, + &#34;issuer&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34;, + &#34;subject&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34; +} +</code></pre><h3 id="create-certificate">Create Certificate<a class="td-heading-self-link" href="#create-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/certs/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{ + &#34;name&#34;: &#34;foo&#34; + &#34;certificate&#34;: &#34;-----BEGIN CERTIFICATE-----&#34;, + &#34;key&#34;: &#34;-----BEGIN RSA PRIVATE KEY-----&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;id&#34;: 22, + &#34;owner&#34;: &#34;test&#34;, + &#34;san&#34;: [], + &#34;domains&#34;: [], + &#34;created&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;updated&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;name&#34;: &#34;foo&#34;, + &#34;common_name&#34;: &#34;bar.com&#34;, + &#34;fingerprint&#34;: &#34;7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0&#34;, + &#34;expires&#34;: &#34;2017-01-14T23:57:57Z&#34;, + &#34;starts&#34;: &#34;2016-01-15T23:57:57Z&#34;, + &#34;issuer&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34;, + &#34;subject&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34; +} +</code></pre><h3 id="destroy-a-certificate">Destroy a Certificate<a class="td-heading-self-link" href="#destroy-a-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/certs/foo HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h3 id="attach-a-domain-to-a-certificate">Attach a Domain to a Certificate<a class="td-heading-self-link" href="#attach-a-domain-to-a-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/certs/foo/domain/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{ + &#34;domain&#34;: &#34;test.com&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h3 id="remove-a-domain-from-a-certificate">Remove a Domain from a Certificate<a class="td-heading-self-link" href="#remove-a-domain-from-a-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/certs/foo/domain/test.com/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h2 id="pods">Pods<a class="td-heading-self-link" href="#pods" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-pods">List all Pods<a class="td-heading-self-link" href="#list-all-pods" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/pods/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;results&#34;: [ + { + &#34;name&#34;: &#34;go-v2-web-e7dej&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2014-01-01T00:00:00Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } + ] +} +</code></pre><h3 id="list-all-pods-by-type">List all Pods by Type<a class="td-heading-self-link" href="#list-all-pods-by-type" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/pods/web/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;results&#34;: [ + { + &#34;name&#34;: &#34;go-v2-web-e7dej&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2014-01-01T00:00:00Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } + ] +} +</code></pre><h3 id="restart-all-pods">Restart All Pods<a class="td-heading-self-link" href="#restart-all-pods" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/pods/restart/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +[ + { + &#34;name&#34;: &#34;go-v2-web-atots&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2016-04-11T21:07:54Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } +] +</code></pre><h3 id="restart-pods-by-type">Restart Pods by Type<a class="td-heading-self-link" href="#restart-pods-by-type" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/pods/web/restart/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +[ + { + &#34;name&#34;: &#34;go-v2-web-atots&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2016-04-11T21:07:54Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } +] +</code></pre><h3 id="restart-pods-by-type-and-name">Restart Pods by Type and Name<a class="td-heading-self-link" href="#restart-pods-by-type-and-name" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/pods/go-v2-web-atots/restart/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +[ + { + &#34;name&#34;: &#34;go-v2-web-atots&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2016-04-11T21:07:54Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } +] +</code></pre><h3 id="scale-pods">Scale Pods<a class="td-heading-self-link" href="#scale-pods" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/scale/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;web&#34;: 3} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h2 id="configuration">Configuration<a class="td-heading-self-link" href="#configuration" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-configuration">List Application Configuration<a class="td-heading-self-link" href="#list-application-configuration" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/config/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;owner&#34;: &#34;test&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;values&#34;: { + &#34;PLATFORM&#34;: &#34;drycc&#34; + }, + &#34;memory&#34;: {}, + &#34;cpu&#34;: {}, + &#34;tags&#34;: {}, + &#34;healthcheck&#34;: {}, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="create-new-config">Create new Config<a class="td-heading-self-link" href="#create-new-config" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/config/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;values&#34;: {&#34;HELLO&#34;: &#34;world&#34;, &#34;PLATFORM&#34;: &#34;drycc&#34;}} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;owner&#34;: &#34;test&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;values&#34;: { + &#34;DRYCC_APP&#34;: &#34;example-go&#34;, + &#34;DRYCC_RELEASE&#34;: &#34;v3&#34;, + &#34;HELLO&#34;: &#34;world&#34;, + &#34;PLATFORM&#34;: &#34;drycc&#34; + + }, + &#34;memory&#34;: {}, + &#34;cpu&#34;: {}, + &#34;tags&#34;: {}, + &#34;healthcheck&#34;: {}, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="unset-config-variable">Unset Config Variable<a class="td-heading-self-link" href="#unset-config-variable" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/config/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;values&#34;: {&#34;HELLO&#34;: null}} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;owner&#34;: &#34;test&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;values&#34;: { + &#34;DRYCC_APP&#34;: &#34;example-go&#34;, + &#34;DRYCC_RELEASE&#34;: &#34;v4&#34;, + &#34;PLATFORM&#34;: &#34;drycc&#34; + }, + &#34;memory&#34;: {}, + &#34;cpu&#34;: {}, + &#34;tags&#34;: {}, + &#34;healthcheck&#34;: {}, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h2 id="domains">Domains<a class="td-heading-self-link" href="#domains" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-domains">List Application Domains<a class="td-heading-self-link" href="#list-application-domains" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/domains/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;domain&#34;: &#34;example.example.com&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34; + } + ] +} +</code></pre><h3 id="add-domain">Add Domain<a class="td-heading-self-link" href="#add-domain" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/domains/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{&#39;domain&#39;: &#39;example.example.com&#39;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;domain&#34;: &#34;example.example.com&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34; +} +</code></pre><h3 id="remove-domain">Remove Domain<a class="td-heading-self-link" href="#remove-domain" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/apps/example-go/domains/example.example.com HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h2 id="builds">Builds<a class="td-heading-self-link" href="#builds" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-builds">List Application Builds<a class="td-heading-self-link" href="#list-application-builds" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/build/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;dockerfile&#34;: &#34;FROM drycc/slugrunner RUN mkdir -p /app WORKDIR /app ENTRYPOINT [\&#34;/runner/init\&#34;] ADD slug.tgz /app ENV GIT_SHA 060da68f654e75fac06dbedd1995d5f8ad9084db&#34;, + &#34;image&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;procfile&#34;: { + &#34;web&#34;: &#34;example-go&#34; + }, + &#34;sha&#34;: &#34;060da68f&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="create-application-build">Create Application Build<a class="td-heading-self-link" href="#create-application-build" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/build/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;image&#34;: &#34;drycc/example-go:latest&#34;} +</code></pre><p>Optional Parameters:</p> +<pre tabindex="0"><code>{ + &#34;procfile&#34;: { + &#34;web&#34;: &#34;./cmd&#34; + } +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;dockerfile&#34;: &#34;&#34;, + &#34;image&#34;: &#34;drycc/example-go:latest&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;procfile&#34;: {}, + &#34;sha&#34;: &#34;&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h2 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-releases">List Application Releases<a class="td-heading-self-link" href="#list-application-releases" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/releases/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;count&#34;: 3, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: &#34;202d8e4b-600e-4425-a85c-ffc7ea607f61&#34;, + &#34;config&#34;: &#34;ed637ceb-5d32-44bd-9406-d326a777a513&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test changed nothing&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 3 + }, + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: &#34;202d8e4b-600e-4425-a85c-ffc7ea607f61&#34;, + &#34;config&#34;: &#34;95bd6dea-1685-4f78-a03d-fd7270b058d1&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test deployed 060da68&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 2 + }, + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: null, + &#34;config&#34;: &#34;95bd6dea-1685-4f78-a03d-fd7270b058d1&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test created initial release&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 1 + } + ] +} +</code></pre><h3 id="list-release-details">List Release Details<a class="td-heading-self-link" href="#list-release-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/releases/v2/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: null, + &#34;config&#34;: &#34;95bd6dea-1685-4f78-a03d-fd7270b058d1&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test created initial release&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 1 +} +</code></pre><h3 id="rollback-release">Rollback Release<a class="td-heading-self-link" href="#rollback-release" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/releases/rollback/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;version&#34;: 1} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{&#34;version&#34;: 5} +</code></pre><h2 id="keys">Keys<a class="td-heading-self-link" href="#keys" aria-label="Heading self-link"></a></h2> +<h3 id="list-keys">List Keys<a class="td-heading-self-link" href="#list-keys" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/keys/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;test@example.com&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;public&#34;: &#34;ssh-rsa &lt;...&gt;&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; + } + ] +} +</code></pre><h3 id="add-key-to-user">Add Key to User<a class="td-heading-self-link" href="#add-key-to-user" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/keys/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{ + &#34;id&#34;: &#34;example&#34;, + &#34;public&#34;: &#34;ssh-rsa &lt;...&gt;&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example&#34;, + &#34;owner&#34;: &#34;example&#34;, + &#34;public&#34;: &#34;ssh-rsa &lt;...&gt;&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="remove-key-from-user">Remove Key from User<a class="td-heading-self-link" href="#remove-key-from-user" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/keys/example HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h2 id="permissions">Permissions<a class="td-heading-self-link" href="#permissions" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-permissions">List Application Permissions<a class="td-heading-self-link" href="#list-application-permissions" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This does not include the app owner.</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/perms/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;users&#34;: [ + &#34;test&#34;, + &#34;foo&#34; + ] +} +</code></pre><h3 id="create-application-permission">Create Application Permission<a class="td-heading-self-link" href="#create-application-permission" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/perms/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{&#34;username&#34;: &#34;example&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h3 id="remove-application-permission">Remove Application Permission<a class="td-heading-self-link" href="#remove-application-permission" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/apps/example-go/perms/example HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h3 id="list-administrators">List Administrators<a class="td-heading-self-link" href="#list-administrators" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/admin/perms/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;count&#34;: 2, + &#34;next&#34;: null + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;username&#34;: &#34;test&#34;, + &#34;is_superuser&#34;: true + }, + { + &#34;username&#34;: &#34;foo&#34;, + &#34;is_superuser&#34;: true + } + ] +} +</code></pre><h3 id="grant-user-administrative-privileges">Grant User Administrative Privileges<a class="td-heading-self-link" href="#grant-user-administrative-privileges" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command requires administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/admin/perms HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{&#34;username&#34;: &#34;example&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h3 id="remove-users-administrative-privileges">Remove User&rsquo;s Administrative Privileges<a class="td-heading-self-link" href="#remove-users-administrative-privileges" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command requires administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/admin/perms/example HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h2 id="users">Users<a class="td-heading-self-link" href="#users" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-users">List all users<a class="td-heading-self-link" href="#list-all-users" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command requires administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/users HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;id&#34;: 1, + &#34;last_login&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;is_superuser&#34;: true, + &#34;username&#34;: &#34;test&#34;, + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34;, + &#34;email&#34;: &#34;test@example.com&#34;, + &#34;is_staff&#34;: true, + &#34;is_active&#34;: true, + &#34;date_joined&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;groups&#34;: [], + &#34;user_permissions&#34;: [] + } + ] +} +</code></pre> + + + + + Docs: Managing Application Processes + /docs/applications/managing-app-processes/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/applications/managing-app-processes/ + + + + <p>Drycc Workflow manages your application as a set of processes that can be named, scaled and configured according to their +role. This gives you the flexibility to easily manage the different facets of your application. For example, you may have +web-facing processes that handle HTTP traffic, background worker processes that do async work, and a helper process that +streams from the Twitter API.</p> +<p>By using a Procfile, either checked in to your application or provided via the CLI you can specify the name of the type +and the application command that should run. To spawn other process types, use <code>drycc scale &lt;ptype&gt;=&lt;n&gt;</code> to scale those +types accordingly.</p> +<h2 id="default-process-types">Default Process Types<a class="td-heading-self-link" href="#default-process-types" aria-label="Heading self-link"></a></h2> +<p>In the absence of a Procfile, a single, default process type is assumed for each application.</p> +<p>Applications built using <a href="/docs/applications/using-buildpacks/">Buildpacks</a> via <code>git push</code> implicitly receive a <code>web</code> process type, which starts +the application server. Rails 4, for example, has the following process type:</p> +<pre><code>web: bundle exec rails server -p $PORT +</code></pre> +<p>All applications utilizing <a href="/docs/applications/using-dockerfiles/">Dockerfiles</a> have an implied <code>web</code> process type, which runs the +Dockerfile&rsquo;s <code>CMD</code> directive unmodified:</p> +<pre><code>$ cat Dockerfile +FROM centos:latest +COPY . /app +WORKDIR /app +CMD python -m SimpleHTTPServer 5000 +EXPOSE 5000 +</code></pre> +<p>For the above Dockerfile-based application, the <code>web</code> process type would run the Container <code>CMD</code> of <code>python -m SimpleHTTPServer 5000</code>.</p> +<p>Applications utilizing <a href="/docs/applications/using-container-images/">remote Container images</a>, a <code>web</code> process type is also implied, and runs the <code>CMD</code> +specified in the Container image.</p> +<p>!!! note +The <code>web</code> process type is special as they’is the default process type that will +receive HTTP traffic from Workflow’s routers. Other process types can be named arbitrarily.</p> +<h2 id="declaring-process-types">Declaring Process Types<a class="td-heading-self-link" href="#declaring-process-types" aria-label="Heading self-link"></a></h2> +<p>If you use <a href="/docs/applications/using-buildpacks/">Buildpack</a> or <a href="/docs/applications/using-dockerfiles/">Dockerfile</a> builds and want to override or specify additional process +types, simply include a file named <code>Procfile</code> in the root of your application&rsquo;s source tree.</p> +<p>The format of a <code>Procfile</code> is one process type per line, with each line containing the command to invoke:</p> +<pre><code>&lt;process type&gt;: &lt;command&gt; +</code></pre> +<p>The syntax is defined as:</p> +<ul> +<li><code>&lt;process type&gt;</code> – a lowercase alphanumeric string, is a name for your command, such as web, worker, urgentworker, clock, etc.</li> +<li><code>&lt;command&gt;</code> – a command line to launch the process, such as <code>rake jobs:work</code>.</li> +</ul> +<p>This example Procfile specifies two types, <code>web</code> and <code>sleeper</code>. The <code>web</code> process launches a web server on port 5000 and +a simple process which sleeps for 900 seconds and exits.</p> +<pre tabindex="0"><code>$ cat Procfile +web: bundle exec ruby web.rb -p ${PORT:-5000} +sleeper: sleep 900 +</code></pre><p>If you are using <a href="/docs/applications/using-container-images/">remote Container images</a>, you may define process types by either running <code>drycc pull</code> with a +<code>Procfile</code> in your working directory, or by passing a stringified Procfile to the <code>--procfile</code> CLI option.</p> +<p>For example, passing process types inline:</p> +<pre tabindex="0"><code>$ drycc pull drycc/example-go:latest --procfile=&#34;web: /app/bin/boot&#34; +</code></pre><p>Read a <code>Procfile</code> in another directory:</p> +<pre tabindex="0"><code>$ drycc pull drycc/example-go:latest --procfile=&#34;$(cat deploy/Procfile)&#34; +</code></pre><p>Or via a Procfile located in your current, working directory:</p> +<pre tabindex="0"><code>$ cat Procfile +web: /bin/boot +sleeper: echo &#34;sleeping&#34;; sleep 900 + + +$ drycc pull -a steely-mainsail drycc/example-go +Creating build... done + +$ drycc scale sleeper=1 -a steely-mainsail +Scaling processes... but first, coffee! +done in 0s + +NAME RELEASE STATE PTYPE READY RESTARTS STARTED +steely-mainsail-sleeper-76c45b967c-4qm6w v3 up sleeper 1/1 0 2023-12-08T02:25:00UTC +steely-mainsail-web-c4f44c4b4-7p7dh v3 up web 1/1 0 2023-12-08T02:25:00UTC +</code></pre><p>!!! note +Only process types of <code>web</code> will be scaled to 1 automatically. If you have additional process types +remember to scale the process counts after creation.</p> +<p>To remove a process type simply scale it to 0:</p> +<pre tabindex="0"><code>$ drycc scale sleeper=0 -a steely-mainsail +Scaling processes... but first, coffee! +done in 3s + +NAME RELEASE STATE PTYPE READY RESTARTS STARTED +steely-mainsail-web-c4f44c4b4-7p7dh v3 up web 1/1 0 2023-12-08T02:25:00UTC +</code></pre><h2 id="scaling-processes">Scaling Processes<a class="td-heading-self-link" href="#scaling-processes" aria-label="Heading self-link"></a></h2> +<p>Applications deployed on Drycc Workflow scale out via the <a href="https://devcenter.heroku.com/articles/process-model">process model</a>. Use <code>drycc scale</code> to control the number of +<a href="../reference-guide/terms.md#container">containers</a> that power your app.</p> +<pre tabindex="0"><code>$ drycc scale web=5 -a iciest-waggoner +Scaling processes... but first, coffee! +done in 3s + +NAME RELEASE STATE PTYPE READY RESTARTS STARTED +iciest-waggoner-web-c4f44c4b4-7p7dh v3 up web 1/1 0 2023-12-08T02:25:00UTC +iciest-waggoner-web-c4f44c4b4-8p7dh v3 up web 1/1 0 2023-12-08T02:25:00UTC +iciest-waggoner-web-c4f44c4b4-9p7dh v3 up web 1/1 0 2023-12-08T02:25:00UTC +iciest-waggoner-web-c4f44c4b4-1p7dh v3 up web 1/1 0 2023-12-08T02:25:00UTC +iciest-waggoner-web-c4f44c4b4-2p7dh v3 up web 1/1 0 2023-12-08T02:25:00UTC +</code></pre><p>If you have multiple process types for your application you may scale the process count for each type separately. For +example, this allows you to manage web process independently from background workers. For more information on process +types see our documentation for <a href="/docs/applications/managing-app-processes/">Managing App Processes</a>.</p> +<p>In this example, we are scaling the process type <code>web</code> to 5 but leaving the process type <code>background</code> with one worker.</p> +<pre tabindex="0"><code>$ drycc scale web=5 +Scaling processes... but first, coffee! +done in 4s + +NAME RELEASE STATE PTYPE READY RESTARTS STARTED +scenic-icehouse-web-3291896318-7lord v3 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-web-3291896318-jn957 v3 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-web-3291896318-rsekj v3 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-web-3291896318-vwhnh v3 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-web-3291896318-vokg7 v3 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-web-3291896318-vokg7 v3 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-background-3291896318-yf8kh v3 up web 1/1 0 2023-12-08T02:25:00UTC +</code></pre><p>Scaling a process down, by reducing the process count, sends a <code>TERM</code> signal to the processes, followed by a <code>SIGKILL</code> +if they have not exited within 30 seconds. Depending on your application, scaling down may interrupt long-running HTTP +client connections.</p> +<p>For example, scaling from 5 processes to 3:</p> +<pre tabindex="0"><code>$ drycc scale web=3 +Scaling processes... but first, coffee! +done in 1s + +NAME RELEASE STATE PTYPE READY RESTARTS STARTED +scenic-icehouse-web-3291896318-vwhnh v2 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-web-3291896318-vokg7 v2 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-web-3291896318-vokg9 v2 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-background-3291896318-yf8kh v2 up web 1/1 0 2023-12-08T02:25:00UTC +</code></pre><h2 id="autoscale">Autoscale<a class="td-heading-self-link" href="#autoscale" aria-label="Heading self-link"></a></h2> +<p>Autoscale allows adding a minimum and maximum number of pods on a per process type basis. This is accomplished by specifying a target CPU usage across all available pods.</p> +<p>This feature is built on top of <a href="https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/">Horizontal Pod Autoscaling</a> in Kubernetes or <a href="https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/">HPA</a> for short.</p> +<p>!!! note +This is an alpha feature. It is recommended to be on the latest Kubernetes when using this feature.</p> +<pre tabindex="0"><code>$ drycc autoscale:set web --min=3 --max=8 --cpu-percent=75 +Applying autoscale settings for process type web on scenic-icehouse... done +</code></pre><p>And then review the scaling rule that was created for <code>web</code></p> +<pre tabindex="0"><code>$ drycc autoscale:list +PTYPE PERCENT MIN MAX +web 75 3 8 +</code></pre><p>Remove scaling rule</p> +<pre tabindex="0"><code>$ drycc autoscale:unset web +Removing autoscale for process type web on scenic-icehouse... done +</code></pre><p>For autoscaling to work CPU requests have to be specified on each application Pod (can be done via <code>drycc limits --cpu</code>). This allows the autoscale policies to do the <a href="https://github.com/kubernetes/community/blob/master/contributors/design-proposals/horizontal-pod-autoscaler.md#autoscaling-algorithm">appropriate calculations</a> and make decisions on when to scale up and down.</p> +<p>Scale up can only happen if there was no rescaling within the last 3 minutes. Scale down will wait for 5 minutes from the last rescaling. That information and more can be found at <a href="https://github.com/kubernetes/community/blob/master/contributors/design-proposals/horizontal-pod-autoscaler.md#autoscaling-algorithm">HPA algorithm page</a>.</p> +<h2 id="fetch-a-container-logs-of-the-application">Fetch a container logs of the application<a class="td-heading-self-link" href="#fetch-a-container-logs-of-the-application" aria-label="Heading self-link"></a></h2> +<p>List the containers:</p> +<pre tabindex="0"><code>$ drycc ps +NAME RELEASE STATE PTYPEE READY RESTARTS STARTED +python-getting-started-web-69b7d4bfdc-kl4xf v2 up web 1/1 0 2023-12-08T02:25:00UTC + +=== python-getting-started Processes +--- web: +python-getting-started-web-69b7d4bfdc-kl4xf up (v2) +</code></pre><p>fetch the container logs:</p> +<pre tabindex="0"><code>$ drycc ps:logs -f python-getting-started-web-69b7d4bfdc-kl4xf +[2024-05-24 07:14:39 +0000] [1] [INFO] Starting gunicorn 20.1.0 +[2024-05-24 07:14:39 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1) +[2024-05-24 07:14:39 +0000] [1] [INFO] Using worker: gevent +[2024-05-24 07:14:39 +0000] [8] [INFO] Booting worker with pid: 8 +[2024-05-24 07:14:39 +0000] [9] [INFO] Booting worker with pid: 9 +[2024-05-24 07:14:39 +0000] [10] [INFO] Booting worker with pid: 10 +[2024-05-24 07:14:39 +0000] [11] [INFO] Booting worker with pid: 11 +</code></pre><h2 id="get-a-container-info-of-the-application">Get a container info of the application<a class="td-heading-self-link" href="#get-a-container-info-of-the-application" aria-label="Heading self-link"></a></h2> +<p>List the containers:</p> +<pre tabindex="0"><code>$ drycc ps:describe python-getting-started-web-69b7d4bfdc-kl4xf +Container: python-getting-started-web +Image: drycc/python-getting-started:latest +Command: +Args: + - gunicorn + - -c + - gunicorn_config.py + - helloworld.wsgi:application +State: running + startedAt: &#34;2024-05-24T07:14:39Z&#34; +Ready: true +Restart Count: 0 +</code></pre><h2 id="delete-a-container-of-the-application">delete a container of the application<a class="td-heading-self-link" href="#delete-a-container-of-the-application" aria-label="Heading self-link"></a></h2> +<p>Delete the containers. +Due to the set number of replicas, a new container will be launched to meet the quantity requirement.</p> +<pre tabindex="0"><code>$ drycc ps:delete python-getting-started-web-69b7d4bfdc-kl4xf +Deleting python-getting-started-web-69b7d4bfdc-kl4xf from python-getting-started... done +</code></pre><h2 id="get-a-shell-to-a-running-container">Get a Shell to a Running Container<a class="td-heading-self-link" href="#get-a-shell-to-a-running-container" aria-label="Heading self-link"></a></h2> +<p>Verify that the container is running:</p> +<pre tabindex="0"><code>$ drycc ps +NAME RELEASE STATE PTYPEE READY RESTARTS STARTED +python-getting-started-web-69b7d4bfdc-kl4xf v2 up web 1/1 0 2023-12-08T02:25:00UTC + +=== python-getting-started Processes +--- web: +python-getting-started-web-69b7d4bfdc-kl4xf up (v2) +</code></pre><p>Get a shell to the running container:</p> +<pre tabindex="0"><code>$ drycc ps:exec python-getting-started-web-69b7d4bfdc-kl4xf -it -- bash +</code></pre><p>In your shell, list the root directory:</p> +<pre tabindex="0"><code># Run this inside the container +ls / +</code></pre><p>Running individual commands in a container</p> +<pre tabindex="0"><code>$ drycc ps:exec python-getting-started-web-69b7d4bfdc-kl4xf -- date +</code></pre><p>Use &ldquo;drycc ps &ndash;help&rdquo; for a list of global command-line (applies to all commands).</p> +<h2 id="restarting-an-application-processes">Restarting an Application Processes<a class="td-heading-self-link" href="#restarting-an-application-processes" aria-label="Heading self-link"></a></h2> +<p>If you need to restart an application process, you may use <code>drycc pts:restart</code>. Behind the scenes, Drycc Workflow instructs +Kubernetes to terminate the old process and launch a new one in its place.</p> +<pre tabindex="0"><code>$ drycc ps +NAME RELEASE STATE PTYPE READY RESTARTS STARTED +scenic-icehouse-web-3291896318-vokg7 v2 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-web-3291896318-rsekj v2 up web 1/1 0 2023-12-08T02:50:21UTC +scenic-icehouse-web-3291896318-vokg7 v2 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-background-3291896318-yf8kh v2 up web 1/1 0 2023-12-08T02:25:00UTC + +$ drycc pts:restart scenic-icehouse-background +NAME RELEASE STATE PTYPE READY RESTARTS STARTED +scenic-icehouse-web-3291896318-vokg7 v2 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-web-3291896318-rsekj v2 up web 1/1 0 2023-12-08T02:50:21UTC +scenic-icehouse-web-3291896318-vokg7 v2 up web 1/1 0 2023-12-08T02:25:00UTC +scenic-icehouse-background-3291896318-yf8kh v2 starting web 1/1 0 2023-12-08T02:25:00UTC +</code></pre><p>Notice that the process name has changed from <code>scenic-icehouse-background-3291896318-yf8kh</code> to +<code>scenic-icehouse-background-3291896318-yd87g</code>. In a multi-node Kubernetes cluster, this may also have the effect of scheduling +the Pod to a new node.</p> +<p>Use &ldquo;drycc pts &ndash;help&rdquo; for a list of pts command-line (process types info).</p> +<h2 id="list-an-application-process-types">List an Application Process Types<a class="td-heading-self-link" href="#list-an-application-process-types" aria-label="Heading self-link"></a></h2> +<pre tabindex="0"><code>$ drycc pts +NAME RELEASE READY UP-TO-DATE AVAILABLE STARTED +web v2 3/3 1 1 2023-12-08T02:25:00UTC +background v2 1/1 1 1 2023-12-08T02:25:00UTC +</code></pre><h2 id="get-deployment-info-of-the-application-process-type">Get deployment info of the application process type<a class="td-heading-self-link" href="#get-deployment-info-of-the-application-process-type" aria-label="Heading self-link"></a></h2> +<pre tabindex="0"><code>$ drycc pts:describe web +Container: python-getting-started-web +Image: drycc/python-getting-started:latest +Command: +Args: + - gunicorn + - -c + - gunicorn_config.py + - helloworld.wsgi:application +Limits: + cpu 1 + ephemeral-storage 2Gi + memory 1Gi +Liveness: http-get headers=[] path=/geo/ port=8000 delay=120s timeout=10s period=20s #success=1 #failure=3 +Readiness: http-get headers=[] path=/geo/ port=8000 delay=120s timeout=10s period=20s #success=1 #failure=3 +</code></pre> + + + + + Docs: Platform Monitoring + /docs/managing-workflow/platform-monitoring/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/managing-workflow/platform-monitoring/ + + + + <h2 id="description">Description<a class="td-heading-self-link" href="#description" aria-label="Heading self-link"></a></h2> +<p>We now include a monitoring stack for introspection on a running Kubernetes cluster. The stack includes 4 components:</p> +<ul> +<li><a href="https://github.com/kubernetes/kube-state-metrics">kube-state-metrics</a>, kube-state-metrics (KSM) is a simple service that listens to the Kubernetes API server and generates metrics about the state of the objects.</li> +<li><a href="http://github.com/prometheus/node_exporter">Node Exporter</a>, Prometheus exporter for hardware and OS metrics exposed by *NIX kernels.</li> +<li><a href="https://prometheus.io/">Prometheus</a>, a <a href="https://cncf.io/">Cloud Native Computing Foundation</a> project, is a systems and service monitoring system.</li> +<li><a href="http://grafana.org/">Grafana</a>, Graphing tool for time series data</li> +</ul> +<h2 id="architecture-diagram">Architecture Diagram<a class="td-heading-self-link" href="#architecture-diagram" aria-label="Heading self-link"></a></h2> +<pre tabindex="0"><code>┌────────────────┐ +│ HOST │ +│ node-exporter │◀──┐ ┌──────────────────┐ +└────────────────┘ │ │kube-state-metrics│ + │ └──────────────────┘ +┌────────────────┐ │ ▲ +│ HOST │ │ ┌────────────┐ │ +│ node-exporter │◀──┼────│ Prometheus │─────────────┘ +└────────────────┘ │ └────────────┘ + │ ▲ +┌───────────────┐ │ │ +│ HOST │ │ ▼ +│ node-exporter│◀───┘ ┌──────────┐ +└───────────────┘ │ Grafana │ + └──────────┘ +</code></pre><h2 id="grafanahttpsgrafanacom"><a href="https://grafana.com/">Grafana</a><a class="td-heading-self-link" href="#grafanahttpsgrafanacom" aria-label="Heading self-link"></a></h2> +<p>Grafana allows users to create custom dashboards that visualize the data captured to the running Prometheus component. By default Grafana is exposed using a <a href="https://github.com/drycc/router#how-it-works">service annotation</a> through the router at the following URL: <code>http://grafana.mydomain.com</code>. The default login is <code>admin/admin</code>. If you are interested in changing these values please see [Tuning Component Settings][].</p> +<p>Grafana will preload several dashboards to help operators get started with monitoring Kubernetes and Drycc Workflow. +These dashboards are meant as starting points and don&rsquo;t include every item that might be desirable to monitor in a +production installation.</p> +<p>Drycc Workflow monitoring by default does not write data to the host filesystem or to long-term storage. If the Grafana instance fails, modified dashboards are lost.</p> +<h3 id="production-configuration">Production Configuration<a class="td-heading-self-link" href="#production-configuration" aria-label="Heading self-link"></a></h3> +<p>A production install of Grafana should have the following configuration values changed if possible:</p> +<ul> +<li>Change the default username and password from <code>admin/admin</code>. The value for the password is passed in plain text so it is best to set this value on the command line instead of checking it into version control.</li> +<li>Enable persistence</li> +<li>Use a supported external database such as mysql or postgres. You can find more information <a href="https://github.com/drycc/monitor/blob/main/grafana/rootfs/usr/share/grafana/grafana.ini.tpl#L62">here</a></li> +</ul> +<h3 id="on-cluster-persistence">On Cluster Persistence<a class="td-heading-self-link" href="#on-cluster-persistence" aria-label="Heading self-link"></a></h3> +<p>Enabling persistence will allow your custom configuration to persist across pod restarts. This means that the default sqllite database (which stores things like sessions and user data) will not disappear if you upgrade the Workflow installation.</p> +<p>If you wish to have persistence for Grafana you can set <code>enabled</code> to <code>true</code> in the <code>values.yaml</code> file before running <code>helm install</code>.</p> +<pre tabindex="0"><code> grafana: + # Configure the following ONLY if you want persistence for on-cluster grafana + # GCP PDs and EBS volumes are supported only + persistence: + enabled: true # Set to true to enable persistence + size: 5Gi # PVC size +</code></pre><h3 id="off-cluster-grafana">Off Cluster Grafana<a class="td-heading-self-link" href="#off-cluster-grafana" aria-label="Heading self-link"></a></h3> +<p>If you wish to provide your own Grafana instance you can set <code>grafanaLocation</code> in the <code>values.yaml</code> file before running <code>helm install</code>.</p> +<h2 id="prometheushttpsprometheusio"><a href="https://prometheus.io/">Prometheus</a><a class="td-heading-self-link" href="#prometheushttpsprometheusio" aria-label="Heading self-link"></a></h2> +<p>Prometheus writes data to the host disk; however, if the prometheus pod dies and comes back on another host, the data will not be recovered. The prometheus graph UI is also exposed through the router allowing users to access the query engine by going to <code>prometheus.mydomain.com</code>.</p> +<h3 id="on-cluster-persistence-1">On Cluster Persistence<a class="td-heading-self-link" href="#on-cluster-persistence-1" aria-label="Heading self-link"></a></h3> +<p>You can set <code>node-exporter</code> and <code>kube-state-metrics</code> to <code>true</code> or <code>false</code> in the <code>values.yaml</code>. +If you wish to have persistence for Prometheus you can set <code>enabled</code> to <code>true</code> in the <code>values.yaml</code> file before running <code>helm install</code>.</p> +<pre tabindex="0"><code>prometheus: + prometheus-server: + persistence: + enabled: true # Set to true to enable persistence + size: 10Gi # PVC size +node-exporter: + enabled: true +kube-state-metrics: + enabled: true +</code></pre><h3 id="off-cluster-prometheus">Off Cluster Prometheus<a class="td-heading-self-link" href="#off-cluster-prometheus" aria-label="Heading self-link"></a></h3> +<p>To use off-cluster Prometheus, please provide the following values in the <code>values.yaml</code> file before running <code>helm install</code>.</p> +<ul> +<li><code>global.prometheusLocation=off-cluster</code></li> +<li><code>url = &quot;http://my.prometheus.url:9090&quot;</code></li> +</ul> + + + + + + Docs: Submitting a Pull Request + /docs/contribution-guidelines/submitting-a-pull-request/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/contribution-guidelines/submitting-a-pull-request/ + + + + <h2 id="design-document">Design Document<a class="td-heading-self-link" href="#design-document" aria-label="Heading self-link"></a></h2> +<p>Before opening a pull request, ensure your change also references a design document if the contribution is substantial. For more information, see <a href="/docs/contribution-guidelines/design-documents/">Design Documents</a>.</p> +<h2 id="single-issue">Single Issue<a class="td-heading-self-link" href="#single-issue" aria-label="Heading self-link"></a></h2> +<p>It&rsquo;s hard to reach agreement on the merit of a PR when it isn&rsquo;t focused. When fixing an issue or implementing a new feature, resist the temptation to refactor nearby code or to fix that potential bug you noticed. Instead, open a separate issue or pull request. Keeping concerns separated allows pull requests to be tested, reviewed, and merged more quickly.</p> +<p>Squash and rebase the commit or commits in your pull request into logical units of work with <code>git</code>. Include tests and documentation changes in the same commit, so that a revert would remove all traces of the feature or fix.</p> +<p>Most pull requests will reference a GitHub issue. In the PR description - not in the commit itself - include a line such as &ldquo;closes #1234&rdquo;. The issue referenced will automatically be closed when your PR is merged.</p> +<h2 id="include-tests">Include Tests<a class="td-heading-self-link" href="#include-tests" aria-label="Heading self-link"></a></h2> +<p>If you significantly alter or add functionality to a component that impacts the broader Drycc Workflow PaaS, you should submit a complementary PR to modify or amend end-to-end integration tests. These integration tests can be found in the <a href="https://github.com/drycc/workflow-e2e">drycc/workflow-e2e</a> repository.</p> +<p>See <a href="/docs/contribution-guidelines/testing/">testing</a> for more information.</p> +<h2 id="include-docs">Include Docs<a class="td-heading-self-link" href="#include-docs" aria-label="Heading self-link"></a></h2> +<p>Changes to any Drycc Workflow component that could affect a user&rsquo;s experience also require a change or addition to the relevant documentation. For most Drycc components, this involves updating the component&rsquo;s <em>own</em> documentation. In some cases where a component is tightly integrated into <a href="https://github.com/drycc/workflow">drycc/workflow</a>, its documentation must also be updated.</p> +<h2 id="cross-repo-commits">Cross-repo commits<a class="td-heading-self-link" href="#cross-repo-commits" aria-label="Heading self-link"></a></h2> +<p>If a pull request is part of a larger piece of work involving one or more additional commits in other Workflow repositories, these commits can be referenced in the last PR to be submitted. The downstream <a href="https://ci.drycc.info/job/workflow-e2e-pr/">e2e test job</a> will then supply every referenced commit (derived from PR issue number supplied) to the test runner so it can source the necessary Container images for inclusion in the generated Workflow chart to be tested.</p> +<p>For example, consider paired commits in <a href="https://github.com/drycc/controller">drycc/controller</a> and <a href="https://github.com/drycc/workflow-e2e">drycc/workflow-e2e</a>. The commit body for the first PR in <code>drycc/workflow-e2e</code> would look like:</p> +<pre tabindex="0"><code>feat(foo_test): add e2e test for feature foo + +[skip e2e] test for controller#42 +</code></pre><p>Adding <code>[skip e2e]</code> forgoes the e2e tests on this commit. This and any other required PRs aside from the final PR should be submitted first, so that their respective build and image push jobs run.</p> +<p>Lastly, the final PR in <code>drycc/controller</code> should be created with the required PR number(s) listed, in the form of <code>[Rr]equires &lt;repoName&gt;#&lt;pullRequestNumber&gt;</code>, for use by the downstream e2e run.</p> +<pre tabindex="0"><code>feat(foo): add feature foo + +Requires workflow-e2e#42 +</code></pre><h2 id="code-standards">Code Standards<a class="td-heading-self-link" href="#code-standards" aria-label="Heading self-link"></a></h2> +<p>Drycc components are implemented in <a href="http://golang.org/">Go</a> and <a href="http://www.python.org/">Python</a>. For both languages, we agree with <a href="http://www.python.org/dev/peps/pep-0020/">The Zen of Python</a>, which emphasizes simple over clever. Readability counts.</p> +<p>Go code should always be run through <code>gofmt</code> on the default settings. Lines of code may be up to 99 characters long. Documentation strings and tests are required for all exported functions. Use of third-party go packages should be minimal, but when doing so, such dependencies should be managed via the <a href="https://github.com/Masterminds/glide">glide</a> tool.</p> +<p>Python code should always adhere to <a href="http://www.python.org/dev/peps/pep-0008/">PEP8</a>, the python code style guide, with the exception that lines of code may be up to 99 characters long. Docstrings and tests are required for all public methods, although the <a href="https://pypi.python.org/pypi/flake8/">flake8</a> tool used by Drycc does not enforce this.</p> +<h2 id="commit-style">Commit Style<a class="td-heading-self-link" href="#commit-style" aria-label="Heading self-link"></a></h2> +<p>We follow a convention for commit messages borrowed from CoreOS, who borrowed theirs +from AngularJS. This is an example of a commit:</p> +<pre tabindex="0"><code>feat(scripts/test-cluster): add a cluster test command + +this uses tmux to setup a test cluster that you can easily kill and +start for debugging. +</code></pre><p>To make it more formal, it looks something like this:</p> +<pre tabindex="0"><code>{type}({scope}): {subject} +&lt;BLANK LINE&gt; +{body} +&lt;BLANK LINE&gt; +{footer} +</code></pre><p>The allowed <code>{types}</code> are as follows:</p> +<ul> +<li><code>feat</code> -&gt; feature</li> +<li><code>fix</code> -&gt; bug fix</li> +<li><code>docs</code> -&gt; documentation</li> +<li><code>style</code> -&gt; formatting</li> +<li><code>ref</code> -&gt; refactoring code</li> +<li><code>test</code> -&gt; adding missing tests</li> +<li><code>chore</code> -&gt; maintenance</li> +</ul> +<p>The <code>{scope}</code> can be anything specifying the location(s) of the commit change(s).</p> +<p>The <code>{subject}</code> needs to be an imperative, present tense verb: “change”, not “changed” nor +“changes”. The first letter should not be capitalized, and there is no dot (.) at the end.</p> +<p>Just like the <code>{subject}</code>, the message <code>{body}</code> needs to be in the present tense, and includes +the motivation for the change, as well as a contrast with the previous behavior. The first +letter in a paragraph must be capitalized.</p> +<p>All breaking changes need to be mentioned in the <code>{footer}</code> with the description of the +change, the justification behind the change and any migration notes required.</p> +<p>Any line of the commit message cannot be longer than 72 characters, with the subject line +limited to 50 characters. This allows the message to be easier to read on GitHub as well +as in various git tools.</p> +<h2 id="merge-approval">Merge Approval<a class="td-heading-self-link" href="#merge-approval" aria-label="Heading self-link"></a></h2> +<p>Any code change - other than a simple typo fix or one-line documentation change - requires at least two <a href="/docs/contribution-guidelines/maintainers/">Drycc maintainers</a> to accept it. Maintainers tag pull requests with &ldquo;<strong>LGTM1</strong>&rdquo; and &ldquo;<strong>LGTM2</strong>&rdquo; (Looks Good To Me) labels to indicate acceptance.</p> +<p>No pull requests can be merged until at least one core maintainer signs off with an LGTM. The other LGTM can come from either a core maintainer or contributing maintainer.</p> +<p>If the PR is from a Drycc maintainer, then he or she should be the one to close it. This keeps the commit stream clean and gives the maintainer the benefit of revisiting the PR before deciding whether or not to merge the changes.</p> +<p>An exception to this is when an errant commit needs to be reverted urgently. If necessary, a PR that only reverts a previous commit can be merged without waiting for LGTM approval.</p> + + + + + + Docs: Community + /docs/contribution-guidelines/community/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/contribution-guidelines/community/ + + + + <p>Drycc software is fully open source. As such, the &ldquo;Drycc community&rdquo; consists of anyone who uses the Drycc software and participates in its evolution, whether by answering questions, finding bugs, suggesting enhancements, or writing documentation or code.</p> +<p>Drycc development is coordinated through numerous project repositories <a href="https://github.com/drycc">on GitHub</a>. Anyone can check out the source code for any Drycc component, fork it, make improvements, and create a pull request to offer those changes back to the Drycc community.</p> +<p><a href="https://www.drycc.cc/community">Engine Yard</a> maintains the numerous Drycc projects, and as such, decides what ends up in the official GitHub repositories. Drycc depends on the contributions of the community; the maintainers will not ignore pull requests or issues.</p> +<p>Drycc uses the timeless, highly efficient, and totally unfair system known as &ldquo;Benevolent Dictator for Life&rdquo; (<a href="http://en.wikipedia.org/wiki/Benevolent_Dictator_for_Life">BDFL</a>). <a href="https://github.com/gabrtv">Gabriel Monroy</a>, the creator of Drycc, is our BDFL and has final say over all decisions related to Drycc.</p> +<h2 id="open-source-bounties">Open Source Bounties<a class="td-heading-self-link" href="#open-source-bounties" aria-label="Heading self-link"></a></h2> +<p>Drycc projects are bounty-friendly. We believe open source bounty sites can be constructive tools in the development of open source software. Community members are encouraged to a) offer bounties and b) receive bounties for open source contributions that benefit everyone. The Drycc maintainers, however, will not accept bounties on this project but are more than happy to help community members attempting bounties.</p> + + + + + + Docs: Controller API v2.3 + /docs/reference-guide/controller-api-v2-3/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/reference-guide/controller-api-v2-3/ + + + + <h2 id="whats-new">What&rsquo;s New<a class="td-heading-self-link" href="#whats-new" aria-label="Heading self-link"></a></h2> +<p><strong>New!</strong> <code>/v2/apps/{name}/logs</code> endpoint was fixed and no longer returns <code>b'log data'</code> and instead returns a normal string <code>log data</code></p> +<h2 id="authentication">Authentication<a class="td-heading-self-link" href="#authentication" aria-label="Heading self-link"></a></h2> +<h3 id="register-a-new-user">Register a New User<a class="td-heading-self-link" href="#register-a-new-user" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/register/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json + +{ + &#34;username&#34;: &#34;test&#34;, + &#34;password&#34;: &#34;opensesame&#34;, + &#34;email&#34;: &#34;test@example.com&#34; +} +</code></pre><p>Optional Parameters:</p> +<pre tabindex="0"><code>{ + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;id&#34;: 1, + &#34;last_login&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;is_superuser&#34;: true, + &#34;username&#34;: &#34;test&#34;, + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34;, + &#34;email&#34;: &#34;test@example.com&#34;, + &#34;is_staff&#34;: true, + &#34;is_active&#34;: true, + &#34;date_joined&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;groups&#34;: [], + &#34;user_permissions&#34;: [] +} +</code></pre><h3 id="log-in">Log in<a class="td-heading-self-link" href="#log-in" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/login/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json + +{&#34;username&#34;: &#34;test&#34;, &#34;password&#34;: &#34;opensesame&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{&#34;token&#34;: &#34;abc123&#34;} +</code></pre><h3 id="cancel-account">Cancel Account<a class="td-heading-self-link" href="#cancel-account" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/auth/cancel/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h3 id="who-am-i">Who Am I<a class="td-heading-self-link" href="#who-am-i" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/auth/whoami/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;id&#34;: 1, + &#34;last_login&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;is_superuser&#34;: true, + &#34;username&#34;: &#34;test&#34;, + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34;, + &#34;email&#34;: &#34;test@example.com&#34;, + &#34;is_staff&#34;: true, + &#34;is_active&#34;: true, + &#34;date_joined&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;groups&#34;: [], + &#34;user_permissions&#34;: [] +} +</code></pre><h3 id="regenerate-token">Regenerate Token<a class="td-heading-self-link" href="#regenerate-token" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command could require administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/tokens/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Optional Parameters:</p> +<pre tabindex="0"><code>{ + &#34;username&#34; : &#34;test&#34; + &#34;all&#34; : &#34;true&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{&#34;token&#34;: &#34;abc123&#34;} +</code></pre><h3 id="change-password">Change Password<a class="td-heading-self-link" href="#change-password" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/passwd/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{ + &#34;password&#34;: &#34;foo&#34;, + &#34;new_password&#34;: &#34;bar&#34; +} +</code></pre><p>Optional parameters:</p> +<pre tabindex="0"><code>{&#34;username&#34;: &#34;testuser&#34;} +</code></pre><blockquote> +<p><strong>note</strong></p> +<p>Using the <code>username</code> parameter requires administrative privileges and makes the <code>password</code> parameter optional.</p> +</blockquote> +<p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h2 id="applications">Applications<a class="td-heading-self-link" href="#applications" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-applications">List all Applications<a class="td-heading-self-link" href="#list-all-applications" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;structure&#34;: {}, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;url&#34;: &#34;example-go.example.com&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; + } + ] +} +</code></pre><h3 id="create-an-application">Create an Application<a class="td-heading-self-link" href="#create-an-application" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 +</code></pre><p>Optional parameters:</p> +<pre tabindex="0"><code>{&#34;id&#34;: &#34;example-go&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;structure&#34;: {}, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;url&#34;: &#34;example-go.example.com&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="destroy-an-application">Destroy an Application<a class="td-heading-self-link" href="#destroy-an-application" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/apps/example-go/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h3 id="list-application-details">List Application Details<a class="td-heading-self-link" href="#list-application-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;structure&#34;: {}, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;url&#34;: &#34;example-go.example.com&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="update-application-details">Update Application Details<a class="td-heading-self-link" href="#update-application-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Optional parameters:</p> +<pre tabindex="0"><code>{ + &#34;owner&#34;: &#34;test&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 1.8.0 +Content-Type: application/json +</code></pre><h3 id="retrieve-application-logs">Retrieve Application Logs<a class="td-heading-self-link" href="#retrieve-application-logs" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/logs/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Optional URL Query Parameters:</p> +<pre tabindex="0"><code>?log_lines= +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: text/plain + +&#34;16:51:14 drycc[api]: test created initial release\n&#34; +</code></pre><h3 id="run-one-off-commands">Run one-off Commands<a class="td-heading-self-link" href="#run-one-off-commands" aria-label="Heading self-link"></a></h3> +<pre tabindex="0"><code>POST /v2/apps/example-go/run/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;command&#34;: &#34;echo hi&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{&#34;exit_code&#34;: 0, &#34;output&#34;: &#34;hi\n&#34;} +</code></pre><h2 id="certificates">Certificates<a class="td-heading-self-link" href="#certificates" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-certificates">List all Certificates<a class="td-heading-self-link" href="#list-all-certificates" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/certs HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;id&#34;: 22, + &#34;owner&#34;: &#34;test&#34;, + &#34;san&#34;: [], + &#34;domains&#34;: [], + &#34;created&#34;: &#34;2016-06-22.32.34:20Z&#34;, + &#34;updated&#34;: &#34;2016-06-22.32.34:20Z&#34;, + &#34;name&#34;: &#34;foo&#34;, + &#34;common_name&#34;: &#34;bar.com&#34;, + &#34;fingerprint&#34;: &#34;7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0&#34;, + &#34;expires&#34;: &#34;2017-01-14T23:57:57Z&#34;, + &#34;starts&#34;: &#34;2016-01-15T23:57:57Z&#34;, + &#34;issuer&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34;, + &#34;subject&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34; + } + ] +} +</code></pre><h3 id="get-certificate-details">Get Certificate Details<a class="td-heading-self-link" href="#get-certificate-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/certs/foo HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;id&#34;: 22, + &#34;owner&#34;: &#34;test&#34;, + &#34;san&#34;: [], + &#34;domains&#34;: [], + &#34;created&#34;: &#34;2016-06-22.32.34:20Z&#34;, + &#34;updated&#34;: &#34;2016-06-22.32.34:20Z&#34;, + &#34;name&#34;: &#34;foo&#34;, + &#34;common_name&#34;: &#34;bar.com&#34;, + &#34;fingerprint&#34;: &#34;7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0&#34;, + &#34;expires&#34;: &#34;2017-01-14T23:57:57Z&#34;, + &#34;starts&#34;: &#34;2016-01-15T23:57:57Z&#34;, + &#34;issuer&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34;, + &#34;subject&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34; +} +</code></pre><h3 id="create-certificate">Create Certificate<a class="td-heading-self-link" href="#create-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/certs/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{ + &#34;name&#34;: &#34;foo&#34; + &#34;certificate&#34;: &#34;-----BEGIN CERTIFICATE-----&#34;, + &#34;key&#34;: &#34;-----BEGIN RSA PRIVATE KEY-----&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;id&#34;: 22, + &#34;owner&#34;: &#34;test&#34;, + &#34;san&#34;: [], + &#34;domains&#34;: [], + &#34;created&#34;: &#34;2016-06-22.32.34:20Z&#34;, + &#34;updated&#34;: &#34;2016-06-22.32.34:20Z&#34;, + &#34;name&#34;: &#34;foo&#34;, + &#34;common_name&#34;: &#34;bar.com&#34;, + &#34;fingerprint&#34;: &#34;7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0&#34;, + &#34;expires&#34;: &#34;2017-01-14T23:57:57Z&#34;, + &#34;starts&#34;: &#34;2016-01-15T23:57:57Z&#34;, + &#34;issuer&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34;, + &#34;subject&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34; +} +</code></pre><h3 id="destroy-a-certificate">Destroy a Certificate<a class="td-heading-self-link" href="#destroy-a-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/certs/foo HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h3 id="attach-a-domain-to-a-certificate">Attach a Domain to a Certificate<a class="td-heading-self-link" href="#attach-a-domain-to-a-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/certs/foo/domain/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{ + &#34;domain&#34;: &#34;test.com&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h3 id="remove-a-domain-from-a-certificate">Remove a Domain from a Certificate<a class="td-heading-self-link" href="#remove-a-domain-from-a-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/certs/foo/domain/test.com/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h3 id="enable-or-disable-tls">Enable or disable TLS<a class="td-heading-self-link" href="#enable-or-disable-tls" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/tls/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{ + &#34;https_enforced&#34;: true +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;https_enforced&#34;: true, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="get-tls-status">Get TLS status<a class="td-heading-self-link" href="#get-tls-status" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/tls/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;https_enforced&#34;: false, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h2 id="pods">Pods<a class="td-heading-self-link" href="#pods" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-pods">List all Pods<a class="td-heading-self-link" href="#list-all-pods" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/pods/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;results&#34;: [ + { + &#34;name&#34;: &#34;go-v2-web-e7dej&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2014-01-01T00:00:00Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } + ] +} +</code></pre><h3 id="list-all-pods-by-type">List all Pods by Type<a class="td-heading-self-link" href="#list-all-pods-by-type" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/pods/web/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;results&#34;: [ + { + &#34;name&#34;: &#34;go-v2-web-e7dej&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2014-01-01T00:00:00Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } + ] +} +</code></pre><h3 id="restart-all-pods">Restart All Pods<a class="td-heading-self-link" href="#restart-all-pods" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/pods/restart/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +[ + { + &#34;name&#34;: &#34;go-v2-web-atots&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2016-04-11T21:07:54Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } +] +</code></pre><h3 id="restart-pods-by-type">Restart Pods by Type<a class="td-heading-self-link" href="#restart-pods-by-type" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/pods/web/restart/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +[ + { + &#34;name&#34;: &#34;go-v2-web-atots&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2016-04-11T21:07:54Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } +] +</code></pre><h3 id="restart-pods-by-type-and-name">Restart Pods by Type and Name<a class="td-heading-self-link" href="#restart-pods-by-type-and-name" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/pods/go-v2-web-atots/restart/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +[ + { + &#34;name&#34;: &#34;go-v2-web-atots&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2016-04-11T21:07:54Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } +] +</code></pre><h3 id="scale-pods">Scale Pods<a class="td-heading-self-link" href="#scale-pods" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/scale/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;web&#34;: 3} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h2 id="configuration">Configuration<a class="td-heading-self-link" href="#configuration" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-configuration">List Application Configuration<a class="td-heading-self-link" href="#list-application-configuration" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/config/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;owner&#34;: &#34;test&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;values&#34;: { + &#34;PLATFORM&#34;: &#34;drycc&#34; + }, + &#34;memory&#34;: {}, + &#34;cpu&#34;: {}, + &#34;tags&#34;: {}, + &#34;healthcheck&#34;: {}, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="create-new-config">Create new Config<a class="td-heading-self-link" href="#create-new-config" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/config/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;values&#34;: {&#34;HELLO&#34;: &#34;world&#34;, &#34;PLATFORM&#34;: &#34;drycc&#34;}} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;owner&#34;: &#34;test&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;values&#34;: { + &#34;DRYCC_APP&#34;: &#34;example-go&#34;, + &#34;DRYCC_RELEASE&#34;: &#34;v3&#34;, + &#34;HELLO&#34;: &#34;world&#34;, + &#34;PLATFORM&#34;: &#34;drycc&#34; + + }, + &#34;memory&#34;: {}, + &#34;cpu&#34;: {}, + &#34;tags&#34;: {}, + &#34;healthcheck&#34;: {}, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="unset-config-variable">Unset Config Variable<a class="td-heading-self-link" href="#unset-config-variable" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/config/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;values&#34;: {&#34;HELLO&#34;: null}} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;owner&#34;: &#34;test&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;values&#34;: { + &#34;DRYCC_APP&#34;: &#34;example-go&#34;, + &#34;DRYCC_RELEASE&#34;: &#34;v4&#34;, + &#34;PLATFORM&#34;: &#34;drycc&#34; + }, + &#34;memory&#34;: {}, + &#34;cpu&#34;: {}, + &#34;tags&#34;: {}, + &#34;healthcheck&#34;: {}, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h2 id="domains">Domains<a class="td-heading-self-link" href="#domains" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-domains">List Application Domains<a class="td-heading-self-link" href="#list-application-domains" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/domains/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;domain&#34;: &#34;example.example.com&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34; + } + ] +} +</code></pre><h3 id="add-domain">Add Domain<a class="td-heading-self-link" href="#add-domain" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/domains/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{&#39;domain&#39;: &#39;example.example.com&#39;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;domain&#34;: &#34;example.example.com&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34; +} +</code></pre><h3 id="remove-domain">Remove Domain<a class="td-heading-self-link" href="#remove-domain" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/apps/example-go/domains/example.example.com HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h2 id="builds">Builds<a class="td-heading-self-link" href="#builds" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-builds">List Application Builds<a class="td-heading-self-link" href="#list-application-builds" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/build/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;dockerfile&#34;: &#34;FROM drycc/slugrunner RUN mkdir -p /app WORKDIR /app ENTRYPOINT [\&#34;/runner/init\&#34;] ADD slug.tgz /app ENV GIT_SHA 060da68f654e75fac06dbedd1995d5f8ad9084db&#34;, + &#34;image&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;procfile&#34;: { + &#34;web&#34;: &#34;example-go&#34; + }, + &#34;sha&#34;: &#34;060da68f&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="create-application-build">Create Application Build<a class="td-heading-self-link" href="#create-application-build" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/build/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;image&#34;: &#34;drycc/example-go:latest&#34;} +</code></pre><p>Optional Parameters:</p> +<pre tabindex="0"><code>{ + &#34;procfile&#34;: { + &#34;web&#34;: &#34;./cmd&#34; + } +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;dockerfile&#34;: &#34;&#34;, + &#34;image&#34;: &#34;drycc/example-go:latest&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;procfile&#34;: {}, + &#34;sha&#34;: &#34;&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h2 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-releases">List Application Releases<a class="td-heading-self-link" href="#list-application-releases" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/releases/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;count&#34;: 3, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: &#34;2.3d8e4b-600e-4425-a85c-ffc7ea607f61&#34;, + &#34;config&#34;: &#34;ed637ceb-5d32-44bd-9406-d326a777a513&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test changed nothing&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 3 + }, + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: &#34;2.3d8e4b-600e-4425-a85c-ffc7ea607f61&#34;, + &#34;config&#34;: &#34;95bd6dea-1685-4f78-a03d-fd7270b058d1&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test deployed 060da68&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 2 + }, + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: null, + &#34;config&#34;: &#34;95bd6dea-1685-4f78-a03d-fd7270b058d1&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test created initial release&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 1 + } + ] +} +</code></pre><h3 id="list-release-details">List Release Details<a class="td-heading-self-link" href="#list-release-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/releases/v2/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: null, + &#34;config&#34;: &#34;95bd6dea-1685-4f78-a03d-fd7270b058d1&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test created initial release&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 1 +} +</code></pre><h3 id="rollback-release">Rollback Release<a class="td-heading-self-link" href="#rollback-release" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/releases/rollback/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;version&#34;: 1} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{&#34;version&#34;: 5} +</code></pre><h2 id="keys">Keys<a class="td-heading-self-link" href="#keys" aria-label="Heading self-link"></a></h2> +<h3 id="list-keys">List Keys<a class="td-heading-self-link" href="#list-keys" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/keys/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;test@example.com&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;public&#34;: &#34;ssh-rsa &lt;...&gt;&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; + } + ] +} +</code></pre><h3 id="add-key-to-user">Add Key to User<a class="td-heading-self-link" href="#add-key-to-user" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/keys/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{ + &#34;id&#34;: &#34;example&#34;, + &#34;public&#34;: &#34;ssh-rsa &lt;...&gt;&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example&#34;, + &#34;owner&#34;: &#34;example&#34;, + &#34;public&#34;: &#34;ssh-rsa &lt;...&gt;&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="remove-key-from-user">Remove Key from User<a class="td-heading-self-link" href="#remove-key-from-user" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/keys/example HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h2 id="permissions">Permissions<a class="td-heading-self-link" href="#permissions" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-permissions">List Application Permissions<a class="td-heading-self-link" href="#list-application-permissions" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This does not include the app owner.</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/perms/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;users&#34;: [ + &#34;test&#34;, + &#34;foo&#34; + ] +} +</code></pre><h3 id="create-application-permission">Create Application Permission<a class="td-heading-self-link" href="#create-application-permission" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/perms/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{&#34;username&#34;: &#34;example&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h3 id="remove-application-permission">Remove Application Permission<a class="td-heading-self-link" href="#remove-application-permission" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/apps/example-go/perms/example HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h3 id="list-administrators">List Administrators<a class="td-heading-self-link" href="#list-administrators" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/admin/perms/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;count&#34;: 2, + &#34;next&#34;: null + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;username&#34;: &#34;test&#34;, + &#34;is_superuser&#34;: true + }, + { + &#34;username&#34;: &#34;foo&#34;, + &#34;is_superuser&#34;: true + } + ] +} +</code></pre><h3 id="grant-user-administrative-privileges">Grant User Administrative Privileges<a class="td-heading-self-link" href="#grant-user-administrative-privileges" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command requires administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/admin/perms HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{&#34;username&#34;: &#34;example&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h3 id="remove-users-administrative-privileges">Remove User&rsquo;s Administrative Privileges<a class="td-heading-self-link" href="#remove-users-administrative-privileges" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command requires administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/admin/perms/example HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h2 id="users">Users<a class="td-heading-self-link" href="#users" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-users">List all users<a class="td-heading-self-link" href="#list-all-users" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command requires administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/users HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;id&#34;: 1, + &#34;last_login&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;is_superuser&#34;: true, + &#34;username&#34;: &#34;test&#34;, + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34;, + &#34;email&#34;: &#34;test@example.com&#34;, + &#34;is_staff&#34;: true, + &#34;is_active&#34;: true, + &#34;date_joined&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;groups&#34;: [], + &#34;user_permissions&#34;: [] + } + ] +} +</code></pre> + + + + + Docs: Configuring an Application + /docs/applications/managing-app-configuration/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/applications/managing-app-configuration/ + + + + <h1 id="configuring-an-application">Configuring an Application<a class="td-heading-self-link" href="#configuring-an-application" aria-label="Heading self-link"></a></h1> +<p>A Drycc application <a href="http://12factor.net/config">stores config in environment variables</a>.</p> +<h2 id="setting-environment-variables">Setting Environment Variables<a class="td-heading-self-link" href="#setting-environment-variables" aria-label="Heading self-link"></a></h2> +<p>Use <code>drycc config</code> to modify environment variables for a deployed application.</p> +<pre><code>$ drycc help config +Valid commands for config: + +config:list list environment variables for an app +config:set set environment variables for an app +config:unset unset environment variables for an app +config:pull extract environment variables to .env +config:push set environment variables from .env + +Use `drycc help [command]` to learn more. +</code></pre> +<p>When config is changed, a new release is created and deployed automatically.</p> +<p>You can set multiple environment variables with one <code>drycc config:set</code> command, +or with <code>drycc config:push</code> and a local .env file.</p> +<pre><code>$ drycc config:set FOO=1 BAR=baz &amp;&amp; drycc config:pull +$ cat .env +FOO=1 +BAR=baz +$ echo &quot;TIDE=high&quot; &gt;&gt; .env +$ drycc config:push +Creating config... done, v4 + +=== yuppie-earthman +DRYCC_APP: yuppie-earthman +FOO: 1 +BAR: baz +TIDE: high +</code></pre> +<p>It can also modify environment variables for a process type of application.</p> +<pre><code>$ drycc config:set FOO=1 BAR=baz --ptype=web +</code></pre> +<h2 id="attach-to-backing-services">Attach to Backing Services<a class="td-heading-self-link" href="#attach-to-backing-services" aria-label="Heading self-link"></a></h2> +<p>Drycc treats backing services like databases, caches and queues as <a href="http://12factor.net/backing-services">attached resources</a>. +Attachments are performed using environment variables.</p> +<p>For example, use <code>drycc config</code> to set a <code>DATABASE_URL</code> that attaches +the application to an external PostgreSQL database.</p> +<pre><code>$ drycc config:set DATABASE_URL=postgres://user:pass@example.com:5432/db +=== peachy-waxworks +DATABASE_URL: postgres://user:pass@example.com:5432/db +</code></pre> +<p>Detachments can be performed with <code>drycc config:unset</code>.</p> +<h2 id="buildpacks-cache">Buildpacks Cache<a class="td-heading-self-link" href="#buildpacks-cache" aria-label="Heading self-link"></a></h2> +<p>By default, apps using the [Imagebuilder][] will reuse the latest image data. +When deploying applications that depend on third-party libraries that have to be fetched, +this could speed up deployments a lot. In order to make use of this, the buildpack must implement +the cache by writing to the cache directory. Most buildpacks already implement this, but when using +custom buildpacks, it might need to be changed to make full use of the cache.</p> +<h3 id="disabling-and-re-enabling-the-cache">Disabling and re-enabling the cache<a class="td-heading-self-link" href="#disabling-and-re-enabling-the-cache" aria-label="Heading self-link"></a></h3> +<p>In some cases, cache might not speed up your application. To disable caching, you can set the +<code>DRYCC_DISABLE_CACHE</code> variable with <code>drycc config:set DRYCC_DISABLE_CACHE=1</code>. When you disable the +cache, Drycc will clear up files it created to store the cache. After having it turned off, run +<code>drycc config:unset DRYCC_DISABLE_CACHE</code> to re-enable the cache.</p> +<h3 id="clearing-the-cache">Clearing the cache<a class="td-heading-self-link" href="#clearing-the-cache" aria-label="Heading self-link"></a></h3> +<p>Use the following procedure to clear the cache:</p> +<pre><code>$ drycc config:set DRYCC_DISABLE_CACHE=1 +$ git commit --allow-empty -m &quot;Clearing Drycc cache&quot; +$ git push drycc # (if you use a different remote, you should use your remote name) +$ drycc config:unset DRYCC_DISABLE_CACHE +</code></pre> +<h2 id="custom-health-checks">Custom Health Checks<a class="td-heading-self-link" href="#custom-health-checks" aria-label="Heading self-link"></a></h2> +<p>By default, Workflow only checks that the application starts in their Container. If it is preferred +to have Kubernetes respond to application health, a health check may be added by configuring a +health check probe for the application.</p> +<p>The health checks are implemented as <a href="https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes">Kubernetes container probes</a>. A <code>liveness</code> +and a <code>readiness</code> probe can be configured, and each probe can be of type <code>httpGet</code>, <code>exec</code>, or +<code>tcpSocket</code> depending on the type of probe the container requires.</p> +<p>A liveness probe is useful for applications running for long periods of time, eventually +transitioning to broken states and cannot recover except by restarting them.</p> +<p>Other times, a readiness probe is useful when the container is only temporarily unable to serve, +and will recover on its own. In this case, if a container fails its readiness probe, the container +will not be shut down, but rather the container will stop receiving incoming requests.</p> +<p><code>httpGet</code> probes are just as it sounds: it performs a HTTP GET operation on the Container. A +response code inside the 200-399 range is considered a pass.</p> +<p><code>exec</code> probes run a command inside the Container to determine its health, such as +<code>cat /var/run/myapp.pid</code> or a script that determines when the application is ready. An exit code of +zero is considered a pass, while a non-zero status code is considered a fail.</p> +<p><code>tcpSocket</code> probes attempt to open a socket in the Container. The Container is only considered +healthy if the check can establish a connection. <code>tcpSocket</code> probes accept a port number to perform +the socket connection on the Container.</p> +<p>Health checks can be configured on a per-proctype basis for each application using <code>drycc healthchecks:set</code>. If no type is mentioned then the health checks are applied to default proc type web, whichever is present. To +configure a <code>httpGet</code> liveness probe:</p> +<pre tabindex="0"><code>$ drycc healthchecks:set liveness httpGet 80 --ptype web +Applying livenessProbe healthcheck... done + +App: peachy-waxworks +UUID: afd84067-29e9-4a5f-9f3a-60d91e938812 +Owner: dev +Created: 2023-12-08T10:25:00Z +Updated: 2023-12-08T10:25:00Z +Healthchecks: + liveness web http-get headers=[] path=/ port=80 delay=50s timeout=50s period=10s #success=1 #failure=3 +</code></pre><p>If the application relies on certain headers being set (such as the <code>Host</code> header) or a specific +URL path relative to the root, you can also send specific HTTP headers:</p> +<pre tabindex="0"><code>$ drycc healthchecks:set liveness httpGet 80 \ + --path /welcome/index.html \ + --headers &#34;X-Client-Version:v1.0,X-Foo:bar&#34; +Applying livenessProbe healthcheck... done + +App: peachy-waxworks +UUID: afd84067-29e9-4a5f-9f3a-60d91e938812 +Owner: dev +Created: 2023-12-08T10:25:00Z +Updated: 2023-12-08T10:25:00Z +Healthchecks: + liveness web http-get headers=[X-Client-Version=v1.0] path=/welcome/index.html port=80 delay=50s timeout=50s period=10s #success=1 #failure=3 +</code></pre><p>To configure an <code>exec</code> readiness probe:</p> +<pre tabindex="0"><code>$ drycc healthchecks:set readiness exec -- /bin/echo -n hello --ptype web +Applying readinessProbe healthcheck... done + +App: peachy-waxworks +UUID: afd84067-29e9-4a5f-9f3a-60d91e938812 +Owner: dev +Created: 2023-12-08T10:25:00Z +Updated: 2023-12-08T10:25:00Z +Healthchecks: + readiness web exec /bin/echo -n hello delay=50s timeout=50s period=10s #success=1 #failure=3 +</code></pre><p>You can overwrite a probe by running <code>drycc healthchecks:set</code> again:</p> +<pre tabindex="0"><code>$ drycc healthchecks:set readiness httpGet 80 --ptype web +Applying livenessProbe healthcheck... done + +App: peachy-waxworks +UUID: afd84067-29e9-4a5f-9f3a-60d91e938812 +Owner: dev +Created: 2023-12-08T10:25:00Z +Updated: 2023-12-08T10:25:00Z +Healthchecks: + liveness web http-get headers=[] path=/ port=80 delay=50s timeout=50s period=10s #success=1 #failure=3 +</code></pre><p>Configured health checks also modify the default application deploy behavior. When starting a new +Pod, Workflow will wait for the health check to pass before moving onto the next Pod.</p> +<h2 id="autodeploy">Autodeploy<a class="td-heading-self-link" href="#autodeploy" aria-label="Heading self-link"></a></h2> +<p>By default, Changes the config, limits or healthchecks and so on will trigger deploy. +If you don&rsquo;t want deploy, you can disable.</p> +<pre tabindex="0"><code>$ drycc autodeploy:disable +</code></pre><p>To re-enable autodeploy.</p> +<pre tabindex="0"><code>drycc autodeploy:enable +</code></pre><p>you can deploy by executing the following command. +deploy all ptypes</p> +<pre tabindex="0"><code>drycc releases:deploy +</code></pre><p>deploy web process type, and support <code>--force</code> option to force deploy.</p> +<pre tabindex="0"><code>drycc releases:deploy web --force +</code></pre><h2 id="autorollback">Autorollback<a class="td-heading-self-link" href="#autorollback" aria-label="Heading self-link"></a></h2> +<p>By default, deployment failures will roll back to the previous successful version. +If you don&rsquo;t want this to happen, you can disable.</p> +<pre tabindex="0"><code>$ drycc autorollback:disable +</code></pre><p>To re-enable autorollback.</p> +<pre tabindex="0"><code>drycc autorollback:enable +</code></pre><h2 id="isolate-the-application">Isolate the Application<a class="td-heading-self-link" href="#isolate-the-application" aria-label="Heading self-link"></a></h2> +<p>Workflow supports isolating applications onto a set of nodes using <code>drycc tags</code>.</p> +<p>!!! note +In order to use tags, you must first launch your cluster with the proper node labels. If you do +not, tag commands will fail. Learn more by reading <a href="http://kubernetes.io/docs/user-guide/node-selection/">&ldquo;Assigning Pods to Nodes&rdquo;</a>.</p> +<p>Once your nodes are configured with appropriate label selectors, use <code>drycc tags:set</code> to restrict +the application ptype to those nodes:</p> +<pre tabindex="0"><code>$ drycc tags:set web environ=prod +Applying tags... done, v4 + +environ prod +</code></pre> + + + + + Docs: Managing Application Metrics + /docs/applications/managing-app-metrics/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/applications/managing-app-metrics/ + + + + <h2 id="create-an-authentication-token">Create an authentication token<a class="td-heading-self-link" href="#create-an-authentication-token" aria-label="Heading self-link"></a></h2> +<p>Create an authentication token using the drycc client.</p> +<pre tabindex="0"><code># drycc tokens:add prometheus --password admin --username admin + ! WARNING: Make sure to copy your token now. + ! You won&#39;t be able to see it again, please confirm whether to continue. + ! To proceed, type &#34;yes&#34; ! + +&gt; yes +UUID USERNAME TOKEN +58176cf1-37a8-4c52-9b27-4c7a47269dfb admin 1F2c7A802aF640fd9F31dD846AdDf56BcMsay +</code></pre><h2 id="add-scrape-configurations-for-prometheus">Add scrape configurations for prometheus<a class="td-heading-self-link" href="#add-scrape-configurations-for-prometheus" aria-label="Heading self-link"></a></h2> +<p>A valid example file can be found here.</p> +<p>The global configuration specifies parameters that are valid in all other configuration contexts. They also serve as defaults for other configuration sections.</p> +<pre tabindex="0"><code>global: + scrape_interval: 60s + evaluation_interval: 60s +scrape_configs: +- job_name: &#39;drycc&#39; + scheme: https + metrics_path: /v2/apps/&lt;appname&gt;/metrics + authorization: + type: Token + credentials: 1F2c7A802aF640fd9F31dD846AdDf56BcMsay + static_configs: + - targets: [&#39;drycc.domain.com&#39;] +</code></pre> + + + + + Docs: Production Deployments + /docs/managing-workflow/production-deployments/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/managing-workflow/production-deployments/ + + + + <h2 id="running-workflow-without-drycc-storage">Running Workflow without drycc storage<a class="td-heading-self-link" href="#running-workflow-without-drycc-storage" aria-label="Heading self-link"></a></h2> +<p>In production, persistent storage can be achieved by running an external object store. +For users on AWS, GCE/GKE or Azure, the convenience of Amazon S3, Google GCS or Microsoft Azure Storage +makes the prospect of running a Storage-less Workflow cluster quite reasonable. For users who have restriction +on using external object storage using swift object storage can be an option.</p> +<p>Running a Workflow cluster without Storage provides several advantages:</p> +<ul> +<li>Removal of state from the worker nodes</li> +<li>Reduced resource usage</li> +<li>Reduced complexity and operational burden of managing Workflow</li> +</ul> +<p>See <a href="/docs/installing-workflow/configuring-object-storage/">Configuring Object Storage</a> for details on removing this operational complexity.</p> +<h2 id="review-security-considerations">Review Security Considerations<a class="td-heading-self-link" href="#review-security-considerations" aria-label="Heading self-link"></a></h2> +<p>There are some additional security-related considerations when running Workflow in production. +See [Security Considerations][] for details.</p> +<h2 id="registration-is-admin-only">Registration is Admin-Only<a class="td-heading-self-link" href="#registration-is-admin-only" aria-label="Heading self-link"></a></h2> +<p>By default, registration with the Workflow controller is in &ldquo;admin_only&rdquo; mode. The first user +to run a <code>drycc register</code> command becomes the initial &ldquo;admin&rdquo; user, and registrations after that +are disallowed unless requested by an admin.</p> +<p>Please see the following documentation to learn about changing registration mode:</p> +<ul> +<li><a href="/docs/managing-workflow/tuning-component-settings/#customizing-the-controller">Customizing Controller</a></li> +</ul> +<h2 id="disable-grafana-signups">Disable Grafana Signups<a class="td-heading-self-link" href="#disable-grafana-signups" aria-label="Heading self-link"></a></h2> +<p>It is also recommended to disable signups for the Grafana dashboards.</p> +<p>Please see the following documentation to learn about disabling Grafana signups:</p> +<ul> +<li><a href="/docs/managing-workflow/tuning-component-settings/#customizing-the-monitor">Customizing Monitor</a></li> +</ul> +<h2 id="running-workflow-with-rbac">Running Workflow with RBAC<a class="td-heading-self-link" href="#running-workflow-with-rbac" aria-label="Heading self-link"></a></h2> +<p>If your cluster has <a href="https://kubernetes.io/docs/admin/authorization/rbac/">RBAC</a> amongst your <a href="https://kubernetes.io/docs/admin/authorization/">authorization</a> modes (<code>$ kubectl api-versions</code> should contains <code>rbac.authorization.k8s.io</code>) it may be necessary to enable RBAC in Workflow. +This can be achieved by setting <code>use_rbac</code> in the <code>global</code> section of <code>values.yaml</code> to <code>true</code>, or by adding <code>--set=global.use_rbac=true</code> to the <code>$ helm install/upgrade</code> command. +RBAC support was announced in Kubernetes-1.5 and is enabled by default if:</p> +<ul> +<li>your Kubernetes cluster is in GKE</li> +<li>your Kubernetes cluster built with <a href="https://kubernetes.io/docs/getting-started-guides/kubeadm/">kubeadm</a></li> +</ul> +<p><strong>Note</strong>: helm may need to be given <a href="/docs/installing-workflow/#check-your-authorization">specific permissions</a> under RBAC if not already done.</p> +<p><strong>Attention</strong>: Azure ACS Kubernetes clusters are not RBAC-enabled for today due to lack in authentication strategy. Feel free to watch this <a href="https://github.com/kubernetes/kubernetes/pull/43987">PR</a> for more details.</p> + + + + + + Docs: Upgrading Workflow + /docs/managing-workflow/upgrading-workflow/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/managing-workflow/upgrading-workflow/ + + + + <p>This upgrade process requires:</p> +<ul> +<li>Helm version <a href="https://github.com/kubernetes/helm/releases/tag/v2.1.0">2.1.0 or newer</a></li> +<li>Configured Off-Cluster Storage</li> +</ul> +<h2 id="upgrade-process">Upgrade Process<a class="td-heading-self-link" href="#upgrade-process" aria-label="Heading self-link"></a></h2> +<p>!!! note +If upgrading from a <a href="https://github.com/helm/helm-classic">Helm Classic</a> install, you&rsquo;ll need to &lsquo;migrate&rsquo; the cluster to a <a href="https://github.com/kubernetes/helm">Kubernetes Helm</a> installation. See <a href="https://github.com/drycc/workflow-migration/blob/main/README.md">Workflow-Migration</a> for steps.</p> +<h3 id="step-1-apply-the-workflow-upgrade">Step 1: Apply the Workflow upgrade<a class="td-heading-self-link" href="#step-1-apply-the-workflow-upgrade" aria-label="Heading self-link"></a></h3> +<p>Helm will remove all components from the previous release. Traffic to applications deployed through +Workflow will continue to flow during the upgrade. No service interruptions should occur.</p> +<p>If Workflow is not configured to use off-cluster Postgres, the Workflow API will experience a brief +period of downtime while the database recovers from backup.</p> +<p>First, find the name of the release helm gave to your deployment with <code>helm ls</code>, then run</p> +<pre tabindex="0"><code>$ helm upgrade &lt;release-name&gt; oci://registry.drycc.cc/charts/workflow +</code></pre><p><strong>Note:</strong> If using off-cluster object storage on <a href="https://cloud.google.com/storage/">gcs</a> and/or off-cluster registry using <a href="https://cloud.google.com/container-registry/">gcr</a> and intending to upgrade from a pre-<code>v2.10.0</code> chart to <code>v2.10.0</code> or greater, the <code>key_json</code> values will now need to be pre-base64-encoded. Therefore, assuming the rest of the custom/off-cluster values are defined in the existing <code>values.yaml</code> used for previous installs, the following may be run:</p> +<pre tabindex="0"><code>$ B64_KEY_JSON=&#34;$(cat ~/path/to/key.json | base64 -w 0)&#34; +$ helm upgrade &lt;release_name&gt; drycc/workflow -f values.yaml --set gcs.key_json=&#34;${B64_KEY_JSON}&#34;,registry-token-refresher.gcr.key_json=&#34;${B64_KEY_JSON}&#34; +</code></pre><p>Alternatively, simply replace the appropriate values in values.yaml and do without the <code>--set</code> +parameter. Make sure to wrap it in single quotes as double quotes will give a parser error when +upgrading.</p> +<h3 id="step-2-verify-upgrade">Step 2: Verify Upgrade<a class="td-heading-self-link" href="#step-2-verify-upgrade" aria-label="Heading self-link"></a></h3> +<p>Verify that all components have started and passed their readiness checks:</p> +<pre tabindex="0"><code>$ kubectl --namespace=drycc get pods +NAME READY STATUS RESTARTS AGE +drycc-builder-2448122224-3cibz 1/1 Running 0 5m +drycc-controller-1410285775-ipc34 1/1 Running 3 5m +drycc-controller-celery-694f75749b-cmxxn 3/3 Running 0 5m +drycc-database-e7c5z 1/1 Running 0 5m +drycc-logger-cgjup 1/1 Running 3 5m +drycc-logger-fluentbit-45h7j 1/1 Running 0 5m +drycc-logger-fluentbit-4z7lw 1/1 Running 0 5m +drycc-logger-fluentbit-k2wsw 1/1 Running 0 5m +drycc-logger-fluentbit-skdw4 1/1 Running 0 5m +drycc-redis-8nazu 1/1 Running 0 5m +drycc-monitor-grafana-tm266 1/1 Running 0 5m +drycc-monitor-telegraf-51zel 1/1 Running 1 5m +drycc-monitor-telegraf-cdasg 1/1 Running 0 5m +drycc-monitor-telegraf-hea6x 1/1 Running 0 5m +drycc-monitor-telegraf-r7lsg 1/1 Running 0 5m +drycc-registry-1814324048-yomz5 1/1 Running 0 5m +drycc-registry-proxy-4m3o4 1/1 Running 0 5m +drycc-registry-proxy-no3r1 1/1 Running 0 5m +drycc-registry-proxy-ou8is 1/1 Running 0 5m +drycc-registry-proxy-zyajl 1/1 Running 0 5m +drycc-rabbitmq-0 1/1 Running 0 5m +</code></pre><h3 id="step-3-upgrade-the-drycc-client">Step 3: Upgrade the Drycc Client<a class="td-heading-self-link" href="#step-3-upgrade-the-drycc-client" aria-label="Heading self-link"></a></h3> +<p>Users of Drycc Workflow should now upgrade their drycc client to avoid getting <code>WARNING: Client and server API versions do not match. Please consider upgrading.</code> warnings.</p> +<pre tabindex="0"><code>curl -sfL https://www.drycc.cc/install-cli.sh | bash - &amp;&amp; sudo mv drycc $(which drycc) +</code></pre> + + + + + Docs: Managing an Application + /docs/applications/managing-app-lifecycle/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/applications/managing-app-lifecycle/ + + + + <h2 id="track-application-changes">Track Application Changes<a class="td-heading-self-link" href="#track-application-changes" aria-label="Heading self-link"></a></h2> +<p>Drycc Workflow tracks all changes to your application. Application changes are the result of either new application code +pushed to the platform (via <code>git push drycc master</code>), or an update to application configuration (via <code>drycc config:set KEY=VAL</code>).</p> +<p>Each time a build or config change is made to your application a new <a href="../reference-guide/terms.md#release">release</a> is created. These release numbers +increase monotonically.</p> +<p>You can see a record of changes to your application using <code>drycc releases</code>:</p> +<pre tabindex="0"><code>$ drycc releases +OWNER STATE VERSION CREATED SUMMARY +dev succeed v3 2023-12-04T10:17:46Z dev deleted PIP_INDEX_URL, DISABLE_COLLECTSTATIC +dev succeed v2 2023-12-01T10:20:22Z dev added IMAGE_PULL_POLICY, PIP_INDEX_URL, PORT, DISABLE_COLLEC[...] +dev succeed v1 2023-11-30T17:54:57Z dev created initial release +</code></pre><h2 id="rollback-a-release">Rollback a Release<a class="td-heading-self-link" href="#rollback-a-release" aria-label="Heading self-link"></a></h2> +<p>Drycc Workflow also supports rolling back go previous releases. If buggy code or an errant configuration change is pushed +to your application, you may rollback to a previously known, good release.</p> +<p>!!! note +All rollbacks create a new, numbered release. But will reference the build/code and configuration from the desired rollback point.</p> +<p>In this example, the application is currently running release v4. Using <code>drycc rollback v2</code> tells Workflow to deploy the +build and configuration that was used for release v2. This creates a new release named v5 whose contents are the source +and configuration from release v2:</p> +<pre tabindex="0"><code>$ drycc releases +OWNER STATE VERSION CREATED SUMMARY +dev succeed v3 2023-12-04T10:17:46Z dev deleted PIP_INDEX_URL, DISABLE_COLLECTSTATIC +dev succeed v2 2023-12-01T10:20:22Z dev added IMAGE_PULL_POLICY, PIP_INDEX_URL, PORT, DISABLE_COLLEC[...] +dev succeed v1 2023-11-30T17:54:57Z dev created initial release + +$ drycc rollback v2 +Rolled back to v2 + +$ drycc releases +OWNER STATE VERSION CREATED SUMMARY +dev succeed v4 2023-12-04T10:20:46Z dev rolled back to v2 +dev succeed v3 2023-12-04T10:17:46Z dev deleted PIP_INDEX_URL, DISABLE_COLLECTSTATIC +dev succeed v2 2023-12-01T10:20:22Z dev added IMAGE_PULL_POLICY, PIP_INDEX_URL, PORT, DISABLE_COLLEC[...] +dev succeed v1 2023-11-30T17:54:57Z dev created initial release +</code></pre><p>Only rollback web process type:</p> +<pre tabindex="0"><code>$ drycc rollback v3 web +Rolled back to v3 + +$ drycc releases +OWNER STATE VERSION CREATED SUMMARY +dev succeed v5 2023-12-04T10:23:49Z dev rolled back to v3 +dev succeed v4 2023-12-04T10:20:46Z dev rolled back to v2 +dev succeed v3 2023-12-04T10:17:46Z dev deleted PIP_INDEX_URL, DISABLE_COLLECTSTATIC +dev succeed v2 2023-12-01T10:20:22Z dev added IMAGE_PULL_POLICY, PIP_INDEX_URL, PORT, DISABLE_COLLEC[...] +dev succeed v1 2023-11-30T17:54:57Z dev created initial release +</code></pre><h2 id="run-one-off-administration-tasks">Run One-off Administration Tasks<a class="td-heading-self-link" href="#run-one-off-administration-tasks" aria-label="Heading self-link"></a></h2> +<p>Drycc applications <a href="http://12factor.net/admin-processes">use one-off processes for admin tasks</a> like database migrations and other commands that must run against the live application.</p> +<p>Use <code>drycc run</code> to execute commands on the deployed application.</p> +<pre><code>$ drycc run 'ls -l' +Running `ls -l`... + +total 28 +-rw-r--r-- 1 root root 553 Dec 2 23:59 LICENSE +-rw-r--r-- 1 root root 60 Dec 2 23:59 Procfile +-rw-r--r-- 1 root root 33 Dec 2 23:59 README.md +-rw-r--r-- 1 root root 1622 Dec 2 23:59 pom.xml +drwxr-xr-x 3 root root 4096 Dec 2 23:59 src +-rw-r--r-- 1 root root 25 Dec 2 23:59 system.properties +drwxr-xr-x 6 root root 4096 Dec 3 00:00 target +</code></pre> +<h2 id="share-an-application">Share an Application<a class="td-heading-self-link" href="#share-an-application" aria-label="Heading self-link"></a></h2> +<p>Use <code>drycc perms:add</code> to allow another Drycc user to collaborate on your application.</p> +<pre tabindex="0"><code>$ drycc perms:add otheruser view,change,delete +Adding user otheruser as a collaborator for view,change,delete peachy-waxwork... done +</code></pre><p>Use <code>drycc perms</code> to see who an application is currently shared with, and <code>drycc perms:remove</code> to remove a collaborator.</p> +<p>!!! note +Collaborators can do anything with an application that its owner can do, except delete the application.</p> +<p>When working with an application that has been shared with you, clone the original repository and add Drycc&rsquo; git remote +entry before attempting to <code>git push</code> any changes to Drycc.</p> +<pre tabindex="0"><code>$ git clone https://github.com/drycc/example-java-jetty.git +Cloning into &#39;example-java-jetty&#39;... done +$ cd example-java-jetty +$ git remote add -f drycc ssh://git@local3.dryccapp.com:2222/peachy-waxworks.git +Updating drycc +From drycc-controller.local:peachy-waxworks + * [new branch] master -&gt; drycc/master +</code></pre><h2 id="application-troubleshooting">Application Troubleshooting<a class="td-heading-self-link" href="#application-troubleshooting" aria-label="Heading self-link"></a></h2> +<p>Applications deployed on Drycc Workflow <a href="http://12factor.net/logs">treat logs as event streams</a>. Drycc Workflow aggregates <code>stdout</code> and <code>stderr</code> +from every <a href="../reference-guide/terms.md#container">Container</a> making it easy to troubleshoot problems with your application.</p> +<p>Use <code>drycc logs</code> to view the log output from your deployed application.</p> +<pre><code>$ drycc logs -f +Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.5]: INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null} +Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.8]: INFO:oejs.Server:jetty-7.6.0.v20120127 +Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.5]: INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:10005 +Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.6]: INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null} +Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.7]: INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null} +Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.6]: INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:10006 +Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.8]: INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null} +Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.7]: INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:10007 +Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.8]: INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:10008 +</code></pre> + + + + + + Docs: Triaging Issues + /docs/contribution-guidelines/triaging-issues/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/contribution-guidelines/triaging-issues/ + + + + <p>Triage helps ensure issues resolve quickly by:</p> +<ul> +<li>Describing the issue&rsquo;s intent and purpose is conveyed precisely. This is necessary because it can be difficult for an issue to explain how an end user experiences an problem and what actions they took.</li> +<li>Giving a contributor the information they need before they commit to resolving an issue.</li> +<li>Lowering the issue count by preventing duplicate issues.</li> +<li>Streamlining the development process by preventing duplicate discussions.</li> +</ul> +<p>If you don&rsquo;t have time to code, consider helping with triage. The community will thank you for saving them time by spending some of yours.</p> +<h2 id="ensure-the-issue-contains-basic-information">Ensure the Issue Contains Basic Information<a class="td-heading-self-link" href="#ensure-the-issue-contains-basic-information" aria-label="Heading self-link"></a></h2> +<p>Before triaging an issue very far, make sure that the issue&rsquo;s author provided the standard issue information. This will help you make an educated recommendation on how this to categorize the issue. Standard information that should be included in most issues are things such as:</p> +<ul> +<li>the version(s) of Drycc this issue affects</li> +<li>a reproducible case if this is a bug</li> +<li>page URL if this is a docs issue or the name of a man page</li> +</ul> +<p>Depending on the issue, you might not feel all this information is needed. Use your best judgment. If you cannot triage an issue using what its author provided, explain kindly to the author that they must provide the above information to clarify the problem.</p> +<p>If the author provides the recommended information but you are still unable to triage the issue, request additional information. Do this kindly and politely because you are asking for more of the author&rsquo;s time.</p> +<p>If the author does not respond requested information within the timespan of a week, close the issue with a kind note stating that the author can request for the issue to be reopened when the necessary information is provided.</p> +<h2 id="classifying-the-issue">Classifying the Issue<a class="td-heading-self-link" href="#classifying-the-issue" aria-label="Heading self-link"></a></h2> +<p>An issue can have multiple of the following labels:</p> +<h3 id="issue-kind">Issue Kind<a class="td-heading-self-link" href="#issue-kind" aria-label="Heading self-link"></a></h3> +<table> +<thead> +<tr> +<th>Kind</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>bug</td> +<td>Bugs are bugs. The cause may or may not be known at triage time so debugging should be taken account into the time estimate.</td> +</tr> +<tr> +<td>docs</td> +<td>Writing documentation, man pages, articles, blogs, or other significant word-driven task.</td> +</tr> +<tr> +<td>enhancement</td> +<td>Enhancements can drastically improve usability or performance of a component.</td> +</tr> +<tr> +<td>question</td> +<td>Contains a user or contributor question requiring a response.</td> +</tr> +<tr> +<td>security</td> +<td>Security-related issues such as TLS encryption, network segregation, authn/authz features, etc.</td> +</tr> +</tbody> +</table> +<h3 id="functional-area">Functional Area<a class="td-heading-self-link" href="#functional-area" aria-label="Heading self-link"></a></h3> +<ul> +<li>builder</li> +<li>cache</li> +<li>contrib and provisioning</li> +<li>client</li> +<li>controller</li> +<li>database</li> +<li>docs</li> +<li>kubernetes</li> +<li>registry</li> +<li>router</li> +<li>store (Ceph)</li> +<li>tests</li> +</ul> +<h2 id="easy-fix">Easy Fix<a class="td-heading-self-link" href="#easy-fix" aria-label="Heading self-link"></a></h2> +<p>&ldquo;Easy Fix&rdquo; issues are a way for a new contributor to find issues that are fit for their experience level. These issues are typically for users who are new to Drycc, and possibly Go, and is looking to help while learning the basics.</p> +<h2 id="prioritizing-issues">Prioritizing issues<a class="td-heading-self-link" href="#prioritizing-issues" aria-label="Heading self-link"></a></h2> +<p>When attached to a specific milestone, an issue can be attributed one of the following labels to indicate their degree of priority.</p> +<table> +<thead> +<tr> +<th>Priority</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>priority 0</td> +<td>Urgent: Security, critical bugs, blocking issues. Drop everything and fix this today, then consider creating a patch release.</td> +</tr> +<tr> +<td>priority 1</td> +<td>Serious: Impedes user actions or is a regression. Fix this before the next planned release.</td> +</tr> +</tbody> +</table> +<p>And that&rsquo;s it. That should be all the information required for a new or existing contributor to come in an resolve an issue.</p> + + + + + + Docs: Conduct + /docs/contribution-guidelines/conduct/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/contribution-guidelines/conduct/ + + + + <h1 id="conduct">Conduct<a class="td-heading-self-link" href="#conduct" aria-label="Heading self-link"></a></h1> +<p>The Drycc community welcomes and encourages participation by <strong>everyone</strong>.</p> +<p>No matter how you identify yourself or how others perceive you: we welcome you. We welcome contributions from everyone as long as they interact constructively with our community.</p> +<p>The Drycc developer community continues to grow, and it is inevitable that disagreements and conflict will arise. We ask that participants conduct themselves according to these principles:</p> +<ol> +<li> +<p><strong>Be welcoming, friendly, and patient.</strong></p> +</li> +<li> +<p><strong>Be considerate.</strong></p> +</li> +</ol> +<p>Your work will be used by other people, and you in turn will depend on the work of others. Any decision you take will affect users and colleagues, and you should take those consequences into account when making decisions. Remember that we&rsquo;re a world-wide community, so you might not be communicating in someone else&rsquo;s primary language.</p> +<ol start="3"> +<li><strong>Be respectful.</strong></li> +</ol> +<p>Not all of us will agree all the time, but disagreement is no excuse for poor behavior and bad manners. We might all experience some frustration now and then, but we cannot allow that frustration to turn into a personal attack. It’s important to remember that a community where people feel uncomfortable or threatened is not a productive one.</p> +<ol start="4"> +<li><strong>Be careful in the words that you choose.</strong></li> +</ol> +<p>Be kind to others. Do not insult or put down other participants. Behave professionally. Remember that harassment and sexist, racist, or exclusionary jokes are never appropriate for the community.</p> +<p>(Thanks to the <a href="http://www.debian.org/intro/diversity">Debian</a> and <a href="https://www.djangoproject.com/conduct/">Django</a> communities for their text and +their inspiration.)</p> + + + + + + diff --git a/docs/installing-workflow/_print/index.html b/docs/installing-workflow/_print/index.html new file mode 100644 index 000000000..845a09b47 --- /dev/null +++ b/docs/installing-workflow/_print/index.html @@ -0,0 +1,674 @@ + + + + + + + + + + + + + + + + + + + + + +Installing To Kubenetes | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+ + + + + +
+
+

+This is the multi-page printable view of this section. +Click here to print. +

+Return to the regular view of this page. +

+
+ + + +

Installing To Kubenetes

+
Deploying Drycc on a Kubernetes Cluster.
+ + + + + + + +
+ +
+
+ + + + + + + + + + + + + + + + +
+ +

1 - Requirements

+
To run Drycc Workflow on a Kubernetes cluster, there are a few requirements to keep in mind.
+

Kubernetes Versions

+

Drycc Workflow requires Kubernetes v1.16.15 or later.

+

Components Requirements

+

Drycc uses gateway as a routing implementation, so you have to choose an gateway. We recommend using istio or kong.

+

Workflow supports the use of ACME to manage automatic certificates, cert-manager is also one of the necessary components, if you use cert-manager EAB, you need to set the clusterResourceNamespace to the namespace of drycc.

+

Workflow supports stateful apps. You can create and use them through the ‘drycc volumes’ command. If you want to use this feature, you must have a StorageClass that supports ReadWriteMany.

+

Workflow also supports the OSB API through the ‘drycc resources’ command. If you want to use this function, you need to install service-catalog.

+

Storage Requirements

+

A variety of Drycc Workflow components rely on an object storage system to do their work, including storing application +slugs, Container images and database logs.

+

Drycc Workflow ships with drycc storage by default, which provides in-cluster.

+

Workflow supports Amazon Simple Storage Service (S3), Google Cloud Storage (GCS), OpenShift Swift, and Azure Blob +Storage. See configuring object storage for setup instructions.

+

Resource Requirements

+

When deploying Drycc Workflow, it’s important to provision machines with adequate resources. Drycc is a highly-available +distributed system, which means that Drycc components and your deployed applications will move around the cluster onto +healthy hosts as hosts leave the cluster for various reasons (failures, reboots, autoscalers, etc.). Because of this, +you should have ample spare resources on any machine in your cluster to withstand the additional load of running +services for failed machines.

+

Drycc Workflow components use about 2.5GB of memory across the cluster, and require approximately 30GB of hard disk +space. Because it may need to handle additional load if another one fails, each machine has minimum requirements of:

+
    +
  • At least 4GB of RAM (more is better)
  • +
  • At least 40GB of hard disk space
  • +
+

Note that these estimates are for Drycc Workflow and Kubernetes only. Be sure to leave enough spare capacity for your +application footprint as well.

+

Running smaller machines will likely result in increased system load and has been known to result in component failures +and instability.

+ +
+ + + + + + + + + + + +
+ +

2 - Specify Gateway

+
Choose the gateway provider that best suits your needs and platform.
+

Install Drycc Workflow (Specify gateway)

+

Now that Helm is installed and the repository has been added, install Workflow with a native gateway by running:

+
$ helm install drycc oci://registry.drycc.cc/charts/workflow \
+    --namespace drycc \
+    --set global.gatewayClass=istio \
+    --set global.platformDomain=drycc.cc \
+    --set builder.service.type=LoadBalancer
+

Of course, if you deploy it on a bare machine, you probably do not have Load Balancer. You need to use NodePort:

+
$ helm install drycc oci://registry.drycc.cc/charts/workflow \
+    --namespace drycc \
+    --set global.gatewayClass=istio \
+    --set global.platformDomain=drycc.cc \
+    --set builder.service.type=NodePort \
+    --set builder.service.nodePort=32222
+

If you want to use Load Balancer on a bare machine, you can look at metallb

+

Where global.platformDomain is a required parameter that is traditionally not required for Workflow that is explained in the next section. In this example we are using drycc.cc for $hostname.

+

Helm will install a variety of Kubernetes resources in the drycc namespace. +Wait for the pods that Helm launched to be ready. Monitor their status by running:

+
$ kubectl --namespace=drycc get pods
+

You should also notice that several Kubernetes gatewayclass has been installed on your cluster. You can view it by running:

+
$ kubectl get gatewayclass --namespace drycc
+

Depending on the order in which the Workflow components initialize, some pods may restart. This is common during the +installation: if a component’s dependencies are not yet available, that component will exit and Kubernetes will +automatically restart it.

+

Here, it can be seen that the controller, builder and registry all took a few loops waiting for storage before they were able to start:

+
$ kubectl --namespace=drycc get pods
+NAME                          READY     STATUS    RESTARTS   AGE
+drycc-builder-hy3xv            1/1       Running   5          5m
+drycc-controller-g3cu8         1/1       Running   5          5m
+drycc-controller-celery-cmxxn  3/3       Running   0          5m
+drycc-database-rad1o           1/1       Running   0          5m
+drycc-logger-fluentbit-1v8uk   1/1       Running   0          5m
+drycc-logger-fluentbit-esm60   1/1       Running   0          5m
+drycc-logger-sm8b3             1/1       Running   0          5m
+drycc-storage-4ww3t            1/1       Running   0          5m
+drycc-registry-asozo           1/1       Running   1          5m
+drycc-rabbitmq-0               1/1       Running   0          5m
+

Install a Kubernetes Gateway

+

Now that Workflow has been deployed with the global.gatewayClass , we will need a Kubernetes gateway in place to begin routing traffic.

+

Here is an example of how to use istio as an gateway for Workflow. Of course, you are welcome to use any controller you wish.

+
$ helm repo add istio https://istio-release.storage.googleapis.com/charts
+$ helm repo update
+$ kubectl create namespace istio-system
+$ helm install istio-base istio/base -n istio-system
+$ helm install istiod istio/istiod -n istio-system --wait
+$ kubectl create namespace istio-ingress
+$ helm install istio-ingress istio/gateway -n istio-ingress --wait
+

Configure DNS

+

User must install drycc and then set up a hostname, and assumes the *.$host convention.

+

We need to point the *.$host record to the public IP address of your gateway. You can get the public IP using the following command. A wildcard entry is necessary here as apps will use the same rule after they are deployed.

+
$ kubectl get gateway --namespace drycc
+NAME      CLASS   ADDRESS         PROGRAMMED   AGE
+gateway   istio   138.91.243.152  True         36d
+

If we were using drycc.cc as a hostname, we would need to create the following A DNS records.

+ + + + + + + + + + + + + + + +
NameTypeValue
*.drycc.ccA138.91.243.152
+

Once all of the pods are in the READY state, and *.$host resolves to the external IP found above, the preparation of gateway has been completed!

+

After installing Workflow, register a user and deploy an application.

+

If your k8s does not provide public network loadblance, you need to install TCP proxy services such as haproxy on machines that can +access both internal and external networks, and then expose 80 and 443.

+ +
+ + + + + + + + + + + +
+ +

3 - Installing Drycc Workflow

+
This document is aimed at those who have already provisioned a Kubernetes cluster and want to install Drycc Workflow.
+

If help is required getting started with Kubernetes and +Drycc Workflow, follow the quickstart guide for assistance.

+

Prerequisites

+
    +
  1. Verify the Kubernetes system requirements
  2. +
  3. Install Helm and Drycc Workflow CLI tools
  4. +
+

Check Your Setup

+

Check that the helm command is available and the version is v2.5.0 or newer.

+
$ helm version
+Client: &version.Version{SemVer:"v2.5.0", GitCommit:"012cb0ac1a1b2f888144ef5a67b8dab6c2d45be6", GitTreeState:"clean"}
+Server: &version.Version{SemVer:"v2.5.0", GitCommit:"012cb0ac1a1b2f888144ef5a67b8dab6c2d45be6", GitTreeState:"clean"}
+

Choose Your Deployment Strategy

+

Drycc Workflow includes everything it needs to run out of the box. However, these defaults are aimed at simplicity rather than +production readiness. Production and staging deployments of Workflow should, at a minimum, use off-cluster storage +which is used by Workflow components to store and backup critical data. Should an operator need to completely re-install +Workflow, the required components can recover from off-cluster storage. See the documentation for configuring object +storage for more details.

+

More rigorous installations would benefit from using outside sources for the following things:

+ +

Gateway

+

Now, workflow requires that gateway and cert-manager must be installed. Any compatible Kubernetes entry controller can be used.

+

Install Drycc Workflow

+

If the version of helm is 3.0 +; you need to create the namespace in advance:

+
kubectl create ns drycc
+

If you want to change it, set the variable when using helm.

+
$ helm install drycc oci://registry.drycc.cc/charts/workflow \
+    --namespace drycc \
+    --set builder.imageRegistry=quay.io \
+    --set imagebuilder.imageRegistry=quay.io \
+    --set controller.imageRegistry=quay.io \
+    --set database.imageRegistry=quay.io \
+    --set fluentbit.imageRegistry=quay.io \
+    --set redis.imageRegistry=quay.io \
+    --set rabbitmq.imageRegistry=quay.io \
+    --set logger.imageRegistry=quay.io \
+    --set storage.imageRegistry=quay.io \
+    --set monitor.imageRegistry=quay.io \
+    --set registry.imageRegistry=quay.io \
+    --set registry-proxy.imageRegistry=quay.io \
+    --set global.platformDomain=drycc.cc
+

Helm will install a variety of Kubernetes resources in the drycc namespace. +Wait for the pods that Helm launched to be ready. Monitor their status by running:

+
$ kubectl --namespace=drycc get pods
+

If it’s preferred to have kubectl automatically update as the pod states change, run (type Ctrl-C to stop the watch):

+
$ kubectl --namespace=drycc get pods -w
+

Depending on the order in which the Workflow components initialize, some pods may restart. This is common during the +installation: if a component’s dependencies are not yet available, that component will exit and Kubernetes will +automatically restart it.

+

Here, it can be seen that the controller, builder and registry all took a few loops before they were able to start:

+
$ kubectl --namespace=drycc get pods
+NAME                                     READY     STATUS    RESTARTS   AGE
+drycc-builder-574483744-l15zj             1/1       Running   0          4m
+drycc-controller-3953262871-pncgq         1/1       Running   2          4m
+drycc-controller-celery-cmxxn             3/3       Running   0          4m
+drycc-database-83844344-47ld6             1/1       Running   0          4m
+drycc-logger-176328999-wjckx              1/1       Running   4          4m
+drycc-logger-fluentbit-zxnqb              1/1       Running   0          4m
+drycc-redis-304849759-1f35p               1/1       Running   0          4m
+drycc-storage-676004970-nxqgt             1/1       Running   0          4m
+drycc-monitor-grafana-432627134-lnl2h     1/1       Running   0          4m
+drycc-monitor-telegraf-wmcmn              1/1       Running   1          4m
+drycc-registry-756475849-lwc6b            1/1       Running   1          4m
+drycc-registry-proxy-96c4p                1/1       Running   0          4m
+drycc-rabbitmq-0                          1/1       Running   0          4m
+

Once all of the pods are in the READY state, Drycc Workflow is up and running!

+

For more installation parameters, please check the values.yaml file of workflow.

+

After installing Workflow, register a user and deploy an application.

+

Configure DNS

+

User must to set up a hostname, and assumes the drycc-builder.$host convention.

+

We need to point the drycc-builder.$host record to the public IP address of your builder. You can get the public IP using the following command. A wildcard entry is necessary here as apps will use the same rule after they are deployed.

+
$ kubectl get svc drycc-builder --namespace drycc
+NAME              CLUSTER-IP   EXTERNAL-IP      PORT(S)                      AGE
+drycc-builder     10.0.25.3    138.91.243.152   2222:31625/TCP               33m
+

If we were using drycc.cc as a hostname, we would need to create the following A DNS records.

+ + + + + + + + + + + + + + + +
NameTypeValue
drycc-builder.drycc.ccA138.91.243.152
+

Once all of the pods are in the READY state, and drycc-builder.$host resolves to the external IP found above, Workflow is up and running!

+

After installing Workflow, register a user and deploy an application.

+

If your k8s does not provide public network loadblance, you need to install TCP proxy services such as haproxy on machines that can +access both internal and external networks, and then expose 80 and 443.

+ +
+ + + + + + + + + + + +
+ +

4 - Configuring Object Storage

+
A variety of Drycc Workflow components rely on an object storage system to do their work including storing application slugs, Container images and database logs.
+

Drycc Workflow ships with Storage by default, which provides in-cluster.

+

Configuring off-cluster Object Storage

+

Every component that relies on object storage uses two inputs for configuration:

+
    +
  1. You must use object storage services that are compatible with S3 API
  2. +
  3. Access credentials stored as a Kubernetes secret named storage-creds
  4. +
+

The helm chart for Drycc Workflow can be easily configured to connect Workflow components to off-cluster object storage. Drycc Workflow currently supports Google Compute Storage, Amazon S3, Azure Blob Storage and OpenStack Swift Storage.

+

Step 1: Create storage buckets

+

Create storage buckets for each of the Workflow subsystems: builder, registry, and database.

+

Depending on your chosen object storage you may need to provide globally unique bucket names. If you are using S3, use hyphens instead of periods in the bucket names. Using periods in the bucket name will cause an ssl certificate validation issue with S3.

+

If you provide credentials with sufficient access to the underlying storage, Workflow components will create the buckets if they do not exist.

+

Step 2: Generate storage credentials

+

If applicable, generate credentials that have create and write access to the storage buckets created in Step 1.

+

If you are using AWS S3 and your Kubernetes nodes are configured with appropriate IAM API keys via InstanceRoles, you do not need to create API credentials. Do, however, validate that the InstanceRole has appropriate permissions to the configured buckets!

+

Step 3: Configure Workflow Chart

+

Operators should configure object storage by editing the Helm values file before running helm install. To do so:

+
    +
  • Fetch the Helm values by running helm inspect values oci://registry.drycc.cc/charts/workflow > values.yaml
  • +
  • Update the global/storage parameter to reference the platform you are using, e.g. s3, azure, gcs, or swift
  • +
  • Find the corresponding section for your storage type and provide appropriate values including region, bucket names, and access credentials.
  • +
  • Save your changes.
  • +
+

!!! note +All values will be automatically (base64) encoded except the key_json values under gcs/gcr. These must be base64-encoded. This is to support cleanly passing said encoded text via helm --set cli functionality rather than attempting to pass the raw JSON data. For example:

+
	$ helm install drycc oci://registry.drycc.cc/charts/workflow \
+	    --namespace drycc \
+		--set global.platformDomain=youdomain.com
+		--set global.storage=gcs,gcs.key_json="$(cat /path/to/gcs_creds.json | base64 -w 0)"
+
+

You are now ready to run helm install drycc oci://registry.drycc.cc/charts/workflow --namespace drycc -f values.yaml using your desired object storage.

+ +
+ + + + + + + + + + + +
+ +

5 - Configuring Postgres

+
Drycc Workflow’s controller and passport component rely on a PostgreSQL database to store platform state.
+

Configuring Postgres

+

By default, Drycc Workflow ships with the database component, which provides an in-cluster PostgreSQL database backed up to in-cluster or off-cluster object storage. Currently, for object storage, which is utilized by several Workflow components, only off-cluster solutions such as S3 or GCS are recommended in production environments. Experience has shown that many operators already opting for off-cluster object storage similarly prefer to host Postgres off-cluster as well, using Amazon RDS or similar. When excercising both options, a Workflow installation becomes entirely stateless, and is thus restored or rebuilt with greater ease should the need ever arise.

+

Provisioning off-cluster Postgres

+

First, provision a PostgreSQL RDBMS using the cloud provider or other infrastructure of your choice. Take care to ensure that security groups or other firewall rules will permit connectivity from your Kubernetes worker nodes, any of which may play host to the Workflow controller component.

+

Take note of the following:

+
    +
  1. The hostname or public IP of your PostgreSQL RDBMS
  2. +
  3. The port on which your PostgreSQL RDBMS runs– typically 5432
  4. +
+

Within the off-cluster RDBMS, manually provision the following:

+
    +
  1. A database user (take note of the username and password)
  2. +
  3. A database owned by that user (take note of its name)
  4. +
+

If you are able to log into the RDBMS as a superuser or a user with appropriate permissions, this process will typically look like this:

+
$ psql -h <host> -p <port> -d postgres -U <"postgres" or your own username>
+> create user <drycc username; typically "drycc"> with password '<password>';
+> create database <database name; typically "drycc"> with owner <drycc username>;
+> \q
+

Configuring Workflow

+

The Helm chart for Drycc Workflow can be easily configured to connect the Workflow controller component to an off-cluster PostgreSQL database.

+
    +
  • Step 1: If you haven’t already fetched the values, do so with helm inspect values drycc/workflow > values.yaml
  • +
  • Step 2: Update database connection details by modifying values.yaml: +
      +
    • Update the databaseLocation parameter to off-cluster.
    • +
    • Update the values in the [database] configuration section to properly reflect all connection details.
    • +
    • Update the values in the [controller] configuration section to properly reflect platformDomain details.
    • +
    • Save your changes.
    • +
    • Note: you do not need to (and must not) base64 encode any values, as the Helm chart will automatically handle encoding as necessary.
    • +
    +
  • +
+

You are now ready to helm install drycc oci://registry.drycc.cc/charts/workflow --namespace drycc -f values.yaml as usual.

+ +
+ + + + + + + + + + + +
+ +

6 - Configuring Registry

+
Drycc Workflow’s builder component relies on a registry for storing application container images.
+

Drycc Workflow ships with a registry component by default, which provides an in-cluster Container registry backed by the platform-configured object storage. Operators might want to use an off-cluster registry for performance or security reasons.

+

Configuring Off-Cluster Private Registry

+

Every component that relies on a registry uses two inputs for configuration:

+
    +
  1. Registry Location environment variable named DRYCC_REGISTRY_LOCATION
  2. +
  3. Access credentials stored as a Kubernetes secret named registry-secret
  4. +
+

The Helm chart for Drycc Workflow can be easily configured to connect Workflow components to off-cluster registry. Drycc Workflow supports external registries which provide either short-lived tokens that are valid only for a specified amount of time or long-lived tokens (basic username/password) which are valid forever for authenticating to them. For those registries which provide short lived tokens for authentication, Drycc Workflow will generate and refresh them such that the deployed apps will only have access to the short-lived tokens and not to the actual credentials for the registries.

+

When using a private registry the container images are no longer pulled by Drycc Workflow Controller but rather are managed by Kubernetes. This will increase security and overall speed, however the port information can no longer be discovered. Instead the port information can be set via drycc config:set PORT=<port> prior to deploying the application.

+

Drycc Workflow currently supports:

+
    +
  1. off-cluster: Any provider which supports long-lived username/password authentication, such as Azure Container Registry, Docker Hub, quay.io, or a self-hosted Container registry.
  2. +
+

Configuration

+
    +
  1. If you haven’t already fetched the values file, do so with helm inspect values drycc/workflow > values.yaml
  2. +
  3. Update registry location details by modifying the values file: +* Update the registryLocation parameter to reference the registry location you are using: off-cluster, ecr, gcr +* Update the values in the section which corresponds to your registry location type.
  4. +
+

You are now ready to helm install drycc oci://registry.drycc.cc/charts/workflow --namespace drycc -f values.yaml using your desired registry.

+

Examples

+

Here we show how the relevant parts of the fetched values.yaml file might look like after configuring for a particular off-cluster registry:

+

Azure Container Registry (ACR)

+

After following the docs and creating a registry, e.g. myregistry, with its corresponding login server of myregistry.azurecr.io, the following values should be supplied:

+
global:
+...
+  registryLocation: "off-cluster"
+...
+registry-token-refresher:
+...
+  registry:
+    hostname: "myregistry.azurecr.io"
+    organization: "myorg"
+    username: "myusername"
+    password: "mypassword"
+...
+

Note: The mandatory organization field (here myorg) will be created as an ACR repository if it does not already exist.

+

Quay.io

+
global:
+...
+  registryLocation: "off-cluster"
+...
+registry-token-refresher:
+...
+  registry:
+    hostname: "quay.io"
+    organization: "myorg"
+    username: "myusername"
+    password: "mypassword"
+...
+
+
+ + + + + + + + + +
+
+
+ + +
+ + + + + + diff --git a/docs/installing-workflow/configuring-object-storage/index.html b/docs/installing-workflow/configuring-object-storage/index.html new file mode 100644 index 000000000..4cdf30c3b --- /dev/null +++ b/docs/installing-workflow/configuring-object-storage/index.html @@ -0,0 +1,496 @@ + + + + + + + + + + + + + + + + + + + +Configuring Object Storage | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Configuring Object Storage

+
A variety of Drycc Workflow components rely on an object storage system to do their work including storing application slugs, Container images and database logs.
+ +

Drycc Workflow ships with Storage by default, which provides in-cluster.

+

Configuring off-cluster Object Storage

+

Every component that relies on object storage uses two inputs for configuration:

+
    +
  1. You must use object storage services that are compatible with S3 API
  2. +
  3. Access credentials stored as a Kubernetes secret named storage-creds
  4. +
+

The helm chart for Drycc Workflow can be easily configured to connect Workflow components to off-cluster object storage. Drycc Workflow currently supports Google Compute Storage, Amazon S3, Azure Blob Storage and OpenStack Swift Storage.

+

Step 1: Create storage buckets

+

Create storage buckets for each of the Workflow subsystems: builder, registry, and database.

+

Depending on your chosen object storage you may need to provide globally unique bucket names. If you are using S3, use hyphens instead of periods in the bucket names. Using periods in the bucket name will cause an ssl certificate validation issue with S3.

+

If you provide credentials with sufficient access to the underlying storage, Workflow components will create the buckets if they do not exist.

+

Step 2: Generate storage credentials

+

If applicable, generate credentials that have create and write access to the storage buckets created in Step 1.

+

If you are using AWS S3 and your Kubernetes nodes are configured with appropriate IAM API keys via InstanceRoles, you do not need to create API credentials. Do, however, validate that the InstanceRole has appropriate permissions to the configured buckets!

+

Step 3: Configure Workflow Chart

+

Operators should configure object storage by editing the Helm values file before running helm install. To do so:

+
    +
  • Fetch the Helm values by running helm inspect values oci://registry.drycc.cc/charts/workflow > values.yaml
  • +
  • Update the global/storage parameter to reference the platform you are using, e.g. s3, azure, gcs, or swift
  • +
  • Find the corresponding section for your storage type and provide appropriate values including region, bucket names, and access credentials.
  • +
  • Save your changes.
  • +
+

!!! note +All values will be automatically (base64) encoded except the key_json values under gcs/gcr. These must be base64-encoded. This is to support cleanly passing said encoded text via helm --set cli functionality rather than attempting to pass the raw JSON data. For example:

+
	$ helm install drycc oci://registry.drycc.cc/charts/workflow \
+	    --namespace drycc \
+		--set global.platformDomain=youdomain.com
+		--set global.storage=gcs,gcs.key_json="$(cat /path/to/gcs_creds.json | base64 -w 0)"
+
+

You are now ready to run helm install drycc oci://registry.drycc.cc/charts/workflow --namespace drycc -f values.yaml using your desired object storage.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/installing-workflow/configuring-postgres/index.html b/docs/installing-workflow/configuring-postgres/index.html new file mode 100644 index 000000000..3df606489 --- /dev/null +++ b/docs/installing-workflow/configuring-postgres/index.html @@ -0,0 +1,494 @@ + + + + + + + + + + + + + + + + + + + +Configuring Postgres | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Configuring Postgres

+
Drycc Workflow’s controller and passport component rely on a PostgreSQL database to store platform state.
+ +

Configuring Postgres

+

By default, Drycc Workflow ships with the database component, which provides an in-cluster PostgreSQL database backed up to in-cluster or off-cluster object storage. Currently, for object storage, which is utilized by several Workflow components, only off-cluster solutions such as S3 or GCS are recommended in production environments. Experience has shown that many operators already opting for off-cluster object storage similarly prefer to host Postgres off-cluster as well, using Amazon RDS or similar. When excercising both options, a Workflow installation becomes entirely stateless, and is thus restored or rebuilt with greater ease should the need ever arise.

+

Provisioning off-cluster Postgres

+

First, provision a PostgreSQL RDBMS using the cloud provider or other infrastructure of your choice. Take care to ensure that security groups or other firewall rules will permit connectivity from your Kubernetes worker nodes, any of which may play host to the Workflow controller component.

+

Take note of the following:

+
    +
  1. The hostname or public IP of your PostgreSQL RDBMS
  2. +
  3. The port on which your PostgreSQL RDBMS runs– typically 5432
  4. +
+

Within the off-cluster RDBMS, manually provision the following:

+
    +
  1. A database user (take note of the username and password)
  2. +
  3. A database owned by that user (take note of its name)
  4. +
+

If you are able to log into the RDBMS as a superuser or a user with appropriate permissions, this process will typically look like this:

+
$ psql -h <host> -p <port> -d postgres -U <"postgres" or your own username>
+> create user <drycc username; typically "drycc"> with password '<password>';
+> create database <database name; typically "drycc"> with owner <drycc username>;
+> \q
+

Configuring Workflow

+

The Helm chart for Drycc Workflow can be easily configured to connect the Workflow controller component to an off-cluster PostgreSQL database.

+
    +
  • Step 1: If you haven’t already fetched the values, do so with helm inspect values drycc/workflow > values.yaml
  • +
  • Step 2: Update database connection details by modifying values.yaml: +
      +
    • Update the databaseLocation parameter to off-cluster.
    • +
    • Update the values in the [database] configuration section to properly reflect all connection details.
    • +
    • Update the values in the [controller] configuration section to properly reflect platformDomain details.
    • +
    • Save your changes.
    • +
    • Note: you do not need to (and must not) base64 encode any values, as the Helm chart will automatically handle encoding as necessary.
    • +
    +
  • +
+

You are now ready to helm install drycc oci://registry.drycc.cc/charts/workflow --namespace drycc -f values.yaml as usual.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/installing-workflow/configuring-registry/index.html b/docs/installing-workflow/configuring-registry/index.html new file mode 100644 index 000000000..725854ae8 --- /dev/null +++ b/docs/installing-workflow/configuring-registry/index.html @@ -0,0 +1,517 @@ + + + + + + + + + + + + + + + + + + + +Configuring Registry | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Configuring Registry

+
Drycc Workflow’s builder component relies on a registry for storing application container images.
+ +

Drycc Workflow ships with a registry component by default, which provides an in-cluster Container registry backed by the platform-configured object storage. Operators might want to use an off-cluster registry for performance or security reasons.

+

Configuring Off-Cluster Private Registry

+

Every component that relies on a registry uses two inputs for configuration:

+
    +
  1. Registry Location environment variable named DRYCC_REGISTRY_LOCATION
  2. +
  3. Access credentials stored as a Kubernetes secret named registry-secret
  4. +
+

The Helm chart for Drycc Workflow can be easily configured to connect Workflow components to off-cluster registry. Drycc Workflow supports external registries which provide either short-lived tokens that are valid only for a specified amount of time or long-lived tokens (basic username/password) which are valid forever for authenticating to them. For those registries which provide short lived tokens for authentication, Drycc Workflow will generate and refresh them such that the deployed apps will only have access to the short-lived tokens and not to the actual credentials for the registries.

+

When using a private registry the container images are no longer pulled by Drycc Workflow Controller but rather are managed by Kubernetes. This will increase security and overall speed, however the port information can no longer be discovered. Instead the port information can be set via drycc config:set PORT=<port> prior to deploying the application.

+

Drycc Workflow currently supports:

+
    +
  1. off-cluster: Any provider which supports long-lived username/password authentication, such as Azure Container Registry, Docker Hub, quay.io, or a self-hosted Container registry.
  2. +
+

Configuration

+
    +
  1. If you haven’t already fetched the values file, do so with helm inspect values drycc/workflow > values.yaml
  2. +
  3. Update registry location details by modifying the values file: +* Update the registryLocation parameter to reference the registry location you are using: off-cluster, ecr, gcr +* Update the values in the section which corresponds to your registry location type.
  4. +
+

You are now ready to helm install drycc oci://registry.drycc.cc/charts/workflow --namespace drycc -f values.yaml using your desired registry.

+

Examples

+

Here we show how the relevant parts of the fetched values.yaml file might look like after configuring for a particular off-cluster registry:

+

Azure Container Registry (ACR)

+

After following the docs and creating a registry, e.g. myregistry, with its corresponding login server of myregistry.azurecr.io, the following values should be supplied:

+
global:
+...
+  registryLocation: "off-cluster"
+...
+registry-token-refresher:
+...
+  registry:
+    hostname: "myregistry.azurecr.io"
+    organization: "myorg"
+    username: "myusername"
+    password: "mypassword"
+...
+

Note: The mandatory organization field (here myorg) will be created as an ACR repository if it does not already exist.

+

Quay.io

+
global:
+...
+  registryLocation: "off-cluster"
+...
+registry-token-refresher:
+...
+  registry:
+    hostname: "quay.io"
+    organization: "myorg"
+    username: "myusername"
+    password: "mypassword"
+...
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/installing-workflow/download-linux-brightgreen.svg b/docs/installing-workflow/download-linux-brightgreen.svg new file mode 100644 index 000000000..a8a6a50be --- /dev/null +++ b/docs/installing-workflow/download-linux-brightgreen.svg @@ -0,0 +1 @@ +downloaddownloadLinuxLinux \ No newline at end of file diff --git a/docs/installing-workflow/download-osx-brightgreen.svg b/docs/installing-workflow/download-osx-brightgreen.svg new file mode 100644 index 000000000..477afbf52 --- /dev/null +++ b/docs/installing-workflow/download-osx-brightgreen.svg @@ -0,0 +1 @@ +downloaddownloadMac OS XMac OS X \ No newline at end of file diff --git a/docs/installing-workflow/gateway/index.html b/docs/installing-workflow/gateway/index.html new file mode 100644 index 000000000..adb1f49c4 --- /dev/null +++ b/docs/installing-workflow/gateway/index.html @@ -0,0 +1,535 @@ + + + + + + + + + + + + + + + + + + + +Specify Gateway | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Specify Gateway

+
Choose the gateway provider that best suits your needs and platform.
+ +

Install Drycc Workflow (Specify gateway)

+

Now that Helm is installed and the repository has been added, install Workflow with a native gateway by running:

+
$ helm install drycc oci://registry.drycc.cc/charts/workflow \
+    --namespace drycc \
+    --set global.gatewayClass=istio \
+    --set global.platformDomain=drycc.cc \
+    --set builder.service.type=LoadBalancer
+

Of course, if you deploy it on a bare machine, you probably do not have Load Balancer. You need to use NodePort:

+
$ helm install drycc oci://registry.drycc.cc/charts/workflow \
+    --namespace drycc \
+    --set global.gatewayClass=istio \
+    --set global.platformDomain=drycc.cc \
+    --set builder.service.type=NodePort \
+    --set builder.service.nodePort=32222
+

If you want to use Load Balancer on a bare machine, you can look at metallb

+

Where global.platformDomain is a required parameter that is traditionally not required for Workflow that is explained in the next section. In this example we are using drycc.cc for $hostname.

+

Helm will install a variety of Kubernetes resources in the drycc namespace. +Wait for the pods that Helm launched to be ready. Monitor their status by running:

+
$ kubectl --namespace=drycc get pods
+

You should also notice that several Kubernetes gatewayclass has been installed on your cluster. You can view it by running:

+
$ kubectl get gatewayclass --namespace drycc
+

Depending on the order in which the Workflow components initialize, some pods may restart. This is common during the +installation: if a component’s dependencies are not yet available, that component will exit and Kubernetes will +automatically restart it.

+

Here, it can be seen that the controller, builder and registry all took a few loops waiting for storage before they were able to start:

+
$ kubectl --namespace=drycc get pods
+NAME                          READY     STATUS    RESTARTS   AGE
+drycc-builder-hy3xv            1/1       Running   5          5m
+drycc-controller-g3cu8         1/1       Running   5          5m
+drycc-controller-celery-cmxxn  3/3       Running   0          5m
+drycc-database-rad1o           1/1       Running   0          5m
+drycc-logger-fluentbit-1v8uk   1/1       Running   0          5m
+drycc-logger-fluentbit-esm60   1/1       Running   0          5m
+drycc-logger-sm8b3             1/1       Running   0          5m
+drycc-storage-4ww3t            1/1       Running   0          5m
+drycc-registry-asozo           1/1       Running   1          5m
+drycc-rabbitmq-0               1/1       Running   0          5m
+

Install a Kubernetes Gateway

+

Now that Workflow has been deployed with the global.gatewayClass , we will need a Kubernetes gateway in place to begin routing traffic.

+

Here is an example of how to use istio as an gateway for Workflow. Of course, you are welcome to use any controller you wish.

+
$ helm repo add istio https://istio-release.storage.googleapis.com/charts
+$ helm repo update
+$ kubectl create namespace istio-system
+$ helm install istio-base istio/base -n istio-system
+$ helm install istiod istio/istiod -n istio-system --wait
+$ kubectl create namespace istio-ingress
+$ helm install istio-ingress istio/gateway -n istio-ingress --wait
+

Configure DNS

+

User must install drycc and then set up a hostname, and assumes the *.$host convention.

+

We need to point the *.$host record to the public IP address of your gateway. You can get the public IP using the following command. A wildcard entry is necessary here as apps will use the same rule after they are deployed.

+
$ kubectl get gateway --namespace drycc
+NAME      CLASS   ADDRESS         PROGRAMMED   AGE
+gateway   istio   138.91.243.152  True         36d
+

If we were using drycc.cc as a hostname, we would need to create the following A DNS records.

+ + + + + + + + + + + + + + + +
NameTypeValue
*.drycc.ccA138.91.243.152
+

Once all of the pods are in the READY state, and *.$host resolves to the external IP found above, the preparation of gateway has been completed!

+

After installing Workflow, register a user and deploy an application.

+

If your k8s does not provide public network loadblance, you need to install TCP proxy services such as haproxy on machines that can +access both internal and external networks, and then expose 80 and 443.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/installing-workflow/index.html b/docs/installing-workflow/index.html new file mode 100644 index 000000000..15f1a70fd --- /dev/null +++ b/docs/installing-workflow/index.html @@ -0,0 +1,490 @@ + + + + + + + + + + + + + + + + + + + + + +Installing To Kubenetes | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Installing To Kubenetes

+
Deploying Drycc on a Kubernetes Cluster.
+ + +
+ + +
+
+
+ Requirements +
+

To run Drycc Workflow on a Kubernetes cluster, there are a few requirements to keep in mind.

+
+
+
+ Specify Gateway +
+

Choose the gateway provider that best suits your needs and platform.

+
+
+
+ Installing Drycc Workflow +
+

This document is aimed at those who have already provisioned a Kubernetes cluster and want to install Drycc Workflow.

+
+
+
+ Configuring Object Storage +
+

A variety of Drycc Workflow components rely on an object storage system to do their work including storing application slugs, Container images and database logs.

+
+
+
+ Configuring Postgres +
+

Drycc Workflow’s controller and passport component rely on a PostgreSQL database to store platform state.

+
+
+
+ Configuring Registry +
+

Drycc Workflow’s builder component relies on a registry for storing application container images.

+
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+
+ +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/installing-workflow/index.xml b/docs/installing-workflow/index.xml new file mode 100644 index 000000000..925eecf20 --- /dev/null +++ b/docs/installing-workflow/index.xml @@ -0,0 +1,415 @@ + + + Drycc – Installing To Kubenetes + /docs/installing-workflow/ + Recent content in Installing To Kubenetes on Drycc + Hugo -- gohugo.io + en + + + + + + + + + + + Docs: Requirements + /docs/installing-workflow/system-requirements/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/installing-workflow/system-requirements/ + + + + <h2 id="kubernetes-versions">Kubernetes Versions<a class="td-heading-self-link" href="#kubernetes-versions" aria-label="Heading self-link"></a></h2> +<p>Drycc Workflow requires Kubernetes v1.16.15 or later.</p> +<h2 id="components-requirements">Components Requirements<a class="td-heading-self-link" href="#components-requirements" aria-label="Heading self-link"></a></h2> +<p>Drycc uses gateway as a routing implementation, so you have to choose an gateway. We recommend using <a href="https://istio.io/">istio</a> or <a href="https://konghq.com/">kong</a>.</p> +<p>Workflow supports the use of ACME to manage automatic certificates, <a href="https://github.com/helm/charts/tree/master/stable/cert-manager">cert-manager</a> is also one of the necessary components, if you use cert-manager EAB, you need to set the <code>clusterResourceNamespace</code> to the namespace of drycc.</p> +<p>Workflow supports stateful apps. You can create and use them through the &lsquo;drycc volumes&rsquo; command. If you want to use this feature, you must have a <code>StorageClass</code> that supports <code>ReadWriteMany</code>.</p> +<p>Workflow also supports the <a href="https://github.com/openservicebrokerapi/servicebroker">OSB</a> API through the &lsquo;drycc resources&rsquo; command. If you want to use this function, you need to install <a href="https://service-catalog.drycc.cc">service-catalog</a>.</p> +<h2 id="storage-requirements">Storage Requirements<a class="td-heading-self-link" href="#storage-requirements" aria-label="Heading self-link"></a></h2> +<p>A variety of Drycc Workflow components rely on an object storage system to do their work, including storing application +slugs, Container images and database logs.</p> +<p>Drycc Workflow ships with drycc storage by default, which provides in-cluster.</p> +<p>Workflow supports Amazon Simple Storage Service (S3), Google Cloud Storage (GCS), OpenShift Swift, and Azure Blob +Storage. See <a href="/docs/installing-workflow/configuring-object-storage/">configuring object storage</a> for setup instructions.</p> +<h2 id="resource-requirements">Resource Requirements<a class="td-heading-self-link" href="#resource-requirements" aria-label="Heading self-link"></a></h2> +<p>When deploying Drycc Workflow, it&rsquo;s important to provision machines with adequate resources. Drycc is a highly-available +distributed system, which means that Drycc components and your deployed applications will move around the cluster onto +healthy hosts as hosts leave the cluster for various reasons (failures, reboots, autoscalers, etc.). Because of this, +you should have ample spare resources on any machine in your cluster to withstand the additional load of running +services for failed machines.</p> +<p>Drycc Workflow components use about 2.5GB of memory across the cluster, and require approximately 30GB of hard disk +space. Because it may need to handle additional load if another one fails, each machine has minimum requirements of:</p> +<ul> +<li>At least 4GB of RAM (more is better)</li> +<li>At least 40GB of hard disk space</li> +</ul> +<p>Note that these estimates are for Drycc Workflow and Kubernetes only. Be sure to leave enough spare capacity for your +application footprint as well.</p> +<p>Running smaller machines will likely result in increased system load and has been known to result in component failures +and instability.</p> + + + + + + Docs: Specify Gateway + /docs/installing-workflow/gateway/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/installing-workflow/gateway/ + + + + <h2 id="install-drycc-workflow-specify-gateway">Install Drycc Workflow (Specify gateway)<a class="td-heading-self-link" href="#install-drycc-workflow-specify-gateway" aria-label="Heading self-link"></a></h2> +<p>Now that Helm is installed and the repository has been added, install Workflow with a native gateway by running:</p> +<pre tabindex="0"><code>$ helm install drycc oci://registry.drycc.cc/charts/workflow \ + --namespace drycc \ + --set global.gatewayClass=istio \ + --set global.platformDomain=drycc.cc \ + --set builder.service.type=LoadBalancer +</code></pre><p>Of course, if you deploy it on a bare machine, you probably do not have Load Balancer. You need to use NodePort:</p> +<pre tabindex="0"><code>$ helm install drycc oci://registry.drycc.cc/charts/workflow \ + --namespace drycc \ + --set global.gatewayClass=istio \ + --set global.platformDomain=drycc.cc \ + --set builder.service.type=NodePort \ + --set builder.service.nodePort=32222 +</code></pre><p>If you want to use Load Balancer on a bare machine, you can look at <a href="https://github.com/metallb/metallb">metallb</a></p> +<p>Where <code>global.platformDomain</code> is a <strong>required</strong> parameter that is traditionally not required for Workflow that is explained in the next section. In this example we are using <code>drycc.cc</code> for <code>$hostname</code>.</p> +<p>Helm will install a variety of Kubernetes resources in the <code>drycc</code> namespace. +Wait for the pods that Helm launched to be ready. Monitor their status by running:</p> +<pre tabindex="0"><code>$ kubectl --namespace=drycc get pods +</code></pre><p>You should also notice that several Kubernetes gatewayclass has been installed on your cluster. You can view it by running:</p> +<pre tabindex="0"><code>$ kubectl get gatewayclass --namespace drycc +</code></pre><p>Depending on the order in which the Workflow components initialize, some pods may restart. This is common during the +installation: if a component&rsquo;s dependencies are not yet available, that component will exit and Kubernetes will +automatically restart it.</p> +<p>Here, it can be seen that the controller, builder and registry all took a few loops waiting for storage before they were able to start:</p> +<pre tabindex="0"><code>$ kubectl --namespace=drycc get pods +NAME READY STATUS RESTARTS AGE +drycc-builder-hy3xv 1/1 Running 5 5m +drycc-controller-g3cu8 1/1 Running 5 5m +drycc-controller-celery-cmxxn 3/3 Running 0 5m +drycc-database-rad1o 1/1 Running 0 5m +drycc-logger-fluentbit-1v8uk 1/1 Running 0 5m +drycc-logger-fluentbit-esm60 1/1 Running 0 5m +drycc-logger-sm8b3 1/1 Running 0 5m +drycc-storage-4ww3t 1/1 Running 0 5m +drycc-registry-asozo 1/1 Running 1 5m +drycc-rabbitmq-0 1/1 Running 0 5m +</code></pre><h2 id="install-a-kubernetes-gateway">Install a Kubernetes Gateway<a class="td-heading-self-link" href="#install-a-kubernetes-gateway" aria-label="Heading self-link"></a></h2> +<p>Now that Workflow has been deployed with the <code>global.gatewayClass</code> , we will need a Kubernetes gateway in place to begin routing traffic.</p> +<p>Here is an example of how to use <a href="https://istio.io/">istio</a> as an gateway for Workflow. Of course, you are welcome to use any controller you wish.</p> +<pre tabindex="0"><code>$ helm repo add istio https://istio-release.storage.googleapis.com/charts +$ helm repo update +$ kubectl create namespace istio-system +$ helm install istio-base istio/base -n istio-system +$ helm install istiod istio/istiod -n istio-system --wait +$ kubectl create namespace istio-ingress +$ helm install istio-ingress istio/gateway -n istio-ingress --wait +</code></pre><h2 id="configure-dns">Configure DNS<a class="td-heading-self-link" href="#configure-dns" aria-label="Heading self-link"></a></h2> +<p>User must install <a href="/docs/quickstart/install-workflow/">drycc</a> and then set up a hostname, and assumes the <code>*.$host</code> convention.</p> +<p>We need to point the <code>*.$host</code> record to the public IP address of your gateway. You can get the public IP using the following command. A wildcard entry is necessary here as apps will use the same rule after they are deployed.</p> +<pre tabindex="0"><code>$ kubectl get gateway --namespace drycc +NAME CLASS ADDRESS PROGRAMMED AGE +gateway istio 138.91.243.152 True 36d +</code></pre><p>If we were using <code>drycc.cc</code> as a hostname, we would need to create the following A DNS records.</p> +<table> +<thead> +<tr> +<th>Name</th> +<th style="text-align:center">Type</th> +<th style="text-align:right">Value</th> +</tr> +</thead> +<tbody> +<tr> +<td>*.drycc.cc</td> +<td style="text-align:center">A</td> +<td style="text-align:right">138.91.243.152</td> +</tr> +</tbody> +</table> +<p>Once all of the pods are in the <code>READY</code> state, and <code>*.$host</code> resolves to the external IP found above, the preparation of gateway has been completed!</p> +<p>After installing Workflow, <a href="/docs/quickstart/deploy-an-app/">register a user and deploy an application</a>.</p> +<p>If your k8s does not provide public network loadblance, you need to install TCP proxy services such as haproxy on machines that can +access both internal and external networks, and then expose <code>80</code> and <code>443</code>.</p> + + + + + + Docs: Installing Drycc Workflow + /docs/installing-workflow/workflow/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/installing-workflow/workflow/ + + + + <p>If help is required getting started with Kubernetes and +Drycc Workflow, follow the <a href="/docs/quickstart/">quickstart guide</a> for assistance.</p> +<h2 id="prerequisites">Prerequisites<a class="td-heading-self-link" href="#prerequisites" aria-label="Heading self-link"></a></h2> +<ol> +<li>Verify the <a href="/docs/installing-workflow/system-requirements/">Kubernetes system requirements</a></li> +<li>Install <a href="/docs/quickstart/install-cli-tools/">Helm and Drycc Workflow CLI</a> tools</li> +</ol> +<h2 id="check-your-setup">Check Your Setup<a class="td-heading-self-link" href="#check-your-setup" aria-label="Heading self-link"></a></h2> +<p>Check that the <code>helm</code> command is available and the version is v2.5.0 or newer.</p> +<pre tabindex="0"><code>$ helm version +Client: &amp;version.Version{SemVer:&#34;v2.5.0&#34;, GitCommit:&#34;012cb0ac1a1b2f888144ef5a67b8dab6c2d45be6&#34;, GitTreeState:&#34;clean&#34;} +Server: &amp;version.Version{SemVer:&#34;v2.5.0&#34;, GitCommit:&#34;012cb0ac1a1b2f888144ef5a67b8dab6c2d45be6&#34;, GitTreeState:&#34;clean&#34;} +</code></pre><h2 id="choose-your-deployment-strategy">Choose Your Deployment Strategy<a class="td-heading-self-link" href="#choose-your-deployment-strategy" aria-label="Heading self-link"></a></h2> +<p>Drycc Workflow includes everything it needs to run out of the box. However, these defaults are aimed at simplicity rather than +production readiness. Production and staging deployments of Workflow should, at a minimum, use off-cluster storage +which is used by Workflow components to store and backup critical data. Should an operator need to completely re-install +Workflow, the required components can recover from off-cluster storage. See the documentation for <a href="/docs/installing-workflow/configuring-object-storage/">configuring object +storage</a> for more details.</p> +<p>More rigorous installations would benefit from using outside sources for the following things:</p> +<ul> +<li><a href="/docs/installing-workflow/configuring-postgres/">Postgres</a> - For example AWS RDS.</li> +<li><a href="/docs/installing-workflow/configuring-registry/">Registry</a> - This includes <a href="https://quay.io">quay.io</a>, <a href="https://hub.docker.com">dockerhub</a>, <a href="https://aws.amazon.com/ecr/">Amazon ECR</a>, and <a href="https://cloud.google.com/container-registry/">Google GCR</a>.</li> +<li><a href="/docs/managing-workflow/platform-logging/#configuring-off-cluster-redis">Redis</a> - Such as AWS Elasticache</li> +<li><a href="/docs/managing-workflow/platform-monitoring/#off-cluster-grafana">Grafana</a></li> +</ul> +<h4 id="gateway">Gateway<a class="td-heading-self-link" href="#gateway" aria-label="Heading self-link"></a></h4> +<p>Now, workflow requires that gateway and cert-manager must be installed. Any compatible Kubernetes entry controller can be used.</p> +<h2 id="install-drycc-workflow">Install Drycc Workflow<a class="td-heading-self-link" href="#install-drycc-workflow" aria-label="Heading self-link"></a></h2> +<p>If the version of helm is 3.0 +; you need to create the namespace in advance:</p> +<pre tabindex="0"><code>kubectl create ns drycc +</code></pre><p>If you want to change it, set the variable when using helm.</p> +<pre tabindex="0"><code>$ helm install drycc oci://registry.drycc.cc/charts/workflow \ + --namespace drycc \ + --set builder.imageRegistry=quay.io \ + --set imagebuilder.imageRegistry=quay.io \ + --set controller.imageRegistry=quay.io \ + --set database.imageRegistry=quay.io \ + --set fluentbit.imageRegistry=quay.io \ + --set redis.imageRegistry=quay.io \ + --set rabbitmq.imageRegistry=quay.io \ + --set logger.imageRegistry=quay.io \ + --set storage.imageRegistry=quay.io \ + --set monitor.imageRegistry=quay.io \ + --set registry.imageRegistry=quay.io \ + --set registry-proxy.imageRegistry=quay.io \ + --set global.platformDomain=drycc.cc +</code></pre><p>Helm will install a variety of Kubernetes resources in the <code>drycc</code> namespace. +Wait for the pods that Helm launched to be ready. Monitor their status by running:</p> +<pre tabindex="0"><code>$ kubectl --namespace=drycc get pods +</code></pre><p>If it&rsquo;s preferred to have <code>kubectl</code> automatically update as the pod states change, run (type Ctrl-C to stop the watch):</p> +<pre tabindex="0"><code>$ kubectl --namespace=drycc get pods -w +</code></pre><p>Depending on the order in which the Workflow components initialize, some pods may restart. This is common during the +installation: if a component&rsquo;s dependencies are not yet available, that component will exit and Kubernetes will +automatically restart it.</p> +<p>Here, it can be seen that the controller, builder and registry all took a few loops before they were able to start:</p> +<pre tabindex="0"><code>$ kubectl --namespace=drycc get pods +NAME READY STATUS RESTARTS AGE +drycc-builder-574483744-l15zj 1/1 Running 0 4m +drycc-controller-3953262871-pncgq 1/1 Running 2 4m +drycc-controller-celery-cmxxn 3/3 Running 0 4m +drycc-database-83844344-47ld6 1/1 Running 0 4m +drycc-logger-176328999-wjckx 1/1 Running 4 4m +drycc-logger-fluentbit-zxnqb 1/1 Running 0 4m +drycc-redis-304849759-1f35p 1/1 Running 0 4m +drycc-storage-676004970-nxqgt 1/1 Running 0 4m +drycc-monitor-grafana-432627134-lnl2h 1/1 Running 0 4m +drycc-monitor-telegraf-wmcmn 1/1 Running 1 4m +drycc-registry-756475849-lwc6b 1/1 Running 1 4m +drycc-registry-proxy-96c4p 1/1 Running 0 4m +drycc-rabbitmq-0 1/1 Running 0 4m +</code></pre><p>Once all of the pods are in the <code>READY</code> state, Drycc Workflow is up and running!</p> +<p>For more installation parameters, please check the <a href="https://github.com/drycc/workflow/blob/main/charts/workflow/values.yaml">values.yaml</a> file of workflow.</p> +<p>After installing Workflow, <a href="/docs/quickstart/deploy-an-app/">register a user and deploy an application</a>.</p> +<h2 id="configure-dns">Configure DNS<a class="td-heading-self-link" href="#configure-dns" aria-label="Heading self-link"></a></h2> +<p>User must to set up a hostname, and assumes the <code>drycc-builder.$host</code> convention.</p> +<p>We need to point the <code>drycc-builder.$host</code> record to the public IP address of your builder. You can get the public IP using the following command. A wildcard entry is necessary here as apps will use the same rule after they are deployed.</p> +<pre tabindex="0"><code>$ kubectl get svc drycc-builder --namespace drycc +NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE +drycc-builder 10.0.25.3 138.91.243.152 2222:31625/TCP 33m +</code></pre><p>If we were using <code>drycc.cc</code> as a hostname, we would need to create the following A DNS records.</p> +<table> +<thead> +<tr> +<th>Name</th> +<th style="text-align:center">Type</th> +<th style="text-align:right">Value</th> +</tr> +</thead> +<tbody> +<tr> +<td>drycc-builder.drycc.cc</td> +<td style="text-align:center">A</td> +<td style="text-align:right">138.91.243.152</td> +</tr> +</tbody> +</table> +<p>Once all of the pods are in the <code>READY</code> state, and <code>drycc-builder.$host</code> resolves to the external IP found above, Workflow is up and running!</p> +<p>After installing Workflow, <a href="/docs/quickstart/deploy-an-app/">register a user and deploy an application</a>.</p> +<p>If your k8s does not provide public network loadblance, you need to install TCP proxy services such as haproxy on machines that can +access both internal and external networks, and then expose <code>80</code> and <code>443</code>.</p> + + + + + + Docs: Configuring Object Storage + /docs/installing-workflow/configuring-object-storage/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/installing-workflow/configuring-object-storage/ + + + + <p>Drycc Workflow ships with <a href="/docs/understanding-workflow/components/#object-storage">Storage</a> by default, which provides in-cluster.</p> +<h2 id="configuring-off-cluster-object-storage">Configuring off-cluster Object Storage<a class="td-heading-self-link" href="#configuring-off-cluster-object-storage" aria-label="Heading self-link"></a></h2> +<p>Every component that relies on object storage uses two inputs for configuration:</p> +<ol> +<li>You must use object storage services that are compatible with S3 API</li> +<li>Access credentials stored as a Kubernetes secret named <code>storage-creds</code></li> +</ol> +<p>The helm chart for Drycc Workflow can be easily configured to connect Workflow components to off-cluster object storage. Drycc Workflow currently supports Google Compute Storage, Amazon S3, <a href="https://azure.microsoft.com/en-us/services/storage/blobs/">Azure Blob Storage</a> and OpenStack Swift Storage.</p> +<h3 id="step-1-create-storage-buckets">Step 1: Create storage buckets<a class="td-heading-self-link" href="#step-1-create-storage-buckets" aria-label="Heading self-link"></a></h3> +<p>Create storage buckets for each of the Workflow subsystems: <code>builder</code>, <code>registry</code>, and <code>database</code>.</p> +<p>Depending on your chosen object storage you may need to provide globally unique bucket names. If you are using S3, use hyphens instead of periods in the bucket names. Using periods in the bucket name will cause an <a href="https://forums.aws.amazon.com/thread.jspa?threadID=105357">ssl certificate validation issue with S3</a>.</p> +<p>If you provide credentials with sufficient access to the underlying storage, Workflow components will create the buckets if they do not exist.</p> +<h3 id="step-2-generate-storage-credentials">Step 2: Generate storage credentials<a class="td-heading-self-link" href="#step-2-generate-storage-credentials" aria-label="Heading self-link"></a></h3> +<p>If applicable, generate credentials that have create and write access to the storage buckets created in Step 1.</p> +<p>If you are using AWS S3 and your Kubernetes nodes are configured with appropriate <a href="http://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html">IAM</a> API keys via InstanceRoles, you do not need to create API credentials. Do, however, validate that the InstanceRole has appropriate permissions to the configured buckets!</p> +<h3 id="step-3-configure-workflow-chart">Step 3: Configure Workflow Chart<a class="td-heading-self-link" href="#step-3-configure-workflow-chart" aria-label="Heading self-link"></a></h3> +<p>Operators should configure object storage by editing the Helm values file before running <code>helm install</code>. To do so:</p> +<ul> +<li>Fetch the Helm values by running <code>helm inspect values oci://registry.drycc.cc/charts/workflow &gt; values.yaml</code></li> +<li>Update the <code>global/storage</code> parameter to reference the platform you are using, e.g. <code>s3</code>, <code>azure</code>, <code>gcs</code>, or <code>swift</code></li> +<li>Find the corresponding section for your storage type and provide appropriate values including region, bucket names, and access credentials.</li> +<li>Save your changes.</li> +</ul> +<p>!!! note +All values will be automatically (base64) encoded <em>except</em> the <code>key_json</code> values under <code>gcs</code>/<code>gcr</code>. These must be base64-encoded. This is to support cleanly passing said encoded text via <code>helm --set</code> cli functionality rather than attempting to pass the raw JSON data. For example:</p> +<pre><code> $ helm install drycc oci://registry.drycc.cc/charts/workflow \ + --namespace drycc \ + --set global.platformDomain=youdomain.com + --set global.storage=gcs,gcs.key_json=&quot;$(cat /path/to/gcs_creds.json | base64 -w 0)&quot; +</code></pre> +<p>You are now ready to run <code>helm install drycc oci://registry.drycc.cc/charts/workflow --namespace drycc -f values.yaml</code> using your desired object storage.</p> + + + + + + Docs: Configuring Postgres + /docs/installing-workflow/configuring-postgres/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/installing-workflow/configuring-postgres/ + + + + <h1 id="configuring-postgres">Configuring Postgres<a class="td-heading-self-link" href="#configuring-postgres" aria-label="Heading self-link"></a></h1> +<p>By default, Drycc Workflow ships with the <a href="/docs/understanding-workflow/components/#database">database</a> component, which provides an in-cluster PostgreSQL database backed up to in-cluster or off-cluster <a href="/docs/installing-workflow/configuring-object-storage/">object storage</a>. Currently, for object storage, which is utilized by <em>several</em> Workflow components, only off-cluster solutions such as S3 or GCS are recommended in production environments. Experience has shown that many operators already opting for off-cluster object storage similarly prefer to host Postgres off-cluster as well, using Amazon RDS or similar. When excercising both options, a Workflow installation becomes entirely stateless, and is thus restored or rebuilt with greater ease should the need ever arise.</p> +<h2 id="provisioning-off-cluster-postgres">Provisioning off-cluster Postgres<a class="td-heading-self-link" href="#provisioning-off-cluster-postgres" aria-label="Heading self-link"></a></h2> +<p>First, provision a PostgreSQL RDBMS using the cloud provider or other infrastructure of your choice. Take care to ensure that security groups or other firewall rules will permit connectivity from your Kubernetes worker nodes, any of which may play host to the Workflow controller component.</p> +<p>Take note of the following:</p> +<ol> +<li>The hostname or public IP of your PostgreSQL RDBMS</li> +<li>The port on which your PostgreSQL RDBMS runs&ndash; typically 5432</li> +</ol> +<p>Within the off-cluster RDBMS, manually provision the following:</p> +<ol> +<li>A database user (take note of the username and password)</li> +<li>A database owned by that user (take note of its name)</li> +</ol> +<p>If you are able to log into the RDBMS as a superuser or a user with appropriate permissions, this process will <em>typically</em> look like this:</p> +<pre tabindex="0"><code>$ psql -h &lt;host&gt; -p &lt;port&gt; -d postgres -U &lt;&#34;postgres&#34; or your own username&gt; +&gt; create user &lt;drycc username; typically &#34;drycc&#34;&gt; with password &#39;&lt;password&gt;&#39;; +&gt; create database &lt;database name; typically &#34;drycc&#34;&gt; with owner &lt;drycc username&gt;; +&gt; \q +</code></pre><h2 id="configuring-workflow">Configuring Workflow<a class="td-heading-self-link" href="#configuring-workflow" aria-label="Heading self-link"></a></h2> +<p>The Helm chart for Drycc Workflow can be easily configured to connect the Workflow controller component to an off-cluster PostgreSQL database.</p> +<ul> +<li><strong>Step 1:</strong> If you haven&rsquo;t already fetched the values, do so with <code>helm inspect values drycc/workflow &gt; values.yaml</code></li> +<li><strong>Step 2:</strong> Update database connection details by modifying <code>values.yaml</code>: +<ul> +<li>Update the <code>databaseLocation</code> parameter to <code>off-cluster</code>.</li> +<li>Update the values in the <code>[database]</code> configuration section to properly reflect all connection details.</li> +<li>Update the values in the <code>[controller]</code> configuration section to properly reflect platformDomain details.</li> +<li>Save your changes.</li> +<li>Note: you do not need to (and must not) base64 encode any values, as the Helm chart will automatically handle encoding as necessary.</li> +</ul> +</li> +</ul> +<p>You are now ready to <code>helm install drycc oci://registry.drycc.cc/charts/workflow --namespace drycc -f values.yaml</code> <a href="/docs/installing-workflow/">as usual</a>.</p> + + + + + + Docs: Configuring Registry + /docs/installing-workflow/configuring-registry/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/installing-workflow/configuring-registry/ + + + + <p>Drycc Workflow ships with a <a href="/docs/understanding-workflow/components/#registry">registry</a> component by default, which provides an in-cluster Container registry backed by the platform-configured <a href="/docs/installing-workflow/configuring-object-storage/">object storage</a>. Operators might want to use an off-cluster registry for performance or security reasons.</p> +<h2 id="configuring-off-cluster-private-registry">Configuring Off-Cluster Private Registry<a class="td-heading-self-link" href="#configuring-off-cluster-private-registry" aria-label="Heading self-link"></a></h2> +<p>Every component that relies on a registry uses two inputs for configuration:</p> +<ol> +<li>Registry Location environment variable named <code>DRYCC_REGISTRY_LOCATION</code></li> +<li>Access credentials stored as a Kubernetes secret named <code>registry-secret</code></li> +</ol> +<p>The Helm chart for Drycc Workflow can be easily configured to connect Workflow components to off-cluster registry. Drycc Workflow supports external registries which provide either short-lived tokens that are valid only for a specified amount of time or long-lived tokens (basic username/password) which are valid forever for authenticating to them. For those registries which provide short lived tokens for authentication, Drycc Workflow will generate and refresh them such that the deployed apps will only have access to the short-lived tokens and not to the actual credentials for the registries.</p> +<p>When using a private registry the container images are no longer pulled by Drycc Workflow Controller but rather are managed by <a href="https://kubernetes.io">Kubernetes</a>. This will increase security and overall speed, however the <code>port</code> information can no longer be discovered. Instead the <code>port</code> information can be set via <code>drycc config:set PORT=&lt;port&gt;</code> prior to deploying the application.</p> +<p>Drycc Workflow currently supports:</p> +<ol> +<li>off-cluster: Any provider which supports long-lived username/password authentication, such as <a href="https://docs.microsoft.com/en-us/azure/container-registry/">Azure Container Registry</a>, <a href="https://hub.docker.com/">Docker Hub</a>, <a href="https://quay.io/">quay.io</a>, or a self-hosted Container registry.</li> +</ol> +<h2 id="configuration">Configuration<a class="td-heading-self-link" href="#configuration" aria-label="Heading self-link"></a></h2> +<ol> +<li>If you haven&rsquo;t already fetched the values file, do so with <code>helm inspect values drycc/workflow &gt; values.yaml</code></li> +<li>Update registry location details by modifying the values file: +* Update the <code>registryLocation</code> parameter to reference the registry location you are using: <code>off-cluster</code>, <code>ecr</code>, <code>gcr</code> +* Update the values in the section which corresponds to your registry location type.</li> +</ol> +<p>You are now ready to <code>helm install drycc oci://registry.drycc.cc/charts/workflow --namespace drycc -f values.yaml</code> using your desired registry.</p> +<h2 id="examples">Examples<a class="td-heading-self-link" href="#examples" aria-label="Heading self-link"></a></h2> +<p>Here we show how the relevant parts of the fetched <code>values.yaml</code> file might look like after configuring for a particular off-cluster registry:</p> +<h3 id="azure-container-registryhttpsazuremicrosoftcomen-usservicescontainer-registry-acr"><a href="https://azure.microsoft.com/en-us/services/container-registry/">Azure Container Registry</a> (ACR)<a class="td-heading-self-link" href="#azure-container-registryhttpsazuremicrosoftcomen-usservicescontainer-registry-acr" aria-label="Heading self-link"></a></h3> +<p>After following the <a href="https://docs.microsoft.com/en-us/azure/container-registry/container-registry-get-started-azure-cli">docs</a> and creating a registry, e.g. <code>myregistry</code>, with its corresponding login server of <code>myregistry.azurecr.io</code>, the following values should be supplied:</p> +<pre tabindex="0"><code>global: +... + registryLocation: &#34;off-cluster&#34; +... +registry-token-refresher: +... + registry: + hostname: &#34;myregistry.azurecr.io&#34; + organization: &#34;myorg&#34; + username: &#34;myusername&#34; + password: &#34;mypassword&#34; +... +</code></pre><p><strong>Note:</strong> The mandatory organization field (here <code>myorg</code>) will be created as an ACR repository if it does not already exist.</p> +<h3 id="quayio">Quay.io<a class="td-heading-self-link" href="#quayio" aria-label="Heading self-link"></a></h3> +<pre tabindex="0"><code>global: +... + registryLocation: &#34;off-cluster&#34; +... +registry-token-refresher: +... + registry: + hostname: &#34;quay.io&#34; + organization: &#34;myorg&#34; + username: &#34;myusername&#34; + password: &#34;mypassword&#34; +... +</code></pre> + + + + + diff --git a/docs/installing-workflow/system-requirements/index.html b/docs/installing-workflow/system-requirements/index.html new file mode 100644 index 000000000..cb8f1a26e --- /dev/null +++ b/docs/installing-workflow/system-requirements/index.html @@ -0,0 +1,491 @@ + + + + + + + + + + + + + + + + + + + +Requirements | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Requirements

+
To run Drycc Workflow on a Kubernetes cluster, there are a few requirements to keep in mind.
+ +

Kubernetes Versions

+

Drycc Workflow requires Kubernetes v1.16.15 or later.

+

Components Requirements

+

Drycc uses gateway as a routing implementation, so you have to choose an gateway. We recommend using istio or kong.

+

Workflow supports the use of ACME to manage automatic certificates, cert-manager is also one of the necessary components, if you use cert-manager EAB, you need to set the clusterResourceNamespace to the namespace of drycc.

+

Workflow supports stateful apps. You can create and use them through the ‘drycc volumes’ command. If you want to use this feature, you must have a StorageClass that supports ReadWriteMany.

+

Workflow also supports the OSB API through the ‘drycc resources’ command. If you want to use this function, you need to install service-catalog.

+

Storage Requirements

+

A variety of Drycc Workflow components rely on an object storage system to do their work, including storing application +slugs, Container images and database logs.

+

Drycc Workflow ships with drycc storage by default, which provides in-cluster.

+

Workflow supports Amazon Simple Storage Service (S3), Google Cloud Storage (GCS), OpenShift Swift, and Azure Blob +Storage. See configuring object storage for setup instructions.

+

Resource Requirements

+

When deploying Drycc Workflow, it’s important to provision machines with adequate resources. Drycc is a highly-available +distributed system, which means that Drycc components and your deployed applications will move around the cluster onto +healthy hosts as hosts leave the cluster for various reasons (failures, reboots, autoscalers, etc.). Because of this, +you should have ample spare resources on any machine in your cluster to withstand the additional load of running +services for failed machines.

+

Drycc Workflow components use about 2.5GB of memory across the cluster, and require approximately 30GB of hard disk +space. Because it may need to handle additional load if another one fails, each machine has minimum requirements of:

+
    +
  • At least 4GB of RAM (more is better)
  • +
  • At least 40GB of hard disk space
  • +
+

Note that these estimates are for Drycc Workflow and Kubernetes only. Be sure to leave enough spare capacity for your +application footprint as well.

+

Running smaller machines will likely result in increased system load and has been known to result in component failures +and instability.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/installing-workflow/workflow/index.html b/docs/installing-workflow/workflow/index.html new file mode 100644 index 000000000..96c2aa8f9 --- /dev/null +++ b/docs/installing-workflow/workflow/index.html @@ -0,0 +1,567 @@ + + + + + + + + + + + + + + + + + + + +Installing Drycc Workflow | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Installing Drycc Workflow

+
This document is aimed at those who have already provisioned a Kubernetes cluster and want to install Drycc Workflow.
+ +

If help is required getting started with Kubernetes and +Drycc Workflow, follow the quickstart guide for assistance.

+

Prerequisites

+
    +
  1. Verify the Kubernetes system requirements
  2. +
  3. Install Helm and Drycc Workflow CLI tools
  4. +
+

Check Your Setup

+

Check that the helm command is available and the version is v2.5.0 or newer.

+
$ helm version
+Client: &version.Version{SemVer:"v2.5.0", GitCommit:"012cb0ac1a1b2f888144ef5a67b8dab6c2d45be6", GitTreeState:"clean"}
+Server: &version.Version{SemVer:"v2.5.0", GitCommit:"012cb0ac1a1b2f888144ef5a67b8dab6c2d45be6", GitTreeState:"clean"}
+

Choose Your Deployment Strategy

+

Drycc Workflow includes everything it needs to run out of the box. However, these defaults are aimed at simplicity rather than +production readiness. Production and staging deployments of Workflow should, at a minimum, use off-cluster storage +which is used by Workflow components to store and backup critical data. Should an operator need to completely re-install +Workflow, the required components can recover from off-cluster storage. See the documentation for configuring object +storage for more details.

+

More rigorous installations would benefit from using outside sources for the following things:

+ +

Gateway

+

Now, workflow requires that gateway and cert-manager must be installed. Any compatible Kubernetes entry controller can be used.

+

Install Drycc Workflow

+

If the version of helm is 3.0 +; you need to create the namespace in advance:

+
kubectl create ns drycc
+

If you want to change it, set the variable when using helm.

+
$ helm install drycc oci://registry.drycc.cc/charts/workflow \
+    --namespace drycc \
+    --set builder.imageRegistry=quay.io \
+    --set imagebuilder.imageRegistry=quay.io \
+    --set controller.imageRegistry=quay.io \
+    --set database.imageRegistry=quay.io \
+    --set fluentbit.imageRegistry=quay.io \
+    --set redis.imageRegistry=quay.io \
+    --set rabbitmq.imageRegistry=quay.io \
+    --set logger.imageRegistry=quay.io \
+    --set storage.imageRegistry=quay.io \
+    --set monitor.imageRegistry=quay.io \
+    --set registry.imageRegistry=quay.io \
+    --set registry-proxy.imageRegistry=quay.io \
+    --set global.platformDomain=drycc.cc
+

Helm will install a variety of Kubernetes resources in the drycc namespace. +Wait for the pods that Helm launched to be ready. Monitor their status by running:

+
$ kubectl --namespace=drycc get pods
+

If it’s preferred to have kubectl automatically update as the pod states change, run (type Ctrl-C to stop the watch):

+
$ kubectl --namespace=drycc get pods -w
+

Depending on the order in which the Workflow components initialize, some pods may restart. This is common during the +installation: if a component’s dependencies are not yet available, that component will exit and Kubernetes will +automatically restart it.

+

Here, it can be seen that the controller, builder and registry all took a few loops before they were able to start:

+
$ kubectl --namespace=drycc get pods
+NAME                                     READY     STATUS    RESTARTS   AGE
+drycc-builder-574483744-l15zj             1/1       Running   0          4m
+drycc-controller-3953262871-pncgq         1/1       Running   2          4m
+drycc-controller-celery-cmxxn             3/3       Running   0          4m
+drycc-database-83844344-47ld6             1/1       Running   0          4m
+drycc-logger-176328999-wjckx              1/1       Running   4          4m
+drycc-logger-fluentbit-zxnqb              1/1       Running   0          4m
+drycc-redis-304849759-1f35p               1/1       Running   0          4m
+drycc-storage-676004970-nxqgt             1/1       Running   0          4m
+drycc-monitor-grafana-432627134-lnl2h     1/1       Running   0          4m
+drycc-monitor-telegraf-wmcmn              1/1       Running   1          4m
+drycc-registry-756475849-lwc6b            1/1       Running   1          4m
+drycc-registry-proxy-96c4p                1/1       Running   0          4m
+drycc-rabbitmq-0                          1/1       Running   0          4m
+

Once all of the pods are in the READY state, Drycc Workflow is up and running!

+

For more installation parameters, please check the values.yaml file of workflow.

+

After installing Workflow, register a user and deploy an application.

+

Configure DNS

+

User must to set up a hostname, and assumes the drycc-builder.$host convention.

+

We need to point the drycc-builder.$host record to the public IP address of your builder. You can get the public IP using the following command. A wildcard entry is necessary here as apps will use the same rule after they are deployed.

+
$ kubectl get svc drycc-builder --namespace drycc
+NAME              CLUSTER-IP   EXTERNAL-IP      PORT(S)                      AGE
+drycc-builder     10.0.25.3    138.91.243.152   2222:31625/TCP               33m
+

If we were using drycc.cc as a hostname, we would need to create the following A DNS records.

+ + + + + + + + + + + + + + + +
NameTypeValue
drycc-builder.drycc.ccA138.91.243.152
+

Once all of the pods are in the READY state, and drycc-builder.$host resolves to the external IP found above, Workflow is up and running!

+

After installing Workflow, register a user and deploy an application.

+

If your k8s does not provide public network loadblance, you need to install TCP proxy services such as haproxy on machines that can +access both internal and external networks, and then expose 80 and 443.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/managing-workflow/_print/index.html b/docs/managing-workflow/_print/index.html new file mode 100644 index 000000000..74ca0b8e2 --- /dev/null +++ b/docs/managing-workflow/_print/index.html @@ -0,0 +1,1037 @@ + + + + + + + + + + + + + + + + + + + + + +Managing Workflow | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+ + + + + +
+
+

+This is the multi-page printable view of this section. +Click here to print. +

+Return to the regular view of this page. +

+
+ + + +

Managing Workflow

+
Managing Workflow using the kubectl.
+ + + + + + + +
+ +
+
+ + + + + + + + + + + + + + + + +
+ +

1 - Tuning Component Settings

+
Helm Charts are a set of Kubernetes manifests that reflect best practices for deploying an application or service on Kubernetes.
+

After you add the Drycc Chart Repository, you can customize the chart using +helm inspect values drycc/workflow > values.yaml before using helm install to complete the +installation.

+

There are a few ways to customize the respective component:

+
    +
  • +

    If the value is exposed in the values.yaml file as derived above, one may modify the section of the component to tune these settings. The modified value(s) will then take effect at chart installation or release upgrade time via either of the two respective commands:

    +
     $ helm install drycc oci://registry.drycc.cc/charts/workflow \
    +     -n drycc \
    +     --namespace drycc \
    +     -f values.yaml
    + $ helm upgrade drycc oci://registry.drycc.cc/charts/workflow \
    +     -n drycc \
    +     --namespace drycc \
    +     -f values.yaml
    +
    +
  • +
  • +

    If the value hasn’t yet been exposed in the values.yaml file, one may edit the component deployment with the tuned setting. Here we edit the drycc-controller deployment:

    +
     $ kubectl --namespace drycc edit deployment drycc-controller
    +
    +

    Add/edit the setting via the appropriate environment variable and value under the env section and save. The updated deployment will recreate the component pod with the new/modified setting.

    +
  • +
  • +

    Lastly, one may also fetch and edit the chart as served by version control/the chart repository itself:

    +
     $ helm fetch oci://registry.drycc.cc/charts/workflow --untar
    + $ $EDITOR workflow/charts/controller/templates/controller-deployment.yaml
    +
    +

    Then run helm install ./workflow --namespace drycc --name drycc to apply the changes, or helm upgrade drycc ./workflow if the cluster is already running.

    +
  • +
+

Setting Resource limits

+

You can set resource limits to Workflow components by modifying the values.yaml file fetched +earlier. This file has a section for each Workflow component. To set a limit to any Workflow +component just add limitsCpu, limitsMemory in the section and set them to the appropriate +values.

+

Below is an example of how the builder section of values.yaml might look with CPU and memory +limits set:

+
builder:
+  imageOrg: "drycc"
+  imagePullPolicy: "Always"
+  imageTag: "canary"
+  limitsCpu: "100m"
+  limitsMemory: "50Mi"
+

Customizing the Builder

+

The following environment variables are tunable for the Builder component:

+ + + + + + + + + + + + + + + + + +
SettingDescription
DEBUGEnable debug log output (default: false)
BUILDER_POD_NODE_SELECTORA node selector setting for builder job. As it may sometimes consume a lot of node resources, one may want a given builder job to run in a specific node only, so it won’t affect critical nodes. for example pool:testing,disk:magnetic
+

Customizing the Controller

+

The following environment variables are tunable for the Controller component:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SettingDescription
REGISTRATION_MODEset registration to “enabled”, “disabled”, or “admin_only” (default: “admin_only”)
GUNICORN_WORKERSnumber of gunicorn workers spawned to process requests (default: CPU cores * 4 + 1)
RESERVED_NAMESa comma-separated list of names which applications cannot reserve for routing (default: “drycc, drycc-builder”)
DRYCC_DEPLOY_HOOK_URLSa comma-separated list of URLs to send deploy hooks to.
DRYCC_DEPLOY_HOOK_SECRET_KEYa private key used to compute the HMAC signature for deploy hooks.
DRYCC_DEPLOY_REJECT_IF_PROCFILE_MISSINGrejects a deploy if the previous build had a Procfile but the current deploy is missing it. A 409 is thrown in the API. Prevents accidental process types removal. (default: “false”, allowed values: “true”, “false”)
DRYCC_DEPLOY_PROCFILE_MISSING_REMOVEwhen turned on (default) any missing process type in a Procfile compared to the previous deploy is removed. When set to false will allow an empty Procfile to go through without removing missing process types, note that new images, configs and so on will get updated on all proc types. (default: “true”, allowed values: “true”, “false”)
DRYCC_DEFAULT_CONFIG_TAGSset tags for all applications by default, for example: ‘{“role”: “worker”}’. (default: ‘’)
KUBERNETES_NAMESPACE_DEFAULT_QUOTA_SPECset resource quota to application namespace by setting ResourceQuota spec, for example: {"spec":{"hard":{"pods":"10"}}}, restrict app owner to spawn more then 10 pods (default: “”, no quota will be applied to namespace)
+

LDAP authentication settings

+

Configuration options for LDAP authentication are detailed here.

+

The following environment variables are available for enabling LDAP +authentication of user accounts in the Passport component:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SettingDescription
LDAP_ENDPOINTThe URI of the LDAP server. If not specified, LDAP authentication is not enabled (default: “”, example: ldap://hostname).
LDAP_BIND_DNThe distinguished name to use when binding to the LDAP server (default: “”)
LDAP_BIND_PASSWORDThe password to use with LDAP_BIND_DN (default: “”)
LDAP_USER_BASEDNThe distinguished name of the search base for user names (default: “”)
LDAP_USER_FILTERThe name of the login field in the users search base (default: “username”)
LDAP_GROUP_BASEDNThe distinguished name of the search base for user’s groups names (default: “”)
LDAP_GROUP_FILTERThe filter for user’s groups (default: “”, example: objectClass=person)
+

Global and per application settings

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SettingDescription
DRYCC_DEPLOY_BATCHESthe number of pods to bring up and take down sequentially during a scale (default: number of available nodes)
DRYCC_DEPLOY_TIMEOUTdeploy timeout in seconds per deploy batch (default: 120)
IMAGE_PULL_POLICYthe kubernetes image pull policy for application images (default: “IfNotPresent”) (allowed values: “Always”, “IfNotPresent”)
KUBERNETES_DEPLOYMENTS_REVISION_HISTORY_LIMIThow many revisions Kubernetes keeps around of a given Deployment (default: all revisions)
KUBERNETES_POD_TERMINATION_GRACE_PERIOD_SECONDShow many seconds kubernetes waits for a pod to finish work after a SIGTERM before sending SIGKILL (default: 30)
+

See the Deploying Apps guide for more detailed information on those.

+

Customizing the Database

+

The following environment variables are tunable for the Database component:

+ + + + + + + + + + + + + + + + + +
SettingDescription
BACKUP_FREQUENCYhow often the database should perform a base backup (default: “12h”)
BACKUPS_TO_RETAINnumber of base backups the backing store should retain (default: 5)
+

Customizing Fluentbit

+

The following values can be changed in the values.yaml file or by using the --values flag with the Helm CLI.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
KeyDescription
config.serviceThe service section defines the global properties of the service.
config.inputsAn input section defines a source (related to an input plugin).
config.filtersA filter section defines a filter (related to a filter plugin)
config.outputsThe outputs section specify a destination that certain records should follow after a Tag match.
+

For more information about the various variables that can be set please see the fluentbit.

+

Customizing the Logger

+

The following environment variables are tunable for the Logger component:

+ + + + + + + + + + + + + + + + + +
SettingDescription
STORAGE_ADAPTERHow to store logs that are sent to the logger. Legal values are “file”, “memory”, and “redis”. (default: “redis”)
NUMBER_OF_LINESHow many lines to store in the ring buffer (default: 1000)
+

Customizing the Monitor

+

Grafana

+

We have exposed some of the more useful configuration values directly in the chart. This allows them to be set using either the values.yaml file or by using the --set flag with the Helm CLI. You can see these options below:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
SettingDefault ValueDescription
user“admin”The first user created in the database (this user has admin privileges)
password“admin”Password for the first user.
allow_sign_up“true”Allows users to sign up for an account.
+

For a list of other options you can set by using environment variables please see the configuration file in Github.

+

Telegraf

+

For a list of configuration values that can be set by using environment variables please see the following configuration file.

+

Prometheus

+

You can find a list of values that can be set using environment variables here.

+

Customizing the Registry

+

The Registry component can be tuned by following the +drycc/distribution config doc.

+

Customizing the Router

+

The majority of router settings are tunable through annotations, which allows the router to be +re-configured with zero downtime post-installation. You can find the list of annotations to tune +here.

+

The following environment variables are tunable for the [Router][] component:

+ + + + + + + + + + + + + +
SettingDescription
POD_NAMESPACEThe pod namespace the router resides in. This is set by the Kubernetes downward API.
+

Customizing Workflow Manager

+

The following environment variables are tunable for [Workflow Manager][]:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SettingDescription
CHECK_VERSIONSEnables the external version check at https://versions.drycc.info/ (default: “true”)
POLL_INTERVAL_SECThe interval when Workflow Manager performs a version check, in seconds (default: 43200, or 12 hours)
VERSIONS_API_URLThe versions API URL (default: “https://versions-staging.drycc.info”)
DOCTOR_API_URLThe doctor API URL (default: “https://doctor-staging.drycc.info”)
API_VERSIONThe version number Workflow Manager sends to the versions API (default: “v2”)
+ +
+ + + + + + + + + + + +
+ +

2 - Configure DNS

+
The Drycc Workflow controller and all applications deployed via Workflow are intended (by default) to be accessible as subdomains of the Workflow cluster’s domain.
+

For example, assuming example.com were a cluster’s domain:

+
    +
  • The controller should be accessible at drycc.example.com
  • +
  • Applications should be accessible (by default) at <application name>.example.com
  • +
+

Given that this is the case, the primary objective in configuring DNS is that traffic for all subdomains of a cluster’s domain be directed to the cluster node(s) hosting the platform’s router component, which is capable of directing traffic within the cluster to the correct endpoints.

+

With a Load Balancer

+

Generally, it is recommended that a [load balancer][] be used to direct inbound traffic to one or more routers. In such a case, configuring DNS is as simple as defining a wildcard record in DNS that points to the load balancer.

+

For example, assuming a domain of example.com:

+
    +
  • An A record enumerating each of your load balancer(s) IPs (i.e. DNS round-robining)
  • +
  • A CNAME record referencing an existing fully-qualified domain name for the load balancer +
      +
    • Per AWS’ own documentation, this is the recommended strategy when using AWS Elastic Load Balancers, as ELB IPs may change over time.
    • +
    +
  • +
+

DNS for any applications using a “custom domain” (a fully-qualified domain name that is not a subdomain of the cluster’s own domain) can be configured by creating a CNAME record that references the wildcard record described above.

+

Although it is dependent upon your distribution of Kubernetes and your underlying infrastructure, in many cases, the IP(s) or existing fully-qualified domain name of a load balancer can be determined directly using the kubectl tool:

+
$ kubectl --namespace=istio-nginx describe service | grep "LoadBalancer"
+LoadBalancer Ingress:	a493e4e58ea0511e5bb390686bc85da3-1558404688.us-west-2.elb.amazonaws.com
+

The LoadBalancer Ingress field typically describes an existing domain name or public IP(s). Note that if Kubernetes is able to automatically provision a load balancer for you, it does so asynchronously. If the command shown above is issued very soon after Workflow installation, the load balancer may not exist yet.

+

Without a Load Balancer

+

On some platforms (Minikube, for instance), a load balancer is not an easy or practical thing to provision. In these cases, one can directly identify the public IP of a Kubernetes node that is hosting a router pod and use that information to configure the local /etc/hosts file.

+

Because wildcard entries do not work in a local /etc/hosts file, using this strategy may result in frequent editing of that file to add fully-qualified subdomains of a cluster for each application added to that cluster. Because of this a more viable option may be to utilize the xip.io service.

+

In general, for any IP, a.b.c.d, the fully-qualified domain name any-subdomain.a.b.c.d.xip.io will resolve to the IP a.b.c.d. This can be enormously useful.

+

To begin, find the node(s) hosting router instances using kubectl:

+
$ kubectl --namespace=istio-ingress describe pod | grep Node:
+Node:       ip-10-0-0-199.us-west-2.compute.internal/10.0.0.199
+Node:       ip-10-0-0-198.us-west-2.compute.internal/10.0.0.198
+

The command will display information for every router pod. For each, a node name and IP are displayed in the Node field. If the IPs appearing in these fields are public, any of these may be used to configure your local /etc/hosts file or may be used with xip.io. If the IPs shown are not public, further investigation may be needed.

+

You can list the IP addresses of a node using kubectl:

+
$ kubectl describe node ip-10-0-0-199.us-west-2.compute.internal
+# ...
+Addresses:	10.0.0.199,10.0.0.199,54.218.85.175
+# ...
+

Here, the Addresses field lists all the node’s IPs. If any of them are public, again, they may be used to configure your local /etc/hosts file or may be used with xip.io.

+

Tutorial: Configuring DNS with Google Cloud DNS

+

In this section, we’ll describe how to configure Google Cloud DNS for routing your domain name to your Drycc cluster.

+

We’ll assume the following in this section:

+
    +
  • Your Ingress service has a load balancer in front of it. +
      +
    • The load balancer need not be cloud based, it just needs to provide a stable IP address or a stable domain name
    • +
    +
  • +
  • You have the mystuff.com domain name registered with a registrar +
      +
    • Replace your domain name with mystuff.com in the instructions to follow
    • +
    +
  • +
  • Your registrar lets you alter the nameservers for your domain name (most registrars do)
  • +
+

Here are the steps for configuring cloud DNS to route to your drycc cluster:

+
    +
  1. Get the load balancer IP or domain name
  2. +
+
    +
  • If you are on Google Container Engine, you can run kubectl get svc -n istio-ingress and look for the LoadBalancer Ingress column to get the IP address
  • +
+
    +
  1. Create a new Cloud DNS Zone (on the console: Networking => Cloud DNS, then click on Create Zone)
  2. +
  3. Name your zone, and set the DNS name to mystuff.com. (note the . at the end
  4. +
  5. Click on the Create button
  6. +
  7. Click on the Add Record Set button on the resulting page
  8. +
  9. If your load balancer provides a stable IP address, enter the following fields in the resulting form:
  10. +
  11. DNS Name: *
  12. +
  13. Resource Record Type: A
  14. +
  15. TTL: the DNS TTL of your choosing. If you’re testing or you anticipate that you’ll tear down and rebuild many drycc clusters over time, we recommend a low TTL
  16. +
  17. IPv4 Address: The IP that you got in the very first step
  18. +
  19. Click the Create button
  20. +
  21. If your load balancer provides the stable domain name lbdomain.com, enter the following fields in the resulting form:
  22. +
  23. DNS Name: *
  24. +
  25. Resource Record Type: CNAME
  26. +
  27. TTL: the DNS TTL of your choosing. If you’re testing or you anticipate that you’ll tear down and rebuild many drycc clusters over time, we recommend a low TTL
  28. +
  29. Canonical name: lbdomain.com. (note the . a the end)
  30. +
  31. Click on the Create button
  32. +
  33. In your domain registrar, set the nameservers for your mystuff.com domain to the ones under the data column in the NS record on the same page. They’ll often be something like the below (note the trailing . characters).
  34. +
+
ns-cloud-b1.googledomains.com.
+ns-cloud-b2.googledomains.com.
+ns-cloud-b3.googledomains.com.
+ns-cloud-b4.googledomains.com.
+

Note: If you ever have to re-create your drycc cluster, simply go back to step 6.4 or 7.4 (depending on your load balancer) and change the IP address or domain name to the new value. You may have to wait for the TTL you set to expire.

+

Testing

+

To test that traffic reaches its intended destination, a request can be +sent to the Drycc controller like so (do not forget the trailing slash!):

+
curl http://drycc.example.com/v2/
+

Or:

+
curl http://drycc.54.218.85.175.xip.io/v2/
+

Since such requests require authentication, a response such as the following should be considered an indicator of success:

+
{"detail":"Authentication credentials were not provided."}
+
+
+ + + + + + + + + + + +
+ +

3 - Deploy Hooks

+
Deploy hooks allow an external service to receive a notification whenever a new version of your app is pushed to Workflow.
+

It’s useful to help keep the development team informed about deploys, while +it can also be used to integrate different systems together.

+

After one or more hooks are setup, hook output and errors appear in your application’s logs:

+
$ drycc logs
+...
+2011-03-15T15:07:29-07:00 drycc[api]: Deploy hook sent to http://drycc.rocks
+

Deploy hooks are a generic HTTP hook. An administrator can create and configure multiple deploy +hooks by tuning the controller settings via the Helm chart.

+

HTTP POST Hook

+

The HTTP deploy hook performs an HTTP POST to a URL. The parameters included in the request are the +same as the variables available in the hook message: app, release, release_summary, sha and +user. See below for their descriptions:

+
app=secure-woodland&release=v4&release_summary=gabrtv%20deployed%35b3726&sha=35b3726&user=gabrtv
+

Optionally, if a deploy hook secret key is added to the controller through +tuning the controller settings, a new Authorization header will be +present in the POST request. The value of this header is computed as the HMAC hex digest of the +request URL, using the secret as the key.

+

In order to authenticate that this request came from Workflow, use the secret key, the full URL and +the HMAC-SHA1 hashing algorithm to compute the signature. In Python, that would look something like +this:

+
import hashlib
+import hmac
+
+hmac.new("my_secret_key", "http://drycc.rocks?app=secure-woodland&release=v4&release_summary=gabrtv%20deployed%35b3726&sha=35b3726&user=gabrtv", digestmod=hashlib.sha1).hexdigest()
+

If the value of the computed HMAC hex digest and the value in the Authorization header are +identical, then the request came from Workflow.

+

!!! important +When computing the signature, ensure that the URL parameters are in alphabetic order. This is +critical when computing the cryptographic signature as most web applications don’t care about +the order of the HTTP parameters, but the cryptographic signature will not be the same.

+ +
+ + + + + + + + + + + +
+ +

4 - Platform Logging

+
Logs are a stream of time-stamped events aggregated from the output streams of all your app’s running processes. Retrieve, filter, or use syslog drains.
+

The logging platform is made up of 2 components - Fluentbit and Logger.

+

Fluentbit runs on every worker node of the cluster and is deployed as a Daemon Set. The Fluentbit pods capture all of the stderr and stdout streams of every container running on the host (even those not hosted directly by kubernetes). Once the log message arrives in our custom fluentbit plugin we determine where the message originated.

+

If the message was from the Workflow Controller or from an application deployed via workflow we send it to the logs topic on the local Redis Stream instance.

+

Logger then acts as a consumer reading messages off of the Redis Stream logs topic storing those messages in a local Redis instance. When a user wants to retrieve log entries using the drycc logs command we make an HTTP request from Controller to Logger which then fetches the appropriate data from Redis.

+

Configuring Off Cluster Redis

+

Even though we provide a redis instance with the default Workflow install, it is recommended that operators use a third-party source like Elasticache or similar offering. This way your data is durable across upgrades or outages. If you have a third-party Redis installation you would like to use all you need to do is set the following values in your helm chart:

+
    +
  • db = “0”
  • +
  • host = “my.host.redis”
  • +
  • port = “6379”
  • +
  • password = ""
  • +
+

These can be changed by running helm inspect values drycc/workflow > values.yaml before using +helm install to complete the installation. To customize the redis credentials, edit values.yaml +and modify the redis section of the file to tune these settings.

+

Debugging Logger

+

If the drycc logs command encounters an error it will return the following message:

+
Error: There are currently no log messages. Please check the following things:
+1) Logger and fluentbit pods are running.
+2) The application is writing logs to the logger component by checking that an entry in the ring buffer was created: kubectl  --namespace=drycc logs <logger pod>
+3) Making sure that the container logs were mounted properly into the fluentbit pod: kubectl --namespace=drycc exec <fluentbit pod> ls /var/log/containers
+

Architecture Diagram

+
                        ┌────────┐                                        
+                        │ Router │                  ┌────────┐     ┌─────┐
+                        └────────┘                  │ Logger │◀───▶│Redis│
+                            │                       └────────┘     └─────┘
+                        Log file                        ▲                
+                            │                           │                
+                            ▼                           │                
+┌────────┐             ┌─────────┐    logs/metrics   ┌──────────────┐     
+│App Logs│──Log File──▶│Fluentbit│───────topics─────▶│ Redis Stream │     
+└────────┘             └─────────┘                   └──────────────┘     
+                                                                          
+

Default Configuration

+

Fluent Bit is based in a pluggable architecture where different plugins plays a major role in the data pipeline, more than 70 built-in plugins available. +Please refer to charts values.yaml for specific configurations.

+ +
+ + + + + + + + + + + +
+ +

5 - Platform Monitoring

+
Platform monitoring to your apps to spot issues in advance and respond to incidents quickly.
+

Description

+

We now include a monitoring stack for introspection on a running Kubernetes cluster. The stack includes 4 components:

+ +

Architecture Diagram

+
┌────────────────┐                                                        
+│ HOST           │                                                        
+│  node-exporter │◀──┐                       ┌──────────────────┐         
+└────────────────┘   │                       │kube-state-metrics│         
+                     │                       └──────────────────┘         
+┌────────────────┐   │                               ▲                    
+│ HOST           │   │    ┌────────────┐             │                    
+│  node-exporter │◀──┼────│ Prometheus │─────────────┘                    
+└────────────────┘   │    └────────────┘                                  
+                     │          ▲                                         
+┌───────────────┐    │          │                                         
+│ HOST          │    │          ▼                                         
+│  node-exporter│◀───┘    ┌──────────┐                                    
+└───────────────┘         │ Grafana  │                                    
+                          └──────────┘                                    
+

Grafana

+

Grafana allows users to create custom dashboards that visualize the data captured to the running Prometheus component. By default Grafana is exposed using a service annotation through the router at the following URL: http://grafana.mydomain.com. The default login is admin/admin. If you are interested in changing these values please see [Tuning Component Settings][].

+

Grafana will preload several dashboards to help operators get started with monitoring Kubernetes and Drycc Workflow. +These dashboards are meant as starting points and don’t include every item that might be desirable to monitor in a +production installation.

+

Drycc Workflow monitoring by default does not write data to the host filesystem or to long-term storage. If the Grafana instance fails, modified dashboards are lost.

+

Production Configuration

+

A production install of Grafana should have the following configuration values changed if possible:

+
    +
  • Change the default username and password from admin/admin. The value for the password is passed in plain text so it is best to set this value on the command line instead of checking it into version control.
  • +
  • Enable persistence
  • +
  • Use a supported external database such as mysql or postgres. You can find more information here
  • +
+

On Cluster Persistence

+

Enabling persistence will allow your custom configuration to persist across pod restarts. This means that the default sqllite database (which stores things like sessions and user data) will not disappear if you upgrade the Workflow installation.

+

If you wish to have persistence for Grafana you can set enabled to true in the values.yaml file before running helm install.

+
 grafana:
+   # Configure the following ONLY if you want persistence for on-cluster grafana
+   # GCP PDs and EBS volumes are supported only
+   persistence:
+     enabled: true # Set to true to enable persistence
+     size: 5Gi # PVC size
+

Off Cluster Grafana

+

If you wish to provide your own Grafana instance you can set grafanaLocation in the values.yaml file before running helm install.

+

Prometheus

+

Prometheus writes data to the host disk; however, if the prometheus pod dies and comes back on another host, the data will not be recovered. The prometheus graph UI is also exposed through the router allowing users to access the query engine by going to prometheus.mydomain.com.

+

On Cluster Persistence

+

You can set node-exporter and kube-state-metrics to true or false in the values.yaml. +If you wish to have persistence for Prometheus you can set enabled to true in the values.yaml file before running helm install.

+
prometheus:
+  prometheus-server:
+    persistence:
+      enabled: true # Set to true to enable persistence
+      size: 10Gi # PVC size
+node-exporter:
+  enabled: true
+kube-state-metrics:
+  enabled: true
+

Off Cluster Prometheus

+

To use off-cluster Prometheus, please provide the following values in the values.yaml file before running helm install.

+
    +
  • global.prometheusLocation=off-cluster
  • +
  • url = "http://my.prometheus.url:9090"
  • +
+ +
+ + + + + + + + + + + +
+ +

6 - Production Deployments

+
When readying a Workflow deployment for production workloads, there are some additional recommendations.
+

Running Workflow without drycc storage

+

In production, persistent storage can be achieved by running an external object store. +For users on AWS, GCE/GKE or Azure, the convenience of Amazon S3, Google GCS or Microsoft Azure Storage +makes the prospect of running a Storage-less Workflow cluster quite reasonable. For users who have restriction +on using external object storage using swift object storage can be an option.

+

Running a Workflow cluster without Storage provides several advantages:

+
    +
  • Removal of state from the worker nodes
  • +
  • Reduced resource usage
  • +
  • Reduced complexity and operational burden of managing Workflow
  • +
+

See Configuring Object Storage for details on removing this operational complexity.

+

Review Security Considerations

+

There are some additional security-related considerations when running Workflow in production. +See [Security Considerations][] for details.

+

Registration is Admin-Only

+

By default, registration with the Workflow controller is in “admin_only” mode. The first user +to run a drycc register command becomes the initial “admin” user, and registrations after that +are disallowed unless requested by an admin.

+

Please see the following documentation to learn about changing registration mode:

+ +

Disable Grafana Signups

+

It is also recommended to disable signups for the Grafana dashboards.

+

Please see the following documentation to learn about disabling Grafana signups:

+ +

Running Workflow with RBAC

+

If your cluster has RBAC amongst your authorization modes ($ kubectl api-versions should contains rbac.authorization.k8s.io) it may be necessary to enable RBAC in Workflow. +This can be achieved by setting use_rbac in the global section of values.yaml to true, or by adding --set=global.use_rbac=true to the $ helm install/upgrade command. +RBAC support was announced in Kubernetes-1.5 and is enabled by default if:

+
    +
  • your Kubernetes cluster is in GKE
  • +
  • your Kubernetes cluster built with kubeadm
  • +
+

Note: helm may need to be given specific permissions under RBAC if not already done.

+

Attention: Azure ACS Kubernetes clusters are not RBAC-enabled for today due to lack in authentication strategy. Feel free to watch this PR for more details.

+ +
+ + + + + + + + + + + +
+ +

7 - Upgrading Workflow

+
Drycc Workflow releases may be upgraded in-place with minimal downtime.
+

This upgrade process requires:

+ +

Upgrade Process

+

!!! note +If upgrading from a Helm Classic install, you’ll need to ‘migrate’ the cluster to a Kubernetes Helm installation. See Workflow-Migration for steps.

+

Step 1: Apply the Workflow upgrade

+

Helm will remove all components from the previous release. Traffic to applications deployed through +Workflow will continue to flow during the upgrade. No service interruptions should occur.

+

If Workflow is not configured to use off-cluster Postgres, the Workflow API will experience a brief +period of downtime while the database recovers from backup.

+

First, find the name of the release helm gave to your deployment with helm ls, then run

+
$ helm upgrade <release-name> oci://registry.drycc.cc/charts/workflow
+

Note: If using off-cluster object storage on gcs and/or off-cluster registry using gcr and intending to upgrade from a pre-v2.10.0 chart to v2.10.0 or greater, the key_json values will now need to be pre-base64-encoded. Therefore, assuming the rest of the custom/off-cluster values are defined in the existing values.yaml used for previous installs, the following may be run:

+
$ B64_KEY_JSON="$(cat ~/path/to/key.json | base64 -w 0)"
+$ helm upgrade <release_name> drycc/workflow -f values.yaml --set gcs.key_json="${B64_KEY_JSON}",registry-token-refresher.gcr.key_json="${B64_KEY_JSON}"
+

Alternatively, simply replace the appropriate values in values.yaml and do without the --set +parameter. Make sure to wrap it in single quotes as double quotes will give a parser error when +upgrading.

+

Step 2: Verify Upgrade

+

Verify that all components have started and passed their readiness checks:

+
$ kubectl --namespace=drycc get pods
+NAME                                     READY     STATUS    RESTARTS   AGE
+drycc-builder-2448122224-3cibz            1/1       Running   0          5m
+drycc-controller-1410285775-ipc34         1/1       Running   3          5m
+drycc-controller-celery-694f75749b-cmxxn  3/3       Running   0          5m
+drycc-database-e7c5z                      1/1       Running   0          5m
+drycc-logger-cgjup                        1/1       Running   3          5m
+drycc-logger-fluentbit-45h7j              1/1       Running   0          5m
+drycc-logger-fluentbit-4z7lw              1/1       Running   0          5m
+drycc-logger-fluentbit-k2wsw              1/1       Running   0          5m
+drycc-logger-fluentbit-skdw4              1/1       Running   0          5m
+drycc-redis-8nazu                         1/1       Running   0          5m
+drycc-monitor-grafana-tm266               1/1       Running   0          5m
+drycc-monitor-telegraf-51zel              1/1       Running   1          5m
+drycc-monitor-telegraf-cdasg              1/1       Running   0          5m
+drycc-monitor-telegraf-hea6x              1/1       Running   0          5m
+drycc-monitor-telegraf-r7lsg              1/1       Running   0          5m
+drycc-registry-1814324048-yomz5           1/1       Running   0          5m
+drycc-registry-proxy-4m3o4                1/1       Running   0          5m
+drycc-registry-proxy-no3r1                1/1       Running   0          5m
+drycc-registry-proxy-ou8is                1/1       Running   0          5m
+drycc-registry-proxy-zyajl                1/1       Running   0          5m
+drycc-rabbitmq-0                          1/1       Running   0          5m
+

Step 3: Upgrade the Drycc Client

+

Users of Drycc Workflow should now upgrade their drycc client to avoid getting WARNING: Client and server API versions do not match. Please consider upgrading. warnings.

+
curl -sfL https://www.drycc.cc/install-cli.sh | bash - && sudo mv drycc $(which drycc)
+
+
+ + + + + + + + + +
+
+
+ + +
+ + + + + + diff --git a/docs/managing-workflow/configuring-dns/index.html b/docs/managing-workflow/configuring-dns/index.html new file mode 100644 index 000000000..3b5b61ac1 --- /dev/null +++ b/docs/managing-workflow/configuring-dns/index.html @@ -0,0 +1,554 @@ + + + + + + + + + + + + + + + + + + + +Configure DNS | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Configure DNS

+
The Drycc Workflow controller and all applications deployed via Workflow are intended (by default) to be accessible as subdomains of the Workflow cluster’s domain.
+ +

For example, assuming example.com were a cluster’s domain:

+
    +
  • The controller should be accessible at drycc.example.com
  • +
  • Applications should be accessible (by default) at <application name>.example.com
  • +
+

Given that this is the case, the primary objective in configuring DNS is that traffic for all subdomains of a cluster’s domain be directed to the cluster node(s) hosting the platform’s router component, which is capable of directing traffic within the cluster to the correct endpoints.

+

With a Load Balancer

+

Generally, it is recommended that a [load balancer][] be used to direct inbound traffic to one or more routers. In such a case, configuring DNS is as simple as defining a wildcard record in DNS that points to the load balancer.

+

For example, assuming a domain of example.com:

+
    +
  • An A record enumerating each of your load balancer(s) IPs (i.e. DNS round-robining)
  • +
  • A CNAME record referencing an existing fully-qualified domain name for the load balancer +
      +
    • Per AWS’ own documentation, this is the recommended strategy when using AWS Elastic Load Balancers, as ELB IPs may change over time.
    • +
    +
  • +
+

DNS for any applications using a “custom domain” (a fully-qualified domain name that is not a subdomain of the cluster’s own domain) can be configured by creating a CNAME record that references the wildcard record described above.

+

Although it is dependent upon your distribution of Kubernetes and your underlying infrastructure, in many cases, the IP(s) or existing fully-qualified domain name of a load balancer can be determined directly using the kubectl tool:

+
$ kubectl --namespace=istio-nginx describe service | grep "LoadBalancer"
+LoadBalancer Ingress:	a493e4e58ea0511e5bb390686bc85da3-1558404688.us-west-2.elb.amazonaws.com
+

The LoadBalancer Ingress field typically describes an existing domain name or public IP(s). Note that if Kubernetes is able to automatically provision a load balancer for you, it does so asynchronously. If the command shown above is issued very soon after Workflow installation, the load balancer may not exist yet.

+

Without a Load Balancer

+

On some platforms (Minikube, for instance), a load balancer is not an easy or practical thing to provision. In these cases, one can directly identify the public IP of a Kubernetes node that is hosting a router pod and use that information to configure the local /etc/hosts file.

+

Because wildcard entries do not work in a local /etc/hosts file, using this strategy may result in frequent editing of that file to add fully-qualified subdomains of a cluster for each application added to that cluster. Because of this a more viable option may be to utilize the xip.io service.

+

In general, for any IP, a.b.c.d, the fully-qualified domain name any-subdomain.a.b.c.d.xip.io will resolve to the IP a.b.c.d. This can be enormously useful.

+

To begin, find the node(s) hosting router instances using kubectl:

+
$ kubectl --namespace=istio-ingress describe pod | grep Node:
+Node:       ip-10-0-0-199.us-west-2.compute.internal/10.0.0.199
+Node:       ip-10-0-0-198.us-west-2.compute.internal/10.0.0.198
+

The command will display information for every router pod. For each, a node name and IP are displayed in the Node field. If the IPs appearing in these fields are public, any of these may be used to configure your local /etc/hosts file or may be used with xip.io. If the IPs shown are not public, further investigation may be needed.

+

You can list the IP addresses of a node using kubectl:

+
$ kubectl describe node ip-10-0-0-199.us-west-2.compute.internal
+# ...
+Addresses:	10.0.0.199,10.0.0.199,54.218.85.175
+# ...
+

Here, the Addresses field lists all the node’s IPs. If any of them are public, again, they may be used to configure your local /etc/hosts file or may be used with xip.io.

+

Tutorial: Configuring DNS with Google Cloud DNS

+

In this section, we’ll describe how to configure Google Cloud DNS for routing your domain name to your Drycc cluster.

+

We’ll assume the following in this section:

+
    +
  • Your Ingress service has a load balancer in front of it. +
      +
    • The load balancer need not be cloud based, it just needs to provide a stable IP address or a stable domain name
    • +
    +
  • +
  • You have the mystuff.com domain name registered with a registrar +
      +
    • Replace your domain name with mystuff.com in the instructions to follow
    • +
    +
  • +
  • Your registrar lets you alter the nameservers for your domain name (most registrars do)
  • +
+

Here are the steps for configuring cloud DNS to route to your drycc cluster:

+
    +
  1. Get the load balancer IP or domain name
  2. +
+
    +
  • If you are on Google Container Engine, you can run kubectl get svc -n istio-ingress and look for the LoadBalancer Ingress column to get the IP address
  • +
+
    +
  1. Create a new Cloud DNS Zone (on the console: Networking => Cloud DNS, then click on Create Zone)
  2. +
  3. Name your zone, and set the DNS name to mystuff.com. (note the . at the end
  4. +
  5. Click on the Create button
  6. +
  7. Click on the Add Record Set button on the resulting page
  8. +
  9. If your load balancer provides a stable IP address, enter the following fields in the resulting form:
  10. +
  11. DNS Name: *
  12. +
  13. Resource Record Type: A
  14. +
  15. TTL: the DNS TTL of your choosing. If you’re testing or you anticipate that you’ll tear down and rebuild many drycc clusters over time, we recommend a low TTL
  16. +
  17. IPv4 Address: The IP that you got in the very first step
  18. +
  19. Click the Create button
  20. +
  21. If your load balancer provides the stable domain name lbdomain.com, enter the following fields in the resulting form:
  22. +
  23. DNS Name: *
  24. +
  25. Resource Record Type: CNAME
  26. +
  27. TTL: the DNS TTL of your choosing. If you’re testing or you anticipate that you’ll tear down and rebuild many drycc clusters over time, we recommend a low TTL
  28. +
  29. Canonical name: lbdomain.com. (note the . a the end)
  30. +
  31. Click on the Create button
  32. +
  33. In your domain registrar, set the nameservers for your mystuff.com domain to the ones under the data column in the NS record on the same page. They’ll often be something like the below (note the trailing . characters).
  34. +
+
ns-cloud-b1.googledomains.com.
+ns-cloud-b2.googledomains.com.
+ns-cloud-b3.googledomains.com.
+ns-cloud-b4.googledomains.com.
+

Note: If you ever have to re-create your drycc cluster, simply go back to step 6.4 or 7.4 (depending on your load balancer) and change the IP address or domain name to the new value. You may have to wait for the TTL you set to expire.

+

Testing

+

To test that traffic reaches its intended destination, a request can be +sent to the Drycc controller like so (do not forget the trailing slash!):

+
curl http://drycc.example.com/v2/
+

Or:

+
curl http://drycc.54.218.85.175.xip.io/v2/
+

Since such requests require authentication, a response such as the following should be considered an indicator of success:

+
{"detail":"Authentication credentials were not provided."}
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/managing-workflow/deploy-hooks/index.html b/docs/managing-workflow/deploy-hooks/index.html new file mode 100644 index 000000000..3a6cf4ba8 --- /dev/null +++ b/docs/managing-workflow/deploy-hooks/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + +Deploy Hooks | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Deploy Hooks

+
Deploy hooks allow an external service to receive a notification whenever a new version of your app is pushed to Workflow.
+ +

It’s useful to help keep the development team informed about deploys, while +it can also be used to integrate different systems together.

+

After one or more hooks are setup, hook output and errors appear in your application’s logs:

+
$ drycc logs
+...
+2011-03-15T15:07:29-07:00 drycc[api]: Deploy hook sent to http://drycc.rocks
+

Deploy hooks are a generic HTTP hook. An administrator can create and configure multiple deploy +hooks by tuning the controller settings via the Helm chart.

+

HTTP POST Hook

+

The HTTP deploy hook performs an HTTP POST to a URL. The parameters included in the request are the +same as the variables available in the hook message: app, release, release_summary, sha and +user. See below for their descriptions:

+
app=secure-woodland&release=v4&release_summary=gabrtv%20deployed%35b3726&sha=35b3726&user=gabrtv
+

Optionally, if a deploy hook secret key is added to the controller through +tuning the controller settings, a new Authorization header will be +present in the POST request. The value of this header is computed as the HMAC hex digest of the +request URL, using the secret as the key.

+

In order to authenticate that this request came from Workflow, use the secret key, the full URL and +the HMAC-SHA1 hashing algorithm to compute the signature. In Python, that would look something like +this:

+
import hashlib
+import hmac
+
+hmac.new("my_secret_key", "http://drycc.rocks?app=secure-woodland&release=v4&release_summary=gabrtv%20deployed%35b3726&sha=35b3726&user=gabrtv", digestmod=hashlib.sha1).hexdigest()
+

If the value of the computed HMAC hex digest and the value in the Authorization header are +identical, then the request came from Workflow.

+

!!! important +When computing the signature, ensure that the URL parameters are in alphabetic order. This is +critical when computing the cryptographic signature as most web applications don’t care about +the order of the HTTP parameters, but the cryptographic signature will not be the same.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/managing-workflow/index.html b/docs/managing-workflow/index.html new file mode 100644 index 000000000..385feaa80 --- /dev/null +++ b/docs/managing-workflow/index.html @@ -0,0 +1,496 @@ + + + + + + + + + + + + + + + + + + + + + +Managing Workflow | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Managing Workflow

+
Managing Workflow using the kubectl.
+ + +
+ + +
+
+
+ Tuning Component Settings +
+

Helm Charts are a set of Kubernetes manifests that reflect best practices for deploying an application or service on Kubernetes.

+
+
+
+ Configure DNS +
+

The Drycc Workflow controller and all applications deployed via Workflow are intended (by default) to be accessible as subdomains of the Workflow cluster’s domain.

+
+
+
+ Deploy Hooks +
+

Deploy hooks allow an external service to receive a notification whenever a new version of your app is pushed to Workflow.

+
+
+
+ Platform Logging +
+

Logs are a stream of time-stamped events aggregated from the output streams of all your app’s running processes. Retrieve, filter, or use syslog drains.

+
+
+
+ Platform Monitoring +
+

Platform monitoring to your apps to spot issues in advance and respond to incidents quickly.

+
+
+
+ Production Deployments +
+

When readying a Workflow deployment for production workloads, there are some additional recommendations.

+
+
+
+ Upgrading Workflow +
+

Drycc Workflow releases may be upgraded in-place with minimal downtime.

+
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+
+ +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/managing-workflow/index.xml b/docs/managing-workflow/index.xml new file mode 100644 index 000000000..9fdc21f42 --- /dev/null +++ b/docs/managing-workflow/index.xml @@ -0,0 +1,766 @@ + + + Drycc – Managing Workflow + /docs/managing-workflow/ + Recent content in Managing Workflow on Drycc + Hugo -- gohugo.io + en + + + + + + + + + + + Docs: Tuning Component Settings + /docs/managing-workflow/tuning-component-settings/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/managing-workflow/tuning-component-settings/ + + + + <p>After you add the Drycc Chart Repository, you can customize the chart using +<code>helm inspect values drycc/workflow &gt; values.yaml</code> before using <code>helm install</code> to complete the +installation.</p> +<p>There are a few ways to customize the respective component:</p> +<ul> +<li> +<p>If the value is exposed in the <code>values.yaml</code> file as derived above, one may modify the section of the component to tune these settings. The modified value(s) will then take effect at chart installation or release upgrade time via either of the two respective commands:</p> +<pre><code> $ helm install drycc oci://registry.drycc.cc/charts/workflow \ + -n drycc \ + --namespace drycc \ + -f values.yaml + $ helm upgrade drycc oci://registry.drycc.cc/charts/workflow \ + -n drycc \ + --namespace drycc \ + -f values.yaml +</code></pre> +</li> +<li> +<p>If the value hasn&rsquo;t yet been exposed in the <code>values.yaml</code> file, one may edit the component deployment with the tuned setting. Here we edit the <code>drycc-controller</code> deployment:</p> +<pre><code> $ kubectl --namespace drycc edit deployment drycc-controller +</code></pre> +<p>Add/edit the setting via the appropriate environment variable and value under the <code>env</code> section and save. The updated deployment will recreate the component pod with the new/modified setting.</p> +</li> +<li> +<p>Lastly, one may also fetch and edit the chart as served by version control/the chart repository itself:</p> +<pre><code> $ helm fetch oci://registry.drycc.cc/charts/workflow --untar + $ $EDITOR workflow/charts/controller/templates/controller-deployment.yaml +</code></pre> +<p>Then run <code>helm install ./workflow --namespace drycc --name drycc</code> to apply the changes, or <code>helm upgrade drycc ./workflow</code> if the cluster is already running.</p> +</li> +</ul> +<h2 id="setting-resource-limits">Setting Resource limits<a class="td-heading-self-link" href="#setting-resource-limits" aria-label="Heading self-link"></a></h2> +<p>You can set resource limits to Workflow components by modifying the values.yaml file fetched +earlier. This file has a section for each Workflow component. To set a limit to any Workflow +component just add <code>limitsCpu</code>, <code>limitsMemory</code> in the section and set them to the appropriate +values.</p> +<p>Below is an example of how the builder section of <code>values.yaml</code> might look with CPU and memory +limits set:</p> +<pre tabindex="0"><code>builder: + imageOrg: &#34;drycc&#34; + imagePullPolicy: &#34;Always&#34; + imageTag: &#34;canary&#34; + limitsCpu: &#34;100m&#34; + limitsMemory: &#34;50Mi&#34; +</code></pre><h2 id="customizing-the-builder">Customizing the Builder<a class="td-heading-self-link" href="#customizing-the-builder" aria-label="Heading self-link"></a></h2> +<p>The following environment variables are tunable for the <a href="/docs/understanding-workflow/components/#builder">Builder</a> component:</p> +<table> +<thead> +<tr> +<th>Setting</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>DEBUG</td> +<td>Enable debug log output (default: false)</td> +</tr> +<tr> +<td>BUILDER_POD_NODE_SELECTOR</td> +<td>A node selector setting for builder job. As it may sometimes consume a lot of node resources, one may want a given builder job to run in a specific node only, so it won&rsquo;t affect critical nodes. for example <code>pool:testing,disk:magnetic</code></td> +</tr> +</tbody> +</table> +<h2 id="customizing-the-controller">Customizing the Controller<a class="td-heading-self-link" href="#customizing-the-controller" aria-label="Heading self-link"></a></h2> +<p>The following environment variables are tunable for the <a href="/docs/understanding-workflow/components/#controller">Controller</a> component:</p> +<table> +<thead> +<tr> +<th>Setting</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>REGISTRATION_MODE</td> +<td>set registration to &ldquo;enabled&rdquo;, &ldquo;disabled&rdquo;, or &ldquo;admin_only&rdquo; (default: &ldquo;admin_only&rdquo;)</td> +</tr> +<tr> +<td>GUNICORN_WORKERS</td> +<td>number of <a href="http://gunicorn.org/">gunicorn</a> workers spawned to process requests (default: CPU cores * 4 + 1)</td> +</tr> +<tr> +<td>RESERVED_NAMES</td> +<td>a comma-separated list of names which applications cannot reserve for routing (default: &ldquo;drycc, drycc-builder&rdquo;)</td> +</tr> +<tr> +<td>DRYCC_DEPLOY_HOOK_URLS</td> +<td>a comma-separated list of URLs to send <a href="/docs/managing-workflow/deploy-hooks/#http-post-hook">deploy hooks</a> to.</td> +</tr> +<tr> +<td>DRYCC_DEPLOY_HOOK_SECRET_KEY</td> +<td>a private key used to compute the HMAC signature for deploy hooks.</td> +</tr> +<tr> +<td>DRYCC_DEPLOY_REJECT_IF_PROCFILE_MISSING</td> +<td>rejects a deploy if the previous build had a Procfile but the current deploy is missing it. A 409 is thrown in the API. Prevents accidental process types removal. (default: &ldquo;false&rdquo;, allowed values: &ldquo;true&rdquo;, &ldquo;false&rdquo;)</td> +</tr> +<tr> +<td>DRYCC_DEPLOY_PROCFILE_MISSING_REMOVE</td> +<td>when turned on (default) any missing process type in a Procfile compared to the previous deploy is removed. When set to false will allow an empty Procfile to go through without removing missing process types, note that new images, configs and so on will get updated on all proc types. (default: &ldquo;true&rdquo;, allowed values: &ldquo;true&rdquo;, &ldquo;false&rdquo;)</td> +</tr> +<tr> +<td>DRYCC_DEFAULT_CONFIG_TAGS</td> +<td>set tags for all applications by default, for example: &lsquo;{&ldquo;role&rdquo;: &ldquo;worker&rdquo;}&rsquo;. (default: &lsquo;&rsquo;)</td> +</tr> +<tr> +<td>KUBERNETES_NAMESPACE_DEFAULT_QUOTA_SPEC</td> +<td>set resource quota to application namespace by setting <a href="http://kubernetes.io/docs/admin/resourcequota/">ResourceQuota</a> spec, for example: <code>{&quot;spec&quot;:{&quot;hard&quot;:{&quot;pods&quot;:&quot;10&quot;}}}</code>, restrict app owner to spawn more then 10 pods (default: &ldquo;&rdquo;, no quota will be applied to namespace)</td> +</tr> +</tbody> +</table> +<h3 id="ldap-authentication-settings">LDAP authentication settings<a class="td-heading-self-link" href="#ldap-authentication-settings" aria-label="Heading self-link"></a></h3> +<p>Configuration options for LDAP authentication are detailed <a href="https://pythonhosted.org/django-auth-ldap/reference.html">here</a>.</p> +<p>The following environment variables are available for enabling LDAP +authentication of user accounts in the <a href="/docs/understanding-workflow/components/#passport">Passport</a> component:</p> +<table> +<thead> +<tr> +<th>Setting</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>LDAP_ENDPOINT</td> +<td>The URI of the LDAP server. If not specified, LDAP authentication is not enabled (default: &ldquo;&rdquo;, example: <code>ldap://hostname</code>).</td> +</tr> +<tr> +<td>LDAP_BIND_DN</td> +<td>The distinguished name to use when binding to the LDAP server (default: &ldquo;&rdquo;)</td> +</tr> +<tr> +<td>LDAP_BIND_PASSWORD</td> +<td>The password to use with LDAP_BIND_DN (default: &ldquo;&rdquo;)</td> +</tr> +<tr> +<td>LDAP_USER_BASEDN</td> +<td>The distinguished name of the search base for user names (default: &ldquo;&rdquo;)</td> +</tr> +<tr> +<td>LDAP_USER_FILTER</td> +<td>The name of the login field in the users search base (default: &ldquo;username&rdquo;)</td> +</tr> +<tr> +<td>LDAP_GROUP_BASEDN</td> +<td>The distinguished name of the search base for user&rsquo;s groups names (default: &ldquo;&rdquo;)</td> +</tr> +<tr> +<td>LDAP_GROUP_FILTER</td> +<td>The filter for user&rsquo;s groups (default: &ldquo;&rdquo;, example: <code>objectClass=person</code>)</td> +</tr> +</tbody> +</table> +<h3 id="global-and-per-application-settings">Global and per application settings<a class="td-heading-self-link" href="#global-and-per-application-settings" aria-label="Heading self-link"></a></h3> +<table> +<thead> +<tr> +<th>Setting</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>DRYCC_DEPLOY_BATCHES</td> +<td>the number of pods to bring up and take down sequentially during a scale (default: number of available nodes)</td> +</tr> +<tr> +<td>DRYCC_DEPLOY_TIMEOUT</td> +<td>deploy timeout in seconds per deploy batch (default: 120)</td> +</tr> +<tr> +<td>IMAGE_PULL_POLICY</td> +<td>the kubernetes <a href="http://kubernetes.io/docs/user-guide/images/">image pull policy</a> for application images (default: &ldquo;IfNotPresent&rdquo;) (allowed values: &ldquo;Always&rdquo;, &ldquo;IfNotPresent&rdquo;)</td> +</tr> +<tr> +<td>KUBERNETES_DEPLOYMENTS_REVISION_HISTORY_LIMIT</td> +<td>how many <a href="http://kubernetes.io/docs/user-guide/deployments/#revision-history-limit">revisions</a> Kubernetes keeps around of a given Deployment (default: all revisions)</td> +</tr> +<tr> +<td>KUBERNETES_POD_TERMINATION_GRACE_PERIOD_SECONDS</td> +<td>how many seconds kubernetes waits for a pod to finish work after a SIGTERM before sending SIGKILL (default: 30)</td> +</tr> +</tbody> +</table> +<p>See the <a href="/docs/applications/deploying-apps/">Deploying Apps</a> guide for more detailed information on those.</p> +<h2 id="customizing-the-database">Customizing the Database<a class="td-heading-self-link" href="#customizing-the-database" aria-label="Heading self-link"></a></h2> +<p>The following environment variables are tunable for the <a href="/docs/understanding-workflow/components/#database">Database</a> component:</p> +<table> +<thead> +<tr> +<th>Setting</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>BACKUP_FREQUENCY</td> +<td>how often the database should perform a base backup (default: &ldquo;12h&rdquo;)</td> +</tr> +<tr> +<td>BACKUPS_TO_RETAIN</td> +<td>number of base backups the backing store should retain (default: 5)</td> +</tr> +</tbody> +</table> +<h2 id="customizing-fluentbit">Customizing Fluentbit<a class="td-heading-self-link" href="#customizing-fluentbit" aria-label="Heading self-link"></a></h2> +<p>The following values can be changed in the <code>values.yaml</code> file or by using the <code>--values</code> flag with the Helm CLI.</p> +<table> +<thead> +<tr> +<th>Key</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>config.service</td> +<td>The service section defines the global properties of the service.</td> +</tr> +<tr> +<td>config.inputs</td> +<td>An input section defines a source (related to an input plugin).</td> +</tr> +<tr> +<td>config.filters</td> +<td>A filter section defines a filter (related to a filter plugin)</td> +</tr> +<tr> +<td>config.outputs</td> +<td>The outputs section specify a destination that certain records should follow after a Tag match.</td> +</tr> +</tbody> +</table> +<p>For more information about the various variables that can be set please see the <a href="https://github.com/drycc/fluentbit">fluentbit</a>.</p> +<h2 id="customizing-the-logger">Customizing the Logger<a class="td-heading-self-link" href="#customizing-the-logger" aria-label="Heading self-link"></a></h2> +<p>The following environment variables are tunable for the <a href="/docs/understanding-workflow/components/#logger-fluentbit-logger">Logger</a> component:</p> +<table> +<thead> +<tr> +<th>Setting</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>STORAGE_ADAPTER</td> +<td>How to store logs that are sent to the logger. Legal values are &ldquo;file&rdquo;, &ldquo;memory&rdquo;, and &ldquo;redis&rdquo;. (default: &ldquo;redis&rdquo;)</td> +</tr> +<tr> +<td>NUMBER_OF_LINES</td> +<td>How many lines to store in the ring buffer (default: 1000)</td> +</tr> +</tbody> +</table> +<h2 id="customizing-the-monitor">Customizing the Monitor<a class="td-heading-self-link" href="#customizing-the-monitor" aria-label="Heading self-link"></a></h2> +<h3 id="grafanahttpsgrafanacom"><a href="https://grafana.com/">Grafana</a><a class="td-heading-self-link" href="#grafanahttpsgrafanacom" aria-label="Heading self-link"></a></h3> +<p>We have exposed some of the more useful configuration values directly in the chart. This allows them to be set using either the <code>values.yaml</code> file or by using the <code>--set</code> flag with the Helm CLI. You can see these options below:</p> +<table> +<thead> +<tr> +<th>Setting</th> +<th>Default Value</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>user</td> +<td>&ldquo;admin&rdquo;</td> +<td>The first user created in the database (this user has admin privileges)</td> +</tr> +<tr> +<td>password</td> +<td>&ldquo;admin&rdquo;</td> +<td>Password for the first user.</td> +</tr> +<tr> +<td>allow_sign_up</td> +<td>&ldquo;true&rdquo;</td> +<td>Allows users to sign up for an account.</td> +</tr> +</tbody> +</table> +<p>For a list of other options you can set by using environment variables please see the <a href="https://github.com/drycc/monitor/blob/main/grafana/rootfs/usr/share/grafana/grafana.ini.tpl">configuration file</a> in Github.</p> +<h3 id="telegrafhttpsdocsinfluxdatacomtelegraf"><a href="https://docs.influxdata.com/telegraf">Telegraf</a><a class="td-heading-self-link" href="#telegrafhttpsdocsinfluxdatacomtelegraf" aria-label="Heading self-link"></a></h3> +<p>For a list of configuration values that can be set by using environment variables please see the following <a href="https://github.com/drycc/monitor/blob/main/telegraf/rootfs/config.toml.tpl">configuration file</a>.</p> +<h3 id="prometheushttpsprometheusio"><a href="https://prometheus.io">Prometheus</a><a class="td-heading-self-link" href="#prometheushttpsprometheusio" aria-label="Heading self-link"></a></h3> +<p>You can find a list of values that can be set using environment variables <a href="https://github.com/drycc/prometheus">here</a>.</p> +<h2 id="customizing-the-registry">Customizing the Registry<a class="td-heading-self-link" href="#customizing-the-registry" aria-label="Heading self-link"></a></h2> +<p>The <a href="/docs/understanding-workflow/components/#registry">Registry</a> component can be tuned by following the +<a href="https://github.com/drycc/distribution/blob/main/docs/configuration.md">drycc/distribution config doc</a>.</p> +<h2 id="customizing-the-router">Customizing the Router<a class="td-heading-self-link" href="#customizing-the-router" aria-label="Heading self-link"></a></h2> +<p>The majority of router settings are tunable through annotations, which allows the router to be +re-configured with zero downtime post-installation. You can find the list of annotations to tune +<a href="https://github.com/drycc/router#annotations">here</a>.</p> +<p>The following environment variables are tunable for the [Router][] component:</p> +<table> +<thead> +<tr> +<th>Setting</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>POD_NAMESPACE</td> +<td>The pod namespace the router resides in. This is set by the <a href="http://kubernetes.io/docs/user-guide/downward-api/">Kubernetes downward API</a>.</td> +</tr> +</tbody> +</table> +<h2 id="customizing-workflow-manager">Customizing Workflow Manager<a class="td-heading-self-link" href="#customizing-workflow-manager" aria-label="Heading self-link"></a></h2> +<p>The following environment variables are tunable for [Workflow Manager][]:</p> +<table> +<thead> +<tr> +<th>Setting</th> +<th>Description</th> +</tr> +</thead> +<tbody> +<tr> +<td>CHECK_VERSIONS</td> +<td>Enables the external version check at <a href="https://versions.drycc.info/">https://versions.drycc.info/</a> (default: &ldquo;true&rdquo;)</td> +</tr> +<tr> +<td>POLL_INTERVAL_SEC</td> +<td>The interval when Workflow Manager performs a version check, in seconds (default: 43200, or 12 hours)</td> +</tr> +<tr> +<td>VERSIONS_API_URL</td> +<td>The versions API URL (default: &ldquo;<a href="https://versions-staging.drycc.info">https://versions-staging.drycc.info</a>&rdquo;)</td> +</tr> +<tr> +<td>DOCTOR_API_URL</td> +<td>The doctor API URL (default: &ldquo;<a href="https://doctor-staging.drycc.info">https://doctor-staging.drycc.info</a>&rdquo;)</td> +</tr> +<tr> +<td>API_VERSION</td> +<td>The version number Workflow Manager sends to the versions API (default: &ldquo;v2&rdquo;)</td> +</tr> +</tbody> +</table> + + + + + + Docs: Configure DNS + /docs/managing-workflow/configuring-dns/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/managing-workflow/configuring-dns/ + + + + <p>For example, assuming <code>example.com</code> were a cluster&rsquo;s domain:</p> +<ul> +<li>The controller should be accessible at <code>drycc.example.com</code></li> +<li>Applications should be accessible (by default) at <code>&lt;application name&gt;.example.com</code></li> +</ul> +<p>Given that this is the case, the primary objective in configuring DNS is that traffic for all subdomains of a cluster&rsquo;s domain be directed to the cluster node(s) hosting the platform&rsquo;s router component, which is capable of directing traffic within the cluster to the correct endpoints.</p> +<h2 id="with-a-load-balancer">With a Load Balancer<a class="td-heading-self-link" href="#with-a-load-balancer" aria-label="Heading self-link"></a></h2> +<p>Generally, it is recommended that a [load balancer][] be used to direct inbound traffic to one or more routers. In such a case, configuring DNS is as simple as defining a wildcard record in DNS that points to the load balancer.</p> +<p>For example, assuming a domain of <code>example.com</code>:</p> +<ul> +<li>An <code>A</code> record enumerating each of your load balancer(s) IPs (i.e. DNS round-robining)</li> +<li>A <code>CNAME</code> record referencing an existing fully-qualified domain name for the load balancer +<ul> +<li>Per <a href="https://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/using-domain-names-with-elb.html">AWS&rsquo; own documentation</a>, this is the recommended strategy when using AWS Elastic Load Balancers, as ELB IPs may change over time.</li> +</ul> +</li> +</ul> +<p>DNS for any applications using a &ldquo;custom domain&rdquo; (a fully-qualified domain name that is not a subdomain of the cluster&rsquo;s own domain) can be configured by creating a <code>CNAME</code> record that references the wildcard record described above.</p> +<p>Although it is dependent upon your distribution of Kubernetes and your underlying infrastructure, in many cases, the IP(s) or existing fully-qualified domain name of a load balancer can be determined directly using the <code>kubectl</code> tool:</p> +<pre tabindex="0"><code>$ kubectl --namespace=istio-nginx describe service | grep &#34;LoadBalancer&#34; +LoadBalancer Ingress: a493e4e58ea0511e5bb390686bc85da3-1558404688.us-west-2.elb.amazonaws.com +</code></pre><p>The <code>LoadBalancer Ingress</code> field typically describes an existing domain name or public IP(s). Note that if Kubernetes is able to automatically provision a load balancer for you, it does so asynchronously. If the command shown above is issued very soon after Workflow installation, the load balancer may not exist yet.</p> +<h2 id="without-a-load-balancer">Without a Load Balancer<a class="td-heading-self-link" href="#without-a-load-balancer" aria-label="Heading self-link"></a></h2> +<p>On some platforms (Minikube, for instance), a load balancer is not an easy or practical thing to provision. In these cases, one can directly identify the public IP of a Kubernetes node that is hosting a router pod and use that information to configure the local <code>/etc/hosts</code> file.</p> +<p>Because wildcard entries do not work in a local <code>/etc/hosts</code> file, using this strategy may result in frequent editing of that file to add fully-qualified subdomains of a cluster for each application added to that cluster. Because of this a more viable option may be to utilize the <a href="http://xip.io/">xip.io</a> service.</p> +<p>In general, for any IP, <code>a.b.c.d</code>, the fully-qualified domain name <code>any-subdomain.a.b.c.d.xip.io</code> will resolve to the IP <code>a.b.c.d</code>. This can be enormously useful.</p> +<p>To begin, find the node(s) hosting router instances using <code>kubectl</code>:</p> +<pre tabindex="0"><code>$ kubectl --namespace=istio-ingress describe pod | grep Node: +Node: ip-10-0-0-199.us-west-2.compute.internal/10.0.0.199 +Node: ip-10-0-0-198.us-west-2.compute.internal/10.0.0.198 +</code></pre><p>The command will display information for every router pod. For each, a node name and IP are displayed in the <code>Node</code> field. If the IPs appearing in these fields are public, any of these may be used to configure your local <code>/etc/hosts</code> file or may be used with <a href="http://xip.io/">xip.io</a>. If the IPs shown are not public, further investigation may be needed.</p> +<p>You can list the IP addresses of a node using <code>kubectl</code>:</p> +<pre tabindex="0"><code>$ kubectl describe node ip-10-0-0-199.us-west-2.compute.internal +# ... +Addresses: 10.0.0.199,10.0.0.199,54.218.85.175 +# ... +</code></pre><p>Here, the <code>Addresses</code> field lists all the node&rsquo;s IPs. If any of them are public, again, they may be used to configure your local <code>/etc/hosts</code> file or may be used with <a href="http://xip.io/">xip.io</a>.</p> +<h2 id="tutorial-configuring-dns-with-google-cloud-dnscloud-dns">Tutorial: Configuring DNS with <a href="https://cloud.google.com/dns/docs">Google Cloud DNS</a><a class="td-heading-self-link" href="#tutorial-configuring-dns-with-google-cloud-dnscloud-dns" aria-label="Heading self-link"></a></h2> +<p>In this section, we&rsquo;ll describe how to configure Google Cloud DNS for routing your domain name to your Drycc cluster.</p> +<p>We&rsquo;ll assume the following in this section:</p> +<ul> +<li>Your Ingress service has a load balancer in front of it. +<ul> +<li>The load balancer need not be cloud based, it just needs to provide a stable IP address or a stable domain name</li> +</ul> +</li> +<li>You have the <code>mystuff.com</code> domain name registered with a registrar +<ul> +<li>Replace your domain name with <code>mystuff.com</code> in the instructions to follow</li> +</ul> +</li> +<li>Your registrar lets you alter the nameservers for your domain name (most registrars do)</li> +</ul> +<p>Here are the steps for configuring cloud DNS to route to your drycc cluster:</p> +<ol> +<li>Get the load balancer IP or domain name</li> +</ol> +<ul> +<li>If you are on Google Container Engine, you can run <code>kubectl get svc -n istio-ingress</code> and look for the <code>LoadBalancer Ingress</code> column to get the IP address</li> +</ul> +<ol start="2"> +<li>Create a new Cloud DNS Zone (on the console: <code>Networking</code> =&gt; <code>Cloud DNS</code>, then click on <code>Create Zone</code>)</li> +<li>Name your zone, and set the DNS name to <code>mystuff.com.</code> (note the <code>.</code> at the end</li> +<li>Click on the <code>Create</code> button</li> +<li>Click on the <code>Add Record Set</code> button on the resulting page</li> +<li>If your load balancer provides a stable IP address, enter the following fields in the resulting form:</li> +<li><code>DNS Name</code>: <code>*</code></li> +<li><code>Resource Record Type</code>: <code>A</code></li> +<li><code>TTL</code>: the DNS TTL of your choosing. If you&rsquo;re testing or you anticipate that you&rsquo;ll tear down and rebuild many drycc clusters over time, we recommend a low TTL</li> +<li><code>IPv4 Address</code>: The IP that you got in the very first step</li> +<li>Click the <code>Create</code> button</li> +<li>If your load balancer provides the stable domain name <code>lbdomain.com</code>, enter the following fields in the resulting form:</li> +<li><code>DNS Name</code>: <code>*</code></li> +<li><code>Resource Record Type</code>: <code>CNAME</code></li> +<li><code>TTL</code>: the DNS TTL of your choosing. If you&rsquo;re testing or you anticipate that you&rsquo;ll tear down and rebuild many drycc clusters over time, we recommend a low TTL</li> +<li><code>Canonical name</code>: <code>lbdomain.com.</code> (note the <code>.</code> a the end)</li> +<li>Click on the <code>Create</code> button</li> +<li>In your domain registrar, set the nameservers for your <code>mystuff.com</code> domain to the ones under the <code>data</code> column in the <code>NS</code> record on the same page. They&rsquo;ll often be something like the below (note the trailing <code>.</code> characters).</li> +</ol> +<pre tabindex="0"><code>ns-cloud-b1.googledomains.com. +ns-cloud-b2.googledomains.com. +ns-cloud-b3.googledomains.com. +ns-cloud-b4.googledomains.com. +</code></pre><p>Note: If you ever have to re-create your drycc cluster, simply go back to step 6.4 or 7.4 (depending on your load balancer) and change the IP address or domain name to the new value. You may have to wait for the TTL you set to expire.</p> +<h2 id="testing">Testing<a class="td-heading-self-link" href="#testing" aria-label="Heading self-link"></a></h2> +<p>To test that traffic reaches its intended destination, a request can be +sent to the Drycc controller like so (do not forget the trailing slash!):</p> +<pre tabindex="0"><code>curl http://drycc.example.com/v2/ +</code></pre><p>Or:</p> +<pre tabindex="0"><code>curl http://drycc.54.218.85.175.xip.io/v2/ +</code></pre><p>Since such requests require authentication, a response such as the following should be considered an indicator of success:</p> +<pre tabindex="0"><code>{&#34;detail&#34;:&#34;Authentication credentials were not provided.&#34;} +</code></pre> + + + + + Docs: Deploy Hooks + /docs/managing-workflow/deploy-hooks/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/managing-workflow/deploy-hooks/ + + + + <p>It’s useful to help keep the development team informed about deploys, while +it can also be used to integrate different systems together.</p> +<p>After one or more hooks are setup, hook output and errors appear in your application’s logs:</p> +<pre tabindex="0"><code>$ drycc logs +... +2011-03-15T15:07:29-07:00 drycc[api]: Deploy hook sent to http://drycc.rocks +</code></pre><p>Deploy hooks are a generic HTTP hook. An administrator can create and configure multiple deploy +hooks by <a href="/docs/managing-workflow/tuning-component-settings/#customizing-the-controller">tuning the controller settings</a> via the Helm chart.</p> +<h2 id="http-post-hook">HTTP POST Hook<a class="td-heading-self-link" href="#http-post-hook" aria-label="Heading self-link"></a></h2> +<p>The HTTP deploy hook performs an HTTP POST to a URL. The parameters included in the request are the +same as the variables available in the hook message: <code>app</code>, <code>release</code>, <code>release_summary</code>, <code>sha</code> and +<code>user</code>. See below for their descriptions:</p> +<pre tabindex="0"><code>app=secure-woodland&amp;release=v4&amp;release_summary=gabrtv%20deployed%35b3726&amp;sha=35b3726&amp;user=gabrtv +</code></pre><p>Optionally, if a deploy hook secret key is added to the controller through +<a href="/docs/managing-workflow/tuning-component-settings/#customizing-the-controller">tuning the controller settings</a>, a new <code>Authorization</code> header will be +present in the POST request. The value of this header is computed as the <a href="https://en.wikipedia.org/wiki/Hash-based_message_authentication_code">HMAC</a> hex digest of the +request URL, using the secret as the key.</p> +<p>In order to authenticate that this request came from Workflow, use the secret key, the full URL and +the HMAC-SHA1 hashing algorithm to compute the signature. In Python, that would look something like +this:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#204a87;font-weight:bold">import</span> <span style="color:#000">hashlib</span> +</span></span><span style="display:flex;"><span><span style="color:#204a87;font-weight:bold">import</span> <span style="color:#000">hmac</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#000">hmac</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#000">new</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;my_secret_key&#34;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#4e9a06">&#34;http://drycc.rocks?app=secure-woodland&amp;release=v4&amp;release_summary=gabrtv</span><span style="color:#4e9a06">%20d</span><span style="color:#4e9a06">eployed%35b3726&amp;sha=35b3726&amp;user=gabrtv&#34;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">digestmod</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#000">hashlib</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#000">sha1</span><span style="color:#000;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#000">hexdigest</span><span style="color:#000;font-weight:bold">()</span> +</span></span></code></pre></div><p>If the value of the computed HMAC hex digest and the value in the <code>Authorization</code> header are +identical, then the request came from Workflow.</p> +<p>!!! important +When computing the signature, ensure that the URL parameters are in alphabetic order. This is +critical when computing the cryptographic signature as most web applications don&rsquo;t care about +the order of the HTTP parameters, but the cryptographic signature will not be the same.</p> + + + + + + Docs: Platform Logging + /docs/managing-workflow/platform-logging/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/managing-workflow/platform-logging/ + + + + <p>The logging platform is made up of 2 components - <a href="https://github.com/drycc/fluentbit">Fluentbit</a> and <a href="https://github.com/drycc/logger">Logger</a>.</p> +<p><a href="https://github.com/drycc/fluentbit">Fluentbit</a> runs on every worker node of the cluster and is deployed as a <a href="http://kubernetes.io/v1.1/docs/admin/daemons.html">Daemon Set</a>. The Fluentbit pods capture all of the stderr and stdout streams of every container running on the host (even those not hosted directly by kubernetes). Once the log message arrives in our <a href="https://github.com/drycc/fluentbit/tree/main/plugin">custom fluentbit plugin</a> we determine where the message originated.</p> +<p>If the message was from the <a href="https://github.com/drycc/controller">Workflow Controller</a> or from an application deployed via workflow we send it to the logs topic on the local <a href="http://redis.io">Redis Stream</a> instance.</p> +<p>Logger then acts as a consumer reading messages off of the Redis Stream logs topic storing those messages in a local Redis instance. When a user wants to retrieve log entries using the <code>drycc logs</code> command we make an HTTP request from Controller to Logger which then fetches the appropriate data from Redis.</p> +<h2 id="configuring-off-cluster-redis">Configuring Off Cluster Redis<a class="td-heading-self-link" href="#configuring-off-cluster-redis" aria-label="Heading self-link"></a></h2> +<p>Even though we provide a redis instance with the default Workflow install, it is recommended that operators use a third-party source like Elasticache or similar offering. This way your data is durable across upgrades or outages. If you have a third-party Redis installation you would like to use all you need to do is set the following values in your helm chart:</p> +<ul> +<li>db = &ldquo;0&rdquo;</li> +<li>host = &ldquo;my.host.redis&rdquo;</li> +<li>port = &ldquo;6379&rdquo;</li> +<li>password = &quot;&quot;</li> +</ul> +<p>These can be changed by running <code>helm inspect values drycc/workflow &gt; values.yaml</code> before using +<code>helm install</code> to complete the installation. To customize the redis credentials, edit <code>values.yaml</code> +and modify the <code>redis</code> section of the file to tune these settings.</p> +<h2 id="debugging-logger">Debugging Logger<a class="td-heading-self-link" href="#debugging-logger" aria-label="Heading self-link"></a></h2> +<p>If the <code>drycc logs</code> command encounters an error it will return the following message:</p> +<pre tabindex="0"><code>Error: There are currently no log messages. Please check the following things: +1) Logger and fluentbit pods are running. +2) The application is writing logs to the logger component by checking that an entry in the ring buffer was created: kubectl --namespace=drycc logs &lt;logger pod&gt; +3) Making sure that the container logs were mounted properly into the fluentbit pod: kubectl --namespace=drycc exec &lt;fluentbit pod&gt; ls /var/log/containers +</code></pre><h2 id="architecture-diagram">Architecture Diagram<a class="td-heading-self-link" href="#architecture-diagram" aria-label="Heading self-link"></a></h2> +<pre tabindex="0"><code> ┌────────┐ + │ Router │ ┌────────┐ ┌─────┐ + └────────┘ │ Logger │◀───▶│Redis│ + │ └────────┘ └─────┘ + Log file ▲ + │ │ + ▼ │ +┌────────┐ ┌─────────┐ logs/metrics ┌──────────────┐ +│App Logs│──Log File──▶│Fluentbit│───────topics─────▶│ Redis Stream │ +└────────┘ └─────────┘ └──────────────┘ + +</code></pre><h2 id="default-configuration">Default Configuration<a class="td-heading-self-link" href="#default-configuration" aria-label="Heading self-link"></a></h2> +<p>Fluent Bit is based in a pluggable architecture where different plugins plays a major role in the data pipeline, more than 70 built-in plugins available. +Please refer to charts <a href="https://github.com/drycc/fluentbit/blob/main/charts/fluentbit/values.yaml">values.yaml</a> for specific configurations.</p> + + + + + + Docs: Platform Monitoring + /docs/managing-workflow/platform-monitoring/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/managing-workflow/platform-monitoring/ + + + + <h2 id="description">Description<a class="td-heading-self-link" href="#description" aria-label="Heading self-link"></a></h2> +<p>We now include a monitoring stack for introspection on a running Kubernetes cluster. The stack includes 4 components:</p> +<ul> +<li><a href="https://github.com/kubernetes/kube-state-metrics">kube-state-metrics</a>, kube-state-metrics (KSM) is a simple service that listens to the Kubernetes API server and generates metrics about the state of the objects.</li> +<li><a href="http://github.com/prometheus/node_exporter">Node Exporter</a>, Prometheus exporter for hardware and OS metrics exposed by *NIX kernels.</li> +<li><a href="https://prometheus.io/">Prometheus</a>, a <a href="https://cncf.io/">Cloud Native Computing Foundation</a> project, is a systems and service monitoring system.</li> +<li><a href="http://grafana.org/">Grafana</a>, Graphing tool for time series data</li> +</ul> +<h2 id="architecture-diagram">Architecture Diagram<a class="td-heading-self-link" href="#architecture-diagram" aria-label="Heading self-link"></a></h2> +<pre tabindex="0"><code>┌────────────────┐ +│ HOST │ +│ node-exporter │◀──┐ ┌──────────────────┐ +└────────────────┘ │ │kube-state-metrics│ + │ └──────────────────┘ +┌────────────────┐ │ ▲ +│ HOST │ │ ┌────────────┐ │ +│ node-exporter │◀──┼────│ Prometheus │─────────────┘ +└────────────────┘ │ └────────────┘ + │ ▲ +┌───────────────┐ │ │ +│ HOST │ │ ▼ +│ node-exporter│◀───┘ ┌──────────┐ +└───────────────┘ │ Grafana │ + └──────────┘ +</code></pre><h2 id="grafanahttpsgrafanacom"><a href="https://grafana.com/">Grafana</a><a class="td-heading-self-link" href="#grafanahttpsgrafanacom" aria-label="Heading self-link"></a></h2> +<p>Grafana allows users to create custom dashboards that visualize the data captured to the running Prometheus component. By default Grafana is exposed using a <a href="https://github.com/drycc/router#how-it-works">service annotation</a> through the router at the following URL: <code>http://grafana.mydomain.com</code>. The default login is <code>admin/admin</code>. If you are interested in changing these values please see [Tuning Component Settings][].</p> +<p>Grafana will preload several dashboards to help operators get started with monitoring Kubernetes and Drycc Workflow. +These dashboards are meant as starting points and don&rsquo;t include every item that might be desirable to monitor in a +production installation.</p> +<p>Drycc Workflow monitoring by default does not write data to the host filesystem or to long-term storage. If the Grafana instance fails, modified dashboards are lost.</p> +<h3 id="production-configuration">Production Configuration<a class="td-heading-self-link" href="#production-configuration" aria-label="Heading self-link"></a></h3> +<p>A production install of Grafana should have the following configuration values changed if possible:</p> +<ul> +<li>Change the default username and password from <code>admin/admin</code>. The value for the password is passed in plain text so it is best to set this value on the command line instead of checking it into version control.</li> +<li>Enable persistence</li> +<li>Use a supported external database such as mysql or postgres. You can find more information <a href="https://github.com/drycc/monitor/blob/main/grafana/rootfs/usr/share/grafana/grafana.ini.tpl#L62">here</a></li> +</ul> +<h3 id="on-cluster-persistence">On Cluster Persistence<a class="td-heading-self-link" href="#on-cluster-persistence" aria-label="Heading self-link"></a></h3> +<p>Enabling persistence will allow your custom configuration to persist across pod restarts. This means that the default sqllite database (which stores things like sessions and user data) will not disappear if you upgrade the Workflow installation.</p> +<p>If you wish to have persistence for Grafana you can set <code>enabled</code> to <code>true</code> in the <code>values.yaml</code> file before running <code>helm install</code>.</p> +<pre tabindex="0"><code> grafana: + # Configure the following ONLY if you want persistence for on-cluster grafana + # GCP PDs and EBS volumes are supported only + persistence: + enabled: true # Set to true to enable persistence + size: 5Gi # PVC size +</code></pre><h3 id="off-cluster-grafana">Off Cluster Grafana<a class="td-heading-self-link" href="#off-cluster-grafana" aria-label="Heading self-link"></a></h3> +<p>If you wish to provide your own Grafana instance you can set <code>grafanaLocation</code> in the <code>values.yaml</code> file before running <code>helm install</code>.</p> +<h2 id="prometheushttpsprometheusio"><a href="https://prometheus.io/">Prometheus</a><a class="td-heading-self-link" href="#prometheushttpsprometheusio" aria-label="Heading self-link"></a></h2> +<p>Prometheus writes data to the host disk; however, if the prometheus pod dies and comes back on another host, the data will not be recovered. The prometheus graph UI is also exposed through the router allowing users to access the query engine by going to <code>prometheus.mydomain.com</code>.</p> +<h3 id="on-cluster-persistence-1">On Cluster Persistence<a class="td-heading-self-link" href="#on-cluster-persistence-1" aria-label="Heading self-link"></a></h3> +<p>You can set <code>node-exporter</code> and <code>kube-state-metrics</code> to <code>true</code> or <code>false</code> in the <code>values.yaml</code>. +If you wish to have persistence for Prometheus you can set <code>enabled</code> to <code>true</code> in the <code>values.yaml</code> file before running <code>helm install</code>.</p> +<pre tabindex="0"><code>prometheus: + prometheus-server: + persistence: + enabled: true # Set to true to enable persistence + size: 10Gi # PVC size +node-exporter: + enabled: true +kube-state-metrics: + enabled: true +</code></pre><h3 id="off-cluster-prometheus">Off Cluster Prometheus<a class="td-heading-self-link" href="#off-cluster-prometheus" aria-label="Heading self-link"></a></h3> +<p>To use off-cluster Prometheus, please provide the following values in the <code>values.yaml</code> file before running <code>helm install</code>.</p> +<ul> +<li><code>global.prometheusLocation=off-cluster</code></li> +<li><code>url = &quot;http://my.prometheus.url:9090&quot;</code></li> +</ul> + + + + + + Docs: Production Deployments + /docs/managing-workflow/production-deployments/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/managing-workflow/production-deployments/ + + + + <h2 id="running-workflow-without-drycc-storage">Running Workflow without drycc storage<a class="td-heading-self-link" href="#running-workflow-without-drycc-storage" aria-label="Heading self-link"></a></h2> +<p>In production, persistent storage can be achieved by running an external object store. +For users on AWS, GCE/GKE or Azure, the convenience of Amazon S3, Google GCS or Microsoft Azure Storage +makes the prospect of running a Storage-less Workflow cluster quite reasonable. For users who have restriction +on using external object storage using swift object storage can be an option.</p> +<p>Running a Workflow cluster without Storage provides several advantages:</p> +<ul> +<li>Removal of state from the worker nodes</li> +<li>Reduced resource usage</li> +<li>Reduced complexity and operational burden of managing Workflow</li> +</ul> +<p>See <a href="/docs/installing-workflow/configuring-object-storage/">Configuring Object Storage</a> for details on removing this operational complexity.</p> +<h2 id="review-security-considerations">Review Security Considerations<a class="td-heading-self-link" href="#review-security-considerations" aria-label="Heading self-link"></a></h2> +<p>There are some additional security-related considerations when running Workflow in production. +See [Security Considerations][] for details.</p> +<h2 id="registration-is-admin-only">Registration is Admin-Only<a class="td-heading-self-link" href="#registration-is-admin-only" aria-label="Heading self-link"></a></h2> +<p>By default, registration with the Workflow controller is in &ldquo;admin_only&rdquo; mode. The first user +to run a <code>drycc register</code> command becomes the initial &ldquo;admin&rdquo; user, and registrations after that +are disallowed unless requested by an admin.</p> +<p>Please see the following documentation to learn about changing registration mode:</p> +<ul> +<li><a href="/docs/managing-workflow/tuning-component-settings/#customizing-the-controller">Customizing Controller</a></li> +</ul> +<h2 id="disable-grafana-signups">Disable Grafana Signups<a class="td-heading-self-link" href="#disable-grafana-signups" aria-label="Heading self-link"></a></h2> +<p>It is also recommended to disable signups for the Grafana dashboards.</p> +<p>Please see the following documentation to learn about disabling Grafana signups:</p> +<ul> +<li><a href="/docs/managing-workflow/tuning-component-settings/#customizing-the-monitor">Customizing Monitor</a></li> +</ul> +<h2 id="running-workflow-with-rbac">Running Workflow with RBAC<a class="td-heading-self-link" href="#running-workflow-with-rbac" aria-label="Heading self-link"></a></h2> +<p>If your cluster has <a href="https://kubernetes.io/docs/admin/authorization/rbac/">RBAC</a> amongst your <a href="https://kubernetes.io/docs/admin/authorization/">authorization</a> modes (<code>$ kubectl api-versions</code> should contains <code>rbac.authorization.k8s.io</code>) it may be necessary to enable RBAC in Workflow. +This can be achieved by setting <code>use_rbac</code> in the <code>global</code> section of <code>values.yaml</code> to <code>true</code>, or by adding <code>--set=global.use_rbac=true</code> to the <code>$ helm install/upgrade</code> command. +RBAC support was announced in Kubernetes-1.5 and is enabled by default if:</p> +<ul> +<li>your Kubernetes cluster is in GKE</li> +<li>your Kubernetes cluster built with <a href="https://kubernetes.io/docs/getting-started-guides/kubeadm/">kubeadm</a></li> +</ul> +<p><strong>Note</strong>: helm may need to be given <a href="/docs/installing-workflow/#check-your-authorization">specific permissions</a> under RBAC if not already done.</p> +<p><strong>Attention</strong>: Azure ACS Kubernetes clusters are not RBAC-enabled for today due to lack in authentication strategy. Feel free to watch this <a href="https://github.com/kubernetes/kubernetes/pull/43987">PR</a> for more details.</p> + + + + + + Docs: Upgrading Workflow + /docs/managing-workflow/upgrading-workflow/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/managing-workflow/upgrading-workflow/ + + + + <p>This upgrade process requires:</p> +<ul> +<li>Helm version <a href="https://github.com/kubernetes/helm/releases/tag/v2.1.0">2.1.0 or newer</a></li> +<li>Configured Off-Cluster Storage</li> +</ul> +<h2 id="upgrade-process">Upgrade Process<a class="td-heading-self-link" href="#upgrade-process" aria-label="Heading self-link"></a></h2> +<p>!!! note +If upgrading from a <a href="https://github.com/helm/helm-classic">Helm Classic</a> install, you&rsquo;ll need to &lsquo;migrate&rsquo; the cluster to a <a href="https://github.com/kubernetes/helm">Kubernetes Helm</a> installation. See <a href="https://github.com/drycc/workflow-migration/blob/main/README.md">Workflow-Migration</a> for steps.</p> +<h3 id="step-1-apply-the-workflow-upgrade">Step 1: Apply the Workflow upgrade<a class="td-heading-self-link" href="#step-1-apply-the-workflow-upgrade" aria-label="Heading self-link"></a></h3> +<p>Helm will remove all components from the previous release. Traffic to applications deployed through +Workflow will continue to flow during the upgrade. No service interruptions should occur.</p> +<p>If Workflow is not configured to use off-cluster Postgres, the Workflow API will experience a brief +period of downtime while the database recovers from backup.</p> +<p>First, find the name of the release helm gave to your deployment with <code>helm ls</code>, then run</p> +<pre tabindex="0"><code>$ helm upgrade &lt;release-name&gt; oci://registry.drycc.cc/charts/workflow +</code></pre><p><strong>Note:</strong> If using off-cluster object storage on <a href="https://cloud.google.com/storage/">gcs</a> and/or off-cluster registry using <a href="https://cloud.google.com/container-registry/">gcr</a> and intending to upgrade from a pre-<code>v2.10.0</code> chart to <code>v2.10.0</code> or greater, the <code>key_json</code> values will now need to be pre-base64-encoded. Therefore, assuming the rest of the custom/off-cluster values are defined in the existing <code>values.yaml</code> used for previous installs, the following may be run:</p> +<pre tabindex="0"><code>$ B64_KEY_JSON=&#34;$(cat ~/path/to/key.json | base64 -w 0)&#34; +$ helm upgrade &lt;release_name&gt; drycc/workflow -f values.yaml --set gcs.key_json=&#34;${B64_KEY_JSON}&#34;,registry-token-refresher.gcr.key_json=&#34;${B64_KEY_JSON}&#34; +</code></pre><p>Alternatively, simply replace the appropriate values in values.yaml and do without the <code>--set</code> +parameter. Make sure to wrap it in single quotes as double quotes will give a parser error when +upgrading.</p> +<h3 id="step-2-verify-upgrade">Step 2: Verify Upgrade<a class="td-heading-self-link" href="#step-2-verify-upgrade" aria-label="Heading self-link"></a></h3> +<p>Verify that all components have started and passed their readiness checks:</p> +<pre tabindex="0"><code>$ kubectl --namespace=drycc get pods +NAME READY STATUS RESTARTS AGE +drycc-builder-2448122224-3cibz 1/1 Running 0 5m +drycc-controller-1410285775-ipc34 1/1 Running 3 5m +drycc-controller-celery-694f75749b-cmxxn 3/3 Running 0 5m +drycc-database-e7c5z 1/1 Running 0 5m +drycc-logger-cgjup 1/1 Running 3 5m +drycc-logger-fluentbit-45h7j 1/1 Running 0 5m +drycc-logger-fluentbit-4z7lw 1/1 Running 0 5m +drycc-logger-fluentbit-k2wsw 1/1 Running 0 5m +drycc-logger-fluentbit-skdw4 1/1 Running 0 5m +drycc-redis-8nazu 1/1 Running 0 5m +drycc-monitor-grafana-tm266 1/1 Running 0 5m +drycc-monitor-telegraf-51zel 1/1 Running 1 5m +drycc-monitor-telegraf-cdasg 1/1 Running 0 5m +drycc-monitor-telegraf-hea6x 1/1 Running 0 5m +drycc-monitor-telegraf-r7lsg 1/1 Running 0 5m +drycc-registry-1814324048-yomz5 1/1 Running 0 5m +drycc-registry-proxy-4m3o4 1/1 Running 0 5m +drycc-registry-proxy-no3r1 1/1 Running 0 5m +drycc-registry-proxy-ou8is 1/1 Running 0 5m +drycc-registry-proxy-zyajl 1/1 Running 0 5m +drycc-rabbitmq-0 1/1 Running 0 5m +</code></pre><h3 id="step-3-upgrade-the-drycc-client">Step 3: Upgrade the Drycc Client<a class="td-heading-self-link" href="#step-3-upgrade-the-drycc-client" aria-label="Heading self-link"></a></h3> +<p>Users of Drycc Workflow should now upgrade their drycc client to avoid getting <code>WARNING: Client and server API versions do not match. Please consider upgrading.</code> warnings.</p> +<pre tabindex="0"><code>curl -sfL https://www.drycc.cc/install-cli.sh | bash - &amp;&amp; sudo mv drycc $(which drycc) +</code></pre> + + + + + diff --git a/docs/managing-workflow/platform-logging/index.html b/docs/managing-workflow/platform-logging/index.html new file mode 100644 index 000000000..3c6f57bac --- /dev/null +++ b/docs/managing-workflow/platform-logging/index.html @@ -0,0 +1,498 @@ + + + + + + + + + + + + + + + + + + + +Platform Logging | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Platform Logging

+
Logs are a stream of time-stamped events aggregated from the output streams of all your app’s running processes. Retrieve, filter, or use syslog drains.
+ +

The logging platform is made up of 2 components - Fluentbit and Logger.

+

Fluentbit runs on every worker node of the cluster and is deployed as a Daemon Set. The Fluentbit pods capture all of the stderr and stdout streams of every container running on the host (even those not hosted directly by kubernetes). Once the log message arrives in our custom fluentbit plugin we determine where the message originated.

+

If the message was from the Workflow Controller or from an application deployed via workflow we send it to the logs topic on the local Redis Stream instance.

+

Logger then acts as a consumer reading messages off of the Redis Stream logs topic storing those messages in a local Redis instance. When a user wants to retrieve log entries using the drycc logs command we make an HTTP request from Controller to Logger which then fetches the appropriate data from Redis.

+

Configuring Off Cluster Redis

+

Even though we provide a redis instance with the default Workflow install, it is recommended that operators use a third-party source like Elasticache or similar offering. This way your data is durable across upgrades or outages. If you have a third-party Redis installation you would like to use all you need to do is set the following values in your helm chart:

+
    +
  • db = “0”
  • +
  • host = “my.host.redis”
  • +
  • port = “6379”
  • +
  • password = ""
  • +
+

These can be changed by running helm inspect values drycc/workflow > values.yaml before using +helm install to complete the installation. To customize the redis credentials, edit values.yaml +and modify the redis section of the file to tune these settings.

+

Debugging Logger

+

If the drycc logs command encounters an error it will return the following message:

+
Error: There are currently no log messages. Please check the following things:
+1) Logger and fluentbit pods are running.
+2) The application is writing logs to the logger component by checking that an entry in the ring buffer was created: kubectl  --namespace=drycc logs <logger pod>
+3) Making sure that the container logs were mounted properly into the fluentbit pod: kubectl --namespace=drycc exec <fluentbit pod> ls /var/log/containers
+

Architecture Diagram

+
                        ┌────────┐                                        
+                        │ Router │                  ┌────────┐     ┌─────┐
+                        └────────┘                  │ Logger │◀───▶│Redis│
+                            │                       └────────┘     └─────┘
+                        Log file                        ▲                
+                            │                           │                
+                            ▼                           │                
+┌────────┐             ┌─────────┐    logs/metrics   ┌──────────────┐     
+│App Logs│──Log File──▶│Fluentbit│───────topics─────▶│ Redis Stream │     
+└────────┘             └─────────┘                   └──────────────┘     
+                                                                          
+

Default Configuration

+

Fluent Bit is based in a pluggable architecture where different plugins plays a major role in the data pipeline, more than 70 built-in plugins available. +Please refer to charts values.yaml for specific configurations.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/managing-workflow/platform-monitoring/index.html b/docs/managing-workflow/platform-monitoring/index.html new file mode 100644 index 000000000..962687cac --- /dev/null +++ b/docs/managing-workflow/platform-monitoring/index.html @@ -0,0 +1,541 @@ + + + + + + + + + + + + + + + + + + + +Platform Monitoring | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Platform Monitoring

+
Platform monitoring to your apps to spot issues in advance and respond to incidents quickly.
+ +

Description

+

We now include a monitoring stack for introspection on a running Kubernetes cluster. The stack includes 4 components:

+ +

Architecture Diagram

+
┌────────────────┐                                                        
+│ HOST           │                                                        
+│  node-exporter │◀──┐                       ┌──────────────────┐         
+└────────────────┘   │                       │kube-state-metrics│         
+                     │                       └──────────────────┘         
+┌────────────────┐   │                               ▲                    
+│ HOST           │   │    ┌────────────┐             │                    
+│  node-exporter │◀──┼────│ Prometheus │─────────────┘                    
+└────────────────┘   │    └────────────┘                                  
+                     │          ▲                                         
+┌───────────────┐    │          │                                         
+│ HOST          │    │          ▼                                         
+│  node-exporter│◀───┘    ┌──────────┐                                    
+└───────────────┘         │ Grafana  │                                    
+                          └──────────┘                                    
+

Grafana

+

Grafana allows users to create custom dashboards that visualize the data captured to the running Prometheus component. By default Grafana is exposed using a service annotation through the router at the following URL: http://grafana.mydomain.com. The default login is admin/admin. If you are interested in changing these values please see [Tuning Component Settings][].

+

Grafana will preload several dashboards to help operators get started with monitoring Kubernetes and Drycc Workflow. +These dashboards are meant as starting points and don’t include every item that might be desirable to monitor in a +production installation.

+

Drycc Workflow monitoring by default does not write data to the host filesystem or to long-term storage. If the Grafana instance fails, modified dashboards are lost.

+

Production Configuration

+

A production install of Grafana should have the following configuration values changed if possible:

+
    +
  • Change the default username and password from admin/admin. The value for the password is passed in plain text so it is best to set this value on the command line instead of checking it into version control.
  • +
  • Enable persistence
  • +
  • Use a supported external database such as mysql or postgres. You can find more information here
  • +
+

On Cluster Persistence

+

Enabling persistence will allow your custom configuration to persist across pod restarts. This means that the default sqllite database (which stores things like sessions and user data) will not disappear if you upgrade the Workflow installation.

+

If you wish to have persistence for Grafana you can set enabled to true in the values.yaml file before running helm install.

+
 grafana:
+   # Configure the following ONLY if you want persistence for on-cluster grafana
+   # GCP PDs and EBS volumes are supported only
+   persistence:
+     enabled: true # Set to true to enable persistence
+     size: 5Gi # PVC size
+

Off Cluster Grafana

+

If you wish to provide your own Grafana instance you can set grafanaLocation in the values.yaml file before running helm install.

+

Prometheus

+

Prometheus writes data to the host disk; however, if the prometheus pod dies and comes back on another host, the data will not be recovered. The prometheus graph UI is also exposed through the router allowing users to access the query engine by going to prometheus.mydomain.com.

+

On Cluster Persistence

+

You can set node-exporter and kube-state-metrics to true or false in the values.yaml. +If you wish to have persistence for Prometheus you can set enabled to true in the values.yaml file before running helm install.

+
prometheus:
+  prometheus-server:
+    persistence:
+      enabled: true # Set to true to enable persistence
+      size: 10Gi # PVC size
+node-exporter:
+  enabled: true
+kube-state-metrics:
+  enabled: true
+

Off Cluster Prometheus

+

To use off-cluster Prometheus, please provide the following values in the values.yaml file before running helm install.

+
    +
  • global.prometheusLocation=off-cluster
  • +
  • url = "http://my.prometheus.url:9090"
  • +
+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/managing-workflow/production-deployments/index.html b/docs/managing-workflow/production-deployments/index.html new file mode 100644 index 000000000..7ad2f9fb7 --- /dev/null +++ b/docs/managing-workflow/production-deployments/index.html @@ -0,0 +1,502 @@ + + + + + + + + + + + + + + + + + + + +Production Deployments | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Production Deployments

+
When readying a Workflow deployment for production workloads, there are some additional recommendations.
+ +

Running Workflow without drycc storage

+

In production, persistent storage can be achieved by running an external object store. +For users on AWS, GCE/GKE or Azure, the convenience of Amazon S3, Google GCS or Microsoft Azure Storage +makes the prospect of running a Storage-less Workflow cluster quite reasonable. For users who have restriction +on using external object storage using swift object storage can be an option.

+

Running a Workflow cluster without Storage provides several advantages:

+
    +
  • Removal of state from the worker nodes
  • +
  • Reduced resource usage
  • +
  • Reduced complexity and operational burden of managing Workflow
  • +
+

See Configuring Object Storage for details on removing this operational complexity.

+

Review Security Considerations

+

There are some additional security-related considerations when running Workflow in production. +See [Security Considerations][] for details.

+

Registration is Admin-Only

+

By default, registration with the Workflow controller is in “admin_only” mode. The first user +to run a drycc register command becomes the initial “admin” user, and registrations after that +are disallowed unless requested by an admin.

+

Please see the following documentation to learn about changing registration mode:

+ +

Disable Grafana Signups

+

It is also recommended to disable signups for the Grafana dashboards.

+

Please see the following documentation to learn about disabling Grafana signups:

+ +

Running Workflow with RBAC

+

If your cluster has RBAC amongst your authorization modes ($ kubectl api-versions should contains rbac.authorization.k8s.io) it may be necessary to enable RBAC in Workflow. +This can be achieved by setting use_rbac in the global section of values.yaml to true, or by adding --set=global.use_rbac=true to the $ helm install/upgrade command. +RBAC support was announced in Kubernetes-1.5 and is enabled by default if:

+
    +
  • your Kubernetes cluster is in GKE
  • +
  • your Kubernetes cluster built with kubeadm
  • +
+

Note: helm may need to be given specific permissions under RBAC if not already done.

+

Attention: Azure ACS Kubernetes clusters are not RBAC-enabled for today due to lack in authentication strategy. Feel free to watch this PR for more details.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/managing-workflow/tuning-component-settings/index.html b/docs/managing-workflow/tuning-component-settings/index.html new file mode 100644 index 000000000..f592ea4f1 --- /dev/null +++ b/docs/managing-workflow/tuning-component-settings/index.html @@ -0,0 +1,822 @@ + + + + + + + + + + + + + + + + + + + +Tuning Component Settings | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Tuning Component Settings

+
Helm Charts are a set of Kubernetes manifests that reflect best practices for deploying an application or service on Kubernetes.
+ +

After you add the Drycc Chart Repository, you can customize the chart using +helm inspect values drycc/workflow > values.yaml before using helm install to complete the +installation.

+

There are a few ways to customize the respective component:

+
    +
  • +

    If the value is exposed in the values.yaml file as derived above, one may modify the section of the component to tune these settings. The modified value(s) will then take effect at chart installation or release upgrade time via either of the two respective commands:

    +
     $ helm install drycc oci://registry.drycc.cc/charts/workflow \
    +     -n drycc \
    +     --namespace drycc \
    +     -f values.yaml
    + $ helm upgrade drycc oci://registry.drycc.cc/charts/workflow \
    +     -n drycc \
    +     --namespace drycc \
    +     -f values.yaml
    +
    +
  • +
  • +

    If the value hasn’t yet been exposed in the values.yaml file, one may edit the component deployment with the tuned setting. Here we edit the drycc-controller deployment:

    +
     $ kubectl --namespace drycc edit deployment drycc-controller
    +
    +

    Add/edit the setting via the appropriate environment variable and value under the env section and save. The updated deployment will recreate the component pod with the new/modified setting.

    +
  • +
  • +

    Lastly, one may also fetch and edit the chart as served by version control/the chart repository itself:

    +
     $ helm fetch oci://registry.drycc.cc/charts/workflow --untar
    + $ $EDITOR workflow/charts/controller/templates/controller-deployment.yaml
    +
    +

    Then run helm install ./workflow --namespace drycc --name drycc to apply the changes, or helm upgrade drycc ./workflow if the cluster is already running.

    +
  • +
+

Setting Resource limits

+

You can set resource limits to Workflow components by modifying the values.yaml file fetched +earlier. This file has a section for each Workflow component. To set a limit to any Workflow +component just add limitsCpu, limitsMemory in the section and set them to the appropriate +values.

+

Below is an example of how the builder section of values.yaml might look with CPU and memory +limits set:

+
builder:
+  imageOrg: "drycc"
+  imagePullPolicy: "Always"
+  imageTag: "canary"
+  limitsCpu: "100m"
+  limitsMemory: "50Mi"
+

Customizing the Builder

+

The following environment variables are tunable for the Builder component:

+ + + + + + + + + + + + + + + + + +
SettingDescription
DEBUGEnable debug log output (default: false)
BUILDER_POD_NODE_SELECTORA node selector setting for builder job. As it may sometimes consume a lot of node resources, one may want a given builder job to run in a specific node only, so it won’t affect critical nodes. for example pool:testing,disk:magnetic
+

Customizing the Controller

+

The following environment variables are tunable for the Controller component:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SettingDescription
REGISTRATION_MODEset registration to “enabled”, “disabled”, or “admin_only” (default: “admin_only”)
GUNICORN_WORKERSnumber of gunicorn workers spawned to process requests (default: CPU cores * 4 + 1)
RESERVED_NAMESa comma-separated list of names which applications cannot reserve for routing (default: “drycc, drycc-builder”)
DRYCC_DEPLOY_HOOK_URLSa comma-separated list of URLs to send deploy hooks to.
DRYCC_DEPLOY_HOOK_SECRET_KEYa private key used to compute the HMAC signature for deploy hooks.
DRYCC_DEPLOY_REJECT_IF_PROCFILE_MISSINGrejects a deploy if the previous build had a Procfile but the current deploy is missing it. A 409 is thrown in the API. Prevents accidental process types removal. (default: “false”, allowed values: “true”, “false”)
DRYCC_DEPLOY_PROCFILE_MISSING_REMOVEwhen turned on (default) any missing process type in a Procfile compared to the previous deploy is removed. When set to false will allow an empty Procfile to go through without removing missing process types, note that new images, configs and so on will get updated on all proc types. (default: “true”, allowed values: “true”, “false”)
DRYCC_DEFAULT_CONFIG_TAGSset tags for all applications by default, for example: ‘{“role”: “worker”}’. (default: ‘’)
KUBERNETES_NAMESPACE_DEFAULT_QUOTA_SPECset resource quota to application namespace by setting ResourceQuota spec, for example: {"spec":{"hard":{"pods":"10"}}}, restrict app owner to spawn more then 10 pods (default: “”, no quota will be applied to namespace)
+

LDAP authentication settings

+

Configuration options for LDAP authentication are detailed here.

+

The following environment variables are available for enabling LDAP +authentication of user accounts in the Passport component:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SettingDescription
LDAP_ENDPOINTThe URI of the LDAP server. If not specified, LDAP authentication is not enabled (default: “”, example: ldap://hostname).
LDAP_BIND_DNThe distinguished name to use when binding to the LDAP server (default: “”)
LDAP_BIND_PASSWORDThe password to use with LDAP_BIND_DN (default: “”)
LDAP_USER_BASEDNThe distinguished name of the search base for user names (default: “”)
LDAP_USER_FILTERThe name of the login field in the users search base (default: “username”)
LDAP_GROUP_BASEDNThe distinguished name of the search base for user’s groups names (default: “”)
LDAP_GROUP_FILTERThe filter for user’s groups (default: “”, example: objectClass=person)
+

Global and per application settings

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SettingDescription
DRYCC_DEPLOY_BATCHESthe number of pods to bring up and take down sequentially during a scale (default: number of available nodes)
DRYCC_DEPLOY_TIMEOUTdeploy timeout in seconds per deploy batch (default: 120)
IMAGE_PULL_POLICYthe kubernetes image pull policy for application images (default: “IfNotPresent”) (allowed values: “Always”, “IfNotPresent”)
KUBERNETES_DEPLOYMENTS_REVISION_HISTORY_LIMIThow many revisions Kubernetes keeps around of a given Deployment (default: all revisions)
KUBERNETES_POD_TERMINATION_GRACE_PERIOD_SECONDShow many seconds kubernetes waits for a pod to finish work after a SIGTERM before sending SIGKILL (default: 30)
+

See the Deploying Apps guide for more detailed information on those.

+

Customizing the Database

+

The following environment variables are tunable for the Database component:

+ + + + + + + + + + + + + + + + + +
SettingDescription
BACKUP_FREQUENCYhow often the database should perform a base backup (default: “12h”)
BACKUPS_TO_RETAINnumber of base backups the backing store should retain (default: 5)
+

Customizing Fluentbit

+

The following values can be changed in the values.yaml file or by using the --values flag with the Helm CLI.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
KeyDescription
config.serviceThe service section defines the global properties of the service.
config.inputsAn input section defines a source (related to an input plugin).
config.filtersA filter section defines a filter (related to a filter plugin)
config.outputsThe outputs section specify a destination that certain records should follow after a Tag match.
+

For more information about the various variables that can be set please see the fluentbit.

+

Customizing the Logger

+

The following environment variables are tunable for the Logger component:

+ + + + + + + + + + + + + + + + + +
SettingDescription
STORAGE_ADAPTERHow to store logs that are sent to the logger. Legal values are “file”, “memory”, and “redis”. (default: “redis”)
NUMBER_OF_LINESHow many lines to store in the ring buffer (default: 1000)
+

Customizing the Monitor

+

Grafana

+

We have exposed some of the more useful configuration values directly in the chart. This allows them to be set using either the values.yaml file or by using the --set flag with the Helm CLI. You can see these options below:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
SettingDefault ValueDescription
user“admin”The first user created in the database (this user has admin privileges)
password“admin”Password for the first user.
allow_sign_up“true”Allows users to sign up for an account.
+

For a list of other options you can set by using environment variables please see the configuration file in Github.

+

Telegraf

+

For a list of configuration values that can be set by using environment variables please see the following configuration file.

+

Prometheus

+

You can find a list of values that can be set using environment variables here.

+

Customizing the Registry

+

The Registry component can be tuned by following the +drycc/distribution config doc.

+

Customizing the Router

+

The majority of router settings are tunable through annotations, which allows the router to be +re-configured with zero downtime post-installation. You can find the list of annotations to tune +here.

+

The following environment variables are tunable for the [Router][] component:

+ + + + + + + + + + + + + +
SettingDescription
POD_NAMESPACEThe pod namespace the router resides in. This is set by the Kubernetes downward API.
+

Customizing Workflow Manager

+

The following environment variables are tunable for [Workflow Manager][]:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SettingDescription
CHECK_VERSIONSEnables the external version check at https://versions.drycc.info/ (default: “true”)
POLL_INTERVAL_SECThe interval when Workflow Manager performs a version check, in seconds (default: 43200, or 12 hours)
VERSIONS_API_URLThe versions API URL (default: “https://versions-staging.drycc.info”)
DOCTOR_API_URLThe doctor API URL (default: “https://doctor-staging.drycc.info”)
API_VERSIONThe version number Workflow Manager sends to the versions API (default: “v2”)
+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/managing-workflow/upgrading-workflow/index.html b/docs/managing-workflow/upgrading-workflow/index.html new file mode 100644 index 000000000..57c317037 --- /dev/null +++ b/docs/managing-workflow/upgrading-workflow/index.html @@ -0,0 +1,514 @@ + + + + + + + + + + + + + + + + + + + +Upgrading Workflow | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Upgrading Workflow

+
Drycc Workflow releases may be upgraded in-place with minimal downtime.
+ +

This upgrade process requires:

+ +

Upgrade Process

+

!!! note +If upgrading from a Helm Classic install, you’ll need to ‘migrate’ the cluster to a Kubernetes Helm installation. See Workflow-Migration for steps.

+

Step 1: Apply the Workflow upgrade

+

Helm will remove all components from the previous release. Traffic to applications deployed through +Workflow will continue to flow during the upgrade. No service interruptions should occur.

+

If Workflow is not configured to use off-cluster Postgres, the Workflow API will experience a brief +period of downtime while the database recovers from backup.

+

First, find the name of the release helm gave to your deployment with helm ls, then run

+
$ helm upgrade <release-name> oci://registry.drycc.cc/charts/workflow
+

Note: If using off-cluster object storage on gcs and/or off-cluster registry using gcr and intending to upgrade from a pre-v2.10.0 chart to v2.10.0 or greater, the key_json values will now need to be pre-base64-encoded. Therefore, assuming the rest of the custom/off-cluster values are defined in the existing values.yaml used for previous installs, the following may be run:

+
$ B64_KEY_JSON="$(cat ~/path/to/key.json | base64 -w 0)"
+$ helm upgrade <release_name> drycc/workflow -f values.yaml --set gcs.key_json="${B64_KEY_JSON}",registry-token-refresher.gcr.key_json="${B64_KEY_JSON}"
+

Alternatively, simply replace the appropriate values in values.yaml and do without the --set +parameter. Make sure to wrap it in single quotes as double quotes will give a parser error when +upgrading.

+

Step 2: Verify Upgrade

+

Verify that all components have started and passed their readiness checks:

+
$ kubectl --namespace=drycc get pods
+NAME                                     READY     STATUS    RESTARTS   AGE
+drycc-builder-2448122224-3cibz            1/1       Running   0          5m
+drycc-controller-1410285775-ipc34         1/1       Running   3          5m
+drycc-controller-celery-694f75749b-cmxxn  3/3       Running   0          5m
+drycc-database-e7c5z                      1/1       Running   0          5m
+drycc-logger-cgjup                        1/1       Running   3          5m
+drycc-logger-fluentbit-45h7j              1/1       Running   0          5m
+drycc-logger-fluentbit-4z7lw              1/1       Running   0          5m
+drycc-logger-fluentbit-k2wsw              1/1       Running   0          5m
+drycc-logger-fluentbit-skdw4              1/1       Running   0          5m
+drycc-redis-8nazu                         1/1       Running   0          5m
+drycc-monitor-grafana-tm266               1/1       Running   0          5m
+drycc-monitor-telegraf-51zel              1/1       Running   1          5m
+drycc-monitor-telegraf-cdasg              1/1       Running   0          5m
+drycc-monitor-telegraf-hea6x              1/1       Running   0          5m
+drycc-monitor-telegraf-r7lsg              1/1       Running   0          5m
+drycc-registry-1814324048-yomz5           1/1       Running   0          5m
+drycc-registry-proxy-4m3o4                1/1       Running   0          5m
+drycc-registry-proxy-no3r1                1/1       Running   0          5m
+drycc-registry-proxy-ou8is                1/1       Running   0          5m
+drycc-registry-proxy-zyajl                1/1       Running   0          5m
+drycc-rabbitmq-0                          1/1       Running   0          5m
+

Step 3: Upgrade the Drycc Client

+

Users of Drycc Workflow should now upgrade their drycc client to avoid getting WARNING: Client and server API versions do not match. Please consider upgrading. warnings.

+
curl -sfL https://www.drycc.cc/install-cli.sh | bash - && sudo mv drycc $(which drycc)
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/quickstart/_print/index.html b/docs/quickstart/_print/index.html new file mode 100644 index 000000000..91c1d3435 --- /dev/null +++ b/docs/quickstart/_print/index.html @@ -0,0 +1,772 @@ + + + + + + + + + + + + + + + + + + + + + +Quick Start | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+ + + + + +
+
+

+This is the multi-page printable view of this section. +Click here to print. +

+Return to the regular view of this page. +

+
+ + + +

Quick Start

+
Step-by-step guides for deploying your first app and mastering the basics of Drycc.
+ + + + + + + +
+ +
+
+ + + + + + + + + + + + + + + + +
+ +

1 - Quick Start

+
This guide helps you set up the Drycc workflow.
+

Get started with Drycc Workflow in three easy steps.

+
    +
  1. Install CLI tools for Helm and Drycc Workflow
  2. +
  3. Boot a Kubernetes and install Drycc Workflow
  4. +
  5. Deploy your first application
  6. +
+

This guide will help you set up a cluster suitable for evaluation, development and testing. When you are ready for staging and production, view our production checklist.

+

Step 1: Install Workflow

+

For the quickstart we will install Drycc Workflow.

+

Step 2: Install CLI tools

+

For the quickstart we will install Drycc Workflow CLI.

+

Step 3: Deploy your first app

+

Last but not least, login and deploy your first application.

+ +
+ + + + + + + + + + + +
+ +

2 - Install Workflow

+
Install Workflow in pure host, it can be a cloud server, bare metal server, virtual machine, or even your laptop.
+

If you have a pure host, it can be a cloud server, bare metal server, virtual machine, or even your laptop. Then this chapter is very suitable for you.

+

Operating Systems

+

Drycc is expected to work on most modern Linux systems. Some OSS have specific requirements:

+
    +
  • (Red Hat/CentOS) Enterprise Linux, they usually use RPM package management.
  • +
  • Ubuntu (Desktop/Server/Cloud) Linux, a very popular distribution.
  • +
  • Debian GNU Linux, a very pure distribution of opensource software.
  • +
+

If you want to add more Linux distribution support, please submit a issue on github or submit PR directly.

+

System Software

+

Some basic software needs to be installed before installing drycc workflow.

+

OS configuration

+

K8s requires a large number of ports. If you are not sure what they are, please close the local firewall or open these ports. +At the same time, because k8s you need system time, you need to ensure that the system time is correct.

+

Installing NFSv4 client

+

The command used to install a NFSv4 client differs depending on the Linux distribution.

+

For Debian and Ubuntu, use this command:

+
$ apt-get install nfs-common
+

For RHEL, CentOS, and EKS with EKS Kubernetes Worker AMI with AmazonLinux2 image, use this command:

+
$ yum install nfs-utils
+

Installing curl

+

For Debian and Ubuntu, use this command:

+
$ apt-get install curl
+

For RHEL, CentOS, and EKS with EKS Kubernetes Worker AMI with AmazonLinux2 image, use this command:

+
$ yum install curl
+

Hardware

+

Hardware requirements scale based on the size of your deployments. Minimum recommendations are outlined here.

+
    +
  • RAM: 1G Minimum (we recommend at least 2GB)
  • +
  • CPU: 1 Minimum
  • +
+

This configuration only contains the minimum requirements that can meet the operation.

+

Disk

+

Drycc performance depends on the performance of the database. To ensure optimal speed, we recommend using an SSD when possible. Disk performance will vary on ARM devices utilizing an SD card or eMMC.

+

Domain Name

+

Drycc needs a root domain name under your full control and points this domain name to the server to be installed. +Suppose there is a wildcard domain pointing to the current server to install drycc, which is the name *.dryccdoman.com. +We need to set the PLATFORM_DOMAIN environment variables before installation.

+
$ export PLATFORM_DOMAIN=dryccdoman.co
+

Of course, if it is a test environment, we can also use nip.io, an IP to domain name service. +For example, your host IP is 59.46.3.190, we will get the following domain name 59.46.3.190.nip.io

+
$ export PLATFORM_DOMAIN=59.46.3.190.nip.io
+

Install

+

Before installation, please make sure whether your installation environment is a public network. +If it is an intranet environment and there is no public IP, you need to disable the automatic certificate.

+
$ export CERT_MANAGER_ENABLED=false
+

Then you can use the installation script available at https://www.drycc.cc/install.sh to install drycc as a service on systemd and openrc based systems.

+
$ curl -sfL https://www.drycc.cc/install.sh | bash -
+

!!! important +If you are in China, you need to use mirror acceleration:

+
```
+$ curl -sfL https://www.drycc.cc/install.sh | INSTALL_DRYCC_MIRROR=cn bash -
+```
+
+

Install Node

+

Node can be a simple agent or a server; Server has the function of agent. Multiple servers have high availability, but the number of servers should not +exceed 7 at most. There is no limit to the number of agents.

+
    +
  • First, check the cluster token of the master.
  • +
+
$ cat /var/lib/rancher/k3s/server/node-token
+K1078e7213ca32bdaabb44536f14b9ce7926bb201f41c3f3edd39975c16ff4901ea::server:33bde27f-ac49-4483-b6ac-f4eec2c6dbfa
+

We assume that the IP address of the cluster master is 192.168.6.240, in that way.

+
    +
  • Then, Set the environment variable:
  • +
+
$ export K3S_URL=https://192.168.6.240:6443
+$ export K3S_TOKEN="K1078e7213ca32bdaabb44536f14b9ce7926bb201f41c3f3edd39975c16ff4901ea::server:33bde27f-ac49-4483-b6ac-f4eec2c6dbfa"
+

!!! important +If you are in China, you need to use mirror acceleration:

+
```
+$ export INSTALL_DRYCC_MIRROR=cn
+```
+
+
    +
  • Join the cluster as server:
  • +
+
$ curl -sfL https://www.drycc.cc/install.sh | bash -s - install_k3s_server
+
    +
  • Join the cluster as agent:
  • +
+
$ curl -sfL https://www.drycc.cc/install.sh | bash -s - install_k3s_agent
+

Install Options

+

When using this method to install drycc, the following environment variables can be used to configure the installation:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ENVIRONMENT VARIABLEDESCRIPTION
PLATFORM_DOMAINRequired item, specify drycc’s domain name
DRYCC_ADMIN_USERNAMERequired item, specify drycc’s admin username
DRYCC_ADMIN_PASSWORDRequired item, specify drycc’s admin password
CERT_MANAGER_ENABLEDWhether to use automatic certificate. It is false by default
CHANNELBy default, stable channel will be installed. You can also specify testing
REGISTRY_FILEThe config.yaml file path used by k3s containers registry
KUBERNETES_SERVICE_HOSTSet with the HOST of the loadbalancer that was in front of kube-apiserver
KUBERNETES_SERVICE_PORTSet with the PORT of the loadbalancer that was in front of kube-apiserver
METALLB_CONFIG_FILEThe metallb config file path, layer 2 network is used by default
INSTALL_DRYCC_MIRRORSpecify the accelerated mirror location. Currently, only cn is supported
BUILDER_REPLICASNumber of builder replicas to deploy
CONTROLLER_API_REPLICASNumber of controller api replicas to deploy
CONTROLLER_CELERY_REPLICASNumber of controller celery replicas to deploy
CONTROLLER_WEBHOOK_REPLICASNumber of controller webhook replicas to deploy
CONTROLLER_APP_RUNTIME_CLASSRuntimeClass is a feature for selecting the container runtime configuration.
CONTROLLER_APP_STORAGE_CLASSStorageClass allocated by drycc volumes; default storageClass is used by default
REDIS_REPLICASNumber of redis replicas to deploy
REDIS_PERSISTENCE_SIZEThe size of the persistence space allocated to redis, which is 5Gi by default
REDIS_PERSISTENCE_STORAGE_CLASSStorangeClass of redis; default storangeclass is used by default
STORAGE_CSI_STATEFULSET_REPLICASNumber of storage csi controller replicas to deploy
STORAGE_MAINNODE_TIPD_REPLICASNumber of storage mainode tipd replicas to deploy
STORAGE_MAINNODE_TIPD_PERSISTENCE_SIZEThe size of the persistence space allocated to mainnode tipd, which is 10Gi by default
STORAGE_MAINNODE_TIPD_PERSISTENCE_STORAGE_CLASSStorangeClass of mainnode tipd; default storangeclass is used by default
STORAGE_MAINNODE_WEED_REPLICASNumber of storage mainode weed replicas to deploy
STORAGE_MAINNODE_WEED_PREALLOCATEPreallocate disk space for volumes, false is used by default
STORAGE_MAINNODE_WEED_SIZE_LIMIT_MBMaster stops directing writes to oversized volumes, 30000 is used by default
STORAGE_MAINNODE_WEED_DEFAULT_REPLICATIONdefault replication type if not specified, which is 000 by default
STORAGE_MAINNODE_WEED_PERSISTENCE_SIZEThe size of the persistence space allocated to mainnode weed, which is 10Gi by default
STORAGE_MAINNODE_WEED_PERSISTENCE_STORAGE_CLASSStorangeClass of mainnode weed; default storangeclass is used by default
STORAGE_METANODE_TIKV_REPLICASNumber of storage metanode tikv replicas to deploy
STORAGE_METANODE_TIKV_PERSISTENCE_SIZEThe size of the persistence space allocated to metanode tikv, which is 10Gi by default
STORAGE_METANODE_TIKV_PERSISTENCE_STORAGE_CLASSStorangeClass of mainnode tikv; default storangeclass is used by default
STORAGE_METANODE_WEED_REPLICASNumber of storage metanode weed replicas to deploy
STORAGE_METANODE_WEED_PERSISTENCE_SIZEThe size of the persistence space allocated to metanode weed, which is 10Gi by default
STORAGE_METANODE_WEED_PERSISTENCE_STORAGE_CLASSStorangeClass of mainnode weed; default storangeclass is used by default
STORAGE_DATANODE_WEED_REPLICASNumber of storage datanode weed replicas to deploy
STORAGE_DATANODE_WEED_PERSISTENCE_SIZEThe size of the persistence space allocated to datanode weed, which is 20Gi by default
STORAGE_DATANODE_WEED_PERSISTENCE_STORAGE_CLASSStorangeClass of datanode weed; default storangeclass is used by default
MONITOR_GRAFANA_PERSISTENCE_SIZEThe size of the persistence space allocated to monitor.grafana, which is 5Gi by default
MONITOR_GRAFANA_PERSISTENCE_STORAGE_CLASSStorangeClass of monitor grafana; default storangeclass is used by default
LOGGER_REPLICASNumber of logger replicas to deploy
RABBITMQ_REPLICASNumber of rabbitmq replicas to deploy
RABBITMQ_PERSISTENCE_SIZEThe size of the persistence space allocated to rabbitmq, which is 5Gi by default
RABBITMQ_PERSISTENCE_STORAGE_CLASSStorangeClass of rabbitmq; default storangeclass is used by default
DATABASE_REPLICASNumber of database replicas to deploy
DATABASE_PERSISTENCE_SIZEThe size of the persistence space allocated to database, which is 5Gi by default
DATABASE_PERSISTENCE_STORAGE_CLASSStorangeClass of database; default storangeclass is used by default
TIMESERIES_REPLICASNumber of timeseries replicas to deploy
TIMESERIES_PERSISTENCE_SIZEThe size of the persistence space allocated to timeseries, which is 5Gi by default
TIMESERIES_PERSISTENCE_STORAGE_CLASSStorangeClass of timeseries; default storangeclass is used by default
PASSPORT_REPLICASNumber of passport replicas to deploy
REGISTRY_REPLICASNumber of registry replicas to deploy
HELMBROKER_REPLICASNumber of helmbroker api replicas to deploy
HELMBROKER_CELERY_REPLICASNumber of helmbroker celery replicas to deploy
HELMBROKER_PERSISTENCE_SIZEThe size of the persistence space allocated to helmbroker, which is 5Gi by default
HELMBROKER_PERSISTENCE_STORAGE_CLASSStorangeClass of helmbroker; default storangeclass is used by default
PROMETHEUS_SERVER_RETENTIONPrometheus data retention period (default if not specified is 15 days)
PROMETHEUS_SERVER_PERSISTENCE_SIZEThe size of the persistence space allocated to prometheus-server, which is 10Gi by default
PROMETHEUS_SERVER_PERSISTENCE_STORAGE_CLASSStorangeClass of prometheus-server; default storangeclass is used by default
K3S_DATA_DIRThe config of k3s data dir; If not set, the default path is used
ACME_SERVERACME Server url, default use letsencrypt
ACME_EAB_KEY_IDThe key ID of which your external account binding is indexed by the external account
ACME_EAB_KEY_SECRETThe key Secret of which your external account symmetric MAC key
+

Since the installation script will install k3s, other environment variables can refer to k3s installation environment variables.

+

Uninstall

+

If you installed drycc using an installation script, you can uninstall the entire drycc using this script.

+
$ curl -sfL https://www.drycc.cc/uninstall.sh | bash -
+
+
+ + + + + + + + + + + +
+ +

3 - Drycc Workflow Client CLI

+
How to download, install Drycc CLI tools.
+

Drycc Workflow Client CLI

+

The Drycc command-line interface (CLI), lets you interact with Drycc Workflow. +Use the CLI to create and configure and manage applications.

+

Install the drycc client for Linux or Mac OS X with:

+
$ curl -sfL https://www.drycc.cc/install-cli.sh | bash -
+

!!! important +Users in Chinese mainland can use the following methods to speed up installation:

+
```
+$ curl -sfL https://www.drycc.cc/install-cli.sh | INSTALL_DRYCC_MIRROR=cn bash -
+```
+
+

Others please visit: https://github.com/drycc/workflow-cli/releases

+

The installer places the drycc binary in your current directory, but you +should move it somewhere in your $PATH:

+
$ sudo ln -fs $PWD/drycc /usr/local/bin/drycc
+

or:

+
$ sudo mv $PWD/drycc /usr/local/bin/drycc
+

Check your work by running drycc version:

+
$ drycc version
+v1.1.0
+

Update workflow cli to latest release.

+
drycc update
+

!!! note +Note that version numbers may vary as new releases become available

+ +
+ + + + + + + + + + + +
+ +

4 - Deploy Your First App

+
Deploy an application using drycc cli.
+

Determine Your Host and Hostname Values

+

Drycc workflow requires a wildcard DNS record to dynamically map app names to the router.

+

User should already have DNS set up pointing to their known host. The $hostname value can be calculated by prepending drycc. to the value set in global.platformDomain.

+

Login to Workflow

+

Workflow use the passport component to create and authorize users. +If you already have an account, use drycc login to authenticate against the Drycc Workflow API.

+
$ drycc login http://drycc.example.com
+Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71
+Waiting for login... .o.Logged in as admin
+Configuration file written to /root/.drycc/client.json
+

Or you can login with username and password

+
$ drycc login http://drycc.example.com --username=demo --password=demo
+Configuration file written to /root/.drycc/client.json
+

Deploy an Application

+

Drycc Workflow supports three different types of applications, Buildpacks, +Dockerfiles and Container Images. Our first application will be a simple Container +Image-based application, so you don’t have to wrestle with checking out code.

+

Run drycc create to create a new application on Drycc Workflow. If you do not +specify a name for your application, Workflow automatically generates a +friendly (and sometimes funny) name.

+
$ drycc create --no-remote
+Creating Application... done, created proper-barbecue
+If you want to add a git remote for this app later, use `drycc git:remote -a proper-barbecue`
+

Our application has been created and named proper-barbecue. As with the +drycc hostname, any HTTP traffic to proper-barbecue will be automatically +routed to your application pods by the edge router.

+

Let’s use the CLI to tell the platform to deploy an application and then use curl to send a request to the app:

+
$ drycc pull drycc/example-go -a proper-barbecue
+Creating build... done
+$ curl http://proper-barbecue.$hostname
+Powered by Drycc
+

!!! note +If you see a 404 error, make sure you specified your application name with -a <appname>!

+

Workflow’s edge router knows all about application names and automatically +sends traffic to the right application. The router sends traffic for +proper-barbecue.104.197.125.75.nip.io to your app, just like +drycc.104.197.125.75.nip.io was sent to the Workflow API service.

+

Change Application Configuration

+

Next, let’s change some configuration using the CLI. Our example app is built +to read configuration from the environment. By using drycc config:set we can +change how the application behaves:

+
$ drycc config:set POWERED_BY="Container Images + Kubernetes" -a proper-barbecue
+Creating config... done
+
+UUID                                    OWNER    NAME                 VALUE
+04bb6e45-9221-4843-a1f9-acc7fded3b06    dev      POWERED_BY           Container Images + Kubernetes
+

Behind the scenes, Workflow creates a new release for your application and uses +Kubernetes to provide a zero-downtime rolling deploy to the new release!

+

Validate that our configuration change has worked:

+
$ curl http://proper-barbecue.104.197.125.75.nip.io
+Powered by Container Images + Kubernetes
+

Scale Your Application

+

Last, let’s scale our application by adding more application processes. Using the CLI you can easily add and remove +additional processes to service requests:

+
$ drycc scale web=2 -a proper-barbecue
+Scaling processes... but first, coffee!
+done in 36s
+
+NAME                                RELEASE    STATE    PTYPE       STARTED
+proper-barbecue-v18-web-rk644       v18        up       web         2023-12-08T03:09:25UTC
+proper-barbecue-v18-web-0ag04       v18        up       web         2023-12-08T03:09:25UTC
+

Congratulations! You have deployed, configured, and scaled your first application using Drycc Workflow.

+

Going Further

+

There is a lot more you can do with Drycc Workflow, play around with the CLI:

+

!!! important +In order to have permission to push an app you must add a SSH key to your user on the Drycc Workflow. +For more information, please check Users and SSH Keys and Troubleshooting Workflow.

+ + +
+ + + + + + + + + +
+
+
+ + +
+ + + + + + diff --git a/docs/quickstart/deploy-an-app/index.html b/docs/quickstart/deploy-an-app/index.html new file mode 100644 index 000000000..a3a69df88 --- /dev/null +++ b/docs/quickstart/deploy-an-app/index.html @@ -0,0 +1,544 @@ + + + + + + + + + + + + + + + + + + + +Deploy Your First App | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Deploy Your First App

+
Deploy an application using drycc cli.
+ +

Determine Your Host and Hostname Values

+

Drycc workflow requires a wildcard DNS record to dynamically map app names to the router.

+

User should already have DNS set up pointing to their known host. The $hostname value can be calculated by prepending drycc. to the value set in global.platformDomain.

+

Login to Workflow

+

Workflow use the passport component to create and authorize users. +If you already have an account, use drycc login to authenticate against the Drycc Workflow API.

+
$ drycc login http://drycc.example.com
+Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71
+Waiting for login... .o.Logged in as admin
+Configuration file written to /root/.drycc/client.json
+

Or you can login with username and password

+
$ drycc login http://drycc.example.com --username=demo --password=demo
+Configuration file written to /root/.drycc/client.json
+

Deploy an Application

+

Drycc Workflow supports three different types of applications, Buildpacks, +Dockerfiles and Container Images. Our first application will be a simple Container +Image-based application, so you don’t have to wrestle with checking out code.

+

Run drycc create to create a new application on Drycc Workflow. If you do not +specify a name for your application, Workflow automatically generates a +friendly (and sometimes funny) name.

+
$ drycc create --no-remote
+Creating Application... done, created proper-barbecue
+If you want to add a git remote for this app later, use `drycc git:remote -a proper-barbecue`
+

Our application has been created and named proper-barbecue. As with the +drycc hostname, any HTTP traffic to proper-barbecue will be automatically +routed to your application pods by the edge router.

+

Let’s use the CLI to tell the platform to deploy an application and then use curl to send a request to the app:

+
$ drycc pull drycc/example-go -a proper-barbecue
+Creating build... done
+$ curl http://proper-barbecue.$hostname
+Powered by Drycc
+

!!! note +If you see a 404 error, make sure you specified your application name with -a <appname>!

+

Workflow’s edge router knows all about application names and automatically +sends traffic to the right application. The router sends traffic for +proper-barbecue.104.197.125.75.nip.io to your app, just like +drycc.104.197.125.75.nip.io was sent to the Workflow API service.

+

Change Application Configuration

+

Next, let’s change some configuration using the CLI. Our example app is built +to read configuration from the environment. By using drycc config:set we can +change how the application behaves:

+
$ drycc config:set POWERED_BY="Container Images + Kubernetes" -a proper-barbecue
+Creating config... done
+
+UUID                                    OWNER    NAME                 VALUE
+04bb6e45-9221-4843-a1f9-acc7fded3b06    dev      POWERED_BY           Container Images + Kubernetes
+

Behind the scenes, Workflow creates a new release for your application and uses +Kubernetes to provide a zero-downtime rolling deploy to the new release!

+

Validate that our configuration change has worked:

+
$ curl http://proper-barbecue.104.197.125.75.nip.io
+Powered by Container Images + Kubernetes
+

Scale Your Application

+

Last, let’s scale our application by adding more application processes. Using the CLI you can easily add and remove +additional processes to service requests:

+
$ drycc scale web=2 -a proper-barbecue
+Scaling processes... but first, coffee!
+done in 36s
+
+NAME                                RELEASE    STATE    PTYPE       STARTED
+proper-barbecue-v18-web-rk644       v18        up       web         2023-12-08T03:09:25UTC
+proper-barbecue-v18-web-0ag04       v18        up       web         2023-12-08T03:09:25UTC
+

Congratulations! You have deployed, configured, and scaled your first application using Drycc Workflow.

+

Going Further

+

There is a lot more you can do with Drycc Workflow, play around with the CLI:

+

!!! important +In order to have permission to push an app you must add a SSH key to your user on the Drycc Workflow. +For more information, please check Users and SSH Keys and Troubleshooting Workflow.

+ + + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/quickstart/index.html b/docs/quickstart/index.html new file mode 100644 index 000000000..885580cce --- /dev/null +++ b/docs/quickstart/index.html @@ -0,0 +1,478 @@ + + + + + + + + + + + + + + + + + + + + + +Quick Start | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Quick Start

+
Step-by-step guides for deploying your first app and mastering the basics of Drycc.
+ + +
+ + +
+
+
+ Quick Start +
+

This guide helps you set up the Drycc workflow.

+
+
+
+ Install Workflow +
+

Install Workflow in pure host, it can be a cloud server, bare metal server, virtual machine, or even your laptop.

+
+
+
+ Drycc Workflow Client CLI +
+

How to download, install Drycc CLI tools.

+
+
+
+ Deploy Your First App +
+

Deploy an application using drycc cli.

+
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+
+ +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/quickstart/index.xml b/docs/quickstart/index.xml new file mode 100644 index 000000000..e02291e77 --- /dev/null +++ b/docs/quickstart/index.xml @@ -0,0 +1,537 @@ + + + Drycc – Quick Start + /docs/quickstart/ + Recent content in Quick Start on Drycc + Hugo -- gohugo.io + en + + + + + + + + + + + Docs: Quick Start + /docs/quickstart/overview/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/quickstart/overview/ + + + + <p>Get started with Drycc Workflow in three easy steps.</p> +<ol> +<li>Install CLI tools for Helm and Drycc Workflow</li> +<li>Boot a Kubernetes and install Drycc Workflow</li> +<li>Deploy your first application</li> +</ol> +<p>This guide will help you set up a cluster suitable for evaluation, development and testing. When you are ready for staging and production, view our <a href="/docs/managing-workflow/production-deployments/">production checklist</a>.</p> +<h2 id="step-1-install-workflow">Step 1: Install Workflow<a class="td-heading-self-link" href="#step-1-install-workflow" aria-label="Heading self-link"></a></h2> +<p>For the quickstart we will <a href="/docs/quickstart/install-workflow/">install Drycc Workflow</a>.</p> +<h2 id="step-2-install-cli-tools">Step 2: Install CLI tools<a class="td-heading-self-link" href="#step-2-install-cli-tools" aria-label="Heading self-link"></a></h2> +<p>For the quickstart we will <a href="/docs/quickstart/install-cli-tools/">install Drycc Workflow CLI</a>.</p> +<h2 id="step-3-deploy-your-first-app">Step 3: Deploy your first app<a class="td-heading-self-link" href="#step-3-deploy-your-first-app" aria-label="Heading self-link"></a></h2> +<p>Last but not least, <a href="/docs/quickstart/deploy-an-app/">login and deploy your first application</a>.</p> + + + + + + Docs: Install Workflow + /docs/quickstart/install-workflow/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/quickstart/install-workflow/ + + + + <p>If you have a pure host, it can be a cloud server, bare metal server, virtual machine, or even your laptop. Then this chapter is very suitable for you.</p> +<h2 id="operating-systems">Operating Systems<a class="td-heading-self-link" href="#operating-systems" aria-label="Heading self-link"></a></h2> +<p>Drycc is expected to work on most modern Linux systems. Some OSS have specific requirements:</p> +<ul> +<li>(Red Hat/CentOS) Enterprise Linux, they usually use RPM package management.</li> +<li>Ubuntu (Desktop/Server/Cloud) Linux, a very popular distribution.</li> +<li>Debian GNU Linux, a very pure distribution of opensource software.</li> +</ul> +<p>If you want to add more Linux distribution support, please submit a issue on github or submit PR directly.</p> +<h2 id="system-software">System Software<a class="td-heading-self-link" href="#system-software" aria-label="Heading self-link"></a></h2> +<p>Some basic software needs to be installed before installing drycc workflow.</p> +<h3 id="os-configuration">OS configuration<a class="td-heading-self-link" href="#os-configuration" aria-label="Heading self-link"></a></h3> +<p>K8s requires a large number of ports. If you are not sure what they are, please close the local firewall or open these ports. +At the same time, because k8s you need system time, you need to ensure that the system time is correct.</p> +<h3 id="installing-nfsv4-client">Installing NFSv4 client<a class="td-heading-self-link" href="#installing-nfsv4-client" aria-label="Heading self-link"></a></h3> +<p>The command used to install a NFSv4 client differs depending on the Linux distribution.</p> +<p>For Debian and Ubuntu, use this command:</p> +<pre tabindex="0"><code>$ apt-get install nfs-common +</code></pre><p>For RHEL, CentOS, and EKS with EKS Kubernetes Worker AMI with AmazonLinux2 image, use this command:</p> +<pre tabindex="0"><code>$ yum install nfs-utils +</code></pre><h3 id="installing-curl">Installing curl<a class="td-heading-self-link" href="#installing-curl" aria-label="Heading self-link"></a></h3> +<p>For Debian and Ubuntu, use this command:</p> +<pre tabindex="0"><code>$ apt-get install curl +</code></pre><p>For RHEL, CentOS, and EKS with EKS Kubernetes Worker AMI with AmazonLinux2 image, use this command:</p> +<pre tabindex="0"><code>$ yum install curl +</code></pre><h2 id="hardware">Hardware<a class="td-heading-self-link" href="#hardware" aria-label="Heading self-link"></a></h2> +<p>Hardware requirements scale based on the size of your deployments. Minimum recommendations are outlined here.</p> +<ul> +<li>RAM: 1G Minimum (we recommend at least 2GB)</li> +<li>CPU: 1 Minimum</li> +</ul> +<p>This configuration only contains the minimum requirements that can meet the operation.</p> +<h2 id="disk">Disk<a class="td-heading-self-link" href="#disk" aria-label="Heading self-link"></a></h2> +<p>Drycc performance depends on the performance of the database. To ensure optimal speed, we recommend using an SSD when possible. Disk performance will vary on ARM devices utilizing an SD card or eMMC.</p> +<h2 id="domain-name">Domain Name<a class="td-heading-self-link" href="#domain-name" aria-label="Heading self-link"></a></h2> +<p>Drycc needs a root domain name under your full control and points this domain name to the server to be installed. +Suppose there is a wildcard domain pointing to the current server to install drycc, which is the name <code>*.dryccdoman.com</code>. +We need to set the <code>PLATFORM_DOMAIN</code> environment variables before installation.</p> +<pre tabindex="0"><code>$ export PLATFORM_DOMAIN=dryccdoman.co +</code></pre><p>Of course, if it is a test environment, we can also use <code>nip.io</code>, an IP to domain name service. +For example, your host IP is <code>59.46.3.190</code>, we will get the following domain name <code>59.46.3.190.nip.io</code></p> +<pre tabindex="0"><code>$ export PLATFORM_DOMAIN=59.46.3.190.nip.io +</code></pre><h2 id="install">Install<a class="td-heading-self-link" href="#install" aria-label="Heading self-link"></a></h2> +<p>Before installation, please make sure whether your installation environment is a public network. +If it is an intranet environment and there is no public IP, you need to disable the automatic certificate.</p> +<pre tabindex="0"><code>$ export CERT_MANAGER_ENABLED=false +</code></pre><p>Then you can use the installation script available at <a href="https://www.drycc.cc/install.sh">https://www.drycc.cc/install.sh</a> to install drycc as a service on systemd and openrc based systems.</p> +<pre tabindex="0"><code>$ curl -sfL https://www.drycc.cc/install.sh | bash - +</code></pre><p>!!! important +If you are in China, you need to use mirror acceleration:</p> +<pre><code>``` +$ curl -sfL https://www.drycc.cc/install.sh | INSTALL_DRYCC_MIRROR=cn bash - +``` +</code></pre> +<h3 id="install-node">Install Node<a class="td-heading-self-link" href="#install-node" aria-label="Heading self-link"></a></h3> +<p>Node can be a simple agent or a server; Server has the function of agent. Multiple servers have high availability, but the number of servers should not +exceed 7 at most. There is no limit to the number of agents.</p> +<ul> +<li>First, check the cluster token of the master.</li> +</ul> +<pre tabindex="0"><code>$ cat /var/lib/rancher/k3s/server/node-token +K1078e7213ca32bdaabb44536f14b9ce7926bb201f41c3f3edd39975c16ff4901ea::server:33bde27f-ac49-4483-b6ac-f4eec2c6dbfa +</code></pre><p>We assume that the IP address of the cluster master is <code>192.168.6.240</code>, in that way.</p> +<ul> +<li>Then, Set the environment variable:</li> +</ul> +<pre tabindex="0"><code>$ export K3S_URL=https://192.168.6.240:6443 +$ export K3S_TOKEN=&#34;K1078e7213ca32bdaabb44536f14b9ce7926bb201f41c3f3edd39975c16ff4901ea::server:33bde27f-ac49-4483-b6ac-f4eec2c6dbfa&#34; +</code></pre><p>!!! important +If you are in China, you need to use mirror acceleration:</p> +<pre><code>``` +$ export INSTALL_DRYCC_MIRROR=cn +``` +</code></pre> +<ul> +<li>Join the cluster as server:</li> +</ul> +<pre tabindex="0"><code>$ curl -sfL https://www.drycc.cc/install.sh | bash -s - install_k3s_server +</code></pre><ul> +<li>Join the cluster as agent:</li> +</ul> +<pre tabindex="0"><code>$ curl -sfL https://www.drycc.cc/install.sh | bash -s - install_k3s_agent +</code></pre><h3 id="install-options">Install Options<a class="td-heading-self-link" href="#install-options" aria-label="Heading self-link"></a></h3> +<p>When using this method to install drycc, the following environment variables can be used to configure the installation:</p> +<table> +<thead> +<tr> +<th>ENVIRONMENT VARIABLE</th> +<th>DESCRIPTION</th> +</tr> +</thead> +<tbody> +<tr> +<td>PLATFORM_DOMAIN</td> +<td>Required item, specify drycc&rsquo;s domain name</td> +</tr> +<tr> +<td>DRYCC_ADMIN_USERNAME</td> +<td>Required item, specify drycc&rsquo;s admin username</td> +</tr> +<tr> +<td>DRYCC_ADMIN_PASSWORD</td> +<td>Required item, specify drycc&rsquo;s admin password</td> +</tr> +<tr> +<td>CERT_MANAGER_ENABLED</td> +<td>Whether to use automatic certificate. It is <code>false</code> by default</td> +</tr> +<tr> +<td>CHANNEL</td> +<td>By default, <code>stable</code> channel will be installed. You can also specify <code>testing</code></td> +</tr> +<tr> +<td>REGISTRY_FILE</td> +<td>The <code>config.yaml</code> file path used by k3s containers registry</td> +</tr> +<tr> +<td>KUBERNETES_SERVICE_HOST</td> +<td>Set with the HOST of the loadbalancer that was in front of kube-apiserver</td> +</tr> +<tr> +<td>KUBERNETES_SERVICE_PORT</td> +<td>Set with the PORT of the loadbalancer that was in front of kube-apiserver</td> +</tr> +<tr> +<td>METALLB_CONFIG_FILE</td> +<td>The metallb config file path, layer 2 network is used by default</td> +</tr> +<tr> +<td>INSTALL_DRYCC_MIRROR</td> +<td>Specify the accelerated mirror location. Currently, only <code>cn</code> is supported</td> +</tr> +<tr> +<td>BUILDER_REPLICAS</td> +<td>Number of builder replicas to deploy</td> +</tr> +<tr> +<td>CONTROLLER_API_REPLICAS</td> +<td>Number of controller api replicas to deploy</td> +</tr> +<tr> +<td>CONTROLLER_CELERY_REPLICAS</td> +<td>Number of controller celery replicas to deploy</td> +</tr> +<tr> +<td>CONTROLLER_WEBHOOK_REPLICAS</td> +<td>Number of controller webhook replicas to deploy</td> +</tr> +<tr> +<td>CONTROLLER_APP_RUNTIME_CLASS</td> +<td>RuntimeClass is a feature for selecting the container runtime configuration.</td> +</tr> +<tr> +<td>CONTROLLER_APP_STORAGE_CLASS</td> +<td>StorageClass allocated by <code>drycc volumes</code>; default storageClass is used by default</td> +</tr> +<tr> +<td>REDIS_REPLICAS</td> +<td>Number of redis replicas to deploy</td> +</tr> +<tr> +<td>REDIS_PERSISTENCE_SIZE</td> +<td>The size of the persistence space allocated to <code>redis</code>, which is <code>5Gi</code> by default</td> +</tr> +<tr> +<td>REDIS_PERSISTENCE_STORAGE_CLASS</td> +<td>StorangeClass of <code>redis</code>; default storangeclass is used by default</td> +</tr> +<tr> +<td>STORAGE_CSI_STATEFULSET_REPLICAS</td> +<td>Number of storage csi controller replicas to deploy</td> +</tr> +<tr> +<td>STORAGE_MAINNODE_TIPD_REPLICAS</td> +<td>Number of storage mainode tipd replicas to deploy</td> +</tr> +<tr> +<td>STORAGE_MAINNODE_TIPD_PERSISTENCE_SIZE</td> +<td>The size of the persistence space allocated to <code>mainnode tipd</code>, which is <code>10Gi</code> by default</td> +</tr> +<tr> +<td>STORAGE_MAINNODE_TIPD_PERSISTENCE_STORAGE_CLASS</td> +<td>StorangeClass of <code>mainnode tipd</code>; default storangeclass is used by default</td> +</tr> +<tr> +<td>STORAGE_MAINNODE_WEED_REPLICAS</td> +<td>Number of storage mainode weed replicas to deploy</td> +</tr> +<tr> +<td>STORAGE_MAINNODE_WEED_PREALLOCATE</td> +<td>Preallocate disk space for volumes, <code>false</code> is used by default</td> +</tr> +<tr> +<td>STORAGE_MAINNODE_WEED_SIZE_LIMIT_MB</td> +<td>Master stops directing writes to oversized volumes, <code>30000</code> is used by default</td> +</tr> +<tr> +<td>STORAGE_MAINNODE_WEED_DEFAULT_REPLICATION</td> +<td>default replication type if not specified, which is <code>000</code> by default</td> +</tr> +<tr> +<td>STORAGE_MAINNODE_WEED_PERSISTENCE_SIZE</td> +<td>The size of the persistence space allocated to <code>mainnode weed</code>, which is <code>10Gi</code> by default</td> +</tr> +<tr> +<td>STORAGE_MAINNODE_WEED_PERSISTENCE_STORAGE_CLASS</td> +<td>StorangeClass of <code>mainnode weed</code>; default storangeclass is used by default</td> +</tr> +<tr> +<td>STORAGE_METANODE_TIKV_REPLICAS</td> +<td>Number of storage metanode tikv replicas to deploy</td> +</tr> +<tr> +<td>STORAGE_METANODE_TIKV_PERSISTENCE_SIZE</td> +<td>The size of the persistence space allocated to <code>metanode tikv</code>, which is <code>10Gi</code> by default</td> +</tr> +<tr> +<td>STORAGE_METANODE_TIKV_PERSISTENCE_STORAGE_CLASS</td> +<td>StorangeClass of <code>mainnode tikv</code>; default storangeclass is used by default</td> +</tr> +<tr> +<td>STORAGE_METANODE_WEED_REPLICAS</td> +<td>Number of storage metanode weed replicas to deploy</td> +</tr> +<tr> +<td>STORAGE_METANODE_WEED_PERSISTENCE_SIZE</td> +<td>The size of the persistence space allocated to <code>metanode weed</code>, which is <code>10Gi</code> by default</td> +</tr> +<tr> +<td>STORAGE_METANODE_WEED_PERSISTENCE_STORAGE_CLASS</td> +<td>StorangeClass of <code>mainnode weed</code>; default storangeclass is used by default</td> +</tr> +<tr> +<td>STORAGE_DATANODE_WEED_REPLICAS</td> +<td>Number of storage datanode weed replicas to deploy</td> +</tr> +<tr> +<td>STORAGE_DATANODE_WEED_PERSISTENCE_SIZE</td> +<td>The size of the persistence space allocated to <code>datanode weed</code>, which is <code>20Gi</code> by default</td> +</tr> +<tr> +<td>STORAGE_DATANODE_WEED_PERSISTENCE_STORAGE_CLASS</td> +<td>StorangeClass of <code>datanode weed</code>; default storangeclass is used by default</td> +</tr> +<tr> +<td>MONITOR_GRAFANA_PERSISTENCE_SIZE</td> +<td>The size of the persistence space allocated to <code>monitor.grafana</code>, which is <code>5Gi</code> by default</td> +</tr> +<tr> +<td>MONITOR_GRAFANA_PERSISTENCE_STORAGE_CLASS</td> +<td>StorangeClass of <code>monitor</code> grafana; default storangeclass is used by default</td> +</tr> +<tr> +<td>LOGGER_REPLICAS</td> +<td>Number of logger replicas to deploy</td> +</tr> +<tr> +<td>RABBITMQ_REPLICAS</td> +<td>Number of rabbitmq replicas to deploy</td> +</tr> +<tr> +<td>RABBITMQ_PERSISTENCE_SIZE</td> +<td>The size of the persistence space allocated to <code>rabbitmq</code>, which is <code>5Gi</code> by default</td> +</tr> +<tr> +<td>RABBITMQ_PERSISTENCE_STORAGE_CLASS</td> +<td>StorangeClass of <code>rabbitmq</code>; default storangeclass is used by default</td> +</tr> +<tr> +<td>DATABASE_REPLICAS</td> +<td>Number of database replicas to deploy</td> +</tr> +<tr> +<td>DATABASE_PERSISTENCE_SIZE</td> +<td>The size of the persistence space allocated to <code>database</code>, which is <code>5Gi</code> by default</td> +</tr> +<tr> +<td>DATABASE_PERSISTENCE_STORAGE_CLASS</td> +<td>StorangeClass of <code>database</code>; default storangeclass is used by default</td> +</tr> +<tr> +<td>TIMESERIES_REPLICAS</td> +<td>Number of timeseries replicas to deploy</td> +</tr> +<tr> +<td>TIMESERIES_PERSISTENCE_SIZE</td> +<td>The size of the persistence space allocated to <code>timeseries</code>, which is <code>5Gi</code> by default</td> +</tr> +<tr> +<td>TIMESERIES_PERSISTENCE_STORAGE_CLASS</td> +<td>StorangeClass of <code>timeseries</code>; default storangeclass is used by default</td> +</tr> +<tr> +<td>PASSPORT_REPLICAS</td> +<td>Number of passport replicas to deploy</td> +</tr> +<tr> +<td>REGISTRY_REPLICAS</td> +<td>Number of registry replicas to deploy</td> +</tr> +<tr> +<td>HELMBROKER_REPLICAS</td> +<td>Number of helmbroker api replicas to deploy</td> +</tr> +<tr> +<td>HELMBROKER_CELERY_REPLICAS</td> +<td>Number of helmbroker celery replicas to deploy</td> +</tr> +<tr> +<td>HELMBROKER_PERSISTENCE_SIZE</td> +<td>The size of the persistence space allocated to <code>helmbroker</code>, which is <code>5Gi</code> by default</td> +</tr> +<tr> +<td>HELMBROKER_PERSISTENCE_STORAGE_CLASS</td> +<td>StorangeClass of <code>helmbroker</code>; default storangeclass is used by default</td> +</tr> +<tr> +<td>PROMETHEUS_SERVER_RETENTION</td> +<td>Prometheus data retention period (default if not specified is 15 days)</td> +</tr> +<tr> +<td>PROMETHEUS_SERVER_PERSISTENCE_SIZE</td> +<td>The size of the persistence space allocated to <code>prometheus-server</code>, which is <code>10Gi</code> by default</td> +</tr> +<tr> +<td>PROMETHEUS_SERVER_PERSISTENCE_STORAGE_CLASS</td> +<td>StorangeClass of <code>prometheus-server</code>; default storangeclass is used by default</td> +</tr> +<tr> +<td>K3S_DATA_DIR</td> +<td>The config of k3s data dir; If not set, the default path is used</td> +</tr> +<tr> +<td>ACME_SERVER</td> +<td>ACME Server url, default use letsencrypt</td> +</tr> +<tr> +<td>ACME_EAB_KEY_ID</td> +<td>The key ID of which your external account binding is indexed by the external account</td> +</tr> +<tr> +<td>ACME_EAB_KEY_SECRET</td> +<td>The key Secret of which your external account symmetric MAC key</td> +</tr> +</tbody> +</table> +<p>Since the installation script will install k3s, other environment variables can refer to k3s installation <a href="https://rancher.com/docs/k3s/latest/en/installation/install-options/">environment variables</a>.</p> +<h2 id="uninstall">Uninstall<a class="td-heading-self-link" href="#uninstall" aria-label="Heading self-link"></a></h2> +<p>If you installed drycc using an installation script, you can uninstall the entire drycc using this script.</p> +<pre tabindex="0"><code>$ curl -sfL https://www.drycc.cc/uninstall.sh | bash - +</code></pre> + + + + + Docs: Drycc Workflow Client CLI + /docs/quickstart/install-cli-tools/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/quickstart/install-cli-tools/ + + + + <h2 id="drycc-workflow-client-cli">Drycc Workflow Client CLI<a class="td-heading-self-link" href="#drycc-workflow-client-cli" aria-label="Heading self-link"></a></h2> +<p>The Drycc command-line interface (CLI), lets you interact with Drycc Workflow. +Use the CLI to create and configure and manage applications.</p> +<p>Install the <code>drycc</code> client for Linux or Mac OS X with:</p> +<pre tabindex="0"><code>$ curl -sfL https://www.drycc.cc/install-cli.sh | bash - +</code></pre><p>!!! important +Users in Chinese mainland can use the following methods to speed up installation:</p> +<pre><code>``` +$ curl -sfL https://www.drycc.cc/install-cli.sh | INSTALL_DRYCC_MIRROR=cn bash - +``` +</code></pre> +<p>Others please visit: <a href="https://github.com/drycc/workflow-cli/releases">https://github.com/drycc/workflow-cli/releases</a></p> +<p>The installer places the <code>drycc</code> binary in your current directory, but you +should move it somewhere in your $PATH:</p> +<pre tabindex="0"><code>$ sudo ln -fs $PWD/drycc /usr/local/bin/drycc +</code></pre><p><em>or</em>:</p> +<pre tabindex="0"><code>$ sudo mv $PWD/drycc /usr/local/bin/drycc +</code></pre><p>Check your work by running <code>drycc version</code>:</p> +<pre tabindex="0"><code>$ drycc version +v1.1.0 +</code></pre><p>Update workflow cli to latest release.</p> +<pre tabindex="0"><code>drycc update +</code></pre><p>!!! note +Note that version numbers may vary as new releases become available</p> + + + + + + Docs: Deploy Your First App + /docs/quickstart/deploy-an-app/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/quickstart/deploy-an-app/ + + + + <h2 id="determine-your-host-and-hostname-values">Determine Your Host and Hostname Values<a class="td-heading-self-link" href="#determine-your-host-and-hostname-values" aria-label="Heading self-link"></a></h2> +<p>Drycc workflow requires a wildcard DNS record to dynamically map app names to the router.</p> +<p>User should already have DNS set up pointing to their known host. The <code>$hostname</code> value can be calculated by prepending <code>drycc.</code> to the value set in <code>global.platformDomain</code>.</p> +<h2 id="login-to-workflow">Login to Workflow<a class="td-heading-self-link" href="#login-to-workflow" aria-label="Heading self-link"></a></h2> +<p>Workflow use the passport component to create and authorize users. +If you already have an account, use <code>drycc login</code> to authenticate against the Drycc Workflow API.</p> +<pre tabindex="0"><code>$ drycc login http://drycc.example.com +Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71 +Waiting for login... .o.Logged in as admin +Configuration file written to /root/.drycc/client.json +</code></pre><p>Or you can login with username and password</p> +<pre tabindex="0"><code>$ drycc login http://drycc.example.com --username=demo --password=demo +Configuration file written to /root/.drycc/client.json +</code></pre><h2 id="deploy-an-application">Deploy an Application<a class="td-heading-self-link" href="#deploy-an-application" aria-label="Heading self-link"></a></h2> +<p>Drycc Workflow supports three different types of applications, Buildpacks, +Dockerfiles and Container Images. Our first application will be a simple Container +Image-based application, so you don&rsquo;t have to wrestle with checking out code.</p> +<p>Run <code>drycc create</code> to create a new application on Drycc Workflow. If you do not +specify a name for your application, Workflow automatically generates a +friendly (and sometimes funny) name.</p> +<pre tabindex="0"><code>$ drycc create --no-remote +Creating Application... done, created proper-barbecue +If you want to add a git remote for this app later, use `drycc git:remote -a proper-barbecue` +</code></pre><p>Our application has been created and named <code>proper-barbecue</code>. As with the +<code>drycc</code> hostname, any HTTP traffic to <code>proper-barbecue</code> will be automatically +routed to your application pods by the edge router.</p> +<p>Let&rsquo;s use the CLI to tell the platform to deploy an application and then use curl to send a request to the app:</p> +<pre tabindex="0"><code>$ drycc pull drycc/example-go -a proper-barbecue +Creating build... done +$ curl http://proper-barbecue.$hostname +Powered by Drycc +</code></pre><p>!!! note +If you see a 404 error, make sure you specified your application name with <code>-a &lt;appname&gt;</code>!</p> +<p>Workflow&rsquo;s edge router knows all about application names and automatically +sends traffic to the right application. The router sends traffic for +<code>proper-barbecue.104.197.125.75.nip.io</code> to your app, just like +<code>drycc.104.197.125.75.nip.io</code> was sent to the Workflow API service.</p> +<h2 id="change-application-configuration">Change Application Configuration<a class="td-heading-self-link" href="#change-application-configuration" aria-label="Heading self-link"></a></h2> +<p>Next, let&rsquo;s change some configuration using the CLI. Our example app is built +to read configuration from the environment. By using <code>drycc config:set</code> we can +change how the application behaves:</p> +<pre tabindex="0"><code>$ drycc config:set POWERED_BY=&#34;Container Images + Kubernetes&#34; -a proper-barbecue +Creating config... done + +UUID OWNER NAME VALUE +04bb6e45-9221-4843-a1f9-acc7fded3b06 dev POWERED_BY Container Images + Kubernetes +</code></pre><p>Behind the scenes, Workflow creates a new release for your application and uses +Kubernetes to provide a zero-downtime rolling deploy to the new release!</p> +<p>Validate that our configuration change has worked:</p> +<pre tabindex="0"><code>$ curl http://proper-barbecue.104.197.125.75.nip.io +Powered by Container Images + Kubernetes +</code></pre><h2 id="scale-your-application">Scale Your Application<a class="td-heading-self-link" href="#scale-your-application" aria-label="Heading self-link"></a></h2> +<p>Last, let&rsquo;s scale our application by adding more application processes. Using the CLI you can easily add and remove +additional processes to service requests:</p> +<pre tabindex="0"><code>$ drycc scale web=2 -a proper-barbecue +Scaling processes... but first, coffee! +done in 36s + +NAME RELEASE STATE PTYPE STARTED +proper-barbecue-v18-web-rk644 v18 up web 2023-12-08T03:09:25UTC +proper-barbecue-v18-web-0ag04 v18 up web 2023-12-08T03:09:25UTC +</code></pre><p>Congratulations! You have deployed, configured, and scaled your first application using Drycc Workflow.</p> +<h2 id="going-further">Going Further<a class="td-heading-self-link" href="#going-further" aria-label="Heading self-link"></a></h2> +<p>There is a lot more you can do with Drycc Workflow, play around with the CLI:</p> +<p>!!! important +In order to have permission to push an app you must add a SSH key to your user on the Drycc Workflow. +For more information, please check <a href="/docs/users/ssh-keys/">Users and SSH Keys</a> and <a href="/docs/troubleshooting/">Troubleshooting Workflow</a>.</p> +<ul> +<li>Roll back to a previous release with <code>drycc rollback -a proper-barbecue</code></li> +<li>See application logs with <code>drycc logs -a proper-barbecue</code></li> +<li>Try one of our other example applications like: +<ul> +<li><a href="https://github.com/drycc/ruby-getting-started">drycc/ruby-getting-started</a></li> +<li><a href="https://github.com/drycc/python-getting-started">drycc/python-getting-started</a></li> +<li><a href="https://github.com/drycc/php-getting-started">drycc/php-getting-started</a></li> +</ul> +</li> +<li>Read about using application <a href="/docs/applications/using-buildpacks/">Buildpacks</a> or <a href="/docs/applications/using-dockerfiles/">Dockerfiles</a></li> +<li>Join our <a href="https://drycc.slack.com/">#community slack channel</a> and meet the team!</li> +</ul> + + + + + + diff --git a/docs/quickstart/install-cli-tools/index.html b/docs/quickstart/install-cli-tools/index.html new file mode 100644 index 000000000..5613030d1 --- /dev/null +++ b/docs/quickstart/install-cli-tools/index.html @@ -0,0 +1,483 @@ + + + + + + + + + + + + + + + + + + + +Drycc Workflow Client CLI | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Drycc Workflow Client CLI

+
How to download, install Drycc CLI tools.
+ +

Drycc Workflow Client CLI

+

The Drycc command-line interface (CLI), lets you interact with Drycc Workflow. +Use the CLI to create and configure and manage applications.

+

Install the drycc client for Linux or Mac OS X with:

+
$ curl -sfL https://www.drycc.cc/install-cli.sh | bash -
+

!!! important +Users in Chinese mainland can use the following methods to speed up installation:

+
```
+$ curl -sfL https://www.drycc.cc/install-cli.sh | INSTALL_DRYCC_MIRROR=cn bash -
+```
+
+

Others please visit: https://github.com/drycc/workflow-cli/releases

+

The installer places the drycc binary in your current directory, but you +should move it somewhere in your $PATH:

+
$ sudo ln -fs $PWD/drycc /usr/local/bin/drycc
+

or:

+
$ sudo mv $PWD/drycc /usr/local/bin/drycc
+

Check your work by running drycc version:

+
$ drycc version
+v1.1.0
+

Update workflow cli to latest release.

+
drycc update
+

!!! note +Note that version numbers may vary as new releases become available

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/quickstart/install-workflow/index.html b/docs/quickstart/install-workflow/index.html new file mode 100644 index 000000000..d44735eb8 --- /dev/null +++ b/docs/quickstart/install-workflow/index.html @@ -0,0 +1,826 @@ + + + + + + + + + + + + + + + + + + + +Install Workflow | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Install Workflow

+
Install Workflow in pure host, it can be a cloud server, bare metal server, virtual machine, or even your laptop.
+ +

If you have a pure host, it can be a cloud server, bare metal server, virtual machine, or even your laptop. Then this chapter is very suitable for you.

+

Operating Systems

+

Drycc is expected to work on most modern Linux systems. Some OSS have specific requirements:

+
    +
  • (Red Hat/CentOS) Enterprise Linux, they usually use RPM package management.
  • +
  • Ubuntu (Desktop/Server/Cloud) Linux, a very popular distribution.
  • +
  • Debian GNU Linux, a very pure distribution of opensource software.
  • +
+

If you want to add more Linux distribution support, please submit a issue on github or submit PR directly.

+

System Software

+

Some basic software needs to be installed before installing drycc workflow.

+

OS configuration

+

K8s requires a large number of ports. If you are not sure what they are, please close the local firewall or open these ports. +At the same time, because k8s you need system time, you need to ensure that the system time is correct.

+

Installing NFSv4 client

+

The command used to install a NFSv4 client differs depending on the Linux distribution.

+

For Debian and Ubuntu, use this command:

+
$ apt-get install nfs-common
+

For RHEL, CentOS, and EKS with EKS Kubernetes Worker AMI with AmazonLinux2 image, use this command:

+
$ yum install nfs-utils
+

Installing curl

+

For Debian and Ubuntu, use this command:

+
$ apt-get install curl
+

For RHEL, CentOS, and EKS with EKS Kubernetes Worker AMI with AmazonLinux2 image, use this command:

+
$ yum install curl
+

Hardware

+

Hardware requirements scale based on the size of your deployments. Minimum recommendations are outlined here.

+
    +
  • RAM: 1G Minimum (we recommend at least 2GB)
  • +
  • CPU: 1 Minimum
  • +
+

This configuration only contains the minimum requirements that can meet the operation.

+

Disk

+

Drycc performance depends on the performance of the database. To ensure optimal speed, we recommend using an SSD when possible. Disk performance will vary on ARM devices utilizing an SD card or eMMC.

+

Domain Name

+

Drycc needs a root domain name under your full control and points this domain name to the server to be installed. +Suppose there is a wildcard domain pointing to the current server to install drycc, which is the name *.dryccdoman.com. +We need to set the PLATFORM_DOMAIN environment variables before installation.

+
$ export PLATFORM_DOMAIN=dryccdoman.co
+

Of course, if it is a test environment, we can also use nip.io, an IP to domain name service. +For example, your host IP is 59.46.3.190, we will get the following domain name 59.46.3.190.nip.io

+
$ export PLATFORM_DOMAIN=59.46.3.190.nip.io
+

Install

+

Before installation, please make sure whether your installation environment is a public network. +If it is an intranet environment and there is no public IP, you need to disable the automatic certificate.

+
$ export CERT_MANAGER_ENABLED=false
+

Then you can use the installation script available at https://www.drycc.cc/install.sh to install drycc as a service on systemd and openrc based systems.

+
$ curl -sfL https://www.drycc.cc/install.sh | bash -
+

!!! important +If you are in China, you need to use mirror acceleration:

+
```
+$ curl -sfL https://www.drycc.cc/install.sh | INSTALL_DRYCC_MIRROR=cn bash -
+```
+
+

Install Node

+

Node can be a simple agent or a server; Server has the function of agent. Multiple servers have high availability, but the number of servers should not +exceed 7 at most. There is no limit to the number of agents.

+
    +
  • First, check the cluster token of the master.
  • +
+
$ cat /var/lib/rancher/k3s/server/node-token
+K1078e7213ca32bdaabb44536f14b9ce7926bb201f41c3f3edd39975c16ff4901ea::server:33bde27f-ac49-4483-b6ac-f4eec2c6dbfa
+

We assume that the IP address of the cluster master is 192.168.6.240, in that way.

+
    +
  • Then, Set the environment variable:
  • +
+
$ export K3S_URL=https://192.168.6.240:6443
+$ export K3S_TOKEN="K1078e7213ca32bdaabb44536f14b9ce7926bb201f41c3f3edd39975c16ff4901ea::server:33bde27f-ac49-4483-b6ac-f4eec2c6dbfa"
+

!!! important +If you are in China, you need to use mirror acceleration:

+
```
+$ export INSTALL_DRYCC_MIRROR=cn
+```
+
+
    +
  • Join the cluster as server:
  • +
+
$ curl -sfL https://www.drycc.cc/install.sh | bash -s - install_k3s_server
+
    +
  • Join the cluster as agent:
  • +
+
$ curl -sfL https://www.drycc.cc/install.sh | bash -s - install_k3s_agent
+

Install Options

+

When using this method to install drycc, the following environment variables can be used to configure the installation:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ENVIRONMENT VARIABLEDESCRIPTION
PLATFORM_DOMAINRequired item, specify drycc’s domain name
DRYCC_ADMIN_USERNAMERequired item, specify drycc’s admin username
DRYCC_ADMIN_PASSWORDRequired item, specify drycc’s admin password
CERT_MANAGER_ENABLEDWhether to use automatic certificate. It is false by default
CHANNELBy default, stable channel will be installed. You can also specify testing
REGISTRY_FILEThe config.yaml file path used by k3s containers registry
KUBERNETES_SERVICE_HOSTSet with the HOST of the loadbalancer that was in front of kube-apiserver
KUBERNETES_SERVICE_PORTSet with the PORT of the loadbalancer that was in front of kube-apiserver
METALLB_CONFIG_FILEThe metallb config file path, layer 2 network is used by default
INSTALL_DRYCC_MIRRORSpecify the accelerated mirror location. Currently, only cn is supported
BUILDER_REPLICASNumber of builder replicas to deploy
CONTROLLER_API_REPLICASNumber of controller api replicas to deploy
CONTROLLER_CELERY_REPLICASNumber of controller celery replicas to deploy
CONTROLLER_WEBHOOK_REPLICASNumber of controller webhook replicas to deploy
CONTROLLER_APP_RUNTIME_CLASSRuntimeClass is a feature for selecting the container runtime configuration.
CONTROLLER_APP_STORAGE_CLASSStorageClass allocated by drycc volumes; default storageClass is used by default
REDIS_REPLICASNumber of redis replicas to deploy
REDIS_PERSISTENCE_SIZEThe size of the persistence space allocated to redis, which is 5Gi by default
REDIS_PERSISTENCE_STORAGE_CLASSStorangeClass of redis; default storangeclass is used by default
STORAGE_CSI_STATEFULSET_REPLICASNumber of storage csi controller replicas to deploy
STORAGE_MAINNODE_TIPD_REPLICASNumber of storage mainode tipd replicas to deploy
STORAGE_MAINNODE_TIPD_PERSISTENCE_SIZEThe size of the persistence space allocated to mainnode tipd, which is 10Gi by default
STORAGE_MAINNODE_TIPD_PERSISTENCE_STORAGE_CLASSStorangeClass of mainnode tipd; default storangeclass is used by default
STORAGE_MAINNODE_WEED_REPLICASNumber of storage mainode weed replicas to deploy
STORAGE_MAINNODE_WEED_PREALLOCATEPreallocate disk space for volumes, false is used by default
STORAGE_MAINNODE_WEED_SIZE_LIMIT_MBMaster stops directing writes to oversized volumes, 30000 is used by default
STORAGE_MAINNODE_WEED_DEFAULT_REPLICATIONdefault replication type if not specified, which is 000 by default
STORAGE_MAINNODE_WEED_PERSISTENCE_SIZEThe size of the persistence space allocated to mainnode weed, which is 10Gi by default
STORAGE_MAINNODE_WEED_PERSISTENCE_STORAGE_CLASSStorangeClass of mainnode weed; default storangeclass is used by default
STORAGE_METANODE_TIKV_REPLICASNumber of storage metanode tikv replicas to deploy
STORAGE_METANODE_TIKV_PERSISTENCE_SIZEThe size of the persistence space allocated to metanode tikv, which is 10Gi by default
STORAGE_METANODE_TIKV_PERSISTENCE_STORAGE_CLASSStorangeClass of mainnode tikv; default storangeclass is used by default
STORAGE_METANODE_WEED_REPLICASNumber of storage metanode weed replicas to deploy
STORAGE_METANODE_WEED_PERSISTENCE_SIZEThe size of the persistence space allocated to metanode weed, which is 10Gi by default
STORAGE_METANODE_WEED_PERSISTENCE_STORAGE_CLASSStorangeClass of mainnode weed; default storangeclass is used by default
STORAGE_DATANODE_WEED_REPLICASNumber of storage datanode weed replicas to deploy
STORAGE_DATANODE_WEED_PERSISTENCE_SIZEThe size of the persistence space allocated to datanode weed, which is 20Gi by default
STORAGE_DATANODE_WEED_PERSISTENCE_STORAGE_CLASSStorangeClass of datanode weed; default storangeclass is used by default
MONITOR_GRAFANA_PERSISTENCE_SIZEThe size of the persistence space allocated to monitor.grafana, which is 5Gi by default
MONITOR_GRAFANA_PERSISTENCE_STORAGE_CLASSStorangeClass of monitor grafana; default storangeclass is used by default
LOGGER_REPLICASNumber of logger replicas to deploy
RABBITMQ_REPLICASNumber of rabbitmq replicas to deploy
RABBITMQ_PERSISTENCE_SIZEThe size of the persistence space allocated to rabbitmq, which is 5Gi by default
RABBITMQ_PERSISTENCE_STORAGE_CLASSStorangeClass of rabbitmq; default storangeclass is used by default
DATABASE_REPLICASNumber of database replicas to deploy
DATABASE_PERSISTENCE_SIZEThe size of the persistence space allocated to database, which is 5Gi by default
DATABASE_PERSISTENCE_STORAGE_CLASSStorangeClass of database; default storangeclass is used by default
TIMESERIES_REPLICASNumber of timeseries replicas to deploy
TIMESERIES_PERSISTENCE_SIZEThe size of the persistence space allocated to timeseries, which is 5Gi by default
TIMESERIES_PERSISTENCE_STORAGE_CLASSStorangeClass of timeseries; default storangeclass is used by default
PASSPORT_REPLICASNumber of passport replicas to deploy
REGISTRY_REPLICASNumber of registry replicas to deploy
HELMBROKER_REPLICASNumber of helmbroker api replicas to deploy
HELMBROKER_CELERY_REPLICASNumber of helmbroker celery replicas to deploy
HELMBROKER_PERSISTENCE_SIZEThe size of the persistence space allocated to helmbroker, which is 5Gi by default
HELMBROKER_PERSISTENCE_STORAGE_CLASSStorangeClass of helmbroker; default storangeclass is used by default
PROMETHEUS_SERVER_RETENTIONPrometheus data retention period (default if not specified is 15 days)
PROMETHEUS_SERVER_PERSISTENCE_SIZEThe size of the persistence space allocated to prometheus-server, which is 10Gi by default
PROMETHEUS_SERVER_PERSISTENCE_STORAGE_CLASSStorangeClass of prometheus-server; default storangeclass is used by default
K3S_DATA_DIRThe config of k3s data dir; If not set, the default path is used
ACME_SERVERACME Server url, default use letsencrypt
ACME_EAB_KEY_IDThe key ID of which your external account binding is indexed by the external account
ACME_EAB_KEY_SECRETThe key Secret of which your external account symmetric MAC key
+

Since the installation script will install k3s, other environment variables can refer to k3s installation environment variables.

+

Uninstall

+

If you installed drycc using an installation script, you can uninstall the entire drycc using this script.

+
$ curl -sfL https://www.drycc.cc/uninstall.sh | bash -
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/quickstart/overview/index.html b/docs/quickstart/overview/index.html new file mode 100644 index 000000000..dff1c3030 --- /dev/null +++ b/docs/quickstart/overview/index.html @@ -0,0 +1,474 @@ + + + + + + + + + + + + + + + + + + + +Quick Start | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Quick Start

+
This guide helps you set up the Drycc workflow.
+ +

Get started with Drycc Workflow in three easy steps.

+
    +
  1. Install CLI tools for Helm and Drycc Workflow
  2. +
  3. Boot a Kubernetes and install Drycc Workflow
  4. +
  5. Deploy your first application
  6. +
+

This guide will help you set up a cluster suitable for evaluation, development and testing. When you are ready for staging and production, view our production checklist.

+

Step 1: Install Workflow

+

For the quickstart we will install Drycc Workflow.

+

Step 2: Install CLI tools

+

For the quickstart we will install Drycc Workflow CLI.

+

Step 3: Deploy your first app

+

Last but not least, login and deploy your first application.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/reference-guide/_print/index.html b/docs/reference-guide/_print/index.html new file mode 100644 index 000000000..baf8abd90 --- /dev/null +++ b/docs/reference-guide/_print/index.html @@ -0,0 +1,4273 @@ + + + + + + + + + + + + + + + + + + + + + +Reference Guide | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+ + + + + +
+
+

+This is the multi-page printable view of this section. +Click here to print. +

+Return to the regular view of this page. +

+
+ + + +

Reference Guide

+
Reference gxwuide definition and meaning.
+ + + + + + + +
+ +
+
+ + + + + + + + + + + + + + + + +
+ +

1 - Creating a Self-Signed SSL Certificate

+
A self-signed TLS/SSL certificate is not signed by a publicly trusted certificate authority (CA) but instead by the developer or company that is responsible for the website.
+

When using the app ssl feature for non-production applications or when installing SSL for the platform, you can avoid the costs associated with the SSL certificate by using a self-signed SSL certificate. Though the certificate implements full encryption, visitors to your site will see a browser warning indicating that the certificate should not be trusted.

+

Prerequisites

+

The openssl library is required to generate your own certificate. Run the following command in your local environment to see if you already have openssl installed.

+
$ which openssl
+/usr/bin/openssl
+
+

If the which command does not return a path then you will need to install openssl yourself:

+ + + + + + + + + + + + + + + + + + + + + +
If you have…Install with…
Mac OS XHomebrew: brew install openssl
Windowscomplete package .exe installed
Ubuntu Linuxapt-get install openssl
+

Generate Private Key and Certificate Signing Request

+

A private key and certificate signing request are required to create an SSL certificate. These can be generated with a few simple commands. When the openssl req command asks for a “challenge password”, just press return, leaving the password empty.

+
$ openssl genrsa -des3 -passout pass:x -out server.pass.key 2048
+...
+$ openssl rsa -passin pass:x -in server.pass.key -out server.key
+writing RSA key
+$ rm server.pass.key
+$ openssl req -new -key server.key -out server.csr
+...
+Country Name (2 letter code) [AU]:US
+State or Province Name (full name) [Some-State]:California
+...
+A challenge password []:
+...
+
+

Generate SSL Certificate

+

The self-signed SSL certificate is generated from the server.key private key and server.csr files.

+
$ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
+
+

The server.crt file is your site certificate suitable for use with Drycc’s SSL endpoint along with the server.key private key.

+ +
+ + + + + + + + + + + +
+ +

2 - Controller API v2.0

+
This is the v2.0 REST API for the Controller.
+

What’s New

+

New! format of POST /v2/apps/<app id>/run has changed.

+

Authentication

+

Register a New User

+

Example Request:

+
POST /v2/auth/register/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+
+{
+    "username": "test",
+    "password": "opensesame",
+    "email": "test@example.com"
+}
+

Optional Parameters:

+
{
+    "first_name": "test",
+    "last_name": "testerson"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "id": 1,
+    "last_login": "2014-10-19T22:01:00.601Z",
+    "is_superuser": true,
+    "username": "test",
+    "first_name": "test",
+    "last_name": "testerson",
+    "email": "test@example.com",
+    "is_staff": true,
+    "is_active": true,
+    "date_joined": "2014-10-19T22:01:00.601Z",
+    "groups": [],
+    "user_permissions": []
+}
+

Log in

+

Example Request:

+
POST /v2/auth/login/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+
+{"username": "test", "password": "opensesame"}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{"token": "abc123"}
+

Cancel Account

+

Example Request:

+
DELETE /v2/auth/cancel/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Regenerate Token

+
+

note

+

This command could require administrative privileges

+
+

Example Request:

+
POST /v2/auth/tokens/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional Parameters:

+
{
+    "username" : "test"
+    "all" : "true"
+}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{"token": "abc123"}
+

Change Password

+

Example Request:

+
POST /v2/auth/passwd/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "password": "foo",
+    "new_password": "bar"
+}
+

Optional parameters:

+
{"username": "testuser"}
+
+

note

+

Using the username parameter requires administrative privileges and makes the password parameter optional.

+
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Applications

+

List all Applications

+

Example Request:

+
GET /v2/apps HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "created": "2014-01-01T00:00:00UTC",
+            "id": "example-go",
+            "owner": "test",
+            "structure": {},
+            "updated": "2014-01-01T00:00:00UTC",
+            "url": "example-go.example.com",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+        }
+    ]
+}
+

Create an Application

+

Example Request:

+
POST /v2/apps/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+

Optional parameters:

+
{"id": "example-go"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example-go",
+    "owner": "test",
+    "structure": {},
+    "updated": "2014-01-01T00:00:00UTC",
+    "url": "example-go.example.com",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Destroy an Application

+

Example Request:

+
DELETE /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

List Application Details

+

Example Request:

+
GET /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example-go",
+    "owner": "test",
+    "structure": {},
+    "updated": "2014-01-01T00:00:00UTC",
+    "url": "example-go.example.com",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Update Application Details

+

Example Request:

+
POST /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional parameters:

+
{
+  "owner": "test"
+}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 1.8.0
+Content-Type: application/json
+

Retrieve Application Logs

+

Example Request:

+
GET /v2/apps/example-go/logs/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional URL Query Parameters:

+
?log_lines=
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: text/plain
+
+"16:51:14 drycc[api]: test created initial release\n"
+

Run one-off Commands

+
POST /v2/apps/example-go/run/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"command": "echo hi"}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{"exit_code": 0, "output": "hi\n"}
+

Certificates

+

List all Certificates

+

Example Request:

+
GET /v2/certs HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+  "count": 1,
+  "next": null,
+  "previous": null,
+  "results": [
+    {
+      "id": 22,
+      "owner": "test",
+      "san": [],
+      "domains": [],
+      "created": "2016-06-22T22:24:20Z",
+      "updated": "2016-06-22T22:24:20Z",
+      "name": "foo",
+      "common_name": "bar.com",
+      "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+      "expires": "2017-01-14T23:57:57Z",
+      "starts": "2016-01-15T23:57:57Z",
+      "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+      "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+    }
+  ]
+}
+

Get Certificate Details

+

Example Request:

+
GET /v2/certs/foo HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+  "id": 22,
+  "owner": "test",
+  "san": [],
+  "domains": [],
+  "created": "2016-06-22T22:24:20Z",
+  "updated": "2016-06-22T22:24:20Z",
+  "name": "foo",
+  "common_name": "bar.com",
+  "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+  "expires": "2017-01-14T23:57:57Z",
+  "starts": "2016-01-15T23:57:57Z",
+  "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+  "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+}
+

Create Certificate

+

Example Request:

+
POST /v2/certs/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{
+    "name": "foo"
+    "certificate": "-----BEGIN CERTIFICATE-----",
+    "key": "-----BEGIN RSA PRIVATE KEY-----"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+  "id": 22,
+  "owner": "test",
+  "san": [],
+  "domains": [],
+  "created": "2016-06-22T22:24:20Z",
+  "updated": "2016-06-22T22:24:20Z",
+  "name": "foo",
+  "common_name": "bar.com",
+  "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+  "expires": "2017-01-14T23:57:57Z",
+  "starts": "2016-01-15T23:57:57Z",
+  "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+  "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+}
+

Destroy a Certificate

+

Example Request:

+
DELETE /v2/certs/foo HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Attach a Domain to a Certificate

+

Example Request:

+
POST /v2/certs/foo/domain/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "domain": "test.com"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Remove a Domain from a Certificate

+

Example Request:

+
DELETE /v2/certs/foo/domain/test.com/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Pods

+

List all Pods

+

Example Request:

+
GET /v2/apps/example-go/pods/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "results": [
+        {
+            "name": "go-v2-web-e7dej",
+            "release": "v2",
+            "started": "2014-01-01T00:00:00Z",
+            "state": "up",
+            "type": "web"
+        }
+    ]
+}
+

List all Pods by Type

+

Example Request:

+
GET /v2/apps/example-go/pods/web/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "results": [
+        {
+            "name": "go-v2-web-e7dej",
+            "release": "v2",
+            "started": "2014-01-01T00:00:00Z",
+            "state": "up",
+            "type": "web"
+        }
+    ]
+}
+

Restart All Pods

+

Example Request:

+
POST /v2/apps/example-go/pods/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Restart Pods by Type

+

Example Request:

+
POST /v2/apps/example-go/pods/web/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Restart Pods by Type and Name

+

Example Request:

+
POST /v2/apps/example-go/pods/go-v2-web-atots/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Scale Pods

+

Example Request:

+
POST /v2/apps/example-go/scale/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"web": 3}
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Configuration

+

List Application Configuration

+

Example Request:

+
GET /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+      "PLATFORM": "drycc"
+    },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Create new Config

+

Example Request:

+
POST /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"values": {"HELLO": "world", "PLATFORM": "drycc"}}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+X-Drycc-Release: 3
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+        "DRYCC_APP": "example-go",
+        "DRYCC_RELEASE": "v3",
+        "HELLO": "world",
+        "PLATFORM": "drycc"
+
+    },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Unset Config Variable

+

Example Request:

+
POST /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"values": {"HELLO": null}}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+X-Drycc-Release: 4
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+        "DRYCC_APP": "example-go",
+        "DRYCC_RELEASE": "v4",
+        "PLATFORM": "drycc"
+   },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Domains

+

List Application Domains

+

Example Request:

+
GET /v2/apps/example-go/domains/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "app": "example-go",
+            "created": "2014-01-01T00:00:00UTC",
+            "domain": "example.example.com",
+            "owner": "test",
+            "updated": "2014-01-01T00:00:00UTC"
+        }
+    ]
+}
+

Add Domain

+

Example Request:

+
POST /v2/apps/example-go/domains/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{'domain': 'example.example.com'}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "domain": "example.example.com",
+    "owner": "test",
+    "updated": "2014-01-01T00:00:00UTC"
+}
+

Remove Domain

+

Example Request:

+
DELETE /v2/apps/example-go/domains/example.example.com HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Builds

+

List Application Builds

+

Example Request:

+
GET /v2/apps/example-go/build/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "dockerfile": "FROM drycc/slugrunner RUN mkdir -p /app WORKDIR /app ENTRYPOINT [\"/runner/init\"] ADD slug.tgz /app ENV GIT_SHA 060da68f654e75fac06dbedd1995d5f8ad9084db",
+    "image": "example-go",
+    "owner": "test",
+    "procfile": {
+        "web": "example-go"
+    },
+    "sha": "060da68f",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Create Application Build

+

Example Request:

+
POST /v2/apps/example-go/build/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"image": "drycc/example-go:latest"}
+

Optional Parameters:

+
{
+    "procfile": {
+      "web": "./cmd"
+    }
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+X-Drycc-Release: 4
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "dockerfile": "",
+    "image": "drycc/example-go:latest",
+    "owner": "test",
+    "procfile": {},
+    "sha": "",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Releases

+

List Application Releases

+

Example Request:

+
GET /v2/apps/example-go/releases/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 3,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "app": "example-go",
+            "build": "202d8e4b-600e-4425-a85c-ffc7ea607f61",
+            "config": "ed637ceb-5d32-44bd-9406-d326a777a513",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test changed nothing",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 3
+        },
+        {
+            "app": "example-go",
+            "build": "202d8e4b-600e-4425-a85c-ffc7ea607f61",
+            "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test deployed 060da68",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 2
+        },
+        {
+            "app": "example-go",
+            "build": null,
+            "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test created initial release",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 1
+        }
+    ]
+}
+

List Release Details

+

Example Request:

+
GET /v2/apps/example-go/releases/v2/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "build": null,
+    "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+    "created": "2014-01-01T00:00:00UTC",
+    "owner": "test",
+    "summary": "test created initial release",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+    "version": 1
+}
+

Rollback Release

+

Example Request:

+
POST /v2/apps/example-go/releases/rollback/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"version": 1}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{"version": 5}
+

Keys

+

List Keys

+

Example Request:

+
GET /v2/keys/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "created": "2014-01-01T00:00:00UTC",
+            "id": "test@example.com",
+            "owner": "test",
+            "public": "ssh-rsa <...>",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+        }
+    ]
+}
+

Add Key to User

+

Example Request:

+
POST /v2/keys/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "id": "example",
+    "public": "ssh-rsa <...>"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example",
+    "owner": "example",
+    "public": "ssh-rsa <...>",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Remove Key from User

+

Example Request:

+
DELETE /v2/keys/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Permissions

+

List Application Permissions

+
+

note

+

This does not include the app owner.

+
+

Example Request:

+
GET /v2/apps/example-go/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "users": [
+        "test",
+        "foo"
+    ]
+}
+

Create Application Permission

+

Example Request:

+
POST /v2/apps/example-go/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{"username": "example"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Remove Application Permission

+

Example Request:

+
DELETE /v2/apps/example-go/perms/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

List Administrators

+

Example Request:

+
GET /v2/admin/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 2,
+    "next": null
+    "previous": null,
+    "results": [
+        {
+            "username": "test",
+            "is_superuser": true
+        },
+        {
+            "username": "foo",
+            "is_superuser": true
+        }
+    ]
+}
+

Grant User Administrative Privileges

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
POST /v2/admin/perms HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{"username": "example"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Remove User’s Administrative Privileges

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
DELETE /v2/admin/perms/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Users

+

List all users

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
GET /v2/users HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "id": 1,
+            "last_login": "2014-10-19T22:01:00.601Z",
+            "is_superuser": true,
+            "username": "test",
+            "first_name": "test",
+            "last_name": "testerson",
+            "email": "test@example.com",
+            "is_staff": true,
+            "is_active": true,
+            "date_joined": "2014-10-19T22:01:00.601Z",
+            "groups": [],
+            "user_permissions": []
+        }
+    ]
+}
+
+
+ + + + + + + + + + + +
+ +

3 - Controller API v2.1

+
This is the v2.1 REST API for the Controller.
+

What’s New

+

New! healthcheck field in configuration, deprecates the HEALTHCHECK_* environment variables.

+

New! Unsetting a configuration variable that does not exist will return a 422.

+

New! Creating an identical sequential release returns a 409 rather than create a no-op release.

+

Authentication

+

Register a New User

+

Example Request:

+
POST /v2/auth/register/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+
+{
+    "username": "test",
+    "password": "opensesame",
+    "email": "test@example.com"
+}
+

Optional Parameters:

+
{
+    "first_name": "test",
+    "last_name": "testerson"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "id": 1,
+    "last_login": "2014-10-19T22:01:00.601Z",
+    "is_superuser": true,
+    "username": "test",
+    "first_name": "test",
+    "last_name": "testerson",
+    "email": "test@example.com",
+    "is_staff": true,
+    "is_active": true,
+    "date_joined": "2014-10-19T22:01:00.601Z",
+    "groups": [],
+    "user_permissions": []
+}
+

Log in

+

Example Request:

+
POST /v2/auth/login/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+
+{"username": "test", "password": "opensesame"}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{"token": "abc123"}
+

Cancel Account

+

Example Request:

+
DELETE /v2/auth/cancel/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Regenerate Token

+
+

note

+

This command could require administrative privileges

+
+

Example Request:

+
POST /v2/auth/tokens/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional Parameters:

+
{
+    "username" : "test"
+    "all" : "true"
+}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{"token": "abc123"}
+

Change Password

+

Example Request:

+
POST /v2/auth/passwd/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "password": "foo",
+    "new_password": "bar"
+}
+

Optional parameters:

+
{"username": "testuser"}
+
+

note

+

Using the username parameter requires administrative privileges and makes the password parameter optional.

+
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Applications

+

List all Applications

+

Example Request:

+
GET /v2/apps HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "created": "2014-01-01T00:00:00UTC",
+            "id": "example-go",
+            "owner": "test",
+            "structure": {},
+            "updated": "2014-01-01T00:00:00UTC",
+            "url": "example-go.example.com",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+        }
+    ]
+}
+

Create an Application

+

Example Request:

+
POST /v2/apps/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+

Optional parameters:

+
{"id": "example-go"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example-go",
+    "owner": "test",
+    "structure": {},
+    "updated": "2014-01-01T00:00:00UTC",
+    "url": "example-go.example.com",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Destroy an Application

+

Example Request:

+
DELETE /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

List Application Details

+

Example Request:

+
GET /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example-go",
+    "owner": "test",
+    "structure": {},
+    "updated": "2014-01-01T00:00:00UTC",
+    "url": "example-go.example.com",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Update Application Details

+

Example Request:

+
POST /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional parameters:

+
{
+  "owner": "test"
+}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 1.8.0
+Content-Type: application/json
+

Retrieve Application Logs

+

Example Request:

+
GET /v2/apps/example-go/logs/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional URL Query Parameters:

+
?log_lines=
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: text/plain
+
+"16:51:14 drycc[api]: test created initial release\n"
+

Run one-off Commands

+
POST /v2/apps/example-go/run/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"command": "echo hi"}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{"exit_code": 0, "output": "hi\n"}
+

Certificates

+

List all Certificates

+

Example Request:

+
GET /v2/certs HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+  "count": 1,
+  "next": null,
+  "previous": null,
+  "results": [
+    {
+      "id": 22,
+      "owner": "test",
+      "san": [],
+      "domains": [],
+      "created": "2016-06-22T22:24:20Z",
+      "updated": "2016-06-22T22:24:20Z",
+      "name": "foo",
+      "common_name": "bar.com",
+      "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+      "expires": "2017-01-14T23:57:57Z",
+      "starts": "2016-01-15T23:57:57Z",
+      "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+      "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+    }
+  ]
+}
+

Get Certificate Details

+

Example Request:

+
GET /v2/certs/foo HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+  "id": 22,
+  "owner": "test",
+  "san": [],
+  "domains": [],
+  "created": "2016-06-22T22:24:20Z",
+  "updated": "2016-06-22T22:24:20Z",
+  "name": "foo",
+  "common_name": "bar.com",
+  "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+  "expires": "2017-01-14T23:57:57Z",
+  "starts": "2016-01-15T23:57:57Z",
+  "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+  "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+}
+

Create Certificate

+

Example Request:

+
POST /v2/certs/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{
+    "name": "foo"
+    "certificate": "-----BEGIN CERTIFICATE-----",
+    "key": "-----BEGIN RSA PRIVATE KEY-----"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+  "id": 22,
+  "owner": "test",
+  "san": [],
+  "domains": [],
+  "created": "2016-06-22T22:24:20Z",
+  "updated": "2016-06-22T22:24:20Z",
+  "name": "foo",
+  "common_name": "bar.com",
+  "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+  "expires": "2017-01-14T23:57:57Z",
+  "starts": "2016-01-15T23:57:57Z",
+  "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+  "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+}
+

Destroy a Certificate

+

Example Request:

+
DELETE /v2/certs/foo HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Attach a Domain to a Certificate

+

Example Request:

+
POST /v2/certs/foo/domain/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "domain": "test.com"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Remove a Domain from a Certificate

+

Example Request:

+
DELETE /v2/certs/foo/domain/test.com/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Pods

+

List all Pods

+

Example Request:

+
GET /v2/apps/example-go/pods/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "results": [
+        {
+            "name": "go-v2-web-e7dej",
+            "release": "v2",
+            "started": "2014-01-01T00:00:00Z",
+            "state": "up",
+            "type": "web"
+        }
+    ]
+}
+

List all Pods by Type

+

Example Request:

+
GET /v2/apps/example-go/pods/web/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "results": [
+        {
+            "name": "go-v2-web-e7dej",
+            "release": "v2",
+            "started": "2014-01-01T00:00:00Z",
+            "state": "up",
+            "type": "web"
+        }
+    ]
+}
+

Restart All Pods

+

Example Request:

+
POST /v2/apps/example-go/pods/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Restart Pods by Type

+

Example Request:

+
POST /v2/apps/example-go/pods/web/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Restart Pods by Type and Name

+

Example Request:

+
POST /v2/apps/example-go/pods/go-v2-web-atots/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Scale Pods

+

Example Request:

+
POST /v2/apps/example-go/scale/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"web": 3}
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Configuration

+

List Application Configuration

+

Example Request:

+
GET /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+      "PLATFORM": "drycc"
+    },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Create new Config

+

Example Request:

+
POST /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"values": {"HELLO": "world", "PLATFORM": "drycc"}}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+        "DRYCC_APP": "example-go",
+        "DRYCC_RELEASE": "v3",
+        "HELLO": "world",
+        "PLATFORM": "drycc"
+
+    },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Unset Config Variable

+

Example Request:

+
POST /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"values": {"HELLO": null}}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+        "DRYCC_APP": "example-go",
+        "DRYCC_RELEASE": "v4",
+        "PLATFORM": "drycc"
+   },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Domains

+

List Application Domains

+

Example Request:

+
GET /v2/apps/example-go/domains/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "app": "example-go",
+            "created": "2014-01-01T00:00:00UTC",
+            "domain": "example.example.com",
+            "owner": "test",
+            "updated": "2014-01-01T00:00:00UTC"
+        }
+    ]
+}
+

Add Domain

+

Example Request:

+
POST /v2/apps/example-go/domains/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{'domain': 'example.example.com'}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "domain": "example.example.com",
+    "owner": "test",
+    "updated": "2014-01-01T00:00:00UTC"
+}
+

Remove Domain

+

Example Request:

+
DELETE /v2/apps/example-go/domains/example.example.com HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Builds

+

List Application Builds

+

Example Request:

+
GET /v2/apps/example-go/build/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "dockerfile": "FROM drycc/slugrunner RUN mkdir -p /app WORKDIR /app ENTRYPOINT [\"/runner/init\"] ADD slug.tgz /app ENV GIT_SHA 060da68f654e75fac06dbedd1995d5f8ad9084db",
+    "image": "example-go",
+    "owner": "test",
+    "procfile": {
+        "web": "example-go"
+    },
+    "sha": "060da68f",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Create Application Build

+

Example Request:

+
POST /v2/apps/example-go/build/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"image": "drycc/example-go:latest"}
+

Optional Parameters:

+
{
+    "procfile": {
+      "web": "./cmd"
+    }
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "dockerfile": "",
+    "image": "drycc/example-go:latest",
+    "owner": "test",
+    "procfile": {},
+    "sha": "",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Releases

+

List Application Releases

+

Example Request:

+
GET /v2/apps/example-go/releases/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 3,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "app": "example-go",
+            "build": "202d8e4b-600e-4425-a85c-ffc7ea607f61",
+            "config": "ed637ceb-5d32-44bd-9406-d326a777a513",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test changed nothing",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 3
+        },
+        {
+            "app": "example-go",
+            "build": "202d8e4b-600e-4425-a85c-ffc7ea607f61",
+            "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test deployed 060da68",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 2
+        },
+        {
+            "app": "example-go",
+            "build": null,
+            "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test created initial release",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 1
+        }
+    ]
+}
+

List Release Details

+

Example Request:

+
GET /v2/apps/example-go/releases/v2/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "build": null,
+    "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+    "created": "2014-01-01T00:00:00UTC",
+    "owner": "test",
+    "summary": "test created initial release",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+    "version": 1
+}
+

Rollback Release

+

Example Request:

+
POST /v2/apps/example-go/releases/rollback/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"version": 1}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{"version": 5}
+

Keys

+

List Keys

+

Example Request:

+
GET /v2/keys/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "created": "2014-01-01T00:00:00UTC",
+            "id": "test@example.com",
+            "owner": "test",
+            "public": "ssh-rsa <...>",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+        }
+    ]
+}
+

Add Key to User

+

Example Request:

+
POST /v2/keys/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "id": "example",
+    "public": "ssh-rsa <...>"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example",
+    "owner": "example",
+    "public": "ssh-rsa <...>",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Remove Key from User

+

Example Request:

+
DELETE /v2/keys/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Permissions

+

List Application Permissions

+
+

note

+

This does not include the app owner.

+
+

Example Request:

+
GET /v2/apps/example-go/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "users": [
+        "test",
+        "foo"
+    ]
+}
+

Create Application Permission

+

Example Request:

+
POST /v2/apps/example-go/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{"username": "example"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Remove Application Permission

+

Example Request:

+
DELETE /v2/apps/example-go/perms/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

List Administrators

+

Example Request:

+
GET /v2/admin/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 2,
+    "next": null
+    "previous": null,
+    "results": [
+        {
+            "username": "test",
+            "is_superuser": true
+        },
+        {
+            "username": "foo",
+            "is_superuser": true
+        }
+    ]
+}
+

Grant User Administrative Privileges

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
POST /v2/admin/perms HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{"username": "example"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Remove User’s Administrative Privileges

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
DELETE /v2/admin/perms/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Users

+

List all users

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
GET /v2/users HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "id": 1,
+            "last_login": "2014-10-19T22:01:00.601Z",
+            "is_superuser": true,
+            "username": "test",
+            "first_name": "test",
+            "last_name": "testerson",
+            "email": "test@example.com",
+            "is_staff": true,
+            "is_active": true,
+            "date_joined": "2014-10-19T22:01:00.601Z",
+            "groups": [],
+            "user_permissions": []
+        }
+    ]
+}
+
+
+ + + + + + + + + + + +
+ +

4 - Controller API v2.2

+
This is the v2.2 REST API for the Controller.
+

What’s New

+

New! /v2/auth/whoami endpoint

+

Authentication

+

Register a New User

+

Example Request:

+
POST /v2/auth/register/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+
+{
+    "username": "test",
+    "password": "opensesame",
+    "email": "test@example.com"
+}
+

Optional Parameters:

+
{
+    "first_name": "test",
+    "last_name": "testerson"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "id": 1,
+    "last_login": "2014-10-19T22:01:00.601Z",
+    "is_superuser": true,
+    "username": "test",
+    "first_name": "test",
+    "last_name": "testerson",
+    "email": "test@example.com",
+    "is_staff": true,
+    "is_active": true,
+    "date_joined": "2014-10-19T22:01:00.601Z",
+    "groups": [],
+    "user_permissions": []
+}
+

Log in

+

Example Request:

+
POST /v2/auth/login/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+
+{"username": "test", "password": "opensesame"}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{"token": "abc123"}
+

Cancel Account

+

Example Request:

+
DELETE /v2/auth/cancel/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Who Am I

+

Example Request:

+
GET /v2/auth/whoami/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "id": 1,
+    "last_login": "2014-10-19T22:01:00.601Z",
+    "is_superuser": true,
+    "username": "test",
+    "first_name": "test",
+    "last_name": "testerson",
+    "email": "test@example.com",
+    "is_staff": true,
+    "is_active": true,
+    "date_joined": "2014-10-19T22:01:00.601Z",
+    "groups": [],
+    "user_permissions": []
+}
+

Regenerate Token

+
+

note

+

This command could require administrative privileges

+
+

Example Request:

+
POST /v2/auth/tokens/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional Parameters:

+
{
+    "username" : "test"
+    "all" : "true"
+}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{"token": "abc123"}
+

Change Password

+

Example Request:

+
POST /v2/auth/passwd/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "password": "foo",
+    "new_password": "bar"
+}
+

Optional parameters:

+
{"username": "testuser"}
+
+

note

+

Using the username parameter requires administrative privileges and makes the password parameter optional.

+
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Applications

+

List all Applications

+

Example Request:

+
GET /v2/apps HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "created": "2014-01-01T00:00:00UTC",
+            "id": "example-go",
+            "owner": "test",
+            "structure": {},
+            "updated": "2014-01-01T00:00:00UTC",
+            "url": "example-go.example.com",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+        }
+    ]
+}
+

Create an Application

+

Example Request:

+
POST /v2/apps/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+

Optional parameters:

+
{"id": "example-go"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example-go",
+    "owner": "test",
+    "structure": {},
+    "updated": "2014-01-01T00:00:00UTC",
+    "url": "example-go.example.com",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Destroy an Application

+

Example Request:

+
DELETE /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

List Application Details

+

Example Request:

+
GET /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example-go",
+    "owner": "test",
+    "structure": {},
+    "updated": "2014-01-01T00:00:00UTC",
+    "url": "example-go.example.com",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Update Application Details

+

Example Request:

+
POST /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional parameters:

+
{
+  "owner": "test"
+}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 1.8.0
+Content-Type: application/json
+

Retrieve Application Logs

+

Example Request:

+
GET /v2/apps/example-go/logs/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional URL Query Parameters:

+
?log_lines=
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: text/plain
+
+"16:51:14 drycc[api]: test created initial release\n"
+

Run one-off Commands

+
POST /v2/apps/example-go/run/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"command": "echo hi"}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{"exit_code": 0, "output": "hi\n"}
+

Certificates

+

List all Certificates

+

Example Request:

+
GET /v2/certs HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+  "count": 1,
+  "next": null,
+  "previous": null,
+  "results": [
+    {
+      "id": 22,
+      "owner": "test",
+      "san": [],
+      "domains": [],
+      "created": "2016-06-22T22:24:20Z",
+      "updated": "2016-06-22T22:24:20Z",
+      "name": "foo",
+      "common_name": "bar.com",
+      "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+      "expires": "2017-01-14T23:57:57Z",
+      "starts": "2016-01-15T23:57:57Z",
+      "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+      "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+    }
+  ]
+}
+

Get Certificate Details

+

Example Request:

+
GET /v2/certs/foo HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+  "id": 22,
+  "owner": "test",
+  "san": [],
+  "domains": [],
+  "created": "2016-06-22T22:24:20Z",
+  "updated": "2016-06-22T22:24:20Z",
+  "name": "foo",
+  "common_name": "bar.com",
+  "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+  "expires": "2017-01-14T23:57:57Z",
+  "starts": "2016-01-15T23:57:57Z",
+  "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+  "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+}
+

Create Certificate

+

Example Request:

+
POST /v2/certs/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{
+    "name": "foo"
+    "certificate": "-----BEGIN CERTIFICATE-----",
+    "key": "-----BEGIN RSA PRIVATE KEY-----"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+  "id": 22,
+  "owner": "test",
+  "san": [],
+  "domains": [],
+  "created": "2016-06-22T22:24:20Z",
+  "updated": "2016-06-22T22:24:20Z",
+  "name": "foo",
+  "common_name": "bar.com",
+  "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+  "expires": "2017-01-14T23:57:57Z",
+  "starts": "2016-01-15T23:57:57Z",
+  "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+  "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+}
+

Destroy a Certificate

+

Example Request:

+
DELETE /v2/certs/foo HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Attach a Domain to a Certificate

+

Example Request:

+
POST /v2/certs/foo/domain/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "domain": "test.com"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Remove a Domain from a Certificate

+

Example Request:

+
DELETE /v2/certs/foo/domain/test.com/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Pods

+

List all Pods

+

Example Request:

+
GET /v2/apps/example-go/pods/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "results": [
+        {
+            "name": "go-v2-web-e7dej",
+            "release": "v2",
+            "started": "2014-01-01T00:00:00Z",
+            "state": "up",
+            "type": "web"
+        }
+    ]
+}
+

List all Pods by Type

+

Example Request:

+
GET /v2/apps/example-go/pods/web/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "results": [
+        {
+            "name": "go-v2-web-e7dej",
+            "release": "v2",
+            "started": "2014-01-01T00:00:00Z",
+            "state": "up",
+            "type": "web"
+        }
+    ]
+}
+

Restart All Pods

+

Example Request:

+
POST /v2/apps/example-go/pods/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Restart Pods by Type

+

Example Request:

+
POST /v2/apps/example-go/pods/web/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Restart Pods by Type and Name

+

Example Request:

+
POST /v2/apps/example-go/pods/go-v2-web-atots/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Scale Pods

+

Example Request:

+
POST /v2/apps/example-go/scale/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"web": 3}
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Configuration

+

List Application Configuration

+

Example Request:

+
GET /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+      "PLATFORM": "drycc"
+    },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Create new Config

+

Example Request:

+
POST /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"values": {"HELLO": "world", "PLATFORM": "drycc"}}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+        "DRYCC_APP": "example-go",
+        "DRYCC_RELEASE": "v3",
+        "HELLO": "world",
+        "PLATFORM": "drycc"
+
+    },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Unset Config Variable

+

Example Request:

+
POST /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"values": {"HELLO": null}}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+        "DRYCC_APP": "example-go",
+        "DRYCC_RELEASE": "v4",
+        "PLATFORM": "drycc"
+   },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Domains

+

List Application Domains

+

Example Request:

+
GET /v2/apps/example-go/domains/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "app": "example-go",
+            "created": "2014-01-01T00:00:00UTC",
+            "domain": "example.example.com",
+            "owner": "test",
+            "updated": "2014-01-01T00:00:00UTC"
+        }
+    ]
+}
+

Add Domain

+

Example Request:

+
POST /v2/apps/example-go/domains/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{'domain': 'example.example.com'}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "domain": "example.example.com",
+    "owner": "test",
+    "updated": "2014-01-01T00:00:00UTC"
+}
+

Remove Domain

+

Example Request:

+
DELETE /v2/apps/example-go/domains/example.example.com HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Builds

+

List Application Builds

+

Example Request:

+
GET /v2/apps/example-go/build/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "dockerfile": "FROM drycc/slugrunner RUN mkdir -p /app WORKDIR /app ENTRYPOINT [\"/runner/init\"] ADD slug.tgz /app ENV GIT_SHA 060da68f654e75fac06dbedd1995d5f8ad9084db",
+    "image": "example-go",
+    "owner": "test",
+    "procfile": {
+        "web": "example-go"
+    },
+    "sha": "060da68f",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Create Application Build

+

Example Request:

+
POST /v2/apps/example-go/build/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"image": "drycc/example-go:latest"}
+

Optional Parameters:

+
{
+    "procfile": {
+      "web": "./cmd"
+    }
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "dockerfile": "",
+    "image": "drycc/example-go:latest",
+    "owner": "test",
+    "procfile": {},
+    "sha": "",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Releases

+

List Application Releases

+

Example Request:

+
GET /v2/apps/example-go/releases/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "count": 3,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "app": "example-go",
+            "build": "202d8e4b-600e-4425-a85c-ffc7ea607f61",
+            "config": "ed637ceb-5d32-44bd-9406-d326a777a513",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test changed nothing",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 3
+        },
+        {
+            "app": "example-go",
+            "build": "202d8e4b-600e-4425-a85c-ffc7ea607f61",
+            "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test deployed 060da68",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 2
+        },
+        {
+            "app": "example-go",
+            "build": null,
+            "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test created initial release",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 1
+        }
+    ]
+}
+

List Release Details

+

Example Request:

+
GET /v2/apps/example-go/releases/v2/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "build": null,
+    "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+    "created": "2014-01-01T00:00:00UTC",
+    "owner": "test",
+    "summary": "test created initial release",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+    "version": 1
+}
+

Rollback Release

+

Example Request:

+
POST /v2/apps/example-go/releases/rollback/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"version": 1}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{"version": 5}
+

Keys

+

List Keys

+

Example Request:

+
GET /v2/keys/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "created": "2014-01-01T00:00:00UTC",
+            "id": "test@example.com",
+            "owner": "test",
+            "public": "ssh-rsa <...>",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+        }
+    ]
+}
+

Add Key to User

+

Example Request:

+
POST /v2/keys/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "id": "example",
+    "public": "ssh-rsa <...>"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example",
+    "owner": "example",
+    "public": "ssh-rsa <...>",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Remove Key from User

+

Example Request:

+
DELETE /v2/keys/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Permissions

+

List Application Permissions

+
+

note

+

This does not include the app owner.

+
+

Example Request:

+
GET /v2/apps/example-go/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "users": [
+        "test",
+        "foo"
+    ]
+}
+

Create Application Permission

+

Example Request:

+
POST /v2/apps/example-go/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{"username": "example"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Remove Application Permission

+

Example Request:

+
DELETE /v2/apps/example-go/perms/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

List Administrators

+

Example Request:

+
GET /v2/admin/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "count": 2,
+    "next": null
+    "previous": null,
+    "results": [
+        {
+            "username": "test",
+            "is_superuser": true
+        },
+        {
+            "username": "foo",
+            "is_superuser": true
+        }
+    ]
+}
+

Grant User Administrative Privileges

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
POST /v2/admin/perms HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{"username": "example"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Remove User’s Administrative Privileges

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
DELETE /v2/admin/perms/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Users

+

List all users

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
GET /v2/users HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "id": 1,
+            "last_login": "2014-10-19T22:01:00.601Z",
+            "is_superuser": true,
+            "username": "test",
+            "first_name": "test",
+            "last_name": "testerson",
+            "email": "test@example.com",
+            "is_staff": true,
+            "is_active": true,
+            "date_joined": "2014-10-19T22:01:00.601Z",
+            "groups": [],
+            "user_permissions": []
+        }
+    ]
+}
+
+
+ + + + + + + + + + + +
+ +

5 - Controller API v2.3

+
This is the v2.3 REST API for the Controller.
+

What’s New

+

New! /v2/apps/{name}/logs endpoint was fixed and no longer returns b'log data' and instead returns a normal string log data

+

Authentication

+

Register a New User

+

Example Request:

+
POST /v2/auth/register/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+
+{
+    "username": "test",
+    "password": "opensesame",
+    "email": "test@example.com"
+}
+

Optional Parameters:

+
{
+    "first_name": "test",
+    "last_name": "testerson"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "id": 1,
+    "last_login": "2014-10-19T22:01:00.601Z",
+    "is_superuser": true,
+    "username": "test",
+    "first_name": "test",
+    "last_name": "testerson",
+    "email": "test@example.com",
+    "is_staff": true,
+    "is_active": true,
+    "date_joined": "2014-10-19T22:01:00.601Z",
+    "groups": [],
+    "user_permissions": []
+}
+

Log in

+

Example Request:

+
POST /v2/auth/login/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+
+{"username": "test", "password": "opensesame"}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{"token": "abc123"}
+

Cancel Account

+

Example Request:

+
DELETE /v2/auth/cancel/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Who Am I

+

Example Request:

+
GET /v2/auth/whoami/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "id": 1,
+    "last_login": "2014-10-19T22:01:00.601Z",
+    "is_superuser": true,
+    "username": "test",
+    "first_name": "test",
+    "last_name": "testerson",
+    "email": "test@example.com",
+    "is_staff": true,
+    "is_active": true,
+    "date_joined": "2014-10-19T22:01:00.601Z",
+    "groups": [],
+    "user_permissions": []
+}
+

Regenerate Token

+
+

note

+

This command could require administrative privileges

+
+

Example Request:

+
POST /v2/auth/tokens/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional Parameters:

+
{
+    "username" : "test"
+    "all" : "true"
+}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{"token": "abc123"}
+

Change Password

+

Example Request:

+
POST /v2/auth/passwd/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "password": "foo",
+    "new_password": "bar"
+}
+

Optional parameters:

+
{"username": "testuser"}
+
+

note

+

Using the username parameter requires administrative privileges and makes the password parameter optional.

+
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Applications

+

List all Applications

+

Example Request:

+
GET /v2/apps HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "created": "2014-01-01T00:00:00UTC",
+            "id": "example-go",
+            "owner": "test",
+            "structure": {},
+            "updated": "2014-01-01T00:00:00UTC",
+            "url": "example-go.example.com",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+        }
+    ]
+}
+

Create an Application

+

Example Request:

+
POST /v2/apps/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+

Optional parameters:

+
{"id": "example-go"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example-go",
+    "owner": "test",
+    "structure": {},
+    "updated": "2014-01-01T00:00:00UTC",
+    "url": "example-go.example.com",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Destroy an Application

+

Example Request:

+
DELETE /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

List Application Details

+

Example Request:

+
GET /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example-go",
+    "owner": "test",
+    "structure": {},
+    "updated": "2014-01-01T00:00:00UTC",
+    "url": "example-go.example.com",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Update Application Details

+

Example Request:

+
POST /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional parameters:

+
{
+  "owner": "test"
+}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 1.8.0
+Content-Type: application/json
+

Retrieve Application Logs

+

Example Request:

+
GET /v2/apps/example-go/logs/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional URL Query Parameters:

+
?log_lines=
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: text/plain
+
+"16:51:14 drycc[api]: test created initial release\n"
+

Run one-off Commands

+
POST /v2/apps/example-go/run/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"command": "echo hi"}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{"exit_code": 0, "output": "hi\n"}
+

Certificates

+

List all Certificates

+

Example Request:

+
GET /v2/certs HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+  "count": 1,
+  "next": null,
+  "previous": null,
+  "results": [
+    {
+      "id": 22,
+      "owner": "test",
+      "san": [],
+      "domains": [],
+      "created": "2016-06-22.32.34:20Z",
+      "updated": "2016-06-22.32.34:20Z",
+      "name": "foo",
+      "common_name": "bar.com",
+      "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+      "expires": "2017-01-14T23:57:57Z",
+      "starts": "2016-01-15T23:57:57Z",
+      "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+      "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+    }
+  ]
+}
+

Get Certificate Details

+

Example Request:

+
GET /v2/certs/foo HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+  "id": 22,
+  "owner": "test",
+  "san": [],
+  "domains": [],
+  "created": "2016-06-22.32.34:20Z",
+  "updated": "2016-06-22.32.34:20Z",
+  "name": "foo",
+  "common_name": "bar.com",
+  "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+  "expires": "2017-01-14T23:57:57Z",
+  "starts": "2016-01-15T23:57:57Z",
+  "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+  "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+}
+

Create Certificate

+

Example Request:

+
POST /v2/certs/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{
+    "name": "foo"
+    "certificate": "-----BEGIN CERTIFICATE-----",
+    "key": "-----BEGIN RSA PRIVATE KEY-----"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+  "id": 22,
+  "owner": "test",
+  "san": [],
+  "domains": [],
+  "created": "2016-06-22.32.34:20Z",
+  "updated": "2016-06-22.32.34:20Z",
+  "name": "foo",
+  "common_name": "bar.com",
+  "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+  "expires": "2017-01-14T23:57:57Z",
+  "starts": "2016-01-15T23:57:57Z",
+  "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+  "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+}
+

Destroy a Certificate

+

Example Request:

+
DELETE /v2/certs/foo HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Attach a Domain to a Certificate

+

Example Request:

+
POST /v2/certs/foo/domain/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "domain": "test.com"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Remove a Domain from a Certificate

+

Example Request:

+
DELETE /v2/certs/foo/domain/test.com/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Enable or disable TLS

+

Example Request:

+
POST /v2/apps/example-go/tls/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{
+  "https_enforced": true
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "app": "example-go",
+    "owner": "test",
+    "https_enforced": true,
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Get TLS status

+

Example Request:

+
GET /v2/apps/example-go/tls/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "app": "example-go",
+    "owner": "test",
+    "https_enforced": false,
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Pods

+

List all Pods

+

Example Request:

+
GET /v2/apps/example-go/pods/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "results": [
+        {
+            "name": "go-v2-web-e7dej",
+            "release": "v2",
+            "started": "2014-01-01T00:00:00Z",
+            "state": "up",
+            "type": "web"
+        }
+    ]
+}
+

List all Pods by Type

+

Example Request:

+
GET /v2/apps/example-go/pods/web/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "results": [
+        {
+            "name": "go-v2-web-e7dej",
+            "release": "v2",
+            "started": "2014-01-01T00:00:00Z",
+            "state": "up",
+            "type": "web"
+        }
+    ]
+}
+

Restart All Pods

+

Example Request:

+
POST /v2/apps/example-go/pods/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Restart Pods by Type

+

Example Request:

+
POST /v2/apps/example-go/pods/web/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Restart Pods by Type and Name

+

Example Request:

+
POST /v2/apps/example-go/pods/go-v2-web-atots/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Scale Pods

+

Example Request:

+
POST /v2/apps/example-go/scale/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"web": 3}
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Configuration

+

List Application Configuration

+

Example Request:

+
GET /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+      "PLATFORM": "drycc"
+    },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Create new Config

+

Example Request:

+
POST /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"values": {"HELLO": "world", "PLATFORM": "drycc"}}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+        "DRYCC_APP": "example-go",
+        "DRYCC_RELEASE": "v3",
+        "HELLO": "world",
+        "PLATFORM": "drycc"
+
+    },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Unset Config Variable

+

Example Request:

+
POST /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"values": {"HELLO": null}}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+        "DRYCC_APP": "example-go",
+        "DRYCC_RELEASE": "v4",
+        "PLATFORM": "drycc"
+   },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Domains

+

List Application Domains

+

Example Request:

+
GET /v2/apps/example-go/domains/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "app": "example-go",
+            "created": "2014-01-01T00:00:00UTC",
+            "domain": "example.example.com",
+            "owner": "test",
+            "updated": "2014-01-01T00:00:00UTC"
+        }
+    ]
+}
+

Add Domain

+

Example Request:

+
POST /v2/apps/example-go/domains/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{'domain': 'example.example.com'}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "domain": "example.example.com",
+    "owner": "test",
+    "updated": "2014-01-01T00:00:00UTC"
+}
+

Remove Domain

+

Example Request:

+
DELETE /v2/apps/example-go/domains/example.example.com HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Builds

+

List Application Builds

+

Example Request:

+
GET /v2/apps/example-go/build/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "dockerfile": "FROM drycc/slugrunner RUN mkdir -p /app WORKDIR /app ENTRYPOINT [\"/runner/init\"] ADD slug.tgz /app ENV GIT_SHA 060da68f654e75fac06dbedd1995d5f8ad9084db",
+    "image": "example-go",
+    "owner": "test",
+    "procfile": {
+        "web": "example-go"
+    },
+    "sha": "060da68f",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Create Application Build

+

Example Request:

+
POST /v2/apps/example-go/build/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"image": "drycc/example-go:latest"}
+

Optional Parameters:

+
{
+    "procfile": {
+      "web": "./cmd"
+    }
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "dockerfile": "",
+    "image": "drycc/example-go:latest",
+    "owner": "test",
+    "procfile": {},
+    "sha": "",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Releases

+

List Application Releases

+

Example Request:

+
GET /v2/apps/example-go/releases/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "count": 3,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "app": "example-go",
+            "build": "2.3d8e4b-600e-4425-a85c-ffc7ea607f61",
+            "config": "ed637ceb-5d32-44bd-9406-d326a777a513",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test changed nothing",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 3
+        },
+        {
+            "app": "example-go",
+            "build": "2.3d8e4b-600e-4425-a85c-ffc7ea607f61",
+            "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test deployed 060da68",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 2
+        },
+        {
+            "app": "example-go",
+            "build": null,
+            "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test created initial release",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 1
+        }
+    ]
+}
+

List Release Details

+

Example Request:

+
GET /v2/apps/example-go/releases/v2/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "build": null,
+    "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+    "created": "2014-01-01T00:00:00UTC",
+    "owner": "test",
+    "summary": "test created initial release",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+    "version": 1
+}
+

Rollback Release

+

Example Request:

+
POST /v2/apps/example-go/releases/rollback/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"version": 1}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{"version": 5}
+

Keys

+

List Keys

+

Example Request:

+
GET /v2/keys/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "created": "2014-01-01T00:00:00UTC",
+            "id": "test@example.com",
+            "owner": "test",
+            "public": "ssh-rsa <...>",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+        }
+    ]
+}
+

Add Key to User

+

Example Request:

+
POST /v2/keys/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "id": "example",
+    "public": "ssh-rsa <...>"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example",
+    "owner": "example",
+    "public": "ssh-rsa <...>",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Remove Key from User

+

Example Request:

+
DELETE /v2/keys/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Permissions

+

List Application Permissions

+
+

note

+

This does not include the app owner.

+
+

Example Request:

+
GET /v2/apps/example-go/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "users": [
+        "test",
+        "foo"
+    ]
+}
+

Create Application Permission

+

Example Request:

+
POST /v2/apps/example-go/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{"username": "example"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Remove Application Permission

+

Example Request:

+
DELETE /v2/apps/example-go/perms/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

List Administrators

+

Example Request:

+
GET /v2/admin/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "count": 2,
+    "next": null
+    "previous": null,
+    "results": [
+        {
+            "username": "test",
+            "is_superuser": true
+        },
+        {
+            "username": "foo",
+            "is_superuser": true
+        }
+    ]
+}
+

Grant User Administrative Privileges

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
POST /v2/admin/perms HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{"username": "example"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Remove User’s Administrative Privileges

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
DELETE /v2/admin/perms/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Users

+

List all users

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
GET /v2/users HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "id": 1,
+            "last_login": "2014-10-19T22:01:00.601Z",
+            "is_superuser": true,
+            "username": "test",
+            "first_name": "test",
+            "last_name": "testerson",
+            "email": "test@example.com",
+            "is_staff": true,
+            "is_active": true,
+            "date_joined": "2014-10-19T22:01:00.601Z",
+            "groups": [],
+            "user_permissions": []
+        }
+    ]
+}
+
+
+ + + + + + + + + +
+
+
+ + +
+ + + + + + diff --git a/docs/reference-guide/controller-api-v2-0/index.html b/docs/reference-guide/controller-api-v2-0/index.html new file mode 100644 index 000000000..e682d7b5b --- /dev/null +++ b/docs/reference-guide/controller-api-v2-0/index.html @@ -0,0 +1,1500 @@ + + + + + + + + + + + + + + + + + + + +Controller API v2.0 | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Controller API v2.0

+
This is the v2.0 REST API for the Controller.
+ +

What’s New

+

New! format of POST /v2/apps/<app id>/run has changed.

+

Authentication

+

Register a New User

+

Example Request:

+
POST /v2/auth/register/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+
+{
+    "username": "test",
+    "password": "opensesame",
+    "email": "test@example.com"
+}
+

Optional Parameters:

+
{
+    "first_name": "test",
+    "last_name": "testerson"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "id": 1,
+    "last_login": "2014-10-19T22:01:00.601Z",
+    "is_superuser": true,
+    "username": "test",
+    "first_name": "test",
+    "last_name": "testerson",
+    "email": "test@example.com",
+    "is_staff": true,
+    "is_active": true,
+    "date_joined": "2014-10-19T22:01:00.601Z",
+    "groups": [],
+    "user_permissions": []
+}
+

Log in

+

Example Request:

+
POST /v2/auth/login/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+
+{"username": "test", "password": "opensesame"}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{"token": "abc123"}
+

Cancel Account

+

Example Request:

+
DELETE /v2/auth/cancel/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Regenerate Token

+
+

note

+

This command could require administrative privileges

+
+

Example Request:

+
POST /v2/auth/tokens/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional Parameters:

+
{
+    "username" : "test"
+    "all" : "true"
+}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{"token": "abc123"}
+

Change Password

+

Example Request:

+
POST /v2/auth/passwd/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "password": "foo",
+    "new_password": "bar"
+}
+

Optional parameters:

+
{"username": "testuser"}
+
+

note

+

Using the username parameter requires administrative privileges and makes the password parameter optional.

+
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Applications

+

List all Applications

+

Example Request:

+
GET /v2/apps HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "created": "2014-01-01T00:00:00UTC",
+            "id": "example-go",
+            "owner": "test",
+            "structure": {},
+            "updated": "2014-01-01T00:00:00UTC",
+            "url": "example-go.example.com",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+        }
+    ]
+}
+

Create an Application

+

Example Request:

+
POST /v2/apps/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+

Optional parameters:

+
{"id": "example-go"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example-go",
+    "owner": "test",
+    "structure": {},
+    "updated": "2014-01-01T00:00:00UTC",
+    "url": "example-go.example.com",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Destroy an Application

+

Example Request:

+
DELETE /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

List Application Details

+

Example Request:

+
GET /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example-go",
+    "owner": "test",
+    "structure": {},
+    "updated": "2014-01-01T00:00:00UTC",
+    "url": "example-go.example.com",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Update Application Details

+

Example Request:

+
POST /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional parameters:

+
{
+  "owner": "test"
+}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 1.8.0
+Content-Type: application/json
+

Retrieve Application Logs

+

Example Request:

+
GET /v2/apps/example-go/logs/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional URL Query Parameters:

+
?log_lines=
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: text/plain
+
+"16:51:14 drycc[api]: test created initial release\n"
+

Run one-off Commands

+
POST /v2/apps/example-go/run/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"command": "echo hi"}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{"exit_code": 0, "output": "hi\n"}
+

Certificates

+

List all Certificates

+

Example Request:

+
GET /v2/certs HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+  "count": 1,
+  "next": null,
+  "previous": null,
+  "results": [
+    {
+      "id": 22,
+      "owner": "test",
+      "san": [],
+      "domains": [],
+      "created": "2016-06-22T22:24:20Z",
+      "updated": "2016-06-22T22:24:20Z",
+      "name": "foo",
+      "common_name": "bar.com",
+      "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+      "expires": "2017-01-14T23:57:57Z",
+      "starts": "2016-01-15T23:57:57Z",
+      "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+      "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+    }
+  ]
+}
+

Get Certificate Details

+

Example Request:

+
GET /v2/certs/foo HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+  "id": 22,
+  "owner": "test",
+  "san": [],
+  "domains": [],
+  "created": "2016-06-22T22:24:20Z",
+  "updated": "2016-06-22T22:24:20Z",
+  "name": "foo",
+  "common_name": "bar.com",
+  "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+  "expires": "2017-01-14T23:57:57Z",
+  "starts": "2016-01-15T23:57:57Z",
+  "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+  "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+}
+

Create Certificate

+

Example Request:

+
POST /v2/certs/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{
+    "name": "foo"
+    "certificate": "-----BEGIN CERTIFICATE-----",
+    "key": "-----BEGIN RSA PRIVATE KEY-----"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+  "id": 22,
+  "owner": "test",
+  "san": [],
+  "domains": [],
+  "created": "2016-06-22T22:24:20Z",
+  "updated": "2016-06-22T22:24:20Z",
+  "name": "foo",
+  "common_name": "bar.com",
+  "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+  "expires": "2017-01-14T23:57:57Z",
+  "starts": "2016-01-15T23:57:57Z",
+  "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+  "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+}
+

Destroy a Certificate

+

Example Request:

+
DELETE /v2/certs/foo HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Attach a Domain to a Certificate

+

Example Request:

+
POST /v2/certs/foo/domain/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "domain": "test.com"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Remove a Domain from a Certificate

+

Example Request:

+
DELETE /v2/certs/foo/domain/test.com/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Pods

+

List all Pods

+

Example Request:

+
GET /v2/apps/example-go/pods/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "results": [
+        {
+            "name": "go-v2-web-e7dej",
+            "release": "v2",
+            "started": "2014-01-01T00:00:00Z",
+            "state": "up",
+            "type": "web"
+        }
+    ]
+}
+

List all Pods by Type

+

Example Request:

+
GET /v2/apps/example-go/pods/web/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "results": [
+        {
+            "name": "go-v2-web-e7dej",
+            "release": "v2",
+            "started": "2014-01-01T00:00:00Z",
+            "state": "up",
+            "type": "web"
+        }
+    ]
+}
+

Restart All Pods

+

Example Request:

+
POST /v2/apps/example-go/pods/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Restart Pods by Type

+

Example Request:

+
POST /v2/apps/example-go/pods/web/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Restart Pods by Type and Name

+

Example Request:

+
POST /v2/apps/example-go/pods/go-v2-web-atots/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Scale Pods

+

Example Request:

+
POST /v2/apps/example-go/scale/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"web": 3}
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Configuration

+

List Application Configuration

+

Example Request:

+
GET /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+      "PLATFORM": "drycc"
+    },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Create new Config

+

Example Request:

+
POST /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"values": {"HELLO": "world", "PLATFORM": "drycc"}}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+X-Drycc-Release: 3
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+        "DRYCC_APP": "example-go",
+        "DRYCC_RELEASE": "v3",
+        "HELLO": "world",
+        "PLATFORM": "drycc"
+
+    },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Unset Config Variable

+

Example Request:

+
POST /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"values": {"HELLO": null}}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+X-Drycc-Release: 4
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+        "DRYCC_APP": "example-go",
+        "DRYCC_RELEASE": "v4",
+        "PLATFORM": "drycc"
+   },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Domains

+

List Application Domains

+

Example Request:

+
GET /v2/apps/example-go/domains/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "app": "example-go",
+            "created": "2014-01-01T00:00:00UTC",
+            "domain": "example.example.com",
+            "owner": "test",
+            "updated": "2014-01-01T00:00:00UTC"
+        }
+    ]
+}
+

Add Domain

+

Example Request:

+
POST /v2/apps/example-go/domains/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{'domain': 'example.example.com'}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "domain": "example.example.com",
+    "owner": "test",
+    "updated": "2014-01-01T00:00:00UTC"
+}
+

Remove Domain

+

Example Request:

+
DELETE /v2/apps/example-go/domains/example.example.com HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Builds

+

List Application Builds

+

Example Request:

+
GET /v2/apps/example-go/build/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "dockerfile": "FROM drycc/slugrunner RUN mkdir -p /app WORKDIR /app ENTRYPOINT [\"/runner/init\"] ADD slug.tgz /app ENV GIT_SHA 060da68f654e75fac06dbedd1995d5f8ad9084db",
+    "image": "example-go",
+    "owner": "test",
+    "procfile": {
+        "web": "example-go"
+    },
+    "sha": "060da68f",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Create Application Build

+

Example Request:

+
POST /v2/apps/example-go/build/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"image": "drycc/example-go:latest"}
+

Optional Parameters:

+
{
+    "procfile": {
+      "web": "./cmd"
+    }
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+X-Drycc-Release: 4
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "dockerfile": "",
+    "image": "drycc/example-go:latest",
+    "owner": "test",
+    "procfile": {},
+    "sha": "",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Releases

+

List Application Releases

+

Example Request:

+
GET /v2/apps/example-go/releases/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 3,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "app": "example-go",
+            "build": "202d8e4b-600e-4425-a85c-ffc7ea607f61",
+            "config": "ed637ceb-5d32-44bd-9406-d326a777a513",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test changed nothing",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 3
+        },
+        {
+            "app": "example-go",
+            "build": "202d8e4b-600e-4425-a85c-ffc7ea607f61",
+            "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test deployed 060da68",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 2
+        },
+        {
+            "app": "example-go",
+            "build": null,
+            "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test created initial release",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 1
+        }
+    ]
+}
+

List Release Details

+

Example Request:

+
GET /v2/apps/example-go/releases/v2/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "build": null,
+    "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+    "created": "2014-01-01T00:00:00UTC",
+    "owner": "test",
+    "summary": "test created initial release",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+    "version": 1
+}
+

Rollback Release

+

Example Request:

+
POST /v2/apps/example-go/releases/rollback/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"version": 1}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{"version": 5}
+

Keys

+

List Keys

+

Example Request:

+
GET /v2/keys/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "created": "2014-01-01T00:00:00UTC",
+            "id": "test@example.com",
+            "owner": "test",
+            "public": "ssh-rsa <...>",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+        }
+    ]
+}
+

Add Key to User

+

Example Request:

+
POST /v2/keys/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "id": "example",
+    "public": "ssh-rsa <...>"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example",
+    "owner": "example",
+    "public": "ssh-rsa <...>",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Remove Key from User

+

Example Request:

+
DELETE /v2/keys/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Permissions

+

List Application Permissions

+
+

note

+

This does not include the app owner.

+
+

Example Request:

+
GET /v2/apps/example-go/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "users": [
+        "test",
+        "foo"
+    ]
+}
+

Create Application Permission

+

Example Request:

+
POST /v2/apps/example-go/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{"username": "example"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Remove Application Permission

+

Example Request:

+
DELETE /v2/apps/example-go/perms/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

List Administrators

+

Example Request:

+
GET /v2/admin/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 2,
+    "next": null
+    "previous": null,
+    "results": [
+        {
+            "username": "test",
+            "is_superuser": true
+        },
+        {
+            "username": "foo",
+            "is_superuser": true
+        }
+    ]
+}
+

Grant User Administrative Privileges

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
POST /v2/admin/perms HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{"username": "example"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Remove User’s Administrative Privileges

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
DELETE /v2/admin/perms/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Users

+

List all users

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
GET /v2/users HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.0
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "id": 1,
+            "last_login": "2014-10-19T22:01:00.601Z",
+            "is_superuser": true,
+            "username": "test",
+            "first_name": "test",
+            "last_name": "testerson",
+            "email": "test@example.com",
+            "is_staff": true,
+            "is_active": true,
+            "date_joined": "2014-10-19T22:01:00.601Z",
+            "groups": [],
+            "user_permissions": []
+        }
+    ]
+}
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/reference-guide/controller-api-v2-1/index.html b/docs/reference-guide/controller-api-v2-1/index.html new file mode 100644 index 000000000..cd8d7d626 --- /dev/null +++ b/docs/reference-guide/controller-api-v2-1/index.html @@ -0,0 +1,1499 @@ + + + + + + + + + + + + + + + + + + + +Controller API v2.1 | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Controller API v2.1

+
This is the v2.1 REST API for the Controller.
+ +

What’s New

+

New! healthcheck field in configuration, deprecates the HEALTHCHECK_* environment variables.

+

New! Unsetting a configuration variable that does not exist will return a 422.

+

New! Creating an identical sequential release returns a 409 rather than create a no-op release.

+

Authentication

+

Register a New User

+

Example Request:

+
POST /v2/auth/register/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+
+{
+    "username": "test",
+    "password": "opensesame",
+    "email": "test@example.com"
+}
+

Optional Parameters:

+
{
+    "first_name": "test",
+    "last_name": "testerson"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "id": 1,
+    "last_login": "2014-10-19T22:01:00.601Z",
+    "is_superuser": true,
+    "username": "test",
+    "first_name": "test",
+    "last_name": "testerson",
+    "email": "test@example.com",
+    "is_staff": true,
+    "is_active": true,
+    "date_joined": "2014-10-19T22:01:00.601Z",
+    "groups": [],
+    "user_permissions": []
+}
+

Log in

+

Example Request:

+
POST /v2/auth/login/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+
+{"username": "test", "password": "opensesame"}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{"token": "abc123"}
+

Cancel Account

+

Example Request:

+
DELETE /v2/auth/cancel/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Regenerate Token

+
+

note

+

This command could require administrative privileges

+
+

Example Request:

+
POST /v2/auth/tokens/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional Parameters:

+
{
+    "username" : "test"
+    "all" : "true"
+}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{"token": "abc123"}
+

Change Password

+

Example Request:

+
POST /v2/auth/passwd/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "password": "foo",
+    "new_password": "bar"
+}
+

Optional parameters:

+
{"username": "testuser"}
+
+

note

+

Using the username parameter requires administrative privileges and makes the password parameter optional.

+
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Applications

+

List all Applications

+

Example Request:

+
GET /v2/apps HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "created": "2014-01-01T00:00:00UTC",
+            "id": "example-go",
+            "owner": "test",
+            "structure": {},
+            "updated": "2014-01-01T00:00:00UTC",
+            "url": "example-go.example.com",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+        }
+    ]
+}
+

Create an Application

+

Example Request:

+
POST /v2/apps/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+

Optional parameters:

+
{"id": "example-go"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example-go",
+    "owner": "test",
+    "structure": {},
+    "updated": "2014-01-01T00:00:00UTC",
+    "url": "example-go.example.com",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Destroy an Application

+

Example Request:

+
DELETE /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

List Application Details

+

Example Request:

+
GET /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example-go",
+    "owner": "test",
+    "structure": {},
+    "updated": "2014-01-01T00:00:00UTC",
+    "url": "example-go.example.com",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Update Application Details

+

Example Request:

+
POST /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional parameters:

+
{
+  "owner": "test"
+}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 1.8.0
+Content-Type: application/json
+

Retrieve Application Logs

+

Example Request:

+
GET /v2/apps/example-go/logs/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional URL Query Parameters:

+
?log_lines=
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: text/plain
+
+"16:51:14 drycc[api]: test created initial release\n"
+

Run one-off Commands

+
POST /v2/apps/example-go/run/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"command": "echo hi"}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{"exit_code": 0, "output": "hi\n"}
+

Certificates

+

List all Certificates

+

Example Request:

+
GET /v2/certs HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+  "count": 1,
+  "next": null,
+  "previous": null,
+  "results": [
+    {
+      "id": 22,
+      "owner": "test",
+      "san": [],
+      "domains": [],
+      "created": "2016-06-22T22:24:20Z",
+      "updated": "2016-06-22T22:24:20Z",
+      "name": "foo",
+      "common_name": "bar.com",
+      "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+      "expires": "2017-01-14T23:57:57Z",
+      "starts": "2016-01-15T23:57:57Z",
+      "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+      "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+    }
+  ]
+}
+

Get Certificate Details

+

Example Request:

+
GET /v2/certs/foo HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+  "id": 22,
+  "owner": "test",
+  "san": [],
+  "domains": [],
+  "created": "2016-06-22T22:24:20Z",
+  "updated": "2016-06-22T22:24:20Z",
+  "name": "foo",
+  "common_name": "bar.com",
+  "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+  "expires": "2017-01-14T23:57:57Z",
+  "starts": "2016-01-15T23:57:57Z",
+  "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+  "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+}
+

Create Certificate

+

Example Request:

+
POST /v2/certs/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{
+    "name": "foo"
+    "certificate": "-----BEGIN CERTIFICATE-----",
+    "key": "-----BEGIN RSA PRIVATE KEY-----"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+  "id": 22,
+  "owner": "test",
+  "san": [],
+  "domains": [],
+  "created": "2016-06-22T22:24:20Z",
+  "updated": "2016-06-22T22:24:20Z",
+  "name": "foo",
+  "common_name": "bar.com",
+  "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+  "expires": "2017-01-14T23:57:57Z",
+  "starts": "2016-01-15T23:57:57Z",
+  "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+  "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+}
+

Destroy a Certificate

+

Example Request:

+
DELETE /v2/certs/foo HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Attach a Domain to a Certificate

+

Example Request:

+
POST /v2/certs/foo/domain/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "domain": "test.com"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Remove a Domain from a Certificate

+

Example Request:

+
DELETE /v2/certs/foo/domain/test.com/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Pods

+

List all Pods

+

Example Request:

+
GET /v2/apps/example-go/pods/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "results": [
+        {
+            "name": "go-v2-web-e7dej",
+            "release": "v2",
+            "started": "2014-01-01T00:00:00Z",
+            "state": "up",
+            "type": "web"
+        }
+    ]
+}
+

List all Pods by Type

+

Example Request:

+
GET /v2/apps/example-go/pods/web/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "results": [
+        {
+            "name": "go-v2-web-e7dej",
+            "release": "v2",
+            "started": "2014-01-01T00:00:00Z",
+            "state": "up",
+            "type": "web"
+        }
+    ]
+}
+

Restart All Pods

+

Example Request:

+
POST /v2/apps/example-go/pods/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Restart Pods by Type

+

Example Request:

+
POST /v2/apps/example-go/pods/web/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Restart Pods by Type and Name

+

Example Request:

+
POST /v2/apps/example-go/pods/go-v2-web-atots/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Scale Pods

+

Example Request:

+
POST /v2/apps/example-go/scale/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"web": 3}
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Configuration

+

List Application Configuration

+

Example Request:

+
GET /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+      "PLATFORM": "drycc"
+    },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Create new Config

+

Example Request:

+
POST /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"values": {"HELLO": "world", "PLATFORM": "drycc"}}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+        "DRYCC_APP": "example-go",
+        "DRYCC_RELEASE": "v3",
+        "HELLO": "world",
+        "PLATFORM": "drycc"
+
+    },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Unset Config Variable

+

Example Request:

+
POST /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"values": {"HELLO": null}}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+        "DRYCC_APP": "example-go",
+        "DRYCC_RELEASE": "v4",
+        "PLATFORM": "drycc"
+   },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Domains

+

List Application Domains

+

Example Request:

+
GET /v2/apps/example-go/domains/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "app": "example-go",
+            "created": "2014-01-01T00:00:00UTC",
+            "domain": "example.example.com",
+            "owner": "test",
+            "updated": "2014-01-01T00:00:00UTC"
+        }
+    ]
+}
+

Add Domain

+

Example Request:

+
POST /v2/apps/example-go/domains/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{'domain': 'example.example.com'}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "domain": "example.example.com",
+    "owner": "test",
+    "updated": "2014-01-01T00:00:00UTC"
+}
+

Remove Domain

+

Example Request:

+
DELETE /v2/apps/example-go/domains/example.example.com HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Builds

+

List Application Builds

+

Example Request:

+
GET /v2/apps/example-go/build/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "dockerfile": "FROM drycc/slugrunner RUN mkdir -p /app WORKDIR /app ENTRYPOINT [\"/runner/init\"] ADD slug.tgz /app ENV GIT_SHA 060da68f654e75fac06dbedd1995d5f8ad9084db",
+    "image": "example-go",
+    "owner": "test",
+    "procfile": {
+        "web": "example-go"
+    },
+    "sha": "060da68f",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Create Application Build

+

Example Request:

+
POST /v2/apps/example-go/build/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"image": "drycc/example-go:latest"}
+

Optional Parameters:

+
{
+    "procfile": {
+      "web": "./cmd"
+    }
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "dockerfile": "",
+    "image": "drycc/example-go:latest",
+    "owner": "test",
+    "procfile": {},
+    "sha": "",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Releases

+

List Application Releases

+

Example Request:

+
GET /v2/apps/example-go/releases/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 3,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "app": "example-go",
+            "build": "202d8e4b-600e-4425-a85c-ffc7ea607f61",
+            "config": "ed637ceb-5d32-44bd-9406-d326a777a513",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test changed nothing",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 3
+        },
+        {
+            "app": "example-go",
+            "build": "202d8e4b-600e-4425-a85c-ffc7ea607f61",
+            "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test deployed 060da68",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 2
+        },
+        {
+            "app": "example-go",
+            "build": null,
+            "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test created initial release",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 1
+        }
+    ]
+}
+

List Release Details

+

Example Request:

+
GET /v2/apps/example-go/releases/v2/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "build": null,
+    "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+    "created": "2014-01-01T00:00:00UTC",
+    "owner": "test",
+    "summary": "test created initial release",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+    "version": 1
+}
+

Rollback Release

+

Example Request:

+
POST /v2/apps/example-go/releases/rollback/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"version": 1}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{"version": 5}
+

Keys

+

List Keys

+

Example Request:

+
GET /v2/keys/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "created": "2014-01-01T00:00:00UTC",
+            "id": "test@example.com",
+            "owner": "test",
+            "public": "ssh-rsa <...>",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+        }
+    ]
+}
+

Add Key to User

+

Example Request:

+
POST /v2/keys/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "id": "example",
+    "public": "ssh-rsa <...>"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example",
+    "owner": "example",
+    "public": "ssh-rsa <...>",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Remove Key from User

+

Example Request:

+
DELETE /v2/keys/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Permissions

+

List Application Permissions

+
+

note

+

This does not include the app owner.

+
+

Example Request:

+
GET /v2/apps/example-go/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "users": [
+        "test",
+        "foo"
+    ]
+}
+

Create Application Permission

+

Example Request:

+
POST /v2/apps/example-go/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{"username": "example"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Remove Application Permission

+

Example Request:

+
DELETE /v2/apps/example-go/perms/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

List Administrators

+

Example Request:

+
GET /v2/admin/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 2,
+    "next": null
+    "previous": null,
+    "results": [
+        {
+            "username": "test",
+            "is_superuser": true
+        },
+        {
+            "username": "foo",
+            "is_superuser": true
+        }
+    ]
+}
+

Grant User Administrative Privileges

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
POST /v2/admin/perms HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{"username": "example"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Remove User’s Administrative Privileges

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
DELETE /v2/admin/perms/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+

Users

+

List all users

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
GET /v2/users HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.1
+DRYCC_PLATFORM_VERSION: 2.1.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "id": 1,
+            "last_login": "2014-10-19T22:01:00.601Z",
+            "is_superuser": true,
+            "username": "test",
+            "first_name": "test",
+            "last_name": "testerson",
+            "email": "test@example.com",
+            "is_staff": true,
+            "is_active": true,
+            "date_joined": "2014-10-19T22:01:00.601Z",
+            "groups": [],
+            "user_permissions": []
+        }
+    ]
+}
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/reference-guide/controller-api-v2-2/index.html b/docs/reference-guide/controller-api-v2-2/index.html new file mode 100644 index 000000000..570c383d1 --- /dev/null +++ b/docs/reference-guide/controller-api-v2-2/index.html @@ -0,0 +1,1523 @@ + + + + + + + + + + + + + + + + + + + +Controller API v2.2 | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Controller API v2.2

+
This is the v2.2 REST API for the Controller.
+ +

What’s New

+

New! /v2/auth/whoami endpoint

+

Authentication

+

Register a New User

+

Example Request:

+
POST /v2/auth/register/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+
+{
+    "username": "test",
+    "password": "opensesame",
+    "email": "test@example.com"
+}
+

Optional Parameters:

+
{
+    "first_name": "test",
+    "last_name": "testerson"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "id": 1,
+    "last_login": "2014-10-19T22:01:00.601Z",
+    "is_superuser": true,
+    "username": "test",
+    "first_name": "test",
+    "last_name": "testerson",
+    "email": "test@example.com",
+    "is_staff": true,
+    "is_active": true,
+    "date_joined": "2014-10-19T22:01:00.601Z",
+    "groups": [],
+    "user_permissions": []
+}
+

Log in

+

Example Request:

+
POST /v2/auth/login/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+
+{"username": "test", "password": "opensesame"}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{"token": "abc123"}
+

Cancel Account

+

Example Request:

+
DELETE /v2/auth/cancel/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Who Am I

+

Example Request:

+
GET /v2/auth/whoami/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "id": 1,
+    "last_login": "2014-10-19T22:01:00.601Z",
+    "is_superuser": true,
+    "username": "test",
+    "first_name": "test",
+    "last_name": "testerson",
+    "email": "test@example.com",
+    "is_staff": true,
+    "is_active": true,
+    "date_joined": "2014-10-19T22:01:00.601Z",
+    "groups": [],
+    "user_permissions": []
+}
+

Regenerate Token

+
+

note

+

This command could require administrative privileges

+
+

Example Request:

+
POST /v2/auth/tokens/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional Parameters:

+
{
+    "username" : "test"
+    "all" : "true"
+}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{"token": "abc123"}
+

Change Password

+

Example Request:

+
POST /v2/auth/passwd/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "password": "foo",
+    "new_password": "bar"
+}
+

Optional parameters:

+
{"username": "testuser"}
+
+

note

+

Using the username parameter requires administrative privileges and makes the password parameter optional.

+
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Applications

+

List all Applications

+

Example Request:

+
GET /v2/apps HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "created": "2014-01-01T00:00:00UTC",
+            "id": "example-go",
+            "owner": "test",
+            "structure": {},
+            "updated": "2014-01-01T00:00:00UTC",
+            "url": "example-go.example.com",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+        }
+    ]
+}
+

Create an Application

+

Example Request:

+
POST /v2/apps/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+

Optional parameters:

+
{"id": "example-go"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example-go",
+    "owner": "test",
+    "structure": {},
+    "updated": "2014-01-01T00:00:00UTC",
+    "url": "example-go.example.com",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Destroy an Application

+

Example Request:

+
DELETE /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

List Application Details

+

Example Request:

+
GET /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example-go",
+    "owner": "test",
+    "structure": {},
+    "updated": "2014-01-01T00:00:00UTC",
+    "url": "example-go.example.com",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Update Application Details

+

Example Request:

+
POST /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional parameters:

+
{
+  "owner": "test"
+}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 1.8.0
+Content-Type: application/json
+

Retrieve Application Logs

+

Example Request:

+
GET /v2/apps/example-go/logs/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional URL Query Parameters:

+
?log_lines=
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: text/plain
+
+"16:51:14 drycc[api]: test created initial release\n"
+

Run one-off Commands

+
POST /v2/apps/example-go/run/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"command": "echo hi"}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{"exit_code": 0, "output": "hi\n"}
+

Certificates

+

List all Certificates

+

Example Request:

+
GET /v2/certs HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+  "count": 1,
+  "next": null,
+  "previous": null,
+  "results": [
+    {
+      "id": 22,
+      "owner": "test",
+      "san": [],
+      "domains": [],
+      "created": "2016-06-22T22:24:20Z",
+      "updated": "2016-06-22T22:24:20Z",
+      "name": "foo",
+      "common_name": "bar.com",
+      "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+      "expires": "2017-01-14T23:57:57Z",
+      "starts": "2016-01-15T23:57:57Z",
+      "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+      "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+    }
+  ]
+}
+

Get Certificate Details

+

Example Request:

+
GET /v2/certs/foo HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+  "id": 22,
+  "owner": "test",
+  "san": [],
+  "domains": [],
+  "created": "2016-06-22T22:24:20Z",
+  "updated": "2016-06-22T22:24:20Z",
+  "name": "foo",
+  "common_name": "bar.com",
+  "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+  "expires": "2017-01-14T23:57:57Z",
+  "starts": "2016-01-15T23:57:57Z",
+  "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+  "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+}
+

Create Certificate

+

Example Request:

+
POST /v2/certs/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{
+    "name": "foo"
+    "certificate": "-----BEGIN CERTIFICATE-----",
+    "key": "-----BEGIN RSA PRIVATE KEY-----"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+  "id": 22,
+  "owner": "test",
+  "san": [],
+  "domains": [],
+  "created": "2016-06-22T22:24:20Z",
+  "updated": "2016-06-22T22:24:20Z",
+  "name": "foo",
+  "common_name": "bar.com",
+  "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+  "expires": "2017-01-14T23:57:57Z",
+  "starts": "2016-01-15T23:57:57Z",
+  "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+  "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+}
+

Destroy a Certificate

+

Example Request:

+
DELETE /v2/certs/foo HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Attach a Domain to a Certificate

+

Example Request:

+
POST /v2/certs/foo/domain/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "domain": "test.com"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Remove a Domain from a Certificate

+

Example Request:

+
DELETE /v2/certs/foo/domain/test.com/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Pods

+

List all Pods

+

Example Request:

+
GET /v2/apps/example-go/pods/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "results": [
+        {
+            "name": "go-v2-web-e7dej",
+            "release": "v2",
+            "started": "2014-01-01T00:00:00Z",
+            "state": "up",
+            "type": "web"
+        }
+    ]
+}
+

List all Pods by Type

+

Example Request:

+
GET /v2/apps/example-go/pods/web/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "results": [
+        {
+            "name": "go-v2-web-e7dej",
+            "release": "v2",
+            "started": "2014-01-01T00:00:00Z",
+            "state": "up",
+            "type": "web"
+        }
+    ]
+}
+

Restart All Pods

+

Example Request:

+
POST /v2/apps/example-go/pods/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Restart Pods by Type

+

Example Request:

+
POST /v2/apps/example-go/pods/web/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Restart Pods by Type and Name

+

Example Request:

+
POST /v2/apps/example-go/pods/go-v2-web-atots/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Scale Pods

+

Example Request:

+
POST /v2/apps/example-go/scale/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"web": 3}
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Configuration

+

List Application Configuration

+

Example Request:

+
GET /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+      "PLATFORM": "drycc"
+    },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Create new Config

+

Example Request:

+
POST /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"values": {"HELLO": "world", "PLATFORM": "drycc"}}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+        "DRYCC_APP": "example-go",
+        "DRYCC_RELEASE": "v3",
+        "HELLO": "world",
+        "PLATFORM": "drycc"
+
+    },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Unset Config Variable

+

Example Request:

+
POST /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"values": {"HELLO": null}}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+        "DRYCC_APP": "example-go",
+        "DRYCC_RELEASE": "v4",
+        "PLATFORM": "drycc"
+   },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Domains

+

List Application Domains

+

Example Request:

+
GET /v2/apps/example-go/domains/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "app": "example-go",
+            "created": "2014-01-01T00:00:00UTC",
+            "domain": "example.example.com",
+            "owner": "test",
+            "updated": "2014-01-01T00:00:00UTC"
+        }
+    ]
+}
+

Add Domain

+

Example Request:

+
POST /v2/apps/example-go/domains/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{'domain': 'example.example.com'}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "domain": "example.example.com",
+    "owner": "test",
+    "updated": "2014-01-01T00:00:00UTC"
+}
+

Remove Domain

+

Example Request:

+
DELETE /v2/apps/example-go/domains/example.example.com HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Builds

+

List Application Builds

+

Example Request:

+
GET /v2/apps/example-go/build/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "dockerfile": "FROM drycc/slugrunner RUN mkdir -p /app WORKDIR /app ENTRYPOINT [\"/runner/init\"] ADD slug.tgz /app ENV GIT_SHA 060da68f654e75fac06dbedd1995d5f8ad9084db",
+    "image": "example-go",
+    "owner": "test",
+    "procfile": {
+        "web": "example-go"
+    },
+    "sha": "060da68f",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Create Application Build

+

Example Request:

+
POST /v2/apps/example-go/build/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"image": "drycc/example-go:latest"}
+

Optional Parameters:

+
{
+    "procfile": {
+      "web": "./cmd"
+    }
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "dockerfile": "",
+    "image": "drycc/example-go:latest",
+    "owner": "test",
+    "procfile": {},
+    "sha": "",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Releases

+

List Application Releases

+

Example Request:

+
GET /v2/apps/example-go/releases/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "count": 3,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "app": "example-go",
+            "build": "202d8e4b-600e-4425-a85c-ffc7ea607f61",
+            "config": "ed637ceb-5d32-44bd-9406-d326a777a513",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test changed nothing",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 3
+        },
+        {
+            "app": "example-go",
+            "build": "202d8e4b-600e-4425-a85c-ffc7ea607f61",
+            "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test deployed 060da68",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 2
+        },
+        {
+            "app": "example-go",
+            "build": null,
+            "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test created initial release",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 1
+        }
+    ]
+}
+

List Release Details

+

Example Request:

+
GET /v2/apps/example-go/releases/v2/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "build": null,
+    "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+    "created": "2014-01-01T00:00:00UTC",
+    "owner": "test",
+    "summary": "test created initial release",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+    "version": 1
+}
+

Rollback Release

+

Example Request:

+
POST /v2/apps/example-go/releases/rollback/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"version": 1}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{"version": 5}
+

Keys

+

List Keys

+

Example Request:

+
GET /v2/keys/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "created": "2014-01-01T00:00:00UTC",
+            "id": "test@example.com",
+            "owner": "test",
+            "public": "ssh-rsa <...>",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+        }
+    ]
+}
+

Add Key to User

+

Example Request:

+
POST /v2/keys/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "id": "example",
+    "public": "ssh-rsa <...>"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example",
+    "owner": "example",
+    "public": "ssh-rsa <...>",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Remove Key from User

+

Example Request:

+
DELETE /v2/keys/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Permissions

+

List Application Permissions

+
+

note

+

This does not include the app owner.

+
+

Example Request:

+
GET /v2/apps/example-go/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "users": [
+        "test",
+        "foo"
+    ]
+}
+

Create Application Permission

+

Example Request:

+
POST /v2/apps/example-go/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{"username": "example"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Remove Application Permission

+

Example Request:

+
DELETE /v2/apps/example-go/perms/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

List Administrators

+

Example Request:

+
GET /v2/admin/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "count": 2,
+    "next": null
+    "previous": null,
+    "results": [
+        {
+            "username": "test",
+            "is_superuser": true
+        },
+        {
+            "username": "foo",
+            "is_superuser": true
+        }
+    ]
+}
+

Grant User Administrative Privileges

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
POST /v2/admin/perms HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{"username": "example"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Remove User’s Administrative Privileges

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
DELETE /v2/admin/perms/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+

Users

+

List all users

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
GET /v2/users HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.2
+DRYCC_PLATFORM_VERSION: 2.2.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "id": 1,
+            "last_login": "2014-10-19T22:01:00.601Z",
+            "is_superuser": true,
+            "username": "test",
+            "first_name": "test",
+            "last_name": "testerson",
+            "email": "test@example.com",
+            "is_staff": true,
+            "is_active": true,
+            "date_joined": "2014-10-19T22:01:00.601Z",
+            "groups": [],
+            "user_permissions": []
+        }
+    ]
+}
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/reference-guide/controller-api-v2-3/index.html b/docs/reference-guide/controller-api-v2-3/index.html new file mode 100644 index 000000000..9e3ebb4dc --- /dev/null +++ b/docs/reference-guide/controller-api-v2-3/index.html @@ -0,0 +1,1568 @@ + + + + + + + + + + + + + + + + + + + +Controller API v2.3 | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Controller API v2.3

+
This is the v2.3 REST API for the Controller.
+ +

What’s New

+

New! /v2/apps/{name}/logs endpoint was fixed and no longer returns b'log data' and instead returns a normal string log data

+

Authentication

+

Register a New User

+

Example Request:

+
POST /v2/auth/register/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+
+{
+    "username": "test",
+    "password": "opensesame",
+    "email": "test@example.com"
+}
+

Optional Parameters:

+
{
+    "first_name": "test",
+    "last_name": "testerson"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "id": 1,
+    "last_login": "2014-10-19T22:01:00.601Z",
+    "is_superuser": true,
+    "username": "test",
+    "first_name": "test",
+    "last_name": "testerson",
+    "email": "test@example.com",
+    "is_staff": true,
+    "is_active": true,
+    "date_joined": "2014-10-19T22:01:00.601Z",
+    "groups": [],
+    "user_permissions": []
+}
+

Log in

+

Example Request:

+
POST /v2/auth/login/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+
+{"username": "test", "password": "opensesame"}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{"token": "abc123"}
+

Cancel Account

+

Example Request:

+
DELETE /v2/auth/cancel/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Who Am I

+

Example Request:

+
GET /v2/auth/whoami/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "id": 1,
+    "last_login": "2014-10-19T22:01:00.601Z",
+    "is_superuser": true,
+    "username": "test",
+    "first_name": "test",
+    "last_name": "testerson",
+    "email": "test@example.com",
+    "is_staff": true,
+    "is_active": true,
+    "date_joined": "2014-10-19T22:01:00.601Z",
+    "groups": [],
+    "user_permissions": []
+}
+

Regenerate Token

+
+

note

+

This command could require administrative privileges

+
+

Example Request:

+
POST /v2/auth/tokens/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional Parameters:

+
{
+    "username" : "test"
+    "all" : "true"
+}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{"token": "abc123"}
+

Change Password

+

Example Request:

+
POST /v2/auth/passwd/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "password": "foo",
+    "new_password": "bar"
+}
+

Optional parameters:

+
{"username": "testuser"}
+
+

note

+

Using the username parameter requires administrative privileges and makes the password parameter optional.

+
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Applications

+

List all Applications

+

Example Request:

+
GET /v2/apps HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "created": "2014-01-01T00:00:00UTC",
+            "id": "example-go",
+            "owner": "test",
+            "structure": {},
+            "updated": "2014-01-01T00:00:00UTC",
+            "url": "example-go.example.com",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+        }
+    ]
+}
+

Create an Application

+

Example Request:

+
POST /v2/apps/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+

Optional parameters:

+
{"id": "example-go"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example-go",
+    "owner": "test",
+    "structure": {},
+    "updated": "2014-01-01T00:00:00UTC",
+    "url": "example-go.example.com",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Destroy an Application

+

Example Request:

+
DELETE /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

List Application Details

+

Example Request:

+
GET /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example-go",
+    "owner": "test",
+    "structure": {},
+    "updated": "2014-01-01T00:00:00UTC",
+    "url": "example-go.example.com",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Update Application Details

+

Example Request:

+
POST /v2/apps/example-go/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional parameters:

+
{
+  "owner": "test"
+}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 1.8.0
+Content-Type: application/json
+

Retrieve Application Logs

+

Example Request:

+
GET /v2/apps/example-go/logs/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Optional URL Query Parameters:

+
?log_lines=
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: text/plain
+
+"16:51:14 drycc[api]: test created initial release\n"
+

Run one-off Commands

+
POST /v2/apps/example-go/run/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"command": "echo hi"}
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{"exit_code": 0, "output": "hi\n"}
+

Certificates

+

List all Certificates

+

Example Request:

+
GET /v2/certs HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+  "count": 1,
+  "next": null,
+  "previous": null,
+  "results": [
+    {
+      "id": 22,
+      "owner": "test",
+      "san": [],
+      "domains": [],
+      "created": "2016-06-22.32.34:20Z",
+      "updated": "2016-06-22.32.34:20Z",
+      "name": "foo",
+      "common_name": "bar.com",
+      "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+      "expires": "2017-01-14T23:57:57Z",
+      "starts": "2016-01-15T23:57:57Z",
+      "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+      "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+    }
+  ]
+}
+

Get Certificate Details

+

Example Request:

+
GET /v2/certs/foo HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+  "id": 22,
+  "owner": "test",
+  "san": [],
+  "domains": [],
+  "created": "2016-06-22.32.34:20Z",
+  "updated": "2016-06-22.32.34:20Z",
+  "name": "foo",
+  "common_name": "bar.com",
+  "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+  "expires": "2017-01-14T23:57:57Z",
+  "starts": "2016-01-15T23:57:57Z",
+  "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+  "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+}
+

Create Certificate

+

Example Request:

+
POST /v2/certs/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{
+    "name": "foo"
+    "certificate": "-----BEGIN CERTIFICATE-----",
+    "key": "-----BEGIN RSA PRIVATE KEY-----"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+  "id": 22,
+  "owner": "test",
+  "san": [],
+  "domains": [],
+  "created": "2016-06-22.32.34:20Z",
+  "updated": "2016-06-22.32.34:20Z",
+  "name": "foo",
+  "common_name": "bar.com",
+  "fingerprint": "7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0",
+  "expires": "2017-01-14T23:57:57Z",
+  "starts": "2016-01-15T23:57:57Z",
+  "issuer": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc",
+  "subject": "/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc"
+}
+

Destroy a Certificate

+

Example Request:

+
DELETE /v2/certs/foo HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Attach a Domain to a Certificate

+

Example Request:

+
POST /v2/certs/foo/domain/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "domain": "test.com"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Remove a Domain from a Certificate

+

Example Request:

+
DELETE /v2/certs/foo/domain/test.com/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Enable or disable TLS

+

Example Request:

+
POST /v2/apps/example-go/tls/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{
+  "https_enforced": true
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "app": "example-go",
+    "owner": "test",
+    "https_enforced": true,
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Get TLS status

+

Example Request:

+
GET /v2/apps/example-go/tls/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "app": "example-go",
+    "owner": "test",
+    "https_enforced": false,
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Pods

+

List all Pods

+

Example Request:

+
GET /v2/apps/example-go/pods/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "results": [
+        {
+            "name": "go-v2-web-e7dej",
+            "release": "v2",
+            "started": "2014-01-01T00:00:00Z",
+            "state": "up",
+            "type": "web"
+        }
+    ]
+}
+

List all Pods by Type

+

Example Request:

+
GET /v2/apps/example-go/pods/web/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "results": [
+        {
+            "name": "go-v2-web-e7dej",
+            "release": "v2",
+            "started": "2014-01-01T00:00:00Z",
+            "state": "up",
+            "type": "web"
+        }
+    ]
+}
+

Restart All Pods

+

Example Request:

+
POST /v2/apps/example-go/pods/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Restart Pods by Type

+

Example Request:

+
POST /v2/apps/example-go/pods/web/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Restart Pods by Type and Name

+

Example Request:

+
POST /v2/apps/example-go/pods/go-v2-web-atots/restart/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+[
+    {
+        "name": "go-v2-web-atots",
+        "release": "v2",
+        "started": "2016-04-11T21:07:54Z",
+        "state": "up",
+        "type": "web"
+    }
+]
+

Scale Pods

+

Example Request:

+
POST /v2/apps/example-go/scale/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"web": 3}
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Configuration

+

List Application Configuration

+

Example Request:

+
GET /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+      "PLATFORM": "drycc"
+    },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Create new Config

+

Example Request:

+
POST /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"values": {"HELLO": "world", "PLATFORM": "drycc"}}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+        "DRYCC_APP": "example-go",
+        "DRYCC_RELEASE": "v3",
+        "HELLO": "world",
+        "PLATFORM": "drycc"
+
+    },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Unset Config Variable

+

Example Request:

+
POST /v2/apps/example-go/config/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"values": {"HELLO": null}}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "owner": "test",
+    "app": "example-go",
+    "values": {
+        "DRYCC_APP": "example-go",
+        "DRYCC_RELEASE": "v4",
+        "PLATFORM": "drycc"
+   },
+    "memory": {},
+    "cpu": {},
+    "tags": {},
+    "healthcheck": {},
+    "created": "2014-01-01T00:00:00UTC",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Domains

+

List Application Domains

+

Example Request:

+
GET /v2/apps/example-go/domains/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "app": "example-go",
+            "created": "2014-01-01T00:00:00UTC",
+            "domain": "example.example.com",
+            "owner": "test",
+            "updated": "2014-01-01T00:00:00UTC"
+        }
+    ]
+}
+

Add Domain

+

Example Request:

+
POST /v2/apps/example-go/domains/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{'domain': 'example.example.com'}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "domain": "example.example.com",
+    "owner": "test",
+    "updated": "2014-01-01T00:00:00UTC"
+}
+

Remove Domain

+

Example Request:

+
DELETE /v2/apps/example-go/domains/example.example.com HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Builds

+

List Application Builds

+

Example Request:

+
GET /v2/apps/example-go/build/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "dockerfile": "FROM drycc/slugrunner RUN mkdir -p /app WORKDIR /app ENTRYPOINT [\"/runner/init\"] ADD slug.tgz /app ENV GIT_SHA 060da68f654e75fac06dbedd1995d5f8ad9084db",
+    "image": "example-go",
+    "owner": "test",
+    "procfile": {
+        "web": "example-go"
+    },
+    "sha": "060da68f",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Create Application Build

+

Example Request:

+
POST /v2/apps/example-go/build/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"image": "drycc/example-go:latest"}
+

Optional Parameters:

+
{
+    "procfile": {
+      "web": "./cmd"
+    }
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "created": "2014-01-01T00:00:00UTC",
+    "dockerfile": "",
+    "image": "drycc/example-go:latest",
+    "owner": "test",
+    "procfile": {},
+    "sha": "",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Releases

+

List Application Releases

+

Example Request:

+
GET /v2/apps/example-go/releases/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "count": 3,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "app": "example-go",
+            "build": "2.3d8e4b-600e-4425-a85c-ffc7ea607f61",
+            "config": "ed637ceb-5d32-44bd-9406-d326a777a513",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test changed nothing",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 3
+        },
+        {
+            "app": "example-go",
+            "build": "2.3d8e4b-600e-4425-a85c-ffc7ea607f61",
+            "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test deployed 060da68",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 2
+        },
+        {
+            "app": "example-go",
+            "build": null,
+            "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+            "created": "2014-01-01T00:00:00UTC",
+            "owner": "test",
+            "summary": "test created initial release",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+            "version": 1
+        }
+    ]
+}
+

List Release Details

+

Example Request:

+
GET /v2/apps/example-go/releases/v2/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "app": "example-go",
+    "build": null,
+    "config": "95bd6dea-1685-4f78-a03d-fd7270b058d1",
+    "created": "2014-01-01T00:00:00UTC",
+    "owner": "test",
+    "summary": "test created initial release",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
+    "version": 1
+}
+

Rollback Release

+

Example Request:

+
POST /v2/apps/example-go/releases/rollback/ HTTP/1.1
+Host: drycc.example.com
+Content-Type: application/json
+Authorization: token abc123
+
+{"version": 1}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{"version": 5}
+

Keys

+

List Keys

+

Example Request:

+
GET /v2/keys/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "created": "2014-01-01T00:00:00UTC",
+            "id": "test@example.com",
+            "owner": "test",
+            "public": "ssh-rsa <...>",
+            "updated": "2014-01-01T00:00:00UTC",
+            "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+        }
+    ]
+}
+

Add Key to User

+

Example Request:

+
POST /v2/keys/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{
+    "id": "example",
+    "public": "ssh-rsa <...>"
+}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "created": "2014-01-01T00:00:00UTC",
+    "id": "example",
+    "owner": "example",
+    "public": "ssh-rsa <...>",
+    "updated": "2014-01-01T00:00:00UTC",
+    "uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
+}
+

Remove Key from User

+

Example Request:

+
DELETE /v2/keys/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Permissions

+

List Application Permissions

+
+

note

+

This does not include the app owner.

+
+

Example Request:

+
GET /v2/apps/example-go/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "users": [
+        "test",
+        "foo"
+    ]
+}
+

Create Application Permission

+

Example Request:

+
POST /v2/apps/example-go/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{"username": "example"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Remove Application Permission

+

Example Request:

+
DELETE /v2/apps/example-go/perms/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

List Administrators

+

Example Request:

+
GET /v2/admin/perms/ HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "count": 2,
+    "next": null
+    "previous": null,
+    "results": [
+        {
+            "username": "test",
+            "is_superuser": true
+        },
+        {
+            "username": "foo",
+            "is_superuser": true
+        }
+    ]
+}
+

Grant User Administrative Privileges

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
POST /v2/admin/perms HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+
+{"username": "example"}
+

Example Response:

+
HTTP/1.1 201 CREATED
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Remove User’s Administrative Privileges

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
DELETE /v2/admin/perms/example HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 204 NO CONTENT
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+

Users

+

List all users

+
+

note

+

This command requires administrative privileges

+
+

Example Request:

+
GET /v2/users HTTP/1.1
+Host: drycc.example.com
+Authorization: token abc123
+

Example Response:

+
HTTP/1.1 200 OK
+DRYCC_API_VERSION: 2.3
+DRYCC_PLATFORM_VERSION: 2.3.0
+Content-Type: application/json
+
+{
+    "count": 1,
+    "next": null,
+    "previous": null,
+    "results": [
+        {
+            "id": 1,
+            "last_login": "2014-10-19T22:01:00.601Z",
+            "is_superuser": true,
+            "username": "test",
+            "first_name": "test",
+            "last_name": "testerson",
+            "email": "test@example.com",
+            "is_staff": true,
+            "is_active": true,
+            "date_joined": "2014-10-19T22:01:00.601Z",
+            "groups": [],
+            "user_permissions": []
+        }
+    ]
+}
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/reference-guide/creating-a-self-signed-ssl-certificate/index.html b/docs/reference-guide/creating-a-self-signed-ssl-certificate/index.html new file mode 100644 index 000000000..4458a1a66 --- /dev/null +++ b/docs/reference-guide/creating-a-self-signed-ssl-certificate/index.html @@ -0,0 +1,510 @@ + + + + + + + + + + + + + + + + + + + +Creating a Self-Signed SSL Certificate | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Creating a Self-Signed SSL Certificate

+
A self-signed TLS/SSL certificate is not signed by a publicly trusted certificate authority (CA) but instead by the developer or company that is responsible for the website.
+ +

When using the app ssl feature for non-production applications or when installing SSL for the platform, you can avoid the costs associated with the SSL certificate by using a self-signed SSL certificate. Though the certificate implements full encryption, visitors to your site will see a browser warning indicating that the certificate should not be trusted.

+

Prerequisites

+

The openssl library is required to generate your own certificate. Run the following command in your local environment to see if you already have openssl installed.

+
$ which openssl
+/usr/bin/openssl
+
+

If the which command does not return a path then you will need to install openssl yourself:

+ + + + + + + + + + + + + + + + + + + + + +
If you have…Install with…
Mac OS XHomebrew: brew install openssl
Windowscomplete package .exe installed
Ubuntu Linuxapt-get install openssl
+

Generate Private Key and Certificate Signing Request

+

A private key and certificate signing request are required to create an SSL certificate. These can be generated with a few simple commands. When the openssl req command asks for a “challenge password”, just press return, leaving the password empty.

+
$ openssl genrsa -des3 -passout pass:x -out server.pass.key 2048
+...
+$ openssl rsa -passin pass:x -in server.pass.key -out server.key
+writing RSA key
+$ rm server.pass.key
+$ openssl req -new -key server.key -out server.csr
+...
+Country Name (2 letter code) [AU]:US
+State or Province Name (full name) [Some-State]:California
+...
+A challenge password []:
+...
+
+

Generate SSL Certificate

+

The self-signed SSL certificate is generated from the server.key private key and server.csr files.

+
$ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
+
+

The server.crt file is your site certificate suitable for use with Drycc’s SSL endpoint along with the server.key private key.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/reference-guide/index.html b/docs/reference-guide/index.html new file mode 100644 index 000000000..9106e1f1a --- /dev/null +++ b/docs/reference-guide/index.html @@ -0,0 +1,484 @@ + + + + + + + + + + + + + + + + + + + + + +Reference Guide | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Reference Guide

+
Reference gxwuide definition and meaning.
+ + +
+ + +
+
+
+ Creating a Self-Signed SSL Certificate +
+

A self-signed TLS/SSL certificate is not signed by a publicly trusted certificate authority (CA) but instead by the developer or company that is responsible for the website.

+
+
+
+ Controller API v2.0 +
+

This is the v2.0 REST API for the Controller.

+
+
+
+ Controller API v2.1 +
+

This is the v2.1 REST API for the Controller.

+
+
+
+ Controller API v2.2 +
+

This is the v2.2 REST API for the Controller.

+
+
+
+ Controller API v2.3 +
+

This is the v2.3 REST API for the Controller.

+
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+
+ +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/reference-guide/index.xml b/docs/reference-guide/index.xml new file mode 100644 index 000000000..f5aaf3ac1 --- /dev/null +++ b/docs/reference-guide/index.xml @@ -0,0 +1,4026 @@ + + + Drycc – Reference Guide + /docs/reference-guide/ + Recent content in Reference Guide on Drycc + Hugo -- gohugo.io + en + + + + + + + + + + + Docs: Creating a Self-Signed SSL Certificate + /docs/reference-guide/creating-a-self-signed-ssl-certificate/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/reference-guide/creating-a-self-signed-ssl-certificate/ + + + + <p>When <a href="/docs/applications/ssl-certificates/">using the app ssl</a> feature for non-production applications or when <a href="https://gateway-api.sigs.k8s.io/guides/tls/">installing SSL for the platform</a>, you can avoid the costs associated with the SSL certificate by using a self-signed SSL certificate. Though the certificate implements full encryption, visitors to your site will see a browser warning indicating that the certificate should not be trusted.</p> +<h2 id="prerequisites">Prerequisites<a class="td-heading-self-link" href="#prerequisites" aria-label="Heading self-link"></a></h2> +<p>The openssl library is required to generate your own certificate. Run the following command in your local environment to see if you already have openssl installed.</p> +<pre><code>$ which openssl +/usr/bin/openssl +</code></pre> +<p>If the which command does not return a path then you will need to install openssl yourself:</p> +<table> +<thead> +<tr> +<th>If you have&hellip;</th> +<th>Install with&hellip;</th> +</tr> +</thead> +<tbody> +<tr> +<td>Mac OS X</td> +<td>Homebrew: <code>brew install openssl</code></td> +</tr> +<tr> +<td>Windows</td> +<td>complete package .exe installed</td> +</tr> +<tr> +<td>Ubuntu Linux</td> +<td><code>apt-get install openssl</code></td> +</tr> +</tbody> +</table> +<h2 id="generate-private-key-and-certificate-signing-request">Generate Private Key and Certificate Signing Request<a class="td-heading-self-link" href="#generate-private-key-and-certificate-signing-request" aria-label="Heading self-link"></a></h2> +<p>A private key and certificate signing request are required to create an SSL certificate. These can be generated with a few simple commands. When the openssl req command asks for a “challenge password”, just press return, leaving the password empty.</p> +<pre><code>$ openssl genrsa -des3 -passout pass:x -out server.pass.key 2048 +... +$ openssl rsa -passin pass:x -in server.pass.key -out server.key +writing RSA key +$ rm server.pass.key +$ openssl req -new -key server.key -out server.csr +... +Country Name (2 letter code) [AU]:US +State or Province Name (full name) [Some-State]:California +... +A challenge password []: +... +</code></pre> +<h2 id="generate-ssl-certificate">Generate SSL Certificate<a class="td-heading-self-link" href="#generate-ssl-certificate" aria-label="Heading self-link"></a></h2> +<p>The self-signed SSL certificate is generated from the server.key private key and server.csr files.</p> +<pre><code>$ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt +</code></pre> +<p>The server.crt file is your site certificate suitable for use with <a href="/docs/applications/ssl-certificates/">Drycc&rsquo;s SSL endpoint</a> along with the server.key private key.</p> + + + + + + Docs: Controller API v2.0 + /docs/reference-guide/controller-api-v2-0/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/reference-guide/controller-api-v2-0/ + + + + <h2 id="whats-new">What&rsquo;s New<a class="td-heading-self-link" href="#whats-new" aria-label="Heading self-link"></a></h2> +<p><strong>New!</strong> format of <code>POST /v2/apps/&lt;app id&gt;/run</code> has changed.</p> +<h2 id="authentication">Authentication<a class="td-heading-self-link" href="#authentication" aria-label="Heading self-link"></a></h2> +<h3 id="register-a-new-user">Register a New User<a class="td-heading-self-link" href="#register-a-new-user" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/register/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json + +{ + &#34;username&#34;: &#34;test&#34;, + &#34;password&#34;: &#34;opensesame&#34;, + &#34;email&#34;: &#34;test@example.com&#34; +} +</code></pre><p>Optional Parameters:</p> +<pre tabindex="0"><code>{ + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;id&#34;: 1, + &#34;last_login&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;is_superuser&#34;: true, + &#34;username&#34;: &#34;test&#34;, + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34;, + &#34;email&#34;: &#34;test@example.com&#34;, + &#34;is_staff&#34;: true, + &#34;is_active&#34;: true, + &#34;date_joined&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;groups&#34;: [], + &#34;user_permissions&#34;: [] +} +</code></pre><h3 id="log-in">Log in<a class="td-heading-self-link" href="#log-in" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/login/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json + +{&#34;username&#34;: &#34;test&#34;, &#34;password&#34;: &#34;opensesame&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{&#34;token&#34;: &#34;abc123&#34;} +</code></pre><h3 id="cancel-account">Cancel Account<a class="td-heading-self-link" href="#cancel-account" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/auth/cancel/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="regenerate-token">Regenerate Token<a class="td-heading-self-link" href="#regenerate-token" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command could require administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/tokens/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Optional Parameters:</p> +<pre tabindex="0"><code>{ + &#34;username&#34; : &#34;test&#34; + &#34;all&#34; : &#34;true&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{&#34;token&#34;: &#34;abc123&#34;} +</code></pre><h3 id="change-password">Change Password<a class="td-heading-self-link" href="#change-password" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/passwd/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{ + &#34;password&#34;: &#34;foo&#34;, + &#34;new_password&#34;: &#34;bar&#34; +} +</code></pre><p>Optional parameters:</p> +<pre tabindex="0"><code>{&#34;username&#34;: &#34;testuser&#34;} +</code></pre><blockquote> +<p><strong>note</strong></p> +<p>Using the <code>username</code> parameter requires administrative privileges and makes the <code>password</code> parameter optional.</p> +</blockquote> +<p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h2 id="applications">Applications<a class="td-heading-self-link" href="#applications" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-applications">List all Applications<a class="td-heading-self-link" href="#list-all-applications" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;structure&#34;: {}, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;url&#34;: &#34;example-go.example.com&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; + } + ] +} +</code></pre><h3 id="create-an-application">Create an Application<a class="td-heading-self-link" href="#create-an-application" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 +</code></pre><p>Optional parameters:</p> +<pre tabindex="0"><code>{&#34;id&#34;: &#34;example-go&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;structure&#34;: {}, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;url&#34;: &#34;example-go.example.com&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="destroy-an-application">Destroy an Application<a class="td-heading-self-link" href="#destroy-an-application" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/apps/example-go/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="list-application-details">List Application Details<a class="td-heading-self-link" href="#list-application-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;structure&#34;: {}, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;url&#34;: &#34;example-go.example.com&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="update-application-details">Update Application Details<a class="td-heading-self-link" href="#update-application-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Optional parameters:</p> +<pre tabindex="0"><code>{ + &#34;owner&#34;: &#34;test&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 1.8.0 +Content-Type: application/json +</code></pre><h3 id="retrieve-application-logs">Retrieve Application Logs<a class="td-heading-self-link" href="#retrieve-application-logs" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/logs/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Optional URL Query Parameters:</p> +<pre tabindex="0"><code>?log_lines= +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: text/plain + +&#34;16:51:14 drycc[api]: test created initial release\n&#34; +</code></pre><h3 id="run-one-off-commands">Run one-off Commands<a class="td-heading-self-link" href="#run-one-off-commands" aria-label="Heading self-link"></a></h3> +<pre tabindex="0"><code>POST /v2/apps/example-go/run/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;command&#34;: &#34;echo hi&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{&#34;exit_code&#34;: 0, &#34;output&#34;: &#34;hi\n&#34;} +</code></pre><h2 id="certificates">Certificates<a class="td-heading-self-link" href="#certificates" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-certificates">List all Certificates<a class="td-heading-self-link" href="#list-all-certificates" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/certs HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;id&#34;: 22, + &#34;owner&#34;: &#34;test&#34;, + &#34;san&#34;: [], + &#34;domains&#34;: [], + &#34;created&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;updated&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;name&#34;: &#34;foo&#34;, + &#34;common_name&#34;: &#34;bar.com&#34;, + &#34;fingerprint&#34;: &#34;7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0&#34;, + &#34;expires&#34;: &#34;2017-01-14T23:57:57Z&#34;, + &#34;starts&#34;: &#34;2016-01-15T23:57:57Z&#34;, + &#34;issuer&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34;, + &#34;subject&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34; + } + ] +} +</code></pre><h3 id="get-certificate-details">Get Certificate Details<a class="td-heading-self-link" href="#get-certificate-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/certs/foo HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;id&#34;: 22, + &#34;owner&#34;: &#34;test&#34;, + &#34;san&#34;: [], + &#34;domains&#34;: [], + &#34;created&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;updated&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;name&#34;: &#34;foo&#34;, + &#34;common_name&#34;: &#34;bar.com&#34;, + &#34;fingerprint&#34;: &#34;7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0&#34;, + &#34;expires&#34;: &#34;2017-01-14T23:57:57Z&#34;, + &#34;starts&#34;: &#34;2016-01-15T23:57:57Z&#34;, + &#34;issuer&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34;, + &#34;subject&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34; +} +</code></pre><h3 id="create-certificate">Create Certificate<a class="td-heading-self-link" href="#create-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/certs/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{ + &#34;name&#34;: &#34;foo&#34; + &#34;certificate&#34;: &#34;-----BEGIN CERTIFICATE-----&#34;, + &#34;key&#34;: &#34;-----BEGIN RSA PRIVATE KEY-----&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;id&#34;: 22, + &#34;owner&#34;: &#34;test&#34;, + &#34;san&#34;: [], + &#34;domains&#34;: [], + &#34;created&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;updated&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;name&#34;: &#34;foo&#34;, + &#34;common_name&#34;: &#34;bar.com&#34;, + &#34;fingerprint&#34;: &#34;7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0&#34;, + &#34;expires&#34;: &#34;2017-01-14T23:57:57Z&#34;, + &#34;starts&#34;: &#34;2016-01-15T23:57:57Z&#34;, + &#34;issuer&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34;, + &#34;subject&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34; +} +</code></pre><h3 id="destroy-a-certificate">Destroy a Certificate<a class="td-heading-self-link" href="#destroy-a-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/certs/foo HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="attach-a-domain-to-a-certificate">Attach a Domain to a Certificate<a class="td-heading-self-link" href="#attach-a-domain-to-a-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/certs/foo/domain/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{ + &#34;domain&#34;: &#34;test.com&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="remove-a-domain-from-a-certificate">Remove a Domain from a Certificate<a class="td-heading-self-link" href="#remove-a-domain-from-a-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/certs/foo/domain/test.com/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h2 id="pods">Pods<a class="td-heading-self-link" href="#pods" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-pods">List all Pods<a class="td-heading-self-link" href="#list-all-pods" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/pods/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;results&#34;: [ + { + &#34;name&#34;: &#34;go-v2-web-e7dej&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2014-01-01T00:00:00Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } + ] +} +</code></pre><h3 id="list-all-pods-by-type">List all Pods by Type<a class="td-heading-self-link" href="#list-all-pods-by-type" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/pods/web/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;results&#34;: [ + { + &#34;name&#34;: &#34;go-v2-web-e7dej&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2014-01-01T00:00:00Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } + ] +} +</code></pre><h3 id="restart-all-pods">Restart All Pods<a class="td-heading-self-link" href="#restart-all-pods" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/pods/restart/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +[ + { + &#34;name&#34;: &#34;go-v2-web-atots&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2016-04-11T21:07:54Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } +] +</code></pre><h3 id="restart-pods-by-type">Restart Pods by Type<a class="td-heading-self-link" href="#restart-pods-by-type" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/pods/web/restart/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +[ + { + &#34;name&#34;: &#34;go-v2-web-atots&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2016-04-11T21:07:54Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } +] +</code></pre><h3 id="restart-pods-by-type-and-name">Restart Pods by Type and Name<a class="td-heading-self-link" href="#restart-pods-by-type-and-name" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/pods/go-v2-web-atots/restart/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +[ + { + &#34;name&#34;: &#34;go-v2-web-atots&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2016-04-11T21:07:54Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } +] +</code></pre><h3 id="scale-pods">Scale Pods<a class="td-heading-self-link" href="#scale-pods" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/scale/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;web&#34;: 3} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h2 id="configuration">Configuration<a class="td-heading-self-link" href="#configuration" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-configuration">List Application Configuration<a class="td-heading-self-link" href="#list-application-configuration" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/config/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;owner&#34;: &#34;test&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;values&#34;: { + &#34;PLATFORM&#34;: &#34;drycc&#34; + }, + &#34;memory&#34;: {}, + &#34;cpu&#34;: {}, + &#34;tags&#34;: {}, + &#34;healthcheck&#34;: {}, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="create-new-config">Create new Config<a class="td-heading-self-link" href="#create-new-config" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/config/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;values&#34;: {&#34;HELLO&#34;: &#34;world&#34;, &#34;PLATFORM&#34;: &#34;drycc&#34;}} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json +X-Drycc-Release: 3 + +{ + &#34;owner&#34;: &#34;test&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;values&#34;: { + &#34;DRYCC_APP&#34;: &#34;example-go&#34;, + &#34;DRYCC_RELEASE&#34;: &#34;v3&#34;, + &#34;HELLO&#34;: &#34;world&#34;, + &#34;PLATFORM&#34;: &#34;drycc&#34; + + }, + &#34;memory&#34;: {}, + &#34;cpu&#34;: {}, + &#34;tags&#34;: {}, + &#34;healthcheck&#34;: {}, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="unset-config-variable">Unset Config Variable<a class="td-heading-self-link" href="#unset-config-variable" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/config/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;values&#34;: {&#34;HELLO&#34;: null}} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json +X-Drycc-Release: 4 + +{ + &#34;owner&#34;: &#34;test&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;values&#34;: { + &#34;DRYCC_APP&#34;: &#34;example-go&#34;, + &#34;DRYCC_RELEASE&#34;: &#34;v4&#34;, + &#34;PLATFORM&#34;: &#34;drycc&#34; + }, + &#34;memory&#34;: {}, + &#34;cpu&#34;: {}, + &#34;tags&#34;: {}, + &#34;healthcheck&#34;: {}, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h2 id="domains">Domains<a class="td-heading-self-link" href="#domains" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-domains">List Application Domains<a class="td-heading-self-link" href="#list-application-domains" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/domains/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;domain&#34;: &#34;example.example.com&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34; + } + ] +} +</code></pre><h3 id="add-domain">Add Domain<a class="td-heading-self-link" href="#add-domain" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/domains/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{&#39;domain&#39;: &#39;example.example.com&#39;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;domain&#34;: &#34;example.example.com&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34; +} +</code></pre><h3 id="remove-domain">Remove Domain<a class="td-heading-self-link" href="#remove-domain" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/apps/example-go/domains/example.example.com HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h2 id="builds">Builds<a class="td-heading-self-link" href="#builds" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-builds">List Application Builds<a class="td-heading-self-link" href="#list-application-builds" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/build/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;dockerfile&#34;: &#34;FROM drycc/slugrunner RUN mkdir -p /app WORKDIR /app ENTRYPOINT [\&#34;/runner/init\&#34;] ADD slug.tgz /app ENV GIT_SHA 060da68f654e75fac06dbedd1995d5f8ad9084db&#34;, + &#34;image&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;procfile&#34;: { + &#34;web&#34;: &#34;example-go&#34; + }, + &#34;sha&#34;: &#34;060da68f&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="create-application-build">Create Application Build<a class="td-heading-self-link" href="#create-application-build" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/build/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;image&#34;: &#34;drycc/example-go:latest&#34;} +</code></pre><p>Optional Parameters:</p> +<pre tabindex="0"><code>{ + &#34;procfile&#34;: { + &#34;web&#34;: &#34;./cmd&#34; + } +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json +X-Drycc-Release: 4 + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;dockerfile&#34;: &#34;&#34;, + &#34;image&#34;: &#34;drycc/example-go:latest&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;procfile&#34;: {}, + &#34;sha&#34;: &#34;&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h2 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-releases">List Application Releases<a class="td-heading-self-link" href="#list-application-releases" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/releases/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 3, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: &#34;202d8e4b-600e-4425-a85c-ffc7ea607f61&#34;, + &#34;config&#34;: &#34;ed637ceb-5d32-44bd-9406-d326a777a513&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test changed nothing&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 3 + }, + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: &#34;202d8e4b-600e-4425-a85c-ffc7ea607f61&#34;, + &#34;config&#34;: &#34;95bd6dea-1685-4f78-a03d-fd7270b058d1&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test deployed 060da68&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 2 + }, + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: null, + &#34;config&#34;: &#34;95bd6dea-1685-4f78-a03d-fd7270b058d1&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test created initial release&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 1 + } + ] +} +</code></pre><h3 id="list-release-details">List Release Details<a class="td-heading-self-link" href="#list-release-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/releases/v2/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: null, + &#34;config&#34;: &#34;95bd6dea-1685-4f78-a03d-fd7270b058d1&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test created initial release&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 1 +} +</code></pre><h3 id="rollback-release">Rollback Release<a class="td-heading-self-link" href="#rollback-release" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/releases/rollback/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;version&#34;: 1} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{&#34;version&#34;: 5} +</code></pre><h2 id="keys">Keys<a class="td-heading-self-link" href="#keys" aria-label="Heading self-link"></a></h2> +<h3 id="list-keys">List Keys<a class="td-heading-self-link" href="#list-keys" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/keys/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;test@example.com&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;public&#34;: &#34;ssh-rsa &lt;...&gt;&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; + } + ] +} +</code></pre><h3 id="add-key-to-user">Add Key to User<a class="td-heading-self-link" href="#add-key-to-user" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/keys/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{ + &#34;id&#34;: &#34;example&#34;, + &#34;public&#34;: &#34;ssh-rsa &lt;...&gt;&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example&#34;, + &#34;owner&#34;: &#34;example&#34;, + &#34;public&#34;: &#34;ssh-rsa &lt;...&gt;&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="remove-key-from-user">Remove Key from User<a class="td-heading-self-link" href="#remove-key-from-user" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/keys/example HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h2 id="permissions">Permissions<a class="td-heading-self-link" href="#permissions" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-permissions">List Application Permissions<a class="td-heading-self-link" href="#list-application-permissions" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This does not include the app owner.</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/perms/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;users&#34;: [ + &#34;test&#34;, + &#34;foo&#34; + ] +} +</code></pre><h3 id="create-application-permission">Create Application Permission<a class="td-heading-self-link" href="#create-application-permission" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/perms/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{&#34;username&#34;: &#34;example&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="remove-application-permission">Remove Application Permission<a class="td-heading-self-link" href="#remove-application-permission" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/apps/example-go/perms/example HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="list-administrators">List Administrators<a class="td-heading-self-link" href="#list-administrators" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/admin/perms/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 2, + &#34;next&#34;: null + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;username&#34;: &#34;test&#34;, + &#34;is_superuser&#34;: true + }, + { + &#34;username&#34;: &#34;foo&#34;, + &#34;is_superuser&#34;: true + } + ] +} +</code></pre><h3 id="grant-user-administrative-privileges">Grant User Administrative Privileges<a class="td-heading-self-link" href="#grant-user-administrative-privileges" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command requires administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/admin/perms HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{&#34;username&#34;: &#34;example&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="remove-users-administrative-privileges">Remove User&rsquo;s Administrative Privileges<a class="td-heading-self-link" href="#remove-users-administrative-privileges" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command requires administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/admin/perms/example HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h2 id="users">Users<a class="td-heading-self-link" href="#users" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-users">List all users<a class="td-heading-self-link" href="#list-all-users" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command requires administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/users HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.0 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;id&#34;: 1, + &#34;last_login&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;is_superuser&#34;: true, + &#34;username&#34;: &#34;test&#34;, + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34;, + &#34;email&#34;: &#34;test@example.com&#34;, + &#34;is_staff&#34;: true, + &#34;is_active&#34;: true, + &#34;date_joined&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;groups&#34;: [], + &#34;user_permissions&#34;: [] + } + ] +} +</code></pre> + + + + + Docs: Controller API v2.1 + /docs/reference-guide/controller-api-v2-1/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/reference-guide/controller-api-v2-1/ + + + + <h2 id="whats-new">What&rsquo;s New<a class="td-heading-self-link" href="#whats-new" aria-label="Heading self-link"></a></h2> +<p><strong>New!</strong> <code>healthcheck</code> field in configuration, deprecates the <code>HEALTHCHECK_*</code> environment variables.</p> +<p><strong>New!</strong> Unsetting a configuration variable that does not exist will return a 422.</p> +<p><strong>New!</strong> Creating an identical sequential release returns a 409 rather than create a no-op release.</p> +<h2 id="authentication">Authentication<a class="td-heading-self-link" href="#authentication" aria-label="Heading self-link"></a></h2> +<h3 id="register-a-new-user">Register a New User<a class="td-heading-self-link" href="#register-a-new-user" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/register/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json + +{ + &#34;username&#34;: &#34;test&#34;, + &#34;password&#34;: &#34;opensesame&#34;, + &#34;email&#34;: &#34;test@example.com&#34; +} +</code></pre><p>Optional Parameters:</p> +<pre tabindex="0"><code>{ + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;id&#34;: 1, + &#34;last_login&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;is_superuser&#34;: true, + &#34;username&#34;: &#34;test&#34;, + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34;, + &#34;email&#34;: &#34;test@example.com&#34;, + &#34;is_staff&#34;: true, + &#34;is_active&#34;: true, + &#34;date_joined&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;groups&#34;: [], + &#34;user_permissions&#34;: [] +} +</code></pre><h3 id="log-in">Log in<a class="td-heading-self-link" href="#log-in" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/login/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json + +{&#34;username&#34;: &#34;test&#34;, &#34;password&#34;: &#34;opensesame&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{&#34;token&#34;: &#34;abc123&#34;} +</code></pre><h3 id="cancel-account">Cancel Account<a class="td-heading-self-link" href="#cancel-account" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/auth/cancel/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="regenerate-token">Regenerate Token<a class="td-heading-self-link" href="#regenerate-token" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command could require administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/tokens/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Optional Parameters:</p> +<pre tabindex="0"><code>{ + &#34;username&#34; : &#34;test&#34; + &#34;all&#34; : &#34;true&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{&#34;token&#34;: &#34;abc123&#34;} +</code></pre><h3 id="change-password">Change Password<a class="td-heading-self-link" href="#change-password" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/passwd/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{ + &#34;password&#34;: &#34;foo&#34;, + &#34;new_password&#34;: &#34;bar&#34; +} +</code></pre><p>Optional parameters:</p> +<pre tabindex="0"><code>{&#34;username&#34;: &#34;testuser&#34;} +</code></pre><blockquote> +<p><strong>note</strong></p> +<p>Using the <code>username</code> parameter requires administrative privileges and makes the <code>password</code> parameter optional.</p> +</blockquote> +<p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h2 id="applications">Applications<a class="td-heading-self-link" href="#applications" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-applications">List all Applications<a class="td-heading-self-link" href="#list-all-applications" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;structure&#34;: {}, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;url&#34;: &#34;example-go.example.com&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; + } + ] +} +</code></pre><h3 id="create-an-application">Create an Application<a class="td-heading-self-link" href="#create-an-application" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 +</code></pre><p>Optional parameters:</p> +<pre tabindex="0"><code>{&#34;id&#34;: &#34;example-go&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;structure&#34;: {}, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;url&#34;: &#34;example-go.example.com&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="destroy-an-application">Destroy an Application<a class="td-heading-self-link" href="#destroy-an-application" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/apps/example-go/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="list-application-details">List Application Details<a class="td-heading-self-link" href="#list-application-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;structure&#34;: {}, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;url&#34;: &#34;example-go.example.com&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="update-application-details">Update Application Details<a class="td-heading-self-link" href="#update-application-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Optional parameters:</p> +<pre tabindex="0"><code>{ + &#34;owner&#34;: &#34;test&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 1.8.0 +Content-Type: application/json +</code></pre><h3 id="retrieve-application-logs">Retrieve Application Logs<a class="td-heading-self-link" href="#retrieve-application-logs" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/logs/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Optional URL Query Parameters:</p> +<pre tabindex="0"><code>?log_lines= +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: text/plain + +&#34;16:51:14 drycc[api]: test created initial release\n&#34; +</code></pre><h3 id="run-one-off-commands">Run one-off Commands<a class="td-heading-self-link" href="#run-one-off-commands" aria-label="Heading self-link"></a></h3> +<pre tabindex="0"><code>POST /v2/apps/example-go/run/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;command&#34;: &#34;echo hi&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{&#34;exit_code&#34;: 0, &#34;output&#34;: &#34;hi\n&#34;} +</code></pre><h2 id="certificates">Certificates<a class="td-heading-self-link" href="#certificates" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-certificates">List all Certificates<a class="td-heading-self-link" href="#list-all-certificates" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/certs HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;id&#34;: 22, + &#34;owner&#34;: &#34;test&#34;, + &#34;san&#34;: [], + &#34;domains&#34;: [], + &#34;created&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;updated&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;name&#34;: &#34;foo&#34;, + &#34;common_name&#34;: &#34;bar.com&#34;, + &#34;fingerprint&#34;: &#34;7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0&#34;, + &#34;expires&#34;: &#34;2017-01-14T23:57:57Z&#34;, + &#34;starts&#34;: &#34;2016-01-15T23:57:57Z&#34;, + &#34;issuer&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34;, + &#34;subject&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34; + } + ] +} +</code></pre><h3 id="get-certificate-details">Get Certificate Details<a class="td-heading-self-link" href="#get-certificate-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/certs/foo HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;id&#34;: 22, + &#34;owner&#34;: &#34;test&#34;, + &#34;san&#34;: [], + &#34;domains&#34;: [], + &#34;created&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;updated&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;name&#34;: &#34;foo&#34;, + &#34;common_name&#34;: &#34;bar.com&#34;, + &#34;fingerprint&#34;: &#34;7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0&#34;, + &#34;expires&#34;: &#34;2017-01-14T23:57:57Z&#34;, + &#34;starts&#34;: &#34;2016-01-15T23:57:57Z&#34;, + &#34;issuer&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34;, + &#34;subject&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34; +} +</code></pre><h3 id="create-certificate">Create Certificate<a class="td-heading-self-link" href="#create-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/certs/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{ + &#34;name&#34;: &#34;foo&#34; + &#34;certificate&#34;: &#34;-----BEGIN CERTIFICATE-----&#34;, + &#34;key&#34;: &#34;-----BEGIN RSA PRIVATE KEY-----&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;id&#34;: 22, + &#34;owner&#34;: &#34;test&#34;, + &#34;san&#34;: [], + &#34;domains&#34;: [], + &#34;created&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;updated&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;name&#34;: &#34;foo&#34;, + &#34;common_name&#34;: &#34;bar.com&#34;, + &#34;fingerprint&#34;: &#34;7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0&#34;, + &#34;expires&#34;: &#34;2017-01-14T23:57:57Z&#34;, + &#34;starts&#34;: &#34;2016-01-15T23:57:57Z&#34;, + &#34;issuer&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34;, + &#34;subject&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34; +} +</code></pre><h3 id="destroy-a-certificate">Destroy a Certificate<a class="td-heading-self-link" href="#destroy-a-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/certs/foo HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="attach-a-domain-to-a-certificate">Attach a Domain to a Certificate<a class="td-heading-self-link" href="#attach-a-domain-to-a-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/certs/foo/domain/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{ + &#34;domain&#34;: &#34;test.com&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="remove-a-domain-from-a-certificate">Remove a Domain from a Certificate<a class="td-heading-self-link" href="#remove-a-domain-from-a-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/certs/foo/domain/test.com/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h2 id="pods">Pods<a class="td-heading-self-link" href="#pods" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-pods">List all Pods<a class="td-heading-self-link" href="#list-all-pods" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/pods/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;results&#34;: [ + { + &#34;name&#34;: &#34;go-v2-web-e7dej&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2014-01-01T00:00:00Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } + ] +} +</code></pre><h3 id="list-all-pods-by-type">List all Pods by Type<a class="td-heading-self-link" href="#list-all-pods-by-type" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/pods/web/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;results&#34;: [ + { + &#34;name&#34;: &#34;go-v2-web-e7dej&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2014-01-01T00:00:00Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } + ] +} +</code></pre><h3 id="restart-all-pods">Restart All Pods<a class="td-heading-self-link" href="#restart-all-pods" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/pods/restart/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +[ + { + &#34;name&#34;: &#34;go-v2-web-atots&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2016-04-11T21:07:54Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } +] +</code></pre><h3 id="restart-pods-by-type">Restart Pods by Type<a class="td-heading-self-link" href="#restart-pods-by-type" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/pods/web/restart/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +[ + { + &#34;name&#34;: &#34;go-v2-web-atots&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2016-04-11T21:07:54Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } +] +</code></pre><h3 id="restart-pods-by-type-and-name">Restart Pods by Type and Name<a class="td-heading-self-link" href="#restart-pods-by-type-and-name" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/pods/go-v2-web-atots/restart/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +[ + { + &#34;name&#34;: &#34;go-v2-web-atots&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2016-04-11T21:07:54Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } +] +</code></pre><h3 id="scale-pods">Scale Pods<a class="td-heading-self-link" href="#scale-pods" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/scale/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;web&#34;: 3} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h2 id="configuration">Configuration<a class="td-heading-self-link" href="#configuration" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-configuration">List Application Configuration<a class="td-heading-self-link" href="#list-application-configuration" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/config/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;owner&#34;: &#34;test&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;values&#34;: { + &#34;PLATFORM&#34;: &#34;drycc&#34; + }, + &#34;memory&#34;: {}, + &#34;cpu&#34;: {}, + &#34;tags&#34;: {}, + &#34;healthcheck&#34;: {}, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="create-new-config">Create new Config<a class="td-heading-self-link" href="#create-new-config" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/config/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;values&#34;: {&#34;HELLO&#34;: &#34;world&#34;, &#34;PLATFORM&#34;: &#34;drycc&#34;}} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;owner&#34;: &#34;test&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;values&#34;: { + &#34;DRYCC_APP&#34;: &#34;example-go&#34;, + &#34;DRYCC_RELEASE&#34;: &#34;v3&#34;, + &#34;HELLO&#34;: &#34;world&#34;, + &#34;PLATFORM&#34;: &#34;drycc&#34; + + }, + &#34;memory&#34;: {}, + &#34;cpu&#34;: {}, + &#34;tags&#34;: {}, + &#34;healthcheck&#34;: {}, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="unset-config-variable">Unset Config Variable<a class="td-heading-self-link" href="#unset-config-variable" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/config/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;values&#34;: {&#34;HELLO&#34;: null}} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;owner&#34;: &#34;test&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;values&#34;: { + &#34;DRYCC_APP&#34;: &#34;example-go&#34;, + &#34;DRYCC_RELEASE&#34;: &#34;v4&#34;, + &#34;PLATFORM&#34;: &#34;drycc&#34; + }, + &#34;memory&#34;: {}, + &#34;cpu&#34;: {}, + &#34;tags&#34;: {}, + &#34;healthcheck&#34;: {}, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h2 id="domains">Domains<a class="td-heading-self-link" href="#domains" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-domains">List Application Domains<a class="td-heading-self-link" href="#list-application-domains" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/domains/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;domain&#34;: &#34;example.example.com&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34; + } + ] +} +</code></pre><h3 id="add-domain">Add Domain<a class="td-heading-self-link" href="#add-domain" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/domains/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{&#39;domain&#39;: &#39;example.example.com&#39;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;domain&#34;: &#34;example.example.com&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34; +} +</code></pre><h3 id="remove-domain">Remove Domain<a class="td-heading-self-link" href="#remove-domain" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/apps/example-go/domains/example.example.com HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h2 id="builds">Builds<a class="td-heading-self-link" href="#builds" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-builds">List Application Builds<a class="td-heading-self-link" href="#list-application-builds" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/build/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;dockerfile&#34;: &#34;FROM drycc/slugrunner RUN mkdir -p /app WORKDIR /app ENTRYPOINT [\&#34;/runner/init\&#34;] ADD slug.tgz /app ENV GIT_SHA 060da68f654e75fac06dbedd1995d5f8ad9084db&#34;, + &#34;image&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;procfile&#34;: { + &#34;web&#34;: &#34;example-go&#34; + }, + &#34;sha&#34;: &#34;060da68f&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="create-application-build">Create Application Build<a class="td-heading-self-link" href="#create-application-build" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/build/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;image&#34;: &#34;drycc/example-go:latest&#34;} +</code></pre><p>Optional Parameters:</p> +<pre tabindex="0"><code>{ + &#34;procfile&#34;: { + &#34;web&#34;: &#34;./cmd&#34; + } +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;dockerfile&#34;: &#34;&#34;, + &#34;image&#34;: &#34;drycc/example-go:latest&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;procfile&#34;: {}, + &#34;sha&#34;: &#34;&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h2 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-releases">List Application Releases<a class="td-heading-self-link" href="#list-application-releases" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/releases/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 3, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: &#34;202d8e4b-600e-4425-a85c-ffc7ea607f61&#34;, + &#34;config&#34;: &#34;ed637ceb-5d32-44bd-9406-d326a777a513&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test changed nothing&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 3 + }, + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: &#34;202d8e4b-600e-4425-a85c-ffc7ea607f61&#34;, + &#34;config&#34;: &#34;95bd6dea-1685-4f78-a03d-fd7270b058d1&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test deployed 060da68&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 2 + }, + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: null, + &#34;config&#34;: &#34;95bd6dea-1685-4f78-a03d-fd7270b058d1&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test created initial release&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 1 + } + ] +} +</code></pre><h3 id="list-release-details">List Release Details<a class="td-heading-self-link" href="#list-release-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/releases/v2/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: null, + &#34;config&#34;: &#34;95bd6dea-1685-4f78-a03d-fd7270b058d1&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test created initial release&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 1 +} +</code></pre><h3 id="rollback-release">Rollback Release<a class="td-heading-self-link" href="#rollback-release" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/releases/rollback/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;version&#34;: 1} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{&#34;version&#34;: 5} +</code></pre><h2 id="keys">Keys<a class="td-heading-self-link" href="#keys" aria-label="Heading self-link"></a></h2> +<h3 id="list-keys">List Keys<a class="td-heading-self-link" href="#list-keys" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/keys/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;test@example.com&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;public&#34;: &#34;ssh-rsa &lt;...&gt;&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; + } + ] +} +</code></pre><h3 id="add-key-to-user">Add Key to User<a class="td-heading-self-link" href="#add-key-to-user" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/keys/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{ + &#34;id&#34;: &#34;example&#34;, + &#34;public&#34;: &#34;ssh-rsa &lt;...&gt;&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example&#34;, + &#34;owner&#34;: &#34;example&#34;, + &#34;public&#34;: &#34;ssh-rsa &lt;...&gt;&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="remove-key-from-user">Remove Key from User<a class="td-heading-self-link" href="#remove-key-from-user" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/keys/example HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h2 id="permissions">Permissions<a class="td-heading-self-link" href="#permissions" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-permissions">List Application Permissions<a class="td-heading-self-link" href="#list-application-permissions" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This does not include the app owner.</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/perms/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;users&#34;: [ + &#34;test&#34;, + &#34;foo&#34; + ] +} +</code></pre><h3 id="create-application-permission">Create Application Permission<a class="td-heading-self-link" href="#create-application-permission" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/perms/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{&#34;username&#34;: &#34;example&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="remove-application-permission">Remove Application Permission<a class="td-heading-self-link" href="#remove-application-permission" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/apps/example-go/perms/example HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="list-administrators">List Administrators<a class="td-heading-self-link" href="#list-administrators" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/admin/perms/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 2, + &#34;next&#34;: null + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;username&#34;: &#34;test&#34;, + &#34;is_superuser&#34;: true + }, + { + &#34;username&#34;: &#34;foo&#34;, + &#34;is_superuser&#34;: true + } + ] +} +</code></pre><h3 id="grant-user-administrative-privileges">Grant User Administrative Privileges<a class="td-heading-self-link" href="#grant-user-administrative-privileges" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command requires administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/admin/perms HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{&#34;username&#34;: &#34;example&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h3 id="remove-users-administrative-privileges">Remove User&rsquo;s Administrative Privileges<a class="td-heading-self-link" href="#remove-users-administrative-privileges" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command requires administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/admin/perms/example HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +</code></pre><h2 id="users">Users<a class="td-heading-self-link" href="#users" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-users">List all users<a class="td-heading-self-link" href="#list-all-users" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command requires administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/users HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.1 +DRYCC_PLATFORM_VERSION: 2.1.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;id&#34;: 1, + &#34;last_login&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;is_superuser&#34;: true, + &#34;username&#34;: &#34;test&#34;, + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34;, + &#34;email&#34;: &#34;test@example.com&#34;, + &#34;is_staff&#34;: true, + &#34;is_active&#34;: true, + &#34;date_joined&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;groups&#34;: [], + &#34;user_permissions&#34;: [] + } + ] +} +</code></pre> + + + + + Docs: Controller API v2.2 + /docs/reference-guide/controller-api-v2-2/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/reference-guide/controller-api-v2-2/ + + + + <h2 id="whats-new">What&rsquo;s New<a class="td-heading-self-link" href="#whats-new" aria-label="Heading self-link"></a></h2> +<p><strong>New!</strong> <code>/v2/auth/whoami</code> endpoint</p> +<h2 id="authentication">Authentication<a class="td-heading-self-link" href="#authentication" aria-label="Heading self-link"></a></h2> +<h3 id="register-a-new-user">Register a New User<a class="td-heading-self-link" href="#register-a-new-user" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/register/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json + +{ + &#34;username&#34;: &#34;test&#34;, + &#34;password&#34;: &#34;opensesame&#34;, + &#34;email&#34;: &#34;test@example.com&#34; +} +</code></pre><p>Optional Parameters:</p> +<pre tabindex="0"><code>{ + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;id&#34;: 1, + &#34;last_login&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;is_superuser&#34;: true, + &#34;username&#34;: &#34;test&#34;, + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34;, + &#34;email&#34;: &#34;test@example.com&#34;, + &#34;is_staff&#34;: true, + &#34;is_active&#34;: true, + &#34;date_joined&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;groups&#34;: [], + &#34;user_permissions&#34;: [] +} +</code></pre><h3 id="log-in">Log in<a class="td-heading-self-link" href="#log-in" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/login/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json + +{&#34;username&#34;: &#34;test&#34;, &#34;password&#34;: &#34;opensesame&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{&#34;token&#34;: &#34;abc123&#34;} +</code></pre><h3 id="cancel-account">Cancel Account<a class="td-heading-self-link" href="#cancel-account" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/auth/cancel/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h3 id="who-am-i">Who Am I<a class="td-heading-self-link" href="#who-am-i" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/auth/whoami/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;id&#34;: 1, + &#34;last_login&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;is_superuser&#34;: true, + &#34;username&#34;: &#34;test&#34;, + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34;, + &#34;email&#34;: &#34;test@example.com&#34;, + &#34;is_staff&#34;: true, + &#34;is_active&#34;: true, + &#34;date_joined&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;groups&#34;: [], + &#34;user_permissions&#34;: [] +} +</code></pre><h3 id="regenerate-token">Regenerate Token<a class="td-heading-self-link" href="#regenerate-token" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command could require administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/tokens/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Optional Parameters:</p> +<pre tabindex="0"><code>{ + &#34;username&#34; : &#34;test&#34; + &#34;all&#34; : &#34;true&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{&#34;token&#34;: &#34;abc123&#34;} +</code></pre><h3 id="change-password">Change Password<a class="td-heading-self-link" href="#change-password" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/passwd/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{ + &#34;password&#34;: &#34;foo&#34;, + &#34;new_password&#34;: &#34;bar&#34; +} +</code></pre><p>Optional parameters:</p> +<pre tabindex="0"><code>{&#34;username&#34;: &#34;testuser&#34;} +</code></pre><blockquote> +<p><strong>note</strong></p> +<p>Using the <code>username</code> parameter requires administrative privileges and makes the <code>password</code> parameter optional.</p> +</blockquote> +<p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h2 id="applications">Applications<a class="td-heading-self-link" href="#applications" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-applications">List all Applications<a class="td-heading-self-link" href="#list-all-applications" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;structure&#34;: {}, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;url&#34;: &#34;example-go.example.com&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; + } + ] +} +</code></pre><h3 id="create-an-application">Create an Application<a class="td-heading-self-link" href="#create-an-application" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 +</code></pre><p>Optional parameters:</p> +<pre tabindex="0"><code>{&#34;id&#34;: &#34;example-go&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;structure&#34;: {}, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;url&#34;: &#34;example-go.example.com&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="destroy-an-application">Destroy an Application<a class="td-heading-self-link" href="#destroy-an-application" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/apps/example-go/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h3 id="list-application-details">List Application Details<a class="td-heading-self-link" href="#list-application-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;structure&#34;: {}, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;url&#34;: &#34;example-go.example.com&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="update-application-details">Update Application Details<a class="td-heading-self-link" href="#update-application-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Optional parameters:</p> +<pre tabindex="0"><code>{ + &#34;owner&#34;: &#34;test&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 1.8.0 +Content-Type: application/json +</code></pre><h3 id="retrieve-application-logs">Retrieve Application Logs<a class="td-heading-self-link" href="#retrieve-application-logs" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/logs/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Optional URL Query Parameters:</p> +<pre tabindex="0"><code>?log_lines= +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: text/plain + +&#34;16:51:14 drycc[api]: test created initial release\n&#34; +</code></pre><h3 id="run-one-off-commands">Run one-off Commands<a class="td-heading-self-link" href="#run-one-off-commands" aria-label="Heading self-link"></a></h3> +<pre tabindex="0"><code>POST /v2/apps/example-go/run/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;command&#34;: &#34;echo hi&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{&#34;exit_code&#34;: 0, &#34;output&#34;: &#34;hi\n&#34;} +</code></pre><h2 id="certificates">Certificates<a class="td-heading-self-link" href="#certificates" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-certificates">List all Certificates<a class="td-heading-self-link" href="#list-all-certificates" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/certs HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;id&#34;: 22, + &#34;owner&#34;: &#34;test&#34;, + &#34;san&#34;: [], + &#34;domains&#34;: [], + &#34;created&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;updated&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;name&#34;: &#34;foo&#34;, + &#34;common_name&#34;: &#34;bar.com&#34;, + &#34;fingerprint&#34;: &#34;7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0&#34;, + &#34;expires&#34;: &#34;2017-01-14T23:57:57Z&#34;, + &#34;starts&#34;: &#34;2016-01-15T23:57:57Z&#34;, + &#34;issuer&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34;, + &#34;subject&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34; + } + ] +} +</code></pre><h3 id="get-certificate-details">Get Certificate Details<a class="td-heading-self-link" href="#get-certificate-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/certs/foo HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;id&#34;: 22, + &#34;owner&#34;: &#34;test&#34;, + &#34;san&#34;: [], + &#34;domains&#34;: [], + &#34;created&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;updated&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;name&#34;: &#34;foo&#34;, + &#34;common_name&#34;: &#34;bar.com&#34;, + &#34;fingerprint&#34;: &#34;7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0&#34;, + &#34;expires&#34;: &#34;2017-01-14T23:57:57Z&#34;, + &#34;starts&#34;: &#34;2016-01-15T23:57:57Z&#34;, + &#34;issuer&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34;, + &#34;subject&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34; +} +</code></pre><h3 id="create-certificate">Create Certificate<a class="td-heading-self-link" href="#create-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/certs/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{ + &#34;name&#34;: &#34;foo&#34; + &#34;certificate&#34;: &#34;-----BEGIN CERTIFICATE-----&#34;, + &#34;key&#34;: &#34;-----BEGIN RSA PRIVATE KEY-----&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;id&#34;: 22, + &#34;owner&#34;: &#34;test&#34;, + &#34;san&#34;: [], + &#34;domains&#34;: [], + &#34;created&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;updated&#34;: &#34;2016-06-22T22:24:20Z&#34;, + &#34;name&#34;: &#34;foo&#34;, + &#34;common_name&#34;: &#34;bar.com&#34;, + &#34;fingerprint&#34;: &#34;7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0&#34;, + &#34;expires&#34;: &#34;2017-01-14T23:57:57Z&#34;, + &#34;starts&#34;: &#34;2016-01-15T23:57:57Z&#34;, + &#34;issuer&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34;, + &#34;subject&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34; +} +</code></pre><h3 id="destroy-a-certificate">Destroy a Certificate<a class="td-heading-self-link" href="#destroy-a-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/certs/foo HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h3 id="attach-a-domain-to-a-certificate">Attach a Domain to a Certificate<a class="td-heading-self-link" href="#attach-a-domain-to-a-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/certs/foo/domain/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{ + &#34;domain&#34;: &#34;test.com&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h3 id="remove-a-domain-from-a-certificate">Remove a Domain from a Certificate<a class="td-heading-self-link" href="#remove-a-domain-from-a-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/certs/foo/domain/test.com/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h2 id="pods">Pods<a class="td-heading-self-link" href="#pods" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-pods">List all Pods<a class="td-heading-self-link" href="#list-all-pods" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/pods/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;results&#34;: [ + { + &#34;name&#34;: &#34;go-v2-web-e7dej&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2014-01-01T00:00:00Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } + ] +} +</code></pre><h3 id="list-all-pods-by-type">List all Pods by Type<a class="td-heading-self-link" href="#list-all-pods-by-type" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/pods/web/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;results&#34;: [ + { + &#34;name&#34;: &#34;go-v2-web-e7dej&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2014-01-01T00:00:00Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } + ] +} +</code></pre><h3 id="restart-all-pods">Restart All Pods<a class="td-heading-self-link" href="#restart-all-pods" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/pods/restart/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +[ + { + &#34;name&#34;: &#34;go-v2-web-atots&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2016-04-11T21:07:54Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } +] +</code></pre><h3 id="restart-pods-by-type">Restart Pods by Type<a class="td-heading-self-link" href="#restart-pods-by-type" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/pods/web/restart/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +[ + { + &#34;name&#34;: &#34;go-v2-web-atots&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2016-04-11T21:07:54Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } +] +</code></pre><h3 id="restart-pods-by-type-and-name">Restart Pods by Type and Name<a class="td-heading-self-link" href="#restart-pods-by-type-and-name" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/pods/go-v2-web-atots/restart/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +[ + { + &#34;name&#34;: &#34;go-v2-web-atots&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2016-04-11T21:07:54Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } +] +</code></pre><h3 id="scale-pods">Scale Pods<a class="td-heading-self-link" href="#scale-pods" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/scale/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;web&#34;: 3} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h2 id="configuration">Configuration<a class="td-heading-self-link" href="#configuration" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-configuration">List Application Configuration<a class="td-heading-self-link" href="#list-application-configuration" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/config/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;owner&#34;: &#34;test&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;values&#34;: { + &#34;PLATFORM&#34;: &#34;drycc&#34; + }, + &#34;memory&#34;: {}, + &#34;cpu&#34;: {}, + &#34;tags&#34;: {}, + &#34;healthcheck&#34;: {}, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="create-new-config">Create new Config<a class="td-heading-self-link" href="#create-new-config" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/config/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;values&#34;: {&#34;HELLO&#34;: &#34;world&#34;, &#34;PLATFORM&#34;: &#34;drycc&#34;}} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;owner&#34;: &#34;test&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;values&#34;: { + &#34;DRYCC_APP&#34;: &#34;example-go&#34;, + &#34;DRYCC_RELEASE&#34;: &#34;v3&#34;, + &#34;HELLO&#34;: &#34;world&#34;, + &#34;PLATFORM&#34;: &#34;drycc&#34; + + }, + &#34;memory&#34;: {}, + &#34;cpu&#34;: {}, + &#34;tags&#34;: {}, + &#34;healthcheck&#34;: {}, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="unset-config-variable">Unset Config Variable<a class="td-heading-self-link" href="#unset-config-variable" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/config/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;values&#34;: {&#34;HELLO&#34;: null}} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;owner&#34;: &#34;test&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;values&#34;: { + &#34;DRYCC_APP&#34;: &#34;example-go&#34;, + &#34;DRYCC_RELEASE&#34;: &#34;v4&#34;, + &#34;PLATFORM&#34;: &#34;drycc&#34; + }, + &#34;memory&#34;: {}, + &#34;cpu&#34;: {}, + &#34;tags&#34;: {}, + &#34;healthcheck&#34;: {}, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h2 id="domains">Domains<a class="td-heading-self-link" href="#domains" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-domains">List Application Domains<a class="td-heading-self-link" href="#list-application-domains" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/domains/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;domain&#34;: &#34;example.example.com&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34; + } + ] +} +</code></pre><h3 id="add-domain">Add Domain<a class="td-heading-self-link" href="#add-domain" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/domains/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{&#39;domain&#39;: &#39;example.example.com&#39;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;domain&#34;: &#34;example.example.com&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34; +} +</code></pre><h3 id="remove-domain">Remove Domain<a class="td-heading-self-link" href="#remove-domain" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/apps/example-go/domains/example.example.com HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h2 id="builds">Builds<a class="td-heading-self-link" href="#builds" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-builds">List Application Builds<a class="td-heading-self-link" href="#list-application-builds" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/build/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;dockerfile&#34;: &#34;FROM drycc/slugrunner RUN mkdir -p /app WORKDIR /app ENTRYPOINT [\&#34;/runner/init\&#34;] ADD slug.tgz /app ENV GIT_SHA 060da68f654e75fac06dbedd1995d5f8ad9084db&#34;, + &#34;image&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;procfile&#34;: { + &#34;web&#34;: &#34;example-go&#34; + }, + &#34;sha&#34;: &#34;060da68f&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="create-application-build">Create Application Build<a class="td-heading-self-link" href="#create-application-build" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/build/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;image&#34;: &#34;drycc/example-go:latest&#34;} +</code></pre><p>Optional Parameters:</p> +<pre tabindex="0"><code>{ + &#34;procfile&#34;: { + &#34;web&#34;: &#34;./cmd&#34; + } +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;dockerfile&#34;: &#34;&#34;, + &#34;image&#34;: &#34;drycc/example-go:latest&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;procfile&#34;: {}, + &#34;sha&#34;: &#34;&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h2 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-releases">List Application Releases<a class="td-heading-self-link" href="#list-application-releases" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/releases/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;count&#34;: 3, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: &#34;202d8e4b-600e-4425-a85c-ffc7ea607f61&#34;, + &#34;config&#34;: &#34;ed637ceb-5d32-44bd-9406-d326a777a513&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test changed nothing&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 3 + }, + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: &#34;202d8e4b-600e-4425-a85c-ffc7ea607f61&#34;, + &#34;config&#34;: &#34;95bd6dea-1685-4f78-a03d-fd7270b058d1&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test deployed 060da68&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 2 + }, + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: null, + &#34;config&#34;: &#34;95bd6dea-1685-4f78-a03d-fd7270b058d1&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test created initial release&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 1 + } + ] +} +</code></pre><h3 id="list-release-details">List Release Details<a class="td-heading-self-link" href="#list-release-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/releases/v2/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: null, + &#34;config&#34;: &#34;95bd6dea-1685-4f78-a03d-fd7270b058d1&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test created initial release&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 1 +} +</code></pre><h3 id="rollback-release">Rollback Release<a class="td-heading-self-link" href="#rollback-release" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/releases/rollback/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;version&#34;: 1} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{&#34;version&#34;: 5} +</code></pre><h2 id="keys">Keys<a class="td-heading-self-link" href="#keys" aria-label="Heading self-link"></a></h2> +<h3 id="list-keys">List Keys<a class="td-heading-self-link" href="#list-keys" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/keys/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;test@example.com&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;public&#34;: &#34;ssh-rsa &lt;...&gt;&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; + } + ] +} +</code></pre><h3 id="add-key-to-user">Add Key to User<a class="td-heading-self-link" href="#add-key-to-user" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/keys/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{ + &#34;id&#34;: &#34;example&#34;, + &#34;public&#34;: &#34;ssh-rsa &lt;...&gt;&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example&#34;, + &#34;owner&#34;: &#34;example&#34;, + &#34;public&#34;: &#34;ssh-rsa &lt;...&gt;&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="remove-key-from-user">Remove Key from User<a class="td-heading-self-link" href="#remove-key-from-user" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/keys/example HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h2 id="permissions">Permissions<a class="td-heading-self-link" href="#permissions" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-permissions">List Application Permissions<a class="td-heading-self-link" href="#list-application-permissions" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This does not include the app owner.</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/perms/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;users&#34;: [ + &#34;test&#34;, + &#34;foo&#34; + ] +} +</code></pre><h3 id="create-application-permission">Create Application Permission<a class="td-heading-self-link" href="#create-application-permission" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/perms/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{&#34;username&#34;: &#34;example&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h3 id="remove-application-permission">Remove Application Permission<a class="td-heading-self-link" href="#remove-application-permission" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/apps/example-go/perms/example HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h3 id="list-administrators">List Administrators<a class="td-heading-self-link" href="#list-administrators" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/admin/perms/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;count&#34;: 2, + &#34;next&#34;: null + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;username&#34;: &#34;test&#34;, + &#34;is_superuser&#34;: true + }, + { + &#34;username&#34;: &#34;foo&#34;, + &#34;is_superuser&#34;: true + } + ] +} +</code></pre><h3 id="grant-user-administrative-privileges">Grant User Administrative Privileges<a class="td-heading-self-link" href="#grant-user-administrative-privileges" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command requires administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/admin/perms HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{&#34;username&#34;: &#34;example&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h3 id="remove-users-administrative-privileges">Remove User&rsquo;s Administrative Privileges<a class="td-heading-self-link" href="#remove-users-administrative-privileges" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command requires administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/admin/perms/example HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +</code></pre><h2 id="users">Users<a class="td-heading-self-link" href="#users" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-users">List all users<a class="td-heading-self-link" href="#list-all-users" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command requires administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/users HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.2 +DRYCC_PLATFORM_VERSION: 2.2.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;id&#34;: 1, + &#34;last_login&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;is_superuser&#34;: true, + &#34;username&#34;: &#34;test&#34;, + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34;, + &#34;email&#34;: &#34;test@example.com&#34;, + &#34;is_staff&#34;: true, + &#34;is_active&#34;: true, + &#34;date_joined&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;groups&#34;: [], + &#34;user_permissions&#34;: [] + } + ] +} +</code></pre> + + + + + Docs: Controller API v2.3 + /docs/reference-guide/controller-api-v2-3/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/reference-guide/controller-api-v2-3/ + + + + <h2 id="whats-new">What&rsquo;s New<a class="td-heading-self-link" href="#whats-new" aria-label="Heading self-link"></a></h2> +<p><strong>New!</strong> <code>/v2/apps/{name}/logs</code> endpoint was fixed and no longer returns <code>b'log data'</code> and instead returns a normal string <code>log data</code></p> +<h2 id="authentication">Authentication<a class="td-heading-self-link" href="#authentication" aria-label="Heading self-link"></a></h2> +<h3 id="register-a-new-user">Register a New User<a class="td-heading-self-link" href="#register-a-new-user" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/register/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json + +{ + &#34;username&#34;: &#34;test&#34;, + &#34;password&#34;: &#34;opensesame&#34;, + &#34;email&#34;: &#34;test@example.com&#34; +} +</code></pre><p>Optional Parameters:</p> +<pre tabindex="0"><code>{ + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;id&#34;: 1, + &#34;last_login&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;is_superuser&#34;: true, + &#34;username&#34;: &#34;test&#34;, + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34;, + &#34;email&#34;: &#34;test@example.com&#34;, + &#34;is_staff&#34;: true, + &#34;is_active&#34;: true, + &#34;date_joined&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;groups&#34;: [], + &#34;user_permissions&#34;: [] +} +</code></pre><h3 id="log-in">Log in<a class="td-heading-self-link" href="#log-in" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/login/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json + +{&#34;username&#34;: &#34;test&#34;, &#34;password&#34;: &#34;opensesame&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{&#34;token&#34;: &#34;abc123&#34;} +</code></pre><h3 id="cancel-account">Cancel Account<a class="td-heading-self-link" href="#cancel-account" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/auth/cancel/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h3 id="who-am-i">Who Am I<a class="td-heading-self-link" href="#who-am-i" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/auth/whoami/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;id&#34;: 1, + &#34;last_login&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;is_superuser&#34;: true, + &#34;username&#34;: &#34;test&#34;, + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34;, + &#34;email&#34;: &#34;test@example.com&#34;, + &#34;is_staff&#34;: true, + &#34;is_active&#34;: true, + &#34;date_joined&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;groups&#34;: [], + &#34;user_permissions&#34;: [] +} +</code></pre><h3 id="regenerate-token">Regenerate Token<a class="td-heading-self-link" href="#regenerate-token" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command could require administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/tokens/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Optional Parameters:</p> +<pre tabindex="0"><code>{ + &#34;username&#34; : &#34;test&#34; + &#34;all&#34; : &#34;true&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{&#34;token&#34;: &#34;abc123&#34;} +</code></pre><h3 id="change-password">Change Password<a class="td-heading-self-link" href="#change-password" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/auth/passwd/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{ + &#34;password&#34;: &#34;foo&#34;, + &#34;new_password&#34;: &#34;bar&#34; +} +</code></pre><p>Optional parameters:</p> +<pre tabindex="0"><code>{&#34;username&#34;: &#34;testuser&#34;} +</code></pre><blockquote> +<p><strong>note</strong></p> +<p>Using the <code>username</code> parameter requires administrative privileges and makes the <code>password</code> parameter optional.</p> +</blockquote> +<p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h2 id="applications">Applications<a class="td-heading-self-link" href="#applications" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-applications">List all Applications<a class="td-heading-self-link" href="#list-all-applications" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;structure&#34;: {}, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;url&#34;: &#34;example-go.example.com&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; + } + ] +} +</code></pre><h3 id="create-an-application">Create an Application<a class="td-heading-self-link" href="#create-an-application" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 +</code></pre><p>Optional parameters:</p> +<pre tabindex="0"><code>{&#34;id&#34;: &#34;example-go&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;structure&#34;: {}, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;url&#34;: &#34;example-go.example.com&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="destroy-an-application">Destroy an Application<a class="td-heading-self-link" href="#destroy-an-application" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/apps/example-go/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h3 id="list-application-details">List Application Details<a class="td-heading-self-link" href="#list-application-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;structure&#34;: {}, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;url&#34;: &#34;example-go.example.com&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="update-application-details">Update Application Details<a class="td-heading-self-link" href="#update-application-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Optional parameters:</p> +<pre tabindex="0"><code>{ + &#34;owner&#34;: &#34;test&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 1.8.0 +Content-Type: application/json +</code></pre><h3 id="retrieve-application-logs">Retrieve Application Logs<a class="td-heading-self-link" href="#retrieve-application-logs" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/logs/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Optional URL Query Parameters:</p> +<pre tabindex="0"><code>?log_lines= +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: text/plain + +&#34;16:51:14 drycc[api]: test created initial release\n&#34; +</code></pre><h3 id="run-one-off-commands">Run one-off Commands<a class="td-heading-self-link" href="#run-one-off-commands" aria-label="Heading self-link"></a></h3> +<pre tabindex="0"><code>POST /v2/apps/example-go/run/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;command&#34;: &#34;echo hi&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{&#34;exit_code&#34;: 0, &#34;output&#34;: &#34;hi\n&#34;} +</code></pre><h2 id="certificates">Certificates<a class="td-heading-self-link" href="#certificates" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-certificates">List all Certificates<a class="td-heading-self-link" href="#list-all-certificates" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/certs HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;id&#34;: 22, + &#34;owner&#34;: &#34;test&#34;, + &#34;san&#34;: [], + &#34;domains&#34;: [], + &#34;created&#34;: &#34;2016-06-22.32.34:20Z&#34;, + &#34;updated&#34;: &#34;2016-06-22.32.34:20Z&#34;, + &#34;name&#34;: &#34;foo&#34;, + &#34;common_name&#34;: &#34;bar.com&#34;, + &#34;fingerprint&#34;: &#34;7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0&#34;, + &#34;expires&#34;: &#34;2017-01-14T23:57:57Z&#34;, + &#34;starts&#34;: &#34;2016-01-15T23:57:57Z&#34;, + &#34;issuer&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34;, + &#34;subject&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34; + } + ] +} +</code></pre><h3 id="get-certificate-details">Get Certificate Details<a class="td-heading-self-link" href="#get-certificate-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/certs/foo HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;id&#34;: 22, + &#34;owner&#34;: &#34;test&#34;, + &#34;san&#34;: [], + &#34;domains&#34;: [], + &#34;created&#34;: &#34;2016-06-22.32.34:20Z&#34;, + &#34;updated&#34;: &#34;2016-06-22.32.34:20Z&#34;, + &#34;name&#34;: &#34;foo&#34;, + &#34;common_name&#34;: &#34;bar.com&#34;, + &#34;fingerprint&#34;: &#34;7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0&#34;, + &#34;expires&#34;: &#34;2017-01-14T23:57:57Z&#34;, + &#34;starts&#34;: &#34;2016-01-15T23:57:57Z&#34;, + &#34;issuer&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34;, + &#34;subject&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34; +} +</code></pre><h3 id="create-certificate">Create Certificate<a class="td-heading-self-link" href="#create-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/certs/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{ + &#34;name&#34;: &#34;foo&#34; + &#34;certificate&#34;: &#34;-----BEGIN CERTIFICATE-----&#34;, + &#34;key&#34;: &#34;-----BEGIN RSA PRIVATE KEY-----&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;id&#34;: 22, + &#34;owner&#34;: &#34;test&#34;, + &#34;san&#34;: [], + &#34;domains&#34;: [], + &#34;created&#34;: &#34;2016-06-22.32.34:20Z&#34;, + &#34;updated&#34;: &#34;2016-06-22.32.34:20Z&#34;, + &#34;name&#34;: &#34;foo&#34;, + &#34;common_name&#34;: &#34;bar.com&#34;, + &#34;fingerprint&#34;: &#34;7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0&#34;, + &#34;expires&#34;: &#34;2017-01-14T23:57:57Z&#34;, + &#34;starts&#34;: &#34;2016-01-15T23:57:57Z&#34;, + &#34;issuer&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34;, + &#34;subject&#34;: &#34;/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc&#34; +} +</code></pre><h3 id="destroy-a-certificate">Destroy a Certificate<a class="td-heading-self-link" href="#destroy-a-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/certs/foo HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h3 id="attach-a-domain-to-a-certificate">Attach a Domain to a Certificate<a class="td-heading-self-link" href="#attach-a-domain-to-a-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/certs/foo/domain/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{ + &#34;domain&#34;: &#34;test.com&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h3 id="remove-a-domain-from-a-certificate">Remove a Domain from a Certificate<a class="td-heading-self-link" href="#remove-a-domain-from-a-certificate" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/certs/foo/domain/test.com/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h3 id="enable-or-disable-tls">Enable or disable TLS<a class="td-heading-self-link" href="#enable-or-disable-tls" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/tls/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{ + &#34;https_enforced&#34;: true +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;https_enforced&#34;: true, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="get-tls-status">Get TLS status<a class="td-heading-self-link" href="#get-tls-status" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/tls/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;https_enforced&#34;: false, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h2 id="pods">Pods<a class="td-heading-self-link" href="#pods" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-pods">List all Pods<a class="td-heading-self-link" href="#list-all-pods" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/pods/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;results&#34;: [ + { + &#34;name&#34;: &#34;go-v2-web-e7dej&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2014-01-01T00:00:00Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } + ] +} +</code></pre><h3 id="list-all-pods-by-type">List all Pods by Type<a class="td-heading-self-link" href="#list-all-pods-by-type" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/pods/web/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;results&#34;: [ + { + &#34;name&#34;: &#34;go-v2-web-e7dej&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2014-01-01T00:00:00Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } + ] +} +</code></pre><h3 id="restart-all-pods">Restart All Pods<a class="td-heading-self-link" href="#restart-all-pods" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/pods/restart/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +[ + { + &#34;name&#34;: &#34;go-v2-web-atots&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2016-04-11T21:07:54Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } +] +</code></pre><h3 id="restart-pods-by-type">Restart Pods by Type<a class="td-heading-self-link" href="#restart-pods-by-type" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/pods/web/restart/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +[ + { + &#34;name&#34;: &#34;go-v2-web-atots&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2016-04-11T21:07:54Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } +] +</code></pre><h3 id="restart-pods-by-type-and-name">Restart Pods by Type and Name<a class="td-heading-self-link" href="#restart-pods-by-type-and-name" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/pods/go-v2-web-atots/restart/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +[ + { + &#34;name&#34;: &#34;go-v2-web-atots&#34;, + &#34;release&#34;: &#34;v2&#34;, + &#34;started&#34;: &#34;2016-04-11T21:07:54Z&#34;, + &#34;state&#34;: &#34;up&#34;, + &#34;type&#34;: &#34;web&#34; + } +] +</code></pre><h3 id="scale-pods">Scale Pods<a class="td-heading-self-link" href="#scale-pods" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/scale/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;web&#34;: 3} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h2 id="configuration">Configuration<a class="td-heading-self-link" href="#configuration" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-configuration">List Application Configuration<a class="td-heading-self-link" href="#list-application-configuration" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/config/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;owner&#34;: &#34;test&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;values&#34;: { + &#34;PLATFORM&#34;: &#34;drycc&#34; + }, + &#34;memory&#34;: {}, + &#34;cpu&#34;: {}, + &#34;tags&#34;: {}, + &#34;healthcheck&#34;: {}, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="create-new-config">Create new Config<a class="td-heading-self-link" href="#create-new-config" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/config/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;values&#34;: {&#34;HELLO&#34;: &#34;world&#34;, &#34;PLATFORM&#34;: &#34;drycc&#34;}} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;owner&#34;: &#34;test&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;values&#34;: { + &#34;DRYCC_APP&#34;: &#34;example-go&#34;, + &#34;DRYCC_RELEASE&#34;: &#34;v3&#34;, + &#34;HELLO&#34;: &#34;world&#34;, + &#34;PLATFORM&#34;: &#34;drycc&#34; + + }, + &#34;memory&#34;: {}, + &#34;cpu&#34;: {}, + &#34;tags&#34;: {}, + &#34;healthcheck&#34;: {}, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="unset-config-variable">Unset Config Variable<a class="td-heading-self-link" href="#unset-config-variable" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/config/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;values&#34;: {&#34;HELLO&#34;: null}} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;owner&#34;: &#34;test&#34;, + &#34;app&#34;: &#34;example-go&#34;, + &#34;values&#34;: { + &#34;DRYCC_APP&#34;: &#34;example-go&#34;, + &#34;DRYCC_RELEASE&#34;: &#34;v4&#34;, + &#34;PLATFORM&#34;: &#34;drycc&#34; + }, + &#34;memory&#34;: {}, + &#34;cpu&#34;: {}, + &#34;tags&#34;: {}, + &#34;healthcheck&#34;: {}, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h2 id="domains">Domains<a class="td-heading-self-link" href="#domains" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-domains">List Application Domains<a class="td-heading-self-link" href="#list-application-domains" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/domains/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;domain&#34;: &#34;example.example.com&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34; + } + ] +} +</code></pre><h3 id="add-domain">Add Domain<a class="td-heading-self-link" href="#add-domain" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/domains/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{&#39;domain&#39;: &#39;example.example.com&#39;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;domain&#34;: &#34;example.example.com&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34; +} +</code></pre><h3 id="remove-domain">Remove Domain<a class="td-heading-self-link" href="#remove-domain" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/apps/example-go/domains/example.example.com HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h2 id="builds">Builds<a class="td-heading-self-link" href="#builds" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-builds">List Application Builds<a class="td-heading-self-link" href="#list-application-builds" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/build/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;dockerfile&#34;: &#34;FROM drycc/slugrunner RUN mkdir -p /app WORKDIR /app ENTRYPOINT [\&#34;/runner/init\&#34;] ADD slug.tgz /app ENV GIT_SHA 060da68f654e75fac06dbedd1995d5f8ad9084db&#34;, + &#34;image&#34;: &#34;example-go&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;procfile&#34;: { + &#34;web&#34;: &#34;example-go&#34; + }, + &#34;sha&#34;: &#34;060da68f&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="create-application-build">Create Application Build<a class="td-heading-self-link" href="#create-application-build" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/build/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;image&#34;: &#34;drycc/example-go:latest&#34;} +</code></pre><p>Optional Parameters:</p> +<pre tabindex="0"><code>{ + &#34;procfile&#34;: { + &#34;web&#34;: &#34;./cmd&#34; + } +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;dockerfile&#34;: &#34;&#34;, + &#34;image&#34;: &#34;drycc/example-go:latest&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;procfile&#34;: {}, + &#34;sha&#34;: &#34;&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h2 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-releases">List Application Releases<a class="td-heading-self-link" href="#list-application-releases" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/releases/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;count&#34;: 3, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: &#34;2.3d8e4b-600e-4425-a85c-ffc7ea607f61&#34;, + &#34;config&#34;: &#34;ed637ceb-5d32-44bd-9406-d326a777a513&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test changed nothing&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 3 + }, + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: &#34;2.3d8e4b-600e-4425-a85c-ffc7ea607f61&#34;, + &#34;config&#34;: &#34;95bd6dea-1685-4f78-a03d-fd7270b058d1&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test deployed 060da68&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 2 + }, + { + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: null, + &#34;config&#34;: &#34;95bd6dea-1685-4f78-a03d-fd7270b058d1&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test created initial release&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 1 + } + ] +} +</code></pre><h3 id="list-release-details">List Release Details<a class="td-heading-self-link" href="#list-release-details" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/releases/v2/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;app&#34;: &#34;example-go&#34;, + &#34;build&#34;: null, + &#34;config&#34;: &#34;95bd6dea-1685-4f78-a03d-fd7270b058d1&#34;, + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;summary&#34;: &#34;test created initial release&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34;, + &#34;version&#34;: 1 +} +</code></pre><h3 id="rollback-release">Rollback Release<a class="td-heading-self-link" href="#rollback-release" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/releases/rollback/ HTTP/1.1 +Host: drycc.example.com +Content-Type: application/json +Authorization: token abc123 + +{&#34;version&#34;: 1} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{&#34;version&#34;: 5} +</code></pre><h2 id="keys">Keys<a class="td-heading-self-link" href="#keys" aria-label="Heading self-link"></a></h2> +<h3 id="list-keys">List Keys<a class="td-heading-self-link" href="#list-keys" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/keys/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;test@example.com&#34;, + &#34;owner&#34;: &#34;test&#34;, + &#34;public&#34;: &#34;ssh-rsa &lt;...&gt;&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; + } + ] +} +</code></pre><h3 id="add-key-to-user">Add Key to User<a class="td-heading-self-link" href="#add-key-to-user" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/keys/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{ + &#34;id&#34;: &#34;example&#34;, + &#34;public&#34;: &#34;ssh-rsa &lt;...&gt;&#34; +} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;created&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;id&#34;: &#34;example&#34;, + &#34;owner&#34;: &#34;example&#34;, + &#34;public&#34;: &#34;ssh-rsa &lt;...&gt;&#34;, + &#34;updated&#34;: &#34;2014-01-01T00:00:00UTC&#34;, + &#34;uuid&#34;: &#34;de1bf5b5-4a72-4f94-a10c-d2a3741cdf75&#34; +} +</code></pre><h3 id="remove-key-from-user">Remove Key from User<a class="td-heading-self-link" href="#remove-key-from-user" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/keys/example HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h2 id="permissions">Permissions<a class="td-heading-self-link" href="#permissions" aria-label="Heading self-link"></a></h2> +<h3 id="list-application-permissions">List Application Permissions<a class="td-heading-self-link" href="#list-application-permissions" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This does not include the app owner.</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/apps/example-go/perms/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;users&#34;: [ + &#34;test&#34;, + &#34;foo&#34; + ] +} +</code></pre><h3 id="create-application-permission">Create Application Permission<a class="td-heading-self-link" href="#create-application-permission" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/apps/example-go/perms/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{&#34;username&#34;: &#34;example&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h3 id="remove-application-permission">Remove Application Permission<a class="td-heading-self-link" href="#remove-application-permission" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/apps/example-go/perms/example HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h3 id="list-administrators">List Administrators<a class="td-heading-self-link" href="#list-administrators" aria-label="Heading self-link"></a></h3> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/admin/perms/ HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;count&#34;: 2, + &#34;next&#34;: null + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;username&#34;: &#34;test&#34;, + &#34;is_superuser&#34;: true + }, + { + &#34;username&#34;: &#34;foo&#34;, + &#34;is_superuser&#34;: true + } + ] +} +</code></pre><h3 id="grant-user-administrative-privileges">Grant User Administrative Privileges<a class="td-heading-self-link" href="#grant-user-administrative-privileges" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command requires administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>POST /v2/admin/perms HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 + +{&#34;username&#34;: &#34;example&#34;} +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 201 CREATED +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h3 id="remove-users-administrative-privileges">Remove User&rsquo;s Administrative Privileges<a class="td-heading-self-link" href="#remove-users-administrative-privileges" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command requires administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>DELETE /v2/admin/perms/example HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 204 NO CONTENT +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +</code></pre><h2 id="users">Users<a class="td-heading-self-link" href="#users" aria-label="Heading self-link"></a></h2> +<h3 id="list-all-users">List all users<a class="td-heading-self-link" href="#list-all-users" aria-label="Heading self-link"></a></h3> +<blockquote> +<p><strong>note</strong></p> +<p>This command requires administrative privileges</p> +</blockquote> +<p>Example Request:</p> +<pre tabindex="0"><code>GET /v2/users HTTP/1.1 +Host: drycc.example.com +Authorization: token abc123 +</code></pre><p>Example Response:</p> +<pre tabindex="0"><code>HTTP/1.1 200 OK +DRYCC_API_VERSION: 2.3 +DRYCC_PLATFORM_VERSION: 2.3.0 +Content-Type: application/json + +{ + &#34;count&#34;: 1, + &#34;next&#34;: null, + &#34;previous&#34;: null, + &#34;results&#34;: [ + { + &#34;id&#34;: 1, + &#34;last_login&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;is_superuser&#34;: true, + &#34;username&#34;: &#34;test&#34;, + &#34;first_name&#34;: &#34;test&#34;, + &#34;last_name&#34;: &#34;testerson&#34;, + &#34;email&#34;: &#34;test@example.com&#34;, + &#34;is_staff&#34;: true, + &#34;is_active&#34;: true, + &#34;date_joined&#34;: &#34;2014-10-19T22:01:00.601Z&#34;, + &#34;groups&#34;: [], + &#34;user_permissions&#34;: [] + } + ] +} +</code></pre> + + + + + diff --git a/docs/roadmap/_print/index.html b/docs/roadmap/_print/index.html new file mode 100644 index 000000000..fb277ceb5 --- /dev/null +++ b/docs/roadmap/_print/index.html @@ -0,0 +1,515 @@ + + + + + + + + + + + + + + + + + + + + + +Roadmap | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+ + + + + +
+
+

+This is the multi-page printable view of this section. +Click here to print. +

+Return to the regular view of this page. +

+
+ + + +

Roadmap

+
Browse the ever-growing list of up-to-date, community driven roadmaps.
+ + + + + + + +
+ +
+
+ + + + + + + + + + + + + + + + +
+ +

1 - Planning Process

+
Drycc features a lightweight process that emphasizes openness and ensures every community member can be an integral part of planning for the future.
+

The Role of Maintainers

+

Maintainers lead the Drycc projects. Their duties include proposing the Roadmap, reviewing and integrating contributions and maintaining the vision of the project.

+

Open Roadmap

+

The Drycc Roadmap is a community document. While Maintainers propose the Roadmap, it gets discussed and refined in Release Planning Meetings.

+

Contributing to the Roadmap

+

Proposals and issues can be opened by anyone. Every member of the community is welcome to participate in the discussion by providing feedback and/or offering counter-proposals.

+

Release Milestones

+

The Roadmap gets delivered progressively via the Release Schedule. Releases are defined during Release Planning Meetings and managed using GitHub Milestones which track specific deliverables and work-in-progress.

+

Release Planning Meetings

+

Major decisions affecting the Roadmap are discussed during Release Planning Meetings on the first Thursday of each month, aligned with the Release Schedule.

+

Release Planning Meetings are open to the public with access coordinated via the Drycc #community Slack channel. +Notes from past meetings are below, along with links to a recording of the entire meeting on YouTube.

+

Credits

+

Thanks to Amy Lindburg and our friends at Podman for their inspiration.

+ +
+ + + + + + + + + + + +
+ +

2 - Drycc Workflow Roadmap

+
Drycc roadmap is community driven and managed through GitHub.
+

Drycc Workflow Roadmap

+

The Drycc Workflow Roadmap is a community document created as part of the open +Planning Process. Each roadmap item describes a high-level capability or +grouping of features that are deemed important to the future of Drycc.

+

Given the project’s rapid Release Schedule, roadmap +items are designed to provide a sense of direction over many releases.

+

Interactive drycc run /bin/bash

+

Provide the ability for developers to launch an interactive terminal session in +their application environment.

+

Related issues:

+ +

Log Streaming

+

Stream application logs via drycc logs -f https://github.com/drycc/drycc/issues/465

+

Teams and Permissions

+

Teams and Permissions represents a more flexible permissions model to allow +more nuanced control to applications, capabilities and resources on the +platform. There have been a number of proposals in this area which need to be +reconciled for Drycc Workflow before we begin implementation.

+

Related issues:

+ +

Monitoring

+ +

Workflow Addons/Services

+

Developers should be able to quickly and easily provision application +dependencies using a services or addon abstraction. +https://github.com/drycc/drycc/issues/231

+

Inbound/Outbound Webhooks

+

Drycc Workflow should be able to send and receive webhooks from external +systems. Facilitating integration with third party services like GitHub, +Gitlab, Slack, Hipchat.

+ + +
+ + + + + + + + + + + +
+ +

3 - Releases

+
Drycc’s release model allows applications to record and roll back to previous versions.
+

Drycc uses a continuous delivery approach for creating releases. Every merged commit that passes +testing results in a deliverable that can be given a semantic version tag and shipped.

+

The master git branch of a project should always work. Only changes considered ready to be +released publicly are merged.

+

Components Release as Needed

+

Drycc components release new versions as often as needed. Fixing a high priority bug requires the +project maintainer to create a new patch release. Merging a backward-compatible feature implies +a minor release.

+

By releasing often, each component release becomes a safe and routine event. This makes it faster +and easier for users to obtain specific fixes. Continuous delivery also reduces the work +necessary to release a product such as Drycc Workflow, which integrates several components.

+

“Components” applies not just to Drycc Workflow projects, but also to development and release +tools, to Container base images, and to other Drycc projects that do semantic version releases.

+

See “How to Release a Component” for more detail.

+

Workflow Releases Each Month

+

Drycc Workflow has a regular, public release cadence. From v2.8.0 onward, new Workflow feature +releases arrive on the first Thursday of each month. Patch releases are created at any time, +as needed. GitHub milestones are used to communicate the content and timing of major and minor +releases, and longer-term planning is visible at the Roadmap.

+

Workflow release timing is not linked to specific features. If a feature is merged before the +release date, it is included in the next release.

+

See “How to Release Workflow” for more detail.

+

Semantic Versioning

+

Drycc releases comply with semantic versioning, with the “public API” broadly +defined as:

+
    +
  • REST, gRPC, or other API that is network-accessible
  • +
  • Library or framework API intended for public use
  • +
  • “Pluggable” socket-level protocols users can redirect
  • +
  • CLI commands and output formats
  • +
+

In general, changes to anything a user might reasonably link to, customize, or integrate with +should be backward-compatible, or else require a major release. Drycc users can be confident that +upgrading to a patch or to a minor release will not break anything.

+

How to Release a Component

+

Most Drycc projects are “components” which produce a Container image or binary executable as a +deliverable. This section leads a maintainer through creating a component release.

+

Step 1: Update Code and Run the Release Tool

+

Major or minor releases should happen on the master branch. Patch releases +should check out the previous release tag and cherry-pick specific commits from master.

+

Note: if a patch release, the release artifact will have to be manually promoted by triggering +the component-promote job with the following values:

+
COMPONENT_NAME=<component name>
+COMPONENT_SHA=<patch commit sha>
+

Make sure you have the dryccrel release tool in your search $PATH.

+

Run dryccrel release once with a fake semver tag to proofread the changelog content. (If HEAD +of master is not what is intended for the release, add the --sha flag as described +in dryccrel release --help.)

+
$ dryccrel release controller v0.0.0
+Doing a dry run of the component release...
+skipping commit 943a49267eeb28546819a266654806cfcbae0e38
+
+Creating changelog for controller with tag v2.8.1 through commit 943a49267eeb28546819a266654806cfcbae0e38
+
+### v2.8.1 -> v0.0.0
+
+#### Fixes
+
+- [`615b834`](https://github.com/drycc/controller/commit/615b834f39cb68a854cc1f1e2f0f82d862ea2731) boot: Ensure DRYCC_DEBUG==true for debug output
+

Based on the changelog content, determine whether the component deserves a minor or patch +release. Run the command again with that semver tag and --dry-run=false. You will still be +asked for confirmation before the release is created:

+
$ dryccrel release controller v2.8.2 --dry-run=false
+skipping commit 943a49267eeb28546819a266654806cfcbae0e38
+
+Creating changelog for controller with tag v2.8.1 through commit 943a49267eeb28546819a266654806cfcbae0e38
+
+### v2.8.1 -> v2.8.2
+
+
+#### Fixes
+
+- [`615b834`](https://github.com/drycc/controller/commit/615b834f39cb68a854cc1f1e2f0f82d862ea2731) boot: Ensure DRYCC_DEBUG==true for debug output
+
+
+Please review the above changelog contents and ensure:
+  1. All intended commits are mentioned
+  2. The changes agree with the semver release tag (major, minor, or patch)
+
+Create release for Drycc Controller v2.8.2? [y/n]: y
+New release is available at https://github.com/drycc/controller/releases/tag/v2.8.2
+

Step 2: Verify the Component is Available

+

Tagging the component (see Step 1) +starts a CI job that eventually results in an artifact being made available for public download. +Please see the CI flow diagrams for details.

+

Double-check that the artifact is available, either by a podman pull command or by running the +appropriate installer script.

+

If the artifact can’t be downloaded, ensure that its CI release jobs are still in progress, or +fix whatever issue arose in the pipeline. For example, the +master merge pipeline +may have failed to promote the :git-abc1d23 candidate image and needs to be restarted with +that component and commit.

+

If the component has a correlating Kubernetes Helm chart, +this chart will also be packaged, signed and uploaded to its production chart repo. Please +verify it can be fetched (and verified):

+
$ helm fetch oci://registry.drycc.cc/charts/controller --version 1.0.0
+Verification: &{0xc4207ec870 sha256:026e766e918ff28d2a7041bc3d560d149ee7eb0cb84165c9d9d00a3045ff45c3 controller-v1.0.1.tgz}
+

How to Release Workflow

+

Drycc Workflow integrates multiple component releases together with a Kubernetes Helm chart +deliverable. This section leads a maintainer through creating a Workflow release.

+

Step 1: Set Environment Variables

+

Export two environment variables that will be used in later steps:

+
export WORKFLOW_RELEASE=v2.17.0 WORKFLOW_PREV_RELEASE=v2.16.0  # for example
+

Step 2: Tag Supporting Repositories

+

Some Workflow components not in the Helm chart must also be tagged in sync with the release. +Follow the component release process above and ensure that +these components are tagged:

+ +

The version number for drycc/workflow-cli should always match the overall Workflow version +number.

+

Step 3: Create Helm Chart

+

To create and stage a release candidate chart for Workflow, we will build the workflow-chart-stage job with the following parameters:

+

RELEASE_TAG=$WORKFLOW_RELEASE

+

This job will gather all of the latest component release tags and use these to specify the versions of all component charts. +It will then package the Workflow chart, upload it to the staging chart repo and kick off an e2e run against said chart.

+

Step 4: Manual Testing

+

Now it’s time to go above and beyond current CI tests. Create a testing matrix spreadsheet (copying +from the previous document is a good start) and sign up testers to cover all permutations.

+

Testers should pay special attention to the overall user experience, make sure upgrading from +earlier versions is smooth, and cover various storage configurations and Kubernetes versions and +infrastructure providers.

+

When showstopper-level bugs are found, the process is as follows:

+
    +
  1. Create a component PR that fixes the bug.
  2. +
  3. Once the PR passes and is reviewed, merge it and do a new +component release
  4. +
  5. Trigger the same workflow-chart-stage job as mentioned in Step 3 to upload the newly-generated Workflow release candidate chart to staging.
  6. +
+

Step 5: Release the Chart

+

When testing has completed without uncovering any new showstopper bugs, kick off the workflow-chart-release job with the following parameter:

+

RELEASE_TAG=$WORKFLOW_RELEASE

+

This job will copy the release candidate chart (now approved by CI and manual testing) from the staging repo to the production repo, signing +it if it has not done so already.

+

Step 6: Assemble Master Changelog

+

Each component already updated its release notes on GitHub with CHANGELOG content. We’ll now +generate the master changelog for the Workflow chart, consisting of all component and auxilliary repo changes.

+

We’ll employ the requirements.lock file from the WORKFLOW_PREV_RELEASE chart, as well as a repo-to-chart-name mapping file, this time invoking dryccrel changelog global to get all component changes between +the chart versions existing in the WORKFLOW_PREV_RELEASE chart and the most recent releases existing in GitHub. +(Therefore, if there are any unreleased commits in a component repo, they will not appear here):

+
helm fetch --untar oci://registry.drycc.cc/charts/workflow --version $WORKFLOW_PREV_RELEASE
+dryccrel changelog global workflow/requirements.lock map.json > changelog-$WORKFLOW_RELEASE.md
+

This master changelog should then be placed into a single gist. The file will also be added to the documentation +update PR created in the next step.

+

Step 7: Update Documentation

+

Create a new pull request at drycc/workflow that updates version references to the new release. +Use git grep $WORKFLOW_PREV_RELEASE to find any references, but be careful not to change +CHANGELOG.md.

+

Place the $WORKFLOW_RELEASE master changelog generated in Step 7 in the changelogs directory. +Make sure to add a header to the page to make it clear that this is for a Workflow release, e.g.:

+
## Workflow v2.16.0 -> v2.17.0
+

Once the PR has been reviewed and merged, do a component release of +drycc/workflow itself. The version number for drycc/workflow should always match the +overall Workflow version number.

+

Step 8: Close GitHub Milestones

+

Create a pull request at seed-repo to close the release +milestone and create the next one. When changes are merged to seed-repo, milestones on all +relevant projects will be updated. If there are open issues attached to the milestone, move them +to the next upcoming milestone before merging the pull request.

+

Milestones map to Drycc Workflow releases in drycc/workflow. These milestones do not correspond +to individual component release tags.

+

Step 9: Release Workflow CLI Stable

+

Now that the $WORKFLOW_RELEASE version of Workflow CLI has been vetted, we can push stable artifacts based on this version.

+

Kick off https://ci.drycc.info/job/workflow-cli-build-stable/ with the TAG build parameter of $WORKFLOW_RELEASE +and then verify stable artifacts are available and appropriately updated after the job completes:

+
$ curl -sfL https://www.drycc.cc/install-cli.sh | bash -
+$ ./drycc version
+# (Should show $WORKFLOW_RELEASE)
+

Step 10: Let Everyone Know

+

Let the rest of the team know they can start blogging and tweeting about the new Workflow release. +Post a message to the #company channel on Slack. Include a link to the released chart and to the +master CHANGELOG:

+
@here Drycc Workflow v2.17.0 is now live!
+Master CHANGELOG: https://drycc.info/docs/workflow/changelogs/v2.17.0/
+

You’re done with the release. Nice job!

+ +
+ + + + + + + + + +
+
+
+ + +
+ + + + + + diff --git a/docs/roadmap/index.html b/docs/roadmap/index.html new file mode 100644 index 000000000..04acba662 --- /dev/null +++ b/docs/roadmap/index.html @@ -0,0 +1,472 @@ + + + + + + + + + + + + + + + + + + + + + +Roadmap | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Roadmap

+
Browse the ever-growing list of up-to-date, community driven roadmaps.
+ + +
+ + +
+
+
+ Planning Process +
+

Drycc features a lightweight process that emphasizes openness and ensures every community member can be an integral part of planning for the future.

+
+
+
+ Drycc Workflow Roadmap +
+

Drycc roadmap is community driven and managed through GitHub.

+
+
+
+ Releases +
+

Drycc’s release model allows applications to record and roll back to previous versions.

+
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+
+ +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/roadmap/index.xml b/docs/roadmap/index.xml new file mode 100644 index 000000000..c528643e3 --- /dev/null +++ b/docs/roadmap/index.xml @@ -0,0 +1,292 @@ + + + Drycc – Roadmap + /docs/roadmap/ + Recent content in Roadmap on Drycc + Hugo -- gohugo.io + en + + + + + + + + + + + Docs: Planning Process + /docs/roadmap/planning-process/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/roadmap/planning-process/ + + + + <h2 id="the-role-of-maintainers">The Role of Maintainers<a class="td-heading-self-link" href="#the-role-of-maintainers" aria-label="Heading self-link"></a></h2> +<p><a href="../contributing/maintainers.md">Maintainers</a> lead the Drycc projects. Their duties include proposing the Roadmap, reviewing and integrating contributions and maintaining the vision of the project.</p> +<h2 id="open-roadmap">Open Roadmap<a class="td-heading-self-link" href="#open-roadmap" aria-label="Heading self-link"></a></h2> +<p>The <a href="/docs/roadmap/roadmap/">Drycc Roadmap</a> is a community document. While Maintainers propose the Roadmap, it gets discussed and refined in Release Planning Meetings.</p> +<h2 id="contributing-to-the-roadmap">Contributing to the Roadmap<a class="td-heading-self-link" href="#contributing-to-the-roadmap" aria-label="Heading self-link"></a></h2> +<p>Proposals and issues can be opened by anyone. Every member of the <a href="../contributing/community.md">community</a> is welcome to participate in the discussion by providing feedback and/or offering counter-proposals.</p> +<h2 id="release-milestones">Release Milestones<a class="td-heading-self-link" href="#release-milestones" aria-label="Heading self-link"></a></h2> +<p>The Roadmap gets delivered progressively via the <a href="/docs/roadmap/releases/">Release Schedule</a>. Releases are defined during Release Planning Meetings and managed using GitHub Milestones which track specific deliverables and work-in-progress.</p> +<h2 id="release-planning-meetings">Release Planning Meetings<a class="td-heading-self-link" href="#release-planning-meetings" aria-label="Heading self-link"></a></h2> +<p>Major decisions affecting the Roadmap are discussed during Release Planning Meetings on the first Thursday of each month, aligned with the <a href="/docs/roadmap/releases/">Release Schedule</a>.</p> +<p>Release Planning Meetings are open to the public with access coordinated via the <a href="https://slack.drycc.cc">Drycc #community Slack channel</a>. +Notes from past meetings are below, along with links to a recording of the entire meeting on YouTube.</p> +<h2 id="credits">Credits<a class="td-heading-self-link" href="#credits" aria-label="Heading self-link"></a></h2> +<p>Thanks to <a href="https://twitter.com/amylindburg">Amy Lindburg</a> and our friends at <a href="https://podman.io/">Podman</a> for their inspiration.</p> + + + + + + Docs: Drycc Workflow Roadmap + /docs/roadmap/roadmap/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/roadmap/roadmap/ + + + + <h1 id="drycc-workflow-roadmap">Drycc Workflow Roadmap<a class="td-heading-self-link" href="#drycc-workflow-roadmap" aria-label="Heading self-link"></a></h1> +<p>The Drycc Workflow Roadmap is a community document created as part of the open +<a href="/docs/roadmap/planning-process/">Planning Process</a>. Each roadmap item describes a high-level capability or +grouping of features that are deemed important to the future of Drycc.</p> +<p>Given the project&rsquo;s rapid <a href="/docs/roadmap/releases/">Release Schedule</a>, roadmap +items are designed to provide a sense of direction over many releases.</p> +<h2 id="interactive-drycc-run-binbash">Interactive <code>drycc run /bin/bash</code><a class="td-heading-self-link" href="#interactive-drycc-run-binbash" aria-label="Heading self-link"></a></h2> +<p>Provide the ability for developers to launch an interactive terminal session in +their application environment.</p> +<p>Related issues:</p> +<ul> +<li><a href="https://github.com/drycc/workflow-cli/issues/28">https://github.com/drycc/workflow-cli/issues/28</a></li> +<li><a href="https://github.com/drycc/drycc/issues/117">https://github.com/drycc/drycc/issues/117</a></li> +</ul> +<h2 id="log-streaming">Log Streaming<a class="td-heading-self-link" href="#log-streaming" aria-label="Heading self-link"></a></h2> +<p>Stream application logs via <code>drycc logs -f</code> <a href="https://github.com/drycc/drycc/issues/465">https://github.com/drycc/drycc/issues/465</a></p> +<h2 id="teams-and-permissions">Teams and Permissions<a class="td-heading-self-link" href="#teams-and-permissions" aria-label="Heading self-link"></a></h2> +<p>Teams and Permissions represents a more flexible permissions model to allow +more nuanced control to applications, capabilities and resources on the +platform. There have been a number of proposals in this area which need to be +reconciled for Drycc Workflow before we begin implementation.</p> +<p>Related issues:</p> +<ul> +<li>Deploy Keys: <a href="https://github.com/drycc/drycc/issues/3875">https://github.com/drycc/drycc/issues/3875</a></li> +<li>Teams: <a href="https://github.com/drycc/drycc/issues/4173">https://github.com/drycc/drycc/issues/4173</a></li> +<li>Fine grained permissions: <a href="https://github.com/drycc/drycc/issues/4150">https://github.com/drycc/drycc/issues/4150</a></li> +<li>Admins create apps only: <a href="https://github.com/drycc/drycc/issues/4052">https://github.com/drycc/drycc/issues/4052</a></li> +<li>Admin Certificate Permissions: <a href="https://github.com/drycc/drycc/issues/4576#issuecomment-170987223">https://github.com/drycc/drycc/issues/4576#issuecomment-170987223</a></li> +</ul> +<h2 id="monitoring">Monitoring<a class="td-heading-self-link" href="#monitoring" aria-label="Heading self-link"></a></h2> +<ul> +<li><input disabled="" type="checkbox"> Define and deliver alerts with Kapacitor: <a href="https://github.com/drycc/monitor/issues/44">https://github.com/drycc/monitor/issues/44</a></li> +</ul> +<h2 id="workflow-addonsservices">Workflow Addons/Services<a class="td-heading-self-link" href="#workflow-addonsservices" aria-label="Heading self-link"></a></h2> +<p>Developers should be able to quickly and easily provision application +dependencies using a services or addon abstraction. +<a href="https://github.com/drycc/drycc/issues/231">https://github.com/drycc/drycc/issues/231</a></p> +<h2 id="inboundoutbound-webhooks">Inbound/Outbound Webhooks<a class="td-heading-self-link" href="#inboundoutbound-webhooks" aria-label="Heading self-link"></a></h2> +<p>Drycc Workflow should be able to send and receive webhooks from external +systems. Facilitating integration with third party services like GitHub, +Gitlab, Slack, Hipchat.</p> +<ul> +<li><input checked="" disabled="" type="checkbox"> Send webhook on platform events: <a href="https://github.com/drycc/drycc/issues/1486">https://github.com/drycc/drycc/issues/1486</a> (Workflow v2.10)</li> +</ul> + + + + + + Docs: Releases + /docs/roadmap/releases/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/roadmap/releases/ + + + + <p>Drycc uses a <a href="https://en.wikipedia.org/wiki/Continuous_delivery">continuous delivery</a> approach for creating releases. Every merged commit that passes +testing results in a deliverable that can be given a <a href="http://semver.org">semantic version</a> tag and shipped.</p> +<p>The master <code>git</code> branch of a project should always work. Only changes considered ready to be +released publicly are merged.</p> +<h2 id="components-release-as-needed">Components Release as Needed<a class="td-heading-self-link" href="#components-release-as-needed" aria-label="Heading self-link"></a></h2> +<p>Drycc components release new versions as often as needed. Fixing a high priority bug requires the +project maintainer to create a new patch release. Merging a backward-compatible feature implies +a minor release.</p> +<p>By releasing often, each component release becomes a safe and routine event. This makes it faster +and easier for users to obtain specific fixes. Continuous delivery also reduces the work +necessary to release a product such as Drycc Workflow, which integrates several components.</p> +<p>&ldquo;Components&rdquo; applies not just to Drycc Workflow projects, but also to development and release +tools, to Container base images, and to other Drycc projects that do <a href="http://semver.org">semantic version</a> releases.</p> +<p>See &ldquo;<a href="/docs/roadmap/releases/#how-to-release-a-component">How to Release a Component</a>&rdquo; for more detail.</p> +<h2 id="workflow-releases-each-month">Workflow Releases Each Month<a class="td-heading-self-link" href="#workflow-releases-each-month" aria-label="Heading self-link"></a></h2> +<p>Drycc Workflow has a regular, public release cadence. From v2.8.0 onward, new Workflow feature +releases arrive on the first Thursday of each month. Patch releases are created at any time, +as needed. GitHub milestones are used to communicate the content and timing of major and minor +releases, and longer-term planning is visible at <a href="/docs/roadmap/roadmap/">the Roadmap</a>.</p> +<p>Workflow release timing is not linked to specific features. If a feature is merged before the +release date, it is included in the next release.</p> +<p>See &ldquo;<a href="/docs/roadmap/releases/#how-to-release-workflow">How to Release Workflow</a>&rdquo; for more detail.</p> +<h2 id="semantic-versioning">Semantic Versioning<a class="td-heading-self-link" href="#semantic-versioning" aria-label="Heading self-link"></a></h2> +<p>Drycc releases comply with <a href="http://semver.org">semantic versioning</a>, with the &ldquo;public API&rdquo; broadly +defined as:</p> +<ul> +<li>REST, gRPC, or other API that is network-accessible</li> +<li>Library or framework API intended for public use</li> +<li>&ldquo;Pluggable&rdquo; socket-level protocols users can redirect</li> +<li>CLI commands and output formats</li> +</ul> +<p>In general, changes to anything a user might reasonably link to, customize, or integrate with +should be backward-compatible, or else require a major release. Drycc users can be confident that +upgrading to a patch or to a minor release will not break anything.</p> +<h2 id="how-to-release-a-component">How to Release a Component<a class="td-heading-self-link" href="#how-to-release-a-component" aria-label="Heading self-link"></a></h2> +<p>Most Drycc projects are &ldquo;components&rdquo; which produce a Container image or binary executable as a +deliverable. This section leads a maintainer through creating a component release.</p> +<h3 id="step-1-update-code-and-run-the-release-tool">Step 1: Update Code and Run the Release Tool<a class="td-heading-self-link" href="#step-1-update-code-and-run-the-release-tool" aria-label="Heading self-link"></a></h3> +<p>Major or minor releases should happen on the master branch. Patch releases +should check out the previous release tag and cherry-pick specific commits from master.</p> +<p><strong>Note:</strong> if a patch release, the release artifact will have to be manually promoted by triggering +the <a href="https://ci.drycc.info/job/component-promote">component-promote</a> job with the following values:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#000">COMPONENT_NAME</span><span style="color:#ce5c00;font-weight:bold">=</span>&lt;component name&gt; +</span></span><span style="display:flex;"><span><span style="color:#000">COMPONENT_SHA</span><span style="color:#ce5c00;font-weight:bold">=</span>&lt;patch commit sha&gt; +</span></span></code></pre></div><p>Make sure you have the <a href="https://github.com/drycc/dryccrel">dryccrel</a> release tool in your search <code>$PATH</code>.</p> +<p>Run <code>dryccrel release</code> once with a fake semver tag to proofread the changelog content. (If <code>HEAD</code> +of master is not what is intended for the release, add the <code>--sha</code> flag as described +in <code>dryccrel release --help</code>.)</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ dryccrel release controller v0.0.0 +</span></span><span style="display:flex;"><span>Doing a dry run of the component release... +</span></span><span style="display:flex;"><span>skipping commit 943a49267eeb28546819a266654806cfcbae0e38 +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span>Creating changelog <span style="color:#204a87;font-weight:bold">for</span> controller with tag v2.8.1 through commit 943a49267eeb28546819a266654806cfcbae0e38 +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">### v2.8.1 -&gt; v0.0.0</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">#### Fixes</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span>- <span style="color:#ce5c00;font-weight:bold">[</span><span style="color:#4e9a06">`</span>615b834<span style="color:#4e9a06">`</span><span style="color:#ce5c00;font-weight:bold">](</span>https://github.com/drycc/controller/commit/615b834f39cb68a854cc1f1e2f0f82d862ea2731<span style="color:#ce5c00;font-weight:bold">)</span> boot: Ensure <span style="color:#000">DRYCC_DEBUG</span><span style="color:#ce5c00;font-weight:bold">==</span><span style="color:#204a87">true</span> <span style="color:#204a87;font-weight:bold">for</span> debug output +</span></span></code></pre></div><p>Based on the changelog content, determine whether the component deserves a minor or patch +release. Run the command again with that semver tag and <code>--dry-run=false</code>. You will still be +asked for confirmation before the release is created:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ dryccrel release controller v2.8.2 --dry-run<span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#204a87">false</span> +</span></span><span style="display:flex;"><span>skipping commit 943a49267eeb28546819a266654806cfcbae0e38 +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span>Creating changelog <span style="color:#204a87;font-weight:bold">for</span> controller with tag v2.8.1 through commit 943a49267eeb28546819a266654806cfcbae0e38 +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">### v2.8.1 -&gt; v2.8.2</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">#### Fixes</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span>- <span style="color:#ce5c00;font-weight:bold">[</span><span style="color:#4e9a06">`</span>615b834<span style="color:#4e9a06">`</span><span style="color:#ce5c00;font-weight:bold">](</span>https://github.com/drycc/controller/commit/615b834f39cb68a854cc1f1e2f0f82d862ea2731<span style="color:#ce5c00;font-weight:bold">)</span> boot: Ensure <span style="color:#000">DRYCC_DEBUG</span><span style="color:#ce5c00;font-weight:bold">==</span><span style="color:#204a87">true</span> <span style="color:#204a87;font-weight:bold">for</span> debug output +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span>Please review the above changelog contents and ensure: +</span></span><span style="display:flex;"><span> 1. All intended commits are mentioned +</span></span><span style="display:flex;"><span> 2. The changes agree with the semver release tag <span style="color:#ce5c00;font-weight:bold">(</span>major, minor, or patch<span style="color:#ce5c00;font-weight:bold">)</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span>Create release <span style="color:#204a87;font-weight:bold">for</span> Drycc Controller v2.8.2? <span style="color:#ce5c00;font-weight:bold">[</span>y/n<span style="color:#ce5c00;font-weight:bold">]</span>: y +</span></span><span style="display:flex;"><span>New release is available at https://github.com/drycc/controller/releases/tag/v2.8.2 +</span></span></code></pre></div><h3 id="step-2-verify-the-component-is-available">Step 2: Verify the Component is Available<a class="td-heading-self-link" href="#step-2-verify-the-component-is-available" aria-label="Heading self-link"></a></h3> +<p>Tagging the component (see <a href="/roadmap/releases/#step-1-update-code-and-run-the-release-tool">Step 1</a>) +starts a CI job that eventually results in an artifact being made available for public download. +Please see the <a href="https://github.com/drycc/jenkins-jobs/#flow">CI flow diagrams</a> for details.</p> +<p>Double-check that the artifact is available, either by a <code>podman pull</code> command or by running the +appropriate installer script.</p> +<p>If the artifact can&rsquo;t be downloaded, ensure that its CI release jobs are still in progress, or +fix whatever issue arose in the pipeline. For example, the +<a href="https://github.com/drycc/jenkins-jobs/#when-a-component-pr-is-merged-to-master">master merge pipeline</a> +may have failed to promote the <code>:git-abc1d23</code> candidate image and needs to be restarted with +that component and commit.</p> +<p>If the component has a correlating <a href="https://github.com/kubernetes/helm">Kubernetes Helm</a> chart, +this chart will also be packaged, signed and uploaded to its production chart repo. Please +verify it can be fetched (and verified):</p> +<pre tabindex="0"><code>$ helm fetch oci://registry.drycc.cc/charts/controller --version 1.0.0 +Verification: &amp;{0xc4207ec870 sha256:026e766e918ff28d2a7041bc3d560d149ee7eb0cb84165c9d9d00a3045ff45c3 controller-v1.0.1.tgz} +</code></pre><h2 id="how-to-release-workflow">How to Release Workflow<a class="td-heading-self-link" href="#how-to-release-workflow" aria-label="Heading self-link"></a></h2> +<p>Drycc Workflow integrates multiple component releases together with a <a href="https://github.com/kubernetes/helm">Kubernetes Helm</a> chart +deliverable. This section leads a maintainer through creating a Workflow release.</p> +<h3 id="step-1-set-environment-variables">Step 1: Set Environment Variables<a class="td-heading-self-link" href="#step-1-set-environment-variables" aria-label="Heading self-link"></a></h3> +<p>Export two environment variables that will be used in later steps:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#204a87">export</span> <span style="color:#000">WORKFLOW_RELEASE</span><span style="color:#ce5c00;font-weight:bold">=</span>v2.17.0 <span style="color:#000">WORKFLOW_PREV_RELEASE</span><span style="color:#ce5c00;font-weight:bold">=</span>v2.16.0 <span style="color:#8f5902;font-style:italic"># for example</span> +</span></span></code></pre></div><h3 id="step-2-tag-supporting-repositories">Step 2: Tag Supporting Repositories<a class="td-heading-self-link" href="#step-2-tag-supporting-repositories" aria-label="Heading self-link"></a></h3> +<p>Some Workflow components not in the Helm chart must also be tagged in sync with the release. +Follow the <a href="/docs/roadmap/releases/#how-to-release-a-component">component release process</a> above and ensure that +these components are tagged:</p> +<ul> +<li><a href="https://github.com/drycc/workflow-cli">drycc/workflow-cli</a></li> +<li><a href="https://github.com/drycc/workflow-e2e">drycc/workflow-e2e</a></li> +</ul> +<p>The version number for <a href="https://github.com/drycc/workflow-cli">drycc/workflow-cli</a> should always match the overall Workflow version +number.</p> +<h3 id="step-3-create-helm-chart">Step 3: Create Helm Chart<a class="td-heading-self-link" href="#step-3-create-helm-chart" aria-label="Heading self-link"></a></h3> +<p>To create and stage a release candidate chart for Workflow, we will build the <a href="https://ci.drycc.info/job/workflow-chart-stage">workflow-chart-stage</a> job with the following parameters:</p> +<p><code>RELEASE_TAG=$WORKFLOW_RELEASE</code></p> +<p>This job will gather all of the latest component release tags and use these to specify the versions of all component charts. +It will then package the Workflow chart, upload it to the staging chart repo and kick off an e2e run against said chart.</p> +<h3 id="step-4-manual-testing">Step 4: Manual Testing<a class="td-heading-self-link" href="#step-4-manual-testing" aria-label="Heading self-link"></a></h3> +<p>Now it&rsquo;s time to go above and beyond current CI tests. Create a testing matrix spreadsheet (copying +from the previous document is a good start) and sign up testers to cover all permutations.</p> +<p>Testers should pay special attention to the overall user experience, make sure upgrading from +earlier versions is smooth, and cover various storage configurations and Kubernetes versions and +infrastructure providers.</p> +<p>When showstopper-level bugs are found, the process is as follows:</p> +<ol> +<li>Create a component PR that fixes the bug.</li> +<li>Once the PR passes and is reviewed, merge it and do a new +<a href="/docs/roadmap/releases/#how-to-release-a-component">component release</a></li> +<li>Trigger the same <code>workflow-chart-stage</code> job as mentioned in Step 3 to upload the newly-generated Workflow release candidate chart to staging.</li> +</ol> +<h3 id="step-5-release-the-chart">Step 5: Release the Chart<a class="td-heading-self-link" href="#step-5-release-the-chart" aria-label="Heading self-link"></a></h3> +<p>When testing has completed without uncovering any new showstopper bugs, kick off the <a href="https://ci.drycc.info/job/workflow-chart-release">workflow-chart-release</a> job with the following parameter:</p> +<p><code>RELEASE_TAG=$WORKFLOW_RELEASE</code></p> +<p>This job will copy the release candidate chart (now approved by CI and manual testing) from the staging repo to the production repo, signing +it if it has not done so already.</p> +<h3 id="step-6-assemble-master-changelog">Step 6: Assemble Master Changelog<a class="td-heading-self-link" href="#step-6-assemble-master-changelog" aria-label="Heading self-link"></a></h3> +<p>Each component already updated its release notes on GitHub with CHANGELOG content. We&rsquo;ll now +generate the master changelog for the Workflow chart, consisting of all component and auxilliary repo changes.</p> +<p>We&rsquo;ll employ the <code>requirements.lock</code> file from the <code>WORKFLOW_PREV_RELEASE</code> chart, as well as a repo-to-chart-name <a href="https://github.com/drycc/dryccrel/blob/main/map.json">mapping file</a>, this time invoking <code>dryccrel changelog global</code> to get all component changes between +the chart versions existing in the <code>WORKFLOW_PREV_RELEASE</code> chart and the <em>most recent</em> releases existing in GitHub. +(Therefore, if there are any unreleased commits in a component repo, they will not appear here):</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>helm fetch --untar oci://registry.drycc.cc/charts/workflow --version <span style="color:#000">$WORKFLOW_PREV_RELEASE</span> +</span></span><span style="display:flex;"><span>dryccrel changelog global workflow/requirements.lock map.json &gt; changelog-<span style="color:#000">$WORKFLOW_RELEASE</span>.md +</span></span></code></pre></div><p>This master changelog should then be placed into a single gist. The file will also be added to the documentation +update PR created in the next step.</p> +<h3 id="step-7-update-documentation">Step 7: Update Documentation<a class="td-heading-self-link" href="#step-7-update-documentation" aria-label="Heading self-link"></a></h3> +<p>Create a new pull request at <a href="https://github.com/drycc/workflow">drycc/workflow</a> that updates version references to the new release. +Use <code>git grep $WORKFLOW_PREV_RELEASE</code> to find any references, but be careful not to change +<code>CHANGELOG.md</code>.</p> +<p>Place the <code>$WORKFLOW_RELEASE</code> master changelog generated in Step 7 in the <code>changelogs</code> directory. +Make sure to add a header to the page to make it clear that this is for a Workflow release, e.g.:</p> +<pre tabindex="0"><code>## Workflow v2.16.0 -&gt; v2.17.0 +</code></pre><p>Once the PR has been reviewed and merged, do a <a href="/docs/roadmap/releases/#how-to-release-a-component">component release</a> of +<a href="https://github.com/drycc/workflow">drycc/workflow</a> itself. The version number for <a href="https://github.com/drycc/workflow">drycc/workflow</a> should always match the +overall Workflow version number.</p> +<h3 id="step-8-close-github-milestones">Step 8: Close GitHub Milestones<a class="td-heading-self-link" href="#step-8-close-github-milestones" aria-label="Heading self-link"></a></h3> +<p>Create a pull request at <a href="https://github.com/drycc/seed-repo">seed-repo</a> to close the release +milestone and create the next one. When changes are merged to seed-repo, milestones on all +relevant projects will be updated. If there are open issues attached to the milestone, move them +to the next upcoming milestone before merging the pull request.</p> +<p>Milestones map to Drycc Workflow releases in <a href="https://github.com/drycc/workflow">drycc/workflow</a>. These milestones do not correspond +to individual component release tags.</p> +<h3 id="step-9-release-workflow-cli-stable">Step 9: Release Workflow CLI Stable<a class="td-heading-self-link" href="#step-9-release-workflow-cli-stable" aria-label="Heading self-link"></a></h3> +<p>Now that the <code>$WORKFLOW_RELEASE</code> version of Workflow CLI has been vetted, we can push <code>stable</code> artifacts based on this version.</p> +<p>Kick off <a href="https://ci.drycc.info/job/workflow-cli-build-stable/">https://ci.drycc.info/job/workflow-cli-build-stable/</a> with the <code>TAG</code> build parameter of <code>$WORKFLOW_RELEASE</code> +and then verify <code>stable</code> artifacts are available and appropriately updated after the job completes:</p> +<pre tabindex="0"><code>$ curl -sfL https://www.drycc.cc/install-cli.sh | bash - +$ ./drycc version +# (Should show $WORKFLOW_RELEASE) +</code></pre><h3 id="step-10-let-everyone-know">Step 10: Let Everyone Know<a class="td-heading-self-link" href="#step-10-let-everyone-know" aria-label="Heading self-link"></a></h3> +<p>Let the rest of the team know they can start blogging and tweeting about the new Workflow release. +Post a message to the #company channel on Slack. Include a link to the released chart and to the +master CHANGELOG:</p> +<pre tabindex="0"><code>@here Drycc Workflow v2.17.0 is now live! +Master CHANGELOG: https://drycc.info/docs/workflow/changelogs/v2.17.0/ +</code></pre><p>You&rsquo;re done with the release. Nice job!</p> + + + + + + diff --git a/docs/roadmap/planning-process/index.html b/docs/roadmap/planning-process/index.html new file mode 100644 index 000000000..6fd645d5e --- /dev/null +++ b/docs/roadmap/planning-process/index.html @@ -0,0 +1,478 @@ + + + + + + + + + + + + + + + + + + + +Planning Process | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Planning Process

+
Drycc features a lightweight process that emphasizes openness and ensures every community member can be an integral part of planning for the future.
+ +

The Role of Maintainers

+

Maintainers lead the Drycc projects. Their duties include proposing the Roadmap, reviewing and integrating contributions and maintaining the vision of the project.

+

Open Roadmap

+

The Drycc Roadmap is a community document. While Maintainers propose the Roadmap, it gets discussed and refined in Release Planning Meetings.

+

Contributing to the Roadmap

+

Proposals and issues can be opened by anyone. Every member of the community is welcome to participate in the discussion by providing feedback and/or offering counter-proposals.

+

Release Milestones

+

The Roadmap gets delivered progressively via the Release Schedule. Releases are defined during Release Planning Meetings and managed using GitHub Milestones which track specific deliverables and work-in-progress.

+

Release Planning Meetings

+

Major decisions affecting the Roadmap are discussed during Release Planning Meetings on the first Thursday of each month, aligned with the Release Schedule.

+

Release Planning Meetings are open to the public with access coordinated via the Drycc #community Slack channel. +Notes from past meetings are below, along with links to a recording of the entire meeting on YouTube.

+

Credits

+

Thanks to Amy Lindburg and our friends at Podman for their inspiration.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/roadmap/releases/index.html b/docs/roadmap/releases/index.html new file mode 100644 index 000000000..98ac3967f --- /dev/null +++ b/docs/roadmap/releases/index.html @@ -0,0 +1,658 @@ + + + + + + + + + + + + + + + + + + + +Releases | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Releases

+
Drycc’s release model allows applications to record and roll back to previous versions.
+ +

Drycc uses a continuous delivery approach for creating releases. Every merged commit that passes +testing results in a deliverable that can be given a semantic version tag and shipped.

+

The master git branch of a project should always work. Only changes considered ready to be +released publicly are merged.

+

Components Release as Needed

+

Drycc components release new versions as often as needed. Fixing a high priority bug requires the +project maintainer to create a new patch release. Merging a backward-compatible feature implies +a minor release.

+

By releasing often, each component release becomes a safe and routine event. This makes it faster +and easier for users to obtain specific fixes. Continuous delivery also reduces the work +necessary to release a product such as Drycc Workflow, which integrates several components.

+

“Components” applies not just to Drycc Workflow projects, but also to development and release +tools, to Container base images, and to other Drycc projects that do semantic version releases.

+

See “How to Release a Component” for more detail.

+

Workflow Releases Each Month

+

Drycc Workflow has a regular, public release cadence. From v2.8.0 onward, new Workflow feature +releases arrive on the first Thursday of each month. Patch releases are created at any time, +as needed. GitHub milestones are used to communicate the content and timing of major and minor +releases, and longer-term planning is visible at the Roadmap.

+

Workflow release timing is not linked to specific features. If a feature is merged before the +release date, it is included in the next release.

+

See “How to Release Workflow” for more detail.

+

Semantic Versioning

+

Drycc releases comply with semantic versioning, with the “public API” broadly +defined as:

+
    +
  • REST, gRPC, or other API that is network-accessible
  • +
  • Library or framework API intended for public use
  • +
  • “Pluggable” socket-level protocols users can redirect
  • +
  • CLI commands and output formats
  • +
+

In general, changes to anything a user might reasonably link to, customize, or integrate with +should be backward-compatible, or else require a major release. Drycc users can be confident that +upgrading to a patch or to a minor release will not break anything.

+

How to Release a Component

+

Most Drycc projects are “components” which produce a Container image or binary executable as a +deliverable. This section leads a maintainer through creating a component release.

+

Step 1: Update Code and Run the Release Tool

+

Major or minor releases should happen on the master branch. Patch releases +should check out the previous release tag and cherry-pick specific commits from master.

+

Note: if a patch release, the release artifact will have to be manually promoted by triggering +the component-promote job with the following values:

+
COMPONENT_NAME=<component name>
+COMPONENT_SHA=<patch commit sha>
+

Make sure you have the dryccrel release tool in your search $PATH.

+

Run dryccrel release once with a fake semver tag to proofread the changelog content. (If HEAD +of master is not what is intended for the release, add the --sha flag as described +in dryccrel release --help.)

+
$ dryccrel release controller v0.0.0
+Doing a dry run of the component release...
+skipping commit 943a49267eeb28546819a266654806cfcbae0e38
+
+Creating changelog for controller with tag v2.8.1 through commit 943a49267eeb28546819a266654806cfcbae0e38
+
+### v2.8.1 -> v0.0.0
+
+#### Fixes
+
+- [`615b834`](https://github.com/drycc/controller/commit/615b834f39cb68a854cc1f1e2f0f82d862ea2731) boot: Ensure DRYCC_DEBUG==true for debug output
+

Based on the changelog content, determine whether the component deserves a minor or patch +release. Run the command again with that semver tag and --dry-run=false. You will still be +asked for confirmation before the release is created:

+
$ dryccrel release controller v2.8.2 --dry-run=false
+skipping commit 943a49267eeb28546819a266654806cfcbae0e38
+
+Creating changelog for controller with tag v2.8.1 through commit 943a49267eeb28546819a266654806cfcbae0e38
+
+### v2.8.1 -> v2.8.2
+
+
+#### Fixes
+
+- [`615b834`](https://github.com/drycc/controller/commit/615b834f39cb68a854cc1f1e2f0f82d862ea2731) boot: Ensure DRYCC_DEBUG==true for debug output
+
+
+Please review the above changelog contents and ensure:
+  1. All intended commits are mentioned
+  2. The changes agree with the semver release tag (major, minor, or patch)
+
+Create release for Drycc Controller v2.8.2? [y/n]: y
+New release is available at https://github.com/drycc/controller/releases/tag/v2.8.2
+

Step 2: Verify the Component is Available

+

Tagging the component (see Step 1) +starts a CI job that eventually results in an artifact being made available for public download. +Please see the CI flow diagrams for details.

+

Double-check that the artifact is available, either by a podman pull command or by running the +appropriate installer script.

+

If the artifact can’t be downloaded, ensure that its CI release jobs are still in progress, or +fix whatever issue arose in the pipeline. For example, the +master merge pipeline +may have failed to promote the :git-abc1d23 candidate image and needs to be restarted with +that component and commit.

+

If the component has a correlating Kubernetes Helm chart, +this chart will also be packaged, signed and uploaded to its production chart repo. Please +verify it can be fetched (and verified):

+
$ helm fetch oci://registry.drycc.cc/charts/controller --version 1.0.0
+Verification: &{0xc4207ec870 sha256:026e766e918ff28d2a7041bc3d560d149ee7eb0cb84165c9d9d00a3045ff45c3 controller-v1.0.1.tgz}
+

How to Release Workflow

+

Drycc Workflow integrates multiple component releases together with a Kubernetes Helm chart +deliverable. This section leads a maintainer through creating a Workflow release.

+

Step 1: Set Environment Variables

+

Export two environment variables that will be used in later steps:

+
export WORKFLOW_RELEASE=v2.17.0 WORKFLOW_PREV_RELEASE=v2.16.0  # for example
+

Step 2: Tag Supporting Repositories

+

Some Workflow components not in the Helm chart must also be tagged in sync with the release. +Follow the component release process above and ensure that +these components are tagged:

+ +

The version number for drycc/workflow-cli should always match the overall Workflow version +number.

+

Step 3: Create Helm Chart

+

To create and stage a release candidate chart for Workflow, we will build the workflow-chart-stage job with the following parameters:

+

RELEASE_TAG=$WORKFLOW_RELEASE

+

This job will gather all of the latest component release tags and use these to specify the versions of all component charts. +It will then package the Workflow chart, upload it to the staging chart repo and kick off an e2e run against said chart.

+

Step 4: Manual Testing

+

Now it’s time to go above and beyond current CI tests. Create a testing matrix spreadsheet (copying +from the previous document is a good start) and sign up testers to cover all permutations.

+

Testers should pay special attention to the overall user experience, make sure upgrading from +earlier versions is smooth, and cover various storage configurations and Kubernetes versions and +infrastructure providers.

+

When showstopper-level bugs are found, the process is as follows:

+
    +
  1. Create a component PR that fixes the bug.
  2. +
  3. Once the PR passes and is reviewed, merge it and do a new +component release
  4. +
  5. Trigger the same workflow-chart-stage job as mentioned in Step 3 to upload the newly-generated Workflow release candidate chart to staging.
  6. +
+

Step 5: Release the Chart

+

When testing has completed without uncovering any new showstopper bugs, kick off the workflow-chart-release job with the following parameter:

+

RELEASE_TAG=$WORKFLOW_RELEASE

+

This job will copy the release candidate chart (now approved by CI and manual testing) from the staging repo to the production repo, signing +it if it has not done so already.

+

Step 6: Assemble Master Changelog

+

Each component already updated its release notes on GitHub with CHANGELOG content. We’ll now +generate the master changelog for the Workflow chart, consisting of all component and auxilliary repo changes.

+

We’ll employ the requirements.lock file from the WORKFLOW_PREV_RELEASE chart, as well as a repo-to-chart-name mapping file, this time invoking dryccrel changelog global to get all component changes between +the chart versions existing in the WORKFLOW_PREV_RELEASE chart and the most recent releases existing in GitHub. +(Therefore, if there are any unreleased commits in a component repo, they will not appear here):

+
helm fetch --untar oci://registry.drycc.cc/charts/workflow --version $WORKFLOW_PREV_RELEASE
+dryccrel changelog global workflow/requirements.lock map.json > changelog-$WORKFLOW_RELEASE.md
+

This master changelog should then be placed into a single gist. The file will also be added to the documentation +update PR created in the next step.

+

Step 7: Update Documentation

+

Create a new pull request at drycc/workflow that updates version references to the new release. +Use git grep $WORKFLOW_PREV_RELEASE to find any references, but be careful not to change +CHANGELOG.md.

+

Place the $WORKFLOW_RELEASE master changelog generated in Step 7 in the changelogs directory. +Make sure to add a header to the page to make it clear that this is for a Workflow release, e.g.:

+
## Workflow v2.16.0 -> v2.17.0
+

Once the PR has been reviewed and merged, do a component release of +drycc/workflow itself. The version number for drycc/workflow should always match the +overall Workflow version number.

+

Step 8: Close GitHub Milestones

+

Create a pull request at seed-repo to close the release +milestone and create the next one. When changes are merged to seed-repo, milestones on all +relevant projects will be updated. If there are open issues attached to the milestone, move them +to the next upcoming milestone before merging the pull request.

+

Milestones map to Drycc Workflow releases in drycc/workflow. These milestones do not correspond +to individual component release tags.

+

Step 9: Release Workflow CLI Stable

+

Now that the $WORKFLOW_RELEASE version of Workflow CLI has been vetted, we can push stable artifacts based on this version.

+

Kick off https://ci.drycc.info/job/workflow-cli-build-stable/ with the TAG build parameter of $WORKFLOW_RELEASE +and then verify stable artifacts are available and appropriately updated after the job completes:

+
$ curl -sfL https://www.drycc.cc/install-cli.sh | bash -
+$ ./drycc version
+# (Should show $WORKFLOW_RELEASE)
+

Step 10: Let Everyone Know

+

Let the rest of the team know they can start blogging and tweeting about the new Workflow release. +Post a message to the #company channel on Slack. Include a link to the released chart and to the +master CHANGELOG:

+
@here Drycc Workflow v2.17.0 is now live!
+Master CHANGELOG: https://drycc.info/docs/workflow/changelogs/v2.17.0/
+

You’re done with the release. Nice job!

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/roadmap/roadmap/index.html b/docs/roadmap/roadmap/index.html new file mode 100644 index 000000000..489298a44 --- /dev/null +++ b/docs/roadmap/roadmap/index.html @@ -0,0 +1,508 @@ + + + + + + + + + + + + + + + + + + + +Drycc Workflow Roadmap | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Drycc Workflow Roadmap

+
Drycc roadmap is community driven and managed through GitHub.
+ +

Drycc Workflow Roadmap

+

The Drycc Workflow Roadmap is a community document created as part of the open +Planning Process. Each roadmap item describes a high-level capability or +grouping of features that are deemed important to the future of Drycc.

+

Given the project’s rapid Release Schedule, roadmap +items are designed to provide a sense of direction over many releases.

+

Interactive drycc run /bin/bash

+

Provide the ability for developers to launch an interactive terminal session in +their application environment.

+

Related issues:

+ +

Log Streaming

+

Stream application logs via drycc logs -f https://github.com/drycc/drycc/issues/465

+

Teams and Permissions

+

Teams and Permissions represents a more flexible permissions model to allow +more nuanced control to applications, capabilities and resources on the +platform. There have been a number of proposals in this area which need to be +reconciled for Drycc Workflow before we begin implementation.

+

Related issues:

+ +

Monitoring

+ +

Workflow Addons/Services

+

Developers should be able to quickly and easily provision application +dependencies using a services or addon abstraction. +https://github.com/drycc/drycc/issues/231

+

Inbound/Outbound Webhooks

+

Drycc Workflow should be able to send and receive webhooks from external +systems. Facilitating integration with third party services like GitHub, +Gitlab, Slack, Hipchat.

+ + + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/security/1d6a97d0.txt b/docs/security/1d6a97d0.txt new file mode 100644 index 000000000..0282082c5 --- /dev/null +++ b/docs/security/1d6a97d0.txt @@ -0,0 +1,92 @@ +sec 4096R/1D6A97D0 2016-11-03 + Key fingerprint = 41AF 6B6A 9489 9B58 1EB6 9ED1 17E5 26B5 1D6A 97D0 +uid Drycc, Inc. (Helm chart signing key) +ssb 4096R/2CA931B0 2016-11-03 +ssb 4096R/41C9CA1E 2016-11-03 [expires: 2024-11-01] + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2 + +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 +K8I9jWQf2UCagoUuV3w= +=qap/ +-----END PGP PUBLIC KEY BLOCK----- diff --git a/docs/troubleshooting/_print/index.html b/docs/troubleshooting/_print/index.html new file mode 100644 index 000000000..0fda13079 --- /dev/null +++ b/docs/troubleshooting/_print/index.html @@ -0,0 +1,402 @@ + + + + + + + + + + + + + + + + + + + + + +Troubleshooting | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+ + + + + +
+
+

+This is the multi-page printable view of this section. +Click here to print. +

+Return to the regular view of this page. +

+
+ + + +

Troubleshooting

+
Troubleshooting is systematic approach to problem-solving.
+ + + + + + + +
+ +
+
+ + + + + + + + + + + + + + + + +
+ +

1 - Troubleshooting Workflow

+
Common issues that users have run into when provisioning Workflow are detailed below.
+

A Component Fails to Start

+

For information on troubleshooting a failing component, see +Troubleshooting with Kubectl.

+

An Application Fails to Start

+

For information on troubleshooting application deployment issues, see +Troubleshooting Applications.

+

Permission denied (publickey)

+

The most common problem for this issue is the user forgetting to run drycc keys:add or add their +private key to their SSH agent. To do so, run ssh-add ~/.ssh/id_rsa and try running +git push drycc master again.

+

If you happen get a Could not open a connection to your authentication agent +error after trying to run ssh-add command above, you may need to load the SSH +agent environment variables issuing the eval "$(ssh-agent)" command before.

+

Other Issues

+

Running into something not detailed here? Please open an issue or hop into +#community on Slack for help!

+ +
+ + + + + + + + + + + +
+ +

2 - Troubleshooting using Kubectl

+
Kubernetes provides a command line tool for communicating with a Kubernetes cluster’s control plane, using the Kubernetes API.
+

This document describes how one can use kubectl to debug any issues with the cluster.

+

Diving into the Components

+

Using kubectl, one can inspect the cluster’s current state. When Workflow is installed +with helm, Workflow is installed into the drycc namespace. To inspect if Workflow is +running, run:

+
$ kubectl --namespace=drycc get pods
+NAME                          READY     STATUS              RESTARTS   AGE
+drycc-builder-gqum7            0/1       ContainerCreating   0          4s
+drycc-controller-h6lk6         0/1       ContainerCreating   0          4s
+drycc-controller-celery-cmxxn  0/3       ContainerCreating   0          4s
+drycc-database-56v39           0/1       ContainerCreating   0          4s
+drycc-logger-fluentbit-xihr1   0/1       Pending             0          2s
+drycc-logger-grupg             0/1       ContainerCreating   0          3s
+drycc-storage-c2exb            0/1       Pending             0          3s
+drycc-monitor-grafana-9ccur    0/1       Pending             0          3s
+drycc-monitor-telegraf-dc3y3   0/1       Pending             0          2s
+drycc-registry-5bor6           0/1       Pending             0          3s
+drycc-rabbitmq-0               0/1       ContainerCreating   0          3s
+
+

!!! tip +To save precious keystrokes, alias kubectl --namespace=drycc to kd so it is easier to type +in the future.

+

To fetch the logs of a specific component, use kubectl logs:

+
$ kubectl --namespace=drycc logs drycc-controller-h6lk6
+system information:
+Django Version: 1.9.6
+Python 3.5.1
+addgroup: gid '0' in use
+Django checks:
+System check identified no issues (2 silenced).
+[...]
+
+

To dive into a running container to inspect its environment, use kubectl exec:

+
$ kubectl --namespace=drycc exec -it drycc-database-56v39 gosu postgres psql
+psql (13.4 (Debian 13.4-1.pgdg100+1))
+Type "help" for help.
+
+postgres=# \l
+                                                List of databases
+     Name          |  Owner   | Encoding |  Collate   |   Ctype    |   Access privileges
+-------------------+----------+----------+------------+------------+-----------------------
+ drycc_controller  | postgres | UTF8     | en_US.utf8 | en_US.utf8 |
+ drycc_passport    | postgres | UTF8     | en_US.utf8 | en_US.utf8 |
+ postgres          | postgres | UTF8     | en_US.utf8 | en_US.utf8 |
+ template0         | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
+                   |          |          |            |            | postgres=CTc/postgres
+ template1         | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
+                   |          |          |            |            | postgres=CTc/postgres
+(4 rows)
+postgres=# \connect drycc_controller
+You are now connected to database "drycc_controller" as user "postgres".
+drycc_controller=# \dt
+                                 List of relations
+ Schema |              Name              | Type  |      Owner
+--------+--------------------------------+-------+-------------------
+ public | api_app                        | table | drycc_controller
+ public | api_build                      | table | drycc_controller
+ public | api_certificate                | table | drycc_controller
+ public | api_config                     | table | drycc_controller
+ public | api_domain                     | table | drycc_controller
+ public | api_key                        | table | drycc_controller
+ public | api_push                       | table | drycc_controller
+ public | api_release                    | table | drycc_controller
+ public | auth_group                     | table | drycc_controller
+ --More--
+ drycc_controller=# SELECT COUNT(*) from api_app;
+ count
+-------
+     0
+(1 row)
+
+ +
+ + + + + + + + + + + +
+ +

3 - Troubleshooting Applications

+
This document describes how one can troubleshoot common issues when deploying or debugging an application that fails to start or deploy.
+

Application has a Dockerfile, but a Buildpack Deployment Occurs

+

When you deploy an application to Workflow using git push drycc master and the Builder +attempts to deploy using the Buildpack workflow, check the following steps:

+
    +
  1. Are you deploying the correct project?
  2. +
  3. Are you pushing the correct git branch (git push drycc <branch>)?
  4. +
  5. Is the Dockerfile in the project’s root directory?
  6. +
  7. Have you committed the Dockerfile to the project?
  8. +
+

Application was Deployed, but is Failing to Start

+

If you deployed your application but it is failing to start, you can use drycc logs to check +why the application fails to boot. Sometimes, the application container may fail to boot without +logging any information about the error. This typically occurs when the healthcheck configured for +the application fails. In this case, you can start by +troubleshooting using kubectl. You can inspect the application’s current +state by examining the pod deployed in the application’s namespace. To do that, run

+
$ kubectl --namespace=myapp get pods
+NAME                          READY     STATUS                RESTARTS   AGE
+myapp-web-1585713350-3brbo    0/1       CrashLoopBackOff      2          43s
+
+

We can then describe the pod and determine why it is failing to boot:

+
Events:
+  FirstSeen     LastSeen        Count   From                            SubobjectPath                           Type            Reason          Message
+  ---------     --------        -----   ----                            -------------                           --------        ------          -------
+  43s           43s             1       {default-scheduler }                                                    Normal          Scheduled       Successfully assigned myapp-web-1585713350-3brbo to kubernetes-node-1
+  41s           41s             1       {kubelet kubernetes-node-1}     spec.containers{myapp-web}              Normal          Created         Created container with container id b86bd851a61f
+  41s           41s             1       {kubelet kubernetes-node-1}     spec.containers{myapp-web}              Normal          Started         Started container with container id b86bd851a61f
+  37s           35s             1       {kubelet kubernetes-node-1}     spec.containers{myapp-web}              Warning         Unhealthy       Liveness probe failed: Get http://10.246.39.13:8000/healthz: dial tcp 10.246.39.13:8000: getsockopt: connection refused
+
+

In this instance, we set the healthcheck initial delay timeout for the application at 1 second, +which is too aggressive. The application needs some time to set up the API server after the +container has booted. By increasing the healthcheck initial delay timeout to 10 seconds, the +application is able to boot and is responding correctly.

+

See Custom Health Checks for more information on how to customize the application’s +health checks to better suit the application’s needs.

+ +
+ + + + + + + + + +
+
+
+ + +
+ + + + + + diff --git a/docs/troubleshooting/applications/index.html b/docs/troubleshooting/applications/index.html new file mode 100644 index 000000000..63f4231a3 --- /dev/null +++ b/docs/troubleshooting/applications/index.html @@ -0,0 +1,495 @@ + + + + + + + + + + + + + + + + + + + +Troubleshooting Applications | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Troubleshooting Applications

+
This document describes how one can troubleshoot common issues when deploying or debugging an application that fails to start or deploy.
+ +

Application has a Dockerfile, but a Buildpack Deployment Occurs

+

When you deploy an application to Workflow using git push drycc master and the Builder +attempts to deploy using the Buildpack workflow, check the following steps:

+
    +
  1. Are you deploying the correct project?
  2. +
  3. Are you pushing the correct git branch (git push drycc <branch>)?
  4. +
  5. Is the Dockerfile in the project’s root directory?
  6. +
  7. Have you committed the Dockerfile to the project?
  8. +
+

Application was Deployed, but is Failing to Start

+

If you deployed your application but it is failing to start, you can use drycc logs to check +why the application fails to boot. Sometimes, the application container may fail to boot without +logging any information about the error. This typically occurs when the healthcheck configured for +the application fails. In this case, you can start by +troubleshooting using kubectl. You can inspect the application’s current +state by examining the pod deployed in the application’s namespace. To do that, run

+
$ kubectl --namespace=myapp get pods
+NAME                          READY     STATUS                RESTARTS   AGE
+myapp-web-1585713350-3brbo    0/1       CrashLoopBackOff      2          43s
+
+

We can then describe the pod and determine why it is failing to boot:

+
Events:
+  FirstSeen     LastSeen        Count   From                            SubobjectPath                           Type            Reason          Message
+  ---------     --------        -----   ----                            -------------                           --------        ------          -------
+  43s           43s             1       {default-scheduler }                                                    Normal          Scheduled       Successfully assigned myapp-web-1585713350-3brbo to kubernetes-node-1
+  41s           41s             1       {kubelet kubernetes-node-1}     spec.containers{myapp-web}              Normal          Created         Created container with container id b86bd851a61f
+  41s           41s             1       {kubelet kubernetes-node-1}     spec.containers{myapp-web}              Normal          Started         Started container with container id b86bd851a61f
+  37s           35s             1       {kubelet kubernetes-node-1}     spec.containers{myapp-web}              Warning         Unhealthy       Liveness probe failed: Get http://10.246.39.13:8000/healthz: dial tcp 10.246.39.13:8000: getsockopt: connection refused
+
+

In this instance, we set the healthcheck initial delay timeout for the application at 1 second, +which is too aggressive. The application needs some time to set up the API server after the +container has booted. By increasing the healthcheck initial delay timeout to 10 seconds, the +application is able to boot and is responding correctly.

+

See Custom Health Checks for more information on how to customize the application’s +health checks to better suit the application’s needs.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/troubleshooting/index.html b/docs/troubleshooting/index.html new file mode 100644 index 000000000..dad278885 --- /dev/null +++ b/docs/troubleshooting/index.html @@ -0,0 +1,472 @@ + + + + + + + + + + + + + + + + + + + + + +Troubleshooting | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Troubleshooting

+
Troubleshooting is systematic approach to problem-solving.
+ + +
+ + +
+
+
+ Troubleshooting Workflow +
+

Common issues that users have run into when provisioning Workflow are detailed below.

+
+
+
+ Troubleshooting using Kubectl +
+

Kubernetes provides a command line tool for communicating with a Kubernetes cluster’s control plane, using the Kubernetes API.

+
+
+
+ Troubleshooting Applications +
+

This document describes how one can troubleshoot common issues when deploying or debugging an application that fails to start or deploy.

+
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+
+ +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/troubleshooting/index.xml b/docs/troubleshooting/index.xml new file mode 100644 index 000000000..5026e96f0 --- /dev/null +++ b/docs/troubleshooting/index.xml @@ -0,0 +1,179 @@ + + + Drycc – Troubleshooting + /docs/troubleshooting/ + Recent content in Troubleshooting on Drycc + Hugo -- gohugo.io + en + + + + + + + + + + + Docs: Troubleshooting Workflow + /docs/troubleshooting/workflow/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/troubleshooting/workflow/ + + + + <h2 id="a-component-fails-to-start">A Component Fails to Start<a class="td-heading-self-link" href="#a-component-fails-to-start" aria-label="Heading self-link"></a></h2> +<p>For information on troubleshooting a failing component, see +<a href="/docs/troubleshooting/kubectl/">Troubleshooting with Kubectl</a>.</p> +<h2 id="an-application-fails-to-start">An Application Fails to Start<a class="td-heading-self-link" href="#an-application-fails-to-start" aria-label="Heading self-link"></a></h2> +<p>For information on troubleshooting application deployment issues, see +<a href="/docs/troubleshooting/applications/">Troubleshooting Applications</a>.</p> +<h2 id="permission-denied-publickey">Permission denied (publickey)<a class="td-heading-self-link" href="#permission-denied-publickey" aria-label="Heading self-link"></a></h2> +<p>The most common problem for this issue is the user forgetting to run <code>drycc keys:add</code> or add their +private key to their SSH agent. To do so, run <code>ssh-add ~/.ssh/id_rsa</code> and try running +<code>git push drycc master</code> again.</p> +<p>If you happen get a <code>Could not open a connection to your authentication agent</code> +error after trying to run <code>ssh-add</code> command above, you may need to load the SSH +agent environment variables issuing the <code>eval &quot;$(ssh-agent)&quot;</code> command before.</p> +<h2 id="other-issues">Other Issues<a class="td-heading-self-link" href="#other-issues" aria-label="Heading self-link"></a></h2> +<p>Running into something not detailed here? Please <a href="https://github.com/drycc/workflow/issues/new">open an issue</a> or hop into +<a href="http://slack.drycc.cc/">#community on Slack</a> for help!</p> + + + + + + Docs: Troubleshooting using Kubectl + /docs/troubleshooting/kubectl/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/troubleshooting/kubectl/ + + + + <p>This document describes how one can use <code>kubectl</code> to debug any issues with the cluster.</p> +<h2 id="diving-into-the-components">Diving into the Components<a class="td-heading-self-link" href="#diving-into-the-components" aria-label="Heading self-link"></a></h2> +<p>Using <code>kubectl</code>, one can inspect the cluster&rsquo;s current state. When Workflow is installed +with <code>helm</code>, Workflow is installed into the <code>drycc</code> namespace. To inspect if Workflow is +running, run:</p> +<pre><code>$ kubectl --namespace=drycc get pods +NAME READY STATUS RESTARTS AGE +drycc-builder-gqum7 0/1 ContainerCreating 0 4s +drycc-controller-h6lk6 0/1 ContainerCreating 0 4s +drycc-controller-celery-cmxxn 0/3 ContainerCreating 0 4s +drycc-database-56v39 0/1 ContainerCreating 0 4s +drycc-logger-fluentbit-xihr1 0/1 Pending 0 2s +drycc-logger-grupg 0/1 ContainerCreating 0 3s +drycc-storage-c2exb 0/1 Pending 0 3s +drycc-monitor-grafana-9ccur 0/1 Pending 0 3s +drycc-monitor-telegraf-dc3y3 0/1 Pending 0 2s +drycc-registry-5bor6 0/1 Pending 0 3s +drycc-rabbitmq-0 0/1 ContainerCreating 0 3s +</code></pre> +<p>!!! tip +To save precious keystrokes, alias <code>kubectl --namespace=drycc</code> to <code>kd</code> so it is easier to type +in the future.</p> +<p>To fetch the logs of a specific component, use <code>kubectl logs</code>:</p> +<pre><code>$ kubectl --namespace=drycc logs drycc-controller-h6lk6 +system information: +Django Version: 1.9.6 +Python 3.5.1 +addgroup: gid '0' in use +Django checks: +System check identified no issues (2 silenced). +[...] +</code></pre> +<p>To dive into a running container to inspect its environment, use <code>kubectl exec</code>:</p> +<pre><code>$ kubectl --namespace=drycc exec -it drycc-database-56v39 gosu postgres psql +psql (13.4 (Debian 13.4-1.pgdg100+1)) +Type &quot;help&quot; for help. + +postgres=# \l + List of databases + Name | Owner | Encoding | Collate | Ctype | Access privileges +-------------------+----------+----------+------------+------------+----------------------- + drycc_controller | postgres | UTF8 | en_US.utf8 | en_US.utf8 | + drycc_passport | postgres | UTF8 | en_US.utf8 | en_US.utf8 | + postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 | + template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres + + | | | | | postgres=CTc/postgres + template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres + + | | | | | postgres=CTc/postgres +(4 rows) +postgres=# \connect drycc_controller +You are now connected to database &quot;drycc_controller&quot; as user &quot;postgres&quot;. +drycc_controller=# \dt + List of relations + Schema | Name | Type | Owner +--------+--------------------------------+-------+------------------- + public | api_app | table | drycc_controller + public | api_build | table | drycc_controller + public | api_certificate | table | drycc_controller + public | api_config | table | drycc_controller + public | api_domain | table | drycc_controller + public | api_key | table | drycc_controller + public | api_push | table | drycc_controller + public | api_release | table | drycc_controller + public | auth_group | table | drycc_controller + --More-- + drycc_controller=# SELECT COUNT(*) from api_app; + count +------- + 0 +(1 row) +</code></pre> + + + + + + Docs: Troubleshooting Applications + /docs/troubleshooting/applications/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/troubleshooting/applications/ + + + + <h2 id="application-has-a-dockerfile-but-a-buildpack-deployment-occurs">Application has a Dockerfile, but a Buildpack Deployment Occurs<a class="td-heading-self-link" href="#application-has-a-dockerfile-but-a-buildpack-deployment-occurs" aria-label="Heading self-link"></a></h2> +<p>When you deploy an application to Workflow using <code>git push drycc master</code> and the <a href="/docs/understanding-workflow/components/#builder">Builder</a> +attempts to deploy using the Buildpack workflow, check the following steps:</p> +<ol> +<li>Are you deploying the correct project?</li> +<li>Are you pushing the correct git branch (<code>git push drycc &lt;branch&gt;</code>)?</li> +<li>Is the <code>Dockerfile</code> in the project&rsquo;s root directory?</li> +<li>Have you committed the <code>Dockerfile</code> to the project?</li> +</ol> +<h2 id="application-was-deployed-but-is-failing-to-start">Application was Deployed, but is Failing to Start<a class="td-heading-self-link" href="#application-was-deployed-but-is-failing-to-start" aria-label="Heading self-link"></a></h2> +<p>If you deployed your application but it is failing to start, you can use <code>drycc logs</code> to check +why the application fails to boot. Sometimes, the application container may fail to boot without +logging any information about the error. This typically occurs when the healthcheck configured for +the application fails. In this case, you can start by +<a href="/docs/troubleshooting/kubectl/">troubleshooting using kubectl</a>. You can inspect the application&rsquo;s current +state by examining the pod deployed in the application&rsquo;s namespace. To do that, run</p> +<pre><code>$ kubectl --namespace=myapp get pods +NAME READY STATUS RESTARTS AGE +myapp-web-1585713350-3brbo 0/1 CrashLoopBackOff 2 43s +</code></pre> +<p>We can then describe the pod and determine why it is failing to boot:</p> +<pre><code>Events: + FirstSeen LastSeen Count From SubobjectPath Type Reason Message + --------- -------- ----- ---- ------------- -------- ------ ------- + 43s 43s 1 {default-scheduler } Normal Scheduled Successfully assigned myapp-web-1585713350-3brbo to kubernetes-node-1 + 41s 41s 1 {kubelet kubernetes-node-1} spec.containers{myapp-web} Normal Created Created container with container id b86bd851a61f + 41s 41s 1 {kubelet kubernetes-node-1} spec.containers{myapp-web} Normal Started Started container with container id b86bd851a61f + 37s 35s 1 {kubelet kubernetes-node-1} spec.containers{myapp-web} Warning Unhealthy Liveness probe failed: Get http://10.246.39.13:8000/healthz: dial tcp 10.246.39.13:8000: getsockopt: connection refused +</code></pre> +<p>In this instance, we set the healthcheck initial delay timeout for the application at 1 second, +which is too aggressive. The application needs some time to set up the API server after the +container has booted. By increasing the healthcheck initial delay timeout to 10 seconds, the +application is able to boot and is responding correctly.</p> +<p>See <a href="/docs/applications/managing-app-configuration/#custom-health-checks">Custom Health Checks</a> for more information on how to customize the application&rsquo;s +health checks to better suit the application&rsquo;s needs.</p> + + + + + + diff --git a/docs/troubleshooting/kubectl/index.html b/docs/troubleshooting/kubectl/index.html new file mode 100644 index 000000000..86a7472ad --- /dev/null +++ b/docs/troubleshooting/kubectl/index.html @@ -0,0 +1,530 @@ + + + + + + + + + + + + + + + + + + + +Troubleshooting using Kubectl | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Troubleshooting using Kubectl

+
Kubernetes provides a command line tool for communicating with a Kubernetes cluster’s control plane, using the Kubernetes API.
+ +

This document describes how one can use kubectl to debug any issues with the cluster.

+

Diving into the Components

+

Using kubectl, one can inspect the cluster’s current state. When Workflow is installed +with helm, Workflow is installed into the drycc namespace. To inspect if Workflow is +running, run:

+
$ kubectl --namespace=drycc get pods
+NAME                          READY     STATUS              RESTARTS   AGE
+drycc-builder-gqum7            0/1       ContainerCreating   0          4s
+drycc-controller-h6lk6         0/1       ContainerCreating   0          4s
+drycc-controller-celery-cmxxn  0/3       ContainerCreating   0          4s
+drycc-database-56v39           0/1       ContainerCreating   0          4s
+drycc-logger-fluentbit-xihr1   0/1       Pending             0          2s
+drycc-logger-grupg             0/1       ContainerCreating   0          3s
+drycc-storage-c2exb            0/1       Pending             0          3s
+drycc-monitor-grafana-9ccur    0/1       Pending             0          3s
+drycc-monitor-telegraf-dc3y3   0/1       Pending             0          2s
+drycc-registry-5bor6           0/1       Pending             0          3s
+drycc-rabbitmq-0               0/1       ContainerCreating   0          3s
+
+

!!! tip +To save precious keystrokes, alias kubectl --namespace=drycc to kd so it is easier to type +in the future.

+

To fetch the logs of a specific component, use kubectl logs:

+
$ kubectl --namespace=drycc logs drycc-controller-h6lk6
+system information:
+Django Version: 1.9.6
+Python 3.5.1
+addgroup: gid '0' in use
+Django checks:
+System check identified no issues (2 silenced).
+[...]
+
+

To dive into a running container to inspect its environment, use kubectl exec:

+
$ kubectl --namespace=drycc exec -it drycc-database-56v39 gosu postgres psql
+psql (13.4 (Debian 13.4-1.pgdg100+1))
+Type "help" for help.
+
+postgres=# \l
+                                                List of databases
+     Name          |  Owner   | Encoding |  Collate   |   Ctype    |   Access privileges
+-------------------+----------+----------+------------+------------+-----------------------
+ drycc_controller  | postgres | UTF8     | en_US.utf8 | en_US.utf8 |
+ drycc_passport    | postgres | UTF8     | en_US.utf8 | en_US.utf8 |
+ postgres          | postgres | UTF8     | en_US.utf8 | en_US.utf8 |
+ template0         | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
+                   |          |          |            |            | postgres=CTc/postgres
+ template1         | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
+                   |          |          |            |            | postgres=CTc/postgres
+(4 rows)
+postgres=# \connect drycc_controller
+You are now connected to database "drycc_controller" as user "postgres".
+drycc_controller=# \dt
+                                 List of relations
+ Schema |              Name              | Type  |      Owner
+--------+--------------------------------+-------+-------------------
+ public | api_app                        | table | drycc_controller
+ public | api_build                      | table | drycc_controller
+ public | api_certificate                | table | drycc_controller
+ public | api_config                     | table | drycc_controller
+ public | api_domain                     | table | drycc_controller
+ public | api_key                        | table | drycc_controller
+ public | api_push                       | table | drycc_controller
+ public | api_release                    | table | drycc_controller
+ public | auth_group                     | table | drycc_controller
+ --More--
+ drycc_controller=# SELECT COUNT(*) from api_app;
+ count
+-------
+     0
+(1 row)
+
+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/troubleshooting/workflow/index.html b/docs/troubleshooting/workflow/index.html new file mode 100644 index 000000000..65767e57e --- /dev/null +++ b/docs/troubleshooting/workflow/index.html @@ -0,0 +1,478 @@ + + + + + + + + + + + + + + + + + + + +Troubleshooting Workflow | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Troubleshooting Workflow

+
Common issues that users have run into when provisioning Workflow are detailed below.
+ +

A Component Fails to Start

+

For information on troubleshooting a failing component, see +Troubleshooting with Kubectl.

+

An Application Fails to Start

+

For information on troubleshooting application deployment issues, see +Troubleshooting Applications.

+

Permission denied (publickey)

+

The most common problem for this issue is the user forgetting to run drycc keys:add or add their +private key to their SSH agent. To do so, run ssh-add ~/.ssh/id_rsa and try running +git push drycc master again.

+

If you happen get a Could not open a connection to your authentication agent +error after trying to run ssh-add command above, you may need to load the SSH +agent environment variables issuing the eval "$(ssh-agent)" command before.

+

Other Issues

+

Running into something not detailed here? Please open an issue or hop into +#community on Slack for help!

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/understanding-workflow/_print/index.html b/docs/understanding-workflow/_print/index.html new file mode 100644 index 000000000..311d4a364 --- /dev/null +++ b/docs/understanding-workflow/_print/index.html @@ -0,0 +1,513 @@ + + + + + + + + + + + + + + + + + + + + + +Understanding Workflow | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+ + + + + +
+
+

+This is the multi-page printable view of this section. +Click here to print. +

+Return to the regular view of this page. +

+
+ + + +

Understanding Workflow

+
Understanding the architecture design of workflow.
+ + + + + + + +
+ +
+
+ + + + + + + + + + + + + + + + +
+ +

1 - Concepts

+
Drycc Workflow is a lightweight application platform that deploys and scales Twelve-Factor apps as containers across a Kubernetes cluster.
+

Twelve-Factor Applications

+

The Twelve-Factor App is a methodology for building modern +applications that can be scaled across a distributed system.

+

Twelve-factor is a valuable synthesis of years of experience with +software-as-a-service apps in the wild, particularly on the +Heroku platform.

+

Workflow is designed to run applications that adhere to the Twelve-Factor App +methodology and best practices.

+

Kubernetes

+

Kubernetes is an open-source cluster manager developed by Google and +donated to the Cloud Native Compute Foundation. Kubernetes manages all +the activity on your cluster, including: desired state convergence, stable +service addresses, health monitoring, service discovery, and DNS resolution.

+

Workflow builds upon Kubernetes abstractions like Services, +Deployments and Pods to provide a developer-friendly experience. +Building containers directly from application source code, aggregating logs, +and managing deployment configurations and app releases are just some of the +features Workflow adds.

+

Drycc Workflow is a set of Kubernetes-native components, installable via +Helm. Systems engineers who are familiar with Kubernetes will feel right +at home running Workflow.

+

See the components overview for more detail.

+

Container

+

[Container][] is an open source project to build, ship and run any +application as a lightweight, portable, self-sufficient container.

+

If you have not yet converted your application to containers, Workflow provides +a simple and straightforward “source to Container image” capability. Supporting +multiple language runtimes via community buildpacks, building your application +in a container can be as easy as git push drycc master.

+

Applications which use either a Dockerfile or reference external Container +images are launched unmodified.

+

Applications

+

Workflow is designed around the concept of an application, or app.

+

Applications come in one of three forms:

+
    +
  1. a collection of source files stored in a git repository
  2. +
  3. a Dockerfile and associated source files stored in a git repository
  4. +
  5. a reference to an existing image at a Container repository
  6. +
+

Applications are identified by a unique name for easy reference. If you do not +specify a name when creating your application, Workflow generates one for you. +Workflow also manages related information, including domain names, SSL +certificates, and developer-provided configuration.

+

Build, Release, Run

+

Git Push Workflow

+

Build Stage

+

The builder component processes incoming git push drycc master requests +and manages your application packaging.

+

If your application is using a buildpack, builder will launch an ephemeral +job to extract and execute the packaging instructions. The resulting +application artifact is stored by the platform for execution during the run +stage.

+

If instead builder finds a Dockerfile, it follows those instructions to +create a Container image. The resulting artifact is stored in a Drycc-managed registry which +will be referenced during the run stage.

+

If another system already builds and packages your application, that container +artifact can be used directly. When referencing an external Container +image, the builder component doesn’t attempt to repackage your +app.

+

Release Stage

+

During the release stage, a build is combined with application configuration +to create a new, numbered release. New releases are created any time a new +build is created or application configuration is changed. Tracking releases as a +“write-only ledger” this way makes it easy to rollback to any previous release.

+

Run Stage

+

The run stage deploys the new release to the underlying Kubernetes cluster by +changing the Deployment object which references the new release. +By managing the desired replica count, Workflow +orchestrates a zero-downtime, rolling update of your application. Once +successfully updated, Workflow removes the last reference to the old release. +Note that during the deploy, your application will be running in a mixed mode.

+

Backing Services

+

Workflow treats all persistent services such as databases, caches, storage, +messaging systems, and other backing services as resources managed +separately from your application. This philosophy aligns with Twelve-Factor +best practices.

+

Applications attach to backing services using environment variables. +Because apps are decoupled from backing services, they are free to +scale up independently, to use services provided by other apps, or to switch +to external or third-party vendor services.

+

See Also

+ + +
+ + + + + + + + + + + +
+ +

2 - Architecture

+
Drycc Workflow is built using a service oriented architecture.
+

All components are published as a set of container images which can be deployed to any +compliant Kubernetes cluster.

+

Overview

+

System Overview

+

Operators use Helm to configure and install the Workflow components which +interface directly with the underlying Kubernetes cluster. Service discovery, +container availability and networking are all delegated to Kubernetes, while +Workflow provides a clean and simple developer experience.

+

Platform Services

+

Workflow Overview

+

Drycc Workflow provides additional functionality to your Kubernetes cluster, including:

+ +

Kubernetes-Native

+

All platform components and applications deployed via Workflow expect to be +running on an existing Kubernetes cluster. This means that you can happily run +your Kubernetes-native workloads next to applications that are managed through +Drycc Workflow.

+

Workflow and Kubernetes

+

Application Layout and Edge Routing

+

By default Workflow creates per-application Namespaces and Services so you can +easily connect your applications to other on-cluster services through standard +Kubernetes mechanisms.

+

Application Configuration

+

The router component is responsible for routing HTTP/s traffic to your +Applications as well as proxying git push and platform API traffic.

+

By default, the router component is deployed as a Kubernetes service with type +LoadBalancer; which, depending on your configuration, will provision a +cloud-native load balancer automatically.

+

The router automatically discovers routable Applications, SSL/TLS certificates +and application-specific configurations through the use of Kubernetes +annotations. Any changes to router configuration or certificates are applied +within seconds.

+

Topologies

+

Drycc Workflow no longer dictates a specific topology or server count for your +deployment. The platform components will happily run on single-server +configurations as well as multi-server production clusters.

+ +
+ + + + + + + + + + + +
+ +

3 - Components

+
Workflow is comprised of a number of small, independent services that combine to create a distributed CaaS.
+

All Workflow components are deployed as services (and associated controllers) in your Kubernetes cluster. +If you are interested we have a more detailed exploration of the Workflow architecture.

+

All of the componentry for Workflow is built with composability in mind. If you +need to customize one of the components for your specific deployment or need +the functionality in your own project we invite you to give it a shot!

+

Controller

+

Project Location: drycc/controller

+

The controller component is an HTTP API server which serves as the endpoint for +the drycc CLI. The controller provides all of the platform functionality as +well as interfacing with your Kubernetes cluster. The controller persists all +of its data to the database component.

+

Passport

+

Project Location: drycc/passport

+

The passport component exposes a web API and provide OAuth2 authentication.

+

Database

+

Project Location: drycc/postgres

+

The database component is a managed instance of PostgreSQL which holds a +majority of the platforms state. Backups and WAL files are pushed to object +storage via WAL-E. When the database is restarted, backups are fetched and +replayed from object storage so no data is lost.

+

Builder

+

Project Location: drycc/builder

+

The builder component is responsible for accepting code pushes via Git and +managing the build process of your Application. The builder process is:

+
    +
  1. Receives incoming git push requests over SSH
  2. +
  3. Authenticates the user via SSH key fingerprint
  4. +
  5. Authorizes the user’s access to push code to the Application
  6. +
  7. Starts the Application Build phase (see below)
  8. +
  9. Triggers a new Release via the Controller
  10. +
+

Builder currently supports both buildpack and Dockerfile based builds.

+

Project Location: drycc/imagebuilder

+

For Buildpack-based deploys, the builder component will launch a one-shot Job +in the drycc namespace. This job runs imagebuilder component which handles +default and custom buildpacks (specified by .packbuilder). The completed image +is pushed to the managed Container registry on cluster. For more information +about buildpacks see using buildpacks.

+

Unlike buildpack-based, For Applications which contain a Dockerfile in the root +of the repository, it generates a Container image (using the underlying Container engine). +For more information see using Dockerfiles.

+

Object Storage

+

Project Location: drycc/storage

+

All of the Workflow components that need to persist data will ship them to the +object storage that was configured for the cluster.For example, database ships +its WAL files, registry stores Container images, and slugbuilder stores slugs.

+

Workflow supports either on or off-cluster storage. For production deployments +we highly recommend that you configure off-cluster object storage.

+

To facilitate experimentation, development and test environments, the default charts for +Workflow include on-cluster storage via storage.

+

If you also feel comfortable using Kubernetes persistent volumes you may +configure storage to use persistent storage available in your environment.

+

Registry

+

Project Location: drycc/registry

+

The registry component is a managed container registry which holds application +images generated from the builder component. Registry persists the Container image +images to either local storage (in development mode) or to object storage +configured for the cluster.

+

Logger: fluentbit, logger

+

The logging subsystem consists of two components. Fluentbit handles log shipping +and logger maintains a ring-buffer of application logs.

+

Project Location: drycc/fluentbit

+

Fluentbit is deployed to your Kubernetes cluster via Daemon Sets. Fluentbit +subscribes to all container logs, decorates the output with Kubernetes metadata +and can be configured to drain logs to multiple destinations. By default, +Fluentbit ships logs to the logger component, which powers drycc logs.

+

Project Location: drycc/logger

+

The logger component receives log streams from fluentbit, collating by +Application name. Logger does not persist logs to disk, instead maintaining an +in-memory ring buffer. For more information on logger see the project +documentation.

+

Monitor

+

Project Location: drycc/monitor

+

The monitoring subsystem consists of two components: Telegraf and Grafana.

+

Telegraf is the is the metrics collection agent that runs using the daemon set API. It runs on +every worker node in the cluster, fetches information about the pods currently running and ships it +to Prometheus.

+

Grafana is a standalone graphing application. It natively supports Prometheus as a datasource and +provides a robust engine for creating dashboards on top of timeseries data. Workflow provides a few +dashboards out of the box for monitoring Drycc Workflow and Kubernetes. The dashboards can be used +as a starting point for creating more custom dashboards to suit a user’s needs.

+

Prometheus

+

Project Location: drycc/prometheus

+

Prometheus is a system monitoring and alerting system. It was opensourced by SoundCloud in 2012 and is +the second project both to join and to graduate within Cloud Native Computing Foundation after Kubernetes. +Prometheus stores all metrics data as time series, i.e metrics information is stored along with the +timestamp at which it was recorded, optional key-value pairs called as labels can also be stored along +with metrics.

+

Rabbitmq

+

Project Location: drycc/rabbitmq

+

RabbitMQ is the most widely deployed open source message broker. +Controller use celery with rabbitMQ to execute the asynchronous task.

+

HelmBroker

+

Project Location: drycc/rabbitmq

+

Helm Broker is a Service Broker that exposes Helm charts as Service Classes in Service Catalog. +To do so, Helm Broker uses the concept of addons. An addon is an abstraction layer over a Helm chart +which provides all information required to convert the chart into a Service Class.

+

Prometheus

+

Project Location: drycc/rabbitmq

+

Prometheus is an open-source systemsmonitoring and alerting toolkit originally built atSoundCloud.

+

See Also

+ + +
+ + + + + + + + + +
+
+
+ + +
+ + + + + + diff --git a/docs/understanding-workflow/architecture/index.html b/docs/understanding-workflow/architecture/index.html new file mode 100644 index 000000000..0a8801a4f --- /dev/null +++ b/docs/understanding-workflow/architecture/index.html @@ -0,0 +1,506 @@ + + + + + + + + + + + + + + + + + + + +Architecture | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Architecture

+
Drycc Workflow is built using a service oriented architecture.
+ +

All components are published as a set of container images which can be deployed to any +compliant Kubernetes cluster.

+

Overview

+

System Overview

+

Operators use Helm to configure and install the Workflow components which +interface directly with the underlying Kubernetes cluster. Service discovery, +container availability and networking are all delegated to Kubernetes, while +Workflow provides a clean and simple developer experience.

+

Platform Services

+

Workflow Overview

+

Drycc Workflow provides additional functionality to your Kubernetes cluster, including:

+ +

Kubernetes-Native

+

All platform components and applications deployed via Workflow expect to be +running on an existing Kubernetes cluster. This means that you can happily run +your Kubernetes-native workloads next to applications that are managed through +Drycc Workflow.

+

Workflow and Kubernetes

+

Application Layout and Edge Routing

+

By default Workflow creates per-application Namespaces and Services so you can +easily connect your applications to other on-cluster services through standard +Kubernetes mechanisms.

+

Application Configuration

+

The router component is responsible for routing HTTP/s traffic to your +Applications as well as proxying git push and platform API traffic.

+

By default, the router component is deployed as a Kubernetes service with type +LoadBalancer; which, depending on your configuration, will provision a +cloud-native load balancer automatically.

+

The router automatically discovers routable Applications, SSL/TLS certificates +and application-specific configurations through the use of Kubernetes +annotations. Any changes to router configuration or certificates are applied +within seconds.

+

Topologies

+

Drycc Workflow no longer dictates a specific topology or server count for your +deployment. The platform components will happily run on single-server +configurations as well as multi-server production clusters.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/understanding-workflow/components/index.html b/docs/understanding-workflow/components/index.html new file mode 100644 index 000000000..e78f7dbdf --- /dev/null +++ b/docs/understanding-workflow/components/index.html @@ -0,0 +1,576 @@ + + + + + + + + + + + + + + + + + + + +Components | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Components

+
Workflow is comprised of a number of small, independent services that combine to create a distributed CaaS.
+ +

All Workflow components are deployed as services (and associated controllers) in your Kubernetes cluster. +If you are interested we have a more detailed exploration of the Workflow architecture.

+

All of the componentry for Workflow is built with composability in mind. If you +need to customize one of the components for your specific deployment or need +the functionality in your own project we invite you to give it a shot!

+

Controller

+

Project Location: drycc/controller

+

The controller component is an HTTP API server which serves as the endpoint for +the drycc CLI. The controller provides all of the platform functionality as +well as interfacing with your Kubernetes cluster. The controller persists all +of its data to the database component.

+

Passport

+

Project Location: drycc/passport

+

The passport component exposes a web API and provide OAuth2 authentication.

+

Database

+

Project Location: drycc/postgres

+

The database component is a managed instance of PostgreSQL which holds a +majority of the platforms state. Backups and WAL files are pushed to object +storage via WAL-E. When the database is restarted, backups are fetched and +replayed from object storage so no data is lost.

+

Builder

+

Project Location: drycc/builder

+

The builder component is responsible for accepting code pushes via Git and +managing the build process of your Application. The builder process is:

+
    +
  1. Receives incoming git push requests over SSH
  2. +
  3. Authenticates the user via SSH key fingerprint
  4. +
  5. Authorizes the user’s access to push code to the Application
  6. +
  7. Starts the Application Build phase (see below)
  8. +
  9. Triggers a new Release via the Controller
  10. +
+

Builder currently supports both buildpack and Dockerfile based builds.

+

Project Location: drycc/imagebuilder

+

For Buildpack-based deploys, the builder component will launch a one-shot Job +in the drycc namespace. This job runs imagebuilder component which handles +default and custom buildpacks (specified by .packbuilder). The completed image +is pushed to the managed Container registry on cluster. For more information +about buildpacks see using buildpacks.

+

Unlike buildpack-based, For Applications which contain a Dockerfile in the root +of the repository, it generates a Container image (using the underlying Container engine). +For more information see using Dockerfiles.

+

Object Storage

+

Project Location: drycc/storage

+

All of the Workflow components that need to persist data will ship them to the +object storage that was configured for the cluster.For example, database ships +its WAL files, registry stores Container images, and slugbuilder stores slugs.

+

Workflow supports either on or off-cluster storage. For production deployments +we highly recommend that you configure off-cluster object storage.

+

To facilitate experimentation, development and test environments, the default charts for +Workflow include on-cluster storage via storage.

+

If you also feel comfortable using Kubernetes persistent volumes you may +configure storage to use persistent storage available in your environment.

+

Registry

+

Project Location: drycc/registry

+

The registry component is a managed container registry which holds application +images generated from the builder component. Registry persists the Container image +images to either local storage (in development mode) or to object storage +configured for the cluster.

+

Logger: fluentbit, logger

+

The logging subsystem consists of two components. Fluentbit handles log shipping +and logger maintains a ring-buffer of application logs.

+

Project Location: drycc/fluentbit

+

Fluentbit is deployed to your Kubernetes cluster via Daemon Sets. Fluentbit +subscribes to all container logs, decorates the output with Kubernetes metadata +and can be configured to drain logs to multiple destinations. By default, +Fluentbit ships logs to the logger component, which powers drycc logs.

+

Project Location: drycc/logger

+

The logger component receives log streams from fluentbit, collating by +Application name. Logger does not persist logs to disk, instead maintaining an +in-memory ring buffer. For more information on logger see the project +documentation.

+

Monitor

+

Project Location: drycc/monitor

+

The monitoring subsystem consists of two components: Telegraf and Grafana.

+

Telegraf is the is the metrics collection agent that runs using the daemon set API. It runs on +every worker node in the cluster, fetches information about the pods currently running and ships it +to Prometheus.

+

Grafana is a standalone graphing application. It natively supports Prometheus as a datasource and +provides a robust engine for creating dashboards on top of timeseries data. Workflow provides a few +dashboards out of the box for monitoring Drycc Workflow and Kubernetes. The dashboards can be used +as a starting point for creating more custom dashboards to suit a user’s needs.

+

Prometheus

+

Project Location: drycc/prometheus

+

Prometheus is a system monitoring and alerting system. It was opensourced by SoundCloud in 2012 and is +the second project both to join and to graduate within Cloud Native Computing Foundation after Kubernetes. +Prometheus stores all metrics data as time series, i.e metrics information is stored along with the +timestamp at which it was recorded, optional key-value pairs called as labels can also be stored along +with metrics.

+

Rabbitmq

+

Project Location: drycc/rabbitmq

+

RabbitMQ is the most widely deployed open source message broker. +Controller use celery with rabbitMQ to execute the asynchronous task.

+

HelmBroker

+

Project Location: drycc/rabbitmq

+

Helm Broker is a Service Broker that exposes Helm charts as Service Classes in Service Catalog. +To do so, Helm Broker uses the concept of addons. An addon is an abstraction layer over a Helm chart +which provides all information required to convert the chart into a Service Class.

+

Prometheus

+

Project Location: drycc/rabbitmq

+

Prometheus is an open-source systemsmonitoring and alerting toolkit originally built atSoundCloud.

+

See Also

+ + + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/understanding-workflow/concepts/index.html b/docs/understanding-workflow/concepts/index.html new file mode 100644 index 000000000..f8ef6d62a --- /dev/null +++ b/docs/understanding-workflow/concepts/index.html @@ -0,0 +1,556 @@ + + + + + + + + + + + + + + + + + + + +Concepts | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Concepts

+
Drycc Workflow is a lightweight application platform that deploys and scales Twelve-Factor apps as containers across a Kubernetes cluster.
+ +

Twelve-Factor Applications

+

The Twelve-Factor App is a methodology for building modern +applications that can be scaled across a distributed system.

+

Twelve-factor is a valuable synthesis of years of experience with +software-as-a-service apps in the wild, particularly on the +Heroku platform.

+

Workflow is designed to run applications that adhere to the Twelve-Factor App +methodology and best practices.

+

Kubernetes

+

Kubernetes is an open-source cluster manager developed by Google and +donated to the Cloud Native Compute Foundation. Kubernetes manages all +the activity on your cluster, including: desired state convergence, stable +service addresses, health monitoring, service discovery, and DNS resolution.

+

Workflow builds upon Kubernetes abstractions like Services, +Deployments and Pods to provide a developer-friendly experience. +Building containers directly from application source code, aggregating logs, +and managing deployment configurations and app releases are just some of the +features Workflow adds.

+

Drycc Workflow is a set of Kubernetes-native components, installable via +Helm. Systems engineers who are familiar with Kubernetes will feel right +at home running Workflow.

+

See the components overview for more detail.

+

Container

+

[Container][] is an open source project to build, ship and run any +application as a lightweight, portable, self-sufficient container.

+

If you have not yet converted your application to containers, Workflow provides +a simple and straightforward “source to Container image” capability. Supporting +multiple language runtimes via community buildpacks, building your application +in a container can be as easy as git push drycc master.

+

Applications which use either a Dockerfile or reference external Container +images are launched unmodified.

+

Applications

+

Workflow is designed around the concept of an application, or app.

+

Applications come in one of three forms:

+
    +
  1. a collection of source files stored in a git repository
  2. +
  3. a Dockerfile and associated source files stored in a git repository
  4. +
  5. a reference to an existing image at a Container repository
  6. +
+

Applications are identified by a unique name for easy reference. If you do not +specify a name when creating your application, Workflow generates one for you. +Workflow also manages related information, including domain names, SSL +certificates, and developer-provided configuration.

+

Build, Release, Run

+

Git Push Workflow

+

Build Stage

+

The builder component processes incoming git push drycc master requests +and manages your application packaging.

+

If your application is using a buildpack, builder will launch an ephemeral +job to extract and execute the packaging instructions. The resulting +application artifact is stored by the platform for execution during the run +stage.

+

If instead builder finds a Dockerfile, it follows those instructions to +create a Container image. The resulting artifact is stored in a Drycc-managed registry which +will be referenced during the run stage.

+

If another system already builds and packages your application, that container +artifact can be used directly. When referencing an external Container +image, the builder component doesn’t attempt to repackage your +app.

+

Release Stage

+

During the release stage, a build is combined with application configuration +to create a new, numbered release. New releases are created any time a new +build is created or application configuration is changed. Tracking releases as a +“write-only ledger” this way makes it easy to rollback to any previous release.

+

Run Stage

+

The run stage deploys the new release to the underlying Kubernetes cluster by +changing the Deployment object which references the new release. +By managing the desired replica count, Workflow +orchestrates a zero-downtime, rolling update of your application. Once +successfully updated, Workflow removes the last reference to the old release. +Note that during the deploy, your application will be running in a mixed mode.

+

Backing Services

+

Workflow treats all persistent services such as databases, caches, storage, +messaging systems, and other backing services as resources managed +separately from your application. This philosophy aligns with Twelve-Factor +best practices.

+

Applications attach to backing services using environment variables. +Because apps are decoupled from backing services, they are free to +scale up independently, to use services provided by other apps, or to switch +to external or third-party vendor services.

+

See Also

+ + + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/understanding-workflow/index.html b/docs/understanding-workflow/index.html new file mode 100644 index 000000000..0e380feb4 --- /dev/null +++ b/docs/understanding-workflow/index.html @@ -0,0 +1,472 @@ + + + + + + + + + + + + + + + + + + + + + +Understanding Workflow | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Understanding Workflow

+
Understanding the architecture design of workflow.
+ + +
+ + +
+
+
+ Concepts +
+

Drycc Workflow is a lightweight application platform that deploys and scales Twelve-Factor apps as containers across a Kubernetes cluster.

+
+
+
+ Architecture +
+

Drycc Workflow is built using a service oriented architecture.

+
+
+
+ Components +
+

Workflow is comprised of a number of small, independent services that combine to create a distributed CaaS.

+
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+
+ +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/understanding-workflow/index.xml b/docs/understanding-workflow/index.xml new file mode 100644 index 000000000..8fef5c8b8 --- /dev/null +++ b/docs/understanding-workflow/index.xml @@ -0,0 +1,290 @@ + + + Drycc – Understanding Workflow + /docs/understanding-workflow/ + Recent content in Understanding Workflow on Drycc + Hugo -- gohugo.io + en + + + + + + + + + + + Docs: Concepts + /docs/understanding-workflow/concepts/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/understanding-workflow/concepts/ + + + + <h2 id="twelve-factor-applications">Twelve-Factor Applications<a class="td-heading-self-link" href="#twelve-factor-applications" aria-label="Heading self-link"></a></h2> +<p>The <a href="http://12factor.net/">Twelve-Factor App</a> is a methodology for building modern +applications that can be scaled across a distributed system.</p> +<p>Twelve-factor is a valuable synthesis of years of experience with +software-as-a-service apps in the wild, particularly on the +Heroku platform.</p> +<p>Workflow is designed to run applications that adhere to the <a href="http://12factor.net/">Twelve-Factor App</a> +methodology and best practices.</p> +<h2 id="kubernetes">Kubernetes<a class="td-heading-self-link" href="#kubernetes" aria-label="Heading self-link"></a></h2> +<p><a href="https://kubernetes.io">Kubernetes</a> is an open-source cluster manager developed by Google and +donated to the <a href="https://cncf.io/">Cloud Native Compute Foundation</a>. Kubernetes manages all +the activity on your cluster, including: desired state convergence, stable +service addresses, health monitoring, service discovery, and DNS resolution.</p> +<p>Workflow builds upon Kubernetes abstractions like Services, +Deployments and Pods to provide a developer-friendly experience. +Building containers directly from application source code, aggregating logs, +and managing deployment configurations and app releases are just some of the +features Workflow adds.</p> +<p>Drycc Workflow is a set of Kubernetes-native components, installable via +<a href="https://github.com/kubernetes/helm">Helm</a>. Systems engineers who are familiar with Kubernetes will feel right +at home running Workflow.</p> +<p>See the <a href="/docs/understanding-workflow/components/">components</a> overview for more detail.</p> +<h2 id="container">Container<a class="td-heading-self-link" href="#container" aria-label="Heading self-link"></a></h2> +<p>[Container][] is an open source project to build, ship and run any +application as a lightweight, portable, self-sufficient container.</p> +<p>If you have not yet converted your application to containers, Workflow provides +a simple and straightforward &ldquo;source to Container image&rdquo; capability. Supporting +multiple language runtimes via community <a href="/docs/applications/using-buildpacks/">buildpacks</a>, building your application +in a container can be as easy as <code>git push drycc master</code>.</p> +<p>Applications which use either a Dockerfile or reference external Container +images are launched unmodified.</p> +<h2 id="applications">Applications<a class="td-heading-self-link" href="#applications" aria-label="Heading self-link"></a></h2> +<p>Workflow is designed around the concept of an <a href="../reference-guide/terms.md#application">application</a>, or app.</p> +<p>Applications come in one of three forms:</p> +<ol> +<li>a collection of source files stored in a <code>git</code> repository</li> +<li>a Dockerfile and associated source files stored in a <code>git</code> repository</li> +<li>a reference to an existing image at a Container repository</li> +</ol> +<p>Applications are identified by a unique name for easy reference. If you do not +specify a name when creating your application, Workflow generates one for you. +Workflow also manages related information, including domain names, SSL +certificates, and developer-provided configuration.</p> +<h2 id="build-release-run">Build, Release, Run<a class="td-heading-self-link" href="#build-release-run" aria-label="Heading self-link"></a></h2> +<p><img alt="Git Push Workflow" src="../../diagrams/Git_Push_Flow.png"></p> +<h3 id="build-stage">Build Stage<a class="td-heading-self-link" href="#build-stage" aria-label="Heading self-link"></a></h3> +<p>The <a href="/docs/understanding-workflow/components/#builder">builder</a> component processes incoming <code>git push drycc master</code> requests +and manages your application packaging.</p> +<p>If your application is using a <a href="/docs/applications/using-buildpacks/">buildpack</a>, builder will launch an ephemeral +job to extract and execute the packaging instructions. The resulting +application artifact is stored by the platform for execution during the run +stage.</p> +<p>If instead builder finds a <a href="/docs/applications/using-dockerfiles/">Dockerfile</a>, it follows those instructions to +create a Container image. The resulting artifact is stored in a Drycc-managed registry which +will be referenced during the run stage.</p> +<p>If another system already builds and packages your application, that container +artifact can be used directly. When referencing an <a href="/docs/applications/using-container-images/">external Container +image</a>, the builder component doesn&rsquo;t attempt to repackage your +app.</p> +<h3 id="release-stage">Release Stage<a class="td-heading-self-link" href="#release-stage" aria-label="Heading self-link"></a></h3> +<p>During the release stage, a <a href="../reference-guide/terms.md#build">build</a> is combined with <a href="../reference-guide/terms.md#config">application configuration</a> +to create a new, numbered <a href="../reference-guide/terms.md#release">release</a>. New releases are created any time a new +build is created or application configuration is changed. Tracking releases as a +&ldquo;write-only ledger&rdquo; this way makes it easy to rollback to any previous release.</p> +<h3 id="run-stage">Run Stage<a class="td-heading-self-link" href="#run-stage" aria-label="Heading self-link"></a></h3> +<p>The run stage deploys the new release to the underlying Kubernetes cluster by +changing the Deployment object which references the new release. +By managing the desired replica count, Workflow +orchestrates a zero-downtime, rolling update of your application. Once +successfully updated, Workflow removes the last reference to the old release. +Note that during the deploy, your application will be running in a mixed mode.</p> +<h2 id="backing-services">Backing Services<a class="td-heading-self-link" href="#backing-services" aria-label="Heading self-link"></a></h2> +<p>Workflow treats all persistent services such as databases, caches, storage, +messaging systems, and other <a href="http://12factor.net/backing-services">backing services</a> as resources managed +separately from your application. This philosophy aligns with Twelve-Factor +best practices.</p> +<p>Applications attach to backing services using <a href="http://12factor.net/config">environment variables</a>. +Because apps are decoupled from backing services, they are free to +scale up independently, to use services provided by other apps, or to switch +to external or third-party vendor services.</p> +<h2 id="see-also">See Also<a class="td-heading-self-link" href="#see-also" aria-label="Heading self-link"></a></h2> +<ul> +<li><a href="/docs/understanding-workflow/architecture/">Workflow Architecture</a></li> +<li><a href="/docs/understanding-workflow/components/">Workflow Components</a></li> +</ul> + + + + + + Docs: Architecture + /docs/understanding-workflow/architecture/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/understanding-workflow/architecture/ + + + + <p>All components are published as a set of container images which can be deployed to any +compliant Kubernetes cluster.</p> +<h2 id="overview">Overview<a class="td-heading-self-link" href="#overview" aria-label="Heading self-link"></a></h2> +<p><img alt="System Overview" src="../../diagrams/Ecosystem_Basic.jpg"></p> +<p>Operators use <a href="https://github.com/kubernetes/helm">Helm</a> to configure and install the Workflow components which +interface directly with the underlying Kubernetes cluster. Service discovery, +container availability and networking are all delegated to Kubernetes, while +Workflow provides a clean and simple developer experience.</p> +<h2 id="platform-services">Platform Services<a class="td-heading-self-link" href="#platform-services" aria-label="Heading self-link"></a></h2> +<p><img alt="Workflow Overview" src="../../diagrams/Workflow_Overview.jpg"></p> +<p>Drycc Workflow provides additional functionality to your Kubernetes cluster, including:</p> +<ul> +<li><a href="/docs/understanding-workflow/components/#builder">Source to Image Builder</a> which compiles your Application code via Buildpacks or Dockerfiles</li> +<li><a href="/docs/understanding-workflow/components/#logger">Cross-Pod Log Aggregation</a> which gathers logs from all of your Application processes</li> +<li><a href="/docs/understanding-workflow/components/#controller">Simple REST API</a> which powers the CLI and any external integrations</li> +<li>Application release and rollback</li> +<li>Authentication and Authorization to Application resources</li> +<li><a href="/docs/understanding-workflow/components/#router">HTTP/HTTPS edge routing</a> for your Applications</li> +</ul> +<h2 id="kubernetes-native">Kubernetes-Native<a class="td-heading-self-link" href="#kubernetes-native" aria-label="Heading self-link"></a></h2> +<p>All platform components and applications deployed via Workflow expect to be +running on an existing Kubernetes cluster. This means that you can happily run +your Kubernetes-native workloads next to applications that are managed through +Drycc Workflow.</p> +<p><img alt="Workflow and Kubernetes" src="../../diagrams/Workflow_Detail.png"></p> +<h2 id="application-layout-and-edge-routing">Application Layout and Edge Routing<a class="td-heading-self-link" href="#application-layout-and-edge-routing" aria-label="Heading self-link"></a></h2> +<p>By default Workflow creates per-application Namespaces and Services so you can +easily connect your applications to other on-cluster services through standard +Kubernetes mechanisms.</p> +<p><img alt="Application Configuration" src="../../diagrams/Application_Layout.png"></p> +<p>The router component is responsible for routing HTTP/s traffic to your +Applications as well as proxying <code>git push</code> and platform API traffic.</p> +<p>By default, the router component is deployed as a Kubernetes service with type +<code>LoadBalancer</code>; which, depending on your configuration, will provision a +cloud-native load balancer automatically.</p> +<p>The router automatically discovers routable Applications, SSL/TLS certificates +and application-specific configurations through the use of Kubernetes +annotations. Any changes to router configuration or certificates are applied +within seconds.</p> +<h2 id="topologies">Topologies<a class="td-heading-self-link" href="#topologies" aria-label="Heading self-link"></a></h2> +<p>Drycc Workflow no longer dictates a specific topology or server count for your +deployment. The platform components will happily run on single-server +configurations as well as multi-server production clusters.</p> + + + + + + Docs: Components + /docs/understanding-workflow/components/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/understanding-workflow/components/ + + + + <p>All Workflow components are deployed as services (and associated controllers) in your Kubernetes cluster. +If you are interested we have a more detailed exploration of the <a href="/docs/understanding-workflow/architecture/">Workflow architecture</a>.</p> +<p>All of the componentry for Workflow is built with composability in mind. If you +need to customize one of the components for your specific deployment or need +the functionality in your own project we invite you to give it a shot!</p> +<h2 id="controller">Controller<a class="td-heading-self-link" href="#controller" aria-label="Heading self-link"></a></h2> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/controller">drycc/controller</a></p> +<p>The controller component is an HTTP API server which serves as the endpoint for +the <code>drycc</code> CLI. The controller provides all of the platform functionality as +well as interfacing with your Kubernetes cluster. The controller persists all +of its data to the database component.</p> +<h2 id="passport">Passport<a class="td-heading-self-link" href="#passport" aria-label="Heading self-link"></a></h2> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/passport">drycc/passport</a></p> +<p>The passport component exposes a web API and provide OAuth2 authentication.</p> +<h2 id="database">Database<a class="td-heading-self-link" href="#database" aria-label="Heading self-link"></a></h2> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/postgres">drycc/postgres</a></p> +<p>The database component is a managed instance of <a href="http://www.postgresql.org/">PostgreSQL</a> which holds a +majority of the platforms state. Backups and WAL files are pushed to object +storage via <a href="https://github.com/wal-e/wal-e">WAL-E</a>. When the database is restarted, backups are fetched and +replayed from object storage so no data is lost.</p> +<h2 id="builder">Builder<a class="td-heading-self-link" href="#builder" aria-label="Heading self-link"></a></h2> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/builder">drycc/builder</a></p> +<p>The builder component is responsible for accepting code pushes via <a href="http://git-scm.com/">Git</a> and +managing the build process of your <a href="../reference-guide/terms.md#application">Application</a>. The builder process is:</p> +<ol> +<li>Receives incoming <code>git push</code> requests over SSH</li> +<li>Authenticates the user via SSH key fingerprint</li> +<li>Authorizes the user&rsquo;s access to push code to the Application</li> +<li>Starts the Application Build phase (see below)</li> +<li>Triggers a new <a href="../reference-guide/terms.md#release">Release</a> via the Controller</li> +</ol> +<p>Builder currently supports both buildpack and Dockerfile based builds.</p> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/imagebuilder">drycc/imagebuilder</a></p> +<p>For Buildpack-based deploys, the builder component will launch a one-shot Job +in the <code>drycc</code> namespace. This job runs <code>imagebuilder</code> component which handles +default and custom buildpacks (specified by <code>.packbuilder</code>). The completed image +is pushed to the managed Container registry on cluster. For more information +about buildpacks see <a href="/docs/applications/using-buildpacks/">using buildpacks</a>.</p> +<p>Unlike buildpack-based, For Applications which contain a <code>Dockerfile</code> in the root +of the repository, it generates a Container image (using the underlying Container engine). +For more information see <a href="/docs/applications/using-dockerfiles/">using Dockerfiles</a>.</p> +<h2 id="object-storage">Object Storage<a class="td-heading-self-link" href="#object-storage" aria-label="Heading self-link"></a></h2> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/storage">drycc/storage</a></p> +<p>All of the Workflow components that need to persist data will ship them to the +object storage that was configured for the cluster.For example, database ships +its WAL files, registry stores Container images, and slugbuilder stores slugs.</p> +<p>Workflow supports either on or off-cluster storage. For production deployments +we highly recommend that you configure <a href="/docs/installing-workflow/configuring-object-storage/">off-cluster object storage</a>.</p> +<p>To facilitate experimentation, development and test environments, the default charts for +Workflow include on-cluster storage via <a href="https://github.com/drycc/storage">storage</a>.</p> +<p>If you also feel comfortable using Kubernetes persistent volumes you may +configure storage to use persistent storage available in your environment.</p> +<h2 id="registry">Registry<a class="td-heading-self-link" href="#registry" aria-label="Heading self-link"></a></h2> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/registry">drycc/registry</a></p> +<p>The registry component is a managed container registry which holds application +images generated from the builder component. Registry persists the Container image +images to either local storage (in development mode) or to object storage +configured for the cluster.</p> +<h2 id="logger-fluentbit-logger">Logger: fluentbit, logger<a class="td-heading-self-link" href="#logger-fluentbit-logger" aria-label="Heading self-link"></a></h2> +<p>The logging subsystem consists of two components. Fluentbit handles log shipping +and logger maintains a ring-buffer of application logs.</p> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/fluentbit">drycc/fluentbit</a></p> +<p>Fluentbit is deployed to your Kubernetes cluster via Daemon Sets. Fluentbit +subscribes to all container logs, decorates the output with Kubernetes metadata +and can be configured to drain logs to multiple destinations. By default, +Fluentbit ships logs to the logger component, which powers <code>drycc logs</code>.</p> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/logger">drycc/logger</a></p> +<p>The <code>logger</code> component receives log streams from <code>fluentbit</code>, collating by +Application name. Logger does not persist logs to disk, instead maintaining an +in-memory ring buffer. For more information on logger see the <a href="https://github.com/drycc/logger">project +documentation</a>.</p> +<h2 id="monitor">Monitor<a class="td-heading-self-link" href="#monitor" aria-label="Heading self-link"></a></h2> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/monitor">drycc/monitor</a></p> +<p>The monitoring subsystem consists of two components: Telegraf and Grafana.</p> +<p>Telegraf is the is the metrics collection agent that runs using the daemon set API. It runs on +every worker node in the cluster, fetches information about the pods currently running and ships it +to Prometheus.</p> +<p>Grafana is a standalone graphing application. It natively supports Prometheus as a datasource and +provides a robust engine for creating dashboards on top of timeseries data. Workflow provides a few +dashboards out of the box for monitoring Drycc Workflow and Kubernetes. The dashboards can be used +as a starting point for creating more custom dashboards to suit a user&rsquo;s needs.</p> +<h2 id="prometheus">Prometheus<a class="td-heading-self-link" href="#prometheus" aria-label="Heading self-link"></a></h2> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/prometheus">drycc/prometheus</a></p> +<p>Prometheus is a system monitoring and alerting system. It was opensourced by SoundCloud in 2012 and is +the second project both to join and to graduate within Cloud Native Computing Foundation after Kubernetes. +Prometheus stores all metrics data as time series, i.e metrics information is stored along with the +timestamp at which it was recorded, optional key-value pairs called as labels can also be stored along +with metrics.</p> +<h2 id="rabbitmq">Rabbitmq<a class="td-heading-self-link" href="#rabbitmq" aria-label="Heading self-link"></a></h2> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/rabbitmq">drycc/rabbitmq</a></p> +<p>RabbitMQ is the most widely deployed open source message broker. +Controller use celery with rabbitMQ to execute the asynchronous task.</p> +<h2 id="helmbroker">HelmBroker<a class="td-heading-self-link" href="#helmbroker" aria-label="Heading self-link"></a></h2> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/helmbroker">drycc/rabbitmq</a></p> +<p>Helm Broker is a Service Broker that exposes Helm charts as Service Classes in Service Catalog. +To do so, Helm Broker uses the concept of addons. An addon is an abstraction layer over a Helm chart +which provides all information required to convert the chart into a Service Class.</p> +<h2 id="prometheus-1">Prometheus<a class="td-heading-self-link" href="#prometheus-1" aria-label="Heading self-link"></a></h2> +<p><strong>Project Location:</strong> <a href="https://github.com/drycc/prometheus">drycc/rabbitmq</a></p> +<p>Prometheus is an open-source systemsmonitoring and alerting toolkit originally built atSoundCloud.</p> +<h2 id="see-also">See Also<a class="td-heading-self-link" href="#see-also" aria-label="Heading self-link"></a></h2> +<ul> +<li><a href="/docs/understanding-workflow/concepts/">Workflow Concepts</a></li> +<li><a href="/docs/understanding-workflow/architecture/">Workflow Architecture</a></li> +</ul> + + + + + + diff --git a/docs/users/_print/index.html b/docs/users/_print/index.html new file mode 100644 index 000000000..2a90846cb --- /dev/null +++ b/docs/users/_print/index.html @@ -0,0 +1,435 @@ + + + + + + + + + + + + + + + + + + + + + +Users | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+ + + + + +
+
+

+This is the multi-page printable view of this section. +Click here to print. +

+Return to the regular view of this page. +

+
+ + + +

Users

+
In this tutorial, you’ll learn how to manage users.
+ + + + + + + +
+ +
+
+ + + + + + + + + + + + + + + + +
+ +

1 - Drycc Workflow CLI

+
How to download, install, and start using the Drycc CLI. The Drycc CLI used to be part of the Drycc Toolbelt.
+

The Drycc Workflow command-line interface (CLI), or client, allows you to interact +with Drycc Workflow.

+

Installation

+

Install the latest drycc client for Linux or Mac OS X with: +$ curl -sfL https://www.drycc.cc/install-cli.sh | bash -

+

The installer puts drycc in your current directory, but you should move it +somewhere in your $PATH:

+
$ ln -fs $PWD/drycc /usr/local/bin/drycc
+
+

Getting Help

+

The Drycc client comes with comprehensive documentation for every command. +Use drycc help to explore the commands available to you:

+
$ drycc help
+The Drycc command-line client issues API calls to a Drycc controller.
+
+Usage: drycc <command> [<args>...]
+
+Auth commands::
+
+  login         login to a controller
+  logout        logout from the current controller
+
+Subcommands, use `drycc help [subcommand]` to learn more::
+...
+
+

To get help on subcommands, use drycc help [subcommand]:

+
$ drycc help apps
+Valid commands for apps:
+
+apps:create        create a new application
+apps:list          list accessible applications
+apps:info          view info about an application
+apps:open          open the application in a browser
+apps:logs          view aggregated application logs
+apps:run           run a command in an ephemeral app container
+apps:destroy       destroy an application
+apps:transfer      transfer app ownership to another user
+
+Use `drycc help [command]` to learn more
+
+

Support for Multiple Profiles

+

The CLI reads from the default client profile, which is located on your +workstation at $HOME/.drycc/client.json.

+

Easily switch between multiple Drycc Workflow installations or users by setting +the $DRYCC_PROFILE environment variable or by using the -c flag.

+

There are two ways to set the $DRYCC_PROFILE option.

+
    +
  1. Path to a json configuration file.
  2. +
  3. Profile name. If you set profile to just a name, it will be saved alongside the default profile, +in $HOME/.drycc/<name>.json.
  4. +
+

Examples:

+
$ DRYCC_PROFILE=production drycc login drycc.production.com
+...
+Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71
+Waiting for login... .o.Logged in as drycc
+Configuration saved to /home/testuser/.drycc/production.json
+$ DRYCC_PROFILE=~/config.json drycc login drycc.example.com
+...
+Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71
+Waiting for login... .o.Logged in as drycc
+Configuration saved to /home/testuser/config.json
+
+

The configuration flag works identically to and overrides $DRYCC_PROFILE:

+
$ drycc whoami -c ~/config.json
+You are drycc at drycc.example.com
+
+

Proxy Support

+

If your workstation uses a proxy to reach the network where the cluster lies, +set the http_proxy or https_proxy environment variable to enable proxy support:

+
$ export http_proxy="http://proxyip:port"
+$ export https_proxy="http://proxyip:port"
+
+

!!! note +Configuring a proxy is generally not necessary for local Minikube clusters.

+

CLI Plugins

+

Plugins allow developers to extend the functionality of the Drycc Client, adding new commands or features.

+

If an unknown command is specified, the client will attempt to execute the command as a dash-separated command. In this case, drycc resource:command will execute drycc-resource with the argument list command. In full form:

+
$ # these two are identical
+$ drycc accounts:list
+$ drycc-accounts list
+
+

Any flags after the command will also be sent to the plugin as an argument:

+
$ # these two are identical
+$ drycc accounts:list --debug
+$ drycc-accounts list --debug
+
+

But flags preceding the command will not:

+
$ # these two are identical
+$ drycc --debug accounts:list
+$ drycc-accounts list
+
+ +
+ + + + + + + + + + + +
+ +

2 - Users and Registration

+
Get started on Drycc today
+

Workflow use the passport component to create and authorize users, it can config options for LDAP authentication or browse passport web site to register users.

+

Login to Workflow

+

If you already have an account, use drycc login to authenticate against the Drycc Workflow API.

+
$ drycc login http://drycc.example.com
+Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71
+Waiting for login... .o.Logged in as drycc
+Configuration file written to /root/.drycc/client.json
+
+

Or you can login with username and password +$ drycc login http://drycc.example.com –username=demo –password=demo +Configuration file written to /root/.drycc/client.json

+

Logout from Workflow

+

Logout of an existing controller session using drycc logout.

+
$ drycc logout
+Logged out as drycc
+
+

Verify Your Session

+

You can verify your client configuration by running drycc whoami.

+
$ drycc whoami
+You are drycc at http://drycc.example.com
+
+

!!! note +Session and client configuration is stored in the ~/.drycc/client.json file.

+ +
+ + + + + + + + + + + +
+ +

3 - Users and SSH Keys

+
Create, manage, and upload SSH keys to Drycc for use in deploying and connecting to applications.
+

For Dockerfile and Buildpack based application deploys via git push, Drycc Workflow identifies users via SSH +keys. SSH keys are pushed to the platform and must be unique to each user. Users may have multiple SSH keys as needed.

+

Generate an SSH Key

+

If you do not already have an SSH key or would like to create a new key for Drycc Workflow, generate a new key using +ssh-keygen:

+
$ ssh-keygen -f ~/.ssh/id_drycc -t rsa
+Generating public/private rsa key pair.
+Enter passphrase (empty for no passphrase):
+Enter same passphrase again:
+Your identification has been saved in /Users/admin/.ssh/id_drycc.
+Your public key has been saved in /Users/admin/.ssh/id_drycc.pub.
+The key fingerprint is:
+3d:ac:1f:f4:83:f7:64:51:c1:7e:7f:80:b6:70:36:c9 admin@plinth-23437.local
+The key's randomart image is:
++--[ RSA 2048]----+
+|              .. |
+|               ..|
+|           . o. .|
+|         o. E .o.|
+|        S == o..o|
+|         o +.  .o|
+|        . o + o .|
+|         . o =   |
+|          .   .  |
++-----------------+
+$ ssh-add ~/.ssh/id_drycc
+Identity added: /Users/admin/.ssh/id_drycc (/Users/admin/.ssh/id_drycc)
+

Adding and Removing SSH Keys

+

By publishing the public half of your SSH key to Drycc Workflow the component responsible for receiving git push +will be able to authenticate the user and ensure that they have access to the destination application.

+
$ drycc keys:add ~/.ssh/id_drycc.pub
+Uploading id_drycc.pub to drycc... done
+

You can always view the keys associated with your user as well:

+
$ drycc keys:list
+ID                              OWNER    KEY                           
+admin@plinth-23437.local        admin    ssh-rsa abc AAAAB3Nz...3437.local
+admin@subgenius.local           admin    ssh-rsa 123 AAAAB3Nz...nius.local
+

Remove keys by their name:

+
$ drycc keys:remove admin@plinth-23437.local
+Removing admin@plinth-23437.local SSH Key... don
+
+
+ + + + + + + + + +
+
+
+ + +
+ + + + + + diff --git a/docs/users/cli/index.html b/docs/users/cli/index.html new file mode 100644 index 000000000..bd0150ed6 --- /dev/null +++ b/docs/users/cli/index.html @@ -0,0 +1,555 @@ + + + + + + + + + + + + + + + + + + + +Drycc Workflow CLI | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Drycc Workflow CLI

+
How to download, install, and start using the Drycc CLI. The Drycc CLI used to be part of the Drycc Toolbelt.
+ +

The Drycc Workflow command-line interface (CLI), or client, allows you to interact +with Drycc Workflow.

+

Installation

+

Install the latest drycc client for Linux or Mac OS X with: +$ curl -sfL https://www.drycc.cc/install-cli.sh | bash -

+

The installer puts drycc in your current directory, but you should move it +somewhere in your $PATH:

+
$ ln -fs $PWD/drycc /usr/local/bin/drycc
+
+

Getting Help

+

The Drycc client comes with comprehensive documentation for every command. +Use drycc help to explore the commands available to you:

+
$ drycc help
+The Drycc command-line client issues API calls to a Drycc controller.
+
+Usage: drycc <command> [<args>...]
+
+Auth commands::
+
+  login         login to a controller
+  logout        logout from the current controller
+
+Subcommands, use `drycc help [subcommand]` to learn more::
+...
+
+

To get help on subcommands, use drycc help [subcommand]:

+
$ drycc help apps
+Valid commands for apps:
+
+apps:create        create a new application
+apps:list          list accessible applications
+apps:info          view info about an application
+apps:open          open the application in a browser
+apps:logs          view aggregated application logs
+apps:run           run a command in an ephemeral app container
+apps:destroy       destroy an application
+apps:transfer      transfer app ownership to another user
+
+Use `drycc help [command]` to learn more
+
+

Support for Multiple Profiles

+

The CLI reads from the default client profile, which is located on your +workstation at $HOME/.drycc/client.json.

+

Easily switch between multiple Drycc Workflow installations or users by setting +the $DRYCC_PROFILE environment variable or by using the -c flag.

+

There are two ways to set the $DRYCC_PROFILE option.

+
    +
  1. Path to a json configuration file.
  2. +
  3. Profile name. If you set profile to just a name, it will be saved alongside the default profile, +in $HOME/.drycc/<name>.json.
  4. +
+

Examples:

+
$ DRYCC_PROFILE=production drycc login drycc.production.com
+...
+Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71
+Waiting for login... .o.Logged in as drycc
+Configuration saved to /home/testuser/.drycc/production.json
+$ DRYCC_PROFILE=~/config.json drycc login drycc.example.com
+...
+Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71
+Waiting for login... .o.Logged in as drycc
+Configuration saved to /home/testuser/config.json
+
+

The configuration flag works identically to and overrides $DRYCC_PROFILE:

+
$ drycc whoami -c ~/config.json
+You are drycc at drycc.example.com
+
+

Proxy Support

+

If your workstation uses a proxy to reach the network where the cluster lies, +set the http_proxy or https_proxy environment variable to enable proxy support:

+
$ export http_proxy="http://proxyip:port"
+$ export https_proxy="http://proxyip:port"
+
+

!!! note +Configuring a proxy is generally not necessary for local Minikube clusters.

+

CLI Plugins

+

Plugins allow developers to extend the functionality of the Drycc Client, adding new commands or features.

+

If an unknown command is specified, the client will attempt to execute the command as a dash-separated command. In this case, drycc resource:command will execute drycc-resource with the argument list command. In full form:

+
$ # these two are identical
+$ drycc accounts:list
+$ drycc-accounts list
+
+

Any flags after the command will also be sent to the plugin as an argument:

+
$ # these two are identical
+$ drycc accounts:list --debug
+$ drycc-accounts list --debug
+
+

But flags preceding the command will not:

+
$ # these two are identical
+$ drycc --debug accounts:list
+$ drycc-accounts list
+
+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/users/index.html b/docs/users/index.html new file mode 100644 index 000000000..d9eacdb06 --- /dev/null +++ b/docs/users/index.html @@ -0,0 +1,472 @@ + + + + + + + + + + + + + + + + + + + + + +Users | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Users

+
In this tutorial, you’ll learn how to manage users.
+ + +
+ + +
+
+
+ Drycc Workflow CLI +
+

How to download, install, and start using the Drycc CLI. The Drycc CLI used to be part of the Drycc Toolbelt.

+
+
+
+ Users and Registration +
+

Get started on Drycc today

+
+
+
+ Users and SSH Keys +
+

Create, manage, and upload SSH keys to Drycc for use in deploying and connecting to applications.

+
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+
+ +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/users/index.xml b/docs/users/index.xml new file mode 100644 index 000000000..c43396601 --- /dev/null +++ b/docs/users/index.xml @@ -0,0 +1,212 @@ + + + Drycc – Users + /docs/users/ + Recent content in Users on Drycc + Hugo -- gohugo.io + en + + + + + + + + + + + Docs: Drycc Workflow CLI + /docs/users/cli/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/users/cli/ + + + + <p>The Drycc Workflow command-line interface (CLI), or client, allows you to interact +with Drycc Workflow.</p> +<h2 id="installation">Installation<a class="td-heading-self-link" href="#installation" aria-label="Heading self-link"></a></h2> +<p>Install the latest <code>drycc</code> client for Linux or Mac OS X with: +$ curl -sfL <a href="https://www.drycc.cc/install-cli.sh">https://www.drycc.cc/install-cli.sh</a> | bash -</p> +<p>The installer puts <code>drycc</code> in your current directory, but you should move it +somewhere in your $PATH:</p> +<pre><code>$ ln -fs $PWD/drycc /usr/local/bin/drycc +</code></pre> +<h2 id="getting-help">Getting Help<a class="td-heading-self-link" href="#getting-help" aria-label="Heading self-link"></a></h2> +<p>The Drycc client comes with comprehensive documentation for every command. +Use <code>drycc help</code> to explore the commands available to you:</p> +<pre><code>$ drycc help +The Drycc command-line client issues API calls to a Drycc controller. + +Usage: drycc &lt;command&gt; [&lt;args&gt;...] + +Auth commands:: + + login login to a controller + logout logout from the current controller + +Subcommands, use `drycc help [subcommand]` to learn more:: +... +</code></pre> +<p>To get help on subcommands, use <code>drycc help [subcommand]</code>:</p> +<pre><code>$ drycc help apps +Valid commands for apps: + +apps:create create a new application +apps:list list accessible applications +apps:info view info about an application +apps:open open the application in a browser +apps:logs view aggregated application logs +apps:run run a command in an ephemeral app container +apps:destroy destroy an application +apps:transfer transfer app ownership to another user + +Use `drycc help [command]` to learn more +</code></pre> +<h2 id="support-for-multiple-profiles">Support for Multiple Profiles<a class="td-heading-self-link" href="#support-for-multiple-profiles" aria-label="Heading self-link"></a></h2> +<p>The CLI reads from the default <code>client</code> profile, which is located on your +workstation at <code>$HOME/.drycc/client.json</code>.</p> +<p>Easily switch between multiple Drycc Workflow installations or users by setting +the <code>$DRYCC_PROFILE</code> environment variable or by using the <code>-c</code> flag.</p> +<p>There are two ways to set the <code>$DRYCC_PROFILE</code> option.</p> +<ol> +<li>Path to a json configuration file.</li> +<li>Profile name. If you set profile to just a name, it will be saved alongside the default profile, +in <code>$HOME/.drycc/&lt;name&gt;.json</code>.</li> +</ol> +<p>Examples:</p> +<pre><code>$ DRYCC_PROFILE=production drycc login drycc.production.com +... +Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71 +Waiting for login... .o.Logged in as drycc +Configuration saved to /home/testuser/.drycc/production.json +$ DRYCC_PROFILE=~/config.json drycc login drycc.example.com +... +Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71 +Waiting for login... .o.Logged in as drycc +Configuration saved to /home/testuser/config.json +</code></pre> +<p>The configuration flag works identically to and overrides <code>$DRYCC_PROFILE</code>:</p> +<pre><code>$ drycc whoami -c ~/config.json +You are drycc at drycc.example.com +</code></pre> +<h2 id="proxy-support">Proxy Support<a class="td-heading-self-link" href="#proxy-support" aria-label="Heading self-link"></a></h2> +<p>If your workstation uses a proxy to reach the network where the cluster lies, +set the <code>http_proxy</code> or <code>https_proxy</code> environment variable to enable proxy support:</p> +<pre><code>$ export http_proxy=&quot;http://proxyip:port&quot; +$ export https_proxy=&quot;http://proxyip:port&quot; +</code></pre> +<p>!!! note +Configuring a proxy is generally not necessary for local Minikube clusters.</p> +<h2 id="cli-plugins">CLI Plugins<a class="td-heading-self-link" href="#cli-plugins" aria-label="Heading self-link"></a></h2> +<p>Plugins allow developers to extend the functionality of the Drycc Client, adding new commands or features.</p> +<p>If an unknown command is specified, the client will attempt to execute the command as a dash-separated command. In this case, <code>drycc resource:command</code> will execute <code>drycc-resource</code> with the argument list <code>command</code>. In full form:</p> +<pre><code>$ # these two are identical +$ drycc accounts:list +$ drycc-accounts list +</code></pre> +<p>Any flags after the command will also be sent to the plugin as an argument:</p> +<pre><code>$ # these two are identical +$ drycc accounts:list --debug +$ drycc-accounts list --debug +</code></pre> +<p>But flags preceding the command will not:</p> +<pre><code>$ # these two are identical +$ drycc --debug accounts:list +$ drycc-accounts list +</code></pre> + + + + + + Docs: Users and Registration + /docs/users/registration/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/users/registration/ + + + + <p>Workflow use the passport component to create and authorize users, it can config options for LDAP authentication or browse passport web site to register users.</p> +<h2 id="login-to-workflow">Login to Workflow<a class="td-heading-self-link" href="#login-to-workflow" aria-label="Heading self-link"></a></h2> +<p>If you already have an account, use <code>drycc login</code> to authenticate against the Drycc Workflow API.</p> +<pre><code>$ drycc login http://drycc.example.com +Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71 +Waiting for login... .o.Logged in as drycc +Configuration file written to /root/.drycc/client.json +</code></pre> +<p>Or you can login with username and password +$ drycc login <a href="http://drycc.example.com">http://drycc.example.com</a> &ndash;username=demo &ndash;password=demo +Configuration file written to /root/.drycc/client.json</p> +<h2 id="logout-from-workflow">Logout from Workflow<a class="td-heading-self-link" href="#logout-from-workflow" aria-label="Heading self-link"></a></h2> +<p>Logout of an existing controller session using <code>drycc logout</code>.</p> +<pre><code>$ drycc logout +Logged out as drycc +</code></pre> +<h2 id="verify-your-session">Verify Your Session<a class="td-heading-self-link" href="#verify-your-session" aria-label="Heading self-link"></a></h2> +<p>You can verify your client configuration by running <code>drycc whoami</code>.</p> +<pre><code>$ drycc whoami +You are drycc at http://drycc.example.com +</code></pre> +<p>!!! note +Session and client configuration is stored in the <code>~/.drycc/client.json</code> file.</p> + + + + + + Docs: Users and SSH Keys + /docs/users/ssh-keys/ + Mon, 01 Jan 0001 00:00:00 +0000 + + /docs/users/ssh-keys/ + + + + <p>For <strong>Dockerfile</strong> and <strong>Buildpack</strong> based application deploys via <code>git push</code>, Drycc Workflow identifies users via SSH +keys. SSH keys are pushed to the platform and must be unique to each user. Users may have multiple SSH keys as needed.</p> +<h2 id="generate-an-ssh-key">Generate an SSH Key<a class="td-heading-self-link" href="#generate-an-ssh-key" aria-label="Heading self-link"></a></h2> +<p>If you do not already have an SSH key or would like to create a new key for Drycc Workflow, generate a new key using +<code>ssh-keygen</code>:</p> +<pre tabindex="0"><code>$ ssh-keygen -f ~/.ssh/id_drycc -t rsa +Generating public/private rsa key pair. +Enter passphrase (empty for no passphrase): +Enter same passphrase again: +Your identification has been saved in /Users/admin/.ssh/id_drycc. +Your public key has been saved in /Users/admin/.ssh/id_drycc.pub. +The key fingerprint is: +3d:ac:1f:f4:83:f7:64:51:c1:7e:7f:80:b6:70:36:c9 admin@plinth-23437.local +The key&#39;s randomart image is: ++--[ RSA 2048]----+ +| .. | +| ..| +| . o. .| +| o. E .o.| +| S == o..o| +| o +. .o| +| . o + o .| +| . o = | +| . . | ++-----------------+ +$ ssh-add ~/.ssh/id_drycc +Identity added: /Users/admin/.ssh/id_drycc (/Users/admin/.ssh/id_drycc) +</code></pre><h2 id="adding-and-removing-ssh-keys">Adding and Removing SSH Keys<a class="td-heading-self-link" href="#adding-and-removing-ssh-keys" aria-label="Heading self-link"></a></h2> +<p>By publishing the <strong>public</strong> half of your SSH key to Drycc Workflow the component responsible for receiving <code>git push</code> +will be able to authenticate the user and ensure that they have access to the destination application.</p> +<pre tabindex="0"><code>$ drycc keys:add ~/.ssh/id_drycc.pub +Uploading id_drycc.pub to drycc... done +</code></pre><p>You can always view the keys associated with your user as well:</p> +<pre tabindex="0"><code>$ drycc keys:list +ID OWNER KEY +admin@plinth-23437.local admin ssh-rsa abc AAAAB3Nz...3437.local +admin@subgenius.local admin ssh-rsa 123 AAAAB3Nz...nius.local +</code></pre><p>Remove keys by their name:</p> +<pre tabindex="0"><code>$ drycc keys:remove admin@plinth-23437.local +Removing admin@plinth-23437.local SSH Key... don +</code></pre> + + + + + diff --git a/docs/users/registration/index.html b/docs/users/registration/index.html new file mode 100644 index 000000000..21c1beb18 --- /dev/null +++ b/docs/users/registration/index.html @@ -0,0 +1,484 @@ + + + + + + + + + + + + + + + + + + + +Users and Registration | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Users and Registration

+
Get started on Drycc today
+ +

Workflow use the passport component to create and authorize users, it can config options for LDAP authentication or browse passport web site to register users.

+

Login to Workflow

+

If you already have an account, use drycc login to authenticate against the Drycc Workflow API.

+
$ drycc login http://drycc.example.com
+Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71
+Waiting for login... .o.Logged in as drycc
+Configuration file written to /root/.drycc/client.json
+
+

Or you can login with username and password +$ drycc login http://drycc.example.com –username=demo –password=demo +Configuration file written to /root/.drycc/client.json

+

Logout from Workflow

+

Logout of an existing controller session using drycc logout.

+
$ drycc logout
+Logged out as drycc
+
+

Verify Your Session

+

You can verify your client configuration by running drycc whoami.

+
$ drycc whoami
+You are drycc at http://drycc.example.com
+
+

!!! note +Session and client configuration is stored in the ~/.drycc/client.json file.

+ + +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/docs/users/ssh-keys/index.html b/docs/users/ssh-keys/index.html new file mode 100644 index 000000000..559c1499e --- /dev/null +++ b/docs/users/ssh-keys/index.html @@ -0,0 +1,500 @@ + + + + + + + + + + + + + + + + + + + +Users and SSH Keys | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ + + + + +
+

Users and SSH Keys

+
Create, manage, and upload SSH keys to Drycc for use in deploying and connecting to applications.
+ +

For Dockerfile and Buildpack based application deploys via git push, Drycc Workflow identifies users via SSH +keys. SSH keys are pushed to the platform and must be unique to each user. Users may have multiple SSH keys as needed.

+

Generate an SSH Key

+

If you do not already have an SSH key or would like to create a new key for Drycc Workflow, generate a new key using +ssh-keygen:

+
$ ssh-keygen -f ~/.ssh/id_drycc -t rsa
+Generating public/private rsa key pair.
+Enter passphrase (empty for no passphrase):
+Enter same passphrase again:
+Your identification has been saved in /Users/admin/.ssh/id_drycc.
+Your public key has been saved in /Users/admin/.ssh/id_drycc.pub.
+The key fingerprint is:
+3d:ac:1f:f4:83:f7:64:51:c1:7e:7f:80:b6:70:36:c9 admin@plinth-23437.local
+The key's randomart image is:
++--[ RSA 2048]----+
+|              .. |
+|               ..|
+|           . o. .|
+|         o. E .o.|
+|        S == o..o|
+|         o +.  .o|
+|        . o + o .|
+|         . o =   |
+|          .   .  |
++-----------------+
+$ ssh-add ~/.ssh/id_drycc
+Identity added: /Users/admin/.ssh/id_drycc (/Users/admin/.ssh/id_drycc)
+

Adding and Removing SSH Keys

+

By publishing the public half of your SSH key to Drycc Workflow the component responsible for receiving git push +will be able to authenticate the user and ensure that they have access to the destination application.

+
$ drycc keys:add ~/.ssh/id_drycc.pub
+Uploading id_drycc.pub to drycc... done
+

You can always view the keys associated with your user as well:

+
$ drycc keys:list
+ID                              OWNER    KEY                           
+admin@plinth-23437.local        admin    ssh-rsa abc AAAAB3Nz...3437.local
+admin@subgenius.local           admin    ssh-rsa 123 AAAAB3Nz...nius.local
+

Remove keys by their name:

+
$ drycc keys:remove admin@plinth-23437.local
+Removing admin@plinth-23437.local SSH Key... don
+
+ +
+ + + + + + +
+ +
+
+ Last modified 19.09.2024: feat(api): new build api (a42cdc8) +
+ +
+ + +
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/favicons/android-144x144.png b/favicons/android-144x144.png new file mode 100644 index 0000000000000000000000000000000000000000..8851c09a46da057628d63a633e0cbec71e0cb0cb GIT binary patch literal 4299 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 literal 0 HcmV?d00001 diff --git a/favicons/android-192x192.png b/favicons/android-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..94b2ad2dba9c9bfa459894c2fee6433ec97ed317 GIT binary patch literal 5264 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 Xdf+!G8nFRY8iBS3R{gcAUFd%R&6IoZ literal 0 HcmV?d00001 diff --git a/favicons/android-36x36.png b/favicons/android-36x36.png new file mode 100644 index 0000000000000000000000000000000000000000..7ec5cf650bcb425d848d7c50d78bca878bcab584 GIT binary patch literal 980 zcmV;_11tQAP)d=B{ict>ib&jis1Q{T zU0aHp9FTnKp=u>o5VasmO9{BLAr7$~-F}_nGf|JMWEv zm+TW>G9J7Fs+N(83XP7A#sop=B81eXB9e>RJYizN$4QIwg6 zf%LsRinmkH@8=-Bb{W3GcOka4*(=l@fY=c@r;wvSCS%yo?&85_7M(qp(a{}&Kxxf2 zWEnaNR46gr(T=gPqazxT@X>&b4!?a-i$s7(0YNzXcN_(>K$1TlqW2QT%HIsdCmdph zuJY-C8y^qIa7$;kN4CHa z2@rI)(sSvkrI;L5sH~TvWtVU__bd9tQM}VN2#;jn=P02NiP*dv+AQ3|H`+YBk_U&U zN9YaoAm|I)3Uejci)g41F0o1XP;P$*w^nb1aRbcc2>V0uxx5vC-b6Iq2N!J;&?!5` zUwa$aDs15O_8#L*O-xxW7hg3SM-{3Ttd{kLfyT$j>wX5k2ykg> zsgz2k>Kf3*larG>!^6YZUC&H>wWv_ZCX>lL)->%aMNv{0niwtPv9YmFOw;T(O|!0- zs}0y8=X_yiW~O*yphnfGXTOstuP6RSjCqqvf19{ zg5pCTgiTaRwm~1p3e_}P)S`|5s8Y3cliEE@t=$@vH22U24hr@BIrluyIH6|U? z-`|h+_I4Tyg=z&s_z3`wWf9EzQT2T})r=5Tb?DzZO@p#4+McLTe z+IpTm>uS0KC4I#tr9d_Fol3Q-gh2m}_n-R{AJ z2~bKgeBf(@2l}IHaJjiyc;>e$0pAYbxHt3oS|A(_FK%gRd6+N(B1JH`c|8jDAAzyZ ziYMQ=VuCj~KZSMwVQ3~m6$L}Ps-d^okYitn@tzCFU%if5BByu(X0H8QI{}q6H1q(& z&HDgCU~N7O$D^EER_0>c zDnmTXZ;VNrfI=v?v^>X0^El`^1$}?$FlVNYS)kmm$DS&qc0C{|6q~+(hPo;}%1TUd zop`|vuLiDIq(}3neC-5Oi0^*+7gz5`qTmY(v*31_W0H7ZaMHF=^c0#Pc>GibrNI0- zJPb3~w@^x)LKE@?d_$L_r;x+)F|7HP^r?V)3LU%X#;w0@g9C>=eI8C!|G+GuQ<1AJd zS27FOXBDBUbiH;0D(UrMKUyz|QRpw1@4~v$HOvAj(Zp&WM3e{!rI^9zq}NqK&7k!B zI>Psk0aQVbeJ8T#eUUyDpp+os`wS$n7=-G<2k(Qou?y%7c4S+twCe#%B#iqu03}T@ z%&kE1%I27|pEbJ@xl6y*P=HbdZ#99uxD9|nXDUVBvg0vGaO(YAI{}rHNCC+I+>Q1C zZ!Uw5PowK}45^MOG^v-ln8+A|GXifXDv_Vplkz@LUthn&X0!e1bUGO~!Sup{!63T3 zyAcY7N<>k7G}&xSpBC%t>gMu1e~9C_{OO@Fk5*qV{C$0WCw)GjJZ%ByWi<$7s(=Pu p%u8kjm{XOYz)S@alvw6zUjfUTx=&P2uVDZH002ovPDHLkV1h_z_%Q$g literal 0 HcmV?d00001 diff --git a/favicons/android-72x72.png b/favicons/android-72x72.png new file mode 100644 index 0000000000000000000000000000000000000000..230b18fd597f3add2a8ab181d3ba992f6cba9aa0 GIT binary patch literal 1926 zcmV;12YL93P)m!;1S~*F6k-9g02y;4mVzt=Sqd^nz*3Mgerfxl z&6_uiZnyh7RaF-m8$$Zll+w5?%cpvKdxzWF+LZKrn%puiKwGzNwTq&-1;Fl^7*wi# zQc9m28XEevsi`TRs%^6NX#uLPt}bF(_SJ%df@+V)1DDH{>^(E`dpsV;z`y`TMn<40 z%6hNYyAJ@(hA7FYildcpFd9sA@_B4b+u-4 zyJbBfjb=|z4_aDU5DW$-Ldc_jzrVSusYy+V^dybv1R!m0hYugdfddB+4u=O-Rejd) z_qSyN(wqULK{|5eh^8bG4u`t{yy0{@n`>)pi4i5uDL@lSYH4YSN2AfBgplpKckga9 z;<)D=AXQb-+1ZKa=4L4xjUG}}^)0X0dnjEM%{f3C2uYG~^ypFS-@iX1Nzzw@kR4vH zw>KR~a}p4x6tP$g?d|P2c<`X4C`u#4Fgthc+BJ|Wq&W#lgP=hQg+dx2baZscgpe9Z zlK$1u&>*D(X+{BQg9IT^$HyQCE&zmrFP;xR-vzKN7$&XPr!qhId_L^kw-13p;GcpZ z?5wM+8%?Eyv__~MHIil08XT%Bh;;veUmEv78tBu<#n|j9dGQrEZ(E~7%EU7j=)S%_ z9Z)bB^eT$-rq}BoN#&h03MhWz90DIVAacAD!opI37a*VWgW)(Vd}%uvyO_#Yf7ezh zDTUxJo>GaX1{CS;!f@?2u%2=hKlK8HyaHUT-wAo>v>`AP#_lJ#pm5zISq$hz7lvQk z2LAdA%-i%V?D_e)SpOEJ!JomoiU5N?Xx_#rP;l=9*$YTMKa5KszK6)kV-T0G0PDy> zw67O@@d6ZW*a(If3@J&xb{T|4*JLLkJ=7{PBEFLt+52xqdyeTaY@TuyJ^UBs-FBz$ zi)Q*Utq+=*IFV&2!HZBve$oHL<>l)Rn-y#`%|`Fv^nmnmPXSp?6#4{?(Ou7MRP61D;ZScPfpv<&_DAzk=H_Pwl4%vB!MPkJXl#$*t79?P_(aMTS16n!gZifn z;jpKbhW)lR?K}gXn_7*g2Go5<#*WXfAm2gp)IAQ!3dMigC5%RlfteumbX5-4-Rj8B zD5fds_@Ip1#w(~?O7TpU6Rvy_uQi6?JDZs+tgHug>Vkq@UyflkOi*>R2v0GGy&X}6 zq7*lj@!(ivN~*faj$4=8vQt6YHi*RuzV%7i`+XGWMiZrBS1yBlZxQj>9XSxL`lXqS z_onqhdZI`v#-ao#&d3=o~(V!$U{(%Y`CGA^ueH019&olP!KmemAv(;;M}H!SC?j6JOwR>`Ee&W(8bd zyd2x^u7=1Ps|QVoplJbV{^zH_0P5P_g(OS3YsnfoI6MC5{|;d}g37Yh;8}h;bDXrz z8qe)mReDQyMllUg&xKy>{N^3pSX_Z8R&PRS;Uc`=`Zj!*66IH;&tF$Pj{8^qF?#{^ z1^Q8U@Lg~$heuYfM@2~mKIr%mXGVumlv4<2_e55(nLz!xk-tot7zA)g^I6UMe>&%;*saP|TskzvI8 z-v=4(0$7{ov9-%Gz*dahKYWw{N3CCvWGA3Rh$m1+k0XBi6OizrzVM8FJ{%Q)2kR`i z@}S@9K}r}Tc1e$7tYaYftS65b6qNJq6_)^bM4`+9<; zr(l=J{8Kgfe`{|6O0wb>APbN&r(h|_Qjnz}V+1S(8RKX9pd|c$1zhK*lu!JWyZ`_I M07*qoM6N<$f-_H+X8-^I literal 0 HcmV?d00001 diff --git a/favicons/android-96x96.png b/favicons/android-96x96.png new file mode 100644 index 0000000000000000000000000000000000000000..8cc698973c29508f60b691caa1c65c0808e45e00 GIT binary patch literal 2309 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 literal 0 HcmV?d00001 diff --git a/favicons/favicon-16x16.png b/favicons/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..ce918ee3ab82aef2ca3ca06689bbc80f1e131871 GIT binary patch literal 498 zcmV-G$w3H# zJ(MCzT5>4VhCs6;*(4fL!Hrus=wh3#hGcHTy!pNV`@i=DJn{&W|FhZbq9jRD5YurS zr(7lKWnwxyGo^U>Ot-T7^4?EpD?_> zM)d6lAd0ui$U+Q6iGp)(8HTZC7{*~BKvh+G^ra2BLp*=I3SpFkga|~5%m!>Qjeh># z$Jb*Aga{Bv8rNUQSfe3yW-0JI;8!;KgFd2jVZX|GIfAeho~?kXjQ%)lLu2?UHxRGvYMtjt!RX`6Jw_ux7`NDD9h5(Ie( zf*iXKAb60*gJW5iRV)_owlSa2D~z%2L?W>~ZNF^WwyV|Zhf=B3{%a0At-7vLLWn#K o;JU8UYPC+9&8G7&;6aQ12hk|m5jY0o-v9sr07*qoM6N<$g7p33od5s; literal 0 HcmV?d00001 diff --git a/favicons/favicon-256.png b/favicons/favicon-256.png new file mode 100644 index 0000000000000000000000000000000000000000..ebd3f8c988e6b39943d71c1f0e1d706621ed817f GIT binary patch literal 8037 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 literal 0 HcmV?d00001 diff --git a/favicons/favicon-32x32.png b/favicons/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..e95c80ad67c19eac36c258c6ac27336a86ac59b8 GIT binary patch literal 807 zcmV+?1K9kDP)?~j&FOZwy|E3A>`bQ}>&ExyT)gLf-_LoTbDsA-1pm2_ z|GYj<05v1v@p$^IR%-CtoEJ ziMt~sBTB7Fjs>uTn4O*FKA$ftacqE{#X_M_L6+swbUOXO>-FaLBI*Vd zGZ}0xL@VRPwhpi+LtUxKX0!17{n6>^Y4_03(A<#$sem7u*aFB_7EF{NG@n)lP*K9E z?p{z)tn}yedC0Q-DG&&h0q>3sNIo6K_F@dBd=7%e3ej;{6+rYNOr1Bu^!i;uI2?`z zgTcPP0u(Z7tWCTGVGL(_Zi7ipb)}#j0Zjmj?*+X1m;)uijkZQuO||QjKmkIkua{Xgu=ul8#O2+VC^;(ZpJ6WqF@hvU4U3J@5<#TEhO ztEPZbsf79X1{mdNzhDBZbBoX{0GAJ0MF-r zNT%0N0!MOl9j#`YDnQan=xy(TNnhQ>Gy^QHf5G^NXW%H|PKOh=8URWN3=M|e6ln(F z#XO4HmC935sTG9k_N@b&e}?(h*T{Vhg79)B>;M(dsRO7ULd#W9)~Ia?wwInj`LS35 zP@MtHXjca?2|8OhsPJnq(4-QUlr-`yetM*}(hoJxf002ovPDHLkV1g%NdCvd< literal 0 HcmV?d00001 diff --git a/favicons/favicon.ico b/favicons/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..216330ff2ec229da1ac9cdbd2a231e577dd385d9 GIT binary patch literal 1150 zcmd6lO-lkn7{|xx=0ymqQ+Vjmp*}+37x5knzJTEO@EVj6bgEoK(4f#IDp2xL5-GuI z$}Y<)x~A=mvro^ida-TYOVBL89ri!-e_nQm5Dz{+AHlbu9IO(uP6*jSP(o#@<3tFq z{o(LLB9X0lJihHjEEe+z0)ZcuBoYa4CX+emIPT7gYPFg*V=VT8ny*wUwG6`mCwQJ0 zFxT#H{t5b7L4{mffj4;q^%*^dT5$y&PJW#l@Feyj*X+W*sKBGBT69Jemwp`@VjZ&2 zmvCA+M$#5F{spK(VOf5&cS#nY-Q_^~l%P9ftc_jeH*^iguMZ$!AHwkF2!^+53$^)z z{^j{8rSM*&wT}Z%vDA4Lmk%zjw`mz6ktV4gGgQii? zFrEp;b20x-p-|vLq0pw?`4@}DmRY|Ys;UCZvSKos+*|aT-@#ze%P`Cd-rc+%<#PEd cl}hc~dFNU<9A1k?qZ@XZYq)P^zW2Y(-_YUZVgLXD literal 0 HcmV?d00001 diff --git a/favicons/pwa-192x192.png b/favicons/pwa-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..94b2ad2dba9c9bfa459894c2fee6433ec97ed317 GIT binary patch literal 5264 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 Xdf+!G8nFRY8iBS3R{gcAUFd%R&6IoZ literal 0 HcmV?d00001 diff --git a/favicons/pwa-512x512.png b/favicons/pwa-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..89258a4e62d10e75630b534675e8c30b0d3c0662 GIT binary patch literal 20743 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≧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 Fe*hy7St0-c literal 0 HcmV?d00001 diff --git a/favicons/tile150x150.png b/favicons/tile150x150.png new file mode 100644 index 0000000000000000000000000000000000000000..3d0c7604e7072ce392783ebf9f59a55eb58d3de9 GIT binary patch literal 8985 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 v6P`m1wp`e7fG(umA;U@ke>(QiJF1I>7eO~ literal 0 HcmV?d00001 diff --git a/favicons/tile310x150.png b/favicons/tile310x150.png new file mode 100644 index 0000000000000000000000000000000000000000..ed8904286dc3fec25856b98e507c97f5704c18e7 GIT binary patch literal 11661 zcmeHtby(Ejw=OX%B_-X8AdR$uG@^8azyOMZbVy2r0wSfPfHKt3Fw#Sdlz?>SfOL1m za5rE5-QT(Aoaed!-sidJpBdTC=d;(|YpwTv*V;Q&L+$ZRJQ_R<42+wKPvo^QFtB(q zFfa*mu7i;x!Y?iu7)%(7@-jLeCL2?@NILVcTRWx)ZihkZw{Jtt!auwxc6`Ld@988j zPm zf3vWB_WOS5^X3Y>iB;`fo%AGE$MxlFyC=1%v9Uzsl9!6NPlpUhFd^v_Oh|d|4o@{) zsP|6Gt+lna9-_dRhdq0dj(MUzh4>kNrlyqDc4v_fmGk<*JssvU5E_vlU<3P&Koix_a5>RaGQ>Od*0Mj zMS4qA1pki4CyYk;9Z5Gg&6#k4?k8Vgcd#!huYMHlYhhTi@(5tUA$(E|?ROU!6GNWz zKcqHdy3dLQN#J|F$Rv#Gy%T2okmb`8Z}t8)+q`7M7bK%xRx;}9J?cgEr>mP!BfqEP zFx}_C4D8H7j*hwp;PW7vruzGL)kEcf+uV?1cwJ|HN^9~=ju?UxbDa6kTU2*AK0Pb) z3LirJUfX|$G@Hl9=-&1a!neFogY7(d=?$!;$OA7@`xc=!=%iLm$81 z*0)TfpF0;M-z>!GPixZhyM+2Df;bgelGW8EJw6?2kd%b=gorHo&bP4CZn`1{3|@U@ z>6x?BhVRJxj&66#&!V0`rKY0lwX2-U60#X4yKEpu7zfGDP6pvqPBXsY<9d&Q#Y{S* zK10G+tXYUdKn_)tIMAuv`?^&?{vl~yp!WCcDc2FJ&iL(n#!B^W$Mu(ooJGjr&lOp2 zsi|W13u3)sl6IuVeo6Q|3S?c1L5uFnbe&h&tocZh@mq%9GY<6yIDs?i@$vC-drLix z=cRBY-b-VMHPnAbYwjM#MuP@`32G8N+o@_@5tMhSu-&*0UNeX)2GkL+G1751Z@X>n zqZ~#+F@TBi2!Y4N@*wfsQ_Xk;YM0FCS|bdrU98%-Ng*9^Aot0MJyI|lg9c_lN=w2<#>;J7+vwdbCo1gV&t6BzFYcX0@fwy{@_OPh5jS8o zviQD;d3gweYSWV<0gwEg;IdR?Tr=%@aWHZeC1XH`6_5my zVsQW13f%%6(;eCfiRU#fGVhEh_gjJwa^eKi3foT}hq5Tgzf(_I48p+T!zG5A1)3X( zgMe`Bw&TjHUrO=%z({LeI;It}b~A8hH6}i}1-7c4 zFIJigx>#d%?KOd6aZT?`WieIlRu&+y;LN}6Un&tW6r zosCP_=EGz$nY{(S6ix2pF{t%$YVV1+rior8VFSUh#Y$IG#V+mWUlEA5z@_WW_L_3^_p@ z#*SlY@K{%}2=7vd^5m`OJ_+FGJn9M43fy24A!>0tve6RrFyFmo)N*e2b-!t|V+{qx zBMQ7A1dm}ETkR4H1`#GiffxL^j@s)17uYlpBwrixju7xG9AbkX^nmHaOA9RSY<5psY%Ki77DZl0bEh3D&a~ zaD#zu`kQ#O9ChVcz26&s{Sl%o5H=a`Ol5$mkOE>6ylI_V4Jcxj*|ErfyGo%7s&<6( zYw$grKyeW8%X!SUvC5AqCU4ygA!|qj0vfu4SPX*4=ls}t{VB^)Rb{8ip4wKCGGz49z~PsC^s42 zD+IJ^x4UMuI&6tX)b)C=3K{SM8<{~9HSmH!hG4~~?X>XO3!Yhrx>(O^GT#P{F4QY3 zD$v0p{50Z9c=^%5dZlf;VHNQ6L}#bMyr~*@%BIfMq5K{!}^nU-1hF?z6N z6lY|9;{!+)&i5chzzA&bp*J+&9-v_LM#V&#{ZzG9;lf*{V>wA!!*&hoVsi$!O^EDN z<{1@8)odKB9^i9FvGDTm!-YoWFWX6jZf6a49$j=+S68DC#%&NcVLV;<{}~Fcao#af zPWhf~jMw{k15NHWJ1y_*16I$jUFhF_Ft;X_A@c?+md zR+Rvna6lAP0w0pN?s~`fnI{+vFGmdo5t*$oFC&qx&n;;JmH+@hpeJ^m|DgP_r<3s~ zMa_;DI}5+-uVL8$2fwq4E1rKIcSB~|l%Ae`$#9gEg_$@P1g4f6MXB-kEKZ);rn7Uj zS zE??~Ahz8$Ff5AFer1(cVJd<<8JrCUVI?P#{7B63FT_c|lz6`c)+PP=_`v$LuMXSo2 zL^0X$##f7ArDZlFMU6#BVkkihEj;2YMx*(9foSwKEY=$d+jz?N@25^bW*m-Wbt&jys1HOz!>3BdyT=aD2ZOqTi9C4-YtiJK6 za)Xv?1W9C^d*nc3^z{*nl-_EE4r1CSV)R6;`SC2$j_hF(U#$TnX~{KZ4b5ItA>cW= z_}Y@}c*I-ddVF1>_|fZg`L5%UElvriezrri0VK$5C;Za-4G=C9_nusQ!uw1CB{a4h zJKR7JpspfUYNg#@mze*? z4HrCoKI!j<+Lqg>*^p8e50Nq7)qzJQ7M_mOE1Jk z&J&ftCe7v~Dc&7A?zk0xS}X~4CF{>tAvOS=jcEg~tuO}ymC@gQ?U38pyI$4Gls@}h zLbXfS)}ot`^72Z`26i%&+!a)@@z=`}frH7Tv)fI|+%TfhU7GN410F?O-M4p#unfu*;NLPl!HUZPckq(MVR0pZ7NUp?au3EIkx< z_PD&fJWg=b?}&c%7>;*RbYZA~jgUz3>q4_H z)+%Ycy(jmgIfkgF0e)z*Fp%=04pJ`B+cyvCN| zfPOVq@D^*cUxK1qz>i@l6r%9*RDIQJKCPcSQ@}du%&`3HiLg-Z`SEYJs;?76b-(L> z%TYV`*m74nSa*D~7Qf(TUU0In*><{N=OC`%-pcyIb8fA-H9Sz30K^@Y7*$7Jq`y@o z%QpV_WzFSqcRmFHesqekoU1@2yL|$xQh)3~olJ^@<6w7nbg28LnmQ;^pUdP%VtR98IJ1@FE`ybYAw>{&oY*?_OoWODJG^*-6Fi&Q0%omZxcj; z>zyrRSS&zR|N4TjtE>3Ed4^Pr%+ssP$; ziqJ?2DA=li@4es!-NXRUpIJNNDiipj{kBx4v`35^bU$)#i5QS_7g~EPmt&tyDr6~|6`ug;}#Hiys0F@UG-6R{NGatf?_tM8dU$e#Gxh->y?R+v-BlyiV z#*@+KsgDh#wy$Y+U;rljEc@6Xw01>U;!WNa8m@%K#3qUvn{beqGIi<$MVhPg@xmAo z9#Zo8DQ%oTcjJPF_H%ztNd(im`PBBvYivc6WBp@B6TW7TT$deK-L~HzzX{;$^Y?7u zIsk3xEnqr<OIrc`Q~mRsW?k%mEs74!|olfiD$QTM0?P_nqtJqDz1jyCY(QIRGi@ zq_@>;f&fm}czN?b%U5}zNJFV&7rua)cp#!hlPCXuafWm{XDvizDfnoKVykmu!??Xl zqtFMJXDE6JS%I^CFPS?gy_=8Z8#|H?k7Gg{zxtJ{o*z^^bvocxj55dVE=hiPsd~}K zFGY59E$@6w6}40xLRrU9j880IfDm~gVUk2!=zp`3g@Eei*`4NM6Dn==#SKM<>j7uX;CV`1_4ajS)w+X_|!*p&y3LmX<->^d*<18-b9mTvQYx$NLOa zrkA0fL&wUh`P6uIc1iE+_t{m`11t^>!|kO4lY3gTqPGq1Lst%}jis8##|30OrW2 z-CU(jKb5w-88A+ZRp%5LtLWwV+Dle_W4kQ7Q-7NGLKrrg(mOIeC5A;UB7)mME$QQ} zm76K*M@9;rd^obqA%^KZUD$Wftb`NG4Ul$a^T@TGNW45de=tNofVJ{eY->JH?I9~1 z_f{)sqDse+PvOKc0*0DEG}!LO(N2kEcOI77wFQS~=kr*O9P2qt@-QPu-6%A-o`Q&O zHT*J1ef8S0@`hA(=#W8w0pHx(WYx7gJNr^Y!z7|J&%KzQd6xydsqxz6d48%pjV;TS z%q_R?=YS5tEo>nD09jS6cdw<}9L0UKTn$73Bzwn&&p-Jg)h&d_9z@%zSHa0d`bkVPLVMPYR zO>K|f;*dbiyakE{|3jq@vK5h{*$dyY)G#tKQrs5TKUhKG^1M9-^|?1p%he7n&e{v@ za(M^vO6RZyFzanUBY79q(%O$op=EOc!iEMG+d>T-modNfk&NWsUrC%-4bKO+f%rEI z7bJhS6x!U^iqb+9b79EpOm#dN6aim2!HHbQ)D+;jE@VHJwrDg%oxF=KPM6 zN3+iP>5YJ5kn!PPg&vnk1N83~Azr4Hn#gvYP`(k>8or;UKe$p*bs*;U+Hf{%cw_D0 zVCg_~sybbL%{_M79a@@wE2``1{X`F?UzrbmX7&|?L_Y8RVy!2n?fz!z`Zjzs4 zHS#{K+CK!AqGSWZ>Xu03q9Xi7w}y*X5;B;BHDyeUo|)_QtS4X6br{kuTCdIZu=jx~jLgcZ>)=5<=n2DU|2qIo%$+K?d7T`6BPAc?H+tgTf2JMAz8@h zM=2xs4*z2SF5O%?&3`Jmv^)-6fE2Qk+3t%6j7R&cjoH_AwmY%&)RmpH;QQ!-r2XBM zm0gPGh^HXNig!zp*Z?PP1V6#=!~IML{lO!$*|D}Lb+EG85RSfg-sC{sl@#4yg|O>& z66g<+7-188q?h-%02~ekc}$U|62(k$Ujq3qVt@ba6!!Sk6_tc3aiZcon$NqTnqo*p z>N%n4nk2won4q$t)cIchJ%{ZR$6PG2kTO8ZW~^&Ks^P zy3Fk=4yXLaf_(RJRv&&Lz1n$wwdY#L0yepW4{oNstkS)@->3-J6s`9Az1wagXh^KQ zWASsP!KbR2=)3t@l5N6j-?L`S=oqd&0wOi^-KR%%SA6jhYDilLN}hd-b&^8h97Aitr&U&RKtoCSn#Vd#C>SSIpm2H$#`N|wTn4@^B@DVG0IYfmz%%dw zEt1a^+uQ}?PpAx~&;ZSPNrxaz4oQ^x2;$ zS`m8OrTZewsrjsUb`*%M*5Txgv45jcJK#?4nauWDzS!8swkb2qEaGAm$$+t+sXZat&5Kvl%4kMm$~FA8SAOsY_d^^uW?? zeLT}{swc-Q^>I+@zCK*rL`y%#xdq2{a^hD^c2+g(5beGbHK5SF@W^za#^u-At>f_l zU;IFbqYg(MT;}pvSj^X=sp&<~W9<^GPx*P{|=!L^?+;*{Vipb9fAt#n6Fpxh&d*A0!>BVx`%8W&;^Cpl`c z1J)O(%%I@`ig_K7$ji^z^2M$M0QSWVmqt~XZt63QkBcrb-O0|8-CqRMU0q#wYbopD zP1~<~2K;)75-#OM8+IL-bzgDp(8tY?!niq^i4#D`@E8o2YXM3qseFZybnaYIGE{R& z$x{DvuGy6+W)#{y!+7-WsLJ~=o;QbgYy3Et+y&Q9R0B zn(}-#J^C%46vt_ZeuMg+1x(TsbPqTTi&rqY(Q^%)l#N6qRc@`sP-rsS#o&LyL2l$b z#x3ui5z~Q`>AJUv#M58S7GL!Ao~e068PXb=ep96~6gxY#nyo_(#MHoOiewEH3^%T+OYh2Qx!k-~v%CGK_D4{+uo<&}X-=I)uj?$Yd zITe;DbA?~W!+yKThz|35y?57KEAh#>t4qz>{5DCz<{dKvvHS5`$0_f@=Kp@tfb@b zGaxa#mdJzj3s@^v^o%a>5qi2y>!5W6Nw8jZwxtE2Cae-l)20F_tEAK`!S}Sc=U`?y zB*Ycx@(~^SGxT_WS<5s{vh0a=mSQ&J9;?ssydRaD@qb%B0^96@8v?zKPQ4B?$VZ4y z_AWA55+%?q)yp?w{e#2o8B=i^FF<#+`F&@<8YnBiP%*2@vt0Feyw-ZmT`%NBmXFpp zBQuAr3bhX!W4cFnw4?MnK83$jr3eLwx1i+DSl(d%AVG!(N_Ftz2MdTTNQ)f}i)Ttk*UmAHbBi%up zLZZB(wqe%tud%)Tq>M#t=o~U<^yxiW5M%E?b1h^7vD{wVuTyo^Jd>McIk!u=^!-g( zIC=Vhc*EHAe05I)p~7Eycio;_9L`|77k>pR5fB3qr@OQ3 zW4d-^-#cz>bC9qRWi?RWwc2&Su|@eI`Q3B)?V;3DmpTgur!ut^-{`C|wP8)Wfw=h; z3heH(eimYAI0I1&HE6GcL;2Wekyk}w?+}pi%K8;XQ)BiA3um#NOM?=<`B^G&X$C&n z7{`M<0#B~)0z|aTkos;^!HW{Vn{`_Wzhr?>Dqnw;sC!k~N2FjUvpv&x6rHD>KHHs? z;?y`!sNF_1)YnNwRaS>CO*|7Kf!ZdLx#}tVOLgV3^f*P3ed9w?;VNpH13lW2^`eai zl#PQwQ>~m|0!;rTTCD30zK?AU#sKJs(K=^_y$72>B2%I=2F6QPMvE1|-$MMB<8+CD zsb8wulEVNPNE+$6$pJ=grCYgk2Xi7&+2chKszLjtj&t5!f_=d&rA|~NQ8V2)Pb)@E zJAH-i4TIDgV;?)|89yXpG*r}o0c1?)jVC94c%x*{U1N3jvu3jsiR4UK7}>jq+1(Kb zDs}?S(6ZWn5+!x7?A1tgjb-suZVKROt^%&rkHFJu&-;}Yu(JMXlYZRNyG$Y^cS9Zh zNaa^KGnslh)UZpdR8gyAa>rPdg0uNbbOgmcq6bF{4+K>VbD^L|N(#AlVyvFKRlLQv zJf&k&nyY7SasHKmpgTUnp4;K(;Rjt1(VV2o_Vp>nt4l_@Usz)?HltFmz@2)hAlQ?3aZY^2nn+X$s#JkKleymT|j(Wkdc{z zTCAnFQA5ua5{}Pv!f^0#oBEoM(T!`ka$zuA-Akl3L9e{IY!}+D3BWnWGgayW}^!#1eIH{asw1 zklQ3sE}v{IH}0zn^3CbK?`MCfM)<23&ji1+`OMt|UR~?%gdu+PXk(KqagM`~h|Xxu z7b_xgC^uUx{ap;Cu`6@N%!6y7MDx8=J0Ng!wx2PNO>wGUeTA;8eL011`6Jo+A|+zg zZ{2j>9T67OHC>L&bJ!i(VWS7sY-vXJPUDpys~8R>x2>*SOepz6Gk-zMvtZf3<_F>| zKd0aS#)it59f|3%N6MhR-bRE0SE1WPT{uk&hVpU$ECa!iR9jUEYkiS-{}oz5}8 zGbPe9KMVZe<(0H8QlOtjp%b7pcjJUCeIOZtU4Q2>lnYx<0J~su>j($&37_ze#o~_{}QxHLWj=@kl!>oV8xlmG`8K zG_fD`!9IbH7U_W{l#9JNWw_Emq!b3V?G+Bmz+LJ=bwqlSqP%eV0lqx1 zG0IrmM7u#}PY#D}G&v5>Vb4dx-#~RXuXV1*S!)Tf5a;_aOe z8BJ=!?0pZFS5}tTBxVmne0)4z!irs?AjFU_4Mxa83~S35c2d~j#@t3>*8>c zEJ$_eBv$t&Ji>vYC-3qO6%1w$#L>8yL~pcpDrYk9n0@+hT3ifJ!g5No5<%z6qR+DSKJ8QkW{4JauCKg|!HxOFs<`r5SZS9@myeBFdcq^k4cYyu!AGziV z062{G^*WCLew8?-RAUrh6oH$yLN(&hc~bxVKKVy92Hma(XHHHwDK57_mC53%tyc!BNVA=7I`*$Kzkf1WF$)6|ZOgc9 zGk}S$xmCIXe_;En##~l4=mQ=IYiV-MbO{V&ew!IF3WBJ(ujE?3wb;NI3YEQy=+ zcqhuQpu4-fiGwiknbqURZDSPWvbi|_5*>Er$3H0R@AJedaev$|rabzn1lQ5me`RAc zXcsE&;D88ZqT)hM4)*o!Fes0wszCl7H&Bn+pe|Ka)yq38X0&VB7Vg&qnT{>M1m5oA znF0_6fcVsjw~U4&rGG1%p7ytaTSHROtRrd@F4iT|#1NnQtp=yrA3>a|MKR;VRQLeQ zp0YU;2^Z4MZ_5J9A(+72Vn*J#4^o#AsEMlr4Aoj?f+8T;u zB|u-dhpVtU=V$7_NohOFbW?DEX3G$t7ih3~+x4YCGK%1g3?$A8#PDO%$NVZce%os{$3i*1FenRNb$#iubu|*gPb)_Eyn+Qaa0F1^|a{SBmZ^%)Er2m4(S(^e=m>b zTs6?eHtER!zO4hCP{szd^8CF(ssZ|+%C3{59Dm;y3wpKe*b&BmucD@k0b5p)&N_eJ z#s(C!)^(bizt>TvU4bn_PD?redRs70mePGaCeC3zR|&3JV<K}z`!6@c=SLM0|Sc( z{TCk>{Lfp(7qb``3>XRz?rVFQY&7D#ek|Mq^{pZ6Q zSfSx}G&I=%ei}+>2QInz*c_jMr~SdhjK8;H;Q0vdckyuqV_?kb;xKutXX3pO{1e)q%z{&ORoduj6aw zij8&ue2G$!C9ZRbyZa~=qQ4p1mj`7f4Gc8JikcH&67DT*d%7L^7HiJD(d^146;9U`{w7)=j1K@iUvz zkNT(E;wrtiHKfu;L~2JTyM4v^`T3$+gKe>@G6qB>@jHxs!Z`LF(9{^g@`8f3C=u7i zJ>p)$h|58r*#c{bB`S zUHq0fCwcq@6LSuoCLbP*J?E`ke&0eK*4lULH049Y=Ny?8(m?44I8{=|JJVDGmQ(Zt z@yggi>I4it8HfnSl5pOpn$J}m#fAy{o3X3!-z6r31R6&m95vVUq@v{UZGRu|E`%zQ zl(zJ#IHZ)auIHoGP3{#C{eU-aFEeta$4LV}^ja2|{p11M^4r^=U4-=c1#j%x&HK>b(d)QGX~f3^ zQ|tj&GQ;l9vA~y3FT<}fooTF8XFo9mi|>8|@46gfdzJv|!H@i3?f07Q)aK`}3Mo|L zCa84+)Kdgy@E;IMf&K4W-uuWdsCp=4uElSvvf*ZLI+`Omzcrkug59=g=4_i;R z7U43gZr8jU!btkI= zCa0%QOcGV{E64!h52CWwiu z8knfGbMNM^wmv=DzuyNb_&{&$(#cZ(;>v>n{Ff>iP=a^XICG3VSEVg4IjSX${JwB()YF(G|8yg$f zwPu@yJ_%GgoTt~<`y!J?Tz4QOa`N~%w*qT$aD=Z-UxjC+_a>9_#RVRh)>)-`%SB5b zS+Dr=Vn#jx;2rD#>zhEIxQHjx2o=+~(9RH<>2dTs2Zs1WF=B5YVLY2msm+^z1sC|OL-#OMP z@HTA8q!(gVy=bs%2_`;w+o&AFJ)4*=A;HB+1@=$X&{36b&2lMAC&PdH=#!rrD#@;B zpbN%@y}`F3tU6Qnan{4b!ym3frD8;2IT}%OEVAiX1ol%krF-AH5pChv(|28Htl~a& z53TI+1{{>9)!r0zkv8iGyZR#7V+&W#2sfIWS=LPWs&jKuz2mg#v>$5PpvqpK!8@j6 zqH06w_~^*rb3{iEc3xTk^BTsI!F9~mtlRdolLSyIgR^f}f`qTKU%PBjX$wQvZ%P(E zE@fKIE4+O@Txw-`xn_H{p!mw(=eOyv`lXuCsi*v*5fM>jETj5o93yXNam^HPq%1DJ z1-eO;kimj*Z*=+iI=y9IY6`dK?W6lXk^X&hX8G`^|fz7jgZIW~P z>=864+?*)s=aW8`5d4Iwc6Rn(UOym5^n*lO8K3;fnMpFoVdPdZdziiK~y<1YeGs@b(Rxjs{nWWC+F z@TIq6sM1?OW@g>yvV_gVFJFE4-PXrRz_Z z9}fUyy^gX%wJ~1!cj%p>ezjJEAg*|(|8X$p*|3Ry}APL4jY3kry6+3 zh!Hf61}fe^g7Eg{CN zpZHk%2L?1^;Y(=&lDQ2PVo|P<4wC{_y~(wfZxQnqEWqYG*sX1!`q`D&?r|qZW798Zrh363uO$9*gTh3Q#!T$LUCMw9-Q{DzeSkL&i zTNC8FYOr61-!(+f2#LW$%>Nja^w&+Sq6Tr)lxx;zgPTXf`SUk(!VeYDpnU+;xih9t zT+e6dGWXY&F|g`c-gGZ0&U!+N8){4^h@G#|ba=}RqH@&I&Pr~veR}LxXoeN4bSb1f zXYh}AN}E;V&~$KYFm0H4*Pfppzd*95fE=LF0c{d9Z;!CLPp5|Vh*}Ua=;{&pi4G(@ zgkzVm(~NjeirBsWs6nIy*fXRX&C>Igp`2n2-xKi0xR!rPF9z1}t^TpG96b7G>bpyQ zdXn_(L${IH5wSeUAS0D{7NPWoh~I;h`anhedeYUexoh z@DHZ@dwVC7I(o()jC&kk+<4d$H0ByZ| z$o~aO3desUK!L-+_W@^0FKevOP%jov!G+a0ZC`&(tx)GS*B%Ks1$Z{7$>ZJ!_29#K zupfjVtkDG;1E&jwP&YauuN78zHDYNYOHaGHh-RQ?l_wn8b2!e!fEgT|Bh#=!s#Rb)o=++NMysckz z(I9MVnaH=i(0ua=ptN>aQL-p}@a9*gulQbWWwC!Bfrp8Pn$sE+jXMbcCu5DTuKoBr zUM1nz9zit=zqb525kshdgc-B7jX77*Hn>JxlX@5n6Q76$6J^_-87*lrp;HI2jcHuM zo??djuU}bklcNdsR1(+CcNmB=Cpn5SEHuMn$HyYQA%o@T=Z6LpihT|7$JsG+!n6sH z)4f)!QFf%I&YE%=!sx-to_P&iWbDI6tYaj=cW8>amiM8ORNg z%$s#lq22wZR+eZ+djW$>ijHB%&3z5RQRRw*p6KMz(Iwga)0h@y&a=O1ij*oyr$850 z)NtFdN*Ouk(MT6HxA!<t4_m53iJZPmyDjNhu3f*$nI?MWy>0UN&k8SaL#0c8j>{=k8#NA`ud)G z5@47aIXO#TOwV@UL7pyqLU$r10Qncs%ufyuRa&sP&jP*!A#44SS{UH-e0Dy(C-4=nGTrCRCBW%!Njz z?YZ{tu2P3_3FEFJ5TRavtvPd}_qR6oo@uuXsvhk>D$B{dxV z@_Mb1Eg9G1+-nonoXsAUK54#+jl7ZtQ>zrd6fi%XI9sZ$BXU)Zo`H^h+b-=aL-}sS ztb>urG+7KROyDz^n7Y=UtywZJ#trpDyMMgYU0zo|FW}Ad{2aIH=h5^!g*HPqKG#Wm zL!%=XNy}D%d^-oDxucoTR&190hKdNw3CQWKt|D7{L!XSU!kuMZFTWb(PA>}C)aiT9 zrt`hwPCrG0pAMX6JbxlHT4yMcUbE+kyvwn*>8D>JI9&ic#S;{Lsb}P&pzB9=0dFDf z@msDs-j*NsKUT>ylu_lmIrGE!CP$3A<)FW<_&$+P+G*b;-QogBP%bY09a&FNA$>-8~S-LecQJJ%CO{MOeP2(kjFDOY~6#VlnEc1e=4)uDtAxqCK+pFBIQ>4k5q3~CQVi~o9d;{W~CcVP6BPJ&rVl2~O8h;RMUY1dS z19KrXO{@>3n?;cgIu6yRY3sg~_vu#W}w^W!(@u(m;AZ51&6 zy+F$I43V~{D{Iy7iVqj6NV;^kViFtD45W5pgViR#)QvCUJ+z@v0}9cv&@N6=C92Es%unh&4;-ME`y%1aHOE zgwDiP_zLyoy|U&g+3|@oZNKjt)W?-hTmt?Gb=@yhq(o zZn`^@_uN329vZ=V_G4*^CqG@8y^RKZLqz{D?;3Plwm@criD%};vf;1f(X%bXpAJcH z^I{kL8Ib8M@oy{A$THg>Ma}QIb(xgQ^diPAoW^fK@MIDN#`z60n}6wyG;IiPvZ-`G zCNCi)V6n9|_ltUxLW3Z?-q}Ts_YW%3wyoIiqFQY@zp_btFwCDAD;KG;^D7P}e0D1< z$uM3qM@L5|%Yt9uXSbuuVPRr29>k%G+BY5Oh)d@cFJDfW?#TS9ju7Ph$I>VKQieCw zVkU+3=k~XIAth>9P%8T`vI3F_e!(g1p4T;AElbFghLi3z^-{lr>MOpsFhz&@FD?_u zFv9ei9{cVMC zUl_zGgp2QVZ8Ucypjdm>Rn430tuE;nkSVq?Y<$UE+r+ry448OWvnm^PTiXn+X+3AN zRa|-YN4?Yv`E?Zik>ZdjQC()a2zG_;B0c?syZ1dtTndjnJ$1gxpV4E$vSwF3pW_*(^Nq8m;(1z%D6!pqi0!_tCQ#X>w{x{`{R|+os-SHqc<%=mfvn< zY37x+cR7uJfSH~r)1XwCul$z!yzoN*y#VfWxU07HB%+{CHPX%&cGfpeJuqcdr!wCp zqTTz`QDm!qkG=q8*#);85*!Zz54}uDL&H6FSu1aE@|G%C-DolJZf`TpRg&6&GJfhe zL%o>|bKm-@n1*tQym_x^Z^E@UB&82_*K57zG}|R4o&Gly^)e;8xXA+}WyNqVo~FUe zw|Sfba`@AZ^I27rv`5Ri#a_F&LDuMtHIBIhwsfQ-8B4^_26PYl_xdkghs#E3kLWcQ zcE+(CCwY#wBmET&i{@S{F@(A;zE+|FrI!Oc3DX#G3z><^2aXipgbw4BXBur$cby_V zhq`R7H5WVJwmb105UE+j6+@qPNW0qb@i%hFn2bFBI>RRl%1t{==yq?{hlJ2@1siBv zo1Q^I(>?_R&V4XqHP*foo^695VB<&6^2ir3c{tlwG22axR?$V4Xs0vULS zr!tE5!(S;VoiZGLwXv-F{NQnlMD=ref61dht#m5L$jDfSPMo=9R-N#sS@Ygxp!H-z zKbjEhzaG62P^M_PB0WFhDJtY{S^GlA6j4b2Vahj2I z@qFP?Tym{mOsK@Ibi%Pobv!Gag)Ok6Moddjk4s-G$HH8Ted!a!BKcS4#C#~_v%VAZ zupdN#u`rM*F7X`xodx)OEwr0dnnaX^WXXr^`{{h9k9m7^*3$vsoW=?_NY-LMv$pTL z7>w$kM#Aw!V|ka$mniN!sBiA76`YU2El~Tosk{S%G9$6ca)Uh^*|xlhFoJ%9 zhFO>u;-V(c$Z}OUjZE0g>N@UU-b@j%a${lD(9*JXuqt=KJ(4)s>%R>k!OmG%MB0Y| z)1x}g9&S3(0URt+FD`VwT|;Xcdaa;jAUkF!HftUl7N0wmOx~TzAZNHc(j~%am=5((>)*UOwj03PX5@g z)u-OVv8luKsdrdbT~bRX{VB*h6yy(c0dfI-HA}wMHhL>mzLMhxr^DH_&Z;lcCLo2` z(P3mX&vwv1Uv$e%DBu@8j83fSBgyPTqq{@*)0qH*qo7jy@tzd^2|tq_L}au#%ACYz zSEyO@Nq6=R?u~Vml?eVhHco*jWl1yVS4ZgFBR)QGDY1e)!*2!km8{Pi5DeFcMqPwG zy-UL$bMC7(y9w$hdOXFiCH54vk* zP>AfHzk=Fd*a0n5g)D=P_!*{r$zOazsUF#bg_$oR9+~1xOOt_TLV#ojpbgpWij&1i z+xitB_nt;I0QKxk0vijp4e~V16-nlF>D_XvXWV^OCb_{(h_o|+@y@|8VJw7ZSl)Uj zYb%SF^{c8v+vbh);q6bxE;7Hm97HJeg(?A1DHvWZ%@^5wB$Vv@nxFhlg3IGUJgj;U ze66m=7iH@uxj|`xmhmo~X2-@oj%KKz@CzTRHbr)kr!O@#+d0PtW%fJL9v}4^)j{In zGZmm&D-N_Q@#p*>sSr;en>p5oDtTqpnvQPxF0i;yLCcR!{qL(vQqKISr|Qhl=b5H< zk@}ftORICFs?@_6!lkb#mAlI?j1vslCQEAG1sZ%wnRFaUIbJojWKy>zky|8>)bnpS z>c0zlRzA2v@}sUS7O;T*`ysFy8W$%D{XA_iw$?{L{&@Ere&JpK(JfimOYMyl{3Uzt z?vh@fHX%!2vLj<@o%L4Srn<@K)$5aS1KWo*}+^1^rsj=MY>X_Hl#xA(H z+CFlY#~XB9b6tv=v60MG#tt@gVILpRQwYfXPyu%kr^LPp^WWk#1E~nu5|{ZH<27BlR+Sg>^x$9V8ry9 z26-z~sYaZN7>hKN4ec#xH4Xr+-@PpitQf$OndIp@Uxq5(dfSqM10{g7Wdc&W4X9MB z0Q#0je-#4;7w`u2Uzrn0ppv8SlnqxW~+t_i(yjpucoG=p}; zC_c{beZ)s_l5I=ZL$n%0N$55qLcop?KK*o_Vthieo zLV0C5Mz3tO4|dN=lq1F2S2@6&}9|Hi5!2CJoTPKa7^$p?^VnGee~J?h~jJ-t_TFpovk8UKJ^lModnL^@A*1_TJAqTetc73TiuU z{p-!aFJ#|ogovRn&lTAG7HxVEs2jotv%14Aybz`8mv=oK0w(S@aCnGm`c-CWk@PJ` zRO_szLs#ynM*d{vyVzjb-vx-Jq2I(Pafr5$Xt@?5Lh&A&kn-A-9&!40TS#>KM?~zD z=w;r=a?b;Afv0s}uz8l`{>3Kobi*Z--9q+LVeABvuD4eSQcioR8_(a`W@(-%CWOT} zqUB<=D_;s=AqLJwKsO=Lx4)LncEnsSR8joe@Fw|D2)XTEka+=Yv8%hudD|7=3ym?q zSQs(4w$*$E4}5G*(j=HJ)w?#7-OE^WuL3?Oe~-m&RIFg%vtx9tU85v)g*b=|Z3n`O zYMOP@Z(;%)Dn@RMta8ix`dX`5@zo0D^`&X#%>7zaI%FIo$C^ZYx6$Q4)lk;e)O)7i zaZL}kzkImheUAO$`y4Iahy7ZCRl!o0&Vs?KE>`)!(4`li=PUR3OKW`-b%&k)(+6(N zE-&^Xub=B|G|98FoVJ7s9UXg)<`%u)YbpU1`UObxFFDHxcxO!1SBH8ZGVz?rOimaNSGxM{ zZ++pvN3(O!n7weCcRkhL0w#GrBPujnreMylPG#{Oy-q5T|3HKSZo-5`x3(0C)m0Lk zImXQ)JX?|cI~m3PC8<4B*cu;poqzLjzl)IE%-ARTe$?aF=<{pgBTAKGaIkUJWgxY{Q9W26V2Sdb9RqFz0;YYbQr4&;q|{RB{%mcwY$Kyj__2~e-N5L4!gFf7 zkAqhR{q*JSCgXfE1@fMTMi10DUH9Al=tIkwa2nB&qpE~&|GV0;{2^&18*0(}D@XFj z4W8eXlu%UTd6}<8ceg&WR$qguKFV`bTyd-0n{c_S*Pp~)Md!m^s5iz2Y(q7?(R1 zX@qpeL=QhTs7eXu)UAG4U0YK+=TA&|_5Shg{OV#;RC9l^VOmTb-Y<&X)a%@hq{3d$ z6yeYOU&6Cnnuq~FVEJUKgGMC{uSVgO`{$OGombq}+BLKyGf8M-hC1;mwDt4~t}@Ft zc*7uSu9LYxD@&Iy&+g+ibgDdmVMQG|D4USyNU`wdJZ>L2Cdg zmM4%~(fkfg%>eL+jjEju=Uq~ILC_*aE0sP(;yOGrk)M=AZMwT@ebSZGa5i_;t3G>| zvw&2z?Kzrv$o-pltTmWcT{>zF;AB)0tCu%7TvbFM(ByI;&2?{j*3)_+JDr38E+FQI z0LXefmHpxsx{sCY2dUaibW@?**H?2a9d$OP4@ufp?W^`TNDgdBKLp!|8Mk^VzFep9xzw@o_8ktmmFbJm6ZS6bysf;O?Soffq% z?556pA@aWN-6v*!lkvtFwB`@dreyoKDJis#qEeE_C}&c}<~!s3dg|@W^^A%FD)g$E zc!Gony>9}tcdRIF)KJc!$AWmOX%HG-Tp=l9ZnvU!vOqVNMB}%ad78z=vmiN(=ryj> zaWe%g4l;bWV0pi}8DO@CVt|zXY7A()wr1CCJ2X+a5a8E)+Ip@gIhxaQC7EQ4I z&eMM^uhKz0d5ue&dK187gx?dis(9f-+^vA1o_m|;r0SEcyDvx6!iPF$r;QE@`W-*> z7JajsAT}=RZvHj5)?h>9gr?Nbu2OD(RJIMPc^iKnf#52oW|KN|0uZaP|@5Pl-!)Auu> zX{$+2X!vM03{=1zZI&P@8DP%>qBins6 zY(Kwv`@o>$IPbjv`W~nt$0Oq%5=^F_2fWaO2AhO9|7VzVO@R<^=88kfH2tM>-o|Hk%4flbi=Lp4{xVwyvVfV9!`?SkQ%P^B!^a(EqB zdq$xX*YZ0(&s?dc#%Oo~f!@<3a$B26U!mG{v=tedx%Q!bKcehZt)D4rrinGGYRPS$ zaz?|GY_R{$Z)Rj&(_Cwhf=nc~V)f|*3KW&_B2-{!ek*?aGiq-W{tJxK}E7V$%2jD^>GgcJ1{JHbf$khT*|Ag$pwH!%&?aN>WNi!C|`bsN{QEE&?aLun4 zqYB!_5+=Pm$TbT>jDYflG0_wkdJI+DuG|ljZbm9LvW*|=Q5bkQ3_n2g3UM>>D($au z>j%nWlwmc$ND6uF)()(W_Lp*Su^bwf11vWsViSf3-}bkTeoz$`&eXb6ph>G|*ns_k z1;^vJ;ID8|SmG%svU}hAA4^B4nj{z3_`R4iZN2KAz*<)w%9_1DlUX2C$DuKL7kgnK zgAxY;CKAI;vyoI_kN_=)Qzp#`8`Re3b~|m3?nGirm1&v~_^#{dv8d3#8+{q0kg{FH zNh`?ns^TRW;rv&z$06JRV9?lIEqc^GkH|Z(^ATR88oa2aVXdE&))&L+>LsPOGo;_q zg2EC=9cTm(5Yn36?or#cgh6ALu!R$KZQs=0;l~pJ_KKO*-@aliQpVWON@Tsl1Q zM%_+J6E9L_zxfWXecEq?BNj2|F{D=K`Erwt7!d3{-j?A>J_4}H}>o*o-NUkyJ-2d8;|g6h0pO;FlZ+`|TM$|CiksGBL;?(K+;jIB9~ z2l(-zm~I>4UjVchv=48JRJ+V`whCqGxHOufUd- z5d5-TkWH|TBkxo`M_aF_FnxLGsT_b#;1*s*fBGAL`qcjyE@dGII(=Zk8SaIqXF$*R zJ+6p}{{SF{FdFY$-AP&_No3i;3SFhu#Y`Jwvlf^cWyU&{we6G0f2xGOa9R z-+rn-uX))WHvoLV3sf#dBKnqSR*9aH`hQAPS&sU5+MZ7wO;nUx#oa~OYxoA#yR;>{ zv^j`z8zf|XfT^>>20~X^D@QByD~leIzhh;8!t$Q?EfpgM=3V`W6(H6U5nYFd@l@;^ zJ6Zp{S-ia86J80_*}8Ix)z1BVsoCQ9#_9v5v$t6@UdD!f$R8TX?;FnJ(aMRb?3rlx zmZH70=uG=vv~th&3NSh~mJu{8*mby^fk%U!P+?73S!W*U7_iSHQM<}9ezYdQ^|PmJDdxZ~^?e`x zITbCR%lY7oMs&9E0^YavSaL1$V#Q7 z=)8PZbZpTZb_0ClMzi8ZWR12hzi%EPl;HYATtVt+5ASTg5Ut${VnO^y`H{+1bNSRl z&kfJme6K|aDZaqGGvKVP0uH|^6nsb4u)#ab|9pMlV6=*9STCi!*m@}y$u*>v#I`2T z;jbAIEfP_T48D{A4Q4?vvGh;ZmD0f1wBG-Gihgf+)k@p#^#U>3eO}M-Ku=|H)ijX< zEoz-v>dz6%nE#48CGU*s-J{c^x$t`ll4GVT@~nviIkRU3jZ2?~=Fje-E9vi%nM48! zQc7~oi7bH5O|6l5iwTw7V?u;QV+d}g6L-2VqgryxgXf-IV?r4=C#1Tche`RszCU&J z@Gbb$*EF@pKE$lmGd$bOddIm_n;?;*A{sL)f8{t`@~kRgUY{}`W{4V#GZaY?MJhB?ORrNri4w9oxXZ&aa^liZ({tArp**3}g* zkzYW0BDq(^iI9*Nh)sD6Pt9W+W4h7VM`(3vRw6!(-4kaB{ zCqJ^#Dpi)*!CX8f<3&hl-9sh)*4cF46%jzh(Nxm42YO}5$K10u8_|<2#A|#>cLxcG@sA&E|Xl#Yx$i2L(D&0Ko)gC&e_`CY* z<*a=|_s!RM!!a8~;>GAz(UUsuo#I^_x_Hb8)~)SK$?Q2cTB|*g2O8oCvP%ogOVUQ~ zt?0bagz8KE_2~k;)W%-l5Qz%=JjVg5IMuNjW)d!f?$E2u@v1qnN4G5W15Slp((<6^ z3ztO-r|J~-B=+qbmZxuc`QrwHlNrgL2)O$Z<|b~JLljm9O4dUbVVa1fzy;6dcx_x^aV-l{l`IcHrI zG{}l-ewkt$LAU$9y`&2bC*au7WJVyk1yPaj`_5+JSd9x>DIZ5ENzNm#(7CHC81Pe_ zo0e|$kt~OxP9GPDj(Tw=>ym!Q1Gn)q1TS+>HM>&ANLfi4@jATYn{HL%s3-EwGrG`o zc0DjV@2E?|RNK|HociX?Zt4OvN;lN|W4Gzud+{S_s-)l1RK!6AP!Zw8(aX>~+;>{r zT%W2Ho1|0i^6XCedlE|tFPw_HHlwV;5PMb#v|D5<#2xOapKU{Ol5^Q(!4dhmw|2nF z8qMcx0H6QgZ?mf_Uc{C9D{JYX-tO0Ui=@s(o;M({VvQ2>p8X)N>}TTn=OgW-XNxLA zKFtEi(ZGGVwe2R`5U^}EOK^>s>TM$E;ZBTcKQwOEq)zAByz?y2Q75*PR)_S~W*tu6 zi>7Tb4(-)_6}sKtS)m&mZWG4HlS)n~Yb5En%(jQbRs&6`xFv7TvHnH`|Hj$5wp!7> zeqp!ZKqWwRtFDkzIwdRHy{dVea07u5DYY7t%sKbANI0+sA`N%a zMUTX=`uZ?_cL&=heSjlC`3or!PYs>|HKBFXvoV8y3N@!Ld7>MaKfsttGT5o5Iy~7y zpBbEg)LiR64Bs4juM)mLpP#cgRkwuQd}b6^q+whqrzNkdW2}=>?3x38M$lljTJQdK z`Nf>?bH)_VoFMyp`6ezjuSB{bzNMwsgx$ezC~jlGDeWvJ_3>#uO4Zk9#l*%Y-*Ncu z(LmC7!TWfXbh*l$nf8oqda)qJhJ#ZhZP)Aw7k1CIZnQqb zs$7{Eteg9Op;Y7i?RP$`&%I=qI+7KA&eYE{Q2*`@>=8%YxA>yEnps%o@YTx_O9wBDM>i08uR=oUv z{16Dqy`23ja2zdj?oMj$UnI#hS=W0a4anM?dtZ*=GWD>z=F3hJ`C2-_A{wBeEhlG6 zWhaPk7MuCL3(_UMLH8SPqmKu1ArMl6lcoEuU59l)UrE_0&FTVyd6?OTMX2gY1*@QH zzm1mK$YeWxk8JJLQmdr@(wP@tEjB%ITk8%Oz*eFkm41@ma38l6e%!9k|Jv5{^ylBRt2f5Obm3^o8d7DbrFV(A`Ni(9{s;@hnmeb7& ztKwDCqGntBRGd}uGVK80F`rV9i z&oSTjwgWgUHH@4;RUOR8B#|?a`O!uCn`(hzBS%hpi zg^Q2hE}2Bt4nbp;P0Ylxm`o$q9MWbUxwr0rb*xcBFyAr$3cYJ+6xI3Nthkjewa}}8 zfq;9s5d*;jH@t>O)fy>Vzj3u$-1s^R{XCqrzg%`q?K6EU{VDL4%zU`I?jGECs^`V+IqR)-pq0 zD%LbPqemKD&M?q~wQ$2P5p%O2Lm!Z-2vu^+a3^sqa7|YNL}H@9QRAJ@U0c^p-CEP1 z?rE>aw?Q|Tvh(zDvaixtKiS+Y#}5W;28z`$?s_mYPD0(&2owQZr+TThG9wuq`%LNO4$M`@LgqEOE%! zeA*m~>9ewYx$dVeZPs7Ruj4znu~hvIHG|(1!8E?_ax0p1pLT?Edho^!odYe{}M`f9PiZi&?-R*aU=(!uk8sLMpr_Td|5&=b&62(y~HFy7Bs zqvsQD6f-qq4Vc|GIPM^BjL-?G=+IQH&JT(b1CP zEtv3|3pMTg{OQ} zBQ&SXEQ1YCt{DUp3EHD+TLk)G*zcjSS3PR^0Y3v??noDL-S%*K`8tuHOOO7Rn1F6q zgeFtW8=ZAcrh1dGvn<6cAGP22Uw{4Sabm)t4%}k*&Wu`8LMiKyCYyv@s+()BL~HY; z@RCQmqr#y|kcFRl)U9pg*_xSWdj9!e+CxA$R#vH_i``U6XZ$EmJ6FsgFG&}|Pn9)f z1Ac8{urT>)DZAJhi#u<8m1O<{)NWbwvrn~gWwsq$8WOBOgx#VEgC1;H=+K{3)+G0) zr{W>_bG<_Bom(Ma`{7b|0DDL|-bhI8IM?s;^ja&SwCNnB%{glqh|d+1cHbw?&&%To z3-_&DC?oYYe%foyI4Kk1bWEho#TAwPQ3y6{ z6O88lXKc}-m;y8*4MzRmS$Fa_2+homB-pw~o(2y)*Cf4@&#$T)9lI&%agMt$;Te>? zzWDz=tUGeP%ED=1(}AA$B@s-{Zqi5_2wjW;BglI!++yurMYa01EPA;4FM0tOIw=O& zRZ4)|hk=LnLxoZ#pvl(_HiwqFkot>-+jIt%YQHixiScaLzn2E=iieK{P503H(w)E5 zUf-Q~{hqU3^tsddBy_fvI{hw&r%T+~G*Tp002qLkT4i zOt+iFf%*UTBlW(lUJ z^(PyJU=TV(r|HZqi{!Y8nwq+cj;$Vn>ME?sUO#ht3A7mJwzgw5!TZ}T1}_fNb=+|1 z;%S;fy9fNPUh=aHIaNPX{p#@bCim5p^M?xSde_+TMVrAG*LD*)%KINHp}V$EQT+Q7 zyA-HKI@8mciJIYZpV+|=qmQeLvKB0{sqHQ_hN_MQN2W(X>&Uj$qkeoW6Oc^MY!943 z{AVJ4)@EPaBPtn#KEsvG&4OdV>q9=tujjFmAzu}BH!H88xS8sm8q1W5HA^={6sk7s zRxpAjK>2AXCjM9VTD9Q3GLf?ZnzQL2F!?!FN8o-U0lh}q;fCUHL|m+xQ_XUdgawJc zcImFr!q^OJy_F50O=)bICUF@*b9GM#CZ>Y!#seLCFP_`tAQHr-`AY}@(6j~}Z;6VN zgdD+=ExcIrK>=1>xv*et7&WxwV^V2ZtWYd09sruS>Gw~Ux;Z_Xc_@4uDQiO#Sf1pi zLkEe5Y`LTTi1FIzxUC3H5S{w}_mP-@W5>{kemCMt;Z@)fbfhs(D<=@$h>yv7^ zBtoV*OrQQ>X2!w;T;!DC|7tcGeT6aj7Qkh&>62aumEo#(#7I_-R z?wy0r^*f>cg#S9$1K*M1n&vm~tS{p_XIPl*zG+e7!@{4n*?Ma&n;l>(%|fstZ7 z>p1_C&T+t0useJ6nd*Y>Gy}!)3*ze)o-2yo4_ItF;F7j*YIn}QN*st{0KPpK4QX}d zxY#!wlAc~vZplwc2>e`?6ZgE!L7yUP6_%UGUSRt{lX*5{I9Dq^ms)>R-R(IB4*ExS z$oh1GE=Ga@KeIX_G^Eq>XmfWt8VeT4&Cvj}p}P7)<`!A+;vN0qv4w1$F*ZBH@8rPo z+k065s6xtMwAjQNiCy1@WXYP8Ypc2xn?mTcH60nBo1i1mCk>{Pp?HEKTO)P zBRoc@JN|G%qOlaLefXn06WDA6HJ2@1Z`z)odjCU1mn?Vc_q8|6SdVQyedD=C;4Rar zlRayEyk9m(YhP7ZU9|=nQ91ih9TG2OSNC*l1qQ%#P=|7c9;icUS>||j-cqe?`xhjA z53*#Iev-2NMB#mhBGqLoM(6ZgBW{;=kQaCL z^eQb~zbD3J&z_=k30O`9t%?h~1?-gmoa*xBsF5;wG8X0v*pA;KCYw3Z^jYmXf@Wyx zzm#}1aA~+sdo*x|R^SG$+cBs1+s&-ZOwR2RZon-83IPjQfQJ%_o}F)hKfm;|?D3rm zz$1VBf4=qj4VucjSio00t?1~|ojW66mRMbhlHdWJUFxt@=*8>T!T$dJ_df}U??0lH z*T2Js$EN4yzK^~6KIc-5x^+&k;!L(V20oJ%IC5l@cl%o_=m-EdwW+|i>&i1R-=eM_ z6_2+8o)K0#X_-`nohop;USLHEQ@LpOQEt#tE;}Z5%beQ^T!FRh|K0a>+jj4`c0xFVQ_ZY^=c-)p?d^R({fn@tdo*y2;*8fyE|5J>g@9)OoJ`tSad1uK z=6UPxXsyg)2iBS&wiY~W6~Cq;)X5J#2Eo?zxRQPwyVp;kh9xZ9yic10Pr&%9v%N#f zHU3))=p;0)<%@q$3sjqId1=!c`KW1M9rL6^{mepu$4P{!0S_bmG-=&to!9BWbN)_F zI<;ofsxr`0xRbkPnB_(-0-hSTBsCIvEaYn?&&kO}S##Jx!DYa?BcES)%9A?3N9TYi zt>kkR7aWtS0j*at?yG47ot1M{*}d=2@)V<=k;e=D60;jlC?_}pk9|1AVbOOvIr3UE z@W7?=pEdv90gq2A4~^)Y@^~UJFa)QpJgc|w$D=lRCjmO5mx1XRup80S z+2sUEJU}jx7r_iN3?wZ9I*&+Ai>no?m7y?^7o-LxoxlSOAel>*@Fo_RZGMV~0-=G2CHTyYelY-o`N-Lm zd3o5>*7kJe?D%>h2f$JKmQ*V1O?`DGEHniJucgpz4`=M`Go>GiR6C|D@~*C~Ru?%m zObGNA^Kb!NC|pejbH8{HM?v|Vqu}O3v?NtjstpqU)iry)1Psuw5cjqo08=+ky6ZgU~t#aLUrdC}9mYzgSeQ0e!+lu_*`q7tPR_Gj-WTG{KC zk{4gnB{Qbgty@n0*_t%BT0{i6bnLKtu{%{=$J_wU#UTTnf59yVdd!t2WbnScm5(bZ#rfU7( zadL6}AYd=>L-4vPUq(miWo1Z@{%oIj4B75~*W%;jP4d{lFmg07K)>hZRd#<`Ejcx{ zdgPV~JY>SXk_2n|W)SP-0#LMx!k|m{r((Ohx;{)?aJ9+KVZpS9UR>iQ%LDj#QZh2F z2Ro}~j*j0f7YuUxRo><1It9H-A8=D<0p6PEvnlZ_u>y$TO%OLo&&kONlTYm3GqYeV z%7pE0IeX816uNO^{YB&)~QqfsKM~iTUQ=^kLBmEle4lF-{Zx8Hwg&| zX>Xktf#GZZDzFc;`P>}IUVeA@d~k!q1UL;@@pPf4)+hzHkIlTnI`++Va$VrsS5W=* z3=EW|{3nyS@A1gb?;_=$4L8|WdituS62JF&1zUaKx|gF0%`K!>+@Li2-p^PNQXB9b zp-Z_O?yeh(d)jIwx$WPfE@W4Xdm9&Lv;zaT=P+FbN91DLYWkZu1RD*pfKg?JCNGc5Tu6gg;yZ*FASH z>2+5ZaOJbgyipBEnI#=R5>YkwQ!KIm`Y9Vf#${PzSD45R$F^UlW>mU%^7p<@P_`=B zrskS@!?6|Ih2g(?8G;`^A?)D_k#`>V_o06t(ParNnH=Y^)56_u+ zZ0W@)TJ}RmUqXri8n6$JKnhXmS#N9%$F9{G+nMu6%Z2hTY3t@OQb}IykX-h04G-hI zrD?lZL@K5}6X*|Dk!;d<#I4}2MWyf^gl#2*2D$@unQT*%&zfx?UQ63m-aQ+ezZO@Q zeYEPW0Le88R}3_E0ibi;9|YwGio6OOBHzdr*`R^xjvHBWozSPo5k8DFMJIg-6Rxej zFVO1^gNa}CAj?~hn|OJkPJ|7qRO{xgzQPc$KM9ZTi(`_12;hR(sCwe*I}MU#&;T1C zSDG01HR~&p5JIC*`j6c>-&5Z&JW3N?=|Tgb_@RN5elfvMUst26Q+LkPspEeCE<|7M zKzlV(iZxhN`Qnh181%{O^M-(Iu|9l5WI94}!|SVGa~gfG zHNpe8!ivhp zlONUt-q4C@;h$@Xr>q6W^-Rm;-<~doni)x{g=f7htP^+9j}z2C8H?yL;)kB;xUM*x zy3kV-kS_!oqTf+PQdZ3Re4$u z5RA5F0eMv)+J=x5;J={bksz?S;Se|fmY?vwy;VDV;i3IORq)-FZ9-MqNRv}3csdbG zOp47EeK6(9D~I54y(YG%9o<$BY^yiN`AxEBMyn42SkINwZx zSwZYv+GA8-b2lP*Jv5PgO!xD=MH(PA4;x%-57qVvW`a@f@umUK?%-$tLHrIKWk3Sw>@y~YqQxK zr)4CE1jV$6^ZpK_95Kaqht_vdEQ8{-w%FBXr6Yhp*A#9E4E5Z7<=1^y-r4g*Qsww$ z;xnGmM0(|Md;7UG7Nu8WTrPZ-+)uV`%Kn#R_(MchL;gN&|U6HXls^yn1*BHSB4>k&2W6J`_%Ny~zoUB*TJqpS(Op)vpXo zaQxgO{oJ#X4; z@{7~94OrHZKcHedAM$VL_WPf7+UtV(D}CgxcSI4aXaZ83Y`&QkrZrD&K^=3|fS@~+ zKQjAt1?5_@MMvBXgyAtj1-!pA2xIAERuXyukM$G=V~5%2hkaI-R5fg);Uv$# zT1i_n`b5%Hb(qG9Loi5k3M`n))Tw*_Eo?_JF2CMZU&1tkOcHN<}SO6dH+TEO$&uaiR)#8(E@$-^s>q1Pc zrwBL+ZF|7eg5Cz|xGw)3>k`AOtO(ddR1;;}wol{5B{9`n5?sIIA(UrE zfsoxZh?Yw*JW`DDe>b|IfV{z2>6@=H>XRof>?w7Yvyr@7Pb^Xv_>PIWG&QKy;l$)?UJB~EQK5o zPEAd{xIKYF0TbM>)PwFvGh8~8-7XjHcuD7?+!E-^(yUTFx!yn&HzBR}@U19+3E + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/index.html b/index.html new file mode 100644 index 000000000..30d60a169 --- /dev/null +++ b/index.html @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + + + + + + +Drycc + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + +
+
+
+
+

A Open, Unified, Lightweight, Simpler Containers as a Service (CaaS).

+ +
+ + + Learn More + + + Quickstart + +

Simpler cloud, happier devs, better results — in the drycc!

+

+ +
+
+
+
+ +
+ +
+
+
+
+
+

Native to Kubernetes, Drycc is the Container as a Service(CaaS) suite available +on every public cloud, every Kubernetes distribution, the private cloud and the edge.

+

(An easy-to-use, scalable CaaS platform available on Metal, AWS, Azure, and Google Cloud, +and more)

+
+
+
+
+
+
+
+
+
+
+ +
+

New monitor metrics!

+
+

We provide a few out of the box dashboards for monitoring Drycc Workflow.

+
+

Read more

+
+
+
+ +
+

Contributions welcome!

+
+

We do a Pull Request contributions workflow on GitHub. New users are always welcome!

+
+

Read more

+
+
+
+ +
+

Contact us on tawk!

+
+

If you have any questions concerning our products, our support team will be happy to help you.

+
+

Read more

+
+
+
+
+
+
+
+
+

Features

+
+
+
+
+
+
+
+
+
+ +
+

Open Source

+
+

Open source from day one, leverage the power of global innovation with the leading database open source community.

+
+

Read more

+
+
+
+ +
+

Multi Platform

+
+

Both X86 and ARM64 are supported with binaries and multiarch images available for both, drycc works great from something in any server.

+
+
+
+
+ +
+

Meet twelve-factor

+
+

Drycc Workflow is a lightweight CaaS platform that deploys and scales Twelve-Factor apps as containers across a K8s cluster.

+
+

Read more

+
+
+
+
+
+
+
+
+

It’s easy to deploy, operate and scale drycc — anywhere.

+
+
+
+ + + +
+ + +
+ + + + + + \ No newline at end of file diff --git a/index.xml b/index.xml new file mode 100644 index 000000000..56de50ecd --- /dev/null +++ b/index.xml @@ -0,0 +1,1817 @@ + + + Drycc – Drycc + / + Recent content on Drycc + Hugo -- gohugo.io + en + + + + + + + + + + Blog: Drycc Workflow v1.7.8 + /blog/2024/05/01/drycc-workflow-v1.7.8/ + Wed, 01 May 2024 00:00:00 +0000 + + /blog/2024/05/01/drycc-workflow-v1.7.8/ + + + + <h2 id="workflow--v177---v178">Workflow ## v1.7.7 -&gt; v1.7.8<a class="td-heading-self-link" href="#workflow--v177---v178" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>builder v1.6.0 -&gt; v1.7.0</li> +<li>controller v1.8.0 -&gt; v1.9.0</li> +<li>workflow-cli v1.6.0 -&gt; v1.7.0</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/384c7ee9c69201b4d3280bb1582e50ad40210b8f"><code>384c7ee</code></a> (builder) - domain: add procfile_type</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/26c8c7f1a2ed3445fc4a52a5f7b8e7cace8a12e8"><code>26c8c7f</code></a> (controller) - domain: add procfile_type</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/bd49789b2aa8bbb8da440d63c83e339fd69d4774"><code>bd49789</code></a> (workflow-cli) - domain: add procfile_type</li> +</ul> + + + + + + Blog: Drycc Workflow v1.7.7 + /blog/2024/04/30/drycc-workflow-v1.7.7/ + Tue, 30 Apr 2024 00:00:00 +0000 + + /blog/2024/04/30/drycc-workflow-v1.7.7/ + + + + <h2 id="workflow--v176---v177">Workflow ## v1.7.6 -&gt; v1.7.7<a class="td-heading-self-link" href="#workflow--v176---v177" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>builder v1.5.1 -&gt; v1.6.0</li> +<li>controller v1.7.0 -&gt; v1.8.0</li> +<li>database v1.2.1 -&gt; v1.3.0</li> +<li>passport v1.2.0 -&gt; v1.3.0</li> +<li>imagebuilder v1.1.1 -&gt; v1.2.0</li> +<li>fluentbit v0.0.1 -&gt; v0.0.2</li> +<li>logger v1.3.3 -&gt; v1.3.4</li> +<li>storage v0.0.5 -&gt; v0.1.0</li> +<li>gateway v0.0.2 -&gt; v0.0.3</li> +<li>monitor v1.4.0 -&gt; v1.4.1</li> +<li>redis v1.3.2 -&gt; v1.4.0</li> +<li>timeseries v0.0.2 -&gt; v0.1.0</li> +<li>prometheus v0.1.1 -&gt; v0.1.2</li> +<li>rabbitmq v1.2.1 -&gt; v1.3.0</li> +<li>registry v1.2.2 -&gt; v1.3.0</li> +<li>registry-proxy v1.2.1 -&gt; v1.2.2</li> +<li>workflow-cli v1.5.2 -&gt; v1.6.0</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/6c1cf5e514543737c38384596abffca1ac96af44"><code>6c1cf5e</code></a> (builder) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/65ae63c4d3aaff3354d162718ff07c0509b4e689"><code>65ae63c</code></a> (builder) - pipeline: add dryccfile support</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/bb7b11de75226c3a1cb9254dfec78a8edda0c864"><code>bb7b11d</code></a> (builder) - auth: add tokens api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/39d022fe0a4106c91ea461f73728490560f8d653"><code>39d022f</code></a> (controller) - ps: add pod logs support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/86056d06d8992172fe02240d7963aa416ec9c754"><code>86056d0</code></a> (controller) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4cf005c1cc4b361af80ef96597e291ebe3baec24"><code>4cf005c</code></a> (controller) - limits: add limits plan support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/bf60e4bdbebb3f3288e0fbd81566c264dd187faf"><code>bf60e4b</code></a> (controller) - controller: add init job</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/98f77a8ceeea6e8a098cd37d79115201c40133e1"><code>98f77a8</code></a> (controller) - pipeline: add dryccfile support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8ce9a83f4bcf46d6039910e052e6ebfa959fd0e8"><code>8ce9a83</code></a> (controller) - cert-manager: add tls events</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7034f5d8347f0c85b40651eaf239a554fd95ae76"><code>7034f5d</code></a> (controller) - config: deploy according to procfile_type</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5554d8f9f26790783d97d6d6128920ffa9b28713"><code>5554d8f</code></a> (controller) - config: add typed_values</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/2c5bbad2d74b1c40c61158477aac9103dac2eff4"><code>2c5bbad</code></a> (controller) - auth: add token api</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/410d34e8e639c973557104c3aee14a85324f3c0f"><code>410d34e</code></a> (database) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/693e4d199b18342e33c7ec68c3a651d29b7d9ad6"><code>693e4d1</code></a> (imagebuilder) - pipeline: add dryccfile support</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/7d9cc0679eac7dd873d8db8f9607e347830b2aa1"><code>7d9cc06</code></a> (imagebuilder) - config: add typed values</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/854e1711180de70bc83d3c65721910df013ef988"><code>854e171</code></a> (passport) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/7ac92557670d915c1e568c7297c5ec1b9620f1a1"><code>7ac9255</code></a> (passport) - oauth2: add authorization code for any grant type</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/4517547e21983dd7192ae8cc985c974ed2c64b51"><code>4517547</code></a> (rabbitmq) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/bccfcb43cd63e62974b55523a75fa994ed560453"><code>bccfcb4</code></a> (redis) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/d8876055c0732c470d17d9205a5188289fdac1ec"><code>d887605</code></a> (registry) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/ff09e5b8279cd3343370bfa58c3acba234621263"><code>ff09e5b</code></a> (storage) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/c6e2ac82c8adc75687dbc814cb2163b06820311e"><code>c6e2ac8</code></a> (timeseries) - charts: reuses the value from an existing secret and config</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/22c4c772e3c9cbfe4f686d2fbe161b6484cdcc12"><code>22c4c77</code></a> (workflow-cli) - apps: change drycc run to async</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/a9e6369153255a6cc84dc73e3095086a34d25ad1"><code>a9e6369</code></a> (workflow-cli) - ps: add pod logs support</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/2bc31c8a2010e147b92827a967238e88dca5b743"><code>2bc31c8</code></a> (workflow-cli) - limits: add limits plan support</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/f40398a555e67a942fbe465d29e1076516941d74"><code>f40398a</code></a> (workflow-cli) - pipeline: add dryccfile support</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/03638ffdaefab5e0c7020f6eb279ddeda99aeded"><code>03638ff</code></a> (workflow-cli) - tls: add tls events</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/91136274d87d2cf9e0d2a1dd313d9b948a5d0a81"><code>9113627</code></a> (workflow-cli) - config: add typed values</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/43ee760c4bc93bc5e5402536a09f05dfd6832b7d"><code>43ee760</code></a> (workflow-cli) - auth: add tokens api</li> +</ul> +<h4 id="fixes">Fixes<a class="td-heading-self-link" href="#fixes" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/50dfe6449cbf50bfcf55421f34f2195cb8d7e26c"><code>50dfe64</code></a> (builder) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ab09b243b8484d8a989327e8e3b41f2a23efa643"><code>ab09b24</code></a> (controller) - healthcheck: delete outdated code</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/52019b541aaaca98b2b6692fec1290d1231e21fe"><code>52019b5</code></a> (controller) - services: default PORT change error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f57ae429fa4d9dbd89c7cf81f805fe9127930219"><code>f57ae42</code></a> (controller) - certificate: failed to create certificate</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/30c3f548324dcfa571a86afbed64ba0d38b72e99"><code>30c3f54</code></a> (controller) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/dbba43ae315644e858eb2330d52cbf636a366a07"><code>dbba43a</code></a> (controller) - service: update port error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e0459c5d43a74c2c38aae6ebf3e207ad8cc9f283"><code>e0459c5</code></a> (controller) - copy: use deepcopy replace copy</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/2122479685d9ce83c986449e20a041de105a2d49"><code>2122479</code></a> (controller) - charts: failed to call webhook</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/53d99775d66648aca41b88992df4ee203cb8f675"><code>53d9977</code></a> (controller) - signals: config limits handle error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/afda287ead80e94a699b3548c01fdfdbd1a6f5a4"><code>afda287</code></a> (controller) - limits: always set default</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/b350cb89e4c313d776592e9e4706909ee72550b5"><code>b350cb8</code></a> (database) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/b48a42243e602637fb04f14cb74d23e23096e2e2"><code>b48a422</code></a> (fluentbit) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/7cebca2a2589c839efbe49cbec6becde85149a8e"><code>7cebca2</code></a> (gateway) - cert-manager: auto tls error</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/190c19bbac3386e277bd7918be5b7f7ad5a25566"><code>190c19b</code></a> (imagebuilder) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/2c6a6f9273a0f5e2c16744f6ac6e77d27a7234a2"><code>2c6a6f9</code></a> (logger) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/10bb98df862bebefcf4142e88c24e8f804e310ba"><code>10bb98d</code></a> (monitor) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/f8225dca4c4ceae7bc4d613e77ae4c8ebf71838c"><code>f8225dc</code></a> (passport) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/06db66c072006f79c10404812ad9f0902cfb52b7"><code>06db66c</code></a> (prometheus) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/f4aff727962b6afe99e89283ce14ebe8d571d9ab"><code>f4aff72</code></a> (rabbitmq) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/88c18ff452bdd478f49dd88f6595ea096e430f2d"><code>88c18ff</code></a> (redis) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/5dcc19d6d47ea30b799ae10e915ebd948b39fc4c"><code>5dcc19d</code></a> (registry) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/092a9398243f19e41ac14cc5fb4f76473848c585"><code>092a939</code></a> (registry-proxy) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/3597ac918db548f837b3262a033d836690378972"><code>3597ac9</code></a> (storage) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/5a49b35d2197c957e43a98e94d38ac8a8ebd894b"><code>5a49b35</code></a> (timeseries) - woodpecker: CI_SYSTEM_ARCH env removed</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/0c4a48a84b998b8e7f57f09f307930630e8efd74"><code>0c4a48a</code></a> (workflow-cli) - tls: change issuer options</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/06a2511195bc1f2a3145a73269428200914b4694"><code>06a2511</code></a> (workflow-cli) - tls: info error</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/2f7617e164707830b52f2ca39c7f634ca53842ed"><code>2f7617e</code></a> (builder) - go: bump controller-sdk-go version</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/aae2f2911197e4643e7a999944401d2e5acd884d"><code>aae2f29</code></a> (builder) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/7304980fb22cd0d56e1fa5b1e573b4795ef2ddd9"><code>7304980</code></a> (builder) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/30b648b0d429ba08f89e1d3b49078e40eae2d897"><code>30b648b</code></a> (builder) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/2afa006867a3d4d4501578f0973ff759d87af87f"><code>2afa006</code></a> (builder) - controller-sdk-go: bump version</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/d127a9070a6dd0be1d96860c719d3b4a71eb7bb9"><code>d127a90</code></a> (builder) - config: add typed values</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/32fdfd0e7f54793d3ced05ff42b300173debe866"><code>32fdfd0</code></a> (controller) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0974942fb8a70d9165ef6524744850cf72629a0c"><code>0974942</code></a> (controller) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f401e08d3ffbfee5d84410ad8e31c18a3267513e"><code>f401e08</code></a> (controller) - python: bump python 3.12</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c565959af53e6ab7be7245faea09fd1a30972ac7"><code>c565959</code></a> (controller) - celery: remove retrieve_resource task</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/47be1a10b03d7522a9bc87b9973c8f126db95478"><code>47be1a1</code></a> (controller) - requirements: bump drf 3.15.1</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/99f7468e561d596121bc981294e6ca4baaed2728"><code>99f7468</code></a> (controller) - charts: add config to values.yaml</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7d17f5ca716596ef66046eb5f3606215feb87731"><code>7d17f5c</code></a> (controller) - scale: prohibit scale when there is a running pipeline</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f09e1c9475e64840ff02e23cee30f5911b507a58"><code>f09e1c9</code></a> (controller) - resource: sort services and plans</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e817505fc5dc6a2e9b959b9fd7d63c044f17fcf1"><code>e817505</code></a> (controller) - limits: change default cpu and gpu name</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5531b2ff4b15a6b9804cc0b146b69ee7308a1a83"><code>5531b2f</code></a> (controller) - auth: add password login</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/27473f72e8b7c1f1b6bb9c56493688f346bbcc9c"><code>27473f7</code></a> (controller) - deps: bump gunicorn from 21.2.0 to 22.0.0 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c1ee1c7a3103c938b8b81219da7b14cd30f3eceb"><code>c1ee1c7</code></a> (controller) - deps: bump aiohttp from 3.9.3 to 3.9.4 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/affbcb587360d7750f3faf4d022e36032f0b3266"><code>affbcb5</code></a> (database) - postgres: add patroni and postgres params (#15)</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/f9e4edaf9a2a22b974a2aced48a7890f767da0c0"><code>f9e4eda</code></a> (database) - dockerfile: install vi</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/008b7b675c244d2aff9b86947fe907dbb84185f4"><code>008b7b6</code></a> (database) - dockerfile: install vim instand of vi</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/dbbfee12b2fe9c773d32660a6bcf26674ae2cd61"><code>dbbfee1</code></a> (database) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/2e26c333df5aa90243cff8c5159a6c3a9b499a00"><code>2e26c33</code></a> (database) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/a1b81f20f517743d9f69ecda526095a4e9c3ee36"><code>a1b81f2</code></a> (database) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/bc725e8169b25eda4017012f72b5d970147f0d08"><code>bc725e8</code></a> (fluentbit) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/5d738865825bd083561972373a5dd8796a53be6c"><code>5d73886</code></a> (fluentbit) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/b85072d0177447ac3f05f1f4ccd4c9d7f4a56f99"><code>b85072d</code></a> (fluentbit) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/761174ddb5bc06643a02c145714587816ea06f8a"><code>761174d</code></a> (gateway) - gateway: change secrets name</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/1c304da25eef99568badf3ece29639dd6d8f8564"><code>1c304da</code></a> (gateway) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/b919a4c24b5abb776876df002cc9d4c15cf3d50d"><code>b919a4c</code></a> (gateway) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/3cea298be74856a2fba40b0a35824e0f3018dcab"><code>3cea298</code></a> (imagebuilder) - charts: allow all dns</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/653bcbeec95adcea209299751a3a94f3ebaf2d4f"><code>653bcbe</code></a> (imagebuilder) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/59daeab055610ce6cc584be73dba3767158b9747"><code>59daeab</code></a> (imagebuilder) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/2834a5acb914eecb7708ad3bd3efdcc38243d784"><code>2834a5a</code></a> (logger) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/6685492c2a8493bad3b59dedb201576f7508ff86"><code>6685492</code></a> (logger) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/191cdaf001ab5b916b0edf53aaa2a7558ef7f35a"><code>191cdaf</code></a> (logger) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/b3c3cfa319fe46d30696a2f4637f91636398ffff"><code>b3c3cfa</code></a> (monitor) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/796799db309de06ea54db56a1c0e5f397c858f47"><code>796799d</code></a> (monitor) - grafana: add node metrics dashboard</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/ef2a2228a27e4eddce1ff3b4b56755ab013c47cd"><code>ef2a222</code></a> (monitor) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/9c830909640fddca03329d4a72eb91ab1d913c86"><code>9c83090</code></a> (monitor) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/1a97c2cedd3ace5c567bf32dbd057bd215502662"><code>1a97c2c</code></a> (passport) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/353e1ae932ea4dae5112b8f8225ee502695b11ee"><code>353e1ae</code></a> (passport) - logger: add oauth2_provider logger config</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/fe735c0d8c5a2840349b27ceb081d02729ae50bf"><code>fe735c0</code></a> (passport) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/41d6144a20f24461e1a393d4b1957f5be19f4f3a"><code>41d6144</code></a> (passport) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/979d4740bdd50a12f5110144cf413c3972164c90"><code>979d474</code></a> (passport) - python: bump python 3.12</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/e9f41a121e11becd9dcd6b5422dcc6e209cbeedf"><code>e9f41a1</code></a> (passport) - requirements: bump drf 3.15.1</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/f479f4d5791ac2917679b70f376ec9bf24fa1fd4"><code>f479f4d</code></a> (passport) - charts: add migrate job</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/ad9abf64ad7e2b959d565eaa0016066183444cd0"><code>ad9abf6</code></a> (passport) - passport: migrations add run_before</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/95ac66705669bd4301af9d3ae812e0843eb6a37c"><code>95ac667</code></a> (passport) - passport: optimize the use of master and slave database rules</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/204f7fc62fd0cdf016cd5e95a4d2fd2e6c841b17"><code>204f7fc</code></a> (passport) - deps: bump gunicorn from 21.2.0 to 22.0.0 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/90a6410c0d0864a434b804cf80fe63960afd4493"><code>90a6410</code></a> (prometheus) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/2d8eb44ef28deae27ac54247a008a5351212eea0"><code>2d8eb44</code></a> (prometheus) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/9687a175b58aed22d314557d7254a82ff0a6d3dd"><code>9687a17</code></a> (rabbitmq) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/35d3d5b7e01bebbeeea5442a22f24d40fcbfdd93"><code>35d3d5b</code></a> (rabbitmq) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/6a6564ddef4f26bc81ea3eb9e965fb8e6180d092"><code>6a6564d</code></a> (rabbitmq) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/cb6722f0df93fae95d4480e1929b55e1e78a2a3a"><code>cb6722f</code></a> (redis) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/9553497d89e358022ab539cb3db658def17bc9cb"><code>9553497</code></a> (redis) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/1c8dc07b0167126d292e3db45f23db5d6ff111dc"><code>1c8dc07</code></a> (redis) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/9fa2a32f965d282940cd3f8489ce8959bb2e791f"><code>9fa2a32</code></a> (registry) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/9b09e51c1d548ba4d1c088aff761391092d746e3"><code>9b09e51</code></a> (registry) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/7dbd3902139c8430c18bfb83e4dbce79a6df16a5"><code>7dbd390</code></a> (registry) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/e1d2a33d8c9f20eddce510d79df050b0fe90a94c"><code>e1d2a33</code></a> (registry-proxy) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/3eabfdda5c2a78fc49e73dce382263faad29f5c3"><code>3eabfdd</code></a> (registry-proxy) - charts: remove default limits</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/f8754dad5de5f88bb0f20f46d73e1cbab2aff68e"><code>f8754da</code></a> (registry-proxy) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/7df73166e6ea521587eb2ba5b8e1626cc334d7f3"><code>7df7316</code></a> (registry-proxy) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/861d3b8f5ebc2ee32f11a600b26a14d79e0acdf1"><code>861d3b8</code></a> (storage) - filer: modify the default parameters of the filer</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/5fa08da71087503071fa780ac2469f4d55e7d0c5"><code>5fa08da</code></a> (storage) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/22c4620e0e724b26943260d58d749bb4efd0999b"><code>22c4620</code></a> (storage) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/6c1e29c1bf187e2b754d6f683014dba7a4ebe342"><code>6c1e29c</code></a> (timeseries) - postgres: add patroni params</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/e280d3ff2d799fa1e0738bf6e7585aaba0e72c58"><code>e280d3f</code></a> (timeseries) - dockerfile: install vi</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/5213617c4a5ace9225e1cad8348c736b943c5e25"><code>5213617</code></a> (timeseries) - dockerfile: install vim instand of vi</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/a569a57f06484738d5801651f9e253553347f928"><code>a569a57</code></a> (timeseries) - charts: add diagnostic mode</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/b93ec702dcbd0e2306d0290cde2d104d4c5897f3"><code>b93ec70</code></a> (timeseries) - woodpecker: migrations woodpecker-ci to 2</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/ff3b8705e65a56f0da392519b54f9b060894ec8c"><code>ff3b870</code></a> (timeseries) - charts: change canary app version</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/e334f74a71ffbd5f10baa38da43248d92c051322"><code>e334f74</code></a> (workflow-cli) - healthcheck: delete outdated healthcheck style</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/4f8b960e9ddcd1351b4567935d0a8d98d2aa843d"><code>4f8b960</code></a> (workflow-cli) - auth: add password login</li> +</ul> + + + + + + Blog: Drycc Workflow v1.7.5 + /blog/2024/02/27/drycc-workflow-v1.7.5/ + Tue, 27 Feb 2024 00:00:00 +0000 + + /blog/2024/02/27/drycc-workflow-v1.7.5/ + + + + <p>These release notes for Drycc Workflow v1.7.5 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.7.4, please refer to the following change summary.</p> +<h2 id="workflow--v174---v175">Workflow ## v1.7.4 -&gt; v1.7.5<a class="td-heading-self-link" href="#workflow--v174---v175" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>builder v1.5.0 -&gt; v1.5.1</li> +<li>controller v1.6.3 -&gt; v1.7.0</li> +<li>logger v1.3.2 -&gt; v1.3.3</li> +<li>storage v0.0.3 -&gt; v0.0.4</li> +<li>redis v1.3.1 -&gt; v1.3.2</li> +<li>rabbitmq v1.2.0 -&gt; v1.2.1</li> +<li>registry v1.2.1 -&gt; v1.2.2</li> +<li>workflow-cli v1.5.1 -&gt; v1.5.2</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/95d130a19f63544defbf415d63ea44b650d07da7"><code>95d130a</code></a> (controller) - controller: volume support nfs</li> +</ul> +<h4 id="fixes">Fixes<a class="td-heading-self-link" href="#fixes" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ee2ee15992331922728aabcf03420fbad7b76a1d"><code>ee2ee15</code></a> (controller) - controller: container entrypoint error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/03ea4f87b58f2e3f12505ff0ba43ab655fdf0528"><code>03ea4f8</code></a> (controller) - controller: class property have been deprecated in python 3.11</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5f04d177fa399a7859d4f0d8e13b58e77983c2e9"><code>5f04d17</code></a> (controller) - controller: miss err msg</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/27972a3a48f5fb67283c50b95e58da7b7ef05458"><code>27972a3</code></a> (controller) - controller: load_db_state_to_k8s err</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a005d629bbdd9a5d68f5bb4c480fd9e6b51300c7"><code>a005d62</code></a> (controller) - controller: volume repeat path no error</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/c7a5ba62b8e513f43aad8143e507d23885558834"><code>c7a5ba6</code></a> (rabbitmq) - rabbitmq: cpu usage to high</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/45c20770d8203ae475c127fe82b00bd04334507d"><code>45c2077</code></a> (workflow-cli) - workflow-cli: miss err msg</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/bc738bd6ef19fa222e675058bc0af79b75026308"><code>bc738bd</code></a> (workflow-cli) - workflow-cli: volumes list format</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/35e1c063c5f40fc97f60ab2a0b9f66de37eef383"><code>35e1c06</code></a> (builder) - builder: bump golang 1.22</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/26caa36c197b968909da1a584dff686cd6bcd651"><code>26caa36</code></a> (controller) - deps: bump aiohttp from 3.9.0 to 3.9.2 in /rootfs (#118)</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3d938c4f00b4a972abe948dc814b2cbf41ea2b3b"><code>3d938c4</code></a> (controller) - deps: bump django from 4.2.7 to 4.2.10</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/e625c2f86176c0acff331f58f84da15d96041f21"><code>e625c2f</code></a> (logger) - logger: bump golang 1.22</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/bfa500dc9271bf0a475c50feb8e6be8574953bcd"><code>bfa500d</code></a> (redis) - redis: headless svc does not require ports</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/330209a5c329c0f34b47a07812e7282ad7890208"><code>330209a</code></a> (registry) - registry: headless svc does not require ports</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/48c42eb3d6ef09471d26a65c88f5cd88cd6684e8"><code>48c42eb</code></a> (storage) - storage: change volume index to leveldb</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/f4fde9d2c871162c14ecf0e993093211f49e7c66"><code>f4fde9d</code></a> (storage) - storage: add volume size limit</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/33e3684ec520a83bccdf7623d4b3d1317c10e9a0"><code>33e3684</code></a> (workflow-cli) - workflow-cli: volume support nfs</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/48d59507ab5f40e8a8cea9875b230e9e1b97644d"><code>48d5950</code></a> (workflow-cli) - workflow-cli: bump golang 1.22</li> +</ul> + + + + + + Blog: Drycc Workflow v1.7.6 + /blog/2024/02/27/drycc-workflow-v1.7.6/ + Tue, 27 Feb 2024 00:00:00 +0000 + + /blog/2024/02/27/drycc-workflow-v1.7.6/ + + + + <h2 id="workflow--v175---v176">Workflow ## v1.7.5 -&gt; v1.7.6<a class="td-heading-self-link" href="#workflow--v175---v176" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>storage v0.0.4 -&gt; v0.0.5</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/6cb63b632ab24cecda10e2e772f46e499d678aa5"><code>6cb63b6</code></a> (storage) - seaweedfs: bump version 3.63</li> +</ul> + + + + + + Blog: Drycc Workflow v1.7.2 + /blog/2024/01/29/drycc-workflow-v1.7.2/ + Mon, 29 Jan 2024 00:00:00 +0000 + + /blog/2024/01/29/drycc-workflow-v1.7.2/ + + + + <p>These release notes for Drycc Workflow v1.7.2 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.7.1, please refer to the following change summary.</p> +<h2 id="workflow--v171---v172">Workflow ## v1.7.1 -&gt; v1.7.2<a class="td-heading-self-link" href="#workflow--v171---v172" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>controller v1.6.0 -&gt; v1.6.1</li> +<li>logger v1.3.1 -&gt; v1.3.2</li> +<li>storage v0.0.1 -&gt; v0.0.2</li> +<li>timeseries v0.0.1 -&gt; v0.0.2</li> +<li>prometheus v0.1.0 -&gt; v0.1.1</li> +<li>workflow-cli v1.5.0 -&gt; v1.5.1</li> +</ul> +<h4 id="fixes">Fixes<a class="td-heading-self-link" href="#fixes" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/2fe80a65e2f564abe94a04a4018af101ca10d55d"><code>2fe80a6</code></a> (controller) - resources: after resources instance update, could not delete (#111)</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a4082ad0c4fca861bc713864ec4539249b707c0e"><code>a4082ad</code></a> (controller) - controller: resource status and binding</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e9bfccc307fd9631361eaedd1db0c98fb11f7a9b"><code>e9bfccc</code></a> (controller) - controller: fix multiple volumes mount at one dir error (#116)</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/58d2b4c35020c25e133f46bb48f7b512e41a0f91"><code>58d2b4c</code></a> (logger) - logger: redis conn error block</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/7cb2700c483040869f3fa5ff1af76cf68d8e8711"><code>7cb2700</code></a> (prometheus) - prometheus: prometheus config basic_auth</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/7838c6b63eec363ec0fccbc8a2b455477edb69db"><code>7838c6b</code></a> (storage) - storage: random accesskey secretkey</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/d9dcdfb7350c003a60883c9e70e3afca730d5419"><code>d9dcdfb</code></a> (storage) - storage: pod restart loses data</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/3cbdd29c8dd94d7bd046a3fe817dabbb59887225"><code>3cbdd29</code></a> (storage) - storage: tipd cannot start after deleting pod</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/be7e11fe5a8a861a976c27b69331779b4edd0a3a"><code>be7e11f</code></a> (storage) - storage: jq command not found</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/878f674be07b4aee660ec66830a9fe29473bdaba"><code>878f674</code></a> (storage) - storage: charts updateStrategy error</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/06cfe561e1327690dfcccd7151711053b8126a9a"><code>06cfe56</code></a> (timeseries) - timeseries: the data node ip is incorrect</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7f29f5a98049b0c256728dad38cf63026c45910e"><code>7f29f5a</code></a> (controller) - resources: retrieve resource instance response add message (#112)</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4a84dcdca75a3c1cd037c01777cf410c21c56225"><code>4a84dcd</code></a> (controller) - controller: add deploy default annotations (#113)</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/829d7e560317a0ac20081f6bd4c81f53b547aac4"><code>829d7e5</code></a> (controller) - controller: modify url match service name (#114)</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/30abf6dba46d215d7747b4443826e6e3fac1138a"><code>30abf6d</code></a> (controller) - controller: transfer app ownership in async</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/dc6f45e98ab77a776a620286465da106a8109ba6"><code>dc6f45e</code></a> (controller) - controller: add channel for pod exec</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/af4f3a771d8a7c6f1f99c17acb67704d9f3f921f"><code>af4f3a7</code></a> (controller) - controller: avoid error when secret no data field (#117)</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ca27956696aa6bd2e4adefcc6827f840eefd4b34"><code>ca27956</code></a> (controller) - controller: add pod default security</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/b2e9c647ff2a1e7828946d363b6cfc5bdca2deb7"><code>b2e9c64</code></a> (prometheus) - charts: node-exporter mount root (#2)</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/3cdb2b62fe9e2d6f7506c5215be9e3e7d27254b3"><code>3cdb2b6</code></a> (storage) - storage: bump seaweedfs 3.61</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/00dd2fd331104fd4f7ee58ca35a0906588318d16"><code>00dd2fd</code></a> (storage) - storage: add csi daemonset updateStrategy</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/48e763cb34c3e9b1004ad222a1e4670739e0b9ba"><code>48e763c</code></a> (storage) - storage: add drycc storage upgrade document</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/841df90682a121df819ea11ba8d2dc7843ffcd54"><code>841df90</code></a> (storage) - storage: bump seaweedfs 3.62</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/cefd52e7b031efc05f305a8d8f456229418556f8"><code>cefd52e</code></a> (timeseries) - timeseries: add check data node exists</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/ad1c46e39f392dd676a0f5c8e00b05ed1959cb95"><code>ad1c46e</code></a> (workflow-cli) - resources: resources instance add message</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/9f955c2c97a0a2875f7badadb4f868649cf44b2e"><code>9f955c2</code></a> (workflow-cli) - workflow-cli: add short options cpu</li> +<li><a href="https://api.github.com/repos/drycc/workflow-cli/git/trees/65399ef156b9fae2d2fe633cb6b4b63fb6263a1c"><code>65399ef</code></a> (workflow-cli) - workflow-cli: add tty resize support</li> +</ul> + + + + + + Blog: Drycc Workflow v1.7.0 + /blog/2023/12/08/drycc-workflow-v1.7.0/ + Fri, 08 Dec 2023 00:00:00 +0000 + + /blog/2023/12/08/drycc-workflow-v1.7.0/ + + + + <p>These release notes for Drycc Workflow v1.7.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.6.0, please refer to the following change summary.</p> +<h2 id="workflow--v160---v170">Workflow ## v1.6.0 -&gt; v1.7.0<a class="td-heading-self-link" href="#workflow--v160---v170" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>builder v1.4.0 -&gt; v1.5.0</li> +<li>controller v1.5.1 -&gt; v1.6.0</li> +<li>database v1.2.0 -&gt; v1.2.1</li> +<li>passport v1.1.0 -&gt; v1.2.0</li> +<li>imagebuilder v1.1.0 -&gt; v1.1.1</li> +<li>fluentbit v0.0.0 -&gt; v0.0.1</li> +<li>logger v1.3.0 -&gt; v1.3.1</li> +<li>storage v0.0.0 -&gt; v0.0.1</li> +<li>gateway v0.0.0 -&gt; v0.0.1</li> +<li>monitor v1.3.0 -&gt; v1.4.0</li> +<li>redis v1.3.0 -&gt; v1.3.1</li> +<li>timeseries v0.0.0 -&gt; v0.0.1</li> +<li>prometheus v0.0.0 -&gt; v0.1.0</li> +<li>rabbitmq v1.1.0 -&gt; v1.2.0</li> +<li>registry v1.2.0 -&gt; v1.2.1</li> +<li>registry-proxy v1.2.0 -&gt; v1.2.1</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/fcbebdae62029cf4308ffc0adeb8a90cf5550077"><code>fcbebda</code></a> (builder) - builder: use TCPRoute expose service</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d02bb5de832e50a281aa550c738b3eb653549806"><code>d02bb5d</code></a> (controller) - controller: support app dns policy config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9aa968ebccdebaf0971a6dbaa890320b9603a6a9"><code>9aa968e</code></a> (controller) - controller: add svc type support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/62e2d348e2987ebcdcaba993559dc1d30a8ffec6"><code>62e2d34</code></a> (controller) - controller: improve the services api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4393755b08a587e093b7603683ac8b5cdf654ac3"><code>4393755</code></a> (controller) - controller: use gateway replace ingress</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/323045d9ab1589c08a8090d7fe9c73ab6276281d"><code>323045d</code></a> (controller) - controller: add canary support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3f81c975baefd4018e6b3426965b4397456f0d0e"><code>3f81c97</code></a> (controller) - gateways: add addresses field</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4e64aa73d0fde9fe667064b420bd9375dbea8397"><code>4e64aa7</code></a> (controller) - gateways: add addresses field</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/02ad5811d9a8d3e031ce97f8ce85d0ce85be7619"><code>02ad581</code></a> (monitor) - grafana: add pd tikv dashboard</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/2a9e2b042941a911a31c846f71988d6eadeff811"><code>2a9e2b0</code></a> (monitor) - monitor: add storage monitor</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/41d5057b1d4067822edcf597e888b3f23e052d9d"><code>41d5057</code></a> (monitor) - grafana: data source change to prometheus</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/ec035d11f3fcf8486f4240aac8db4890e4520b53"><code>ec035d1</code></a> (monitor) - monitor: usegateway replace ingress</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/c694c98cfab10d8381fd70d7efbbdaedc26caf2d"><code>c694c98</code></a> (monitor) - grafana: add drycc storage seaweedfs dashboard</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/1e1fdc8a8f3ca0974ff5d06ade500afed29a16ed"><code>1e1fdc8</code></a> (passport) - passport: use gateway replace ingress</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/ffdb408776bfa42c80ba5df56730c689a26a821a"><code>ffdb408</code></a> (prometheus) - prometheus: use gateway replace ingress</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/04152b99ca9a8aacddc246af78968191e41ea9d7"><code>04152b9</code></a> (rabbitmq) - rabbitmq: use gateway replace ingress</li> +</ul> +<h4 id="fixes">Fixes<a class="td-heading-self-link" href="#fixes" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/0499500a1335791a89ffcab18e97b22d55ac232c"><code>0499500</code></a> (builder) - builder: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/642491d68a4958cdd6b9b78771ad512d7a462231"><code>642491d</code></a> (builder) - builder: no build log</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/873d146812f40de609100d9a2181d50e79695a54"><code>873d146</code></a> (controller) - controller: do not set entrypoint when no procfile</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d9028c53547b4d53d46d5cba508602ae31d0b391"><code>d9028c5</code></a> (controller) - controller: pip8 error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3efcfb764325255ff9ae4ca47ab82927e88ff9ab"><code>3efcfb7</code></a> (controller) - controller: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/18a3a1a3f777597966da8f8fb21545a18b44d887"><code>18a3a1a</code></a> (controller) - controller: miss service error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/94f796cd2ebd8dd76b4e8073cab039fed0211cae"><code>94f796c</code></a> (controller) - controller: drycc run pod should not restart</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/80f31614601daf30351033c3d9ce8610d4a41581"><code>80f3161</code></a> (controller) - controller: monitor query error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b76f2c5ee9c0e3461737ec7fc6cc73b73a0c043c"><code>b76f2c5</code></a> (controller) - controller: read websocket delay</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b6e068ee19354b98d613985c8c80ec6d42171cc0"><code>b6e068e</code></a> (controller) - controller: metrics sql tpl, gateway pod should not restart, cleanup old rs, update monitor datatbase config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ad9adc645759445702688b2a486ed5d6a1e6a5f7"><code>ad9adc6</code></a> (controller) - controller: rabbitmq sharding err</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/67739075a1134b817e9be97b7d594c1e3790f444"><code>6773907</code></a> (controller) - controller: default k8s pod annotaions</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ffcf1f931c395c3293d909f32a3bf35136b72776"><code>ffcf1f9</code></a> (controller) - controller: under-indented for visual indent</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3afd0cf8e36cec5bbfb59424d5ab036268287d3a"><code>3afd0cf</code></a> (controller) - controller: charts env error</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/769bb8b8dc47ef032377a61e6288c514bff16a9b"><code>769bb8b</code></a> (database) - database: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/769bb8b8dc47ef032377a61e6288c514bff16a9b"><code>769bb8b</code></a> (database) - database: label conflict error</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/6a321c5c802b3a0826bc283f2ffe429769f8753c"><code>6a321c5</code></a> (database) - database: link error</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/558feae9c0edfb4fa7f0dae08f09dc987f822c88"><code>558feae</code></a> (fluentbit) - fluentbit: build charts error</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/98d8a2a6046dffa3213f84fd5cb2f054727ca798"><code>98d8a2a</code></a> (gateway) - fixup</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/8b5dde1d5b0107913f3fca7c90703902fd9a360e"><code>8b5dde1</code></a> (gateway) - gateway: secretName</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/702866da3014497e303eb346be0f88c3c161586c"><code>702866d</code></a> (gateway) - gateway: build status</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/f55dac1cbab3214f60b33992f3e08e186bfa6198"><code>f55dac1</code></a> (imagebuilder) - imagebuilder: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/ac13b5f036e036073d39ddf2e34627be340df078"><code>ac13b5f</code></a> (imagebuilder) - imagebuilder: build svg</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/6b7bbc5a38a8550457585908ac7ce9858c19a034"><code>6b7bbc5</code></a> (logger) - logger: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/0136b5c3ac711f132be35d8382f9df9268145be6"><code>0136b5c</code></a> (monitor) - monitor: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/f03d975fe88a4419f58b54f8d1ac944f968b0bfe"><code>f03d975</code></a> (passport) - passport: DRYCC_GRAFANA_DOMAIN error</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/b530ea8960c173b16968dc5c4da5f8e5f783d9dd"><code>b530ea8</code></a> (passport) - passport: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/be5a0a77f5e037456676af5617cdcd01c2f868ea"><code>be5a0a7</code></a> (passport) - passport: change passport</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/1596c7f723d493b8f17e367999e0315d7f2bc205"><code>1596c7f</code></a> (rabbitmq) - rabbitmq: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/0dc4f6fef0bf147e2cec96cd26f490ae5799fa57"><code>0dc4f6f</code></a> (rabbitmq) - rabbitmq: images-shard error</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/43293ae792f0fc8fa932b7fac865f57510de793d"><code>43293ae</code></a> (redis) - redis: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/ca13b7d7592995b057f1075b3223074c7a9de54b"><code>ca13b7d</code></a> (registry) - registry: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/ab5c7937aac830c2b09b08777f39180248911442"><code>ab5c793</code></a> (registry) - registry: garbage collect error</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/ab0fabc77483f531acaeaa089afce1636200c20a"><code>ab0fabc</code></a> (registry-proxy) - registry-proxy: manifest error</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/dfc72361f70380697d7090cb0e5bfa61c5264560"><code>dfc7236</code></a> (registry-proxy) - registry-proxy: daemon yaml format</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/42c03bee957cb46b5703cd163cea24c754b3cccc"><code>42c03be</code></a> (storage) - storage: seaweedfs csi error</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/453e41a13ecaedf256dc823c37de3233a2f60cab"><code>453e41a</code></a> (timeseries) - timeseries: could not register node</li> +</ul> +<h4 id="docs">Docs<a class="td-heading-self-link" href="#docs" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/5433c8907bdf4c0320566878a0cfc4f38730f3d4"><code>5433c89</code></a> (gateway) - gateway: add prerequisites</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/2f0c5d8ed5a227507f7848426824759db673eb20"><code>2f0c5d8</code></a> (logger) - logger: change architecture</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/bdd02ebf1178209cca08c0e94d76638405100083"><code>bdd02eb</code></a> (builder) - builder: use dynamic clusterrole name</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/66b4b25ec7c517152a37e375f9a7e86e05cceada"><code>66b4b25</code></a> (builder) - builder: upgrade new controller-go-sdk</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/219d86f6bebf11fce80e2535b724bf8ad94b204b"><code>219d86f</code></a> (builder) - builder: upgrade go.mod</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/91f2f14b0b02af099fe67d4a9be65432de0cb18d"><code>91f2f14</code></a> (builder) - builder: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/9abca168d6a8b26f45a3787c2a80bf5aa6354451"><code>9abca16</code></a> (builder) - woodpecker: use woodpecker ci build status</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/f43dd5030ac3715ab96cfb2a114bd0416b21110c"><code>f43dd50</code></a> (builder) - deps: bump golang.org/x/net from 0.2.0 to 0.7.0</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/0384c69ad46cdabeabb3ca23d01367d047eb0c84"><code>0384c69</code></a> (builder) - builder: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/e3149b95e8c64c1d01444d58de67aa4747c4ebf7"><code>e3149b9</code></a> (builder) - builder: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/d88ea1bd5538e5425cb4cbb856ab82bb5dfe47e8"><code>d88ea1b</code></a> (builder) - builder: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/ba590303b791ff954e41a64ef8babe54170aba3b"><code>ba59030</code></a> (builder) - builder: upgrade go.mod</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/1114dd7d951215c23a6fcefc75a5a71a85391561"><code>1114dd7</code></a> (builder) - builder: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/fe50b626d9edf4908f6c820fa2714e5bde0fbc0e"><code>fe50b62</code></a> (builder) - builder: change drycc gateway listener name</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/db3950cf47cd8f5f0c06c579eec1189c2bcdb0b3"><code>db3950c</code></a> (builder) - builder: remove gateway route</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/5a508bbc9e21852c4e47e598bb42a7c8c75e93ee"><code>5a508bb</code></a> (builder) - builder: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/bbb9029e773f24d2692afdd801e8d09ca75538a3"><code>bbb9029</code></a> (builder) - deps: bump golang.org/x/net from 0.12.0 to 0.17.0</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/f4e5d6ca78d597e020ce398fd9fd132c41591826"><code>f4e5d6c</code></a> (builder) - builder: remove health url</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/9111c8ffd87978db6734d405ef0362c34b9fe4ef"><code>9111c8f</code></a> (builder) - builder: remove io/ioutil</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1f36e3ddd67b29571707c57819bdd8148647359c"><code>1f36e3d</code></a> (controller) - deps: bump django from 4.1.2 to 4.1.6 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e4ab434db6fd84cd35a127c8414951df7e138503"><code>e4ab434</code></a> (controller) - controller: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9f0301e4a138d337d9530807b347775d25ee6525"><code>9f0301e</code></a> (controller) - deps: bump django from 4.1.6 to 4.1.7 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/39324238c251f982072b28fdbb79c04df6230889"><code>3932423</code></a> (controller) - woodpecker: use woodpecker ci build status</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ae8b6b464f3733bd0ca743bd419ecf806646909f"><code>ae8b6b4</code></a> (controller) - setting: support KUBERNETES_LIMITS env config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c10b9bc740f74ed820d36ba5cb6eb462bce3bb7c"><code>c10b9bc</code></a> (controller) - controller: using the api_version instead of hard coding</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e6908cd934ec0360344c2120bbd4bd9a27b6fe9d"><code>e6908cd</code></a> (controller) - controller: upgrade requirements</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b0eba0c0f03b3b74bf6b2d013a8e2fd69dd5fc6c"><code>b0eba0c</code></a> (controller) - controller: add route rules serializer</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/2e4b6a457f6ab66137badecaa0ce5a020e2208e2"><code>2e4b6a4</code></a> (controller) - controller: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7d32b55dad2a0da5a2d539c970608182dfd00c52"><code>7d32b55</code></a> (controller) - controller: upgrade to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f2dc8dd737e44d1297f6a6903bc17392f767a828"><code>f2dc8dd</code></a> (controller) - controller: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5739b8306921408b11b921515cd6dc7a818e6a1a"><code>5739b83</code></a> (controller) - controller: use timescaledb replace influxdb</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/53892cb796b69ba91b1520ee2b1e35bf6516fb57"><code>53892cb</code></a> (controller) - controller: add timeseries</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0fe0eae17d2af7e0a955d6e8041db22a66b64317"><code>0fe0eae</code></a> (controller) - controller: upgrade requirements</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/18b2a915d043cade51e0d4017d08e4ffa9f54dd6"><code>18b2a91</code></a> (controller) - deps: bump aiohttp from 3.8.4 to 3.8.5 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f50874a6e180d9a18fd3a9b9ad1ec1491acae114"><code>f50874a</code></a> (controller) - controller: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/956cd081922f8eeda637530e8397a40d9f7d9c3d"><code>956cd08</code></a> (controller) - controller: change drycc gateway listener name</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9ab3ead47263e0f00f5d31afdad028eedefd6a56"><code>9ab3ead</code></a> (controller) - controller: remove passport url check</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a24c7b011de56845fcc0ffaa78424d60e6cb8aac"><code>a24c7b0</code></a> (controller) - controller: remove gateway route</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f7e539acb9890593d5b3ba970221f333b81abff5"><code>f7e539a</code></a> (controller) - controller: change celery priority</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ab77a529bc9ac2e61a45af4676b8d8796789f014"><code>ab77a52</code></a> (controller) - controller: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8e27501fc6f024bd590508ad827d6a28ca871776"><code>8e27501</code></a> (controller) - controller: dynamic app storage class</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/385978b8f8a07696196974f7f021886448fbc31c"><code>385978b</code></a> (controller) - controller: list_pods datetime format</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b20362c09cf14cbb64148476948481bca11fcf99"><code>b20362c</code></a> (controller) - deps: bump django from 4.2.3 to 4.2.7 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e11ae1ba7d5ef0423b6a51874704739e6a3c86df"><code>e11ae1b</code></a> (controller) - controller: add cluster migrate</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ca6e9dfa4e90c613572faf449445cebabcf1a310"><code>ca6e9df</code></a> (controller) - controller: async mount</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9a7fbfc5e7037dbcd6f8415da1540fc0d0785bff"><code>9a7fbfc</code></a> (controller) - controller: remove FOSSA</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3d55279d81f93783dfdcf0af47c429094fd45019"><code>3d55279</code></a> (controller) - deps: bump aiohttp from 3.8.5 to 3.8.6 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d498a11d8c1179d9ef7e09d4638b10663fc3266d"><code>d498a11</code></a> (controller) - controller: add measure loalancers</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/249a985410e98ab0250af7eaf88c28735f2d7ef1"><code>249a985</code></a> (controller) - deps: bump aiohttp from 3.8.5 to 3.8.6 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b967f5846a006e03d41374266d689a34bd387ba8"><code>b967f58</code></a> (controller) - deps: bump aiohttp from 3.8.6 to 3.9.0 in /rootfs (#107)</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8ca9ed61477fe4c538b0eefbe08f42757f9ec527"><code>8ca9ed6</code></a> (controller) - controller: no longer restrict reserved domain</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/9ff6649b311185927398a12d55451897015ba491"><code>9ff6649</code></a> (database) - database: add init database configure</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/9b4cd26e827862bbcbd2f95eb9ff5aea3031ef80"><code>9b4cd26</code></a> (database) - database: use dynamic clusterrole name</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/b59cde4a41499b1739f51776524c969963706a1e"><code>b59cde4</code></a> (database) - database: remove minio require</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/86462f8e432c21ed691f17544313747a1a95bf2a"><code>86462f8</code></a> (database) - database: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/1e8555a4fa0aa4ab14e276af95eeadb11e7ea2f3"><code>1e8555a</code></a> (database) - database: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/1b762d54948614e8ff8179f91ba4087c1c24cd93"><code>1b762d5</code></a> (database) - database: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/9ffe1fdcc1d1fd33e1d5a69d38c6e2c044f7e002"><code>9ffe1fd</code></a> (database) - database: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/69466d71dfb0fac98f5e2372eae4923d2cb55dde"><code>69466d7</code></a> (database) - database: add database extension</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/beb4b628783f30b8dec35f0ee50d179a27781915"><code>beb4b62</code></a> (database) - database: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/67e27148766a6a16379bccbb160df881e8638cfa"><code>67e2714</code></a> (database) - database: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/8f328f85f28b51b0ea8ce4fe508701c2e875a668"><code>8f328f8</code></a> (fluentbit) - fluentbit: no limit buffer size for kube api</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/fc0552c72b83267e37d67766a0e1040c7d3d59d8"><code>fc0552c</code></a> (fluentbit) - fluentbit: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/63a6cab0c5004ade3c332f16d87f70daaebc12b0"><code>63a6cab</code></a> (fluentbit) - fluentbit: change fluentbit match</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/220f81adae775c21f6eac5fca0f16f2f96962e7d"><code>220f81a</code></a> (fluentbit) - fluentbit: run as no-root</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/aec1393d9e976f2ecb24281a3fc92f5f8bdcf563"><code>aec1393</code></a> (fluentbit) - fluentbit: change configmap name</li> +<li><a href="https://api.github.com/repos/drycc/fluentbit/git/trees/1af4fd24c9e061cb74c3c09af75ad33262a74a19"><code>1af4fd2</code></a> (fluentbit) - fluentbit: change default stream name</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/bef90adfd96f4c713a7de261cb2c66e7cb9900af"><code>bef90ad</code></a> (gateway) - gateway: add route for gateway</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/d523ddb7f794774c5e237c10779fe43713cdc0b6"><code>d523ddb</code></a> (gateway) - gateway: change drycc gateway listener name</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/d9137f4c7681be9edacc2f1123660d0feb961601"><code>d9137f4</code></a> (gateway) - gateway: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/gateway/git/trees/0425dd4e7a0399fd757a80880e67eda2e8c150fc"><code>0425dd4</code></a> (gateway) - gateway: add customListeners</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/3982b86cb7515d42ead064dee86b931f2f4c58a7"><code>3982b86</code></a> (imagebuilder) - imagebuilder: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/3e4e7a329c7532d8787c9c76eb71d938d12fad45"><code>3e4e7a3</code></a> (imagebuilder) - imagebuilder: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/8df6e8e0e6684a4c4a21bf477958b36eb6750e97"><code>8df6e8e</code></a> (imagebuilder) - imagebuilder: upgrade stack version</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/a5601f7588843698b336eccacbc12559dc915779"><code>a5601f7</code></a> (imagebuilder) - imagebuilder: add drycc_app env</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/07465f8bc16cbb15e12d02d522df94265d503c45"><code>07465f8</code></a> (imagebuilder) - imagebuilder: upgrade to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/00d22d2a3c3fa5dce5595fee94bfa8d5a5ca9b2c"><code>00d22d2</code></a> (imagebuilder) - imagebuilder: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/0b7a24e9211acef3252234e4ebce81353c2a8218"><code>0b7a24e</code></a> (imagebuilder) - imagebuilder: upgrade podman/mc/caddy</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/a7d8be869f0b128e9fc6a28ec5c45e5cdca0ea90"><code>a7d8be8</code></a> (imagebuilder) - imagebuilder: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/6b2da83d29e0210a9307e4c5ad1199ed7d7599ce"><code>6b2da83</code></a> (logger) - logger: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/8245b2588a3c350b9c1405c9e56664881534c4b4"><code>8245b25</code></a> (logger) - woodpecker: use woodpecker ci build status</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/f811a74710324fa3ac4ac1fbafc76fe38b042c33"><code>f811a74</code></a> (logger) - logger: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/413f6f60b255f43adbf98cfdbdf2a8325cf3327a"><code>413f6f6</code></a> (logger) - logger: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/2ac6b101d2a205cce7653dcbf635cf1afea8e47e"><code>2ac6b10</code></a> (logger) - logger: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/2581426b262362e04fc4906cfb7d4567ca58d40a"><code>2581426</code></a> (logger) - logger: bump redis to v9</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/364b25aebe91236be41b5974b3643fc1a2b6d352"><code>364b25a</code></a> (logger) - logger: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/dc169a303663ce319037fcf19d0b6bd164b8ee82"><code>dc169a3</code></a> (logger) - logger: use fluentbit replace fluentd</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/d855d91ba3b4651d2a384f3919a39a84f6794b95"><code>d855d91</code></a> (logger) - logger: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/f76723507196a4814dc98e8d9c6403157b6273c4"><code>f767235</code></a> (monitor) - monitor: add off-cluster passport configure</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/ab23936f8d8610f88c061996217b28a8da0ffe3d"><code>ab23936</code></a> (monitor) - monitor: use dynamic clusterrole name</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/47beee0619ee974ad702d813e4db39b187a0507b"><code>47beee0</code></a> (monitor) - monitor: change tikv secret key</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/af7703f7a646a074adf89f9e1d7681bc2a4a8cfb"><code>af7703f</code></a> (monitor) - grafana: remove panel when component off-cluster</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/1b870c2a5b5212d9aeae8dd720bab8190a2b8002"><code>1b870c2</code></a> (monitor) - monitor: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/4a5f1f164c48e93271e28e5a252eb9c87ce4e293"><code>4a5f1f1</code></a> (monitor) - grafana: up ldap api_url config</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/143cabe692cd9d80f909afbe91de0bb8b3c18dea"><code>143cabe</code></a> (monitor) - monitor: add prometheus architecture diagram</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/93091c2dcde35d1ca63450ba08cd2e92b532cdda"><code>93091c2</code></a> (monitor) - woodpecker: use woodpecker ci build status</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/0b7045a1ec3d0061a8434e7e8beed47183287b2c"><code>0b7045a</code></a> (monitor) - grafana: add dashboard kubernetes_deployment_metrics</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/2fb1839f48277724e394b04697d1eb1fb748bf3e"><code>2fb1839</code></a> (monitor) - woodpecker: pipeline config VERSION, when build container image</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/e2724164a3e2855d1f62e4bdcdcff99f6b10e48f"><code>e272416</code></a> (monitor) - monitor: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/abc0e5373a0aef065fd8887e9f8bee5fd13a5e92"><code>abc0e53</code></a> (monitor) - monitor: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/86cc01bd318becf9528feffcfd7c6080c3faafa2"><code>86cc01b</code></a> (monitor) - monitor: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/1cd849ff6f8367375f6d80430e9fe623ebe0162d"><code>1cd849f</code></a> (monitor) - monitor: add postgresql outputs</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/c3205c04418bbb794286eca1bcaa2bf37f26437c"><code>c3205c0</code></a> (monitor) - monitor: change default agent config</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/8c802c01af85fbf40b42c124cd6c72a7c3d8266d"><code>8c802c0</code></a> (monitor) - monitor: add timeseries database</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/e9abc40801c5d90934d19b5ca1b838dbdf9b2431"><code>e9abc40</code></a> (monitor) - monitor: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/6af66cd45685080c5242f6bc6758df35e0c7a69f"><code>6af66cd</code></a> (monitor) - monitor: change drycc gateway listener name</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/d02d718b64837e2869aea66f8a9205d0d3205feb"><code>d02d718</code></a> (monitor) - monitor: remove gateway route</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/3509c2916b9b6aabe709b0057afdacbdc747e462"><code>3509c29</code></a> (monitor) - monitor: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/ed7bfa2f0c17b3e2577f168af719a6c9b3adc436"><code>ed7bfa2</code></a> (monitor) - monitor: optimize env PROMETHEUS_URL</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/da89befad4be1c66ae33740c7a2567b8b83b6b46"><code>da89bef</code></a> (passport) - passport: charts codereview</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/61c4a964022e28f81727efdc858e5ec3a07a71fb"><code>61c4a96</code></a> (passport) - passport: support init app config</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/91010068522d524dfd6680d09915a5444e29a1ba"><code>9101006</code></a> (passport) - passport: add initApplications to charts</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/7dd7fa414f07cc61771cec2d3e98cc1a32d38a00"><code>7dd7fa4</code></a> (passport) - passport: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/4400199ac576b00e0e268ca74d18ff1da15f32bc"><code>4400199</code></a> (passport) - woodpecker: use woodpecker ci build status</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/6b2c546ec6a5dd0311667cab1ac322819ea71918"><code>6b2c546</code></a> (passport) - passport: change secret name to drycc-passport-auto-tls</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/c8bd824c567bfc68df8fd118ad5a9805242507bd"><code>c8bd824</code></a> (passport) - passport: upgrade requirements</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/aee5aefe0c074816b6ba99624f0e2e5fb6462516"><code>aee5aef</code></a> (passport) - passport: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/2d819533a0d6e10534e5a82fac370dd67ef96fc2"><code>2d81953</code></a> (passport) - passport: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/9e662428f39d73651a0c70bd613595c7205c4494"><code>9e66242</code></a> (passport) - passport: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/0fca9982e2ff45bbb5ebe7e3e91fcf0a6af52d94"><code>0fca998</code></a> (passport) - passport: upgrade requirements</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/348252849763e5e96b5908293bd78d84b52b6ad0"><code>3482528</code></a> (passport) - passport: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/0c5ec939da419910c9e98ea97cee9d66916ba14f"><code>0c5ec93</code></a> (passport) - passport: change drycc gateway listener name</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/f7b8f5312d0e9707d2f41b14fb1113e2dfa63dc3"><code>f7b8f53</code></a> (passport) - passport: remove gateway route</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/baf69da9f8b9e1858fa89418e12f3133ab567d88"><code>baf69da</code></a> (passport) - passport: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/fcd45dd063da8338c812d5d8af9c41c6d4405826"><code>fcd45dd</code></a> (passport) - passport: add cluster migrate</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/da6d32a3f09d43209fd1037cb1cff810ddcdcf68"><code>da6d32a</code></a> (prometheus) - prometheus: add prometheus-config</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/683de9e2c03941152196e4fb986cb9ce8e7c1a0f"><code>683de9e</code></a> (prometheus) - prometheus: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/3323300fa23d53bc09e3e70041f4a300aaace68b"><code>3323300</code></a> (prometheus) - prometheus: remove gateway route</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/da1d356e3f978a01fcbbd6b5996ff9272748ed87"><code>da1d356</code></a> (prometheus) - prometheus: change drycc gateway listener name</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/4e7a936edaf8446d48b80e69afd610af6d59a6a4"><code>4e7a936</code></a> (prometheus) - prometheus: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/44c1c6f6a3a11cd1792753c7ba94faf6675e8fa3"><code>44c1c6f</code></a> (prometheus) - prometheus: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/d1f1dda09da1cd0b82dd18854e196b206e27e931"><code>d1f1dda</code></a> (prometheus) - prometheus: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/0836fc1cea544fd928fb6727c99ca9369a1c2134"><code>0836fc1</code></a> (prometheus) - prometheus: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/prometheus/git/trees/9e132322c6c36fde1a6ce4f8fabce6ffdb73cb32"><code>9e13232</code></a> (prometheus) - prometheus: add LICENSE</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/f53e14a9e741122cef2a88976a4ccafc6ad6f6fd"><code>f53e14a</code></a> (rabbitmq) - rabbitmq: remove auto user</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/0ec7277c5624b35ea1ac9d5d88a9eddb75278794"><code>0ec7277</code></a> (rabbitmq) - rabbitmq: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/f376a30bdb6223f03b7d3e40eb3093616830291b"><code>f376a30</code></a> (rabbitmq) - woodpecker: use woodpecker ci build status</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/51405d8f429584fcf5d38a7b1422971304f3981c"><code>51405d8</code></a> (rabbitmq) - rabbitmq: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/463ca03544a31a0a6c98ceb4862e9cd15a47271b"><code>463ca03</code></a> (rabbitmq) - rabbitmq: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/1978a714c0f868de9d4dfc863be003c313d3db6f"><code>1978a71</code></a> (rabbitmq) - rabbitmq: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/139277f11035e0e548bfdc35272579806cd8bb0c"><code>139277f</code></a> (rabbitmq) - rabbitmq: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/be49741721134fd966c09ea44ef87b705668c8a2"><code>be49741</code></a> (rabbitmq) - rabbitmq: change drycc gateway listener name</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/6d22518f5bbb3883bc4bdc05b6c93ea6b40e3be9"><code>6d22518</code></a> (rabbitmq) - rabbitmq: remove gateway route</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/0eb7833ac8a01bbde78f3e0172e6d3d2948d6234"><code>0eb7833</code></a> (rabbitmq) - rabbitmq: add check shards</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/921106312dc679e79c8dc8ce226ae62fa68ce0ec"><code>9211063</code></a> (rabbitmq) - rabbitmq: erlang vm tuning optimization</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/648a78d9b886890e924250a198624972d28a2ad8"><code>648a78d</code></a> (rabbitmq) - rabbitmq: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/0b43a4d04556eb2bfa81cc8ed22d84d636ad45d1"><code>0b43a4d</code></a> (rabbitmq) - rabbitmq: add x-random exchange</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/ad1c4da3f11a1e690508c71a992a3bda86b56201"><code>ad1c4da</code></a> (redis) - redis: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/3f37f92a06db4b06c105718bec48aeaac2bf1a31"><code>3f37f92</code></a> (redis) - redis: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/e3bef7a15e73fb77ba76ac4f0140fa03ebd2a813"><code>e3bef7a</code></a> (redis) - redis: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/4e806d40f4a203db5c91dd184a712fba8ce55820"><code>4e806d4</code></a> (redis) - redis: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/d5023be85937f1f4cf4b625fb8250a63c4776f3b"><code>d5023be</code></a> (redis) - redis: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/98f5d6fa30d4fb28c89eb547a0e2631aa34a46ac"><code>98f5d6f</code></a> (redis) - redis: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/063f29e85bc565c29d19b900b96017161263cb88"><code>063f29e</code></a> (registry) - registry: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/17bf8ae8cc1a257ff978a6a8ee27d8988f3ed9c2"><code>17bf8ae</code></a> (registry) - woodpecker: use woodpecker ci build status</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/7bbad151b1d5c934f9d81a882ea6ebef16bf1723"><code>7bbad15</code></a> (registry) - registry: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/279154fdec97b5e0d28a5c27481928d433ac1369"><code>279154f</code></a> (registry) - registry: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/3e4ae840d5718521278051122c19b96b9dbf2791"><code>3e4ae84</code></a> (registry) - registry: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/fa322d6c372fd6d622a2054584bbcab934ff67f0"><code>fa322d6</code></a> (registry) - registry: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/6c18fe004f3431a59ecd5c874c3bd77af544c661"><code>6c18fe0</code></a> (registry) - registry: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/0bc8472a7baa4b8f982694b97528fa984c03639d"><code>0bc8472</code></a> (registry) - registry: remove health url</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/5dacd9f735816decc4b6af7c4994a75ce280d92b"><code>5dacd9f</code></a> (registry) - registry: add wait-for-port check</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/fdeefc3888d5ec0dbfff8db6c797621a90896531"><code>fdeefc3</code></a> (registry) - registry: use headless</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/08bf9f882de2d94f8c3bdefafe24fafa9b9870c4"><code>08bf9f8</code></a> (registry) - registry: change registry port to 5000</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/40bcea2ddf3a6e6316422e14a25df360fb4dcf81"><code>40bcea2</code></a> (registry) - registry: add registry push test</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/871b8e72735b0c17f4c692ea53495e1abb4497d1"><code>871b8e7</code></a> (registry) - registry: add default env</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/7f3b3aceea1cc28475f9cec0a3244f693eaf1e6a"><code>7f3b3ac</code></a> (registry) - registry: bump registry 2.8.3</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/569f15dca6d21c69f3ad3734e6509addf2caf913"><code>569f15d</code></a> (registry-proxy) - registry-proxy: use woodpecker replace drone</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/cc33caf06d9aa2c4bec7a745aa233f8827695972"><code>cc33caf</code></a> (registry-proxy) - woodpecker: use woodpecker ci build status</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/0002aab36b2692250f8653db3505a0300275bea3"><code>0002aab</code></a> (registry-proxy) - registry-proxy: add chart appVersion</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/40af10ba90e5e0e6e050f5d97625a1294ab6f910"><code>40af10b</code></a> (registry-proxy) - registry-proxy: upgrade codename to bookworm</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/c56b9dff701130403d9d0ecc932069fa16d2e462"><code>c56b9df</code></a> (registry-proxy) - registry-proxy: add codename build-arg</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/9d5bfe091bddf0f6d7d0cd8995823540b084dc77"><code>9d5bfe0</code></a> (registry-proxy) - registry-proxy: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/e6a33500e5eba9a32baa3f2e9841e67546236965"><code>e6a3350</code></a> (registry-proxy) - registry-proxy: change worker_processes to 1</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/726f39d51f196a28effb917fbacb20db960cf5f3"><code>726f39d</code></a> (storage) - storage: add volume compactionMBps</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/a5aa2d87bd4d320e30833cbe3e3598f5199e7da5"><code>a5aa2d8</code></a> (storage) - storage: add threshold to vacuum and reclaim spaces</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/e687d044f2796dbfef23239df62337b2e658b797"><code>e687d04</code></a> (storage) - storage: delete disk type in single disk case</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/75ee2e4f4acfa1c4fd8f725252ffdc8a30495dda"><code>75ee2e4</code></a> (storage) - storage: change datanode replicas to 4</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/c5fd7bad70e239cd389fc92372305435e099d4ce"><code>c5fd7ba</code></a> (storage) - storage: delete useless env</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/b3826ea800b1fbde96178f590d25361560f3bc3a"><code>b3826ea</code></a> (storage) - storage: add ssd hdd dir</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/29881a0702b1e68e69c86e6ae96da8c4eda209a4"><code>29881a0</code></a> (storage) - storage: add balance cronjob</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/c5a0f512283eb2c32814f3b2f3c0e3ebfb57bd1f"><code>c5a0f51</code></a> (storage) - storage: add defaultReplication for seaweedfs master</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/543c7a273c2988d477782ba97462263c93068669"><code>543c7a2</code></a> (timeseries) - timeseries: use podman replace docker</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/5376024ea1489cf311fd18dd691ab5b80eb4e5e8"><code>5376024</code></a> (timeseries) - timeseries: update timeseries-service-replica</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/52e8520d0e2bb6b0625304a8e29d3b680bc44840"><code>52e8520</code></a> (timeseries) - timeseries: bump common 1.1.2</li> +<li><a href="https://api.github.com/repos/drycc/timeseries/git/trees/f82657ceb0cdf390fb07e721ce57e07081d43968"><code>f82657c</code></a> (timeseries) - timeseries: add start script</li> +</ul> + + + + + + Blog: Drycc Workflow v1.6.0 + /blog/2022/10/21/drycc-workflow-v1.6.0/ + Fri, 21 Oct 2022 00:00:00 +0000 + + /blog/2022/10/21/drycc-workflow-v1.6.0/ + + + + <p>These release notes for Drycc Workflow v1.6.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.5.0, please refer to the following change summary.</p> +<h2 id="workflow--v150---v160">Workflow ## v1.5.0 -&gt; v1.6.0<a class="td-heading-self-link" href="#workflow--v150---v160" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>builder v1.3.0 -&gt; v1.4.0</li> +<li>controller v1.4.0 -&gt; v1.5.0</li> +<li>passport v1.0.0 -&gt; v1.1.0</li> +<li>database v1.1.0 -&gt; v1.2.0</li> +<li>imagebuilder v1.0.1 -&gt; v1.1.0</li> +<li>fluentd v1.2.0 -&gt; v1.3.0</li> +<li>logger v1.2.0 -&gt; v1.3.0</li> +<li>storage v1.2.0 -&gt; v1.3.0</li> +<li>monitor v1.2.0 -&gt; v1.3.0</li> +<li>redis v1.2.0 -&gt; v1.3.0</li> +<li>influxdb v1.1.0 -&gt; v1.2.0</li> +<li>rabbitmq v1.0.0 -&gt; v1.1.0</li> +<li>registry v1.1.0 -&gt; v1.2.0</li> +<li>registry-proxy v1.1.0 -&gt; v1.2.0</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/52517d9323bfcd246e1fd8e13bdee2c45739136a"><code>52517d9</code></a> (builder) - builder: update controller-sdk-go</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/1d78ca01de03c80ac86687999d82dba0077df31a"><code>1d78ca0</code></a> (builder) - builder: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/26b69801c78321da8754c814b6503ec76e857a1b"><code>26b6980</code></a> (builder) - builder: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/bfd43851009116d6d4bceb4c46edc3cd21cf9d41"><code>bfd4385</code></a> (controller) - controller: add get manager user status</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/874208d8501198ed8780f2e820ab112d3b78eae2"><code>874208d</code></a> (controller) - controller: unified measurement model</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/cadf98f888c384890c529700c16208b17e17dff2"><code>cadf98f</code></a> (controller) - controller: add admission webhook</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e0050c23869dd3a1d5e8038859a7324484b227b2"><code>e0050c2</code></a> (controller) - controller: new measurement model</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a11ba587b73058c3af610fc9fc101e5d446eb43f"><code>a11ba58</code></a> (controller) - controller: multi pod restart uses async</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/fb3c15d70041d4b215c34b5625cb82ae52279d2b"><code>fb3c15d</code></a> (controller) - controller: add check app owner status</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3d78b764c874c30f23aa7e6db9a0d03cb09b6a24"><code>3d78b76</code></a> (controller) - controller: add resource services api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3d6a2012ab840dcde1be3c8f197df76eac9c5d88"><code>3d6a201</code></a> (controller) - controller: add search apps api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/01c443a3bf142d6497d20492e3ee7f534db64322"><code>01c443a</code></a> (controller) - controller: add KUBERNETES_CPU_MEMORY_RATIO parameter</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7c2623276991b46b7ac2b8e9d8ce2f84e8ebf26b"><code>7c26232</code></a> (controller) - controller: add volume size limit</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3bee749fc0c670d3ee371c7ffb031f47f0d45873"><code>3bee749</code></a> (controller) - controller: add annotations support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/23cd97c1f213ea9dcec45a4a40e9c3942904e55a"><code>23cd97c</code></a> (controller) - controller: traefik v2 support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e37b7db45049776d7d7455e01f5928986b24b043"><code>e37b7db</code></a> (controller) - controller: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b3b367b108bea56a5fa5ccc603f0dafc14bb5edb"><code>b3b367b</code></a> (controller) - controller: add volume expand support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a4e154aaf0f6cd3b01ebbab0a4af1a4b693a45a4"><code>a4e154a</code></a> (controller) - controller: add database replica support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/2f37216fbaed5fa707c76b44881b1f7507a75f49"><code>2f37216</code></a> (controller) - controller: switch wsgi to asgi</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b3314a50607e9d5383d0ce954811827acae8fa05"><code>b3314a5</code></a> (controller) - controller: add pod exec api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/75df2dce65591da4e1e56c7f56a1903749fa4e20"><code>75df2dc</code></a> (controller) - controller: add stream support for app logs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4229badbcd4e367cbe13bf13f2b5c62271b7b31e"><code>4229bad</code></a> (controller) - ccontroller: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/89bb19b20f2eb0d8918cdc7223fa3b117af620d5"><code>89bb19b</code></a> (database) - database: upgrade to pg14</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/9f45a5d5e9b7871c47acd73ce227856c1683f6a2"><code>9f45a5d</code></a> (database) - database: add hugepages support</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/c4008c9fbe0f99d1200a58466a15466d92840fa5"><code>c4008c9</code></a> (database) - database: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/411a7b269a3333caed809a1afac69578a7c5ad9b"><code>411a7b2</code></a> (database) - postgres: use patroni</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/64e5cb0aaaacfa2d9976e278583fa700c858ce92"><code>64e5cb0</code></a> (database) - database: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/2bab823194abea35c7a1ff4d59db6a88eb19fcad"><code>2bab823</code></a> (fluentd) - fluentd: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/337ba62d587a4f6c7321aa6ef843d5764692a09e"><code>337ba62</code></a> (imagebuilder) - imagebuilder: run podman as rootless</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/4396ffaeb6a2751e6f78907ac7c517966b5e3c08"><code>4396ffa</code></a> (imagebuilder) - imagebuilder: switch to oci charts</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/f37ae0927023685d88f9e594d8316d8c40cd5296"><code>f37ae09</code></a> (influxdb) - influxdb: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/04503b2c0d5c455c1a106c71be727d2b2b14a2f8"><code>04503b2</code></a> (influxdb) - influxdb: add influxdb ha</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/41ddad5e9acb54fa5bb2c35559615d1cc4fd3af5"><code>41ddad5</code></a> (influxdb) - influxdb: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/2006480f82ab4291efa75a69cad0080a29872110"><code>2006480</code></a> (logger) - logger: use redis stream replace nsqd</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/ab23d17f378ea1b740fb4c43dc06f4853d5c729f"><code>ab23d17</code></a> (logger) - logger: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/81d4e9dcde820ab8dc1df6fb99f82fdf39eb35ea"><code>81d4e9d</code></a> (logger) - logger: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/c3d9796e21c344d660bfd036d6154c28a3051995"><code>c3d9796</code></a> (monitor) - monitor: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/cd9de3c70c33236975b1d2547b75a66649fba93d"><code>cd9de3c</code></a> (monitor) - monitor: switch to oci charts</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/318a73f7f03c01faa23ce3a89b4b52d5cae4279d"><code>318a73f</code></a> (passport) - passport: add change user confirm</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/79ef1004687152d93a5e60058fd4f40a6273b55a"><code>79ef100</code></a> (passport) - passport: add re login at authorize</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/6927bb5884a7ee332a64afabfd6439467d7fee3c"><code>6927bb5</code></a> (passport) - passport: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/3146a0981b744962d68a75fab65e074ab61d4b1c"><code>3146a09</code></a> (passport) - passport: add google reCAPTCHA</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/802abcdd5f0768d75b4fc9f08f46c4b2a590be29"><code>802abcd</code></a> (passport) - passport: add replica database support</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/a0dcd1b7b2bdd3ba247d50fdf554a2918b065588"><code>a0dcd1b</code></a> (passport) - passport: switch wsgi to asgi</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/4c9dbba2b1e79cf9860e19529bd99f52f5588328"><code>4c9dbba</code></a> (passport) - passport: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/74825f7827e22b75938cbcc5bf81ad1a40c4ab37"><code>74825f7</code></a> (rabbitmq) - rabbitmq: add rabbitmq managentment ingress</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/12cf7d60e4e89e3396e786f4487cca55f1322887"><code>12cf7d6</code></a> (rabbitmq) - rabbitmq: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/103417de373246b4f1e0b9cdaf2eaae6ba704dea"><code>103417d</code></a> (rabbitmq) - rabbitmq: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/5d428bbd55c0ec12f6fcafe312b2cd3768fb51d1"><code>5d428bb</code></a> (redis) - redis: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/a88c1a9625757b901515682f39d40a7f5b877f95"><code>a88c1a9</code></a> (redis) - redis: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/541585d4060d6006b99fd3649718566a6ea3163b"><code>541585d</code></a> (registry) - registry: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/e9ca9d475dade575ae13c3b288148b8094faf3f6"><code>e9ca9d4</code></a> (registry) - registry: add garbage-collect cronjob</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/ec62a5969747738252132510923637c1b63b63d8"><code>ec62a59</code></a> (registry) - registry: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/fde0b07f243deabc0818efc4088583c6ca6aa5b8"><code>fde0b07</code></a> (registry-proxy) - registry-proxy: switch charts to oci</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/be14eb42fcda99f9160d21f437858e89337543a2"><code>be14eb4</code></a> (storage) - minio: add affinity</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/51af6966183c496c9c1374cf4c4fa9b66f319a44"><code>51af696</code></a> (storage) - storage: add k8s csi support</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/76a75d922b965b8961f872b62c67569924e0cf49"><code>76a75d9</code></a> (storage) - storage: add cluster health checker</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/a17dc8cc37c2c2d96acdbcc08a6c2e52676cb777"><code>a17dc8c</code></a> (storage) - storage: switch charts to oci</li> +</ul> +<h4 id="fixes">Fixes<a class="td-heading-self-link" href="#fixes" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/e4f44fba4f4a71812b0a1b0d42668d8a6f3bbc65"><code>e4f44fb</code></a> (builder) - builder: no error return</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/e38dfc71c5dfa0edafc5603f274235048a3992d7"><code>e38dfc7</code></a> (builder) - builderControllerHost/ControllerPort init error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ff9069fee85633db4801a43d4fa70292099c94dc"><code>ff9069f</code></a> (controller) - controller: influxdb query error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f7f5069569e3f7325fc8fa5f90f8c19e95c0c6ce"><code>f7f5069</code></a> (controller) - controller: authentication 500</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7e297a8996c9fbf490fcbce364c0b4172bdc6388"><code>7e297a8</code></a> (controller) - controller: add check remote user status</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9db28e1ea4627f8f63dcc6f83db2962dc5b47451"><code>9db28e1</code></a> (controller) - controller: celery MaxRetriesExceededError</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4bcff08d38a01a4d7267fef00650395275e3203b"><code>4bcff08</code></a> (controller) - controller: wrong name</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d69fde2efc71b015ae2894fcc3efa0cf369457e5"><code>d69fde2</code></a> (controller) - controller: traefik ingress create error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a3ad743c2ecd0528c5c69915272dc68a90fd841a"><code>a3ad743</code></a> (controller) - fixup(controller: user login error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/662c8ddfbcb03d19f5ced769de21964ff5ed413e"><code>662c8dd</code></a> (controller) - controller: change influxdb port</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/957bdf67128b45abad43e8ee560fb6cb749b0783"><code>957bdf6</code></a> (controller) - controller: validate rsa key pairing before storage</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/419ec4c4de6ad77c9cc3f551260fdc35504ceb15"><code>419ec4c</code></a> (controller) - controller: kubernetes pod/exec cluster role</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a67edaae26c00a7ce806bde95b73041ec1c84734"><code>a67edaa</code></a> (controller) - controller: Cannot routing:disable</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e09e2144f1906b19d9b00f0883effe3491198ebf"><code>e09e214</code></a> (controller) - controller: allowlist cannot remove</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/318b1267f35bcf158fc21b20f8e367a3e23fa454"><code>318b126</code></a> (controller) - controller: domains update error</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/92855ebc7df34fb8cc5ea440db4f821681ae2408"><code>92855eb</code></a> (database) - database: premission denied</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/bde945ab972d9085009b291c0faac55d8942b014"><code>bde945a</code></a> (database) - fixup(postgres: support arm, fix Failed to build psutil</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/7854d45a2164a1db8ee37bc3ce39c8515bacae30"><code>7854d45</code></a> (database) - fixup(postgres: user name converted to lowercase letters</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/57b2a0708d5ab8fff913e97be09f132074d1ff56"><code>57b2a07</code></a> (fluentd) - fluentd: ifconfig_path not found</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/20e72b962a415773fd97919832c7a0bde9c55a28"><code>20e72b9</code></a> (imagebuilder) - imagebuilder: upgrade pack version</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/651db8a1d2f40f0fafb88f2da4b6fd20ee920715"><code>651db8a</code></a> (imagebuilder) - imagebuilder: chown uid gid order</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/d2e9164afe61fac362beb65ee9113453c2ecd970"><code>d2e9164</code></a> (influxdb) - influxdb: proxy not running</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/3a1d3618d881880abcd752c9c9184a570b38442e"><code>3a1d361</code></a> (monitor) - monitor: charts naming</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/d754ae0244e6e1e300062db24c8e4477b7522715"><code>d754ae0</code></a> (monitor) - monitor: telegraf init error</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/63f9e346a4ded75b7b4f8f0c6708bbe725ee6160"><code>63f9e34</code></a> (monitor) - monitor: affinity error</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/95ae1e5f51e528b75ccae36ad86e9abfbff52050"><code>95ae1e5</code></a> (passport) - passport: yarn build fail</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/3f5365e8e5be0b2a486651e87fb5b82fe4668bbc"><code>3f5365e</code></a> (passport) - passport: wrong name</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/907f17b95c1114a802781f2bbec3ba046464f1a8"><code>907f17b</code></a> (passport) - passport: change uid gid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/e3911e0f5e9174ab8e7542f60b8bd0c3ff7f85f6"><code>e3911e0</code></a> (passport) - passport: &lsquo;registration_done&rsquo; not found</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/2ace5f0a2a363d959a381bd3f759b4990bc13953"><code>2ace5f0</code></a> (passport) - passport: ui style</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/b3ba1e1545f07ee2322850ee6cfb6915ee26967d"><code>b3ba1e1</code></a> (passport) - passport privacy policy link</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/172e9c8b680a83d6c437292febf0418d35c99aa9"><code>172e9c8</code></a> (passport) - passport: check databaseReplicaUrl error</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/a3aeb7052d4ebdbc7bd020850f94921c253a8a38"><code>a3aeb70</code></a> (rabbitmq) - passport: change uid gid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/5c73dcf6a8692e83abd40f1d5e991714b3c51876"><code>5c73dcf</code></a> (redis) - reids: DRYCC_REGISTY misspelling</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/d7e3baf4600d87e4d4af2b3e581cb62c591a25b6"><code>d7e3baf</code></a> (redis) - redis: env miss</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/cadaa9151519a4efb52d5c5f779cc0aff0f8fe1e"><code>cadaa91</code></a> (registry) - registry: set gid uid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/d524217dccfc6dd80c86547d5f2f875b15a8054d"><code>d524217</code></a> (registry) - registry: storage run error</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/854f912bf746ac69d0117378888c1fe8334dd7fb"><code>854f912</code></a> (registry) - registry: chown uid gid order</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/e642bb7452fb62bbc7ce6f1b852e029b88a71488"><code>e642bb7</code></a> (registry-proxy) - registry-proxy: containerPort error</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/8dfd029b78d2dcd1b6bf31960d35234deb6bfc5b"><code>8dfd029</code></a> (registry-proxy) - registry-proxy: chown uid gid order</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/bbea3642114ac83e3c9cb56e7131146378bbf213"><code>bbea364</code></a> (storage) - minio: premission denied</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/97deba16553dd6dc8d2625d8747825692e8667bb"><code>97deba1</code></a> (storage) - storage: node unimplemented error</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/b9bdeff3ef47f43ec12dd16194297d63298fbd34"><code>b9bdeff</code></a> (storage) - storage: pd can not connect each other</li> +</ul> +<h4 id="style">Style<a class="td-heading-self-link" href="#style" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1edb10c23e5ae5654e6a7daf08b7a74fe9c86b74"><code>1edb10c</code></a> (controller) - controller: database convention over configuration</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/1960cc3367aa6b0e8f0db5f0117a271c884356a0"><code>1960cc3</code></a> (database) - database: database name convention over configuration</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/06d1f5dd3b7ff353ae26615695732f54dd09e5c7"><code>06d1f5d</code></a> (imagebuilder) - imagebuilder: URL to Url</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/b8a89412e7794fe9e16689d4e8902d34f68a6ce1"><code>b8a8941</code></a> (passport) - passport: database convention over configuration</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/8e9a199ac90382e67f64c757d9d207e7aa106c86"><code>8e9a199</code></a> (builder) - builder: upgrade controller-sdk-go</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/48401512b2eee6a608efe45c962809a4a388ed9a"><code>4840151</code></a> (builder) - builder: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/68ccfb12da3fdc35519b23fdb8212f7de377f8b5"><code>68ccfb1</code></a> (builder) - builder: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/8f971cbd509062f952e0b0fe2fdc9983891077ad"><code>8f971cb</code></a> (builder) - builder: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/fe2c55d0e5264818e482fcd71510d9a616689c79"><code>fe2c55d</code></a> (builder) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/2b5e70609f11eff1eb1e1d8a5591644799fa8982"><code>2b5e706</code></a> (builder) - dockerfile: change user and workdir</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/7a6c8d319bcc67e1cbe5a733de773860aa859765"><code>7a6c8d3</code></a> (builder) - builder: set gid uid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/fe494f75669f9e3a51ff32e330edb8c5a33efed7"><code>fe494f7</code></a> (builder) - dockerfile: use uid gid</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/a7c87525709c6903e4fb254740eac710c3e18385"><code>a7c8752</code></a> (builder) - builder: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/eb2e94c2ab4358e74a74c8d198eb6798e9bdeae7"><code>eb2e94c</code></a> (builder) - database: bump mc 2022.04.01.23.44.48</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/cfaae66aa31b4b7b28c7d4577e9bf9c7f17a6716"><code>cfaae66</code></a> (builder) - builder: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/d7d289060ddafcc94855bb46dc4fbc24cf1c3527"><code>d7d2890</code></a> (builder) - builder: change default imagebuilder registry</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/ecfdb19270198fc3f2b46cc0dc91151bd3ebf114"><code>ecfdb19</code></a> (builder) - imagebuilder: change python-dev registry</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/6da17f489543950af850ee3d5bb4e1cfbcc5cac1"><code>6da17f4</code></a> (builder) - builder: <a href="https://github.com/minio/minio/issues/14331">https://github.com/minio/minio/issues/14331</a></li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/1a57e5bd5e467b859e0d69e6b3775454132cb225"><code>1a57e5b</code></a> (builder) - builder: <a href="https://github.com/minio/minio/issues/14331">https://github.com/minio/minio/issues/14331</a></li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/f1464fa6065483d23b98f01a847b73e951f896ae"><code>f1464fa</code></a> (builder) - builder: <a href="https://github.com/minio/minio/issues/13799">https://github.com/minio/minio/issues/13799</a></li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/b1e1c4f5920ba82235a253f9980960ef9dca527d"><code>b1e1c4f</code></a> (builder) - builder: use env replace creds volume</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/71a41453660c6d731247a10e00f94121ae3a69a5"><code>71a4145</code></a> (builder) - builder: bump go.mod</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/3567688f8809e3805e47170d4b3109a31b1f883f"><code>3567688</code></a> (builder) - builder: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/73ea38b11c631415aa02c5ee43ff92ecfe48348d"><code>73ea38b</code></a> (builder) - builder: change storage to minio</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/1f913215ba18670fe83891bf84317b72985151dc"><code>1f91321</code></a> (builder) - builder: use testify replace assert</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/d148b9c998759b886ea5493d0e2aa94518d39dcb"><code>d148b9c</code></a> (builder) - builder: add check storage health</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/b768101f69233fa792f3240be47b71b24881e90c"><code>b768101</code></a> (builder) - builder: change initContainers</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/1b3bec3ea2783c5124f372c2874c3691b71489cd"><code>1b3bec3</code></a> (builder) - builder: add replicas</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/5cb0d618ff5bb1136501f4ba6359e5e5c46a7a63"><code>5cb0d61</code></a> (builder) - builder: upgrade to latest controller-sdk-go</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/98b9d581209eacabdb9e28c5eb6a7975f13bd454"><code>98b9d58</code></a> (builder) - builder: upgrade new require</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/65817c3e519df8368cd4427f5d366f9edde1fbd5"><code>65817c3</code></a> (builder) - builder: change drycc.cc to <a href="https://www.drycc.cc">www.drycc.cc</a></li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4e3f9d05bb8d00023e6f1927785b7c27d4801652"><code>4e3f9d0</code></a> (controller) - controller: add celery retry mechanism</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f6716fee7625ad8f0cad2b1cf5ad746beb847a65"><code>f6716fe</code></a> (controller) - controller: change cronjob name</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/eb606938533da2673ed2aa2986bcb0cdd2c9ee2c"><code>eb60693</code></a> (controller) - controller: refine celery task priority</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/66905e95bb3c9f71fb4c75038199d54c6b5a0edc"><code>66905e9</code></a> (controller) - controller: change manager auth</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ea20c415af0ee4e70f32873748cd979bd36f8240"><code>ea20c41</code></a> (controller) - controller: remove start/stop api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4c8fc807f950064d2cc98ebdd6a51ec86eabb20f"><code>4c8fc80</code></a> (controller) - controller: improve tasks error handling</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/cf7402eaff8373c956e6c0ffa1c7ff479cade8e2"><code>cf7402e</code></a> (controller) - controller: add blocklist api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/80f14dd5b8852c235e3de496261b416c8b59a043"><code>80f14dd</code></a> (controller) - controller: use get_user_model replace auth.User</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ffc7bb790f2257f5e5f9902400f78524d1f528e3"><code>ffc7bb7</code></a> (controller) - controller: use JSONField replace ArrayField</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/370df8c9d011e25785a06e5a4a737dcdb622f4f5"><code>370df8c</code></a> (controller) - controller: add validate metric</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/29084ce759bddd671de4441c6f8e6889774e4c80"><code>29084ce</code></a> (controller) - controller: use user id request manager api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/718fe123eafe5136ac08635c8cf1dbca3dcad4ab"><code>718fe12</code></a> (controller) - controller change urlpatterns order</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/71f40426a65bc6cdc90e6185b1487ae30a3c73de"><code>71f4042</code></a> (controller) - controller: measurements uses lowercase letters</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e5123ea55ae516d94b0cb54ec6ffb464c050ce87"><code>e5123ea</code></a> (controller) - controller: change resource unit to number</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/18fee9aeb1114ea8dbcc4d8eacea93148206e002"><code>18fee9a</code></a> (controller) - deps: bump celery from 5.1.2 to 5.2.2 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ffca6c11c67012e13540e06c12cf30dea5e5cde7"><code>ffca6c1</code></a> (controller) - controller: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9ec12e1ff7bcfb3b72953313484d3f605d97c73b"><code>9ec12e1</code></a> (controller) - controller: simplify drone configuration</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4b4749e2fd391a492fbf40fb7ee25c7b61b52f26"><code>4b4749e</code></a> (controller) - controller: set default CSRF_COOKIE_SECURE false</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/2ef6338c20c8625b2cc76c6021149bc07141fcd0"><code>2ef6338</code></a> (controller) - deps: bump django from 3.2.5 to 3.2.10 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c7570d0a40f7daa04de0a4fe1ecbb001e436ee41"><code>c7570d0</code></a> (controller) - deps: bump django from 3.2.10 to 3.2.11 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8b17bc16624fd9caddbbc462cc3487d3500a5216"><code>8b17bc1</code></a> (controller) - controller: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c928fb09f88ce210df7b495b80a005146320e2bf"><code>c928fb0</code></a> (controller) - controller: use rabbitmq cluster</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f9171852a8530c9bd385576517d24172917a1b33"><code>f917185</code></a> (controller) - controller: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/22a8f634a3574553132ecd53e8be467d84a255e9"><code>22a8f63</code></a> (controller) - deps: bump django from 3.2.11 to 3.2.12 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3cc3b00a705b9c7b0ff5d36fb2c0ab4139113dd9"><code>3cc3b00</code></a> (controller) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ee274f6d6728b3b9b3fd91b344be3f8a0d3f737f"><code>ee274f6</code></a> (controller) - controller: set venv profile</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ce6b069644ed3952a47bdd1bd728a395a9f1af05"><code>ce6b069</code></a> (controller) - controller: set gid uid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3a105d3628e40e2f53dfd2badeb7221555207227"><code>3a105d3</code></a> (controller) - dockerfile: use uid gid</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/15f9b0ea96630a818ec191dac15497a5dc99cadc"><code>15f9b0e</code></a> (controller) - controller: code review</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/01e6fd9ef5d730749a33986ff9d58dd854f50cb5"><code>01e6fd9</code></a> (controller) - controller: use passport user id</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/893ee31a1de6036136d0b813d5ff6575267e640a"><code>893ee31</code></a> (controller) - oauth2: update user info pipline</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3028fb470f23d858a5e36312e419dcdfbcc00be0"><code>3028fb4</code></a> (controller) - user: set AnonymousUser username</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5daf82d3bd17f2c653d2db52fb79d2a895ed1335"><code>5daf82d</code></a> (controller) - controller: set worker_cancel_long_running_tasks_on_connection_loss</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/61f2c53a7841099e33c8d5f8d25de311392ce317"><code>61f2c53</code></a> (controller) - controller: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/88feb1df0f3508c29a47ea291f225207a8a4c754"><code>88feb1d</code></a> (controller) - imagebuilder: python=3.10.4 rabbitmq=3.9.14</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/914e03fb8d6d6bff7ef9b5f91b0a3eeedac2ebeb"><code>914e03f</code></a> (controller) - controller: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a5bb548ee73cd201cafe797fdba4fe89e4bbb377"><code>a5bb548</code></a> (controller) - controller: change python-dev registry</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3ecdd7c05b7cddd640ffe92012b777a80cae1eec"><code>3ecdd7c</code></a> (controller) - controller: add a separate rabbitmqUrl configuration</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/967cb116bdbbf040c3c3c15579bb2d334666d3e8"><code>967cb11</code></a> (controller) - controller: remove APP_STORAGE</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/473d2b5f08c205240b5e081fcb9256d7ecd4cd45"><code>473d2b5</code></a> (controller) - controller: use env replace creds volume</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e410d4cba17662bad797fbd7288052b81e50df29"><code>e410d4c</code></a> (controller) - deps: bump django from 3.2.12 to 3.2.13 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c6ef777035d5e955984f9f4c84fac465943d8b74"><code>c6ef777</code></a> (controller) - controller: simplified passport config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0fd3233f1471b32c621149ac4ca5b5527741fda8"><code>0fd3233</code></a> (controller) - controller: remove settings hardcode</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a64e99cf099eba92c6df749c3c89f4245488b3e4"><code>a64e99c</code></a> (controller) - controller: change passport config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/62aba2594f1240c4368d95c61d75fa08343d05fb"><code>62aba25</code></a> (controller) - controller: set cronjob timezone to utc</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/760b70b635d6eecedfd3d40991740b13e587c1c5"><code>760b70b</code></a> (controller) - controller: change default ratio</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8dffc3afbce3871dc82fe4ce94c92b1fbbacc9b6"><code>8dffc3a</code></a> (controller) - controller: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/26043c40c89cb162b3ce322eba6a79f81a6b24cf"><code>26043c4</code></a> (controller) - controller: change default app storage</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/608bd8da7a7cb75d8fadfa965bcd9ea32e4a96ef"><code>608bd8d</code></a> (controller) - deps: bump django from 3.2.13 to 3.2.14 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/18ed0c2a656497108f98c5c8dbd3b27253dd7915"><code>18ed0c2</code></a> (controller) - controller: remove conjob affinity</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/add671288d5f4af68735a69771f024e4ed856196"><code>add6712</code></a> (controller) - controller: add volume expand support use patch</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/cc1ad1322ba638aa7f6acf45823047712a85e86f"><code>cc1ad13</code></a> (controller) - controller: add startupProbe</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0e9a6033b1a2b66f937010601df70e5625674a66"><code>0e9a603</code></a> (controller) - controller: add clearsocial cronjob</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/eb6f05d969102c008051ebd4c7e39a1300ed1b25"><code>eb6f05d</code></a> (controller) - controller: change initContainers</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/762c6767947b6407a7fb23ffbcb07dc46154b222"><code>762c676</code></a> (controller) - controller: change replicas</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/abd7e8c2210eb1f71c1d280383794af5fa786c98"><code>abd7e8c</code></a> (controller) - deps: bump django from 3.2.14 to 3.2.15 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/07fdf1b9938d868ef55c1d2067258a1eb6c59d23"><code>07fdf1b</code></a> (controller) - controller: remove database conn_max_age</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ef8e41f523aa0159831c95623b96fa74b3570d0c"><code>ef8e41f</code></a> (controller) - controller: add database replica check</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/79143f2301bfc52f8181fc0e0f07263645e065d8"><code>79143f2</code></a> (controller) - controller: upgrade new require</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a62404890973cb26c9360878e7625e15eb87d281"><code>a624048</code></a> (controller) - controller: add app.refresh func annotation</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b22d367d54aa2ab131c8e69491e084dc283826a4"><code>b22d367</code></a> (controller) - controller: optimize app refresh timing</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/fe98f0c8f3d2cfebc2b6ad13927627ebee96e39e"><code>fe98f0c</code></a> (database) - database: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/5e00c118e5830c43158417486b83602d1e9839ff"><code>5e00c11</code></a> (database) - database: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/d2cb8607a95e098fe0c50a82ebadd3393a52cd56"><code>d2cb860</code></a> (database) - database: disable huge_pages</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/197d80d95e42443351abbf1aae216d5f80073334"><code>197d80d</code></a> (database) - database: add persistence</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/1c3e64596ee5970c3ef7a1daeee86ced68ae3ec1"><code>1c3e645</code></a> (database) - database: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/37730ab6ca7ac86728f9fe0f1c41240402abb9bc"><code>37730ab</code></a> (database) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/5014112dd279d1e3a8d5b6fa23797d0996fb2047"><code>5014112</code></a> (database) - dockerfile: change entrypoint</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/29b538e8b33cd19bb3a781abb8335905fa7a533f"><code>29b538e</code></a> (database) - database: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/c2bb0746172d4dc764cd8543d98bb6cbd9205cf9"><code>c2bb074</code></a> (database) - database: bump python 3.10.4 and mc 2022.04.01.23.44.48</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/077a4e95b2ee3d772e030971218e880f31a55e4c"><code>077a4e9</code></a> (database) - database: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/560bdb97a46897ae0fd464ca6e2b54d129d91b37"><code>560bdb9</code></a> (database) - database: change python-dev registry</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/1e54b554f4a29df49ac42ba046f00f71a105f84e"><code>1e54b55</code></a> (database) - database: <a href="https://github.com/minio/minio/issues/14331">https://github.com/minio/minio/issues/14331</a></li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/d6466723b4f949a4771d7415f1a80924f398963d"><code>d646672</code></a> (database) - database: <a href="https://github.com/minio/minio/issues/13799">https://github.com/minio/minio/issues/13799</a></li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/a6ac4e350fec8e27c1bdc560130c585d3a7ab7d2"><code>a6ac4e3</code></a> (database) - database: use env replace creds volume</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/9618d87f3bc63c8933553278e88c7d6758b9e2af"><code>9618d87</code></a> (database) - database: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/b8232737ff893b064a558821da49b40905b4e83d"><code>b823273</code></a> (database) - database: change minio to storage</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/7bd5a90fe97b9b0ec20f5305431891f10a975c61"><code>7bd5a90</code></a> (database) - database: add check storage health</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/20c6d96e16b2dc7fc7d1bf75a8b44dd6ca459f6f"><code>20c6d96</code></a> (database) - database: fix storage run error</li> +<li><a href="https://api.github.com/repos/drycc/database/git/trees/8bde83071df44a11b01ae13fbe2676567780170b"><code>8bde830</code></a> (database) - database: upgrade to pg 14.5</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/a33b5e5ef09bfc8cf5fbf79fd11dee4766a910e2"><code>a33b5e5</code></a> (fluentd) - fluentd: update plugins</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/eed7a7804b91dba5c31762adcf1245950365b4fe"><code>eed7a78</code></a> (fluentd) - fluentd: update filter kubernetes setting</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/cc83dd87809f1b71e18636240582c0a58eb73ad2"><code>cc83dd8</code></a> (fluentd) - fluentd: update elasticsearch store setting and support exclude specific container logs</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/ba2feb28bc7a96ec2a0632c5c4070d5300de3c37"><code>ba2feb2</code></a> (fluentd) - fluentd: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/d528676b75699d731ceba78ca7b207bd1472aed6"><code>d528676</code></a> (fluentd) - fluentd: simplify drone configuration</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/dece82d3a85c2b69d4315d324d03fd1f523e53fa"><code>dece82d</code></a> (fluentd) - fluentd: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/4e0a80244c190607f9e706fdeed0f3829c505a76"><code>4e0a802</code></a> (fluentd) - fluend: replace nsqd with redis</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/15ceca0cdbfb56e03b96cfd96e9b13909667f2e3"><code>15ceca0</code></a> (fluentd) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/a7f619f70d0fb77d08f544dc593d033396b984af"><code>a7f619f</code></a> (fluentd) - dockerfile: change workdir</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/9adf5ed9a2387c79a596a4e8fddcc099316e9fd8"><code>9adf5ed</code></a> (fluentd) - database: bump fluentd 1.14.6</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/50c14c28eb1f3c673787b1f59f6b713995cd1441"><code>50c14c2</code></a> (fluentd) - fluentd: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/83171b1e36a4fc787459ffdceb9a2573b518a287"><code>83171b1</code></a> (fluentd) - fluentd: change python-dev registry</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/ec8358165e029e7c82316877f629b128bb3a00f7"><code>ec83581</code></a> (fluentd) - fluentd: unified reids declaration</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/07c63e24a3760a0604d3c17936690f31380e7b8c"><code>07c63e2</code></a> (fluentd) - fluentd: upgrade fluentd 1.15.2</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/65df9be7b31a93f6ea30d259cb13cf0401d78234"><code>65df9be</code></a> (imagebuilder) - imagebuilder: update pack version</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/66cab351e53388cdb2bddf4f415240883c3217f9"><code>66cab35</code></a> (imagebuilder) - imagebuilder: use dind replace go-dev</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/0c8206098ba01f01039c1b563238a6612e6a1fed"><code>0c82060</code></a> (imagebuilder) - imagebuilder: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/8146da94bfef611398b03c70be316676aa49f626"><code>8146da9</code></a> (imagebuilder) - imagebuilder: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/7d97241d42a0282255d9c1d6a823159671f25fd4"><code>7d97241</code></a> (imagebuilder) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/07e805c48d9f9ccf44e23d91791995f38fa28345"><code>07e805c</code></a> (imagebuilder) - imagebuilder: change default buildpack</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/8d1038df7e714b72d43b491a3fddb36639736937"><code>8d1038d</code></a> (imagebuilder) - imagebuilder: upgrade podman to 4.0.1</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/62d3687a1edeefee68d5fedfb59eea38e791a3f7"><code>62d3687</code></a> (imagebuilder) - imagebuilder: change workdir to /workspace</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/da8bfb0f576bc292eb6427f7945271cc00fcb0ce"><code>da8bfb0</code></a> (imagebuilder) - imagebuilder: change uid gid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/d44e3bc2007f4e70c7dfa6d59279e7643345bd46"><code>d44e3bc</code></a> (imagebuilder) - imagebuilder: upgrade stack</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/5b0c7e69839ac408230bc142a2ba42953a068216"><code>5b0c7e6</code></a> (imagebuilder) - imagebuilder: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/f74cbf6113d99064c5b734da329980434c4f854a"><code>f74cbf6</code></a> (imagebuilder) - imagebuilder: add defaultBuildpacksURL</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/941d4939323573679841cc114669e1dec2154f94"><code>941d493</code></a> (imagebuilder) - imagebuilder: <a href="https://github.com/minio/minio/issues/14331">https://github.com/minio/minio/issues/14331</a></li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/449be91d0c64e4e7947de68c4e35fcfd8a944a14"><code>449be91</code></a> (imagebuilder) - imagebuilder: <a href="https://github.com/minio/minio/issues/13799">https://github.com/minio/minio/issues/13799</a></li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/63b052341db3e1dcd2458ded7be233ec9877a3bf"><code>63b0523</code></a> (imagebuilder) - imagebuilder: use env replace creds volume</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/4e8a6e570108c8db393c764bd6cfa8f66cb126c7"><code>4e8a6e5</code></a> (imagebuilder) - imagebuilder: add imagebuilder config</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/2d891f53998f135bc91c34ff1e80189e01969ab5"><code>2d891f5</code></a> (imagebuilder) - imagebuilder: change minio to storage</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/addceda27e7416c7e75d7502265448a95377ed4d"><code>addceda</code></a> (imagebuilder) - imagebuilder: upgrade new require</li> +<li><a href="https://api.github.com/repos/drycc/imagebuilder/git/trees/a6e569fdfaf379bb7c64c32e2406ecbb61ad890f"><code>a6e569f</code></a> (imagebuilder) - imagebuilder: pack_build add &ndash;env-file parameter</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/6191ff5c4cc132b0a5f9bf4bc227f8a64ed0c327"><code>6191ff5</code></a> (influxdb) - influxdb: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/dc3f8c7ed955953e4b576111edde4f05726a86cb"><code>dc3f8c7</code></a> (influxdb) - influxdb: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/6b5c81922dd498c0abb22e44ff85226881df187f"><code>6b5c819</code></a> (influxdb) - influxdb: new ingress style</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/68b381d1f377bdd805d4db86fb244ece080851bc"><code>68b381d</code></a> (influxdb) - influxdb: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/ea20eb81c27c90d8038872a9b5517ea1a7eafb8f"><code>ea20eb8</code></a> (influxdb) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/64c0a71ef6d0139d8c8df6b8823f53d444df1adf"><code>64c0a71</code></a> (influxdb) - influxdb: set gid uid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/a709ca19e2ee8a37f9f46263a714aea85e413391"><code>a709ca1</code></a> (influxdb) - influxdb: use DRYCC_UID DRYCC_GID env</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/740dff00afe4b6b207d3e64819745702861e7b8b"><code>740dff0</code></a> (influxdb) - influxdb: use common affinity template</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/e0356737f548edc85730aecbbf3ac402ef0fc3a0"><code>e035673</code></a> (influxdb) - influxdb: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/f1cefbd0b3107e5a4a228cce55e580eda0a6e849"><code>f1cefbd</code></a> (influxdb) - influxdb: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/a00100ebf6f1f8ee29d0341689823be68297a9f6"><code>a00100e</code></a> (influxdb) - influxdb: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/9d165ef2cf43f2abceba893a883e34285e694cb3"><code>9d165ef</code></a> (influxdb) - influxdb: add probe</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/bee7fff49a4c9410c5ccae1f3a2435ac0b505e82"><code>bee7fff</code></a> (influxdb) - influxdb: upgrade to influxdb 2.4.0</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/254914c02d7bd968e52586a52b8749d5b3fb6388"><code>254914c</code></a> (logger) - logger: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/8d91c68965c76c955300ec0f2e583020c14465e7"><code>8d91c68</code></a> (logger) - logger: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/b6d21828ed8355c658716f9684c7dee4c73a964f"><code>b6d2182</code></a> (logger) - logger: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/c35e59a79f6ccd9946db9979abb9f5125c899695"><code>c35e59a</code></a> (logger) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/a63c07029db0b5f7ec7dc38f4f60489956944475"><code>a63c070</code></a> (logger) - logger: change workdir to /workspace</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/a594b28985d601c0289deedef07ac09ccd58a1f4"><code>a594b28</code></a> (logger) - logger: set gid uid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/9a90e22cac7243e36d88d33f95369a7a5b0a5baf"><code>9a90e22</code></a> (logger) - dockerfile: use uid gid</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/36493b41b11e8847d578dd9563d581bf25adcb2e"><code>36493b4</code></a> (logger) - logger: use common affinity template</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/897a3a5a77ea96250b76bcf06274179c85549c86"><code>897a3a5</code></a> (logger) - logger: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/03b32ab19cd49ddeb966682fe5e7dd4c3b34235e"><code>03b32ab</code></a> (logger) - logger: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/a50ba5fcd9ef8205a1b5064789735241b5ece4b8"><code>a50ba5f</code></a> (logger) - logger: change python-dev registry</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/23187a3fe6e2ffe2d4fc38a705e72c14a85fbb67"><code>23187a3</code></a> (logger) - logger: unified reids declaration</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/aaa129ade36389917750e10389b3274331caf03a"><code>aaa129a</code></a> (logger) - logger: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/be4f65615f0735303f9be4f9d67158979741b395"><code>be4f656</code></a> (logger) - logger: add replicas</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/7c25459be3cb002ea933a47e9ec318d20d69616b"><code>7c25459</code></a> (logger) - charts: add NetworkPolicy</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/6810149b5d3d6199c69909374a72836287f66b9e"><code>6810149</code></a> (logger) - logger: remove memory storage</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/a918c50d5294d3ac8bd6d156d0a63ecd373ba72c"><code>a918c50</code></a> (logger) - logger: add .vscode to .gitignore</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/a41521029d715d227582cb00edc64953028f5983"><code>a415210</code></a> (logger) - logger: add log follow support</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/59b1da3a3172da80b3b16205a6dc420a79208450"><code>59b1da3</code></a> (logger) - logger: upgrade new require</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/27cc151c73ef774d4799e04431748bdd8ffbeea5"><code>27cc151</code></a> (monitor) - monitor: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/07d6a9dff96571e1445fb04da374935062fa18e0"><code>07d6a9d</code></a> (monitor) - monitor: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/105435759e1f9250aaf0e7c0ea8d5b34aa2e0a76"><code>1054357</code></a> (monitor) - monitor: use redis default port</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/e3673dfa93515ecd8507a00b2081ab7749091038"><code>e3673df</code></a> (monitor) - monitor: remove nsqd</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/fc9dd3ed61d7990e451af7b28d7691a6a0557e28"><code>fc9dd3e</code></a> (monitor) - monitor: new ingress style</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/856a898d34a21c18479f11c20926621bcb75894d"><code>856a898</code></a> (monitor) - monitor: add default user env</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/9857535c0cdb43253706d3f6d47d15fd0cc592cd"><code>9857535</code></a> (monitor) - monitor: add random user</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/38b5a040f4617782597abd1ed63f2ac732c64bb8"><code>38b5a04</code></a> (monitor) - grafana: oauth auto login</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/5dfc5797cc291d2a6387713989bc0eb5c130127b"><code>5dfc579</code></a> (monitor) - monitor: upgrade version</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/e121b5a7844ed76b7cca01a89c0cfdbc36438487"><code>e121b5a</code></a> (monitor) - monitor: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/84462a03ead9ebc1addf53ede3089f4abb0db1f0"><code>84462a0</code></a> (monitor) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/b9e8ce8c0775c6ce6725200ca8639b372a91bbe9"><code>b9e8ce8</code></a> (monitor) - monitor: chore(imagebuilder): change uid gid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/05ee8abd8e44a731e070c6417b00f9a777649c22"><code>05ee8ab</code></a> (monitor) - dockerfile: use uid gid</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/e1fa68e170a1b4c8a1fd6ee67d211cb023cb6963"><code>e1fa68e</code></a> (monitor) - monitor: use common affinity template</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/b8f302b73ef2f71f53d3c165db6ca0f9d446e294"><code>b8f302b</code></a> (monitor) - monitor: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/4fc991f9be7d47ea1a029d57bbc8c7fb3c80bd5d"><code>4fc991f</code></a> (monitor) - database: bump telegraf 1.22.0 and grafana 8.4.5</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/21a2f6a6b23f23308d50f97ad99b9164919ff5b8"><code>21a2f6a</code></a> (monitor) - monitor: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/acc976f8c3a834f511cb482de03b0e6473de855f"><code>acc976f</code></a> (monitor) - monitor: change python-dev registry</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/62d76c13d28d136aba544749a837426f3317a794"><code>62d76c1</code></a> (monitor) - monitor: unified reids declaration</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/b3c57ad982406161ef60f04442d4dd9cee91b5b1"><code>b3c57ad</code></a> (monitor) - monitor: optimize oauth2 configuration</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/70af6b07c4c724fbd3070776f4863bffb381d549"><code>70af6b0</code></a> (monitor) - monitor: change passport config</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/69f9a888501b560c698bc6781a80752180f86f04"><code>69f9a88</code></a> (monitor) - monitor: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/2fb278f0ce0d7b9d606b04a4afc297ce44c146f4"><code>2fb278f</code></a> (monitor) - monitor: rename influxdb port</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/17548ffc21f7e10499c535c55ffb413f28576727"><code>17548ff</code></a> (monitor) - grafana: update dashborad</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/69d7bbda0547bae588e01dbcf167d31dfc7debfe"><code>69d7bbd</code></a> (monitor) - grafana: influx dashborad disk size</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/75db1b021bdd974f23f769ae69c9e33aed420d6e"><code>75db1b0</code></a> (monitor) - monitor: upgrade new grafana/telegraf</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/80504a1bb18cfd20493406dccf01e0de1b83713e"><code>80504a1</code></a> (monitor) - grafana: update influx and redis dashboard</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/f7078cba8022651a395db8484be72ca8156556dd"><code>f7078cb</code></a> (monitor) - monitor:chown use env</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/91ae0ddb94a172421923af2b63918b051bc65695"><code>91ae0dd</code></a> (passport) - passport: optimize login display</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/2d3bbbca40f25656872268f3862f71047f861349"><code>2d3bbbc</code></a> (passport) - passport: change drycc logo</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/59790a747eb6bf83345b57dbd3b27d23b760d48e"><code>59790a7</code></a> (passport) - passport: make user email unique</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/faea034774c19cfac3e5858262600cf1842601ed"><code>faea034</code></a> (passport) - passport: use strtobool</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/1fbf2bc2ce25b003a4f424efeeb67a54408b7744"><code>1fbf2bc</code></a> (passport) - passport: use yarn replace npm</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/119cac8f95d371bc51803dd482d9195460e1ede3"><code>119cac8</code></a> (passport) - passport: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/cff5062a2d8acc931c7a88d3afb7b7b8effd2642"><code>cff5062</code></a> (passport) - passport: set default CSRF_COOKIE_SECURE false</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/9cc021077c3f4f3992727c6661ac758bc8f9e60d"><code>9cc0210</code></a> (passport) - passport: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/9ab38969eff6a8bc8b33166ccd5352b0158e5c17"><code>9ab3896</code></a> (passport) - passport: new ingress style</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/259ccc91b805ed463ff0b0889a58debd78214fc2"><code>259ccc9</code></a> (passport) - passport: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/af1bbcdce7c677597c9647b27e96a1e3fcde7f5e"><code>af1bbcd</code></a> (passport) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/9ae5373f0ce8d6ec3a3f2f2915c9e6b08ca1a025"><code>9ae5373</code></a> (passport) - passport: set venv profile</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/8f610901ad7f5aa175433c2c160076cd0bcc3a15"><code>8f61090</code></a> (passport) - dockerfile: use uid gid</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/fcaf72dc9e5f196dc671a8a887ac33dcc4e1b5e2"><code>fcaf72d</code></a> (passport) - passport: upgrade npm package</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/546dcd5b8d668635ada247c7f44d95c0a001bac9"><code>546dcd5</code></a> (passport) - passport: add license</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/4bda2d661883876248c0dd0211fe15551c888c56"><code>4bda2d6</code></a> (passport) - passport: use minify</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/73b0fd135a91bf0e5c6238a659b0e41a5603d179"><code>73b0fd1</code></a> (passport) - passport: use common affinity template</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/278fe7a321f4a8561094d0cd8789918a1fd9a5fa"><code>278fe7a</code></a> (passport) - passport: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/3cd93d36d49972d4c87fc6fc7cbf38c8b6bd8a1b"><code>3cd93d3</code></a> (passport) - passport: add reactive</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/370b493ccac77e04b1366b4037e9fa7f46d4fda1"><code>370b493</code></a> (passport) - passport: add footer</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/483cbd6ae503b4a3116b673272526a842cd1dcff"><code>483cbd6</code></a> (passport) - passport: use h_captcha replace re_captcha</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/3d1675e2af62a5c858b1ae28385af97257c140d8"><code>3d1675e</code></a> (passport) - database: bump python 3.10.4 and node 16.14.2</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/86a783592e559b0a13d2cffcbea6bb4dd7e33684"><code>86a7835</code></a> (passport) - passport: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/2d65355b89a12658a69fad874add357378aedf83"><code>2d65355</code></a> (passport) - passport: change python-dev registry</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/90c1444d2f1f45658fe5a51f406ca58485eb251c"><code>90c1444</code></a> (passport) - passport: unified reids declaration</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/2e0e417f1ce86eff2c4d4f35bf5c40e230382cb8"><code>2e0e417</code></a> (passport) - passport: fix firefox footer</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/ad274bed8c36be339d461c657403070abbb695c6"><code>ad274be</code></a> (passport) - passport: use bulecss</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/f986d8b3a47d9fd83831fece5000189b1ca82dfc"><code>f986d8b</code></a> (passport) - passport: add main footer</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/3e528676fed3aae01fedbc1be39bcab7e997f088"><code>3e52867</code></a> (passport) - passport: dynamic settings for vue</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/38adabc356280f02d3cc048bd00b8ec1be8d91a8"><code>38adabc</code></a> (passport) - passport: change passport config</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/f8d6b604a6009be7b04d4b97d3457dcc0ba1b697"><code>f8d6b60</code></a> (passport) - passport: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/2cbd79daaeb948f274552e897acd53d0bddefb69"><code>2cbd79d</code></a> (passport) - passport: remove database conn_max_age</li> +<li><a href="https://api.github.com/repos/drycc/passport/git/trees/712279768f9c4dee75e5f0f6f6a1ab0865d5e701"><code>7122797</code></a> (passport) - passport: change drycc.cc to <a href="https://www.drycc.cc">www.drycc.cc</a></li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/8cc84cdb7717cc5a50353f7c32e745725c4c5973"><code>8cc84cd</code></a> (rabbitmq) - rabbitmq: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/f35930fb57b5a0b15c82be2f09879de46bd027e7"><code>f35930f</code></a> (rabbitmq) - rabbitmq: add rabbitmq cluster support</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/fbfa3ba8ff88b80d736ae2dee02575d43754529e"><code>fbfa3ba</code></a> (rabbitmq) - rabbitmq: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/ca607015c53dbf68bcdfe636ff46ce17cb973a01"><code>ca60701</code></a> (rabbitmq) - rabbitmq: use volumeClaimTemplates</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/fe5d1b41f48a729f1ada17ddaec4fd738d2c5c26"><code>fe5d1b4</code></a> (rabbitmq) - rabbitmq: add sharding support</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/9c4ab976e148b46d7fb2ba218254bb4cb8789152"><code>9c4ab97</code></a> (rabbitmq) - rabbitmq: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/348a88a95bad2b93971805ae9563555bfbd4ab00"><code>348a88a</code></a> (rabbitmq) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/2388be18e4d23623cc5b461a31f4dbc13562762f"><code>2388be1</code></a> (rabbitmq) - rabbitmq: upgrade erlang to 24.2.2</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/db2eaa5fac326200594c9768a6e6ce85721a8cea"><code>db2eaa5</code></a> (rabbitmq) - dockerfile: use uid gid</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/772afd1f7ed5732355bb9af28018d542d0c6e837"><code>772afd1</code></a> (rabbitmq) - rabbitmq: change to wait pid file</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/2bfc25ec33619c1b10be7639c819c8c2f383bbaf"><code>2bfc25e</code></a> (rabbitmq) - rabbitmq: use common affinity template</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/11d505ea19d520d98f74457054dfdbe9e91a98fc"><code>11d505e</code></a> (rabbitmq) - rabbitmq: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/69d63f1c0ce2ed2a0a80945582db041e5dd7bb7e"><code>69d63f1</code></a> (rabbitmq) - database: bump erlang 24.3.3 and rabbitmq 3.9.14</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/838029926101907d9da255e2cbcabc97dd1b0dba"><code>8380299</code></a> (rabbitmq) - rabbitmq: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/b3f69f14a151124887f49a9c4740905221d8f65a"><code>b3f69f1</code></a> (rabbitmq) - rabbitmq: add check rabbitmqLocaltion</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/5327c76d66cb6339d68036aeff52f13f315ca4f0"><code>5327c76</code></a> (rabbitmq) - rabbitmq: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/5c66b5a74037aa530ed84203c153a7d83f2ba6cc"><code>5c66b5a</code></a> (rabbitmq) - rabbitmq: change probe</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/27bebf99a4fac504dc3e4a2a8d395cc5c23c9ff4"><code>27bebf9</code></a> (rabbitmq) - rabbitmq: add start-rabbitmq script</li> +<li><a href="https://api.github.com/repos/drycc/rabbitmq/git/trees/86ee6a780841f4f4927aa4dc6bbc50362fc5f5a0"><code>86ee6a7</code></a> (rabbitmq) - rabbitmq: upgrade to rabbitmq 3.10.7</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/1f29683eb9630822c50687276941bf10b2e1c014"><code>1f29683</code></a> (redis) - redis: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/a5041fc911aa86b277f3577949637f090d7d0488"><code>a5041fc</code></a> (redis) - redis: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/64468c2257c828e61d183d4680b632ea0a24021e"><code>64468c2</code></a> (redis) - redis: add redis persistence</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/de5d7538e64ec86c2d7393dfab922dfe66d29bde"><code>de5d753</code></a> (redis) - redis: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/f6446395fbf46fd644ce3b12a3b5996e7a5b66a2"><code>f644639</code></a> (redis) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/98051d20ecb8f946c8e5093b50791df77494da52"><code>98051d2</code></a> (redis) - redis: premission denied</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/bcb548eca8ae83d1f828bd47e190b6f78a919635"><code>bcb548e</code></a> (redis) - dockerfile: use uid gid</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/524aa412e589ed21c61e31ad03067f8b96a0e116"><code>524aa41</code></a> (redis) - redis: use common affinity template</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/26c946651e503cf3be26225010fcf67a646e8c27"><code>26c9466</code></a> (redis) - redis: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/b67d7a25db6484862676b57d89530f5de4cd254e"><code>b67d7a2</code></a> (redis) - redis: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/839ec50c7c473dcac3fc2fb7e0a51a3493b3db62"><code>839ec50</code></a> (redis) - redis: use env replace creds volume</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/237ca86c239a392e23ce9b7ce68bcf9d1d0da27f"><code>237ca86</code></a> (redis) - redis: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/bdd968d27a01a06110ac394fcb4f7893cfb0edc1"><code>bdd968d</code></a> (redis) - redis: upgrade neew require</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/8b2910f10b7f5b6da8828bf8558f4eb373fcc238"><code>8b2910f</code></a> (registry) - registry: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/eedbe78543bf04298134ee2900b21d9218fd99e5"><code>eedbe78</code></a> (registry) - registry: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/024161578b010ad70702ae9480cb07a9b210ca61"><code>0241615</code></a> (registry) - registry: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/9b58da4298fd28f3ca060ce2ffd11a0977b755e1"><code>9b58da4</code></a> (registry) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/ab6acb71f85990865cd4322ef21e3d2ae0903ac8"><code>ab6acb7</code></a> (registry) - registry: change workdir to /workspace</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/f368bf7d7dfb8357acc8bf5019d052057dba393e"><code>f368bf7</code></a> (registry) - registry: use DRYCC_UID DRYCC_GID env</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/f4b9041f9c18721dcfc71091a89145323c5fc092"><code>f4b9041</code></a> (registry) - registry: use common affinity template</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/c2e87ca32c58633e9f86b3422d48249b3c1d81a8"><code>c2e87ca</code></a> (registry) - registry: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/feb6aba75f16044ecd927e020372338cd6ddf519"><code>feb6aba</code></a> (registry) - database: bump mc 2022.04.01.23.44.48</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/956932b04720266b896c0ea150a595c77a513444"><code>956932b</code></a> (registry) - rregistry: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/deda8d8d7868938fa890b5e7a0f22911e7151837"><code>deda8d8</code></a> (registry) - registry: move registry-secret.yaml from workflow to registry</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/f52c7bf6e4bc23d4f7b4e78224ff2d8da81198bc"><code>f52c7bf</code></a> (registry) - registry: change python-dev registry</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/007fe03a89f5e3b6d9baeda0b3fea84041a46ea4"><code>007fe03</code></a> (registry) - registry: <a href="https://github.com/minio/minio/issues/14331">https://github.com/minio/minio/issues/14331</a></li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/d620c6db554f29b6c9b044c12b5dfd62194f274b"><code>d620c6d</code></a> (registry) - registry: <a href="https://github.com/minio/minio/issues/13799">https://github.com/minio/minio/issues/13799</a></li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/85e6b732126ea2dacb4db0d79b2fbb831b0d984a"><code>85e6b73</code></a> (registry) - registry: use env replace creds volume</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/6a1155d75f7d6007f7ef3fe2c947423567c20e65"><code>6a1155d</code></a> (registry) - registry: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/7b8ebae5738c401580391a631757fa4646a31f3c"><code>7b8ebae</code></a> (registry) - registry: change minio to storage</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/13389519866129557fe9e08b446eb3a3de163a71"><code>1338951</code></a> (registry) - registry: add check storage health</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/2fa769dcfb770b1f9789e3ab13f96380f3e708c6"><code>2fa769d</code></a> (registry) - registry: change probe</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/f187cbf22c9206693656df844e2f97007dd95574"><code>f187cbf</code></a> (registry) - registry: add replicas</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/09d8a7b3cc69d6e0f90ab19b727f54b7129a3ae5"><code>09d8a7b</code></a> (registry) - registry: upgrade to mc 2022.08.28.20.08.11</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/4b187b8d076ef387b667e0807081021184c1f55f"><code>4b187b8</code></a> (registry-proxy) - registry-proxy: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/29ffbbe58737a14432a69938c69ff54c056b7f85"><code>29ffbbe</code></a> (registry-proxy) - registry-proxy: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/6d783baa4be1de057980040830fd6d3b161347a8"><code>6d783ba</code></a> (registry-proxy) - registry-proxy: remove use_cni</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/8cf05cff7cb44bf0b0f5c94e76567607d2f9adef"><code>8cf05cf</code></a> (registry-proxy) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/090e28647345560182a8f21da8f9445d567e3c73"><code>090e286</code></a> (registry-proxy) - registry-proxy: chore(imagebuilder): change uid gid to 1001</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/7cf6120e818b9a12799a305d8d17dfef8746a9b1"><code>7cf6120</code></a> (registry-proxy) - registry-proxy: use DRYCC_UID DRYCC_GID env</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/3a00697ed5de2230fc98971798d16de4ac6ceccd"><code>3a00697</code></a> (registry-proxy) - registry-proxy: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/30e69e8ca26894cc9efcd206665c5d96aa198085"><code>30e69e8</code></a> (registry-proxy) - registry-proxy: add registry basic auth proxy</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/942abce928797f2a77883f3a6a1a6720a6774c34"><code>942abce</code></a> (registry-proxy) - registry-proxy: upgrade to nginx 1.23.1</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/5ea3297285ab826c6686bcd20c34b1dd178615f6"><code>5ea3297</code></a> (storage) - minio: use exec runner replace docker runner</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/8306addad83bf486ae0d796d85b8f5593ca22ef7"><code>8306add</code></a> (storage) - minio: canonical charts naming</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/c917e9f3e1b03d0c9557f41f753c05f5d48f60df"><code>c917e9f</code></a> (storage) - minio: provide any additional service annotations</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/042c73208b255364db2cc08374a7b9ba39946edf"><code>042c732</code></a> (storage) - dockerfile: use drycc/base image</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/7b47b82f903ecd1e6f6c1a30ed856f7153eaef20"><code>7b47b82</code></a> (storage) - minio: change workdir to /workspace</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/6f3531ef29ed032f3f0bcbc09211e9030a02340a"><code>6f3531e</code></a> (storage) - minio: use DRYCC_UID DRYCC_GID env</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/9795fb1c71641cd106dc06abeb355c8479b0a351"><code>9795fb1</code></a> (storage) - minio: use common affinity template</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/a7b09c5b264fa9ce068ae06b12ac5fec6e7a63d4"><code>a7b09c5</code></a> (storage) - minio: change nodes to pod affinity</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/76073428fa40f6048482594720707c1e92ca17d5"><code>7607342</code></a> (storage) - database: bump mc 2022.04.01.23.44.48 and minio 2022.04.01.03.41.39</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/ea2b2f15ffc2c4d263e537aa14a74f9c71a450cc"><code>ea2b2f1</code></a> (storage) - minio: use registry.drycc.cc replace docker.io</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/445b50100629f5799b4137fa5d71a4768836f8d2"><code>445b501</code></a> (storage) - minio: <a href="https://github.com/minio/minio/issues/14331">https://github.com/minio/minio/issues/14331</a></li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/f19fbc75f98c5f1349bdfe098c69bdf732a10886"><code>f19fbc7</code></a> (storage) - minio: use env replace creds volume</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/8982e2eab58a059040d483c4ac373e9ccced0765"><code>8982e2e</code></a> (storage) - minio: use minio to distributed</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/06bec7372476dec97304f51754a9c031498fd888"><code>06bec73</code></a> (storage) - minio: fine management affinity</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/9b8f0062892bcd4f720014a142efde4ce6ed10c6"><code>9b8f006</code></a> (storage) - storage: remove assert</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/59d64b92e21603e86573699e5b1e2914672cfe3a"><code>59d64b9</code></a> (storage) - storage: change listen to POD_IP</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/60044ee012378c0c344518f5945ed6dace124535"><code>60044ee</code></a> (storage) - storage: add juicefs mount options</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/189f944175bd9c16d3a8d5347a9040143903e15a"><code>189f944</code></a> (storage) - storage: remove volumeName</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/302fe8964b3171bc6c7cdddd494d5e3ca62c5209"><code>302fe89</code></a> (storage) - storage: mv to minio dir</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/6ec586d742cf14f311e2ac097ad207c2b3fb65b4"><code>6ec586d</code></a> (storage) - storage: change readinessProbee andlivenessProbe</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/0e028dfee98c4cf8a54110101f1084b03cf75b8e"><code>0e028df</code></a> (storage) - storage: add minio pdb</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/cf9bd2de2b8138b6a75c1d804e919586d2d53eca"><code>cf9bd2d</code></a> (storage) - storage: add check storage health svc</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/2dd5c9f20dcbbdb184d3e0be19a9e93b41ac1019"><code>2dd5c9f</code></a> (storage) - storage: add volumeBindingMode</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/fa2effc313905bf8e7a0d41d6d09335ca1a70552"><code>fa2effc</code></a> (storage) - storage: remove databaseBucket</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/d166cc721e45bf1955a2d99b70187ee9b3d6970a"><code>d166cc7</code></a> (storage) - charts: format network-policy name</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/d06bcce9fe0e8de7720e5c93b5d87e742be7f5a7"><code>d06bcce</code></a> (storage) - storage: upgrade to golang 1.19</li> +<li><a href="https://api.github.com/repos/drycc/storage/git/trees/c2ca05cd4b92259d4454723ab25252e4f6e220ac"><code>c2ca05c</code></a> (storage) - storage: upgrade new require</li> +</ul> + + + + + + Blog: Drycc Workflow v1.5.0 + /blog/2022/10/06/drycc-workflow-v1.5.0/ + Thu, 06 Oct 2022 00:00:00 +0000 + + /blog/2022/10/06/drycc-workflow-v1.5.0/ + + + + <p>These release notes for Drycc Workflow v1.5.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.4.0, please refer to the following change summary.</p> +<h2 id="workflow--v140---v150">Workflow ## v1.4.0 -&gt; v1.5.0<a class="td-heading-self-link" href="#workflow--v140---v150" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>passport v1.0.0</li> +<li>rabbitmq v1.0.0</li> +<li>imagebuilder v1.0.0</li> +<li>builder v1.2.0 -&gt; v1.3.0</li> +<li>controller v1.3.0 -&gt; v1.4.0</li> +<li>database v1.0.2 -&gt; v1.1.0</li> +<li>fluentd v1.1.0 -&gt; v1.2.0</li> +<li>redis v1.1.0 -&gt; v1.2.0</li> +<li>influxdb v1.0.1 -&gt; v1.1.0</li> +<li>logger v1.1.0 -&gt; v1.2.0</li> +<li>minio v1.1.0 -&gt; v1.2.0</li> +<li>monitor v1.1.0 -&gt; v1.2.0</li> +<li>nsqd v1.1.0 -&gt; v1.2.0</li> +<li>registry v1.0.3 -&gt; v1.1.0</li> +<li>registry-proxy v1.0.2 -&gt; v1.1.0</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/0f5f8e4171313ea56de2d659d92458acd39a3201"><code>0f5f8e4</code></a> (builder) - builder: multi-platform support</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/f269d06ddc42464ba99ceeabc283645778034547"><code>f269d06</code></a> (builder) - build: add buildx supportjkjkk:q</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/5e72fe88f057c1814c6d8075638d124445c16157"><code>5e72fe8</code></a> (builder) - registry: use docker build</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/25d8a4cbc14ccfeccc0a33d17fc723149103a0d3"><code>25d8a4c</code></a> (builder) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/7a3e1c58942dfdfde474462f92a2a5bddf1c15a8"><code>7a3e1c5</code></a> (builder) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/46b75ff211da2985ce17737e7c6bb29ce73c8df3"><code>46b75ff</code></a> (builder) - builder: add cloud native buildpacks support</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/2db2054dd960f80ee76c442d3705490c5f70358a"><code>2db2054</code></a> (builder) - builder: unified build model</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/4b7f9d9bc38c65ca56e162701b4cbce43c1cbbbe"><code>4b7f9d9</code></a> (builder) - builder: add initContainers</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b78c936ec706cce8bd8e8676a411187fed658b23"><code>b78c936</code></a> (controller) - token: add get token api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/bac52a51b06872d48ecefabfb14b29b9f70d4357"><code>bac52a5</code></a> (controller) - tasks: use celery replace nsqd</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b9b0c58b1f877d077543efb202c71f5cec07b6fc"><code>b9b0c58</code></a> (controller) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/205dcb3b5b1003d704a0033d3a3b8b6761393df9"><code>205dcb3</code></a> (controller) - influxdb: add influxdb client</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ff15849bafddc47e06820ca89e8e95abc6c89311"><code>ff15849</code></a> (controller) - influxdb: upgrade to influxdb 2.x</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4016244757d764b553abd20ffb8ed79368c7caa1"><code>4016244</code></a> (controller) - controller: push data to influx</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/fcfce2ea7f6af657c46a1c53f0f78b7224b56ff6"><code>fcfce2e</code></a> (controller) - workflow-manager: add workflow-manager support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/00e9bfb627c11be35fd57c330d3127c84675b0f6"><code>00e9bfb</code></a> (controller) - influxdb: review influxdb code</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/dd644d5a5e626d51ddb6f4d6488691ac7f2f2804"><code>dd644d5</code></a> (controller) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/118278b332877428f09d13801432a8c7f51ebbee"><code>118278b</code></a> (controller) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/122a9cd267f8b80d4b922938b97a71032f174648"><code>122a9cd</code></a> (controller) - oauth2: add oauth2 support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/559a5b6c76a0b9925bdd7d027e5653b7d494d4ac"><code>559a5b6</code></a> (controller) - controller: use cncf buildpacks replace slugrunner</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/96130e6900dae2bc31899e3a06fec87c5c6684c9"><code>96130e6</code></a> (controller) - charts: database configuration optimization of passport and controller</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/2ea85089f9ef7814e7c504380929c09cd73fadb2"><code>2ea8508</code></a> (controller) - oauth: using passport authentication</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/868c437940b7cde4caaf0b4f81ab5265cd2f197c"><code>868c437</code></a> (database) - database: multi-platform support</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/eadd5da76c3a5979a90b52b245dc9041da861d6a"><code>eadd5da</code></a> (database) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/b6eea4c09dcd95d7f8f0540c2ffef63567146167"><code>b6eea4c</code></a> (database) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/04a88dbafe96027068badd9e65c30b832432c371"><code>04a88db</code></a> (database) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/92ed309894ef2d065d4dc20acf5cf44dfafa84d7"><code>92ed309</code></a> (database) - database: add initContainer</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/ee6b78ff78bfe978edf2e9a9789bdf58c2dc846f"><code>ee6b78f</code></a> (fluentd) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/f523e30c5e93d80e509232e7bb25f4de92267312"><code>f523e30</code></a> (fluentd) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/ee47b53b6f18bf4e2cdd41aaabf4dcd807d4b2d7"><code>ee47b53</code></a> (fluentd) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/80a51af1c0dbf689ead41a4b88d5e31861a7b0d0"><code>80a51af</code></a> (influxdb) - influxdb: modify influxdb naming rules</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/fb1003086e3819ada293e1792b46e966e509ee3a"><code>fb10030</code></a> (influxdb) - influxdb: use influxdb v2</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/0e87ad8c239a8cbb4ec02a584081ac1be0cb21af"><code>0e87ad8</code></a> (influxdb) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/9d108019d94ce2e653ec16482e89dff314810f9b"><code>9d10801</code></a> (influxdb) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/d825c9f7b4198c10e93abc7121af54f7af63f711"><code>d825c9f</code></a> (logger) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/b1395766670636ecbb42fb0b4ca1649186bfd4c5"><code>b139576</code></a> (logger) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/88f84ea95e334fcfef45ecd4f28c8bc468523574"><code>88f84ea</code></a> (logger) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/5ccae3ef8fa0894f08bf6ba552b17455a481a698"><code>5ccae3e</code></a> (logger) - dockerfile: remove chmod cmd</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/193aefc8c4106c7c6d5022c9183c68d6e604e735"><code>193aefc</code></a> (logger) - logger: add initContainers</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/baee3305a3b09a0fba83f33fb161400a7e7fd7fb"><code>baee330</code></a> (minio) - minio: multi-platform support</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/ad5d055e170977801a6951813e4896d1f854e14f"><code>ad5d055</code></a> (minio) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/19868d457852e423536d8ae8f426a2c3437f423d"><code>19868d4</code></a> (minio) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/4bd84b8bb8af65a0ab05eff3a4c227452c4a3a2f"><code>4bd84b8</code></a> (minio) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/79d1f2f85c17c71ec609e8e191e04e9de87deec0"><code>79d1f2f</code></a> (monitor) - database: multi-platform support</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/88e5a7f45886f5ca947e44052c5c52a2f8e17497"><code>88e5a7f</code></a> (monitor) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/5672e99a81ce856e4cd42a1b4e1083919e165272"><code>5672e99</code></a> (monitor) - influxdb: modify influxdb naming rules</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/867210310f29da9600bb2d052e05d5181cfe5a4f"><code>8672103</code></a> (monitor) - influxdb: use influxdb v2</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/66cb4c877ee0acfdcabab284da18b58266b61201"><code>66cb4c8</code></a> (monitor) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/9576eb38c61048d3d540303047c8690763d664e1"><code>9576eb3</code></a> (monitor) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/30809c9ce3f31f52ac10616dbe9a24135d74828d"><code>30809c9</code></a> (monitor) - monitor: add initContainers</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/70d140ce05b061462a990029b9fd7ac749c383c7"><code>70d140c</code></a> (nsqd) - nsqd: using self compiled nsq binary</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/1073d4f35b082ea6dd63570d8427d7e3d1c2fecf"><code>1073d4f</code></a> (nsqd) - nsqd: use GOPATH replace /go</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/e49848037b54362f83ee063adc6e954afe8fa84a"><code>e498480</code></a> (nsqd) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/cf9b7d5cd6ee63d77acadec5c3a410acb60df400"><code>cf9b7d5</code></a> (nsqd) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/c335856f1ca9c80b0dc23df3445d395a13b8b50b"><code>c335856</code></a> (nsqd) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/efba7134453bc730b968d909089564de3de3079a"><code>efba713</code></a> (redis) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/c7a3b53025faa393bf6e915ec71b96ef7a5da27f"><code>c7a3b53</code></a> (redis) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/4cdad7bab726dd11973c1dbc643a81eb6313ba1f"><code>4cdad7b</code></a> (redis) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/652b443a4e5c54765bb40cfeb38310eee455a3c2"><code>652b443</code></a> (registry) - registry: multi-platform support</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/4060176efaca5531faec4ecdd02eb30b6451e16e"><code>4060176</code></a> (registry) - registry: use docker build</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/7102a03677830beb4b0ad093b141cb48ba948dd7"><code>7102a03</code></a> (registry) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/6c8600d293589b36748acf7b4dfb913f2cefde8d"><code>6c8600d</code></a> (registry) - charts: set the default chart version</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/33a51c99e3f278c7c36dfc27c124db3dec530914"><code>33a51c9</code></a> (registry) - registry: add initContainers</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/bef70dc98c4b044d1108f6b42f439b36d37270e1"><code>bef70dc</code></a> (registry-proxy) - build: add buildx support</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/d2319c1fce4e57cd9257ec3978f4e5a8d0101a23"><code>d2319c1</code></a> (registry-proxy) - docker: dealing with the change of docker in kubenetes 1.20</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/02fafed2b1b5648274c3d44c3d113a0a025e4fca"><code>02fafed</code></a> (registry-proxy) - charts: set the default chart version</li> +</ul> +<h4 id="fixes">Fixes<a class="td-heading-self-link" href="#fixes" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5499c9a2844c192285d5afdbf6a08d803a70cf8d"><code>5499c9a</code></a> (controller) - gunicorn: gunicorn not running</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/06e9e8869fbf61b3db753ab211bd9d465afa9058"><code>06e9e88</code></a> (controller) - controller: error loading shared library</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/01b5bd04cf1848b876b2b5acbeae6c361bebf975"><code>01b5bd0</code></a> (controller) - controller: upgrade celery config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/6e32d55cf9de3dce1b7d470f850c2d155809cc07"><code>6e32d55</code></a> (controller) - controller: fix update resources bug</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0e0d53f3056dfbf427ad7a474786e723b87cb39c"><code>0e0d53f</code></a> (controller) - chart: set the domain depends certManagerEnabled</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/2ac4ca839d76a4b80205506938d63f25bb4abea0"><code>2ac4ca8</code></a> (controller) - passport: error loading shared library libexpat.so.1</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/a0dd517e189a2ba9472c0d320ba32d091520dcbe"><code>a0dd517</code></a> (fluentd) - fluentd: drone build</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/6eca2a3e17e2965816718963fe4d7f6ffeb15a42"><code>6eca2a3</code></a> (logger) - logger: golang lint</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/63b0aa0989db8f9e15daa415c5a0b56e9350c0a9"><code>63b0aa0</code></a> (registry) - drone: charts url error</li> +</ul> +<h4 id="docs">Docs<a class="td-heading-self-link" href="#docs" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/472cfcc226c98d2b9a74c367519d57ec31890b71"><code>472cfcc</code></a> (controller) - controller organize README.md document</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/d9d6e292c602c3538784de6755b40f4655710278"><code>d9d6e29</code></a> (redis) - redis: delete links that do not exist</li> +</ul> +<h4 id="test-case">Test case<a class="td-heading-self-link" href="#test-case" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1468f57465243709594b0d6472636ccc0d7b7f62"><code>1468f57</code></a> (controller) - controller: add command unittest</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/9999bfd30ab9550966eb70a6e52efbbb38f5cef1"><code>9999bfd</code></a> (builder) - builder:replace the special words</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/cda8b5814e507ab72a0ce7125eaa8d6bdd168a06"><code>cda8b58</code></a> (builder) - builder: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/dc575dde93ad1334be9d1337fbc1b0b66a06ebd9"><code>dc575dd</code></a> (builder) - builder: use imagebuilder replace dockerbuilder</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/d3bb183df646a7f2503c739633bb6d5d61778219"><code>d3bb183</code></a> (builder) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/5fe34d1fee978986729120af7d5732ed3759b88c"><code>5fe34d1</code></a> (builder) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/7e364532bf841109fe5e75c6a5c357ad46f7c4b7"><code>7e36453</code></a> (builder) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/52b8d9df26f28e562b4eca72e777106db86db9db"><code>52b8d9d</code></a> (builder) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/65963f4b35d2b60e376818d314cd203fb698eaba"><code>65963f4</code></a> (builder) - k8s: add privileged to dind</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/d345fcf23f1c3e755ec646d988c5d1e0e90d2eba"><code>d345fcf</code></a> (builder) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/7975c998252a66557bbfa774ac18f18e17a5ddbd"><code>7975c99</code></a> (builder) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/59633dd9197fed8400d8007cc93e7a62404e92b1"><code>59633dd</code></a> (builder) - builder: modify launch imagebuild pod</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/8d14e67e5e84c2d6b6254b7704219c9ed38aac67"><code>8d14e67</code></a> (builder) - builder: use Procfile in anywhere</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/5357fa88e56ef24fac7f8d3dc0bfa5d990c1be58"><code>5357fa8</code></a> (builder) - go: bump go mod</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/8d26ac054edeb67e4ce473507a96951dbda10db2"><code>8d26ac0</code></a> (builder) - k8s: k8s deprecated api migration</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/0af620def4db8473c799c9499a4a27ee4a278210"><code>0af620d</code></a> (builder) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/ae84303f6d15b22c525e62cf3ae2d1e314d9a67b"><code>ae84303</code></a> (builder) - builder: run imagebuider replace pod with job</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/3b2c496a00a8512731c18d79215ce9e279b60e19"><code>3b2c496</code></a> (builder) - builder: change docs website</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/5679a4cfefd214b7bb0014cde3f7c461bd70ca91"><code>5679a4c</code></a> (builder) - builder: upgrade to golang1.17</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a214503452b10f3e265d97954964d321480b007d"><code>a214503</code></a> (controller) - controller:replace whitelist with allowlist</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/375ddcc15761326b8c74f8cd78a239cfe9c14224"><code>375ddcc</code></a> (controller) - ps:drycc ps:list show autoscale num</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c32e409b6fe09c533bc5cfdbf35b47e633d2a644"><code>c32e409</code></a> (controller) - ldap: canot register when ldap is enabled</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c46580a6264cbe21ee5240fde5791c9c78ef2a19"><code>c46580a</code></a> (controller) - controller:modify redis config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/fa9e87b6131a9669eebafb4bfea26dc5f15bde64"><code>fa9e87b</code></a> (controller) - chart:modify controller charts</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/6f9fd081e6826fd89316ff4d064c9cf03501e1d3"><code>6f9fd08</code></a> (controller) - nsq: remove nsq</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/994b2dc68afdeaedc540525422183565bc1e3230"><code>994b2dc</code></a> (controller) - docker-buildx: add check-docker</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a720c3a9933aaaa15d5933143708fbcac2d5233a"><code>a720c3a</code></a> (controller) - controller: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e9a5c843d0abd85ae57d8cb87cbe7369364b07e6"><code>e9a5c84</code></a> (controller) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a26614acb4fb8cef5030e0e56681939977a7a266"><code>a26614a</code></a> (controller) - controller: add rabbitmq env</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3df229d2d31b6f8fc79a260e5088a86d00716459"><code>3df229d</code></a> (controller) - controller: modify database config &amp;&amp; remove redis port config &amp;&amp; add env prefix with DRYCC</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/257e94b429c8f7b0c636a083215d9709baaf5c8d"><code>257e94b</code></a> (controller) - controller: CELERY_BROKER use rabbitmq and modify celery-deployment cronjob</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f4d6ec343ec3fb618ef9ee8da09474294d49807e"><code>f4d6ec3</code></a> (controller) - chart: pretty chart format</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/63e61951cda276fe59a91a64a7b84f7feb66ce6d"><code>63e6195</code></a> (controller) - influxdb: modify influxdb code</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0f6d408734984e4ec9bbc56c0a4b68ba5783b680"><code>0f6d408</code></a> (controller) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/87bad28b65b773e6534c4cc8e2128045d3ffb7c3"><code>87bad28</code></a> (controller) - python: upgrade to python3.9</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e8f75603cd0cd38423d774f1b3220b64ef9eb6dd"><code>e8f7560</code></a> (controller) - volumes: modify mount summary</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/6cf6c6bdbf029b1e52a36d5148d5a025fb6d04c1"><code>6cf6c6b</code></a> (controller) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a9397e8c06a69d5539e8f5b67be242932e69c2c8"><code>a9397e8</code></a> (controller) - oauth: modify token Authentication</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c7f8c8b3b2294205603afd9ca4a7ba2e3f6cea02"><code>c7f8c8b</code></a> (controller) - deps: bump django from 2.2.14 to 2.2.18 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a1a08aa4165ba678e979d6ca4477694999d0e5b8"><code>a1a08aa</code></a> (controller) - deps: bump djangorestframework from 3.11.0 to 3.11.2 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/efd78b42038a404d53d06e92bb609cc7f97739db"><code>efd78b4</code></a> (controller) - deps: bump django from 2.2.18 to 2.2.20 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/649b044c644c9729b80e5f0e2663779bcc648ef2"><code>649b044</code></a> (controller) - deps: bump django from 2.2.20 to 2.2.22 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/41b742bbec9370490b0176fac407bcbd83abd2ed"><code>41b742b</code></a> (controller) - deps: bump django from 2.2.22 to 2.2.24 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/22ffe5d8dd51cffc38e5e3757ac97eba02861e2b"><code>22ffe5d</code></a> (controller) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c98b46837efa85a5daf46c6dc40d45606b7548bc"><code>c98b468</code></a> (controller) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/20e6edb1001fb709ea877349771404ee807ae36d"><code>20e6edb</code></a> (controller) - chart: modify the problem of using buildpack</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/db16879a4ce64c7020b7622603f53ef88898be0a"><code>db16879</code></a> (controller) - controller: pretty pods list print</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ba6f456ddb0a48a0e8c1f446330a838ba27b8f48"><code>ba6f456</code></a> (controller) - test: pretty pods list print</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5fce4b7a77c91836d921c6d1f4cb8cacb2ab953d"><code>5fce4b7</code></a> (controller) - k8s: k8s deprecated api migration</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e9e0bcb36d4b6b1169446c484357260aee7feba7"><code>e9e0bcb</code></a> (controller) - oauth: using passport authentication</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0311172bea0f1d28959ee528c0e50493d0c8d425"><code>0311172</code></a> (controller) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/150eff1c246b908e8f5521cc1e5e9ff4c765433d"><code>150eff1</code></a> (controller) - charts: update cert-manager api version</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/de8545a568984f52e5757806d9ce631864285fed"><code>de8545a</code></a> (controller) - controller: update requirements</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1442207889955cbf230bd1c87867acaab72256fb"><code>1442207</code></a> (controller) - controller: using django native JSONFiled</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ab4e836a55aa61cbdb222a8fc606b5619625337e"><code>ab4e836</code></a> (controller) - oauth: modify passport api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5c54e0642c76bfa1253397177b5aef2dc28dc611"><code>5c54e06</code></a> (controller) - controller: eliminate pip warnings</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/870328ddf06ab6b3004fd0e56516de6496c06e26"><code>870328d</code></a> (controller) - controller: remove entrypoint</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5e5e6ae5763333989e153119c6078c06788d0f78"><code>5e5e6ae</code></a> (controller) - controller: upgrade celery config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/607778ffb2f81b74457db2b34952a0cd01647eb3"><code>607778f</code></a> (controller) - controller: add initContainer</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/23dc016da2419237814a7d1ac54435adc99f0423"><code>23dc016</code></a> (controller) - chart: set the domain depends certManagerEnabled</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f3cf20b610a649d105e4889212272604615ddfa7"><code>f3cf20b</code></a> (controller) - controller: remove default bash env</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/73f26364110a1cdee5bdfe868e4fbf0be2cdbcf4"><code>73f2636</code></a> (controller) - controller: modify alpinelinux repositories</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/498e9f2fbd5470ff8079e09eacc04be4272d9601"><code>498e9f2</code></a> (controller) - chart: change certManagerEnabled to boolean type</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/27f5308938f972d078e78c539e9160cc2f3b3a1a"><code>27f5308</code></a> (controller) - passport: exclude cryptography</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/370b75dc9cbdcf24b3955b562ff276e3214eb5a2"><code>370b75d</code></a> (controller) - controller: use sh env</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/07585b4f45471b22e6942590dac51cf724e8bd57"><code>07585b4</code></a> (database) - postgres:replace the special words</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/20172dcfac8370b389aa26a30cc9e2f0a96f6a6d"><code>20172dc</code></a> (database) - database: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/abb9b88a96e0098d3fb1128d123825ca4faea3a4"><code>abb9b88</code></a> (database) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/e72f58ffa50be0f5170423529292872fcd53cfea"><code>e72f58f</code></a> (database) - chart: modify the off-cluster database</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/a91f64f694c15143b7210597ffdd7dacfa6668bf"><code>a91f64f</code></a> (database) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/614fb76a1c77b8f5697a87aadfd094d6eaa8c27b"><code>614fb76</code></a> (database) - tests: use add-host replace link</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/a3428f353c38f440381890fd80416ad302033352"><code>a3428f3</code></a> (database) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/239fef11f87655203f6090e55259cb09906fb253"><code>239fef1</code></a> (database) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/42858e1e2ae1a09e1bad75e1fabb7ec4115e7197"><code>42858e1</code></a> (database) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/d0fe85094eb305ce071f51bf40bdf2099b88ea13"><code>d0fe850</code></a> (database) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/34a36ad4f650d6eaf2320e55f4d80a06e0dd1675"><code>34a36ad</code></a> (database) - charts: Nn secret is generated during off-cluster</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/064ccf462a1bd2fe513809c39919fc1ccaba7801"><code>064ccf4</code></a> (database) - database: create database</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/9228992327543f008bf4158be8b8cd1777c3ba90"><code>9228992</code></a> (database) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/9f7810c6dcf6323bc6f75345f4c9fc25a5e11ef6"><code>9f7810c</code></a> (database) - database: upgrade to wal-g v1.1</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/05783f4118cd7e8cc80e41c20656f5b16961fa3d"><code>05783f4</code></a> (fluentd) - fluentd:replace the special words</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/0739809ba68d12ef8940f0f6addcfea7353885f5"><code>0739809</code></a> (fluentd) - influxdb:replace monitor-influx with influx</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/f02487cea73f20a2039fe6c1960950a3b73107b5"><code>f02487c</code></a> (fluentd) - fluentd: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/2c96cc089f7965286409cb4d710df5ab947b20b5"><code>2c96cc0</code></a> (fluentd) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/b20c429b9ace293c7add60fa350098b91285bf87"><code>b20c429</code></a> (fluentd) - charts: remove port config</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/6dd019721438cf32f2262bdb76d74da9ab5b37a3"><code>6dd0197</code></a> (fluentd) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/c5bec512a902662a8200639b3b574925c836e734"><code>c5bec51</code></a> (fluentd) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/f8524b78536b6d6cc1022e3cfa6ab61ac36fbca8"><code>f8524b7</code></a> (fluentd) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/a50878aabea91b3fbbafaf9c1f43c2eca7fe5a5c"><code>a50878a</code></a> (fluentd) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/14fe20e811ba3c8814188dcec18ed69c169c4b9d"><code>14fe20e</code></a> (fluentd) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/4a2f66070910abcc3068d0e03a8e52d1e5d2659d"><code>4a2f660</code></a> (fluentd) - k8s: k8s deprecated api migration</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/de2dd9178130101f4b0c5ed82d5e80a1ba4dd591"><code>de2dd91</code></a> (fluentd) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/a9f1944c3dcac5e8f0eb2f44d11ec81517735b8c"><code>a9f1944</code></a> (fluentd) - fluentd: upgrade to fluentd1.14</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/7cb4e954704cfa5ff37d3b95b5e9a231188f4264"><code>7cb4e95</code></a> (influxdb) - influxdb: change username to user</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/0fdc21b2a95003abd488cb05b640ec1fa1db3ff7"><code>0fdc21b</code></a> (influxdb) - influxdb: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/b2acddb8d72bd0e17fb0b543a8f98e2fa5d57735"><code>b2acddb</code></a> (influxdb) - influxdb: change default path</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/ba8891910d5ef9084f9dd9b7569d905e19f056ea"><code>ba88919</code></a> (influxdb) - influxdb: add check_env function</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/91174010ed68356d9b813b70e2def18af9ed5186"><code>9117401</code></a> (influxdb) - influxdb: modify init_influxdb has_bucket</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/092a3e6b96e9494f00e7a0627b2aa9ce1212c7d4"><code>092a3e6</code></a> (influxdb) - chart: pod not readiness</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/51de380cc83177be8bdb557894b9fd5c28ed0a3d"><code>51de380</code></a> (influxdb) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/66d76679cc55578d13274fa5bf0e653b258e57b4"><code>66d7667</code></a> (influxdb) - docker: replace influxdb base image</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/3aa30943cea519fff18c23264c99c226cfb43c80"><code>3aa3094</code></a> (influxdb) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/influxdb/git/trees/14b9c24f110297e5b6a632ce4ad94625f5663038"><code>14b9c24</code></a> (influxdb) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/02b4cd111c092393b0f2d3f1c1654d0476603b03"><code>02b4cd1</code></a> (logger) - logger:replace the special words</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/114b5d5392a1d82f8dc73b4b1527e742fcaf22f1"><code>114b5d5</code></a> (logger) - reids: delete the logger prefix of redis</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/639278a8f055d7872491db2240f4327d4f77114e"><code>639278a</code></a> (logger) - redis: remove logger from redis conf</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/90195e27521b44e0d43f8fb7ff9ab9a658f60676"><code>90195e2</code></a> (logger) - go: remove GOOS and GOARCH</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/31e2e27f9160e62b199c196972fe5c0097a78a22"><code>31e2e27</code></a> (logger) - logger: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/8fbd9fa7b119f112221be5fa5bdc21e3a891a6b9"><code>8fbd9fa</code></a> (logger) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/b39df2d46e0f625900f80d0103a5a35c4e7fbb0e"><code>b39df2d</code></a> (logger) - charts: remove redis\nsqd port config</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/35d6d0784df91dc1036928c83905052962a84ca0"><code>35d6d07</code></a> (logger) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/69aabf527a1bea60f6d7792a488ed074d138a27a"><code>69aabf5</code></a> (logger) - tests: remove docker link</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/e916644cd89379731f5a9990044e3f64d570b6dc"><code>e916644</code></a> (logger) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/d6872b7cfbd30d0be087270b581a0730961f4b8b"><code>d6872b7</code></a> (logger) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/37801daabfe98292c54ed2902aeb120069448b64"><code>37801da</code></a> (logger) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/cfb4b38897136e5c1b942433b52944cdccc9b195"><code>cfb4b38</code></a> (logger) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/8bda3bf9906424c9be8661ab0d6850ae6e3352ea"><code>8bda3bf</code></a> (logger) - go: bump go mod</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/e13ebfcd5fc940393e1d398623650bfcd31c24de"><code>e13ebfc</code></a> (logger) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/38e6d8d592ad42a176d08f0d7edbe38e55b39b72"><code>38e6d8d</code></a> (minio) - minio:replace the special words</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/d6925ddec232dd3b6187414f4a11327330baa95a"><code>d6925dd</code></a> (minio) - minio: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/d56bc39ba487c24e89a47e6c63375342ba3c3552"><code>d56bc39</code></a> (minio) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/e4696cc243711c53a1fe16051cd80209c8a3d281"><code>e4696cc</code></a> (minio) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/70c5c7988a513b5a39b92e442b0f9052d1507f67"><code>70c5c79</code></a> (minio) - minio: use latest version</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/773cf6c47a4ab539dcac29084980953bdd0e9e04"><code>773cf6c</code></a> (minio) - Makefile: remove DEV_REGISTRY ?=</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/5ce5bc696e7522107139cccfec37c6dc4b759059"><code>5ce5bc6</code></a> (minio) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/5da8be3ca9345e7a6c87ad61bf104b7345523691"><code>5da8be3</code></a> (minio) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/c1f0611fed4e73a5109f1d15901721fa968d6c34"><code>c1f0611</code></a> (minio) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/b73f7927c34fca39605e13930a06fad829658e7b"><code>b73f792</code></a> (minio) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/79d1c935ee59bf45af52a1265aa87e2ef3233f40"><code>79d1c93</code></a> (minio) - go: bump go mod</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/c448899edbaacf8d54cdbad53561733069c1020b"><code>c448899</code></a> (minio) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/15ee49ef85be819d3f6eed5dde4551ffa31f5fae"><code>15ee49e</code></a> (minio) - minio: migrate deprecated warning</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/9968a1a2095fecda1d3ba3fbd2263e83494d716e"><code>9968a1a</code></a> (minio) - minio: upgrade to golang1.7</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/14fedd29ba64e02c05b6cd5fb06bd261bf9f367b"><code>14fedd2</code></a> (monitor) - monitor:replace the special works</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/52c431ad1701cc15e03d55cbc436c5f4f7472522"><code>52c431a</code></a> (monitor) - reids: delete the logger prefix of redis</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/2c95b47a1f714a421be5860a78dd94c23ddcfdf3"><code>2c95b47</code></a> (monitor) - redis: remove logger from redis conf</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/da9bc5605eb4a118bca92fdff3cc49c2f208c040"><code>da9bc56</code></a> (monitor) - monitor:remove influxdb</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/53f47b9a3b8dec717d049b9be3961e4efd446381"><code>53f47b9</code></a> (monitor) - grafana: use grafana docker image</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/5bdb188a7255e845cda8a49806053f12032d196d"><code>5bdb188</code></a> (monitor) - grafana: use grafana docker image</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/c0586dda982c857e61b89964f34b57028cfaa29c"><code>c0586dd</code></a> (monitor) - monitor: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/87d02b6c80ef04c1170e848e9febdb723c9503c3"><code>87d02b6</code></a> (monitor) - charts: add nodes and persistentvolumes rule</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/1b5598fb479f85808bb33ef29b8cd21ab9d40bc6"><code>1b5598f</code></a> (monitor) - monitor: modify grafana dashboard with FLUX and pretty config.toml</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/bcbc0d5b3ef1b16a9e4b22208f5c628156a556cc"><code>bcbc0d5</code></a> (monitor) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/9418c9e13b4fb20f4174ee965044cf30ca12ae38"><code>9418c9e</code></a> (monitor) - monitor: fix upload dashboard error and modify INFLUXDB input</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/589f29a84eeab3f9fbc1cce1e49a601938a32987"><code>589f29a</code></a> (monitor) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/f776f8a650fd4c0c1e5f21dc9aa38ad36ca5be72"><code>f776f8a</code></a> (monitor) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/6ca306092ca874c666066dffce4f3f8fad11bbcb"><code>6ca3060</code></a> (monitor) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/6a9ffb24264ff8d7e5e9407f811e5b38b9e20a38"><code>6a9ffb2</code></a> (monitor) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/45e41ed8d104205a708fd82327e0fa3f3ac3d97e"><code>45e41ed</code></a> (monitor) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/654d407bea3cc3e686416cb2f6e1224990bab741"><code>654d407</code></a> (monitor) - k8s: k8s deprecated api migration</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/41e9b9c3c1b371ea815cd480e33c53779c2211a7"><code>41e9b9c</code></a> (monitor) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/99c10d38471587b09fb51ee65c8e602e443b44e7"><code>99c10d3</code></a> (monitor) - charts: update cert-manager api version</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/9bf83c40a846784e8375db884a2d417073324408"><code>9bf83c4</code></a> (monitor) - oauth: user oauth passport</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/a128f6d5f97fc060a80a2384f4a2dd2dc916dd12"><code>a128f6d</code></a> (monitor) - chart: change certManagerEnabled to boolean type</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/8f897fe306e15f4d528d0665171d634f0d9b93c4"><code>8f897fe</code></a> (monitor) - chart: set the domain depends certManagerEnabled</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/ba6d793c6110993b227246b8bf0bb861fc468975"><code>ba6d793</code></a> (nsqd) - README:update travis build status</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/49879c4baba2a6824b9f32bb2734aec21debefb0"><code>49879c4</code></a> (nsqd) - nsqd: minimum git clone code</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/c5e26805e49bd1be880fd4857b435359a0840992"><code>c5e2680</code></a> (nsqd) - nsqd: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/21dd17b886aad7e673fdb72fe4ccce3d9786a623"><code>21dd17b</code></a> (nsqd) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/7d86b3cbb2452da48abcc99f165dfa8954f103bb"><code>7d86b3c</code></a> (nsqd) - charts: remove port config</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/c073d952af18ffd83b6f86ce7a55140b36029a63"><code>c073d95</code></a> (nsqd) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/55c297ca70952986cb6a971593bbe0e64adea029"><code>55c297c</code></a> (nsqd) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/165c2aef05413585886651299c11dfb741469b0c"><code>165c2ae</code></a> (nsqd) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/9c6a1f8eb363e1d09eaef29c97eff7b60053103b"><code>9c6a1f8</code></a> (nsqd) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/92830984c4627f1a034f8fcfcb490a09576aa960"><code>9283098</code></a> (nsqd) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/46acf8a349c2d8462ee2ec0b592bde8a26e5f459"><code>46acf8a</code></a> (nsqd) - k8s: k8s deprecated api migration</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/43caf8058c5c9b129744c1a191f234d3b44c793f"><code>43caf80</code></a> (nsqd) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/689747119e18e2f1151404beb1729cad9d6ea5f6"><code>6897471</code></a> (nsqd) - nsqd: use official image</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/297bc05baf835ffe4d103bb6cb7613aa1286be68"><code>297bc05</code></a> (redis) - redis:replace the special words</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/f5f8b5e75b99f11e20a1b3210e4c4a42e342df92"><code>f5f8b5e</code></a> (redis) - reids: delete the logger prefix of redis</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/af7b657e76bbc1201391fe3915e081bd220b96a8"><code>af7b657</code></a> (redis) - redis: change logger-redis to redis</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/8dca154e5ae4a38b42e1eb6e16e01f3e78d5fee1"><code>8dca154</code></a> (redis) - redis: remove logger from redis conf</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/eaeda2d2650c61768092ea7f5846733328e47dc6"><code>eaeda2d</code></a> (redis) - redis: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/53c6358e7fbaf02ec15d0a01afa5e02769e3bfb4"><code>53c6358</code></a> (redis) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/ae37416efe8b6fcfdfabf2d444bd241e7128d889"><code>ae37416</code></a> (redis) - charts: remove port config</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/e985656354c17c1221d8ec35007710e0b9d4f6a3"><code>e985656</code></a> (redis) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/423336a645aa3b5091b76e88e58b501357cc733c"><code>423336a</code></a> (redis) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/be64ab4c2fd6e1edd33ca8c5a4458c74bf6fa372"><code>be64ab4</code></a> (redis) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/3bec735f6849b5649c5a2416e8fdb76fb6c780d7"><code>3bec735</code></a> (redis) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/4f934f6ee96925b70463c660416706eafc21fc3e"><code>4f934f6</code></a> (redis) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/359b8780f014c1627a1290e32231cd53caf6f762"><code>359b878</code></a> (redis) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/83b8ac299c215de85e85485c6c0546bc25a37ab1"><code>83b8ac2</code></a> (registry) - workflow:replace the special words</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/869b280b55534a7fbd2dfc9052044cb487d97730"><code>869b280</code></a> (registry) - registry: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/999c1e936026b79dc0462da166998f3fa4cebec3"><code>999c1e9</code></a> (registry) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/5652da941334dfdddbe2636d974e9d687b0d912d"><code>5652da9</code></a> (registry) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/cc8c6c2bc077bad277232d25bc536416dfa6c244"><code>cc8c6c2</code></a> (registry) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/c7bdbd0e67e6bcd35423db7d05aca99a511054ed"><code>c7bdbd0</code></a> (registry) - CICD: pretty .drone.yaml format</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/5c55a38592dfd1a7356992018f15f022c02fdfc6"><code>5c55a38</code></a> (registry) - test: use add-host replace link</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/f8866f3e6b4f94e15815e5f79b2adbebe3fd1ed1"><code>f8866f3</code></a> (registry) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/6c8292f9c65b38816fad79bf3f49ff54ad8760dc"><code>6c8292f</code></a> (registry) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/1d50f2ce75f708fd3b07b0c5d5dff2f4bdb8adc7"><code>1d50f2c</code></a> (registry) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/efbca6d2c99e2b170e945f050afa8fb139398a49"><code>efbca6d</code></a> (registry) - chars: change org to imageTag</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/2eafc592dc68c529a8a3a8077ef9d48916718079"><code>2eafc59</code></a> (registry-proxy) - registry-proxy: update nginx</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/071bd86ae3bef755f47e22aad54762a7f1e4c0f1"><code>071bd86</code></a> (registry-proxy) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/c72db9618ee6a73655b4b2c5e940ee9fc9447380"><code>c72db96</code></a> (registry-proxy) - registry-proxy: change travis icon url</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/63ffb920f62b692071fcbf825cbac55bbebe6598"><code>63ffb92</code></a> (registry-proxy) - registry-proxy:replace the special works</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/1d904a61de6cc38bfb071a965de09f5dea0d9996"><code>1d904a6</code></a> (registry-proxy) - registry-proxy: remove docker keyword from charts</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/c8200b1f6f573dba0edb19509fdb56a8357828c7"><code>c8200b1</code></a> (registry-proxy) - docker: use the full name of registry</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/d3fa939d910c7b0c707f191b174d1fce89e4cdb6"><code>d3fa939</code></a> (registry-proxy) - travis: add DEV_REGISTRY</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/5a8b353fa642dbef5929d372ef4ce39657bd40fb"><code>5a8b353</code></a> (registry-proxy) - CICD: use drone</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/703d05a7fa07fc8d5b4c5c4ca0fed8a1ee156536"><code>703d05a</code></a> (registry-proxy) - drone: add image_registries volumes</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/aa71db189c6b489347d8f723bdf881bc0b0abf67"><code>aa71db1</code></a> (registry-proxy) - LICENSE: revert modifications to Apache license</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/710c1260065431acf427bdf7d6d6319024598852"><code>710c126</code></a> (registry-proxy) - drone: always pull image</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/2dcc5e6c4b469cb74b56c8c1f0b69d1d5c58291a"><code>2dcc5e6</code></a> (registry-proxy) - chars: change org to imageTag</li> +</ul> + + + + + + Blog: Drycc Workflow v1.4.0 + /blog/2021/10/06/drycc-workflow-v1.4.0/ + Wed, 06 Oct 2021 00:00:00 +0000 + + /blog/2021/10/06/drycc-workflow-v1.4.0/ + + + + <p>These release notes for Drycc Workflow v1.3.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.4.0, please refer to the following change summary.</p> +<h2 id="workflow--v130---v140">Workflow ## v1.3.0 -&gt; v1.4.0<a class="td-heading-self-link" href="#workflow--v130---v140" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>builder v1.1.0 -&gt; v1.2.0</li> +<li>slugbuilder v1.1.1 -&gt; v1.2.0</li> +<li>dockerbuilder v1.1.1 -&gt; v1.1.2</li> +<li>controller v1.2.1 -&gt; v1.3.0</li> +<li>slugrunner v1.1.1 -&gt; v1.1.2</li> +<li>database v1.0.1 -&gt; v1.0.2</li> +<li>fluentd v1.0.1 -&gt; v1.1.0</li> +<li>redis v1.0.0 -&gt; v1.1.0</li> +<li>logger v1.0.0 -&gt; v1.1.0</li> +<li>minio v1.0.1 -&gt; v1.1.0</li> +<li>monitor v1.0.1 -&gt; v1.1.0</li> +<li>nsqd v1.0.0 -&gt; v1.1.0</li> +<li>registry v1.0.2 -&gt; v1.0.3</li> +<li>registry-proxy v1.0.0 -&gt; v1.0.1</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/fc7d93f718019cfae02b04c745470b4975c91a84"><code>fc7d93f</code></a> (builder) - builder: use go-dev</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/0c2159e4a44f0c3f635dcee1b95afdd741d1935c"><code>0c2159e</code></a> (builder) - builder: fmt code and add create_bucket script</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1b88340205ac77e84ebba7a42215d7d3d40578a0"><code>1b88340</code></a> (controller) - controller: remove deprecated api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a92fdebab64716e4194653a9a17f1c00f70c882d"><code>a92fdeb</code></a> (controller) - routable: ingress support routable</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1e3eab3602538f266305a78c9244be466d685c68"><code>1e3eab3</code></a> (controller) - maintenance: add maintenance support for ingress</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/56b9dd0691c904bd75df928bace98830879eb31d"><code>56b9dd0</code></a> (controller) - crt: support containerd-ctr</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5fc3b46b2acd67af89590f1c7dd85fbfa5e989a6"><code>5fc3b46</code></a> (controller) - controller: add ephemeral-storage restriction</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d677e52c288431517de9ae4bddaaadbd1c8b976c"><code>d677e52</code></a> (controller) - controller: add a volume command</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5f1323a837c71127bb99fd8631934c5bd0cab2a7"><code>5f1323a</code></a> (controller) - controller:drycc run cmd add &ndash;mount para</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/74c36a51eef46ea1c110ee53472be632079ce5e1"><code>74c36a5</code></a> (controller) - tasks: add distributed async task</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/139c3ca9d01d7188c1a499dfffad7b7697e5fd0f"><code>139c3ca</code></a> (controller) - tasks: change nsq reader to async</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f237d74ca6344a5929c9b5089dae07a38c13753b"><code>f237d74</code></a> (controller) - controller:add drycc resource cmd</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/41b46d0653d39d0bdfb42907f7a0b9863bc20992"><code>41b46d0</code></a> (controller) - controller:add drycc resource cmd improvement</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c26f7d82e8fa6fcf4b45ab16fcb0298cb2880f6a"><code>c26f7d8</code></a> (controller) - controller: add LimitRanges support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/45b5d1b904abe94819c3dd306117dcd4e09123ed"><code>45b5d1b</code></a> (controller) - users: add users status api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4e16f9b86ac24b4c62d7d6fddb33278d1880dfa7"><code>4e16f9b</code></a> (controller) - ps:add ps:stop/start command</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/c659fa9e058620fd8ce0ba4fcfc48898f1219f2c"><code>c659fa9</code></a> (controller) - k8s: add k8s cluster domain</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/31a625d71733b47944876ac3fb58fe55cd9b746b"><code>31a625d</code></a> (controller) - ps:add ps:stop/start command</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/00a779a5dbb60a33b621fae13b30a24e39ac55f3"><code>00a779a</code></a> (fluentd) - fluentd: support containerd log format</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/f3f1bd42697f08340b6b6f5fbe161c5b6fbb31b6"><code>f3f1bd4</code></a> (fluentd) - nsqd: add stateless nsqd cluster support</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/db7147c0e7556a655e185c6f00419f99aff4ed29"><code>db7147c</code></a> (fluentd) - mirrors: delete aliyun mirrors</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/689c12eed60f53e1afbbcede91a5955360183fa7"><code>689c12e</code></a> (logger) - nsqd: add stateless nsqd cluster support</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/78ccc5de7718b8f6fb1caf701d1b4ef72fc64362"><code>78ccc5d</code></a> (logger) - redis: add redis client cluster support</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/9843f2cf9d1d03511296bf7731b59d547bc10387"><code>9843f2c</code></a> (logger) - k8s: add k8s cluster domain</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/6ba122e8b6cbdf7b73785d21961056e6b9fc91ee"><code>6ba122e</code></a> (minio) - minio: add pvc support</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/69735500c483f9144f461a2b8a3444e51ddd4dc4"><code>6973550</code></a> (monitor) - monitor: add ingress for monitor</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/cd733053287efbd12c29217cd47c6345c39457ce"><code>cd73305</code></a> (monitor) - charts: add volumeName support</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/4769fe9e8d14bdbdca9447f9df23c67c09db2a45"><code>4769fe9</code></a> (monitor) - nsqd: add stateless nsqd cluster support</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/87806df02cd84fc5feec304e9bc6e32996396b80"><code>87806df</code></a> (monitor) - k8s: add k8s cluster domain</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/4db40c4f129115019ef41c14df56a2d0092e9da1"><code>4db40c4</code></a> (nsqd) - nsqd: add stateless nsqd cluster support</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/b6f3d4fe0f6bc8d3467fdebf21374bed378edf9e"><code>b6f3d4f</code></a> (nsqd) - nsqd: add stateless nsqd cluster support</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/74b85bb9efdcba88a25a2734d512d07ef8068032"><code>74b85bb</code></a> (redis) - redis: change redis to statefulset</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/ff98b5018610d0e2be0ec5c03c7a11232199811a"><code>ff98b50</code></a> (slugbuilder) - slugbuilder: delete build hook</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/b201c2ff207eddac7327f75d698a77e89d4125a1"><code>b201c2f</code></a> (slugbuilder) - buildpacks: use drycc buildpacks</li> +</ul> +<h4 id="fixes">Fixes<a class="td-heading-self-link" href="#fixes" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/0ec042db3c8a4db39088ffe381f518abdb55287d"><code>0ec042d</code></a> (builder) - test: fix test case error</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/4fb113b7351f9f02612b3e14b4d0787b77abb3b2"><code>4fb113b</code></a> (builder) - build: base image replace by alpine</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/443df48c699846c176c1e4a12b5bb42abe790633"><code>443df48</code></a> (builder) - minio: fix not bucket error</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/3dab5b0ce203bcc03891122aca73da5c7342a40b"><code>3dab5b0</code></a> (builder) - minio: create bucket error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/734fca6f371bf73d79d35f1fcdc04ff66cb196fc"><code>734fca6</code></a> (controller) - autoscale: Fix for autoscale on k8s-1.9+ without breaking manual scaling</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a7dcd1000965fae97bad4dc4b908741f856e2d2b"><code>a7dcd10</code></a> (controller) - controller: test pass</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/93f0f2eaa361386bf7775edcbc27c143a71f0dc7"><code>93f0f2e</code></a> (controller) - controller: fix migrations error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4724375b4319e1cbfa1a587e0e856d9eb9b6ac00"><code>4724375</code></a> (controller) - controller: fix test error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7bacf298db4e431c58e86cef028f99fffb5b349e"><code>7bacf29</code></a> (controller) - charts: fix clusterrole</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/90957f727cc883084ff1a81deaada4d62419f0a9"><code>90957f7</code></a> (controller) - pod: sort events error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/440b13edb6e5b9c9fa69f8b6c72f10329a4087d2"><code>440b13e</code></a> (controller) - controller: review table structure</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0a470a6ecffa1fa9d5ef2bb0a71b00ddefb84a1f"><code>0a470a6</code></a> (controller) - controller: bump tornado 5.1.1</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e39218b2216591b7d412baeee5c8e85a7209996d"><code>e39218b</code></a> (controller) - pynsq: no current event loop in thread</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1d8630e250c65051df90b22f023f0f95034f0cc1"><code>1d8630e</code></a> (controller) - tests: fix test_task.py run error</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1ff120213ee452a570a1e23dff85ab3032704a30"><code>1ff1202</code></a> (controller) - controller: fix test case</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d8c0da319db0b559eb8c8b0c28280d7e70613da2"><code>d8c0da3</code></a> (controller) - settings: fix env name</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/6d8fd3605f54c5a3c7ce0d4e5164f772fa22a8ec"><code>6d8fd36</code></a> (database) - 003_restore_from_backup.sh: ignore script exit 1</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/e0394a9a6aa44a066df18b8ad3ddd21e9c9fa1c2"><code>e0394a9</code></a> (database) - minio: fix not bucket error</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/f35f2525602c90dbe397f56005206ed6abf6eb39"><code>f35f252</code></a> (database) - mc: fix create_bucket error</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/74d68865fb7502d04e74418cc2b6ef8316c45778"><code>74d6886</code></a> (database) - postgres: recovery mode not run</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/e50d0c105151dac43b2bbc5f4e316a47dd55e925"><code>e50d0c1</code></a> (dockerbuilder) - caddy: fix caddy not start</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/f3bec7a8a63c586d19caa777b3fa4a7d0de112c7"><code>f3bec7a</code></a> (fluentd) - influxdb: fix influxdb host and port</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/bc19f27d1567281c5c1ae10b9072c9aad33e2013"><code>bc19f27</code></a> (fluentd) - charts: skipped value for daemon_environment: Not a table</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/338d6237ed76464fc47a6ca3d6f3d34927af6aa2"><code>338d623</code></a> (logger) - logger: logger not run in alpine</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/77883026f33f38aa9d01dd4d88298d162a9050e1"><code>7788302</code></a> (minio) - minio: bump minio version</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/619eed0426591646d5fa9e72b77391d6ac817946"><code>619eed0</code></a> (minio) - fix: use go mod replace dep</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/3b42122703b8bfa3203c8115b8d673f2081d2559"><code>3b42122</code></a> (monitor) - monitor: fix host error</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/67998eff2439c406db048a868f61ae9861268449"><code>67998ef</code></a> (monitor) - influxdb: replace drycc-monitor-influxapi to drycc-monitor-influx-api</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/2cc361cf42754562ffa5b6e7c2e14c065e2cd0f1"><code>2cc361c</code></a> (registry) - registry: fix test case</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/548297a7b97e8f28498fa51b50f9232d8c78053b"><code>548297a</code></a> (registry) - minio: fix not bucket error</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/5412ddb1b956fad53d0c59a87c2158b6e014b05f"><code>5412ddb</code></a> (registry) - minio: create bucket error</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/d0d629e5a58d7e91421f2cd344029474e5c630d4"><code>d0d629e</code></a> (slugbuilder) - slugbuilder:fix normalize_storage path</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/d76ecbe4d4d05aeb23a566b2d3c929cca4e63e63"><code>d76ecbe</code></a> (slugbuilder) - slugbuilder: use v3 api</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/c505e182006dd8a734efa14fc851f15340d05929"><code>c505e18</code></a> (slugbuilder) - shellcheck: SC2039</li> +</ul> +<h4 id="style">Style<a class="td-heading-self-link" href="#style" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/c893a1771550c7728f697216b17e38da0f18ec3f"><code>c893a17</code></a> (builder) - builder: fmt code</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/bba5795cd3f3f36bf2a4b6d37661254143f60328"><code>bba5795</code></a> (controller) - controller: format code</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d36082b6f0fbf46487e3fdc6aff0e7866f6462a7"><code>d36082b</code></a> (controller) - controller: fix pep8</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/66026f2f2110fca58f783b8844d9c5b7a794d1f4"><code>66026f2</code></a> (controller) - resource: standardize the naming of resource</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/03d7e2c8bfb120627ec13c4aa37ff7bc3074e88e"><code>03d7e2c</code></a> (controller) - servicecatalog: change servicecatalog to svcat</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/49dbb6d99655dd398978b273ce3fb29051a56cb7"><code>49dbb6d</code></a> (controller) - controller: flake8 upgrade</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/cbfc108b4f209dfbd088f260fe84399bdda5d502"><code>cbfc108</code></a> (monitor) - monitor: format charts and dashboard</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/ee85954d57ae9d19e6e2790090a6fcf1413e8b2d"><code>ee85954</code></a> (slugbuilder) - slugbuilder: use shellcheck</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/3afed2e3592173fcc3522d71dfdbdd45a8b70a01"><code>3afed2e</code></a> (slugbuilder) - docker: simplify dockerfile</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/36b7f688afcb9c8c81016fbbc7b8a3da9537911d"><code>36b7f68</code></a> (slugrunner) - docker: simplify dockerfile</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/61bb0ef367bdabdb3072473e1d639d723b2a8f08"><code>61bb0ef</code></a> (builder) - aws: upgrade aws sdk version</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/0f2e074b748b9f7067cadac63fb83684bc582272"><code>0f2e074</code></a> (builder) - chore: use go mode replace dep</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/e9a2219c2d1c9303cd1a60d2e9bdc9e676f07348"><code>e9a2219</code></a> (builder) - builder: delete glide up</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/bb8c518645bcee82e6ab7782496799b6b82b9fd4"><code>bb8c518</code></a> (builder) - registry: del quay.io</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/fa6d02f54af2daf51c1b08b4b7ad6a3be2425b45"><code>fa6d02f</code></a> (builder) - builder: upgrade go.sum</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/9d61e8da908fae47c33a77c8547e80d1d6d3d812"><code>9d61e8d</code></a> (builder) - build: upgrade go.mod</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/d763a984a800366eb2f6384fbf23c596342720fb"><code>d763a98</code></a> (builder) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/d1bc1aae69b9b16859e11bfa18b1fa2b602bc686"><code>d1bc1aa</code></a> (builder) - pkg: upgrade to new drycc/pkg</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/02b1e98a3b208be80326adb85307663ef931adf6"><code>02b1e98</code></a> (builder) - builder: update go mod</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/8e17d6579e022ce3574ee7582a1f48fc88bb5e95"><code>8e17d65</code></a> (builder) - builder: change alpine repositories</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/f32b723ef49069ffeee6f2419e87b5450617df1e"><code>f32b723</code></a> (builder) - mirrors: delete aliyun mirrors</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/e33dc612d4910ad3b0e56fbb797a7d1dd609bf6d"><code>e33dc61</code></a> (builder) - minio: use bin mc replace docker images</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/3ab4f1c4a587f58230c1c91670831a0927dc6dfb"><code>3ab4f1c</code></a> (builder) - builder: update controller-sdk-go</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/b2adfac62d24626a8dc5f2cf4d011c4610170e3a"><code>b2adfac</code></a> (builder) - heroku: remove heroku-16 support</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/f429ac8fa76a4b59ed36ab9b1dc2bfee19d0be3e"><code>f429ac8</code></a> (builder) - builder: set GIT_LOCK_TIMEOUT to 30 minutes</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/7197c833a68b1168ee4eba0ac16a6fb569f2066e"><code>7197c83</code></a> (builder) - go.mod:upgrade require pkg controller-sdk-go</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5f3e22dc87a55d9bd8fd3299f37be26b19c2350f"><code>5f3e22d</code></a> (controller) - deps: bump django from 1.11.21 to 1.11.22 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1db645af644946d8694234b0b7e1f22e762c5424"><code>1db645a</code></a> (controller) - deps: bump django from 1.11.22 to 1.11.23 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/fbe80677bc8fe7d19772a0bc002fb541106ef75d"><code>fbe8067</code></a> (controller) - deps: bump django from 1.11.23 to 1.11.29 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/537d667d5fd896eec054adda6185042d6492cbd1"><code>537d667</code></a> (controller) - registry: del quay.io</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a23c65b14ba90a60a6d57aa56a12f201ad7ba33b"><code>a23c65b</code></a> (controller) - deps: update all deps to the latest version</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/546337eced482db0b8e879ce8caaa322503f5f52"><code>546337e</code></a> (controller) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/06023f8b84897c4aeaa14fc45c6d35c16eeed1d7"><code>06023f8</code></a> (controller) - workflow-manager: del workflow-manager</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/bba573609e25e87875ca40ccdef6e4dd4c8cfd1a"><code>bba5736</code></a> (controller) - controller: change cluster-issuer location</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/6c436612923a18486982c268d1e23bbd42a3f9a7"><code>6c43661</code></a> (controller) - Certificatechange cluster-issuer location</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/39a47288e3e0bcf7bfa55768c6759ac94c416c33"><code>39a4728</code></a> (controller) - controller:change cluster-issuer location del controller-cluster-issuer.yaml</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9e96d3f9ccda7f8934628444e72e4959bafde91a"><code>9e96d3f</code></a> (controller) - Certificate:upgrade version cert-manager.io/v1alpha2</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8e68049a870b2277663bd0dc09430baa343a5881"><code>8e68049</code></a> (controller) - docker: use INDEX_URL replace index.docker.io</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8fda20583558fefcd239d5e2d6ae09c5c5f881a7"><code>8fda205</code></a> (controller) - cert_manager: change cert_manager_enabled to global</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/6fefb6d00f8909d7269a9171af9db7ba016533c4"><code>6fefb6d</code></a> (controller) - charts: change platform_domain to global</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/064b2ad886b7782598a7f68925d5275ebd88bfd4"><code>064b2ad</code></a> (controller) - maintenance: remove maintenance support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b8797c98a1b2e01f835169ca7493fff508a3cf95"><code>b8797c9</code></a> (controller) - workflow: remove namespace</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1b20d7632a8ca8e4e9f0f6b1c98826af1d846008"><code>1b20d76</code></a> (controller) - quota: add kube quota config</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d780075077cf9f9843ecf79ae36e569eec59cd3d"><code>d780075</code></a> (controller) - pod: add pod default resources support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/3d72c0817b582f050321396240bd4a6bad3bfb16"><code>3d72c08</code></a> (controller) - rename: rename ingress name</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0aa6ab9cd277231420b1404b922601debe0aa89b"><code>0aa6ab9</code></a> (controller) - mirrors: delete aliyun mirrors</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7533a65e78efd06ebe809712791c5399b85efcba"><code>7533a65</code></a> (controller) - heroku: remove heroku-16 support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e5a885d676f052ffdee6bc74e2fe0cffb85a1f86"><code>e5a885d</code></a> (controller) - controller:check mount volume path</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9014e74b5c0312014aa9d20cf9d6aff128f8022f"><code>9014e74</code></a> (controller) - test: optimization Dockerfile.test</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/0b6ebb2f0e18f7e97ed2bb7b2c6008e3be7248f2"><code>0b6ebb2</code></a> (controller) - tasks: change apply_async parameters</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/835f009573d5643d271b6e558793b1c9ae1463da"><code>835f009</code></a> (controller) - wsgi: add tornado 6 support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/67a4ad7cbd50cd9de1214e8d4be27196e8077367"><code>67a4ad7</code></a> (controller) - utils: use threads replace asyncio</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a28949b093e9f4d73c798f24e41d1eaff0cc1cc2"><code>a28949b</code></a> (controller) - ldap: add AUTH_LDAP_USER_FLAGS_BY_GROUP</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a903209c062f3e275f97bc18dc1d2b9a17e1a826"><code>a903209</code></a> (controller) - charts: add custom controller environment variables support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e0e783ecb5e87bf68e83411cfd92f54916aa9931"><code>e0e783e</code></a> (controller) - ldap: change filter style</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d7608251c2f8938b8f5ee1edd0c7d0f371931826"><code>d760825</code></a> (controller) - scheduler: remove debug log</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/a25928ee84e75a84c13c5402cc351e1ec6e3f151"><code>a25928e</code></a> (controller) - wsgi: remove a wsgi.py file</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7b2696e3ea066b59395b63d97fbad5a472d49b5b"><code>7b2696e</code></a> (controller) - log: disable nsq.client info log</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8d5c07b49ba4220ba7946a8bef1a22b1e8d78e47"><code>8d5c07b</code></a> (controller) - charts: add default environment</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/025f4a2ea96c883df3c35b961aaac2bdd9a5b4ea"><code>025f4a2</code></a> (controller) - controller: change quota name</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/ebda60ed125f49524169cb320c79c37d5adc2e6c"><code>ebda60e</code></a> (controller) - controller: review pvc code</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/8832ba952281c2a06dc98dfc6726e7f9e9207d81"><code>8832ba9</code></a> (controller) - controller: change status\binding model type and mount path check container_types</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7148d04c5f1223f06747fae9a33cb3787159ce9e"><code>7148d04</code></a> (controller) - controller: add overcommit cpu and ram support</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4d2087cc9c783e5c2722fd446b64c7263b783001"><code>4d2087c</code></a> (controller) - limits: modify limits unit verification</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/af36970d90b9a8d95857052ab1c97b7727a01976"><code>af36970</code></a> (controller) - api: check cpu/memory range for api</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/329355b6cdde8a382a5fe271f764cca747cd9444"><code>329355b</code></a> (controller) - volumes: modify the volume size</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/9dfee0919449d13e11ec3cfe50a187ecd5de07b2"><code>9dfee09</code></a> (controller) - LimitRanges: modify the default limits</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/5205bca582cd292fcfa7c0abb1bcc98c3dce05f1"><code>5205bca</code></a> (controller) - controller: improve the details of certificate</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/7ebecdfdca2de4936b67bc542053305f098db6d6"><code>7ebecdf</code></a> (database) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/6415e2ccacef3af313b4df2e7d0924797217238f"><code>6415e2c</code></a> (database) - postgres: upgrade to pg13</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/12e68062d48938c8619f94c30741af6fd2fee8e9"><code>12e6806</code></a> (database) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/d294509c192eb7e2f6f11aedad8aefff83fb8532"><code>d294509</code></a> (database) - minio: use canary minio test</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/1bad02e1768d4d54df61f7df3e54c81bd68e6c52"><code>1bad02e</code></a> (database) - mirrors: delete aliyun mirrors</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/d51420bbde24cada100f764288c9bd165dbc9f31"><code>d51420b</code></a> (database) - minio: use bin mc replace docker images</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/4133d05d8edec1f1ba2b995354dc98ae863a1da7"><code>4133d05</code></a> (dockerbuilder) - dockerbuilder: update caddy and kaniko</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/6b4dd18637b3a81a64c1be34a6d73832095c638d"><code>6b4dd18</code></a> (dockerbuilder) - minio: use bin mc replace docker images</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/6df9b7c0bc4a22bca7ed2588a070868680382f68"><code>6df9b7c</code></a> (fluentd) - deps-dev: update rake requirement from ~&gt; 10.0 to ~&gt; 12.3</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/c2490f84d991ddfc588bded7e6afe9706e82f090"><code>c2490f8</code></a> (fluentd) - fluentd: upgrade fluentd</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/be4a56a12ce0c8a812b8922630122225532ac3fa"><code>be4a56a</code></a> (fluentd) - fluentd: add Gemfile.lock</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/2237f755e0123eb4138289648b5a0ee64bbd4183"><code>2237f75</code></a> (fluentd) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/c5740650bcb218c59676733c20f5765ae4cb905d"><code>c574065</code></a> (fluentd) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/52b8084cbaa5d0b8c8ca7014f94b596dca911708"><code>52b8084</code></a> (fluentd) - router: delete obsolete router code</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/3b3ccebeced1c4257c0c3ed1a70b7f18a8c6aa85"><code>3b3cceb</code></a> (fluentd) - fluentd: remove manifests dir</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/25c6702f8c1e1c5916b0544ccda64eced3451448"><code>25c6702</code></a> (fluentd) - nsqd: change var name</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/bd571be4178f69cb4bd7ee233440ca889ec5c601"><code>bd571be</code></a> (fluentd) - nsqd: change DRYCC_NSQD_ADDRESSES to DRYCC_NSQD_ADDRS</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/72aa4e6b7fe5cb5ef784f894429e3f1e177e5c82"><code>72aa4e6</code></a> (fluentd) - influxdb: change influxdb service name</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/bd61903dd01aa61374a5f527f8ee85bc7820c042"><code>bd61903</code></a> (logger) - logger: use go mod replace dep</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/69c63a1bd602c9a5a68ef3b93d43b2dca161d495"><code>69c63a1</code></a> (logger) - logger: update go.mod</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/3aa9cd715568b46efa26025f25c73ce897436b4f"><code>3aa9cd7</code></a> (logger) - registry: del quay.io</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/f05849639ef8e34bacf9a55965ab3d7297df4cf7"><code>f058496</code></a> (logger) - nsqd: change var name</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/6d9787cebb2e992de9743ac0544201b012b21094"><code>6d9787c</code></a> (logger) - nsqd: change DRYCC_NSQD_ADDRESSES to DRYCC_NSQD_ADDRS</li> +<li><a href="https://api.github.com/repos/drycc/logger/git/trees/85ed307592a38ae80186f59bf31e504124013e07"><code>85ed307</code></a> (logger) - logger: standard naming</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/d88e7b65131e2fdaa7d4164a4d66793d89cc384d"><code>d88e7b6</code></a> (minio) - minio: update minio api to v7</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/43715d2dd30bc15f5564124e0e5e444ce7ca63c2"><code>43715d2</code></a> (minio) - minio: upgrade minio</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/0e1239b358ce3bde11a1401634f519b7e1c38156"><code>0e1239b</code></a> (minio) - minio: use docker.io replace quay.io</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/f7f047b506a0e6b30b7b88e916d67b1faaba8a52"><code>f7f047b</code></a> (minio) - registry: del quay.io</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/afa71289345ed311e603c8847188ccef40774869"><code>afa7128</code></a> (minio) - build: upgrade go.mod</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/aff2db5a41ae72b899f2fc9f70af96730ed16fdf"><code>aff2db5</code></a> (minio) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/4547f14617a76db897b71ef7451db92a832dff1e"><code>4547f14</code></a> (minio) - pkg: upgrade to new drycc/pkg</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/2769b85cbd316cb08da58753d6bae3946d32032a"><code>2769b85</code></a> (minio) - minio: use bin mc replace docker images</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/35dde8df07fb96c4996ef8410780da48e1170e4a"><code>35dde8d</code></a> (monitor) - monitor: update grafana influxdb telegraf</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/9e3a949734f326290dd752c636991cf2e1c962f9"><code>9e3a949</code></a> (monitor) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/6af0432fe174769e9d44c03c264ad4a9ea5cee5f"><code>6af0432</code></a> (monitor) - workflow-manager: remove workflow-manager</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/0611c07996da19eb1401278ad5cc5e46d3b1435c"><code>0611c07</code></a> (monitor) - router: delete obsolete router code</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/be048248577d97f8679863c179999ce843806c09"><code>be04824</code></a> (monitor) - cert_manager: change cert_manager_enabled to global</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/37801650414da8539390c4d7cad66f614b90ef6e"><code>3780165</code></a> (monitor) - charts: change platform_domain to global</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/50b04e15f9c3aa51751bb78250907fa22023a419"><code>50b04e1</code></a> (monitor) - influxdb: remove influxdb admin ui</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/6ab4d68b758904d12697b9a129835e6d0474cafb"><code>6ab4d68</code></a> (monitor) - influxdb: remove unuse port</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/f1510bd94e48ea41ff4c36ac2140688b5c2dde87"><code>f1510bd</code></a> (monitor) - monitor: update grafana dashboard,telegraf inputs.kubernetes</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/f36de2c251dc63b21a1fdc2c05413d6d50e9f8cb"><code>f36de2c</code></a> (monitor) - pvc: upgrade to new format</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/fc78a0a2627b51a28c730e19f2c8c1c16103829f"><code>fc78a0a</code></a> (monitor) - workflow: remove namespace</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/e85890f298dd68cf6c0e8af70d843e84da600361"><code>e85890f</code></a> (monitor) - monitor: monitoring nsqd and redis separately</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/694f6b1dc801769a8fe82b90ba26422747df6539"><code>694f6b1</code></a> (monitor) - mirrors: delete aliyun mirrors</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/4aea36a822079ba593a646683dba0e35e3e68416"><code>4aea36a</code></a> (monitor) - grafana: add ldap support for grafana</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/68fc30f0f05af759b80e07c4dcd3d2a57c7ffd6a"><code>68fc30f</code></a> (nsqd) - nsq: update nsq</li> +<li><a href="https://api.github.com/repos/drycc/nsqd/git/trees/16f32aaf7b984b24853044b6619dbe9f2b8613e2"><code>16f32aa</code></a> (nsqd) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/04db389e01f6832a6a105a73a0a02c9b7dd6623b"><code>04db389</code></a> (redis) - reids: update to redis 6</li> +<li><a href="https://api.github.com/repos/drycc/redis/git/trees/3f01bab0dbe89fa4094750bdb5c3f0ac503b8f00"><code>3f01bab</code></a> (redis) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/647e4bed5f617727fd50c5e0645fd27cc128461e"><code>647e4be</code></a> (registry) - registry: del quay.io</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/0bbce990d4ff5660ce79020e0bca346a0c716b3d"><code>0bbce99</code></a> (registry) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/a982b503350abfd584d33d0e088bc0a79714fb9c"><code>a982b50</code></a> (registry) - minio: use bin mc replace docker images</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/e088da3304147b568868e0546c321b57f84263b9"><code>e088da3</code></a> (registry-proxy) - ingress: renmae use_native_ingress to use_ingress</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/7e88337bbfbc73bc30bd0906f25027c5d266b1c2"><code>7e88337</code></a> (registry-proxy) - nginx: upgrade nginx to mainline</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/7204d72c00b2d7360a2d3a20833d701e303a9f62"><code>7204d72</code></a> (registry-proxy) - registry: optimizing variable naming</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/2eafc592dc68c529a8a3a8077ef9d48916718079"><code>2eafc59</code></a> (registry-proxy) - registry-proxy: update nginx</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/071bd86ae3bef755f47e22aad54762a7f1e4c0f1"><code>071bd86</code></a> (registry-proxy) - charts: upgrade k8s newer API versions</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/c72db9618ee6a73655b4b2c5e940ee9fc9447380"><code>c72db96</code></a> (registry-proxy) - registry-proxy: change travis icon url</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/ca9f9623a6867f0c5f4ff973c06613deff9e5dd3"><code>ca9f962</code></a> (slugbuilder) - slugbuilder: del BUILDPACK_URL support</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/1b74dd57a7f19040577f8e55b6a9d993ef496c8d"><code>1b74dd5</code></a> (slugbuilder) - slugbuilder: add heroku-20 support</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/54d4ad2e97e9ff5c805ac985a0e5af0050677388"><code>54d4ad2</code></a> (slugbuilder) - slugbuilder: del quay.io</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/a78f37ee99cec1b7c3eb7cb7a803bf2a5ed7c45b"><code>a78f37e</code></a> (slugbuilder) - slugbuilder: add heroku-20 stack</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/94ac94ac5dd4a387c0e1aaef6638954e41e9983a"><code>94ac94a</code></a> (slugbuilder) - minio: use bin mc replace docker images</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/53b4b8b7ef9dece421a7893c5c3137ab0df8b960"><code>53b4b8b</code></a> (slugbuilder) - slugbuilder: modify stack priority</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/58e2bd28cf5fda8c618a2ba540d9e3acbf46fab5"><code>58e2bd2</code></a> (slugbuilder) - dockerfile: add WORKDIR /tmp</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/b29cd04c1769ef3481ff7c61c41a6e8722664469"><code>b29cd04</code></a> (slugbuilder) - slugbuilder: add pre_build.sh</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/9d319f60a1edd735bc5217054fe365047bd8795a"><code>9d319f6</code></a> (slugbuilder) - slugbuilder: silent mc command output</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/d1ec3c983be9934dd6b86fa51200489eb5555fa7"><code>d1ec3c9</code></a> (slugbuilder) - heroku: remove heroku-16 support</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/5048534c684b76f41ca12136cefd6e6da51ace3e"><code>5048534</code></a> (slugbuilder) - slugbuilder: use drycc stack-images</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/a1165373fc9ca369eec2715a2a49f166430cefa9"><code>a116537</code></a> (slugrunner) - slugrunner: add heroku-20 support</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/a1196bf153c21cefde2122aee5bf7dfa32ac5f0a"><code>a1196bf</code></a> (slugrunner) - slugrunner: del quay.io</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/64c96d720f4b5cdc54b66d349bac6de5567ab331"><code>64c96d7</code></a> (slugrunner) - slugrunner: add heroku-20 stack</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/cc3e2264b67f950fb888502aeea08d41d4c8ccf4"><code>cc3e226</code></a> (slugrunner) - minio: use bin mc replace docker images</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/9130bde01bcfa897ae5c4be6bc59b4a4fe7b92f3"><code>9130bde</code></a> (slugrunner) - shellcheck: shellcheck installer</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/4ea33e154ab4353de5bd5bf6afeb0157756224e8"><code>4ea33e1</code></a> (slugrunner) - slugrunner: modify stack priority</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/5514e8b393daa6f4cd8f3ebe0a619158e32945e6"><code>5514e8b</code></a> (slugrunner) - heroku: remove heroku-16 support</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/be829fb66e68bb9ccc2a1d49e1b364af09219fff"><code>be829fb</code></a> (slugrunner) - slugrunner: use drycc stack-images</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/e1e06be74f2f40740c8e72178ae6ba97233c5bbe"><code>e1e06be</code></a> (slugrunner) - slugrunner: remove Dockerfile.heroku-16</li> +</ul> + + + + + + Blog: Drycc Workflow v1.3.0 + /blog/2020/10/06/drycc-workflow-v1.3.0/ + Tue, 06 Oct 2020 00:00:00 +0000 + + /blog/2020/10/06/drycc-workflow-v1.3.0/ + + + + <p>These release notes for Drycc Workflow v1.3.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.2.0, please refer to the following change summary.</p> +<h2 id="workflow--v120---v130">Workflow ## v1.2.0 -&gt; v1.3.0<a class="td-heading-self-link" href="#workflow--v120---v130" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>builder v1.0.2 -&gt; v1.1.0</li> +<li>slugbuilder v1.1.0 -&gt; v1.1.1</li> +<li>dockerbuilder v1.1.0 -&gt; v1.1.1</li> +<li>controller v1.2.0 -&gt; v1.2.1</li> +<li>slugrunner v1.1.0 -&gt; v1.1.1</li> +<li>database v1.0.0 -&gt; v1.0.1</li> +<li>fluentd v1.0.0 -&gt; v1.0.1</li> +<li>minio v1.0.0 -&gt; v1.0.1</li> +<li>monitor v1.0.0 -&gt; v1.0.1</li> +<li>registry v1.0.1 -&gt; v1.0.2</li> +<li>workflow-manager v1.0.0 -&gt; v1.0.1</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/9c7cceb2b775850cbe30c6df7b03bdcf7a35d0d2"><code>9c7cceb</code></a> (builder) - builder: add app config to env</li> +</ul> +<h4 id="fixes">Fixes<a class="td-heading-self-link" href="#fixes" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/7fe44faf2663b20e39b27221a8426cf332f2085b"><code>7fe44fa</code></a> (controller) - docker: docker timeout must be an int, float or None</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/b196550f9ac51f22f422e29d6b1a7aa3708421c3"><code>b196550</code></a> (controller) - controller: revert release.check_image_access for now</li> +<li><a href="https://api.github.com/repos/drycc/workflow-manager/git/trees/cc3ec13a5d5173160f1f6b42726df81119cd69ae"><code>cc3ec13</code></a> (workflow-manager) - glide: bump goautoneg</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/ef932c4eb4ea0d592b57f0a4aebdbd6ad039c998"><code>ef932c4</code></a> (builder) - controller-sdk-go: upgrade controller-sdk-go</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4654cf64a919aa64b10253b080e0b6aae86edcb5"><code>4654cf6</code></a> (controller) - django-rest-framework: upgrade to 3.9.3</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/14121f1dae135b137f8ded451cfd1d8f8ca62543"><code>14121f1</code></a> (controller) - deps: bump djangorestframework from 3.9.3 to 3.9.4 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/385acdc7e0359eedb83e10e71877a9ff591bff15"><code>385acdc</code></a> (controller) - deps: bump django from 1.11.20 to 1.11.21 in /rootfs</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/fa312bb7f57f5f8638484bc4d9825aa962031a25"><code>fa312bb</code></a> (database) - postgres: set max_connections = 1024</li> +<li><a href="https://api.github.com/repos/drycc/postgres/git/trees/7ebecdfdca2de4936b67bc542053305f098db6d6"><code>7ebecdf</code></a> (database) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/b8878f6d4c32540bc864581a457aa6c996e7e50c"><code>b8878f6</code></a> (dockerbuilder) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z</li> +<li><a href="https://api.github.com/repos/drycc/fluentd/git/trees/b097451f312c0386c466be3b638242535849def0"><code>b097451</code></a> (fluentd) - fluent: upgrade fluent to v1.4</li> +<li><a href="https://api.github.com/repos/drycc/minio/git/trees/4341f9ae71b5dc55c14984d9cacc8e48a3e6e089"><code>4341f9a</code></a> (minio) - mc: upgrade mc and minio</li> +<li><a href="https://api.github.com/repos/drycc/monitor/git/trees/c1ee2a46808c6054ab1393cdd31bf861e01ebdfc"><code>c1ee2a4</code></a> (monitor) - monitor: remove copyrights.tar.gz</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/9854260ef4738be5d25e4a028ebd3125988fec34"><code>9854260</code></a> (registry) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/acc5627dd8f96d3f62e02cd8813cbd829321bd18"><code>acc5627</code></a> (slugbuilder) - slugbuilder: internal support for multi buildpack</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/d58907eb664185c25950953dae4fe4774a2f6310"><code>d58907e</code></a> (slugbuilder) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/b39a0c29fef7d76ae681ec7ba2f01e3605a33657"><code>b39a0c2</code></a> (slugrunner) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z</li> +</ul> + + + + + + Blog: Drycc Workflow v1.2.0 + /blog/2019/10/06/drycc-workflow-v1.2.0/ + Sun, 06 Oct 2019 00:00:00 +0000 + + /blog/2019/10/06/drycc-workflow-v1.2.0/ + + + + <p>These release notes for Drycc Workflow v1.2.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.1.0, please refer to the following change summary.</p> +<h2 id="workflow--v110---v120">Workflow ## v1.1.0 -&gt; v1.2.0<a class="td-heading-self-link" href="#workflow--v110---v120" aria-label="Heading self-link"></a></h2> +<h4 id="releases">Releases<a class="td-heading-self-link" href="#releases" aria-label="Heading self-link"></a></h4> +<ul> +<li>builder v1.0.1 -&gt; v1.0.2</li> +<li>slugbuilder v1.0.0 -&gt; v1.1.0</li> +<li>dockerbuilder v1.0.0 -&gt; v1.1.0</li> +<li>controller v1.1.0 -&gt; v1.2.0</li> +<li>slugrunner v1.0.0 -&gt; v1.1.0</li> +<li>registry v1.0.0 -&gt; v1.0.1</li> +<li>registry-proxy v1.0.1 -&gt; v1.0.2</li> +</ul> +<h4 id="features">Features<a class="td-heading-self-link" href="#features" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/e5584e32ef02329fd091a7a4d3f40bac9894d5a4"><code>e5584e3</code></a> (controller) - controller: add STACK support</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/ad34dc1a501aada4aa2f8ceeb7eefa9fed6baf75"><code>ad34dc1</code></a> (dockerbuilder) - kaniko: use kaniko replace docker-py</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/b81430e8d7ac10167450667cf41e2f9efada6cca"><code>b81430e</code></a> (dockerbuilder) - dockerbuilder: change image to image.json format</li> +<li><a href="https://api.github.com/repos/drycc/slugbuilder/git/trees/60dde96064c69aa7578476c2e4855680f5186706"><code>60dde96</code></a> (slugbuilder) - slugbuilder: add STACK support</li> +<li><a href="https://api.github.com/repos/drycc/slugrunner/git/trees/fe8b6e56dd1a9334844581183bb16eb3d59df366"><code>fe8b6e5</code></a> (slugrunner) - slugrunner: add STACK support</li> +</ul> +<h4 id="maintenance">Maintenance<a class="td-heading-self-link" href="#maintenance" aria-label="Heading self-link"></a></h4> +<ul> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/942f050ec90f771262cbb5634f5df8d5a3818a5d"><code>942f050</code></a> (builder) - registry: remove env DRYCC_REGISTRY_PROXY_PORT</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/ff7a16f53ac78dac0c334a9718cdc76c65400732"><code>ff7a16f</code></a> (builder) - registry: remove ecr and gcr registry</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/ad13683ce634c9b4835f45d2b474bac16ca52baa"><code>ad13683</code></a> (builder) - builder: change DRYCC_BUILD_TYPE to DRYCC_STACK</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/6def637d5331330940d0a94cf6313a4bcb67fec0"><code>6def637</code></a> (builder) - registry: rename DRYCC_REGISTRY_SERVICE to DRYCC_REGISTRY_PROXY</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/5044e223a56ee6283ac8d68a1442a6430b18dd99"><code>5044e22</code></a> (builder) - registry: remove registry_secret_prefix</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/2ea39cc0a9dd68fa1baca4b3725a00b9bcf7f89a"><code>2ea39cc</code></a> (builder) - controller-go-sdk: upgrade controller-go-sdk</li> +<li><a href="https://api.github.com/repos/drycc/builder/git/trees/6aee0d7f092b53c37c70d05db076eaae1bbcff44"><code>6aee0d7</code></a> (builder) - registry: optimizing variable naming</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f9c62d9db809bfe03af33092e71a16e56fc35483"><code>f9c62d9</code></a> (controller) - domain: added reserved domain check</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/f5a135be6aa2b319e623fd59bb711705d1cfe13f"><code>f5a135b</code></a> (controller) - migrations: clean old migrations</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/4369b2c2fb6ef861978588a61efa1bfc6a4572ec"><code>4369b2c</code></a> (controller) - registry: rename DRYCC_REGISTRY_SERVICE to DRYCC_REGISTRY_PROXY</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/1057ca59c3ae6bbd85d772f6b49b0c542d7d18c4"><code>1057ca5</code></a> (controller) - registry: remove registry_secret_prefix</li> +<li><a href="https://api.github.com/repos/drycc/controller/git/trees/d114b3e93544624a5f01b1ca71db92d0b33f4e0d"><code>d114b3e</code></a> (controller) - docker: update docker client</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/edbe9631dcfb34ed50d9e931d36506fa262b6299"><code>edbe963</code></a> (dockerbuilder) - dockerfile: change base image to alpine</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/fb35baf913ff846e08ba79d9ad8195fca1411684"><code>fb35baf</code></a> (dockerbuilder) - registry: rename DRYCC_REGISTRY_SERVICE to DRYCC_REGISTRY_PROXY</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/946dbf688474933f821f641f6c027bab68cd9e79"><code>946dbf6</code></a> (dockerbuilder) - docker: remove insecure support</li> +<li><a href="https://api.github.com/repos/drycc/dockerbuilder/git/trees/628d8532256e32a046268491f2a331dcb608b713"><code>628d853</code></a> (dockerbuilder) - proxy: add registry proxy</li> +<li><a href="https://api.github.com/repos/drycc/registry/git/trees/ff27cbdd27e9dc51ce29b6a68777888ed8737862"><code>ff27cbd</code></a> (registry) - env: remove unused env</li> +<li><a href="https://api.github.com/repos/drycc/registry-proxy/git/trees/7204d72c00b2d7360a2d3a20833d701e303a9f62"><code>7204d72</code></a> (registry-proxy) - registry: optimizing variable naming</li> +</ul> + + + + + + Blog: Welcome to Drycc + /blog/2018/10/06/welcome-to-drycc/ + Sat, 06 Oct 2018 00:00:00 +0000 + + /blog/2018/10/06/welcome-to-drycc/ + + + + <p><strong>Drycc Workflow</strong> is an open source Container as a Service (CaaS) that adds a developer-friendly layer to any <a href="http://kubernetes.io">Kubernetes</a> cluster, making it easy to deploy and manage applications.</p> +<p>We welcome your input! If you have feedback, please <a href="https://github.com/drycc/workflow/issues">submit an issue</a>. If you&rsquo;d like to participate in development, please read the &ldquo;Working on Documentation&rdquo; section below and <a href="https://github.com/drycc/workflow/pulls">submit a pull request</a>.</p> + + + + + + diff --git a/install-cli.sh b/install-cli.sh new file mode 100644 index 000000000..882aa6c3b --- /dev/null +++ b/install-cli.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +set -eo pipefail +shopt -s expand_aliases + +check_platform_arch() { + local supported="darwin-amd64 darwin-arm64 linux-amd64 linux-386 linux-arm linux-arm64 windows-386 windows-amd64" + + if ! echo "${supported}" | tr ' ' '\n' | grep -q "${PLATFORM}-${ARCH}"; then + cat < + + old_lang=$LANG + LANG=C + + old_lc_collate=$LC_COLLATE + LC_COLLATE=C + + local length="${#1}" + for (( i = 0; i < length; i++ )); do + local c="${1:i:1}" + case $c in + [a-zA-Z0-9.~_-]) printf "$c" ;; + *) printf '%%%02X' "'$c" ;; + esac + done + + LANG=$old_lang + LC_COLLATE=$old_lc_collate +} + +function install_helm { + if [[ "${INSTALL_DRYCC_MIRROR}" == "cn" ]] ; then + version=$(curl -Ls https://drycc-mirrors.drycc.cc/helm/helm/releases|grep /helm/helm/releases/tag/ | sed -E 's/.*\/helm\/helm\/releases\/tag\/(v[0-9\.]{1,}(-rc.[0-9]{1,})?)".*/\1/g' | head -1) + tar_name="helm-${version}-linux-${ARCH}.tar.gz" + helm_download_url="https://drycc-mirrors.drycc.cc/helm/${tar_name}" + else + version=$(curl -Ls https://github.com/helm/helm/releases|grep /helm/helm/releases/tag/ | sed -E 's/.*\/helm\/helm\/releases\/tag\/(v[0-9\.]{1,}(-rc.[0-9]{1,})?)".*/\1/g' | head -1) + tar_name="helm-${version}-linux-${ARCH}.tar.gz" + helm_download_url="https://get.helm.sh/${tar_name}" + fi + curl -fsSL -o "${tar_name}" "${helm_download_url}" + tar -zxvf "${tar_name}" + mv "linux-${ARCH}/helm" /usr/local/bin/helm + rm -rf "${tar_name}" "linux-${ARCH}" +} + +function configure_os { + echo -e "\\033[32m---> Start configuring kernel parameters\\033[0m" + if [[ "$(command -v iptables)" != "" ]] ; then + iptables -F + iptables -X + iptables -F -t nat + iptables -X -t nat + iptables -P FORWARD ACCEPT + else + # Kube hostport depends on iptables + echo -e "\\033[33m---> The iptables does not exist...\\033[0m" + exit 1 + fi + swapoff -a + sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab + mount bpffs -t bpf /sys/fs/bpf + rmem_max=$(sysctl -ne net.core.rmem_max) + if [ ! -n "$rmem_max" ] || [ 2500000 -gt $rmem_max ] ;then + echo 'net.core.rmem_max = 2500000' >> /etc/sysctl.conf + fi + nr_hugepages=$(sysctl -ne vm.nr_hugepages) + if [ ! -n "$nr_hugepages" ] || [ 1024 -gt $nr_hugepages ] ;then + echo 'vm.nr_hugepages = 1024' >> /etc/sysctl.conf + fi + max_user_instances=$(sysctl -ne fs.inotify.max_user_instances) + if [ ! -n "$max_user_instances" ] || [ 65535 -gt $max_user_instances ] ;then + echo 'fs.inotify.max_user_instances = 65535' >> /etc/sysctl.conf + fi + sysctl -p + + cpufreq=$(ls /sys/devices/system/cpu/cpu*/cpufreq >/dev/null 2>&1 || echo "false") + if [[ $cpufreq != "false" ]]; then + for cpu in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do + echo performance > $cpu + done + fi + echo -e "\\033[32m---> Configuring kernel parameters finish\\033[0m" +} + +function install_runtime { + # download crun + if [[ "${INSTALL_DRYCC_MIRROR}" == "cn" ]] ; then + crun_base_url="https://drycc-mirrors.drycc.cc/containers" + else + crun_base_url="https://github.com/containers" + fi + crun_version=$(curl -Ls ${crun_base_url}/crun/releases|grep /containers/crun/releases/tag/ | sed -E 's/.*\/containers\/crun\/releases\/tag\/([0-9\.]{1,}(-rc.[0-9]{1,})?)".*/\1/g' | head -1) + crun_download_url=${crun_base_url}/crun/releases/download/${crun_version}/crun-${crun_version}-linux-${ARCH} + curl -sfL "${crun_download_url}" -o /usr/local/bin/crun + chmod a+rx /usr/local/bin/crun +} + +function configure_containerd { + CONTAINERD_ETC_PATH="/var/lib/rancher/k3s/agent/etc/containerd" + CONTAINERD_CONFIG_FILE="${CONTAINERD_ETC_PATH}/config.toml.tmpl" + mkdir -p "${CONTAINERD_ETC_PATH}" + if [[ -f "${REGISTRY_FILE}" ]]; then + cat "${REGISTRY_FILE}" > "${CONTAINERD_CONFIG_FILE}" + else + cat << EOF > "${CONTAINERD_CONFIG_FILE}" +[plugins.cri.containerd] + snapshotter = "overlayfs" + default_runtime_name = "crun" + disable_snapshot_annotations = true +[plugins.cri.containerd.runtimes.crun] + runtime_type = "io.containerd.runc.v2" +[plugins.cri.containerd.runtimes.crun.options] + SystemdCgroup = true +[plugins.cri.containerd.runtimes.runc] + runtime_type = "io.containerd.runc.v2" +[plugins.cri.containerd.runtimes.runc.options] + SystemdCgroup = true +EOF + if [[ "${INSTALL_DRYCC_MIRROR}" == "cn" ]]; then + if [[ "$1" == "runtime" ]] ; then + cat << EOF >> "${CONTAINERD_CONFIG_FILE}" +[plugins.cri.registry.mirrors] +[plugins.cri.registry.mirrors."docker.io"] + endpoint = ["https://docker-mirror.drycc.cc", "https://registry-1.docker.io"] +EOF + else + cat << EOF >> "${CONTAINERD_CONFIG_FILE}" +[plugins.cri.registry.mirrors] +[plugins.cri.registry.mirrors."docker.io"] + endpoint = ["https://docker-mirror.drycc.cc", "https://registry-1.docker.io"] +[plugins.cri.registry.mirrors."quay.io"] + endpoint = ["https://quay-mirror.drycc.cc", "https://quay.io"] +[plugins.cri.registry.mirrors."gcr.io"] + endpoint = ["https://gcr-mirror.drycc.cc", "https://gcr.io"] +[plugins.cri.registry.mirrors."registry.k8s.io"] + endpoint = ["https://k8s-mirror.drycc.cc", "https://registry.k8s.io"] +EOF + fi + fi + fi +} + +function configure_mirrors { + echo -e "\\033[32m---> Start configuring mirrors\\033[0m" + if [[ "${INSTALL_DRYCC_MIRROR}" == "cn" ]] ; then + INSTALL_K3S_MIRROR="${INSTALL_DRYCC_MIRROR}" + k3s_install_url="https://drycc-mirrors.drycc.cc/get-k3s/" + K3S_RELEASE_URL=https://drycc-mirrors.drycc.cc/k3s-io/k3s/releases + export INSTALL_K3S_MIRROR + else + k3s_install_url="https://get.k3s.io" + K3S_RELEASE_URL=github.com/k3s-io/k3s/releases + fi + if [ -z "${INSTALL_K3S_VERSION}" ]; then + INSTALL_K3S_VERSION=$(curl -Ls "$K3S_RELEASE_URL" | grep /k3s-io/k3s/releases/tag/ | sed -E 's/.*\/k3s-io\/k3s\/releases\/tag\/(v[0-9\.]{1,}[rc0-9\-]{0,}%2Bk3s[0-9])".*/\1/g' | head -1) + else + INSTALL_K3S_VERSION=$(urlencode "$INSTALL_K3S_VERSION") + fi + export INSTALL_K3S_VERSION + echo -e "\\033[32m---> Configuring mirrors finish\\033[0m" +} + +function install_k3s_server { + configure_os + install_runtime + configure_mirrors + configure_containerd + INSTALL_K3S_EXEC="server ${INSTALL_K3S_EXEC} --embedded-registry --flannel-backend=none --disable-network-policy --disable=traefik --disable=servicelb --disable-kube-proxy --cluster-cidr=${CLUSTER_CIDR} --service-cidr=${SERVICE_CIDR} --cluster-domain=${CLUSTER_DOMAIN}" + if [[ -n "${K3S_DATA_DIR}" ]] ; then + INSTALL_K3S_EXEC="$INSTALL_K3S_EXEC --data-dir=${K3S_DATA_DIR}/rancher/k3s" + fi + if [[ -z "${K3S_URL}" ]] ; then + INSTALL_K3S_EXEC="$INSTALL_K3S_EXEC --cluster-init" + fi + curl -sfL "${k3s_install_url}" |INSTALL_K3S_EXEC="$INSTALL_K3S_EXEC" sh -s - + kubectl apply -f - < The path ${METALLB_CONFIG_FILE} does not exist...\\033[0m" + exit 1 + fi +} + +function install_network() { + command=${1:-"install"} + options=${2:-""} + echo -e "\\033[32m---> Start $command network...\\033[0m" + kubernetes_service_host=(`ip -o route get to 8.8.8.8 | sed -n 's/.*src \([0-9.]\+\).*/\1/p'`) + helm $command cilium $CHARTS_URL/cilium \ + --set endpointHealthChecking.enabled=false \ + --set healthChecking=false \ + --set operator.replicas=1 \ + --set sysctlfix.enabled=true \ + --set bpf.masquerade=true \ + --set bandwidthManager.enabled=true \ + --set bandwidthManager.bbr=true \ + --set kubeProxyReplacement=true \ + --set hubble.enabled=false \ + --set hostPort.enabled=true \ + --set k8sServiceHost=${KUBERNETES_SERVICE_HOST:-$kubernetes_service_host} \ + --set k8sServicePort=${KUBERNETES_SERVICE_PORT:-6443} \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set envoy.enabled=false \ + --namespace kube-system $options --wait + echo -e "\\033[32m---> Network $command completed!\\033[0m" +} + +function install_metallb() { + check_metallb + command=${1:-"install"} + options=${2:-""} + echo -e "\\033[32m---> Start $command metallb...\\033[0m" + helm $command metallb $CHARTS_URL/metallb \ + --set speaker.frr.enabled=true \ + --namespace metallb \ + --create-namespace $options + + echo -e "\\033[32m---> Waiting metallb pods ready...\\033[0m" + kubectl wait pods -n metallb --all --for condition=Ready --timeout=600s + echo -e "\\033[32m---> Waiting metallb webhook ready...\\033[0m" + sleep 30s + + if [[ -z "${METALLB_CONFIG_FILE}" ]] ; then + echo -e "\\033[32m---> Metallb using the default configuration.\\033[0m" + kubectl apply -n metallb -f - < Metallb $command completed!\\033[0m" +} + +function install_gateway() { + command=${1:-"install"} + options=${2:-""} + echo -e "\\033[32m---> Start $command gateway...\\033[0m" + if [[ "${INSTALL_DRYCC_MIRROR}" == "cn" ]] ; then + gateway_api_url=https://drycc-mirrors.drycc.cc/kubernetes-sigs/gateway-api + else + gateway_api_url=https://github.com/kubernetes-sigs/gateway-api + fi + version=$(curl -Ls $gateway_api_url/releases|grep /kubernetes-sigs/gateway-api/releases/tag/ | sed -E 's/.*\/kubernetes-sigs\/gateway-api\/releases\/tag\/(v[0-9\.]{1,}(-rc[0-9]{1,})?)".*/\1/g' | head -1) + + helm repo add istio https://drycc-mirrors.drycc.cc/istio-charts + helm repo update + kubectl apply -f $gateway_api_url/releases/download/${version}/experimental-install.yaml + helm $command istio-base istio/base -n istio-system --set defaultRevision=default --create-namespace --wait $options + helm $command istio-istiod istio/istiod -n istio-system \ + --set pilot.env.PILOT_ENABLE_ALPHA_GATEWAY_API=true \ + --set pilot.env.PILOT_ENABLE_QUIC_LISTENERS=true \ + --wait $options + helm $command istio-gateway istio/gateway -n istio-gateway --create-namespace --wait $options + echo -e "\\033[32m---> Gateway $command completed!\\033[0m" +} + +function install_cert_manager() { + command=${1:-"install"} + options=${2:-""} + echo -e "\\033[32m---> Start $command cert-manager...\\033[0m" + helm $command cert-manager $CHARTS_URL/cert-manager \ + --namespace cert-manager \ + --create-namespace \ + --set clusterResourceNamespace=drycc \ + --set "extraArgs={--feature-gates=ExperimentalGatewayAPISupport=true}" \ + --set crds.enabled=true --wait $options + echo -e "\\033[32m---> Cert-manager $command completed!\\033[0m" +} + +function install_catalog() { + command=${1:-"install"} + options=${2:-""} + echo -e "\\033[32m---> Start $command catalog...\\033[0m" + helm $command catalog $CHARTS_URL/catalog \ + --set asyncBindingOperationsEnabled=true \ + --set image=registry.drycc.cc/drycc-addons/service-catalog:canary \ + --namespace catalog \ + --create-namespace --wait $options + echo -e "\\033[32m---> Catalog $command completed!\\033[0m" +} + +function install_components { + install_network + install_metallb + install_gateway + install_cert_manager + install_catalog +} + +function check_drycc { + if [[ -z "${PLATFORM_DOMAIN}" ]] ; then + echo -e "\\033[33m---> Please set the PLATFORM_DOMAIN variable.\\033[0m" + echo -e "\\033[33m---> For example:\\033[0m" + echo -e "\\033[33m---> export PLATFORM_DOMAIN=drycc.cc\\033[0m" + echo -e "\\033[33m---> And confirm that wildcard domain name resolution has been set.\\033[0m" + echo -e "\\033[33m---> For example, the current server IP is 8.8.8.8\\033[0m" + echo -e "\\033[33m---> Please point *.drycc.cc to 8.8.8.8\\033[0m" + exit 1 + fi + + if [[ -z "${DRYCC_ADMIN_USERNAME}" || -z "${DRYCC_ADMIN_PASSWORD}" ]] ; then + echo -e "\\033[33m---> Please set the DRYCC_ADMIN_USERNAME and DRYCC_ADMIN_PASSWORD variable.\\033[0m" + echo -e "\\033[33m---> For example:\\033[0m" + echo -e "\\033[33m---> export DRYCC_ADMIN_USERNAME=admin\\033[0m" + echo -e "\\033[33m---> export DRYCC_ADMIN_PASSWORD=admin\\033[0m" + echo -e "\\033[33m---> This password is used by end users to log in and manage drycc.\\033[0m" + echo -e "\\033[33m---> Please set a high security string!!!\\033[0m" + exit 1 + fi +} + +function install_drycc { + check_drycc + command=${1:-"install"} + options=${2:-""} + echo -e "\\033[32m---> Start $command workflow...\\033[0m" + RABBITMQ_USERNAME=${RABBITMQ_USERNAME:-$(cat /proc/sys/kernel/random/uuid)} + RABBITMQ_PASSWORD=${RABBITMQ_PASSWORD:-$(cat /proc/sys/kernel/random/uuid)} + if [[ "$CHANNEL" == "stable" ]]; then + if [[ "${INSTALL_DRYCC_MIRROR}" == "cn" ]] ; then + FILER_VERSION=$(curl -Ls https://drycc-mirrors.drycc.cc/drycc/filer/releases|grep /drycc/filer/releases/tag/ | sed -E 's/.*\/drycc\/filer\/releases\/tag\/(v[0-9\.]{1,}(-rc.[0-9]{1,})?)".*/\1/g' | head -1) + else + FILER_VERSION=$(curl -Ls https://github.com/drycc/filer/releases|grep /drycc/filer/releases/tag/ | sed -E 's/.*\/drycc\/filer\/releases\/tag\/(v[0-9\.]{1,}(-rc.[0-9]{1,})?)".*/\1/g' | head -1) + fi + FILER_IMAGE=${DRYCC_REGISTRY}/drycc/filer:$(sed 's#v##' <<< $FILER_VERSION) + FILER_IMAGE_PULL_POLICY="IfNotPresent" + else + FILER_IMAGE=${DRYCC_REGISTRY}/drycc/filer:canary + FILER_IMAGE_PULL_POLICY="Always" + fi + +cat << EOF > "/tmp/drycc-values.yaml" +global: + clusterDomain: ${CLUSTER_DOMAIN} + platformDomain: ${PLATFORM_DOMAIN} + certManagerEnabled: ${CERT_MANAGER_ENABLED} + gatewayClass: ${GATEWAY_CLASS} + +builder: + replicas: ${BUILDER_REPLICAS:-1} + imageRegistry: ${DRYCC_REGISTRY} + +database: + replicas: ${DATABASE_REPLICAS:-2} + imageRegistry: ${DRYCC_REGISTRY} + limitsMemory: "512Mi" + limitsHugepages2Mi: "256Mi" + persistence: + enabled: true + size: ${DATABASE_PERSISTENCE_SIZE:-5Gi} + storageClass: ${DATABASE_PERSISTENCE_STORAGE_CLASS:-""} + +timeseries: + replicas: ${TIMESERIES_REPLICAS:-1} + imageRegistry: ${DRYCC_REGISTRY} + limitsMemory: "512Mi" + limitsHugepages2Mi: "256Mi" + persistence: + enabled: true + size: ${TIMESERIES_PERSISTENCE_SIZE:-5Gi} + storageClass: ${TIMESERIES_PERSISTENCE_STORAGE_CLASS:-""} + +fluentbit: + imageRegistry: ${DRYCC_REGISTRY} + +controller: + apiReplicas: ${CONTROLLER_API_REPLICAS:-1} + celeryReplicas: ${CONTROLLER_CELERY_REPLICAS:-1} + webhookReplicas: ${CONTROLLER_WEBHOOK_REPLICAS:-1} + imageRegistry: ${DRYCC_REGISTRY} + appRuntimeClass: ${CONTROLLER_APP_RUNTIME_CLASS:-""} + appStorageClass: ${CONTROLLER_APP_STORAGE_CLASS:-"drycc-storage"} + filerImage: ${FILER_IMAGE} + filerImagePullPolicy: ${FILER_IMAGE_PULL_POLICY} + +redis: + replicas: ${REDIS_REPLICAS:-1} + imageRegistry: ${DRYCC_REGISTRY} + persistence: + enabled: true + size: ${REDIS_PERSISTENCE_SIZE:-5Gi} + storageClass: ${REDIS_PERSISTENCE_STORAGE_CLASS:-""} + +storage: + csi: + statefulset: + replicas: ${STORAGE_CSI_STATEFULSET_REPLICAS:-1} + mainnode: + tipd: + replicas: ${STORAGE_MAINNODE_TIPD_REPLICAS:-1} + persistence: + enabled: true + size: ${STORAGE_MAINNODE_TIPD_PERSISTENCE_SIZE:-5Gi} + storageClass: "${STORAGE_MAINNODE_TIPD_PERSISTENCE_STORAGE_CLASS}" + weed: + replicas: ${STORAGE_MAINNODE_WEED_REPLICAS:-1} + volumePreallocate: ${STORAGE_MAINNODE_WEED_PREALLOCATE:-false} + volumeSizeLimitMB: ${STORAGE_MAINNODE_WEED_SIZE_LIMIT_MB:-512} + defaultReplication: "${STORAGE_MAINNODE_WEED_DEFAULT_REPLICATION:-000}" + persistence: + enabled: true + size: ${STORAGE_MAINNODE_WEED_PERSISTENCE_SIZE:-5Gi} + storageClass: "${STORAGE_MAINNODE_WEED_PERSISTENCE_STORAGE_CLASS}" + metanode: + tikv: + replicas: ${STORAGE_METANODE_TIKV_REPLICAS:-1} + persistence: + enabled: true + size: ${STORAGE_METANODE_TIKV_PERSISTENCE_SIZE:-5Gi} + storageClass: "${STORAGE_METANODE_TIKV_PERSISTENCE_STORAGE_CLASS}" + weed: + replicas: ${STORAGE_METANODE_WEED_REPLICAS:-1} + persistence: + enabled: true + size: ${STORAGE_METANODE_WEED_PERSISTENCE_SIZE:-5Gi} + storageClass: "${STORAGE_METANODE_WEED_PERSISTENCE_STORAGE_CLASS}" + datanode: + weed: + replicas: ${STORAGE_DATANODE_WEED_REPLICAS:-1} + persistence: + enabled: true + size: ${STORAGE_DATANODE_WEED_PERSISTENCE_SIZE:-10Gi} + storageClass: "${STORAGE_DATANODE_WEED_PERSISTENCE_STORAGE_CLASS}" + +rabbitmq: + replicas: ${RABBITMQ_REPLICAS:-1} + imageRegistry: ${DRYCC_REGISTRY} + username: "${RABBITMQ_USERNAME}" + password: "${RABBITMQ_PASSWORD}" + persistence: + enabled: true + size: ${RABBITMQ_PERSISTENCE_SIZE:-5Gi} + storageClass: ${RABBITMQ_PERSISTENCE_STORAGE_CLASS:-""} + +imagebuilder: + imageRegistry: ${DRYCC_REGISTRY} + +logger: + replicas: ${LOGGER_REPLICAS:-1} + imageRegistry: ${DRYCC_REGISTRY} + +monitor: + grafana: + imageRegistry: ${DRYCC_REGISTRY} + persistence: + enabled: true + size: ${MONITOR_GRAFANA_PERSISTENCE_SIZE:-5Gi} + storageClass: ${MONITOR_GRAFANA_PERSISTENCE_STORAGE_CLASS:-""} + telegraf: + imageRegistry: ${DRYCC_REGISTRY} + +prometheus: + prometheus-server: + retention: ${PROMETHEUS_SERVER_RETENTION:-"15d"} + persistence: + enabled: true + accessMode: ReadWriteOnce + size: ${PROMETHEUS_SERVER_PERSISTENCE_SIZE:-10Gi} + storageClass: ${PROMETHEUS_SERVER_PERSISTENCE_STORAGE_CLASS:-""} + +passport: + replicas: ${PASSPORT_REPLICAS:-1} + imageRegistry: ${DRYCC_REGISTRY} + adminUsername: ${DRYCC_ADMIN_USERNAME} + adminPassword: ${DRYCC_ADMIN_PASSWORD} + +registry: + replicas: ${REGISTRY_REPLICAS:-1} + imageRegistry: ${DRYCC_REGISTRY} + +registry-proxy: + imageRegistry: ${DRYCC_REGISTRY} + +acme: + server: ${ACME_SERVER:-"https://acme-v02.api.letsencrypt.org/directory"} + externalAccountBinding: + keyID: ${ACME_EAB_KEY_ID:-""} + keySecret: ${ACME_EAB_KEY_SECRET:-""} +EOF + + if [[ "${INSTALL_DRYCC_MIRROR}" == "cn" ]] ; then + cat << EOF > "/tmp/drycc-mirror-values.yaml" +imagebuilder: + container_registries: | + unqualified-search-registries = ["docker.io"] + short-name-mode="permissive" + [[registry]] + prefix = "docker.io" + location = "registry-1.docker.io" + [[registry.mirror]] + prefix = "docker.io" + location = "hub-mirror.c.163.com" +EOF + else + cat << EOF > "/tmp/drycc-mirror-values.yaml" +imagebuilder: + container_registries: | + unqualified-search-registries = ["docker.io"] + short-name-mode="permissive" +EOF + fi + + helm $command drycc $CHARTS_URL/workflow \ + --namespace drycc \ + --values /tmp/drycc-values.yaml \ + --values /tmp/drycc-mirror-values.yaml \ + --create-namespace --wait --timeout 30m0s $options + echo -e "\\033[32m---> Rabbitmq username: $RABBITMQ_USERNAME\\033[0m" + echo -e "\\033[32m---> Rabbitmq password: $RABBITMQ_PASSWORD\\033[0m" + echo -e "\\033[32m---> Workflow $command completed!\\033[0m" +} + +function install_helmbroker { + if [[ "${INSTALL_DRYCC_MIRROR}" == "cn" ]] ; then + addons_url="https://drycc-mirrors.drycc.cc/drycc-addons/addons/releases/download/latest/index.yaml" + else + addons_url="https://github.com/drycc-addons/addons/releases/download/latest/index.yaml" + fi + command=${1:-"install"} + options=${2:-""} + HELMBROKER_USERNAME=${HELMBROKER_USERNAME:-$(cat /proc/sys/kernel/random/uuid)} + HELMBROKER_PASSWORD=${HELMBROKER_PASSWORD:-$(cat /proc/sys/kernel/random/uuid)} + + echo -e "\\033[32m---> Start $command helmbroker...\\033[0m" + + helm $command helmbroker $CHARTS_URL/helmbroker \ + --set global.rabbitmqLocation="off-cluster" \ + --set global.gatewayClass=${GATEWAY_CLASS} \ + --set global.clusterDomain=${CLUSTER_DOMAIN} \ + --set global.platformDomain=${PLATFORM_DOMAIN} \ + --set global.certManagerEnabled=${CERT_MANAGER_ENABLED} \ + --set persistence.size=${HELMBROKER_PERSISTENCE_SIZE:-5Gi} \ + --set persistence.storageClass=${HELMBROKER_PERSISTENCE_STORAGE_CLASS:-"drycc-storage"} \ + --set username=${HELMBROKER_USERNAME} \ + --set password=${HELMBROKER_PASSWORD} \ + --set replicas=${HELMBROKER_REPLICAS} \ + --set celeryReplicas=${HELMBROKER_CELERY_REPLICAS} \ + --set rabbitmqUrl="amqp://${RABBITMQ_USERNAME}:${RABBITMQ_PASSWORD}@drycc-rabbitmq.drycc.svc.${CLUSTER_DOMAIN}:5672/helmbroker" \ + --namespace drycc-helmbroker --create-namespace $options --wait -f - < Helmbroker username: $HELMBROKER_USERNAME\\033[0m" + echo -e "\\033[32m---> Helmbroker password: $HELMBROKER_PASSWORD\\033[0m" + echo -e "\\033[32m---> Helmbroker $command completed!\\033[0m" +} + +function upgrade { + RABBITMQ_USERNAME=$(kubectl get secrets -n drycc rabbitmq-creds -o jsonpath="{.data.username}"| base64 -d) + RABBITMQ_PASSWORD=$(kubectl get secrets -n drycc rabbitmq-creds -o jsonpath="{.data.password}"| base64 -d) + export RABBITMQ_USERNAME RABBITMQ_PASSWORD + + install_network upgrade --reset-then-reuse-values + install_metallb upgrade --reset-then-reuse-values + install_gateway upgrade --reset-then-reuse-values + install_cert_manager upgrade --reset-then-reuse-values + install_catalog upgrade --reset-then-reuse-values + install_drycc upgrade --reset-then-reuse-values + install_helmbroker upgrade --reset-then-reuse-values + echo -e "\\033[32m---> Upgrade complete, enjoy life...\\033[0m" +} + +export KUBECONFIG=/etc/rancher/k3s/k3s.yaml + +if [[ -z "$@" ]] ; then + check_drycc + check_metallb + install_k3s_server + install_helm + install_components + install_drycc + install_helmbroker + echo -e "\\033[32m---> Installation complete, enjoy life...\\033[0m" +else + for command in "$@" + do + $command + echo -e "\\033[32m---> Execute $command complete, enjoy life...\\033[0m" + done +fi diff --git a/js/click-to-copy.min.f724d3de49218995223b7316aa2e53e2b34bf42026bf399ebb21bb02212402d1.js b/js/click-to-copy.min.f724d3de49218995223b7316aa2e53e2b34bf42026bf399ebb21bb02212402d1.js new file mode 100644 index 000000000..26dffe3a2 --- /dev/null +++ b/js/click-to-copy.min.f724d3de49218995223b7316aa2e53e2b34bf42026bf399ebb21bb02212402d1.js @@ -0,0 +1,2 @@ +let codeListings=document.querySelectorAll(".highlight > pre");for(let t=0;t{e.setAttribute(t,o[t])}),e.classList.add("fas","fa-copy","btn","btn-dark","btn-sm","td-click-to-copy");const i=new bootstrap.Tooltip(e);e.onclick=()=>{copyCode(s),e.setAttribute("data-bs-original-title","Copied!"),i.show()},e.onmouseout=()=>{e.setAttribute("data-bs-original-title","Copy to clipboard"),i.hide()};const n=document.createElement("div");n.classList.add("click-to-copy"),n.append(e),codeListings[t].insertBefore(n,s)}const copyCode=e=>{navigator.clipboard.writeText(e.textContent.trim()+` +`)} \ No newline at end of file diff --git a/js/deflate.js b/js/deflate.js new file mode 100644 index 000000000..b452c84e9 --- /dev/null +++ b/js/deflate.js @@ -0,0 +1,1652 @@ +/* Copyright (C) 1999 Masanao Izumo +* Version: 1.0.1 +* LastModified: Dec 25 1999 +*/ + +/* Interface: +* data = deflate(src); +*/ +const deflate = (function () { + /* constant parameters */ + var zip_WSIZE = 32768; // Sliding Window size + var zip_STORED_BLOCK = 0; + var zip_STATIC_TREES = 1; + var zip_DYN_TREES = 2; + + /* for deflate */ + var zip_DEFAULT_LEVEL = 6; + var zip_FULL_SEARCH = true; + var zip_INBUFSIZ = 32768; // Input buffer size + var zip_INBUF_EXTRA = 64; // Extra buffer + var zip_OUTBUFSIZ = 1024 * 8; + var zip_window_size = 2 * zip_WSIZE; + var zip_MIN_MATCH = 3; + var zip_MAX_MATCH = 258; + var zip_BITS = 16; + // for SMALL_MEM + var zip_LIT_BUFSIZE = 0x2000; + var zip_HASH_BITS = 13; + // for MEDIUM_MEM + // var zip_LIT_BUFSIZE = 0x4000; + // var zip_HASH_BITS = 14; + // for BIG_MEM + // var zip_LIT_BUFSIZE = 0x8000; + // var zip_HASH_BITS = 15; + //if(zip_LIT_BUFSIZE > zip_INBUFSIZ) + // alert("error: zip_INBUFSIZ is too small"); + //if((zip_WSIZE<<1) > (1< zip_BITS-1) + // alert("error: zip_HASH_BITS is too large"); + //if(zip_HASH_BITS < 8 || zip_MAX_MATCH != 258) + // alert("error: Code too clever"); + var zip_DIST_BUFSIZE = zip_LIT_BUFSIZE; + var zip_HASH_SIZE = 1 << zip_HASH_BITS; + var zip_HASH_MASK = zip_HASH_SIZE - 1; + var zip_WMASK = zip_WSIZE - 1; + var zip_NIL = 0; // Tail of hash chains + var zip_TOO_FAR = 4096; + var zip_MIN_LOOKAHEAD = zip_MAX_MATCH + zip_MIN_MATCH + 1; + var zip_MAX_DIST = zip_WSIZE - zip_MIN_LOOKAHEAD; + var zip_SMALLEST = 1; + var zip_MAX_BITS = 15; + var zip_MAX_BL_BITS = 7; + var zip_LENGTH_CODES = 29; + var zip_LITERALS = 256; + var zip_END_BLOCK = 256; + var zip_L_CODES = zip_LITERALS + 1 + zip_LENGTH_CODES; + var zip_D_CODES = 30; + var zip_BL_CODES = 19; + var zip_REP_3_6 = 16; + var zip_REPZ_3_10 = 17; + var zip_REPZ_11_138 = 18; + var zip_HEAP_SIZE = 2 * zip_L_CODES + 1; + var zip_H_SHIFT = parseInt((zip_HASH_BITS + zip_MIN_MATCH - 1) / + zip_MIN_MATCH); + + /* variables */ + var zip_free_queue; + var zip_qhead, zip_qtail; + var zip_initflag; + var zip_outbuf = null; + var zip_outcnt, zip_outoff; + var zip_complete; + var zip_window; + var zip_d_buf; + var zip_l_buf; + var zip_prev; + var zip_bi_buf; + var zip_bi_valid; + var zip_block_start; + var zip_ins_h; + var zip_hash_head; + var zip_prev_match; + var zip_match_available; + var zip_match_length; + var zip_prev_length; + var zip_strstart; + var zip_match_start; + var zip_eofile; + var zip_lookahead; + var zip_max_chain_length; + var zip_max_lazy_match; + var zip_compr_level; + var zip_good_match; + var zip_nice_match; + var zip_dyn_ltree; + var zip_dyn_dtree; + var zip_static_ltree; + var zip_static_dtree; + var zip_bl_tree; + var zip_l_desc; + var zip_d_desc; + var zip_bl_desc; + var zip_bl_count; + var zip_heap; + var zip_heap_len; + var zip_heap_max; + var zip_depth; + var zip_length_code; + var zip_dist_code; + var zip_base_length; + var zip_base_dist; + var zip_flag_buf; + var zip_last_lit; + var zip_last_dist; + var zip_last_flags; + var zip_flags; + var zip_flag_bit; + var zip_opt_len; + var zip_static_len; + var zip_deflate_data; + var zip_deflate_pos; + + /* objects (deflate) */ + + function zip_DeflateCT() { + this.fc = 0; // frequency count or bit string + this.dl = 0; // father node in Huffman tree or length of bit string + } + + function zip_DeflateTreeDesc() { + this.dyn_tree = null; // the dynamic tree + this.static_tree = null; // corresponding static tree or NULL + this.extra_bits = null; // extra bits for each code or NULL + this.extra_base = 0; // base index for extra_bits + this.elems = 0; // max number of elements in the tree + this.max_length = 0; // max bit length for the codes + this.max_code = 0; // largest code with non zero frequency + } + + /* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ + function zip_DeflateConfiguration(a, b, c, d) { + this.good_length = a; // reduce lazy search above this match length + this.max_lazy = b; // do not perform lazy search above this match length + this.nice_length = c; // quit search above this match length + this.max_chain = d; + } + + function zip_DeflateBuffer() { + this.next = null; + this.len = 0; + this.ptr = new Array(zip_OUTBUFSIZ); + this.off = 0; + } + + /* constant tables */ + var zip_extra_lbits = [ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0]; + var zip_extra_dbits = [ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13]; + var zip_extra_blbits = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7]; + var zip_bl_order = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; + var zip_configuration_table = [ + new zip_DeflateConfiguration(0, 0, 0, 0), + new zip_DeflateConfiguration(4, 4, 8, 4), + new zip_DeflateConfiguration(4, 5, 16, 8), + new zip_DeflateConfiguration(4, 6, 32, 32), + new zip_DeflateConfiguration(4, 4, 16, 16), + new zip_DeflateConfiguration(8, 16, 32, 32), + new zip_DeflateConfiguration(8, 16, 128, 128), + new zip_DeflateConfiguration(8, 32, 128, 256), + new zip_DeflateConfiguration(32, 128, 258, 1024), + new zip_DeflateConfiguration(32, 258, 258, 4096)]; + + + /* routines (deflate) */ + + function zip_deflate_start(level) { + var i; + + if (!level) + level = zip_DEFAULT_LEVEL; + else if (level < 1) + level = 1; + else if (level > 9) + level = 9; + + zip_compr_level = level; + zip_initflag = false; + zip_eofile = false; + if (zip_outbuf != null) + return; + + zip_free_queue = zip_qhead = zip_qtail = null; + zip_outbuf = new Array(zip_OUTBUFSIZ); + zip_window = new Array(zip_window_size); + zip_d_buf = new Array(zip_DIST_BUFSIZE); + zip_l_buf = new Array(zip_INBUFSIZ + zip_INBUF_EXTRA); + zip_prev = new Array(1 << zip_BITS); + zip_dyn_ltree = new Array(zip_HEAP_SIZE); + for (i = 0; i < zip_HEAP_SIZE; i++) + zip_dyn_ltree[i] = new zip_DeflateCT(); + zip_dyn_dtree = new Array(2 * zip_D_CODES + 1); + for (i = 0; i < 2 * zip_D_CODES + 1; i++) + zip_dyn_dtree[i] = new zip_DeflateCT(); + zip_static_ltree = new Array(zip_L_CODES + 2); + for (i = 0; i < zip_L_CODES + 2; i++) + zip_static_ltree[i] = new zip_DeflateCT(); + zip_static_dtree = new Array(zip_D_CODES); + for (i = 0; i < zip_D_CODES; i++) + zip_static_dtree[i] = new zip_DeflateCT(); + zip_bl_tree = new Array(2 * zip_BL_CODES + 1); + for (i = 0; i < 2 * zip_BL_CODES + 1; i++) + zip_bl_tree[i] = new zip_DeflateCT(); + zip_l_desc = new zip_DeflateTreeDesc(); + zip_d_desc = new zip_DeflateTreeDesc(); + zip_bl_desc = new zip_DeflateTreeDesc(); + zip_bl_count = new Array(zip_MAX_BITS + 1); + zip_heap = new Array(2 * zip_L_CODES + 1); + zip_depth = new Array(2 * zip_L_CODES + 1); + zip_length_code = new Array(zip_MAX_MATCH - zip_MIN_MATCH + 1); + zip_dist_code = new Array(512); + zip_base_length = new Array(zip_LENGTH_CODES); + zip_base_dist = new Array(zip_D_CODES); + zip_flag_buf = new Array(parseInt(zip_LIT_BUFSIZE / 8)); + } + + function zip_deflate_end() { + zip_free_queue = zip_qhead = zip_qtail = null; + zip_outbuf = null; + zip_window = null; + zip_d_buf = null; + zip_l_buf = null; + zip_prev = null; + zip_dyn_ltree = null; + zip_dyn_dtree = null; + zip_static_ltree = null; + zip_static_dtree = null; + zip_bl_tree = null; + zip_l_desc = null; + zip_d_desc = null; + zip_bl_desc = null; + zip_bl_count = null; + zip_heap = null; + zip_depth = null; + zip_length_code = null; + zip_dist_code = null; + zip_base_length = null; + zip_base_dist = null; + zip_flag_buf = null; + } + + function zip_reuse_queue(p) { + p.next = zip_free_queue; + zip_free_queue = p; + } + + function zip_new_queue() { + var p; + + if (zip_free_queue != null) { + p = zip_free_queue; + zip_free_queue = zip_free_queue.next; + } + else + p = new zip_DeflateBuffer(); + p.next = null; + p.len = p.off = 0; + + return p; + } + + function zip_head1(i) { + return zip_prev[zip_WSIZE + i]; + } + + function zip_head2(i, val) { + return zip_prev[zip_WSIZE + i] = val; + } + + /* put_byte is used for the compressed output, put_ubyte for the + * uncompressed output. However unlzw() uses window for its + * suffix table instead of its output buffer, so it does not use put_ubyte + * (to be cleaned up). + */ + function zip_put_byte(c) { + zip_outbuf[zip_outoff + zip_outcnt++] = c; + if (zip_outoff + zip_outcnt == zip_OUTBUFSIZ) + zip_qoutbuf(); + } + + /* Output a 16 bit value, lsb first */ + function zip_put_short(w) { + w &= 0xffff; + if (zip_outoff + zip_outcnt < zip_OUTBUFSIZ - 2) { + zip_outbuf[zip_outoff + zip_outcnt++] = (w & 0xff); + zip_outbuf[zip_outoff + zip_outcnt++] = (w >>> 8); + } else { + zip_put_byte(w & 0xff); + zip_put_byte(w >>> 8); + } + } + + /* ========================================================================== + * Insert string s in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of s are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ + function zip_INSERT_STRING() { + zip_ins_h = ((zip_ins_h << zip_H_SHIFT) + ^ (zip_window[zip_strstart + zip_MIN_MATCH - 1] & 0xff)) + & zip_HASH_MASK; + zip_hash_head = zip_head1(zip_ins_h); + zip_prev[zip_strstart & zip_WMASK] = zip_hash_head; + zip_head2(zip_ins_h, zip_strstart); + } + + /* Send a code of the given tree. c and tree must not have side effects */ + function zip_SEND_CODE(c, tree) { + zip_send_bits(tree[c].fc, tree[c].dl); + } + + /* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. dist_code[256] and dist_code[257] are never + * used. + */ + function zip_D_CODE(dist) { + return (dist < 256 ? zip_dist_code[dist] + : zip_dist_code[256 + (dist >> 7)]) & 0xff; + } + + /* ========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ + function zip_SMALLER(tree, n, m) { + return tree[n].fc < tree[m].fc || + (tree[n].fc == tree[m].fc && zip_depth[n] <= zip_depth[m]); + } + + /* ========================================================================== + * read string data + */ + function zip_read_buff(buff, offset, n) { + var i; + for (i = 0; i < n && zip_deflate_pos < zip_deflate_data.length; i++) + buff[offset + i] = + zip_deflate_data.charCodeAt(zip_deflate_pos++) & 0xff; + return i; + } + + /* ========================================================================== + * Initialize the "longest match" routines for a new file + */ + function zip_lm_init() { + var j; + + /* Initialize the hash table. */ + for (j = 0; j < zip_HASH_SIZE; j++) + // zip_head2(j, zip_NIL); + zip_prev[zip_WSIZE + j] = 0; + /* prev will be initialized on the fly */ + + /* Set the default configuration parameters: + */ + zip_max_lazy_match = zip_configuration_table[zip_compr_level].max_lazy; + zip_good_match = zip_configuration_table[zip_compr_level].good_length; + if (!zip_FULL_SEARCH) + zip_nice_match = zip_configuration_table[zip_compr_level].nice_length; + zip_max_chain_length = zip_configuration_table[zip_compr_level].max_chain; + + zip_strstart = 0; + zip_block_start = 0; + + zip_lookahead = zip_read_buff(zip_window, 0, 2 * zip_WSIZE); + if (zip_lookahead <= 0) { + zip_eofile = true; + zip_lookahead = 0; + return; + } + zip_eofile = false; + /* Make sure that we always have enough lookahead. This is important + * if input comes from a device such as a tty. + */ + while (zip_lookahead < zip_MIN_LOOKAHEAD && !zip_eofile) + zip_fill_window(); + + /* If lookahead < MIN_MATCH, ins_h is garbage, but this is + * not important since only literal bytes will be emitted. + */ + zip_ins_h = 0; + for (j = 0; j < zip_MIN_MATCH - 1; j++) { + // UPDATE_HASH(ins_h, window[j]); + zip_ins_h = ((zip_ins_h << zip_H_SHIFT) ^ (zip_window[j] & 0xff)) & zip_HASH_MASK; + } + } + + /* ========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + */ + function zip_longest_match(cur_match) { + var chain_length = zip_max_chain_length; // max hash chain length + var scanp = zip_strstart; // current string + var matchp; // matched string + var len; // length of current match + var best_len = zip_prev_length; // best match length so far + + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + var limit = (zip_strstart > zip_MAX_DIST ? zip_strstart - zip_MAX_DIST : zip_NIL); + + var strendp = zip_strstart + zip_MAX_MATCH; + var scan_end1 = zip_window[scanp + best_len - 1]; + var scan_end = zip_window[scanp + best_len]; + + /* Do not waste too much time if we already have a good match: */ + if (zip_prev_length >= zip_good_match) + chain_length >>= 2; + + // Assert(encoder->strstart <= window_size-MIN_LOOKAHEAD, "insufficient lookahead"); + + do { + // Assert(cur_match < encoder->strstart, "no future"); + matchp = cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ + if (zip_window[matchp + best_len] != scan_end || + zip_window[matchp + best_len - 1] != scan_end1 || + zip_window[matchp] != zip_window[scanp] || + zip_window[++matchp] != zip_window[scanp + 1]) { + continue; + } + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scanp += 2; + matchp++; + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (zip_window[++scanp] == zip_window[++matchp] && + zip_window[++scanp] == zip_window[++matchp] && + zip_window[++scanp] == zip_window[++matchp] && + zip_window[++scanp] == zip_window[++matchp] && + zip_window[++scanp] == zip_window[++matchp] && + zip_window[++scanp] == zip_window[++matchp] && + zip_window[++scanp] == zip_window[++matchp] && + zip_window[++scanp] == zip_window[++matchp] && + scanp < strendp); + + len = zip_MAX_MATCH - (strendp - scanp); + scanp = strendp - zip_MAX_MATCH; + + if (len > best_len) { + zip_match_start = cur_match; + best_len = len; + if (zip_FULL_SEARCH) { + if (len >= zip_MAX_MATCH) break; + } else { + if (len >= zip_nice_match) break; + } + + scan_end1 = zip_window[scanp + best_len - 1]; + scan_end = zip_window[scanp + best_len]; + } + } while ((cur_match = zip_prev[cur_match & zip_WMASK]) > limit + && --chain_length != 0); + + return best_len; + } + + /* ========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead, and sets eofile if end of input file. + * IN assertion: lookahead < MIN_LOOKAHEAD && strstart + lookahead > 0 + * OUT assertions: at least one byte has been read, or eofile is set; + * file reads are performed for at least two bytes (required for the + * translate_eol option). + */ + function zip_fill_window() { + var n, m; + + // Amount of free space at the end of the window. + var more = zip_window_size - zip_lookahead - zip_strstart; + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (more == -1) { + /* Very unlikely, but possible on 16 bit machine if strstart == 0 + * and lookahead == 1 (input done one byte at time) + */ + more--; + } else if (zip_strstart >= zip_WSIZE + zip_MAX_DIST) { + /* By the IN assertion, the window is not empty so we can't confuse + * more == 0 with more == 64K on a 16 bit machine. + */ + // Assert(window_size == (ulg)2*WSIZE, "no sliding with BIG_MEM"); + + // System.arraycopy(window, WSIZE, window, 0, WSIZE); + for (n = 0; n < zip_WSIZE; n++) + zip_window[n] = zip_window[n + zip_WSIZE]; + + zip_match_start -= zip_WSIZE; + zip_strstart -= zip_WSIZE; /* we now have strstart >= MAX_DIST: */ + zip_block_start -= zip_WSIZE; + + for (n = 0; n < zip_HASH_SIZE; n++) { + m = zip_head1(n); + zip_head2(n, m >= zip_WSIZE ? m - zip_WSIZE : zip_NIL); + } + for (n = 0; n < zip_WSIZE; n++) { + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + m = zip_prev[n]; + zip_prev[n] = (m >= zip_WSIZE ? m - zip_WSIZE : zip_NIL); + } + more += zip_WSIZE; + } + // At this point, more >= 2 + if (!zip_eofile) { + n = zip_read_buff(zip_window, zip_strstart + zip_lookahead, more); + if (n <= 0) + zip_eofile = true; + else + zip_lookahead += n; + } + } + + /* ========================================================================== + * Processes a new input file and return its compressed length. This + * function does not perform lazy evaluationof matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ + function zip_deflate_fast() { + while (zip_lookahead != 0 && zip_qhead == null) { + var flush; // set if current block must be flushed + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + zip_INSERT_STRING(); + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (zip_hash_head != zip_NIL && + zip_strstart - zip_hash_head <= zip_MAX_DIST) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + zip_match_length = zip_longest_match(zip_hash_head); + /* longest_match() sets match_start */ + if (zip_match_length > zip_lookahead) + zip_match_length = zip_lookahead; + } + if (zip_match_length >= zip_MIN_MATCH) { + // check_match(strstart, match_start, match_length); + + flush = zip_ct_tally(zip_strstart - zip_match_start, + zip_match_length - zip_MIN_MATCH); + zip_lookahead -= zip_match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ + if (zip_match_length <= zip_max_lazy_match) { + zip_match_length--; // string at strstart already in hash table + do { + zip_strstart++; + zip_INSERT_STRING(); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH + * these bytes are garbage, but it does not matter since + * the next lookahead bytes will be emitted as literals. + */ + } while (--zip_match_length != 0); + zip_strstart++; + } else { + zip_strstart += zip_match_length; + zip_match_length = 0; + zip_ins_h = zip_window[zip_strstart] & 0xff; + // UPDATE_HASH(ins_h, window[strstart + 1]); + zip_ins_h = ((zip_ins_h << zip_H_SHIFT) ^ (zip_window[zip_strstart + 1] & 0xff)) & zip_HASH_MASK; + + //#if MIN_MATCH != 3 + // Call UPDATE_HASH() MIN_MATCH-3 more times + //#endif + + } + } else { + /* No match, output a literal byte */ + flush = zip_ct_tally(0, zip_window[zip_strstart] & 0xff); + zip_lookahead--; + zip_strstart++; + } + if (flush) { + zip_flush_block(0); + zip_block_start = zip_strstart; + } + + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + while (zip_lookahead < zip_MIN_LOOKAHEAD && !zip_eofile) + zip_fill_window(); + } + } + + function zip_deflate_better() { + /* Process the input block. */ + while (zip_lookahead != 0 && zip_qhead == null) { + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + zip_INSERT_STRING(); + + /* Find the longest match, discarding those <= prev_length. + */ + zip_prev_length = zip_match_length; + zip_prev_match = zip_match_start; + zip_match_length = zip_MIN_MATCH - 1; + + if (zip_hash_head != zip_NIL && + zip_prev_length < zip_max_lazy_match && + zip_strstart - zip_hash_head <= zip_MAX_DIST) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + zip_match_length = zip_longest_match(zip_hash_head); + /* longest_match() sets match_start */ + if (zip_match_length > zip_lookahead) + zip_match_length = zip_lookahead; + + /* Ignore a length 3 match if it is too distant: */ + if (zip_match_length == zip_MIN_MATCH && + zip_strstart - zip_match_start > zip_TOO_FAR) { + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + zip_match_length--; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (zip_prev_length >= zip_MIN_MATCH && + zip_match_length <= zip_prev_length) { + var flush; // set if current block must be flushed + + // check_match(strstart - 1, prev_match, prev_length); + flush = zip_ct_tally(zip_strstart - 1 - zip_prev_match, + zip_prev_length - zip_MIN_MATCH); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. + */ + zip_lookahead -= zip_prev_length - 1; + zip_prev_length -= 2; + do { + zip_strstart++; + zip_INSERT_STRING(); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH + * these bytes are garbage, but it does not matter since the + * next lookahead bytes will always be emitted as literals. + */ + } while (--zip_prev_length != 0); + zip_match_available = 0; + zip_match_length = zip_MIN_MATCH - 1; + zip_strstart++; + if (flush) { + zip_flush_block(0); + zip_block_start = zip_strstart; + } + } else if (zip_match_available != 0) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + if (zip_ct_tally(0, zip_window[zip_strstart - 1] & 0xff)) { + zip_flush_block(0); + zip_block_start = zip_strstart; + } + zip_strstart++; + zip_lookahead--; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + zip_match_available = 1; + zip_strstart++; + zip_lookahead--; + } + + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + while (zip_lookahead < zip_MIN_LOOKAHEAD && !zip_eofile) + zip_fill_window(); + } + } + + function zip_init_deflate() { + if (zip_eofile) + return; + zip_bi_buf = 0; + zip_bi_valid = 0; + zip_ct_init(); + zip_lm_init(); + + zip_qhead = null; + zip_outcnt = 0; + zip_outoff = 0; + + if (zip_compr_level <= 3) { + zip_prev_length = zip_MIN_MATCH - 1; + zip_match_length = 0; + } + else { + zip_match_length = zip_MIN_MATCH - 1; + zip_match_available = 0; + } + + zip_complete = false; + } + + /* ========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ + function zip_deflate_internal(buff, off, buff_size) { + var n; + + if (!zip_initflag) { + zip_init_deflate(); + zip_initflag = true; + if (zip_lookahead == 0) { // empty + zip_complete = true; + return 0; + } + } + + if ((n = zip_qcopy(buff, off, buff_size)) == buff_size) + return buff_size; + + if (zip_complete) + return n; + + if (zip_compr_level <= 3) // optimized for speed + zip_deflate_fast(); + else + zip_deflate_better(); + if (zip_lookahead == 0) { + if (zip_match_available != 0) + zip_ct_tally(0, zip_window[zip_strstart - 1] & 0xff); + zip_flush_block(1); + zip_complete = true; + } + return n + zip_qcopy(buff, n + off, buff_size - n); + } + + function zip_qcopy(buff, off, buff_size) { + var n, i, j; + + n = 0; + while (zip_qhead != null && n < buff_size) { + i = buff_size - n; + if (i > zip_qhead.len) + i = zip_qhead.len; + // System.arraycopy(qhead.ptr, qhead.off, buff, off + n, i); + for (j = 0; j < i; j++) + buff[off + n + j] = zip_qhead.ptr[zip_qhead.off + j]; + + zip_qhead.off += i; + zip_qhead.len -= i; + n += i; + if (zip_qhead.len == 0) { + var p; + p = zip_qhead; + zip_qhead = zip_qhead.next; + zip_reuse_queue(p); + } + } + + if (n == buff_size) + return n; + + if (zip_outoff < zip_outcnt) { + i = buff_size - n; + if (i > zip_outcnt - zip_outoff) + i = zip_outcnt - zip_outoff; + // System.arraycopy(outbuf, outoff, buff, off + n, i); + for (j = 0; j < i; j++) + buff[off + n + j] = zip_outbuf[zip_outoff + j]; + zip_outoff += i; + n += i; + if (zip_outcnt == zip_outoff) + zip_outcnt = zip_outoff = 0; + } + return n; + } + + /* ========================================================================== + * Allocate the match buffer, initialize the various tables and save the + * location of the internal file attribute (ascii/binary) and method + * (DEFLATE/STORE). + */ + function zip_ct_init() { + var n; // iterates over tree elements + var bits; // bit counter + var length; // length value + var code; // code value + var dist; // distance index + + if (zip_static_dtree[0].dl != 0) return; // ct_init already called + + zip_l_desc.dyn_tree = zip_dyn_ltree; + zip_l_desc.static_tree = zip_static_ltree; + zip_l_desc.extra_bits = zip_extra_lbits; + zip_l_desc.extra_base = zip_LITERALS + 1; + zip_l_desc.elems = zip_L_CODES; + zip_l_desc.max_length = zip_MAX_BITS; + zip_l_desc.max_code = 0; + + zip_d_desc.dyn_tree = zip_dyn_dtree; + zip_d_desc.static_tree = zip_static_dtree; + zip_d_desc.extra_bits = zip_extra_dbits; + zip_d_desc.extra_base = 0; + zip_d_desc.elems = zip_D_CODES; + zip_d_desc.max_length = zip_MAX_BITS; + zip_d_desc.max_code = 0; + + zip_bl_desc.dyn_tree = zip_bl_tree; + zip_bl_desc.static_tree = null; + zip_bl_desc.extra_bits = zip_extra_blbits; + zip_bl_desc.extra_base = 0; + zip_bl_desc.elems = zip_BL_CODES; + zip_bl_desc.max_length = zip_MAX_BL_BITS; + zip_bl_desc.max_code = 0; + + // Initialize the mapping length (0..255) -> length code (0..28) + length = 0; + for (code = 0; code < zip_LENGTH_CODES - 1; code++) { + zip_base_length[code] = length; + for (n = 0; n < (1 << zip_extra_lbits[code]); n++) + zip_length_code[length++] = code; + } + // Assert (length == 256, "ct_init: length != 256"); + + /* Note that the length 255 (match length 258) can be represented + * in two different ways: code 284 + 5 bits or code 285, so we + * overwrite length_code[255] to use the best encoding: + */ + zip_length_code[length - 1] = code; + + /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ + dist = 0; + for (code = 0; code < 16; code++) { + zip_base_dist[code] = dist; + for (n = 0; n < (1 << zip_extra_dbits[code]); n++) { + zip_dist_code[dist++] = code; + } + } + // Assert (dist == 256, "ct_init: dist != 256"); + dist >>= 7; // from now on, all distances are divided by 128 + for (; code < zip_D_CODES; code++) { + zip_base_dist[code] = dist << 7; + for (n = 0; n < (1 << (zip_extra_dbits[code] - 7)); n++) + zip_dist_code[256 + dist++] = code; + } + // Assert (dist == 256, "ct_init: 256+dist != 512"); + + // Construct the codes of the static literal tree + for (bits = 0; bits <= zip_MAX_BITS; bits++) + zip_bl_count[bits] = 0; + n = 0; + while (n <= 143) { zip_static_ltree[n++].dl = 8; zip_bl_count[8]++; } + while (n <= 255) { zip_static_ltree[n++].dl = 9; zip_bl_count[9]++; } + while (n <= 279) { zip_static_ltree[n++].dl = 7; zip_bl_count[7]++; } + while (n <= 287) { zip_static_ltree[n++].dl = 8; zip_bl_count[8]++; } + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + zip_gen_codes(zip_static_ltree, zip_L_CODES + 1); + + /* The static distance tree is trivial: */ + for (n = 0; n < zip_D_CODES; n++) { + zip_static_dtree[n].dl = 5; + zip_static_dtree[n].fc = zip_bi_reverse(n, 5); + } + + // Initialize the first block of the first file: + zip_init_block(); + } + + /* ========================================================================== + * Initialize a new block. + */ + function zip_init_block() { + var n; // iterates over tree elements + + // Initialize the trees. + for (n = 0; n < zip_L_CODES; n++) zip_dyn_ltree[n].fc = 0; + for (n = 0; n < zip_D_CODES; n++) zip_dyn_dtree[n].fc = 0; + for (n = 0; n < zip_BL_CODES; n++) zip_bl_tree[n].fc = 0; + + zip_dyn_ltree[zip_END_BLOCK].fc = 1; + zip_opt_len = zip_static_len = 0; + zip_last_lit = zip_last_dist = zip_last_flags = 0; + zip_flags = 0; + zip_flag_bit = 1; + } + + /* ========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ + function zip_pqdownheap( + tree, // the tree to restore + k) { // node to move down + var v = zip_heap[k]; + var j = k << 1; // left son of k + + while (j <= zip_heap_len) { + // Set j to the smallest of the two sons: + if (j < zip_heap_len && + zip_SMALLER(tree, zip_heap[j + 1], zip_heap[j])) + j++; + + // Exit if v is smaller than both sons + if (zip_SMALLER(tree, v, zip_heap[j])) + break; + + // Exchange v with the smallest son + zip_heap[k] = zip_heap[j]; + k = j; + + // And continue down the tree, setting j to the left son of k + j <<= 1; + } + zip_heap[k] = v; + } + + /* ========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ + function zip_gen_bitlen(desc) { // the tree descriptor + var tree = desc.dyn_tree; + var extra = desc.extra_bits; + var base = desc.extra_base; + var max_code = desc.max_code; + var max_length = desc.max_length; + var stree = desc.static_tree; + var h; // heap index + var n, m; // iterate over the tree elements + var bits; // bit length + var xbits; // extra bits + var f; // frequency + var overflow = 0; // number of elements with bit length too large + + for (bits = 0; bits <= zip_MAX_BITS; bits++) + zip_bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[zip_heap[zip_heap_max]].dl = 0; // root of the heap + + for (h = zip_heap_max + 1; h < zip_HEAP_SIZE; h++) { + n = zip_heap[h]; + bits = tree[tree[n].dl].dl + 1; + if (bits > max_length) { + bits = max_length; + overflow++; + } + tree[n].dl = bits; + // We overwrite tree[n].dl which is no longer needed + + if (n > max_code) + continue; // not a leaf node + + zip_bl_count[bits]++; + xbits = 0; + if (n >= base) + xbits = extra[n - base]; + f = tree[n].fc; + zip_opt_len += f * (bits + xbits); + if (stree != null) + zip_static_len += f * (stree[n].dl + xbits); + } + if (overflow == 0) + return; + + // This happens for example on obj2 and pic of the Calgary corpus + + // Find the first bit length which could increase: + do { + bits = max_length - 1; + while (zip_bl_count[bits] == 0) + bits--; + zip_bl_count[bits]--; // move one leaf down the tree + zip_bl_count[bits + 1] += 2; // move one overflow item as its brother + zip_bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = zip_bl_count[bits]; + while (n != 0) { + m = zip_heap[--h]; + if (m > max_code) + continue; + if (tree[m].dl != bits) { + zip_opt_len += (bits - tree[m].dl) * tree[m].fc; + tree[m].fc = bits; + } + n--; + } + } + } + + /* ========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ + function zip_gen_codes(tree, // the tree to decorate + max_code) { // largest code with non zero frequency + var next_code = new Array(zip_MAX_BITS + 1); // next code value for each bit length + var code = 0; // running code value + var bits; // bit index + var n; // code index + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= zip_MAX_BITS; bits++) { + code = ((code + zip_bl_count[bits - 1]) << 1); + next_code[bits] = code; + } + + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + // Assert (code + encoder->bl_count[MAX_BITS]-1 == (1<> 1; n >= 1; n--) + zip_pqdownheap(tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + do { + n = zip_heap[zip_SMALLEST]; + zip_heap[zip_SMALLEST] = zip_heap[zip_heap_len--]; + zip_pqdownheap(tree, zip_SMALLEST); + + m = zip_heap[zip_SMALLEST]; // m = node of next least frequency + + // keep the nodes sorted by frequency + zip_heap[--zip_heap_max] = n; + zip_heap[--zip_heap_max] = m; + + // Create a new node father of n and m + tree[node].fc = tree[n].fc + tree[m].fc; + // depth[node] = (char)(MAX(depth[n], depth[m]) + 1); + if (zip_depth[n] > zip_depth[m] + 1) + zip_depth[node] = zip_depth[n]; + else + zip_depth[node] = zip_depth[m] + 1; + tree[n].dl = tree[m].dl = node; + + // and insert the new node in the heap + zip_heap[zip_SMALLEST] = node++; + zip_pqdownheap(tree, zip_SMALLEST); + + } while (zip_heap_len >= 2); + + zip_heap[--zip_heap_max] = zip_heap[zip_SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + zip_gen_bitlen(desc); + + // The field len is now set, we can generate the bit codes + zip_gen_codes(tree, max_code); + } + + /* ========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. Updates opt_len to take into account the repeat + * counts. (The contribution of the bit length codes will be added later + * during the construction of bl_tree.) + */ + function zip_scan_tree(tree,// the tree to be scanned + max_code) { // and its largest code of non zero frequency + var n; // iterates over all tree elements + var prevlen = -1; // last emitted length + var curlen; // length of current code + var nextlen = tree[0].dl; // length of next code + var count = 0; // repeat count of the current code + var max_count = 7; // max repeat count + var min_count = 4; // min repeat count + + if (nextlen == 0) { + max_count = 138; + min_count = 3; + } + tree[max_code + 1].dl = 0xffff; // guard + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[n + 1].dl; + if (++count < max_count && curlen == nextlen) + continue; + else if (count < min_count) + zip_bl_tree[curlen].fc += count; + else if (curlen != 0) { + if (curlen != prevlen) + zip_bl_tree[curlen].fc++; + zip_bl_tree[zip_REP_3_6].fc++; + } else if (count <= 10) + zip_bl_tree[zip_REPZ_3_10].fc++; + else + zip_bl_tree[zip_REPZ_11_138].fc++; + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138; + min_count = 3; + } else if (curlen == nextlen) { + max_count = 6; + min_count = 3; + } else { + max_count = 7; + min_count = 4; + } + } + } + + /* ========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ + function zip_send_tree(tree, // the tree to be scanned + max_code) { // and its largest code of non zero frequency + var n; // iterates over all tree elements + var prevlen = -1; // last emitted length + var curlen; // length of current code + var nextlen = tree[0].dl; // length of next code + var count = 0; // repeat count of the current code + var max_count = 7; // max repeat count + var min_count = 4; // min repeat count + + /* tree[max_code+1].dl = -1; */ /* guard already set */ + if (nextlen == 0) { + max_count = 138; + min_count = 3; + } + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[n + 1].dl; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { zip_SEND_CODE(curlen, zip_bl_tree); } while (--count != 0); + } else if (curlen != 0) { + if (curlen != prevlen) { + zip_SEND_CODE(curlen, zip_bl_tree); + count--; + } + // Assert(count >= 3 && count <= 6, " 3_6?"); + zip_SEND_CODE(zip_REP_3_6, zip_bl_tree); + zip_send_bits(count - 3, 2); + } else if (count <= 10) { + zip_SEND_CODE(zip_REPZ_3_10, zip_bl_tree); + zip_send_bits(count - 3, 3); + } else { + zip_SEND_CODE(zip_REPZ_11_138, zip_bl_tree); + zip_send_bits(count - 11, 7); + } + count = 0; + prevlen = curlen; + if (nextlen == 0) { + max_count = 138; + min_count = 3; + } else if (curlen == nextlen) { + max_count = 6; + min_count = 3; + } else { + max_count = 7; + min_count = 4; + } + } + } + + /* ========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ + function zip_build_bl_tree() { + var max_blindex; // index of last bit length code of non zero freq + + // Determine the bit length frequencies for literal and distance trees + zip_scan_tree(zip_dyn_ltree, zip_l_desc.max_code); + zip_scan_tree(zip_dyn_dtree, zip_d_desc.max_code); + + // Build the bit length tree: + zip_build_tree(zip_bl_desc); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = zip_BL_CODES - 1; max_blindex >= 3; max_blindex--) { + if (zip_bl_tree[zip_bl_order[max_blindex]].dl != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + zip_opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; + // Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + // encoder->opt_len, encoder->static_len)); + + return max_blindex; + } + + /* ========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ + function zip_send_all_trees(lcodes, dcodes, blcodes) { // number of codes for each tree + var rank; // index in bl_order + + // Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + // Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + // "too many codes"); + // Tracev((stderr, "\nbl counts: ")); + zip_send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt + zip_send_bits(dcodes - 1, 5); + zip_send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt + for (rank = 0; rank < blcodes; rank++) { + // Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + zip_send_bits(zip_bl_tree[zip_bl_order[rank]].dl, 3); + } + + // send the literal tree + zip_send_tree(zip_dyn_ltree, lcodes - 1); + + // send the distance tree + zip_send_tree(zip_dyn_dtree, dcodes - 1); + } + + /* ========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ + function zip_flush_block(eof) { // true if this is the last block for a file + var opt_lenb, static_lenb; // opt_len and static_len in bytes + var max_blindex; // index of last bit length code of non zero freq + var stored_len; // length of input block + + stored_len = zip_strstart - zip_block_start; + zip_flag_buf[zip_last_flags] = zip_flags; // Save the flags for the last 8 items + + // Construct the literal and distance trees + zip_build_tree(zip_l_desc); + // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", + // encoder->opt_len, encoder->static_len)); + + zip_build_tree(zip_d_desc); + // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", + // encoder->opt_len, encoder->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = zip_build_bl_tree(); + + // Determine the best encoding. Compute first the block length in bytes + opt_lenb = (zip_opt_len + 3 + 7) >> 3; + static_lenb = (zip_static_len + 3 + 7) >> 3; + + // Trace((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ", + // opt_lenb, encoder->opt_len, + // static_lenb, encoder->static_len, stored_len, + // encoder->last_lit, encoder->last_dist)); + + if (static_lenb <= opt_lenb) + opt_lenb = static_lenb; + if (stored_len + 4 <= opt_lenb // 4: two words for the lengths + && zip_block_start >= 0) { + var i; + + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + zip_send_bits((zip_STORED_BLOCK << 1) + eof, 3); /* send block type */ + zip_bi_windup(); /* align on byte boundary */ + zip_put_short(stored_len); + zip_put_short(~stored_len); + + // copy block + /* + p = &window[block_start]; + for(i = 0; i < stored_len; i++) + put_byte(p[i]); + */ + for (i = 0; i < stored_len; i++) + zip_put_byte(zip_window[zip_block_start + i]); + + } else if (static_lenb == opt_lenb) { + zip_send_bits((zip_STATIC_TREES << 1) + eof, 3); + zip_compress_block(zip_static_ltree, zip_static_dtree); + } else { + zip_send_bits((zip_DYN_TREES << 1) + eof, 3); + zip_send_all_trees(zip_l_desc.max_code + 1, + zip_d_desc.max_code + 1, + max_blindex + 1); + zip_compress_block(zip_dyn_ltree, zip_dyn_dtree); + } + + zip_init_block(); + + if (eof != 0) + zip_bi_windup(); + } + + /* ========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ + function zip_ct_tally( + dist, // distance of matched string + lc) { // match length-MIN_MATCH or unmatched char (if dist==0) + zip_l_buf[zip_last_lit++] = lc; + if (dist == 0) { + // lc is the unmatched char + zip_dyn_ltree[lc].fc++; + } else { + // Here, lc is the match length - MIN_MATCH + dist--; // dist = match distance - 1 + // Assert((ush)dist < (ush)MAX_DIST && + // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + // (ush)D_CODE(dist) < (ush)D_CODES, "ct_tally: bad match"); + + zip_dyn_ltree[zip_length_code[lc] + zip_LITERALS + 1].fc++; + zip_dyn_dtree[zip_D_CODE(dist)].fc++; + + zip_d_buf[zip_last_dist++] = dist; + zip_flags |= zip_flag_bit; + } + zip_flag_bit <<= 1; + + // Output the flags if they fill a byte + if ((zip_last_lit & 7) == 0) { + zip_flag_buf[zip_last_flags++] = zip_flags; + zip_flags = 0; + zip_flag_bit = 1; + } + // Try to guess if it is profitable to stop the current block here + if (zip_compr_level > 2 && (zip_last_lit & 0xfff) == 0) { + // Compute an upper bound for the compressed length + var out_length = zip_last_lit * 8; + var in_length = zip_strstart - zip_block_start; + var dcode; + + for (dcode = 0; dcode < zip_D_CODES; dcode++) { + out_length += zip_dyn_dtree[dcode].fc * (5 + zip_extra_dbits[dcode]); + } + out_length >>= 3; + // Trace((stderr,"\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ", + // encoder->last_lit, encoder->last_dist, in_length, out_length, + // 100L - out_length*100L/in_length)); + if (zip_last_dist < parseInt(zip_last_lit / 2) && + out_length < parseInt(in_length / 2)) + return true; + } + return (zip_last_lit == zip_LIT_BUFSIZE - 1 || + zip_last_dist == zip_DIST_BUFSIZE); + /* We avoid equality with LIT_BUFSIZE because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ + } + + /* ========================================================================== + * Send the block data compressed using the given Huffman trees + */ + function zip_compress_block( + ltree, // literal tree + dtree) { // distance tree + var dist; // distance of matched string + var lc; // match length or unmatched char (if dist == 0) + var lx = 0; // running index in l_buf + var dx = 0; // running index in d_buf + var fx = 0; // running index in flag_buf + var flag = 0; // current flags + var code; // the code to send + var extra; // number of extra bits to send + + if (zip_last_lit != 0) do { + if ((lx & 7) == 0) + flag = zip_flag_buf[fx++]; + lc = zip_l_buf[lx++] & 0xff; + if ((flag & 1) == 0) { + zip_SEND_CODE(lc, ltree); /* send a literal byte */ + // Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + // Here, lc is the match length - MIN_MATCH + code = zip_length_code[lc]; + zip_SEND_CODE(code + zip_LITERALS + 1, ltree); // send the length code + extra = zip_extra_lbits[code]; + if (extra != 0) { + lc -= zip_base_length[code]; + zip_send_bits(lc, extra); // send the extra length bits + } + dist = zip_d_buf[dx++]; + // Here, dist is the match distance - 1 + code = zip_D_CODE(dist); + // Assert (code < D_CODES, "bad d_code"); + + zip_SEND_CODE(code, dtree); // send the distance code + extra = zip_extra_dbits[code]; + if (extra != 0) { + dist -= zip_base_dist[code]; + zip_send_bits(dist, extra); // send the extra distance bits + } + } // literal or match pair ? + flag >>= 1; + } while (lx < zip_last_lit); + + zip_SEND_CODE(zip_END_BLOCK, ltree); + } + + /* ========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ + var zip_Buf_size = 16; // bit size of bi_buf + function zip_send_bits( + value, // value to send + length) { // number of bits + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (zip_bi_valid > zip_Buf_size - length) { + zip_bi_buf |= (value << zip_bi_valid); + zip_put_short(zip_bi_buf); + zip_bi_buf = (value >> (zip_Buf_size - zip_bi_valid)); + zip_bi_valid += length - zip_Buf_size; + } else { + zip_bi_buf |= value << zip_bi_valid; + zip_bi_valid += length; + } + } + + /* ========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ + function zip_bi_reverse( + code, // the value to invert + len) { // its bit length + var res = 0; + do { + res |= code & 1; + code >>= 1; + res <<= 1; + } while (--len > 0); + return res >> 1; + } + + /* ========================================================================== + * Write out any remaining bits in an incomplete byte. + */ + function zip_bi_windup() { + if (zip_bi_valid > 8) { + zip_put_short(zip_bi_buf); + } else if (zip_bi_valid > 0) { + zip_put_byte(zip_bi_buf); + } + zip_bi_buf = 0; + zip_bi_valid = 0; + } + + function zip_qoutbuf() { + if (zip_outcnt != 0) { + var q, i; + q = zip_new_queue(); + if (zip_qhead == null) + zip_qhead = zip_qtail = q; + else + zip_qtail = zip_qtail.next = q; + q.len = zip_outcnt - zip_outoff; + // System.arraycopy(zip_outbuf, zip_outoff, q.ptr, 0, q.len); + for (i = 0; i < q.len; i++) + q.ptr[i] = zip_outbuf[zip_outoff + i]; + zip_outcnt = zip_outoff = 0; + } + } + + return function deflate(str, level) { + var i, j; + + zip_deflate_data = str; + zip_deflate_pos = 0; + if (typeof level == "undefined") + level = zip_DEFAULT_LEVEL; + zip_deflate_start(level); + + var buff = new Array(1024); + var aout = []; + while ((i = zip_deflate_internal(buff, 0, buff.length)) > 0) { + var cbuf = new Array(i); + for (j = 0; j < i; j++) { + cbuf[j] = String.fromCharCode(buff[j]); + } + aout[aout.length] = cbuf.join(""); + } + zip_deflate_data = null; // G.C. + return aout.join(""); + }; +})(); \ No newline at end of file diff --git a/js/main.min.248655eb216150e39da254c2f7aa5357805d0ec66bdb741b591cd35fb5f629ab.js b/js/main.min.248655eb216150e39da254c2f7aa5357805d0ec66bdb741b591cd35fb5f629ab.js new file mode 100644 index 000000000..cc0a66fd8 --- /dev/null +++ b/js/main.min.248655eb216150e39da254c2f7aa5357805d0ec66bdb741b591cd35fb5f629ab.js @@ -0,0 +1,5 @@ +/*! + * Bootstrap v5.2.3 (https://getbootstrap.com/) + * Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */(function(e,t){typeof exports=="object"&&typeof module!="undefined"?module.exports=t():typeof define=="function"&&define.amd?define(t):(e=typeof globalThis!="undefined"?globalThis:e||self,e.bootstrap=t())})(this,function(){"use strict";const ro=1e6,Jr=1e3,ut="transitionend",Xr=e=>e==null?`${e}`:Object.prototype.toString.call(e).match(/\s([a-z]+)/i)[1].toLowerCase(),Gr=e=>{do e+=Math.floor(Math.random()*ro);while(document.getElementById(e))return e},ss=e=>{let t=e.getAttribute("data-bs-target");if(!t||t==="#"){let n=e.getAttribute("href");if(!n||!n.includes("#")&&!n.startsWith("."))return null;n.includes("#")&&!n.startsWith("#")&&(n=`#${n.split("#")[1]}`),t=n&&n!=="#"?n.trim():null}return t},ns=e=>{const t=ss(e);return t?document.querySelector(t)?t:null:null},v=e=>{const t=ss(e);return t?document.querySelector(t):null},Yr=e=>{if(!e)return 0;let{transitionDuration:t,transitionDelay:n}=window.getComputedStyle(e);const s=Number.parseFloat(t),o=Number.parseFloat(n);return!s&&!o?0:(t=t.split(",")[0],n=n.split(",")[0],(Number.parseFloat(t)+Number.parseFloat(n))*Jr)},es=e=>{e.dispatchEvent(new Event(ut))},g=e=>!!e&&typeof e=="object"&&(typeof e.jquery!="undefined"&&(e=e[0]),typeof e.nodeType!="undefined"),E=e=>g(e)?e.jquery?e[0]:e:typeof e=="string"&&e.length>0?document.querySelector(e):null,H=e=>{if(!g(e)||e.getClientRects().length===0)return!1;const n=getComputedStyle(e).getPropertyValue("visibility")==="visible",t=e.closest("details:not([open])");if(!t)return n;if(t!==e){const n=e.closest("summary");if(n&&n.parentNode!==t)return!1;if(n===null)return!1}return n},w=e=>!e||e.nodeType!==Node.ELEMENT_NODE||!!e.classList.contains("disabled")||(typeof e.disabled!="undefined"?e.disabled:e.hasAttribute("disabled")&&e.getAttribute("disabled")!=="false"),Jn=e=>{if(!document.documentElement.attachShadow)return null;if(typeof e.getRootNode=="function"){const t=e.getRootNode();return t instanceof ShadowRoot?t:null}return e instanceof ShadowRoot?e:e.parentNode?Jn(e.parentNode):null},Oe=()=>{},ne=e=>{e.offsetHeight},Xn=()=>window.jQuery&&!document.body.hasAttribute("data-bs-no-jquery")?window.jQuery:null,He=[],Pr=e=>{document.readyState==="loading"?(He.length||document.addEventListener("DOMContentLoaded",()=>{for(const e of He)e()}),He.push(e)):e()},a=()=>document.documentElement.dir==="rtl",c=e=>{Pr(()=>{const t=Xn();if(t){const n=e.NAME,s=t.fn[n];t.fn[n]=e.jQueryInterface,t.fn[n].Constructor=e,t.fn[n].noConflict=()=>(t.fn[n]=s,e.jQueryInterface)}})},y=e=>{typeof e=="function"&&e()},Yn=(e,t,n=!0)=>{if(!n){y(e);return}const i=5,a=Yr(t)+i;let s=!1;const o=({target:n})=>{if(n!==t)return;s=!0,t.removeEventListener(ut,o),y(e)};t.addEventListener(ut,o),setTimeout(()=>{s||es(t)},a)},Le=(e,t,n,s)=>{const i=e.length;let o=e.indexOf(t);return o===-1?!n&&s?e[i-1]:e[0]:(o+=n?1:-1,s&&(o=(o+i)%i),e[Math.max(0,Math.min(o,i-1))])},Nr=/[^.]*(?=\..*)\.|.*/,zr=/\..*/,Tr=/::\d+$/,Ge={};let Un=1;const Vn={mouseenter:"mouseover",mouseleave:"mouseout"},Ar=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function In(e,t){return t&&`${t}::${Un++}`||e.uidEvent||Un++}function Fn(e){const t=In(e);return e.uidEvent=t,Ge[t]=Ge[t]||{},Ge[t]}function xr(t,n){return function s(o){return st(o,{delegateTarget:t}),s.oneOff&&e.off(t,o.type,n),n.apply(t,[o])}}function Or(t,n,s){return function o(i){const a=t.querySelectorAll(n);for(let{target:r}=i;r&&r!==this;r=r.parentNode)for(const c of a){if(c!==r)continue;return st(i,{delegateTarget:r}),o.oneOff&&e.off(t,i.type,n,s),s.apply(r,[i])}}}function Sn(e,t,n=null){return Object.values(e).find(e=>e.callable===t&&e.delegationSelector===n)}function En(e,t,n){const o=typeof t=="string",i=o?n:t||n;let s=On(e);return Ar.has(s)||(s=e),[o,i,s]}function Cn(e,t,n,s,o){if(typeof t!="string"||!e)return;let[r,i,c]=En(t,n,s);if(t in Vn){const e=e=>function(t){if(!t.relatedTarget||t.relatedTarget!==t.delegateTarget&&!t.delegateTarget.contains(t.relatedTarget))return e.call(this,t)};i=e(i)}const d=Fn(e),u=d[c]||(d[c]={}),l=Sn(u,i,r?n:null);if(l){l.oneOff=l.oneOff&&o;return}const h=In(i,t.replace(Nr,"")),a=r?Or(e,n,i):xr(e,i);a.delegationSelector=r?n:null,a.callable=i,a.oneOff=o,a.uidEvent=h,u[h]=a,e.addEventListener(c,a,r)}function Me(e,t,n,s,o){const i=Sn(t[n],s,o);if(!i)return;e.removeEventListener(n,i,Boolean(o)),delete t[n][i.uidEvent]}function wr(e,t,n,s){const o=t[n]||{};for(const i of Object.keys(o))if(i.includes(s)){const s=o[i];Me(e,t,n,s.callable,s.delegationSelector)}}function On(e){return e=e.replace(zr,""),Vn[e]||e}const e={on(e,t,n,s){Cn(e,t,n,s,!1)},one(e,t,n,s){Cn(e,t,n,s,!0)},off(e,t,n,s){if(typeof t!="string"||!e)return;const[c,r,i]=En(t,n,s),l=i!==t,o=Fn(e),a=o[i]||{},d=t.startsWith(".");if(typeof r!="undefined"){if(!Object.keys(a).length)return;Me(e,o,i,r,c?n:null);return}if(d)for(const n of Object.keys(o))wr(e,o,n,t.slice(1));for(const n of Object.keys(a)){const s=n.replace(Tr,"");if(!l||t.includes(s)){const t=a[n];Me(e,o,i,t.callable,t.delegationSelector)}}},trigger(e,t,n){if(typeof t!="string"||!e)return null;const i=Xn(),l=On(t),d=t!==l;let s=null,a=!0,r=!0,c=!1;d&&i&&(s=i.Event(t,n),i(e).trigger(s),a=!s.isPropagationStopped(),r=!s.isImmediatePropagationStopped(),c=s.isDefaultPrevented());let o=new Event(t,{bubbles:a,cancelable:!0});return o=st(o,n),c&&o.preventDefault(),r&&e.dispatchEvent(o),o.defaultPrevented&&s&&s.preventDefault(),o}};function st(e,t){for(const[n,s]of Object.entries(t||{}))try{e[n]=s}catch{Object.defineProperty(e,n,{configurable:!0,get(){return s}})}return e}const x=new Map,it={set(e,t,n){x.has(e)||x.set(e,new Map);const s=x.get(e);if(!s.has(t)&&s.size!==0){console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(s.keys())[0]}.`);return}s.set(t,n)},get(e,t){return x.has(e)?x.get(e).get(t)||null:null},remove(e,t){if(!x.has(e))return;const n=x.get(e);n.delete(t),n.size===0&&x.delete(e)}};function _n(e){if(e==="true")return!0;if(e==="false")return!1;if(e===Number(e).toString())return Number(e);if(e===""||e==="null")return null;if(typeof e!="string")return e;try{return JSON.parse(decodeURIComponent(e))}catch{return e}}function ht(e){return e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`)}const b={setDataAttribute(e,t,n){e.setAttribute(`data-bs-${ht(t)}`,n)},removeDataAttribute(e,t){e.removeAttribute(`data-bs-${ht(t)}`)},getDataAttributes(e){if(!e)return{};const t={},n=Object.keys(e.dataset).filter(e=>e.startsWith("bs")&&!e.startsWith("bsConfig"));for(const o of n){let s=o.replace(/^bs/,"");s=s.charAt(0).toLowerCase()+s.slice(1,s.length),t[s]=_n(e.dataset[o])}return t},getDataAttribute(e,t){return _n(e.getAttribute(`data-bs-${ht(t)}`))}};class te{static get Default(){return{}}static get DefaultType(){return{}}static get NAME(){throw new Error('You have to implement the static method "NAME", for each component!')}_getConfig(e){return e=this._mergeConfigObj(e),e=this._configAfterMerge(e),this._typeCheckConfig(e),e}_configAfterMerge(e){return e}_mergeConfigObj(e,t){const n=g(t)?b.getDataAttribute(t,"config"):{};return{...this.constructor.Default,...typeof n=="object"?n:{},...g(t)?b.getDataAttributes(t):{},...typeof e=="object"?e:{}}}_typeCheckConfig(e,t=this.constructor.DefaultType){for(const n of Object.keys(t)){const s=t[n],o=e[n],i=g(o)?"element":Xr(o);if(!new RegExp(s).test(i))throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${n}" provided type "${i}" but expected type "${s}".`)}}}const _r="5.2.3";class u extends te{constructor(e,t){if(super(),e=E(e),!e)return;this._element=e,this._config=this._getConfig(t),it.set(this._element,this.constructor.DATA_KEY,this)}dispose(){it.remove(this._element,this.constructor.DATA_KEY),e.off(this._element,this.constructor.EVENT_KEY);for(const e of Object.getOwnPropertyNames(this))this[e]=null}_queueCallback(e,t,n=!0){Yn(e,t,n)}_getConfig(e){return e=this._mergeConfigObj(e,this._element),e=this._configAfterMerge(e),this._typeCheckConfig(e),e}static getInstance(e){return it.get(E(e),this.DATA_KEY)}static getOrCreateInstance(e,t={}){return this.getInstance(e)||new this(e,typeof t=="object"?t:null)}static get VERSION(){return _r}static get DATA_KEY(){return`bs.${this.NAME}`}static get EVENT_KEY(){return`.${this.DATA_KEY}`}static eventName(e){return`${e}${this.EVENT_KEY}`}}const Se=(t,n="hide")=>{const o=`click.dismiss${t.EVENT_KEY}`,s=t.NAME;e.on(document,o,`[data-bs-dismiss="${s}"]`,function(e){if(["A","AREA"].includes(this.tagName)&&e.preventDefault(),w(this))return;const o=v(this)||this.closest(`.${s}`),i=t.getOrCreateInstance(o);i[n]()})},jr="alert",dr="bs.alert",vn=`.${dr}`,rr=`close${vn}`,Ja=`closed${vn}`,Qa="fade",Ga="show";class de extends u{static get NAME(){return jr}close(){const t=e.trigger(this._element,rr);if(t.defaultPrevented)return;this._element.classList.remove(Ga);const n=this._element.classList.contains(Qa);this._queueCallback(()=>this._destroyElement(),this._element,n)}_destroyElement(){this._element.remove(),e.trigger(this._element,Ja),this.dispose()}static jQueryInterface(e){return this.each(function(){const t=de.getOrCreateInstance(this);if(typeof e!="string")return;if(t[e]===void 0||e.startsWith("_")||e==="constructor")throw new TypeError(`No method named "${e}"`);t[e](this)})}}Se(de,"close"),c(de);const Ka="button",$a="bs.button",Ia=`.${$a}`,Da=".data-api",ba="active",fn='[data-bs-toggle="button"]',va=`click${Ia}${Da}`;class fe extends u{static get NAME(){return Ka}toggle(){this._element.setAttribute("aria-pressed",this._element.classList.toggle(ba))}static jQueryInterface(e){return this.each(function(){const t=fe.getOrCreateInstance(this);e==="toggle"&&t[e]()})}}e.on(document,va,fn,e=>{e.preventDefault();const t=e.target.closest(fn),n=fe.getOrCreateInstance(t);n.toggle()}),c(fe);const t={find(e,t=document.documentElement){return[].concat(...Element.prototype.querySelectorAll.call(t,e))},findOne(e,t=document.documentElement){return Element.prototype.querySelector.call(t,e)},children(e,t){return[].concat(...e.children).filter(e=>e.matches(t))},parents(e,t){const s=[];let n=e.parentNode.closest(t);for(;n;)s.push(n),n=n.parentNode.closest(t);return s},prev(e,t){let n=e.previousElementSibling;for(;n;){if(n.matches(t))return[n];n=n.previousElementSibling}return[]},next(e,t){let n=e.nextElementSibling;for(;n;){if(n.matches(t))return[n];n=n.nextElementSibling}return[]},focusableChildren(e){const t=["a","button","input","textarea","select","details","[tabindex]",'[contenteditable="true"]'].map(e=>`${e}:not([tabindex^="-"])`).join(",");return this.find(t,e).filter(e=>!w(e)&&H(e))}},ga="swipe",$=".bs.swipe",pa=`touchstart${$}`,ma=`touchmove${$}`,ua=`touchend${$}`,na=`pointerdown${$}`,Xi=`pointerup${$}`,$i="touch",Vi="pen",Pi="pointer-event",Li=40,Ni={endCallback:null,leftCallback:null,rightCallback:null},Di={endCallback:"(function|null)",leftCallback:"(function|null)",rightCallback:"(function|null)"};class Re extends te{constructor(e,t){if(super(),this._element=e,!e||!Re.isSupported())return;this._config=this._getConfig(t),this._deltaX=0,this._supportPointerEvents=Boolean(window.PointerEvent),this._initEvents()}static get Default(){return Ni}static get DefaultType(){return Di}static get NAME(){return ga}dispose(){e.off(this._element,$)}_start(e){if(!this._supportPointerEvents){this._deltaX=e.touches[0].clientX;return}this._eventIsPointerPenTouch(e)&&(this._deltaX=e.clientX)}_end(e){this._eventIsPointerPenTouch(e)&&(this._deltaX=e.clientX-this._deltaX),this._handleSwipe(),y(this._config.endCallback)}_move(e){this._deltaX=e.touches&&e.touches.length>1?0:e.touches[0].clientX-this._deltaX}_handleSwipe(){const e=Math.abs(this._deltaX);if(e<=Li)return;const t=e/this._deltaX;if(this._deltaX=0,!t)return;y(t>0?this._config.rightCallback:this._config.leftCallback)}_initEvents(){this._supportPointerEvents?(e.on(this._element,na,e=>this._start(e)),e.on(this._element,Xi,e=>this._end(e)),this._element.classList.add(Pi)):(e.on(this._element,pa,e=>this._start(e)),e.on(this._element,ma,e=>this._move(e)),e.on(this._element,ua,e=>this._end(e)))}_eventIsPointerPenTouch(e){return this._supportPointerEvents&&(e.pointerType===Vi||e.pointerType===$i)}static isSupported(){return"ontouchstart"in document.documentElement||navigator.maxTouchPoints>0}}const is="carousel",Mi="bs.carousel",k=`.${Mi}`,Wt=".data-api",ki="ArrowLeft",yi="ArrowRight",ji=500,Z="next",K="prev",P="left",Ae="right",vi=`slide${k}`,Ve=`slid${k}`,di=`keydown${k}`,li=`mouseenter${k}`,oi=`mouseleave${k}`,ti=`dragstart${k}`,Zo=`load${k}${Wt}`,qo=`click${k}${Wt}`,Lt="carousel",ye="active",Wo="slide",Bo="carousel-item-end",Io="carousel-item-start",Po="carousel-item-next",Ro="carousel-item-prev",Mt=".active",Ct=".carousel-item",Lo=Mt+Ct,No=".carousel-item img",Do=".carousel-indicators",zo="[data-bs-slide], [data-bs-slide-to]",To='[data-bs-ride="carousel"]',bo={[ki]:Ae,[yi]:P},go={interval:5e3,keyboard:!0,pause:"hover",ride:!1,touch:!0,wrap:!0},lo={interval:"(number|boolean)",keyboard:"boolean",pause:"(string|boolean)",ride:"(boolean|string)",touch:"boolean",wrap:"boolean"};class ie extends u{constructor(e,n){super(e,n),this._interval=null,this._activeElement=null,this._isSliding=!1,this.touchTimeout=null,this._swipeHelper=null,this._indicatorsElement=t.findOne(Do,this._element),this._addEventListeners(),this._config.ride===Lt&&this.cycle()}static get Default(){return go}static get DefaultType(){return lo}static get NAME(){return is}next(){this._slide(Z)}nextWhenVisible(){!document.hidden&&H(this._element)&&this.next()}prev(){this._slide(K)}pause(){this._isSliding&&es(this._element),this._clearInterval()}cycle(){this._clearInterval(),this._updateInterval(),this._interval=setInterval(()=>this.nextWhenVisible(),this._config.interval)}_maybeEnableCycle(){if(!this._config.ride)return;if(this._isSliding){e.one(this._element,Ve,()=>this.cycle());return}this.cycle()}to(t){const n=this._getItems();if(t>n.length-1||t<0)return;if(this._isSliding){e.one(this._element,Ve,()=>this.to(t));return}const s=this._getItemIndex(this._getActive());if(s===t)return;const o=t>s?Z:K;this._slide(o,n[t])}dispose(){this._swipeHelper&&this._swipeHelper.dispose(),super.dispose()}_configAfterMerge(e){return e.defaultInterval=e.interval,e}_addEventListeners(){this._config.keyboard&&e.on(this._element,di,e=>this._keydown(e)),this._config.pause==="hover"&&(e.on(this._element,li,()=>this.pause()),e.on(this._element,oi,()=>this._maybeEnableCycle())),this._config.touch&&Re.isSupported()&&this._addTouchEventListeners()}_addTouchEventListeners(){for(const n of t.find(No,this._element))e.on(n,ti,e=>e.preventDefault());const n=()=>{if(this._config.pause!=="hover")return;this.pause(),this.touchTimeout&&clearTimeout(this.touchTimeout),this.touchTimeout=setTimeout(()=>this._maybeEnableCycle(),ji+this._config.interval)},s={leftCallback:()=>this._slide(this._directionToOrder(P)),rightCallback:()=>this._slide(this._directionToOrder(Ae)),endCallback:n};this._swipeHelper=new Re(this._element,s)}_keydown(e){if(/input|textarea/i.test(e.target.tagName))return;const t=bo[e.key];t&&(e.preventDefault(),this._slide(this._directionToOrder(t)))}_getItemIndex(e){return this._getItems().indexOf(e)}_setActiveIndicatorElement(e){if(!this._indicatorsElement)return;const s=t.findOne(Mt,this._indicatorsElement);s.classList.remove(ye),s.removeAttribute("aria-current");const n=t.findOne(`[data-bs-slide-to="${e}"]`,this._indicatorsElement);n&&(n.classList.add(ye),n.setAttribute("aria-current","true"))}_updateInterval(){const e=this._activeElement||this._getActive();if(!e)return;const t=Number.parseInt(e.getAttribute("data-bs-interval"),10);this._config.interval=t||this._config.defaultInterval}_slide(t,n=null){if(this._isSliding)return;const o=this._getActive(),a=t===Z,s=n||Le(this._getItems(),o,a,this._config.wrap);if(s===o)return;const c=this._getItemIndex(s),l=n=>e.trigger(this._element,n,{relatedTarget:s,direction:this._orderToDirection(t),from:this._getItemIndex(o),to:c}),d=l(vi);if(d.defaultPrevented)return;if(!o||!s)return;const u=Boolean(this._interval);this.pause(),this._isSliding=!0,this._setActiveIndicatorElement(c),this._activeElement=s;const i=a?Io:Bo,r=a?Po:Ro;s.classList.add(r),ne(s),o.classList.add(i),s.classList.add(i);const h=()=>{s.classList.remove(i,r),s.classList.add(ye),o.classList.remove(ye,r,i),this._isSliding=!1,l(Ve)};this._queueCallback(h,o,this._isAnimated()),u&&this.cycle()}_isAnimated(){return this._element.classList.contains(Wo)}_getActive(){return t.findOne(Lo,this._element)}_getItems(){return t.find(Ct,this._element)}_clearInterval(){this._interval&&(clearInterval(this._interval),this._interval=null)}_directionToOrder(e){return a()?e===P?K:Z:e===P?Z:K}_orderToDirection(e){return a()?e===K?P:Ae:e===K?Ae:P}static jQueryInterface(e){return this.each(function(){const t=ie.getOrCreateInstance(this,e);if(typeof e=="number"){t.to(e);return}if(typeof e=="string"){if(t[e]===void 0||e.startsWith("_")||e==="constructor")throw new TypeError(`No method named "${e}"`);t[e]()}})}}e.on(document,qo,zo,function(e){const n=v(this);if(!n||!n.classList.contains(Lt))return;e.preventDefault();const t=ie.getOrCreateInstance(n),s=this.getAttribute("data-bs-slide-to");if(s){t.to(s),t._maybeEnableCycle();return}if(b.getDataAttribute(this,"slide")==="next"){t.next(),t._maybeEnableCycle();return}t.prev(),t._maybeEnableCycle()}),e.on(window,Zo,()=>{const e=t.find(To);for(const t of e)ie.getOrCreateInstance(t)}),c(ie);const os="collapse",ao="bs.collapse",ee=`.${ao}`,eo=".data-api",Zs=`show${ee}`,Xs=`shown${ee}`,Gs=`hide${ee}`,qs=`hidden${ee}`,Ks=`click${ee}${eo}`,rt="show",V="collapse",je="collapsing",Us="collapsed",Ws=`:scope .${V} .${V}`,$s="collapse-horizontal",Vs="width",Bs="height",Is=".collapse.show, .collapse.collapsing",et='[data-bs-toggle="collapse"]',Hs={parent:null,toggle:!0},Ps={parent:"(null|element)",toggle:"boolean"};class le extends u{constructor(e,n){super(e,n),this._isTransitioning=!1,this._triggerArray=[];const s=t.find(et);for(const e of s){const n=ns(e),o=t.find(n).filter(e=>e===this._element);n!==null&&o.length&&this._triggerArray.push(e)}this._initializeChildren(),this._config.parent||this._addAriaAndCollapsedClass(this._triggerArray,this._isShown()),this._config.toggle&&this.toggle()}static get Default(){return Hs}static get DefaultType(){return Ps}static get NAME(){return os}toggle(){this._isShown()?this.hide():this.show()}show(){if(this._isTransitioning||this._isShown())return;let n=[];if(this._config.parent&&(n=this._getFirstLevelChildren(Is).filter(e=>e!==this._element).map(e=>le.getOrCreateInstance(e,{toggle:!1}))),n.length&&n[0]._isTransitioning)return;const s=e.trigger(this._element,Zs);if(s.defaultPrevented)return;for(const e of n)e.hide();const t=this._getDimension();this._element.classList.remove(V),this._element.classList.add(je),this._element.style[t]=0,this._addAriaAndCollapsedClass(this._triggerArray,!0),this._isTransitioning=!0;const o=()=>{this._isTransitioning=!1,this._element.classList.remove(je),this._element.classList.add(V,rt),this._element.style[t]="",e.trigger(this._element,Xs)},i=t[0].toUpperCase()+t.slice(1),a=`scroll${i}`;this._queueCallback(o,this._element,!0),this._element.style[t]=`${this._element[a]}px`}hide(){if(this._isTransitioning||!this._isShown())return;const n=e.trigger(this._element,Gs);if(n.defaultPrevented)return;const t=this._getDimension();this._element.style[t]=`${this._element.getBoundingClientRect()[t]}px`,ne(this._element),this._element.classList.add(je),this._element.classList.remove(V,rt);for(const e of this._triggerArray){const t=v(e);t&&!this._isShown(t)&&this._addAriaAndCollapsedClass([e],!1)}this._isTransitioning=!0;const s=()=>{this._isTransitioning=!1,this._element.classList.remove(je),this._element.classList.add(V),e.trigger(this._element,qs)};this._element.style[t]="",this._queueCallback(s,this._element,!0)}_isShown(e=this._element){return e.classList.contains(rt)}_configAfterMerge(e){return e.toggle=Boolean(e.toggle),e.parent=E(e.parent),e}_getDimension(){return this._element.classList.contains($s)?Vs:Bs}_initializeChildren(){if(!this._config.parent)return;const e=this._getFirstLevelChildren(et);for(const t of e){const n=v(t);n&&this._addAriaAndCollapsedClass([t],this._isShown(n))}}_getFirstLevelChildren(e){const n=t.find(Ws,this._config.parent);return t.find(e,this._config.parent).filter(e=>!n.includes(e))}_addAriaAndCollapsedClass(e,t){if(!e.length)return;for(const n of e)n.classList.toggle(Us,!t),n.setAttribute("aria-expanded",t)}static jQueryInterface(e){const t={};return typeof e=="string"&&/show|hide/.test(e)&&(t.toggle=!1),this.each(function(){const n=le.getOrCreateInstance(this,t);if(typeof e=="string"){if(typeof n[e]=="undefined")throw new TypeError(`No method named "${e}"`);n[e]()}})}}e.on(document,Ks,et,function(e){(e.target.tagName==="A"||e.delegateTarget&&e.delegateTarget.tagName==="A")&&e.preventDefault();const n=ns(this),s=t.find(n);for(const e of s)le.getOrCreateInstance(e,{toggle:!1}).toggle()}),c(le);var O,z,s="top",se,Ln,Bn,ae,Gn,Qn,Je,St,At,kt,Et,he,o="bottom",i="right",n="left",xe="auto",G=[s,o,i,n],F="start",W="end",$t="clippingParents",ze="viewport",L="popper",Kt="reference",Ie=G.reduce(function(e,t){return e.concat([t+"-"+F,t+"-"+W])},[]),Be=[].concat(G,[xe]).reduce(function(e,t){return e.concat([t,t+"-"+F,t+"-"+W])},[]),Gt="beforeRead",Xt="read",Qt="afterRead",Zt="beforeMain",Jt="main",en="afterMain",tn="beforeWrite",nn="write",sn="afterWrite",on=[Gt,Xt,Qt,Zt,Jt,en,tn,nn,sn];function f(e){return e?(e.nodeName||"").toLowerCase():null}function r(e){if(e==null)return window;if(e.toString()!=="[object Window]"){var t=e.ownerDocument;return t?t.defaultView||window:window}return e}function D(e){var t=r(e).Element;return e instanceof t||e instanceof Element}function l(e){var t=r(e).HTMLElement;return e instanceof t||e instanceof HTMLElement}function Ye(e){if(typeof ShadowRoot=="undefined")return!1;var t=r(e).ShadowRoot;return e instanceof t||e instanceof ShadowRoot}function Ss(e){var t=e.state;Object.keys(t.elements).forEach(function(e){var o=t.styles[e]||{},s=t.attributes[e]||{},n=t.elements[e];if(!l(n)||!f(n))return;Object.assign(n.style,o),Object.keys(s).forEach(function(e){var t=s[e];t===!1?n.removeAttribute(e):n.setAttribute(e,t===!0?"":t)})})}function Es(e){var t=e.state,n={popper:{position:t.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(t.elements.popper.style,n.popper),t.styles=n,t.elements.arrow&&Object.assign(t.elements.arrow.style,n.arrow),function(){Object.keys(t.elements).forEach(function(e){var s=t.elements[e],o=t.attributes[e]||{},i=Object.keys(t.styles.hasOwnProperty(e)?t.styles[e]:n[e]),a=i.reduce(function(e,t){return e[t]="",e},{});if(!l(s)||!f(s))return;Object.assign(s.style,a),Object.keys(o).forEach(function(e){s.removeAttribute(e)})})}}const Ze={name:"applyStyles",enabled:!0,phase:"write",fn:Ss,effect:Es,requires:["computeStyles"]};function m(e){return e.split("-")[0]}O=Math.max,se=Math.min,z=Math.round;function nt(){var e=navigator.userAgentData;return e!=null&&e.brands?e.brands.map(function(e){return e.brand+"/"+e.version}).join(" "):navigator.userAgent}function jn(){return!/^((?!chrome|android).)*safari/i.test(nt())}function X(e,t,n){t===void 0&&(t=!1),n===void 0&&(n=!1),s=e.getBoundingClientRect(),o=1,i=1,t&&l(e)&&(o=e.offsetWidth>0?z(s.width)/e.offsetWidth||1:1,i=e.offsetHeight>0?z(s.height)/e.offsetHeight||1:1);var s,o,i,f=D(e)?r(e):window,a=f.visualViewport,u=!jn()&&n,c=(s.left+(u&&a?a.offsetLeft:0))/o,d=(s.top+(u&&a?a.offsetTop:0))/i,h=s.width/o,m=s.height/i;return{width:h,height:m,top:d,right:c+h,bottom:d+m,left:c,x:c,y:d}}function dt(e){var t=X(e),n=e.offsetWidth,s=e.offsetHeight;return Math.abs(t.width-n)<=1&&(n=t.width),Math.abs(t.height-s)<=1&&(s=t.height),{x:e.offsetLeft,y:e.offsetTop,width:n,height:s}}function wn(e,t){var n,s=t.getRootNode&&t.getRootNode();if(e.contains(t))return!0;if(s&&Ye(s)){n=t;do{if(n&&e.isSameNode(n))return!0;n=n.parentNode||n.host}while(n)}return!1}function p(e){return r(e).getComputedStyle(e)}function xs(e){return["table","td","th"].indexOf(f(e))>=0}function _(e){return((D(e)?e.ownerDocument:e.document)||window.document).documentElement}function ve(e){return f(e)==="html"?e:e.assignedSlot||e.parentNode||(Ye(e)?e.host:null)||_(e)}function kn(e){return!l(e)||p(e).position==="fixed"?null:e.offsetParent}function _s(e){var t,n,o,s=/firefox/i.test(nt()),i=/Trident/i.test(nt());if(i&&l(e)&&(o=p(e),o.position==="fixed"))return null;for(t=ve(e),Ye(t)&&(t=t.host);l(t)&&["html","body"].indexOf(f(t))<0;){if(n=p(t),n.transform!=="none"||n.perspective!=="none"||n.contain==="paint"||["transform","perspective"].indexOf(n.willChange)!==-1||s&&n.willChange==="filter"||s&&n.filter&&n.filter!=="none")return t;t=t.parentNode}return null}function re(e){for(var n=r(e),t=kn(e);t&&xs(t)&&p(t).position==="static";)t=kn(t);return t&&(f(t)==="html"||f(t)==="body"&&p(t).position==="static")?n:t||_s(e)||n}function Ue(e){return["top","bottom"].indexOf(e)>=0?"x":"y"}function oe(e,t,n){return O(e,se(t,n))}function js(e,t,n){var s=oe(e,t,n);return s>n?n:s}function zn(){return{top:0,right:0,bottom:0,left:0}}function Dn(e){return Object.assign({},zn(),e)}function Nn(e,t){return t.reduce(function(t,n){return t[n]=e,t},{})}Ln=function(t,n){return t=typeof t=="function"?t(Object.assign({},n.rects,{placement:n.placement})):t,Dn(typeof t!="number"?t:Nn(t,G))};function bs(e){var r,c,d,u,p,g,v,b,j,y,_,O,x,C,E,t=e.state,S=e.name,A=e.options,h=t.elements.arrow,f=t.modifiersData.popperOffsets,w=m(t.placement),a=Ue(w),k=[n,i].indexOf(w)>=0,l=k?"height":"width";if(!h||!f)return;g=Ln(A.padding,t),v=dt(h),b=a==="y"?s:n,j=a==="y"?o:i,y=t.rects.reference[l]+t.rects.reference[a]-f[a]-t.rects.popper[l],_=f[a]-t.rects.reference[a],c=re(h),p=c?a==="y"?c.clientHeight||0:c.clientWidth||0:0,O=y/2-_/2,x=g[b],C=p-v[l]-g[j],u=p/2-v[l]/2+O,d=oe(x,u,C),E=a,t.modifiersData[S]=(r={},r[E]=d,r.centerOffset=d-u,r)}function vs(e){var n=e.state,o=e.options,s=o.element,t=s===void 0?"[data-popper-arrow]":s;if(t==null)return;if(typeof t=="string"&&(t=n.elements.popper.querySelector(t),!t))return;if(!wn(n.elements.popper,t))return;n.elements.arrow=t}const Hn={name:"arrow",enabled:!0,phase:"main",fn:bs,effect:vs,requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function Q(e){return e.split("-")[1]}Bn={top:"auto",right:"auto",bottom:"auto",left:"auto"};function ms(e){var n=e.x,s=e.y,o=window,t=o.devicePixelRatio||1;return{x:z(n*t)/t||0,y:z(s*t)/t||0}}function $n(e){var c,u,h,b,j,y,x,T,z,f=e.popper,D=e.popperRect,d=e.placement,k=e.variation,m=e.offsets,S=e.position,v=e.gpuAcceleration,A=e.adaptive,w=e.roundOffsets,L=e.isFixed,N=m.x,t=N===void 0?0:N,M=m.y,a=M===void 0?0:M,E=typeof w=="function"?w({x:t,y:a}):{x:t,y:a},t=E.x,a=E.y,F=m.hasOwnProperty("x"),C=m.hasOwnProperty("y"),O=n,g=s,l=window;return A&&(c=re(f),y="clientHeight",j="clientWidth",c===r(f)&&(c=_(f),p(c).position!=="static"&&S==="absolute"&&(y="scrollHeight",j="scrollWidth")),c=c,(d===s||(d===n||d===i)&&k===W)&&(g=o,T=L&&c===l&&l.visualViewport?l.visualViewport.height:c[y],a-=T-D.height,a*=v?1:-1),(d===n||(d===s||d===o)&&k===W)&&(O=i,z=L&&c===l&&l.visualViewport?l.visualViewport.width:c[j],t-=z-D.width,t*=v?1:-1)),x=Object.assign({position:S},A&&Bn),b=w===!0?ms({x:t,y:a}):{x:t,y:a},t=b.x,a=b.y,v?Object.assign({},x,(h={},h[g]=C?"0":"",h[O]=F?"0":"",h.transform=(l.devicePixelRatio||1)<=1?"translate("+t+"px, "+a+"px)":"translate3d("+t+"px, "+a+"px, 0)",h)):Object.assign({},x,(u={},u[g]=C?a+"px":"",u[O]=F?t+"px":"",u.transform="",u))}function hs(e){var t=e.state,n=e.options,s=n.gpuAcceleration,c=s===void 0||s,o=n.adaptive,l=o===void 0||o,i=n.roundOffsets,a=i===void 0||i,r={placement:m(t.placement),variation:Q(t.placement),popper:t.elements.popper,popperRect:t.rects.popper,gpuAcceleration:c,isFixed:t.options.strategy==="fixed"};t.modifiersData.popperOffsets!=null&&(t.styles.popper=Object.assign({},t.styles.popper,$n(Object.assign({},r,{offsets:t.modifiersData.popperOffsets,position:t.options.strategy,adaptive:l,roundOffsets:a})))),t.modifiersData.arrow!=null&&(t.styles.arrow=Object.assign({},t.styles.arrow,$n(Object.assign({},r,{offsets:t.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:a})))),t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-placement":t.placement})}const Te={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:hs,data:{}};ae={passive:!0};function ls(e){var n=e.state,t=e.instance,s=e.options,o=s.scroll,i=o===void 0||o,a=s.resize,c=a===void 0||a,l=r(n.elements.popper),d=[].concat(n.scrollParents.reference,n.scrollParents.popper);return i&&d.forEach(function(e){e.addEventListener("scroll",t.update,ae)}),c&&l.addEventListener("resize",t.update,ae),function(){i&&d.forEach(function(e){e.removeEventListener("scroll",t.update,ae)}),c&&l.removeEventListener("resize",t.update,ae)}}const Pe={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:ls,data:{}};Gn={left:"right",right:"left",bottom:"top",top:"bottom"};function ke(e){return e.replace(/left|right|bottom|top/g,function(e){return Gn[e]})}Qn={start:"end",end:"start"};function Zn(e){return e.replace(/start|end/g,function(e){return Qn[e]})}function Ke(e){var t=r(e),n=t.pageXOffset,s=t.pageYOffset;return{scrollLeft:n,scrollTop:s}}function qe(e){return X(_(e)).left+Ke(e).scrollLeft}function rs(e,t){var s,d=r(e),o=_(e),n=d.visualViewport,i=o.clientWidth,a=o.clientHeight,c=0,l=0;return n&&(i=n.width,a=n.height,s=jn(),(s||!s&&t==="fixed")&&(c=n.offsetLeft,l=n.offsetTop)),{width:i,height:a,x:c+qe(e),y:l}}function Fi(e){var s,n=_(e),o=Ke(e),t=(s=e.ownerDocument)==null?void 0:s.body,i=O(n.scrollWidth,n.clientWidth,t?t.scrollWidth:0,t?t.clientWidth:0),r=O(n.scrollHeight,n.clientHeight,t?t.scrollHeight:0,t?t.clientHeight:0),a=-o.scrollLeft+qe(e),c=-o.scrollTop;return p(t||n).direction==="rtl"&&(a+=O(n.clientWidth,t?t.clientWidth:0)-i),{width:i,height:r,x:a,y:c}}function at(e){var t=p(e),n=t.overflow,s=t.overflowX,o=t.overflowY;return/auto|scroll|overlay|hidden/.test(n+o+s)}function zt(e){return["html","body","#document"].indexOf(f(e))>=0?e.ownerDocument.body:l(e)&&at(e)?e:zt(ve(e))}function ce(e,t){t===void 0&&(t=[]);var s,n=zt(e),o=n===((s=e.ownerDocument)==null?void 0:s.body),i=r(n),a=o?[i].concat(i.visualViewport||[],at(n)?n:[]):n,c=t.concat(a);return o?c:c.concat(ce(ve(a)))}function Fe(e){return Object.assign({},e,{left:e.x,top:e.y,right:e.x+e.width,bottom:e.y+e.height})}function cs(e,t){var n=X(e,!1,t==="fixed");return n.top=n.top+e.clientTop,n.left=n.left+e.clientLeft,n.bottom=n.top+e.clientHeight,n.right=n.left+e.clientWidth,n.width=e.clientWidth,n.height=e.clientHeight,n.x=n.left,n.y=n.top,n}function qn(e,t,n){return t===ze?Fe(rs(e,n)):D(t)?cs(t,n):Fe(Fi(_(e)))}function ds(e){var n=ce(ve(e)),s=["absolute","fixed"].indexOf(p(e).position)>=0,t=s&&l(e)?re(e):e;return D(t)?n.filter(function(e){return D(e)&&wn(e,t)&&f(e)!=="body"}):[]}function us(e,t,n,s){var a=t==="clippingParents"?ds(e):[].concat(t),i=[].concat(a,[n]),r=i[0],o=i.reduce(function(t,n){var o=qn(e,n,s);return t.top=O(o.top,t.top),t.right=se(o.right,t.right),t.bottom=se(o.bottom,t.bottom),t.left=O(o.left,t.left),t},qn(e,r,s));return o.width=o.right-o.left,o.height=o.bottom-o.top,o.x=o.left,o.y=o.top,o}function Wn(e){var a,r,l,t=e.reference,c=e.element,d=e.placement,u=d?m(d):null,p=d?Q(d):null,h=t.x+t.width/2-c.width/2,f=t.y+t.height/2-c.height/2;switch(u){case s:a={x:h,y:t.y-c.height};break;case o:a={x:h,y:t.y+t.height};break;case i:a={x:t.x+t.width,y:f};break;case n:a={x:t.x-c.width,y:f};break;default:a={x:t.x,y:t.y}}if(r=u?Ue(u):null,r!=null)switch(l=r==="y"?"height":"width",p){case F:a[r]=a[r]-(t[l]/2-c[l]/2);break;case W:a[r]=a[r]+(t[l]/2-c[l]/2);break}return a}function I(e,t){t===void 0&&(t={});var w,n=t,v=n.placement,j=v===void 0?e.placement:v,f=n.strategy,T=f===void 0?e.strategy:f,p=n.boundary,E=p===void 0?$t:p,x=n.rootBoundary,F=x===void 0?ze:x,C=n.elementContext,c=C===void 0?L:C,m=n.altBoundary,M=m!==void 0&&m,b=n.padding,d=b===void 0?0:b,a=Dn(typeof d!="number"?d:Nn(d,G)),S=c===L?Kt:L,O=e.rects.popper,h=e.elements[M?S:c],r=us(D(h)?h:h.contextElement||_(e.elements.popper),E,F,T),y=X(e.elements.reference),k=Wn({reference:y,element:O,strategy:"absolute",placement:j}),A=Fe(Object.assign({},O,k)),l=c===L?A:y,u={top:r.top-l.top+a.top,bottom:l.bottom-r.bottom+a.bottom,left:r.left-l.left+a.left,right:l.right-r.right+a.right},g=e.modifiersData.offset;return c===L&&g&&(w=g[j],Object.keys(u).forEach(function(e){var t=[i,o].indexOf(e)>=0?1:-1,n=[s,o].indexOf(e)>=0?"y":"x";u[e]+=w[n]*t})),u}function fs(e,t){t===void 0&&(t={});var s,n=t,c=n.placement,l=n.boundary,d=n.rootBoundary,u=n.padding,h=n.flipVariations,i=n.allowedAutoPlacements,f=i===void 0?Be:i,a=Q(c),r=a?h?Ie:Ie.filter(function(e){return Q(e)===a}):G,o=r.filter(function(e){return f.indexOf(e)>=0});return o.length===0&&(o=r),s=o.reduce(function(t,n){return t[n]=I(e,{placement:n,boundary:l,rootBoundary:d,padding:u})[m(n)],t},{}),Object.keys(s).sort(function(e,t){return s[e]-s[t]})}function ps(e){if(m(e)===xe)return[];var t=ke(e);return[Zn(e),t,Zn(t)]}function gs(e){var r,c,l,u,h,g,v,y,_,x,E,k,z,t=e.state,a=e.options,C=e.name;if(t.modifiersData[C]._skip)return;for(var M=a.mainAxis,H=M===void 0||M,D=a.altAxis,R=D===void 0||D,L=a.fallbackPlacements,N=a.padding,w=a.boundary,O=a.rootBoundary,B=a.altBoundary,T=a.flipVariations,j=T===void 0||T,V=a.allowedAutoPlacements,d=t.options.placement,U=m(d),P=U===d,K=L||(P||!j?[ke(d)]:ps(d)),p=[d].concat(K).reduce(function(e,n){return e.concat(m(n)===xe?fs(t,{placement:n,boundary:w,rootBoundary:O,padding:N,flipVariations:j,allowedAutoPlacements:V}):n)},[]),W=t.rects.reference,$=t.rects.popper,A=new Map,S=!0,f=p[0],b=0;b=0,_=y?"width":"height",h=I(t,{placement:r,boundary:w,rootBoundary:O,altBoundary:B,padding:N}),l=y?g?i:n:g?o:s,W[_]>$[_]&&(l=ke(l)),z=ke(l),c=[],H&&c.push(h[v]<=0),R&&c.push(h[l]<=0,h[z]<=0),c.every(function(e){return e})){f=r,S=!1;break}A.set(r,c)}if(S)for(k=j?3:1,E=function(t){var n=p.find(function(e){var n=A.get(e);if(n)return n.slice(0,t).every(function(e){return e})});if(n)return f=n,"break"},u=k;u>0;u--)if(x=E(u),x==="break")break;t.placement!==f&&(t.modifiersData[C]._skip=!0,t.placement=f,t.reset=!0)}const Pn={name:"flip",enabled:!0,phase:"main",fn:gs,requiresIfExists:["offset"],data:{_skip:!1}};function Rn(e,t,n){return n===void 0&&(n={x:0,y:0}),{top:e.top-t.height-n.y,right:e.right-t.width+n.x,bottom:e.bottom-t.height+n.y,left:e.left-t.width-n.x}}function Tn(e){return[s,i,o,n].some(function(t){return e[t]>=0})}function ys(e){var t=e.state,a=e.name,r=t.rects.reference,c=t.rects.popper,l=t.modifiersData.preventOverflow,d=I(t,{elementContext:"reference"}),u=I(t,{altBoundary:!0}),n=Rn(d,r),s=Rn(u,c,l),o=Tn(n),i=Tn(s);t.modifiersData[a]={referenceClippingOffsets:n,popperEscapeOffsets:s,isReferenceHidden:o,hasPopperEscaped:i},t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-reference-hidden":o,"data-popper-escaped":i})}const An={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:ys};function ws(e,t,o){var c=m(e),d=[n,s].indexOf(c)>=0?-1:1,l=typeof o=="function"?o(Object.assign({},t,{placement:e})):o,a=l[0],r=l[1],a=a||0,r=(r||0)*d;return[n,i].indexOf(c)>=0?{x:r,y:a}:{x:a,y:r}}function Os(e){var t=e.state,i=e.options,a=e.name,n=i.offset,r=n===void 0?[0,0]:n,s=Be.reduce(function(e,n){return e[n]=ws(n,t.rects,r),e},{}),o=s[t.placement],c=o.x,l=o.y;t.modifiersData.popperOffsets!=null&&(t.modifiersData.popperOffsets.x+=c,t.modifiersData.popperOffsets.y+=l),t.modifiersData[a]=s}const xn={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:Os};function Cs(e){var t=e.state,n=e.name;t.modifiersData[n]=Wn({reference:t.rects.reference,element:t.rects.popper,strategy:"absolute",placement:t.placement})}const Qe={name:"popperOffsets",enabled:!0,phase:"read",fn:Cs,data:{}};function ks(e){return e==="x"?"y":"x"}function As(e){var r,c,h,p,v,w,C,k,A,M,T,z,D,L,R,P,H,B,V,$,W,U,K,q,Y,G,X,Z,t=e.state,l=e.options,be=e.name,fe,ue,ee,te,ie,ce,le,me,pe=l.mainAxis,ge=pe===void 0||pe,ne=l.altAxis,we=ne!==void 0&&ne,_e=l.boundary,ye=l.rootBoundary,ve=l.altBoundary,je=l.padding,de=l.tether,d=de===void 0||de,ae=l.tetherOffset,S=ae===void 0?0:ae,x=I(t,{boundary:_e,rootBoundary:ye,padding:je,altBoundary:ve}),J=m(t.placement),E=Q(t.placement),he=!E,a=Ue(J),j=ks(a),b=t.modifiersData.popperOffsets,u=t.rects.reference,g=t.rects.popper,_=typeof S=="function"?S(Object.assign({},t.rects,{placement:t.placement})):S,f=typeof _=="number"?{mainAxis:_,altAxis:_}:Object.assign({mainAxis:0,altAxis:0},_),y=t.modifiersData.offset?t.modifiersData.offset[t.placement]:null,N={x:0,y:0};if(!b)return;ge&&(R=a==="y"?s:n,P=a==="y"?o:i,r=a==="y"?"height":"width",h=b[a],V=h+x[R],$=h-x[P],W=d?-g[r]/2:0,Z=E===F?u[r]:g[r],X=E===F?-g[r]:-u[r],q=t.elements.arrow,ue=d&&q?dt(q):{width:0,height:0},k=t.modifiersData["arrow#persistent"]?t.modifiersData["arrow#persistent"].padding:zn(),K=k[R],U=k[P],v=oe(0,u[r],ue[r]),ee=he?u[r]/2-W-v-K-f.mainAxis:Z-v-K-f.mainAxis,te=he?-u[r]/2+W+v+U+f.mainAxis:X+v+U+f.mainAxis,C=t.elements.arrow&&re(t.elements.arrow),ie=C?a==="y"?C.clientTop||0:C.clientLeft||0:0,B=(fe=y?.[a])!=null?fe:0,ce=h+ee-B-ie,le=h+te-B,H=oe(d?se(V,ce):V,h,d?O($,le):$),b[a]=H,N[a]=H-h),we&&(Y=a==="x"?s:n,me=a==="x"?o:i,c=b[j],p=j==="y"?"height":"width",L=c+x[Y],D=c-x[me],w=[s,n].indexOf(J)!==-1,z=(G=y?.[j])!=null?G:0,T=w?L:c-u[p]-g[p]-z+f.altAxis,M=w?c+u[p]+g[p]-z-f.altAxis:D,A=d&&w?js(T,c,M):oe(d?T:L,c,d?M:D),b[j]=A,N[j]=A-c),t.modifiersData[be]=N}const un={name:"preventOverflow",enabled:!0,phase:"main",fn:As,requiresIfExists:["offset"]};function Ms(e){return{scrollLeft:e.scrollLeft,scrollTop:e.scrollTop}}function Fs(e){return e===r(e)||!l(e)?Ke(e):Ms(e)}function Ts(e){var t=e.getBoundingClientRect(),n=z(t.width)/e.offsetWidth||1,s=z(t.height)/e.offsetHeight||1;return n!==1||s!==1}function zs(e,t,n){n===void 0&&(n=!1);var r=l(t),c=l(t)&&Ts(t),i=_(t),o=X(e,c,n),a={scrollLeft:0,scrollTop:0},s={x:0,y:0};return(r||!r&&!n)&&((f(t)!=="body"||at(i))&&(a=Fs(t)),l(t)?(s=X(t,!0),s.x+=t.clientLeft,s.y+=t.clientTop):i&&(s.x=qe(i))),{x:o.left+a.scrollLeft-s.x,y:o.top+a.scrollTop-s.y,width:o.width,height:o.height}}function Ds(e){var n=new Map,t=new Set,s=[];e.forEach(function(e){n.set(e.name,e)});function o(e){t.add(e.name);var i=[].concat(e.requires||[],e.requiresIfExists||[]);i.forEach(function(e){if(!t.has(e)){var s=n.get(e);s&&o(s)}}),s.push(e)}return e.forEach(function(e){t.has(e.name)||o(e)}),s}function Ns(e){var t=Ds(e);return on.reduce(function(e,n){return e.concat(t.filter(function(e){return e.phase===n}))},[])}function Ls(e){var t;return function(){return t||(t=new Promise(function(n){Promise.resolve().then(function(){t=void 0,n(e())})})),t}}function Rs(e){var t=e.reduce(function(e,t){var n=e[t.name];return e[t.name]=n?Object.assign({},n,t,{options:Object.assign({},n.options,t.options),data:Object.assign({},n.data,t.data)}):t,e},{});return Object.keys(t).map(function(e){return t[e]})}Je={placement:"bottom",modifiers:[],strategy:"absolute"};function Tt(){for(var t=arguments.length,n=new Array(t),e=0;eNumber.parseInt(e,10)):typeof e=="function"?t=>e(t,this._element):e}_getPopperConfig(){const e={placement:this._getPlacement(),modifiers:[{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"offset",options:{offset:this._getOffset()}}]};return(this._inNavbar||this._config.display==="static")&&(b.setDataAttribute(this._menu,"popper","static"),e.modifiers=[{name:"applyStyles",enabled:!1}]),{...e,...typeof this._config.popperConfig=="function"?this._config.popperConfig(e):this._config.popperConfig}}_selectMenuItem({key:e,target:n}){const s=t.find(_o,this._menu).filter(e=>H(e));if(!s.length)return;Le(s,n,e===gt,!s.includes(n)).focus()}static jQueryInterface(e){return this.each(function(){const t=h.getOrCreateInstance(this,e);if(typeof e!="string")return;if(typeof t[e]=="undefined")throw new TypeError(`No method named "${e}"`);t[e]()})}static clearMenus(e){if(e.button===to||e.type==="keyup"&&e.key!==vt)return;const n=t.find(vo);for(const a of n){const t=h.getInstance(a);if(!t||t._config.autoClose===!1)continue;const s=e.composedPath(),o=s.includes(t._menu);if(s.includes(t._element)||t._config.autoClose==="inside"&&!o||t._config.autoClose==="outside"&&o)continue;if(t._menu.contains(e.target)&&(e.type==="keyup"&&e.key===vt||/input|select|option|textarea|form/i.test(e.target.tagName)))continue;const i={relatedTarget:t._element};e.type==="click"&&(i.clickEvent=e),t._completeHide(i)}}static dataApiKeydownHandler(e){const a=/input|textarea/i.test(e.target.tagName),s=e.key===Qs,o=[Js,gt].includes(e.key);if(!o&&!s)return;if(a&&!s)return;e.preventDefault();const i=this.matches(S)?this:t.prev(this,S)[0]||t.next(this,S)[0]||t.findOne(S,e.delegateTarget.parentNode),n=h.getOrCreateInstance(i);if(o){e.stopPropagation(),n.show(),n._selectMenuItem(e);return}n._isShown()&&(e.stopPropagation(),n.hide(),i.focus())}}e.on(document,jt,S,h.dataApiKeydownHandler),e.on(document,jt,be,h.dataApiKeydownHandler),e.on(document,bt,h.clearMenus),e.on(document,co,h.clearMenus),e.on(document,bt,S,function(e){e.preventDefault(),h.getOrCreateInstance(this).toggle()}),c(h);const wt=".fixed-top, .fixed-bottom, .is-fixed, .sticky-top",Ot=".sticky-top",me="padding-right",xt="margin-right";class tt{constructor(){this._element=document.body}getWidth(){const e=document.documentElement.clientWidth;return Math.abs(window.innerWidth-e)}hide(){const e=this.getWidth();this._disableOverFlow(),this._setElementAttributes(this._element,me,t=>t+e),this._setElementAttributes(wt,me,t=>t+e),this._setElementAttributes(Ot,xt,t=>t-e)}reset(){this._resetElementAttributes(this._element,"overflow"),this._resetElementAttributes(this._element,me),this._resetElementAttributes(wt,me),this._resetElementAttributes(Ot,xt)}isOverflowing(){return this.getWidth()>0}_disableOverFlow(){this._saveInitialAttribute(this._element,"overflow"),this._element.style.overflow="hidden"}_setElementAttributes(e,t,n){const s=this.getWidth(),o=e=>{if(e!==this._element&&window.innerWidth>e.clientWidth+s)return;this._saveInitialAttribute(e,t);const o=window.getComputedStyle(e).getPropertyValue(t);e.style.setProperty(t,`${n(Number.parseFloat(o))}px`)};this._applyManipulationCallback(e,o)}_saveInitialAttribute(e,t){const n=e.style.getPropertyValue(t);n&&b.setDataAttribute(e,t,n)}_resetElementAttributes(e,t){const n=e=>{const n=b.getDataAttribute(e,t);if(n===null){e.style.removeProperty(t);return}b.removeDataAttribute(e,t),e.style.setProperty(t,n)};this._applyManipulationCallback(e,n)}_applyManipulationCallback(e,n){if(g(e)){n(e);return}for(const s of t.find(e,this._element))n(s)}}const Ft="backdrop",Ho="fade",pt="show",Dt=`mousedown.bs.${Ft}`,Vo={className:"modal-backdrop",clickCallback:null,isAnimated:!1,isVisible:!0,rootElement:"body"},$o={className:"string",clickCallback:"(function|null)",isAnimated:"boolean",isVisible:"boolean",rootElement:"(element|string)"};class Nt extends te{constructor(e){super(),this._config=this._getConfig(e),this._isAppended=!1,this._element=null}static get Default(){return Vo}static get DefaultType(){return $o}static get NAME(){return Ft}show(e){if(!this._config.isVisible){y(e);return}this._append();const t=this._getElement();this._config.isAnimated&&ne(t),t.classList.add(pt),this._emulateAnimation(()=>{y(e)})}hide(e){if(!this._config.isVisible){y(e);return}this._getElement().classList.remove(pt),this._emulateAnimation(()=>{this.dispose(),y(e)})}dispose(){if(!this._isAppended)return;e.off(this._element,Dt),this._element.remove(),this._isAppended=!1}_getElement(){if(!this._element){const e=document.createElement("div");e.className=this._config.className,this._config.isAnimated&&e.classList.add(Ho),this._element=e}return this._element}_configAfterMerge(e){return e.rootElement=E(e.rootElement),e}_append(){if(this._isAppended)return;const t=this._getElement();this._config.rootElement.append(t),e.on(t,Dt,()=>{y(this._config.clickCallback)}),this._isAppended=!0}_emulateAnimation(e){Yn(e,this._getElement(),this._config.isAnimated)}}const Uo="focustrap",Ko="bs.focustrap",_e=`.${Ko}`,Yo=`focusin${_e}`,Go=`keydown.tab${_e}`,Xo="Tab",Qo="forward",Rt="backward",Jo={autofocus:!0,trapElement:null},ei={autofocus:"boolean",trapElement:"element"};class Pt extends te{constructor(e){super(),this._config=this._getConfig(e),this._isActive=!1,this._lastTabNavDirection=null}static get Default(){return Jo}static get DefaultType(){return ei}static get NAME(){return Uo}activate(){if(this._isActive)return;this._config.autofocus&&this._config.trapElement.focus(),e.off(document,_e),e.on(document,Yo,e=>this._handleFocusin(e)),e.on(document,Go,e=>this._handleKeydown(e)),this._isActive=!0}deactivate(){if(!this._isActive)return;this._isActive=!1,e.off(document,_e)}_handleFocusin(e){const{trapElement:n}=this._config;if(e.target===document||e.target===n||n.contains(e.target))return;const s=t.focusableChildren(n);s.length===0?n.focus():this._lastTabNavDirection===Rt?s[s.length-1].focus():s[0].focus()}_handleKeydown(e){if(e.key!==Xo)return;this._lastTabNavDirection=e.shiftKey?Rt:Qo}}const ni="modal",si="bs.modal",d=`.${si}`,ii=".data-api",ai="Escape",ri=`hide${d}`,ci=`hidePrevented${d}`,Ht=`hidden${d}`,It=`show${d}`,ui=`shown${d}`,hi=`resize${d}`,mi=`click.dismiss${d}`,fi=`mousedown.dismiss${d}`,pi=`keydown.dismiss${d}`,gi=`click${d}${ii}`,Bt="modal-open",bi="fade",Vt="show",Ne="modal-static",_i=".modal.show",wi=".modal-dialog",Oi=".modal-body",xi='[data-bs-toggle="modal"]',Ci={backdrop:!0,focus:!0,keyboard:!0},Ei={backdrop:"(boolean|string)",focus:"boolean",keyboard:"boolean"};class B extends u{constructor(e,n){super(e,n),this._dialog=t.findOne(wi,this._element),this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._isShown=!1,this._isTransitioning=!1,this._scrollBar=new tt,this._addEventListeners()}static get Default(){return Ci}static get DefaultType(){return Ei}static get NAME(){return ni}toggle(e){return this._isShown?this.hide():this.show(e)}show(t){if(this._isShown||this._isTransitioning)return;const n=e.trigger(this._element,It,{relatedTarget:t});if(n.defaultPrevented)return;this._isShown=!0,this._isTransitioning=!0,this._scrollBar.hide(),document.body.classList.add(Bt),this._adjustDialog(),this._backdrop.show(()=>this._showElement(t))}hide(){if(!this._isShown||this._isTransitioning)return;const t=e.trigger(this._element,ri);if(t.defaultPrevented)return;this._isShown=!1,this._isTransitioning=!0,this._focustrap.deactivate(),this._element.classList.remove(Vt),this._queueCallback(()=>this._hideModal(),this._element,this._isAnimated())}dispose(){for(const t of[window,this._dialog])e.off(t,d);this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}handleUpdate(){this._adjustDialog()}_initializeBackDrop(){return new Nt({isVisible:Boolean(this._config.backdrop),isAnimated:this._isAnimated()})}_initializeFocusTrap(){return new Pt({trapElement:this._element})}_showElement(n){document.body.contains(this._element)||document.body.append(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.scrollTop=0;const s=t.findOne(Oi,this._dialog);s&&(s.scrollTop=0),ne(this._element),this._element.classList.add(Vt);const o=()=>{this._config.focus&&this._focustrap.activate(),this._isTransitioning=!1,e.trigger(this._element,ui,{relatedTarget:n})};this._queueCallback(o,this._dialog,this._isAnimated())}_addEventListeners(){e.on(this._element,pi,e=>{if(e.key!==ai)return;if(this._config.keyboard){e.preventDefault(),this.hide();return}this._triggerBackdropTransition()}),e.on(window,hi,()=>{this._isShown&&!this._isTransitioning&&this._adjustDialog()}),e.on(this._element,fi,t=>{e.one(this._element,mi,e=>{if(this._element!==t.target||this._element!==e.target)return;if(this._config.backdrop==="static"){this._triggerBackdropTransition();return}this._config.backdrop&&this.hide()})})}_hideModal(){this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._backdrop.hide(()=>{document.body.classList.remove(Bt),this._resetAdjustments(),this._scrollBar.reset(),e.trigger(this._element,Ht)})}_isAnimated(){return this._element.classList.contains(bi)}_triggerBackdropTransition(){const n=e.trigger(this._element,ci);if(n.defaultPrevented)return;const s=this._element.scrollHeight>document.documentElement.clientHeight,t=this._element.style.overflowY;if(t==="hidden"||this._element.classList.contains(Ne))return;s||(this._element.style.overflowY="hidden"),this._element.classList.add(Ne),this._queueCallback(()=>{this._element.classList.remove(Ne),this._queueCallback(()=>{this._element.style.overflowY=t},this._dialog)},this._dialog),this._element.focus()}_adjustDialog(){const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._scrollBar.getWidth(),n=e>0;if(n&&!t){const t=a()?"paddingLeft":"paddingRight";this._element.style[t]=`${e}px`}if(!n&&t){const t=a()?"paddingRight":"paddingLeft";this._element.style[t]=`${e}px`}}_resetAdjustments(){this._element.style.paddingLeft="",this._element.style.paddingRight=""}static jQueryInterface(e,t){return this.each(function(){const n=B.getOrCreateInstance(this,e);if(typeof e!="string")return;if(typeof n[e]=="undefined")throw new TypeError(`No method named "${e}"`);n[e](t)})}}e.on(document,gi,xi,function(n){const s=v(this);["A","AREA"].includes(this.tagName)&&n.preventDefault(),e.one(s,It,t=>{if(t.defaultPrevented)return;e.one(s,Ht,()=>{H(this)&&this.focus()})});const o=t.findOne(_i);o&&B.getInstance(o).hide();const i=B.getOrCreateInstance(s);i.toggle(this)}),Se(B),c(B);const Ai="offcanvas",Si="bs.offcanvas",j=`.${Si}`,Ut=".data-api",Ti=`load${j}${Ut}`,zi="Escape",qt="show",Yt="showing",an="hiding",Ri="offcanvas-backdrop",rn=".offcanvas.show",Hi=`show${j}`,Ii=`shown${j}`,Bi=`hide${j}`,cn=`hidePrevented${j}`,ln=`hidden${j}`,Wi=`resize${j}`,Ui=`click${j}${Ut}`,Ki=`keydown.dismiss${j}`,qi='[data-bs-toggle="offcanvas"]',Yi={backdrop:!0,keyboard:!0,scroll:!1},Gi={backdrop:"(boolean|string)",keyboard:"boolean",scroll:"boolean"};class A extends u{constructor(e,t){super(e,t),this._isShown=!1,this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._addEventListeners()}static get Default(){return Yi}static get DefaultType(){return Gi}static get NAME(){return Ai}toggle(e){return this._isShown?this.hide():this.show(e)}show(t){if(this._isShown)return;const n=e.trigger(this._element,Hi,{relatedTarget:t});if(n.defaultPrevented)return;this._isShown=!0,this._backdrop.show(),this._config.scroll||(new tt).hide(),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.classList.add(Yt);const s=()=>{(!this._config.scroll||this._config.backdrop)&&this._focustrap.activate(),this._element.classList.add(qt),this._element.classList.remove(Yt),e.trigger(this._element,Ii,{relatedTarget:t})};this._queueCallback(s,this._element,!0)}hide(){if(!this._isShown)return;const t=e.trigger(this._element,Bi);if(t.defaultPrevented)return;this._focustrap.deactivate(),this._element.blur(),this._isShown=!1,this._element.classList.add(an),this._backdrop.hide();const n=()=>{this._element.classList.remove(qt,an),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._config.scroll||(new tt).reset(),e.trigger(this._element,ln)};this._queueCallback(n,this._element,!0)}dispose(){this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}_initializeBackDrop(){const n=()=>{if(this._config.backdrop==="static"){e.trigger(this._element,cn);return}this.hide()},t=Boolean(this._config.backdrop);return new Nt({className:Ri,isVisible:t,isAnimated:!0,rootElement:this._element.parentNode,clickCallback:t?n:null})}_initializeFocusTrap(){return new Pt({trapElement:this._element})}_addEventListeners(){e.on(this._element,Ki,t=>{if(t.key!==zi)return;if(!this._config.keyboard){e.trigger(this._element,cn);return}this.hide()})}static jQueryInterface(e){return this.each(function(){const t=A.getOrCreateInstance(this,e);if(typeof e!="string")return;if(t[e]===void 0||e.startsWith("_")||e==="constructor")throw new TypeError(`No method named "${e}"`);t[e](this)})}}e.on(document,Ui,qi,function(n){const s=v(this);if(["A","AREA"].includes(this.tagName)&&n.preventDefault(),w(this))return;e.one(s,ln,()=>{H(this)&&this.focus()});const o=t.findOne(rn);o&&o!==s&&A.getInstance(o).hide();const i=A.getOrCreateInstance(s);i.toggle(this)}),e.on(window,Ti,()=>{for(const e of t.find(rn))A.getOrCreateInstance(e).show()}),e.on(window,Wi,()=>{for(const e of t.find("[aria-modal][class*=show][class*=offcanvas-]"))getComputedStyle(e).position!=="fixed"&&A.getOrCreateInstance(e).hide()}),Se(A),c(A);const Qi=new Set(["background","cite","href","itemtype","longdesc","poster","src","xlink:href"]),Zi=/^aria-[\w-]*$/i,Ji=/^(?:(?:https?|mailto|ftp|tel|file|sms):|[^#&/:?]*(?:[#/?]|$))/i,ea=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i,ta=(e,t)=>{const n=e.nodeName.toLowerCase();return t.includes(n)?!Qi.has(n)||Boolean(Ji.test(e.nodeValue)||ea.test(e.nodeValue)):t.filter(e=>e instanceof RegExp).some(e=>e.test(n))},dn={"*":["class","dir","id","lang","role",Zi],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]};function sa(e,t,n){if(!e.length)return e;if(n&&typeof n=="function")return n(e);const o=new window.DOMParser,s=o.parseFromString(e,"text/html"),i=[].concat(...s.body.querySelectorAll("*"));for(const e of i){const n=e.nodeName.toLowerCase();if(!Object.keys(t).includes(n)){e.remove();continue}const s=[].concat(...e.attributes),o=[].concat(t["*"]||[],t[n]||[]);for(const t of s)ta(t,o)||e.removeAttribute(t.nodeName)}return s.body.innerHTML}const oa="TemplateFactory",ia={allowList:dn,content:{},extraClass:"",html:!1,sanitize:!0,sanitizeFn:null,template:"
"},aa={allowList:"object",content:"object",extraClass:"(string|function)",html:"boolean",sanitize:"boolean",sanitizeFn:"(null|function)",template:"string"},ra={entry:"(string|element|function|null)",selector:"(string|element)"};class ca extends te{constructor(e){super(),this._config=this._getConfig(e)}static get Default(){return ia}static get DefaultType(){return aa}static get NAME(){return oa}getContent(){return Object.values(this._config.content).map(e=>this._resolvePossibleFunction(e)).filter(Boolean)}hasContent(){return this.getContent().length>0}changeContent(e){return this._checkContent(e),this._config.content={...this._config.content,...e},this}toHtml(){const e=document.createElement("div");e.innerHTML=this._maybeSanitize(this._config.template);for(const[t,n]of Object.entries(this._config.content))this._setContent(e,n,t);const t=e.children[0],n=this._resolvePossibleFunction(this._config.extraClass);return n&&t.classList.add(...n.split(" ")),t}_typeCheckConfig(e){super._typeCheckConfig(e),this._checkContent(e.content)}_checkContent(e){for(const[t,n]of Object.entries(e))super._typeCheckConfig({selector:t,entry:n},ra)}_setContent(e,n,s){const o=t.findOne(s,e);if(!o)return;if(n=this._resolvePossibleFunction(n),!n){o.remove();return}if(g(n)){this._putElementInTemplate(E(n),o);return}if(this._config.html){o.innerHTML=this._maybeSanitize(n);return}o.textContent=n}_maybeSanitize(e){return this._config.sanitize?sa(e,this._config.allowList,this._config.sanitizeFn):e}_resolvePossibleFunction(e){return typeof e=="function"?e(this):e}_putElementInTemplate(e,t){if(this._config.html){t.innerHTML="",t.append(e);return}t.textContent=e.textContent}}const la="tooltip",da=new Set(["sanitize","allowList","sanitizeFn"]),Xe="fade",ha="modal",ue="show",fa=".tooltip-inner",hn=`.${ha}`,mn="hide.bs.modal",J="hover",ot="focus",ja="click",ya="manual",_a="hide",wa="hidden",Oa="show",xa="shown",Ca="inserted",Ea="click",ka="focusin",Aa="focusout",Sa="mouseenter",Ma="mouseleave",Fa={AUTO:"auto",TOP:"top",RIGHT:a()?"left":"right",BOTTOM:"bottom",LEFT:a()?"right":"left"},Ta={allowList:dn,animation:!0,boundary:"clippingParents",container:!1,customClass:"",delay:0,fallbackPlacements:["top","right","bottom","left"],html:!1,offset:[0,0],placement:"top",popperConfig:null,sanitize:!0,sanitizeFn:null,selector:!1,template:'',title:"",trigger:"hover focus"},za={allowList:"object",animation:"boolean",boundary:"(string|element)",container:"(string|element|boolean)",customClass:"(string|function)",delay:"(number|object)",fallbackPlacements:"array",html:"boolean",offset:"(array|string|function)",placement:"(string|function)",popperConfig:"(null|object|function)",sanitize:"boolean",sanitizeFn:"(null|function)",selector:"(string|boolean)",template:"string",title:"(string|element|function)",trigger:"string"};class U extends u{constructor(e,t){if(typeof _t=="undefined")throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");super(e,t),this._isEnabled=!0,this._timeout=0,this._isHovered=null,this._activeTrigger={},this._popper=null,this._templateFactory=null,this._newContent=null,this.tip=null,this._setListeners(),this._config.selector||this._fixTitle()}static get Default(){return Ta}static get DefaultType(){return za}static get NAME(){return la}enable(){this._isEnabled=!0}disable(){this._isEnabled=!1}toggleEnabled(){this._isEnabled=!this._isEnabled}toggle(){if(!this._isEnabled)return;if(this._activeTrigger.click=!this._activeTrigger.click,this._isShown()){this._leave();return}this._enter()}dispose(){clearTimeout(this._timeout),e.off(this._element.closest(hn),mn,this._hideModalHandler),this._element.getAttribute("data-bs-original-title")&&this._element.setAttribute("title",this._element.getAttribute("data-bs-original-title")),this._disposePopper(),super.dispose()}show(){if(this._element.style.display==="none")throw new Error("Please use show on visible elements");if(!this._isWithContent()||!this._isEnabled)return;const n=e.trigger(this._element,this.constructor.eventName(Oa)),s=Jn(this._element),o=(s||this._element.ownerDocument.documentElement).contains(this._element);if(n.defaultPrevented||!o)return;this._disposePopper();const t=this._getTipElement();this._element.setAttribute("aria-describedby",t.getAttribute("id"));const{container:i}=this._config;if(this._element.ownerDocument.documentElement.contains(this.tip)||(i.append(t),e.trigger(this._element,this.constructor.eventName(Ca))),this._popper=this._createPopper(t),t.classList.add(ue),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))e.on(t,"mouseover",Oe);const a=()=>{e.trigger(this._element,this.constructor.eventName(xa)),this._isHovered===!1&&this._leave(),this._isHovered=!1};this._queueCallback(a,this.tip,this._isAnimated())}hide(){if(!this._isShown())return;const t=e.trigger(this._element,this.constructor.eventName(_a));if(t.defaultPrevented)return;const n=this._getTipElement();if(n.classList.remove(ue),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))e.off(t,"mouseover",Oe);this._activeTrigger[ja]=!1,this._activeTrigger[ot]=!1,this._activeTrigger[J]=!1,this._isHovered=null;const s=()=>{if(this._isWithActiveTrigger())return;this._isHovered||this._disposePopper(),this._element.removeAttribute("aria-describedby"),e.trigger(this._element,this.constructor.eventName(wa))};this._queueCallback(s,this.tip,this._isAnimated())}update(){this._popper&&this._popper.update()}_isWithContent(){return Boolean(this._getTitle())}_getTipElement(){return this.tip||(this.tip=this._createTipElement(this._newContent||this._getContentForTemplate())),this.tip}_createTipElement(e){const t=this._getTemplateFactory(e).toHtml();if(!t)return null;t.classList.remove(Xe,ue),t.classList.add(`bs-${this.constructor.NAME}-auto`);const n=Gr(this.constructor.NAME).toString();return t.setAttribute("id",n),this._isAnimated()&&t.classList.add(Xe),t}setContent(e){this._newContent=e,this._isShown()&&(this._disposePopper(),this.show())}_getTemplateFactory(e){return this._templateFactory?this._templateFactory.changeContent(e):this._templateFactory=new ca({...this._config,content:e,extraClass:this._resolvePossibleFunction(this._config.customClass)}),this._templateFactory}_getContentForTemplate(){return{[fa]:this._getTitle()}}_getTitle(){return this._resolvePossibleFunction(this._config.title)||this._element.getAttribute("data-bs-original-title")}_initializeOnDelegatedTarget(e){return this.constructor.getOrCreateInstance(e.delegateTarget,this._getDelegateConfig())}_isAnimated(){return this._config.animation||this.tip&&this.tip.classList.contains(Xe)}_isShown(){return this.tip&&this.tip.classList.contains(ue)}_createPopper(e){const t=typeof this._config.placement=="function"?this._config.placement.call(this,e,this._element):this._config.placement,n=Fa[t.toUpperCase()];return he(this._element,e,this._getPopperConfig(n))}_getOffset(){const{offset:e}=this._config;return typeof e=="string"?e.split(",").map(e=>Number.parseInt(e,10)):typeof e=="function"?t=>e(t,this._element):e}_resolvePossibleFunction(e){return typeof e=="function"?e.call(this._element):e}_getPopperConfig(e){const t={placement:e,modifiers:[{name:"flip",options:{fallbackPlacements:this._config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"arrow",options:{element:`.${this.constructor.NAME}-arrow`}},{name:"preSetPlacement",enabled:!0,phase:"beforeMain",fn:e=>{this._getTipElement().setAttribute("data-popper-placement",e.state.placement)}}]};return{...t,...typeof this._config.popperConfig=="function"?this._config.popperConfig(t):this._config.popperConfig}}_setListeners(){const t=this._config.trigger.split(" ");for(const n of t)if(n==="click")e.on(this._element,this.constructor.eventName(Ea),this._config.selector,e=>{const t=this._initializeOnDelegatedTarget(e);t.toggle()});else if(n!==ya){const t=n===J?this.constructor.eventName(Sa):this.constructor.eventName(ka),s=n===J?this.constructor.eventName(Ma):this.constructor.eventName(Aa);e.on(this._element,t,this._config.selector,e=>{const t=this._initializeOnDelegatedTarget(e);t._activeTrigger[e.type==="focusin"?ot:J]=!0,t._enter()}),e.on(this._element,s,this._config.selector,e=>{const t=this._initializeOnDelegatedTarget(e);t._activeTrigger[e.type==="focusout"?ot:J]=t._element.contains(e.relatedTarget),t._leave()})}this._hideModalHandler=()=>{this._element&&this.hide()},e.on(this._element.closest(hn),mn,this._hideModalHandler)}_fixTitle(){const e=this._element.getAttribute("title");if(!e)return;!this._element.getAttribute("aria-label")&&!this._element.textContent.trim()&&this._element.setAttribute("aria-label",e),this._element.setAttribute("data-bs-original-title",e),this._element.removeAttribute("title")}_enter(){if(this._isShown()||this._isHovered){this._isHovered=!0;return}this._isHovered=!0,this._setTimeout(()=>{this._isHovered&&this.show()},this._config.delay.show)}_leave(){if(this._isWithActiveTrigger())return;this._isHovered=!1,this._setTimeout(()=>{this._isHovered||this.hide()},this._config.delay.hide)}_setTimeout(e,t){clearTimeout(this._timeout),this._timeout=setTimeout(e,t)}_isWithActiveTrigger(){return Object.values(this._activeTrigger).includes(!0)}_getConfig(e){const t=b.getDataAttributes(this._element);for(const e of Object.keys(t))da.has(e)&&delete t[e];return e={...t,...typeof e=="object"&&e?e:{}},e=this._mergeConfigObj(e),e=this._configAfterMerge(e),this._typeCheckConfig(e),e}_configAfterMerge(e){return e.container=e.container===!1?document.body:E(e.container),typeof e.delay=="number"&&(e.delay={show:e.delay,hide:e.delay}),typeof e.title=="number"&&(e.title=e.title.toString()),typeof e.content=="number"&&(e.content=e.content.toString()),e}_getDelegateConfig(){const e={};for(const t in this._config)this.constructor.Default[t]!==this._config[t]&&(e[t]=this._config[t]);return e.selector=!1,e.trigger="manual",e}_disposePopper(){this._popper&&(this._popper.destroy(),this._popper=null),this.tip&&(this.tip.remove(),this.tip=null)}static jQueryInterface(e){return this.each(function(){const t=U.getOrCreateInstance(this,e);if(typeof e!="string")return;if(typeof t[e]=="undefined")throw new TypeError(`No method named "${e}"`);t[e]()})}}c(U);const Na="popover",La=".popover-header",Ra=".popover-body",Pa={...U.Default,content:"",offset:[0,8],placement:"right",template:'',trigger:"click"},Ha={...U.DefaultType,content:"(null|string|element|function)"};class ct extends U{static get Default(){return Pa}static get DefaultType(){return Ha}static get NAME(){return Na}_isWithContent(){return this._getTitle()||this._getContent()}_getContentForTemplate(){return{[La]:this._getTitle(),[Ra]:this._getContent()}}_getContent(){return this._resolvePossibleFunction(this._config.content)}static jQueryInterface(e){return this.each(function(){const t=ct.getOrCreateInstance(this,e);if(typeof e!="string")return;if(typeof t[e]=="undefined")throw new TypeError(`No method named "${e}"`);t[e]()})}}c(ct);const Ba="scrollspy",Va="bs.scrollspy",lt=`.${Va}`,Wa=".data-api",Ua=`activate${lt}`,pn=`click${lt}`,qa=`load${lt}${Wa}`,Ya="dropdown-item",q="active",Xa='[data-bs-spy="scroll"]',mt="[href]",Za=".nav, .list-group",gn=".nav-link",er=".nav-item",tr=".list-group-item",nr=`${gn}, ${er} > ${gn}, ${tr}`,sr=".dropdown",or=".dropdown-toggle",ir={offset:null,rootMargin:"0px 0px -25%",smoothScroll:!1,target:null,threshold:[.1,.5,1]},ar={offset:"(number|null)",rootMargin:"string",smoothScroll:"boolean",target:"element",threshold:"array"};class Ee extends u{constructor(e,t){super(e,t),this._targetLinks=new Map,this._observableSections=new Map,this._rootElement=getComputedStyle(this._element).overflowY==="visible"?null:this._element,this._activeTarget=null,this._observer=null,this._previousScrollData={visibleEntryTop:0,parentScrollTop:0},this.refresh()}static get Default(){return ir}static get DefaultType(){return ar}static get NAME(){return Ba}refresh(){this._initializeTargetsAndObservables(),this._maybeEnableSmoothScroll(),this._observer?this._observer.disconnect():this._observer=this._getNewObserver();for(const e of this._observableSections.values())this._observer.observe(e)}dispose(){this._observer.disconnect(),super.dispose()}_configAfterMerge(e){return e.target=E(e.target)||document.body,e.rootMargin=e.offset?`${e.offset}px 0px -30%`:e.rootMargin,typeof e.threshold=="string"&&(e.threshold=e.threshold.split(",").map(e=>Number.parseFloat(e))),e}_maybeEnableSmoothScroll(){if(!this._config.smoothScroll)return;e.off(this._config.target,pn),e.on(this._config.target,pn,mt,e=>{const t=this._observableSections.get(e.target.hash);if(t){e.preventDefault();const n=this._rootElement||window,s=t.offsetTop-this._element.offsetTop;if(n.scrollTo){n.scrollTo({top:s,behavior:"smooth"});return}n.scrollTop=s}})}_getNewObserver(){const e={root:this._rootElement,threshold:this._config.threshold,rootMargin:this._config.rootMargin};return new IntersectionObserver(e=>this._observerCallback(e),e)}_observerCallback(e){const n=e=>this._targetLinks.get(`#${e.target.id}`),s=e=>{this._previousScrollData.visibleEntryTop=e.target.offsetTop,this._process(n(e))},t=(this._rootElement||document.documentElement).scrollTop,o=t>=this._previousScrollData.parentScrollTop;this._previousScrollData.parentScrollTop=t;for(const i of e){if(!i.isIntersecting){this._activeTarget=null,this._clearActiveClass(n(i));continue}const a=i.target.offsetTop>=this._previousScrollData.visibleEntryTop;if(o&&a){if(s(i),!t)return;continue}!o&&!a&&s(i)}}_initializeTargetsAndObservables(){this._targetLinks=new Map,this._observableSections=new Map;const e=t.find(mt,this._config.target);for(const n of e){if(!n.hash||w(n))continue;const s=t.findOne(n.hash,this._element);H(s)&&(this._targetLinks.set(n.hash,n),this._observableSections.set(n.hash,s))}}_process(t){if(this._activeTarget===t)return;this._clearActiveClass(this._config.target),this._activeTarget=t,t.classList.add(q),this._activateParents(t),e.trigger(this._element,Ua,{relatedTarget:t})}_activateParents(e){if(e.classList.contains(Ya)){t.findOne(or,e.closest(sr)).classList.add(q);return}for(const n of t.parents(e,Za))for(const e of t.prev(n,nr))e.classList.add(q)}_clearActiveClass(e){e.classList.remove(q);const n=t.find(`${mt}.${q}`,e);for(const e of n)e.classList.remove(q)}static jQueryInterface(e){return this.each(function(){const t=Ee.getOrCreateInstance(this,e);if(typeof e!="string")return;if(t[e]===void 0||e.startsWith("_")||e==="constructor")throw new TypeError(`No method named "${e}"`);t[e]()})}}e.on(window,qa,()=>{for(const e of t.find(Xa))Ee.getOrCreateInstance(e)}),c(Ee);const cr="tab",lr="bs.tab",M=`.${lr}`,ur=`hide${M}`,hr=`hidden${M}`,mr=`show${M}`,fr=`shown${M}`,pr=`click${M}`,gr=`keydown${M}`,vr=`load${M}`,br="ArrowLeft",bn="ArrowRight",yr="ArrowUp",yn="ArrowDown",N="active",Mn="fade",We="show",Cr="dropdown",Er=".dropdown-toggle",kr=".dropdown-menu",$e=":not(.dropdown-toggle)",Sr='.list-group, .nav, [role="tablist"]',Mr=".nav-item, .list-group-item",Fr=`.nav-link${$e}, .list-group-item${$e}, [role="tab"]${$e}`,Kn='[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',De=`${Fr}, ${Kn}`,Dr=`.${N}[data-bs-toggle="tab"], .${N}[data-bs-toggle="pill"], .${N}[data-bs-toggle="list"]`;class R extends u{constructor(t){if(super(t),this._parent=this._element.closest(Sr),!this._parent)return;this._setInitialAttributes(this._parent,this._getChildren()),e.on(this._element,gr,e=>this._keydown(e))}static get NAME(){return cr}show(){const t=this._element;if(this._elemIsActive(t))return;const n=this._getActiveElem(),s=n?e.trigger(n,ur,{relatedTarget:t}):null,o=e.trigger(t,mr,{relatedTarget:n});if(o.defaultPrevented||s&&s.defaultPrevented)return;this._deactivate(n,t),this._activate(t,n)}_activate(t,n){if(!t)return;t.classList.add(N),this._activate(v(t));const s=()=>{if(t.getAttribute("role")!=="tab"){t.classList.add(We);return}t.removeAttribute("tabindex"),t.setAttribute("aria-selected",!0),this._toggleDropDown(t,!0),e.trigger(t,fr,{relatedTarget:n})};this._queueCallback(s,t,t.classList.contains(Mn))}_deactivate(t,n){if(!t)return;t.classList.remove(N),t.blur(),this._deactivate(v(t));const s=()=>{if(t.getAttribute("role")!=="tab"){t.classList.remove(We);return}t.setAttribute("aria-selected",!1),t.setAttribute("tabindex","-1"),this._toggleDropDown(t,!1),e.trigger(t,hr,{relatedTarget:n})};this._queueCallback(s,t,t.classList.contains(Mn))}_keydown(e){if(![br,bn,yr,yn].includes(e.key))return;e.stopPropagation(),e.preventDefault();const n=[bn,yn].includes(e.key),t=Le(this._getChildren().filter(e=>!w(e)),e.target,n,!0);t&&(t.focus({preventScroll:!0}),R.getOrCreateInstance(t).show())}_getChildren(){return t.find(De,this._parent)}_getActiveElem(){return this._getChildren().find(e=>this._elemIsActive(e))||null}_setInitialAttributes(e,t){this._setAttributeIfNotExists(e,"role","tablist");for(const e of t)this._setInitialAttributesOnChild(e)}_setInitialAttributesOnChild(e){e=this._getInnerElement(e);const t=this._elemIsActive(e),n=this._getOuterElement(e);e.setAttribute("aria-selected",t),n!==e&&this._setAttributeIfNotExists(n,"role","presentation"),t||e.setAttribute("tabindex","-1"),this._setAttributeIfNotExists(e,"role","tab"),this._setInitialAttributesOnTargetPanel(e)}_setInitialAttributesOnTargetPanel(e){const t=v(e);if(!t)return;this._setAttributeIfNotExists(t,"role","tabpanel"),e.id&&this._setAttributeIfNotExists(t,"aria-labelledby",`#${e.id}`)}_toggleDropDown(e,n){const s=this._getOuterElement(e);if(!s.classList.contains(Cr))return;const o=(e,o)=>{const i=t.findOne(e,s);i&&i.classList.toggle(o,n)};o(Er,N),o(kr,We),s.setAttribute("aria-expanded",n)}_setAttributeIfNotExists(e,t,n){e.hasAttribute(t)||e.setAttribute(t,n)}_elemIsActive(e){return e.classList.contains(N)}_getInnerElement(e){return e.matches(De)?e:t.findOne(De,e)}_getOuterElement(e){return e.closest(Mr)||e}static jQueryInterface(e){return this.each(function(){const t=R.getOrCreateInstance(this);if(typeof e!="string")return;if(t[e]===void 0||e.startsWith("_")||e==="constructor")throw new TypeError(`No method named "${e}"`);t[e]()})}}e.on(document,pr,Kn,function(e){if(["A","AREA"].includes(this.tagName)&&e.preventDefault(),w(this))return;R.getOrCreateInstance(this).show()}),e.on(window,vr,()=>{for(const e of t.find(Dr))R.getOrCreateInstance(e)}),c(R);const Lr="toast",Rr="bs.toast",C=`.${Rr}`,Hr=`mouseover${C}`,Ir=`mouseout${C}`,Br=`focusin${C}`,Vr=`focusout${C}`,$r=`hide${C}`,Wr=`hidden${C}`,Ur=`show${C}`,Kr=`shown${C}`,qr="fade",ts="hide",ge="show",we="showing",Qr={animation:"boolean",autohide:"boolean",delay:"number"},Zr={animation:!0,autohide:!0,delay:5e3};class Ce extends u{constructor(e,t){super(e,t),this._timeout=null,this._hasMouseInteraction=!1,this._hasKeyboardInteraction=!1,this._setListeners()}static get Default(){return Zr}static get DefaultType(){return Qr}static get NAME(){return Lr}show(){const t=e.trigger(this._element,Ur);if(t.defaultPrevented)return;this._clearTimeout(),this._config.animation&&this._element.classList.add(qr);const n=()=>{this._element.classList.remove(we),e.trigger(this._element,Kr),this._maybeScheduleHide()};this._element.classList.remove(ts),ne(this._element),this._element.classList.add(ge,we),this._queueCallback(n,this._element,this._config.animation)}hide(){if(!this.isShown())return;const t=e.trigger(this._element,$r);if(t.defaultPrevented)return;const n=()=>{this._element.classList.add(ts),this._element.classList.remove(we,ge),e.trigger(this._element,Wr)};this._element.classList.add(we),this._queueCallback(n,this._element,this._config.animation)}dispose(){this._clearTimeout(),this.isShown()&&this._element.classList.remove(ge),super.dispose()}isShown(){return this._element.classList.contains(ge)}_maybeScheduleHide(){if(!this._config.autohide)return;if(this._hasMouseInteraction||this._hasKeyboardInteraction)return;this._timeout=setTimeout(()=>{this.hide()},this._config.delay)}_onInteraction(e,t){switch(e.type){case"mouseover":case"mouseout":{this._hasMouseInteraction=t;break}case"focusin":case"focusout":{this._hasKeyboardInteraction=t;break}}if(t){this._clearTimeout();return}const n=e.relatedTarget;if(this._element===n||this._element.contains(n))return;this._maybeScheduleHide()}_setListeners(){e.on(this._element,Hr,e=>this._onInteraction(e,!0)),e.on(this._element,Ir,e=>this._onInteraction(e,!1)),e.on(this._element,Br,e=>this._onInteraction(e,!0)),e.on(this._element,Vr,e=>this._onInteraction(e,!1))}_clearTimeout(){clearTimeout(this._timeout),this._timeout=null}static jQueryInterface(e){return this.each(function(){const t=Ce.getOrCreateInstance(this,e);if(typeof e=="string"){if(typeof t[e]=="undefined")throw new TypeError(`No method named "${e}"`);t[e](this)}})}}Se(Ce),c(Ce);const ec={Alert:de,Button:fe,Carousel:ie,Collapse:le,Dropdown:h,Modal:B,Offcanvas:A,Popover:ct,ScrollSpy:Ee,Tab:R,Toast:Ce,Tooltip:U};return ec}),function(e){"use strict";e(function(){e('[data-bs-toggle="tooltip"]').tooltip(),e('[data-bs-toggle="popover"]').popover(),e(".popover-dismiss").popover({trigger:"focus"})});function t(e){return e.offset().top+e.outerHeight()}e(function(){var n,o,i,s=e(".js-td-cover");if(!s.length)return;o=t(s),i=e(".js-navbar-scroll").offset().top,n=Math.ceil(e(".js-navbar-scroll").outerHeight()),o-i{o(e(n.target)),t.blur()}),t.closest("form").on("submit",()=>!1);let n=null;const s=new Map;e.ajax(t.data("offline-search-index-json-src")).then(e=>{n=lunr(function(){this.ref("ref"),this.field("title",{boost:5}),this.field("categories",{boost:3}),this.field("tags",{boost:3}),this.field("description",{boost:2}),this.field("body"),e.forEach(e=>{this.add(e),s.set(e.ref,{title:e.title,excerpt:e.excerpt})})}),t.trigger("change")});const o=o=>{{let e=bootstrap.Popover.getInstance(o[0]);e!==null&&e.dispose()}if(n===null)return;const i=o.val();if(i==="")return;const c=n.query(e=>{const t=lunr.tokenizer(i.toLowerCase());t.forEach(t=>{const n=t.toString();e.term(n,{boost:100}),e.term(n,{wildcard:lunr.Query.wildcard.LEADING|lunr.Query.wildcard.TRAILING,boost:10}),e.term(n,{editDistance:2})})}).slice(0,o.data("offline-search-max-results")),a=e("
");a.append(e("
").css({display:"flex",justifyContent:"space-between",marginBottom:"1em"}).append(e("").text("Search results").css({fontWeight:"bold"})).append(e("").addClass("td-offline-search-results__close-button")));const r=e("
").css({maxHeight:`calc(100vh - ${o.offset().top-e(window).scrollTop()+180}px)`,overflowY:"auto"});a.append(r),c.length===0?r.append(e("

").text(`No results found for query "${i}"`)):c.forEach(n=>{const i=s.get(n.ref),a=t.data("offline-search-base-href")+n.ref.replace(/^\//,""),o=e("

").addClass("mt-4");o.append(e("").addClass("d-block text-muted").text(n.ref)),o.append(e("").addClass("d-block").css({fontSize:"1.2rem"}).attr("href",a).text(i.title)),o.append(e("

").text(i.excerpt)),r.append(o)}),o.one("shown.bs.popover",()=>{e(".td-offline-search-results__close-button").on("click",()=>{o.val(""),o.trigger("change")})});const l=new bootstrap.Popover(o,{content:a[0],html:!0,customClass:"td-offline-search-results",placement:"bottom"});l.show()}})}(jQuery) \ No newline at end of file diff --git a/js/prism.js b/js/prism.js new file mode 100644 index 000000000..15f0f7825 --- /dev/null +++ b/js/prism.js @@ -0,0 +1,21 @@ +/* PrismJS 1.28.0 +https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+bash+c+csharp+cpp+go+java+markdown+python+scss+sql+toml+yaml&plugins=toolbar+copy-to-clipboard */ +var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(e){var n=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,r={},a={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof i?new i(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/=g.reach);A+=w.value.length,w=w.next){var E=w.value;if(n.length>e.length)return;if(!(E instanceof i)){var P,L=1;if(y){if(!(P=l(b,A,e,m))||P.index>=e.length)break;var S=P.index,O=P.index+P[0].length,j=A;for(j+=w.value.length;S>=j;)j+=(w=w.next).value.length;if(A=j-=w.value.length,w.value instanceof i)continue;for(var C=w;C!==n.tail&&(jg.reach&&(g.reach=W);var z=w.prev;if(_&&(z=u(n,z,_),A+=_.length),c(n,z,L),w=u(n,z,new i(f,p?a.tokenize(N,p):N,k,N)),M&&u(n,w,M),L>1){var I={cause:f+","+d,reach:W};o(e,n,t,w.prev,A,I),g&&I.reach>g.reach&&(g.reach=I.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function u(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a,r.prev=a,e.length++,a}function c(e,n,t){for(var r=n.next,a=0;a"+i.content+""},!e.document)return e.addEventListener?(a.disableWorkerMessageHandler||e.addEventListener("message",(function(n){var t=JSON.parse(n.data),r=t.language,i=t.code,l=t.immediateClose;e.postMessage(a.highlight(i,a.languages[r],r)),l&&e.close()}),!1),a):a;var g=a.util.currentScript();function f(){a.manual||a.highlightAll()}if(g&&(a.filename=g.src,g.hasAttribute("data-manual")&&(a.manual=!0)),!a.manual){var h=document.readyState;"loading"===h||"interactive"===h&&g&&g.defer?document.addEventListener("DOMContentLoaded",f):window.requestAnimationFrame?window.requestAnimationFrame(f):window.setTimeout(f,16)}return a}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); +Prism.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",(function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))})),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^$/i;var t={"included-cdata":{pattern://i,inside:s}};t["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var n={};n[a]={pattern:RegExp("(<__[^>]*>)(?:))*\\]\\]>|(?!)".replace(/__/g,(function(){return a})),"i"),lookbehind:!0,greedy:!0,inside:t},Prism.languages.insertBefore("markup","cdata",n)}}),Object.defineProperty(Prism.languages.markup.tag,"addAttribute",{value:function(a,e){Prism.languages.markup.tag.inside["special-attr"].push({pattern:RegExp("(^|[\"'\\s])(?:"+a+")\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))","i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[e,"language-"+e],inside:Prism.languages[e]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml; +!function(s){var e=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:[^;{\\s\"']|\\s+(?!\\s)|"+e.source+")*?(?:;|(?=\\s*\\{))"),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+e.source+"|(?:[^\\\\\r\n()\"']|\\\\[^])*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+e.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+e.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:e,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var t=s.languages.markup;t&&(t.tag.addInlined("style","css"),t.tag.addAttribute("style","css"))}(Prism); +Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}; +Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp("(^|[^\\w$])(?:NaN|Infinity|0[bB][01]+(?:_[01]+)*n?|0[oO][0-7]+(?:_[0-7]+)*n?|0[xX][\\dA-Fa-f]+(?:_[\\dA-Fa-f]+)*n?|\\d+(?:_\\d+)*n|(?:\\d+(?:_\\d+)*(?:\\.(?:\\d+(?:_\\d+)*)?)?|\\.\\d+(?:_\\d+)*)(?:[Ee][+-]?\\d+(?:_\\d+)*)?)(?![\\w$])"),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp("((?:^|[^$\\w\\xA0-\\uFFFF.\"'\\])\\s]|\\b(?:return|yield))\\s*)/(?:(?:\\[(?:[^\\]\\\\\r\n]|\\\\.)*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}|(?:\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.)*\\])*\\])*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}v[dgimyus]{0,7})(?=(?:\\s|/\\*(?:[^*]|\\*(?!/))*\\*/)*(?:$|[\r\n,.;:})\\]]|//))"),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),Prism.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),Prism.languages.markup&&(Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.markup.tag.addAttribute("on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)","javascript")),Prism.languages.js=Prism.languages.javascript; +!function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",n={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},a={bash:n,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?:\.\w+)*(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},parameter:{pattern:/(^|\s)-{1,2}(?:\w+:[+-]?)?\w+(?:\.\w+)*(?=[=\s]|$)/,alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:a},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:n}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:a},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:a.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:a.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cargo|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|java|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|sysctl|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},n.inside=e.languages.bash;for(var s=["comment","function-name","for-or-select","assign-left","parameter","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],o=a.variable[1].inside,i=0;i>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),Prism.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),Prism.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},Prism.languages.c.string],char:Prism.languages.c.char,comment:Prism.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:Prism.languages.c}}}}),Prism.languages.insertBefore("c","function",{constant:/\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/}),delete Prism.languages.c.boolean; +!function(e){function n(e,n){return e.replace(/<<(\d+)>>/g,(function(e,s){return"(?:"+n[+s]+")"}))}function s(e,s,a){return RegExp(n(e,s),a||"")}function a(e,n){for(var s=0;s>/g,(function(){return"(?:"+e+")"}));return e.replace(/<>/g,"[^\\s\\S]")}var t="bool byte char decimal double dynamic float int long object sbyte short string uint ulong ushort var void",r="class enum interface record struct",i="add alias and ascending async await by descending from(?=\\s*(?:\\w|$)) get global group into init(?=\\s*;) join let nameof not notnull on or orderby partial remove select set unmanaged value when where with(?=\\s*{)",o="abstract as base break case catch checked const continue default delegate do else event explicit extern finally fixed for foreach goto if implicit in internal is lock namespace new null operator out override params private protected public readonly ref return sealed sizeof stackalloc static switch this throw try typeof unchecked unsafe using virtual volatile while yield";function l(e){return"\\b(?:"+e.trim().replace(/ /g,"|")+")\\b"}var d=l(r),p=RegExp(l(t+" "+r+" "+i+" "+o)),c=l(r+" "+i+" "+o),u=l(t+" "+r+" "+o),g=a("<(?:[^<>;=+\\-*/%&|^]|<>)*>",2),b=a("\\((?:[^()]|<>)*\\)",2),h="@?\\b[A-Za-z_]\\w*\\b",f=n("<<0>>(?:\\s*<<1>>)?",[h,g]),m=n("(?!<<0>>)<<1>>(?:\\s*\\.\\s*<<1>>)*",[c,f]),k="\\[\\s*(?:,\\s*)*\\]",y=n("<<0>>(?:\\s*(?:\\?\\s*)?<<1>>)*(?:\\s*\\?)?",[m,k]),w=n("[^,()<>[\\];=+\\-*/%&|^]|<<0>>|<<1>>|<<2>>",[g,b,k]),v=n("\\(<<0>>+(?:,<<0>>+)+\\)",[w]),x=n("(?:<<0>>|<<1>>)(?:\\s*(?:\\?\\s*)?<<2>>)*(?:\\s*\\?)?",[v,m,k]),$={keyword:p,punctuation:/[<>()?,.:[\]]/},_="'(?:[^\r\n'\\\\]|\\\\.|\\\\[Uux][\\da-fA-F]{1,8})'",B='"(?:\\\\.|[^\\\\"\r\n])*"';e.languages.csharp=e.languages.extend("clike",{string:[{pattern:s("(^|[^$\\\\])<<0>>",['@"(?:""|\\\\[^]|[^\\\\"])*"(?!")']),lookbehind:!0,greedy:!0},{pattern:s("(^|[^@$\\\\])<<0>>",[B]),lookbehind:!0,greedy:!0}],"class-name":[{pattern:s("(\\busing\\s+static\\s+)<<0>>(?=\\s*;)",[m]),lookbehind:!0,inside:$},{pattern:s("(\\busing\\s+<<0>>\\s*=\\s*)<<1>>(?=\\s*;)",[h,x]),lookbehind:!0,inside:$},{pattern:s("(\\busing\\s+)<<0>>(?=\\s*=)",[h]),lookbehind:!0},{pattern:s("(\\b<<0>>\\s+)<<1>>",[d,f]),lookbehind:!0,inside:$},{pattern:s("(\\bcatch\\s*\\(\\s*)<<0>>",[m]),lookbehind:!0,inside:$},{pattern:s("(\\bwhere\\s+)<<0>>",[h]),lookbehind:!0},{pattern:s("(\\b(?:is(?:\\s+not)?|as)\\s+)<<0>>",[y]),lookbehind:!0,inside:$},{pattern:s("\\b<<0>>(?=\\s+(?!<<1>>|with\\s*\\{)<<2>>(?:\\s*[=,;:{)\\]]|\\s+(?:in|when)\\b))",[x,u,h]),inside:$}],keyword:p,number:/(?:\b0(?:x[\da-f_]*[\da-f]|b[01_]*[01])|(?:\B\.\d+(?:_+\d+)*|\b\d+(?:_+\d+)*(?:\.\d+(?:_+\d+)*)?)(?:e[-+]?\d+(?:_+\d+)*)?)(?:[dflmu]|lu|ul)?\b/i,operator:/>>=?|<<=?|[-=]>|([-+&|])\1|~|\?\?=?|[-+*/%&|^!=<>]=?/,punctuation:/\?\.?|::|[{}[\];(),.:]/}),e.languages.insertBefore("csharp","number",{range:{pattern:/\.\./,alias:"operator"}}),e.languages.insertBefore("csharp","punctuation",{"named-parameter":{pattern:s("([(,]\\s*)<<0>>(?=\\s*:)",[h]),lookbehind:!0,alias:"punctuation"}}),e.languages.insertBefore("csharp","class-name",{namespace:{pattern:s("(\\b(?:namespace|using)\\s+)<<0>>(?:\\s*\\.\\s*<<0>>)*(?=\\s*[;{])",[h]),lookbehind:!0,inside:{punctuation:/\./}},"type-expression":{pattern:s("(\\b(?:default|sizeof|typeof)\\s*\\(\\s*(?!\\s))(?:[^()\\s]|\\s(?!\\s)|<<0>>)*(?=\\s*\\))",[b]),lookbehind:!0,alias:"class-name",inside:$},"return-type":{pattern:s("<<0>>(?=\\s+(?:<<1>>\\s*(?:=>|[({]|\\.\\s*this\\s*\\[)|this\\s*\\[))",[x,m]),inside:$,alias:"class-name"},"constructor-invocation":{pattern:s("(\\bnew\\s+)<<0>>(?=\\s*[[({])",[x]),lookbehind:!0,inside:$,alias:"class-name"},"generic-method":{pattern:s("<<0>>\\s*<<1>>(?=\\s*\\()",[h,g]),inside:{function:s("^<<0>>",[h]),generic:{pattern:RegExp(g),alias:"class-name",inside:$}}},"type-list":{pattern:s("\\b((?:<<0>>\\s+<<1>>|record\\s+<<1>>\\s*<<5>>|where\\s+<<2>>)\\s*:\\s*)(?:<<3>>|<<4>>|<<1>>\\s*<<5>>|<<6>>)(?:\\s*,\\s*(?:<<3>>|<<4>>|<<6>>))*(?=\\s*(?:where|[{;]|=>|$))",[d,f,h,x,p.source,b,"\\bnew\\s*\\(\\s*\\)"]),lookbehind:!0,inside:{"record-arguments":{pattern:s("(^(?!new\\s*\\()<<0>>\\s*)<<1>>",[f,b]),lookbehind:!0,greedy:!0,inside:e.languages.csharp},keyword:p,"class-name":{pattern:RegExp(x),greedy:!0,inside:$},punctuation:/[,()]/}},preprocessor:{pattern:/(^[\t ]*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(#)\b(?:define|elif|else|endif|endregion|error|if|line|nullable|pragma|region|undef|warning)\b/,lookbehind:!0,alias:"keyword"}}}});var E=B+"|"+_,R=n("/(?![*/])|//[^\r\n]*[\r\n]|/\\*(?:[^*]|\\*(?!/))*\\*/|<<0>>",[E]),z=a(n("[^\"'/()]|<<0>>|\\(<>*\\)",[R]),2),S="\\b(?:assembly|event|field|method|module|param|property|return|type)\\b",j=n("<<0>>(?:\\s*\\(<<1>>*\\))?",[m,z]);e.languages.insertBefore("csharp","class-name",{attribute:{pattern:s("((?:^|[^\\s\\w>)?])\\s*\\[\\s*)(?:<<0>>\\s*:\\s*)?<<1>>(?:\\s*,\\s*<<1>>)*(?=\\s*\\])",[S,j]),lookbehind:!0,greedy:!0,inside:{target:{pattern:s("^<<0>>(?=\\s*:)",[S]),alias:"keyword"},"attribute-arguments":{pattern:s("\\(<<0>>*\\)",[z]),inside:e.languages.csharp},"class-name":{pattern:RegExp(m),inside:{punctuation:/\./}},punctuation:/[:,]/}}});var A=":[^}\r\n]+",F=a(n("[^\"'/()]|<<0>>|\\(<>*\\)",[R]),2),P=n("\\{(?!\\{)(?:(?![}:])<<0>>)*<<1>>?\\}",[F,A]),U=a(n("[^\"'/()]|/(?!\\*)|/\\*(?:[^*]|\\*(?!/))*\\*/|<<0>>|\\(<>*\\)",[E]),2),Z=n("\\{(?!\\{)(?:(?![}:])<<0>>)*<<1>>?\\}",[U,A]);function q(n,a){return{interpolation:{pattern:s("((?:^|[^{])(?:\\{\\{)*)<<0>>",[n]),lookbehind:!0,inside:{"format-string":{pattern:s("(^\\{(?:(?![}:])<<0>>)*)<<1>>(?=\\}$)",[a,A]),lookbehind:!0,inside:{punctuation:/^:/}},punctuation:/^\{|\}$/,expression:{pattern:/[\s\S]+/,alias:"language-csharp",inside:e.languages.csharp}}},string:/[\s\S]+/}}e.languages.insertBefore("csharp","string",{"interpolation-string":[{pattern:s('(^|[^\\\\])(?:\\$@|@\\$)"(?:""|\\\\[^]|\\{\\{|<<0>>|[^\\\\{"])*"',[P]),lookbehind:!0,greedy:!0,inside:q(P,F)},{pattern:s('(^|[^@\\\\])\\$"(?:\\\\.|\\{\\{|<<0>>|[^\\\\"{])*"',[Z]),lookbehind:!0,greedy:!0,inside:q(Z,U)}],char:{pattern:RegExp(_),greedy:!0}}),e.languages.dotnet=e.languages.cs=e.languages.csharp}(Prism); +!function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n="\\b(?!)\\w+(?:\\s*\\.\\s*\\w+)*\\b".replace(//g,(function(){return t.source}));e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp("(\\b(?:class|concept|enum|struct|typename)\\s+)(?!)\\w+".replace(//g,(function(){return t.source}))),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:false|true)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp('(\\b(?:import|module)\\s+)(?:"(?:\\\\(?:\r\n|[^])|[^"\\\\\r\n])*"|<[^<>\r\n]*>|'+"(?:\\s*:\\s*)?|:\\s*".replace(//g,(function(){return n}))+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:e.languages.cpp}}}}),e.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(Prism); +Prism.languages.go=Prism.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,lookbehind:!0,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|false|iota|nil|true)\b/,number:[/\b0(?:b[01_]+|o[0-7_]+)i?\b/i,/\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,/(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/}),Prism.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}}),delete Prism.languages.go["class-name"]; +!function(e){var n=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record(?!\s*[(){}[\]<>=%~.:,;?+\-*/&|^])|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,t="(?:[a-z]\\w*\\s*\\.\\s*)*(?:[A-Z]\\w*\\s*\\.\\s*)*",s={pattern:RegExp("(^|[^\\w.])"+t+"[A-Z](?:[\\d_A-Z]*[a-z]\\w*)?\\b"),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};e.languages.java=e.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"/,lookbehind:!0,greedy:!0},"class-name":[s,{pattern:RegExp("(^|[^\\w.])"+t+"[A-Z]\\w*(?=\\s+\\w+\\s*[;,=()]|\\s*(?:\\[[\\s,]*\\]\\s*)?::\\s*new\\b)"),lookbehind:!0,inside:s.inside},{pattern:RegExp("(\\b(?:class|enum|extends|implements|instanceof|interface|new|record|throws)\\s+)"+t+"[A-Z]\\w*\\b"),lookbehind:!0,inside:s.inside}],keyword:n,function:[e.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0},constant:/\b[A-Z][A-Z_\d]+\b/}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"},char:{pattern:/'(?:\\.|[^'\\\r\n]){1,6}'/,greedy:!0}}),e.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":s,keyword:n,punctuation:/[<>(),.:]/,operator:/[?&|]/}},import:[{pattern:RegExp("(\\bimport\\s+)"+t+"(?:[A-Z]\\w*|\\*)(?=\\s*;)"),lookbehind:!0,inside:{namespace:s.inside.namespace,punctuation:/\./,operator:/\*/,"class-name":/\w+/}},{pattern:RegExp("(\\bimport\\s+static\\s+)"+t+"(?:\\w+|\\*)(?=\\s*;)"),lookbehind:!0,alias:"static",inside:{namespace:s.inside.namespace,static:/\b\w+$/,punctuation:/\./,operator:/\*/,"class-name":/\w+/}}],namespace:{pattern:RegExp("(\\b(?:exports|import(?:\\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\\s+)(?!)[a-z]\\w*(?:\\.[a-z]\\w*)*\\.?".replace(//g,(function(){return n.source}))),lookbehind:!0,inside:{punctuation:/\./}}})}(Prism); +!function(n){function e(n){return n=n.replace(//g,(function(){return"(?:\\\\.|[^\\\\\n\r]|(?:\n|\r\n?)(?![\r\n]))"})),RegExp("((?:^|[^\\\\])(?:\\\\{2})*)(?:"+n+")")}var t="(?:\\\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\\\|\r\n`])+",a="\\|?__(?:\\|__)+\\|?(?:(?:\n|\r\n?)|(?![^]))".replace(/__/g,(function(){return t})),i="\\|?[ \t]*:?-{3,}:?[ \t]*(?:\\|[ \t]*:?-{3,}:?[ \t]*)+\\|?(?:\n|\r\n?)";n.languages.markdown=n.languages.extend("markup",{}),n.languages.insertBefore("markdown","prolog",{"front-matter-block":{pattern:/(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,lookbehind:!0,greedy:!0,inside:{punctuation:/^---|---$/,"front-matter":{pattern:/\S+(?:\s+\S+)*/,alias:["yaml","language-yaml"],inside:n.languages.yaml}}},blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+a+i+"(?:"+a+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+a+i+")(?:"+a+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(t),inside:n.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+a+")"+i+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+a+"$"),inside:{"table-header":{pattern:RegExp(t),alias:"important",inside:n.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,lookbehind:!0,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:e("\\b__(?:(?!_)|_(?:(?!_))+_)+__\\b|\\*\\*(?:(?!\\*)|\\*(?:(?!\\*))+\\*)+\\*\\*"),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:e("\\b_(?:(?!_)|__(?:(?!_))+__)+_\\b|\\*(?:(?!\\*)|\\*\\*(?:(?!\\*))+\\*\\*)+\\*"),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:e("(~~?)(?:(?!~))+\\2"),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},"code-snippet":{pattern:/(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,lookbehind:!0,greedy:!0,alias:["code","keyword"]},url:{pattern:e('!?\\[(?:(?!\\]))+\\](?:\\([^\\s)]+(?:[\t ]+"(?:\\\\.|[^"\\\\])*")?\\)|[ \t]?\\[(?:(?!\\]))+\\])'),lookbehind:!0,greedy:!0,inside:{operator:/^!/,content:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},variable:{pattern:/(^\][ \t]?\[)[^\]]+(?=\]$)/,lookbehind:!0},url:{pattern:/(^\]\()[^\s)]+/,lookbehind:!0},string:{pattern:/(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,lookbehind:!0}}}}),["url","bold","italic","strike"].forEach((function(e){["url","bold","italic","strike","code-snippet"].forEach((function(t){e!==t&&(n.languages.markdown[e].inside.content.inside[t]=n.languages.markdown[t])}))})),n.hooks.add("after-tokenize",(function(n){"markdown"!==n.language&&"md"!==n.language||function n(e){if(e&&"string"!=typeof e)for(var t=0,a=e.length;t",quot:'"'},l=String.fromCodePoint||String.fromCharCode;n.languages.md=n.languages.markdown}(Prism); +Prism.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},Prism.languages.python["string-interpolation"].inside.interpolation.inside.rest=Prism.languages.python,Prism.languages.py=Prism.languages.python; +Prism.languages.scss=Prism.languages.extend("css",{comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},atrule:{pattern:/@[\w-](?:\([^()]+\)|[^()\s]|\s+(?!\s))*?(?=\s+[{;])/,inside:{rule:/@[\w-]+/}},url:/(?:[-a-z]+-)?url(?=\()/i,selector:{pattern:/(?=\S)[^@;{}()]?(?:[^@;{}()\s]|\s+(?!\s)|#\{\$[-\w]+\})+(?=\s*\{(?:\}|\s|[^}][^:{}]*[:{][^}]))/,inside:{parent:{pattern:/&/,alias:"important"},placeholder:/%[-\w]+/,variable:/\$[-\w]+|#\{\$[-\w]+\}/}},property:{pattern:/(?:[-\w]|\$[-\w]|#\{\$[-\w]+\})+(?=\s*:)/,inside:{variable:/\$[-\w]+|#\{\$[-\w]+\}/}}}),Prism.languages.insertBefore("scss","atrule",{keyword:[/@(?:content|debug|each|else(?: if)?|extend|for|forward|function|if|import|include|mixin|return|use|warn|while)\b/i,{pattern:/( )(?:from|through)(?= )/,lookbehind:!0}]}),Prism.languages.insertBefore("scss","important",{variable:/\$[-\w]+|#\{\$[-\w]+\}/}),Prism.languages.insertBefore("scss","function",{"module-modifier":{pattern:/\b(?:as|hide|show|with)\b/i,alias:"keyword"},placeholder:{pattern:/%[-\w]+/,alias:"selector"},statement:{pattern:/\B!(?:default|optional)\b/i,alias:"keyword"},boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"},operator:{pattern:/(\s)(?:[-+*\/%]|[=!]=|<=?|>=?|and|not|or)(?=\s)/,lookbehind:!0}}),Prism.languages.scss.atrule.inside.rest=Prism.languages.scss; +Prism.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},variable:[{pattern:/@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,greedy:!0},/@[\w.$]+/],string:{pattern:/(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,greedy:!0,lookbehind:!0},identifier:{pattern:/(^|[^@\\])`(?:\\[\s\S]|[^`\\]|``)*`/,greedy:!0,lookbehind:!0,inside:{punctuation:/^`|`$/}},function:/\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:COL|_INSERT)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURN(?:ING|S)?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,boolean:/\b(?:FALSE|NULL|TRUE)\b/i,number:/\b0x[\da-f]+\b|\b\d+(?:\.\d*)?|\B\.\d+\b/i,operator:/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/}; +!function(e){function n(e){return e.replace(/__/g,(function(){return"(?:[\\w-]+|'[^'\n\r]*'|\"(?:\\\\.|[^\\\\\"\r\n])*\")"}))}e.languages.toml={comment:{pattern:/#.*/,greedy:!0},table:{pattern:RegExp(n("(^[\t ]*\\[\\s*(?:\\[\\s*)?)__(?:\\s*\\.\\s*__)*(?=\\s*\\])"),"m"),lookbehind:!0,greedy:!0,alias:"class-name"},key:{pattern:RegExp(n("(^[\t ]*|[{,]\\s*)__(?:\\s*\\.\\s*__)*(?=\\s*=)"),"m"),lookbehind:!0,greedy:!0,alias:"property"},string:{pattern:/"""(?:\\[\s\S]|[^\\])*?"""|'''[\s\S]*?'''|'[^'\n\r]*'|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},date:[{pattern:/\b\d{4}-\d{2}-\d{2}(?:[T\s]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})?)?\b/i,alias:"number"},{pattern:/\b\d{2}:\d{2}:\d{2}(?:\.\d+)?\b/,alias:"number"}],number:/(?:\b0(?:x[\da-zA-Z]+(?:_[\da-zA-Z]+)*|o[0-7]+(?:_[0-7]+)*|b[10]+(?:_[10]+)*))\b|[-+]?\b\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?\b|[-+]?\b(?:inf|nan)\b/,boolean:/\b(?:false|true)\b/,punctuation:/[.,=[\]{}]/}}(Prism); +!function(e){var n=/[*&][^\s[\]{},]+/,r=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,t="(?:"+r.source+"(?:[ \t]+"+n.source+")?|"+n.source+"(?:[ \t]+"+r.source+")?)",a="(?:[^\\s\\x00-\\x08\\x0e-\\x1f!\"#%&'*,\\-:>?@[\\]`{|}\\x7f-\\x84\\x86-\\x9f\\ud800-\\udfff\\ufffe\\uffff]|[?:-])(?:[ \t]*(?:(?![#:])|:))*".replace(//g,(function(){return"[^\\s\\x00-\\x08\\x0e-\\x1f,[\\]{}\\x7f-\\x84\\x86-\\x9f\\ud800-\\udfff\\ufffe\\uffff]"})),d="\"(?:[^\"\\\\\r\n]|\\\\.)*\"|'(?:[^'\\\\\r\n]|\\\\.)*'";function o(e,n){n=(n||"").replace(/m/g,"")+"m";var r="([:\\-,[{]\\s*(?:\\s<>[ \t]+)?)(?:<>)(?=[ \t]*(?:$|,|\\]|\\}|(?:[\r\n]\\s*)?#))".replace(/<>/g,(function(){return t})).replace(/<>/g,(function(){return e}));return RegExp(r,n)}e.languages.yaml={scalar:{pattern:RegExp("([\\-:]\\s*(?:\\s<>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\\S[^\r\n]*(?:\\2[^\r\n]+)*)".replace(/<>/g,(function(){return t}))),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp("((?:^|[:\\-,[{\r\n?])[ \t]*(?:<>[ \t]+)?)<>(?=\\s*:\\s)".replace(/<>/g,(function(){return t})).replace(/<>/g,(function(){return"(?:"+a+"|"+d+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:o("\\d{4}-\\d\\d?-\\d\\d?(?:[tT]|[ \t]+)\\d\\d?:\\d{2}:\\d{2}(?:\\.\\d*)?(?:[ \t]*(?:Z|[-+]\\d\\d?(?::\\d{2})?))?|\\d{4}-\\d{2}-\\d{2}|\\d\\d?:\\d{2}(?::\\d{2}(?:\\.\\d*)?)?"),lookbehind:!0,alias:"number"},boolean:{pattern:o("false|true","i"),lookbehind:!0,alias:"important"},null:{pattern:o("null|~","i"),lookbehind:!0,alias:"important"},string:{pattern:o(d),lookbehind:!0,greedy:!0},number:{pattern:o("[+-]?(?:0x[\\da-f]+|0o[0-7]+|(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[+-]?\\d+)?|\\.inf|\\.nan)","i"),lookbehind:!0},tag:r,important:n,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(Prism); +!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document){var e=[],t={},n=function(){};Prism.plugins.toolbar={};var a=Prism.plugins.toolbar.registerButton=function(n,a){var r;r="function"==typeof a?a:function(e){var t;return"function"==typeof a.onClick?((t=document.createElement("button")).type="button",t.addEventListener("click",(function(){a.onClick.call(this,e)}))):"string"==typeof a.url?(t=document.createElement("a")).href=a.url:t=document.createElement("span"),a.className&&t.classList.add(a.className),t.textContent=a.text,t},n in t?console.warn('There is a button with the key "'+n+'" registered already.'):e.push(t[n]=r)},r=Prism.plugins.toolbar.hook=function(a){var r=a.element.parentNode;if(r&&/pre/i.test(r.nodeName)&&!r.parentNode.classList.contains("code-toolbar")){var o=document.createElement("div");o.classList.add("code-toolbar"),r.parentNode.insertBefore(o,r),o.appendChild(r);var i=document.createElement("div");i.classList.add("toolbar");var l=e,d=function(e){for(;e;){var t=e.getAttribute("data-toolbar-order");if(null!=t)return(t=t.trim()).length?t.split(/\s*,\s*/g):[];e=e.parentElement}}(a.element);d&&(l=d.map((function(e){return t[e]||n}))),l.forEach((function(e){var t=e(a);if(t){var n=document.createElement("div");n.classList.add("toolbar-item"),n.appendChild(t),i.appendChild(n)}})),o.appendChild(i)}};a("label",(function(e){var t=e.element.parentNode;if(t&&/pre/i.test(t.nodeName)&&t.hasAttribute("data-label")){var n,a,r=t.getAttribute("data-label");try{a=document.querySelector("template#"+r)}catch(e){}return a?n=a.content:(t.hasAttribute("data-url")?(n=document.createElement("a")).href=t.getAttribute("data-url"):n=document.createElement("span"),n.textContent=r),n}})),Prism.hooks.add("complete",r)}}(); +!function(){function t(t){var e=document.createElement("textarea");e.value=t.getText(),e.style.top="0",e.style.left="0",e.style.position="fixed",document.body.appendChild(e),e.focus(),e.select();try{var o=document.execCommand("copy");setTimeout((function(){o?t.success():t.error()}),1)}catch(e){setTimeout((function(){t.error(e)}),1)}document.body.removeChild(e)}"undefined"!=typeof Prism&&"undefined"!=typeof document&&(Prism.plugins.toolbar?Prism.plugins.toolbar.registerButton("copy-to-clipboard",(function(e){var o=e.element,n=function(t){var e={copy:"Copy","copy-error":"Press Ctrl+C to copy","copy-success":"Copied!","copy-timeout":5e3};for(var o in e){for(var n="data-prismjs-"+o,c=t;c&&!c.hasAttribute(n);)c=c.parentElement;c&&(e[o]=c.getAttribute(n))}return e}(o),c=document.createElement("button");c.className="copy-to-clipboard-button",c.setAttribute("type","button");var r=document.createElement("span");return c.appendChild(r),u("copy"),function(e,o){e.addEventListener("click",(function(){!function(e){navigator.clipboard?navigator.clipboard.writeText(e.getText()).then(e.success,(function(){t(e)})):t(e)}(o)}))}(c,{getText:function(){return o.textContent},success:function(){u("copy-success"),i()},error:function(){u("copy-error"),setTimeout((function(){!function(t){window.getSelection().selectAllChildren(t)}(o)}),1),i()}}),c;function i(){setTimeout((function(){u("copy")}),n["copy-timeout"])}function u(t){r.textContent=n[t],c.setAttribute("data-copy-state",t)}})):console.warn("Copy to Clipboard plugin loaded before Toolbar plugin."))}(); diff --git a/js/tabpane-persist.js b/js/tabpane-persist.js new file mode 100644 index 000000000..236213075 --- /dev/null +++ b/js/tabpane-persist.js @@ -0,0 +1,116 @@ +// Storage key names and data attribute name: +const td_persistStorageKeyNameBase = 'td-tp-persist'; +const td_persistCounterStorageKeyName = `${td_persistStorageKeyNameBase}-count`; +const td_persistDataAttrName = `data-${td_persistStorageKeyNameBase}`; + +// Utilities + +const _tdPersistCssSelector = (attrValue) => + attrValue + ? `[${td_persistDataAttrName}="${attrValue}"]` + : `[${td_persistDataAttrName}]`; + +const _tdStoragePersistKey = (tabKey) => + td_persistStorageKeyNameBase + ':' + (tabKey || ''); + +const _tdSupportsLocalStorage = () => typeof Storage !== 'undefined'; + +// Helpers + +function tdPersistKey(key, value) { + // @requires: tdSupportsLocalStorage(); + + try { + if (value) { + localStorage.setItem(key, value); + } else { + localStorage.removeItem(key); + } + } catch (error) { + const action = value ? 'add' : 'remove'; + console.error( + `Docsy tabpane: unable to ${action} localStorage key '${key}': `, + error + ); + } +} + +// Retrieve, increment, and store tab-select event count, then returns it. +function tdGetTabSelectEventCountAndInc() { + // @requires: tdSupportsLocalStorage(); + + const storedCount = localStorage.getItem(td_persistCounterStorageKeyName); + let numTabSelectEvents = parseInt(storedCount) || 0; + numTabSelectEvents++; + tdPersistKey(td_persistCounterStorageKeyName, numTabSelectEvents.toString()); + return numTabSelectEvents; +} + +// Main functions + +function tdActivateTabsWithKey(key) { + if (!key) return; + + document.querySelectorAll(_tdPersistCssSelector(key)).forEach((element) => { + new bootstrap.Tab(element).show(); + }); +} + +function tdPersistActiveTab(activeTabKey) { + if (!_tdSupportsLocalStorage()) return; + + tdPersistKey( + _tdStoragePersistKey(activeTabKey), + tdGetTabSelectEventCountAndInc() + ); + tdActivateTabsWithKey(activeTabKey); +} + +// Handlers + +function tdGetAndActivatePersistedTabs(tabs) { + // Get unique persistence keys of tabs in this page + var keyOfTabsInThisPage = [ + ...new Set( + Array.from(tabs).map((el) => el.getAttribute(td_persistDataAttrName)) + ), + ]; + + // Create a list of active tabs with their age: + let key_ageList = keyOfTabsInThisPage + // Map to [tab-key, last-activated-age] + .map((k) => [ + k, + parseInt(localStorage.getItem(_tdStoragePersistKey(k))) || 0, + ]) + // Exclude tabs that have never been activated + .filter(([k, v]) => v) + // Sort from oldest selected to most recently selected + .sort((a, b) => a[1] - b[1]); + + // Activate tabs from the oldest to the newest + key_ageList.forEach(([key]) => { + tdActivateTabsWithKey(key); + }); + + return key_ageList; +} + +function tdRegisterTabClickHandler(tabs) { + tabs.forEach((tab) => { + tab.addEventListener('click', () => { + const activeTabKey = tab.getAttribute(td_persistDataAttrName); + tdPersistActiveTab(activeTabKey); + }); + }); +} + +// Register listeners and activate tabs + +window.addEventListener('DOMContentLoaded', () => { + if (!_tdSupportsLocalStorage()) return; + + var allTabsInThisPage = document.querySelectorAll(_tdPersistCssSelector()); + tdRegisterTabClickHandler(allTabsInThisPage); + tdGetAndActivatePersistedTabs(allTabsInThisPage); +}); diff --git a/offline-search-index.16ddb05ee41dd47586f606ac04120324.json b/offline-search-index.16ddb05ee41dd47586f606ac04120324.json new file mode 100644 index 000000000..9c6e31f65 --- /dev/null +++ b/offline-search-index.16ddb05ee41dd47586f606ac04120324.json @@ -0,0 +1 @@ +[{"body":"The Drycc Workflow command-line interface (CLI), or client, allows you to interact with Drycc Workflow.\nInstallation Install the latest drycc client for Linux or Mac OS X with: $ curl -sfL https://www.drycc.cc/install-cli.sh | bash -\nThe installer puts drycc in your current directory, but you should move it somewhere in your $PATH:\n$ ln -fs $PWD/drycc /usr/local/bin/drycc Getting Help The Drycc client comes with comprehensive documentation for every command. Use drycc help to explore the commands available to you:\n$ drycc help The Drycc command-line client issues API calls to a Drycc controller. Usage: drycc \u003ccommand\u003e [\u003cargs\u003e...] Auth commands:: login login to a controller logout logout from the current controller Subcommands, use `drycc help [subcommand]` to learn more:: ... To get help on subcommands, use drycc help [subcommand]:\n$ drycc help apps Valid commands for apps: apps:create create a new application apps:list list accessible applications apps:info view info about an application apps:open open the application in a browser apps:logs view aggregated application logs apps:run run a command in an ephemeral app container apps:destroy destroy an application apps:transfer transfer app ownership to another user Use `drycc help [command]` to learn more Support for Multiple Profiles The CLI reads from the default client profile, which is located on your workstation at $HOME/.drycc/client.json.\nEasily switch between multiple Drycc Workflow installations or users by setting the $DRYCC_PROFILE environment variable or by using the -c flag.\nThere are two ways to set the $DRYCC_PROFILE option.\nPath to a json configuration file. Profile name. If you set profile to just a name, it will be saved alongside the default profile, in $HOME/.drycc/\u003cname\u003e.json. Examples:\n$ DRYCC_PROFILE=production drycc login drycc.production.com ... Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71 Waiting for login... .o.Logged in as drycc Configuration saved to /home/testuser/.drycc/production.json $ DRYCC_PROFILE=~/config.json drycc login drycc.example.com ... Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71 Waiting for login... .o.Logged in as drycc Configuration saved to /home/testuser/config.json The configuration flag works identically to and overrides $DRYCC_PROFILE:\n$ drycc whoami -c ~/config.json You are drycc at drycc.example.com Proxy Support If your workstation uses a proxy to reach the network where the cluster lies, set the http_proxy or https_proxy environment variable to enable proxy support:\n$ export http_proxy=\"http://proxyip:port\" $ export https_proxy=\"http://proxyip:port\" !!! note Configuring a proxy is generally not necessary for local Minikube clusters.\nCLI Plugins Plugins allow developers to extend the functionality of the Drycc Client, adding new commands or features.\nIf an unknown command is specified, the client will attempt to execute the command as a dash-separated command. In this case, drycc resource:command will execute drycc-resource with the argument list command. In full form:\n$ # these two are identical $ drycc accounts:list $ drycc-accounts list Any flags after the command will also be sent to the plugin as an argument:\n$ # these two are identical $ drycc accounts:list --debug $ drycc-accounts list --debug But flags preceding the command will not:\n$ # these two are identical $ drycc --debug accounts:list $ drycc-accounts list ","categories":"","description":"How to download, install, and start using the Drycc CLI. The Drycc CLI used to be part of the Drycc Toolbelt.","excerpt":"How to download, install, and start using the Drycc CLI. The Drycc CLI …","ref":"/docs/users/cli/","tags":"","title":"Drycc Workflow CLI"},{"body":"Twelve-Factor Applications The Twelve-Factor App is a methodology for building modern applications that can be scaled across a distributed system.\nTwelve-factor is a valuable synthesis of years of experience with software-as-a-service apps in the wild, particularly on the Heroku platform.\nWorkflow is designed to run applications that adhere to the Twelve-Factor App methodology and best practices.\nKubernetes Kubernetes is an open-source cluster manager developed by Google and donated to the Cloud Native Compute Foundation. Kubernetes manages all the activity on your cluster, including: desired state convergence, stable service addresses, health monitoring, service discovery, and DNS resolution.\nWorkflow builds upon Kubernetes abstractions like Services, Deployments and Pods to provide a developer-friendly experience. Building containers directly from application source code, aggregating logs, and managing deployment configurations and app releases are just some of the features Workflow adds.\nDrycc Workflow is a set of Kubernetes-native components, installable via Helm. Systems engineers who are familiar with Kubernetes will feel right at home running Workflow.\nSee the components overview for more detail.\nContainer [Container][] is an open source project to build, ship and run any application as a lightweight, portable, self-sufficient container.\nIf you have not yet converted your application to containers, Workflow provides a simple and straightforward “source to Container image” capability. Supporting multiple language runtimes via community buildpacks, building your application in a container can be as easy as git push drycc master.\nApplications which use either a Dockerfile or reference external Container images are launched unmodified.\nApplications Workflow is designed around the concept of an application, or app.\nApplications come in one of three forms:\na collection of source files stored in a git repository a Dockerfile and associated source files stored in a git repository a reference to an existing image at a Container repository Applications are identified by a unique name for easy reference. If you do not specify a name when creating your application, Workflow generates one for you. Workflow also manages related information, including domain names, SSL certificates, and developer-provided configuration.\nBuild, Release, Run Build Stage The builder component processes incoming git push drycc master requests and manages your application packaging.\nIf your application is using a buildpack, builder will launch an ephemeral job to extract and execute the packaging instructions. The resulting application artifact is stored by the platform for execution during the run stage.\nIf instead builder finds a Dockerfile, it follows those instructions to create a Container image. The resulting artifact is stored in a Drycc-managed registry which will be referenced during the run stage.\nIf another system already builds and packages your application, that container artifact can be used directly. When referencing an external Container image, the builder component doesn’t attempt to repackage your app.\nRelease Stage During the release stage, a build is combined with application configuration to create a new, numbered release. New releases are created any time a new build is created or application configuration is changed. Tracking releases as a “write-only ledger” this way makes it easy to rollback to any previous release.\nRun Stage The run stage deploys the new release to the underlying Kubernetes cluster by changing the Deployment object which references the new release. By managing the desired replica count, Workflow orchestrates a zero-downtime, rolling update of your application. Once successfully updated, Workflow removes the last reference to the old release. Note that during the deploy, your application will be running in a mixed mode.\nBacking Services Workflow treats all persistent services such as databases, caches, storage, messaging systems, and other backing services as resources managed separately from your application. This philosophy aligns with Twelve-Factor best practices.\nApplications attach to backing services using environment variables. Because apps are decoupled from backing services, they are free to scale up independently, to use services provided by other apps, or to switch to external or third-party vendor services.\nSee Also Workflow Architecture Workflow Components ","categories":"","description":"Drycc Workflow is a lightweight application platform that deploys and scales Twelve-Factor apps as containers across a Kubernetes cluster.","excerpt":"Drycc Workflow is a lightweight application platform that deploys and …","ref":"/docs/understanding-workflow/concepts/","tags":"","title":"Concepts"},{"body":"When using the app ssl feature for non-production applications or when installing SSL for the platform, you can avoid the costs associated with the SSL certificate by using a self-signed SSL certificate. Though the certificate implements full encryption, visitors to your site will see a browser warning indicating that the certificate should not be trusted.\nPrerequisites The openssl library is required to generate your own certificate. Run the following command in your local environment to see if you already have openssl installed.\n$ which openssl /usr/bin/openssl If the which command does not return a path then you will need to install openssl yourself:\nIf you have… Install with… Mac OS X Homebrew: brew install openssl Windows complete package .exe installed Ubuntu Linux apt-get install openssl Generate Private Key and Certificate Signing Request A private key and certificate signing request are required to create an SSL certificate. These can be generated with a few simple commands. When the openssl req command asks for a “challenge password”, just press return, leaving the password empty.\n$ openssl genrsa -des3 -passout pass:x -out server.pass.key 2048 ... $ openssl rsa -passin pass:x -in server.pass.key -out server.key writing RSA key $ rm server.pass.key $ openssl req -new -key server.key -out server.csr ... Country Name (2 letter code) [AU]:US State or Province Name (full name) [Some-State]:California ... A challenge password []: ... Generate SSL Certificate The self-signed SSL certificate is generated from the server.key private key and server.csr files.\n$ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt The server.crt file is your site certificate suitable for use with Drycc’s SSL endpoint along with the server.key private key.\n","categories":"","description":"A self-signed TLS/SSL certificate is not signed by a publicly trusted certificate authority (CA) but instead by the developer or company that is responsible for the website.","excerpt":"A self-signed TLS/SSL certificate is not signed by a publicly trusted …","ref":"/docs/reference-guide/creating-a-self-signed-ssl-certificate/","tags":"","title":"Creating a Self-Signed SSL Certificate"},{"body":"An Application is deployed to Drycc using git push or the drycc client.\nSupported Applications Drycc Workflow can deploy any application or service that can run inside a container. In order to be scaled horizontally, applications must follow the Twelve-Factor App methodology and store any application state in external backing services.\nFor example, if your application persists state to the local filesystem – common with content management systems like Wordpress and Drupal – it cannot be scaled horizontally using drycc scale.\nFortunately, most modern applications feature a stateless application tier that can scale horizontally inside Drycc.\nLogin to the Controller !!! important if you haven’t yet, now is a good time to install the client and register.\nBefore deploying an application, users must first authenticate against the Drycc Controller using the URL supplied by their Drycc administrator.\n$ drycc login http://drycc.example.com Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71 Waiting for login... .o.Logged in as admin Configuration file written to /root/.drycc/client.json Or you can login with username and password\n$ drycc login http://drycc.example.com --username=demo --password=demo Configuration file written to /root/.drycc/client.json Select a Build Process Drycc Workflow supports three different ways of building applications:\nBuildpacks Cloud Native Buildpacks are useful if you want to follow cnb’s docs for building applications.\nLearn how to deploy applications using Buildpacks.\nDockerfiles Dockerfiles are a powerful way to define a portable execution environment built on a base OS of your choosing.\nLearn how to deploy applications using Dockerfiles.\nContainer Image Deploying a Container image onto Drycc allows you to take a Container image from either a public or a private registry and copy it over bit-for-bit, ensuring that you are running the same image in development or in your CI pipeline as you are in production.\nLearn how to deploy applications using Container images.\nTuning Application Settings It is possible to configure a few of the globally tunable settings on per application basis using config:set.\nSetting Description DRYCC_DISABLE_CACHE if set, this will disable the [imagebuilder cache][] (default: not set) DRYCC_DEPLOY_BATCHES the number of pods to bring up and take down sequentially during a scale (default: number of available nodes) DRYCC_DEPLOY_TIMEOUT deploy timeout in seconds per deploy batch (default: 120) IMAGE_PULL_POLICY the kubernetes [image pull policy][pull-policy] for application images (default: “IfNotPresent”) (allowed values: “Always”, “IfNotPresent”) KUBERNETES_DEPLOYMENTS_REVISION_HISTORY_LIMIT how many revisions Kubernetes keeps around of a given Deployment (default: all revisions) KUBERNETES_POD_TERMINATION_GRACE_PERIOD_SECONDS how many seconds kubernetes waits for a pod to finish work after a SIGTERM before sending SIGKILL (default: 30) Deploy Timeout Deploy timeout in seconds - There are 2 deploy methods, Deployments (see below) and RC (versions prior to 2.4) and this setting affects those a bit differently.\nDeployments Deployments behave a little bit differently from the RC based deployment strategy.\nKubernetes takes care of the entire deploy, doing rolling updates in the background. As a result, there is only an overall deployment timeout instead of a configurable per-batch timeout.\nThe base timeout is multiplied with DRYCC_DEPLOY_BATCHES to create an overall timeout. This would be 240 (timeout) * 4 (batches) = 960 second overall timeout.\nRC deploy This deploy timeout defines how long to wait for each batch to complete in DRYCC_DEPLOY_BATCHES.\nAdditions to the base timeout The base timeout is extended as well with healthchecks using initialDelaySeconds on liveness and readiness where the bigger of those two is applied. Additionally the timeout system accounts for slow image pulls by adding an additional 10 minutes when it has seen an image pull take over 1 minute. This allows the timeout values to be reasonable without having to account for image pull slowness in the base deploy timeout.\nDeployments Workflow uses Deployments for deploys. In prior versions ReplicationControllers were used with the ability to turn on Deployments via DRYCC_KUBERNETES_DEPLOYMENTS=1.\nThe advantage of Deployments is that rolling-updates will happen server-side in Kubernetes instead of in Drycc Workflow Controller, along with a few other Pod management related functionality. This allows a deploy to continue even when the CLI connection is interrupted.\nBehind the scenes your application deploy will be built up of a Deployment object per process type, each having multiple ReplicaSets (one per release) which in turn manage the Pods running your application.\nDrycc Workflow will behave the same way with DRYCC_KUBERNETES_DEPLOYMENTS enabled or disabled (only applicable to versions prior to 2.4). The changes are behind the scenes. Where you will see differences while using the CLI is drycc ps:list will output Pod names differently.\n","categories":"","description":"Learn how to deploy the application to drycc.","excerpt":"Learn how to deploy the application to drycc.","ref":"/docs/applications/deploying-apps/","tags":"","title":"Deploying an Application"},{"body":"Get started with Drycc Workflow in three easy steps.\nInstall CLI tools for Helm and Drycc Workflow Boot a Kubernetes and install Drycc Workflow Deploy your first application This guide will help you set up a cluster suitable for evaluation, development and testing. When you are ready for staging and production, view our production checklist.\nStep 1: Install Workflow For the quickstart we will install Drycc Workflow.\nStep 2: Install CLI tools For the quickstart we will install Drycc Workflow CLI.\nStep 3: Deploy your first app Last but not least, login and deploy your first application.\n","categories":"","description":"This guide helps you set up the Drycc workflow.","excerpt":"This guide helps you set up the Drycc workflow.","ref":"/docs/quickstart/overview/","tags":"","title":"Quick Start"},{"body":"File Bugs \u0026 Enhancements Find a bug? Want to see a new feature? Have a request for the maintainers? Open a Github issue in the applicable repository and we’ll get the conversation started.\nOur official support channel is the Drycc #community Slack channel.\nDon’t know what the applicable repository for an issue is? Open up in issue in workflow or chat with a maintainer in the Drycc #community Slack channel and we’ll make sure it gets to the right place.\nAdditionally, take a look at the troubleshooting documentation for common issues.\nBefore opening a new issue, it’s helpful to search and see if anyone else has already reported the problem. You can search through a list of issues for all Drycc projects here.\nWrite Documentation We are always looking to improve and expand our documentation. Most docs reside in the drycc/workflow repository. Simply fork the project, update docs and send us a pull request.\nContribute Code We are always looking for help improving the core platform, other workloads, tooling, and test coverage. Interested in contributing code? Let’s chat in the Drycc #community Slack channel. Make sure to check out issues tagged easy fix or help wanted.\nWhen you’re ready to begin writing code, review Design Documents and get your Development Environment set up.\nBy contributing to any Drycc project you agree to its Developer Certificate of Origin (DCO). This document was created by the Linux Kernel community and is a simple statement that you, as a contributor, have the legal right to make the contribution.\nTriage Issues If you don’t have time to code, consider helping with triage. The community will thank you for saving them time by spending some of yours. See Triaging Issues for more info.\nShare your Experience Interact with the community on our user mailing list or live in our Drycc #community Slack channel, where you can chat with other Drycc Workflow users any time of day.\n","categories":"","description":"Interested in contributing to a Drycc project? There are lots of ways to help.","excerpt":"Interested in contributing to a Drycc project? There are lots of ways …","ref":"/docs/contribution-guidelines/overview/","tags":"","title":"Contributor Overview"},{"body":"The Role of Maintainers Maintainers lead the Drycc projects. Their duties include proposing the Roadmap, reviewing and integrating contributions and maintaining the vision of the project.\nOpen Roadmap The Drycc Roadmap is a community document. While Maintainers propose the Roadmap, it gets discussed and refined in Release Planning Meetings.\nContributing to the Roadmap Proposals and issues can be opened by anyone. Every member of the community is welcome to participate in the discussion by providing feedback and/or offering counter-proposals.\nRelease Milestones The Roadmap gets delivered progressively via the Release Schedule. Releases are defined during Release Planning Meetings and managed using GitHub Milestones which track specific deliverables and work-in-progress.\nRelease Planning Meetings Major decisions affecting the Roadmap are discussed during Release Planning Meetings on the first Thursday of each month, aligned with the Release Schedule.\nRelease Planning Meetings are open to the public with access coordinated via the Drycc #community Slack channel. Notes from past meetings are below, along with links to a recording of the entire meeting on YouTube.\nCredits Thanks to Amy Lindburg and our friends at Podman for their inspiration.\n","categories":"","description":"Drycc features a lightweight process that emphasizes openness and ensures every community member can be an integral part of planning for the future.","excerpt":"Drycc features a lightweight process that emphasizes openness and …","ref":"/docs/roadmap/planning-process/","tags":"","title":"Planning Process"},{"body":"","categories":"","description":"Step-by-step guides for deploying your first app and mastering the basics of Drycc.\n","excerpt":"Step-by-step guides for deploying your first app and mastering the …","ref":"/docs/quickstart/","tags":"","title":"Quick Start"},{"body":"Kubernetes Versions Drycc Workflow requires Kubernetes v1.16.15 or later.\nComponents Requirements Drycc uses gateway as a routing implementation, so you have to choose an gateway. We recommend using istio or kong.\nWorkflow supports the use of ACME to manage automatic certificates, cert-manager is also one of the necessary components, if you use cert-manager EAB, you need to set the clusterResourceNamespace to the namespace of drycc.\nWorkflow supports stateful apps. You can create and use them through the ‘drycc volumes’ command. If you want to use this feature, you must have a StorageClass that supports ReadWriteMany.\nWorkflow also supports the OSB API through the ‘drycc resources’ command. If you want to use this function, you need to install service-catalog.\nStorage Requirements A variety of Drycc Workflow components rely on an object storage system to do their work, including storing application slugs, Container images and database logs.\nDrycc Workflow ships with drycc storage by default, which provides in-cluster.\nWorkflow supports Amazon Simple Storage Service (S3), Google Cloud Storage (GCS), OpenShift Swift, and Azure Blob Storage. See configuring object storage for setup instructions.\nResource Requirements When deploying Drycc Workflow, it’s important to provision machines with adequate resources. Drycc is a highly-available distributed system, which means that Drycc components and your deployed applications will move around the cluster onto healthy hosts as hosts leave the cluster for various reasons (failures, reboots, autoscalers, etc.). Because of this, you should have ample spare resources on any machine in your cluster to withstand the additional load of running services for failed machines.\nDrycc Workflow components use about 2.5GB of memory across the cluster, and require approximately 30GB of hard disk space. Because it may need to handle additional load if another one fails, each machine has minimum requirements of:\nAt least 4GB of RAM (more is better) At least 40GB of hard disk space Note that these estimates are for Drycc Workflow and Kubernetes only. Be sure to leave enough spare capacity for your application footprint as well.\nRunning smaller machines will likely result in increased system load and has been known to result in component failures and instability.\n","categories":"","description":"To run Drycc Workflow on a Kubernetes cluster, there are a few requirements to keep in mind.","excerpt":"To run Drycc Workflow on a Kubernetes cluster, there are a few …","ref":"/docs/installing-workflow/system-requirements/","tags":"","title":"Requirements"},{"body":"A Component Fails to Start For information on troubleshooting a failing component, see Troubleshooting with Kubectl.\nAn Application Fails to Start For information on troubleshooting application deployment issues, see Troubleshooting Applications.\nPermission denied (publickey) The most common problem for this issue is the user forgetting to run drycc keys:add or add their private key to their SSH agent. To do so, run ssh-add ~/.ssh/id_rsa and try running git push drycc master again.\nIf you happen get a Could not open a connection to your authentication agent error after trying to run ssh-add command above, you may need to load the SSH agent environment variables issuing the eval \"$(ssh-agent)\" command before.\nOther Issues Running into something not detailed here? Please open an issue or hop into #community on Slack for help!\n","categories":"","description":"Common issues that users have run into when provisioning Workflow are detailed below.","excerpt":"Common issues that users have run into when provisioning Workflow are …","ref":"/docs/troubleshooting/workflow/","tags":"","title":"Troubleshooting Workflow"},{"body":"After you add the Drycc Chart Repository, you can customize the chart using helm inspect values drycc/workflow \u003e values.yaml before using helm install to complete the installation.\nThere are a few ways to customize the respective component:\nIf the value is exposed in the values.yaml file as derived above, one may modify the section of the component to tune these settings. The modified value(s) will then take effect at chart installation or release upgrade time via either of the two respective commands:\n$ helm install drycc oci://registry.drycc.cc/charts/workflow \\ -n drycc \\ --namespace drycc \\ -f values.yaml $ helm upgrade drycc oci://registry.drycc.cc/charts/workflow \\ -n drycc \\ --namespace drycc \\ -f values.yaml If the value hasn’t yet been exposed in the values.yaml file, one may edit the component deployment with the tuned setting. Here we edit the drycc-controller deployment:\n$ kubectl --namespace drycc edit deployment drycc-controller Add/edit the setting via the appropriate environment variable and value under the env section and save. The updated deployment will recreate the component pod with the new/modified setting.\nLastly, one may also fetch and edit the chart as served by version control/the chart repository itself:\n$ helm fetch oci://registry.drycc.cc/charts/workflow --untar $ $EDITOR workflow/charts/controller/templates/controller-deployment.yaml Then run helm install ./workflow --namespace drycc --name drycc to apply the changes, or helm upgrade drycc ./workflow if the cluster is already running.\nSetting Resource limits You can set resource limits to Workflow components by modifying the values.yaml file fetched earlier. This file has a section for each Workflow component. To set a limit to any Workflow component just add limitsCpu, limitsMemory in the section and set them to the appropriate values.\nBelow is an example of how the builder section of values.yaml might look with CPU and memory limits set:\nbuilder: imageOrg: \"drycc\" imagePullPolicy: \"Always\" imageTag: \"canary\" limitsCpu: \"100m\" limitsMemory: \"50Mi\" Customizing the Builder The following environment variables are tunable for the Builder component:\nSetting Description DEBUG Enable debug log output (default: false) BUILDER_POD_NODE_SELECTOR A node selector setting for builder job. As it may sometimes consume a lot of node resources, one may want a given builder job to run in a specific node only, so it won’t affect critical nodes. for example pool:testing,disk:magnetic Customizing the Controller The following environment variables are tunable for the Controller component:\nSetting Description REGISTRATION_MODE set registration to “enabled”, “disabled”, or “admin_only” (default: “admin_only”) GUNICORN_WORKERS number of gunicorn workers spawned to process requests (default: CPU cores * 4 + 1) RESERVED_NAMES a comma-separated list of names which applications cannot reserve for routing (default: “drycc, drycc-builder”) DRYCC_DEPLOY_HOOK_URLS a comma-separated list of URLs to send deploy hooks to. DRYCC_DEPLOY_HOOK_SECRET_KEY a private key used to compute the HMAC signature for deploy hooks. DRYCC_DEPLOY_REJECT_IF_PROCFILE_MISSING rejects a deploy if the previous build had a Procfile but the current deploy is missing it. A 409 is thrown in the API. Prevents accidental process types removal. (default: “false”, allowed values: “true”, “false”) DRYCC_DEPLOY_PROCFILE_MISSING_REMOVE when turned on (default) any missing process type in a Procfile compared to the previous deploy is removed. When set to false will allow an empty Procfile to go through without removing missing process types, note that new images, configs and so on will get updated on all proc types. (default: “true”, allowed values: “true”, “false”) DRYCC_DEFAULT_CONFIG_TAGS set tags for all applications by default, for example: ‘{“role”: “worker”}’. (default: ‘’) KUBERNETES_NAMESPACE_DEFAULT_QUOTA_SPEC set resource quota to application namespace by setting ResourceQuota spec, for example: {\"spec\":{\"hard\":{\"pods\":\"10\"}}}, restrict app owner to spawn more then 10 pods (default: “”, no quota will be applied to namespace) LDAP authentication settings Configuration options for LDAP authentication are detailed here.\nThe following environment variables are available for enabling LDAP authentication of user accounts in the Passport component:\nSetting Description LDAP_ENDPOINT The URI of the LDAP server. If not specified, LDAP authentication is not enabled (default: “”, example: ldap://hostname). LDAP_BIND_DN The distinguished name to use when binding to the LDAP server (default: “”) LDAP_BIND_PASSWORD The password to use with LDAP_BIND_DN (default: “”) LDAP_USER_BASEDN The distinguished name of the search base for user names (default: “”) LDAP_USER_FILTER The name of the login field in the users search base (default: “username”) LDAP_GROUP_BASEDN The distinguished name of the search base for user’s groups names (default: “”) LDAP_GROUP_FILTER The filter for user’s groups (default: “”, example: objectClass=person) Global and per application settings Setting Description DRYCC_DEPLOY_BATCHES the number of pods to bring up and take down sequentially during a scale (default: number of available nodes) DRYCC_DEPLOY_TIMEOUT deploy timeout in seconds per deploy batch (default: 120) IMAGE_PULL_POLICY the kubernetes image pull policy for application images (default: “IfNotPresent”) (allowed values: “Always”, “IfNotPresent”) KUBERNETES_DEPLOYMENTS_REVISION_HISTORY_LIMIT how many revisions Kubernetes keeps around of a given Deployment (default: all revisions) KUBERNETES_POD_TERMINATION_GRACE_PERIOD_SECONDS how many seconds kubernetes waits for a pod to finish work after a SIGTERM before sending SIGKILL (default: 30) See the Deploying Apps guide for more detailed information on those.\nCustomizing the Database The following environment variables are tunable for the Database component:\nSetting Description BACKUP_FREQUENCY how often the database should perform a base backup (default: “12h”) BACKUPS_TO_RETAIN number of base backups the backing store should retain (default: 5) Customizing Fluentbit The following values can be changed in the values.yaml file or by using the --values flag with the Helm CLI.\nKey Description config.service The service section defines the global properties of the service. config.inputs An input section defines a source (related to an input plugin). config.filters A filter section defines a filter (related to a filter plugin) config.outputs The outputs section specify a destination that certain records should follow after a Tag match. For more information about the various variables that can be set please see the fluentbit.\nCustomizing the Logger The following environment variables are tunable for the Logger component:\nSetting Description STORAGE_ADAPTER How to store logs that are sent to the logger. Legal values are “file”, “memory”, and “redis”. (default: “redis”) NUMBER_OF_LINES How many lines to store in the ring buffer (default: 1000) Customizing the Monitor Grafana We have exposed some of the more useful configuration values directly in the chart. This allows them to be set using either the values.yaml file or by using the --set flag with the Helm CLI. You can see these options below:\nSetting Default Value Description user “admin” The first user created in the database (this user has admin privileges) password “admin” Password for the first user. allow_sign_up “true” Allows users to sign up for an account. For a list of other options you can set by using environment variables please see the configuration file in Github.\nTelegraf For a list of configuration values that can be set by using environment variables please see the following configuration file.\nPrometheus You can find a list of values that can be set using environment variables here.\nCustomizing the Registry The Registry component can be tuned by following the drycc/distribution config doc.\nCustomizing the Router The majority of router settings are tunable through annotations, which allows the router to be re-configured with zero downtime post-installation. You can find the list of annotations to tune here.\nThe following environment variables are tunable for the [Router][] component:\nSetting Description POD_NAMESPACE The pod namespace the router resides in. This is set by the Kubernetes downward API. Customizing Workflow Manager The following environment variables are tunable for [Workflow Manager][]:\nSetting Description CHECK_VERSIONS Enables the external version check at https://versions.drycc.info/ (default: “true”) POLL_INTERVAL_SEC The interval when Workflow Manager performs a version check, in seconds (default: 43200, or 12 hours) VERSIONS_API_URL The versions API URL (default: “https://versions-staging.drycc.info”) DOCTOR_API_URL The doctor API URL (default: “https://doctor-staging.drycc.info”) API_VERSION The version number Workflow Manager sends to the versions API (default: “v2”) ","categories":"","description":"Helm Charts are a set of Kubernetes manifests that reflect best practices for deploying an application or service on Kubernetes.","excerpt":"Helm Charts are a set of Kubernetes manifests that reflect best …","ref":"/docs/managing-workflow/tuning-component-settings/","tags":"","title":"Tuning Component Settings"},{"body":"All components are published as a set of container images which can be deployed to any compliant Kubernetes cluster.\nOverview Operators use Helm to configure and install the Workflow components which interface directly with the underlying Kubernetes cluster. Service discovery, container availability and networking are all delegated to Kubernetes, while Workflow provides a clean and simple developer experience.\nPlatform Services Drycc Workflow provides additional functionality to your Kubernetes cluster, including:\nSource to Image Builder which compiles your Application code via Buildpacks or Dockerfiles Cross-Pod Log Aggregation which gathers logs from all of your Application processes Simple REST API which powers the CLI and any external integrations Application release and rollback Authentication and Authorization to Application resources HTTP/HTTPS edge routing for your Applications Kubernetes-Native All platform components and applications deployed via Workflow expect to be running on an existing Kubernetes cluster. This means that you can happily run your Kubernetes-native workloads next to applications that are managed through Drycc Workflow.\nApplication Layout and Edge Routing By default Workflow creates per-application Namespaces and Services so you can easily connect your applications to other on-cluster services through standard Kubernetes mechanisms.\nThe router component is responsible for routing HTTP/s traffic to your Applications as well as proxying git push and platform API traffic.\nBy default, the router component is deployed as a Kubernetes service with type LoadBalancer; which, depending on your configuration, will provision a cloud-native load balancer automatically.\nThe router automatically discovers routable Applications, SSL/TLS certificates and application-specific configurations through the use of Kubernetes annotations. Any changes to router configuration or certificates are applied within seconds.\nTopologies Drycc Workflow no longer dictates a specific topology or server count for your deployment. The platform components will happily run on single-server configurations as well as multi-server production clusters.\n","categories":"","description":"Drycc Workflow is built using a service oriented architecture.","excerpt":"Drycc Workflow is built using a service oriented architecture.","ref":"/docs/understanding-workflow/architecture/","tags":"","title":"Architecture"},{"body":"Drycc supports deploying applications via Cloud Native Buildpacks. Cloud Native Buildpacks are useful if you want to follow cnb’s docs for building applications.\nAdd SSH Key For Buildpack based application deploys via git push, Drycc Workflow identifies users via SSH keys. SSH keys are pushed to the platform and must be unique to each user.\nSee this document for instructions on how to generate an SSH key.\nRun drycc keys:add to upload your SSH key to Drycc Workflow.\n$ drycc keys:add ~/.ssh/id_drycc.pub Uploading id_drycc.pub to drycc... done Read more about adding/removing SSH Keys here.\nPrepare an Application If you do not have an existing application, you can clone an example application that demonstrates the Heroku Buildpack workflow.\n$ git clone https://github.com/drycc/example-go.git $ cd example-go Create an Application Use drycc create to create an application on the Controller.\n$ drycc create Creating application... done, created skiing-keypunch Git remote drycc added Push to Deploy Use git push drycc master to deploy your application.\n$ git push drycc master Counting objects: 75, done. Delta compression using up to 8 threads. Compressing objects: 100% (48/48), done. Writing objects: 100% (75/75), 18.28 KiB | 0 bytes/s, done. Total 75 (delta 30), reused 58 (delta 22) remote: ---\u003e Starting build... but first, coffee! ---\u003e Waiting podman running. ---\u003e Process podman started. ---\u003e Waiting caddy running. ---\u003e Process caddy started. ---\u003e Building pack ---\u003e Using builder registry.drycc.cc/drycc/buildpacks:bookworm Builder 'registry.drycc.cc/drycc/buildpacks:bookworm' is trusted Pulling image 'registry.drycc.cc/drycc/buildpacks:bookworm' Resolving \"drycc/buildpacks\" using unqualified-search registries (/etc/containers/registries.conf) Trying to pull registry.drycc.cc/drycc/buildpacks:bookworm... Getting image source signatures ... ---\u003e Skip generate base layer ---\u003e Python Buildpack ---\u003e Downloading and extracting Python 3.10.0 ---\u003e Installing requirements with pip Collecting Django==3.2.8 Downloading Django-3.2.8-py3-none-any.whl (7.9 MB) Collecting gunicorn==20.1.0 Downloading gunicorn-20.1.0-py3-none-any.whl (79 kB) Collecting sqlparse\u003e=0.2.2 Downloading sqlparse-0.4.2-py3-none-any.whl (42 kB) Collecting pytz Downloading pytz-2021.3-py2.py3-none-any.whl (503 kB) Collecting asgiref\u003c4,\u003e=3.3.2 Downloading asgiref-3.4.1-py3-none-any.whl (25 kB) Requirement already satisfied: setuptools\u003e=3.0 in /layers/drycc_python/python/lib/python3.10/site-packages (from gunicorn==20.1.0-\u003e-r requirements.txt (line 2)) (57.5.0) Installing collected packages: sqlparse, pytz, asgiref, gunicorn, Django Successfully installed Django-3.2.8 asgiref-3.4.1 gunicorn-20.1.0 pytz-2021.3 sqlparse-0.4.2 ---\u003e Generate Launcher ... Build complete. Launching App... ... Done, skiing-keypunch:v2 deployed to Workflow Use 'drycc open' to view this application in your browser To learn more, use 'drycc help' or visit https://www.drycc.cc To ssh://git@drycc.staging-2.drycc.cc:2222/skiing-keypunch.git * [new branch] master -\u003e master $ curl -s http://skiing-keypunch.example.com Powered by Drycc Release v2 on skiing-keypunch-v2-web-02zb9 Because a Buildpacks-style application is detected, the web process type is automatically scaled to 1 on first deploy.\nUse drycc scale web=3 to increase web processes to 3, for example. Scaling a process type directly changes the number of pods running that process.\nIncluded Buildpacks For convenience, a number of buildpacks come bundled with Drycc:\nGo Buildpack Java Buildpack Nodejs Buildpack PHP Buildpack Python Buildpack Ruby Buildpack Rust Buildpack Drycc will cycle through the bin/detect script of each buildpack to match the code you are pushing.\n!!! note If you’re testing against the [Scala Buildpack][], the Builder requires at least 512MB of free memory to execute the Scala Build Tool.\nUsing a Custom Buildpack To use a custom buildpack, you need create a .pack_builder file in your root path app.\n$ tee \u003e .pack_builder \u003c\u003c EOF \u003e registry.drycc.cc/drycc/buildpacks:bookworm \u003e EOF On your next git push, the custom buildpack will be used.\nUsing Private Repositories To pull code from private repositories, set the SSH_KEY environment variable to a private key which has access. Use either the path of a private key file or the raw key material:\n$ drycc config:set SSH_KEY=/home/user/.ssh/id_rsa $ drycc config:set SSH_KEY=\"\"\"-----BEGIN RSA PRIVATE KEY----- (...) -----END RSA PRIVATE KEY-----\"\"\" For example, to use a custom buildpack hosted at a private GitHub URL, ensure that an SSH public key exists in your GitHub settings. Then set SSH_KEY to the corresponding SSH private key and set .pack_builder to the builder image:\n$ tee \u003e .pack_builder \u003c\u003c EOF \u003e registry.drycc.cc/drycc/buildpacks:bookworm \u003e EOF $ git add .buildpack $ git commit -m \"chore(buildpack): modify the pack_builder\" $ git push drycc master Builder selector Which way to build a project conforms to the following principles:\nIf Dockerfile exists in the project, the stack uses container If Procfile exists in the project, the stack uses buildpack If both exist, container is used by default You can also set the DRYCC_STACK to container or buildpack determine which stack to use. ","categories":"","description":"An overview of buildpacks, which are responsible for transforming deployed code into a slug, which can then be executed on a container.","excerpt":"An overview of buildpacks, which are responsible for transforming …","ref":"/docs/applications/using-buildpacks/","tags":"","title":"Using Buildpacks"},{"body":"For example, assuming example.com were a cluster’s domain:\nThe controller should be accessible at drycc.example.com Applications should be accessible (by default) at \u003capplication name\u003e.example.com Given that this is the case, the primary objective in configuring DNS is that traffic for all subdomains of a cluster’s domain be directed to the cluster node(s) hosting the platform’s router component, which is capable of directing traffic within the cluster to the correct endpoints.\nWith a Load Balancer Generally, it is recommended that a [load balancer][] be used to direct inbound traffic to one or more routers. In such a case, configuring DNS is as simple as defining a wildcard record in DNS that points to the load balancer.\nFor example, assuming a domain of example.com:\nAn A record enumerating each of your load balancer(s) IPs (i.e. DNS round-robining) A CNAME record referencing an existing fully-qualified domain name for the load balancer Per AWS’ own documentation, this is the recommended strategy when using AWS Elastic Load Balancers, as ELB IPs may change over time. DNS for any applications using a “custom domain” (a fully-qualified domain name that is not a subdomain of the cluster’s own domain) can be configured by creating a CNAME record that references the wildcard record described above.\nAlthough it is dependent upon your distribution of Kubernetes and your underlying infrastructure, in many cases, the IP(s) or existing fully-qualified domain name of a load balancer can be determined directly using the kubectl tool:\n$ kubectl --namespace=istio-nginx describe service | grep \"LoadBalancer\" LoadBalancer Ingress:\ta493e4e58ea0511e5bb390686bc85da3-1558404688.us-west-2.elb.amazonaws.com The LoadBalancer Ingress field typically describes an existing domain name or public IP(s). Note that if Kubernetes is able to automatically provision a load balancer for you, it does so asynchronously. If the command shown above is issued very soon after Workflow installation, the load balancer may not exist yet.\nWithout a Load Balancer On some platforms (Minikube, for instance), a load balancer is not an easy or practical thing to provision. In these cases, one can directly identify the public IP of a Kubernetes node that is hosting a router pod and use that information to configure the local /etc/hosts file.\nBecause wildcard entries do not work in a local /etc/hosts file, using this strategy may result in frequent editing of that file to add fully-qualified subdomains of a cluster for each application added to that cluster. Because of this a more viable option may be to utilize the xip.io service.\nIn general, for any IP, a.b.c.d, the fully-qualified domain name any-subdomain.a.b.c.d.xip.io will resolve to the IP a.b.c.d. This can be enormously useful.\nTo begin, find the node(s) hosting router instances using kubectl:\n$ kubectl --namespace=istio-ingress describe pod | grep Node: Node: ip-10-0-0-199.us-west-2.compute.internal/10.0.0.199 Node: ip-10-0-0-198.us-west-2.compute.internal/10.0.0.198 The command will display information for every router pod. For each, a node name and IP are displayed in the Node field. If the IPs appearing in these fields are public, any of these may be used to configure your local /etc/hosts file or may be used with xip.io. If the IPs shown are not public, further investigation may be needed.\nYou can list the IP addresses of a node using kubectl:\n$ kubectl describe node ip-10-0-0-199.us-west-2.compute.internal # ... Addresses:\t10.0.0.199,10.0.0.199,54.218.85.175 # ... Here, the Addresses field lists all the node’s IPs. If any of them are public, again, they may be used to configure your local /etc/hosts file or may be used with xip.io.\nTutorial: Configuring DNS with Google Cloud DNS In this section, we’ll describe how to configure Google Cloud DNS for routing your domain name to your Drycc cluster.\nWe’ll assume the following in this section:\nYour Ingress service has a load balancer in front of it. The load balancer need not be cloud based, it just needs to provide a stable IP address or a stable domain name You have the mystuff.com domain name registered with a registrar Replace your domain name with mystuff.com in the instructions to follow Your registrar lets you alter the nameservers for your domain name (most registrars do) Here are the steps for configuring cloud DNS to route to your drycc cluster:\nGet the load balancer IP or domain name If you are on Google Container Engine, you can run kubectl get svc -n istio-ingress and look for the LoadBalancer Ingress column to get the IP address Create a new Cloud DNS Zone (on the console: Networking =\u003e Cloud DNS, then click on Create Zone) Name your zone, and set the DNS name to mystuff.com. (note the . at the end Click on the Create button Click on the Add Record Set button on the resulting page If your load balancer provides a stable IP address, enter the following fields in the resulting form: DNS Name: * Resource Record Type: A TTL: the DNS TTL of your choosing. If you’re testing or you anticipate that you’ll tear down and rebuild many drycc clusters over time, we recommend a low TTL IPv4 Address: The IP that you got in the very first step Click the Create button If your load balancer provides the stable domain name lbdomain.com, enter the following fields in the resulting form: DNS Name: * Resource Record Type: CNAME TTL: the DNS TTL of your choosing. If you’re testing or you anticipate that you’ll tear down and rebuild many drycc clusters over time, we recommend a low TTL Canonical name: lbdomain.com. (note the . a the end) Click on the Create button In your domain registrar, set the nameservers for your mystuff.com domain to the ones under the data column in the NS record on the same page. They’ll often be something like the below (note the trailing . characters). ns-cloud-b1.googledomains.com. ns-cloud-b2.googledomains.com. ns-cloud-b3.googledomains.com. ns-cloud-b4.googledomains.com. Note: If you ever have to re-create your drycc cluster, simply go back to step 6.4 or 7.4 (depending on your load balancer) and change the IP address or domain name to the new value. You may have to wait for the TTL you set to expire.\nTesting To test that traffic reaches its intended destination, a request can be sent to the Drycc controller like so (do not forget the trailing slash!):\ncurl http://drycc.example.com/v2/ Or:\ncurl http://drycc.54.218.85.175.xip.io/v2/ Since such requests require authentication, a response such as the following should be considered an indicator of success:\n{\"detail\":\"Authentication credentials were not provided.\"} ","categories":"","description":"The Drycc Workflow controller and all applications deployed via Workflow are intended (by default) to be accessible as subdomains of the Workflow cluster's domain.","excerpt":"The Drycc Workflow controller and all applications deployed via …","ref":"/docs/managing-workflow/configuring-dns/","tags":"","title":"Configure DNS"},{"body":"Before submitting a pull request which will significantly alter the behavior of any Drycc component, such as a new feature or major refactoring, contributors should first open an issue representing a design document.\nGoals Design documents help ensure project contributors:\nInvolve stakeholders as early as possible in a feature’s development Ensure code changes accomplish the original motivations and design goals Establish clear acceptance criteria for a feature or change Enforce test-driven design methodology and automated test coverage Contents Design document issues should be named Design Doc: \u003cchange description\u003e and contain the following sections:\nGoal This section should briefly describe the proposed change and the motivations behind it. Tests will be written to ensure this design goal is met by the change.\nThis section should also reference a separate GitHub issue tracking the feature or change, which will typically be assigned to a release milestone.\nCode Changes This section should detail the code changes necessary to accomplish the change, as well as the proposed implementation. This should be as detailed as necessary to help reviewers understand the change.\nTests All changes should be covered by automated tests, either unit or integration tests (ideally both). This section should detail how tests will be written to validate that the change accomplishes the design goals and doesn’t introduce any regressions.\nIf a change cannot be sufficiently covered by automated testing, the design should be reconsidered. If there is no test coverage whatsoever for an affected section of code, a separate issue should be filed to integrate automated testing with that section of the codebase.\nThe tests described here also form the acceptance criteria for the change, so that when it’s completed maintainers can merge the pull request after confirming the tests pass CI.\nApproval A design document follows the same merge approval review process as final pull requests do, and maintainers will take extra care to ensure that any stakeholders for the change are included in the discussion and review of the design document.\nOnce the design is accepted, the author can complete the change and submit a pull request for review. The pull request should close both the design document for the change as well as any issues that either track the issue or are closed as a result of the change.\nSee Submitting a Pull Request for more information on pull request and commit message formatting.\n","categories":"","description":"Before submitting a pull request which will significantly alter the behavior of any Drycc component.","excerpt":"Before submitting a pull request which will significantly alter the …","ref":"/docs/contribution-guidelines/design-documents/","tags":"","title":"Design Documents"},{"body":"If you have a pure host, it can be a cloud server, bare metal server, virtual machine, or even your laptop. Then this chapter is very suitable for you.\nOperating Systems Drycc is expected to work on most modern Linux systems. Some OSS have specific requirements:\n(Red Hat/CentOS) Enterprise Linux, they usually use RPM package management. Ubuntu (Desktop/Server/Cloud) Linux, a very popular distribution. Debian GNU Linux, a very pure distribution of opensource software. If you want to add more Linux distribution support, please submit a issue on github or submit PR directly.\nSystem Software Some basic software needs to be installed before installing drycc workflow.\nOS configuration K8s requires a large number of ports. If you are not sure what they are, please close the local firewall or open these ports. At the same time, because k8s you need system time, you need to ensure that the system time is correct.\nInstalling NFSv4 client The command used to install a NFSv4 client differs depending on the Linux distribution.\nFor Debian and Ubuntu, use this command:\n$ apt-get install nfs-common For RHEL, CentOS, and EKS with EKS Kubernetes Worker AMI with AmazonLinux2 image, use this command:\n$ yum install nfs-utils Installing curl For Debian and Ubuntu, use this command:\n$ apt-get install curl For RHEL, CentOS, and EKS with EKS Kubernetes Worker AMI with AmazonLinux2 image, use this command:\n$ yum install curl Hardware Hardware requirements scale based on the size of your deployments. Minimum recommendations are outlined here.\nRAM: 1G Minimum (we recommend at least 2GB) CPU: 1 Minimum This configuration only contains the minimum requirements that can meet the operation.\nDisk Drycc performance depends on the performance of the database. To ensure optimal speed, we recommend using an SSD when possible. Disk performance will vary on ARM devices utilizing an SD card or eMMC.\nDomain Name Drycc needs a root domain name under your full control and points this domain name to the server to be installed. Suppose there is a wildcard domain pointing to the current server to install drycc, which is the name *.dryccdoman.com. We need to set the PLATFORM_DOMAIN environment variables before installation.\n$ export PLATFORM_DOMAIN=dryccdoman.co Of course, if it is a test environment, we can also use nip.io, an IP to domain name service. For example, your host IP is 59.46.3.190, we will get the following domain name 59.46.3.190.nip.io\n$ export PLATFORM_DOMAIN=59.46.3.190.nip.io Install Before installation, please make sure whether your installation environment is a public network. If it is an intranet environment and there is no public IP, you need to disable the automatic certificate.\n$ export CERT_MANAGER_ENABLED=false Then you can use the installation script available at https://www.drycc.cc/install.sh to install drycc as a service on systemd and openrc based systems.\n$ curl -sfL https://www.drycc.cc/install.sh | bash - !!! important If you are in China, you need to use mirror acceleration:\n``` $ curl -sfL https://www.drycc.cc/install.sh | INSTALL_DRYCC_MIRROR=cn bash - ``` Install Node Node can be a simple agent or a server; Server has the function of agent. Multiple servers have high availability, but the number of servers should not exceed 7 at most. There is no limit to the number of agents.\nFirst, check the cluster token of the master. $ cat /var/lib/rancher/k3s/server/node-token K1078e7213ca32bdaabb44536f14b9ce7926bb201f41c3f3edd39975c16ff4901ea::server:33bde27f-ac49-4483-b6ac-f4eec2c6dbfa We assume that the IP address of the cluster master is 192.168.6.240, in that way.\nThen, Set the environment variable: $ export K3S_URL=https://192.168.6.240:6443 $ export K3S_TOKEN=\"K1078e7213ca32bdaabb44536f14b9ce7926bb201f41c3f3edd39975c16ff4901ea::server:33bde27f-ac49-4483-b6ac-f4eec2c6dbfa\" !!! important If you are in China, you need to use mirror acceleration:\n``` $ export INSTALL_DRYCC_MIRROR=cn ``` Join the cluster as server: $ curl -sfL https://www.drycc.cc/install.sh | bash -s - install_k3s_server Join the cluster as agent: $ curl -sfL https://www.drycc.cc/install.sh | bash -s - install_k3s_agent Install Options When using this method to install drycc, the following environment variables can be used to configure the installation:\nENVIRONMENT VARIABLE DESCRIPTION PLATFORM_DOMAIN Required item, specify drycc’s domain name DRYCC_ADMIN_USERNAME Required item, specify drycc’s admin username DRYCC_ADMIN_PASSWORD Required item, specify drycc’s admin password CERT_MANAGER_ENABLED Whether to use automatic certificate. It is false by default CHANNEL By default, stable channel will be installed. You can also specify testing REGISTRY_FILE The config.yaml file path used by k3s containers registry KUBERNETES_SERVICE_HOST Set with the HOST of the loadbalancer that was in front of kube-apiserver KUBERNETES_SERVICE_PORT Set with the PORT of the loadbalancer that was in front of kube-apiserver METALLB_CONFIG_FILE The metallb config file path, layer 2 network is used by default INSTALL_DRYCC_MIRROR Specify the accelerated mirror location. Currently, only cn is supported BUILDER_REPLICAS Number of builder replicas to deploy CONTROLLER_API_REPLICAS Number of controller api replicas to deploy CONTROLLER_CELERY_REPLICAS Number of controller celery replicas to deploy CONTROLLER_WEBHOOK_REPLICAS Number of controller webhook replicas to deploy CONTROLLER_APP_RUNTIME_CLASS RuntimeClass is a feature for selecting the container runtime configuration. CONTROLLER_APP_STORAGE_CLASS StorageClass allocated by drycc volumes; default storageClass is used by default REDIS_REPLICAS Number of redis replicas to deploy REDIS_PERSISTENCE_SIZE The size of the persistence space allocated to redis, which is 5Gi by default REDIS_PERSISTENCE_STORAGE_CLASS StorangeClass of redis; default storangeclass is used by default STORAGE_CSI_STATEFULSET_REPLICAS Number of storage csi controller replicas to deploy STORAGE_MAINNODE_TIPD_REPLICAS Number of storage mainode tipd replicas to deploy STORAGE_MAINNODE_TIPD_PERSISTENCE_SIZE The size of the persistence space allocated to mainnode tipd, which is 10Gi by default STORAGE_MAINNODE_TIPD_PERSISTENCE_STORAGE_CLASS StorangeClass of mainnode tipd; default storangeclass is used by default STORAGE_MAINNODE_WEED_REPLICAS Number of storage mainode weed replicas to deploy STORAGE_MAINNODE_WEED_PREALLOCATE Preallocate disk space for volumes, false is used by default STORAGE_MAINNODE_WEED_SIZE_LIMIT_MB Master stops directing writes to oversized volumes, 30000 is used by default STORAGE_MAINNODE_WEED_DEFAULT_REPLICATION default replication type if not specified, which is 000 by default STORAGE_MAINNODE_WEED_PERSISTENCE_SIZE The size of the persistence space allocated to mainnode weed, which is 10Gi by default STORAGE_MAINNODE_WEED_PERSISTENCE_STORAGE_CLASS StorangeClass of mainnode weed; default storangeclass is used by default STORAGE_METANODE_TIKV_REPLICAS Number of storage metanode tikv replicas to deploy STORAGE_METANODE_TIKV_PERSISTENCE_SIZE The size of the persistence space allocated to metanode tikv, which is 10Gi by default STORAGE_METANODE_TIKV_PERSISTENCE_STORAGE_CLASS StorangeClass of mainnode tikv; default storangeclass is used by default STORAGE_METANODE_WEED_REPLICAS Number of storage metanode weed replicas to deploy STORAGE_METANODE_WEED_PERSISTENCE_SIZE The size of the persistence space allocated to metanode weed, which is 10Gi by default STORAGE_METANODE_WEED_PERSISTENCE_STORAGE_CLASS StorangeClass of mainnode weed; default storangeclass is used by default STORAGE_DATANODE_WEED_REPLICAS Number of storage datanode weed replicas to deploy STORAGE_DATANODE_WEED_PERSISTENCE_SIZE The size of the persistence space allocated to datanode weed, which is 20Gi by default STORAGE_DATANODE_WEED_PERSISTENCE_STORAGE_CLASS StorangeClass of datanode weed; default storangeclass is used by default MONITOR_GRAFANA_PERSISTENCE_SIZE The size of the persistence space allocated to monitor.grafana, which is 5Gi by default MONITOR_GRAFANA_PERSISTENCE_STORAGE_CLASS StorangeClass of monitor grafana; default storangeclass is used by default LOGGER_REPLICAS Number of logger replicas to deploy RABBITMQ_REPLICAS Number of rabbitmq replicas to deploy RABBITMQ_PERSISTENCE_SIZE The size of the persistence space allocated to rabbitmq, which is 5Gi by default RABBITMQ_PERSISTENCE_STORAGE_CLASS StorangeClass of rabbitmq; default storangeclass is used by default DATABASE_REPLICAS Number of database replicas to deploy DATABASE_PERSISTENCE_SIZE The size of the persistence space allocated to database, which is 5Gi by default DATABASE_PERSISTENCE_STORAGE_CLASS StorangeClass of database; default storangeclass is used by default TIMESERIES_REPLICAS Number of timeseries replicas to deploy TIMESERIES_PERSISTENCE_SIZE The size of the persistence space allocated to timeseries, which is 5Gi by default TIMESERIES_PERSISTENCE_STORAGE_CLASS StorangeClass of timeseries; default storangeclass is used by default PASSPORT_REPLICAS Number of passport replicas to deploy REGISTRY_REPLICAS Number of registry replicas to deploy HELMBROKER_REPLICAS Number of helmbroker api replicas to deploy HELMBROKER_CELERY_REPLICAS Number of helmbroker celery replicas to deploy HELMBROKER_PERSISTENCE_SIZE The size of the persistence space allocated to helmbroker, which is 5Gi by default HELMBROKER_PERSISTENCE_STORAGE_CLASS StorangeClass of helmbroker; default storangeclass is used by default PROMETHEUS_SERVER_RETENTION Prometheus data retention period (default if not specified is 15 days) PROMETHEUS_SERVER_PERSISTENCE_SIZE The size of the persistence space allocated to prometheus-server, which is 10Gi by default PROMETHEUS_SERVER_PERSISTENCE_STORAGE_CLASS StorangeClass of prometheus-server; default storangeclass is used by default K3S_DATA_DIR The config of k3s data dir; If not set, the default path is used ACME_SERVER ACME Server url, default use letsencrypt ACME_EAB_KEY_ID The key ID of which your external account binding is indexed by the external account ACME_EAB_KEY_SECRET The key Secret of which your external account symmetric MAC key Since the installation script will install k3s, other environment variables can refer to k3s installation environment variables.\nUninstall If you installed drycc using an installation script, you can uninstall the entire drycc using this script.\n$ curl -sfL https://www.drycc.cc/uninstall.sh | bash - ","categories":"","description":"Install Workflow in pure host, it can be a cloud server, bare metal server, virtual machine, or even your laptop.","excerpt":"Install Workflow in pure host, it can be a cloud server, bare metal …","ref":"/docs/quickstart/install-workflow/","tags":"","title":"Install Workflow"},{"body":"Install Drycc Workflow (Specify gateway) Now that Helm is installed and the repository has been added, install Workflow with a native gateway by running:\n$ helm install drycc oci://registry.drycc.cc/charts/workflow \\ --namespace drycc \\ --set global.gatewayClass=istio \\ --set global.platformDomain=drycc.cc \\ --set builder.service.type=LoadBalancer Of course, if you deploy it on a bare machine, you probably do not have Load Balancer. You need to use NodePort:\n$ helm install drycc oci://registry.drycc.cc/charts/workflow \\ --namespace drycc \\ --set global.gatewayClass=istio \\ --set global.platformDomain=drycc.cc \\ --set builder.service.type=NodePort \\ --set builder.service.nodePort=32222 If you want to use Load Balancer on a bare machine, you can look at metallb\nWhere global.platformDomain is a required parameter that is traditionally not required for Workflow that is explained in the next section. In this example we are using drycc.cc for $hostname.\nHelm will install a variety of Kubernetes resources in the drycc namespace. Wait for the pods that Helm launched to be ready. Monitor their status by running:\n$ kubectl --namespace=drycc get pods You should also notice that several Kubernetes gatewayclass has been installed on your cluster. You can view it by running:\n$ kubectl get gatewayclass --namespace drycc Depending on the order in which the Workflow components initialize, some pods may restart. This is common during the installation: if a component’s dependencies are not yet available, that component will exit and Kubernetes will automatically restart it.\nHere, it can be seen that the controller, builder and registry all took a few loops waiting for storage before they were able to start:\n$ kubectl --namespace=drycc get pods NAME READY STATUS RESTARTS AGE drycc-builder-hy3xv 1/1 Running 5 5m drycc-controller-g3cu8 1/1 Running 5 5m drycc-controller-celery-cmxxn 3/3 Running 0 5m drycc-database-rad1o 1/1 Running 0 5m drycc-logger-fluentbit-1v8uk 1/1 Running 0 5m drycc-logger-fluentbit-esm60 1/1 Running 0 5m drycc-logger-sm8b3 1/1 Running 0 5m drycc-storage-4ww3t 1/1 Running 0 5m drycc-registry-asozo 1/1 Running 1 5m drycc-rabbitmq-0 1/1 Running 0 5m Install a Kubernetes Gateway Now that Workflow has been deployed with the global.gatewayClass , we will need a Kubernetes gateway in place to begin routing traffic.\nHere is an example of how to use istio as an gateway for Workflow. Of course, you are welcome to use any controller you wish.\n$ helm repo add istio https://istio-release.storage.googleapis.com/charts $ helm repo update $ kubectl create namespace istio-system $ helm install istio-base istio/base -n istio-system $ helm install istiod istio/istiod -n istio-system --wait $ kubectl create namespace istio-ingress $ helm install istio-ingress istio/gateway -n istio-ingress --wait Configure DNS User must install drycc and then set up a hostname, and assumes the *.$host convention.\nWe need to point the *.$host record to the public IP address of your gateway. You can get the public IP using the following command. A wildcard entry is necessary here as apps will use the same rule after they are deployed.\n$ kubectl get gateway --namespace drycc NAME CLASS ADDRESS PROGRAMMED AGE gateway istio 138.91.243.152 True 36d If we were using drycc.cc as a hostname, we would need to create the following A DNS records.\nName Type Value *.drycc.cc A 138.91.243.152 Once all of the pods are in the READY state, and *.$host resolves to the external IP found above, the preparation of gateway has been completed!\nAfter installing Workflow, register a user and deploy an application.\nIf your k8s does not provide public network loadblance, you need to install TCP proxy services such as haproxy on machines that can access both internal and external networks, and then expose 80 and 443.\n","categories":"","description":"Choose the gateway provider that best suits your needs and platform.","excerpt":"Choose the gateway provider that best suits your needs and platform.","ref":"/docs/installing-workflow/gateway/","tags":"","title":"Specify Gateway"},{"body":"If help is required getting started with Kubernetes and Drycc Workflow, follow the quickstart guide for assistance.\nPrerequisites Verify the Kubernetes system requirements Install Helm and Drycc Workflow CLI tools Check Your Setup Check that the helm command is available and the version is v2.5.0 or newer.\n$ helm version Client: \u0026version.Version{SemVer:\"v2.5.0\", GitCommit:\"012cb0ac1a1b2f888144ef5a67b8dab6c2d45be6\", GitTreeState:\"clean\"} Server: \u0026version.Version{SemVer:\"v2.5.0\", GitCommit:\"012cb0ac1a1b2f888144ef5a67b8dab6c2d45be6\", GitTreeState:\"clean\"} Choose Your Deployment Strategy Drycc Workflow includes everything it needs to run out of the box. However, these defaults are aimed at simplicity rather than production readiness. Production and staging deployments of Workflow should, at a minimum, use off-cluster storage which is used by Workflow components to store and backup critical data. Should an operator need to completely re-install Workflow, the required components can recover from off-cluster storage. See the documentation for configuring object storage for more details.\nMore rigorous installations would benefit from using outside sources for the following things:\nPostgres - For example AWS RDS. Registry - This includes quay.io, dockerhub, Amazon ECR, and Google GCR. Redis - Such as AWS Elasticache Grafana Gateway Now, workflow requires that gateway and cert-manager must be installed. Any compatible Kubernetes entry controller can be used.\nInstall Drycc Workflow If the version of helm is 3.0 +; you need to create the namespace in advance:\nkubectl create ns drycc If you want to change it, set the variable when using helm.\n$ helm install drycc oci://registry.drycc.cc/charts/workflow \\ --namespace drycc \\ --set builder.imageRegistry=quay.io \\ --set imagebuilder.imageRegistry=quay.io \\ --set controller.imageRegistry=quay.io \\ --set database.imageRegistry=quay.io \\ --set fluentbit.imageRegistry=quay.io \\ --set redis.imageRegistry=quay.io \\ --set rabbitmq.imageRegistry=quay.io \\ --set logger.imageRegistry=quay.io \\ --set storage.imageRegistry=quay.io \\ --set monitor.imageRegistry=quay.io \\ --set registry.imageRegistry=quay.io \\ --set registry-proxy.imageRegistry=quay.io \\ --set global.platformDomain=drycc.cc Helm will install a variety of Kubernetes resources in the drycc namespace. Wait for the pods that Helm launched to be ready. Monitor their status by running:\n$ kubectl --namespace=drycc get pods If it’s preferred to have kubectl automatically update as the pod states change, run (type Ctrl-C to stop the watch):\n$ kubectl --namespace=drycc get pods -w Depending on the order in which the Workflow components initialize, some pods may restart. This is common during the installation: if a component’s dependencies are not yet available, that component will exit and Kubernetes will automatically restart it.\nHere, it can be seen that the controller, builder and registry all took a few loops before they were able to start:\n$ kubectl --namespace=drycc get pods NAME READY STATUS RESTARTS AGE drycc-builder-574483744-l15zj 1/1 Running 0 4m drycc-controller-3953262871-pncgq 1/1 Running 2 4m drycc-controller-celery-cmxxn 3/3 Running 0 4m drycc-database-83844344-47ld6 1/1 Running 0 4m drycc-logger-176328999-wjckx 1/1 Running 4 4m drycc-logger-fluentbit-zxnqb 1/1 Running 0 4m drycc-redis-304849759-1f35p 1/1 Running 0 4m drycc-storage-676004970-nxqgt 1/1 Running 0 4m drycc-monitor-grafana-432627134-lnl2h 1/1 Running 0 4m drycc-monitor-telegraf-wmcmn 1/1 Running 1 4m drycc-registry-756475849-lwc6b 1/1 Running 1 4m drycc-registry-proxy-96c4p 1/1 Running 0 4m drycc-rabbitmq-0 1/1 Running 0 4m Once all of the pods are in the READY state, Drycc Workflow is up and running!\nFor more installation parameters, please check the values.yaml file of workflow.\nAfter installing Workflow, register a user and deploy an application.\nConfigure DNS User must to set up a hostname, and assumes the drycc-builder.$host convention.\nWe need to point the drycc-builder.$host record to the public IP address of your builder. You can get the public IP using the following command. A wildcard entry is necessary here as apps will use the same rule after they are deployed.\n$ kubectl get svc drycc-builder --namespace drycc NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE drycc-builder 10.0.25.3 138.91.243.152 2222:31625/TCP 33m If we were using drycc.cc as a hostname, we would need to create the following A DNS records.\nName Type Value drycc-builder.drycc.cc A 138.91.243.152 Once all of the pods are in the READY state, and drycc-builder.$host resolves to the external IP found above, Workflow is up and running!\nAfter installing Workflow, register a user and deploy an application.\nIf your k8s does not provide public network loadblance, you need to install TCP proxy services such as haproxy on machines that can access both internal and external networks, and then expose 80 and 443.\n","categories":"","description":"This document is aimed at those who have already provisioned a Kubernetes cluster and want to install Drycc Workflow.","excerpt":"This document is aimed at those who have already provisioned a …","ref":"/docs/installing-workflow/workflow/","tags":"","title":"Installing Drycc Workflow"},{"body":"Drycc Workflow Roadmap The Drycc Workflow Roadmap is a community document created as part of the open Planning Process. Each roadmap item describes a high-level capability or grouping of features that are deemed important to the future of Drycc.\nGiven the project’s rapid Release Schedule, roadmap items are designed to provide a sense of direction over many releases.\nInteractive drycc run /bin/bash Provide the ability for developers to launch an interactive terminal session in their application environment.\nRelated issues:\nhttps://github.com/drycc/workflow-cli/issues/28 https://github.com/drycc/drycc/issues/117 Log Streaming Stream application logs via drycc logs -f https://github.com/drycc/drycc/issues/465\nTeams and Permissions Teams and Permissions represents a more flexible permissions model to allow more nuanced control to applications, capabilities and resources on the platform. There have been a number of proposals in this area which need to be reconciled for Drycc Workflow before we begin implementation.\nRelated issues:\nDeploy Keys: https://github.com/drycc/drycc/issues/3875 Teams: https://github.com/drycc/drycc/issues/4173 Fine grained permissions: https://github.com/drycc/drycc/issues/4150 Admins create apps only: https://github.com/drycc/drycc/issues/4052 Admin Certificate Permissions: https://github.com/drycc/drycc/issues/4576#issuecomment-170987223 Monitoring Define and deliver alerts with Kapacitor: https://github.com/drycc/monitor/issues/44 Workflow Addons/Services Developers should be able to quickly and easily provision application dependencies using a services or addon abstraction. https://github.com/drycc/drycc/issues/231\nInbound/Outbound Webhooks Drycc Workflow should be able to send and receive webhooks from external systems. Facilitating integration with third party services like GitHub, Gitlab, Slack, Hipchat.\nSend webhook on platform events: https://github.com/drycc/drycc/issues/1486 (Workflow v2.10) ","categories":"","description":"Drycc roadmap is community driven and managed through GitHub.","excerpt":"Drycc roadmap is community driven and managed through GitHub.","ref":"/docs/roadmap/roadmap/","tags":"","title":"Drycc Workflow Roadmap"},{"body":"This document describes how one can use kubectl to debug any issues with the cluster.\nDiving into the Components Using kubectl, one can inspect the cluster’s current state. When Workflow is installed with helm, Workflow is installed into the drycc namespace. To inspect if Workflow is running, run:\n$ kubectl --namespace=drycc get pods NAME READY STATUS RESTARTS AGE drycc-builder-gqum7 0/1 ContainerCreating 0 4s drycc-controller-h6lk6 0/1 ContainerCreating 0 4s drycc-controller-celery-cmxxn 0/3 ContainerCreating 0 4s drycc-database-56v39 0/1 ContainerCreating 0 4s drycc-logger-fluentbit-xihr1 0/1 Pending 0 2s drycc-logger-grupg 0/1 ContainerCreating 0 3s drycc-storage-c2exb 0/1 Pending 0 3s drycc-monitor-grafana-9ccur 0/1 Pending 0 3s drycc-monitor-telegraf-dc3y3 0/1 Pending 0 2s drycc-registry-5bor6 0/1 Pending 0 3s drycc-rabbitmq-0 0/1 ContainerCreating 0 3s !!! tip To save precious keystrokes, alias kubectl --namespace=drycc to kd so it is easier to type in the future.\nTo fetch the logs of a specific component, use kubectl logs:\n$ kubectl --namespace=drycc logs drycc-controller-h6lk6 system information: Django Version: 1.9.6 Python 3.5.1 addgroup: gid '0' in use Django checks: System check identified no issues (2 silenced). [...] To dive into a running container to inspect its environment, use kubectl exec:\n$ kubectl --namespace=drycc exec -it drycc-database-56v39 gosu postgres psql psql (13.4 (Debian 13.4-1.pgdg100+1)) Type \"help\" for help. postgres=# \\l List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges -------------------+----------+----------+------------+------------+----------------------- drycc_controller | postgres | UTF8 | en_US.utf8 | en_US.utf8 | drycc_passport | postgres | UTF8 | en_US.utf8 | en_US.utf8 | postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 | template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres + | | | | | postgres=CTc/postgres template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres + | | | | | postgres=CTc/postgres (4 rows) postgres=# \\connect drycc_controller You are now connected to database \"drycc_controller\" as user \"postgres\". drycc_controller=# \\dt List of relations Schema | Name | Type | Owner --------+--------------------------------+-------+------------------- public | api_app | table | drycc_controller public | api_build | table | drycc_controller public | api_certificate | table | drycc_controller public | api_config | table | drycc_controller public | api_domain | table | drycc_controller public | api_key | table | drycc_controller public | api_push | table | drycc_controller public | api_release | table | drycc_controller public | auth_group | table | drycc_controller --More-- drycc_controller=# SELECT COUNT(*) from api_app; count ------- 0 (1 row) ","categories":"","description":"Kubernetes provides a command line tool for communicating with a Kubernetes cluster's control plane, using the Kubernetes API.","excerpt":"Kubernetes provides a command line tool for communicating with a …","ref":"/docs/troubleshooting/kubectl/","tags":"","title":"Troubleshooting using Kubectl"},{"body":"","categories":"","description":"Understanding the architecture design of workflow.\n","excerpt":"Understanding the architecture design of workflow.\n","ref":"/docs/understanding-workflow/","tags":"","title":"Understanding Workflow"},{"body":"Workflow use the passport component to create and authorize users, it can config options for LDAP authentication or browse passport web site to register users.\nLogin to Workflow If you already have an account, use drycc login to authenticate against the Drycc Workflow API.\n$ drycc login http://drycc.example.com Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71 Waiting for login... .o.Logged in as drycc Configuration file written to /root/.drycc/client.json Or you can login with username and password $ drycc login http://drycc.example.com –username=demo –password=demo Configuration file written to /root/.drycc/client.json\nLogout from Workflow Logout of an existing controller session using drycc logout.\n$ drycc logout Logged out as drycc Verify Your Session You can verify your client configuration by running drycc whoami.\n$ drycc whoami You are drycc at http://drycc.example.com !!! note Session and client configuration is stored in the ~/.drycc/client.json file.\n","categories":"","description":"Get started on Drycc today","excerpt":"Get started on Drycc today","ref":"/docs/users/registration/","tags":"","title":"Users and Registration"},{"body":"All Workflow components are deployed as services (and associated controllers) in your Kubernetes cluster. If you are interested we have a more detailed exploration of the Workflow architecture.\nAll of the componentry for Workflow is built with composability in mind. If you need to customize one of the components for your specific deployment or need the functionality in your own project we invite you to give it a shot!\nController Project Location: drycc/controller\nThe controller component is an HTTP API server which serves as the endpoint for the drycc CLI. The controller provides all of the platform functionality as well as interfacing with your Kubernetes cluster. The controller persists all of its data to the database component.\nPassport Project Location: drycc/passport\nThe passport component exposes a web API and provide OAuth2 authentication.\nDatabase Project Location: drycc/postgres\nThe database component is a managed instance of PostgreSQL which holds a majority of the platforms state. Backups and WAL files are pushed to object storage via WAL-E. When the database is restarted, backups are fetched and replayed from object storage so no data is lost.\nBuilder Project Location: drycc/builder\nThe builder component is responsible for accepting code pushes via Git and managing the build process of your Application. The builder process is:\nReceives incoming git push requests over SSH Authenticates the user via SSH key fingerprint Authorizes the user’s access to push code to the Application Starts the Application Build phase (see below) Triggers a new Release via the Controller Builder currently supports both buildpack and Dockerfile based builds.\nProject Location: drycc/imagebuilder\nFor Buildpack-based deploys, the builder component will launch a one-shot Job in the drycc namespace. This job runs imagebuilder component which handles default and custom buildpacks (specified by .packbuilder). The completed image is pushed to the managed Container registry on cluster. For more information about buildpacks see using buildpacks.\nUnlike buildpack-based, For Applications which contain a Dockerfile in the root of the repository, it generates a Container image (using the underlying Container engine). For more information see using Dockerfiles.\nObject Storage Project Location: drycc/storage\nAll of the Workflow components that need to persist data will ship them to the object storage that was configured for the cluster.For example, database ships its WAL files, registry stores Container images, and slugbuilder stores slugs.\nWorkflow supports either on or off-cluster storage. For production deployments we highly recommend that you configure off-cluster object storage.\nTo facilitate experimentation, development and test environments, the default charts for Workflow include on-cluster storage via storage.\nIf you also feel comfortable using Kubernetes persistent volumes you may configure storage to use persistent storage available in your environment.\nRegistry Project Location: drycc/registry\nThe registry component is a managed container registry which holds application images generated from the builder component. Registry persists the Container image images to either local storage (in development mode) or to object storage configured for the cluster.\nLogger: fluentbit, logger The logging subsystem consists of two components. Fluentbit handles log shipping and logger maintains a ring-buffer of application logs.\nProject Location: drycc/fluentbit\nFluentbit is deployed to your Kubernetes cluster via Daemon Sets. Fluentbit subscribes to all container logs, decorates the output with Kubernetes metadata and can be configured to drain logs to multiple destinations. By default, Fluentbit ships logs to the logger component, which powers drycc logs.\nProject Location: drycc/logger\nThe logger component receives log streams from fluentbit, collating by Application name. Logger does not persist logs to disk, instead maintaining an in-memory ring buffer. For more information on logger see the project documentation.\nMonitor Project Location: drycc/monitor\nThe monitoring subsystem consists of two components: Telegraf and Grafana.\nTelegraf is the is the metrics collection agent that runs using the daemon set API. It runs on every worker node in the cluster, fetches information about the pods currently running and ships it to Prometheus.\nGrafana is a standalone graphing application. It natively supports Prometheus as a datasource and provides a robust engine for creating dashboards on top of timeseries data. Workflow provides a few dashboards out of the box for monitoring Drycc Workflow and Kubernetes. The dashboards can be used as a starting point for creating more custom dashboards to suit a user’s needs.\nPrometheus Project Location: drycc/prometheus\nPrometheus is a system monitoring and alerting system. It was opensourced by SoundCloud in 2012 and is the second project both to join and to graduate within Cloud Native Computing Foundation after Kubernetes. Prometheus stores all metrics data as time series, i.e metrics information is stored along with the timestamp at which it was recorded, optional key-value pairs called as labels can also be stored along with metrics.\nRabbitmq Project Location: drycc/rabbitmq\nRabbitMQ is the most widely deployed open source message broker. Controller use celery with rabbitMQ to execute the asynchronous task.\nHelmBroker Project Location: drycc/rabbitmq\nHelm Broker is a Service Broker that exposes Helm charts as Service Classes in Service Catalog. To do so, Helm Broker uses the concept of addons. An addon is an abstraction layer over a Helm chart which provides all information required to convert the chart into a Service Class.\nPrometheus Project Location: drycc/rabbitmq\nPrometheus is an open-source systemsmonitoring and alerting toolkit originally built atSoundCloud.\nSee Also Workflow Concepts Workflow Architecture ","categories":"","description":"Workflow is comprised of a number of small, independent services that combine to create a distributed CaaS.","excerpt":"Workflow is comprised of a number of small, independent services that …","ref":"/docs/understanding-workflow/components/","tags":"","title":"Components"},{"body":"What’s New New! format of POST /v2/apps/\u003capp id\u003e/run has changed.\nAuthentication Register a New User Example Request:\nPOST /v2/auth/register/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json { \"username\": \"test\", \"password\": \"opensesame\", \"email\": \"test@example.com\" } Optional Parameters:\n{ \"first_name\": \"test\", \"last_name\": \"testerson\" } Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"id\": 1, \"last_login\": \"2014-10-19T22:01:00.601Z\", \"is_superuser\": true, \"username\": \"test\", \"first_name\": \"test\", \"last_name\": \"testerson\", \"email\": \"test@example.com\", \"is_staff\": true, \"is_active\": true, \"date_joined\": \"2014-10-19T22:01:00.601Z\", \"groups\": [], \"user_permissions\": [] } Log in Example Request:\nPOST /v2/auth/login/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json {\"username\": \"test\", \"password\": \"opensesame\"} Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json {\"token\": \"abc123\"} Cancel Account Example Request:\nDELETE /v2/auth/cancel/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Regenerate Token note\nThis command could require administrative privileges\nExample Request:\nPOST /v2/auth/tokens/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Optional Parameters:\n{ \"username\" : \"test\" \"all\" : \"true\" } Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json {\"token\": \"abc123\"} Change Password Example Request:\nPOST /v2/auth/passwd/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 { \"password\": \"foo\", \"new_password\": \"bar\" } Optional parameters:\n{\"username\": \"testuser\"} note\nUsing the username parameter requires administrative privileges and makes the password parameter optional.\nExample Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Applications List all Applications Example Request:\nGET /v2/apps HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"count\": 1, \"next\": null, \"previous\": null, \"results\": [ { \"created\": \"2014-01-01T00:00:00UTC\", \"id\": \"example-go\", \"owner\": \"test\", \"structure\": {}, \"updated\": \"2014-01-01T00:00:00UTC\", \"url\": \"example-go.example.com\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } ] } Create an Application Example Request:\nPOST /v2/apps/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 Optional parameters:\n{\"id\": \"example-go\"} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"created\": \"2014-01-01T00:00:00UTC\", \"id\": \"example-go\", \"owner\": \"test\", \"structure\": {}, \"updated\": \"2014-01-01T00:00:00UTC\", \"url\": \"example-go.example.com\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Destroy an Application Example Request:\nDELETE /v2/apps/example-go/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 List Application Details Example Request:\nGET /v2/apps/example-go/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"created\": \"2014-01-01T00:00:00UTC\", \"id\": \"example-go\", \"owner\": \"test\", \"structure\": {}, \"updated\": \"2014-01-01T00:00:00UTC\", \"url\": \"example-go.example.com\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Update Application Details Example Request:\nPOST /v2/apps/example-go/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Optional parameters:\n{ \"owner\": \"test\" } Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 1.8.0 Content-Type: application/json Retrieve Application Logs Example Request:\nGET /v2/apps/example-go/logs/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Optional URL Query Parameters:\n?log_lines= Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: text/plain \"16:51:14 drycc[api]: test created initial release\\n\" Run one-off Commands POST /v2/apps/example-go/run/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 {\"command\": \"echo hi\"} Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json {\"exit_code\": 0, \"output\": \"hi\\n\"} Certificates List all Certificates Example Request:\nGET /v2/certs HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"count\": 1, \"next\": null, \"previous\": null, \"results\": [ { \"id\": 22, \"owner\": \"test\", \"san\": [], \"domains\": [], \"created\": \"2016-06-22T22:24:20Z\", \"updated\": \"2016-06-22T22:24:20Z\", \"name\": \"foo\", \"common_name\": \"bar.com\", \"fingerprint\": \"7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0\", \"expires\": \"2017-01-14T23:57:57Z\", \"starts\": \"2016-01-15T23:57:57Z\", \"issuer\": \"/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc\", \"subject\": \"/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc\" } ] } Get Certificate Details Example Request:\nGET /v2/certs/foo HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"id\": 22, \"owner\": \"test\", \"san\": [], \"domains\": [], \"created\": \"2016-06-22T22:24:20Z\", \"updated\": \"2016-06-22T22:24:20Z\", \"name\": \"foo\", \"common_name\": \"bar.com\", \"fingerprint\": \"7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0\", \"expires\": \"2017-01-14T23:57:57Z\", \"starts\": \"2016-01-15T23:57:57Z\", \"issuer\": \"/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc\", \"subject\": \"/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc\" } Create Certificate Example Request:\nPOST /v2/certs/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 { \"name\": \"foo\" \"certificate\": \"-----BEGIN CERTIFICATE-----\", \"key\": \"-----BEGIN RSA PRIVATE KEY-----\" } Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"id\": 22, \"owner\": \"test\", \"san\": [], \"domains\": [], \"created\": \"2016-06-22T22:24:20Z\", \"updated\": \"2016-06-22T22:24:20Z\", \"name\": \"foo\", \"common_name\": \"bar.com\", \"fingerprint\": \"7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0\", \"expires\": \"2017-01-14T23:57:57Z\", \"starts\": \"2016-01-15T23:57:57Z\", \"issuer\": \"/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc\", \"subject\": \"/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc\" } Destroy a Certificate Example Request:\nDELETE /v2/certs/foo HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Attach a Domain to a Certificate Example Request:\nPOST /v2/certs/foo/domain/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 { \"domain\": \"test.com\" } Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Remove a Domain from a Certificate Example Request:\nDELETE /v2/certs/foo/domain/test.com/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Pods List all Pods Example Request:\nGET /v2/apps/example-go/pods/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"count\": 1, \"results\": [ { \"name\": \"go-v2-web-e7dej\", \"release\": \"v2\", \"started\": \"2014-01-01T00:00:00Z\", \"state\": \"up\", \"type\": \"web\" } ] } List all Pods by Type Example Request:\nGET /v2/apps/example-go/pods/web/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"count\": 1, \"results\": [ { \"name\": \"go-v2-web-e7dej\", \"release\": \"v2\", \"started\": \"2014-01-01T00:00:00Z\", \"state\": \"up\", \"type\": \"web\" } ] } Restart All Pods Example Request:\nPOST /v2/apps/example-go/pods/restart/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json [ { \"name\": \"go-v2-web-atots\", \"release\": \"v2\", \"started\": \"2016-04-11T21:07:54Z\", \"state\": \"up\", \"type\": \"web\" } ] Restart Pods by Type Example Request:\nPOST /v2/apps/example-go/pods/web/restart/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json [ { \"name\": \"go-v2-web-atots\", \"release\": \"v2\", \"started\": \"2016-04-11T21:07:54Z\", \"state\": \"up\", \"type\": \"web\" } ] Restart Pods by Type and Name Example Request:\nPOST /v2/apps/example-go/pods/go-v2-web-atots/restart/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json [ { \"name\": \"go-v2-web-atots\", \"release\": \"v2\", \"started\": \"2016-04-11T21:07:54Z\", \"state\": \"up\", \"type\": \"web\" } ] Scale Pods Example Request:\nPOST /v2/apps/example-go/scale/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 {\"web\": 3} Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Configuration List Application Configuration Example Request:\nGET /v2/apps/example-go/config/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"owner\": \"test\", \"app\": \"example-go\", \"values\": { \"PLATFORM\": \"drycc\" }, \"memory\": {}, \"cpu\": {}, \"tags\": {}, \"healthcheck\": {}, \"created\": \"2014-01-01T00:00:00UTC\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Create new Config Example Request:\nPOST /v2/apps/example-go/config/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 {\"values\": {\"HELLO\": \"world\", \"PLATFORM\": \"drycc\"}} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json X-Drycc-Release: 3 { \"owner\": \"test\", \"app\": \"example-go\", \"values\": { \"DRYCC_APP\": \"example-go\", \"DRYCC_RELEASE\": \"v3\", \"HELLO\": \"world\", \"PLATFORM\": \"drycc\" }, \"memory\": {}, \"cpu\": {}, \"tags\": {}, \"healthcheck\": {}, \"created\": \"2014-01-01T00:00:00UTC\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Unset Config Variable Example Request:\nPOST /v2/apps/example-go/config/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 {\"values\": {\"HELLO\": null}} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json X-Drycc-Release: 4 { \"owner\": \"test\", \"app\": \"example-go\", \"values\": { \"DRYCC_APP\": \"example-go\", \"DRYCC_RELEASE\": \"v4\", \"PLATFORM\": \"drycc\" }, \"memory\": {}, \"cpu\": {}, \"tags\": {}, \"healthcheck\": {}, \"created\": \"2014-01-01T00:00:00UTC\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Domains List Application Domains Example Request:\nGET /v2/apps/example-go/domains/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"count\": 1, \"next\": null, \"previous\": null, \"results\": [ { \"app\": \"example-go\", \"created\": \"2014-01-01T00:00:00UTC\", \"domain\": \"example.example.com\", \"owner\": \"test\", \"updated\": \"2014-01-01T00:00:00UTC\" } ] } Add Domain Example Request:\nPOST /v2/apps/example-go/domains/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 {'domain': 'example.example.com'} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"app\": \"example-go\", \"created\": \"2014-01-01T00:00:00UTC\", \"domain\": \"example.example.com\", \"owner\": \"test\", \"updated\": \"2014-01-01T00:00:00UTC\" } Remove Domain Example Request:\nDELETE /v2/apps/example-go/domains/example.example.com HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Builds List Application Builds Example Request:\nGET /v2/apps/example-go/build/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"app\": \"example-go\", \"created\": \"2014-01-01T00:00:00UTC\", \"dockerfile\": \"FROM drycc/slugrunner RUN mkdir -p /app WORKDIR /app ENTRYPOINT [\\\"/runner/init\\\"] ADD slug.tgz /app ENV GIT_SHA 060da68f654e75fac06dbedd1995d5f8ad9084db\", \"image\": \"example-go\", \"owner\": \"test\", \"procfile\": { \"web\": \"example-go\" }, \"sha\": \"060da68f\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Create Application Build Example Request:\nPOST /v2/apps/example-go/build/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 {\"image\": \"drycc/example-go:latest\"} Optional Parameters:\n{ \"procfile\": { \"web\": \"./cmd\" } } Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json X-Drycc-Release: 4 { \"app\": \"example-go\", \"created\": \"2014-01-01T00:00:00UTC\", \"dockerfile\": \"\", \"image\": \"drycc/example-go:latest\", \"owner\": \"test\", \"procfile\": {}, \"sha\": \"\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Releases List Application Releases Example Request:\nGET /v2/apps/example-go/releases/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"count\": 3, \"next\": null, \"previous\": null, \"results\": [ { \"app\": \"example-go\", \"build\": \"202d8e4b-600e-4425-a85c-ffc7ea607f61\", \"config\": \"ed637ceb-5d32-44bd-9406-d326a777a513\", \"created\": \"2014-01-01T00:00:00UTC\", \"owner\": \"test\", \"summary\": \"test changed nothing\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\", \"version\": 3 }, { \"app\": \"example-go\", \"build\": \"202d8e4b-600e-4425-a85c-ffc7ea607f61\", \"config\": \"95bd6dea-1685-4f78-a03d-fd7270b058d1\", \"created\": \"2014-01-01T00:00:00UTC\", \"owner\": \"test\", \"summary\": \"test deployed 060da68\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\", \"version\": 2 }, { \"app\": \"example-go\", \"build\": null, \"config\": \"95bd6dea-1685-4f78-a03d-fd7270b058d1\", \"created\": \"2014-01-01T00:00:00UTC\", \"owner\": \"test\", \"summary\": \"test created initial release\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\", \"version\": 1 } ] } List Release Details Example Request:\nGET /v2/apps/example-go/releases/v2/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"app\": \"example-go\", \"build\": null, \"config\": \"95bd6dea-1685-4f78-a03d-fd7270b058d1\", \"created\": \"2014-01-01T00:00:00UTC\", \"owner\": \"test\", \"summary\": \"test created initial release\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\", \"version\": 1 } Rollback Release Example Request:\nPOST /v2/apps/example-go/releases/rollback/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 {\"version\": 1} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json {\"version\": 5} Keys List Keys Example Request:\nGET /v2/keys/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"count\": 1, \"next\": null, \"previous\": null, \"results\": [ { \"created\": \"2014-01-01T00:00:00UTC\", \"id\": \"test@example.com\", \"owner\": \"test\", \"public\": \"ssh-rsa \u003c...\u003e\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } ] } Add Key to User Example Request:\nPOST /v2/keys/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 { \"id\": \"example\", \"public\": \"ssh-rsa \u003c...\u003e\" } Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"created\": \"2014-01-01T00:00:00UTC\", \"id\": \"example\", \"owner\": \"example\", \"public\": \"ssh-rsa \u003c...\u003e\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Remove Key from User Example Request:\nDELETE /v2/keys/example HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Permissions List Application Permissions note\nThis does not include the app owner.\nExample Request:\nGET /v2/apps/example-go/perms/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"users\": [ \"test\", \"foo\" ] } Create Application Permission Example Request:\nPOST /v2/apps/example-go/perms/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 {\"username\": \"example\"} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Remove Application Permission Example Request:\nDELETE /v2/apps/example-go/perms/example HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 List Administrators Example Request:\nGET /v2/admin/perms/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"count\": 2, \"next\": null \"previous\": null, \"results\": [ { \"username\": \"test\", \"is_superuser\": true }, { \"username\": \"foo\", \"is_superuser\": true } ] } Grant User Administrative Privileges note\nThis command requires administrative privileges\nExample Request:\nPOST /v2/admin/perms HTTP/1.1 Host: drycc.example.com Authorization: token abc123 {\"username\": \"example\"} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Remove User’s Administrative Privileges note\nThis command requires administrative privileges\nExample Request:\nDELETE /v2/admin/perms/example HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Users List all users note\nThis command requires administrative privileges\nExample Request:\nGET /v2/users HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.0 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"count\": 1, \"next\": null, \"previous\": null, \"results\": [ { \"id\": 1, \"last_login\": \"2014-10-19T22:01:00.601Z\", \"is_superuser\": true, \"username\": \"test\", \"first_name\": \"test\", \"last_name\": \"testerson\", \"email\": \"test@example.com\", \"is_staff\": true, \"is_active\": true, \"date_joined\": \"2014-10-19T22:01:00.601Z\", \"groups\": [], \"user_permissions\": [] } ] } ","categories":"","description":"This is the v2.0 REST API for the Controller.","excerpt":"This is the v2.0 REST API for the Controller.","ref":"/docs/reference-guide/controller-api-v2-0/","tags":"","title":"Controller API v2.0"},{"body":"It’s useful to help keep the development team informed about deploys, while it can also be used to integrate different systems together.\nAfter one or more hooks are setup, hook output and errors appear in your application’s logs:\n$ drycc logs ... 2011-03-15T15:07:29-07:00 drycc[api]: Deploy hook sent to http://drycc.rocks Deploy hooks are a generic HTTP hook. An administrator can create and configure multiple deploy hooks by tuning the controller settings via the Helm chart.\nHTTP POST Hook The HTTP deploy hook performs an HTTP POST to a URL. The parameters included in the request are the same as the variables available in the hook message: app, release, release_summary, sha and user. See below for their descriptions:\napp=secure-woodland\u0026release=v4\u0026release_summary=gabrtv%20deployed%35b3726\u0026sha=35b3726\u0026user=gabrtv Optionally, if a deploy hook secret key is added to the controller through tuning the controller settings, a new Authorization header will be present in the POST request. The value of this header is computed as the HMAC hex digest of the request URL, using the secret as the key.\nIn order to authenticate that this request came from Workflow, use the secret key, the full URL and the HMAC-SHA1 hashing algorithm to compute the signature. In Python, that would look something like this:\nimport hashlib import hmac hmac.new(\"my_secret_key\", \"http://drycc.rocks?app=secure-woodland\u0026release=v4\u0026release_summary=gabrtv%20deployed%35b3726\u0026sha=35b3726\u0026user=gabrtv\", digestmod=hashlib.sha1).hexdigest() If the value of the computed HMAC hex digest and the value in the Authorization header are identical, then the request came from Workflow.\n!!! important When computing the signature, ensure that the URL parameters are in alphabetic order. This is critical when computing the cryptographic signature as most web applications don’t care about the order of the HTTP parameters, but the cryptographic signature will not be the same.\n","categories":"","description":"Deploy hooks allow an external service to receive a notification whenever a new version of your app is pushed to Workflow.","excerpt":"Deploy hooks allow an external service to receive a notification …","ref":"/docs/managing-workflow/deploy-hooks/","tags":"","title":"Deploy Hooks"},{"body":"Drycc supports deploying applications via Dockerfiles. A Dockerfile automates the steps for crafting a [Container Image][]. Dockerfiles are incredibly powerful but require some extra work to define your exact application runtime environment.\nAdd SSH Key For Dockerfile based application deploys via git push, Drycc Workflow identifies users via SSH keys. SSH keys are pushed to the platform and must be unique to each user.\nSee this document for instructions on how to generate an SSH key.\nRun drycc keys:add to upload your SSH key to Drycc Workflow.\n$ drycc keys:add ~/.ssh/id_drycc.pub Uploading id_drycc.pub to drycc... done Read more about adding/removing SSH Keys here.\nPrepare an Application If you do not have an existing application, you can clone an example application that demonstrates the Dockerfile workflow.\n$ git clone https://github.com/drycc/helloworld.git $ cd helloworld Dockerfile Requirements In order to deploy Dockerfile applications, they must conform to the following requirements:\nThe Dockerfile must use the EXPOSE directive to expose exactly one port. That port must be listening for an HTTP connection. The Dockerfile must use the CMD directive to define the default process that will run within the container. The Container image must contain bash to run processes. !!! note Note that if you are using a private registry of any kind (gcr or other) the application environment must include a $PORT config variable that matches the EXPOSE’d port, example: drycc config:set PORT=5000. See Configuring Registry for more info.\nCreate an Application Use drycc create to create an application on the Controller.\n$ drycc create Creating application... done, created folksy-offshoot Git remote drycc added Push to Deploy Use git push drycc master to deploy your application.\n$ git push drycc master Counting objects: 13, done. Delta compression using up to 8 threads. Compressing objects: 100% (13/13), done. Writing objects: 100% (13/13), 1.99 KiB | 0 bytes/s, done. Total 13 (delta 2), reused 0 (delta 0) -----\u003e Building Docker image Uploading context 4.096 kB Uploading context Step 0 : FROM drycc/base:latest ---\u003e 60024338bc63 Step 1 : RUN wget -O /tmp/go1.2.1.linux-amd64.tar.gz -q https://go.googlecode.com/files/go1.2.1.linux-amd64.tar.gz ---\u003e Using cache ---\u003e cf9ef8c5caa7 Step 2 : RUN tar -C /usr/local -xzf /tmp/go1.2.1.linux-amd64.tar.gz ---\u003e Using cache ---\u003e 515b1faf3bd8 Step 3 : RUN mkdir -p /go ---\u003e Using cache ---\u003e ebf4927a00e9 Step 4 : ENV GOPATH /go ---\u003e Using cache ---\u003e c6a276eded37 Step 5 : ENV PATH /usr/local/go/bin:/go/bin:$PATH ---\u003e Using cache ---\u003e 2ba6f6c9f108 Step 6 : ADD . /go/src/github.com/drycc/helloworld ---\u003e 94ab7f4b977b Removing intermediate container 171b7d9fdb34 Step 7 : RUN cd /go/src/github.com/drycc/helloworld \u0026\u0026 go install -v . ---\u003e Running in 0c8fbb2d2812 github.com/drycc/helloworld ---\u003e 13b5af931393 Removing intermediate container 0c8fbb2d2812 Step 8 : ENV PORT 80 ---\u003e Running in 9b07da36a272 ---\u003e 2dce83167874 Removing intermediate container 9b07da36a272 Step 9 : CMD [\"/go/bin/helloworld\"] ---\u003e Running in f7b215199940 ---\u003e b1e55ce5195a Removing intermediate container f7b215199940 Step 10 : EXPOSE 80 ---\u003e Running in 7eb8ec45dcb0 ---\u003e ea1a8cc93ca3 Removing intermediate container 7eb8ec45dcb0 Successfully built ea1a8cc93ca3 -----\u003e Pushing image to private registry Launching... done, v2 -----\u003e folksy-offshoot deployed to Drycc http://folksy-offshoot.local3.dryccapp.com To learn more, use `drycc help` or visit https://www.drycc.cc To ssh://git@local3.dryccapp.com:2222/folksy-offshoot.git * [new branch] master -\u003e master $ curl -s http://folksy-offshoot.local3.dryccapp.com Welcome to Drycc! See the documentation at http://docs.drycc.cc/ for more information. Because a Dockerfile application is detected, the web process type is automatically scaled to 1 on first deploy.\nUse drycc scale web=3 to increase web processes to 3, for example. Scaling a process type directly changes the number of containers running that process.\nContainer Build Arguments As of Workflow v2.13.0, users can inject their application config into the Container image using Container build arguments. To opt into this, users must add a new environment variable to their application:\n$ drycc config:set DRYCC_DOCKER_BUILD_ARGS_ENABLED=1 Every environment variable set with drycc config:set will then be available for use inside the user’s Dockerfile. For example, if a user runs drycc config:set POWERED_BY=Workflow, the user can utilize that build argument in their Dockerfile:\nARG POWERED_BY RUN echo \"Powered by $POWERED_BY\" \u003e /etc/motd ","categories":"","description":"Drycc Container Registry allows you to deploy your Docker-based app to Drycc. Both Common Runtime and Private Spaces are supported.","excerpt":"Drycc Container Registry allows you to deploy your Docker-based app to …","ref":"/docs/applications/using-dockerfiles/","tags":"","title":"Using Dockerfiles"},{"body":"In this guide, we walk you through the process of setting up a development environment that is suitable for hacking on most Drycc components.\nWe try to make it simple to hack on Drycc components. However, there are necessarily several moving pieces and some setup required. We welcome any suggestions for automating or simplifying this process.\n!!! note The Drycc team is actively engaged in containerizing Go and Python based development environments tailored specifically for Drycc development in order to minimize the setup required. This work is ongoing. Refer to the drycc/router project for a working example of a fully containerized development environment.\nIf you’re just getting into the Drycc codebase, look for GitHub issues with the label easy-fix. These are more straightforward or low-risk issues and are a great way to become more familiar with Drycc.\nPrerequisites In order to successfully compile and test Drycc binaries and build Container images of Drycc components, the following are required:\ngit Go 1.5 or later, with support for compiling to linux/amd64 glide golint shellcheck Podman (in a non-Linux environment, you will additionally want [Podman Machine][machine]) For drycc/controller, in particular, you will also need:\nPython 2.7 or later (with pip) virtualenv (sudo pip install virtualenv) In most cases, you should simply install according to the instructions. There are a few special cases, though. We cover these below.\nConfiguring Go If your local workstation does not support the linux/amd64 target environment, you will have to install Go from source with cross-compile support for that environment. This is because some of the components are built on your local machine and then injected into a container.\nHomebrew users can just install with cross compiling support:\n$ brew install go --with-cc-common It is also straightforward to build Go from source:\n$ sudo su $ curl -sSL https://golang.org/dl/go1.5.src.tar.gz | tar -v -C /usr/local -xz $ cd /usr/local/go/src $ # compile Go for our default platform first, then add cross-compile support $ ./make.bash --no-clean $ GOOS=linux GOARCH=amd64 ./make.bash --no-clean Once you can compile to linux/amd64, you should be able to compile Drycc components as normal.\nFork the Repository Once the prerequisites have been met, we can begin to work with Drycc components.\nBegin at Github by forking whichever Drycc project you would like to contribute to, then clone that fork locally. Since Drycc is predominantly written in Go, the best place to put it is under $GOPATH/src/github.com/drycc/.\n$ mkdir -p $GOPATH/src/github.com/drycc $ cd $GOPATH/src/github.com/drycc $ git clone git@github.com:\u003cusername\u003e/\u003ccomponent\u003e.git $ cd \u003ccomponent\u003e !!! note By checking out the forked copy into the namespace github.com/drycc/\u003ccomponent\u003e, we are tricking the Go toolchain into seeing our fork as the “official” source tree.\nIf you are going to be issuing pull requests to the upstream repository from which you forked, we suggest configuring Git such that you can easily rebase your code to the upstream repository’s main branch. There are various strategies for doing this, but the most common is to add an upstream remote:\n$ git remote add upstream https://github.com/drycc/\u003ccomponent\u003e.git For the sake of simplicity, you may want to point an environment variable to your Drycc code - the directory containing one or more Drycc components:\n$ export DRYCC=$GOPATH/src/github.com/drycc Throughout the rest of this document, $DRYCC refers to that location.\nAlternative: Forking with a Pushurl A number of Drycc contributors prefer to pull directly from drycc/\u003ccomponent\u003e, but push to \u003cusername\u003e/\u003ccomponent\u003e. If that workflow suits you better, you can set it up this way:\n$ git clone git@github.com:drycc/\u003ccomponent\u003e.git $ cd drycc $ git config remote.origin.pushurl git@github.com:\u003cusername\u003e/\u003ccomponent\u003e.git In this setup, fetching and pulling code will work directly with the upstream repository, while pushing code will send changes to your fork. This makes it easy to stay up to date, but also make changes and then issue pull requests.\nMake Your Changes With your development environment set up and the code you wish to work on forked and cloned, you can begin making your changes.\nTest Your Changes Drycc components each include a comprehensive suite of automated tests, mostly written in Go. See testing for instructions on running the tests.\nDeploying Your Changes Although writing and executing tests are critical to ensuring code quality, most contributors will also want to deploy their changes to a live environment, whether to make use of those changes or to test them further. The remainder of this section documents the procedure for running officially released Drycc components in a development cluster and replacing any one of those with your customizations.\nRunning a Kubernetes Cluster for Development To run a Kubernetes cluster locally or elsewhere to support your development activities, refer to Drycc installation instructions here.\nUsing a Development Registry To facilitate deploying Container images containing your changes to your Kubernetes cluster, you will need to make use of a Container registry. This is a location to where you can push your custom-built images and from where your Kubernetes cluster can retrieve those same images.\nIf your development cluster runs locally (in Minikube, for instance), the most efficient and economical means of achieving this is to run a Container registry locally as a Container container.\nTo facilitate this, most Drycc components provide a make target to create such a registry:\n$ make dev-registry In a Linux environment, to begin using the registry:\nexport DRYCC_REGISTRY=\u003cIP of the host machine\u003e:5000 In non-Linux environments:\nexport DRYCC_REGISTRY=\u003cIP of the drycc Container Machine VM\u003e:5000 If your development cluster runs on a cloud provider such as Google Container Engine, a local registry such as the one above will not be accessible to your Kubernetes nodes. In such cases, a public registry such as [DockerHub][dh] or quay.io will suffice.\nTo use DockerHub for this purpose, for instance:\n$ export DRYCC_REGISTRY=\"registry.drycc.cc\" $ export IMAGE_PREFIX=\u003cyour DockerHub username\u003e To use quay.io:\n$ export DRYCC_REGISTRY=quay.io $ export IMAGE_PREFIX=\u003cyour quay.io username\u003e Note the importance of the trailing slash.\nDev / Deployment Workflow With a functioning Kubernetes cluster and the officially released Drycc components installed onto it, deployment and further testing of any Drycc component you have made changes to is facilitated by replacing the officially released component with a custom built image that contains your changes. Most Drycc components include Makefiles with targets specifically intended to facilitate this workflow with minimal friction.\nIn the general case, this workflow looks like this:\nUpdate source code and commit your changes using git Use make build to build a new Container image Use make dev-release to generate Kubernetes manifest(s) Use make deploy to restart the component using the updated manifest This can be shortened to a one-liner using just the deploy target:\n$ make deploy Useful Commands Once your customized Drycc component has been deployed, here are some helpful commands that will allow you to inspect your cluster and to troubleshoot, if necessary:\nSee All Drycc Pods $ kubectl --namespace=drycc get pods Describe a Pod This is often useful for troubleshooting pods that are in pending or crashed states:\n$ kubectl --namespace=drycc describe -f \u003cpod name\u003e Tail Logs $ kubectl --namespace=drycc logs -f \u003cpod name\u003e Django Shell Specific to drycc/controller\n$ kubectl --namespace=drycc exec -it \u003cpod name\u003e -- python manage.py shell Have commands other Drycc contributors might find useful? Send us a PR!\nPull Requests Satisfied with your changes? Share them!\nPlease read Submitting a Pull Request. It contains a checklist of things you should do when proposing a change to any Drycc component.\n","categories":"","description":"This document is for developers who are interested in working directly on the Drycc codebase.","excerpt":"This document is for developers who are interested in working directly …","ref":"/docs/contribution-guidelines/development-environment/","tags":"","title":"Development Environment"},{"body":"Drycc Workflow Client CLI The Drycc command-line interface (CLI), lets you interact with Drycc Workflow. Use the CLI to create and configure and manage applications.\nInstall the drycc client for Linux or Mac OS X with:\n$ curl -sfL https://www.drycc.cc/install-cli.sh | bash - !!! important Users in Chinese mainland can use the following methods to speed up installation:\n``` $ curl -sfL https://www.drycc.cc/install-cli.sh | INSTALL_DRYCC_MIRROR=cn bash - ``` Others please visit: https://github.com/drycc/workflow-cli/releases\nThe installer places the drycc binary in your current directory, but you should move it somewhere in your $PATH:\n$ sudo ln -fs $PWD/drycc /usr/local/bin/drycc or:\n$ sudo mv $PWD/drycc /usr/local/bin/drycc Check your work by running drycc version:\n$ drycc version v1.1.0 Update workflow cli to latest release.\ndrycc update !!! note Note that version numbers may vary as new releases become available\n","categories":"","description":"How to download, install Drycc CLI tools.","excerpt":"How to download, install Drycc CLI tools.","ref":"/docs/quickstart/install-cli-tools/","tags":"","title":"Drycc Workflow Client CLI"},{"body":"","categories":"","description":"Deploying Drycc on a Kubernetes Cluster.\n","excerpt":"Deploying Drycc on a Kubernetes Cluster.\n","ref":"/docs/installing-workflow/","tags":"","title":"Installing To Kubenetes"},{"body":"Drycc uses a continuous delivery approach for creating releases. Every merged commit that passes testing results in a deliverable that can be given a semantic version tag and shipped.\nThe master git branch of a project should always work. Only changes considered ready to be released publicly are merged.\nComponents Release as Needed Drycc components release new versions as often as needed. Fixing a high priority bug requires the project maintainer to create a new patch release. Merging a backward-compatible feature implies a minor release.\nBy releasing often, each component release becomes a safe and routine event. This makes it faster and easier for users to obtain specific fixes. Continuous delivery also reduces the work necessary to release a product such as Drycc Workflow, which integrates several components.\n“Components” applies not just to Drycc Workflow projects, but also to development and release tools, to Container base images, and to other Drycc projects that do semantic version releases.\nSee “How to Release a Component” for more detail.\nWorkflow Releases Each Month Drycc Workflow has a regular, public release cadence. From v2.8.0 onward, new Workflow feature releases arrive on the first Thursday of each month. Patch releases are created at any time, as needed. GitHub milestones are used to communicate the content and timing of major and minor releases, and longer-term planning is visible at the Roadmap.\nWorkflow release timing is not linked to specific features. If a feature is merged before the release date, it is included in the next release.\nSee “How to Release Workflow” for more detail.\nSemantic Versioning Drycc releases comply with semantic versioning, with the “public API” broadly defined as:\nREST, gRPC, or other API that is network-accessible Library or framework API intended for public use “Pluggable” socket-level protocols users can redirect CLI commands and output formats In general, changes to anything a user might reasonably link to, customize, or integrate with should be backward-compatible, or else require a major release. Drycc users can be confident that upgrading to a patch or to a minor release will not break anything.\nHow to Release a Component Most Drycc projects are “components” which produce a Container image or binary executable as a deliverable. This section leads a maintainer through creating a component release.\nStep 1: Update Code and Run the Release Tool Major or minor releases should happen on the master branch. Patch releases should check out the previous release tag and cherry-pick specific commits from master.\nNote: if a patch release, the release artifact will have to be manually promoted by triggering the component-promote job with the following values:\nCOMPONENT_NAME=\u003ccomponent name\u003e COMPONENT_SHA=\u003cpatch commit sha\u003e Make sure you have the dryccrel release tool in your search $PATH.\nRun dryccrel release once with a fake semver tag to proofread the changelog content. (If HEAD of master is not what is intended for the release, add the --sha flag as described in dryccrel release --help.)\n$ dryccrel release controller v0.0.0 Doing a dry run of the component release... skipping commit 943a49267eeb28546819a266654806cfcbae0e38 Creating changelog for controller with tag v2.8.1 through commit 943a49267eeb28546819a266654806cfcbae0e38 ### v2.8.1 -\u003e v0.0.0 #### Fixes - [`615b834`](https://github.com/drycc/controller/commit/615b834f39cb68a854cc1f1e2f0f82d862ea2731) boot: Ensure DRYCC_DEBUG==true for debug output Based on the changelog content, determine whether the component deserves a minor or patch release. Run the command again with that semver tag and --dry-run=false. You will still be asked for confirmation before the release is created:\n$ dryccrel release controller v2.8.2 --dry-run=false skipping commit 943a49267eeb28546819a266654806cfcbae0e38 Creating changelog for controller with tag v2.8.1 through commit 943a49267eeb28546819a266654806cfcbae0e38 ### v2.8.1 -\u003e v2.8.2 #### Fixes - [`615b834`](https://github.com/drycc/controller/commit/615b834f39cb68a854cc1f1e2f0f82d862ea2731) boot: Ensure DRYCC_DEBUG==true for debug output Please review the above changelog contents and ensure: 1. All intended commits are mentioned 2. The changes agree with the semver release tag (major, minor, or patch) Create release for Drycc Controller v2.8.2? [y/n]: y New release is available at https://github.com/drycc/controller/releases/tag/v2.8.2 Step 2: Verify the Component is Available Tagging the component (see Step 1) starts a CI job that eventually results in an artifact being made available for public download. Please see the CI flow diagrams for details.\nDouble-check that the artifact is available, either by a podman pull command or by running the appropriate installer script.\nIf the artifact can’t be downloaded, ensure that its CI release jobs are still in progress, or fix whatever issue arose in the pipeline. For example, the master merge pipeline may have failed to promote the :git-abc1d23 candidate image and needs to be restarted with that component and commit.\nIf the component has a correlating Kubernetes Helm chart, this chart will also be packaged, signed and uploaded to its production chart repo. Please verify it can be fetched (and verified):\n$ helm fetch oci://registry.drycc.cc/charts/controller --version 1.0.0 Verification: \u0026{0xc4207ec870 sha256:026e766e918ff28d2a7041bc3d560d149ee7eb0cb84165c9d9d00a3045ff45c3 controller-v1.0.1.tgz} How to Release Workflow Drycc Workflow integrates multiple component releases together with a Kubernetes Helm chart deliverable. This section leads a maintainer through creating a Workflow release.\nStep 1: Set Environment Variables Export two environment variables that will be used in later steps:\nexport WORKFLOW_RELEASE=v2.17.0 WORKFLOW_PREV_RELEASE=v2.16.0 # for example Step 2: Tag Supporting Repositories Some Workflow components not in the Helm chart must also be tagged in sync with the release. Follow the component release process above and ensure that these components are tagged:\ndrycc/workflow-cli drycc/workflow-e2e The version number for drycc/workflow-cli should always match the overall Workflow version number.\nStep 3: Create Helm Chart To create and stage a release candidate chart for Workflow, we will build the workflow-chart-stage job with the following parameters:\nRELEASE_TAG=$WORKFLOW_RELEASE\nThis job will gather all of the latest component release tags and use these to specify the versions of all component charts. It will then package the Workflow chart, upload it to the staging chart repo and kick off an e2e run against said chart.\nStep 4: Manual Testing Now it’s time to go above and beyond current CI tests. Create a testing matrix spreadsheet (copying from the previous document is a good start) and sign up testers to cover all permutations.\nTesters should pay special attention to the overall user experience, make sure upgrading from earlier versions is smooth, and cover various storage configurations and Kubernetes versions and infrastructure providers.\nWhen showstopper-level bugs are found, the process is as follows:\nCreate a component PR that fixes the bug. Once the PR passes and is reviewed, merge it and do a new component release Trigger the same workflow-chart-stage job as mentioned in Step 3 to upload the newly-generated Workflow release candidate chart to staging. Step 5: Release the Chart When testing has completed without uncovering any new showstopper bugs, kick off the workflow-chart-release job with the following parameter:\nRELEASE_TAG=$WORKFLOW_RELEASE\nThis job will copy the release candidate chart (now approved by CI and manual testing) from the staging repo to the production repo, signing it if it has not done so already.\nStep 6: Assemble Master Changelog Each component already updated its release notes on GitHub with CHANGELOG content. We’ll now generate the master changelog for the Workflow chart, consisting of all component and auxilliary repo changes.\nWe’ll employ the requirements.lock file from the WORKFLOW_PREV_RELEASE chart, as well as a repo-to-chart-name mapping file, this time invoking dryccrel changelog global to get all component changes between the chart versions existing in the WORKFLOW_PREV_RELEASE chart and the most recent releases existing in GitHub. (Therefore, if there are any unreleased commits in a component repo, they will not appear here):\nhelm fetch --untar oci://registry.drycc.cc/charts/workflow --version $WORKFLOW_PREV_RELEASE dryccrel changelog global workflow/requirements.lock map.json \u003e changelog-$WORKFLOW_RELEASE.md This master changelog should then be placed into a single gist. The file will also be added to the documentation update PR created in the next step.\nStep 7: Update Documentation Create a new pull request at drycc/workflow that updates version references to the new release. Use git grep $WORKFLOW_PREV_RELEASE to find any references, but be careful not to change CHANGELOG.md.\nPlace the $WORKFLOW_RELEASE master changelog generated in Step 7 in the changelogs directory. Make sure to add a header to the page to make it clear that this is for a Workflow release, e.g.:\n## Workflow v2.16.0 -\u003e v2.17.0 Once the PR has been reviewed and merged, do a component release of drycc/workflow itself. The version number for drycc/workflow should always match the overall Workflow version number.\nStep 8: Close GitHub Milestones Create a pull request at seed-repo to close the release milestone and create the next one. When changes are merged to seed-repo, milestones on all relevant projects will be updated. If there are open issues attached to the milestone, move them to the next upcoming milestone before merging the pull request.\nMilestones map to Drycc Workflow releases in drycc/workflow. These milestones do not correspond to individual component release tags.\nStep 9: Release Workflow CLI Stable Now that the $WORKFLOW_RELEASE version of Workflow CLI has been vetted, we can push stable artifacts based on this version.\nKick off https://ci.drycc.info/job/workflow-cli-build-stable/ with the TAG build parameter of $WORKFLOW_RELEASE and then verify stable artifacts are available and appropriately updated after the job completes:\n$ curl -sfL https://www.drycc.cc/install-cli.sh | bash - $ ./drycc version # (Should show $WORKFLOW_RELEASE) Step 10: Let Everyone Know Let the rest of the team know they can start blogging and tweeting about the new Workflow release. Post a message to the #company channel on Slack. Include a link to the released chart and to the master CHANGELOG:\n@here Drycc Workflow v2.17.0 is now live! Master CHANGELOG: https://drycc.info/docs/workflow/changelogs/v2.17.0/ You’re done with the release. Nice job!\n","categories":"","description":"Drycc's release model allows applications to record and roll back to previous versions.","excerpt":"Drycc's release model allows applications to record and roll back to …","ref":"/docs/roadmap/releases/","tags":"","title":"Releases"},{"body":"For Dockerfile and Buildpack based application deploys via git push, Drycc Workflow identifies users via SSH keys. SSH keys are pushed to the platform and must be unique to each user. Users may have multiple SSH keys as needed.\nGenerate an SSH Key If you do not already have an SSH key or would like to create a new key for Drycc Workflow, generate a new key using ssh-keygen:\n$ ssh-keygen -f ~/.ssh/id_drycc -t rsa Generating public/private rsa key pair. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /Users/admin/.ssh/id_drycc. Your public key has been saved in /Users/admin/.ssh/id_drycc.pub. The key fingerprint is: 3d:ac:1f:f4:83:f7:64:51:c1:7e:7f:80:b6:70:36:c9 admin@plinth-23437.local The key's randomart image is: +--[ RSA 2048]----+ | .. | | ..| | . o. .| | o. E .o.| | S == o..o| | o +. .o| | . o + o .| | . o = | | . . | +-----------------+ $ ssh-add ~/.ssh/id_drycc Identity added: /Users/admin/.ssh/id_drycc (/Users/admin/.ssh/id_drycc) Adding and Removing SSH Keys By publishing the public half of your SSH key to Drycc Workflow the component responsible for receiving git push will be able to authenticate the user and ensure that they have access to the destination application.\n$ drycc keys:add ~/.ssh/id_drycc.pub Uploading id_drycc.pub to drycc... done You can always view the keys associated with your user as well:\n$ drycc keys:list ID OWNER KEY admin@plinth-23437.local admin ssh-rsa abc AAAAB3Nz...3437.local admin@subgenius.local admin ssh-rsa 123 AAAAB3Nz...nius.local Remove keys by their name:\n$ drycc keys:remove admin@plinth-23437.local Removing admin@plinth-23437.local SSH Key... don ","categories":"","description":"Create, manage, and upload SSH keys to Drycc for use in deploying and connecting to applications.","excerpt":"Create, manage, and upload SSH keys to Drycc for use in deploying and …","ref":"/docs/users/ssh-keys/","tags":"","title":"Users and SSH Keys"},{"body":"Application has a Dockerfile, but a Buildpack Deployment Occurs When you deploy an application to Workflow using git push drycc master and the Builder attempts to deploy using the Buildpack workflow, check the following steps:\nAre you deploying the correct project? Are you pushing the correct git branch (git push drycc \u003cbranch\u003e)? Is the Dockerfile in the project’s root directory? Have you committed the Dockerfile to the project? Application was Deployed, but is Failing to Start If you deployed your application but it is failing to start, you can use drycc logs to check why the application fails to boot. Sometimes, the application container may fail to boot without logging any information about the error. This typically occurs when the healthcheck configured for the application fails. In this case, you can start by troubleshooting using kubectl. You can inspect the application’s current state by examining the pod deployed in the application’s namespace. To do that, run\n$ kubectl --namespace=myapp get pods NAME READY STATUS RESTARTS AGE myapp-web-1585713350-3brbo 0/1 CrashLoopBackOff 2 43s We can then describe the pod and determine why it is failing to boot:\nEvents: FirstSeen LastSeen Count From SubobjectPath Type Reason Message --------- -------- ----- ---- ------------- -------- ------ ------- 43s 43s 1 {default-scheduler } Normal Scheduled Successfully assigned myapp-web-1585713350-3brbo to kubernetes-node-1 41s 41s 1 {kubelet kubernetes-node-1} spec.containers{myapp-web} Normal Created Created container with container id b86bd851a61f 41s 41s 1 {kubelet kubernetes-node-1} spec.containers{myapp-web} Normal Started Started container with container id b86bd851a61f 37s 35s 1 {kubelet kubernetes-node-1} spec.containers{myapp-web} Warning Unhealthy Liveness probe failed: Get http://10.246.39.13:8000/healthz: dial tcp 10.246.39.13:8000: getsockopt: connection refused In this instance, we set the healthcheck initial delay timeout for the application at 1 second, which is too aggressive. The application needs some time to set up the API server after the container has booted. By increasing the healthcheck initial delay timeout to 10 seconds, the application is able to boot and is responding correctly.\nSee Custom Health Checks for more information on how to customize the application’s health checks to better suit the application’s needs.\n","categories":"","description":"This document describes how one can troubleshoot common issues when deploying or debugging an application that fails to start or deploy.","excerpt":"This document describes how one can troubleshoot common issues when …","ref":"/docs/troubleshooting/applications/","tags":"","title":"Troubleshooting Applications"},{"body":"Drycc Workflow ships with Storage by default, which provides in-cluster.\nConfiguring off-cluster Object Storage Every component that relies on object storage uses two inputs for configuration:\nYou must use object storage services that are compatible with S3 API Access credentials stored as a Kubernetes secret named storage-creds The helm chart for Drycc Workflow can be easily configured to connect Workflow components to off-cluster object storage. Drycc Workflow currently supports Google Compute Storage, Amazon S3, Azure Blob Storage and OpenStack Swift Storage.\nStep 1: Create storage buckets Create storage buckets for each of the Workflow subsystems: builder, registry, and database.\nDepending on your chosen object storage you may need to provide globally unique bucket names. If you are using S3, use hyphens instead of periods in the bucket names. Using periods in the bucket name will cause an ssl certificate validation issue with S3.\nIf you provide credentials with sufficient access to the underlying storage, Workflow components will create the buckets if they do not exist.\nStep 2: Generate storage credentials If applicable, generate credentials that have create and write access to the storage buckets created in Step 1.\nIf you are using AWS S3 and your Kubernetes nodes are configured with appropriate IAM API keys via InstanceRoles, you do not need to create API credentials. Do, however, validate that the InstanceRole has appropriate permissions to the configured buckets!\nStep 3: Configure Workflow Chart Operators should configure object storage by editing the Helm values file before running helm install. To do so:\nFetch the Helm values by running helm inspect values oci://registry.drycc.cc/charts/workflow \u003e values.yaml Update the global/storage parameter to reference the platform you are using, e.g. s3, azure, gcs, or swift Find the corresponding section for your storage type and provide appropriate values including region, bucket names, and access credentials. Save your changes. !!! note All values will be automatically (base64) encoded except the key_json values under gcs/gcr. These must be base64-encoded. This is to support cleanly passing said encoded text via helm --set cli functionality rather than attempting to pass the raw JSON data. For example:\n$ helm install drycc oci://registry.drycc.cc/charts/workflow \\ --namespace drycc \\ --set global.platformDomain=youdomain.com --set global.storage=gcs,gcs.key_json=\"$(cat /path/to/gcs_creds.json | base64 -w 0)\" You are now ready to run helm install drycc oci://registry.drycc.cc/charts/workflow --namespace drycc -f values.yaml using your desired object storage.\n","categories":"","description":"A variety of Drycc Workflow components rely on an object storage system to do their work including storing application slugs, Container images and database logs.","excerpt":"A variety of Drycc Workflow components rely on an object storage …","ref":"/docs/installing-workflow/configuring-object-storage/","tags":"","title":"Configuring Object Storage"},{"body":"Drycc supports deploying applications via an existing Docker Image. This is useful for integrating Drycc into Docker-based CI/CD pipelines.\nPrepare an Application Start by cloning an example application:\n$ git clone https://github.com/drycc/example-dockerfile-http.git $ cd example-dockerfile-http Next use your local docker client to build the image and push it to DockerHub.\n$ docker build -t \u003cusername\u003e/example-dockerfile-http . $ docker push \u003cusername\u003e/example-dockerfile-http Docker Image Requirements In order to deploy Docker images, they must conform to the following requirements:\nThe Dockerfile must use the EXPOSE directive to expose exactly one port. That port must be listening for an HTTP connection. The Dockerfile must use the CMD directive to define the default process that will run within the container. The Docker image must contain bash to run processes. !!! note Note that if you are using a private registry of any kind (gcr or other) the application environment must include a $PORT config variable that matches the EXPOSE’d port, example: drycc config:set PORT=5000. See Configuring Registry for more info.\nCreate an Application Use drycc create to create an application on the controller.\n$ mkdir -p /tmp/example-dockerfile-http \u0026\u0026 cd /tmp/example-dockerfile-http $ drycc create example-dockerfile-http --no-remote Creating application... done, created example-dockerfile-http !!! note For all commands except for drycc create, the drycc client uses the name of the current directory as the app name if you don’t specify it explicitly with --app.\nDeploy the Application Use drycc pull to deploy your application from DockerHub or a public registry.\n$ drycc pull \u003cusername\u003e/example-dockerfile-http:latest Creating build... done, v2 $ curl -s http://example-dockerfile-http.local3.dryccapp.com Powered by Drycc Because you are deploying a Docker image, the web process type is automatically scaled to 1 on first deploy.\nUse drycc scale web=3 to increase web processes to 3, for example. Scaling a process type directly changes the number of Containers running that process.\nPrivate Registry To deploy Docker images from a private registry or from a private repository, use drycc registry to attach credentials to your application. These credentials are the same as you’d use when running docker login at your private registry.\nTo deploy private Docker images, take the following steps:\nGather the username and password for the registry, such as a Quay.io Robot Account or a GCR.io Long Lived Token Run drycc registry:set username=\u003cthe-user\u003e password=\u003csecret\u003e -a \u003capplication-name\u003e Now perform drycc pull as normal, against an image in the private registry When using a GCR.io Long Lived Token, the JSON blob will have to be compacted first using a tool like jq and then used in the password field in drycc registry:set. For the username, use _json_key. For example:\ndrycc registry:set username=_json_key password=\"$(cat google_cloud_cred.json | jq -c .)\" When using a private registry the docker images are no longer pulled into the Drycc Internal Registry via the Drycc Workflow Controller but rather is managed by Kubernetes. This will increase security and overall speed, however the application port information can no longer be discovered. Instead the application port information can be set via drycc config:set PORT=80 prior to setting the registry information.\n!!! note Currently GCR.io and ECR in short lived auth token mode are not supported.\n","categories":"","description":"Deploy an application using a container image stored in your Drycc Container Registry.","excerpt":"Deploy an application using a container image stored in your Drycc …","ref":"/docs/applications/using-container-images/","tags":"","title":"Using Docker Images"},{"body":"What’s New New! healthcheck field in configuration, deprecates the HEALTHCHECK_* environment variables.\nNew! Unsetting a configuration variable that does not exist will return a 422.\nNew! Creating an identical sequential release returns a 409 rather than create a no-op release.\nAuthentication Register a New User Example Request:\nPOST /v2/auth/register/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json { \"username\": \"test\", \"password\": \"opensesame\", \"email\": \"test@example.com\" } Optional Parameters:\n{ \"first_name\": \"test\", \"last_name\": \"testerson\" } Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"id\": 1, \"last_login\": \"2014-10-19T22:01:00.601Z\", \"is_superuser\": true, \"username\": \"test\", \"first_name\": \"test\", \"last_name\": \"testerson\", \"email\": \"test@example.com\", \"is_staff\": true, \"is_active\": true, \"date_joined\": \"2014-10-19T22:01:00.601Z\", \"groups\": [], \"user_permissions\": [] } Log in Example Request:\nPOST /v2/auth/login/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json {\"username\": \"test\", \"password\": \"opensesame\"} Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json {\"token\": \"abc123\"} Cancel Account Example Request:\nDELETE /v2/auth/cancel/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Regenerate Token note\nThis command could require administrative privileges\nExample Request:\nPOST /v2/auth/tokens/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Optional Parameters:\n{ \"username\" : \"test\" \"all\" : \"true\" } Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json {\"token\": \"abc123\"} Change Password Example Request:\nPOST /v2/auth/passwd/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 { \"password\": \"foo\", \"new_password\": \"bar\" } Optional parameters:\n{\"username\": \"testuser\"} note\nUsing the username parameter requires administrative privileges and makes the password parameter optional.\nExample Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Applications List all Applications Example Request:\nGET /v2/apps HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"count\": 1, \"next\": null, \"previous\": null, \"results\": [ { \"created\": \"2014-01-01T00:00:00UTC\", \"id\": \"example-go\", \"owner\": \"test\", \"structure\": {}, \"updated\": \"2014-01-01T00:00:00UTC\", \"url\": \"example-go.example.com\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } ] } Create an Application Example Request:\nPOST /v2/apps/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 Optional parameters:\n{\"id\": \"example-go\"} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"created\": \"2014-01-01T00:00:00UTC\", \"id\": \"example-go\", \"owner\": \"test\", \"structure\": {}, \"updated\": \"2014-01-01T00:00:00UTC\", \"url\": \"example-go.example.com\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Destroy an Application Example Request:\nDELETE /v2/apps/example-go/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 List Application Details Example Request:\nGET /v2/apps/example-go/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"created\": \"2014-01-01T00:00:00UTC\", \"id\": \"example-go\", \"owner\": \"test\", \"structure\": {}, \"updated\": \"2014-01-01T00:00:00UTC\", \"url\": \"example-go.example.com\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Update Application Details Example Request:\nPOST /v2/apps/example-go/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Optional parameters:\n{ \"owner\": \"test\" } Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 1.8.0 Content-Type: application/json Retrieve Application Logs Example Request:\nGET /v2/apps/example-go/logs/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Optional URL Query Parameters:\n?log_lines= Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: text/plain \"16:51:14 drycc[api]: test created initial release\\n\" Run one-off Commands POST /v2/apps/example-go/run/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 {\"command\": \"echo hi\"} Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json {\"exit_code\": 0, \"output\": \"hi\\n\"} Certificates List all Certificates Example Request:\nGET /v2/certs HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"count\": 1, \"next\": null, \"previous\": null, \"results\": [ { \"id\": 22, \"owner\": \"test\", \"san\": [], \"domains\": [], \"created\": \"2016-06-22T22:24:20Z\", \"updated\": \"2016-06-22T22:24:20Z\", \"name\": \"foo\", \"common_name\": \"bar.com\", \"fingerprint\": \"7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0\", \"expires\": \"2017-01-14T23:57:57Z\", \"starts\": \"2016-01-15T23:57:57Z\", \"issuer\": \"/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc\", \"subject\": \"/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc\" } ] } Get Certificate Details Example Request:\nGET /v2/certs/foo HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"id\": 22, \"owner\": \"test\", \"san\": [], \"domains\": [], \"created\": \"2016-06-22T22:24:20Z\", \"updated\": \"2016-06-22T22:24:20Z\", \"name\": \"foo\", \"common_name\": \"bar.com\", \"fingerprint\": \"7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0\", \"expires\": \"2017-01-14T23:57:57Z\", \"starts\": \"2016-01-15T23:57:57Z\", \"issuer\": \"/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc\", \"subject\": \"/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc\" } Create Certificate Example Request:\nPOST /v2/certs/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 { \"name\": \"foo\" \"certificate\": \"-----BEGIN CERTIFICATE-----\", \"key\": \"-----BEGIN RSA PRIVATE KEY-----\" } Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"id\": 22, \"owner\": \"test\", \"san\": [], \"domains\": [], \"created\": \"2016-06-22T22:24:20Z\", \"updated\": \"2016-06-22T22:24:20Z\", \"name\": \"foo\", \"common_name\": \"bar.com\", \"fingerprint\": \"7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0\", \"expires\": \"2017-01-14T23:57:57Z\", \"starts\": \"2016-01-15T23:57:57Z\", \"issuer\": \"/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc\", \"subject\": \"/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc\" } Destroy a Certificate Example Request:\nDELETE /v2/certs/foo HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Attach a Domain to a Certificate Example Request:\nPOST /v2/certs/foo/domain/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 { \"domain\": \"test.com\" } Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Remove a Domain from a Certificate Example Request:\nDELETE /v2/certs/foo/domain/test.com/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Pods List all Pods Example Request:\nGET /v2/apps/example-go/pods/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"count\": 1, \"results\": [ { \"name\": \"go-v2-web-e7dej\", \"release\": \"v2\", \"started\": \"2014-01-01T00:00:00Z\", \"state\": \"up\", \"type\": \"web\" } ] } List all Pods by Type Example Request:\nGET /v2/apps/example-go/pods/web/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"count\": 1, \"results\": [ { \"name\": \"go-v2-web-e7dej\", \"release\": \"v2\", \"started\": \"2014-01-01T00:00:00Z\", \"state\": \"up\", \"type\": \"web\" } ] } Restart All Pods Example Request:\nPOST /v2/apps/example-go/pods/restart/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json [ { \"name\": \"go-v2-web-atots\", \"release\": \"v2\", \"started\": \"2016-04-11T21:07:54Z\", \"state\": \"up\", \"type\": \"web\" } ] Restart Pods by Type Example Request:\nPOST /v2/apps/example-go/pods/web/restart/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json [ { \"name\": \"go-v2-web-atots\", \"release\": \"v2\", \"started\": \"2016-04-11T21:07:54Z\", \"state\": \"up\", \"type\": \"web\" } ] Restart Pods by Type and Name Example Request:\nPOST /v2/apps/example-go/pods/go-v2-web-atots/restart/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json [ { \"name\": \"go-v2-web-atots\", \"release\": \"v2\", \"started\": \"2016-04-11T21:07:54Z\", \"state\": \"up\", \"type\": \"web\" } ] Scale Pods Example Request:\nPOST /v2/apps/example-go/scale/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 {\"web\": 3} Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Configuration List Application Configuration Example Request:\nGET /v2/apps/example-go/config/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"owner\": \"test\", \"app\": \"example-go\", \"values\": { \"PLATFORM\": \"drycc\" }, \"memory\": {}, \"cpu\": {}, \"tags\": {}, \"healthcheck\": {}, \"created\": \"2014-01-01T00:00:00UTC\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Create new Config Example Request:\nPOST /v2/apps/example-go/config/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 {\"values\": {\"HELLO\": \"world\", \"PLATFORM\": \"drycc\"}} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"owner\": \"test\", \"app\": \"example-go\", \"values\": { \"DRYCC_APP\": \"example-go\", \"DRYCC_RELEASE\": \"v3\", \"HELLO\": \"world\", \"PLATFORM\": \"drycc\" }, \"memory\": {}, \"cpu\": {}, \"tags\": {}, \"healthcheck\": {}, \"created\": \"2014-01-01T00:00:00UTC\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Unset Config Variable Example Request:\nPOST /v2/apps/example-go/config/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 {\"values\": {\"HELLO\": null}} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"owner\": \"test\", \"app\": \"example-go\", \"values\": { \"DRYCC_APP\": \"example-go\", \"DRYCC_RELEASE\": \"v4\", \"PLATFORM\": \"drycc\" }, \"memory\": {}, \"cpu\": {}, \"tags\": {}, \"healthcheck\": {}, \"created\": \"2014-01-01T00:00:00UTC\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Domains List Application Domains Example Request:\nGET /v2/apps/example-go/domains/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"count\": 1, \"next\": null, \"previous\": null, \"results\": [ { \"app\": \"example-go\", \"created\": \"2014-01-01T00:00:00UTC\", \"domain\": \"example.example.com\", \"owner\": \"test\", \"updated\": \"2014-01-01T00:00:00UTC\" } ] } Add Domain Example Request:\nPOST /v2/apps/example-go/domains/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 {'domain': 'example.example.com'} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"app\": \"example-go\", \"created\": \"2014-01-01T00:00:00UTC\", \"domain\": \"example.example.com\", \"owner\": \"test\", \"updated\": \"2014-01-01T00:00:00UTC\" } Remove Domain Example Request:\nDELETE /v2/apps/example-go/domains/example.example.com HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Builds List Application Builds Example Request:\nGET /v2/apps/example-go/build/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"app\": \"example-go\", \"created\": \"2014-01-01T00:00:00UTC\", \"dockerfile\": \"FROM drycc/slugrunner RUN mkdir -p /app WORKDIR /app ENTRYPOINT [\\\"/runner/init\\\"] ADD slug.tgz /app ENV GIT_SHA 060da68f654e75fac06dbedd1995d5f8ad9084db\", \"image\": \"example-go\", \"owner\": \"test\", \"procfile\": { \"web\": \"example-go\" }, \"sha\": \"060da68f\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Create Application Build Example Request:\nPOST /v2/apps/example-go/build/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 {\"image\": \"drycc/example-go:latest\"} Optional Parameters:\n{ \"procfile\": { \"web\": \"./cmd\" } } Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"app\": \"example-go\", \"created\": \"2014-01-01T00:00:00UTC\", \"dockerfile\": \"\", \"image\": \"drycc/example-go:latest\", \"owner\": \"test\", \"procfile\": {}, \"sha\": \"\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Releases List Application Releases Example Request:\nGET /v2/apps/example-go/releases/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"count\": 3, \"next\": null, \"previous\": null, \"results\": [ { \"app\": \"example-go\", \"build\": \"202d8e4b-600e-4425-a85c-ffc7ea607f61\", \"config\": \"ed637ceb-5d32-44bd-9406-d326a777a513\", \"created\": \"2014-01-01T00:00:00UTC\", \"owner\": \"test\", \"summary\": \"test changed nothing\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\", \"version\": 3 }, { \"app\": \"example-go\", \"build\": \"202d8e4b-600e-4425-a85c-ffc7ea607f61\", \"config\": \"95bd6dea-1685-4f78-a03d-fd7270b058d1\", \"created\": \"2014-01-01T00:00:00UTC\", \"owner\": \"test\", \"summary\": \"test deployed 060da68\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\", \"version\": 2 }, { \"app\": \"example-go\", \"build\": null, \"config\": \"95bd6dea-1685-4f78-a03d-fd7270b058d1\", \"created\": \"2014-01-01T00:00:00UTC\", \"owner\": \"test\", \"summary\": \"test created initial release\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\", \"version\": 1 } ] } List Release Details Example Request:\nGET /v2/apps/example-go/releases/v2/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"app\": \"example-go\", \"build\": null, \"config\": \"95bd6dea-1685-4f78-a03d-fd7270b058d1\", \"created\": \"2014-01-01T00:00:00UTC\", \"owner\": \"test\", \"summary\": \"test created initial release\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\", \"version\": 1 } Rollback Release Example Request:\nPOST /v2/apps/example-go/releases/rollback/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 {\"version\": 1} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json {\"version\": 5} Keys List Keys Example Request:\nGET /v2/keys/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"count\": 1, \"next\": null, \"previous\": null, \"results\": [ { \"created\": \"2014-01-01T00:00:00UTC\", \"id\": \"test@example.com\", \"owner\": \"test\", \"public\": \"ssh-rsa \u003c...\u003e\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } ] } Add Key to User Example Request:\nPOST /v2/keys/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 { \"id\": \"example\", \"public\": \"ssh-rsa \u003c...\u003e\" } Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"created\": \"2014-01-01T00:00:00UTC\", \"id\": \"example\", \"owner\": \"example\", \"public\": \"ssh-rsa \u003c...\u003e\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Remove Key from User Example Request:\nDELETE /v2/keys/example HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Permissions List Application Permissions note\nThis does not include the app owner.\nExample Request:\nGET /v2/apps/example-go/perms/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"users\": [ \"test\", \"foo\" ] } Create Application Permission Example Request:\nPOST /v2/apps/example-go/perms/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 {\"username\": \"example\"} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Remove Application Permission Example Request:\nDELETE /v2/apps/example-go/perms/example HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 List Administrators Example Request:\nGET /v2/admin/perms/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"count\": 2, \"next\": null \"previous\": null, \"results\": [ { \"username\": \"test\", \"is_superuser\": true }, { \"username\": \"foo\", \"is_superuser\": true } ] } Grant User Administrative Privileges note\nThis command requires administrative privileges\nExample Request:\nPOST /v2/admin/perms HTTP/1.1 Host: drycc.example.com Authorization: token abc123 {\"username\": \"example\"} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Remove User’s Administrative Privileges note\nThis command requires administrative privileges\nExample Request:\nDELETE /v2/admin/perms/example HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Users List all users note\nThis command requires administrative privileges\nExample Request:\nGET /v2/users HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.1 DRYCC_PLATFORM_VERSION: 2.1.0 Content-Type: application/json { \"count\": 1, \"next\": null, \"previous\": null, \"results\": [ { \"id\": 1, \"last_login\": \"2014-10-19T22:01:00.601Z\", \"is_superuser\": true, \"username\": \"test\", \"first_name\": \"test\", \"last_name\": \"testerson\", \"email\": \"test@example.com\", \"is_staff\": true, \"is_active\": true, \"date_joined\": \"2014-10-19T22:01:00.601Z\", \"groups\": [], \"user_permissions\": [] } ] } ","categories":"","description":"This is the v2.1 REST API for the Controller.","excerpt":"This is the v2.1 REST API for the Controller.","ref":"/docs/reference-guide/controller-api-v2-1/","tags":"","title":"Controller API v2.1"},{"body":"Determine Your Host and Hostname Values Drycc workflow requires a wildcard DNS record to dynamically map app names to the router.\nUser should already have DNS set up pointing to their known host. The $hostname value can be calculated by prepending drycc. to the value set in global.platformDomain.\nLogin to Workflow Workflow use the passport component to create and authorize users. If you already have an account, use drycc login to authenticate against the Drycc Workflow API.\n$ drycc login http://drycc.example.com Opening browser to http://drycc.example.com/v2/login/drycc/?key=4ccc81ee2dce4349ad5261ceffe72c71 Waiting for login... .o.Logged in as admin Configuration file written to /root/.drycc/client.json Or you can login with username and password\n$ drycc login http://drycc.example.com --username=demo --password=demo Configuration file written to /root/.drycc/client.json Deploy an Application Drycc Workflow supports three different types of applications, Buildpacks, Dockerfiles and Container Images. Our first application will be a simple Container Image-based application, so you don’t have to wrestle with checking out code.\nRun drycc create to create a new application on Drycc Workflow. If you do not specify a name for your application, Workflow automatically generates a friendly (and sometimes funny) name.\n$ drycc create --no-remote Creating Application... done, created proper-barbecue If you want to add a git remote for this app later, use `drycc git:remote -a proper-barbecue` Our application has been created and named proper-barbecue. As with the drycc hostname, any HTTP traffic to proper-barbecue will be automatically routed to your application pods by the edge router.\nLet’s use the CLI to tell the platform to deploy an application and then use curl to send a request to the app:\n$ drycc pull drycc/example-go -a proper-barbecue Creating build... done $ curl http://proper-barbecue.$hostname Powered by Drycc !!! note If you see a 404 error, make sure you specified your application name with -a \u003cappname\u003e!\nWorkflow’s edge router knows all about application names and automatically sends traffic to the right application. The router sends traffic for proper-barbecue.104.197.125.75.nip.io to your app, just like drycc.104.197.125.75.nip.io was sent to the Workflow API service.\nChange Application Configuration Next, let’s change some configuration using the CLI. Our example app is built to read configuration from the environment. By using drycc config:set we can change how the application behaves:\n$ drycc config:set POWERED_BY=\"Container Images + Kubernetes\" -a proper-barbecue Creating config... done UUID OWNER NAME VALUE 04bb6e45-9221-4843-a1f9-acc7fded3b06 dev POWERED_BY Container Images + Kubernetes Behind the scenes, Workflow creates a new release for your application and uses Kubernetes to provide a zero-downtime rolling deploy to the new release!\nValidate that our configuration change has worked:\n$ curl http://proper-barbecue.104.197.125.75.nip.io Powered by Container Images + Kubernetes Scale Your Application Last, let’s scale our application by adding more application processes. Using the CLI you can easily add and remove additional processes to service requests:\n$ drycc scale web=2 -a proper-barbecue Scaling processes... but first, coffee! done in 36s NAME RELEASE STATE PTYPE STARTED proper-barbecue-v18-web-rk644 v18 up web 2023-12-08T03:09:25UTC proper-barbecue-v18-web-0ag04 v18 up web 2023-12-08T03:09:25UTC Congratulations! You have deployed, configured, and scaled your first application using Drycc Workflow.\nGoing Further There is a lot more you can do with Drycc Workflow, play around with the CLI:\n!!! important In order to have permission to push an app you must add a SSH key to your user on the Drycc Workflow. For more information, please check Users and SSH Keys and Troubleshooting Workflow.\nRoll back to a previous release with drycc rollback -a proper-barbecue See application logs with drycc logs -a proper-barbecue Try one of our other example applications like: drycc/ruby-getting-started drycc/python-getting-started drycc/php-getting-started Read about using application Buildpacks or Dockerfiles Join our #community slack channel and meet the team! ","categories":"","description":"Deploy an application using drycc cli.","excerpt":"Deploy an application using drycc cli.","ref":"/docs/quickstart/deploy-an-app/","tags":"","title":"Deploy Your First App"},{"body":"The logging platform is made up of 2 components - Fluentbit and Logger.\nFluentbit runs on every worker node of the cluster and is deployed as a Daemon Set. The Fluentbit pods capture all of the stderr and stdout streams of every container running on the host (even those not hosted directly by kubernetes). Once the log message arrives in our custom fluentbit plugin we determine where the message originated.\nIf the message was from the Workflow Controller or from an application deployed via workflow we send it to the logs topic on the local Redis Stream instance.\nLogger then acts as a consumer reading messages off of the Redis Stream logs topic storing those messages in a local Redis instance. When a user wants to retrieve log entries using the drycc logs command we make an HTTP request from Controller to Logger which then fetches the appropriate data from Redis.\nConfiguring Off Cluster Redis Even though we provide a redis instance with the default Workflow install, it is recommended that operators use a third-party source like Elasticache or similar offering. This way your data is durable across upgrades or outages. If you have a third-party Redis installation you would like to use all you need to do is set the following values in your helm chart:\ndb = “0” host = “my.host.redis” port = “6379” password = \"\" These can be changed by running helm inspect values drycc/workflow \u003e values.yaml before using helm install to complete the installation. To customize the redis credentials, edit values.yaml and modify the redis section of the file to tune these settings.\nDebugging Logger If the drycc logs command encounters an error it will return the following message:\nError: There are currently no log messages. Please check the following things: 1) Logger and fluentbit pods are running. 2) The application is writing logs to the logger component by checking that an entry in the ring buffer was created: kubectl --namespace=drycc logs \u003clogger pod\u003e 3) Making sure that the container logs were mounted properly into the fluentbit pod: kubectl --namespace=drycc exec \u003cfluentbit pod\u003e ls /var/log/containers Architecture Diagram ┌────────┐ │ Router │ ┌────────┐ ┌─────┐ └────────┘ │ Logger │◀───▶│Redis│ │ └────────┘ └─────┘ Log file ▲ │ │ ▼ │ ┌────────┐ ┌─────────┐ logs/metrics ┌──────────────┐ │App Logs│──Log File──▶│Fluentbit│───────topics─────▶│ Redis Stream │ └────────┘ └─────────┘ └──────────────┘ Default Configuration Fluent Bit is based in a pluggable architecture where different plugins plays a major role in the data pipeline, more than 70 built-in plugins available. Please refer to charts values.yaml for specific configurations.\n","categories":"","description":"Logs are a stream of time-stamped events aggregated from the output streams of all your app’s running processes. Retrieve, filter, or use syslog drains.","excerpt":"Logs are a stream of time-stamped events aggregated from the output …","ref":"/docs/managing-workflow/platform-logging/","tags":"","title":"Platform Logging"},{"body":"Each Drycc component includes its own suite of style checks, unit tests, and black-box type functional tests.\nIntegration tests verify the behavior of the Drycc components together as a system and are provided separately by the drycc/workflow-e2e project.\nGitHub pull requests for all Drycc components are tested automatically by the Travis CI continuous integration system. Contributors should run the same tests locally before proposing any changes to the Drycc codebase.\nSet Up the Environment Successfully executing the unit and functional tests for any Drycc component requires that the Development Environment is set up first.\nRun the Tests The style checks, unit tests, and functional tests for each component can all be executed via make targets:\nTo execute style checks:\n$ make test-style To execute unit tests:\n$ make test-unit To execute functional tests:\n$ make test-functional To execute style checks, unit tests, and functional tests all in one shot:\n$ make test To execute integration tests, refer to drycc/workflow-e2e documentation.\n","categories":"","description":"Each Drycc component is one among an ecosystem of such components - many of which integrate with one another - which makes testing each component thoroughly a matter of paramount importance.","excerpt":"Each Drycc component is one among an ecosystem of such components - …","ref":"/docs/contribution-guidelines/testing/","tags":"","title":"Testing Drycc"},{"body":"","categories":"","description":"In this tutorial, you'll learn how to manage users.\n","excerpt":"In this tutorial, you'll learn how to manage users.\n","ref":"/docs/users/","tags":"","title":"Users"},{"body":"","categories":"","description":"A simple and scalable cloud platform for all developer needs.\n","excerpt":"A simple and scalable cloud platform for all developer needs.\n","ref":"/docs/applications/","tags":"","title":"Applications"},{"body":"Configuring Postgres By default, Drycc Workflow ships with the database component, which provides an in-cluster PostgreSQL database backed up to in-cluster or off-cluster object storage. Currently, for object storage, which is utilized by several Workflow components, only off-cluster solutions such as S3 or GCS are recommended in production environments. Experience has shown that many operators already opting for off-cluster object storage similarly prefer to host Postgres off-cluster as well, using Amazon RDS or similar. When excercising both options, a Workflow installation becomes entirely stateless, and is thus restored or rebuilt with greater ease should the need ever arise.\nProvisioning off-cluster Postgres First, provision a PostgreSQL RDBMS using the cloud provider or other infrastructure of your choice. Take care to ensure that security groups or other firewall rules will permit connectivity from your Kubernetes worker nodes, any of which may play host to the Workflow controller component.\nTake note of the following:\nThe hostname or public IP of your PostgreSQL RDBMS The port on which your PostgreSQL RDBMS runs– typically 5432 Within the off-cluster RDBMS, manually provision the following:\nA database user (take note of the username and password) A database owned by that user (take note of its name) If you are able to log into the RDBMS as a superuser or a user with appropriate permissions, this process will typically look like this:\n$ psql -h \u003chost\u003e -p \u003cport\u003e -d postgres -U \u003c\"postgres\" or your own username\u003e \u003e create user \u003cdrycc username; typically \"drycc\"\u003e with password '\u003cpassword\u003e'; \u003e create database \u003cdatabase name; typically \"drycc\"\u003e with owner \u003cdrycc username\u003e; \u003e \\q Configuring Workflow The Helm chart for Drycc Workflow can be easily configured to connect the Workflow controller component to an off-cluster PostgreSQL database.\nStep 1: If you haven’t already fetched the values, do so with helm inspect values drycc/workflow \u003e values.yaml Step 2: Update database connection details by modifying values.yaml: Update the databaseLocation parameter to off-cluster. Update the values in the [database] configuration section to properly reflect all connection details. Update the values in the [controller] configuration section to properly reflect platformDomain details. Save your changes. Note: you do not need to (and must not) base64 encode any values, as the Helm chart will automatically handle encoding as necessary. You are now ready to helm install drycc oci://registry.drycc.cc/charts/workflow --namespace drycc -f values.yaml as usual.\n","categories":"","description":"Drycc Workflow's controller and passport component rely on a PostgreSQL database to store platform state.","excerpt":"Drycc Workflow's controller and passport component rely on a …","ref":"/docs/installing-workflow/configuring-postgres/","tags":"","title":"Configuring Postgres"},{"body":"Drycc Workflow ships with a registry component by default, which provides an in-cluster Container registry backed by the platform-configured object storage. Operators might want to use an off-cluster registry for performance or security reasons.\nConfiguring Off-Cluster Private Registry Every component that relies on a registry uses two inputs for configuration:\nRegistry Location environment variable named DRYCC_REGISTRY_LOCATION Access credentials stored as a Kubernetes secret named registry-secret The Helm chart for Drycc Workflow can be easily configured to connect Workflow components to off-cluster registry. Drycc Workflow supports external registries which provide either short-lived tokens that are valid only for a specified amount of time or long-lived tokens (basic username/password) which are valid forever for authenticating to them. For those registries which provide short lived tokens for authentication, Drycc Workflow will generate and refresh them such that the deployed apps will only have access to the short-lived tokens and not to the actual credentials for the registries.\nWhen using a private registry the container images are no longer pulled by Drycc Workflow Controller but rather are managed by Kubernetes. This will increase security and overall speed, however the port information can no longer be discovered. Instead the port information can be set via drycc config:set PORT=\u003cport\u003e prior to deploying the application.\nDrycc Workflow currently supports:\noff-cluster: Any provider which supports long-lived username/password authentication, such as Azure Container Registry, Docker Hub, quay.io, or a self-hosted Container registry. Configuration If you haven’t already fetched the values file, do so with helm inspect values drycc/workflow \u003e values.yaml Update registry location details by modifying the values file: * Update the registryLocation parameter to reference the registry location you are using: off-cluster, ecr, gcr * Update the values in the section which corresponds to your registry location type. You are now ready to helm install drycc oci://registry.drycc.cc/charts/workflow --namespace drycc -f values.yaml using your desired registry.\nExamples Here we show how the relevant parts of the fetched values.yaml file might look like after configuring for a particular off-cluster registry:\nAzure Container Registry (ACR) After following the docs and creating a registry, e.g. myregistry, with its corresponding login server of myregistry.azurecr.io, the following values should be supplied:\nglobal: ... registryLocation: \"off-cluster\" ... registry-token-refresher: ... registry: hostname: \"myregistry.azurecr.io\" organization: \"myorg\" username: \"myusername\" password: \"mypassword\" ... Note: The mandatory organization field (here myorg) will be created as an ACR repository if it does not already exist.\nQuay.io global: ... registryLocation: \"off-cluster\" ... registry-token-refresher: ... registry: hostname: \"quay.io\" organization: \"myorg\" username: \"myusername\" password: \"mypassword\" ... ","categories":"","description":"Drycc Workflow's builder component relies on a registry for storing application container images.","excerpt":"Drycc Workflow's builder component relies on a registry for storing …","ref":"/docs/installing-workflow/configuring-registry/","tags":"","title":"Configuring Registry"},{"body":"What’s New New! /v2/auth/whoami endpoint\nAuthentication Register a New User Example Request:\nPOST /v2/auth/register/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json { \"username\": \"test\", \"password\": \"opensesame\", \"email\": \"test@example.com\" } Optional Parameters:\n{ \"first_name\": \"test\", \"last_name\": \"testerson\" } Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json { \"id\": 1, \"last_login\": \"2014-10-19T22:01:00.601Z\", \"is_superuser\": true, \"username\": \"test\", \"first_name\": \"test\", \"last_name\": \"testerson\", \"email\": \"test@example.com\", \"is_staff\": true, \"is_active\": true, \"date_joined\": \"2014-10-19T22:01:00.601Z\", \"groups\": [], \"user_permissions\": [] } Log in Example Request:\nPOST /v2/auth/login/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json {\"username\": \"test\", \"password\": \"opensesame\"} Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json {\"token\": \"abc123\"} Cancel Account Example Request:\nDELETE /v2/auth/cancel/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Who Am I Example Request:\nGET /v2/auth/whoami/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json { \"id\": 1, \"last_login\": \"2014-10-19T22:01:00.601Z\", \"is_superuser\": true, \"username\": \"test\", \"first_name\": \"test\", \"last_name\": \"testerson\", \"email\": \"test@example.com\", \"is_staff\": true, \"is_active\": true, \"date_joined\": \"2014-10-19T22:01:00.601Z\", \"groups\": [], \"user_permissions\": [] } Regenerate Token note\nThis command could require administrative privileges\nExample Request:\nPOST /v2/auth/tokens/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Optional Parameters:\n{ \"username\" : \"test\" \"all\" : \"true\" } Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json {\"token\": \"abc123\"} Change Password Example Request:\nPOST /v2/auth/passwd/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 { \"password\": \"foo\", \"new_password\": \"bar\" } Optional parameters:\n{\"username\": \"testuser\"} note\nUsing the username parameter requires administrative privileges and makes the password parameter optional.\nExample Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Applications List all Applications Example Request:\nGET /v2/apps HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json { \"count\": 1, \"next\": null, \"previous\": null, \"results\": [ { \"created\": \"2014-01-01T00:00:00UTC\", \"id\": \"example-go\", \"owner\": \"test\", \"structure\": {}, \"updated\": \"2014-01-01T00:00:00UTC\", \"url\": \"example-go.example.com\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } ] } Create an Application Example Request:\nPOST /v2/apps/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 Optional parameters:\n{\"id\": \"example-go\"} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json { \"created\": \"2014-01-01T00:00:00UTC\", \"id\": \"example-go\", \"owner\": \"test\", \"structure\": {}, \"updated\": \"2014-01-01T00:00:00UTC\", \"url\": \"example-go.example.com\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Destroy an Application Example Request:\nDELETE /v2/apps/example-go/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 List Application Details Example Request:\nGET /v2/apps/example-go/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json { \"created\": \"2014-01-01T00:00:00UTC\", \"id\": \"example-go\", \"owner\": \"test\", \"structure\": {}, \"updated\": \"2014-01-01T00:00:00UTC\", \"url\": \"example-go.example.com\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Update Application Details Example Request:\nPOST /v2/apps/example-go/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Optional parameters:\n{ \"owner\": \"test\" } Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 1.8.0 Content-Type: application/json Retrieve Application Logs Example Request:\nGET /v2/apps/example-go/logs/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Optional URL Query Parameters:\n?log_lines= Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: text/plain \"16:51:14 drycc[api]: test created initial release\\n\" Run one-off Commands POST /v2/apps/example-go/run/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 {\"command\": \"echo hi\"} Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json {\"exit_code\": 0, \"output\": \"hi\\n\"} Certificates List all Certificates Example Request:\nGET /v2/certs HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json { \"count\": 1, \"next\": null, \"previous\": null, \"results\": [ { \"id\": 22, \"owner\": \"test\", \"san\": [], \"domains\": [], \"created\": \"2016-06-22T22:24:20Z\", \"updated\": \"2016-06-22T22:24:20Z\", \"name\": \"foo\", \"common_name\": \"bar.com\", \"fingerprint\": \"7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0\", \"expires\": \"2017-01-14T23:57:57Z\", \"starts\": \"2016-01-15T23:57:57Z\", \"issuer\": \"/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc\", \"subject\": \"/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc\" } ] } Get Certificate Details Example Request:\nGET /v2/certs/foo HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json { \"id\": 22, \"owner\": \"test\", \"san\": [], \"domains\": [], \"created\": \"2016-06-22T22:24:20Z\", \"updated\": \"2016-06-22T22:24:20Z\", \"name\": \"foo\", \"common_name\": \"bar.com\", \"fingerprint\": \"7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0\", \"expires\": \"2017-01-14T23:57:57Z\", \"starts\": \"2016-01-15T23:57:57Z\", \"issuer\": \"/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc\", \"subject\": \"/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc\" } Create Certificate Example Request:\nPOST /v2/certs/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 { \"name\": \"foo\" \"certificate\": \"-----BEGIN CERTIFICATE-----\", \"key\": \"-----BEGIN RSA PRIVATE KEY-----\" } Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json { \"id\": 22, \"owner\": \"test\", \"san\": [], \"domains\": [], \"created\": \"2016-06-22T22:24:20Z\", \"updated\": \"2016-06-22T22:24:20Z\", \"name\": \"foo\", \"common_name\": \"bar.com\", \"fingerprint\": \"7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0\", \"expires\": \"2017-01-14T23:57:57Z\", \"starts\": \"2016-01-15T23:57:57Z\", \"issuer\": \"/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc\", \"subject\": \"/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc\" } Destroy a Certificate Example Request:\nDELETE /v2/certs/foo HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Attach a Domain to a Certificate Example Request:\nPOST /v2/certs/foo/domain/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 { \"domain\": \"test.com\" } Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Remove a Domain from a Certificate Example Request:\nDELETE /v2/certs/foo/domain/test.com/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Pods List all Pods Example Request:\nGET /v2/apps/example-go/pods/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json { \"count\": 1, \"results\": [ { \"name\": \"go-v2-web-e7dej\", \"release\": \"v2\", \"started\": \"2014-01-01T00:00:00Z\", \"state\": \"up\", \"type\": \"web\" } ] } List all Pods by Type Example Request:\nGET /v2/apps/example-go/pods/web/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json { \"count\": 1, \"results\": [ { \"name\": \"go-v2-web-e7dej\", \"release\": \"v2\", \"started\": \"2014-01-01T00:00:00Z\", \"state\": \"up\", \"type\": \"web\" } ] } Restart All Pods Example Request:\nPOST /v2/apps/example-go/pods/restart/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json [ { \"name\": \"go-v2-web-atots\", \"release\": \"v2\", \"started\": \"2016-04-11T21:07:54Z\", \"state\": \"up\", \"type\": \"web\" } ] Restart Pods by Type Example Request:\nPOST /v2/apps/example-go/pods/web/restart/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json [ { \"name\": \"go-v2-web-atots\", \"release\": \"v2\", \"started\": \"2016-04-11T21:07:54Z\", \"state\": \"up\", \"type\": \"web\" } ] Restart Pods by Type and Name Example Request:\nPOST /v2/apps/example-go/pods/go-v2-web-atots/restart/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json [ { \"name\": \"go-v2-web-atots\", \"release\": \"v2\", \"started\": \"2016-04-11T21:07:54Z\", \"state\": \"up\", \"type\": \"web\" } ] Scale Pods Example Request:\nPOST /v2/apps/example-go/scale/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 {\"web\": 3} Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Configuration List Application Configuration Example Request:\nGET /v2/apps/example-go/config/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json { \"owner\": \"test\", \"app\": \"example-go\", \"values\": { \"PLATFORM\": \"drycc\" }, \"memory\": {}, \"cpu\": {}, \"tags\": {}, \"healthcheck\": {}, \"created\": \"2014-01-01T00:00:00UTC\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Create new Config Example Request:\nPOST /v2/apps/example-go/config/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 {\"values\": {\"HELLO\": \"world\", \"PLATFORM\": \"drycc\"}} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json { \"owner\": \"test\", \"app\": \"example-go\", \"values\": { \"DRYCC_APP\": \"example-go\", \"DRYCC_RELEASE\": \"v3\", \"HELLO\": \"world\", \"PLATFORM\": \"drycc\" }, \"memory\": {}, \"cpu\": {}, \"tags\": {}, \"healthcheck\": {}, \"created\": \"2014-01-01T00:00:00UTC\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Unset Config Variable Example Request:\nPOST /v2/apps/example-go/config/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 {\"values\": {\"HELLO\": null}} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json { \"owner\": \"test\", \"app\": \"example-go\", \"values\": { \"DRYCC_APP\": \"example-go\", \"DRYCC_RELEASE\": \"v4\", \"PLATFORM\": \"drycc\" }, \"memory\": {}, \"cpu\": {}, \"tags\": {}, \"healthcheck\": {}, \"created\": \"2014-01-01T00:00:00UTC\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Domains List Application Domains Example Request:\nGET /v2/apps/example-go/domains/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json { \"count\": 1, \"next\": null, \"previous\": null, \"results\": [ { \"app\": \"example-go\", \"created\": \"2014-01-01T00:00:00UTC\", \"domain\": \"example.example.com\", \"owner\": \"test\", \"updated\": \"2014-01-01T00:00:00UTC\" } ] } Add Domain Example Request:\nPOST /v2/apps/example-go/domains/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 {'domain': 'example.example.com'} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json { \"app\": \"example-go\", \"created\": \"2014-01-01T00:00:00UTC\", \"domain\": \"example.example.com\", \"owner\": \"test\", \"updated\": \"2014-01-01T00:00:00UTC\" } Remove Domain Example Request:\nDELETE /v2/apps/example-go/domains/example.example.com HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Builds List Application Builds Example Request:\nGET /v2/apps/example-go/build/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json { \"app\": \"example-go\", \"created\": \"2014-01-01T00:00:00UTC\", \"dockerfile\": \"FROM drycc/slugrunner RUN mkdir -p /app WORKDIR /app ENTRYPOINT [\\\"/runner/init\\\"] ADD slug.tgz /app ENV GIT_SHA 060da68f654e75fac06dbedd1995d5f8ad9084db\", \"image\": \"example-go\", \"owner\": \"test\", \"procfile\": { \"web\": \"example-go\" }, \"sha\": \"060da68f\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Create Application Build Example Request:\nPOST /v2/apps/example-go/build/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 {\"image\": \"drycc/example-go:latest\"} Optional Parameters:\n{ \"procfile\": { \"web\": \"./cmd\" } } Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json { \"app\": \"example-go\", \"created\": \"2014-01-01T00:00:00UTC\", \"dockerfile\": \"\", \"image\": \"drycc/example-go:latest\", \"owner\": \"test\", \"procfile\": {}, \"sha\": \"\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Releases List Application Releases Example Request:\nGET /v2/apps/example-go/releases/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json { \"count\": 3, \"next\": null, \"previous\": null, \"results\": [ { \"app\": \"example-go\", \"build\": \"202d8e4b-600e-4425-a85c-ffc7ea607f61\", \"config\": \"ed637ceb-5d32-44bd-9406-d326a777a513\", \"created\": \"2014-01-01T00:00:00UTC\", \"owner\": \"test\", \"summary\": \"test changed nothing\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\", \"version\": 3 }, { \"app\": \"example-go\", \"build\": \"202d8e4b-600e-4425-a85c-ffc7ea607f61\", \"config\": \"95bd6dea-1685-4f78-a03d-fd7270b058d1\", \"created\": \"2014-01-01T00:00:00UTC\", \"owner\": \"test\", \"summary\": \"test deployed 060da68\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\", \"version\": 2 }, { \"app\": \"example-go\", \"build\": null, \"config\": \"95bd6dea-1685-4f78-a03d-fd7270b058d1\", \"created\": \"2014-01-01T00:00:00UTC\", \"owner\": \"test\", \"summary\": \"test created initial release\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\", \"version\": 1 } ] } List Release Details Example Request:\nGET /v2/apps/example-go/releases/v2/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json { \"app\": \"example-go\", \"build\": null, \"config\": \"95bd6dea-1685-4f78-a03d-fd7270b058d1\", \"created\": \"2014-01-01T00:00:00UTC\", \"owner\": \"test\", \"summary\": \"test created initial release\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\", \"version\": 1 } Rollback Release Example Request:\nPOST /v2/apps/example-go/releases/rollback/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 {\"version\": 1} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json {\"version\": 5} Keys List Keys Example Request:\nGET /v2/keys/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json { \"count\": 1, \"next\": null, \"previous\": null, \"results\": [ { \"created\": \"2014-01-01T00:00:00UTC\", \"id\": \"test@example.com\", \"owner\": \"test\", \"public\": \"ssh-rsa \u003c...\u003e\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } ] } Add Key to User Example Request:\nPOST /v2/keys/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 { \"id\": \"example\", \"public\": \"ssh-rsa \u003c...\u003e\" } Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json { \"created\": \"2014-01-01T00:00:00UTC\", \"id\": \"example\", \"owner\": \"example\", \"public\": \"ssh-rsa \u003c...\u003e\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Remove Key from User Example Request:\nDELETE /v2/keys/example HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Permissions List Application Permissions note\nThis does not include the app owner.\nExample Request:\nGET /v2/apps/example-go/perms/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json { \"users\": [ \"test\", \"foo\" ] } Create Application Permission Example Request:\nPOST /v2/apps/example-go/perms/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 {\"username\": \"example\"} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Remove Application Permission Example Request:\nDELETE /v2/apps/example-go/perms/example HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 List Administrators Example Request:\nGET /v2/admin/perms/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json { \"count\": 2, \"next\": null \"previous\": null, \"results\": [ { \"username\": \"test\", \"is_superuser\": true }, { \"username\": \"foo\", \"is_superuser\": true } ] } Grant User Administrative Privileges note\nThis command requires administrative privileges\nExample Request:\nPOST /v2/admin/perms HTTP/1.1 Host: drycc.example.com Authorization: token abc123 {\"username\": \"example\"} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Remove User’s Administrative Privileges note\nThis command requires administrative privileges\nExample Request:\nDELETE /v2/admin/perms/example HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Users List all users note\nThis command requires administrative privileges\nExample Request:\nGET /v2/users HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.2 DRYCC_PLATFORM_VERSION: 2.2.0 Content-Type: application/json { \"count\": 1, \"next\": null, \"previous\": null, \"results\": [ { \"id\": 1, \"last_login\": \"2014-10-19T22:01:00.601Z\", \"is_superuser\": true, \"username\": \"test\", \"first_name\": \"test\", \"last_name\": \"testerson\", \"email\": \"test@example.com\", \"is_staff\": true, \"is_active\": true, \"date_joined\": \"2014-10-19T22:01:00.601Z\", \"groups\": [], \"user_permissions\": [] } ] } ","categories":"","description":"This is the v2.2 REST API for the Controller.","excerpt":"This is the v2.2 REST API for the Controller.","ref":"/docs/reference-guide/controller-api-v2-2/","tags":"","title":"Controller API v2.2"},{"body":"Drycc Workflow manages your application as a set of processes that can be named, scaled and configured according to their role. This gives you the flexibility to easily manage the different facets of your application. For example, you may have web-facing processes that handle HTTP traffic, background worker processes that do async work, and a helper process that streams from the Twitter API.\nBy using a Procfile, either checked in to your application or provided via the CLI you can specify the name of the type and the application command that should run. To spawn other process types, use drycc scale \u003cptype\u003e=\u003cn\u003e to scale those types accordingly.\nDefault Process Types In the absence of a Procfile, a single, default process type is assumed for each application.\nApplications built using Buildpacks via git push implicitly receive a web process type, which starts the application server. Rails 4, for example, has the following process type:\nweb: bundle exec rails server -p $PORT All applications utilizing Dockerfiles have an implied web process type, which runs the Dockerfile’s CMD directive unmodified:\n$ cat Dockerfile FROM centos:latest COPY . /app WORKDIR /app CMD python -m SimpleHTTPServer 5000 EXPOSE 5000 For the above Dockerfile-based application, the web process type would run the Container CMD of python -m SimpleHTTPServer 5000.\nApplications utilizing remote Container images, a web process type is also implied, and runs the CMD specified in the Container image.\n!!! note The web process type is special as they’is the default process type that will receive HTTP traffic from Workflow’s routers. Other process types can be named arbitrarily.\nDeclaring Process Types If you use Buildpack or Dockerfile builds and want to override or specify additional process types, simply include a file named Procfile in the root of your application’s source tree.\nThe format of a Procfile is one process type per line, with each line containing the command to invoke:\n\u003cprocess type\u003e: \u003ccommand\u003e The syntax is defined as:\n\u003cprocess type\u003e – a lowercase alphanumeric string, is a name for your command, such as web, worker, urgentworker, clock, etc. \u003ccommand\u003e – a command line to launch the process, such as rake jobs:work. This example Procfile specifies two types, web and sleeper. The web process launches a web server on port 5000 and a simple process which sleeps for 900 seconds and exits.\n$ cat Procfile web: bundle exec ruby web.rb -p ${PORT:-5000} sleeper: sleep 900 If you are using remote Container images, you may define process types by either running drycc pull with a Procfile in your working directory, or by passing a stringified Procfile to the --procfile CLI option.\nFor example, passing process types inline:\n$ drycc pull drycc/example-go:latest --procfile=\"web: /app/bin/boot\" Read a Procfile in another directory:\n$ drycc pull drycc/example-go:latest --procfile=\"$(cat deploy/Procfile)\" Or via a Procfile located in your current, working directory:\n$ cat Procfile web: /bin/boot sleeper: echo \"sleeping\"; sleep 900 $ drycc pull -a steely-mainsail drycc/example-go Creating build... done $ drycc scale sleeper=1 -a steely-mainsail Scaling processes... but first, coffee! done in 0s NAME RELEASE STATE PTYPE READY RESTARTS STARTED steely-mainsail-sleeper-76c45b967c-4qm6w v3 up sleeper 1/1 0 2023-12-08T02:25:00UTC steely-mainsail-web-c4f44c4b4-7p7dh v3 up web 1/1 0 2023-12-08T02:25:00UTC !!! note Only process types of web will be scaled to 1 automatically. If you have additional process types remember to scale the process counts after creation.\nTo remove a process type simply scale it to 0:\n$ drycc scale sleeper=0 -a steely-mainsail Scaling processes... but first, coffee! done in 3s NAME RELEASE STATE PTYPE READY RESTARTS STARTED steely-mainsail-web-c4f44c4b4-7p7dh v3 up web 1/1 0 2023-12-08T02:25:00UTC Scaling Processes Applications deployed on Drycc Workflow scale out via the process model. Use drycc scale to control the number of containers that power your app.\n$ drycc scale web=5 -a iciest-waggoner Scaling processes... but first, coffee! done in 3s NAME RELEASE STATE PTYPE READY RESTARTS STARTED iciest-waggoner-web-c4f44c4b4-7p7dh v3 up web 1/1 0 2023-12-08T02:25:00UTC iciest-waggoner-web-c4f44c4b4-8p7dh v3 up web 1/1 0 2023-12-08T02:25:00UTC iciest-waggoner-web-c4f44c4b4-9p7dh v3 up web 1/1 0 2023-12-08T02:25:00UTC iciest-waggoner-web-c4f44c4b4-1p7dh v3 up web 1/1 0 2023-12-08T02:25:00UTC iciest-waggoner-web-c4f44c4b4-2p7dh v3 up web 1/1 0 2023-12-08T02:25:00UTC If you have multiple process types for your application you may scale the process count for each type separately. For example, this allows you to manage web process independently from background workers. For more information on process types see our documentation for Managing App Processes.\nIn this example, we are scaling the process type web to 5 but leaving the process type background with one worker.\n$ drycc scale web=5 Scaling processes... but first, coffee! done in 4s NAME RELEASE STATE PTYPE READY RESTARTS STARTED scenic-icehouse-web-3291896318-7lord v3 up web 1/1 0 2023-12-08T02:25:00UTC scenic-icehouse-web-3291896318-jn957 v3 up web 1/1 0 2023-12-08T02:25:00UTC scenic-icehouse-web-3291896318-rsekj v3 up web 1/1 0 2023-12-08T02:25:00UTC scenic-icehouse-web-3291896318-vwhnh v3 up web 1/1 0 2023-12-08T02:25:00UTC scenic-icehouse-web-3291896318-vokg7 v3 up web 1/1 0 2023-12-08T02:25:00UTC scenic-icehouse-web-3291896318-vokg7 v3 up web 1/1 0 2023-12-08T02:25:00UTC scenic-icehouse-background-3291896318-yf8kh v3 up web 1/1 0 2023-12-08T02:25:00UTC Scaling a process down, by reducing the process count, sends a TERM signal to the processes, followed by a SIGKILL if they have not exited within 30 seconds. Depending on your application, scaling down may interrupt long-running HTTP client connections.\nFor example, scaling from 5 processes to 3:\n$ drycc scale web=3 Scaling processes... but first, coffee! done in 1s NAME RELEASE STATE PTYPE READY RESTARTS STARTED scenic-icehouse-web-3291896318-vwhnh v2 up web 1/1 0 2023-12-08T02:25:00UTC scenic-icehouse-web-3291896318-vokg7 v2 up web 1/1 0 2023-12-08T02:25:00UTC scenic-icehouse-web-3291896318-vokg9 v2 up web 1/1 0 2023-12-08T02:25:00UTC scenic-icehouse-background-3291896318-yf8kh v2 up web 1/1 0 2023-12-08T02:25:00UTC Autoscale Autoscale allows adding a minimum and maximum number of pods on a per process type basis. This is accomplished by specifying a target CPU usage across all available pods.\nThis feature is built on top of Horizontal Pod Autoscaling in Kubernetes or HPA for short.\n!!! note This is an alpha feature. It is recommended to be on the latest Kubernetes when using this feature.\n$ drycc autoscale:set web --min=3 --max=8 --cpu-percent=75 Applying autoscale settings for process type web on scenic-icehouse... done And then review the scaling rule that was created for web\n$ drycc autoscale:list PTYPE PERCENT MIN MAX web 75 3 8 Remove scaling rule\n$ drycc autoscale:unset web Removing autoscale for process type web on scenic-icehouse... done For autoscaling to work CPU requests have to be specified on each application Pod (can be done via drycc limits --cpu). This allows the autoscale policies to do the appropriate calculations and make decisions on when to scale up and down.\nScale up can only happen if there was no rescaling within the last 3 minutes. Scale down will wait for 5 minutes from the last rescaling. That information and more can be found at HPA algorithm page.\nFetch a container logs of the application List the containers:\n$ drycc ps NAME RELEASE STATE PTYPEE READY RESTARTS STARTED python-getting-started-web-69b7d4bfdc-kl4xf v2 up web 1/1 0 2023-12-08T02:25:00UTC === python-getting-started Processes --- web: python-getting-started-web-69b7d4bfdc-kl4xf up (v2) fetch the container logs:\n$ drycc ps:logs -f python-getting-started-web-69b7d4bfdc-kl4xf [2024-05-24 07:14:39 +0000] [1] [INFO] Starting gunicorn 20.1.0 [2024-05-24 07:14:39 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1) [2024-05-24 07:14:39 +0000] [1] [INFO] Using worker: gevent [2024-05-24 07:14:39 +0000] [8] [INFO] Booting worker with pid: 8 [2024-05-24 07:14:39 +0000] [9] [INFO] Booting worker with pid: 9 [2024-05-24 07:14:39 +0000] [10] [INFO] Booting worker with pid: 10 [2024-05-24 07:14:39 +0000] [11] [INFO] Booting worker with pid: 11 Get a container info of the application List the containers:\n$ drycc ps:describe python-getting-started-web-69b7d4bfdc-kl4xf Container: python-getting-started-web Image: drycc/python-getting-started:latest Command: Args: - gunicorn - -c - gunicorn_config.py - helloworld.wsgi:application State: running startedAt: \"2024-05-24T07:14:39Z\" Ready: true Restart Count: 0 delete a container of the application Delete the containers. Due to the set number of replicas, a new container will be launched to meet the quantity requirement.\n$ drycc ps:delete python-getting-started-web-69b7d4bfdc-kl4xf Deleting python-getting-started-web-69b7d4bfdc-kl4xf from python-getting-started... done Get a Shell to a Running Container Verify that the container is running:\n$ drycc ps NAME RELEASE STATE PTYPEE READY RESTARTS STARTED python-getting-started-web-69b7d4bfdc-kl4xf v2 up web 1/1 0 2023-12-08T02:25:00UTC === python-getting-started Processes --- web: python-getting-started-web-69b7d4bfdc-kl4xf up (v2) Get a shell to the running container:\n$ drycc ps:exec python-getting-started-web-69b7d4bfdc-kl4xf -it -- bash In your shell, list the root directory:\n# Run this inside the container ls / Running individual commands in a container\n$ drycc ps:exec python-getting-started-web-69b7d4bfdc-kl4xf -- date Use “drycc ps –help” for a list of global command-line (applies to all commands).\nRestarting an Application Processes If you need to restart an application process, you may use drycc pts:restart. Behind the scenes, Drycc Workflow instructs Kubernetes to terminate the old process and launch a new one in its place.\n$ drycc ps NAME RELEASE STATE PTYPE READY RESTARTS STARTED scenic-icehouse-web-3291896318-vokg7 v2 up web 1/1 0 2023-12-08T02:25:00UTC scenic-icehouse-web-3291896318-rsekj v2 up web 1/1 0 2023-12-08T02:50:21UTC scenic-icehouse-web-3291896318-vokg7 v2 up web 1/1 0 2023-12-08T02:25:00UTC scenic-icehouse-background-3291896318-yf8kh v2 up web 1/1 0 2023-12-08T02:25:00UTC $ drycc pts:restart scenic-icehouse-background NAME RELEASE STATE PTYPE READY RESTARTS STARTED scenic-icehouse-web-3291896318-vokg7 v2 up web 1/1 0 2023-12-08T02:25:00UTC scenic-icehouse-web-3291896318-rsekj v2 up web 1/1 0 2023-12-08T02:50:21UTC scenic-icehouse-web-3291896318-vokg7 v2 up web 1/1 0 2023-12-08T02:25:00UTC scenic-icehouse-background-3291896318-yf8kh v2 starting web 1/1 0 2023-12-08T02:25:00UTC Notice that the process name has changed from scenic-icehouse-background-3291896318-yf8kh to scenic-icehouse-background-3291896318-yd87g. In a multi-node Kubernetes cluster, this may also have the effect of scheduling the Pod to a new node.\nUse “drycc pts –help” for a list of pts command-line (process types info).\nList an Application Process Types $ drycc pts NAME RELEASE READY UP-TO-DATE AVAILABLE STARTED web v2 3/3 1 1 2023-12-08T02:25:00UTC background v2 1/1 1 1 2023-12-08T02:25:00UTC Get deployment info of the application process type $ drycc pts:describe web Container: python-getting-started-web Image: drycc/python-getting-started:latest Command: Args: - gunicorn - -c - gunicorn_config.py - helloworld.wsgi:application Limits: cpu 1 ephemeral-storage 2Gi memory 1Gi Liveness: http-get headers=[] path=/geo/ port=8000 delay=120s timeout=10s period=20s #success=1 #failure=3 Readiness: http-get headers=[] path=/geo/ port=8000 delay=120s timeout=10s period=20s #success=1 #failure=3 ","categories":"","description":"A Procfile is a list of process types in an app. Each process type declares a command that is executed when a container of that process type is started.","excerpt":"A Procfile is a list of process types in an app. Each process type …","ref":"/docs/applications/managing-app-processes/","tags":"","title":"Managing Application Processes"},{"body":"","categories":"","description":"Managing Workflow using the kubectl.\n","excerpt":"Managing Workflow using the kubectl.\n","ref":"/docs/managing-workflow/","tags":"","title":"Managing Workflow"},{"body":"Description We now include a monitoring stack for introspection on a running Kubernetes cluster. The stack includes 4 components:\nkube-state-metrics, kube-state-metrics (KSM) is a simple service that listens to the Kubernetes API server and generates metrics about the state of the objects. Node Exporter, Prometheus exporter for hardware and OS metrics exposed by *NIX kernels. Prometheus, a Cloud Native Computing Foundation project, is a systems and service monitoring system. Grafana, Graphing tool for time series data Architecture Diagram ┌────────────────┐ │ HOST │ │ node-exporter │◀──┐ ┌──────────────────┐ └────────────────┘ │ │kube-state-metrics│ │ └──────────────────┘ ┌────────────────┐ │ ▲ │ HOST │ │ ┌────────────┐ │ │ node-exporter │◀──┼────│ Prometheus │─────────────┘ └────────────────┘ │ └────────────┘ │ ▲ ┌───────────────┐ │ │ │ HOST │ │ ▼ │ node-exporter│◀───┘ ┌──────────┐ └───────────────┘ │ Grafana │ └──────────┘ Grafana Grafana allows users to create custom dashboards that visualize the data captured to the running Prometheus component. By default Grafana is exposed using a service annotation through the router at the following URL: http://grafana.mydomain.com. The default login is admin/admin. If you are interested in changing these values please see [Tuning Component Settings][].\nGrafana will preload several dashboards to help operators get started with monitoring Kubernetes and Drycc Workflow. These dashboards are meant as starting points and don’t include every item that might be desirable to monitor in a production installation.\nDrycc Workflow monitoring by default does not write data to the host filesystem or to long-term storage. If the Grafana instance fails, modified dashboards are lost.\nProduction Configuration A production install of Grafana should have the following configuration values changed if possible:\nChange the default username and password from admin/admin. The value for the password is passed in plain text so it is best to set this value on the command line instead of checking it into version control. Enable persistence Use a supported external database such as mysql or postgres. You can find more information here On Cluster Persistence Enabling persistence will allow your custom configuration to persist across pod restarts. This means that the default sqllite database (which stores things like sessions and user data) will not disappear if you upgrade the Workflow installation.\nIf you wish to have persistence for Grafana you can set enabled to true in the values.yaml file before running helm install.\ngrafana: # Configure the following ONLY if you want persistence for on-cluster grafana # GCP PDs and EBS volumes are supported only persistence: enabled: true # Set to true to enable persistence size: 5Gi # PVC size Off Cluster Grafana If you wish to provide your own Grafana instance you can set grafanaLocation in the values.yaml file before running helm install.\nPrometheus Prometheus writes data to the host disk; however, if the prometheus pod dies and comes back on another host, the data will not be recovered. The prometheus graph UI is also exposed through the router allowing users to access the query engine by going to prometheus.mydomain.com.\nOn Cluster Persistence You can set node-exporter and kube-state-metrics to true or false in the values.yaml. If you wish to have persistence for Prometheus you can set enabled to true in the values.yaml file before running helm install.\nprometheus: prometheus-server: persistence: enabled: true # Set to true to enable persistence size: 10Gi # PVC size node-exporter: enabled: true kube-state-metrics: enabled: true Off Cluster Prometheus To use off-cluster Prometheus, please provide the following values in the values.yaml file before running helm install.\nglobal.prometheusLocation=off-cluster url = \"http://my.prometheus.url:9090\" ","categories":"","description":"Platform monitoring to your apps to spot issues in advance and respond to incidents quickly.","excerpt":"Platform monitoring to your apps to spot issues in advance and respond …","ref":"/docs/managing-workflow/platform-monitoring/","tags":"","title":"Platform Monitoring"},{"body":"Design Document Before opening a pull request, ensure your change also references a design document if the contribution is substantial. For more information, see Design Documents.\nSingle Issue It’s hard to reach agreement on the merit of a PR when it isn’t focused. When fixing an issue or implementing a new feature, resist the temptation to refactor nearby code or to fix that potential bug you noticed. Instead, open a separate issue or pull request. Keeping concerns separated allows pull requests to be tested, reviewed, and merged more quickly.\nSquash and rebase the commit or commits in your pull request into logical units of work with git. Include tests and documentation changes in the same commit, so that a revert would remove all traces of the feature or fix.\nMost pull requests will reference a GitHub issue. In the PR description - not in the commit itself - include a line such as “closes #1234”. The issue referenced will automatically be closed when your PR is merged.\nInclude Tests If you significantly alter or add functionality to a component that impacts the broader Drycc Workflow PaaS, you should submit a complementary PR to modify or amend end-to-end integration tests. These integration tests can be found in the drycc/workflow-e2e repository.\nSee testing for more information.\nInclude Docs Changes to any Drycc Workflow component that could affect a user’s experience also require a change or addition to the relevant documentation. For most Drycc components, this involves updating the component’s own documentation. In some cases where a component is tightly integrated into drycc/workflow, its documentation must also be updated.\nCross-repo commits If a pull request is part of a larger piece of work involving one or more additional commits in other Workflow repositories, these commits can be referenced in the last PR to be submitted. The downstream e2e test job will then supply every referenced commit (derived from PR issue number supplied) to the test runner so it can source the necessary Container images for inclusion in the generated Workflow chart to be tested.\nFor example, consider paired commits in drycc/controller and drycc/workflow-e2e. The commit body for the first PR in drycc/workflow-e2e would look like:\nfeat(foo_test): add e2e test for feature foo [skip e2e] test for controller#42 Adding [skip e2e] forgoes the e2e tests on this commit. This and any other required PRs aside from the final PR should be submitted first, so that their respective build and image push jobs run.\nLastly, the final PR in drycc/controller should be created with the required PR number(s) listed, in the form of [Rr]equires \u003crepoName\u003e#\u003cpullRequestNumber\u003e, for use by the downstream e2e run.\nfeat(foo): add feature foo Requires workflow-e2e#42 Code Standards Drycc components are implemented in Go and Python. For both languages, we agree with The Zen of Python, which emphasizes simple over clever. Readability counts.\nGo code should always be run through gofmt on the default settings. Lines of code may be up to 99 characters long. Documentation strings and tests are required for all exported functions. Use of third-party go packages should be minimal, but when doing so, such dependencies should be managed via the glide tool.\nPython code should always adhere to PEP8, the python code style guide, with the exception that lines of code may be up to 99 characters long. Docstrings and tests are required for all public methods, although the flake8 tool used by Drycc does not enforce this.\nCommit Style We follow a convention for commit messages borrowed from CoreOS, who borrowed theirs from AngularJS. This is an example of a commit:\nfeat(scripts/test-cluster): add a cluster test command this uses tmux to setup a test cluster that you can easily kill and start for debugging. To make it more formal, it looks something like this:\n{type}({scope}): {subject} \u003cBLANK LINE\u003e {body} \u003cBLANK LINE\u003e {footer} The allowed {types} are as follows:\nfeat -\u003e feature fix -\u003e bug fix docs -\u003e documentation style -\u003e formatting ref -\u003e refactoring code test -\u003e adding missing tests chore -\u003e maintenance The {scope} can be anything specifying the location(s) of the commit change(s).\nThe {subject} needs to be an imperative, present tense verb: “change”, not “changed” nor “changes”. The first letter should not be capitalized, and there is no dot (.) at the end.\nJust like the {subject}, the message {body} needs to be in the present tense, and includes the motivation for the change, as well as a contrast with the previous behavior. The first letter in a paragraph must be capitalized.\nAll breaking changes need to be mentioned in the {footer} with the description of the change, the justification behind the change and any migration notes required.\nAny line of the commit message cannot be longer than 72 characters, with the subject line limited to 50 characters. This allows the message to be easier to read on GitHub as well as in various git tools.\nMerge Approval Any code change - other than a simple typo fix or one-line documentation change - requires at least two Drycc maintainers to accept it. Maintainers tag pull requests with “LGTM1” and “LGTM2” (Looks Good To Me) labels to indicate acceptance.\nNo pull requests can be merged until at least one core maintainer signs off with an LGTM. The other LGTM can come from either a core maintainer or contributing maintainer.\nIf the PR is from a Drycc maintainer, then he or she should be the one to close it. This keeps the commit stream clean and gives the maintainer the benefit of revisiting the PR before deciding whether or not to merge the changes.\nAn exception to this is when an errant commit needs to be reverted urgently. If necessary, a PR that only reverts a previous commit can be merged without waiting for LGTM approval.\n","categories":"","description":"Proposed changes to Drycc projects are made as GitHub pull requests.","excerpt":"Proposed changes to Drycc projects are made as GitHub pull requests.","ref":"/docs/contribution-guidelines/submitting-a-pull-request/","tags":"","title":"Submitting a Pull Request"},{"body":"Drycc software is fully open source. As such, the “Drycc community” consists of anyone who uses the Drycc software and participates in its evolution, whether by answering questions, finding bugs, suggesting enhancements, or writing documentation or code.\nDrycc development is coordinated through numerous project repositories on GitHub. Anyone can check out the source code for any Drycc component, fork it, make improvements, and create a pull request to offer those changes back to the Drycc community.\nEngine Yard maintains the numerous Drycc projects, and as such, decides what ends up in the official GitHub repositories. Drycc depends on the contributions of the community; the maintainers will not ignore pull requests or issues.\nDrycc uses the timeless, highly efficient, and totally unfair system known as “Benevolent Dictator for Life” (BDFL). Gabriel Monroy, the creator of Drycc, is our BDFL and has final say over all decisions related to Drycc.\nOpen Source Bounties Drycc projects are bounty-friendly. We believe open source bounty sites can be constructive tools in the development of open source software. Community members are encouraged to a) offer bounties and b) receive bounties for open source contributions that benefit everyone. The Drycc maintainers, however, will not accept bounties on this project but are more than happy to help community members attempting bounties.\n","categories":"","description":"Drycc is an open source project that anyone in the community can use, improve, and enjoy. We'd love you to join us! Here's a few ways to find out what's happening and get involved.","excerpt":"Drycc is an open source project that anyone in the community can use, …","ref":"/docs/contribution-guidelines/community/","tags":"","title":"Community"},{"body":"What’s New New! /v2/apps/{name}/logs endpoint was fixed and no longer returns b'log data' and instead returns a normal string log data\nAuthentication Register a New User Example Request:\nPOST /v2/auth/register/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json { \"username\": \"test\", \"password\": \"opensesame\", \"email\": \"test@example.com\" } Optional Parameters:\n{ \"first_name\": \"test\", \"last_name\": \"testerson\" } Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"id\": 1, \"last_login\": \"2014-10-19T22:01:00.601Z\", \"is_superuser\": true, \"username\": \"test\", \"first_name\": \"test\", \"last_name\": \"testerson\", \"email\": \"test@example.com\", \"is_staff\": true, \"is_active\": true, \"date_joined\": \"2014-10-19T22:01:00.601Z\", \"groups\": [], \"user_permissions\": [] } Log in Example Request:\nPOST /v2/auth/login/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json {\"username\": \"test\", \"password\": \"opensesame\"} Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json {\"token\": \"abc123\"} Cancel Account Example Request:\nDELETE /v2/auth/cancel/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Who Am I Example Request:\nGET /v2/auth/whoami/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"id\": 1, \"last_login\": \"2014-10-19T22:01:00.601Z\", \"is_superuser\": true, \"username\": \"test\", \"first_name\": \"test\", \"last_name\": \"testerson\", \"email\": \"test@example.com\", \"is_staff\": true, \"is_active\": true, \"date_joined\": \"2014-10-19T22:01:00.601Z\", \"groups\": [], \"user_permissions\": [] } Regenerate Token note\nThis command could require administrative privileges\nExample Request:\nPOST /v2/auth/tokens/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Optional Parameters:\n{ \"username\" : \"test\" \"all\" : \"true\" } Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json {\"token\": \"abc123\"} Change Password Example Request:\nPOST /v2/auth/passwd/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 { \"password\": \"foo\", \"new_password\": \"bar\" } Optional parameters:\n{\"username\": \"testuser\"} note\nUsing the username parameter requires administrative privileges and makes the password parameter optional.\nExample Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Applications List all Applications Example Request:\nGET /v2/apps HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"count\": 1, \"next\": null, \"previous\": null, \"results\": [ { \"created\": \"2014-01-01T00:00:00UTC\", \"id\": \"example-go\", \"owner\": \"test\", \"structure\": {}, \"updated\": \"2014-01-01T00:00:00UTC\", \"url\": \"example-go.example.com\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } ] } Create an Application Example Request:\nPOST /v2/apps/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 Optional parameters:\n{\"id\": \"example-go\"} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"created\": \"2014-01-01T00:00:00UTC\", \"id\": \"example-go\", \"owner\": \"test\", \"structure\": {}, \"updated\": \"2014-01-01T00:00:00UTC\", \"url\": \"example-go.example.com\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Destroy an Application Example Request:\nDELETE /v2/apps/example-go/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 List Application Details Example Request:\nGET /v2/apps/example-go/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"created\": \"2014-01-01T00:00:00UTC\", \"id\": \"example-go\", \"owner\": \"test\", \"structure\": {}, \"updated\": \"2014-01-01T00:00:00UTC\", \"url\": \"example-go.example.com\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Update Application Details Example Request:\nPOST /v2/apps/example-go/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Optional parameters:\n{ \"owner\": \"test\" } Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 1.8.0 Content-Type: application/json Retrieve Application Logs Example Request:\nGET /v2/apps/example-go/logs/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Optional URL Query Parameters:\n?log_lines= Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: text/plain \"16:51:14 drycc[api]: test created initial release\\n\" Run one-off Commands POST /v2/apps/example-go/run/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 {\"command\": \"echo hi\"} Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json {\"exit_code\": 0, \"output\": \"hi\\n\"} Certificates List all Certificates Example Request:\nGET /v2/certs HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"count\": 1, \"next\": null, \"previous\": null, \"results\": [ { \"id\": 22, \"owner\": \"test\", \"san\": [], \"domains\": [], \"created\": \"2016-06-22.32.34:20Z\", \"updated\": \"2016-06-22.32.34:20Z\", \"name\": \"foo\", \"common_name\": \"bar.com\", \"fingerprint\": \"7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0\", \"expires\": \"2017-01-14T23:57:57Z\", \"starts\": \"2016-01-15T23:57:57Z\", \"issuer\": \"/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc\", \"subject\": \"/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc\" } ] } Get Certificate Details Example Request:\nGET /v2/certs/foo HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"id\": 22, \"owner\": \"test\", \"san\": [], \"domains\": [], \"created\": \"2016-06-22.32.34:20Z\", \"updated\": \"2016-06-22.32.34:20Z\", \"name\": \"foo\", \"common_name\": \"bar.com\", \"fingerprint\": \"7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0\", \"expires\": \"2017-01-14T23:57:57Z\", \"starts\": \"2016-01-15T23:57:57Z\", \"issuer\": \"/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc\", \"subject\": \"/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc\" } Create Certificate Example Request:\nPOST /v2/certs/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 { \"name\": \"foo\" \"certificate\": \"-----BEGIN CERTIFICATE-----\", \"key\": \"-----BEGIN RSA PRIVATE KEY-----\" } Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"id\": 22, \"owner\": \"test\", \"san\": [], \"domains\": [], \"created\": \"2016-06-22.32.34:20Z\", \"updated\": \"2016-06-22.32.34:20Z\", \"name\": \"foo\", \"common_name\": \"bar.com\", \"fingerprint\": \"7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0\", \"expires\": \"2017-01-14T23:57:57Z\", \"starts\": \"2016-01-15T23:57:57Z\", \"issuer\": \"/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc\", \"subject\": \"/C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=bar.com/emailAddress=engineering@drycc.cc\" } Destroy a Certificate Example Request:\nDELETE /v2/certs/foo HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Attach a Domain to a Certificate Example Request:\nPOST /v2/certs/foo/domain/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 { \"domain\": \"test.com\" } Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Remove a Domain from a Certificate Example Request:\nDELETE /v2/certs/foo/domain/test.com/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Enable or disable TLS Example Request:\nPOST /v2/apps/example-go/tls/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 { \"https_enforced\": true } Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"created\": \"2014-01-01T00:00:00UTC\", \"app\": \"example-go\", \"owner\": \"test\", \"https_enforced\": true, \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Get TLS status Example Request:\nGET /v2/apps/example-go/tls/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"created\": \"2014-01-01T00:00:00UTC\", \"app\": \"example-go\", \"owner\": \"test\", \"https_enforced\": false, \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Pods List all Pods Example Request:\nGET /v2/apps/example-go/pods/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"count\": 1, \"results\": [ { \"name\": \"go-v2-web-e7dej\", \"release\": \"v2\", \"started\": \"2014-01-01T00:00:00Z\", \"state\": \"up\", \"type\": \"web\" } ] } List all Pods by Type Example Request:\nGET /v2/apps/example-go/pods/web/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"count\": 1, \"results\": [ { \"name\": \"go-v2-web-e7dej\", \"release\": \"v2\", \"started\": \"2014-01-01T00:00:00Z\", \"state\": \"up\", \"type\": \"web\" } ] } Restart All Pods Example Request:\nPOST /v2/apps/example-go/pods/restart/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json [ { \"name\": \"go-v2-web-atots\", \"release\": \"v2\", \"started\": \"2016-04-11T21:07:54Z\", \"state\": \"up\", \"type\": \"web\" } ] Restart Pods by Type Example Request:\nPOST /v2/apps/example-go/pods/web/restart/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json [ { \"name\": \"go-v2-web-atots\", \"release\": \"v2\", \"started\": \"2016-04-11T21:07:54Z\", \"state\": \"up\", \"type\": \"web\" } ] Restart Pods by Type and Name Example Request:\nPOST /v2/apps/example-go/pods/go-v2-web-atots/restart/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json [ { \"name\": \"go-v2-web-atots\", \"release\": \"v2\", \"started\": \"2016-04-11T21:07:54Z\", \"state\": \"up\", \"type\": \"web\" } ] Scale Pods Example Request:\nPOST /v2/apps/example-go/scale/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 {\"web\": 3} Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Configuration List Application Configuration Example Request:\nGET /v2/apps/example-go/config/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"owner\": \"test\", \"app\": \"example-go\", \"values\": { \"PLATFORM\": \"drycc\" }, \"memory\": {}, \"cpu\": {}, \"tags\": {}, \"healthcheck\": {}, \"created\": \"2014-01-01T00:00:00UTC\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Create new Config Example Request:\nPOST /v2/apps/example-go/config/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 {\"values\": {\"HELLO\": \"world\", \"PLATFORM\": \"drycc\"}} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"owner\": \"test\", \"app\": \"example-go\", \"values\": { \"DRYCC_APP\": \"example-go\", \"DRYCC_RELEASE\": \"v3\", \"HELLO\": \"world\", \"PLATFORM\": \"drycc\" }, \"memory\": {}, \"cpu\": {}, \"tags\": {}, \"healthcheck\": {}, \"created\": \"2014-01-01T00:00:00UTC\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Unset Config Variable Example Request:\nPOST /v2/apps/example-go/config/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 {\"values\": {\"HELLO\": null}} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"owner\": \"test\", \"app\": \"example-go\", \"values\": { \"DRYCC_APP\": \"example-go\", \"DRYCC_RELEASE\": \"v4\", \"PLATFORM\": \"drycc\" }, \"memory\": {}, \"cpu\": {}, \"tags\": {}, \"healthcheck\": {}, \"created\": \"2014-01-01T00:00:00UTC\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Domains List Application Domains Example Request:\nGET /v2/apps/example-go/domains/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"count\": 1, \"next\": null, \"previous\": null, \"results\": [ { \"app\": \"example-go\", \"created\": \"2014-01-01T00:00:00UTC\", \"domain\": \"example.example.com\", \"owner\": \"test\", \"updated\": \"2014-01-01T00:00:00UTC\" } ] } Add Domain Example Request:\nPOST /v2/apps/example-go/domains/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 {'domain': 'example.example.com'} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"app\": \"example-go\", \"created\": \"2014-01-01T00:00:00UTC\", \"domain\": \"example.example.com\", \"owner\": \"test\", \"updated\": \"2014-01-01T00:00:00UTC\" } Remove Domain Example Request:\nDELETE /v2/apps/example-go/domains/example.example.com HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Builds List Application Builds Example Request:\nGET /v2/apps/example-go/build/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"app\": \"example-go\", \"created\": \"2014-01-01T00:00:00UTC\", \"dockerfile\": \"FROM drycc/slugrunner RUN mkdir -p /app WORKDIR /app ENTRYPOINT [\\\"/runner/init\\\"] ADD slug.tgz /app ENV GIT_SHA 060da68f654e75fac06dbedd1995d5f8ad9084db\", \"image\": \"example-go\", \"owner\": \"test\", \"procfile\": { \"web\": \"example-go\" }, \"sha\": \"060da68f\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Create Application Build Example Request:\nPOST /v2/apps/example-go/build/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 {\"image\": \"drycc/example-go:latest\"} Optional Parameters:\n{ \"procfile\": { \"web\": \"./cmd\" } } Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"app\": \"example-go\", \"created\": \"2014-01-01T00:00:00UTC\", \"dockerfile\": \"\", \"image\": \"drycc/example-go:latest\", \"owner\": \"test\", \"procfile\": {}, \"sha\": \"\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Releases List Application Releases Example Request:\nGET /v2/apps/example-go/releases/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"count\": 3, \"next\": null, \"previous\": null, \"results\": [ { \"app\": \"example-go\", \"build\": \"2.3d8e4b-600e-4425-a85c-ffc7ea607f61\", \"config\": \"ed637ceb-5d32-44bd-9406-d326a777a513\", \"created\": \"2014-01-01T00:00:00UTC\", \"owner\": \"test\", \"summary\": \"test changed nothing\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\", \"version\": 3 }, { \"app\": \"example-go\", \"build\": \"2.3d8e4b-600e-4425-a85c-ffc7ea607f61\", \"config\": \"95bd6dea-1685-4f78-a03d-fd7270b058d1\", \"created\": \"2014-01-01T00:00:00UTC\", \"owner\": \"test\", \"summary\": \"test deployed 060da68\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\", \"version\": 2 }, { \"app\": \"example-go\", \"build\": null, \"config\": \"95bd6dea-1685-4f78-a03d-fd7270b058d1\", \"created\": \"2014-01-01T00:00:00UTC\", \"owner\": \"test\", \"summary\": \"test created initial release\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\", \"version\": 1 } ] } List Release Details Example Request:\nGET /v2/apps/example-go/releases/v2/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"app\": \"example-go\", \"build\": null, \"config\": \"95bd6dea-1685-4f78-a03d-fd7270b058d1\", \"created\": \"2014-01-01T00:00:00UTC\", \"owner\": \"test\", \"summary\": \"test created initial release\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\", \"version\": 1 } Rollback Release Example Request:\nPOST /v2/apps/example-go/releases/rollback/ HTTP/1.1 Host: drycc.example.com Content-Type: application/json Authorization: token abc123 {\"version\": 1} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json {\"version\": 5} Keys List Keys Example Request:\nGET /v2/keys/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"count\": 1, \"next\": null, \"previous\": null, \"results\": [ { \"created\": \"2014-01-01T00:00:00UTC\", \"id\": \"test@example.com\", \"owner\": \"test\", \"public\": \"ssh-rsa \u003c...\u003e\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } ] } Add Key to User Example Request:\nPOST /v2/keys/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 { \"id\": \"example\", \"public\": \"ssh-rsa \u003c...\u003e\" } Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"created\": \"2014-01-01T00:00:00UTC\", \"id\": \"example\", \"owner\": \"example\", \"public\": \"ssh-rsa \u003c...\u003e\", \"updated\": \"2014-01-01T00:00:00UTC\", \"uuid\": \"de1bf5b5-4a72-4f94-a10c-d2a3741cdf75\" } Remove Key from User Example Request:\nDELETE /v2/keys/example HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Permissions List Application Permissions note\nThis does not include the app owner.\nExample Request:\nGET /v2/apps/example-go/perms/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"users\": [ \"test\", \"foo\" ] } Create Application Permission Example Request:\nPOST /v2/apps/example-go/perms/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 {\"username\": \"example\"} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Remove Application Permission Example Request:\nDELETE /v2/apps/example-go/perms/example HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 List Administrators Example Request:\nGET /v2/admin/perms/ HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"count\": 2, \"next\": null \"previous\": null, \"results\": [ { \"username\": \"test\", \"is_superuser\": true }, { \"username\": \"foo\", \"is_superuser\": true } ] } Grant User Administrative Privileges note\nThis command requires administrative privileges\nExample Request:\nPOST /v2/admin/perms HTTP/1.1 Host: drycc.example.com Authorization: token abc123 {\"username\": \"example\"} Example Response:\nHTTP/1.1 201 CREATED DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Remove User’s Administrative Privileges note\nThis command requires administrative privileges\nExample Request:\nDELETE /v2/admin/perms/example HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 204 NO CONTENT DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Users List all users note\nThis command requires administrative privileges\nExample Request:\nGET /v2/users HTTP/1.1 Host: drycc.example.com Authorization: token abc123 Example Response:\nHTTP/1.1 200 OK DRYCC_API_VERSION: 2.3 DRYCC_PLATFORM_VERSION: 2.3.0 Content-Type: application/json { \"count\": 1, \"next\": null, \"previous\": null, \"results\": [ { \"id\": 1, \"last_login\": \"2014-10-19T22:01:00.601Z\", \"is_superuser\": true, \"username\": \"test\", \"first_name\": \"test\", \"last_name\": \"testerson\", \"email\": \"test@example.com\", \"is_staff\": true, \"is_active\": true, \"date_joined\": \"2014-10-19T22:01:00.601Z\", \"groups\": [], \"user_permissions\": [] } ] } ","categories":"","description":"This is the v2.3 REST API for the Controller.","excerpt":"This is the v2.3 REST API for the Controller.","ref":"/docs/reference-guide/controller-api-v2-3/","tags":"","title":"Controller API v2.3"},{"body":"Configuring an Application A Drycc application stores config in environment variables.\nSetting Environment Variables Use drycc config to modify environment variables for a deployed application.\n$ drycc help config Valid commands for config: config:list list environment variables for an app config:set set environment variables for an app config:unset unset environment variables for an app config:pull extract environment variables to .env config:push set environment variables from .env Use `drycc help [command]` to learn more. When config is changed, a new release is created and deployed automatically.\nYou can set multiple environment variables with one drycc config:set command, or with drycc config:push and a local .env file.\n$ drycc config:set FOO=1 BAR=baz \u0026\u0026 drycc config:pull $ cat .env FOO=1 BAR=baz $ echo \"TIDE=high\" \u003e\u003e .env $ drycc config:push Creating config... done, v4 === yuppie-earthman DRYCC_APP: yuppie-earthman FOO: 1 BAR: baz TIDE: high It can also modify environment variables for a process type of application.\n$ drycc config:set FOO=1 BAR=baz --ptype=web Attach to Backing Services Drycc treats backing services like databases, caches and queues as attached resources. Attachments are performed using environment variables.\nFor example, use drycc config to set a DATABASE_URL that attaches the application to an external PostgreSQL database.\n$ drycc config:set DATABASE_URL=postgres://user:pass@example.com:5432/db === peachy-waxworks DATABASE_URL: postgres://user:pass@example.com:5432/db Detachments can be performed with drycc config:unset.\nBuildpacks Cache By default, apps using the [Imagebuilder][] will reuse the latest image data. When deploying applications that depend on third-party libraries that have to be fetched, this could speed up deployments a lot. In order to make use of this, the buildpack must implement the cache by writing to the cache directory. Most buildpacks already implement this, but when using custom buildpacks, it might need to be changed to make full use of the cache.\nDisabling and re-enabling the cache In some cases, cache might not speed up your application. To disable caching, you can set the DRYCC_DISABLE_CACHE variable with drycc config:set DRYCC_DISABLE_CACHE=1. When you disable the cache, Drycc will clear up files it created to store the cache. After having it turned off, run drycc config:unset DRYCC_DISABLE_CACHE to re-enable the cache.\nClearing the cache Use the following procedure to clear the cache:\n$ drycc config:set DRYCC_DISABLE_CACHE=1 $ git commit --allow-empty -m \"Clearing Drycc cache\" $ git push drycc # (if you use a different remote, you should use your remote name) $ drycc config:unset DRYCC_DISABLE_CACHE Custom Health Checks By default, Workflow only checks that the application starts in their Container. If it is preferred to have Kubernetes respond to application health, a health check may be added by configuring a health check probe for the application.\nThe health checks are implemented as Kubernetes container probes. A liveness and a readiness probe can be configured, and each probe can be of type httpGet, exec, or tcpSocket depending on the type of probe the container requires.\nA liveness probe is useful for applications running for long periods of time, eventually transitioning to broken states and cannot recover except by restarting them.\nOther times, a readiness probe is useful when the container is only temporarily unable to serve, and will recover on its own. In this case, if a container fails its readiness probe, the container will not be shut down, but rather the container will stop receiving incoming requests.\nhttpGet probes are just as it sounds: it performs a HTTP GET operation on the Container. A response code inside the 200-399 range is considered a pass.\nexec probes run a command inside the Container to determine its health, such as cat /var/run/myapp.pid or a script that determines when the application is ready. An exit code of zero is considered a pass, while a non-zero status code is considered a fail.\ntcpSocket probes attempt to open a socket in the Container. The Container is only considered healthy if the check can establish a connection. tcpSocket probes accept a port number to perform the socket connection on the Container.\nHealth checks can be configured on a per-proctype basis for each application using drycc healthchecks:set. If no type is mentioned then the health checks are applied to default proc type web, whichever is present. To configure a httpGet liveness probe:\n$ drycc healthchecks:set liveness httpGet 80 --ptype web Applying livenessProbe healthcheck... done App: peachy-waxworks UUID: afd84067-29e9-4a5f-9f3a-60d91e938812 Owner: dev Created: 2023-12-08T10:25:00Z Updated: 2023-12-08T10:25:00Z Healthchecks: liveness web http-get headers=[] path=/ port=80 delay=50s timeout=50s period=10s #success=1 #failure=3 If the application relies on certain headers being set (such as the Host header) or a specific URL path relative to the root, you can also send specific HTTP headers:\n$ drycc healthchecks:set liveness httpGet 80 \\ --path /welcome/index.html \\ --headers \"X-Client-Version:v1.0,X-Foo:bar\" Applying livenessProbe healthcheck... done App: peachy-waxworks UUID: afd84067-29e9-4a5f-9f3a-60d91e938812 Owner: dev Created: 2023-12-08T10:25:00Z Updated: 2023-12-08T10:25:00Z Healthchecks: liveness web http-get headers=[X-Client-Version=v1.0] path=/welcome/index.html port=80 delay=50s timeout=50s period=10s #success=1 #failure=3 To configure an exec readiness probe:\n$ drycc healthchecks:set readiness exec -- /bin/echo -n hello --ptype web Applying readinessProbe healthcheck... done App: peachy-waxworks UUID: afd84067-29e9-4a5f-9f3a-60d91e938812 Owner: dev Created: 2023-12-08T10:25:00Z Updated: 2023-12-08T10:25:00Z Healthchecks: readiness web exec /bin/echo -n hello delay=50s timeout=50s period=10s #success=1 #failure=3 You can overwrite a probe by running drycc healthchecks:set again:\n$ drycc healthchecks:set readiness httpGet 80 --ptype web Applying livenessProbe healthcheck... done App: peachy-waxworks UUID: afd84067-29e9-4a5f-9f3a-60d91e938812 Owner: dev Created: 2023-12-08T10:25:00Z Updated: 2023-12-08T10:25:00Z Healthchecks: liveness web http-get headers=[] path=/ port=80 delay=50s timeout=50s period=10s #success=1 #failure=3 Configured health checks also modify the default application deploy behavior. When starting a new Pod, Workflow will wait for the health check to pass before moving onto the next Pod.\nAutodeploy By default, Changes the config, limits or healthchecks and so on will trigger deploy. If you don’t want deploy, you can disable.\n$ drycc autodeploy:disable To re-enable autodeploy.\ndrycc autodeploy:enable you can deploy by executing the following command. deploy all ptypes\ndrycc releases:deploy deploy web process type, and support --force option to force deploy.\ndrycc releases:deploy web --force Autorollback By default, deployment failures will roll back to the previous successful version. If you don’t want this to happen, you can disable.\n$ drycc autorollback:disable To re-enable autorollback.\ndrycc autorollback:enable Isolate the Application Workflow supports isolating applications onto a set of nodes using drycc tags.\n!!! note In order to use tags, you must first launch your cluster with the proper node labels. If you do not, tag commands will fail. Learn more by reading “Assigning Pods to Nodes”.\nOnce your nodes are configured with appropriate label selectors, use drycc tags:set to restrict the application ptype to those nodes:\n$ drycc tags:set web environ=prod Applying tags... done, v4 environ prod ","categories":"","description":"How to store configuration of a Drycc app in the environment, keeping config out of code, making it easy to maintain app or deployment specific configs.","excerpt":"How to store configuration of a Drycc app in the environment, keeping …","ref":"/docs/applications/managing-app-configuration/","tags":"","title":"Configuring an Application"},{"body":"Create an authentication token Create an authentication token using the drycc client.\n# drycc tokens:add prometheus --password admin --username admin ! WARNING: Make sure to copy your token now. ! You won't be able to see it again, please confirm whether to continue. ! To proceed, type \"yes\" ! \u003e yes UUID USERNAME TOKEN 58176cf1-37a8-4c52-9b27-4c7a47269dfb admin 1F2c7A802aF640fd9F31dD846AdDf56BcMsay Add scrape configurations for prometheus A valid example file can be found here.\nThe global configuration specifies parameters that are valid in all other configuration contexts. They also serve as defaults for other configuration sections.\nglobal: scrape_interval: 60s evaluation_interval: 60s scrape_configs: - job_name: 'drycc' scheme: https metrics_path: /v2/apps/\u003cappname\u003e/metrics authorization: type: Token credentials: 1F2c7A802aF640fd9F31dD846AdDf56BcMsay static_configs: - targets: ['drycc.domain.com'] ","categories":"","description":"Metrics supports basic monitoring capabilities for Pod, providing various monitoring indicators such as CPU, memory, disk, network, etc., to meet the basic monitoring requirements for Pod resources.","excerpt":"Metrics supports basic monitoring capabilities for Pod, providing …","ref":"/docs/applications/managing-app-metrics/","tags":"","title":"Managing Application Metrics"},{"body":"Running Workflow without drycc storage In production, persistent storage can be achieved by running an external object store. For users on AWS, GCE/GKE or Azure, the convenience of Amazon S3, Google GCS or Microsoft Azure Storage makes the prospect of running a Storage-less Workflow cluster quite reasonable. For users who have restriction on using external object storage using swift object storage can be an option.\nRunning a Workflow cluster without Storage provides several advantages:\nRemoval of state from the worker nodes Reduced resource usage Reduced complexity and operational burden of managing Workflow See Configuring Object Storage for details on removing this operational complexity.\nReview Security Considerations There are some additional security-related considerations when running Workflow in production. See [Security Considerations][] for details.\nRegistration is Admin-Only By default, registration with the Workflow controller is in “admin_only” mode. The first user to run a drycc register command becomes the initial “admin” user, and registrations after that are disallowed unless requested by an admin.\nPlease see the following documentation to learn about changing registration mode:\nCustomizing Controller Disable Grafana Signups It is also recommended to disable signups for the Grafana dashboards.\nPlease see the following documentation to learn about disabling Grafana signups:\nCustomizing Monitor Running Workflow with RBAC If your cluster has RBAC amongst your authorization modes ($ kubectl api-versions should contains rbac.authorization.k8s.io) it may be necessary to enable RBAC in Workflow. This can be achieved by setting use_rbac in the global section of values.yaml to true, or by adding --set=global.use_rbac=true to the $ helm install/upgrade command. RBAC support was announced in Kubernetes-1.5 and is enabled by default if:\nyour Kubernetes cluster is in GKE your Kubernetes cluster built with kubeadm Note: helm may need to be given specific permissions under RBAC if not already done.\nAttention: Azure ACS Kubernetes clusters are not RBAC-enabled for today due to lack in authentication strategy. Feel free to watch this PR for more details.\n","categories":"","description":"When readying a Workflow deployment for production workloads, there are some additional recommendations.","excerpt":"When readying a Workflow deployment for production workloads, there …","ref":"/docs/managing-workflow/production-deployments/","tags":"","title":"Production Deployments"},{"body":"This upgrade process requires:\nHelm version 2.1.0 or newer Configured Off-Cluster Storage Upgrade Process !!! note If upgrading from a Helm Classic install, you’ll need to ‘migrate’ the cluster to a Kubernetes Helm installation. See Workflow-Migration for steps.\nStep 1: Apply the Workflow upgrade Helm will remove all components from the previous release. Traffic to applications deployed through Workflow will continue to flow during the upgrade. No service interruptions should occur.\nIf Workflow is not configured to use off-cluster Postgres, the Workflow API will experience a brief period of downtime while the database recovers from backup.\nFirst, find the name of the release helm gave to your deployment with helm ls, then run\n$ helm upgrade \u003crelease-name\u003e oci://registry.drycc.cc/charts/workflow Note: If using off-cluster object storage on gcs and/or off-cluster registry using gcr and intending to upgrade from a pre-v2.10.0 chart to v2.10.0 or greater, the key_json values will now need to be pre-base64-encoded. Therefore, assuming the rest of the custom/off-cluster values are defined in the existing values.yaml used for previous installs, the following may be run:\n$ B64_KEY_JSON=\"$(cat ~/path/to/key.json | base64 -w 0)\" $ helm upgrade \u003crelease_name\u003e drycc/workflow -f values.yaml --set gcs.key_json=\"${B64_KEY_JSON}\",registry-token-refresher.gcr.key_json=\"${B64_KEY_JSON}\" Alternatively, simply replace the appropriate values in values.yaml and do without the --set parameter. Make sure to wrap it in single quotes as double quotes will give a parser error when upgrading.\nStep 2: Verify Upgrade Verify that all components have started and passed their readiness checks:\n$ kubectl --namespace=drycc get pods NAME READY STATUS RESTARTS AGE drycc-builder-2448122224-3cibz 1/1 Running 0 5m drycc-controller-1410285775-ipc34 1/1 Running 3 5m drycc-controller-celery-694f75749b-cmxxn 3/3 Running 0 5m drycc-database-e7c5z 1/1 Running 0 5m drycc-logger-cgjup 1/1 Running 3 5m drycc-logger-fluentbit-45h7j 1/1 Running 0 5m drycc-logger-fluentbit-4z7lw 1/1 Running 0 5m drycc-logger-fluentbit-k2wsw 1/1 Running 0 5m drycc-logger-fluentbit-skdw4 1/1 Running 0 5m drycc-redis-8nazu 1/1 Running 0 5m drycc-monitor-grafana-tm266 1/1 Running 0 5m drycc-monitor-telegraf-51zel 1/1 Running 1 5m drycc-monitor-telegraf-cdasg 1/1 Running 0 5m drycc-monitor-telegraf-hea6x 1/1 Running 0 5m drycc-monitor-telegraf-r7lsg 1/1 Running 0 5m drycc-registry-1814324048-yomz5 1/1 Running 0 5m drycc-registry-proxy-4m3o4 1/1 Running 0 5m drycc-registry-proxy-no3r1 1/1 Running 0 5m drycc-registry-proxy-ou8is 1/1 Running 0 5m drycc-registry-proxy-zyajl 1/1 Running 0 5m drycc-rabbitmq-0 1/1 Running 0 5m Step 3: Upgrade the Drycc Client Users of Drycc Workflow should now upgrade their drycc client to avoid getting WARNING: Client and server API versions do not match. Please consider upgrading. warnings.\ncurl -sfL https://www.drycc.cc/install-cli.sh | bash - \u0026\u0026 sudo mv drycc $(which drycc) ","categories":"","description":"Drycc Workflow releases may be upgraded in-place with minimal downtime.","excerpt":"Drycc Workflow releases may be upgraded in-place with minimal …","ref":"/docs/managing-workflow/upgrading-workflow/","tags":"","title":"Upgrading Workflow"},{"body":"Track Application Changes Drycc Workflow tracks all changes to your application. Application changes are the result of either new application code pushed to the platform (via git push drycc master), or an update to application configuration (via drycc config:set KEY=VAL).\nEach time a build or config change is made to your application a new release is created. These release numbers increase monotonically.\nYou can see a record of changes to your application using drycc releases:\n$ drycc releases OWNER STATE VERSION CREATED SUMMARY dev succeed v3 2023-12-04T10:17:46Z dev deleted PIP_INDEX_URL, DISABLE_COLLECTSTATIC dev succeed v2 2023-12-01T10:20:22Z dev added IMAGE_PULL_POLICY, PIP_INDEX_URL, PORT, DISABLE_COLLEC[...] dev succeed v1 2023-11-30T17:54:57Z dev created initial release Rollback a Release Drycc Workflow also supports rolling back go previous releases. If buggy code or an errant configuration change is pushed to your application, you may rollback to a previously known, good release.\n!!! note All rollbacks create a new, numbered release. But will reference the build/code and configuration from the desired rollback point.\nIn this example, the application is currently running release v4. Using drycc rollback v2 tells Workflow to deploy the build and configuration that was used for release v2. This creates a new release named v5 whose contents are the source and configuration from release v2:\n$ drycc releases OWNER STATE VERSION CREATED SUMMARY dev succeed v3 2023-12-04T10:17:46Z dev deleted PIP_INDEX_URL, DISABLE_COLLECTSTATIC dev succeed v2 2023-12-01T10:20:22Z dev added IMAGE_PULL_POLICY, PIP_INDEX_URL, PORT, DISABLE_COLLEC[...] dev succeed v1 2023-11-30T17:54:57Z dev created initial release $ drycc rollback v2 Rolled back to v2 $ drycc releases OWNER STATE VERSION CREATED SUMMARY dev succeed v4 2023-12-04T10:20:46Z dev rolled back to v2 dev succeed v3 2023-12-04T10:17:46Z dev deleted PIP_INDEX_URL, DISABLE_COLLECTSTATIC dev succeed v2 2023-12-01T10:20:22Z dev added IMAGE_PULL_POLICY, PIP_INDEX_URL, PORT, DISABLE_COLLEC[...] dev succeed v1 2023-11-30T17:54:57Z dev created initial release Only rollback web process type:\n$ drycc rollback v3 web Rolled back to v3 $ drycc releases OWNER STATE VERSION CREATED SUMMARY dev succeed v5 2023-12-04T10:23:49Z dev rolled back to v3 dev succeed v4 2023-12-04T10:20:46Z dev rolled back to v2 dev succeed v3 2023-12-04T10:17:46Z dev deleted PIP_INDEX_URL, DISABLE_COLLECTSTATIC dev succeed v2 2023-12-01T10:20:22Z dev added IMAGE_PULL_POLICY, PIP_INDEX_URL, PORT, DISABLE_COLLEC[...] dev succeed v1 2023-11-30T17:54:57Z dev created initial release Run One-off Administration Tasks Drycc applications use one-off processes for admin tasks like database migrations and other commands that must run against the live application.\nUse drycc run to execute commands on the deployed application.\n$ drycc run 'ls -l' Running `ls -l`... total 28 -rw-r--r-- 1 root root 553 Dec 2 23:59 LICENSE -rw-r--r-- 1 root root 60 Dec 2 23:59 Procfile -rw-r--r-- 1 root root 33 Dec 2 23:59 README.md -rw-r--r-- 1 root root 1622 Dec 2 23:59 pom.xml drwxr-xr-x 3 root root 4096 Dec 2 23:59 src -rw-r--r-- 1 root root 25 Dec 2 23:59 system.properties drwxr-xr-x 6 root root 4096 Dec 3 00:00 target Share an Application Use drycc perms:add to allow another Drycc user to collaborate on your application.\n$ drycc perms:add otheruser view,change,delete Adding user otheruser as a collaborator for view,change,delete peachy-waxwork... done Use drycc perms to see who an application is currently shared with, and drycc perms:remove to remove a collaborator.\n!!! note Collaborators can do anything with an application that its owner can do, except delete the application.\nWhen working with an application that has been shared with you, clone the original repository and add Drycc’ git remote entry before attempting to git push any changes to Drycc.\n$ git clone https://github.com/drycc/example-java-jetty.git Cloning into 'example-java-jetty'... done $ cd example-java-jetty $ git remote add -f drycc ssh://git@local3.dryccapp.com:2222/peachy-waxworks.git Updating drycc From drycc-controller.local:peachy-waxworks * [new branch] master -\u003e drycc/master Application Troubleshooting Applications deployed on Drycc Workflow treat logs as event streams. Drycc Workflow aggregates stdout and stderr from every Container making it easy to troubleshoot problems with your application.\nUse drycc logs to view the log output from your deployed application.\n$ drycc logs -f Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.5]: INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null} Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.8]: INFO:oejs.Server:jetty-7.6.0.v20120127 Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.5]: INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:10005 Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.6]: INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null} Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.7]: INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null} Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.6]: INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:10006 Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.8]: INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null} Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.7]: INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:10007 Dec 3 00:30:31 ip-10-250-15-201 peachy-waxworks[web.8]: INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:10008 ","categories":"","description":"This is a high-level, technical description of how Drycc works. It ties together many of the concepts you'll encounter while writing, configuring, deploying and running applications on the Drycc platform.","excerpt":"This is a high-level, technical description of how Drycc works. It …","ref":"/docs/applications/managing-app-lifecycle/","tags":"","title":"Managing an Application"},{"body":"Triage helps ensure issues resolve quickly by:\nDescribing the issue’s intent and purpose is conveyed precisely. This is necessary because it can be difficult for an issue to explain how an end user experiences an problem and what actions they took. Giving a contributor the information they need before they commit to resolving an issue. Lowering the issue count by preventing duplicate issues. Streamlining the development process by preventing duplicate discussions. If you don’t have time to code, consider helping with triage. The community will thank you for saving them time by spending some of yours.\nEnsure the Issue Contains Basic Information Before triaging an issue very far, make sure that the issue’s author provided the standard issue information. This will help you make an educated recommendation on how this to categorize the issue. Standard information that should be included in most issues are things such as:\nthe version(s) of Drycc this issue affects a reproducible case if this is a bug page URL if this is a docs issue or the name of a man page Depending on the issue, you might not feel all this information is needed. Use your best judgment. If you cannot triage an issue using what its author provided, explain kindly to the author that they must provide the above information to clarify the problem.\nIf the author provides the recommended information but you are still unable to triage the issue, request additional information. Do this kindly and politely because you are asking for more of the author’s time.\nIf the author does not respond requested information within the timespan of a week, close the issue with a kind note stating that the author can request for the issue to be reopened when the necessary information is provided.\nClassifying the Issue An issue can have multiple of the following labels:\nIssue Kind Kind Description bug Bugs are bugs. The cause may or may not be known at triage time so debugging should be taken account into the time estimate. docs Writing documentation, man pages, articles, blogs, or other significant word-driven task. enhancement Enhancements can drastically improve usability or performance of a component. question Contains a user or contributor question requiring a response. security Security-related issues such as TLS encryption, network segregation, authn/authz features, etc. Functional Area builder cache contrib and provisioning client controller database docs kubernetes registry router store (Ceph) tests Easy Fix “Easy Fix” issues are a way for a new contributor to find issues that are fit for their experience level. These issues are typically for users who are new to Drycc, and possibly Go, and is looking to help while learning the basics.\nPrioritizing issues When attached to a specific milestone, an issue can be attributed one of the following labels to indicate their degree of priority.\nPriority Description priority 0 Urgent: Security, critical bugs, blocking issues. Drop everything and fix this today, then consider creating a patch release. priority 1 Serious: Impedes user actions or is a regression. Fix this before the next planned release. And that’s it. That should be all the information required for a new or existing contributor to come in an resolve an issue.\n","categories":"","description":"Issue triage provides an important way to contribute to an open source project.","excerpt":"Issue triage provides an important way to contribute to an open source …","ref":"/docs/contribution-guidelines/triaging-issues/","tags":"","title":"Triaging Issues"},{"body":"","categories":"","description":"Troubleshooting is systematic approach to problem-solving.\n","excerpt":"Troubleshooting is systematic approach to problem-solving.\n","ref":"/docs/troubleshooting/","tags":"","title":"Troubleshooting"},{"body":"Conduct The Drycc community welcomes and encourages participation by everyone.\nNo matter how you identify yourself or how others perceive you: we welcome you. We welcome contributions from everyone as long as they interact constructively with our community.\nThe Drycc developer community continues to grow, and it is inevitable that disagreements and conflict will arise. We ask that participants conduct themselves according to these principles:\nBe welcoming, friendly, and patient.\nBe considerate.\nYour work will be used by other people, and you in turn will depend on the work of others. Any decision you take will affect users and colleagues, and you should take those consequences into account when making decisions. Remember that we’re a world-wide community, so you might not be communicating in someone else’s primary language.\nBe respectful. Not all of us will agree all the time, but disagreement is no excuse for poor behavior and bad manners. We might all experience some frustration now and then, but we cannot allow that frustration to turn into a personal attack. It’s important to remember that a community where people feel uncomfortable or threatened is not a productive one.\nBe careful in the words that you choose. Be kind to others. Do not insult or put down other participants. Behave professionally. Remember that harassment and sexist, racist, or exclusionary jokes are never appropriate for the community.\n(Thanks to the Debian and Django communities for their text and their inspiration.)\n","categories":"","description":"The Drycc community welcomes and encourages participation by **everyone**.","excerpt":"The Drycc community welcomes and encourages participation by …","ref":"/docs/contribution-guidelines/conduct/","tags":"","title":"Conduct"},{"body":"We can use the blow command to create volumes and mount the created volumes. Drycc create volume support ReadWriteMany, so before deploying drycc, you need to have a StorageClass ready which can support ReadWriteMany. Deploying drycc, set controller.appStorageClass to this StorageClass.\nUse drycc volumes to mount a volume for a deployed application’s processes.\n$ drycc help volumes Valid commands for volumes: volumes:create create a volume for the application volumes:list list volumes in the application volumes:delete delete a volume from the application volumes:client the client used to manage volume files volumes:mount mount a volume to process of the application volumes:unmount unmount a volume from process of the application Use 'drycc help [command]' to learn more. Create a volume for the application You can create a csi volume with the drycc volumes:create command.\n$ drycc volumes:create myvolume 200M Creating myvolumes to scenic-icehouse... done Or use an existing nfs server\n$ drycc volumes:create myvolume 200M -t nfs --nfs-server=nfs.drycc.com --nfs-path=/ Creating myvolumes to scenic-icehouse... done List volumes in the application After volume is created, you can list the volumes in this application.\n$ drycc volumes:list === scenic-icehouse volumes --- myvolumes 200M Mount a volume The volume which is named myvolumes is created, you can mount the volume with process of the application, use the command of drycc volumes:mount. When volume is mounted, a new release will be created and deployed automatically.\n$ drycc volumes:mount myvolumes web=/data/web Mounting volume... done And use drycc volumes:list show mount detail.\n$ drycc volumes:list === scenic-icehouse volumes --- myvolumes 200M web /data/web If you don’t need the volume, use drycc volumes:unmount to unmount the volume and then use drycc volumes:delete to delete the volume from the application. Before deleting volume, the volume has to be unmounted.\n$ drycc volumes:unmount myvolumes web Unmounting volume... done $ drycc volumes:delete myvolumes Deleting myvolumes from scenic-icehouse... done Use volume client to manage volume files. Assume the volume which is named myvolumes is created and mounted.\nPrepare a file named testfile.\n$ echo \"testtext\" \u003e testfile Upload. $ drycc volumes:client cp testfile vol://myvolume/ [↑] testfile 100% [==================================================] (5/ 5 B, 355 B/s)\nList files in myvolume.\n$ drycc volumes:client ls vol://myvolume/ [2024-07-22T15:32:28+08:00] 5 testfile Delete testfle in myvolume.\n$ drycc volumes:client rm vol://myvolume/testfile ","categories":"","description":"Drycc supports many types of volumes. A container can use any number of volume types simultaneously.","excerpt":"Drycc supports many types of volumes. A container can use any number …","ref":"/docs/applications/managing-app-volumes/","tags":"","title":"Mounting volumes for an Application"},{"body":"","categories":"","description":"Browse the ever-growing list of up-to-date, community driven roadmaps.\n","excerpt":"Browse the ever-growing list of up-to-date, community driven roadmaps. …","ref":"/docs/roadmap/","tags":"","title":"Roadmap"},{"body":"","categories":"","description":"This HowTo is for project maintainers who need a Contributing Guide for their project.\n","excerpt":"This HowTo is for project maintainers who need a Contributing Guide …","ref":"/docs/contribution-guidelines/","tags":"","title":"Contribution Guidelines"},{"body":"What is a maintainer? (Unabashedly stolen from the Podman project)\nThere are different types of maintainers, with different responsibilities, but all maintainers have 3 things in common:\nThey share responsibility in the project’s success. They have made a long-term, recurring time investment to improve the project. They spend that time doing whatever needs to be done, not necessarily what is the most interesting or fun. Maintainers are often under-appreciated, because their work is harder to appreciate. It’s easy to appreciate a really cool and technically advanced feature. It’s harder to appreciate the absence of bugs, the slow but steady improvement in stability, or the reliability of a release process. But those things distinguish a good project from a great one.\nDrycc maintainers Drycc has two groups of maintainers in addition to our beloved Benevolent Dictator for Life.\nBDFL Drycc follows the timeless, highly efficient and totally unfair system known as Benevolent dictator for life.\nGabriel Monroy (@gabrtv), as creator of the Drycc project, serves as our project’s BDFL. While the day-to-day project management is carried out by the maintainers, Gabriel serves as the final arbiter of any disputes and has the final say on project direction.\nCore maintainers Core maintainers are exceptionally knowledgeable about all areas of Drycc. Some maintainers work on Drycc full-time, although this is not a requirement.\nThe duties of a core maintainer include:\nClassify and respond to GitHub issues and review pull requests Help to shape the Drycc roadmap and lead efforts to accomplish roadmap milestones Participate actively in feature development and bug fixing Answer questions and help users in the Drycc #community Slack channel The current list of core maintainers can be seen here.\nNo pull requests can be merged until at least one core maintainer signs off with an LGTM. The other LGTM can come from either a core maintainer or contributing maintainer.\nContributing maintainers Contributing maintainers are exceptionally knowledgeable about some but not necessarily all areas of Drycc, and are often selected due to specific domain knowledge that complements the project (but a willingness to continually contribute to the project is most important!). Often, core maintainers will ask a contributing maintainer to weigh in on issues, pull requests, or conversations where the contributing maintainer is knowledgeable.\nThe duties of a contributing maintainer are very similar to those of a core maintainer, but they are limited to areas of the Drycc project where the contributing maintainer is knowledgeable.\nContributing maintainers are defined in practice as those who have write access to the Drycc repository. All maintainers can review pull requests and add LGTM labels as appropriate.\nBecoming a maintainer The Drycc project wouldn’t be where it is today without its community. Many of the project’s community members embody the spirit of maintainership, and have contributed substantially to the project.\nThe contributing maintainers group was created in part so that exceptional members of the community who have an interest in the continued success of the project have the opportunity to join the core maintainers in guiding the future of Drycc.\nGenerally, potential contributing maintainers are selected by the Drycc core maintainers based in part on the following criteria:\nSustained contributions to the project over a period of time (usually months) A willingness to help Drycc users on GitHub and in the Drycc #community Slack channel A friendly attitude :) The Drycc core maintainers must unanimously agree before inviting a community member to join as a contributing maintainer, although in many cases the candidate has already been acting in the capacity of a contributing maintainer for some time, and has been consulted on issues, pull requests, etc.\n","categories":"","description":"This document serves to describe the leadership structure of the Drycc project, and list the current project maintainers.","excerpt":"This document serves to describe the leadership structure of the Drycc …","ref":"/docs/contribution-guidelines/maintainers/","tags":"","title":"Drycc Maintainers"},{"body":"A Gateway describes how traffic can be translated to Services within the cluster. That is, it defines a request for a way to translate traffic from somewhere that does not know about Kubernetes to somewhere that does. For example, traffic sent to a Kubernetes Service by a cloud load balancer, an in-cluster proxy, or an external hardware load balancer. While many use cases have client traffic originating “outside” the cluster, this is not a requirement.\nCreate Gateway for an Application Gateway is a way of exposing services externally, which generates an external IP address to connect route and service. After deploy, the gateway has been created.\nList the containers:\n# drycc gateways NAME LISENTER PORT PROTOCOL ADDRESSES python-getting-started tcp-80-0 80 HTTP 101.65.132.51 You can also add a port in this gateway or create a one.\n# drycc gateways:add python-getting-started --port=443 --protocol=HTTPS Adding gateway python-getting-started to python-getting-started... done Create service for an Application Service is a way of exposing services internally, creating a service generates an internal DNS that can access ptype. the web process type has been created, for others types, you should add as needed.\nList the services:\n$ drycc services PTYPE PORT PROTOCOL TARGET-PORT DOMAIN web 80 TCP 8000 python-getting-started.python-getting-started.svc.cluster.local Add a new service for process type\n# drycc services:add --help # drycc services:add sleep 8001:8001 Create Route for an Application A Gateway may be attached to one or more Route references which serve to direct traffic for a subset of traffic to a specific service. Same as the above, the web process type already bind the gateway and servies.\n# drycc routes NAME OWNER PTYPE KIND SERVICE-PORT GATEWAY LISTENER-PORT python-getting-started demo web HTTPRoute 80 python-getting-started 80 create a new route and attach gateway.\ndrycc routes:create sleep --ptype=sleep --kind=HTTPRoute --port=8001 drycc routes:attach sleep --gateway=python-getting-started --port=80 ","categories":"","description":"A Gateway describes how traffic can be translated to Services within the cluster.","excerpt":"A Gateway describes how traffic can be translated to Services within …","ref":"/docs/applications/managing-app-gateway/","tags":"","title":"About gateway for an Application"},{"body":"We can use blow command to create resources and bind which resource is created. This command depend on service-catalog.\nUse drycc resources to create and bind a resource for a deployed application.\n$ drycc help resources Valid commands for resources: resources:services list all available resource services resources:plans list all available plans for an resource services resources:create create a resource for the application resources:list list resources in the application resources:describe get a resource detail info in the application resources:update update a resource from the application resources:destroy delete a resource from the applicationa resources:bind bind a resource to servicebroker resources:unbind unbind a resource from servicebroker Use 'drycc help [command]' to learn more. List all available resource services You can list available resource services with one drycc resources:services command\n$ drycc resources:services ID NAME UPDATEABLE 15032a52-33c2-4b40-97aa-ceb972f51509 airflow true b7cb26a4-b258-445c-860b-a664239a67f8 cloudbeaver true 9ce3c3ba-33b5-4e4e-a5e9-a338a83d5070 flink true b80c51a1-957c-4d93-b3d5-efde84cd8031 fluentbit true fff5b6c7-ed85-429b-8265-493e40cc53c7 grafana true 412e368f-bf78-4798-92cc-43343119a57d kafka true ea2a9b87-fbc4-4e2a-adee-161c1f91d98d minio true 383f7316-84f3-4955-8491-1d4b02b749c8 mongodb true fbee746b-f3a7-4bef-8b55-cbecfd4c8ac3 mysql-cluster true 5975094d-45cc-4e85-8573-f93937d026c7 opensearch true 1db95161-7193-4544-8c76-e5ad5f6c03f6 pmm true 5cfb0abf-276c-445b-9060-9aa964ede87d postgresql-cluster true b8f70264-eafc-4b2f-848e-2ec0d059032b prometheus true f8186d36-f334-4094-8e02-d21a61da657b rabbitmq true e1fd0d37-9046-4152-a29b-d155c5657c8b redis true 7d2b64c6-0b59-4f08-a2f5-7b17cea6e5ee redis-cluster true 2e6877df-86e7-4bcc-a869-2a9b6847a465 seaweedfs true 4aea5c0f-9495-420d-896a-ffc61a3eced5 spark true b50db3b5-8d5f-4be9-b8bd-467ecd6cc11d zookeeper true List all available plans for an resource services You can list all available plans for an resource services with one drycc resources:plans command\n$ drycc resources:plans redis ID NAME DESCRIPTION 8d659058-a3b4-4058-b039-cc03a31b9442 standard-128 Redis standard-128 plan which limit resources memory size 128Mi. 36e3dbec-fc51-4f6b-9baa-e31e316858be standard-256 Redis standard-256 plan which limit resources memory size 256Mi. 560817c2-5aa1-41c4-9ee6-a77e3ee552d5 standard-512 Redis standard-512 plan which limit resources memory size 512Mi. d544d989-9fb8-43e9-a74e-0840ce1b8f0f standard-1024 Redis standard-1024 plan which limit resources memory size 1Gi. ad51b7bb-9b12-4ffd-8e49-010c0141b263 standard-2048 Redis standard-2048 plan which limit resources memory size 2Gi. 5097d76e-557c-453f-bdb1-54009e0df78d standard-4096 Redis standard-4096 plan which limit resources memory size 4Gi. be3fa2d0-36d2-47c5-9561-9deffe5ba373 standard-8192 Redis standard-8192 plan which limit resources memory size 8Gi. 4ca812a8-d7c3-439f-96cd-26523e88400e standard-16384 Redis standard-16384 plan which limit resources memory size 16Gi. b7f2a71f-0d97-48fd-8eed-aab24a7822f3 standard-32768 Redis standard-32768 plan which limit resources memory size 32Gi. 25c6b5d5-7505-47c8-95b1-dc9bdc698063 standard-65536 Redis standard-65536 plan which limit resources memory size 64Gi. Create resource in application You can create a resource with one drycc resources:create command\n$ drycc resources:create redis:1000 redis Creating redis to scenic-icehouse... done After resources are created, you can list the resources in this application.\n$ drycc resources:list UUID NAME OWNER PLAN UPDATED 07220e9e-d54d-4d74-a88c-f464aa374386 redis admin redis:standard-128 2024-05-08T01:01:00Z Bind resources The resource which is named redis is created, you can bind the redis to the application, use the command of drycc resources:bind redis.\n$ drycc resources:bind redis Binding resource... done Describe resources And use drycc resources:describe show the binding detail. If the binding is successful, this command will show the information of connect to the resource.\n$ drycc resources:describe redis === scenic-icehouse resource redis plan: redis:1000 status: Ready binding: Ready REDISPORT: 6379 REDIS_PASSWORD: RzG87SJWG1 SENTINELHOST: 172.16.0.2 SENTINELPORT: 26379 Update resources You can use the drycc resources:update command to upgrade a new plan. An example of how to upgrade the plan’s capacity to 100MB:\n$ drycc resources:update redis:10000 redis Updating redis to scenic-icehouse... done Remove the resource If you don’t need resources, use drycc resources:unbind to unbind the resource and then use drycc resources:destroy to delete the resource from the application. Before deleting the resource, the resource must be unbinded.\n$ drycc resources:unbind redis Unbinding resource... done $ drycc resources:destroy redis Deleting redis from scenic-icehouse... done ","categories":"","description":"Tools and services for developing, extending, and operating your app.","excerpt":"Tools and services for developing, extending, and operating your app.","ref":"/docs/applications/managing-app-resources/","tags":"","title":"Managing resources for an Application"},{"body":"","categories":"","description":"","excerpt":"","ref":"/blog/news/","tags":"","title":"News"},{"body":"","categories":"","description":"Reference gxwuide definition and meaning.\n","excerpt":"Reference gxwuide definition and meaning.\n","ref":"/docs/reference-guide/","tags":"","title":"Reference Guide"},{"body":"A common architecture pattern of multi-process applications is to have one process serve public requests while having multiple other processes supporting the public one to, for example, perform actions on a schedule or process work items from a queue. To implement this system of apps in Drycc Workflow, set up the apps to communicate using DNS resolution, as shown above, and hide the supporting processes from public view by removing them from the Drycc Workflow router.\nDNS Service Discovery Drycc Workflow supports deploying a single app composed of a system of processes. Each Drycc Workflow app communicates on a single port, so communicating with another Workflow app means finding that app’s address and port. All Workflow apps are mapped to port 80 externally, so finding its IP address is the only challenge. Workflow creates a Kubernetes Service for each app, which effectively assigns a name and one cluster-internal IP address to an app. The DNS service running in the cluster adds and removes DNS records which point from the app name to its IP address as services are added and removed. Drycc Workflow apps, then, can simply send requests to the domain name given to the service, which is “app-name.app-namespace”.\n","categories":"","description":"The Communication Solution between Drycc Applicatios.","excerpt":"The Communication Solution between Drycc Applicatios.","ref":"/docs/applications/inter-app-communication/","tags":"","title":"Inter-app Communication"},{"body":" Managing Application Resource Limits Drycc Workflow supports restricting memory and CPU shares of each process. Requests/Limits set on a per-process type are given to Kubernetes as a requests and limits. Which means you guarantee \u003crequests\u003e amount of resource for a process as well as limit the process from using more than \u003climits\u003e. By default, Kubernetes will set \u003crequests\u003e equal to \u003climit\u003e if we don’t explicitly set \u003crequests\u003e value. Please keep in mind that 0 \u003c= requests \u003c= limits.\nLimiting If you set a requests/limits that is out of range for your cluster, Kubernetes will be unable to schedule your application processes into the cluster!\n$ drycc limits:plans ID SPEC CPU VCPUS MEMORY FEATURES std1.large.c1m1 std1 Universal CPU 1 1 GiB Integrated GPU shared std1.large.c1m2 std1 Universal CPU 1 2 GiB Integrated GPU shared std1.large.c1m4 std1 Universal CPU 1 4 GiB Integrated GPU shared std1.large.c1m8 std1 Universal CPU 1 8 GiB Integrated GPU shared std1.large.c2m2 std1 Universal CPU 2 2 GiB Integrated GPU shared std1.large.c2m4 std1 Universal CPU 2 4 GiB Integrated GPU shared std1.large.c2m8 std1 Universal CPU 2 8 GiB Integrated GPU shared std1.large.c2m16 std1 Universal CPU 2 16 GiB Integrated GPU shared $ drycc limits:set web=std1.large.c1m1 Applying limits... done ","categories":"","description":"Drycc Workflow supports restricting memory and CPU shares of each process.","excerpt":"Drycc Workflow supports restricting memory and CPU shares of each …","ref":"/docs/applications/managing-resource-limits/","tags":"","title":"Resource Limits"},{"body":"You can use drycc domains to add or remove custom domains to the application:\n$ drycc domains:add hello.bacongobbler.com --ptype=web Adding hello.bacongobbler.com to finest-woodshed... done Once that’s done, you can go into a DNS registrar and set up a CNAME from the new appname to the old one:\n$ dig hello.dryccapp.com [...] ;; ANSWER SECTION: hello.bacongobbler.com. 1759 IN CNAME finest-woodshed.dryccapp.com. finest-woodshed.dryccapp.com. 270 IN A 172.17.8.100 !!! note Setting a CNAME for a root domain can cause issues. Setting an @ record to be a CNAME causes all traffic to go to the other domain, including mail and the SOA (“start-of-authority”) records. It is highly recommended that you bind a subdomain to an application, however you can work around this by pointing the @ record to the address of the load balancer (if any).\nTo add or remove the application from the routing mesh, use drycc routing:\n$ drycc routing:disable Disabling routing for finest-woodshed... done This will make the application unreachable through the Router, but the application is still reachable internally through its Kubernetes Service. To re-enable routing:\n$ drycc routing:enable Enabling routing for finest-woodshed... done ","categories":"","description":"Make your apps accessible via custom domain names.","excerpt":"Make your apps accessible via custom domain names.","ref":"/docs/applications/domains-and-routing/","tags":"","title":"Domains and Routing"},{"body":"Application SSL Certificates SSL is a cryptographic protocol that provides end-to-end encryption and integrity for all web requests. Apps that transmit sensitive data should enable SSL to ensure all information is transmitted securely.\nTo enable SSL on a custom domain, e.g., www.example.com, use the SSL endpoint.\n!!! note drycc certs is only useful for custom domains. Default application domains are SSL-enabled already and can be accessed simply by using https, e.g. https://foo.dryccapp.com (provided that you have installed your wildcard certificate on the routers or on the load balancer).\nOverview Because of the unique nature of SSL validation, provisioning SSL for your domain is a multi-step process that involves several third-parties. You will need to:\nPurchase an SSL certificate from your SSL provider Upload the cert to Drycc Acquire SSL Certificate Purchasing an SSL cert varies in cost and process depending on the vendor. RapidSSL offers a simple way to purchase a certificate and is a recommended solution. If you’re able to use this provider, see buy an SSL certificate with RapidSSL for instructions.\nDNS and Domain Configuration Once the SSL certificate is provisioned and your cert is confirmed, you must route requests for your domain through Drycc. Unless you’ve already done so, add the domain specified when generating the CSR to your app with:\n$ drycc domains:add www.example.com --ptype==web -a foo Adding www.example.com to foo... done Add a Certificate Add your certificate, any intermediate certificates, and private key to the endpoint with the certs:add command.\n$ drycc certs:add example-com server.crt server.key -a foo Adding SSL endpoint... done www.example.com !!! note The name given to the certificate can only contain a-z (lowercase), 0-9 and hyphens\nThe Drycc platform will investigate the certificate and extract any relevant information from it such as the Common Name, Subject Alt Names (SAN), fingerprint and more.\nThis allows for wildcard certificates and multiple domains in the SAN without uploading duplicates.\nAdd a Certificate Chain Sometimes, your certificates (such as a self-signed or a cheap certificate) need additional certificates to establish the chain of trust. What you need to do is bundle all the certificates into one file and give that to Drycc. Importantly, your site’s certificate must be the first one:\n$ cat server.crt server.ca \u003e server.bundle After that, you can add them to Drycc with the certs:add command:\n$ drycc certs:add example-com server.bundle server.key -a foo Adding SSL endpoint... done www.example.com Attach SSL certificate to a domain Certificates are not automagically connected up to domains, instead you will have to attach a certificate to a domain\n$ drycc certs:attach example-com example.com -a foo Each certificate can be connected to many domains. There is no need to upload duplicates.\nTo remove an association\n$ drycc certs:detach example-com example.com -a foo Endpoint overview You can verify the details of your domain’s SSL configuration with drycc certs.\n$ drycc certs Name | Common Name | SubjectAltName | Expires | Fingerprint | Domains | Updated | Created +-------------+-------------------+-------------------+-------------------------+-----------------+--------------+-------------+-------------+ example-com | example.com | blog.example.com | 31 Dec 2017 (in 1 year) | 8F:8E[...]CD:EB | example.com | 30 Jan 2016 | 29 Jan 2016 or by looking at at each certificates detailed information\n$ drycc certs:info example-com -a foo === bar-com Certificate Common Name(s): example.com Expires At: 2017-01-14 23:57:57 +0000 UTC Starts At: 2016-01-15 23:57:57 +0000 UTC Fingerprint: 7A:CA:B8:50:FF:8D:EB:03:3D:AC:AD:13:4F:EE:03:D5:5D:EB:5E:37:51:8C:E0:98:F8:1B:36:2B:20:83:0D:C0 Subject Alt Name: blog.example.com Issuer: /C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=example.com/emailAddress=engineering@drycc.cc Subject: /C=US/ST=CA/L=San Francisco/O=Drycc/OU=Engineering/CN=example.com/emailAddress=engineering@drycc.cc Connected Domains: example.com Owner: admin-user Created: 2016-01-28 19:07:41 +0000 UTC Updated: 2016-01-30 00:10:02 +0000 UTC Testing SSL Use a command line utility like curl to test that everything is configured correctly for your secure domain.\n!!! note The -k option flag tells curl to ignore untrusted certificates.\nPay attention to the output. It should print SSL certificate verify ok. If it prints something like common name: www.example.com (does not match 'www.somedomain.com') then something is not configured correctly.\nEnforcing SSL at the Router To enforce all HTTP requests be redirected to HTTPS, TLS can be enforced at the router level by running\n$ drycc tls:force:enable -a foo Enabling https-only requests for foo... done Users hitting the HTTP endpoint for the application will now receive a 301 redirect to the HTTPS endpoint.\nTo disable enforced TLS, run\n$ drycc tls:force:disable -a foo Disabling https-only requests for foo... done Automated Certificate Management With Automated Certificate Management (ACM), Drycc automatically manages TLS certificates for apps with Hobby and Professional dynos on the Common Runtime, and for apps in Private Spaces that enable the feature. Certificates handled by ACM automatically renew one month before they expire, and new certificates are created automatically whenever you add or remove a custom domain. All applications with paid dynos include ACM for free. Automated Certificate Management uses Let’s Encrypt, the free, automated, and open certificate authority for managing your application’s TLS certificates. Let’s Encrypt is run for the public benefit by the Internet Security Research Group (ISRG).\nTo enable ACM with the following command: $ drycc tls:auto:enable -a foo\nTo disable ACM with the following command: $ drycc tls:auto:disable -a foo\nRemove Certificate You can remove a certificate using the certs:remove command:\n$ drycc certs:remove my-cert -a foo Removing www.example.com... Done. Swapping out certificates Over the lifetime of an application an operator will have to acquire certificates with new expire dates and apply it to all relevant applications, below is the recommended way to swap out certificates.\nBe intentional with certificate names, name them example-com-2017 when possible, where the year signifies the expiry year. This allows for example-com-2018 when a new certificate is purchased.\nAssuming all applications are already using example-com-2017 the following commands can be ran, chained together or otherwise:\n$ drycc certs:detach example-com-2017 example.com -a foo $ drycc certs:attach example-com-2018 example.com -a foo This will take care of a singular domain which allows the operator to verify everything went as planned and slowly roll it out to any other application using the same method.\nTroubleshooting Here are some steps you can follow if your SSL endpoint is not working as you’d expect.\nUntrusted Certificate In some cases when accessing the SSL endpoint, it may list your certificate as untrusted.\nIf this occurs, it may be because it is not trusted by Mozilla’s list of root CAs. If this is the case, your certificate may be considered untrusted for many browsers.\nIf you have uploaded a certificate that was signed by a root authority but you get the message that it is not trusted, then something is wrong with the certificate. For example, it may be missing intermediary certificates. If so, download the intermediary certificates from your SSL provider, remove the certificate from Drycc and re-run the certs:add command.\n","categories":"","description":"SSL is a cryptographic protocol that provides end-to-end encryption and integrity for all web requests.","excerpt":"SSL is a cryptographic protocol that provides end-to-end encryption …","ref":"/docs/applications/ssl-certificates/","tags":"","title":"Application SSL Certificates"},{"body":"The Drycc stack is intended for advanced use cases only. Unless you have a specific need for custom Docker images, we recommend using Drycc’s default buildpack-powered build system. It offers automatic base image security updates and language-specific optimizations. It also avoids the need to maintain a .containerDockerfile\ndrycc.yaml Overview A manifest has three top-level sections.\nbuild – Specifies the to build Dockerfile run – Specifies the release phase tasks to execute deploy – Specifies process types and the commands to run for each type Here’s an example that illustrates using a manifest to build Docker images.\nbuild: docker: web: Dockerfile worker: worker/Dockerfile config: web: FOO: bar worker: RAILS_ENV: development run: - command: - ./deployment-tasks.sh image: worker # If the field is empty, it means it will be executed forever when: ptypes: - web - webbbsbs # Maximum execution time timeout: 100 deploy: web: command: - bash - -ec args: - bundle exec puma -C config/puma.rb worker: command: - bash - -ec args: - python myworker.py asset-syncer: command: - bash - -ec args: - python asset-syncer.py image: worker For more deployment information, please refer to the drycc examples.\n","categories":"","description":"Drycc Container Registry allows you to deploy your Docker-based app to Drycc. Both Common Runtime and Private Spaces are supported.","excerpt":"Drycc Container Registry allows you to deploy your Docker-based app to …","ref":"/docs/applications/using-dryccfile/","tags":"","title":"Using drycc.yaml"},{"body":" A Open, Unified, Lightweight, Simpler Containers as a Service (CaaS).\nWelcome to Drycc Drycc Workflow is an open source container cloud platform.\nUsually we also call it Container as a Service(CaaS) that adds a developer-friendly layer to any Kubernetes cluster, making it easy to deploy and manage applications.\nDrycc Workflow includes capabilities for building and deploying from source via git push, simple application configuration, creating and rolling back releases, managing domain names and SSL certificates, providing seamless edge routing, aggregating logs, and sharing applications with teams. All of this is exposed through a simple REST API and command line interface.\nGetting Started To get started with Workflow, follow our Quick Start guide.\nTake a deep dive into Drycc Workflow in our Concepts, Architecture, and Components sections.\nFeel like contibuting some code or want to get started as a maintainer? Pick an issue tagged as an easy fix or help wanted and start contributing!\n","categories":"","description":"","excerpt":" A Open, Unified, Lightweight, Simpler Containers as a Service (CaaS). …","ref":"/docs/","tags":"","title":"Docs"},{"body":"","categories":"","description":"","excerpt":"","ref":"/blog/releases/","tags":"","title":"Release"},{"body":"Workflow ## v1.7.7 -\u003e v1.7.8 Releases builder v1.6.0 -\u003e v1.7.0 controller v1.8.0 -\u003e v1.9.0 workflow-cli v1.6.0 -\u003e v1.7.0 Features 384c7ee (builder) - domain: add procfile_type 26c8c7f (controller) - domain: add procfile_type bd49789 (workflow-cli) - domain: add procfile_type ","categories":"","description":"New Drycc Workflow Release v1.7.8","excerpt":"New Drycc Workflow Release v1.7.8","ref":"/blog/2024/05/01/drycc-workflow-v1.7.8/","tags":"","title":"Drycc Workflow v1.7.8"},{"body":"Workflow ## v1.7.6 -\u003e v1.7.7 Releases builder v1.5.1 -\u003e v1.6.0 controller v1.7.0 -\u003e v1.8.0 database v1.2.1 -\u003e v1.3.0 passport v1.2.0 -\u003e v1.3.0 imagebuilder v1.1.1 -\u003e v1.2.0 fluentbit v0.0.1 -\u003e v0.0.2 logger v1.3.3 -\u003e v1.3.4 storage v0.0.5 -\u003e v0.1.0 gateway v0.0.2 -\u003e v0.0.3 monitor v1.4.0 -\u003e v1.4.1 redis v1.3.2 -\u003e v1.4.0 timeseries v0.0.2 -\u003e v0.1.0 prometheus v0.1.1 -\u003e v0.1.2 rabbitmq v1.2.1 -\u003e v1.3.0 registry v1.2.2 -\u003e v1.3.0 registry-proxy v1.2.1 -\u003e v1.2.2 workflow-cli v1.5.2 -\u003e v1.6.0 Features 6c1cf5e (builder) - charts: reuses the value from an existing secret and config 65ae63c (builder) - pipeline: add dryccfile support bb7b11d (builder) - auth: add tokens api 39d022f (controller) - ps: add pod logs support 86056d0 (controller) - charts: reuses the value from an existing secret and config 4cf005c (controller) - limits: add limits plan support bf60e4b (controller) - controller: add init job 98f77a8 (controller) - pipeline: add dryccfile support 8ce9a83 (controller) - cert-manager: add tls events 7034f5d (controller) - config: deploy according to procfile_type 5554d8f (controller) - config: add typed_values 2c5bbad (controller) - auth: add token api 410d34e (database) - charts: reuses the value from an existing secret and config 693e4d1 (imagebuilder) - pipeline: add dryccfile support 7d9cc06 (imagebuilder) - config: add typed values 854e171 (passport) - charts: reuses the value from an existing secret and config 7ac9255 (passport) - oauth2: add authorization code for any grant type 4517547 (rabbitmq) - charts: reuses the value from an existing secret and config bccfcb4 (redis) - charts: reuses the value from an existing secret and config d887605 (registry) - charts: reuses the value from an existing secret and config ff09e5b (storage) - charts: reuses the value from an existing secret and config c6e2ac8 (timeseries) - charts: reuses the value from an existing secret and config 22c4c77 (workflow-cli) - apps: change drycc run to async a9e6369 (workflow-cli) - ps: add pod logs support 2bc31c8 (workflow-cli) - limits: add limits plan support f40398a (workflow-cli) - pipeline: add dryccfile support 03638ff (workflow-cli) - tls: add tls events 9113627 (workflow-cli) - config: add typed values 43ee760 (workflow-cli) - auth: add tokens api Fixes 50dfe64 (builder) - woodpecker: CI_SYSTEM_ARCH env removed ab09b24 (controller) - healthcheck: delete outdated code 52019b5 (controller) - services: default PORT change error f57ae42 (controller) - certificate: failed to create certificate 30c3f54 (controller) - woodpecker: CI_SYSTEM_ARCH env removed dbba43a (controller) - service: update port error e0459c5 (controller) - copy: use deepcopy replace copy 2122479 (controller) - charts: failed to call webhook 53d9977 (controller) - signals: config limits handle error afda287 (controller) - limits: always set default b350cb8 (database) - woodpecker: CI_SYSTEM_ARCH env removed b48a422 (fluentbit) - woodpecker: CI_SYSTEM_ARCH env removed 7cebca2 (gateway) - cert-manager: auto tls error 190c19b (imagebuilder) - woodpecker: CI_SYSTEM_ARCH env removed 2c6a6f9 (logger) - woodpecker: CI_SYSTEM_ARCH env removed 10bb98d (monitor) - woodpecker: CI_SYSTEM_ARCH env removed f8225dc (passport) - woodpecker: CI_SYSTEM_ARCH env removed 06db66c (prometheus) - woodpecker: CI_SYSTEM_ARCH env removed f4aff72 (rabbitmq) - woodpecker: CI_SYSTEM_ARCH env removed 88c18ff (redis) - woodpecker: CI_SYSTEM_ARCH env removed 5dcc19d (registry) - woodpecker: CI_SYSTEM_ARCH env removed 092a939 (registry-proxy) - woodpecker: CI_SYSTEM_ARCH env removed 3597ac9 (storage) - woodpecker: CI_SYSTEM_ARCH env removed 5a49b35 (timeseries) - woodpecker: CI_SYSTEM_ARCH env removed 0c4a48a (workflow-cli) - tls: change issuer options 06a2511 (workflow-cli) - tls: info error Maintenance 2f7617e (builder) - go: bump controller-sdk-go version aae2f29 (builder) - charts: add diagnostic mode 7304980 (builder) - woodpecker: migrations woodpecker-ci to 2 30b648b (builder) - charts: change canary app version 2afa006 (builder) - controller-sdk-go: bump version d127a90 (builder) - config: add typed values 32fdfd0 (controller) - charts: add diagnostic mode 0974942 (controller) - woodpecker: migrations woodpecker-ci to 2 f401e08 (controller) - python: bump python 3.12 c565959 (controller) - celery: remove retrieve_resource task 47be1a1 (controller) - requirements: bump drf 3.15.1 99f7468 (controller) - charts: add config to values.yaml 7d17f5c (controller) - scale: prohibit scale when there is a running pipeline f09e1c9 (controller) - resource: sort services and plans e817505 (controller) - limits: change default cpu and gpu name 5531b2f (controller) - auth: add password login 27473f7 (controller) - deps: bump gunicorn from 21.2.0 to 22.0.0 in /rootfs c1ee1c7 (controller) - deps: bump aiohttp from 3.9.3 to 3.9.4 in /rootfs affbcb5 (database) - postgres: add patroni and postgres params (#15) f9e4eda (database) - dockerfile: install vi 008b7b6 (database) - dockerfile: install vim instand of vi dbbfee1 (database) - charts: add diagnostic mode 2e26c33 (database) - woodpecker: migrations woodpecker-ci to 2 a1b81f2 (database) - charts: change canary app version bc725e8 (fluentbit) - charts: add diagnostic mode 5d73886 (fluentbit) - woodpecker: migrations woodpecker-ci to 2 b85072d (fluentbit) - charts: change canary app version 761174d (gateway) - gateway: change secrets name 1c304da (gateway) - woodpecker: migrations woodpecker-ci to 2 b919a4c (gateway) - charts: change canary app version 3cea298 (imagebuilder) - charts: allow all dns 653bcbe (imagebuilder) - woodpecker: migrations woodpecker-ci to 2 59daeab (imagebuilder) - charts: change canary app version 2834a5a (logger) - charts: add diagnostic mode 6685492 (logger) - woodpecker: migrations woodpecker-ci to 2 191cdaf (logger) - charts: change canary app version b3c3cfa (monitor) - charts: add diagnostic mode 796799d (monitor) - grafana: add node metrics dashboard ef2a222 (monitor) - woodpecker: migrations woodpecker-ci to 2 9c83090 (monitor) - charts: change canary app version 1a97c2c (passport) - charts: add diagnostic mode 353e1ae (passport) - logger: add oauth2_provider logger config fe735c0 (passport) - woodpecker: migrations woodpecker-ci to 2 41d6144 (passport) - charts: change canary app version 979d474 (passport) - python: bump python 3.12 e9f41a1 (passport) - requirements: bump drf 3.15.1 f479f4d (passport) - charts: add migrate job ad9abf6 (passport) - passport: migrations add run_before 95ac667 (passport) - passport: optimize the use of master and slave database rules 204f7fc (passport) - deps: bump gunicorn from 21.2.0 to 22.0.0 in /rootfs 90a6410 (prometheus) - woodpecker: migrations woodpecker-ci to 2 2d8eb44 (prometheus) - charts: change canary app version 9687a17 (rabbitmq) - charts: add diagnostic mode 35d3d5b (rabbitmq) - woodpecker: migrations woodpecker-ci to 2 6a6564d (rabbitmq) - charts: change canary app version cb6722f (redis) - charts: add diagnostic mode 9553497 (redis) - woodpecker: migrations woodpecker-ci to 2 1c8dc07 (redis) - charts: change canary app version 9fa2a32 (registry) - charts: add diagnostic mode 9b09e51 (registry) - woodpecker: migrations woodpecker-ci to 2 7dbd390 (registry) - charts: change canary app version e1d2a33 (registry-proxy) - charts: add diagnostic mode 3eabfdd (registry-proxy) - charts: remove default limits f8754da (registry-proxy) - woodpecker: migrations woodpecker-ci to 2 7df7316 (registry-proxy) - charts: change canary app version 861d3b8 (storage) - filer: modify the default parameters of the filer 5fa08da (storage) - woodpecker: migrations woodpecker-ci to 2 22c4620 (storage) - charts: change canary app version 6c1e29c (timeseries) - postgres: add patroni params e280d3f (timeseries) - dockerfile: install vi 5213617 (timeseries) - dockerfile: install vim instand of vi a569a57 (timeseries) - charts: add diagnostic mode b93ec70 (timeseries) - woodpecker: migrations woodpecker-ci to 2 ff3b870 (timeseries) - charts: change canary app version e334f74 (workflow-cli) - healthcheck: delete outdated healthcheck style 4f8b960 (workflow-cli) - auth: add password login ","categories":"","description":"New Drycc Workflow Release v1.7.7","excerpt":"New Drycc Workflow Release v1.7.7","ref":"/blog/2024/04/30/drycc-workflow-v1.7.7/","tags":"","title":"Drycc Workflow v1.7.7"},{"body":"These release notes for Drycc Workflow v1.7.5 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.7.4, please refer to the following change summary.\nWorkflow ## v1.7.4 -\u003e v1.7.5 Releases builder v1.5.0 -\u003e v1.5.1 controller v1.6.3 -\u003e v1.7.0 logger v1.3.2 -\u003e v1.3.3 storage v0.0.3 -\u003e v0.0.4 redis v1.3.1 -\u003e v1.3.2 rabbitmq v1.2.0 -\u003e v1.2.1 registry v1.2.1 -\u003e v1.2.2 workflow-cli v1.5.1 -\u003e v1.5.2 Features 95d130a (controller) - controller: volume support nfs Fixes ee2ee15 (controller) - controller: container entrypoint error 03ea4f8 (controller) - controller: class property have been deprecated in python 3.11 5f04d17 (controller) - controller: miss err msg 27972a3 (controller) - controller: load_db_state_to_k8s err a005d62 (controller) - controller: volume repeat path no error c7a5ba6 (rabbitmq) - rabbitmq: cpu usage to high 45c2077 (workflow-cli) - workflow-cli: miss err msg bc738bd (workflow-cli) - workflow-cli: volumes list format Maintenance 35e1c06 (builder) - builder: bump golang 1.22 26caa36 (controller) - deps: bump aiohttp from 3.9.0 to 3.9.2 in /rootfs (#118) 3d938c4 (controller) - deps: bump django from 4.2.7 to 4.2.10 e625c2f (logger) - logger: bump golang 1.22 bfa500d (redis) - redis: headless svc does not require ports 330209a (registry) - registry: headless svc does not require ports 48c42eb (storage) - storage: change volume index to leveldb f4fde9d (storage) - storage: add volume size limit 33e3684 (workflow-cli) - workflow-cli: volume support nfs 48d5950 (workflow-cli) - workflow-cli: bump golang 1.22 ","categories":"","description":"New Drycc Workflow Release v1.7.5","excerpt":"New Drycc Workflow Release v1.7.5","ref":"/blog/2024/02/27/drycc-workflow-v1.7.5/","tags":"","title":"Drycc Workflow v1.7.5"},{"body":"Workflow ## v1.7.5 -\u003e v1.7.6 Releases storage v0.0.4 -\u003e v0.0.5 Maintenance 6cb63b6 (storage) - seaweedfs: bump version 3.63 ","categories":"","description":"New Drycc Workflow Release v1.7.6","excerpt":"New Drycc Workflow Release v1.7.6","ref":"/blog/2024/02/27/drycc-workflow-v1.7.6/","tags":"","title":"Drycc Workflow v1.7.6"},{"body":"These release notes for Drycc Workflow v1.7.2 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.7.1, please refer to the following change summary.\nWorkflow ## v1.7.1 -\u003e v1.7.2 Releases controller v1.6.0 -\u003e v1.6.1 logger v1.3.1 -\u003e v1.3.2 storage v0.0.1 -\u003e v0.0.2 timeseries v0.0.1 -\u003e v0.0.2 prometheus v0.1.0 -\u003e v0.1.1 workflow-cli v1.5.0 -\u003e v1.5.1 Fixes 2fe80a6 (controller) - resources: after resources instance update, could not delete (#111) a4082ad (controller) - controller: resource status and binding e9bfccc (controller) - controller: fix multiple volumes mount at one dir error (#116) 58d2b4c (logger) - logger: redis conn error block 7cb2700 (prometheus) - prometheus: prometheus config basic_auth 7838c6b (storage) - storage: random accesskey secretkey d9dcdfb (storage) - storage: pod restart loses data 3cbdd29 (storage) - storage: tipd cannot start after deleting pod be7e11f (storage) - storage: jq command not found 878f674 (storage) - storage: charts updateStrategy error 06cfe56 (timeseries) - timeseries: the data node ip is incorrect Maintenance 7f29f5a (controller) - resources: retrieve resource instance response add message (#112) 4a84dcd (controller) - controller: add deploy default annotations (#113) 829d7e5 (controller) - controller: modify url match service name (#114) 30abf6d (controller) - controller: transfer app ownership in async dc6f45e (controller) - controller: add channel for pod exec af4f3a7 (controller) - controller: avoid error when secret no data field (#117) ca27956 (controller) - controller: add pod default security b2e9c64 (prometheus) - charts: node-exporter mount root (#2) 3cdb2b6 (storage) - storage: bump seaweedfs 3.61 00dd2fd (storage) - storage: add csi daemonset updateStrategy 48e763c (storage) - storage: add drycc storage upgrade document 841df90 (storage) - storage: bump seaweedfs 3.62 cefd52e (timeseries) - timeseries: add check data node exists ad1c46e (workflow-cli) - resources: resources instance add message 9f955c2 (workflow-cli) - workflow-cli: add short options cpu 65399ef (workflow-cli) - workflow-cli: add tty resize support ","categories":"","description":"New Drycc Workflow Release v1.7.2","excerpt":"New Drycc Workflow Release v1.7.2","ref":"/blog/2024/01/29/drycc-workflow-v1.7.2/","tags":"","title":"Drycc Workflow v1.7.2"},{"body":"These release notes for Drycc Workflow v1.7.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.6.0, please refer to the following change summary.\nWorkflow ## v1.6.0 -\u003e v1.7.0 Releases builder v1.4.0 -\u003e v1.5.0 controller v1.5.1 -\u003e v1.6.0 database v1.2.0 -\u003e v1.2.1 passport v1.1.0 -\u003e v1.2.0 imagebuilder v1.1.0 -\u003e v1.1.1 fluentbit v0.0.0 -\u003e v0.0.1 logger v1.3.0 -\u003e v1.3.1 storage v0.0.0 -\u003e v0.0.1 gateway v0.0.0 -\u003e v0.0.1 monitor v1.3.0 -\u003e v1.4.0 redis v1.3.0 -\u003e v1.3.1 timeseries v0.0.0 -\u003e v0.0.1 prometheus v0.0.0 -\u003e v0.1.0 rabbitmq v1.1.0 -\u003e v1.2.0 registry v1.2.0 -\u003e v1.2.1 registry-proxy v1.2.0 -\u003e v1.2.1 Features fcbebda (builder) - builder: use TCPRoute expose service d02bb5d (controller) - controller: support app dns policy config 9aa968e (controller) - controller: add svc type support 62e2d34 (controller) - controller: improve the services api 4393755 (controller) - controller: use gateway replace ingress 323045d (controller) - controller: add canary support 3f81c97 (controller) - gateways: add addresses field 4e64aa7 (controller) - gateways: add addresses field 02ad581 (monitor) - grafana: add pd tikv dashboard 2a9e2b0 (monitor) - monitor: add storage monitor 41d5057 (monitor) - grafana: data source change to prometheus ec035d1 (monitor) - monitor: usegateway replace ingress c694c98 (monitor) - grafana: add drycc storage seaweedfs dashboard 1e1fdc8 (passport) - passport: use gateway replace ingress ffdb408 (prometheus) - prometheus: use gateway replace ingress 04152b9 (rabbitmq) - rabbitmq: use gateway replace ingress Fixes 0499500 (builder) - builder: manifest error 642491d (builder) - builder: no build log 873d146 (controller) - controller: do not set entrypoint when no procfile d9028c5 (controller) - controller: pip8 error 3efcfb7 (controller) - controller: manifest error 18a3a1a (controller) - controller: miss service error 94f796c (controller) - controller: drycc run pod should not restart 80f3161 (controller) - controller: monitor query error b76f2c5 (controller) - controller: read websocket delay b6e068e (controller) - controller: metrics sql tpl, gateway pod should not restart, cleanup old rs, update monitor datatbase config ad9adc6 (controller) - controller: rabbitmq sharding err 6773907 (controller) - controller: default k8s pod annotaions ffcf1f9 (controller) - controller: under-indented for visual indent 3afd0cf (controller) - controller: charts env error 769bb8b (database) - database: manifest error 769bb8b (database) - database: label conflict error 6a321c5 (database) - database: link error 558feae (fluentbit) - fluentbit: build charts error 98d8a2a (gateway) - fixup 8b5dde1 (gateway) - gateway: secretName 702866d (gateway) - gateway: build status f55dac1 (imagebuilder) - imagebuilder: manifest error ac13b5f (imagebuilder) - imagebuilder: build svg 6b7bbc5 (logger) - logger: manifest error 0136b5c (monitor) - monitor: manifest error f03d975 (passport) - passport: DRYCC_GRAFANA_DOMAIN error b530ea8 (passport) - passport: manifest error be5a0a7 (passport) - passport: change passport 1596c7f (rabbitmq) - rabbitmq: manifest error 0dc4f6f (rabbitmq) - rabbitmq: images-shard error 43293ae (redis) - redis: manifest error ca13b7d (registry) - registry: manifest error ab5c793 (registry) - registry: garbage collect error ab0fabc (registry-proxy) - registry-proxy: manifest error dfc7236 (registry-proxy) - registry-proxy: daemon yaml format 42c03be (storage) - storage: seaweedfs csi error 453e41a (timeseries) - timeseries: could not register node Docs 5433c89 (gateway) - gateway: add prerequisites 2f0c5d8 (logger) - logger: change architecture Maintenance bdd02eb (builder) - builder: use dynamic clusterrole name 66b4b25 (builder) - builder: upgrade new controller-go-sdk 219d86f (builder) - builder: upgrade go.mod 91f2f14 (builder) - builder: use woodpecker replace drone 9abca16 (builder) - woodpecker: use woodpecker ci build status f43dd50 (builder) - deps: bump golang.org/x/net from 0.2.0 to 0.7.0 0384c69 (builder) - builder: add chart appVersion e3149b9 (builder) - builder: upgrade codename to bookworm d88ea1b (builder) - builder: add codename build-arg ba59030 (builder) - builder: upgrade go.mod 1114dd7 (builder) - builder: bump common 1.1.2 fe50b62 (builder) - builder: change drycc gateway listener name db3950c (builder) - builder: remove gateway route 5a508bb (builder) - builder: use podman replace docker bbb9029 (builder) - deps: bump golang.org/x/net from 0.12.0 to 0.17.0 f4e5d6c (builder) - builder: remove health url 9111c8f (builder) - builder: remove io/ioutil 1f36e3d (controller) - deps: bump django from 4.1.2 to 4.1.6 in /rootfs e4ab434 (controller) - controller: use woodpecker replace drone 9f0301e (controller) - deps: bump django from 4.1.6 to 4.1.7 in /rootfs 3932423 (controller) - woodpecker: use woodpecker ci build status ae8b6b4 (controller) - setting: support KUBERNETES_LIMITS env config c10b9bc (controller) - controller: using the api_version instead of hard coding e6908cd (controller) - controller: upgrade requirements b0eba0c (controller) - controller: add route rules serializer 2e4b6a4 (controller) - controller: add chart appVersion 7d32b55 (controller) - controller: upgrade to bookworm f2dc8dd (controller) - controller: add codename build-arg 5739b83 (controller) - controller: use timescaledb replace influxdb 53892cb (controller) - controller: add timeseries 0fe0eae (controller) - controller: upgrade requirements 18b2a91 (controller) - deps: bump aiohttp from 3.8.4 to 3.8.5 in /rootfs f50874a (controller) - controller: bump common 1.1.2 956cd08 (controller) - controller: change drycc gateway listener name 9ab3ead (controller) - controller: remove passport url check a24c7b0 (controller) - controller: remove gateway route f7e539a (controller) - controller: change celery priority ab77a52 (controller) - controller: use podman replace docker 8e27501 (controller) - controller: dynamic app storage class 385978b (controller) - controller: list_pods datetime format b20362c (controller) - deps: bump django from 4.2.3 to 4.2.7 in /rootfs e11ae1b (controller) - controller: add cluster migrate ca6e9df (controller) - controller: async mount 9a7fbfc (controller) - controller: remove FOSSA 3d55279 (controller) - deps: bump aiohttp from 3.8.5 to 3.8.6 in /rootfs d498a11 (controller) - controller: add measure loalancers 249a985 (controller) - deps: bump aiohttp from 3.8.5 to 3.8.6 in /rootfs b967f58 (controller) - deps: bump aiohttp from 3.8.6 to 3.9.0 in /rootfs (#107) 8ca9ed6 (controller) - controller: no longer restrict reserved domain 9ff6649 (database) - database: add init database configure 9b4cd26 (database) - database: use dynamic clusterrole name b59cde4 (database) - database: remove minio require 86462f8 (database) - database: use woodpecker replace drone 1e8555a (database) - database: add chart appVersion 1b762d5 (database) - database: upgrade codename to bookworm 9ffe1fd (database) - database: add codename build-arg 69466d7 (database) - database: add database extension beb4b62 (database) - database: bump common 1.1.2 67e2714 (database) - database: use podman replace docker 8f328f8 (fluentbit) - fluentbit: no limit buffer size for kube api fc0552c (fluentbit) - fluentbit: use podman replace docker 63a6cab (fluentbit) - fluentbit: change fluentbit match 220f81a (fluentbit) - fluentbit: run as no-root aec1393 (fluentbit) - fluentbit: change configmap name 1af4fd2 (fluentbit) - fluentbit: change default stream name bef90ad (gateway) - gateway: add route for gateway d523ddb (gateway) - gateway: change drycc gateway listener name d9137f4 (gateway) - gateway: add chart appVersion 0425dd4 (gateway) - gateway: add customListeners 3982b86 (imagebuilder) - imagebuilder: use woodpecker replace drone 3e4e7a3 (imagebuilder) - imagebuilder: add chart appVersion 8df6e8e (imagebuilder) - imagebuilder: upgrade stack version a5601f7 (imagebuilder) - imagebuilder: add drycc_app env 07465f8 (imagebuilder) - imagebuilder: upgrade to bookworm 00d22d2 (imagebuilder) - imagebuilder: add codename build-arg 0b7a24e (imagebuilder) - imagebuilder: upgrade podman/mc/caddy a7d8be8 (imagebuilder) - imagebuilder: use podman replace docker 6b2da83 (logger) - logger: use woodpecker replace drone 8245b25 (logger) - woodpecker: use woodpecker ci build status f811a74 (logger) - logger: add chart appVersion 413f6f6 (logger) - logger: upgrade codename to bookworm 2ac6b10 (logger) - logger: add codename build-arg 2581426 (logger) - logger: bump redis to v9 364b25a (logger) - logger: bump common 1.1.2 dc169a3 (logger) - logger: use fluentbit replace fluentd d855d91 (logger) - logger: use podman replace docker f767235 (monitor) - monitor: add off-cluster passport configure ab23936 (monitor) - monitor: use dynamic clusterrole name 47beee0 (monitor) - monitor: change tikv secret key af7703f (monitor) - grafana: remove panel when component off-cluster 1b870c2 (monitor) - monitor: use woodpecker replace drone 4a5f1f1 (monitor) - grafana: up ldap api_url config 143cabe (monitor) - monitor: add prometheus architecture diagram 93091c2 (monitor) - woodpecker: use woodpecker ci build status 0b7045a (monitor) - grafana: add dashboard kubernetes_deployment_metrics 2fb1839 (monitor) - woodpecker: pipeline config VERSION, when build container image e272416 (monitor) - monitor: add chart appVersion abc0e53 (monitor) - monitor: upgrade codename to bookworm 86cc01b (monitor) - monitor: add codename build-arg 1cd849f (monitor) - monitor: add postgresql outputs c3205c0 (monitor) - monitor: change default agent config 8c802c0 (monitor) - monitor: add timeseries database e9abc40 (monitor) - monitor: bump common 1.1.2 6af66cd (monitor) - monitor: change drycc gateway listener name d02d718 (monitor) - monitor: remove gateway route 3509c29 (monitor) - monitor: use podman replace docker ed7bfa2 (monitor) - monitor: optimize env PROMETHEUS_URL da89bef (passport) - passport: charts codereview 61c4a96 (passport) - passport: support init app config 9101006 (passport) - passport: add initApplications to charts 7dd7fa4 (passport) - passport: use woodpecker replace drone 4400199 (passport) - woodpecker: use woodpecker ci build status 6b2c546 (passport) - passport: change secret name to drycc-passport-auto-tls c8bd824 (passport) - passport: upgrade requirements aee5aef (passport) - passport: add chart appVersion 2d81953 (passport) - passport: upgrade codename to bookworm 9e66242 (passport) - passport: add codename build-arg 0fca998 (passport) - passport: upgrade requirements 3482528 (passport) - passport: bump common 1.1.2 0c5ec93 (passport) - passport: change drycc gateway listener name f7b8f53 (passport) - passport: remove gateway route baf69da (passport) - passport: use podman replace docker fcd45dd (passport) - passport: add cluster migrate da6d32a (prometheus) - prometheus: add prometheus-config 683de9e (prometheus) - prometheus: use podman replace docker 3323300 (prometheus) - prometheus: remove gateway route da1d356 (prometheus) - prometheus: change drycc gateway listener name 4e7a936 (prometheus) - prometheus: bump common 1.1.2 44c1c6f (prometheus) - prometheus: add codename build-arg d1f1dda (prometheus) - prometheus: upgrade codename to bookworm 0836fc1 (prometheus) - prometheus: add chart appVersion 9e13232 (prometheus) - prometheus: add LICENSE f53e14a (rabbitmq) - rabbitmq: remove auto user 0ec7277 (rabbitmq) - rabbitmq: use woodpecker replace drone f376a30 (rabbitmq) - woodpecker: use woodpecker ci build status 51405d8 (rabbitmq) - rabbitmq: add chart appVersion 463ca03 (rabbitmq) - rabbitmq: upgrade codename to bookworm 1978a71 (rabbitmq) - rabbitmq: add codename build-arg 139277f (rabbitmq) - rabbitmq: bump common 1.1.2 be49741 (rabbitmq) - rabbitmq: change drycc gateway listener name 6d22518 (rabbitmq) - rabbitmq: remove gateway route 0eb7833 (rabbitmq) - rabbitmq: add check shards 9211063 (rabbitmq) - rabbitmq: erlang vm tuning optimization 648a78d (rabbitmq) - rabbitmq: use podman replace docker 0b43a4d (rabbitmq) - rabbitmq: add x-random exchange ad1c4da (redis) - redis: use woodpecker replace drone 3f37f92 (redis) - redis: add chart appVersion e3bef7a (redis) - redis: upgrade codename to bookworm 4e806d4 (redis) - redis: add codename build-arg d5023be (redis) - redis: bump common 1.1.2 98f5d6f (redis) - redis: use podman replace docker 063f29e (registry) - registry: use woodpecker replace drone 17bf8ae (registry) - woodpecker: use woodpecker ci build status 7bbad15 (registry) - registry: add chart appVersion 279154f (registry) - registry: upgrade codename to bookworm 3e4ae84 (registry) - registry: add codename build-arg fa322d6 (registry) - registry: bump common 1.1.2 6c18fe0 (registry) - registry: use podman replace docker 0bc8472 (registry) - registry: remove health url 5dacd9f (registry) - registry: add wait-for-port check fdeefc3 (registry) - registry: use headless 08bf9f8 (registry) - registry: change registry port to 5000 40bcea2 (registry) - registry: add registry push test 871b8e7 (registry) - registry: add default env 7f3b3ac (registry) - registry: bump registry 2.8.3 569f15d (registry-proxy) - registry-proxy: use woodpecker replace drone cc33caf (registry-proxy) - woodpecker: use woodpecker ci build status 0002aab (registry-proxy) - registry-proxy: add chart appVersion 40af10b (registry-proxy) - registry-proxy: upgrade codename to bookworm c56b9df (registry-proxy) - registry-proxy: add codename build-arg 9d5bfe0 (registry-proxy) - registry-proxy: use podman replace docker e6a3350 (registry-proxy) - registry-proxy: change worker_processes to 1 726f39d (storage) - storage: add volume compactionMBps a5aa2d8 (storage) - storage: add threshold to vacuum and reclaim spaces e687d04 (storage) - storage: delete disk type in single disk case 75ee2e4 (storage) - storage: change datanode replicas to 4 c5fd7ba (storage) - storage: delete useless env b3826ea (storage) - storage: add ssd hdd dir 29881a0 (storage) - storage: add balance cronjob c5a0f51 (storage) - storage: add defaultReplication for seaweedfs master 543c7a2 (timeseries) - timeseries: use podman replace docker 5376024 (timeseries) - timeseries: update timeseries-service-replica 52e8520 (timeseries) - timeseries: bump common 1.1.2 f82657c (timeseries) - timeseries: add start script ","categories":"","description":"New Drycc Workflow Release v1.7.0","excerpt":"New Drycc Workflow Release v1.7.0","ref":"/blog/2023/12/08/drycc-workflow-v1.7.0/","tags":"","title":"Drycc Workflow v1.7.0"},{"body":"These release notes for Drycc Workflow v1.6.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.5.0, please refer to the following change summary.\nWorkflow ## v1.5.0 -\u003e v1.6.0 Releases builder v1.3.0 -\u003e v1.4.0 controller v1.4.0 -\u003e v1.5.0 passport v1.0.0 -\u003e v1.1.0 database v1.1.0 -\u003e v1.2.0 imagebuilder v1.0.1 -\u003e v1.1.0 fluentd v1.2.0 -\u003e v1.3.0 logger v1.2.0 -\u003e v1.3.0 storage v1.2.0 -\u003e v1.3.0 monitor v1.2.0 -\u003e v1.3.0 redis v1.2.0 -\u003e v1.3.0 influxdb v1.1.0 -\u003e v1.2.0 rabbitmq v1.0.0 -\u003e v1.1.0 registry v1.1.0 -\u003e v1.2.0 registry-proxy v1.1.0 -\u003e v1.2.0 Features 52517d9 (builder) - builder: update controller-sdk-go 1d78ca0 (builder) - builder: add affinity 26b6980 (builder) - builder: switch charts to oci bfd4385 (controller) - controller: add get manager user status 874208d (controller) - controller: unified measurement model cadf98f (controller) - controller: add admission webhook e0050c2 (controller) - controller: new measurement model a11ba58 (controller) - controller: multi pod restart uses async fb3c15d (controller) - controller: add check app owner status 3d78b76 (controller) - controller: add resource services api 3d6a201 (controller) - controller: add search apps api 01c443a (controller) - controller: add KUBERNETES_CPU_MEMORY_RATIO parameter 7c26232 (controller) - controller: add volume size limit 3bee749 (controller) - controller: add annotations support 23cd97c (controller) - controller: traefik v2 support e37b7db (controller) - controller: add affinity b3b367b (controller) - controller: add volume expand support a4e154a (controller) - controller: add database replica support 2f37216 (controller) - controller: switch wsgi to asgi b3314a5 (controller) - controller: add pod exec api 75df2dc (controller) - controller: add stream support for app logs 4229bad (controller) - ccontroller: switch charts to oci 89bb19b (database) - database: upgrade to pg14 9f45a5d (database) - database: add hugepages support c4008c9 (database) - database: add affinity 411a7b2 (database) - postgres: use patroni 64e5cb0 (database) - database: switch charts to oci 2bab823 (fluentd) - fluentd: switch charts to oci 337ba62 (imagebuilder) - imagebuilder: run podman as rootless 4396ffa (imagebuilder) - imagebuilder: switch to oci charts f37ae09 (influxdb) - influxdb: add affinity 04503b2 (influxdb) - influxdb: add influxdb ha 41ddad5 (influxdb) - influxdb: switch charts to oci 2006480 (logger) - logger: use redis stream replace nsqd ab23d17 (logger) - logger: add affinity 81d4e9d (logger) - logger: switch charts to oci c3d9796 (monitor) - monitor: add affinity cd9de3c (monitor) - monitor: switch to oci charts 318a73f (passport) - passport: add change user confirm 79ef100 (passport) - passport: add re login at authorize 6927bb5 (passport) - passport: add affinity 3146a09 (passport) - passport: add google reCAPTCHA 802abcd (passport) - passport: add replica database support a0dcd1b (passport) - passport: switch wsgi to asgi 4c9dbba (passport) - passport: switch charts to oci 74825f7 (rabbitmq) - rabbitmq: add rabbitmq managentment ingress 12cf7d6 (rabbitmq) - rabbitmq: add affinity 103417d (rabbitmq) - rabbitmq: switch charts to oci 5d428bb (redis) - redis: add affinity a88c1a9 (redis) - redis: switch charts to oci 541585d (registry) - registry: add affinity e9ca9d4 (registry) - registry: add garbage-collect cronjob ec62a59 (registry) - registry: switch charts to oci fde0b07 (registry-proxy) - registry-proxy: switch charts to oci be14eb4 (storage) - minio: add affinity 51af696 (storage) - storage: add k8s csi support 76a75d9 (storage) - storage: add cluster health checker a17dc8c (storage) - storage: switch charts to oci Fixes e4f44fb (builder) - builder: no error return e38dfc7 (builder) - builderControllerHost/ControllerPort init error ff9069f (controller) - controller: influxdb query error f7f5069 (controller) - controller: authentication 500 7e297a8 (controller) - controller: add check remote user status 9db28e1 (controller) - controller: celery MaxRetriesExceededError 4bcff08 (controller) - controller: wrong name d69fde2 (controller) - controller: traefik ingress create error a3ad743 (controller) - fixup(controller: user login error 662c8dd (controller) - controller: change influxdb port 957bdf6 (controller) - controller: validate rsa key pairing before storage 419ec4c (controller) - controller: kubernetes pod/exec cluster role a67edaa (controller) - controller: Cannot routing:disable e09e214 (controller) - controller: allowlist cannot remove 318b126 (controller) - controller: domains update error 92855eb (database) - database: premission denied bde945a (database) - fixup(postgres: support arm, fix Failed to build psutil 7854d45 (database) - fixup(postgres: user name converted to lowercase letters 57b2a07 (fluentd) - fluentd: ifconfig_path not found 20e72b9 (imagebuilder) - imagebuilder: upgrade pack version 651db8a (imagebuilder) - imagebuilder: chown uid gid order d2e9164 (influxdb) - influxdb: proxy not running 3a1d361 (monitor) - monitor: charts naming d754ae0 (monitor) - monitor: telegraf init error 63f9e34 (monitor) - monitor: affinity error 95ae1e5 (passport) - passport: yarn build fail 3f5365e (passport) - passport: wrong name 907f17b (passport) - passport: change uid gid to 1001 e3911e0 (passport) - passport: ‘registration_done’ not found 2ace5f0 (passport) - passport: ui style b3ba1e1 (passport) - passport privacy policy link 172e9c8 (passport) - passport: check databaseReplicaUrl error a3aeb70 (rabbitmq) - passport: change uid gid to 1001 5c73dcf (redis) - reids: DRYCC_REGISTY misspelling d7e3baf (redis) - redis: env miss cadaa91 (registry) - registry: set gid uid to 1001 d524217 (registry) - registry: storage run error 854f912 (registry) - registry: chown uid gid order e642bb7 (registry-proxy) - registry-proxy: containerPort error 8dfd029 (registry-proxy) - registry-proxy: chown uid gid order bbea364 (storage) - minio: premission denied 97deba1 (storage) - storage: node unimplemented error b9bdeff (storage) - storage: pd can not connect each other Style 1edb10c (controller) - controller: database convention over configuration 1960cc3 (database) - database: database name convention over configuration 06d1f5d (imagebuilder) - imagebuilder: URL to Url b8a8941 (passport) - passport: database convention over configuration Maintenance 8e9a199 (builder) - builder: upgrade controller-sdk-go 4840151 (builder) - builder: use exec runner replace docker runner 68ccfb1 (builder) - builder: canonical charts naming 8f971cb (builder) - builder: provide any additional service annotations fe2c55d (builder) - dockerfile: use drycc/base image 2b5e706 (builder) - dockerfile: change user and workdir 7a6c8d3 (builder) - builder: set gid uid to 1001 fe494f7 (builder) - dockerfile: use uid gid a7c8752 (builder) - builder: change nodes to pod affinity eb2e94c (builder) - database: bump mc 2022.04.01.23.44.48 cfaae66 (builder) - builder: use registry.drycc.cc replace docker.io d7d2890 (builder) - builder: change default imagebuilder registry ecfdb19 (builder) - imagebuilder: change python-dev registry 6da17f4 (builder) - builder: https://github.com/minio/minio/issues/14331 1a57e5b (builder) - builder: https://github.com/minio/minio/issues/14331 f1464fa (builder) - builder: https://github.com/minio/minio/issues/13799 b1e1c4f (builder) - builder: use env replace creds volume 71a4145 (builder) - builder: bump go.mod 3567688 (builder) - builder: fine management affinity 73ea38b (builder) - builder: change storage to minio 1f91321 (builder) - builder: use testify replace assert d148b9c (builder) - builder: add check storage health b768101 (builder) - builder: change initContainers 1b3bec3 (builder) - builder: add replicas 5cb0d61 (builder) - builder: upgrade to latest controller-sdk-go 98b9d58 (builder) - builder: upgrade new require 65817c3 (builder) - builder: change drycc.cc to www.drycc.cc 4e3f9d0 (controller) - controller: add celery retry mechanism f6716fe (controller) - controller: change cronjob name eb60693 (controller) - controller: refine celery task priority 66905e9 (controller) - controller: change manager auth ea20c41 (controller) - controller: remove start/stop api 4c8fc80 (controller) - controller: improve tasks error handling cf7402e (controller) - controller: add blocklist api 80f14dd (controller) - controller: use get_user_model replace auth.User ffc7bb7 (controller) - controller: use JSONField replace ArrayField 370df8c (controller) - controller: add validate metric 29084ce (controller) - controller: use user id request manager api 718fe12 (controller) - controller change urlpatterns order 71f4042 (controller) - controller: measurements uses lowercase letters e5123ea (controller) - controller: change resource unit to number 18fee9a (controller) - deps: bump celery from 5.1.2 to 5.2.2 in /rootfs ffca6c1 (controller) - controller: use exec runner replace docker runner 9ec12e1 (controller) - controller: simplify drone configuration 4b4749e (controller) - controller: set default CSRF_COOKIE_SECURE false 2ef6338 (controller) - deps: bump django from 3.2.5 to 3.2.10 in /rootfs c7570d0 (controller) - deps: bump django from 3.2.10 to 3.2.11 in /rootfs 8b17bc1 (controller) - controller: canonical charts naming c928fb0 (controller) - controller: use rabbitmq cluster f917185 (controller) - controller: provide any additional service annotations 22a8f63 (controller) - deps: bump django from 3.2.11 to 3.2.12 in /rootfs 3cc3b00 (controller) - dockerfile: use drycc/base image ee274f6 (controller) - controller: set venv profile ce6b069 (controller) - controller: set gid uid to 1001 3a105d3 (controller) - dockerfile: use uid gid 15f9b0e (controller) - controller: code review 01e6fd9 (controller) - controller: use passport user id 893ee31 (controller) - oauth2: update user info pipline 3028fb4 (controller) - user: set AnonymousUser username 5daf82d (controller) - controller: set worker_cancel_long_running_tasks_on_connection_loss 61f2c53 (controller) - controller: change nodes to pod affinity 88feb1d (controller) - imagebuilder: python=3.10.4 rabbitmq=3.9.14 914e03f (controller) - controller: use registry.drycc.cc replace docker.io a5bb548 (controller) - controller: change python-dev registry 3ecdd7c (controller) - controller: add a separate rabbitmqUrl configuration 967cb11 (controller) - controller: remove APP_STORAGE 473d2b5 (controller) - controller: use env replace creds volume e410d4c (controller) - deps: bump django from 3.2.12 to 3.2.13 in /rootfs c6ef777 (controller) - controller: simplified passport config 0fd3233 (controller) - controller: remove settings hardcode a64e99c (controller) - controller: change passport config 62aba25 (controller) - controller: set cronjob timezone to utc 760b70b (controller) - controller: change default ratio 8dffc3a (controller) - controller: fine management affinity 26043c4 (controller) - controller: change default app storage 608bd8d (controller) - deps: bump django from 3.2.13 to 3.2.14 in /rootfs 18ed0c2 (controller) - controller: remove conjob affinity add6712 (controller) - controller: add volume expand support use patch cc1ad13 (controller) - controller: add startupProbe 0e9a603 (controller) - controller: add clearsocial cronjob eb6f05d (controller) - controller: change initContainers 762c676 (controller) - controller: change replicas abd7e8c (controller) - deps: bump django from 3.2.14 to 3.2.15 in /rootfs 07fdf1b (controller) - controller: remove database conn_max_age ef8e41f (controller) - controller: add database replica check 79143f2 (controller) - controller: upgrade new require a624048 (controller) - controller: add app.refresh func annotation b22d367 (controller) - controller: optimize app refresh timing fe98f0c (database) - database: use exec runner replace docker runner 5e00c11 (database) - database: canonical charts naming d2cb860 (database) - database: disable huge_pages 197d80d (database) - database: add persistence 1c3e645 (database) - database: provide any additional service annotations 37730ab (database) - dockerfile: use drycc/base image 5014112 (database) - dockerfile: change entrypoint 29b538e (database) - database: change nodes to pod affinity c2bb074 (database) - database: bump python 3.10.4 and mc 2022.04.01.23.44.48 077a4e9 (database) - database: use registry.drycc.cc replace docker.io 560bdb9 (database) - database: change python-dev registry 1e54b55 (database) - database: https://github.com/minio/minio/issues/14331 d646672 (database) - database: https://github.com/minio/minio/issues/13799 a6ac4e3 (database) - database: use env replace creds volume 9618d87 (database) - database: fine management affinity b823273 (database) - database: change minio to storage 7bd5a90 (database) - database: add check storage health 20c6d96 (database) - database: fix storage run error 8bde830 (database) - database: upgrade to pg 14.5 a33b5e5 (fluentd) - fluentd: update plugins eed7a78 (fluentd) - fluentd: update filter kubernetes setting cc83dd8 (fluentd) - fluentd: update elasticsearch store setting and support exclude specific container logs ba2feb2 (fluentd) - fluentd: use exec runner replace docker runner d528676 (fluentd) - fluentd: simplify drone configuration dece82d (fluentd) - fluentd: canonical charts naming 4e0a802 (fluentd) - fluend: replace nsqd with redis 15ceca0 (fluentd) - dockerfile: use drycc/base image a7f619f (fluentd) - dockerfile: change workdir 9adf5ed (fluentd) - database: bump fluentd 1.14.6 50c14c2 (fluentd) - fluentd: use registry.drycc.cc replace docker.io 83171b1 (fluentd) - fluentd: change python-dev registry ec83581 (fluentd) - fluentd: unified reids declaration 07c63e2 (fluentd) - fluentd: upgrade fluentd 1.15.2 65df9be (imagebuilder) - imagebuilder: update pack version 66cab35 (imagebuilder) - imagebuilder: use dind replace go-dev 0c82060 (imagebuilder) - imagebuilder: use exec runner replace docker runner 8146da9 (imagebuilder) - imagebuilder: canonical charts naming 7d97241 (imagebuilder) - dockerfile: use drycc/base image 07e805c (imagebuilder) - imagebuilder: change default buildpack 8d1038d (imagebuilder) - imagebuilder: upgrade podman to 4.0.1 62d3687 (imagebuilder) - imagebuilder: change workdir to /workspace da8bfb0 (imagebuilder) - imagebuilder: change uid gid to 1001 d44e3bc (imagebuilder) - imagebuilder: upgrade stack 5b0c7e6 (imagebuilder) - imagebuilder: use registry.drycc.cc replace docker.io f74cbf6 (imagebuilder) - imagebuilder: add defaultBuildpacksURL 941d493 (imagebuilder) - imagebuilder: https://github.com/minio/minio/issues/14331 449be91 (imagebuilder) - imagebuilder: https://github.com/minio/minio/issues/13799 63b0523 (imagebuilder) - imagebuilder: use env replace creds volume 4e8a6e5 (imagebuilder) - imagebuilder: add imagebuilder config 2d891f5 (imagebuilder) - imagebuilder: change minio to storage addceda (imagebuilder) - imagebuilder: upgrade new require a6e569f (imagebuilder) - imagebuilder: pack_build add –env-file parameter 6191ff5 (influxdb) - influxdb: use exec runner replace docker runner dc3f8c7 (influxdb) - influxdb: canonical charts naming 6b5c819 (influxdb) - influxdb: new ingress style 68b381d (influxdb) - influxdb: provide any additional service annotations ea20eb8 (influxdb) - dockerfile: use drycc/base image 64c0a71 (influxdb) - influxdb: set gid uid to 1001 a709ca1 (influxdb) - influxdb: use DRYCC_UID DRYCC_GID env 740dff0 (influxdb) - influxdb: use common affinity template e035673 (influxdb) - influxdb: change nodes to pod affinity f1cefbd (influxdb) - influxdb: use registry.drycc.cc replace docker.io a00100e (influxdb) - influxdb: fine management affinity 9d165ef (influxdb) - influxdb: add probe bee7fff (influxdb) - influxdb: upgrade to influxdb 2.4.0 254914c (logger) - logger: use exec runner replace docker runner 8d91c68 (logger) - logger: canonical charts naming b6d2182 (logger) - logger: provide any additional service annotations c35e59a (logger) - dockerfile: use drycc/base image a63c070 (logger) - logger: change workdir to /workspace a594b28 (logger) - logger: set gid uid to 1001 9a90e22 (logger) - dockerfile: use uid gid 36493b4 (logger) - logger: use common affinity template 897a3a5 (logger) - logger: change nodes to pod affinity 03b32ab (logger) - logger: use registry.drycc.cc replace docker.io a50ba5f (logger) - logger: change python-dev registry 23187a3 (logger) - logger: unified reids declaration aaa129a (logger) - logger: fine management affinity be4f656 (logger) - logger: add replicas 7c25459 (logger) - charts: add NetworkPolicy 6810149 (logger) - logger: remove memory storage a918c50 (logger) - logger: add .vscode to .gitignore a415210 (logger) - logger: add log follow support 59b1da3 (logger) - logger: upgrade new require 27cc151 (monitor) - monitor: use exec runner replace docker runner 07d6a9d (monitor) - monitor: canonical charts naming 1054357 (monitor) - monitor: use redis default port e3673df (monitor) - monitor: remove nsqd fc9dd3e (monitor) - monitor: new ingress style 856a898 (monitor) - monitor: add default user env 9857535 (monitor) - monitor: add random user 38b5a04 (monitor) - grafana: oauth auto login 5dfc579 (monitor) - monitor: upgrade version e121b5a (monitor) - monitor: provide any additional service annotations 84462a0 (monitor) - dockerfile: use drycc/base image b9e8ce8 (monitor) - monitor: chore(imagebuilder): change uid gid to 1001 05ee8ab (monitor) - dockerfile: use uid gid e1fa68e (monitor) - monitor: use common affinity template b8f302b (monitor) - monitor: change nodes to pod affinity 4fc991f (monitor) - database: bump telegraf 1.22.0 and grafana 8.4.5 21a2f6a (monitor) - monitor: use registry.drycc.cc replace docker.io acc976f (monitor) - monitor: change python-dev registry 62d76c1 (monitor) - monitor: unified reids declaration b3c57ad (monitor) - monitor: optimize oauth2 configuration 70af6b0 (monitor) - monitor: change passport config 69f9a88 (monitor) - monitor: fine management affinity 2fb278f (monitor) - monitor: rename influxdb port 17548ff (monitor) - grafana: update dashborad 69d7bbd (monitor) - grafana: influx dashborad disk size 75db1b0 (monitor) - monitor: upgrade new grafana/telegraf 80504a1 (monitor) - grafana: update influx and redis dashboard f7078cb (monitor) - monitor:chown use env 91ae0dd (passport) - passport: optimize login display 2d3bbbc (passport) - passport: change drycc logo 59790a7 (passport) - passport: make user email unique faea034 (passport) - passport: use strtobool 1fbf2bc (passport) - passport: use yarn replace npm 119cac8 (passport) - passport: use exec runner replace docker runner cff5062 (passport) - passport: set default CSRF_COOKIE_SECURE false 9cc0210 (passport) - passport: canonical charts naming 9ab3896 (passport) - passport: new ingress style 259ccc9 (passport) - passport: provide any additional service annotations af1bbcd (passport) - dockerfile: use drycc/base image 9ae5373 (passport) - passport: set venv profile 8f61090 (passport) - dockerfile: use uid gid fcaf72d (passport) - passport: upgrade npm package 546dcd5 (passport) - passport: add license 4bda2d6 (passport) - passport: use minify 73b0fd1 (passport) - passport: use common affinity template 278fe7a (passport) - passport: change nodes to pod affinity 3cd93d3 (passport) - passport: add reactive 370b493 (passport) - passport: add footer 483cbd6 (passport) - passport: use h_captcha replace re_captcha 3d1675e (passport) - database: bump python 3.10.4 and node 16.14.2 86a7835 (passport) - passport: use registry.drycc.cc replace docker.io 2d65355 (passport) - passport: change python-dev registry 90c1444 (passport) - passport: unified reids declaration 2e0e417 (passport) - passport: fix firefox footer ad274be (passport) - passport: use bulecss f986d8b (passport) - passport: add main footer 3e52867 (passport) - passport: dynamic settings for vue 38adabc (passport) - passport: change passport config f8d6b60 (passport) - passport: fine management affinity 2cbd79d (passport) - passport: remove database conn_max_age 7122797 (passport) - passport: change drycc.cc to www.drycc.cc 8cc84cd (rabbitmq) - rabbitmq: use exec runner replace docker runner f35930f (rabbitmq) - rabbitmq: add rabbitmq cluster support fbfa3ba (rabbitmq) - rabbitmq: canonical charts naming ca60701 (rabbitmq) - rabbitmq: use volumeClaimTemplates fe5d1b4 (rabbitmq) - rabbitmq: add sharding support 9c4ab97 (rabbitmq) - rabbitmq: provide any additional service annotations 348a88a (rabbitmq) - dockerfile: use drycc/base image 2388be1 (rabbitmq) - rabbitmq: upgrade erlang to 24.2.2 db2eaa5 (rabbitmq) - dockerfile: use uid gid 772afd1 (rabbitmq) - rabbitmq: change to wait pid file 2bfc25e (rabbitmq) - rabbitmq: use common affinity template 11d505e (rabbitmq) - rabbitmq: change nodes to pod affinity 69d63f1 (rabbitmq) - database: bump erlang 24.3.3 and rabbitmq 3.9.14 8380299 (rabbitmq) - rabbitmq: use registry.drycc.cc replace docker.io b3f69f1 (rabbitmq) - rabbitmq: add check rabbitmqLocaltion 5327c76 (rabbitmq) - rabbitmq: fine management affinity 5c66b5a (rabbitmq) - rabbitmq: change probe 27bebf9 (rabbitmq) - rabbitmq: add start-rabbitmq script 86ee6a7 (rabbitmq) - rabbitmq: upgrade to rabbitmq 3.10.7 1f29683 (redis) - redis: use exec runner replace docker runner a5041fc (redis) - redis: canonical charts naming 64468c2 (redis) - redis: add redis persistence de5d753 (redis) - redis: provide any additional service annotations f644639 (redis) - dockerfile: use drycc/base image 98051d2 (redis) - redis: premission denied bcb548e (redis) - dockerfile: use uid gid 524aa41 (redis) - redis: use common affinity template 26c9466 (redis) - redis: change nodes to pod affinity b67d7a2 (redis) - redis: use registry.drycc.cc replace docker.io 839ec50 (redis) - redis: use env replace creds volume 237ca86 (redis) - redis: fine management affinity bdd968d (redis) - redis: upgrade neew require 8b2910f (registry) - registry: use exec runner replace docker runner eedbe78 (registry) - registry: canonical charts naming 0241615 (registry) - registry: provide any additional service annotations 9b58da4 (registry) - dockerfile: use drycc/base image ab6acb7 (registry) - registry: change workdir to /workspace f368bf7 (registry) - registry: use DRYCC_UID DRYCC_GID env f4b9041 (registry) - registry: use common affinity template c2e87ca (registry) - registry: change nodes to pod affinity feb6aba (registry) - database: bump mc 2022.04.01.23.44.48 956932b (registry) - rregistry: use registry.drycc.cc replace docker.io deda8d8 (registry) - registry: move registry-secret.yaml from workflow to registry f52c7bf (registry) - registry: change python-dev registry 007fe03 (registry) - registry: https://github.com/minio/minio/issues/14331 d620c6d (registry) - registry: https://github.com/minio/minio/issues/13799 85e6b73 (registry) - registry: use env replace creds volume 6a1155d (registry) - registry: fine management affinity 7b8ebae (registry) - registry: change minio to storage 1338951 (registry) - registry: add check storage health 2fa769d (registry) - registry: change probe f187cbf (registry) - registry: add replicas 09d8a7b (registry) - registry: upgrade to mc 2022.08.28.20.08.11 4b187b8 (registry-proxy) - registry-proxy: use exec runner replace docker runner 29ffbbe (registry-proxy) - registry-proxy: canonical charts naming 6d783ba (registry-proxy) - registry-proxy: remove use_cni 8cf05cf (registry-proxy) - dockerfile: use drycc/base image 090e286 (registry-proxy) - registry-proxy: chore(imagebuilder): change uid gid to 1001 7cf6120 (registry-proxy) - registry-proxy: use DRYCC_UID DRYCC_GID env 3a00697 (registry-proxy) - registry-proxy: use registry.drycc.cc replace docker.io 30e69e8 (registry-proxy) - registry-proxy: add registry basic auth proxy 942abce (registry-proxy) - registry-proxy: upgrade to nginx 1.23.1 5ea3297 (storage) - minio: use exec runner replace docker runner 8306add (storage) - minio: canonical charts naming c917e9f (storage) - minio: provide any additional service annotations 042c732 (storage) - dockerfile: use drycc/base image 7b47b82 (storage) - minio: change workdir to /workspace 6f3531e (storage) - minio: use DRYCC_UID DRYCC_GID env 9795fb1 (storage) - minio: use common affinity template a7b09c5 (storage) - minio: change nodes to pod affinity 7607342 (storage) - database: bump mc 2022.04.01.23.44.48 and minio 2022.04.01.03.41.39 ea2b2f1 (storage) - minio: use registry.drycc.cc replace docker.io 445b501 (storage) - minio: https://github.com/minio/minio/issues/14331 f19fbc7 (storage) - minio: use env replace creds volume 8982e2e (storage) - minio: use minio to distributed 06bec73 (storage) - minio: fine management affinity 9b8f006 (storage) - storage: remove assert 59d64b9 (storage) - storage: change listen to POD_IP 60044ee (storage) - storage: add juicefs mount options 189f944 (storage) - storage: remove volumeName 302fe89 (storage) - storage: mv to minio dir 6ec586d (storage) - storage: change readinessProbee andlivenessProbe 0e028df (storage) - storage: add minio pdb cf9bd2d (storage) - storage: add check storage health svc 2dd5c9f (storage) - storage: add volumeBindingMode fa2effc (storage) - storage: remove databaseBucket d166cc7 (storage) - charts: format network-policy name d06bcce (storage) - storage: upgrade to golang 1.19 c2ca05c (storage) - storage: upgrade new require ","categories":"","description":"New Drycc Workflow Release v1.6.0","excerpt":"New Drycc Workflow Release v1.6.0","ref":"/blog/2022/10/21/drycc-workflow-v1.6.0/","tags":"","title":"Drycc Workflow v1.6.0"},{"body":"These release notes for Drycc Workflow v1.5.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.4.0, please refer to the following change summary.\nWorkflow ## v1.4.0 -\u003e v1.5.0 Releases passport v1.0.0 rabbitmq v1.0.0 imagebuilder v1.0.0 builder v1.2.0 -\u003e v1.3.0 controller v1.3.0 -\u003e v1.4.0 database v1.0.2 -\u003e v1.1.0 fluentd v1.1.0 -\u003e v1.2.0 redis v1.1.0 -\u003e v1.2.0 influxdb v1.0.1 -\u003e v1.1.0 logger v1.1.0 -\u003e v1.2.0 minio v1.1.0 -\u003e v1.2.0 monitor v1.1.0 -\u003e v1.2.0 nsqd v1.1.0 -\u003e v1.2.0 registry v1.0.3 -\u003e v1.1.0 registry-proxy v1.0.2 -\u003e v1.1.0 Features 0f5f8e4 (builder) - builder: multi-platform support f269d06 (builder) - build: add buildx supportjkjkk:q 5e72fe8 (builder) - registry: use docker build 25d8a4c (builder) - docker: dealing with the change of docker in kubenetes 1.20 7a3e1c5 (builder) - charts: set the default chart version 46b75ff (builder) - builder: add cloud native buildpacks support 2db2054 (builder) - builder: unified build model 4b7f9d9 (builder) - builder: add initContainers b78c936 (controller) - token: add get token api bac52a5 (controller) - tasks: use celery replace nsqd b9b0c58 (controller) - build: add buildx support 205dcb3 (controller) - influxdb: add influxdb client ff15849 (controller) - influxdb: upgrade to influxdb 2.x 4016244 (controller) - controller: push data to influx fcfce2e (controller) - workflow-manager: add workflow-manager support 00e9bfb (controller) - influxdb: review influxdb code dd644d5 (controller) - docker: dealing with the change of docker in kubenetes 1.20 118278b (controller) - charts: set the default chart version 122a9cd (controller) - oauth2: add oauth2 support 559a5b6 (controller) - controller: use cncf buildpacks replace slugrunner 96130e6 (controller) - charts: database configuration optimization of passport and controller 2ea8508 (controller) - oauth: using passport authentication 868c437 (database) - database: multi-platform support eadd5da (database) - build: add buildx support b6eea4c (database) - docker: dealing with the change of docker in kubenetes 1.20 04a88db (database) - charts: set the default chart version 92ed309 (database) - database: add initContainer ee6b78f (fluentd) - build: add buildx support f523e30 (fluentd) - docker: dealing with the change of docker in kubenetes 1.20 ee47b53 (fluentd) - charts: set the default chart version 80a51af (influxdb) - influxdb: modify influxdb naming rules fb10030 (influxdb) - influxdb: use influxdb v2 0e87ad8 (influxdb) - docker: dealing with the change of docker in kubenetes 1.20 9d10801 (influxdb) - charts: set the default chart version d825c9f (logger) - build: add buildx support b139576 (logger) - docker: dealing with the change of docker in kubenetes 1.20 88f84ea (logger) - charts: set the default chart version 5ccae3e (logger) - dockerfile: remove chmod cmd 193aefc (logger) - logger: add initContainers baee330 (minio) - minio: multi-platform support ad5d055 (minio) - build: add buildx support 19868d4 (minio) - docker: dealing with the change of docker in kubenetes 1.20 4bd84b8 (minio) - charts: set the default chart version 79d1f2f (monitor) - database: multi-platform support 88e5a7f (monitor) - build: add buildx support 5672e99 (monitor) - influxdb: modify influxdb naming rules 8672103 (monitor) - influxdb: use influxdb v2 66cb4c8 (monitor) - docker: dealing with the change of docker in kubenetes 1.20 9576eb3 (monitor) - charts: set the default chart version 30809c9 (monitor) - monitor: add initContainers 70d140c (nsqd) - nsqd: using self compiled nsq binary 1073d4f (nsqd) - nsqd: use GOPATH replace /go e498480 (nsqd) - build: add buildx support cf9b7d5 (nsqd) - docker: dealing with the change of docker in kubenetes 1.20 c335856 (nsqd) - charts: set the default chart version efba713 (redis) - build: add buildx support c7a3b53 (redis) - docker: dealing with the change of docker in kubenetes 1.20 4cdad7b (redis) - charts: set the default chart version 652b443 (registry) - registry: multi-platform support 4060176 (registry) - registry: use docker build 7102a03 (registry) - docker: dealing with the change of docker in kubenetes 1.20 6c8600d (registry) - charts: set the default chart version 33a51c9 (registry) - registry: add initContainers bef70dc (registry-proxy) - build: add buildx support d2319c1 (registry-proxy) - docker: dealing with the change of docker in kubenetes 1.20 02fafed (registry-proxy) - charts: set the default chart version Fixes 5499c9a (controller) - gunicorn: gunicorn not running 06e9e88 (controller) - controller: error loading shared library 01b5bd0 (controller) - controller: upgrade celery config 6e32d55 (controller) - controller: fix update resources bug 0e0d53f (controller) - chart: set the domain depends certManagerEnabled 2ac4ca8 (controller) - passport: error loading shared library libexpat.so.1 a0dd517 (fluentd) - fluentd: drone build 6eca2a3 (logger) - logger: golang lint 63b0aa0 (registry) - drone: charts url error Docs 472cfcc (controller) - controller organize README.md document d9d6e29 (redis) - redis: delete links that do not exist Test case 1468f57 (controller) - controller: add command unittest Maintenance 9999bfd (builder) - builder:replace the special words cda8b58 (builder) - builder: remove docker keyword from charts dc575dd (builder) - builder: use imagebuilder replace dockerbuilder d3bb183 (builder) - docker: use the full name of registry 5fe34d1 (builder) - travis: add DEV_REGISTRY 7e36453 (builder) - CICD: use drone 52b8d9d (builder) - drone: add image_registries volumes 65963f4 (builder) - k8s: add privileged to dind d345fcf (builder) - LICENSE: revert modifications to Apache license 7975c99 (builder) - drone: always pull image 59633dd (builder) - builder: modify launch imagebuild pod 8d14e67 (builder) - builder: use Procfile in anywhere 5357fa8 (builder) - go: bump go mod 8d26ac0 (builder) - k8s: k8s deprecated api migration 0af620d (builder) - chars: change org to imageTag ae84303 (builder) - builder: run imagebuider replace pod with job 3b2c496 (builder) - builder: change docs website 5679a4c (builder) - builder: upgrade to golang1.17 a214503 (controller) - controller:replace whitelist with allowlist 375ddcc (controller) - ps:drycc ps:list show autoscale num c32e409 (controller) - ldap: canot register when ldap is enabled c46580a (controller) - controller:modify redis config fa9e87b (controller) - chart:modify controller charts 6f9fd08 (controller) - nsq: remove nsq 994b2dc (controller) - docker-buildx: add check-docker a720c3a (controller) - controller: remove docker keyword from charts e9a5c84 (controller) - docker: use the full name of registry a26614a (controller) - controller: add rabbitmq env 3df229d (controller) - controller: modify database config \u0026\u0026 remove redis port config \u0026\u0026 add env prefix with DRYCC 257e94b (controller) - controller: CELERY_BROKER use rabbitmq and modify celery-deployment cronjob f4d6ec3 (controller) - chart: pretty chart format 63e6195 (controller) - influxdb: modify influxdb code 0f6d408 (controller) - CICD: use drone 87bad28 (controller) - python: upgrade to python3.9 e8f7560 (controller) - volumes: modify mount summary 6cf6c6b (controller) - drone: add image_registries volumes a9397e8 (controller) - oauth: modify token Authentication c7f8c8b (controller) - deps: bump django from 2.2.14 to 2.2.18 in /rootfs a1a08aa (controller) - deps: bump djangorestframework from 3.11.0 to 3.11.2 in /rootfs efd78b4 (controller) - deps: bump django from 2.2.18 to 2.2.20 in /rootfs 649b044 (controller) - deps: bump django from 2.2.20 to 2.2.22 in /rootfs 41b742b (controller) - deps: bump django from 2.2.22 to 2.2.24 in /rootfs 22ffe5d (controller) - LICENSE: revert modifications to Apache license c98b468 (controller) - drone: always pull image 20e6edb (controller) - chart: modify the problem of using buildpack db16879 (controller) - controller: pretty pods list print ba6f456 (controller) - test: pretty pods list print 5fce4b7 (controller) - k8s: k8s deprecated api migration e9e0bcb (controller) - oauth: using passport authentication 0311172 (controller) - chars: change org to imageTag 150eff1 (controller) - charts: update cert-manager api version de8545a (controller) - controller: update requirements 1442207 (controller) - controller: using django native JSONFiled ab4e836 (controller) - oauth: modify passport api 5c54e06 (controller) - controller: eliminate pip warnings 870328d (controller) - controller: remove entrypoint 5e5e6ae (controller) - controller: upgrade celery config 607778f (controller) - controller: add initContainer 23dc016 (controller) - chart: set the domain depends certManagerEnabled f3cf20b (controller) - controller: remove default bash env 73f2636 (controller) - controller: modify alpinelinux repositories 498e9f2 (controller) - chart: change certManagerEnabled to boolean type 27f5308 (controller) - passport: exclude cryptography 370b75d (controller) - controller: use sh env 07585b4 (database) - postgres:replace the special words 20172dc (database) - database: remove docker keyword from charts abb9b88 (database) - docker: use the full name of registry e72f58f (database) - chart: modify the off-cluster database a91f64f (database) - travis: add DEV_REGISTRY 614fb76 (database) - tests: use add-host replace link a3428f3 (database) - CICD: use drone 239fef1 (database) - drone: add image_registries volumes 42858e1 (database) - LICENSE: revert modifications to Apache license d0fe850 (database) - drone: always pull image 34a36ad (database) - charts: Nn secret is generated during off-cluster 064ccf4 (database) - database: create database 9228992 (database) - chars: change org to imageTag 9f7810c (database) - database: upgrade to wal-g v1.1 05783f4 (fluentd) - fluentd:replace the special words 0739809 (fluentd) - influxdb:replace monitor-influx with influx f02487c (fluentd) - fluentd: remove docker keyword from charts 2c96cc0 (fluentd) - docker: use the full name of registry b20c429 (fluentd) - charts: remove port config 6dd0197 (fluentd) - travis: add DEV_REGISTRY c5bec51 (fluentd) - CICD: use drone f8524b7 (fluentd) - drone: add image_registries volumes a50878a (fluentd) - LICENSE: revert modifications to Apache license 14fe20e (fluentd) - drone: always pull image 4a2f660 (fluentd) - k8s: k8s deprecated api migration de2dd91 (fluentd) - chars: change org to imageTag a9f1944 (fluentd) - fluentd: upgrade to fluentd1.14 7cb4e95 (influxdb) - influxdb: change username to user 0fdc21b (influxdb) - influxdb: remove docker keyword from charts b2acddb (influxdb) - influxdb: change default path ba88919 (influxdb) - influxdb: add check_env function 9117401 (influxdb) - influxdb: modify init_influxdb has_bucket 092a3e6 (influxdb) - chart: pod not readiness 51de380 (influxdb) - travis: add DEV_REGISTRY 66d7667 (influxdb) - docker: replace influxdb base image 3aa3094 (influxdb) - CICD: use drone 14b9c24 (influxdb) - drone: add image_registries volumes 02b4cd1 (logger) - logger:replace the special words 114b5d5 (logger) - reids: delete the logger prefix of redis 639278a (logger) - redis: remove logger from redis conf 90195e2 (logger) - go: remove GOOS and GOARCH 31e2e27 (logger) - logger: remove docker keyword from charts 8fbd9fa (logger) - docker: use the full name of registry b39df2d (logger) - charts: remove redis\\nsqd port config 35d6d07 (logger) - travis: add DEV_REGISTRY 69aabf5 (logger) - tests: remove docker link e916644 (logger) - CICD: use drone d6872b7 (logger) - drone: add image_registries volumes 37801da (logger) - LICENSE: revert modifications to Apache license cfb4b38 (logger) - drone: always pull image 8bda3bf (logger) - go: bump go mod e13ebfc (logger) - chars: change org to imageTag 38e6d8d (minio) - minio:replace the special words d6925dd (minio) - minio: remove docker keyword from charts d56bc39 (minio) - docker: use the full name of registry e4696cc (minio) - travis: add DEV_REGISTRY 70c5c79 (minio) - minio: use latest version 773cf6c (minio) - Makefile: remove DEV_REGISTRY ?= 5ce5bc6 (minio) - CICD: use drone 5da8be3 (minio) - drone: add image_registries volumes c1f0611 (minio) - LICENSE: revert modifications to Apache license b73f792 (minio) - drone: always pull image 79d1c93 (minio) - go: bump go mod c448899 (minio) - chars: change org to imageTag 15ee49e (minio) - minio: migrate deprecated warning 9968a1a (minio) - minio: upgrade to golang1.7 14fedd2 (monitor) - monitor:replace the special works 52c431a (monitor) - reids: delete the logger prefix of redis 2c95b47 (monitor) - redis: remove logger from redis conf da9bc56 (monitor) - monitor:remove influxdb 53f47b9 (monitor) - grafana: use grafana docker image 5bdb188 (monitor) - grafana: use grafana docker image c0586dd (monitor) - monitor: remove docker keyword from charts 87d02b6 (monitor) - charts: add nodes and persistentvolumes rule 1b5598f (monitor) - monitor: modify grafana dashboard with FLUX and pretty config.toml bcbc0d5 (monitor) - docker: use the full name of registry 9418c9e (monitor) - monitor: fix upload dashboard error and modify INFLUXDB input 589f29a (monitor) - travis: add DEV_REGISTRY f776f8a (monitor) - CICD: use drone 6ca3060 (monitor) - drone: add image_registries volumes 6a9ffb2 (monitor) - LICENSE: revert modifications to Apache license 45e41ed (monitor) - drone: always pull image 654d407 (monitor) - k8s: k8s deprecated api migration 41e9b9c (monitor) - chars: change org to imageTag 99c10d3 (monitor) - charts: update cert-manager api version 9bf83c4 (monitor) - oauth: user oauth passport a128f6d (monitor) - chart: change certManagerEnabled to boolean type 8f897fe (monitor) - chart: set the domain depends certManagerEnabled ba6d793 (nsqd) - README:update travis build status 49879c4 (nsqd) - nsqd: minimum git clone code c5e2680 (nsqd) - nsqd: remove docker keyword from charts 21dd17b (nsqd) - docker: use the full name of registry 7d86b3c (nsqd) - charts: remove port config c073d95 (nsqd) - travis: add DEV_REGISTRY 55c297c (nsqd) - CICD: use drone 165c2ae (nsqd) - drone: add image_registries volumes 9c6a1f8 (nsqd) - LICENSE: revert modifications to Apache license 9283098 (nsqd) - drone: always pull image 46acf8a (nsqd) - k8s: k8s deprecated api migration 43caf80 (nsqd) - chars: change org to imageTag 6897471 (nsqd) - nsqd: use official image 297bc05 (redis) - redis:replace the special words f5f8b5e (redis) - reids: delete the logger prefix of redis af7b657 (redis) - redis: change logger-redis to redis 8dca154 (redis) - redis: remove logger from redis conf eaeda2d (redis) - redis: remove docker keyword from charts 53c6358 (redis) - docker: use the full name of registry ae37416 (redis) - charts: remove port config e985656 (redis) - travis: add DEV_REGISTRY 423336a (redis) - CICD: use drone be64ab4 (redis) - drone: add image_registries volumes 3bec735 (redis) - LICENSE: revert modifications to Apache license 4f934f6 (redis) - drone: always pull image 359b878 (redis) - chars: change org to imageTag 83b8ac2 (registry) - workflow:replace the special words 869b280 (registry) - registry: remove docker keyword from charts 999c1e9 (registry) - docker: use the full name of registry 5652da9 (registry) - travis: add DEV_REGISTRY cc8c6c2 (registry) - CICD: use drone c7bdbd0 (registry) - CICD: pretty .drone.yaml format 5c55a38 (registry) - test: use add-host replace link f8866f3 (registry) - drone: add image_registries volumes 6c8292f (registry) - LICENSE: revert modifications to Apache license 1d50f2c (registry) - drone: always pull image efbca6d (registry) - chars: change org to imageTag 2eafc59 (registry-proxy) - registry-proxy: update nginx 071bd86 (registry-proxy) - charts: upgrade k8s newer API versions c72db96 (registry-proxy) - registry-proxy: change travis icon url 63ffb92 (registry-proxy) - registry-proxy:replace the special works 1d904a6 (registry-proxy) - registry-proxy: remove docker keyword from charts c8200b1 (registry-proxy) - docker: use the full name of registry d3fa939 (registry-proxy) - travis: add DEV_REGISTRY 5a8b353 (registry-proxy) - CICD: use drone 703d05a (registry-proxy) - drone: add image_registries volumes aa71db1 (registry-proxy) - LICENSE: revert modifications to Apache license 710c126 (registry-proxy) - drone: always pull image 2dcc5e6 (registry-proxy) - chars: change org to imageTag ","categories":"","description":"New Drycc Workflow Release v1.5.0","excerpt":"New Drycc Workflow Release v1.5.0","ref":"/blog/2022/10/06/drycc-workflow-v1.5.0/","tags":"","title":"Drycc Workflow v1.5.0"},{"body":"These release notes for Drycc Workflow v1.3.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.4.0, please refer to the following change summary.\nWorkflow ## v1.3.0 -\u003e v1.4.0 Releases builder v1.1.0 -\u003e v1.2.0 slugbuilder v1.1.1 -\u003e v1.2.0 dockerbuilder v1.1.1 -\u003e v1.1.2 controller v1.2.1 -\u003e v1.3.0 slugrunner v1.1.1 -\u003e v1.1.2 database v1.0.1 -\u003e v1.0.2 fluentd v1.0.1 -\u003e v1.1.0 redis v1.0.0 -\u003e v1.1.0 logger v1.0.0 -\u003e v1.1.0 minio v1.0.1 -\u003e v1.1.0 monitor v1.0.1 -\u003e v1.1.0 nsqd v1.0.0 -\u003e v1.1.0 registry v1.0.2 -\u003e v1.0.3 registry-proxy v1.0.0 -\u003e v1.0.1 Features fc7d93f (builder) - builder: use go-dev 0c2159e (builder) - builder: fmt code and add create_bucket script 1b88340 (controller) - controller: remove deprecated api a92fdeb (controller) - routable: ingress support routable 1e3eab3 (controller) - maintenance: add maintenance support for ingress 56b9dd0 (controller) - crt: support containerd-ctr 5fc3b46 (controller) - controller: add ephemeral-storage restriction d677e52 (controller) - controller: add a volume command 5f1323a (controller) - controller:drycc run cmd add –mount para 74c36a5 (controller) - tasks: add distributed async task 139c3ca (controller) - tasks: change nsq reader to async f237d74 (controller) - controller:add drycc resource cmd 41b46d0 (controller) - controller:add drycc resource cmd improvement c26f7d8 (controller) - controller: add LimitRanges support 45b5d1b (controller) - users: add users status api 4e16f9b (controller) - ps:add ps:stop/start command c659fa9 (controller) - k8s: add k8s cluster domain 31a625d (controller) - ps:add ps:stop/start command 00a779a (fluentd) - fluentd: support containerd log format f3f1bd4 (fluentd) - nsqd: add stateless nsqd cluster support db7147c (fluentd) - mirrors: delete aliyun mirrors 689c12e (logger) - nsqd: add stateless nsqd cluster support 78ccc5d (logger) - redis: add redis client cluster support 9843f2c (logger) - k8s: add k8s cluster domain 6ba122e (minio) - minio: add pvc support 6973550 (monitor) - monitor: add ingress for monitor cd73305 (monitor) - charts: add volumeName support 4769fe9 (monitor) - nsqd: add stateless nsqd cluster support 87806df (monitor) - k8s: add k8s cluster domain 4db40c4 (nsqd) - nsqd: add stateless nsqd cluster support b6f3d4f (nsqd) - nsqd: add stateless nsqd cluster support 74b85bb (redis) - redis: change redis to statefulset ff98b50 (slugbuilder) - slugbuilder: delete build hook b201c2f (slugbuilder) - buildpacks: use drycc buildpacks Fixes 0ec042d (builder) - test: fix test case error 4fb113b (builder) - build: base image replace by alpine 443df48 (builder) - minio: fix not bucket error 3dab5b0 (builder) - minio: create bucket error 734fca6 (controller) - autoscale: Fix for autoscale on k8s-1.9+ without breaking manual scaling a7dcd10 (controller) - controller: test pass 93f0f2e (controller) - controller: fix migrations error 4724375 (controller) - controller: fix test error 7bacf29 (controller) - charts: fix clusterrole 90957f7 (controller) - pod: sort events error 440b13e (controller) - controller: review table structure 0a470a6 (controller) - controller: bump tornado 5.1.1 e39218b (controller) - pynsq: no current event loop in thread 1d8630e (controller) - tests: fix test_task.py run error 1ff1202 (controller) - controller: fix test case d8c0da3 (controller) - settings: fix env name 6d8fd36 (database) - 003_restore_from_backup.sh: ignore script exit 1 e0394a9 (database) - minio: fix not bucket error f35f252 (database) - mc: fix create_bucket error 74d6886 (database) - postgres: recovery mode not run e50d0c1 (dockerbuilder) - caddy: fix caddy not start f3bec7a (fluentd) - influxdb: fix influxdb host and port bc19f27 (fluentd) - charts: skipped value for daemon_environment: Not a table 338d623 (logger) - logger: logger not run in alpine 7788302 (minio) - minio: bump minio version 619eed0 (minio) - fix: use go mod replace dep 3b42122 (monitor) - monitor: fix host error 67998ef (monitor) - influxdb: replace drycc-monitor-influxapi to drycc-monitor-influx-api 2cc361c (registry) - registry: fix test case 548297a (registry) - minio: fix not bucket error 5412ddb (registry) - minio: create bucket error d0d629e (slugbuilder) - slugbuilder:fix normalize_storage path d76ecbe (slugbuilder) - slugbuilder: use v3 api c505e18 (slugbuilder) - shellcheck: SC2039 Style c893a17 (builder) - builder: fmt code bba5795 (controller) - controller: format code d36082b (controller) - controller: fix pep8 66026f2 (controller) - resource: standardize the naming of resource 03d7e2c (controller) - servicecatalog: change servicecatalog to svcat 49dbb6d (controller) - controller: flake8 upgrade cbfc108 (monitor) - monitor: format charts and dashboard ee85954 (slugbuilder) - slugbuilder: use shellcheck 3afed2e (slugbuilder) - docker: simplify dockerfile 36b7f68 (slugrunner) - docker: simplify dockerfile Maintenance 61bb0ef (builder) - aws: upgrade aws sdk version 0f2e074 (builder) - chore: use go mode replace dep e9a2219 (builder) - builder: delete glide up bb8c518 (builder) - registry: del quay.io fa6d02f (builder) - builder: upgrade go.sum 9d61e8d (builder) - build: upgrade go.mod d763a98 (builder) - charts: upgrade k8s newer API versions d1bc1aa (builder) - pkg: upgrade to new drycc/pkg 02b1e98 (builder) - builder: update go mod 8e17d65 (builder) - builder: change alpine repositories f32b723 (builder) - mirrors: delete aliyun mirrors e33dc61 (builder) - minio: use bin mc replace docker images 3ab4f1c (builder) - builder: update controller-sdk-go b2adfac (builder) - heroku: remove heroku-16 support f429ac8 (builder) - builder: set GIT_LOCK_TIMEOUT to 30 minutes 7197c83 (builder) - go.mod:upgrade require pkg controller-sdk-go 5f3e22d (controller) - deps: bump django from 1.11.21 to 1.11.22 in /rootfs 1db645a (controller) - deps: bump django from 1.11.22 to 1.11.23 in /rootfs fbe8067 (controller) - deps: bump django from 1.11.23 to 1.11.29 in /rootfs 537d667 (controller) - registry: del quay.io a23c65b (controller) - deps: update all deps to the latest version 546337e (controller) - charts: upgrade k8s newer API versions 06023f8 (controller) - workflow-manager: del workflow-manager bba5736 (controller) - controller: change cluster-issuer location 6c43661 (controller) - Certificatechange cluster-issuer location 39a4728 (controller) - controller:change cluster-issuer location del controller-cluster-issuer.yaml 9e96d3f (controller) - Certificate:upgrade version cert-manager.io/v1alpha2 8e68049 (controller) - docker: use INDEX_URL replace index.docker.io 8fda205 (controller) - cert_manager: change cert_manager_enabled to global 6fefb6d (controller) - charts: change platform_domain to global 064b2ad (controller) - maintenance: remove maintenance support b8797c9 (controller) - workflow: remove namespace 1b20d76 (controller) - quota: add kube quota config d780075 (controller) - pod: add pod default resources support 3d72c08 (controller) - rename: rename ingress name 0aa6ab9 (controller) - mirrors: delete aliyun mirrors 7533a65 (controller) - heroku: remove heroku-16 support e5a885d (controller) - controller:check mount volume path 9014e74 (controller) - test: optimization Dockerfile.test 0b6ebb2 (controller) - tasks: change apply_async parameters 835f009 (controller) - wsgi: add tornado 6 support 67a4ad7 (controller) - utils: use threads replace asyncio a28949b (controller) - ldap: add AUTH_LDAP_USER_FLAGS_BY_GROUP a903209 (controller) - charts: add custom controller environment variables support e0e783e (controller) - ldap: change filter style d760825 (controller) - scheduler: remove debug log a25928e (controller) - wsgi: remove a wsgi.py file 7b2696e (controller) - log: disable nsq.client info log 8d5c07b (controller) - charts: add default environment 025f4a2 (controller) - controller: change quota name ebda60e (controller) - controller: review pvc code 8832ba9 (controller) - controller: change status\\binding model type and mount path check container_types 7148d04 (controller) - controller: add overcommit cpu and ram support 4d2087c (controller) - limits: modify limits unit verification af36970 (controller) - api: check cpu/memory range for api 329355b (controller) - volumes: modify the volume size 9dfee09 (controller) - LimitRanges: modify the default limits 5205bca (controller) - controller: improve the details of certificate 7ebecdf (database) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z 6415e2c (database) - postgres: upgrade to pg13 12e6806 (database) - charts: upgrade k8s newer API versions d294509 (database) - minio: use canary minio test 1bad02e (database) - mirrors: delete aliyun mirrors d51420b (database) - minio: use bin mc replace docker images 4133d05 (dockerbuilder) - dockerbuilder: update caddy and kaniko 6b4dd18 (dockerbuilder) - minio: use bin mc replace docker images 6df9b7c (fluentd) - deps-dev: update rake requirement from ~\u003e 10.0 to ~\u003e 12.3 c2490f8 (fluentd) - fluentd: upgrade fluentd be4a56a (fluentd) - fluentd: add Gemfile.lock 2237f75 (fluentd) - charts: upgrade k8s newer API versions c574065 (fluentd) - charts: upgrade k8s newer API versions 52b8084 (fluentd) - router: delete obsolete router code 3b3cceb (fluentd) - fluentd: remove manifests dir 25c6702 (fluentd) - nsqd: change var name bd571be (fluentd) - nsqd: change DRYCC_NSQD_ADDRESSES to DRYCC_NSQD_ADDRS 72aa4e6 (fluentd) - influxdb: change influxdb service name bd61903 (logger) - logger: use go mod replace dep 69c63a1 (logger) - logger: update go.mod 3aa9cd7 (logger) - registry: del quay.io f058496 (logger) - nsqd: change var name 6d9787c (logger) - nsqd: change DRYCC_NSQD_ADDRESSES to DRYCC_NSQD_ADDRS 85ed307 (logger) - logger: standard naming d88e7b6 (minio) - minio: update minio api to v7 43715d2 (minio) - minio: upgrade minio 0e1239b (minio) - minio: use docker.io replace quay.io f7f047b (minio) - registry: del quay.io afa7128 (minio) - build: upgrade go.mod aff2db5 (minio) - charts: upgrade k8s newer API versions 4547f14 (minio) - pkg: upgrade to new drycc/pkg 2769b85 (minio) - minio: use bin mc replace docker images 35dde8d (monitor) - monitor: update grafana influxdb telegraf 9e3a949 (monitor) - charts: upgrade k8s newer API versions 6af0432 (monitor) - workflow-manager: remove workflow-manager 0611c07 (monitor) - router: delete obsolete router code be04824 (monitor) - cert_manager: change cert_manager_enabled to global 3780165 (monitor) - charts: change platform_domain to global 50b04e1 (monitor) - influxdb: remove influxdb admin ui 6ab4d68 (monitor) - influxdb: remove unuse port f1510bd (monitor) - monitor: update grafana dashboard,telegraf inputs.kubernetes f36de2c (monitor) - pvc: upgrade to new format fc78a0a (monitor) - workflow: remove namespace e85890f (monitor) - monitor: monitoring nsqd and redis separately 694f6b1 (monitor) - mirrors: delete aliyun mirrors 4aea36a (monitor) - grafana: add ldap support for grafana 68fc30f (nsqd) - nsq: update nsq 16f32aa (nsqd) - charts: upgrade k8s newer API versions 04db389 (redis) - reids: update to redis 6 3f01bab (redis) - charts: upgrade k8s newer API versions 647e4be (registry) - registry: del quay.io 0bbce99 (registry) - charts: upgrade k8s newer API versions a982b50 (registry) - minio: use bin mc replace docker images e088da3 (registry-proxy) - ingress: renmae use_native_ingress to use_ingress 7e88337 (registry-proxy) - nginx: upgrade nginx to mainline 7204d72 (registry-proxy) - registry: optimizing variable naming 2eafc59 (registry-proxy) - registry-proxy: update nginx 071bd86 (registry-proxy) - charts: upgrade k8s newer API versions c72db96 (registry-proxy) - registry-proxy: change travis icon url ca9f962 (slugbuilder) - slugbuilder: del BUILDPACK_URL support 1b74dd5 (slugbuilder) - slugbuilder: add heroku-20 support 54d4ad2 (slugbuilder) - slugbuilder: del quay.io a78f37e (slugbuilder) - slugbuilder: add heroku-20 stack 94ac94a (slugbuilder) - minio: use bin mc replace docker images 53b4b8b (slugbuilder) - slugbuilder: modify stack priority 58e2bd2 (slugbuilder) - dockerfile: add WORKDIR /tmp b29cd04 (slugbuilder) - slugbuilder: add pre_build.sh 9d319f6 (slugbuilder) - slugbuilder: silent mc command output d1ec3c9 (slugbuilder) - heroku: remove heroku-16 support 5048534 (slugbuilder) - slugbuilder: use drycc stack-images a116537 (slugrunner) - slugrunner: add heroku-20 support a1196bf (slugrunner) - slugrunner: del quay.io 64c96d7 (slugrunner) - slugrunner: add heroku-20 stack cc3e226 (slugrunner) - minio: use bin mc replace docker images 9130bde (slugrunner) - shellcheck: shellcheck installer 4ea33e1 (slugrunner) - slugrunner: modify stack priority 5514e8b (slugrunner) - heroku: remove heroku-16 support be829fb (slugrunner) - slugrunner: use drycc stack-images e1e06be (slugrunner) - slugrunner: remove Dockerfile.heroku-16 ","categories":"","description":"New Drycc Workflow Release v1.4.0","excerpt":"New Drycc Workflow Release v1.4.0","ref":"/blog/2021/10/06/drycc-workflow-v1.4.0/","tags":"","title":"Drycc Workflow v1.4.0"},{"body":"These release notes for Drycc Workflow v1.3.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.2.0, please refer to the following change summary.\nWorkflow ## v1.2.0 -\u003e v1.3.0 Releases builder v1.0.2 -\u003e v1.1.0 slugbuilder v1.1.0 -\u003e v1.1.1 dockerbuilder v1.1.0 -\u003e v1.1.1 controller v1.2.0 -\u003e v1.2.1 slugrunner v1.1.0 -\u003e v1.1.1 database v1.0.0 -\u003e v1.0.1 fluentd v1.0.0 -\u003e v1.0.1 minio v1.0.0 -\u003e v1.0.1 monitor v1.0.0 -\u003e v1.0.1 registry v1.0.1 -\u003e v1.0.2 workflow-manager v1.0.0 -\u003e v1.0.1 Features 9c7cceb (builder) - builder: add app config to env Fixes 7fe44fa (controller) - docker: docker timeout must be an int, float or None b196550 (controller) - controller: revert release.check_image_access for now cc3ec13 (workflow-manager) - glide: bump goautoneg Maintenance ef932c4 (builder) - controller-sdk-go: upgrade controller-sdk-go 4654cf6 (controller) - django-rest-framework: upgrade to 3.9.3 14121f1 (controller) - deps: bump djangorestframework from 3.9.3 to 3.9.4 in /rootfs 385acdc (controller) - deps: bump django from 1.11.20 to 1.11.21 in /rootfs fa312bb (database) - postgres: set max_connections = 1024 7ebecdf (database) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z b8878f6 (dockerbuilder) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z b097451 (fluentd) - fluent: upgrade fluent to v1.4 4341f9a (minio) - mc: upgrade mc and minio c1ee2a4 (monitor) - monitor: remove copyrights.tar.gz 9854260 (registry) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z acc5627 (slugbuilder) - slugbuilder: internal support for multi buildpack d58907e (slugbuilder) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z b39a0c2 (slugrunner) - mc: upgrade mc to RELEASE.2019-05-23T01-33-27Z ","categories":"","description":"New Drycc Workflow Release v1.3.0","excerpt":"New Drycc Workflow Release v1.3.0","ref":"/blog/2020/10/06/drycc-workflow-v1.3.0/","tags":"","title":"Drycc Workflow v1.3.0"},{"body":"These release notes for Drycc Workflow v1.2.0 provide an overview of the release and document the known issues with Drycc Workflow and its flavours. For details of the changes applied since v1.1.0, please refer to the following change summary.\nWorkflow ## v1.1.0 -\u003e v1.2.0 Releases builder v1.0.1 -\u003e v1.0.2 slugbuilder v1.0.0 -\u003e v1.1.0 dockerbuilder v1.0.0 -\u003e v1.1.0 controller v1.1.0 -\u003e v1.2.0 slugrunner v1.0.0 -\u003e v1.1.0 registry v1.0.0 -\u003e v1.0.1 registry-proxy v1.0.1 -\u003e v1.0.2 Features e5584e3 (controller) - controller: add STACK support ad34dc1 (dockerbuilder) - kaniko: use kaniko replace docker-py b81430e (dockerbuilder) - dockerbuilder: change image to image.json format 60dde96 (slugbuilder) - slugbuilder: add STACK support fe8b6e5 (slugrunner) - slugrunner: add STACK support Maintenance 942f050 (builder) - registry: remove env DRYCC_REGISTRY_PROXY_PORT ff7a16f (builder) - registry: remove ecr and gcr registry ad13683 (builder) - builder: change DRYCC_BUILD_TYPE to DRYCC_STACK 6def637 (builder) - registry: rename DRYCC_REGISTRY_SERVICE to DRYCC_REGISTRY_PROXY 5044e22 (builder) - registry: remove registry_secret_prefix 2ea39cc (builder) - controller-go-sdk: upgrade controller-go-sdk 6aee0d7 (builder) - registry: optimizing variable naming f9c62d9 (controller) - domain: added reserved domain check f5a135b (controller) - migrations: clean old migrations 4369b2c (controller) - registry: rename DRYCC_REGISTRY_SERVICE to DRYCC_REGISTRY_PROXY 1057ca5 (controller) - registry: remove registry_secret_prefix d114b3e (controller) - docker: update docker client edbe963 (dockerbuilder) - dockerfile: change base image to alpine fb35baf (dockerbuilder) - registry: rename DRYCC_REGISTRY_SERVICE to DRYCC_REGISTRY_PROXY 946dbf6 (dockerbuilder) - docker: remove insecure support 628d853 (dockerbuilder) - proxy: add registry proxy ff27cbd (registry) - env: remove unused env 7204d72 (registry-proxy) - registry: optimizing variable naming ","categories":"","description":"New Drycc Workflow Release v1.2.0","excerpt":"New Drycc Workflow Release v1.2.0","ref":"/blog/2019/10/06/drycc-workflow-v1.2.0/","tags":"","title":"Drycc Workflow v1.2.0"},{"body":"Drycc Workflow is an open source Container as a Service (CaaS) that adds a developer-friendly layer to any Kubernetes cluster, making it easy to deploy and manage applications.\nWe welcome your input! If you have feedback, please submit an issue. If you’d like to participate in development, please read the “Working on Documentation” section below and submit a pull request.\n","categories":"","description":"Drycc Workflow is A Open, Unified, Lightweight, Simpler Containers as a Service (CaaS).","excerpt":"Drycc Workflow is A Open, Unified, Lightweight, Simpler Containers as …","ref":"/blog/2018/10/06/welcome-to-drycc/","tags":"","title":"Welcome to Drycc"},{"body":" About Drycc Drycc, the only Container as a Service (CaaS) you need.\nNative to Kubernetes, Drycc is the Container as a Service(CaaS) suite available on every public cloud, every Kubernetes distribution, the private cloud and the edge.\nMission\nEmpower engineers and enterprises to innovate with speed, agility, and scale.\nVision\nBecome the best and most respected infrastructure software company in the world.\nCore values\nNative to Kubernetes, Drycc is the Container as a Service(CaaS) suite available on every public cloud, every Kubernetes distribution, the private cloud and the edge.\nWe value each other We recognize we come from a variety of backgrounds and have a variety of beliefs and values. We embrace each other as people, respect our differences, and are committed to working together to achieve our shared objectives.\nWork for Customer Success We listen to our customers to understand their needs and think from their perspective. We identify current and potential challenges and optimize business value for our customers. Our goal is to be a trusted, reliable, and long-term partner providing leading technology to our users.\nWe embrace failure We try things, break things, take risks, and believe failure is key to innovation. We bounce back from failure and learn quickly.\nWe are committed to open source We strive to make information and the decision process as transparent as possible. We endeavor to be humble, curious, and always open to learning and improving ourselves. We are open to different opinions, diverse perspectives and challenges, but after a decision is made, we fully commit to it. We believe in open source and are committed to participating in and contributing to the open source community in meaningful ways.\nWe are committed to helping our customers build cool stuff that transforms their business in less time – we call it Time to Awesome.\n","categories":"","description":"","excerpt":" About Drycc Drycc, the only Container as a Service (CaaS) you need. …","ref":"/about/","tags":"","title":"About"},{"body":"This is the blog section. It has two categories: News and Releases.\nFiles in these directories will be listed in reverse chronological order.\n","categories":"","description":"","excerpt":"This is the blog section. It has two categories: News and Releases. …","ref":"/blog/","tags":"","title":"Blog"},{"body":"","categories":"","description":"","excerpt":"","ref":"/categories/","tags":"","title":"Categories"},{"body":" ","categories":"","description":"","excerpt":" ","ref":"/community/","tags":"","title":"Community"},{"body":" A Open, Unified, Lightweight, Simpler Containers as a Service (CaaS). Learn More Quickstart Simpler cloud, happier devs, better results — in the drycc!\nNative to Kubernetes, Drycc is the Container as a Service(CaaS) suite available on every public cloud, every Kubernetes distribution, the private cloud and the edge.\n(An easy-to-use, scalable CaaS platform available on Metal, AWS, Azure, and Google Cloud, and more)\nNew monitor metrics! We provide a few out of the box dashboards for monitoring Drycc Workflow.\nRead more\nContributions welcome! We do a Pull Request contributions workflow on GitHub. New users are always welcome!\nRead more\nContact us on tawk! If you have any questions concerning our products, our support team will be happy to help you.\nRead more\nFeatures\nOpen Source Open source from day one, leverage the power of global innovation with the leading database open source community.\nRead more\nMulti Platform Both X86 and ARM64 are supported with binaries and multiarch images available for both, drycc works great from something in any server.\nMeet twelve-factor Drycc Workflow is a lightweight CaaS platform that deploys and scales Twelve-Factor apps as containers across a K8s cluster.\nRead more\nIt’s easy to deploy, operate and scale drycc — anywhere.\n","categories":"","description":"","excerpt":" A Open, Unified, Lightweight, Simpler Containers as a Service (CaaS). …","ref":"/","tags":"","title":"Drycc"},{"body":"","categories":"","description":"","excerpt":"","ref":"/search/","tags":"","title":"Search Results"},{"body":"","categories":"","description":"","excerpt":"","ref":"/tags/","tags":"","title":"Tags"}] \ No newline at end of file diff --git a/robots.txt b/robots.txt new file mode 100644 index 000000000..4f9540ba3 --- /dev/null +++ b/robots.txt @@ -0,0 +1 @@ +User-agent: * \ No newline at end of file diff --git a/scss/main.min.3a5b24585fce93f20631bc122a4100bf83163d9bce2eabc28b44f9ef96cb84a0.css b/scss/main.min.3a5b24585fce93f20631bc122a4100bf83163d9bce2eabc28b44f9ef96cb84a0.css new file mode 100644 index 000000000..40c92866b --- /dev/null +++ b/scss/main.min.3a5b24585fce93f20631bc122a4100bf83163d9bce2eabc28b44f9ef96cb84a0.css @@ -0,0 +1,10 @@ +/*!* Bootstrap v5.2.3 (https://getbootstrap.com/) +* Copyright 2011-2022 The Bootstrap Authors +* Copyright 2011-2022 Twitter, Inc. +* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)*/@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,700,700i&display=swap";:root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-black:#000;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#6c757d;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray-900:#212529;--bs-primary:#081b4b;--bs-secondary:#fff;--bs-success:#3772ff;--bs-info:#c0e0de;--bs-warning:#ed6a5a;--bs-danger:#ed6a5a;--bs-light:#d3f3ee;--bs-dark:#403f4c;--bs-primary-rgb:8, 27, 75;--bs-secondary-rgb:255, 255, 255;--bs-success-rgb:55, 114, 255;--bs-info-rgb:192, 224, 222;--bs-warning-rgb:237, 106, 90;--bs-danger-rgb:237, 106, 90;--bs-light-rgb:211, 243, 238;--bs-dark-rgb:64, 63, 76;--bs-white-rgb:255, 255, 255;--bs-black-rgb:0, 0, 0;--bs-body-color-rgb:33, 37, 41;--bs-body-bg-rgb:255, 255, 255;--bs-font-sans-serif:"Open Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";--bs-font-monospace:SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--bs-gradient:linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));--bs-body-font-family:Open Sans, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;--bs-body-font-size:1rem;--bs-body-font-weight:400;--bs-body-line-height:1.5;--bs-body-color:#212529;--bs-body-bg:#fff;--bs-border-width:1px;--bs-border-style:solid;--bs-border-color:#dee2e6;--bs-border-color-translucent:rgba(0, 0, 0, 0.175);--bs-border-radius:0.375rem;--bs-border-radius-sm:0.25rem;--bs-border-radius-lg:0.5rem;--bs-border-radius-xl:1rem;--bs-border-radius-2xl:2rem;--bs-border-radius-pill:50rem;--bs-link-color:#0d6efd;--bs-link-hover-color:#094db1;--bs-code-color:#999999;--bs-highlight-bg:#fff3cd}*,*::before,*::after{box-sizing:border-box}@media(prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;border:0;border-top:1px solid;opacity:.25}h6,.h6,h5,.h5,h4,.h4,h3,.h3,.td-footer__links-item,h2,.h2,h1,.h1{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1,.h1{font-size:calc(1.375rem + 1.5vw)}@media(min-width:1200px){h1,.h1{font-size:2.5rem}}h2,.h2{font-size:calc(1.325rem + .9vw)}@media(min-width:1200px){h2,.h2{font-size:2rem}}h3,.h3,.td-footer__links-item{font-size:calc(1.275rem + .3vw)}@media(min-width:1200px){h3,.h3,.td-footer__links-item{font-size:1.5rem}}h4,.h4{font-size:calc(1.26rem + .12vw)}@media(min-width:1200px){h4,.h4{font-size:1.35rem}}h5,.h5{font-size:1.15rem}h6,.h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}ol,ul,dl{margin-top:0;margin-bottom:1rem}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small,.small,.td-footer__center,.td-cover-block>.byline{font-size:.875em}mark,.mark{padding:.1875em;background-color:var(--bs-highlight-bg)}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:var(--bs-link-color);text-decoration:underline}a:hover{color:var(--bs-link-hover-color)}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}pre,code,kbd,samp{font-family:var(--bs-font-monospace);font-size:1em}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:var(--bs-code-color);word-wrap:break-word}a>code{color:inherit}kbd{padding:.1875rem .375rem;font-size:.875em;color:var(--bs-body-bg);background-color:var(--bs-body-color);border-radius:.25rem}kbd kbd{padding:0;font-size:1em}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}thead,tbody,tfoot,tr,td,th{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}input,button,select,optgroup,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator{display:none!important}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button:not(:disabled),[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media(min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-text,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:calc(1.625rem + 4.5vw);font-weight:300;line-height:1.2}@media(min-width:1200px){.display-1{font-size:5rem}}.display-2{font-size:calc(1.575rem + 3.9vw);font-weight:300;line-height:1.2}@media(min-width:1200px){.display-2{font-size:4.5rem}}.display-3{font-size:calc(1.525rem + 3.3vw);font-weight:300;line-height:1.2}@media(min-width:1200px){.display-3{font-size:4rem}}.display-4{font-size:calc(1.475rem + 2.7vw);font-weight:300;line-height:1.2}@media(min-width:1200px){.display-4{font-size:3.5rem}}.display-5{font-size:calc(1.425rem + 2.1vw);font-weight:300;line-height:1.2}@media(min-width:1200px){.display-5{font-size:3rem}}.display-6{font-size:calc(1.375rem + 1.5vw);font-weight:300;line-height:1.2}@media(min-width:1200px){.display-6{font-size:2.5rem}}.list-unstyled,.td-blog-posts-list{padding-left:0;list-style:none}.list-inline,.td-footer__links-list{padding-left:0;list-style:none}.list-inline-item,.td-footer__links-item{display:inline-block}.list-inline-item:not(:last-child),.td-footer__links-item:not(:last-child){margin-right:1rem}.initialism{font-size:.875em;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote>:last-child{margin-bottom:0}.blockquote-footer{margin-top:-1rem;margin-bottom:1rem;font-size:.875em;color:#6c757d}.blockquote-footer::before{content:"\2014\00A0"}.img-fluid,.td-content img{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid var(--bs-border-color);border-radius:.375rem;box-shadow:0 .125rem .25rem rgba(0,0,0,.075);max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:.875em;color:#6c757d}.container,.container-fluid,.container-xxl,.container-xl,.container-lg,.container-md,.container-sm{--bs-gutter-x:1.5rem;--bs-gutter-y:0;width:100%;padding-right:calc(var(--bs-gutter-x) * .5);padding-left:calc(var(--bs-gutter-x) * .5);margin-right:auto;margin-left:auto}@media(min-width:576px){.container-sm,.container{max-width:540px}}@media(min-width:768px){.container-md,.container-sm,.container{max-width:720px}}@media(min-width:992px){.container-lg,.container-md,.container-sm,.container{max-width:960px}}@media(min-width:1200px){.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1140px}}@media(min-width:1400px){.container-xxl,.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1320px}}.row{--bs-gutter-x:1.5rem;--bs-gutter-y:0;display:flex;flex-wrap:wrap;margin-top:calc(-1 * var(--bs-gutter-y));margin-right:calc(-.5 * var(--bs-gutter-x));margin-left:calc(-.5 * var(--bs-gutter-x))}.row>*{flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--bs-gutter-x) * .5);padding-left:calc(var(--bs-gutter-x) * .5);margin-top:var(--bs-gutter-y)}.col{flex:1 0}.row-cols-auto>*{flex:none;width:auto}.row-cols-1>*{flex:none;width:100%}.row-cols-2>*{flex:none;width:50%}.row-cols-3>*{flex:none;width:33.33333333%}.row-cols-4>*{flex:none;width:25%}.row-cols-5>*{flex:none;width:20%}.row-cols-6>*{flex:none;width:16.66666667%}.col-auto{flex:none;width:auto}.col-1{flex:none;width:8.33333333%}.col-2{flex:none;width:16.66666667%}.col-3{flex:none;width:25%}.col-4{flex:none;width:33.33333333%}.col-5{flex:none;width:41.66666667%}.col-6{flex:none;width:50%}.col-7{flex:none;width:58.33333333%}.col-8{flex:none;width:66.66666667%}.col-9{flex:none;width:75%}.col-10{flex:none;width:83.33333333%}.col-11{flex:none;width:91.66666667%}.col-12{flex:none;width:100%}.offset-1{margin-left:8.33333333%}.offset-2{margin-left:16.66666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333333%}.offset-5{margin-left:41.66666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333333%}.offset-8{margin-left:66.66666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333333%}.offset-11{margin-left:91.66666667%}.g-0,.gx-0{--bs-gutter-x:0}.g-0,.gy-0{--bs-gutter-y:0}.g-1,.gx-1{--bs-gutter-x:0.25rem}.g-1,.gy-1{--bs-gutter-y:0.25rem}.g-2,.gx-2{--bs-gutter-x:0.5rem}.g-2,.gy-2{--bs-gutter-y:0.5rem}.g-3,.gx-3{--bs-gutter-x:1rem}.g-3,.gy-3{--bs-gutter-y:1rem}.g-4,.gx-4{--bs-gutter-x:1.5rem}.g-4,.gy-4{--bs-gutter-y:1.5rem}.g-5,.gx-5{--bs-gutter-x:3rem}.g-5,.gy-5{--bs-gutter-y:3rem}@media(min-width:576px){.col-sm{flex:1 0}.row-cols-sm-auto>*{flex:none;width:auto}.row-cols-sm-1>*{flex:none;width:100%}.row-cols-sm-2>*{flex:none;width:50%}.row-cols-sm-3>*{flex:none;width:33.33333333%}.row-cols-sm-4>*{flex:none;width:25%}.row-cols-sm-5>*{flex:none;width:20%}.row-cols-sm-6>*{flex:none;width:16.66666667%}.col-sm-auto{flex:none;width:auto}.col-sm-1{flex:none;width:8.33333333%}.col-sm-2{flex:none;width:16.66666667%}.col-sm-3{flex:none;width:25%}.col-sm-4{flex:none;width:33.33333333%}.col-sm-5{flex:none;width:41.66666667%}.col-sm-6{flex:none;width:50%}.col-sm-7{flex:none;width:58.33333333%}.col-sm-8{flex:none;width:66.66666667%}.col-sm-9{flex:none;width:75%}.col-sm-10{flex:none;width:83.33333333%}.col-sm-11{flex:none;width:91.66666667%}.col-sm-12{flex:none;width:100%}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333333%}.offset-sm-2{margin-left:16.66666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333333%}.offset-sm-5{margin-left:41.66666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333333%}.offset-sm-8{margin-left:66.66666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333333%}.offset-sm-11{margin-left:91.66666667%}.g-sm-0,.gx-sm-0{--bs-gutter-x:0}.g-sm-0,.gy-sm-0{--bs-gutter-y:0}.g-sm-1,.gx-sm-1{--bs-gutter-x:0.25rem}.g-sm-1,.gy-sm-1{--bs-gutter-y:0.25rem}.g-sm-2,.gx-sm-2{--bs-gutter-x:0.5rem}.g-sm-2,.gy-sm-2{--bs-gutter-y:0.5rem}.g-sm-3,.gx-sm-3{--bs-gutter-x:1rem}.g-sm-3,.gy-sm-3{--bs-gutter-y:1rem}.g-sm-4,.gx-sm-4{--bs-gutter-x:1.5rem}.g-sm-4,.gy-sm-4{--bs-gutter-y:1.5rem}.g-sm-5,.gx-sm-5{--bs-gutter-x:3rem}.g-sm-5,.gy-sm-5{--bs-gutter-y:3rem}}@media(min-width:768px){.col-md{flex:1 0}.row-cols-md-auto>*{flex:none;width:auto}.row-cols-md-1>*{flex:none;width:100%}.row-cols-md-2>*{flex:none;width:50%}.row-cols-md-3>*{flex:none;width:33.33333333%}.row-cols-md-4>*{flex:none;width:25%}.row-cols-md-5>*{flex:none;width:20%}.row-cols-md-6>*{flex:none;width:16.66666667%}.col-md-auto{flex:none;width:auto}.col-md-1{flex:none;width:8.33333333%}.col-md-2{flex:none;width:16.66666667%}.col-md-3{flex:none;width:25%}.col-md-4{flex:none;width:33.33333333%}.col-md-5{flex:none;width:41.66666667%}.col-md-6{flex:none;width:50%}.col-md-7{flex:none;width:58.33333333%}.col-md-8{flex:none;width:66.66666667%}.col-md-9{flex:none;width:75%}.col-md-10{flex:none;width:83.33333333%}.col-md-11{flex:none;width:91.66666667%}.col-md-12{flex:none;width:100%}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333333%}.offset-md-2{margin-left:16.66666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333333%}.offset-md-5{margin-left:41.66666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333333%}.offset-md-8{margin-left:66.66666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333333%}.offset-md-11{margin-left:91.66666667%}.g-md-0,.gx-md-0{--bs-gutter-x:0}.g-md-0,.gy-md-0{--bs-gutter-y:0}.g-md-1,.gx-md-1{--bs-gutter-x:0.25rem}.g-md-1,.gy-md-1{--bs-gutter-y:0.25rem}.g-md-2,.gx-md-2{--bs-gutter-x:0.5rem}.g-md-2,.gy-md-2{--bs-gutter-y:0.5rem}.g-md-3,.gx-md-3{--bs-gutter-x:1rem}.g-md-3,.gy-md-3{--bs-gutter-y:1rem}.g-md-4,.gx-md-4{--bs-gutter-x:1.5rem}.g-md-4,.gy-md-4{--bs-gutter-y:1.5rem}.g-md-5,.gx-md-5{--bs-gutter-x:3rem}.g-md-5,.gy-md-5{--bs-gutter-y:3rem}}@media(min-width:992px){.col-lg{flex:1 0}.row-cols-lg-auto>*{flex:none;width:auto}.row-cols-lg-1>*{flex:none;width:100%}.row-cols-lg-2>*{flex:none;width:50%}.row-cols-lg-3>*{flex:none;width:33.33333333%}.row-cols-lg-4>*{flex:none;width:25%}.row-cols-lg-5>*{flex:none;width:20%}.row-cols-lg-6>*{flex:none;width:16.66666667%}.col-lg-auto{flex:none;width:auto}.col-lg-1{flex:none;width:8.33333333%}.col-lg-2{flex:none;width:16.66666667%}.col-lg-3{flex:none;width:25%}.col-lg-4{flex:none;width:33.33333333%}.col-lg-5{flex:none;width:41.66666667%}.col-lg-6{flex:none;width:50%}.col-lg-7{flex:none;width:58.33333333%}.col-lg-8{flex:none;width:66.66666667%}.col-lg-9{flex:none;width:75%}.col-lg-10{flex:none;width:83.33333333%}.col-lg-11{flex:none;width:91.66666667%}.col-lg-12{flex:none;width:100%}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333333%}.offset-lg-2{margin-left:16.66666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333333%}.offset-lg-5{margin-left:41.66666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333333%}.offset-lg-8{margin-left:66.66666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333333%}.offset-lg-11{margin-left:91.66666667%}.g-lg-0,.gx-lg-0{--bs-gutter-x:0}.g-lg-0,.gy-lg-0{--bs-gutter-y:0}.g-lg-1,.gx-lg-1{--bs-gutter-x:0.25rem}.g-lg-1,.gy-lg-1{--bs-gutter-y:0.25rem}.g-lg-2,.gx-lg-2{--bs-gutter-x:0.5rem}.g-lg-2,.gy-lg-2{--bs-gutter-y:0.5rem}.g-lg-3,.gx-lg-3{--bs-gutter-x:1rem}.g-lg-3,.gy-lg-3{--bs-gutter-y:1rem}.g-lg-4,.gx-lg-4{--bs-gutter-x:1.5rem}.g-lg-4,.gy-lg-4{--bs-gutter-y:1.5rem}.g-lg-5,.gx-lg-5{--bs-gutter-x:3rem}.g-lg-5,.gy-lg-5{--bs-gutter-y:3rem}}@media(min-width:1200px){.col-xl{flex:1 0}.row-cols-xl-auto>*{flex:none;width:auto}.row-cols-xl-1>*{flex:none;width:100%}.row-cols-xl-2>*{flex:none;width:50%}.row-cols-xl-3>*{flex:none;width:33.33333333%}.row-cols-xl-4>*{flex:none;width:25%}.row-cols-xl-5>*{flex:none;width:20%}.row-cols-xl-6>*{flex:none;width:16.66666667%}.col-xl-auto{flex:none;width:auto}.col-xl-1{flex:none;width:8.33333333%}.col-xl-2{flex:none;width:16.66666667%}.col-xl-3{flex:none;width:25%}.col-xl-4{flex:none;width:33.33333333%}.col-xl-5{flex:none;width:41.66666667%}.col-xl-6{flex:none;width:50%}.col-xl-7{flex:none;width:58.33333333%}.col-xl-8{flex:none;width:66.66666667%}.col-xl-9{flex:none;width:75%}.col-xl-10{flex:none;width:83.33333333%}.col-xl-11{flex:none;width:91.66666667%}.col-xl-12{flex:none;width:100%}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333333%}.offset-xl-2{margin-left:16.66666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333333%}.offset-xl-5{margin-left:41.66666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333333%}.offset-xl-8{margin-left:66.66666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333333%}.offset-xl-11{margin-left:91.66666667%}.g-xl-0,.gx-xl-0{--bs-gutter-x:0}.g-xl-0,.gy-xl-0{--bs-gutter-y:0}.g-xl-1,.gx-xl-1{--bs-gutter-x:0.25rem}.g-xl-1,.gy-xl-1{--bs-gutter-y:0.25rem}.g-xl-2,.gx-xl-2{--bs-gutter-x:0.5rem}.g-xl-2,.gy-xl-2{--bs-gutter-y:0.5rem}.g-xl-3,.gx-xl-3{--bs-gutter-x:1rem}.g-xl-3,.gy-xl-3{--bs-gutter-y:1rem}.g-xl-4,.gx-xl-4{--bs-gutter-x:1.5rem}.g-xl-4,.gy-xl-4{--bs-gutter-y:1.5rem}.g-xl-5,.gx-xl-5{--bs-gutter-x:3rem}.g-xl-5,.gy-xl-5{--bs-gutter-y:3rem}}@media(min-width:1400px){.col-xxl{flex:1 0}.row-cols-xxl-auto>*{flex:none;width:auto}.row-cols-xxl-1>*{flex:none;width:100%}.row-cols-xxl-2>*{flex:none;width:50%}.row-cols-xxl-3>*{flex:none;width:33.33333333%}.row-cols-xxl-4>*{flex:none;width:25%}.row-cols-xxl-5>*{flex:none;width:20%}.row-cols-xxl-6>*{flex:none;width:16.66666667%}.col-xxl-auto{flex:none;width:auto}.col-xxl-1{flex:none;width:8.33333333%}.col-xxl-2{flex:none;width:16.66666667%}.col-xxl-3{flex:none;width:25%}.col-xxl-4{flex:none;width:33.33333333%}.col-xxl-5{flex:none;width:41.66666667%}.col-xxl-6{flex:none;width:50%}.col-xxl-7{flex:none;width:58.33333333%}.col-xxl-8{flex:none;width:66.66666667%}.col-xxl-9{flex:none;width:75%}.col-xxl-10{flex:none;width:83.33333333%}.col-xxl-11{flex:none;width:91.66666667%}.col-xxl-12{flex:none;width:100%}.offset-xxl-0{margin-left:0}.offset-xxl-1{margin-left:8.33333333%}.offset-xxl-2{margin-left:16.66666667%}.offset-xxl-3{margin-left:25%}.offset-xxl-4{margin-left:33.33333333%}.offset-xxl-5{margin-left:41.66666667%}.offset-xxl-6{margin-left:50%}.offset-xxl-7{margin-left:58.33333333%}.offset-xxl-8{margin-left:66.66666667%}.offset-xxl-9{margin-left:75%}.offset-xxl-10{margin-left:83.33333333%}.offset-xxl-11{margin-left:91.66666667%}.g-xxl-0,.gx-xxl-0{--bs-gutter-x:0}.g-xxl-0,.gy-xxl-0{--bs-gutter-y:0}.g-xxl-1,.gx-xxl-1{--bs-gutter-x:0.25rem}.g-xxl-1,.gy-xxl-1{--bs-gutter-y:0.25rem}.g-xxl-2,.gx-xxl-2{--bs-gutter-x:0.5rem}.g-xxl-2,.gy-xxl-2{--bs-gutter-y:0.5rem}.g-xxl-3,.gx-xxl-3{--bs-gutter-x:1rem}.g-xxl-3,.gy-xxl-3{--bs-gutter-y:1rem}.g-xxl-4,.gx-xxl-4{--bs-gutter-x:1.5rem}.g-xxl-4,.gy-xxl-4{--bs-gutter-y:1.5rem}.g-xxl-5,.gx-xxl-5{--bs-gutter-x:3rem}.g-xxl-5,.gy-xxl-5{--bs-gutter-y:3rem}}.table,.td-table:not(.td-initial),.td-content table:not(.td-initial),.td-box table:not(.td-initial){--bs-table-color:var(--bs-body-color);--bs-table-bg:transparent;--bs-table-border-color:var(--bs-border-color);--bs-table-accent-bg:transparent;--bs-table-striped-color:var(--bs-body-color);--bs-table-striped-bg:rgba(0, 0, 0, 0.05);--bs-table-active-color:var(--bs-body-color);--bs-table-active-bg:rgba(0, 0, 0, 0.1);--bs-table-hover-color:var(--bs-body-color);--bs-table-hover-bg:rgba(0, 0, 0, 0.075);width:100%;margin-bottom:1rem;color:var(--bs-table-color);vertical-align:top;border-color:var(--bs-table-border-color)}.table>:not(caption)>*>*,.td-table:not(.td-initial)>:not(caption)>*>*,.td-content table:not(.td-initial)>:not(caption)>*>*,.td-box table:not(.td-initial)>:not(caption)>*>*{padding:.5rem;background-color:var(--bs-table-bg);border-bottom-width:1px;box-shadow:inset 0 0 0 9999px var(--bs-table-accent-bg)}.table>tbody,.td-table:not(.td-initial)>tbody,.td-content table:not(.td-initial)>tbody,.td-box table:not(.td-initial)>tbody{vertical-align:inherit}.table>thead,.td-table:not(.td-initial)>thead,.td-content table:not(.td-initial)>thead,.td-box table:not(.td-initial)>thead{vertical-align:bottom}.table-group-divider{border-top:2px solid}.caption-top{caption-side:top}.table-sm>:not(caption)>*>*{padding:.25rem}.table-bordered>:not(caption)>*{border-width:1px 0}.table-bordered>:not(caption)>*>*{border-width:0 1px}.table-borderless>:not(caption)>*>*{border-bottom-width:0}.table-borderless>:not(:first-child){border-top-width:0}.table-striped>tbody>tr:nth-of-type(odd)>*,.td-table:not(.td-initial)>tbody>tr:nth-of-type(odd)>*,.td-content table:not(.td-initial)>tbody>tr:nth-of-type(odd)>*,.td-box table:not(.td-initial)>tbody>tr:nth-of-type(odd)>*{--bs-table-accent-bg:var(--bs-table-striped-bg);color:var(--bs-table-striped-color)}.table-striped-columns>:not(caption)>tr>:nth-child(even){--bs-table-accent-bg:var(--bs-table-striped-bg);color:var(--bs-table-striped-color)}.table-active{--bs-table-accent-bg:var(--bs-table-active-bg);color:var(--bs-table-active-color)}.table-hover>tbody>tr:hover>*{--bs-table-accent-bg:var(--bs-table-hover-bg);color:var(--bs-table-hover-color)}.table-primary{--bs-table-color:#000;--bs-table-bg:#ced1db;--bs-table-border-color:#b9bcc5;--bs-table-striped-bg:#c4c7d0;--bs-table-striped-color:#000;--bs-table-active-bg:#b9bcc5;--bs-table-active-color:#000;--bs-table-hover-bg:#bfc1cb;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-secondary{--bs-table-color:#000;--bs-table-bg:white;--bs-table-border-color:#e6e6e6;--bs-table-striped-bg:#f2f2f2;--bs-table-striped-color:#000;--bs-table-active-bg:#e6e6e6;--bs-table-active-color:#000;--bs-table-hover-bg:#ececec;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-success{--bs-table-color:#000;--bs-table-bg:#d7e3ff;--bs-table-border-color:#c2cce6;--bs-table-striped-bg:#ccd8f2;--bs-table-striped-color:#000;--bs-table-active-bg:#c2cce6;--bs-table-active-color:#000;--bs-table-hover-bg:#c7d2ec;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-info{--bs-table-color:#000;--bs-table-bg:#f2f9f8;--bs-table-border-color:#dae0df;--bs-table-striped-bg:#e6edec;--bs-table-striped-color:#000;--bs-table-active-bg:#dae0df;--bs-table-active-color:#000;--bs-table-hover-bg:#e0e6e5;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-warning{--bs-table-color:#000;--bs-table-bg:#fbe1de;--bs-table-border-color:#e2cbc8;--bs-table-striped-bg:#eed6d3;--bs-table-striped-color:#000;--bs-table-active-bg:#e2cbc8;--bs-table-active-color:#000;--bs-table-hover-bg:#e8d0cd;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-danger{--bs-table-color:#000;--bs-table-bg:#fbe1de;--bs-table-border-color:#e2cbc8;--bs-table-striped-bg:#eed6d3;--bs-table-striped-color:#000;--bs-table-active-bg:#e2cbc8;--bs-table-active-color:#000;--bs-table-hover-bg:#e8d0cd;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-light{--bs-table-color:#000;--bs-table-bg:#d3f3ee;--bs-table-border-color:#bedbd6;--bs-table-striped-bg:#c8e7e2;--bs-table-striped-color:#000;--bs-table-active-bg:#bedbd6;--bs-table-active-color:#000;--bs-table-hover-bg:#c3e1dc;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-dark{--bs-table-color:#fff;--bs-table-bg:#403f4c;--bs-table-border-color:#53525e;--bs-table-striped-bg:#4a4955;--bs-table-striped-color:#fff;--bs-table-active-bg:#53525e;--bs-table-active-color:#fff;--bs-table-hover-bg:#4e4d59;--bs-table-hover-color:#fff;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-responsive,.td-table:not(.td-initial),.td-content table:not(.td-initial),.td-box table:not(.td-initial){overflow-x:auto;-webkit-overflow-scrolling:touch}@media(max-width:575.98px){.table-responsive-sm{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width:767.98px){.table-responsive-md{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width:991.98px){.table-responsive-lg{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width:1199.98px){.table-responsive-xl{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width:1399.98px){.table-responsive-xxl{overflow-x:auto;-webkit-overflow-scrolling:touch}}.form-label{margin-bottom:.5rem}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem}.form-text{margin-top:.25rem;font-size:.875em;color:#6c757d}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:.375rem;box-shadow:inset 0 1px 2px rgba(0,0,0,.075);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus{color:#212529;background-color:#fff;border-color:#848da5;outline:0;box-shadow:inset 0 1px 2px rgba(0,0,0,.075),0 0 0 .25rem rgba(8,27,75,.25)}.form-control::-webkit-date-and-time-value{height:1.5em}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled{background-color:#e9ecef;opacity:1}.form-control::file-selector-button{padding:.375rem .75rem;margin:-.375rem -.75rem;margin-inline-end:.75rem;color:#212529;background-color:#e9ecef;background-image:var(--bs-gradient);pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:1px;border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion:reduce){.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:#dde0e3}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext:focus{outline:0}.form-control-plaintext.form-control-sm,.form-control-plaintext.form-control-lg{padding-right:0;padding-left:0}.form-control-sm{min-height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;border-radius:.25rem}.form-control-sm::file-selector-button{padding:.25rem .5rem;margin:-.25rem -.5rem;margin-inline-end:.5rem}.form-control-lg{min-height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;border-radius:.5rem}.form-control-lg::file-selector-button{padding:.5rem 1rem;margin:-.5rem -1rem;margin-inline-end:1rem}textarea.form-control{min-height:calc(1.5em + .75rem + 2px)}textarea.form-control-sm{min-height:calc(1.5em + .5rem + 2px)}textarea.form-control-lg{min-height:calc(1.5em + 1rem + 2px)}.form-control-color{width:3rem;height:calc(1.5em + .75rem + 2px);padding:.375rem}.form-control-color:not(:disabled):not([readonly]){cursor:pointer}.form-control-color::-moz-color-swatch{border:0!important;border-radius:.375rem}.form-control-color::-webkit-color-swatch{border-radius:.375rem}.form-control-color.form-control-sm{height:calc(1.5em + .5rem + 2px)}.form-control-color.form-control-lg{height:calc(1.5em + 1rem + 2px)}.form-select{display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;-moz-padding-start:calc(.75rem - 3px);font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:1px solid #ced4da;border-radius:.375rem;box-shadow:inset 0 1px 2px rgba(0,0,0,.075);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;-moz-appearance:none;appearance:none}@media(prefers-reduced-motion:reduce){.form-select{transition:none}}.form-select:focus{border-color:#848da5;outline:0;box-shadow:inset 0 1px 2px rgba(0,0,0,.075),0 0 0 .25rem rgba(8,27,75,.25)}.form-select[multiple],.form-select[size]:not([size="1"]){padding-right:.75rem;background-image:none}.form-select:disabled{background-color:#e9ecef}.form-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #212529}.form-select-sm{padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem;border-radius:.25rem}.form-select-lg{padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem;border-radius:.5rem}.form-check{display:block;min-height:1.5rem;padding-left:1.5em;margin-bottom:.125rem}.form-check .form-check-input{float:left;margin-left:-1.5em}.form-check-reverse{padding-right:1.5em;padding-left:0;text-align:right}.form-check-reverse .form-check-input{float:right;margin-right:-1.5em;margin-left:0}.form-check-input{width:1em;height:1em;margin-top:.25em;vertical-align:top;background-color:#fff;background-repeat:no-repeat;background-position:50%;background-size:contain;border:1px solid rgba(0,0,0,.25);-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-print-color-adjust:exact;print-color-adjust:exact}.form-check-input[type=checkbox]{border-radius:.25em}.form-check-input[type=radio]{border-radius:50%}.form-check-input:active{filter:brightness(90%)}.form-check-input:focus{border-color:#848da5;outline:0;box-shadow:0 0 0 .25rem rgba(8,27,75,.25)}.form-check-input:checked{background-color:#081b4b;border-color:#081b4b}.form-check-input:checked[type=checkbox]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e"),var(--bs-gradient)}.form-check-input:checked[type=radio]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e"),var(--bs-gradient)}.form-check-input[type=checkbox]:indeterminate{background-color:#081b4b;border-color:#081b4b;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e"),var(--bs-gradient)}.form-check-input:disabled{pointer-events:none;filter:none;opacity:.5}.form-check-input[disabled]~.form-check-label,.form-check-input:disabled~.form-check-label{cursor:default;opacity:.5}.form-switch{padding-left:2.5em}.form-switch .form-check-input{width:2em;margin-left:-2.5em;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e");background-position:0;border-radius:2em;transition:background-position .15s ease-in-out}@media(prefers-reduced-motion:reduce){.form-switch .form-check-input{transition:none}}.form-switch .form-check-input:focus{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23848da5'/%3e%3c/svg%3e")}.form-switch .form-check-input:checked{background-position:100%;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e"),var(--bs-gradient)}.form-switch.form-check-reverse{padding-right:2.5em;padding-left:0}.form-switch.form-check-reverse .form-check-input{margin-right:-2.5em;margin-left:0}.form-check-inline{display:inline-block;margin-right:1rem}.btn-check{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.btn-check[disabled]+.btn,div.drawio .btn-check[disabled]+button,.td-blog .btn-check[disabled]+.td-rss-button,.btn-check:disabled+.btn,div.drawio .btn-check:disabled+button,.td-blog .btn-check:disabled+.td-rss-button{pointer-events:none;filter:none;opacity:.65}.form-range{width:100%;height:1.5rem;padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.form-range:focus{outline:0}.form-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(8,27,75,.25)}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(8,27,75,.25)}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#081b4b;background-image:var(--bs-gradient);border:0;border-radius:1rem;box-shadow:0 .1rem .25rem rgba(0,0,0,.1);-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media(prefers-reduced-motion:reduce){.form-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.form-range::-webkit-slider-thumb:active{background-color:#b5bbc9;background-image:var(--bs-gradient)}.form-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem;box-shadow:inset 0 1px 2px rgba(0,0,0,.075)}.form-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#081b4b;background-image:var(--bs-gradient);border:0;border-radius:1rem;box-shadow:0 .1rem .25rem rgba(0,0,0,.1);-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media(prefers-reduced-motion:reduce){.form-range::-moz-range-thumb{-moz-transition:none;transition:none}}.form-range::-moz-range-thumb:active{background-color:#b5bbc9;background-image:var(--bs-gradient)}.form-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem;box-shadow:inset 0 1px 2px rgba(0,0,0,.075)}.form-range:disabled{pointer-events:none}.form-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.form-range:disabled::-moz-range-thumb{background-color:#adb5bd}.form-floating{position:relative}.form-floating>.form-control,.form-floating>.form-control-plaintext,.form-floating>.form-select{height:calc(3.5rem + 2px);line-height:1.25}.form-floating>label{position:absolute;top:0;left:0;width:100%;height:100%;padding:1rem .75rem;overflow:hidden;text-align:start;text-overflow:ellipsis;white-space:nowrap;pointer-events:none;border:1px solid transparent;transform-origin:0 0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}@media(prefers-reduced-motion:reduce){.form-floating>label{transition:none}}.form-floating>.form-control,.form-floating>.form-control-plaintext{padding:1rem .75rem}.form-floating>.form-control::-moz-placeholder,.form-floating>.form-control-plaintext::-moz-placeholder{color:transparent}.form-floating>.form-control::placeholder,.form-floating>.form-control-plaintext::placeholder{color:transparent}.form-floating>.form-control:not(:-moz-placeholder-shown),.form-floating>.form-control-plaintext:not(:-moz-placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:focus,.form-floating>.form-control:not(:placeholder-shown),.form-floating>.form-control-plaintext:focus,.form-floating>.form-control-plaintext:not(:placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:-webkit-autofill,.form-floating>.form-control-plaintext:-webkit-autofill{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-select{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:not(:-moz-placeholder-shown)~label{opacity:.65;transform:scale(.85)translateY(-.5rem)translateX(.15rem)}.form-floating>.form-control:focus~label,.form-floating>.form-control:not(:placeholder-shown)~label,.form-floating>.form-control-plaintext~label,.form-floating>.form-select~label{opacity:.65;transform:scale(.85)translateY(-.5rem)translateX(.15rem)}.form-floating>.form-control:-webkit-autofill~label{opacity:.65;transform:scale(.85)translateY(-.5rem)translateX(.15rem)}.form-floating>.form-control-plaintext~label{border-width:1px 0}.input-group{position:relative;display:flex;flex-wrap:wrap;align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-select,.input-group>.form-floating{position:relative;flex:auto;width:1%;min-width:0}.input-group>.form-control:focus,.input-group>.form-select:focus,.input-group>.form-floating:focus-within{z-index:5}.input-group .btn,.input-group div.drawio button,div.drawio .input-group button,.input-group .td-blog .td-rss-button,.td-blog .input-group .td-rss-button{position:relative;z-index:2}.input-group .btn:focus,.input-group div.drawio button:focus,div.drawio .input-group button:focus,.input-group .td-blog .td-rss-button:focus,.td-blog .input-group .td-rss-button:focus{z-index:5}.input-group-text{display:flex;align-items:center;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.375rem}.input-group-lg>.form-control,.input-group-lg>.form-select,.input-group-lg>.input-group-text,.input-group-lg>.btn,div.drawio .input-group-lg>button,.td-blog .input-group-lg>.td-rss-button{padding:.5rem 1rem;font-size:1.25rem;border-radius:.5rem}.input-group-sm>.form-control,.input-group-sm>.form-select,.input-group-sm>.input-group-text,.input-group-sm>.btn,div.drawio .input-group-sm>button,.td-blog .input-group-sm>.td-rss-button{padding:.25rem .5rem;font-size:.875rem;border-radius:.25rem}.input-group-lg>.form-select,.input-group-sm>.form-select{padding-right:3rem}.input-group:not(.has-validation)>:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating),.input-group:not(.has-validation)>.dropdown-toggle:nth-last-child(n+3),.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-control,.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-select{border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>:nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating),.input-group.has-validation>.dropdown-toggle:nth-last-child(n+4),.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-control,.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-select{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback){margin-left:-1px;border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.form-floating:not(:first-child)>.form-control,.input-group>.form-floating:not(:first-child)>.form-select{border-top-left-radius:0;border-bottom-left-radius:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#3772ff}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#000;background-color:rgba(55,114,255,.9);border-radius:.375rem}.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip,.is-valid~.valid-feedback,.is-valid~.valid-tooltip{display:block}.was-validated .form-control:valid,.form-control.is-valid{border-color:#3772ff;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%233772ff' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem)center;background-size:calc(.75em + .375rem)calc(.75em + .375rem)}.was-validated .form-control:valid:focus,.form-control.is-valid:focus{border-color:#3772ff;box-shadow:0 0 0 .25rem rgba(55,114,255,.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem)right calc(.375em + .1875rem)}.was-validated .form-select:valid,.form-select.is-valid{border-color:#3772ff}.was-validated .form-select:valid:not([multiple]):not([size]),.was-validated .form-select:valid:not([multiple])[size="1"],.form-select.is-valid:not([multiple]):not([size]),.form-select.is-valid:not([multiple])[size="1"]{padding-right:4.125rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%233772ff' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem)calc(.75em + .375rem)}.was-validated .form-select:valid:focus,.form-select.is-valid:focus{border-color:#3772ff;box-shadow:0 0 0 .25rem rgba(55,114,255,.25)}.was-validated .form-control-color:valid,.form-control-color.is-valid{width:calc(3rem + calc(1.5em + .75rem))}.was-validated .form-check-input:valid,.form-check-input.is-valid{border-color:#3772ff}.was-validated .form-check-input:valid:checked,.form-check-input.is-valid:checked{background-color:#3772ff}.was-validated .form-check-input:valid:focus,.form-check-input.is-valid:focus{box-shadow:0 0 0 .25rem rgba(55,114,255,.25)}.was-validated .form-check-input:valid~.form-check-label,.form-check-input.is-valid~.form-check-label{color:#3772ff}.form-check-inline .form-check-input~.valid-feedback{margin-left:.5em}.was-validated .input-group>.form-control:not(:focus):valid,.input-group>.form-control:not(:focus).is-valid,.was-validated .input-group>.form-select:not(:focus):valid,.input-group>.form-select:not(:focus).is-valid,.was-validated .input-group>.form-floating:not(:focus-within):valid,.input-group>.form-floating:not(:focus-within).is-valid{z-index:3}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#ed6a5a}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#000;background-color:rgba(237,106,90,.9);border-radius:.375rem}.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip,.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip{display:block}.was-validated .form-control:invalid,.form-control.is-invalid{border-color:#ed6a5a;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23ed6a5a'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23ed6a5a' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem)center;background-size:calc(.75em + .375rem)calc(.75em + .375rem)}.was-validated .form-control:invalid:focus,.form-control.is-invalid:focus{border-color:#ed6a5a;box-shadow:0 0 0 .25rem rgba(237,106,90,.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem)right calc(.375em + .1875rem)}.was-validated .form-select:invalid,.form-select.is-invalid{border-color:#ed6a5a}.was-validated .form-select:invalid:not([multiple]):not([size]),.was-validated .form-select:invalid:not([multiple])[size="1"],.form-select.is-invalid:not([multiple]):not([size]),.form-select.is-invalid:not([multiple])[size="1"]{padding-right:4.125rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23ed6a5a'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23ed6a5a' stroke='none'/%3e%3c/svg%3e");background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem)calc(.75em + .375rem)}.was-validated .form-select:invalid:focus,.form-select.is-invalid:focus{border-color:#ed6a5a;box-shadow:0 0 0 .25rem rgba(237,106,90,.25)}.was-validated .form-control-color:invalid,.form-control-color.is-invalid{width:calc(3rem + calc(1.5em + .75rem))}.was-validated .form-check-input:invalid,.form-check-input.is-invalid{border-color:#ed6a5a}.was-validated .form-check-input:invalid:checked,.form-check-input.is-invalid:checked{background-color:#ed6a5a}.was-validated .form-check-input:invalid:focus,.form-check-input.is-invalid:focus{box-shadow:0 0 0 .25rem rgba(237,106,90,.25)}.was-validated .form-check-input:invalid~.form-check-label,.form-check-input.is-invalid~.form-check-label{color:#ed6a5a}.form-check-inline .form-check-input~.invalid-feedback{margin-left:.5em}.was-validated .input-group>.form-control:not(:focus):invalid,.input-group>.form-control:not(:focus).is-invalid,.was-validated .input-group>.form-select:not(:focus):invalid,.input-group>.form-select:not(:focus).is-invalid,.was-validated .input-group>.form-floating:not(:focus-within):invalid,.input-group>.form-floating:not(:focus-within).is-invalid{z-index:4}.btn,div.drawio button,.td-blog .td-rss-button{--bs-btn-padding-x:0.75rem;--bs-btn-padding-y:0.375rem;--bs-btn-font-family: ;--bs-btn-font-size:1rem;--bs-btn-font-weight:400;--bs-btn-line-height:1.5;--bs-btn-color:#212529;--bs-btn-bg:transparent;--bs-btn-border-width:1px;--bs-btn-border-color:transparent;--bs-btn-border-radius:0.375rem;--bs-btn-hover-border-color:transparent;--bs-btn-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);--bs-btn-disabled-opacity:0.65;--bs-btn-focus-box-shadow:0 0 0 0.25rem rgba(var(--bs-btn-focus-shadow-rgb), .5);display:inline-block;padding:var(--bs-btn-padding-y)var(--bs-btn-padding-x);font-family:var(--bs-btn-font-family);font-size:var(--bs-btn-font-size);font-weight:var(--bs-btn-font-weight);line-height:var(--bs-btn-line-height);color:var(--bs-btn-color);text-align:center;text-decoration:none;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;border:var(--bs-btn-border-width)solid var(--bs-btn-border-color);border-radius:var(--bs-btn-border-radius);background-color:var(--bs-btn-bg);background-image:var(--bs-gradient);box-shadow:var(--bs-btn-box-shadow);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion:reduce){.btn,div.drawio button,.td-blog .td-rss-button{transition:none}}.btn:hover,div.drawio button:hover,.td-blog .td-rss-button:hover{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color)}.btn-check+.btn:hover,div.drawio .btn-check+button:hover,.td-blog .btn-check+.td-rss-button:hover{color:var(--bs-btn-color);background-color:var(--bs-btn-bg);border-color:var(--bs-btn-border-color)}.btn:focus-visible,div.drawio button:focus-visible,.td-blog .td-rss-button:focus-visible{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);background-image:var(--bs-gradient);border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-box-shadow),var(--bs-btn-focus-box-shadow)}.btn-check:focus-visible+.btn,div.drawio .btn-check:focus-visible+button,.td-blog .btn-check:focus-visible+.td-rss-button{border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-box-shadow),var(--bs-btn-focus-box-shadow)}.btn-check:checked+.btn,div.drawio .btn-check:checked+button,.td-blog .btn-check:checked+.td-rss-button,:not(.btn-check)+.btn:active,div.drawio :not(.btn-check)+button:active,.td-blog :not(.btn-check)+.td-rss-button:active,.btn:first-child:active,div.drawio button:first-child:active,.td-blog .td-rss-button:first-child:active,.btn.active,div.drawio button.active,.td-blog .active.td-rss-button,.btn.show,div.drawio button.show,.td-blog .show.td-rss-button{color:var(--bs-btn-active-color);background-color:var(--bs-btn-active-bg);background-image:none;border-color:var(--bs-btn-active-border-color);box-shadow:var(--bs-btn-active-shadow)}.btn-check:checked+.btn:focus-visible,div.drawio .btn-check:checked+button:focus-visible,.td-blog .btn-check:checked+.td-rss-button:focus-visible,:not(.btn-check)+.btn:active:focus-visible,div.drawio :not(.btn-check)+button:active:focus-visible,.td-blog :not(.btn-check)+.td-rss-button:active:focus-visible,.btn:first-child:active:focus-visible,div.drawio button:first-child:active:focus-visible,.td-blog .td-rss-button:first-child:active:focus-visible,.btn.active:focus-visible,div.drawio button.active:focus-visible,.td-blog .active.td-rss-button:focus-visible,.btn.show:focus-visible,div.drawio button.show:focus-visible,.td-blog .show.td-rss-button:focus-visible{box-shadow:var(--bs-btn-active-shadow),var(--bs-btn-focus-box-shadow)}.btn:disabled,div.drawio button:disabled,.td-blog .td-rss-button:disabled,.btn.disabled,div.drawio button.disabled,.td-blog .disabled.td-rss-button,fieldset:disabled .btn,fieldset:disabled div.drawio button,div.drawio fieldset:disabled button,fieldset:disabled .td-blog .td-rss-button,.td-blog fieldset:disabled .td-rss-button{color:var(--bs-btn-disabled-color);pointer-events:none;background-color:var(--bs-btn-disabled-bg);background-image:none;border-color:var(--bs-btn-disabled-border-color);opacity:var(--bs-btn-disabled-opacity);box-shadow:none}.btn-primary{--bs-btn-color:#fff;--bs-btn-bg:#081b4b;--bs-btn-border-color:#081b4b;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#071740;--bs-btn-hover-border-color:#06163c;--bs-btn-focus-shadow-rgb:45, 61, 102;--bs-btn-active-color:#fff;--bs-btn-active-bg:#06163c;--bs-btn-active-border-color:#061438;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#081b4b;--bs-btn-disabled-border-color:#081b4b}.btn-secondary{--bs-btn-color:#000;--bs-btn-bg:#fff;--bs-btn-border-color:#fff;--bs-btn-hover-color:#000;--bs-btn-hover-bg:white;--bs-btn-hover-border-color:white;--bs-btn-focus-shadow-rgb:217, 217, 217;--bs-btn-active-color:#000;--bs-btn-active-bg:white;--bs-btn-active-border-color:white;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#fff;--bs-btn-disabled-border-color:#fff}.btn-success{--bs-btn-color:#000;--bs-btn-bg:#3772ff;--bs-btn-border-color:#3772ff;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#5587ff;--bs-btn-hover-border-color:#4b80ff;--bs-btn-focus-shadow-rgb:47, 97, 217;--bs-btn-active-color:#000;--bs-btn-active-bg:#5f8eff;--bs-btn-active-border-color:#4b80ff;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#3772ff;--bs-btn-disabled-border-color:#3772ff}.btn-info,.td-blog .td-rss-button{--bs-btn-color:#000;--bs-btn-bg:#c0e0de;--bs-btn-border-color:#c0e0de;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#c9e5e3;--bs-btn-hover-border-color:#c6e3e1;--bs-btn-focus-shadow-rgb:163, 190, 189;--bs-btn-active-color:#000;--bs-btn-active-bg:#cde6e5;--bs-btn-active-border-color:#c6e3e1;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#c0e0de;--bs-btn-disabled-border-color:#c0e0de}.btn-warning{--bs-btn-color:#000;--bs-btn-bg:#ed6a5a;--bs-btn-border-color:#ed6a5a;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#f08073;--bs-btn-hover-border-color:#ef796b;--bs-btn-focus-shadow-rgb:201, 90, 77;--bs-btn-active-color:#000;--bs-btn-active-bg:#f1887b;--bs-btn-active-border-color:#ef796b;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#ed6a5a;--bs-btn-disabled-border-color:#ed6a5a}.btn-danger{--bs-btn-color:#000;--bs-btn-bg:#ed6a5a;--bs-btn-border-color:#ed6a5a;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#f08073;--bs-btn-hover-border-color:#ef796b;--bs-btn-focus-shadow-rgb:201, 90, 77;--bs-btn-active-color:#000;--bs-btn-active-bg:#f1887b;--bs-btn-active-border-color:#ef796b;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#ed6a5a;--bs-btn-disabled-border-color:#ed6a5a}.btn-light{--bs-btn-color:#000;--bs-btn-bg:#d3f3ee;--bs-btn-border-color:#d3f3ee;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#b3cfca;--bs-btn-hover-border-color:#a9c2be;--bs-btn-focus-shadow-rgb:179, 207, 202;--bs-btn-active-color:#000;--bs-btn-active-bg:#a9c2be;--bs-btn-active-border-color:#9eb6b3;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#d3f3ee;--bs-btn-disabled-border-color:#d3f3ee}.btn-dark{--bs-btn-color:#fff;--bs-btn-bg:#403f4c;--bs-btn-border-color:#403f4c;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#5d5c67;--bs-btn-hover-border-color:#53525e;--bs-btn-focus-shadow-rgb:93, 92, 103;--bs-btn-active-color:#fff;--bs-btn-active-bg:#666570;--bs-btn-active-border-color:#53525e;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#403f4c;--bs-btn-disabled-border-color:#403f4c}.btn-outline-primary,div.drawio button{--bs-btn-color:#081b4b;--bs-btn-border-color:#081b4b;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#081b4b;--bs-btn-hover-border-color:#081b4b;--bs-btn-focus-shadow-rgb:8, 27, 75;--bs-btn-active-color:#fff;--bs-btn-active-bg:#081b4b;--bs-btn-active-border-color:#081b4b;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#081b4b;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#081b4b;--bs-gradient:none}.btn-outline-secondary{--bs-btn-color:#fff;--bs-btn-border-color:#fff;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#fff;--bs-btn-hover-border-color:#fff;--bs-btn-focus-shadow-rgb:255, 255, 255;--bs-btn-active-color:#000;--bs-btn-active-bg:#fff;--bs-btn-active-border-color:#fff;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#fff;--bs-gradient:none}.btn-outline-success{--bs-btn-color:#3772ff;--bs-btn-border-color:#3772ff;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#3772ff;--bs-btn-hover-border-color:#3772ff;--bs-btn-focus-shadow-rgb:55, 114, 255;--bs-btn-active-color:#000;--bs-btn-active-bg:#3772ff;--bs-btn-active-border-color:#3772ff;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#3772ff;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#3772ff;--bs-gradient:none}.btn-outline-info{--bs-btn-color:#c0e0de;--bs-btn-border-color:#c0e0de;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#c0e0de;--bs-btn-hover-border-color:#c0e0de;--bs-btn-focus-shadow-rgb:192, 224, 222;--bs-btn-active-color:#000;--bs-btn-active-bg:#c0e0de;--bs-btn-active-border-color:#c0e0de;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#c0e0de;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#c0e0de;--bs-gradient:none}.btn-outline-warning{--bs-btn-color:#ed6a5a;--bs-btn-border-color:#ed6a5a;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#ed6a5a;--bs-btn-hover-border-color:#ed6a5a;--bs-btn-focus-shadow-rgb:237, 106, 90;--bs-btn-active-color:#000;--bs-btn-active-bg:#ed6a5a;--bs-btn-active-border-color:#ed6a5a;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#ed6a5a;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#ed6a5a;--bs-gradient:none}.btn-outline-danger{--bs-btn-color:#ed6a5a;--bs-btn-border-color:#ed6a5a;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#ed6a5a;--bs-btn-hover-border-color:#ed6a5a;--bs-btn-focus-shadow-rgb:237, 106, 90;--bs-btn-active-color:#000;--bs-btn-active-bg:#ed6a5a;--bs-btn-active-border-color:#ed6a5a;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#ed6a5a;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#ed6a5a;--bs-gradient:none}.btn-outline-light{--bs-btn-color:#d3f3ee;--bs-btn-border-color:#d3f3ee;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#d3f3ee;--bs-btn-hover-border-color:#d3f3ee;--bs-btn-focus-shadow-rgb:211, 243, 238;--bs-btn-active-color:#000;--bs-btn-active-bg:#d3f3ee;--bs-btn-active-border-color:#d3f3ee;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#d3f3ee;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#d3f3ee;--bs-gradient:none}.btn-outline-dark{--bs-btn-color:#403f4c;--bs-btn-border-color:#403f4c;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#403f4c;--bs-btn-hover-border-color:#403f4c;--bs-btn-focus-shadow-rgb:64, 63, 76;--bs-btn-active-color:#fff;--bs-btn-active-bg:#403f4c;--bs-btn-active-border-color:#403f4c;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#403f4c;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#403f4c;--bs-gradient:none}.btn-link{--bs-btn-font-weight:400;--bs-btn-color:var(--bs-link-color);--bs-btn-bg:transparent;--bs-btn-border-color:transparent;--bs-btn-hover-color:var(--bs-link-hover-color);--bs-btn-hover-border-color:transparent;--bs-btn-active-color:var(--bs-link-hover-color);--bs-btn-active-border-color:transparent;--bs-btn-disabled-color:#6c757d;--bs-btn-disabled-border-color:transparent;--bs-btn-box-shadow:none;--bs-btn-focus-shadow-rgb:45, 61, 102;text-decoration:underline;background-image:none}.btn-link:focus-visible{color:var(--bs-btn-color)}.btn-link:hover{color:var(--bs-btn-hover-color)}.btn-lg,.td-blog .td-rss-button,.btn-group-lg>.btn,div.drawio .btn-group-lg>button{--bs-btn-padding-y:0.5rem;--bs-btn-padding-x:1rem;--bs-btn-font-size:1.25rem;--bs-btn-border-radius:0.5rem}.btn-sm,.btn-group-sm>.btn,div.drawio .btn-group-sm>button,.td-blog .btn-group-sm>.td-rss-button{--bs-btn-padding-y:0.25rem;--bs-btn-padding-x:0.5rem;--bs-btn-font-size:0.875rem;--bs-btn-border-radius:0.25rem}.fade{transition:opacity .15s linear}@media(prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;transition:height .35s ease}@media(prefers-reduced-motion:reduce){.collapsing{transition:none}}.collapsing.collapse-horizontal{width:0;height:auto;transition:width .35s ease}@media(prefers-reduced-motion:reduce){.collapsing.collapse-horizontal{transition:none}}.dropup,.dropend,.dropdown,.dropstart,.dropup-center,.dropdown-center{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{--bs-dropdown-zindex:1000;--bs-dropdown-min-width:10rem;--bs-dropdown-padding-x:0;--bs-dropdown-padding-y:0.5rem;--bs-dropdown-spacer:0.125rem;--bs-dropdown-font-size:1rem;--bs-dropdown-color:#212529;--bs-dropdown-bg:#fff;--bs-dropdown-border-color:var(--bs-border-color-translucent);--bs-dropdown-border-radius:0.375rem;--bs-dropdown-border-width:1px;--bs-dropdown-inner-border-radius:calc(0.375rem - 1px);--bs-dropdown-divider-bg:var(--bs-border-color-translucent);--bs-dropdown-divider-margin-y:0.5rem;--bs-dropdown-box-shadow:0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-dropdown-link-color:#212529;--bs-dropdown-link-hover-color:#1e2125;--bs-dropdown-link-hover-bg:#e9ecef;--bs-dropdown-link-active-color:#fff;--bs-dropdown-link-active-bg:#081b4b;--bs-dropdown-link-disabled-color:#adb5bd;--bs-dropdown-item-padding-x:1rem;--bs-dropdown-item-padding-y:0.25rem;--bs-dropdown-header-color:#6c757d;--bs-dropdown-header-padding-x:1rem;--bs-dropdown-header-padding-y:0.5rem;position:absolute;z-index:var(--bs-dropdown-zindex);display:none;min-width:var(--bs-dropdown-min-width);padding:var(--bs-dropdown-padding-y)var(--bs-dropdown-padding-x);margin:0;font-size:var(--bs-dropdown-font-size);color:var(--bs-dropdown-color);text-align:left;list-style:none;background-color:var(--bs-dropdown-bg);background-clip:padding-box;border:var(--bs-dropdown-border-width)solid var(--bs-dropdown-border-color);border-radius:var(--bs-dropdown-border-radius);box-shadow:var(--bs-dropdown-box-shadow)}.dropdown-menu[data-bs-popper]{top:100%;left:0;margin-top:var(--bs-dropdown-spacer)}.dropdown-menu-start{--bs-position:start}.dropdown-menu-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-end{--bs-position:end}.dropdown-menu-end[data-bs-popper]{right:0;left:auto}@media(min-width:576px){.dropdown-menu-sm-start{--bs-position:start}.dropdown-menu-sm-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-sm-end{--bs-position:end}.dropdown-menu-sm-end[data-bs-popper]{right:0;left:auto}}@media(min-width:768px){.dropdown-menu-md-start{--bs-position:start}.dropdown-menu-md-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-md-end{--bs-position:end}.dropdown-menu-md-end[data-bs-popper]{right:0;left:auto}}@media(min-width:992px){.dropdown-menu-lg-start{--bs-position:start}.dropdown-menu-lg-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-lg-end{--bs-position:end}.dropdown-menu-lg-end[data-bs-popper]{right:0;left:auto}}@media(min-width:1200px){.dropdown-menu-xl-start{--bs-position:start}.dropdown-menu-xl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xl-end{--bs-position:end}.dropdown-menu-xl-end[data-bs-popper]{right:0;left:auto}}@media(min-width:1400px){.dropdown-menu-xxl-start{--bs-position:start}.dropdown-menu-xxl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xxl-end{--bs-position:end}.dropdown-menu-xxl-end[data-bs-popper]{right:0;left:auto}}.dropup .dropdown-menu[data-bs-popper]{top:auto;bottom:100%;margin-top:0;margin-bottom:var(--bs-dropdown-spacer)}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-menu[data-bs-popper]{top:0;right:auto;left:100%;margin-top:0;margin-left:var(--bs-dropdown-spacer)}.dropend .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropend .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-toggle::after{vertical-align:0}.dropstart .dropdown-menu[data-bs-popper]{top:0;right:100%;left:auto;margin-top:0;margin-right:var(--bs-dropdown-spacer)}.dropstart .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropstart .dropdown-toggle::after{display:none}.dropstart .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropstart .dropdown-toggle:empty::after{margin-left:0}.dropstart .dropdown-toggle::before{vertical-align:0}.dropdown-divider{height:0;margin:var(--bs-dropdown-divider-margin-y)0;overflow:hidden;border-top:1px solid var(--bs-dropdown-divider-bg);opacity:1}.dropdown-item{display:block;width:100%;padding:var(--bs-dropdown-item-padding-y)var(--bs-dropdown-item-padding-x);clear:both;font-weight:400;color:var(--bs-dropdown-link-color);text-align:inherit;text-decoration:none;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:hover,.dropdown-item:focus{color:var(--bs-dropdown-link-hover-color);background-color:var(--bs-dropdown-link-hover-bg);background-image:var(--bs-gradient)}.dropdown-item.active,.dropdown-item:active{color:var(--bs-dropdown-link-active-color);text-decoration:none;background-color:var(--bs-dropdown-link-active-bg);background-image:var(--bs-gradient)}.dropdown-item.disabled,.dropdown-item:disabled{color:var(--bs-dropdown-link-disabled-color);pointer-events:none;background-color:transparent;background-image:none}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:var(--bs-dropdown-header-padding-y)var(--bs-dropdown-header-padding-x);margin-bottom:0;font-size:.875rem;color:var(--bs-dropdown-header-color);white-space:nowrap}.dropdown-item-text{display:block;padding:var(--bs-dropdown-item-padding-y)var(--bs-dropdown-item-padding-x);color:var(--bs-dropdown-link-color)}.dropdown-menu-dark{--bs-dropdown-color:#dee2e6;--bs-dropdown-bg:#343a40;--bs-dropdown-border-color:var(--bs-border-color-translucent);--bs-dropdown-box-shadow: ;--bs-dropdown-link-color:#dee2e6;--bs-dropdown-link-hover-color:#fff;--bs-dropdown-divider-bg:var(--bs-border-color-translucent);--bs-dropdown-link-hover-bg:rgba(255, 255, 255, 0.15);--bs-dropdown-link-active-color:#fff;--bs-dropdown-link-active-bg:#081b4b;--bs-dropdown-link-disabled-color:#adb5bd;--bs-dropdown-header-color:#adb5bd}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group>.btn,div.drawio .btn-group>button,.td-blog .btn-group>.td-rss-button,.btn-group-vertical>.btn,div.drawio .btn-group-vertical>button,.td-blog .btn-group-vertical>.td-rss-button{position:relative;flex:auto}.btn-group>.btn-check:checked+.btn,div.drawio .btn-group>.btn-check:checked+button,.td-blog .btn-group>.btn-check:checked+.td-rss-button,.btn-group>.btn-check:focus+.btn,div.drawio .btn-group>.btn-check:focus+button,.td-blog .btn-group>.btn-check:focus+.td-rss-button,.btn-group>.btn:hover,div.drawio .btn-group>button:hover,.td-blog .btn-group>.td-rss-button:hover,.btn-group>.btn:focus,div.drawio .btn-group>button:focus,.td-blog .btn-group>.td-rss-button:focus,.btn-group>.btn:active,div.drawio .btn-group>button:active,.td-blog .btn-group>.td-rss-button:active,.btn-group>.btn.active,div.drawio .btn-group>button.active,.td-blog .btn-group>.active.td-rss-button,.btn-group-vertical>.btn-check:checked+.btn,div.drawio .btn-group-vertical>.btn-check:checked+button,.td-blog .btn-group-vertical>.btn-check:checked+.td-rss-button,.btn-group-vertical>.btn-check:focus+.btn,div.drawio .btn-group-vertical>.btn-check:focus+button,.td-blog .btn-group-vertical>.btn-check:focus+.td-rss-button,.btn-group-vertical>.btn:hover,div.drawio .btn-group-vertical>button:hover,.td-blog .btn-group-vertical>.td-rss-button:hover,.btn-group-vertical>.btn:focus,div.drawio .btn-group-vertical>button:focus,.td-blog .btn-group-vertical>.td-rss-button:focus,.btn-group-vertical>.btn:active,div.drawio .btn-group-vertical>button:active,.td-blog .btn-group-vertical>.td-rss-button:active,.btn-group-vertical>.btn.active,div.drawio .btn-group-vertical>button.active,.td-blog .btn-group-vertical>.active.td-rss-button{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group{border-radius:.375rem}.btn-group>:not(.btn-check:first-child)+.btn,div.drawio .btn-group>:not(.btn-check:first-child)+button,.td-blog .btn-group>:not(.btn-check:first-child)+.td-rss-button,.btn-group>.btn-group:not(:first-child){margin-left:-1px}.btn-group>.btn:not(:last-child):not(.dropdown-toggle),div.drawio .btn-group>button:not(:last-child):not(.dropdown-toggle),.td-blog .btn-group>.td-rss-button:not(:last-child):not(.dropdown-toggle),.btn-group>.btn.dropdown-toggle-split:first-child,div.drawio .btn-group>button.dropdown-toggle-split:first-child,.td-blog .btn-group>.dropdown-toggle-split.td-rss-button:first-child,.btn-group>.btn-group:not(:last-child)>.btn,div.drawio .btn-group>.btn-group:not(:last-child)>button,.td-blog .btn-group>.btn-group:not(:last-child)>.td-rss-button{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:nth-child(n+3),div.drawio .btn-group>button:nth-child(n+3),.td-blog .btn-group>.td-rss-button:nth-child(n+3),.btn-group>:not(.btn-check)+.btn,div.drawio .btn-group>:not(.btn-check)+button,.td-blog .btn-group>:not(.btn-check)+.td-rss-button,.btn-group>.btn-group:not(:first-child)>.btn,div.drawio .btn-group>.btn-group:not(:first-child)>button,.td-blog .btn-group>.btn-group:not(:first-child)>.td-rss-button{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after,.dropend .dropdown-toggle-split::after{margin-left:0}.dropstart .dropdown-toggle-split::before{margin-right:0}.btn-sm+.dropdown-toggle-split,.btn-group-sm>.btn+.dropdown-toggle-split,div.drawio .btn-group-sm>button+.dropdown-toggle-split,.td-blog .btn-group-sm>.td-rss-button+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-lg+.dropdown-toggle-split,.td-blog .td-rss-button+.dropdown-toggle-split,.btn-group-lg>.btn+.dropdown-toggle-split,div.drawio .btn-group-lg>button+.dropdown-toggle-split,.td-blog .btn-group-lg>.td-rss-button+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group.show .dropdown-toggle{box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.show .dropdown-toggle.btn-link{box-shadow:none}.btn-group-vertical{flex-direction:column;align-items:flex-start;justify-content:center}.btn-group-vertical>.btn,div.drawio .btn-group-vertical>button,.td-blog .btn-group-vertical>.td-rss-button,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn:not(:first-child),div.drawio .btn-group-vertical>button:not(:first-child),.td-blog .btn-group-vertical>.td-rss-button:not(:first-child),.btn-group-vertical>.btn-group:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle),div.drawio .btn-group-vertical>button:not(:last-child):not(.dropdown-toggle),.td-blog .btn-group-vertical>.td-rss-button:not(:last-child):not(.dropdown-toggle),.btn-group-vertical>.btn-group:not(:last-child)>.btn,div.drawio .btn-group-vertical>.btn-group:not(:last-child)>button,.td-blog .btn-group-vertical>.btn-group:not(:last-child)>.td-rss-button{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn~.btn,div.drawio .btn-group-vertical>button~.btn,div.drawio .btn-group-vertical>.btn~button,div.drawio .btn-group-vertical>button~button,.td-blog .btn-group-vertical>.td-rss-button~.btn,.td-blog div.drawio .btn-group-vertical>.td-rss-button~button,div.drawio .td-blog .btn-group-vertical>.td-rss-button~button,.td-blog .btn-group-vertical>.btn~.td-rss-button,.td-blog div.drawio .btn-group-vertical>button~.td-rss-button,div.drawio .td-blog .btn-group-vertical>button~.td-rss-button,.td-blog .btn-group-vertical>.td-rss-button~.td-rss-button,.btn-group-vertical>.btn-group:not(:first-child)>.btn,div.drawio .btn-group-vertical>.btn-group:not(:first-child)>button,.td-blog .btn-group-vertical>.btn-group:not(:first-child)>.td-rss-button{border-top-left-radius:0;border-top-right-radius:0}.nav{--bs-nav-link-padding-x:1rem;--bs-nav-link-padding-y:0.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color:var(--bs-link-color);--bs-nav-link-hover-color:var(--bs-link-hover-color);--bs-nav-link-disabled-color:#6c757d;display:flex;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:var(--bs-nav-link-padding-y)var(--bs-nav-link-padding-x);font-size:var(--bs-nav-link-font-size);font-weight:var(--bs-nav-link-font-weight);color:var(--bs-nav-link-color);text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}@media(prefers-reduced-motion:reduce){.nav-link{transition:none}}.nav-link:hover,.nav-link:focus{color:var(--bs-nav-link-hover-color)}.nav-link.disabled{color:var(--bs-nav-link-disabled-color);pointer-events:none;cursor:default}.nav-tabs{--bs-nav-tabs-border-width:1px;--bs-nav-tabs-border-color:#dee2e6;--bs-nav-tabs-border-radius:0.375rem;--bs-nav-tabs-link-hover-border-color:#e9ecef #e9ecef #dee2e6;--bs-nav-tabs-link-active-color:#495057;--bs-nav-tabs-link-active-bg:#fff;--bs-nav-tabs-link-active-border-color:#dee2e6 #dee2e6 #fff;border-bottom:var(--bs-nav-tabs-border-width)solid var(--bs-nav-tabs-border-color)}.nav-tabs .nav-link{margin-bottom:calc(-1 * var(--bs-nav-tabs-border-width));background:0 0;border:var(--bs-nav-tabs-border-width)solid transparent;border-top-left-radius:var(--bs-nav-tabs-border-radius);border-top-right-radius:var(--bs-nav-tabs-border-radius)}.nav-tabs .nav-link:hover,.nav-tabs .nav-link:focus{isolation:isolate;border-color:var(--bs-nav-tabs-link-hover-border-color)}.nav-tabs .nav-link.disabled,.nav-tabs .nav-link:disabled{color:var(--bs-nav-link-disabled-color);background-color:transparent;border-color:transparent}.nav-tabs .nav-link.active,.nav-tabs .nav-item.show .nav-link{color:var(--bs-nav-tabs-link-active-color);background-color:var(--bs-nav-tabs-link-active-bg);border-color:var(--bs-nav-tabs-link-active-border-color)}.nav-tabs .dropdown-menu{margin-top:calc(-1 * var(--bs-nav-tabs-border-width));border-top-left-radius:0;border-top-right-radius:0}.nav-pills{--bs-nav-pills-border-radius:0.375rem;--bs-nav-pills-link-active-color:#fff;--bs-nav-pills-link-active-bg:#081b4b}.nav-pills .nav-link{background:0 0;border:0;border-radius:var(--bs-nav-pills-border-radius)}.nav-pills .nav-link:disabled{color:var(--bs-nav-link-disabled-color);background-color:transparent;border-color:transparent}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:var(--bs-nav-pills-link-active-color);background-color:var(--bs-nav-pills-link-active-bg);background-image:var(--bs-gradient)}.nav-fill>.nav-link,.nav-fill .nav-item{flex:auto;text-align:center}.nav-justified>.nav-link,.nav-justified .nav-item{flex-basis:0;flex-grow:1;text-align:center}.nav-fill .nav-item .nav-link,.nav-justified .nav-item .nav-link{width:100%}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar,.td-navbar{--bs-navbar-padding-x:0;--bs-navbar-padding-y:0.5rem;--bs-navbar-color:rgba(0, 0, 0, 0.55);--bs-navbar-hover-color:rgba(0, 0, 0, 0.7);--bs-navbar-disabled-color:rgba(0, 0, 0, 0.3);--bs-navbar-active-color:rgba(0, 0, 0, 0.9);--bs-navbar-brand-padding-y:0.3125rem;--bs-navbar-brand-margin-end:1rem;--bs-navbar-brand-font-size:1.25rem;--bs-navbar-brand-color:rgba(0, 0, 0, 0.9);--bs-navbar-brand-hover-color:rgba(0, 0, 0, 0.9);--bs-navbar-nav-link-padding-x:0.5rem;--bs-navbar-toggler-padding-y:0.25rem;--bs-navbar-toggler-padding-x:0.75rem;--bs-navbar-toggler-font-size:1.25rem;--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");--bs-navbar-toggler-border-color:rgba(0, 0, 0, 0.1);--bs-navbar-toggler-border-radius:0.375rem;--bs-navbar-toggler-focus-width:0.25rem;--bs-navbar-toggler-transition:box-shadow 0.15s ease-in-out;position:relative;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;padding:var(--bs-navbar-padding-y)var(--bs-navbar-padding-x);background-image:var(--bs-gradient)}.navbar>.container,.td-navbar>.container,.navbar>.container-fluid,.td-navbar>.container-fluid,.navbar>.container-sm,.td-navbar>.container-sm,.navbar>.container-md,.td-navbar>.container-md,.navbar>.container-lg,.td-navbar>.container-lg,.navbar>.container-xl,.td-navbar>.container-xl,.navbar>.container-xxl,.td-navbar>.container-xxl{display:flex;flex-wrap:inherit;align-items:center;justify-content:space-between}.navbar-brand{padding-top:var(--bs-navbar-brand-padding-y);padding-bottom:var(--bs-navbar-brand-padding-y);margin-right:var(--bs-navbar-brand-margin-end);font-size:var(--bs-navbar-brand-font-size);color:var(--bs-navbar-brand-color);text-decoration:none;white-space:nowrap}.navbar-brand:hover,.navbar-brand:focus{color:var(--bs-navbar-brand-hover-color)}.navbar-nav{--bs-nav-link-padding-x:0;--bs-nav-link-padding-y:0.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color:var(--bs-navbar-color);--bs-nav-link-hover-color:var(--bs-navbar-hover-color);--bs-nav-link-disabled-color:var(--bs-navbar-disabled-color);display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .show>.nav-link,.navbar-nav .nav-link.active{color:var(--bs-navbar-active-color)}.navbar-nav .dropdown-menu{position:static}.navbar-text{padding-top:.5rem;padding-bottom:.5rem;color:var(--bs-navbar-color)}.navbar-text a,.navbar-text a:hover,.navbar-text a:focus{color:var(--bs-navbar-active-color)}.navbar-collapse{flex-basis:100%;flex-grow:1;align-items:center}.navbar-toggler{padding:var(--bs-navbar-toggler-padding-y)var(--bs-navbar-toggler-padding-x);font-size:var(--bs-navbar-toggler-font-size);line-height:1;color:var(--bs-navbar-color);background-color:transparent;border:var(--bs-border-width)solid var(--bs-navbar-toggler-border-color);border-radius:var(--bs-navbar-toggler-border-radius);transition:var(--bs-navbar-toggler-transition)}@media(prefers-reduced-motion:reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{text-decoration:none;outline:0;box-shadow:0 0 0 var(--bs-navbar-toggler-focus-width)}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;background-image:var(--bs-navbar-toggler-icon-bg);background-repeat:no-repeat;background-position:50%;background-size:100%}.navbar-nav-scroll{max-height:var(--bs-scroll-height,75vh);overflow-y:auto}@media(min-width:576px){.navbar-expand-sm{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}.navbar-expand-sm .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;box-shadow:none;transition:none}.navbar-expand-sm .offcanvas .offcanvas-header{display:none}.navbar-expand-sm .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media(min-width:768px){.navbar-expand-md{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}.navbar-expand-md .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;box-shadow:none;transition:none}.navbar-expand-md .offcanvas .offcanvas-header{display:none}.navbar-expand-md .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media(min-width:992px){.navbar-expand-lg{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}.navbar-expand-lg .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;box-shadow:none;transition:none}.navbar-expand-lg .offcanvas .offcanvas-header{display:none}.navbar-expand-lg .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media(min-width:1200px){.navbar-expand-xl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}.navbar-expand-xl .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;box-shadow:none;transition:none}.navbar-expand-xl .offcanvas .offcanvas-header{display:none}.navbar-expand-xl .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media(min-width:1400px){.navbar-expand-xxl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xxl .navbar-nav{flex-direction:row}.navbar-expand-xxl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xxl .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-xxl .navbar-nav-scroll{overflow:visible}.navbar-expand-xxl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xxl .navbar-toggler{display:none}.navbar-expand-xxl .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;box-shadow:none;transition:none}.navbar-expand-xxl .offcanvas .offcanvas-header{display:none}.navbar-expand-xxl .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}.navbar-expand,.td-navbar{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand .navbar-nav,.td-navbar .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu,.td-navbar .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link,.td-navbar .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand .navbar-nav-scroll,.td-navbar .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse,.td-navbar .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler,.td-navbar .navbar-toggler{display:none}.navbar-expand .offcanvas,.td-navbar .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;box-shadow:none;transition:none}.navbar-expand .offcanvas .offcanvas-header,.td-navbar .offcanvas .offcanvas-header{display:none}.navbar-expand .offcanvas .offcanvas-body,.td-navbar .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}.navbar-dark{--bs-navbar-color:rgba(255, 255, 255, 0.75);--bs-navbar-hover-color:rgba(255, 255, 255, 0.5);--bs-navbar-disabled-color:rgba(255, 255, 255, 0.25);--bs-navbar-active-color:#fff;--bs-navbar-brand-color:#fff;--bs-navbar-brand-hover-color:#fff;--bs-navbar-toggler-border-color:rgba(255, 255, 255, 0.1);--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.75%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.card,.td-content .highlight{--bs-card-spacer-y:1rem;--bs-card-spacer-x:1rem;--bs-card-title-spacer-y:0.5rem;--bs-card-border-width:1px;--bs-card-border-color:var(--bs-border-color-translucent);--bs-card-border-radius:0.375rem;--bs-card-box-shadow: ;--bs-card-inner-border-radius:calc(0.375rem - 1px);--bs-card-cap-padding-y:0.5rem;--bs-card-cap-padding-x:1rem;--bs-card-cap-bg:rgba(0, 0, 0, 0.03);--bs-card-cap-color: ;--bs-card-height: ;--bs-card-color: ;--bs-card-bg:#fff;--bs-card-img-overlay-padding:1rem;--bs-card-group-margin:0.75rem;position:relative;display:flex;flex-direction:column;min-width:0;height:var(--bs-card-height);word-wrap:break-word;background-color:var(--bs-card-bg);background-clip:border-box;border:var(--bs-card-border-width)solid var(--bs-card-border-color);border-radius:var(--bs-card-border-radius);box-shadow:var(--bs-card-box-shadow)}.card>hr,.td-content .highlight>hr{margin-right:0;margin-left:0}.card>.list-group,.td-content .highlight>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child,.td-content .highlight>.list-group:first-child{border-top-width:0;border-top-left-radius:var(--bs-card-inner-border-radius);border-top-right-radius:var(--bs-card-inner-border-radius)}.card>.list-group:last-child,.td-content .highlight>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:var(--bs-card-inner-border-radius);border-bottom-left-radius:var(--bs-card-inner-border-radius)}.card>.card-header+.list-group,.td-content .highlight>.card-header+.list-group,.card>.list-group+.card-footer,.td-content .highlight>.list-group+.card-footer{border-top:0}.card-body{flex:auto;padding:var(--bs-card-spacer-y)var(--bs-card-spacer-x);color:var(--bs-card-color)}.card-title{margin-bottom:var(--bs-card-title-spacer-y)}.card-subtitle{margin-top:calc(-.5 * var(--bs-card-title-spacer-y));margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link+.card-link{margin-left:var(--bs-card-spacer-x)}.card-header{padding:var(--bs-card-cap-padding-y)var(--bs-card-cap-padding-x);margin-bottom:0;color:var(--bs-card-cap-color);background-color:var(--bs-card-cap-bg);border-bottom:var(--bs-card-border-width)solid var(--bs-card-border-color)}.card-header:first-child{border-radius:var(--bs-card-inner-border-radius)var(--bs-card-inner-border-radius)0 0}.card-footer{padding:var(--bs-card-cap-padding-y)var(--bs-card-cap-padding-x);color:var(--bs-card-cap-color);background-color:var(--bs-card-cap-bg);border-top:var(--bs-card-border-width)solid var(--bs-card-border-color)}.card-footer:last-child{border-radius:0 0 var(--bs-card-inner-border-radius)var(--bs-card-inner-border-radius)}.card-header-tabs{margin-right:calc(-.5 * var(--bs-card-cap-padding-x));margin-bottom:calc(-1 * var(--bs-card-cap-padding-y));margin-left:calc(-.5 * var(--bs-card-cap-padding-x));border-bottom:0}.card-header-tabs .nav-link.active{background-color:var(--bs-card-bg);border-bottom-color:var(--bs-card-bg)}.card-header-pills{margin-right:calc(-.5 * var(--bs-card-cap-padding-x));margin-left:calc(-.5 * var(--bs-card-cap-padding-x))}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:var(--bs-card-img-overlay-padding);border-radius:var(--bs-card-inner-border-radius)}.card-img,.card-img-top,.card-img-bottom{width:100%}.card-img,.card-img-top{border-top-left-radius:var(--bs-card-inner-border-radius);border-top-right-radius:var(--bs-card-inner-border-radius)}.card-img,.card-img-bottom{border-bottom-right-radius:var(--bs-card-inner-border-radius);border-bottom-left-radius:var(--bs-card-inner-border-radius)}.card-group>.card,.td-content .card-group>.highlight{margin-bottom:var(--bs-card-group-margin)}@media(min-width:576px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card,.td-content .card-group>.highlight{flex:1 0;margin-bottom:0}.card-group>.card+.card,.td-content .card-group>.highlight+.card,.td-content .card-group>.card+.highlight,.td-content .card-group>.highlight+.highlight{margin-left:0;border-left:0}.card-group>.card:not(:last-child),.td-content .card-group>.highlight:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-img-top,.td-content .card-group>.highlight:not(:last-child) .card-img-top,.card-group>.card:not(:last-child) .card-header,.td-content .card-group>.highlight:not(:last-child) .card-header{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-img-bottom,.td-content .card-group>.highlight:not(:last-child) .card-img-bottom,.card-group>.card:not(:last-child) .card-footer,.td-content .card-group>.highlight:not(:last-child) .card-footer{border-bottom-right-radius:0}.card-group>.card:not(:first-child),.td-content .card-group>.highlight:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-img-top,.td-content .card-group>.highlight:not(:first-child) .card-img-top,.card-group>.card:not(:first-child) .card-header,.td-content .card-group>.highlight:not(:first-child) .card-header{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-img-bottom,.td-content .card-group>.highlight:not(:first-child) .card-img-bottom,.card-group>.card:not(:first-child) .card-footer,.td-content .card-group>.highlight:not(:first-child) .card-footer{border-bottom-left-radius:0}}.accordion{--bs-accordion-color:#212529;--bs-accordion-bg:#fff;--bs-accordion-transition:color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, border-radius 0.15s ease;--bs-accordion-border-color:var(--bs-border-color);--bs-accordion-border-width:1px;--bs-accordion-border-radius:0.375rem;--bs-accordion-inner-border-radius:calc(0.375rem - 1px);--bs-accordion-btn-padding-x:1.25rem;--bs-accordion-btn-padding-y:1rem;--bs-accordion-btn-color:#212529;--bs-accordion-btn-bg:var(--bs-accordion-bg);--bs-accordion-btn-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");--bs-accordion-btn-icon-width:1.25rem;--bs-accordion-btn-icon-transform:rotate(-180deg);--bs-accordion-btn-icon-transition:transform 0.2s ease-in-out;--bs-accordion-btn-active-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23071844'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");--bs-accordion-btn-focus-border-color:#848da5;--bs-accordion-btn-focus-box-shadow:0 0 0 0.25rem rgba(8, 27, 75, 0.25);--bs-accordion-body-padding-x:1.25rem;--bs-accordion-body-padding-y:1rem;--bs-accordion-active-color:#071844;--bs-accordion-active-bg:#e6e8ed}.accordion-button{position:relative;display:flex;align-items:center;width:100%;padding:var(--bs-accordion-btn-padding-y)var(--bs-accordion-btn-padding-x);font-size:1rem;color:var(--bs-accordion-btn-color);text-align:left;background-color:var(--bs-accordion-btn-bg);border:0;border-radius:0;overflow-anchor:none;transition:var(--bs-accordion-transition)}@media(prefers-reduced-motion:reduce){.accordion-button{transition:none}}.accordion-button:not(.collapsed){color:var(--bs-accordion-active-color);background-color:var(--bs-accordion-active-bg);box-shadow:inset 0 calc(-1 * var(--bs-accordion-border-width))0 var(--bs-accordion-border-color)}.accordion-button:not(.collapsed)::after{background-image:var(--bs-accordion-btn-active-icon);transform:var(--bs-accordion-btn-icon-transform)}.accordion-button::after{flex-shrink:0;width:var(--bs-accordion-btn-icon-width);height:var(--bs-accordion-btn-icon-width);margin-left:auto;content:"";background-image:var(--bs-accordion-btn-icon);background-repeat:no-repeat;background-size:var(--bs-accordion-btn-icon-width);transition:var(--bs-accordion-btn-icon-transition)}@media(prefers-reduced-motion:reduce){.accordion-button::after{transition:none}}.accordion-button:hover{z-index:2}.accordion-button:focus{z-index:3;border-color:var(--bs-accordion-btn-focus-border-color);outline:0;box-shadow:var(--bs-accordion-btn-focus-box-shadow)}.accordion-header{margin-bottom:0}.accordion-item{color:var(--bs-accordion-color);background-color:var(--bs-accordion-bg);border:var(--bs-accordion-border-width)solid var(--bs-accordion-border-color)}.accordion-item:first-of-type{border-top-left-radius:var(--bs-accordion-border-radius);border-top-right-radius:var(--bs-accordion-border-radius)}.accordion-item:first-of-type .accordion-button{border-top-left-radius:var(--bs-accordion-inner-border-radius);border-top-right-radius:var(--bs-accordion-inner-border-radius)}.accordion-item:not(:first-of-type){border-top:0}.accordion-item:last-of-type{border-bottom-right-radius:var(--bs-accordion-border-radius);border-bottom-left-radius:var(--bs-accordion-border-radius)}.accordion-item:last-of-type .accordion-button.collapsed{border-bottom-right-radius:var(--bs-accordion-inner-border-radius);border-bottom-left-radius:var(--bs-accordion-inner-border-radius)}.accordion-item:last-of-type .accordion-collapse{border-bottom-right-radius:var(--bs-accordion-border-radius);border-bottom-left-radius:var(--bs-accordion-border-radius)}.accordion-body{padding:var(--bs-accordion-body-padding-y)var(--bs-accordion-body-padding-x)}.accordion-flush .accordion-collapse{border-width:0}.accordion-flush .accordion-item{border-right:0;border-left:0;border-radius:0}.accordion-flush .accordion-item:first-child{border-top:0}.accordion-flush .accordion-item:last-child{border-bottom:0}.accordion-flush .accordion-item .accordion-button,.accordion-flush .accordion-item .accordion-button.collapsed{border-radius:0}.breadcrumb{--bs-breadcrumb-padding-x:0;--bs-breadcrumb-padding-y:0;--bs-breadcrumb-margin-bottom:1rem;--bs-breadcrumb-bg: ;--bs-breadcrumb-border-radius: ;--bs-breadcrumb-divider-color:#6c757d;--bs-breadcrumb-item-padding-x:0.5rem;--bs-breadcrumb-item-active-color:#6c757d;display:flex;flex-wrap:wrap;padding:var(--bs-breadcrumb-padding-y)var(--bs-breadcrumb-padding-x);margin-bottom:var(--bs-breadcrumb-margin-bottom);font-size:var(--bs-breadcrumb-font-size);list-style:none;background-color:var(--bs-breadcrumb-bg);border-radius:var(--bs-breadcrumb-border-radius)}.breadcrumb-item+.breadcrumb-item{padding-left:var(--bs-breadcrumb-item-padding-x)}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:var(--bs-breadcrumb-item-padding-x);color:var(--bs-breadcrumb-divider-color);content:var(--bs-breadcrumb-divider,"/")}.breadcrumb-item.active{color:var(--bs-breadcrumb-item-active-color)}.pagination{--bs-pagination-padding-x:0.75rem;--bs-pagination-padding-y:0.375rem;--bs-pagination-font-size:1rem;--bs-pagination-color:#6c757d;--bs-pagination-bg:#fff;--bs-pagination-border-width:1px;--bs-pagination-border-color:#dee2e6;--bs-pagination-border-radius:0.375rem;--bs-pagination-hover-color:var(--bs-link-hover-color);--bs-pagination-hover-bg:#e9ecef;--bs-pagination-hover-border-color:#dee2e6;--bs-pagination-focus-color:var(--bs-link-hover-color);--bs-pagination-focus-bg:#e9ecef;--bs-pagination-focus-box-shadow:0 0 0 0.25rem rgba(8, 27, 75, 0.25);--bs-pagination-active-color:#fff;--bs-pagination-active-bg:#081b4b;--bs-pagination-active-border-color:#081b4b;--bs-pagination-disabled-color:#dee2e6;--bs-pagination-disabled-bg:#fff;--bs-pagination-disabled-border-color:#dee2e6;display:flex;padding-left:0;list-style:none}.page-link{position:relative;display:block;padding:var(--bs-pagination-padding-y)var(--bs-pagination-padding-x);font-size:var(--bs-pagination-font-size);color:var(--bs-pagination-color);text-decoration:none;background-color:var(--bs-pagination-bg);border:var(--bs-pagination-border-width)solid var(--bs-pagination-border-color);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion:reduce){.page-link{transition:none}}.page-link:hover{z-index:2;color:var(--bs-pagination-hover-color);background-color:var(--bs-pagination-hover-bg);border-color:var(--bs-pagination-hover-border-color)}.page-link:focus{z-index:3;color:var(--bs-pagination-focus-color);background-color:var(--bs-pagination-focus-bg);outline:0;box-shadow:var(--bs-pagination-focus-box-shadow)}.page-link.active,.active>.page-link{z-index:3;color:var(--bs-pagination-active-color);background-color:var(--bs-pagination-active-bg);background-image:var(--bs-gradient);border-color:var(--bs-pagination-active-border-color)}.page-link.disabled,.disabled>.page-link{color:var(--bs-pagination-disabled-color);pointer-events:none;background-color:var(--bs-pagination-disabled-bg);border-color:var(--bs-pagination-disabled-border-color)}.page-item:not(:first-child) .page-link{margin-left:-1px}.page-item:first-child .page-link{border-top-left-radius:var(--bs-pagination-border-radius);border-bottom-left-radius:var(--bs-pagination-border-radius)}.page-item:last-child .page-link{border-top-right-radius:var(--bs-pagination-border-radius);border-bottom-right-radius:var(--bs-pagination-border-radius)}.pagination-lg{--bs-pagination-padding-x:1.5rem;--bs-pagination-padding-y:0.75rem;--bs-pagination-font-size:1.25rem;--bs-pagination-border-radius:0.5rem}.pagination-sm{--bs-pagination-padding-x:0.5rem;--bs-pagination-padding-y:0.25rem;--bs-pagination-font-size:0.875rem;--bs-pagination-border-radius:0.25rem}.badge{--bs-badge-padding-x:0.65em;--bs-badge-padding-y:0.35em;--bs-badge-font-size:0.75em;--bs-badge-font-weight:700;--bs-badge-color:#fff;--bs-badge-border-radius:0.375rem;display:inline-block;padding:var(--bs-badge-padding-y)var(--bs-badge-padding-x);font-size:var(--bs-badge-font-size);font-weight:var(--bs-badge-font-weight);line-height:1;color:var(--bs-badge-color);text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:var(--bs-badge-border-radius);background-image:var(--bs-gradient)}.badge:empty{display:none}.btn .badge,div.drawio button .badge,.td-blog .td-rss-button .badge{position:relative;top:-1px}.alert{--bs-alert-bg:transparent;--bs-alert-padding-x:1rem;--bs-alert-padding-y:1rem;--bs-alert-margin-bottom:1rem;--bs-alert-color:inherit;--bs-alert-border-color:transparent;--bs-alert-border:1px solid var(--bs-alert-border-color);--bs-alert-border-radius:0.375rem;position:relative;padding:var(--bs-alert-padding-y)var(--bs-alert-padding-x);margin-bottom:var(--bs-alert-margin-bottom);color:var(--bs-alert-color);background-color:var(--bs-alert-bg);border:var(--bs-alert-border);border-radius:var(--bs-alert-border-radius)}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:3rem}.alert-dismissible .btn-close{position:absolute;top:0;right:0;z-index:2;padding:1.25rem 1rem}.alert-primary{--bs-alert-color:#05102d;--bs-alert-bg:#ced1db;--bs-alert-border-color:#b5bbc9;background-image:var(--bs-gradient)}.alert-primary .alert-link{color:#040d24}.alert-secondary{--bs-alert-color:#666666;--bs-alert-bg:white;--bs-alert-border-color:white;background-image:var(--bs-gradient)}.alert-secondary .alert-link{color:#525252}.alert-success{--bs-alert-color:#214499;--bs-alert-bg:#d7e3ff;--bs-alert-border-color:#c3d5ff;background-image:var(--bs-gradient)}.alert-success .alert-link{color:#1a367a}.alert-info{--bs-alert-color:#4d5a59;--bs-alert-bg:#f2f9f8;--bs-alert-border-color:#ecf6f5;background-image:var(--bs-gradient)}.alert-info .alert-link{color:#3e4847}.alert-warning{--bs-alert-color:#8e4036;--bs-alert-bg:#fbe1de;--bs-alert-border-color:#fad2ce;background-image:var(--bs-gradient)}.alert-warning .alert-link{color:#72332b}.alert-danger{--bs-alert-color:#8e4036;--bs-alert-bg:#fbe1de;--bs-alert-border-color:#fad2ce;background-image:var(--bs-gradient)}.alert-danger .alert-link{color:#72332b}.alert-light{--bs-alert-color:#54615f;--bs-alert-bg:#f6fdfc;--bs-alert-border-color:#f2fbfa;background-image:var(--bs-gradient)}.alert-light .alert-link{color:#434e4c}.alert-dark{--bs-alert-color:#26262e;--bs-alert-bg:#d9d9db;--bs-alert-border-color:#c6c5c9;background-image:var(--bs-gradient)}.alert-dark .alert-link{color:#1e1e25}@keyframes progress-bar-stripes{0%{background-position-x:1rem}}.progress{--bs-progress-height:1rem;--bs-progress-font-size:0.75rem;--bs-progress-bg:#e9ecef;--bs-progress-border-radius:0.375rem;--bs-progress-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.075);--bs-progress-bar-color:#fff;--bs-progress-bar-bg:#081b4b;--bs-progress-bar-transition:width 0.6s ease;display:flex;height:var(--bs-progress-height);overflow:hidden;font-size:var(--bs-progress-font-size);background-color:var(--bs-progress-bg);border-radius:var(--bs-progress-border-radius);box-shadow:var(--bs-progress-box-shadow)}.progress-bar{display:flex;flex-direction:column;justify-content:center;overflow:hidden;color:var(--bs-progress-bar-color);text-align:center;white-space:nowrap;background-color:var(--bs-progress-bar-bg);transition:var(--bs-progress-bar-transition)}@media(prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:var(--bs-progress-height)var(--bs-progress-height)}.progress-bar-animated{animation:1s linear infinite progress-bar-stripes}@media(prefers-reduced-motion:reduce){.progress-bar-animated{animation:none}}.list-group{--bs-list-group-color:#212529;--bs-list-group-bg:#fff;--bs-list-group-border-color:rgba(0, 0, 0, 0.125);--bs-list-group-border-width:1px;--bs-list-group-border-radius:0.375rem;--bs-list-group-item-padding-x:1rem;--bs-list-group-item-padding-y:0.5rem;--bs-list-group-action-color:#495057;--bs-list-group-action-hover-color:#495057;--bs-list-group-action-hover-bg:#f8f9fa;--bs-list-group-action-active-color:#212529;--bs-list-group-action-active-bg:#e9ecef;--bs-list-group-disabled-color:#6c757d;--bs-list-group-disabled-bg:#fff;--bs-list-group-active-color:#fff;--bs-list-group-active-bg:#081b4b;--bs-list-group-active-border-color:#081b4b;display:flex;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:var(--bs-list-group-border-radius)}.list-group-numbered{list-style-type:none;counter-reset:section}.list-group-numbered>.list-group-item::before{content:counters(section,".")". ";counter-increment:section}.list-group-item-action{width:100%;color:var(--bs-list-group-action-color);text-align:inherit}.list-group-item-action:hover,.list-group-item-action:focus{z-index:1;color:var(--bs-list-group-action-hover-color);text-decoration:none;background-color:var(--bs-list-group-action-hover-bg)}.list-group-item-action:active{color:var(--bs-list-group-action-active-color);background-color:var(--bs-list-group-action-active-bg)}.list-group-item{position:relative;display:block;padding:var(--bs-list-group-item-padding-y)var(--bs-list-group-item-padding-x);color:var(--bs-list-group-color);text-decoration:none;background-color:var(--bs-list-group-bg);border:var(--bs-list-group-border-width)solid var(--bs-list-group-border-color)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:var(--bs-list-group-disabled-color);pointer-events:none;background-color:var(--bs-list-group-disabled-bg)}.list-group-item.active{z-index:2;color:var(--bs-list-group-active-color);background-color:var(--bs-list-group-active-bg);border-color:var(--bs-list-group-active-border-color)}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:calc(-1 * var(--bs-list-group-border-width));border-top-width:var(--bs-list-group-border-width)}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}@media(min-width:576px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media(min-width:768px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media(min-width:992px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media(min-width:1200px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media(min-width:1400px){.list-group-horizontal-xxl{flex-direction:row}.list-group-horizontal-xxl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xxl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xxl>.list-group-item.active{margin-top:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 var(--bs-list-group-border-width)}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#05102d;background-color:#ced1db}.list-group-item-primary.list-group-item-action:hover,.list-group-item-primary.list-group-item-action:focus{color:#05102d;background-color:#b9bcc5}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#05102d;border-color:#05102d}.list-group-item-secondary{color:#666;background-color:#fff}.list-group-item-secondary.list-group-item-action:hover,.list-group-item-secondary.list-group-item-action:focus{color:#666;background-color:#e6e6e6}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#666;border-color:#666}.list-group-item-success{color:#214499;background-color:#d7e3ff}.list-group-item-success.list-group-item-action:hover,.list-group-item-success.list-group-item-action:focus{color:#214499;background-color:#c2cce6}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#214499;border-color:#214499}.list-group-item-info{color:#4d5a59;background-color:#f2f9f8}.list-group-item-info.list-group-item-action:hover,.list-group-item-info.list-group-item-action:focus{color:#4d5a59;background-color:#dae0df}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#4d5a59;border-color:#4d5a59}.list-group-item-warning{color:#8e4036;background-color:#fbe1de}.list-group-item-warning.list-group-item-action:hover,.list-group-item-warning.list-group-item-action:focus{color:#8e4036;background-color:#e2cbc8}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#8e4036;border-color:#8e4036}.list-group-item-danger{color:#8e4036;background-color:#fbe1de}.list-group-item-danger.list-group-item-action:hover,.list-group-item-danger.list-group-item-action:focus{color:#8e4036;background-color:#e2cbc8}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#8e4036;border-color:#8e4036}.list-group-item-light{color:#54615f;background-color:#f6fdfc}.list-group-item-light.list-group-item-action:hover,.list-group-item-light.list-group-item-action:focus{color:#54615f;background-color:#dde4e3}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#54615f;border-color:#54615f}.list-group-item-dark{color:#26262e;background-color:#d9d9db}.list-group-item-dark.list-group-item-action:hover,.list-group-item-dark.list-group-item-action:focus{color:#26262e;background-color:#c3c3c5}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#26262e;border-color:#26262e}.btn-close{box-sizing:content-box;width:1em;height:1em;padding:.25em;color:#000;background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/%3e%3c/svg%3e")50%/1em no-repeat;border:0;border-radius:.375rem;opacity:.5}.btn-close:hover{color:#000;text-decoration:none;opacity:.75}.btn-close:focus{outline:0;box-shadow:0 0 0 .25rem rgba(8,27,75,.25);opacity:1}.btn-close:disabled,.btn-close.disabled{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;opacity:.25}.btn-close-white{filter:invert(1)grayscale(100%)brightness(200%)}.toast{--bs-toast-zindex:1090;--bs-toast-padding-x:0.75rem;--bs-toast-padding-y:0.5rem;--bs-toast-spacing:1.5rem;--bs-toast-max-width:350px;--bs-toast-font-size:0.875rem;--bs-toast-color: ;--bs-toast-bg:rgba(255, 255, 255, 0.85);--bs-toast-border-width:1px;--bs-toast-border-color:var(--bs-border-color-translucent);--bs-toast-border-radius:0.375rem;--bs-toast-box-shadow:0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-toast-header-color:#6c757d;--bs-toast-header-bg:rgba(255, 255, 255, 0.85);--bs-toast-header-border-color:rgba(0, 0, 0, 0.05);width:var(--bs-toast-max-width);max-width:100%;font-size:var(--bs-toast-font-size);color:var(--bs-toast-color);pointer-events:auto;background-color:var(--bs-toast-bg);background-clip:padding-box;border:var(--bs-toast-border-width)solid var(--bs-toast-border-color);box-shadow:var(--bs-toast-box-shadow);border-radius:var(--bs-toast-border-radius)}.toast.showing{opacity:0}.toast:not(.show){display:none}.toast-container{--bs-toast-zindex:1090;position:absolute;z-index:var(--bs-toast-zindex);width:-moz-max-content;width:max-content;max-width:100%;pointer-events:none}.toast-container>:not(:last-child){margin-bottom:var(--bs-toast-spacing)}.toast-header{display:flex;align-items:center;padding:var(--bs-toast-padding-y)var(--bs-toast-padding-x);color:var(--bs-toast-header-color);background-color:var(--bs-toast-header-bg);background-clip:padding-box;border-bottom:var(--bs-toast-border-width)solid var(--bs-toast-header-border-color);border-top-left-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width));border-top-right-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width))}.toast-header .btn-close{margin-right:calc(-.5 * var(--bs-toast-padding-x));margin-left:var(--bs-toast-padding-x)}.toast-body{padding:var(--bs-toast-padding-x);word-wrap:break-word}.modal{--bs-modal-zindex:1055;--bs-modal-width:500px;--bs-modal-padding:1rem;--bs-modal-margin:0.5rem;--bs-modal-color: ;--bs-modal-bg:#fff;--bs-modal-border-color:var(--bs-border-color-translucent);--bs-modal-border-width:1px;--bs-modal-border-radius:0.5rem;--bs-modal-box-shadow:0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);--bs-modal-inner-border-radius:calc(0.5rem - 1px);--bs-modal-header-padding-x:1rem;--bs-modal-header-padding-y:1rem;--bs-modal-header-padding:1rem 1rem;--bs-modal-header-border-color:var(--bs-border-color);--bs-modal-header-border-width:1px;--bs-modal-title-line-height:1.5;--bs-modal-footer-gap:0.5rem;--bs-modal-footer-bg: ;--bs-modal-footer-border-color:var(--bs-border-color);--bs-modal-footer-border-width:1px;position:fixed;top:0;left:0;z-index:var(--bs-modal-zindex);display:none;width:100%;height:100%;overflow-x:hidden;overflow-y:auto;outline:0}.modal-dialog{position:relative;width:auto;margin:var(--bs-modal-margin);pointer-events:none}.modal.fade .modal-dialog{transition:transform .3s ease-out;transform:translate(0,-50px)}@media(prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{height:calc(100% - var(--bs-modal-margin) * 2)}.modal-dialog-scrollable .modal-content{max-height:100%;overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;align-items:center;min-height:calc(100% - var(--bs-modal-margin) * 2)}.modal-content{position:relative;display:flex;flex-direction:column;width:100%;color:var(--bs-modal-color);pointer-events:auto;background-color:var(--bs-modal-bg);background-clip:padding-box;border:var(--bs-modal-border-width)solid var(--bs-modal-border-color);border-radius:var(--bs-modal-border-radius);box-shadow:var(--bs-modal-box-shadow);outline:0}.modal-backdrop{--bs-backdrop-zindex:1050;--bs-backdrop-bg:#000;--bs-backdrop-opacity:0.5;position:fixed;top:0;left:0;z-index:var(--bs-backdrop-zindex);width:100vw;height:100vh;background-color:var(--bs-backdrop-bg)}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:var(--bs-backdrop-opacity)}.modal-header{display:flex;flex-shrink:0;align-items:center;justify-content:space-between;padding:var(--bs-modal-header-padding);border-bottom:var(--bs-modal-header-border-width)solid var(--bs-modal-header-border-color);border-top-left-radius:var(--bs-modal-inner-border-radius);border-top-right-radius:var(--bs-modal-inner-border-radius)}.modal-header .btn-close{padding:calc(var(--bs-modal-header-padding-y) * .5);margin:calc(-.5 * var(--bs-modal-header-padding-y))calc(-.5 * var(--bs-modal-header-padding-x))calc(-.5 * var(--bs-modal-header-padding-y))auto}.modal-title{margin-bottom:0;line-height:var(--bs-modal-title-line-height)}.modal-body{position:relative;flex:auto;padding:var(--bs-modal-padding)}.modal-footer{display:flex;flex-shrink:0;flex-wrap:wrap;align-items:center;justify-content:flex-end;padding:calc(var(--bs-modal-padding) - var(--bs-modal-footer-gap) * .5);background-color:var(--bs-modal-footer-bg);border-top:var(--bs-modal-footer-border-width)solid var(--bs-modal-footer-border-color);border-bottom-right-radius:var(--bs-modal-inner-border-radius);border-bottom-left-radius:var(--bs-modal-inner-border-radius)}.modal-footer>*{margin:calc(var(--bs-modal-footer-gap) * .5)}@media(min-width:576px){.modal{--bs-modal-margin:1.75rem;--bs-modal-box-shadow:0 0.5rem 1rem rgba(0, 0, 0, 0.15)}.modal-dialog{max-width:var(--bs-modal-width);margin-right:auto;margin-left:auto}.modal-sm{--bs-modal-width:300px}}@media(min-width:992px){.modal-lg,.modal-xl{--bs-modal-width:800px}}@media(min-width:1200px){.modal-xl{--bs-modal-width:1140px}}.modal-fullscreen{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen .modal-header,.modal-fullscreen .modal-footer{border-radius:0}.modal-fullscreen .modal-body{overflow-y:auto}@media(max-width:575.98px){.modal-fullscreen-sm-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-sm-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-sm-down .modal-header,.modal-fullscreen-sm-down .modal-footer{border-radius:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}}@media(max-width:767.98px){.modal-fullscreen-md-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-md-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-md-down .modal-header,.modal-fullscreen-md-down .modal-footer{border-radius:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}}@media(max-width:991.98px){.modal-fullscreen-lg-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-lg-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-lg-down .modal-header,.modal-fullscreen-lg-down .modal-footer{border-radius:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}}@media(max-width:1199.98px){.modal-fullscreen-xl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xl-down .modal-header,.modal-fullscreen-xl-down .modal-footer{border-radius:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}}@media(max-width:1399.98px){.modal-fullscreen-xxl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xxl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xxl-down .modal-header,.modal-fullscreen-xxl-down .modal-footer{border-radius:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}}.tooltip{--bs-tooltip-zindex:1080;--bs-tooltip-max-width:200px;--bs-tooltip-padding-x:0.5rem;--bs-tooltip-padding-y:0.25rem;--bs-tooltip-margin: ;--bs-tooltip-font-size:0.875rem;--bs-tooltip-color:#fff;--bs-tooltip-bg:#000;--bs-tooltip-border-radius:0.375rem;--bs-tooltip-opacity:0.9;--bs-tooltip-arrow-width:0.8rem;--bs-tooltip-arrow-height:0.4rem;z-index:var(--bs-tooltip-zindex);display:block;padding:var(--bs-tooltip-arrow-height);margin:var(--bs-tooltip-margin);font-family:open sans,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol;font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--bs-tooltip-font-size);word-wrap:break-word;opacity:0}.tooltip.show{opacity:var(--bs-tooltip-opacity)}.tooltip .tooltip-arrow{display:block;width:var(--bs-tooltip-arrow-width);height:var(--bs-tooltip-arrow-height)}.tooltip .tooltip-arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-top .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow{bottom:0}.bs-tooltip-top .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before{top:-1px;border-width:var(--bs-tooltip-arrow-height)calc(var(--bs-tooltip-arrow-width) * .5)0;border-top-color:var(--bs-tooltip-bg)}.bs-tooltip-end .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow{left:0;width:var(--bs-tooltip-arrow-height);height:var(--bs-tooltip-arrow-width)}.bs-tooltip-end .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before{right:-1px;border-width:calc(var(--bs-tooltip-arrow-width) * .5)var(--bs-tooltip-arrow-height)calc(var(--bs-tooltip-arrow-width) * .5)0;border-right-color:var(--bs-tooltip-bg)}.bs-tooltip-bottom .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow{top:0}.bs-tooltip-bottom .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before{bottom:-1px;border-width:0 calc(var(--bs-tooltip-arrow-width) * .5)var(--bs-tooltip-arrow-height);border-bottom-color:var(--bs-tooltip-bg)}.bs-tooltip-start .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow{right:0;width:var(--bs-tooltip-arrow-height);height:var(--bs-tooltip-arrow-width)}.bs-tooltip-start .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before{left:-1px;border-width:calc(var(--bs-tooltip-arrow-width) * .5)0 calc(var(--bs-tooltip-arrow-width) * .5)var(--bs-tooltip-arrow-height);border-left-color:var(--bs-tooltip-bg)}.tooltip-inner{max-width:var(--bs-tooltip-max-width);padding:var(--bs-tooltip-padding-y)var(--bs-tooltip-padding-x);color:var(--bs-tooltip-color);text-align:center;background-color:var(--bs-tooltip-bg);border-radius:var(--bs-tooltip-border-radius)}.popover{--bs-popover-zindex:1070;--bs-popover-max-width:276px;--bs-popover-font-size:0.875rem;--bs-popover-bg:#fff;--bs-popover-border-width:1px;--bs-popover-border-color:var(--bs-border-color-translucent);--bs-popover-border-radius:0.5rem;--bs-popover-inner-border-radius:calc(0.5rem - 1px);--bs-popover-box-shadow:0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-popover-header-padding-x:1rem;--bs-popover-header-padding-y:0.5rem;--bs-popover-header-font-size:1rem;--bs-popover-header-color: ;--bs-popover-header-bg:#f0f0f0;--bs-popover-body-padding-x:1rem;--bs-popover-body-padding-y:1rem;--bs-popover-body-color:#212529;--bs-popover-arrow-width:1rem;--bs-popover-arrow-height:0.5rem;--bs-popover-arrow-border:var(--bs-popover-border-color);z-index:var(--bs-popover-zindex);display:block;max-width:var(--bs-popover-max-width);font-family:open sans,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol;font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--bs-popover-font-size);word-wrap:break-word;background-color:var(--bs-popover-bg);background-clip:padding-box;border:var(--bs-popover-border-width)solid var(--bs-popover-border-color);border-radius:var(--bs-popover-border-radius);box-shadow:var(--bs-popover-box-shadow)}.popover .popover-arrow{display:block;width:var(--bs-popover-arrow-width);height:var(--bs-popover-arrow-height)}.popover .popover-arrow::before,.popover .popover-arrow::after{position:absolute;display:block;content:"";border-color:transparent;border-style:solid;border-width:0}.bs-popover-top>.popover-arrow,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow{bottom:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width))}.bs-popover-top>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before,.bs-popover-top>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after{border-width:var(--bs-popover-arrow-height)calc(var(--bs-popover-arrow-width) * .5)0}.bs-popover-top>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before{bottom:0;border-top-color:var(--bs-popover-arrow-border)}.bs-popover-top>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after{bottom:var(--bs-popover-border-width);border-top-color:var(--bs-popover-bg)}.bs-popover-end>.popover-arrow,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow{left:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width));width:var(--bs-popover-arrow-height);height:var(--bs-popover-arrow-width)}.bs-popover-end>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before,.bs-popover-end>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after{border-width:calc(var(--bs-popover-arrow-width) * .5)var(--bs-popover-arrow-height)calc(var(--bs-popover-arrow-width) * .5)0}.bs-popover-end>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before{left:0;border-right-color:var(--bs-popover-arrow-border)}.bs-popover-end>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after{left:var(--bs-popover-border-width);border-right-color:var(--bs-popover-bg)}.bs-popover-bottom>.popover-arrow,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow{top:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width))}.bs-popover-bottom>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before,.bs-popover-bottom>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after{border-width:0 calc(var(--bs-popover-arrow-width) * .5)var(--bs-popover-arrow-height)}.bs-popover-bottom>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before{top:0;border-bottom-color:var(--bs-popover-arrow-border)}.bs-popover-bottom>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after{top:var(--bs-popover-border-width);border-bottom-color:var(--bs-popover-bg)}.bs-popover-bottom .popover-header::before,.bs-popover-auto[data-popper-placement^=bottom] .popover-header::before{position:absolute;top:0;left:50%;display:block;width:var(--bs-popover-arrow-width);margin-left:calc(-.5 * var(--bs-popover-arrow-width));content:"";border-bottom:var(--bs-popover-border-width)solid var(--bs-popover-header-bg)}.bs-popover-start>.popover-arrow,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow{right:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width));width:var(--bs-popover-arrow-height);height:var(--bs-popover-arrow-width)}.bs-popover-start>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before,.bs-popover-start>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after{border-width:calc(var(--bs-popover-arrow-width) * .5)0 calc(var(--bs-popover-arrow-width) * .5)var(--bs-popover-arrow-height)}.bs-popover-start>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before{right:0;border-left-color:var(--bs-popover-arrow-border)}.bs-popover-start>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after{right:var(--bs-popover-border-width);border-left-color:var(--bs-popover-bg)}.popover-header{padding:var(--bs-popover-header-padding-y)var(--bs-popover-header-padding-x);margin-bottom:0;font-size:var(--bs-popover-header-font-size);color:var(--bs-popover-header-color);background-color:var(--bs-popover-header-bg);border-bottom:var(--bs-popover-border-width)solid var(--bs-popover-border-color);border-top-left-radius:var(--bs-popover-inner-border-radius);border-top-right-radius:var(--bs-popover-inner-border-radius)}.popover-header:empty{display:none}.popover-body{padding:var(--bs-popover-body-padding-y)var(--bs-popover-body-padding-x);color:var(--bs-popover-body-color)}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;backface-visibility:hidden;transition:transform .6s ease-in-out}@media(prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item.active,.carousel-item-next,.carousel-item-prev{display:block}.carousel-item-next:not(.carousel-item-start),.active.carousel-item-end{transform:translateX(100%)}.carousel-item-prev:not(.carousel-item-end),.active.carousel-item-start{transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item.active,.carousel-fade .carousel-item-next.carousel-item-start,.carousel-fade .carousel-item-prev.carousel-item-end{z-index:1;opacity:1}.carousel-fade .active.carousel-item-start,.carousel-fade .active.carousel-item-end{z-index:0;opacity:0;transition:opacity 0s .6s}@media(prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-start,.carousel-fade .active.carousel-item-end{transition:none}}.carousel-control-prev,.carousel-control-next{position:absolute;top:0;bottom:0;z-index:1;display:flex;align-items:center;justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:0 0;border:0;opacity:.5;transition:opacity .15s ease}@media(prefers-reduced-motion:reduce){.carousel-control-prev,.carousel-control-next{transition:none}}.carousel-control-prev:hover,.carousel-control-prev:focus,.carousel-control-next:hover,.carousel-control-next:focus{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0;background-image:linear-gradient(90deg,rgba(0,0,0,.25),rgba(0,0,0,.1%))}.carousel-control-next{right:0;background-image:linear-gradient(270deg,rgba(0,0,0,.25),rgba(0,0,0,.1%))}.carousel-control-prev-icon,.carousel-control-next-icon{display:inline-block;width:2rem;height:2rem;background-repeat:no-repeat;background-position:50%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:2;display:flex;justify-content:center;padding:0;margin-right:15%;margin-bottom:1rem;margin-left:15%;list-style:none}.carousel-indicators [data-bs-target]{box-sizing:content-box;flex:initial;width:30px;height:3px;padding:0;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border:0;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media(prefers-reduced-motion:reduce){.carousel-indicators [data-bs-target]{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:1.25rem;left:15%;padding-top:1.25rem;padding-bottom:1.25rem;color:#fff;text-align:center}.carousel-dark .carousel-control-prev-icon,.carousel-dark .carousel-control-next-icon{filter:invert(1)grayscale(100)}.carousel-dark .carousel-indicators [data-bs-target]{background-color:#000}.carousel-dark .carousel-caption{color:#000}.spinner-grow,.spinner-border{display:inline-block;width:var(--bs-spinner-width);height:var(--bs-spinner-height);vertical-align:var(--bs-spinner-vertical-align);border-radius:50%;animation:var(--bs-spinner-animation-speed)linear infinite var(--bs-spinner-animation-name)}@keyframes spinner-border{to{transform:rotate(360deg)}}.spinner-border{--bs-spinner-width:2rem;--bs-spinner-height:2rem;--bs-spinner-vertical-align:-0.125em;--bs-spinner-border-width:0.25em;--bs-spinner-animation-speed:0.75s;--bs-spinner-animation-name:spinner-border;border:var(--bs-spinner-border-width)solid;border-right-color:transparent}.spinner-border-sm{--bs-spinner-width:1rem;--bs-spinner-height:1rem;--bs-spinner-border-width:0.2em}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{--bs-spinner-width:2rem;--bs-spinner-height:2rem;--bs-spinner-vertical-align:-0.125em;--bs-spinner-animation-speed:0.75s;--bs-spinner-animation-name:spinner-grow;background-color:currentcolor;opacity:0}.spinner-grow-sm{--bs-spinner-width:1rem;--bs-spinner-height:1rem}@media(prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{--bs-spinner-animation-speed:1.5s}}.offcanvas,.offcanvas-xxl,.offcanvas-xl,.offcanvas-lg,.offcanvas-md,.offcanvas-sm{--bs-offcanvas-zindex:1045;--bs-offcanvas-width:400px;--bs-offcanvas-height:30vh;--bs-offcanvas-padding-x:1rem;--bs-offcanvas-padding-y:1rem;--bs-offcanvas-color: ;--bs-offcanvas-bg:#fff;--bs-offcanvas-border-width:1px;--bs-offcanvas-border-color:var(--bs-border-color-translucent);--bs-offcanvas-box-shadow:0 0.125rem 0.25rem rgba(0, 0, 0, 0.075)}@media(max-width:575.98px){.offcanvas-sm{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;box-shadow:var(--bs-offcanvas-box-shadow);transition:transform .3s ease-in-out}}@media(max-width:575.98px) and (prefers-reduced-motion:reduce){.offcanvas-sm{transition:none}}@media(max-width:575.98px){.offcanvas-sm.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width)solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-sm.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width)solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-sm.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width)solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-sm.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width)solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-sm.showing,.offcanvas-sm.show:not(.hiding){transform:none}.offcanvas-sm.showing,.offcanvas-sm.hiding,.offcanvas-sm.show{visibility:visible}}@media(min-width:576px){.offcanvas-sm{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-sm .offcanvas-header{display:none}.offcanvas-sm .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media(max-width:767.98px){.offcanvas-md{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;box-shadow:var(--bs-offcanvas-box-shadow);transition:transform .3s ease-in-out}}@media(max-width:767.98px) and (prefers-reduced-motion:reduce){.offcanvas-md{transition:none}}@media(max-width:767.98px){.offcanvas-md.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width)solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-md.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width)solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-md.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width)solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-md.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width)solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-md.showing,.offcanvas-md.show:not(.hiding){transform:none}.offcanvas-md.showing,.offcanvas-md.hiding,.offcanvas-md.show{visibility:visible}}@media(min-width:768px){.offcanvas-md{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-md .offcanvas-header{display:none}.offcanvas-md .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media(max-width:991.98px){.offcanvas-lg{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;box-shadow:var(--bs-offcanvas-box-shadow);transition:transform .3s ease-in-out}}@media(max-width:991.98px) and (prefers-reduced-motion:reduce){.offcanvas-lg{transition:none}}@media(max-width:991.98px){.offcanvas-lg.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width)solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-lg.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width)solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-lg.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width)solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-lg.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width)solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-lg.showing,.offcanvas-lg.show:not(.hiding){transform:none}.offcanvas-lg.showing,.offcanvas-lg.hiding,.offcanvas-lg.show{visibility:visible}}@media(min-width:992px){.offcanvas-lg{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-lg .offcanvas-header{display:none}.offcanvas-lg .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media(max-width:1199.98px){.offcanvas-xl{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;box-shadow:var(--bs-offcanvas-box-shadow);transition:transform .3s ease-in-out}}@media(max-width:1199.98px) and (prefers-reduced-motion:reduce){.offcanvas-xl{transition:none}}@media(max-width:1199.98px){.offcanvas-xl.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width)solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-xl.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width)solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-xl.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width)solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-xl.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width)solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-xl.showing,.offcanvas-xl.show:not(.hiding){transform:none}.offcanvas-xl.showing,.offcanvas-xl.hiding,.offcanvas-xl.show{visibility:visible}}@media(min-width:1200px){.offcanvas-xl{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-xl .offcanvas-header{display:none}.offcanvas-xl .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media(max-width:1399.98px){.offcanvas-xxl{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;box-shadow:var(--bs-offcanvas-box-shadow);transition:transform .3s ease-in-out}}@media(max-width:1399.98px) and (prefers-reduced-motion:reduce){.offcanvas-xxl{transition:none}}@media(max-width:1399.98px){.offcanvas-xxl.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width)solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-xxl.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width)solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-xxl.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width)solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-xxl.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width)solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-xxl.showing,.offcanvas-xxl.show:not(.hiding){transform:none}.offcanvas-xxl.showing,.offcanvas-xxl.hiding,.offcanvas-xxl.show{visibility:visible}}@media(min-width:1400px){.offcanvas-xxl{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-xxl .offcanvas-header{display:none}.offcanvas-xxl .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}.offcanvas{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;box-shadow:var(--bs-offcanvas-box-shadow);transition:transform .3s ease-in-out}@media(prefers-reduced-motion:reduce){.offcanvas{transition:none}}.offcanvas.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width)solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width)solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width)solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width)solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas.showing,.offcanvas.show:not(.hiding){transform:none}.offcanvas.showing,.offcanvas.hiding,.offcanvas.show{visibility:visible}.offcanvas-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.offcanvas-backdrop.fade{opacity:0}.offcanvas-backdrop.show{opacity:.5}.offcanvas-header{display:flex;align-items:center;justify-content:space-between;padding:var(--bs-offcanvas-padding-y)var(--bs-offcanvas-padding-x)}.offcanvas-header .btn-close{padding:calc(var(--bs-offcanvas-padding-y) * .5);margin-top:calc(-.5 * var(--bs-offcanvas-padding-y));margin-right:calc(-.5 * var(--bs-offcanvas-padding-x));margin-bottom:calc(-.5 * var(--bs-offcanvas-padding-y))}.offcanvas-title{margin-bottom:0;line-height:1.5}.offcanvas-body{flex-grow:1;padding:var(--bs-offcanvas-padding-y)var(--bs-offcanvas-padding-x);overflow-y:auto}.placeholder{display:inline-block;min-height:1em;vertical-align:middle;cursor:wait;background-color:currentcolor;opacity:.5}.placeholder.btn::before,div.drawio button.placeholder::before,.td-blog .placeholder.td-rss-button::before{display:inline-block;content:""}.placeholder-xs{min-height:.6em}.placeholder-sm{min-height:.8em}.placeholder-lg{min-height:1.2em}.placeholder-glow .placeholder{animation:placeholder-glow 2s ease-in-out infinite}@keyframes placeholder-glow{50%{opacity:.2}}.placeholder-wave{-webkit-mask-image:linear-gradient(130deg,#000 55%,rgba(0,0,0,.8) 75%,#000 95%);mask-image:linear-gradient(130deg,#000 55%,rgba(0,0,0,.8) 75%,#000 95%);-webkit-mask-size:200% 100%;mask-size:200% 100%;animation:placeholder-wave 2s linear infinite}@keyframes placeholder-wave{100%{-webkit-mask-position:-200% 0%;mask-position:-200% 0%}}.clearfix::after{display:block;clear:both;content:""}.text-bg-primary{color:#fff!important;background-color:RGBA(8,27,75,var(--bs-bg-opacity,1))!important}.text-bg-secondary{color:#000!important;background-color:RGBA(255,255,255,var(--bs-bg-opacity,1))!important}.text-bg-success{color:#000!important;background-color:RGBA(55,114,255,var(--bs-bg-opacity,1))!important}.text-bg-info{color:#000!important;background-color:RGBA(192,224,222,var(--bs-bg-opacity,1))!important}.text-bg-warning{color:#000!important;background-color:RGBA(237,106,90,var(--bs-bg-opacity,1))!important}.text-bg-danger{color:#000!important;background-color:RGBA(237,106,90,var(--bs-bg-opacity,1))!important}.text-bg-light{color:#000!important;background-color:RGBA(211,243,238,var(--bs-bg-opacity,1))!important}.text-bg-dark{color:#fff!important;background-color:RGBA(64,63,76,var(--bs-bg-opacity,1))!important}.link-primary{color:#081b4b!important}.link-primary:hover,.link-primary:focus{color:#061335!important}.link-secondary{color:#fff!important}.link-secondary:hover,.link-secondary:focus{color:#fff!important}.link-success{color:#3772ff!important}.link-success:hover,.link-success:focus{color:#739cff!important}.link-info{color:#c0e0de!important}.link-info:hover,.link-info:focus{color:#d3e9e8!important}.link-warning{color:#ed6a5a!important}.link-warning:hover,.link-warning:focus{color:#f2978c!important}.link-danger{color:#ed6a5a!important}.link-danger:hover,.link-danger:focus{color:#f2978c!important}.link-light{color:#d3f3ee!important}.link-light:hover,.link-light:focus{color:#e0f7f3!important}.link-dark{color:#403f4c!important}.link-dark:hover,.link-dark:focus{color:#2d2c35!important}.ratio{position:relative;width:100%}.ratio::before{display:block;padding-top:var(--bs-aspect-ratio);content:""}.ratio>*{position:absolute;top:0;left:0;width:100%;height:100%}.ratio-1x1{--bs-aspect-ratio:100%}.ratio-4x3{--bs-aspect-ratio:calc(3 / 4 * 100%)}.ratio-16x9{--bs-aspect-ratio:calc(9 / 16 * 100%)}.ratio-21x9{--bs-aspect-ratio:calc(9 / 21 * 100%)}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:sticky;top:0;z-index:1020}.sticky-bottom{position:sticky;bottom:0;z-index:1020}@media(min-width:576px){.sticky-sm-top{position:sticky;top:0;z-index:1020}.sticky-sm-bottom{position:sticky;bottom:0;z-index:1020}}@media(min-width:768px){.sticky-md-top{position:sticky;top:0;z-index:1020}.sticky-md-bottom{position:sticky;bottom:0;z-index:1020}}@media(min-width:992px){.sticky-lg-top{position:sticky;top:0;z-index:1020}.sticky-lg-bottom{position:sticky;bottom:0;z-index:1020}}@media(min-width:1200px){.sticky-xl-top{position:sticky;top:0;z-index:1020}.sticky-xl-bottom{position:sticky;bottom:0;z-index:1020}}@media(min-width:1400px){.sticky-xxl-top{position:sticky;top:0;z-index:1020}.sticky-xxl-bottom{position:sticky;bottom:0;z-index:1020}}.hstack{display:flex;flex-direction:row;align-items:center;align-self:stretch}.vstack{display:flex;flex:auto;flex-direction:column;align-self:stretch}.visually-hidden,.visually-hidden-focusable:not(:focus):not(:focus-within){position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vr{display:inline-block;align-self:stretch;width:1px;min-height:1em;background-color:currentcolor;opacity:.25}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.float-start{float:left!important}.float-end{float:right!important}.float-none{float:none!important}.opacity-0{opacity:0!important}.opacity-25{opacity:.25!important}.opacity-50{opacity:.5!important}.opacity-75{opacity:.75!important}.opacity-100{opacity:1!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.overflow-visible{overflow:visible!important}.overflow-scroll{overflow:scroll!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-grid{display:grid!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}.d-none{display:none!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:sticky!important}.top-0{top:0!important}.top-50{top:50%!important}.top-100{top:100%!important}.bottom-0{bottom:0!important}.bottom-50{bottom:50%!important}.bottom-100{bottom:100%!important}.start-0{left:0!important}.start-50{left:50%!important}.start-100{left:100%!important}.end-0{right:0!important}.end-50{right:50%!important}.end-100{right:100%!important}.translate-middle{transform:translate(-50%,-50%)!important}.translate-middle-x{transform:translateX(-50%)!important}.translate-middle-y{transform:translateY(-50%)!important}.border{border:var(--bs-border-width)var(--bs-border-style)var(--bs-border-color)!important}.border-0{border:0!important}.border-top,.td-page-meta__lastmod{border-top:var(--bs-border-width)var(--bs-border-style)var(--bs-border-color)!important}.border-top-0{border-top:0!important}.border-end{border-right:var(--bs-border-width)var(--bs-border-style)var(--bs-border-color)!important}.border-end-0{border-right:0!important}.border-bottom{border-bottom:var(--bs-border-width)var(--bs-border-style)var(--bs-border-color)!important}.border-bottom-0{border-bottom:0!important}.border-start{border-left:var(--bs-border-width)var(--bs-border-style)var(--bs-border-color)!important}.border-start-0{border-left:0!important}.border-primary{--bs-border-opacity:1;border-color:rgba(var(--bs-primary-rgb),var(--bs-border-opacity))!important}.border-secondary{--bs-border-opacity:1;border-color:rgba(var(--bs-secondary-rgb),var(--bs-border-opacity))!important}.border-success{--bs-border-opacity:1;border-color:rgba(var(--bs-success-rgb),var(--bs-border-opacity))!important}.border-info{--bs-border-opacity:1;border-color:rgba(var(--bs-info-rgb),var(--bs-border-opacity))!important}.border-warning{--bs-border-opacity:1;border-color:rgba(var(--bs-warning-rgb),var(--bs-border-opacity))!important}.border-danger{--bs-border-opacity:1;border-color:rgba(var(--bs-danger-rgb),var(--bs-border-opacity))!important}.border-light{--bs-border-opacity:1;border-color:rgba(var(--bs-light-rgb),var(--bs-border-opacity))!important}.border-dark{--bs-border-opacity:1;border-color:rgba(var(--bs-dark-rgb),var(--bs-border-opacity))!important}.border-white{--bs-border-opacity:1;border-color:rgba(var(--bs-white-rgb),var(--bs-border-opacity))!important}.border-1{--bs-border-width:1px}.border-2{--bs-border-width:2px}.border-3{--bs-border-width:3px}.border-4{--bs-border-width:4px}.border-5{--bs-border-width:5px}.border-opacity-10{--bs-border-opacity:0.1}.border-opacity-25{--bs-border-opacity:0.25}.border-opacity-50{--bs-border-opacity:0.5}.border-opacity-75{--bs-border-opacity:0.75}.border-opacity-100{--bs-border-opacity:1}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.mw-100{max-width:100%!important}.vw-100{width:100vw!important}.min-vw-100{min-width:100vw!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mh-100{max-height:100%!important}.vh-100{height:100vh!important}.min-vh-100{min-height:100vh!important}.flex-fill{flex:auto!important}.flex-row{flex-direction:row!important}.flex-column{flex-direction:column!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-column-reverse{flex-direction:column-reverse!important}.flex-grow-0{flex-grow:0!important}.flex-grow-1{flex-grow:1!important}.flex-shrink-0{flex-shrink:0!important}.flex-shrink-1{flex-shrink:1!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-start{justify-content:flex-start!important}.justify-content-end{justify-content:flex-end!important}.justify-content-center{justify-content:center!important}.justify-content-between{justify-content:space-between!important}.justify-content-around{justify-content:space-around!important}.justify-content-evenly{justify-content:space-evenly!important}.align-items-start{align-items:flex-start!important}.align-items-end{align-items:flex-end!important}.align-items-center{align-items:center!important}.align-items-baseline{align-items:baseline!important}.align-items-stretch{align-items:stretch!important}.align-content-start{align-content:flex-start!important}.align-content-end{align-content:flex-end!important}.align-content-center{align-content:center!important}.align-content-between{align-content:space-between!important}.align-content-around{align-content:space-around!important}.align-content-stretch{align-content:stretch!important}.align-self-auto{align-self:auto!important}.align-self-start{align-self:flex-start!important}.align-self-end{align-self:flex-end!important}.align-self-center{align-self:center!important}.align-self-baseline{align-self:baseline!important}.align-self-stretch{align-self:stretch!important}.order-first{order:-1!important}.order-0{order:0!important}.order-1{order:1!important}.order-2{order:2!important}.order-3{order:3!important}.order-4{order:4!important}.order-5{order:5!important}.order-last{order:6!important}.m-0{margin:0!important}.m-1{margin:.25rem!important}.m-2{margin:.5rem!important}.m-3{margin:1rem!important}.m-4{margin:1.5rem!important}.m-5{margin:3rem!important}.m-auto{margin:auto!important}.mx-0{margin-right:0!important;margin-left:0!important}.mx-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-3{margin-right:1rem!important;margin-left:1rem!important}.mx-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-5{margin-right:3rem!important;margin-left:3rem!important}.mx-auto{margin-right:auto!important;margin-left:auto!important}.my-0{margin-top:0!important;margin-bottom:0!important}.my-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-0{margin-top:0!important}.mt-1{margin-top:.25rem!important}.mt-2{margin-top:.5rem!important}.mt-3{margin-top:1rem!important}.mt-4{margin-top:1.5rem!important}.mt-5{margin-top:3rem!important}.mt-auto{margin-top:auto!important}.me-0{margin-right:0!important}.me-1{margin-right:.25rem!important}.me-2{margin-right:.5rem!important}.me-3{margin-right:1rem!important}.me-4{margin-right:1.5rem!important}.me-5{margin-right:3rem!important}.me-auto{margin-right:auto!important}.mb-0{margin-bottom:0!important}.mb-1{margin-bottom:.25rem!important}.mb-2{margin-bottom:.5rem!important}.mb-3{margin-bottom:1rem!important}.mb-4{margin-bottom:1.5rem!important}.mb-5{margin-bottom:3rem!important}.mb-auto{margin-bottom:auto!important}.ms-0{margin-left:0!important}.ms-1{margin-left:.25rem!important}.ms-2{margin-left:.5rem!important}.ms-3{margin-left:1rem!important}.ms-4{margin-left:1.5rem!important}.ms-5{margin-left:3rem!important}.ms-auto{margin-left:auto!important}.p-0{padding:0!important}.p-1{padding:.25rem!important}.p-2{padding:.5rem!important}.p-3{padding:1rem!important}.p-4{padding:1.5rem!important}.p-5{padding:3rem!important}.px-0{padding-right:0!important;padding-left:0!important}.px-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-3{padding-right:1rem!important;padding-left:1rem!important}.px-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-5{padding-right:3rem!important;padding-left:3rem!important}.py-0{padding-top:0!important;padding-bottom:0!important}.py-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-0{padding-top:0!important}.pt-1{padding-top:.25rem!important}.pt-2{padding-top:.5rem!important}.pt-3{padding-top:1rem!important}.pt-4{padding-top:1.5rem!important}.pt-5{padding-top:3rem!important}.pe-0{padding-right:0!important}.pe-1{padding-right:.25rem!important}.pe-2{padding-right:.5rem!important}.pe-3{padding-right:1rem!important}.pe-4{padding-right:1.5rem!important}.pe-5{padding-right:3rem!important}.pb-0{padding-bottom:0!important}.pb-1{padding-bottom:.25rem!important}.pb-2{padding-bottom:.5rem!important}.pb-3{padding-bottom:1rem!important}.pb-4{padding-bottom:1.5rem!important}.pb-5{padding-bottom:3rem!important}.ps-0{padding-left:0!important}.ps-1{padding-left:.25rem!important}.ps-2{padding-left:.5rem!important}.ps-3{padding-left:1rem!important}.ps-4{padding-left:1.5rem!important}.ps-5{padding-left:3rem!important}.gap-0{gap:0!important}.gap-1{gap:.25rem!important}.gap-2{gap:.5rem!important}.gap-3{gap:1rem!important}.gap-4{gap:1.5rem!important}.gap-5{gap:3rem!important}.font-monospace{font-family:var(--bs-font-monospace)!important}.fs-1{font-size:calc(1.375rem + 1.5vw)!important}.fs-2{font-size:calc(1.325rem + .9vw)!important}.fs-3{font-size:calc(1.275rem + .3vw)!important}.fs-4{font-size:calc(1.26rem + .12vw)!important}.fs-5{font-size:1.15rem!important}.fs-6{font-size:1rem!important}.fst-italic{font-style:italic!important}.fst-normal{font-style:normal!important}.fw-light{font-weight:300!important}.fw-lighter{font-weight:lighter!important}.fw-normal{font-weight:400!important}.fw-bold{font-weight:700!important}.fw-semibold{font-weight:600!important}.fw-bolder{font-weight:bolder!important}.lh-1{line-height:1!important}.lh-sm{line-height:1.25!important}.lh-base{line-height:1.5!important}.lh-lg{line-height:2!important}.text-start{text-align:left!important}.text-end{text-align:right!important}.text-center{text-align:center!important}.text-decoration-none{text-decoration:none!important}.text-decoration-underline{text-decoration:underline!important}.text-decoration-line-through{text-decoration:line-through!important}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-break{word-wrap:break-word!important;word-break:break-word!important}.text-primary{--bs-text-opacity:1;color:rgba(var(--bs-primary-rgb),var(--bs-text-opacity))!important}.text-secondary{--bs-text-opacity:1;color:rgba(var(--bs-secondary-rgb),var(--bs-text-opacity))!important}.text-success{--bs-text-opacity:1;color:rgba(var(--bs-success-rgb),var(--bs-text-opacity))!important}.text-info{--bs-text-opacity:1;color:rgba(var(--bs-info-rgb),var(--bs-text-opacity))!important}.text-warning{--bs-text-opacity:1;color:rgba(var(--bs-warning-rgb),var(--bs-text-opacity))!important}.text-danger{--bs-text-opacity:1;color:rgba(var(--bs-danger-rgb),var(--bs-text-opacity))!important}.text-light{--bs-text-opacity:1;color:rgba(var(--bs-light-rgb),var(--bs-text-opacity))!important}.text-dark{--bs-text-opacity:1;color:rgba(var(--bs-dark-rgb),var(--bs-text-opacity))!important}.text-black{--bs-text-opacity:1;color:rgba(var(--bs-black-rgb),var(--bs-text-opacity))!important}.text-white{--bs-text-opacity:1;color:rgba(var(--bs-white-rgb),var(--bs-text-opacity))!important}.text-body{--bs-text-opacity:1;color:rgba(var(--bs-body-color-rgb),var(--bs-text-opacity))!important}.text-muted,.td-page-meta__lastmod{--bs-text-opacity:1;color:#6c757d!important}.text-black-50{--bs-text-opacity:1;color:rgba(0,0,0,.5)!important}.text-white-50{--bs-text-opacity:1;color:rgba(255,255,255,.5)!important}.text-reset{--bs-text-opacity:1;color:inherit!important}.text-opacity-25{--bs-text-opacity:0.25}.text-opacity-50{--bs-text-opacity:0.5}.text-opacity-75{--bs-text-opacity:0.75}.text-opacity-100{--bs-text-opacity:1}.bg-primary{--bs-bg-opacity:1;background-color:rgba(var(--bs-primary-rgb),var(--bs-bg-opacity))!important}.bg-secondary{--bs-bg-opacity:1;background-color:rgba(var(--bs-secondary-rgb),var(--bs-bg-opacity))!important}.bg-success{--bs-bg-opacity:1;background-color:rgba(var(--bs-success-rgb),var(--bs-bg-opacity))!important}.bg-info{--bs-bg-opacity:1;background-color:rgba(var(--bs-info-rgb),var(--bs-bg-opacity))!important}.bg-warning{--bs-bg-opacity:1;background-color:rgba(var(--bs-warning-rgb),var(--bs-bg-opacity))!important}.bg-danger{--bs-bg-opacity:1;background-color:rgba(var(--bs-danger-rgb),var(--bs-bg-opacity))!important}.bg-light{--bs-bg-opacity:1;background-color:rgba(var(--bs-light-rgb),var(--bs-bg-opacity))!important}.bg-dark{--bs-bg-opacity:1;background-color:rgba(var(--bs-dark-rgb),var(--bs-bg-opacity))!important}.bg-black{--bs-bg-opacity:1;background-color:rgba(var(--bs-black-rgb),var(--bs-bg-opacity))!important}.bg-white{--bs-bg-opacity:1;background-color:rgba(var(--bs-white-rgb),var(--bs-bg-opacity))!important}.bg-body{--bs-bg-opacity:1;background-color:rgba(var(--bs-body-bg-rgb),var(--bs-bg-opacity))!important}.bg-transparent{--bs-bg-opacity:1;background-color:transparent!important}.bg-opacity-10{--bs-bg-opacity:0.1}.bg-opacity-25{--bs-bg-opacity:0.25}.bg-opacity-50{--bs-bg-opacity:0.5}.bg-opacity-75{--bs-bg-opacity:0.75}.bg-opacity-100{--bs-bg-opacity:1}.bg-gradient{background-image:var(--bs-gradient)!important}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;user-select:none!important}.pe-none{pointer-events:none!important}.pe-auto{pointer-events:auto!important}.rounded{border-radius:var(--bs-border-radius)!important}.rounded-0{border-radius:0!important}.rounded-1{border-radius:var(--bs-border-radius-sm)!important}.rounded-2{border-radius:var(--bs-border-radius)!important}.rounded-3{border-radius:var(--bs-border-radius-lg)!important}.rounded-4{border-radius:var(--bs-border-radius-xl)!important}.rounded-5{border-radius:var(--bs-border-radius-2xl)!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:var(--bs-border-radius-pill)!important}.rounded-top{border-top-left-radius:var(--bs-border-radius)!important;border-top-right-radius:var(--bs-border-radius)!important}.rounded-end{border-top-right-radius:var(--bs-border-radius)!important;border-bottom-right-radius:var(--bs-border-radius)!important}.rounded-bottom{border-bottom-right-radius:var(--bs-border-radius)!important;border-bottom-left-radius:var(--bs-border-radius)!important}.rounded-start{border-bottom-left-radius:var(--bs-border-radius)!important;border-top-left-radius:var(--bs-border-radius)!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media(min-width:576px){.float-sm-start{float:left!important}.float-sm-end{float:right!important}.float-sm-none{float:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-grid{display:grid!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:flex!important}.d-sm-inline-flex{display:inline-flex!important}.d-sm-none{display:none!important}.flex-sm-fill{flex:auto!important}.flex-sm-row{flex-direction:row!important}.flex-sm-column{flex-direction:column!important}.flex-sm-row-reverse{flex-direction:row-reverse!important}.flex-sm-column-reverse{flex-direction:column-reverse!important}.flex-sm-grow-0{flex-grow:0!important}.flex-sm-grow-1{flex-grow:1!important}.flex-sm-shrink-0{flex-shrink:0!important}.flex-sm-shrink-1{flex-shrink:1!important}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-sm-start{justify-content:flex-start!important}.justify-content-sm-end{justify-content:flex-end!important}.justify-content-sm-center{justify-content:center!important}.justify-content-sm-between{justify-content:space-between!important}.justify-content-sm-around{justify-content:space-around!important}.justify-content-sm-evenly{justify-content:space-evenly!important}.align-items-sm-start{align-items:flex-start!important}.align-items-sm-end{align-items:flex-end!important}.align-items-sm-center{align-items:center!important}.align-items-sm-baseline{align-items:baseline!important}.align-items-sm-stretch{align-items:stretch!important}.align-content-sm-start{align-content:flex-start!important}.align-content-sm-end{align-content:flex-end!important}.align-content-sm-center{align-content:center!important}.align-content-sm-between{align-content:space-between!important}.align-content-sm-around{align-content:space-around!important}.align-content-sm-stretch{align-content:stretch!important}.align-self-sm-auto{align-self:auto!important}.align-self-sm-start{align-self:flex-start!important}.align-self-sm-end{align-self:flex-end!important}.align-self-sm-center{align-self:center!important}.align-self-sm-baseline{align-self:baseline!important}.align-self-sm-stretch{align-self:stretch!important}.order-sm-first{order:-1!important}.order-sm-0{order:0!important}.order-sm-1{order:1!important}.order-sm-2{order:2!important}.order-sm-3{order:3!important}.order-sm-4{order:4!important}.order-sm-5{order:5!important}.order-sm-last{order:6!important}.m-sm-0{margin:0!important}.m-sm-1{margin:.25rem!important}.m-sm-2{margin:.5rem!important}.m-sm-3{margin:1rem!important}.m-sm-4{margin:1.5rem!important}.m-sm-5{margin:3rem!important}.m-sm-auto{margin:auto!important}.mx-sm-0{margin-right:0!important;margin-left:0!important}.mx-sm-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-sm-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-sm-3{margin-right:1rem!important;margin-left:1rem!important}.mx-sm-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-sm-5{margin-right:3rem!important;margin-left:3rem!important}.mx-sm-auto{margin-right:auto!important;margin-left:auto!important}.my-sm-0{margin-top:0!important;margin-bottom:0!important}.my-sm-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-sm-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-sm-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-sm-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-sm-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-sm-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-sm-0{margin-top:0!important}.mt-sm-1{margin-top:.25rem!important}.mt-sm-2{margin-top:.5rem!important}.mt-sm-3{margin-top:1rem!important}.mt-sm-4{margin-top:1.5rem!important}.mt-sm-5{margin-top:3rem!important}.mt-sm-auto{margin-top:auto!important}.me-sm-0{margin-right:0!important}.me-sm-1{margin-right:.25rem!important}.me-sm-2{margin-right:.5rem!important}.me-sm-3{margin-right:1rem!important}.me-sm-4{margin-right:1.5rem!important}.me-sm-5{margin-right:3rem!important}.me-sm-auto{margin-right:auto!important}.mb-sm-0{margin-bottom:0!important}.mb-sm-1{margin-bottom:.25rem!important}.mb-sm-2{margin-bottom:.5rem!important}.mb-sm-3{margin-bottom:1rem!important}.mb-sm-4{margin-bottom:1.5rem!important}.mb-sm-5{margin-bottom:3rem!important}.mb-sm-auto{margin-bottom:auto!important}.ms-sm-0{margin-left:0!important}.ms-sm-1{margin-left:.25rem!important}.ms-sm-2{margin-left:.5rem!important}.ms-sm-3{margin-left:1rem!important}.ms-sm-4{margin-left:1.5rem!important}.ms-sm-5{margin-left:3rem!important}.ms-sm-auto{margin-left:auto!important}.p-sm-0{padding:0!important}.p-sm-1{padding:.25rem!important}.p-sm-2{padding:.5rem!important}.p-sm-3{padding:1rem!important}.p-sm-4{padding:1.5rem!important}.p-sm-5{padding:3rem!important}.px-sm-0{padding-right:0!important;padding-left:0!important}.px-sm-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-sm-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-sm-3{padding-right:1rem!important;padding-left:1rem!important}.px-sm-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-sm-5{padding-right:3rem!important;padding-left:3rem!important}.py-sm-0{padding-top:0!important;padding-bottom:0!important}.py-sm-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-sm-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-sm-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-sm-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-sm-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-sm-0{padding-top:0!important}.pt-sm-1{padding-top:.25rem!important}.pt-sm-2{padding-top:.5rem!important}.pt-sm-3{padding-top:1rem!important}.pt-sm-4{padding-top:1.5rem!important}.pt-sm-5{padding-top:3rem!important}.pe-sm-0{padding-right:0!important}.pe-sm-1{padding-right:.25rem!important}.pe-sm-2{padding-right:.5rem!important}.pe-sm-3{padding-right:1rem!important}.pe-sm-4{padding-right:1.5rem!important}.pe-sm-5{padding-right:3rem!important}.pb-sm-0{padding-bottom:0!important}.pb-sm-1{padding-bottom:.25rem!important}.pb-sm-2{padding-bottom:.5rem!important}.pb-sm-3{padding-bottom:1rem!important}.pb-sm-4{padding-bottom:1.5rem!important}.pb-sm-5{padding-bottom:3rem!important}.ps-sm-0{padding-left:0!important}.ps-sm-1{padding-left:.25rem!important}.ps-sm-2{padding-left:.5rem!important}.ps-sm-3{padding-left:1rem!important}.ps-sm-4{padding-left:1.5rem!important}.ps-sm-5{padding-left:3rem!important}.gap-sm-0{gap:0!important}.gap-sm-1{gap:.25rem!important}.gap-sm-2{gap:.5rem!important}.gap-sm-3{gap:1rem!important}.gap-sm-4{gap:1.5rem!important}.gap-sm-5{gap:3rem!important}.text-sm-start{text-align:left!important}.text-sm-end{text-align:right!important}.text-sm-center{text-align:center!important}}@media(min-width:768px){.float-md-start{float:left!important}.float-md-end{float:right!important}.float-md-none{float:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-grid{display:grid!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:flex!important}.d-md-inline-flex{display:inline-flex!important}.d-md-none{display:none!important}.flex-md-fill{flex:auto!important}.flex-md-row{flex-direction:row!important}.flex-md-column{flex-direction:column!important}.flex-md-row-reverse{flex-direction:row-reverse!important}.flex-md-column-reverse{flex-direction:column-reverse!important}.flex-md-grow-0{flex-grow:0!important}.flex-md-grow-1{flex-grow:1!important}.flex-md-shrink-0{flex-shrink:0!important}.flex-md-shrink-1{flex-shrink:1!important}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-md-start{justify-content:flex-start!important}.justify-content-md-end{justify-content:flex-end!important}.justify-content-md-center{justify-content:center!important}.justify-content-md-between{justify-content:space-between!important}.justify-content-md-around{justify-content:space-around!important}.justify-content-md-evenly{justify-content:space-evenly!important}.align-items-md-start{align-items:flex-start!important}.align-items-md-end{align-items:flex-end!important}.align-items-md-center{align-items:center!important}.align-items-md-baseline{align-items:baseline!important}.align-items-md-stretch{align-items:stretch!important}.align-content-md-start{align-content:flex-start!important}.align-content-md-end{align-content:flex-end!important}.align-content-md-center{align-content:center!important}.align-content-md-between{align-content:space-between!important}.align-content-md-around{align-content:space-around!important}.align-content-md-stretch{align-content:stretch!important}.align-self-md-auto{align-self:auto!important}.align-self-md-start{align-self:flex-start!important}.align-self-md-end{align-self:flex-end!important}.align-self-md-center{align-self:center!important}.align-self-md-baseline{align-self:baseline!important}.align-self-md-stretch{align-self:stretch!important}.order-md-first{order:-1!important}.order-md-0{order:0!important}.order-md-1{order:1!important}.order-md-2{order:2!important}.order-md-3{order:3!important}.order-md-4{order:4!important}.order-md-5{order:5!important}.order-md-last{order:6!important}.m-md-0{margin:0!important}.m-md-1{margin:.25rem!important}.m-md-2{margin:.5rem!important}.m-md-3{margin:1rem!important}.m-md-4{margin:1.5rem!important}.m-md-5{margin:3rem!important}.m-md-auto{margin:auto!important}.mx-md-0{margin-right:0!important;margin-left:0!important}.mx-md-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-md-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-md-3{margin-right:1rem!important;margin-left:1rem!important}.mx-md-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-md-5{margin-right:3rem!important;margin-left:3rem!important}.mx-md-auto{margin-right:auto!important;margin-left:auto!important}.my-md-0{margin-top:0!important;margin-bottom:0!important}.my-md-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-md-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-md-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-md-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-md-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-md-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-md-0{margin-top:0!important}.mt-md-1{margin-top:.25rem!important}.mt-md-2{margin-top:.5rem!important}.mt-md-3{margin-top:1rem!important}.mt-md-4{margin-top:1.5rem!important}.mt-md-5{margin-top:3rem!important}.mt-md-auto{margin-top:auto!important}.me-md-0{margin-right:0!important}.me-md-1{margin-right:.25rem!important}.me-md-2{margin-right:.5rem!important}.me-md-3{margin-right:1rem!important}.me-md-4{margin-right:1.5rem!important}.me-md-5{margin-right:3rem!important}.me-md-auto{margin-right:auto!important}.mb-md-0{margin-bottom:0!important}.mb-md-1{margin-bottom:.25rem!important}.mb-md-2{margin-bottom:.5rem!important}.mb-md-3{margin-bottom:1rem!important}.mb-md-4{margin-bottom:1.5rem!important}.mb-md-5{margin-bottom:3rem!important}.mb-md-auto{margin-bottom:auto!important}.ms-md-0{margin-left:0!important}.ms-md-1{margin-left:.25rem!important}.ms-md-2{margin-left:.5rem!important}.ms-md-3{margin-left:1rem!important}.ms-md-4{margin-left:1.5rem!important}.ms-md-5{margin-left:3rem!important}.ms-md-auto{margin-left:auto!important}.p-md-0{padding:0!important}.p-md-1{padding:.25rem!important}.p-md-2{padding:.5rem!important}.p-md-3{padding:1rem!important}.p-md-4{padding:1.5rem!important}.p-md-5{padding:3rem!important}.px-md-0{padding-right:0!important;padding-left:0!important}.px-md-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-md-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-md-3{padding-right:1rem!important;padding-left:1rem!important}.px-md-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-md-5{padding-right:3rem!important;padding-left:3rem!important}.py-md-0{padding-top:0!important;padding-bottom:0!important}.py-md-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-md-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-md-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-md-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-md-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-md-0{padding-top:0!important}.pt-md-1{padding-top:.25rem!important}.pt-md-2{padding-top:.5rem!important}.pt-md-3{padding-top:1rem!important}.pt-md-4{padding-top:1.5rem!important}.pt-md-5{padding-top:3rem!important}.pe-md-0{padding-right:0!important}.pe-md-1{padding-right:.25rem!important}.pe-md-2{padding-right:.5rem!important}.pe-md-3{padding-right:1rem!important}.pe-md-4{padding-right:1.5rem!important}.pe-md-5{padding-right:3rem!important}.pb-md-0{padding-bottom:0!important}.pb-md-1{padding-bottom:.25rem!important}.pb-md-2{padding-bottom:.5rem!important}.pb-md-3{padding-bottom:1rem!important}.pb-md-4{padding-bottom:1.5rem!important}.pb-md-5{padding-bottom:3rem!important}.ps-md-0{padding-left:0!important}.ps-md-1{padding-left:.25rem!important}.ps-md-2{padding-left:.5rem!important}.ps-md-3{padding-left:1rem!important}.ps-md-4{padding-left:1.5rem!important}.ps-md-5{padding-left:3rem!important}.gap-md-0{gap:0!important}.gap-md-1{gap:.25rem!important}.gap-md-2{gap:.5rem!important}.gap-md-3{gap:1rem!important}.gap-md-4{gap:1.5rem!important}.gap-md-5{gap:3rem!important}.text-md-start{text-align:left!important}.text-md-end{text-align:right!important}.text-md-center{text-align:center!important}}@media(min-width:992px){.float-lg-start{float:left!important}.float-lg-end{float:right!important}.float-lg-none{float:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block,.td-blog .td-rss-button{display:block!important}.d-lg-grid{display:grid!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:flex!important}.d-lg-inline-flex{display:inline-flex!important}.d-lg-none{display:none!important}.flex-lg-fill{flex:auto!important}.flex-lg-row{flex-direction:row!important}.flex-lg-column{flex-direction:column!important}.flex-lg-row-reverse{flex-direction:row-reverse!important}.flex-lg-column-reverse{flex-direction:column-reverse!important}.flex-lg-grow-0{flex-grow:0!important}.flex-lg-grow-1{flex-grow:1!important}.flex-lg-shrink-0{flex-shrink:0!important}.flex-lg-shrink-1{flex-shrink:1!important}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-lg-start{justify-content:flex-start!important}.justify-content-lg-end{justify-content:flex-end!important}.justify-content-lg-center{justify-content:center!important}.justify-content-lg-between{justify-content:space-between!important}.justify-content-lg-around{justify-content:space-around!important}.justify-content-lg-evenly{justify-content:space-evenly!important}.align-items-lg-start{align-items:flex-start!important}.align-items-lg-end{align-items:flex-end!important}.align-items-lg-center{align-items:center!important}.align-items-lg-baseline{align-items:baseline!important}.align-items-lg-stretch{align-items:stretch!important}.align-content-lg-start{align-content:flex-start!important}.align-content-lg-end{align-content:flex-end!important}.align-content-lg-center{align-content:center!important}.align-content-lg-between{align-content:space-between!important}.align-content-lg-around{align-content:space-around!important}.align-content-lg-stretch{align-content:stretch!important}.align-self-lg-auto{align-self:auto!important}.align-self-lg-start{align-self:flex-start!important}.align-self-lg-end{align-self:flex-end!important}.align-self-lg-center{align-self:center!important}.align-self-lg-baseline{align-self:baseline!important}.align-self-lg-stretch{align-self:stretch!important}.order-lg-first{order:-1!important}.order-lg-0{order:0!important}.order-lg-1{order:1!important}.order-lg-2{order:2!important}.order-lg-3{order:3!important}.order-lg-4{order:4!important}.order-lg-5{order:5!important}.order-lg-last{order:6!important}.m-lg-0{margin:0!important}.m-lg-1{margin:.25rem!important}.m-lg-2{margin:.5rem!important}.m-lg-3{margin:1rem!important}.m-lg-4{margin:1.5rem!important}.m-lg-5{margin:3rem!important}.m-lg-auto{margin:auto!important}.mx-lg-0{margin-right:0!important;margin-left:0!important}.mx-lg-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-lg-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-lg-3{margin-right:1rem!important;margin-left:1rem!important}.mx-lg-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-lg-5{margin-right:3rem!important;margin-left:3rem!important}.mx-lg-auto{margin-right:auto!important;margin-left:auto!important}.my-lg-0{margin-top:0!important;margin-bottom:0!important}.my-lg-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-lg-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-lg-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-lg-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-lg-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-lg-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-lg-0{margin-top:0!important}.mt-lg-1{margin-top:.25rem!important}.mt-lg-2{margin-top:.5rem!important}.mt-lg-3{margin-top:1rem!important}.mt-lg-4{margin-top:1.5rem!important}.mt-lg-5{margin-top:3rem!important}.mt-lg-auto{margin-top:auto!important}.me-lg-0{margin-right:0!important}.me-lg-1{margin-right:.25rem!important}.me-lg-2{margin-right:.5rem!important}.me-lg-3{margin-right:1rem!important}.me-lg-4{margin-right:1.5rem!important}.me-lg-5{margin-right:3rem!important}.me-lg-auto{margin-right:auto!important}.mb-lg-0{margin-bottom:0!important}.mb-lg-1{margin-bottom:.25rem!important}.mb-lg-2{margin-bottom:.5rem!important}.mb-lg-3{margin-bottom:1rem!important}.mb-lg-4{margin-bottom:1.5rem!important}.mb-lg-5{margin-bottom:3rem!important}.mb-lg-auto{margin-bottom:auto!important}.ms-lg-0{margin-left:0!important}.ms-lg-1{margin-left:.25rem!important}.ms-lg-2{margin-left:.5rem!important}.ms-lg-3{margin-left:1rem!important}.ms-lg-4{margin-left:1.5rem!important}.ms-lg-5{margin-left:3rem!important}.ms-lg-auto{margin-left:auto!important}.p-lg-0{padding:0!important}.p-lg-1{padding:.25rem!important}.p-lg-2{padding:.5rem!important}.p-lg-3{padding:1rem!important}.p-lg-4{padding:1.5rem!important}.p-lg-5{padding:3rem!important}.px-lg-0{padding-right:0!important;padding-left:0!important}.px-lg-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-lg-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-lg-3{padding-right:1rem!important;padding-left:1rem!important}.px-lg-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-lg-5{padding-right:3rem!important;padding-left:3rem!important}.py-lg-0{padding-top:0!important;padding-bottom:0!important}.py-lg-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-lg-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-lg-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-lg-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-lg-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-lg-0{padding-top:0!important}.pt-lg-1{padding-top:.25rem!important}.pt-lg-2{padding-top:.5rem!important}.pt-lg-3{padding-top:1rem!important}.pt-lg-4{padding-top:1.5rem!important}.pt-lg-5{padding-top:3rem!important}.pe-lg-0{padding-right:0!important}.pe-lg-1{padding-right:.25rem!important}.pe-lg-2{padding-right:.5rem!important}.pe-lg-3{padding-right:1rem!important}.pe-lg-4{padding-right:1.5rem!important}.pe-lg-5{padding-right:3rem!important}.pb-lg-0{padding-bottom:0!important}.pb-lg-1{padding-bottom:.25rem!important}.pb-lg-2{padding-bottom:.5rem!important}.pb-lg-3{padding-bottom:1rem!important}.pb-lg-4{padding-bottom:1.5rem!important}.pb-lg-5{padding-bottom:3rem!important}.ps-lg-0{padding-left:0!important}.ps-lg-1{padding-left:.25rem!important}.ps-lg-2{padding-left:.5rem!important}.ps-lg-3{padding-left:1rem!important}.ps-lg-4{padding-left:1.5rem!important}.ps-lg-5{padding-left:3rem!important}.gap-lg-0{gap:0!important}.gap-lg-1{gap:.25rem!important}.gap-lg-2{gap:.5rem!important}.gap-lg-3{gap:1rem!important}.gap-lg-4{gap:1.5rem!important}.gap-lg-5{gap:3rem!important}.text-lg-start{text-align:left!important}.text-lg-end{text-align:right!important}.text-lg-center{text-align:center!important}}@media(min-width:1200px){.float-xl-start{float:left!important}.float-xl-end{float:right!important}.float-xl-none{float:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-grid{display:grid!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:flex!important}.d-xl-inline-flex{display:inline-flex!important}.d-xl-none{display:none!important}.flex-xl-fill{flex:auto!important}.flex-xl-row{flex-direction:row!important}.flex-xl-column{flex-direction:column!important}.flex-xl-row-reverse{flex-direction:row-reverse!important}.flex-xl-column-reverse{flex-direction:column-reverse!important}.flex-xl-grow-0{flex-grow:0!important}.flex-xl-grow-1{flex-grow:1!important}.flex-xl-shrink-0{flex-shrink:0!important}.flex-xl-shrink-1{flex-shrink:1!important}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-xl-start{justify-content:flex-start!important}.justify-content-xl-end{justify-content:flex-end!important}.justify-content-xl-center{justify-content:center!important}.justify-content-xl-between{justify-content:space-between!important}.justify-content-xl-around{justify-content:space-around!important}.justify-content-xl-evenly{justify-content:space-evenly!important}.align-items-xl-start{align-items:flex-start!important}.align-items-xl-end{align-items:flex-end!important}.align-items-xl-center{align-items:center!important}.align-items-xl-baseline{align-items:baseline!important}.align-items-xl-stretch{align-items:stretch!important}.align-content-xl-start{align-content:flex-start!important}.align-content-xl-end{align-content:flex-end!important}.align-content-xl-center{align-content:center!important}.align-content-xl-between{align-content:space-between!important}.align-content-xl-around{align-content:space-around!important}.align-content-xl-stretch{align-content:stretch!important}.align-self-xl-auto{align-self:auto!important}.align-self-xl-start{align-self:flex-start!important}.align-self-xl-end{align-self:flex-end!important}.align-self-xl-center{align-self:center!important}.align-self-xl-baseline{align-self:baseline!important}.align-self-xl-stretch{align-self:stretch!important}.order-xl-first{order:-1!important}.order-xl-0{order:0!important}.order-xl-1{order:1!important}.order-xl-2{order:2!important}.order-xl-3{order:3!important}.order-xl-4{order:4!important}.order-xl-5{order:5!important}.order-xl-last{order:6!important}.m-xl-0{margin:0!important}.m-xl-1{margin:.25rem!important}.m-xl-2{margin:.5rem!important}.m-xl-3{margin:1rem!important}.m-xl-4{margin:1.5rem!important}.m-xl-5{margin:3rem!important}.m-xl-auto{margin:auto!important}.mx-xl-0{margin-right:0!important;margin-left:0!important}.mx-xl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xl-5{margin-right:3rem!important;margin-left:3rem!important}.mx-xl-auto{margin-right:auto!important;margin-left:auto!important}.my-xl-0{margin-top:0!important;margin-bottom:0!important}.my-xl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xl-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-xl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xl-0{margin-top:0!important}.mt-xl-1{margin-top:.25rem!important}.mt-xl-2{margin-top:.5rem!important}.mt-xl-3{margin-top:1rem!important}.mt-xl-4{margin-top:1.5rem!important}.mt-xl-5{margin-top:3rem!important}.mt-xl-auto{margin-top:auto!important}.me-xl-0{margin-right:0!important}.me-xl-1{margin-right:.25rem!important}.me-xl-2{margin-right:.5rem!important}.me-xl-3{margin-right:1rem!important}.me-xl-4{margin-right:1.5rem!important}.me-xl-5{margin-right:3rem!important}.me-xl-auto{margin-right:auto!important}.mb-xl-0{margin-bottom:0!important}.mb-xl-1{margin-bottom:.25rem!important}.mb-xl-2{margin-bottom:.5rem!important}.mb-xl-3{margin-bottom:1rem!important}.mb-xl-4{margin-bottom:1.5rem!important}.mb-xl-5{margin-bottom:3rem!important}.mb-xl-auto{margin-bottom:auto!important}.ms-xl-0{margin-left:0!important}.ms-xl-1{margin-left:.25rem!important}.ms-xl-2{margin-left:.5rem!important}.ms-xl-3{margin-left:1rem!important}.ms-xl-4{margin-left:1.5rem!important}.ms-xl-5{margin-left:3rem!important}.ms-xl-auto{margin-left:auto!important}.p-xl-0{padding:0!important}.p-xl-1{padding:.25rem!important}.p-xl-2{padding:.5rem!important}.p-xl-3{padding:1rem!important}.p-xl-4{padding:1.5rem!important}.p-xl-5{padding:3rem!important}.px-xl-0{padding-right:0!important;padding-left:0!important}.px-xl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xl-0{padding-top:0!important;padding-bottom:0!important}.py-xl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xl-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-xl-0{padding-top:0!important}.pt-xl-1{padding-top:.25rem!important}.pt-xl-2{padding-top:.5rem!important}.pt-xl-3{padding-top:1rem!important}.pt-xl-4{padding-top:1.5rem!important}.pt-xl-5{padding-top:3rem!important}.pe-xl-0{padding-right:0!important}.pe-xl-1{padding-right:.25rem!important}.pe-xl-2{padding-right:.5rem!important}.pe-xl-3{padding-right:1rem!important}.pe-xl-4{padding-right:1.5rem!important}.pe-xl-5{padding-right:3rem!important}.pb-xl-0{padding-bottom:0!important}.pb-xl-1{padding-bottom:.25rem!important}.pb-xl-2{padding-bottom:.5rem!important}.pb-xl-3{padding-bottom:1rem!important}.pb-xl-4{padding-bottom:1.5rem!important}.pb-xl-5{padding-bottom:3rem!important}.ps-xl-0{padding-left:0!important}.ps-xl-1{padding-left:.25rem!important}.ps-xl-2{padding-left:.5rem!important}.ps-xl-3{padding-left:1rem!important}.ps-xl-4{padding-left:1.5rem!important}.ps-xl-5{padding-left:3rem!important}.gap-xl-0{gap:0!important}.gap-xl-1{gap:.25rem!important}.gap-xl-2{gap:.5rem!important}.gap-xl-3{gap:1rem!important}.gap-xl-4{gap:1.5rem!important}.gap-xl-5{gap:3rem!important}.text-xl-start{text-align:left!important}.text-xl-end{text-align:right!important}.text-xl-center{text-align:center!important}}@media(min-width:1400px){.float-xxl-start{float:left!important}.float-xxl-end{float:right!important}.float-xxl-none{float:none!important}.d-xxl-inline{display:inline!important}.d-xxl-inline-block{display:inline-block!important}.d-xxl-block{display:block!important}.d-xxl-grid{display:grid!important}.d-xxl-table{display:table!important}.d-xxl-table-row{display:table-row!important}.d-xxl-table-cell{display:table-cell!important}.d-xxl-flex{display:flex!important}.d-xxl-inline-flex{display:inline-flex!important}.d-xxl-none{display:none!important}.flex-xxl-fill{flex:auto!important}.flex-xxl-row{flex-direction:row!important}.flex-xxl-column{flex-direction:column!important}.flex-xxl-row-reverse{flex-direction:row-reverse!important}.flex-xxl-column-reverse{flex-direction:column-reverse!important}.flex-xxl-grow-0{flex-grow:0!important}.flex-xxl-grow-1{flex-grow:1!important}.flex-xxl-shrink-0{flex-shrink:0!important}.flex-xxl-shrink-1{flex-shrink:1!important}.flex-xxl-wrap{flex-wrap:wrap!important}.flex-xxl-nowrap{flex-wrap:nowrap!important}.flex-xxl-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-xxl-start{justify-content:flex-start!important}.justify-content-xxl-end{justify-content:flex-end!important}.justify-content-xxl-center{justify-content:center!important}.justify-content-xxl-between{justify-content:space-between!important}.justify-content-xxl-around{justify-content:space-around!important}.justify-content-xxl-evenly{justify-content:space-evenly!important}.align-items-xxl-start{align-items:flex-start!important}.align-items-xxl-end{align-items:flex-end!important}.align-items-xxl-center{align-items:center!important}.align-items-xxl-baseline{align-items:baseline!important}.align-items-xxl-stretch{align-items:stretch!important}.align-content-xxl-start{align-content:flex-start!important}.align-content-xxl-end{align-content:flex-end!important}.align-content-xxl-center{align-content:center!important}.align-content-xxl-between{align-content:space-between!important}.align-content-xxl-around{align-content:space-around!important}.align-content-xxl-stretch{align-content:stretch!important}.align-self-xxl-auto{align-self:auto!important}.align-self-xxl-start{align-self:flex-start!important}.align-self-xxl-end{align-self:flex-end!important}.align-self-xxl-center{align-self:center!important}.align-self-xxl-baseline{align-self:baseline!important}.align-self-xxl-stretch{align-self:stretch!important}.order-xxl-first{order:-1!important}.order-xxl-0{order:0!important}.order-xxl-1{order:1!important}.order-xxl-2{order:2!important}.order-xxl-3{order:3!important}.order-xxl-4{order:4!important}.order-xxl-5{order:5!important}.order-xxl-last{order:6!important}.m-xxl-0{margin:0!important}.m-xxl-1{margin:.25rem!important}.m-xxl-2{margin:.5rem!important}.m-xxl-3{margin:1rem!important}.m-xxl-4{margin:1.5rem!important}.m-xxl-5{margin:3rem!important}.m-xxl-auto{margin:auto!important}.mx-xxl-0{margin-right:0!important;margin-left:0!important}.mx-xxl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xxl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xxl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xxl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xxl-5{margin-right:3rem!important;margin-left:3rem!important}.mx-xxl-auto{margin-right:auto!important;margin-left:auto!important}.my-xxl-0{margin-top:0!important;margin-bottom:0!important}.my-xxl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xxl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xxl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xxl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xxl-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-xxl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xxl-0{margin-top:0!important}.mt-xxl-1{margin-top:.25rem!important}.mt-xxl-2{margin-top:.5rem!important}.mt-xxl-3{margin-top:1rem!important}.mt-xxl-4{margin-top:1.5rem!important}.mt-xxl-5{margin-top:3rem!important}.mt-xxl-auto{margin-top:auto!important}.me-xxl-0{margin-right:0!important}.me-xxl-1{margin-right:.25rem!important}.me-xxl-2{margin-right:.5rem!important}.me-xxl-3{margin-right:1rem!important}.me-xxl-4{margin-right:1.5rem!important}.me-xxl-5{margin-right:3rem!important}.me-xxl-auto{margin-right:auto!important}.mb-xxl-0{margin-bottom:0!important}.mb-xxl-1{margin-bottom:.25rem!important}.mb-xxl-2{margin-bottom:.5rem!important}.mb-xxl-3{margin-bottom:1rem!important}.mb-xxl-4{margin-bottom:1.5rem!important}.mb-xxl-5{margin-bottom:3rem!important}.mb-xxl-auto{margin-bottom:auto!important}.ms-xxl-0{margin-left:0!important}.ms-xxl-1{margin-left:.25rem!important}.ms-xxl-2{margin-left:.5rem!important}.ms-xxl-3{margin-left:1rem!important}.ms-xxl-4{margin-left:1.5rem!important}.ms-xxl-5{margin-left:3rem!important}.ms-xxl-auto{margin-left:auto!important}.p-xxl-0{padding:0!important}.p-xxl-1{padding:.25rem!important}.p-xxl-2{padding:.5rem!important}.p-xxl-3{padding:1rem!important}.p-xxl-4{padding:1.5rem!important}.p-xxl-5{padding:3rem!important}.px-xxl-0{padding-right:0!important;padding-left:0!important}.px-xxl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xxl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xxl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xxl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xxl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xxl-0{padding-top:0!important;padding-bottom:0!important}.py-xxl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xxl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xxl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xxl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xxl-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-xxl-0{padding-top:0!important}.pt-xxl-1{padding-top:.25rem!important}.pt-xxl-2{padding-top:.5rem!important}.pt-xxl-3{padding-top:1rem!important}.pt-xxl-4{padding-top:1.5rem!important}.pt-xxl-5{padding-top:3rem!important}.pe-xxl-0{padding-right:0!important}.pe-xxl-1{padding-right:.25rem!important}.pe-xxl-2{padding-right:.5rem!important}.pe-xxl-3{padding-right:1rem!important}.pe-xxl-4{padding-right:1.5rem!important}.pe-xxl-5{padding-right:3rem!important}.pb-xxl-0{padding-bottom:0!important}.pb-xxl-1{padding-bottom:.25rem!important}.pb-xxl-2{padding-bottom:.5rem!important}.pb-xxl-3{padding-bottom:1rem!important}.pb-xxl-4{padding-bottom:1.5rem!important}.pb-xxl-5{padding-bottom:3rem!important}.ps-xxl-0{padding-left:0!important}.ps-xxl-1{padding-left:.25rem!important}.ps-xxl-2{padding-left:.5rem!important}.ps-xxl-3{padding-left:1rem!important}.ps-xxl-4{padding-left:1.5rem!important}.ps-xxl-5{padding-left:3rem!important}.gap-xxl-0{gap:0!important}.gap-xxl-1{gap:.25rem!important}.gap-xxl-2{gap:.5rem!important}.gap-xxl-3{gap:1rem!important}.gap-xxl-4{gap:1.5rem!important}.gap-xxl-5{gap:3rem!important}.text-xxl-start{text-align:left!important}.text-xxl-end{text-align:right!important}.text-xxl-center{text-align:center!important}}@media(min-width:1200px){.fs-1{font-size:2.5rem!important}.fs-2{font-size:2rem!important}.fs-3{font-size:1.5rem!important}.fs-4{font-size:1.35rem!important}}@media print{.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-grid{display:grid!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}.d-print-none{display:none!important}}/*!* Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com +* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) +* Copyright 2023 Fonticons, Inc.*/.fa,.td-search__icon:before{font-family:var(--fa-style-family,"Font Awesome 6 Free");font-weight:var(--fa-style,900)}.fa,.td-search__icon:before,.fa-classic,.fa-sharp,.fas,.td-offline-search-results__close-button:after,.fa-solid,.far,.fa-regular,.fab,.fa-brands{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:var(--fa-display,inline-block);font-style:normal;font-variant:normal;line-height:1;text-rendering:auto}.fas,.td-offline-search-results__close-button:after,.fa-classic,.fa-solid,.far,.fa-regular{font-family:'font awesome 6 free'}.fab,.fa-brands{font-family:'font awesome 6 brands'}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-2xs{font-size:.625em;line-height:.1em;vertical-align:.225em}.fa-xs{font-size:.75em;line-height:.08333333em;vertical-align:.125em}.fa-sm{font-size:.875em;line-height:.07142857em;vertical-align:.05357143em}.fa-lg{font-size:1.25em;line-height:.05em;vertical-align:-.075em}.fa-xl{font-size:1.5em;line-height:.04166667em;vertical-align:-.125em}.fa-2xl{font-size:2em;line-height:.03125em;vertical-align:-.1875em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:var(--fa-li-margin,2.5em);padding-left:0}.fa-ul>li{position:relative}.fa-li{left:calc(var(--fa-li-width,2em) * -1);position:absolute;text-align:center;width:var(--fa-li-width,2em);line-height:inherit}.fa-border{border-color:var(--fa-border-color,#eee);border-radius:var(--fa-border-radius,.1em);border-style:var(--fa-border-style,solid);border-width:var(--fa-border-width,.08em);padding:var(--fa-border-padding,.2em .25em .15em)}.fa-pull-left{float:left;margin-right:var(--fa-pull-margin,.3em)}.fa-pull-right{float:right;margin-left:var(--fa-pull-margin,.3em)}.fa-beat{animation-name:fa-beat;animation-delay:var(--fa-animation-delay,0s);animation-direction:var(--fa-animation-direction,normal);animation-duration:var(--fa-animation-duration,1s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,ease-in-out)}.fa-bounce{animation-name:fa-bounce;animation-delay:var(--fa-animation-delay,0s);animation-direction:var(--fa-animation-direction,normal);animation-duration:var(--fa-animation-duration,1s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,cubic-bezier(.28,.84,.42,1))}.fa-fade{animation-name:fa-fade;animation-delay:var(--fa-animation-delay,0s);animation-direction:var(--fa-animation-direction,normal);animation-duration:var(--fa-animation-duration,1s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1))}.fa-beat-fade{animation-name:fa-beat-fade;animation-delay:var(--fa-animation-delay,0s);animation-direction:var(--fa-animation-direction,normal);animation-duration:var(--fa-animation-duration,1s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1))}.fa-flip{animation-name:fa-flip;animation-delay:var(--fa-animation-delay,0s);animation-direction:var(--fa-animation-direction,normal);animation-duration:var(--fa-animation-duration,1s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,ease-in-out)}.fa-shake{animation-name:fa-shake;animation-delay:var(--fa-animation-delay,0s);animation-direction:var(--fa-animation-direction,normal);animation-duration:var(--fa-animation-duration,1s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,linear)}.fa-spin{animation-name:fa-spin;animation-delay:var(--fa-animation-delay,0s);animation-direction:var(--fa-animation-direction,normal);animation-duration:var(--fa-animation-duration,2s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,linear)}.fa-spin-reverse{--fa-animation-direction:reverse}.fa-pulse,.fa-spin-pulse{animation-name:fa-spin;animation-direction:var(--fa-animation-direction,normal);animation-duration:var(--fa-animation-duration,1s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,steps(8))}@media(prefers-reduced-motion:reduce){.fa-beat,.fa-bounce,.fa-fade,.fa-beat-fade,.fa-flip,.fa-pulse,.fa-shake,.fa-spin,.fa-spin-pulse{animation-delay:-1ms;animation-duration:1ms;animation-iteration-count:1;transition-delay:0s;transition-duration:0s}}@keyframes fa-beat{0%,90%{transform:scale(1)}45%{transform:scale(var(--fa-beat-scale,1.25))}}@keyframes fa-bounce{0%{transform:scale(1,1)translateY(0)}10%{transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9))translateY(0)}30%{transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1))translateY(var(--fa-bounce-height,-.5em))}50%{transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95))translateY(0)}57%{transform:scale(1,1)translateY(var(--fa-bounce-rebound,-.125em))}64%{transform:scale(1,1)translateY(0)}100%{transform:scale(1,1)translateY(0)}}@keyframes fa-fade{50%{opacity:var(--fa-fade-opacity,.4)}}@keyframes fa-beat-fade{0%,100%{opacity:var(--fa-beat-fade-opacity,.4);transform:scale(1)}50%{opacity:1;transform:scale(var(--fa-beat-fade-scale,1.125))}}@keyframes fa-flip{50%{transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg))}}@keyframes fa-shake{0%{transform:rotate(-15deg)}4%{transform:rotate(15deg)}8%,24%{transform:rotate(-18deg)}12%,28%{transform:rotate(18deg)}16%{transform:rotate(-22deg)}20%{transform:rotate(22deg)}32%{transform:rotate(-12deg)}36%{transform:rotate(12deg)}40%,100%{transform:rotate(0)}}@keyframes fa-spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}.fa-rotate-90{transform:rotate(90deg)}.fa-rotate-180{transform:rotate(180deg)}.fa-rotate-270{transform:rotate(270deg)}.fa-flip-horizontal{transform:scale(-1,1)}.fa-flip-vertical{transform:scale(1,-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{transform:scale(-1,-1)}.fa-rotate-by{transform:rotate(var(--fa-rotate-angle,none))}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%;z-index:var(--fa-stack-z-index,auto)}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:var(--fa-inverse,#fff)}.fa-0::before{content:"\30"}.fa-1::before{content:"\31"}.fa-2::before{content:"\32"}.fa-3::before{content:"\33"}.fa-4::before{content:"\34"}.fa-5::before{content:"\35"}.fa-6::before{content:"\36"}.fa-7::before{content:"\37"}.fa-8::before{content:"\38"}.fa-9::before{content:"\39"}.fa-fill-drip::before{content:"\f576"}.fa-arrows-to-circle::before{content:"\e4bd"}.fa-circle-chevron-right::before{content:"\f138"}.fa-chevron-circle-right::before{content:"\f138"}.fa-at::before{content:"\40"}.fa-trash-can::before{content:"\f2ed"}.fa-trash-alt::before{content:"\f2ed"}.fa-text-height::before{content:"\f034"}.fa-user-xmark::before{content:"\f235"}.fa-user-times::before{content:"\f235"}.fa-stethoscope::before{content:"\f0f1"}.fa-message::before{content:"\f27a"}.fa-comment-alt::before{content:"\f27a"}.fa-info::before{content:"\f129"}.fa-down-left-and-up-right-to-center::before{content:"\f422"}.fa-compress-alt::before{content:"\f422"}.fa-explosion::before{content:"\e4e9"}.fa-file-lines::before{content:"\f15c"}.fa-file-alt::before{content:"\f15c"}.fa-file-text::before{content:"\f15c"}.fa-wave-square::before{content:"\f83e"}.fa-ring::before{content:"\f70b"}.fa-building-un::before{content:"\e4d9"}.fa-dice-three::before{content:"\f527"}.fa-calendar-days::before{content:"\f073"}.fa-calendar-alt::before{content:"\f073"}.fa-anchor-circle-check::before{content:"\e4aa"}.fa-building-circle-arrow-right::before{content:"\e4d1"}.fa-volleyball::before{content:"\f45f"}.fa-volleyball-ball::before{content:"\f45f"}.fa-arrows-up-to-line::before{content:"\e4c2"}.fa-sort-down::before{content:"\f0dd"}.fa-sort-desc::before{content:"\f0dd"}.fa-circle-minus::before{content:"\f056"}.fa-minus-circle::before{content:"\f056"}.fa-door-open::before{content:"\f52b"}.fa-right-from-bracket::before{content:"\f2f5"}.fa-sign-out-alt::before{content:"\f2f5"}.fa-atom::before{content:"\f5d2"}.fa-soap::before{content:"\e06e"}.fa-icons::before{content:"\f86d"}.fa-heart-music-camera-bolt::before{content:"\f86d"}.fa-microphone-lines-slash::before{content:"\f539"}.fa-microphone-alt-slash::before{content:"\f539"}.fa-bridge-circle-check::before{content:"\e4c9"}.fa-pump-medical::before{content:"\e06a"}.fa-fingerprint::before{content:"\f577"}.fa-hand-point-right::before{content:"\f0a4"}.fa-magnifying-glass-location::before{content:"\f689"}.fa-search-location::before{content:"\f689"}.fa-forward-step::before{content:"\f051"}.fa-step-forward::before{content:"\f051"}.fa-face-smile-beam::before{content:"\f5b8"}.fa-smile-beam::before{content:"\f5b8"}.fa-flag-checkered::before{content:"\f11e"}.fa-football::before{content:"\f44e"}.fa-football-ball::before{content:"\f44e"}.fa-school-circle-exclamation::before{content:"\e56c"}.fa-crop::before{content:"\f125"}.fa-angles-down::before{content:"\f103"}.fa-angle-double-down::before{content:"\f103"}.fa-users-rectangle::before{content:"\e594"}.fa-people-roof::before{content:"\e537"}.fa-people-line::before{content:"\e534"}.fa-beer-mug-empty::before{content:"\f0fc"}.fa-beer::before{content:"\f0fc"}.fa-diagram-predecessor::before{content:"\e477"}.fa-arrow-up-long::before{content:"\f176"}.fa-long-arrow-up::before{content:"\f176"}.fa-fire-flame-simple::before{content:"\f46a"}.fa-burn::before{content:"\f46a"}.fa-person::before{content:"\f183"}.fa-male::before{content:"\f183"}.fa-laptop::before{content:"\f109"}.fa-file-csv::before{content:"\f6dd"}.fa-menorah::before{content:"\f676"}.fa-truck-plane::before{content:"\e58f"}.fa-record-vinyl::before{content:"\f8d9"}.fa-face-grin-stars::before{content:"\f587"}.fa-grin-stars::before{content:"\f587"}.fa-bong::before{content:"\f55c"}.fa-spaghetti-monster-flying::before{content:"\f67b"}.fa-pastafarianism::before{content:"\f67b"}.fa-arrow-down-up-across-line::before{content:"\e4af"}.fa-spoon::before{content:"\f2e5"}.fa-utensil-spoon::before{content:"\f2e5"}.fa-jar-wheat::before{content:"\e517"}.fa-envelopes-bulk::before{content:"\f674"}.fa-mail-bulk::before{content:"\f674"}.fa-file-circle-exclamation::before{content:"\e4eb"}.fa-circle-h::before{content:"\f47e"}.fa-hospital-symbol::before{content:"\f47e"}.fa-pager::before{content:"\f815"}.fa-address-book::before{content:"\f2b9"}.fa-contact-book::before{content:"\f2b9"}.fa-strikethrough::before{content:"\f0cc"}.fa-k::before{content:"\4b"}.fa-landmark-flag::before{content:"\e51c"}.fa-pencil::before{content:"\f303"}.fa-pencil-alt::before{content:"\f303"}.fa-backward::before{content:"\f04a"}.fa-caret-right::before{content:"\f0da"}.fa-comments::before{content:"\f086"}.fa-paste::before{content:"\f0ea"}.fa-file-clipboard::before{content:"\f0ea"}.fa-code-pull-request::before{content:"\e13c"}.fa-clipboard-list::before{content:"\f46d"}.fa-truck-ramp-box::before{content:"\f4de"}.fa-truck-loading::before{content:"\f4de"}.fa-user-check::before{content:"\f4fc"}.fa-vial-virus::before{content:"\e597"}.fa-sheet-plastic::before{content:"\e571"}.fa-blog::before{content:"\f781"}.fa-user-ninja::before{content:"\f504"}.fa-person-arrow-up-from-line::before{content:"\e539"}.fa-scroll-torah::before{content:"\f6a0"}.fa-torah::before{content:"\f6a0"}.fa-broom-ball::before{content:"\f458"}.fa-quidditch::before{content:"\f458"}.fa-quidditch-broom-ball::before{content:"\f458"}.fa-toggle-off::before{content:"\f204"}.fa-box-archive::before{content:"\f187"}.fa-archive::before{content:"\f187"}.fa-person-drowning::before{content:"\e545"}.fa-arrow-down-9-1::before{content:"\f886"}.fa-sort-numeric-desc::before{content:"\f886"}.fa-sort-numeric-down-alt::before{content:"\f886"}.fa-face-grin-tongue-squint::before{content:"\f58a"}.fa-grin-tongue-squint::before{content:"\f58a"}.fa-spray-can::before{content:"\f5bd"}.fa-truck-monster::before{content:"\f63b"}.fa-w::before{content:"\57"}.fa-earth-africa::before{content:"\f57c"}.fa-globe-africa::before{content:"\f57c"}.fa-rainbow::before{content:"\f75b"}.fa-circle-notch::before{content:"\f1ce"}.fa-tablet-screen-button::before{content:"\f3fa"}.fa-tablet-alt::before{content:"\f3fa"}.fa-paw::before{content:"\f1b0"}.fa-cloud::before{content:"\f0c2"}.fa-trowel-bricks::before{content:"\e58a"}.fa-face-flushed::before{content:"\f579"}.fa-flushed::before{content:"\f579"}.fa-hospital-user::before{content:"\f80d"}.fa-tent-arrow-left-right::before{content:"\e57f"}.fa-gavel::before{content:"\f0e3"}.fa-legal::before{content:"\f0e3"}.fa-binoculars::before{content:"\f1e5"}.fa-microphone-slash::before{content:"\f131"}.fa-box-tissue::before{content:"\e05b"}.fa-motorcycle::before{content:"\f21c"}.fa-bell-concierge::before{content:"\f562"}.fa-concierge-bell::before{content:"\f562"}.fa-pen-ruler::before{content:"\f5ae"}.fa-pencil-ruler::before{content:"\f5ae"}.fa-people-arrows::before{content:"\e068"}.fa-people-arrows-left-right::before{content:"\e068"}.fa-mars-and-venus-burst::before{content:"\e523"}.fa-square-caret-right::before{content:"\f152"}.fa-caret-square-right::before{content:"\f152"}.fa-scissors::before{content:"\f0c4"}.fa-cut::before{content:"\f0c4"}.fa-sun-plant-wilt::before{content:"\e57a"}.fa-toilets-portable::before{content:"\e584"}.fa-hockey-puck::before{content:"\f453"}.fa-table::before{content:"\f0ce"}.fa-magnifying-glass-arrow-right::before{content:"\e521"}.fa-tachograph-digital::before{content:"\f566"}.fa-digital-tachograph::before{content:"\f566"}.fa-users-slash::before{content:"\e073"}.fa-clover::before{content:"\e139"}.fa-reply::before{content:"\f3e5"}.fa-mail-reply::before{content:"\f3e5"}.fa-star-and-crescent::before{content:"\f699"}.fa-house-fire::before{content:"\e50c"}.fa-square-minus::before{content:"\f146"}.fa-minus-square::before{content:"\f146"}.fa-helicopter::before{content:"\f533"}.fa-compass::before{content:"\f14e"}.fa-square-caret-down::before{content:"\f150"}.fa-caret-square-down::before{content:"\f150"}.fa-file-circle-question::before{content:"\e4ef"}.fa-laptop-code::before{content:"\f5fc"}.fa-swatchbook::before{content:"\f5c3"}.fa-prescription-bottle::before{content:"\f485"}.fa-bars::before{content:"\f0c9"}.fa-navicon::before{content:"\f0c9"}.fa-people-group::before{content:"\e533"}.fa-hourglass-end::before{content:"\f253"}.fa-hourglass-3::before{content:"\f253"}.fa-heart-crack::before{content:"\f7a9"}.fa-heart-broken::before{content:"\f7a9"}.fa-square-up-right::before{content:"\f360"}.fa-external-link-square-alt::before{content:"\f360"}.fa-face-kiss-beam::before{content:"\f597"}.fa-kiss-beam::before{content:"\f597"}.fa-film::before{content:"\f008"}.fa-ruler-horizontal::before{content:"\f547"}.fa-people-robbery::before{content:"\e536"}.fa-lightbulb::before{content:"\f0eb"}.fa-caret-left::before{content:"\f0d9"}.fa-circle-exclamation::before{content:"\f06a"}.fa-exclamation-circle::before{content:"\f06a"}.fa-school-circle-xmark::before{content:"\e56d"}.fa-arrow-right-from-bracket::before{content:"\f08b"}.fa-sign-out::before{content:"\f08b"}.fa-circle-chevron-down::before{content:"\f13a"}.fa-chevron-circle-down::before{content:"\f13a"}.fa-unlock-keyhole::before{content:"\f13e"}.fa-unlock-alt::before{content:"\f13e"}.fa-cloud-showers-heavy::before{content:"\f740"}.fa-headphones-simple::before{content:"\f58f"}.fa-headphones-alt::before{content:"\f58f"}.fa-sitemap::before{content:"\f0e8"}.fa-circle-dollar-to-slot::before{content:"\f4b9"}.fa-donate::before{content:"\f4b9"}.fa-memory::before{content:"\f538"}.fa-road-spikes::before{content:"\e568"}.fa-fire-burner::before{content:"\e4f1"}.fa-flag::before{content:"\f024"}.fa-hanukiah::before{content:"\f6e6"}.fa-feather::before{content:"\f52d"}.fa-volume-low::before{content:"\f027"}.fa-volume-down::before{content:"\f027"}.fa-comment-slash::before{content:"\f4b3"}.fa-cloud-sun-rain::before{content:"\f743"}.fa-compress::before{content:"\f066"}.fa-wheat-awn::before{content:"\e2cd"}.fa-wheat-alt::before{content:"\e2cd"}.fa-ankh::before{content:"\f644"}.fa-hands-holding-child::before{content:"\e4fa"}.fa-asterisk::before{content:"\2a"}.fa-square-check::before{content:"\f14a"}.fa-check-square::before{content:"\f14a"}.fa-peseta-sign::before{content:"\e221"}.fa-heading::before{content:"\f1dc"}.fa-header::before{content:"\f1dc"}.fa-ghost::before{content:"\f6e2"}.fa-list::before{content:"\f03a"}.fa-list-squares::before{content:"\f03a"}.fa-square-phone-flip::before{content:"\f87b"}.fa-phone-square-alt::before{content:"\f87b"}.fa-cart-plus::before{content:"\f217"}.fa-gamepad::before{content:"\f11b"}.fa-circle-dot::before{content:"\f192"}.fa-dot-circle::before{content:"\f192"}.fa-face-dizzy::before{content:"\f567"}.fa-dizzy::before{content:"\f567"}.fa-egg::before{content:"\f7fb"}.fa-house-medical-circle-xmark::before{content:"\e513"}.fa-campground::before{content:"\f6bb"}.fa-folder-plus::before{content:"\f65e"}.fa-futbol::before{content:"\f1e3"}.fa-futbol-ball::before{content:"\f1e3"}.fa-soccer-ball::before{content:"\f1e3"}.fa-paintbrush::before{content:"\f1fc"}.fa-paint-brush::before{content:"\f1fc"}.fa-lock::before{content:"\f023"}.fa-gas-pump::before{content:"\f52f"}.fa-hot-tub-person::before{content:"\f593"}.fa-hot-tub::before{content:"\f593"}.fa-map-location::before{content:"\f59f"}.fa-map-marked::before{content:"\f59f"}.fa-house-flood-water::before{content:"\e50e"}.fa-tree::before{content:"\f1bb"}.fa-bridge-lock::before{content:"\e4cc"}.fa-sack-dollar::before{content:"\f81d"}.fa-pen-to-square::before{content:"\f044"}.fa-edit::before{content:"\f044"}.fa-car-side::before{content:"\f5e4"}.fa-share-nodes::before{content:"\f1e0"}.fa-share-alt::before{content:"\f1e0"}.fa-heart-circle-minus::before{content:"\e4ff"}.fa-hourglass-half::before{content:"\f252"}.fa-hourglass-2::before{content:"\f252"}.fa-microscope::before{content:"\f610"}.fa-sink::before{content:"\e06d"}.fa-bag-shopping::before{content:"\f290"}.fa-shopping-bag::before{content:"\f290"}.fa-arrow-down-z-a::before{content:"\f881"}.fa-sort-alpha-desc::before{content:"\f881"}.fa-sort-alpha-down-alt::before{content:"\f881"}.fa-mitten::before{content:"\f7b5"}.fa-person-rays::before{content:"\e54d"}.fa-users::before{content:"\f0c0"}.fa-eye-slash::before{content:"\f070"}.fa-flask-vial::before{content:"\e4f3"}.fa-hand::before{content:"\f256"}.fa-hand-paper::before{content:"\f256"}.fa-om::before{content:"\f679"}.fa-worm::before{content:"\e599"}.fa-house-circle-xmark::before{content:"\e50b"}.fa-plug::before{content:"\f1e6"}.fa-chevron-up::before{content:"\f077"}.fa-hand-spock::before{content:"\f259"}.fa-stopwatch::before{content:"\f2f2"}.fa-face-kiss::before{content:"\f596"}.fa-kiss::before{content:"\f596"}.fa-bridge-circle-xmark::before{content:"\e4cb"}.fa-face-grin-tongue::before{content:"\f589"}.fa-grin-tongue::before{content:"\f589"}.fa-chess-bishop::before{content:"\f43a"}.fa-face-grin-wink::before{content:"\f58c"}.fa-grin-wink::before{content:"\f58c"}.fa-ear-deaf::before{content:"\f2a4"}.fa-deaf::before{content:"\f2a4"}.fa-deafness::before{content:"\f2a4"}.fa-hard-of-hearing::before{content:"\f2a4"}.fa-road-circle-check::before{content:"\e564"}.fa-dice-five::before{content:"\f523"}.fa-square-rss::before{content:"\f143"}.fa-rss-square::before{content:"\f143"}.fa-land-mine-on::before{content:"\e51b"}.fa-i-cursor::before{content:"\f246"}.fa-stamp::before{content:"\f5bf"}.fa-stairs::before{content:"\e289"}.fa-i::before{content:"\49"}.fa-hryvnia-sign::before{content:"\f6f2"}.fa-hryvnia::before{content:"\f6f2"}.fa-pills::before{content:"\f484"}.fa-face-grin-wide::before{content:"\f581"}.fa-grin-alt::before{content:"\f581"}.fa-tooth::before{content:"\f5c9"}.fa-v::before{content:"\56"}.fa-bangladeshi-taka-sign::before{content:"\e2e6"}.fa-bicycle::before{content:"\f206"}.fa-staff-snake::before{content:"\e579"}.fa-rod-asclepius::before{content:"\e579"}.fa-rod-snake::before{content:"\e579"}.fa-staff-aesculapius::before{content:"\e579"}.fa-head-side-cough-slash::before{content:"\e062"}.fa-truck-medical::before{content:"\f0f9"}.fa-ambulance::before{content:"\f0f9"}.fa-wheat-awn-circle-exclamation::before{content:"\e598"}.fa-snowman::before{content:"\f7d0"}.fa-mortar-pestle::before{content:"\f5a7"}.fa-road-barrier::before{content:"\e562"}.fa-school::before{content:"\f549"}.fa-igloo::before{content:"\f7ae"}.fa-joint::before{content:"\f595"}.fa-angle-right::before{content:"\f105"}.fa-horse::before{content:"\f6f0"}.fa-q::before{content:"\51"}.fa-g::before{content:"\47"}.fa-notes-medical::before{content:"\f481"}.fa-temperature-half::before{content:"\f2c9"}.fa-temperature-2::before{content:"\f2c9"}.fa-thermometer-2::before{content:"\f2c9"}.fa-thermometer-half::before{content:"\f2c9"}.fa-dong-sign::before{content:"\e169"}.fa-capsules::before{content:"\f46b"}.fa-poo-storm::before{content:"\f75a"}.fa-poo-bolt::before{content:"\f75a"}.fa-face-frown-open::before{content:"\f57a"}.fa-frown-open::before{content:"\f57a"}.fa-hand-point-up::before{content:"\f0a6"}.fa-money-bill::before{content:"\f0d6"}.fa-bookmark::before{content:"\f02e"}.fa-align-justify::before{content:"\f039"}.fa-umbrella-beach::before{content:"\f5ca"}.fa-helmet-un::before{content:"\e503"}.fa-bullseye::before{content:"\f140"}.fa-bacon::before{content:"\f7e5"}.fa-hand-point-down::before{content:"\f0a7"}.fa-arrow-up-from-bracket::before{content:"\e09a"}.fa-folder::before{content:"\f07b"}.fa-folder-blank::before{content:"\f07b"}.fa-file-waveform::before{content:"\f478"}.fa-file-medical-alt::before{content:"\f478"}.fa-radiation::before{content:"\f7b9"}.fa-chart-simple::before{content:"\e473"}.fa-mars-stroke::before{content:"\f229"}.fa-vial::before{content:"\f492"}.fa-gauge::before{content:"\f624"}.fa-dashboard::before{content:"\f624"}.fa-gauge-med::before{content:"\f624"}.fa-tachometer-alt-average::before{content:"\f624"}.fa-wand-magic-sparkles::before{content:"\e2ca"}.fa-magic-wand-sparkles::before{content:"\e2ca"}.fa-e::before{content:"\45"}.fa-pen-clip::before{content:"\f305"}.fa-pen-alt::before{content:"\f305"}.fa-bridge-circle-exclamation::before{content:"\e4ca"}.fa-user::before{content:"\f007"}.fa-school-circle-check::before{content:"\e56b"}.fa-dumpster::before{content:"\f793"}.fa-van-shuttle::before{content:"\f5b6"}.fa-shuttle-van::before{content:"\f5b6"}.fa-building-user::before{content:"\e4da"}.fa-square-caret-left::before{content:"\f191"}.fa-caret-square-left::before{content:"\f191"}.fa-highlighter::before{content:"\f591"}.fa-key::before{content:"\f084"}.fa-bullhorn::before{content:"\f0a1"}.fa-globe::before{content:"\f0ac"}.fa-synagogue::before{content:"\f69b"}.fa-person-half-dress::before{content:"\e548"}.fa-road-bridge::before{content:"\e563"}.fa-location-arrow::before{content:"\f124"}.fa-c::before{content:"\43"}.fa-tablet-button::before{content:"\f10a"}.fa-building-lock::before{content:"\e4d6"}.fa-pizza-slice::before{content:"\f818"}.fa-money-bill-wave::before{content:"\f53a"}.fa-chart-area::before{content:"\f1fe"}.fa-area-chart::before{content:"\f1fe"}.fa-house-flag::before{content:"\e50d"}.fa-person-circle-minus::before{content:"\e540"}.fa-ban::before{content:"\f05e"}.fa-cancel::before{content:"\f05e"}.fa-camera-rotate::before{content:"\e0d8"}.fa-spray-can-sparkles::before{content:"\f5d0"}.fa-air-freshener::before{content:"\f5d0"}.fa-star::before{content:"\f005"}.fa-repeat::before{content:"\f363"}.fa-cross::before{content:"\f654"}.fa-box::before{content:"\f466"}.fa-venus-mars::before{content:"\f228"}.fa-arrow-pointer::before{content:"\f245"}.fa-mouse-pointer::before{content:"\f245"}.fa-maximize::before{content:"\f31e"}.fa-expand-arrows-alt::before{content:"\f31e"}.fa-charging-station::before{content:"\f5e7"}.fa-shapes::before{content:"\f61f"}.fa-triangle-circle-square::before{content:"\f61f"}.fa-shuffle::before{content:"\f074"}.fa-random::before{content:"\f074"}.fa-person-running::before{content:"\f70c"}.fa-running::before{content:"\f70c"}.fa-mobile-retro::before{content:"\e527"}.fa-grip-lines-vertical::before{content:"\f7a5"}.fa-spider::before{content:"\f717"}.fa-hands-bound::before{content:"\e4f9"}.fa-file-invoice-dollar::before{content:"\f571"}.fa-plane-circle-exclamation::before{content:"\e556"}.fa-x-ray::before{content:"\f497"}.fa-spell-check::before{content:"\f891"}.fa-slash::before{content:"\f715"}.fa-computer-mouse::before{content:"\f8cc"}.fa-mouse::before{content:"\f8cc"}.fa-arrow-right-to-bracket::before{content:"\f090"}.fa-sign-in::before{content:"\f090"}.fa-shop-slash::before{content:"\e070"}.fa-store-alt-slash::before{content:"\e070"}.fa-server::before{content:"\f233"}.fa-virus-covid-slash::before{content:"\e4a9"}.fa-shop-lock::before{content:"\e4a5"}.fa-hourglass-start::before{content:"\f251"}.fa-hourglass-1::before{content:"\f251"}.fa-blender-phone::before{content:"\f6b6"}.fa-building-wheat::before{content:"\e4db"}.fa-person-breastfeeding::before{content:"\e53a"}.fa-right-to-bracket::before{content:"\f2f6"}.fa-sign-in-alt::before{content:"\f2f6"}.fa-venus::before{content:"\f221"}.fa-passport::before{content:"\f5ab"}.fa-heart-pulse::before{content:"\f21e"}.fa-heartbeat::before{content:"\f21e"}.fa-people-carry-box::before{content:"\f4ce"}.fa-people-carry::before{content:"\f4ce"}.fa-temperature-high::before{content:"\f769"}.fa-microchip::before{content:"\f2db"}.fa-crown::before{content:"\f521"}.fa-weight-hanging::before{content:"\f5cd"}.fa-xmarks-lines::before{content:"\e59a"}.fa-file-prescription::before{content:"\f572"}.fa-weight-scale::before{content:"\f496"}.fa-weight::before{content:"\f496"}.fa-user-group::before{content:"\f500"}.fa-user-friends::before{content:"\f500"}.fa-arrow-up-a-z::before{content:"\f15e"}.fa-sort-alpha-up::before{content:"\f15e"}.fa-chess-knight::before{content:"\f441"}.fa-face-laugh-squint::before{content:"\f59b"}.fa-laugh-squint::before{content:"\f59b"}.fa-wheelchair::before{content:"\f193"}.fa-circle-arrow-up::before{content:"\f0aa"}.fa-arrow-circle-up::before{content:"\f0aa"}.fa-toggle-on::before{content:"\f205"}.fa-person-walking::before{content:"\f554"}.fa-walking::before{content:"\f554"}.fa-l::before{content:"\4c"}.fa-fire::before{content:"\f06d"}.fa-bed-pulse::before{content:"\f487"}.fa-procedures::before{content:"\f487"}.fa-shuttle-space::before{content:"\f197"}.fa-space-shuttle::before{content:"\f197"}.fa-face-laugh::before{content:"\f599"}.fa-laugh::before{content:"\f599"}.fa-folder-open::before{content:"\f07c"}.fa-heart-circle-plus::before{content:"\e500"}.fa-code-fork::before{content:"\e13b"}.fa-city::before{content:"\f64f"}.fa-microphone-lines::before{content:"\f3c9"}.fa-microphone-alt::before{content:"\f3c9"}.fa-pepper-hot::before{content:"\f816"}.fa-unlock::before{content:"\f09c"}.fa-colon-sign::before{content:"\e140"}.fa-headset::before{content:"\f590"}.fa-store-slash::before{content:"\e071"}.fa-road-circle-xmark::before{content:"\e566"}.fa-user-minus::before{content:"\f503"}.fa-mars-stroke-up::before{content:"\f22a"}.fa-mars-stroke-v::before{content:"\f22a"}.fa-champagne-glasses::before{content:"\f79f"}.fa-glass-cheers::before{content:"\f79f"}.fa-clipboard::before{content:"\f328"}.fa-house-circle-exclamation::before{content:"\e50a"}.fa-file-arrow-up::before{content:"\f574"}.fa-file-upload::before{content:"\f574"}.fa-wifi::before{content:"\f1eb"}.fa-wifi-3::before{content:"\f1eb"}.fa-wifi-strong::before{content:"\f1eb"}.fa-bath::before{content:"\f2cd"}.fa-bathtub::before{content:"\f2cd"}.fa-underline::before{content:"\f0cd"}.fa-user-pen::before{content:"\f4ff"}.fa-user-edit::before{content:"\f4ff"}.fa-signature::before{content:"\f5b7"}.fa-stroopwafel::before{content:"\f551"}.fa-bold::before{content:"\f032"}.fa-anchor-lock::before{content:"\e4ad"}.fa-building-ngo::before{content:"\e4d7"}.fa-manat-sign::before{content:"\e1d5"}.fa-not-equal::before{content:"\f53e"}.fa-border-top-left::before{content:"\f853"}.fa-border-style::before{content:"\f853"}.fa-map-location-dot::before{content:"\f5a0"}.fa-map-marked-alt::before{content:"\f5a0"}.fa-jedi::before{content:"\f669"}.fa-square-poll-vertical::before{content:"\f681"}.fa-poll::before{content:"\f681"}.fa-mug-hot::before{content:"\f7b6"}.fa-car-battery::before{content:"\f5df"}.fa-battery-car::before{content:"\f5df"}.fa-gift::before{content:"\f06b"}.fa-dice-two::before{content:"\f528"}.fa-chess-queen::before{content:"\f445"}.fa-glasses::before{content:"\f530"}.fa-chess-board::before{content:"\f43c"}.fa-building-circle-check::before{content:"\e4d2"}.fa-person-chalkboard::before{content:"\e53d"}.fa-mars-stroke-right::before{content:"\f22b"}.fa-mars-stroke-h::before{content:"\f22b"}.fa-hand-back-fist::before{content:"\f255"}.fa-hand-rock::before{content:"\f255"}.fa-square-caret-up::before{content:"\f151"}.fa-caret-square-up::before{content:"\f151"}.fa-cloud-showers-water::before{content:"\e4e4"}.fa-chart-bar::before{content:"\f080"}.fa-bar-chart::before{content:"\f080"}.fa-hands-bubbles::before{content:"\e05e"}.fa-hands-wash::before{content:"\e05e"}.fa-less-than-equal::before{content:"\f537"}.fa-train::before{content:"\f238"}.fa-eye-low-vision::before{content:"\f2a8"}.fa-low-vision::before{content:"\f2a8"}.fa-crow::before{content:"\f520"}.fa-sailboat::before{content:"\e445"}.fa-window-restore::before{content:"\f2d2"}.fa-square-plus::before{content:"\f0fe"}.fa-plus-square::before{content:"\f0fe"}.fa-torii-gate::before{content:"\f6a1"}.fa-frog::before{content:"\f52e"}.fa-bucket::before{content:"\e4cf"}.fa-image::before{content:"\f03e"}.fa-microphone::before{content:"\f130"}.fa-cow::before{content:"\f6c8"}.fa-caret-up::before{content:"\f0d8"}.fa-screwdriver::before{content:"\f54a"}.fa-folder-closed::before{content:"\e185"}.fa-house-tsunami::before{content:"\e515"}.fa-square-nfi::before{content:"\e576"}.fa-arrow-up-from-ground-water::before{content:"\e4b5"}.fa-martini-glass::before{content:"\f57b"}.fa-glass-martini-alt::before{content:"\f57b"}.fa-rotate-left::before{content:"\f2ea"}.fa-rotate-back::before{content:"\f2ea"}.fa-rotate-backward::before{content:"\f2ea"}.fa-undo-alt::before{content:"\f2ea"}.fa-table-columns::before{content:"\f0db"}.fa-columns::before{content:"\f0db"}.fa-lemon::before{content:"\f094"}.fa-head-side-mask::before{content:"\e063"}.fa-handshake::before{content:"\f2b5"}.fa-gem::before{content:"\f3a5"}.fa-dolly::before{content:"\f472"}.fa-dolly-box::before{content:"\f472"}.fa-smoking::before{content:"\f48d"}.fa-minimize::before{content:"\f78c"}.fa-compress-arrows-alt::before{content:"\f78c"}.fa-monument::before{content:"\f5a6"}.fa-snowplow::before{content:"\f7d2"}.fa-angles-right::before{content:"\f101"}.fa-angle-double-right::before{content:"\f101"}.fa-cannabis::before{content:"\f55f"}.fa-circle-play::before{content:"\f144"}.fa-play-circle::before{content:"\f144"}.fa-tablets::before{content:"\f490"}.fa-ethernet::before{content:"\f796"}.fa-euro-sign::before{content:"\f153"}.fa-eur::before{content:"\f153"}.fa-euro::before{content:"\f153"}.fa-chair::before{content:"\f6c0"}.fa-circle-check::before{content:"\f058"}.fa-check-circle::before{content:"\f058"}.fa-circle-stop::before{content:"\f28d"}.fa-stop-circle::before{content:"\f28d"}.fa-compass-drafting::before{content:"\f568"}.fa-drafting-compass::before{content:"\f568"}.fa-plate-wheat::before{content:"\e55a"}.fa-icicles::before{content:"\f7ad"}.fa-person-shelter::before{content:"\e54f"}.fa-neuter::before{content:"\f22c"}.fa-id-badge::before{content:"\f2c1"}.fa-marker::before{content:"\f5a1"}.fa-face-laugh-beam::before{content:"\f59a"}.fa-laugh-beam::before{content:"\f59a"}.fa-helicopter-symbol::before{content:"\e502"}.fa-universal-access::before{content:"\f29a"}.fa-circle-chevron-up::before{content:"\f139"}.fa-chevron-circle-up::before{content:"\f139"}.fa-lari-sign::before{content:"\e1c8"}.fa-volcano::before{content:"\f770"}.fa-person-walking-dashed-line-arrow-right::before{content:"\e553"}.fa-sterling-sign::before{content:"\f154"}.fa-gbp::before{content:"\f154"}.fa-pound-sign::before{content:"\f154"}.fa-viruses::before{content:"\e076"}.fa-square-person-confined::before{content:"\e577"}.fa-user-tie::before{content:"\f508"}.fa-arrow-down-long::before{content:"\f175"}.fa-long-arrow-down::before{content:"\f175"}.fa-tent-arrow-down-to-line::before{content:"\e57e"}.fa-certificate::before{content:"\f0a3"}.fa-reply-all::before{content:"\f122"}.fa-mail-reply-all::before{content:"\f122"}.fa-suitcase::before{content:"\f0f2"}.fa-person-skating::before{content:"\f7c5"}.fa-skating::before{content:"\f7c5"}.fa-filter-circle-dollar::before{content:"\f662"}.fa-funnel-dollar::before{content:"\f662"}.fa-camera-retro::before{content:"\f083"}.fa-circle-arrow-down::before{content:"\f0ab"}.fa-arrow-circle-down::before{content:"\f0ab"}.fa-file-import::before{content:"\f56f"}.fa-arrow-right-to-file::before{content:"\f56f"}.fa-square-arrow-up-right::before{content:"\f14c"}.fa-external-link-square::before{content:"\f14c"}.fa-box-open::before{content:"\f49e"}.fa-scroll::before{content:"\f70e"}.fa-spa::before{content:"\f5bb"}.fa-location-pin-lock::before{content:"\e51f"}.fa-pause::before{content:"\f04c"}.fa-hill-avalanche::before{content:"\e507"}.fa-temperature-empty::before{content:"\f2cb"}.fa-temperature-0::before{content:"\f2cb"}.fa-thermometer-0::before{content:"\f2cb"}.fa-thermometer-empty::before{content:"\f2cb"}.fa-bomb::before{content:"\f1e2"}.fa-registered::before{content:"\f25d"}.fa-address-card::before{content:"\f2bb"}.fa-contact-card::before{content:"\f2bb"}.fa-vcard::before{content:"\f2bb"}.fa-scale-unbalanced-flip::before{content:"\f516"}.fa-balance-scale-right::before{content:"\f516"}.fa-subscript::before{content:"\f12c"}.fa-diamond-turn-right::before{content:"\f5eb"}.fa-directions::before{content:"\f5eb"}.fa-burst::before{content:"\e4dc"}.fa-house-laptop::before{content:"\e066"}.fa-laptop-house::before{content:"\e066"}.fa-face-tired::before{content:"\f5c8"}.fa-tired::before{content:"\f5c8"}.fa-money-bills::before{content:"\e1f3"}.fa-smog::before{content:"\f75f"}.fa-crutch::before{content:"\f7f7"}.fa-cloud-arrow-up::before{content:"\f0ee"}.fa-cloud-upload::before{content:"\f0ee"}.fa-cloud-upload-alt::before{content:"\f0ee"}.fa-palette::before{content:"\f53f"}.fa-arrows-turn-right::before{content:"\e4c0"}.fa-vest::before{content:"\e085"}.fa-ferry::before{content:"\e4ea"}.fa-arrows-down-to-people::before{content:"\e4b9"}.fa-seedling::before{content:"\f4d8"}.fa-sprout::before{content:"\f4d8"}.fa-left-right::before{content:"\f337"}.fa-arrows-alt-h::before{content:"\f337"}.fa-boxes-packing::before{content:"\e4c7"}.fa-circle-arrow-left::before{content:"\f0a8"}.fa-arrow-circle-left::before{content:"\f0a8"}.fa-group-arrows-rotate::before{content:"\e4f6"}.fa-bowl-food::before{content:"\e4c6"}.fa-candy-cane::before{content:"\f786"}.fa-arrow-down-wide-short::before{content:"\f160"}.fa-sort-amount-asc::before{content:"\f160"}.fa-sort-amount-down::before{content:"\f160"}.fa-cloud-bolt::before{content:"\f76c"}.fa-thunderstorm::before{content:"\f76c"}.fa-text-slash::before{content:"\f87d"}.fa-remove-format::before{content:"\f87d"}.fa-face-smile-wink::before{content:"\f4da"}.fa-smile-wink::before{content:"\f4da"}.fa-file-word::before{content:"\f1c2"}.fa-file-powerpoint::before{content:"\f1c4"}.fa-arrows-left-right::before{content:"\f07e"}.fa-arrows-h::before{content:"\f07e"}.fa-house-lock::before{content:"\e510"}.fa-cloud-arrow-down::before{content:"\f0ed"}.fa-cloud-download::before{content:"\f0ed"}.fa-cloud-download-alt::before{content:"\f0ed"}.fa-children::before{content:"\e4e1"}.fa-chalkboard::before{content:"\f51b"}.fa-blackboard::before{content:"\f51b"}.fa-user-large-slash::before{content:"\f4fa"}.fa-user-alt-slash::before{content:"\f4fa"}.fa-envelope-open::before{content:"\f2b6"}.fa-handshake-simple-slash::before{content:"\e05f"}.fa-handshake-alt-slash::before{content:"\e05f"}.fa-mattress-pillow::before{content:"\e525"}.fa-guarani-sign::before{content:"\e19a"}.fa-arrows-rotate::before{content:"\f021"}.fa-refresh::before{content:"\f021"}.fa-sync::before{content:"\f021"}.fa-fire-extinguisher::before{content:"\f134"}.fa-cruzeiro-sign::before{content:"\e152"}.fa-greater-than-equal::before{content:"\f532"}.fa-shield-halved::before{content:"\f3ed"}.fa-shield-alt::before{content:"\f3ed"}.fa-book-atlas::before{content:"\f558"}.fa-atlas::before{content:"\f558"}.fa-virus::before{content:"\e074"}.fa-envelope-circle-check::before{content:"\e4e8"}.fa-layer-group::before{content:"\f5fd"}.fa-arrows-to-dot::before{content:"\e4be"}.fa-archway::before{content:"\f557"}.fa-heart-circle-check::before{content:"\e4fd"}.fa-house-chimney-crack::before{content:"\f6f1"}.fa-house-damage::before{content:"\f6f1"}.fa-file-zipper::before{content:"\f1c6"}.fa-file-archive::before{content:"\f1c6"}.fa-square::before{content:"\f0c8"}.fa-martini-glass-empty::before{content:"\f000"}.fa-glass-martini::before{content:"\f000"}.fa-couch::before{content:"\f4b8"}.fa-cedi-sign::before{content:"\e0df"}.fa-italic::before{content:"\f033"}.fa-church::before{content:"\f51d"}.fa-comments-dollar::before{content:"\f653"}.fa-democrat::before{content:"\f747"}.fa-z::before{content:"\5a"}.fa-person-skiing::before{content:"\f7c9"}.fa-skiing::before{content:"\f7c9"}.fa-road-lock::before{content:"\e567"}.fa-a::before{content:"\41"}.fa-temperature-arrow-down::before{content:"\e03f"}.fa-temperature-down::before{content:"\e03f"}.fa-feather-pointed::before{content:"\f56b"}.fa-feather-alt::before{content:"\f56b"}.fa-p::before{content:"\50"}.fa-snowflake::before{content:"\f2dc"}.fa-newspaper::before{content:"\f1ea"}.fa-rectangle-ad::before{content:"\f641"}.fa-ad::before{content:"\f641"}.fa-circle-arrow-right::before{content:"\f0a9"}.fa-arrow-circle-right::before{content:"\f0a9"}.fa-filter-circle-xmark::before{content:"\e17b"}.fa-locust::before{content:"\e520"}.fa-sort::before{content:"\f0dc"}.fa-unsorted::before{content:"\f0dc"}.fa-list-ol::before{content:"\f0cb"}.fa-list-1-2::before{content:"\f0cb"}.fa-list-numeric::before{content:"\f0cb"}.fa-person-dress-burst::before{content:"\e544"}.fa-money-check-dollar::before{content:"\f53d"}.fa-money-check-alt::before{content:"\f53d"}.fa-vector-square::before{content:"\f5cb"}.fa-bread-slice::before{content:"\f7ec"}.fa-language::before{content:"\f1ab"}.fa-face-kiss-wink-heart::before{content:"\f598"}.fa-kiss-wink-heart::before{content:"\f598"}.fa-filter::before{content:"\f0b0"}.fa-question::before{content:"\3f"}.fa-file-signature::before{content:"\f573"}.fa-up-down-left-right::before{content:"\f0b2"}.fa-arrows-alt::before{content:"\f0b2"}.fa-house-chimney-user::before{content:"\e065"}.fa-hand-holding-heart::before{content:"\f4be"}.fa-puzzle-piece::before{content:"\f12e"}.fa-money-check::before{content:"\f53c"}.fa-star-half-stroke::before{content:"\f5c0"}.fa-star-half-alt::before{content:"\f5c0"}.fa-code::before{content:"\f121"}.fa-whiskey-glass::before{content:"\f7a0"}.fa-glass-whiskey::before{content:"\f7a0"}.fa-building-circle-exclamation::before{content:"\e4d3"}.fa-magnifying-glass-chart::before{content:"\e522"}.fa-arrow-up-right-from-square::before{content:"\f08e"}.fa-external-link::before{content:"\f08e"}.fa-cubes-stacked::before{content:"\e4e6"}.fa-won-sign::before{content:"\f159"}.fa-krw::before{content:"\f159"}.fa-won::before{content:"\f159"}.fa-virus-covid::before{content:"\e4a8"}.fa-austral-sign::before{content:"\e0a9"}.fa-f::before{content:"\46"}.fa-leaf::before{content:"\f06c"}.fa-road::before{content:"\f018"}.fa-taxi::before{content:"\f1ba"}.fa-cab::before{content:"\f1ba"}.fa-person-circle-plus::before{content:"\e541"}.fa-chart-pie::before{content:"\f200"}.fa-pie-chart::before{content:"\f200"}.fa-bolt-lightning::before{content:"\e0b7"}.fa-sack-xmark::before{content:"\e56a"}.fa-file-excel::before{content:"\f1c3"}.fa-file-contract::before{content:"\f56c"}.fa-fish-fins::before{content:"\e4f2"}.fa-building-flag::before{content:"\e4d5"}.fa-face-grin-beam::before{content:"\f582"}.fa-grin-beam::before{content:"\f582"}.fa-object-ungroup::before{content:"\f248"}.fa-poop::before{content:"\f619"}.fa-location-pin::before{content:"\f041"}.fa-map-marker::before{content:"\f041"}.fa-kaaba::before{content:"\f66b"}.fa-toilet-paper::before{content:"\f71e"}.fa-helmet-safety::before{content:"\f807"}.fa-hard-hat::before{content:"\f807"}.fa-hat-hard::before{content:"\f807"}.fa-eject::before{content:"\f052"}.fa-circle-right::before{content:"\f35a"}.fa-arrow-alt-circle-right::before{content:"\f35a"}.fa-plane-circle-check::before{content:"\e555"}.fa-face-rolling-eyes::before{content:"\f5a5"}.fa-meh-rolling-eyes::before{content:"\f5a5"}.fa-object-group::before{content:"\f247"}.fa-chart-line::before{content:"\f201"}.fa-line-chart::before{content:"\f201"}.fa-mask-ventilator::before{content:"\e524"}.fa-arrow-right::before{content:"\f061"}.fa-signs-post::before{content:"\f277"}.fa-map-signs::before{content:"\f277"}.fa-cash-register::before{content:"\f788"}.fa-person-circle-question::before{content:"\e542"}.fa-h::before{content:"\48"}.fa-tarp::before{content:"\e57b"}.fa-screwdriver-wrench::before{content:"\f7d9"}.fa-tools::before{content:"\f7d9"}.fa-arrows-to-eye::before{content:"\e4bf"}.fa-plug-circle-bolt::before{content:"\e55b"}.fa-heart::before{content:"\f004"}.fa-mars-and-venus::before{content:"\f224"}.fa-house-user::before{content:"\e1b0"}.fa-home-user::before{content:"\e1b0"}.fa-dumpster-fire::before{content:"\f794"}.fa-house-crack::before{content:"\e3b1"}.fa-martini-glass-citrus::before{content:"\f561"}.fa-cocktail::before{content:"\f561"}.fa-face-surprise::before{content:"\f5c2"}.fa-surprise::before{content:"\f5c2"}.fa-bottle-water::before{content:"\e4c5"}.fa-circle-pause::before{content:"\f28b"}.fa-pause-circle::before{content:"\f28b"}.fa-toilet-paper-slash::before{content:"\e072"}.fa-apple-whole::before{content:"\f5d1"}.fa-apple-alt::before{content:"\f5d1"}.fa-kitchen-set::before{content:"\e51a"}.fa-r::before{content:"\52"}.fa-temperature-quarter::before{content:"\f2ca"}.fa-temperature-1::before{content:"\f2ca"}.fa-thermometer-1::before{content:"\f2ca"}.fa-thermometer-quarter::before{content:"\f2ca"}.fa-cube::before{content:"\f1b2"}.fa-bitcoin-sign::before{content:"\e0b4"}.fa-shield-dog::before{content:"\e573"}.fa-solar-panel::before{content:"\f5ba"}.fa-lock-open::before{content:"\f3c1"}.fa-elevator::before{content:"\e16d"}.fa-money-bill-transfer::before{content:"\e528"}.fa-money-bill-trend-up::before{content:"\e529"}.fa-house-flood-water-circle-arrow-right::before{content:"\e50f"}.fa-square-poll-horizontal::before{content:"\f682"}.fa-poll-h::before{content:"\f682"}.fa-circle::before{content:"\f111"}.fa-backward-fast::before{content:"\f049"}.fa-fast-backward::before{content:"\f049"}.fa-recycle::before{content:"\f1b8"}.fa-user-astronaut::before{content:"\f4fb"}.fa-plane-slash::before{content:"\e069"}.fa-trademark::before{content:"\f25c"}.fa-basketball::before{content:"\f434"}.fa-basketball-ball::before{content:"\f434"}.fa-satellite-dish::before{content:"\f7c0"}.fa-circle-up::before{content:"\f35b"}.fa-arrow-alt-circle-up::before{content:"\f35b"}.fa-mobile-screen-button::before{content:"\f3cd"}.fa-mobile-alt::before{content:"\f3cd"}.fa-volume-high::before{content:"\f028"}.fa-volume-up::before{content:"\f028"}.fa-users-rays::before{content:"\e593"}.fa-wallet::before{content:"\f555"}.fa-clipboard-check::before{content:"\f46c"}.fa-file-audio::before{content:"\f1c7"}.fa-burger::before{content:"\f805"}.fa-hamburger::before{content:"\f805"}.fa-wrench::before{content:"\f0ad"}.fa-bugs::before{content:"\e4d0"}.fa-rupee-sign::before{content:"\f156"}.fa-rupee::before{content:"\f156"}.fa-file-image::before{content:"\f1c5"}.fa-circle-question::before{content:"\f059"}.fa-question-circle::before{content:"\f059"}.fa-plane-departure::before{content:"\f5b0"}.fa-handshake-slash::before{content:"\e060"}.fa-book-bookmark::before{content:"\e0bb"}.fa-code-branch::before{content:"\f126"}.fa-hat-cowboy::before{content:"\f8c0"}.fa-bridge::before{content:"\e4c8"}.fa-phone-flip::before{content:"\f879"}.fa-phone-alt::before{content:"\f879"}.fa-truck-front::before{content:"\e2b7"}.fa-cat::before{content:"\f6be"}.fa-anchor-circle-exclamation::before{content:"\e4ab"}.fa-truck-field::before{content:"\e58d"}.fa-route::before{content:"\f4d7"}.fa-clipboard-question::before{content:"\e4e3"}.fa-panorama::before{content:"\e209"}.fa-comment-medical::before{content:"\f7f5"}.fa-teeth-open::before{content:"\f62f"}.fa-file-circle-minus::before{content:"\e4ed"}.fa-tags::before{content:"\f02c"}.fa-wine-glass::before{content:"\f4e3"}.fa-forward-fast::before{content:"\f050"}.fa-fast-forward::before{content:"\f050"}.fa-face-meh-blank::before{content:"\f5a4"}.fa-meh-blank::before{content:"\f5a4"}.fa-square-parking::before{content:"\f540"}.fa-parking::before{content:"\f540"}.fa-house-signal::before{content:"\e012"}.fa-bars-progress::before{content:"\f828"}.fa-tasks-alt::before{content:"\f828"}.fa-faucet-drip::before{content:"\e006"}.fa-cart-flatbed::before{content:"\f474"}.fa-dolly-flatbed::before{content:"\f474"}.fa-ban-smoking::before{content:"\f54d"}.fa-smoking-ban::before{content:"\f54d"}.fa-terminal::before{content:"\f120"}.fa-mobile-button::before{content:"\f10b"}.fa-house-medical-flag::before{content:"\e514"}.fa-basket-shopping::before{content:"\f291"}.fa-shopping-basket::before{content:"\f291"}.fa-tape::before{content:"\f4db"}.fa-bus-simple::before{content:"\f55e"}.fa-bus-alt::before{content:"\f55e"}.fa-eye::before{content:"\f06e"}.fa-face-sad-cry::before{content:"\f5b3"}.fa-sad-cry::before{content:"\f5b3"}.fa-audio-description::before{content:"\f29e"}.fa-person-military-to-person::before{content:"\e54c"}.fa-file-shield::before{content:"\e4f0"}.fa-user-slash::before{content:"\f506"}.fa-pen::before{content:"\f304"}.fa-tower-observation::before{content:"\e586"}.fa-file-code::before{content:"\f1c9"}.fa-signal::before{content:"\f012"}.fa-signal-5::before{content:"\f012"}.fa-signal-perfect::before{content:"\f012"}.fa-bus::before{content:"\f207"}.fa-heart-circle-xmark::before{content:"\e501"}.fa-house-chimney::before{content:"\e3af"}.fa-home-lg::before{content:"\e3af"}.fa-window-maximize::before{content:"\f2d0"}.fa-face-frown::before{content:"\f119"}.fa-frown::before{content:"\f119"}.fa-prescription::before{content:"\f5b1"}.fa-shop::before{content:"\f54f"}.fa-store-alt::before{content:"\f54f"}.fa-floppy-disk::before{content:"\f0c7"}.fa-save::before{content:"\f0c7"}.fa-vihara::before{content:"\f6a7"}.fa-scale-unbalanced::before{content:"\f515"}.fa-balance-scale-left::before{content:"\f515"}.fa-sort-up::before{content:"\f0de"}.fa-sort-asc::before{content:"\f0de"}.fa-comment-dots::before{content:"\f4ad"}.fa-commenting::before{content:"\f4ad"}.fa-plant-wilt::before{content:"\e5aa"}.fa-diamond::before{content:"\f219"}.fa-face-grin-squint::before{content:"\f585"}.fa-grin-squint::before{content:"\f585"}.fa-hand-holding-dollar::before{content:"\f4c0"}.fa-hand-holding-usd::before{content:"\f4c0"}.fa-bacterium::before{content:"\e05a"}.fa-hand-pointer::before{content:"\f25a"}.fa-drum-steelpan::before{content:"\f56a"}.fa-hand-scissors::before{content:"\f257"}.fa-hands-praying::before{content:"\f684"}.fa-praying-hands::before{content:"\f684"}.fa-arrow-rotate-right::before{content:"\f01e"}.fa-arrow-right-rotate::before{content:"\f01e"}.fa-arrow-rotate-forward::before{content:"\f01e"}.fa-redo::before{content:"\f01e"}.fa-biohazard::before{content:"\f780"}.fa-location-crosshairs::before{content:"\f601"}.fa-location::before{content:"\f601"}.fa-mars-double::before{content:"\f227"}.fa-child-dress::before{content:"\e59c"}.fa-users-between-lines::before{content:"\e591"}.fa-lungs-virus::before{content:"\e067"}.fa-face-grin-tears::before{content:"\f588"}.fa-grin-tears::before{content:"\f588"}.fa-phone::before{content:"\f095"}.fa-calendar-xmark::before{content:"\f273"}.fa-calendar-times::before{content:"\f273"}.fa-child-reaching::before{content:"\e59d"}.fa-head-side-virus::before{content:"\e064"}.fa-user-gear::before{content:"\f4fe"}.fa-user-cog::before{content:"\f4fe"}.fa-arrow-up-1-9::before{content:"\f163"}.fa-sort-numeric-up::before{content:"\f163"}.fa-door-closed::before{content:"\f52a"}.fa-shield-virus::before{content:"\e06c"}.fa-dice-six::before{content:"\f526"}.fa-mosquito-net::before{content:"\e52c"}.fa-bridge-water::before{content:"\e4ce"}.fa-person-booth::before{content:"\f756"}.fa-text-width::before{content:"\f035"}.fa-hat-wizard::before{content:"\f6e8"}.fa-pen-fancy::before{content:"\f5ac"}.fa-person-digging::before{content:"\f85e"}.fa-digging::before{content:"\f85e"}.fa-trash::before{content:"\f1f8"}.fa-gauge-simple::before{content:"\f629"}.fa-gauge-simple-med::before{content:"\f629"}.fa-tachometer-average::before{content:"\f629"}.fa-book-medical::before{content:"\f7e6"}.fa-poo::before{content:"\f2fe"}.fa-quote-right::before{content:"\f10e"}.fa-quote-right-alt::before{content:"\f10e"}.fa-shirt::before{content:"\f553"}.fa-t-shirt::before{content:"\f553"}.fa-tshirt::before{content:"\f553"}.fa-cubes::before{content:"\f1b3"}.fa-divide::before{content:"\f529"}.fa-tenge-sign::before{content:"\f7d7"}.fa-tenge::before{content:"\f7d7"}.fa-headphones::before{content:"\f025"}.fa-hands-holding::before{content:"\f4c2"}.fa-hands-clapping::before{content:"\e1a8"}.fa-republican::before{content:"\f75e"}.fa-arrow-left::before{content:"\f060"}.fa-person-circle-xmark::before{content:"\e543"}.fa-ruler::before{content:"\f545"}.fa-align-left::before{content:"\f036"}.fa-dice-d6::before{content:"\f6d1"}.fa-restroom::before{content:"\f7bd"}.fa-j::before{content:"\4a"}.fa-users-viewfinder::before{content:"\e595"}.fa-file-video::before{content:"\f1c8"}.fa-up-right-from-square::before{content:"\f35d"}.fa-external-link-alt::before{content:"\f35d"}.fa-table-cells::before{content:"\f00a"}.fa-th::before{content:"\f00a"}.fa-file-pdf::before{content:"\f1c1"}.fa-book-bible::before{content:"\f647"}.fa-bible::before{content:"\f647"}.fa-o::before{content:"\4f"}.fa-suitcase-medical::before{content:"\f0fa"}.fa-medkit::before{content:"\f0fa"}.fa-user-secret::before{content:"\f21b"}.fa-otter::before{content:"\f700"}.fa-person-dress::before{content:"\f182"}.fa-female::before{content:"\f182"}.fa-comment-dollar::before{content:"\f651"}.fa-business-time::before{content:"\f64a"}.fa-briefcase-clock::before{content:"\f64a"}.fa-table-cells-large::before{content:"\f009"}.fa-th-large::before{content:"\f009"}.fa-book-tanakh::before{content:"\f827"}.fa-tanakh::before{content:"\f827"}.fa-phone-volume::before{content:"\f2a0"}.fa-volume-control-phone::before{content:"\f2a0"}.fa-hat-cowboy-side::before{content:"\f8c1"}.fa-clipboard-user::before{content:"\f7f3"}.fa-child::before{content:"\f1ae"}.fa-lira-sign::before{content:"\f195"}.fa-satellite::before{content:"\f7bf"}.fa-plane-lock::before{content:"\e558"}.fa-tag::before{content:"\f02b"}.fa-comment::before{content:"\f075"}.fa-cake-candles::before{content:"\f1fd"}.fa-birthday-cake::before{content:"\f1fd"}.fa-cake::before{content:"\f1fd"}.fa-envelope::before{content:"\f0e0"}.fa-angles-up::before{content:"\f102"}.fa-angle-double-up::before{content:"\f102"}.fa-paperclip::before{content:"\f0c6"}.fa-arrow-right-to-city::before{content:"\e4b3"}.fa-ribbon::before{content:"\f4d6"}.fa-lungs::before{content:"\f604"}.fa-arrow-up-9-1::before{content:"\f887"}.fa-sort-numeric-up-alt::before{content:"\f887"}.fa-litecoin-sign::before{content:"\e1d3"}.fa-border-none::before{content:"\f850"}.fa-circle-nodes::before{content:"\e4e2"}.fa-parachute-box::before{content:"\f4cd"}.fa-indent::before{content:"\f03c"}.fa-truck-field-un::before{content:"\e58e"}.fa-hourglass::before{content:"\f254"}.fa-hourglass-empty::before{content:"\f254"}.fa-mountain::before{content:"\f6fc"}.fa-user-doctor::before{content:"\f0f0"}.fa-user-md::before{content:"\f0f0"}.fa-circle-info::before{content:"\f05a"}.fa-info-circle::before{content:"\f05a"}.fa-cloud-meatball::before{content:"\f73b"}.fa-camera::before{content:"\f030"}.fa-camera-alt::before{content:"\f030"}.fa-square-virus::before{content:"\e578"}.fa-meteor::before{content:"\f753"}.fa-car-on::before{content:"\e4dd"}.fa-sleigh::before{content:"\f7cc"}.fa-arrow-down-1-9::before{content:"\f162"}.fa-sort-numeric-asc::before{content:"\f162"}.fa-sort-numeric-down::before{content:"\f162"}.fa-hand-holding-droplet::before{content:"\f4c1"}.fa-hand-holding-water::before{content:"\f4c1"}.fa-water::before{content:"\f773"}.fa-calendar-check::before{content:"\f274"}.fa-braille::before{content:"\f2a1"}.fa-prescription-bottle-medical::before{content:"\f486"}.fa-prescription-bottle-alt::before{content:"\f486"}.fa-landmark::before{content:"\f66f"}.fa-truck::before{content:"\f0d1"}.fa-crosshairs::before{content:"\f05b"}.fa-person-cane::before{content:"\e53c"}.fa-tent::before{content:"\e57d"}.fa-vest-patches::before{content:"\e086"}.fa-check-double::before{content:"\f560"}.fa-arrow-down-a-z::before{content:"\f15d"}.fa-sort-alpha-asc::before{content:"\f15d"}.fa-sort-alpha-down::before{content:"\f15d"}.fa-money-bill-wheat::before{content:"\e52a"}.fa-cookie::before{content:"\f563"}.fa-arrow-rotate-left::before{content:"\f0e2"}.fa-arrow-left-rotate::before{content:"\f0e2"}.fa-arrow-rotate-back::before{content:"\f0e2"}.fa-arrow-rotate-backward::before{content:"\f0e2"}.fa-undo::before{content:"\f0e2"}.fa-hard-drive::before{content:"\f0a0"}.fa-hdd::before{content:"\f0a0"}.fa-face-grin-squint-tears::before{content:"\f586"}.fa-grin-squint-tears::before{content:"\f586"}.fa-dumbbell::before{content:"\f44b"}.fa-rectangle-list::before{content:"\f022"}.fa-list-alt::before{content:"\f022"}.fa-tarp-droplet::before{content:"\e57c"}.fa-house-medical-circle-check::before{content:"\e511"}.fa-person-skiing-nordic::before{content:"\f7ca"}.fa-skiing-nordic::before{content:"\f7ca"}.fa-calendar-plus::before{content:"\f271"}.fa-plane-arrival::before{content:"\f5af"}.fa-circle-left::before{content:"\f359"}.fa-arrow-alt-circle-left::before{content:"\f359"}.fa-train-subway::before{content:"\f239"}.fa-subway::before{content:"\f239"}.fa-chart-gantt::before{content:"\e0e4"}.fa-indian-rupee-sign::before{content:"\e1bc"}.fa-indian-rupee::before{content:"\e1bc"}.fa-inr::before{content:"\e1bc"}.fa-crop-simple::before{content:"\f565"}.fa-crop-alt::before{content:"\f565"}.fa-money-bill-1::before{content:"\f3d1"}.fa-money-bill-alt::before{content:"\f3d1"}.fa-left-long::before{content:"\f30a"}.fa-long-arrow-alt-left::before{content:"\f30a"}.fa-dna::before{content:"\f471"}.fa-virus-slash::before{content:"\e075"}.fa-minus::before{content:"\f068"}.fa-subtract::before{content:"\f068"}.fa-chess::before{content:"\f439"}.fa-arrow-left-long::before{content:"\f177"}.fa-long-arrow-left::before{content:"\f177"}.fa-plug-circle-check::before{content:"\e55c"}.fa-street-view::before{content:"\f21d"}.fa-franc-sign::before{content:"\e18f"}.fa-volume-off::before{content:"\f026"}.fa-hands-asl-interpreting::before{content:"\f2a3"}.fa-american-sign-language-interpreting::before{content:"\f2a3"}.fa-asl-interpreting::before{content:"\f2a3"}.fa-hands-american-sign-language-interpreting::before{content:"\f2a3"}.fa-gear::before{content:"\f013"}.fa-cog::before{content:"\f013"}.fa-droplet-slash::before{content:"\f5c7"}.fa-tint-slash::before{content:"\f5c7"}.fa-mosque::before{content:"\f678"}.fa-mosquito::before{content:"\e52b"}.fa-star-of-david::before{content:"\f69a"}.fa-person-military-rifle::before{content:"\e54b"}.fa-cart-shopping::before{content:"\f07a"}.fa-shopping-cart::before{content:"\f07a"}.fa-vials::before{content:"\f493"}.fa-plug-circle-plus::before{content:"\e55f"}.fa-place-of-worship::before{content:"\f67f"}.fa-grip-vertical::before{content:"\f58e"}.fa-arrow-turn-up::before{content:"\f148"}.fa-level-up::before{content:"\f148"}.fa-u::before{content:"\55"}.fa-square-root-variable::before{content:"\f698"}.fa-square-root-alt::before{content:"\f698"}.fa-clock::before{content:"\f017"}.fa-clock-four::before{content:"\f017"}.fa-backward-step::before{content:"\f048"}.fa-step-backward::before{content:"\f048"}.fa-pallet::before{content:"\f482"}.fa-faucet::before{content:"\e005"}.fa-baseball-bat-ball::before{content:"\f432"}.fa-s::before{content:"\53"}.fa-timeline::before{content:"\e29c"}.fa-keyboard::before{content:"\f11c"}.fa-caret-down::before{content:"\f0d7"}.fa-house-chimney-medical::before{content:"\f7f2"}.fa-clinic-medical::before{content:"\f7f2"}.fa-temperature-three-quarters::before{content:"\f2c8"}.fa-temperature-3::before{content:"\f2c8"}.fa-thermometer-3::before{content:"\f2c8"}.fa-thermometer-three-quarters::before{content:"\f2c8"}.fa-mobile-screen::before{content:"\f3cf"}.fa-mobile-android-alt::before{content:"\f3cf"}.fa-plane-up::before{content:"\e22d"}.fa-piggy-bank::before{content:"\f4d3"}.fa-battery-half::before{content:"\f242"}.fa-battery-3::before{content:"\f242"}.fa-mountain-city::before{content:"\e52e"}.fa-coins::before{content:"\f51e"}.fa-khanda::before{content:"\f66d"}.fa-sliders::before{content:"\f1de"}.fa-sliders-h::before{content:"\f1de"}.fa-folder-tree::before{content:"\f802"}.fa-network-wired::before{content:"\f6ff"}.fa-map-pin::before{content:"\f276"}.fa-hamsa::before{content:"\f665"}.fa-cent-sign::before{content:"\e3f5"}.fa-flask::before{content:"\f0c3"}.fa-person-pregnant::before{content:"\e31e"}.fa-wand-sparkles::before{content:"\f72b"}.fa-ellipsis-vertical::before{content:"\f142"}.fa-ellipsis-v::before{content:"\f142"}.fa-ticket::before{content:"\f145"}.fa-power-off::before{content:"\f011"}.fa-right-long::before{content:"\f30b"}.fa-long-arrow-alt-right::before{content:"\f30b"}.fa-flag-usa::before{content:"\f74d"}.fa-laptop-file::before{content:"\e51d"}.fa-tty::before{content:"\f1e4"}.fa-teletype::before{content:"\f1e4"}.fa-diagram-next::before{content:"\e476"}.fa-person-rifle::before{content:"\e54e"}.fa-house-medical-circle-exclamation::before{content:"\e512"}.fa-closed-captioning::before{content:"\f20a"}.fa-person-hiking::before{content:"\f6ec"}.fa-hiking::before{content:"\f6ec"}.fa-venus-double::before{content:"\f226"}.fa-images::before{content:"\f302"}.fa-calculator::before{content:"\f1ec"}.fa-people-pulling::before{content:"\e535"}.fa-n::before{content:"\4e"}.fa-cable-car::before{content:"\f7da"}.fa-tram::before{content:"\f7da"}.fa-cloud-rain::before{content:"\f73d"}.fa-building-circle-xmark::before{content:"\e4d4"}.fa-ship::before{content:"\f21a"}.fa-arrows-down-to-line::before{content:"\e4b8"}.fa-download::before{content:"\f019"}.fa-face-grin::before{content:"\f580"}.fa-grin::before{content:"\f580"}.fa-delete-left::before{content:"\f55a"}.fa-backspace::before{content:"\f55a"}.fa-eye-dropper::before{content:"\f1fb"}.fa-eye-dropper-empty::before{content:"\f1fb"}.fa-eyedropper::before{content:"\f1fb"}.fa-file-circle-check::before{content:"\e5a0"}.fa-forward::before{content:"\f04e"}.fa-mobile::before{content:"\f3ce"}.fa-mobile-android::before{content:"\f3ce"}.fa-mobile-phone::before{content:"\f3ce"}.fa-face-meh::before{content:"\f11a"}.fa-meh::before{content:"\f11a"}.fa-align-center::before{content:"\f037"}.fa-book-skull::before{content:"\f6b7"}.fa-book-dead::before{content:"\f6b7"}.fa-id-card::before{content:"\f2c2"}.fa-drivers-license::before{content:"\f2c2"}.fa-outdent::before{content:"\f03b"}.fa-dedent::before{content:"\f03b"}.fa-heart-circle-exclamation::before{content:"\e4fe"}.fa-house::before{content:"\f015"}.fa-home::before{content:"\f015"}.fa-home-alt::before{content:"\f015"}.fa-home-lg-alt::before{content:"\f015"}.fa-calendar-week::before{content:"\f784"}.fa-laptop-medical::before{content:"\f812"}.fa-b::before{content:"\42"}.fa-file-medical::before{content:"\f477"}.fa-dice-one::before{content:"\f525"}.fa-kiwi-bird::before{content:"\f535"}.fa-arrow-right-arrow-left::before{content:"\f0ec"}.fa-exchange::before{content:"\f0ec"}.fa-rotate-right::before{content:"\f2f9"}.fa-redo-alt::before{content:"\f2f9"}.fa-rotate-forward::before{content:"\f2f9"}.fa-utensils::before{content:"\f2e7"}.fa-cutlery::before{content:"\f2e7"}.fa-arrow-up-wide-short::before{content:"\f161"}.fa-sort-amount-up::before{content:"\f161"}.fa-mill-sign::before{content:"\e1ed"}.fa-bowl-rice::before{content:"\e2eb"}.fa-skull::before{content:"\f54c"}.fa-tower-broadcast::before{content:"\f519"}.fa-broadcast-tower::before{content:"\f519"}.fa-truck-pickup::before{content:"\f63c"}.fa-up-long::before{content:"\f30c"}.fa-long-arrow-alt-up::before{content:"\f30c"}.fa-stop::before{content:"\f04d"}.fa-code-merge::before{content:"\f387"}.fa-upload::before{content:"\f093"}.fa-hurricane::before{content:"\f751"}.fa-mound::before{content:"\e52d"}.fa-toilet-portable::before{content:"\e583"}.fa-compact-disc::before{content:"\f51f"}.fa-file-arrow-down::before{content:"\f56d"}.fa-file-download::before{content:"\f56d"}.fa-caravan::before{content:"\f8ff"}.fa-shield-cat::before{content:"\e572"}.fa-bolt::before{content:"\f0e7"}.fa-zap::before{content:"\f0e7"}.fa-glass-water::before{content:"\e4f4"}.fa-oil-well::before{content:"\e532"}.fa-vault::before{content:"\e2c5"}.fa-mars::before{content:"\f222"}.fa-toilet::before{content:"\f7d8"}.fa-plane-circle-xmark::before{content:"\e557"}.fa-yen-sign::before{content:"\f157"}.fa-cny::before{content:"\f157"}.fa-jpy::before{content:"\f157"}.fa-rmb::before{content:"\f157"}.fa-yen::before{content:"\f157"}.fa-ruble-sign::before{content:"\f158"}.fa-rouble::before{content:"\f158"}.fa-rub::before{content:"\f158"}.fa-ruble::before{content:"\f158"}.fa-sun::before{content:"\f185"}.fa-guitar::before{content:"\f7a6"}.fa-face-laugh-wink::before{content:"\f59c"}.fa-laugh-wink::before{content:"\f59c"}.fa-horse-head::before{content:"\f7ab"}.fa-bore-hole::before{content:"\e4c3"}.fa-industry::before{content:"\f275"}.fa-circle-down::before{content:"\f358"}.fa-arrow-alt-circle-down::before{content:"\f358"}.fa-arrows-turn-to-dots::before{content:"\e4c1"}.fa-florin-sign::before{content:"\e184"}.fa-arrow-down-short-wide::before{content:"\f884"}.fa-sort-amount-desc::before{content:"\f884"}.fa-sort-amount-down-alt::before{content:"\f884"}.fa-less-than::before{content:"\3c"}.fa-angle-down::before{content:"\f107"}.fa-car-tunnel::before{content:"\e4de"}.fa-head-side-cough::before{content:"\e061"}.fa-grip-lines::before{content:"\f7a4"}.fa-thumbs-down::before{content:"\f165"}.fa-user-lock::before{content:"\f502"}.fa-arrow-right-long::before{content:"\f178"}.fa-long-arrow-right::before{content:"\f178"}.fa-anchor-circle-xmark::before{content:"\e4ac"}.fa-ellipsis::before{content:"\f141"}.fa-ellipsis-h::before{content:"\f141"}.fa-chess-pawn::before{content:"\f443"}.fa-kit-medical::before{content:"\f479"}.fa-first-aid::before{content:"\f479"}.fa-person-through-window::before{content:"\e5a9"}.fa-toolbox::before{content:"\f552"}.fa-hands-holding-circle::before{content:"\e4fb"}.fa-bug::before{content:"\f188"}.fa-credit-card::before{content:"\f09d"}.fa-credit-card-alt::before{content:"\f09d"}.fa-car::before{content:"\f1b9"}.fa-automobile::before{content:"\f1b9"}.fa-hand-holding-hand::before{content:"\e4f7"}.fa-book-open-reader::before{content:"\f5da"}.fa-book-reader::before{content:"\f5da"}.fa-mountain-sun::before{content:"\e52f"}.fa-arrows-left-right-to-line::before{content:"\e4ba"}.fa-dice-d20::before{content:"\f6cf"}.fa-truck-droplet::before{content:"\e58c"}.fa-file-circle-xmark::before{content:"\e5a1"}.fa-temperature-arrow-up::before{content:"\e040"}.fa-temperature-up::before{content:"\e040"}.fa-medal::before{content:"\f5a2"}.fa-bed::before{content:"\f236"}.fa-square-h::before{content:"\f0fd"}.fa-h-square::before{content:"\f0fd"}.fa-podcast::before{content:"\f2ce"}.fa-temperature-full::before{content:"\f2c7"}.fa-temperature-4::before{content:"\f2c7"}.fa-thermometer-4::before{content:"\f2c7"}.fa-thermometer-full::before{content:"\f2c7"}.fa-bell::before{content:"\f0f3"}.fa-superscript::before{content:"\f12b"}.fa-plug-circle-xmark::before{content:"\e560"}.fa-star-of-life::before{content:"\f621"}.fa-phone-slash::before{content:"\f3dd"}.fa-paint-roller::before{content:"\f5aa"}.fa-handshake-angle::before{content:"\f4c4"}.fa-hands-helping::before{content:"\f4c4"}.fa-location-dot::before{content:"\f3c5"}.fa-map-marker-alt::before{content:"\f3c5"}.fa-file::before{content:"\f15b"}.fa-greater-than::before{content:"\3e"}.fa-person-swimming::before{content:"\f5c4"}.fa-swimmer::before{content:"\f5c4"}.fa-arrow-down::before{content:"\f063"}.fa-droplet::before{content:"\f043"}.fa-tint::before{content:"\f043"}.fa-eraser::before{content:"\f12d"}.fa-earth-americas::before{content:"\f57d"}.fa-earth::before{content:"\f57d"}.fa-earth-america::before{content:"\f57d"}.fa-globe-americas::before{content:"\f57d"}.fa-person-burst::before{content:"\e53b"}.fa-dove::before{content:"\f4ba"}.fa-battery-empty::before{content:"\f244"}.fa-battery-0::before{content:"\f244"}.fa-socks::before{content:"\f696"}.fa-inbox::before{content:"\f01c"}.fa-section::before{content:"\e447"}.fa-gauge-high::before{content:"\f625"}.fa-tachometer-alt::before{content:"\f625"}.fa-tachometer-alt-fast::before{content:"\f625"}.fa-envelope-open-text::before{content:"\f658"}.fa-hospital::before{content:"\f0f8"}.fa-hospital-alt::before{content:"\f0f8"}.fa-hospital-wide::before{content:"\f0f8"}.fa-wine-bottle::before{content:"\f72f"}.fa-chess-rook::before{content:"\f447"}.fa-bars-staggered::before{content:"\f550"}.fa-reorder::before{content:"\f550"}.fa-stream::before{content:"\f550"}.fa-dharmachakra::before{content:"\f655"}.fa-hotdog::before{content:"\f80f"}.fa-person-walking-with-cane::before{content:"\f29d"}.fa-blind::before{content:"\f29d"}.fa-drum::before{content:"\f569"}.fa-ice-cream::before{content:"\f810"}.fa-heart-circle-bolt::before{content:"\e4fc"}.fa-fax::before{content:"\f1ac"}.fa-paragraph::before{content:"\f1dd"}.fa-check-to-slot::before{content:"\f772"}.fa-vote-yea::before{content:"\f772"}.fa-star-half::before{content:"\f089"}.fa-boxes-stacked::before{content:"\f468"}.fa-boxes::before{content:"\f468"}.fa-boxes-alt::before{content:"\f468"}.fa-link::before{content:"\f0c1"}.fa-chain::before{content:"\f0c1"}.fa-ear-listen::before{content:"\f2a2"}.fa-assistive-listening-systems::before{content:"\f2a2"}.fa-tree-city::before{content:"\e587"}.fa-play::before{content:"\f04b"}.fa-font::before{content:"\f031"}.fa-rupiah-sign::before{content:"\e23d"}.fa-magnifying-glass::before{content:"\f002"}.fa-search::before{content:"\f002"}.fa-table-tennis-paddle-ball::before{content:"\f45d"}.fa-ping-pong-paddle-ball::before{content:"\f45d"}.fa-table-tennis::before{content:"\f45d"}.fa-person-dots-from-line::before{content:"\f470"}.fa-diagnoses::before{content:"\f470"}.fa-trash-can-arrow-up::before{content:"\f82a"}.fa-trash-restore-alt::before{content:"\f82a"}.fa-naira-sign::before{content:"\e1f6"}.fa-cart-arrow-down::before{content:"\f218"}.fa-walkie-talkie::before{content:"\f8ef"}.fa-file-pen::before{content:"\f31c"}.fa-file-edit::before{content:"\f31c"}.fa-receipt::before{content:"\f543"}.fa-square-pen::before{content:"\f14b"}.fa-pen-square::before{content:"\f14b"}.fa-pencil-square::before{content:"\f14b"}.fa-suitcase-rolling::before{content:"\f5c1"}.fa-person-circle-exclamation::before{content:"\e53f"}.fa-chevron-down::before{content:"\f078"}.fa-battery-full::before{content:"\f240"}.fa-battery::before{content:"\f240"}.fa-battery-5::before{content:"\f240"}.fa-skull-crossbones::before{content:"\f714"}.fa-code-compare::before{content:"\e13a"}.fa-list-ul::before{content:"\f0ca"}.fa-list-dots::before{content:"\f0ca"}.fa-school-lock::before{content:"\e56f"}.fa-tower-cell::before{content:"\e585"}.fa-down-long::before{content:"\f309"}.fa-long-arrow-alt-down::before{content:"\f309"}.fa-ranking-star::before{content:"\e561"}.fa-chess-king::before{content:"\f43f"}.fa-person-harassing::before{content:"\e549"}.fa-brazilian-real-sign::before{content:"\e46c"}.fa-landmark-dome::before{content:"\f752"}.fa-landmark-alt::before{content:"\f752"}.fa-arrow-up::before{content:"\f062"}.fa-tv::before{content:"\f26c"}.fa-television::before{content:"\f26c"}.fa-tv-alt::before{content:"\f26c"}.fa-shrimp::before{content:"\e448"}.fa-list-check::before{content:"\f0ae"}.fa-tasks::before{content:"\f0ae"}.fa-jug-detergent::before{content:"\e519"}.fa-circle-user::before{content:"\f2bd"}.fa-user-circle::before{content:"\f2bd"}.fa-user-shield::before{content:"\f505"}.fa-wind::before{content:"\f72e"}.fa-car-burst::before{content:"\f5e1"}.fa-car-crash::before{content:"\f5e1"}.fa-y::before{content:"\59"}.fa-person-snowboarding::before{content:"\f7ce"}.fa-snowboarding::before{content:"\f7ce"}.fa-truck-fast::before{content:"\f48b"}.fa-shipping-fast::before{content:"\f48b"}.fa-fish::before{content:"\f578"}.fa-user-graduate::before{content:"\f501"}.fa-circle-half-stroke::before{content:"\f042"}.fa-adjust::before{content:"\f042"}.fa-clapperboard::before{content:"\e131"}.fa-circle-radiation::before{content:"\f7ba"}.fa-radiation-alt::before{content:"\f7ba"}.fa-baseball::before{content:"\f433"}.fa-baseball-ball::before{content:"\f433"}.fa-jet-fighter-up::before{content:"\e518"}.fa-diagram-project::before{content:"\f542"}.fa-project-diagram::before{content:"\f542"}.fa-copy::before{content:"\f0c5"}.fa-volume-xmark::before{content:"\f6a9"}.fa-volume-mute::before{content:"\f6a9"}.fa-volume-times::before{content:"\f6a9"}.fa-hand-sparkles::before{content:"\e05d"}.fa-grip::before{content:"\f58d"}.fa-grip-horizontal::before{content:"\f58d"}.fa-share-from-square::before{content:"\f14d"}.fa-share-square::before{content:"\f14d"}.fa-child-combatant::before{content:"\e4e0"}.fa-child-rifle::before{content:"\e4e0"}.fa-gun::before{content:"\e19b"}.fa-square-phone::before{content:"\f098"}.fa-phone-square::before{content:"\f098"}.fa-plus::before{content:"\2b"}.fa-add::before{content:"\2b"}.fa-expand::before{content:"\f065"}.fa-computer::before{content:"\e4e5"}.fa-xmark::before{content:"\f00d"}.fa-close::before{content:"\f00d"}.fa-multiply::before{content:"\f00d"}.fa-remove::before{content:"\f00d"}.fa-times::before{content:"\f00d"}.fa-arrows-up-down-left-right::before{content:"\f047"}.fa-arrows::before{content:"\f047"}.fa-chalkboard-user::before{content:"\f51c"}.fa-chalkboard-teacher::before{content:"\f51c"}.fa-peso-sign::before{content:"\e222"}.fa-building-shield::before{content:"\e4d8"}.fa-baby::before{content:"\f77c"}.fa-users-line::before{content:"\e592"}.fa-quote-left::before{content:"\f10d"}.fa-quote-left-alt::before{content:"\f10d"}.fa-tractor::before{content:"\f722"}.fa-trash-arrow-up::before{content:"\f829"}.fa-trash-restore::before{content:"\f829"}.fa-arrow-down-up-lock::before{content:"\e4b0"}.fa-lines-leaning::before{content:"\e51e"}.fa-ruler-combined::before{content:"\f546"}.fa-copyright::before{content:"\f1f9"}.fa-equals::before{content:"\3d"}.fa-blender::before{content:"\f517"}.fa-teeth::before{content:"\f62e"}.fa-shekel-sign::before{content:"\f20b"}.fa-ils::before{content:"\f20b"}.fa-shekel::before{content:"\f20b"}.fa-sheqel::before{content:"\f20b"}.fa-sheqel-sign::before{content:"\f20b"}.fa-map::before{content:"\f279"}.fa-rocket::before{content:"\f135"}.fa-photo-film::before{content:"\f87c"}.fa-photo-video::before{content:"\f87c"}.fa-folder-minus::before{content:"\f65d"}.fa-store::before{content:"\f54e"}.fa-arrow-trend-up::before{content:"\e098"}.fa-plug-circle-minus::before{content:"\e55e"}.fa-sign-hanging::before{content:"\f4d9"}.fa-sign::before{content:"\f4d9"}.fa-bezier-curve::before{content:"\f55b"}.fa-bell-slash::before{content:"\f1f6"}.fa-tablet::before{content:"\f3fb"}.fa-tablet-android::before{content:"\f3fb"}.fa-school-flag::before{content:"\e56e"}.fa-fill::before{content:"\f575"}.fa-angle-up::before{content:"\f106"}.fa-drumstick-bite::before{content:"\f6d7"}.fa-holly-berry::before{content:"\f7aa"}.fa-chevron-left::before{content:"\f053"}.fa-bacteria::before{content:"\e059"}.fa-hand-lizard::before{content:"\f258"}.fa-notdef::before{content:"\e1fe"}.fa-disease::before{content:"\f7fa"}.fa-briefcase-medical::before{content:"\f469"}.fa-genderless::before{content:"\f22d"}.fa-chevron-right::before{content:"\f054"}.fa-retweet::before{content:"\f079"}.fa-car-rear::before{content:"\f5de"}.fa-car-alt::before{content:"\f5de"}.fa-pump-soap::before{content:"\e06b"}.fa-video-slash::before{content:"\f4e2"}.fa-battery-quarter::before{content:"\f243"}.fa-battery-2::before{content:"\f243"}.fa-radio::before{content:"\f8d7"}.fa-baby-carriage::before{content:"\f77d"}.fa-carriage-baby::before{content:"\f77d"}.fa-traffic-light::before{content:"\f637"}.fa-thermometer::before{content:"\f491"}.fa-vr-cardboard::before{content:"\f729"}.fa-hand-middle-finger::before{content:"\f806"}.fa-percent::before{content:"\25"}.fa-percentage::before{content:"\25"}.fa-truck-moving::before{content:"\f4df"}.fa-glass-water-droplet::before{content:"\e4f5"}.fa-display::before{content:"\e163"}.fa-face-smile::before{content:"\f118"}.fa-smile::before{content:"\f118"}.fa-thumbtack::before{content:"\f08d"}.fa-thumb-tack::before{content:"\f08d"}.fa-trophy::before{content:"\f091"}.fa-person-praying::before{content:"\f683"}.fa-pray::before{content:"\f683"}.fa-hammer::before{content:"\f6e3"}.fa-hand-peace::before{content:"\f25b"}.fa-rotate::before{content:"\f2f1"}.fa-sync-alt::before{content:"\f2f1"}.fa-spinner::before{content:"\f110"}.fa-robot::before{content:"\f544"}.fa-peace::before{content:"\f67c"}.fa-gears::before{content:"\f085"}.fa-cogs::before{content:"\f085"}.fa-warehouse::before{content:"\f494"}.fa-arrow-up-right-dots::before{content:"\e4b7"}.fa-splotch::before{content:"\f5bc"}.fa-face-grin-hearts::before{content:"\f584"}.fa-grin-hearts::before{content:"\f584"}.fa-dice-four::before{content:"\f524"}.fa-sim-card::before{content:"\f7c4"}.fa-transgender::before{content:"\f225"}.fa-transgender-alt::before{content:"\f225"}.fa-mercury::before{content:"\f223"}.fa-arrow-turn-down::before{content:"\f149"}.fa-level-down::before{content:"\f149"}.fa-person-falling-burst::before{content:"\e547"}.fa-award::before{content:"\f559"}.fa-ticket-simple::before{content:"\f3ff"}.fa-ticket-alt::before{content:"\f3ff"}.fa-building::before{content:"\f1ad"}.fa-angles-left::before{content:"\f100"}.fa-angle-double-left::before{content:"\f100"}.fa-qrcode::before{content:"\f029"}.fa-clock-rotate-left::before{content:"\f1da"}.fa-history::before{content:"\f1da"}.fa-face-grin-beam-sweat::before{content:"\f583"}.fa-grin-beam-sweat::before{content:"\f583"}.fa-file-export::before{content:"\f56e"}.fa-arrow-right-from-file::before{content:"\f56e"}.fa-shield::before{content:"\f132"}.fa-shield-blank::before{content:"\f132"}.fa-arrow-up-short-wide::before{content:"\f885"}.fa-sort-amount-up-alt::before{content:"\f885"}.fa-house-medical::before{content:"\e3b2"}.fa-golf-ball-tee::before{content:"\f450"}.fa-golf-ball::before{content:"\f450"}.fa-circle-chevron-left::before{content:"\f137"}.fa-chevron-circle-left::before{content:"\f137"}.fa-house-chimney-window::before{content:"\e00d"}.fa-pen-nib::before{content:"\f5ad"}.fa-tent-arrow-turn-left::before{content:"\e580"}.fa-tents::before{content:"\e582"}.fa-wand-magic::before{content:"\f0d0"}.fa-magic::before{content:"\f0d0"}.fa-dog::before{content:"\f6d3"}.fa-carrot::before{content:"\f787"}.fa-moon::before{content:"\f186"}.fa-wine-glass-empty::before{content:"\f5ce"}.fa-wine-glass-alt::before{content:"\f5ce"}.fa-cheese::before{content:"\f7ef"}.fa-yin-yang::before{content:"\f6ad"}.fa-music::before{content:"\f001"}.fa-code-commit::before{content:"\f386"}.fa-temperature-low::before{content:"\f76b"}.fa-person-biking::before{content:"\f84a"}.fa-biking::before{content:"\f84a"}.fa-broom::before{content:"\f51a"}.fa-shield-heart::before{content:"\e574"}.fa-gopuram::before{content:"\f664"}.fa-earth-oceania::before{content:"\e47b"}.fa-globe-oceania::before{content:"\e47b"}.fa-square-xmark::before{content:"\f2d3"}.fa-times-square::before{content:"\f2d3"}.fa-xmark-square::before{content:"\f2d3"}.fa-hashtag::before{content:"\23"}.fa-up-right-and-down-left-from-center::before{content:"\f424"}.fa-expand-alt::before{content:"\f424"}.fa-oil-can::before{content:"\f613"}.fa-t::before{content:"\54"}.fa-hippo::before{content:"\f6ed"}.fa-chart-column::before{content:"\e0e3"}.fa-infinity::before{content:"\f534"}.fa-vial-circle-check::before{content:"\e596"}.fa-person-arrow-down-to-line::before{content:"\e538"}.fa-voicemail::before{content:"\f897"}.fa-fan::before{content:"\f863"}.fa-person-walking-luggage::before{content:"\e554"}.fa-up-down::before{content:"\f338"}.fa-arrows-alt-v::before{content:"\f338"}.fa-cloud-moon-rain::before{content:"\f73c"}.fa-calendar::before{content:"\f133"}.fa-trailer::before{content:"\e041"}.fa-bahai::before{content:"\f666"}.fa-haykal::before{content:"\f666"}.fa-sd-card::before{content:"\f7c2"}.fa-dragon::before{content:"\f6d5"}.fa-shoe-prints::before{content:"\f54b"}.fa-circle-plus::before{content:"\f055"}.fa-plus-circle::before{content:"\f055"}.fa-face-grin-tongue-wink::before{content:"\f58b"}.fa-grin-tongue-wink::before{content:"\f58b"}.fa-hand-holding::before{content:"\f4bd"}.fa-plug-circle-exclamation::before{content:"\e55d"}.fa-link-slash::before{content:"\f127"}.fa-chain-broken::before{content:"\f127"}.fa-chain-slash::before{content:"\f127"}.fa-unlink::before{content:"\f127"}.fa-clone::before{content:"\f24d"}.fa-person-walking-arrow-loop-left::before{content:"\e551"}.fa-arrow-up-z-a::before{content:"\f882"}.fa-sort-alpha-up-alt::before{content:"\f882"}.fa-fire-flame-curved::before{content:"\f7e4"}.fa-fire-alt::before{content:"\f7e4"}.fa-tornado::before{content:"\f76f"}.fa-file-circle-plus::before{content:"\e494"}.fa-book-quran::before{content:"\f687"}.fa-quran::before{content:"\f687"}.fa-anchor::before{content:"\f13d"}.fa-border-all::before{content:"\f84c"}.fa-face-angry::before{content:"\f556"}.fa-angry::before{content:"\f556"}.fa-cookie-bite::before{content:"\f564"}.fa-arrow-trend-down::before{content:"\e097"}.fa-rss::before{content:"\f09e"}.fa-feed::before{content:"\f09e"}.fa-draw-polygon::before{content:"\f5ee"}.fa-scale-balanced::before{content:"\f24e"}.fa-balance-scale::before{content:"\f24e"}.fa-gauge-simple-high::before{content:"\f62a"}.fa-tachometer::before{content:"\f62a"}.fa-tachometer-fast::before{content:"\f62a"}.fa-shower::before{content:"\f2cc"}.fa-desktop::before{content:"\f390"}.fa-desktop-alt::before{content:"\f390"}.fa-m::before{content:"\4d"}.fa-table-list::before{content:"\f00b"}.fa-th-list::before{content:"\f00b"}.fa-comment-sms::before{content:"\f7cd"}.fa-sms::before{content:"\f7cd"}.fa-book::before{content:"\f02d"}.fa-user-plus::before{content:"\f234"}.fa-check::before{content:"\f00c"}.fa-battery-three-quarters::before{content:"\f241"}.fa-battery-4::before{content:"\f241"}.fa-house-circle-check::before{content:"\e509"}.fa-angle-left::before{content:"\f104"}.fa-diagram-successor::before{content:"\e47a"}.fa-truck-arrow-right::before{content:"\e58b"}.fa-arrows-split-up-and-left::before{content:"\e4bc"}.fa-hand-fist::before{content:"\f6de"}.fa-fist-raised::before{content:"\f6de"}.fa-cloud-moon::before{content:"\f6c3"}.fa-briefcase::before{content:"\f0b1"}.fa-person-falling::before{content:"\e546"}.fa-image-portrait::before{content:"\f3e0"}.fa-portrait::before{content:"\f3e0"}.fa-user-tag::before{content:"\f507"}.fa-rug::before{content:"\e569"}.fa-earth-europe::before{content:"\f7a2"}.fa-globe-europe::before{content:"\f7a2"}.fa-cart-flatbed-suitcase::before{content:"\f59d"}.fa-luggage-cart::before{content:"\f59d"}.fa-rectangle-xmark::before{content:"\f410"}.fa-rectangle-times::before{content:"\f410"}.fa-times-rectangle::before{content:"\f410"}.fa-window-close::before{content:"\f410"}.fa-baht-sign::before{content:"\e0ac"}.fa-book-open::before{content:"\f518"}.fa-book-journal-whills::before{content:"\f66a"}.fa-journal-whills::before{content:"\f66a"}.fa-handcuffs::before{content:"\e4f8"}.fa-triangle-exclamation::before{content:"\f071"}.fa-exclamation-triangle::before{content:"\f071"}.fa-warning::before{content:"\f071"}.fa-database::before{content:"\f1c0"}.fa-share::before{content:"\f064"}.fa-mail-forward::before{content:"\f064"}.fa-bottle-droplet::before{content:"\e4c4"}.fa-mask-face::before{content:"\e1d7"}.fa-hill-rockslide::before{content:"\e508"}.fa-right-left::before{content:"\f362"}.fa-exchange-alt::before{content:"\f362"}.fa-paper-plane::before{content:"\f1d8"}.fa-road-circle-exclamation::before{content:"\e565"}.fa-dungeon::before{content:"\f6d9"}.fa-align-right::before{content:"\f038"}.fa-money-bill-1-wave::before{content:"\f53b"}.fa-money-bill-wave-alt::before{content:"\f53b"}.fa-life-ring::before{content:"\f1cd"}.fa-hands::before{content:"\f2a7"}.fa-sign-language::before{content:"\f2a7"}.fa-signing::before{content:"\f2a7"}.fa-calendar-day::before{content:"\f783"}.fa-water-ladder::before{content:"\f5c5"}.fa-ladder-water::before{content:"\f5c5"}.fa-swimming-pool::before{content:"\f5c5"}.fa-arrows-up-down::before{content:"\f07d"}.fa-arrows-v::before{content:"\f07d"}.fa-face-grimace::before{content:"\f57f"}.fa-grimace::before{content:"\f57f"}.fa-wheelchair-move::before{content:"\e2ce"}.fa-wheelchair-alt::before{content:"\e2ce"}.fa-turn-down::before{content:"\f3be"}.fa-level-down-alt::before{content:"\f3be"}.fa-person-walking-arrow-right::before{content:"\e552"}.fa-square-envelope::before{content:"\f199"}.fa-envelope-square::before{content:"\f199"}.fa-dice::before{content:"\f522"}.fa-bowling-ball::before{content:"\f436"}.fa-brain::before{content:"\f5dc"}.fa-bandage::before{content:"\f462"}.fa-band-aid::before{content:"\f462"}.fa-calendar-minus::before{content:"\f272"}.fa-circle-xmark::before{content:"\f057"}.fa-times-circle::before{content:"\f057"}.fa-xmark-circle::before{content:"\f057"}.fa-gifts::before{content:"\f79c"}.fa-hotel::before{content:"\f594"}.fa-earth-asia::before{content:"\f57e"}.fa-globe-asia::before{content:"\f57e"}.fa-id-card-clip::before{content:"\f47f"}.fa-id-card-alt::before{content:"\f47f"}.fa-magnifying-glass-plus::before{content:"\f00e"}.fa-search-plus::before{content:"\f00e"}.fa-thumbs-up::before{content:"\f164"}.fa-user-clock::before{content:"\f4fd"}.fa-hand-dots::before{content:"\f461"}.fa-allergies::before{content:"\f461"}.fa-file-invoice::before{content:"\f570"}.fa-window-minimize::before{content:"\f2d1"}.fa-mug-saucer::before{content:"\f0f4"}.fa-coffee::before{content:"\f0f4"}.fa-brush::before{content:"\f55d"}.fa-mask::before{content:"\f6fa"}.fa-magnifying-glass-minus::before{content:"\f010"}.fa-search-minus::before{content:"\f010"}.fa-ruler-vertical::before{content:"\f548"}.fa-user-large::before{content:"\f406"}.fa-user-alt::before{content:"\f406"}.fa-train-tram::before{content:"\e5b4"}.fa-user-nurse::before{content:"\f82f"}.fa-syringe::before{content:"\f48e"}.fa-cloud-sun::before{content:"\f6c4"}.fa-stopwatch-20::before{content:"\e06f"}.fa-square-full::before{content:"\f45c"}.fa-magnet::before{content:"\f076"}.fa-jar::before{content:"\e516"}.fa-note-sticky::before{content:"\f249"}.fa-sticky-note::before{content:"\f249"}.fa-bug-slash::before{content:"\e490"}.fa-arrow-up-from-water-pump::before{content:"\e4b6"}.fa-bone::before{content:"\f5d7"}.fa-user-injured::before{content:"\f728"}.fa-face-sad-tear::before{content:"\f5b4"}.fa-sad-tear::before{content:"\f5b4"}.fa-plane::before{content:"\f072"}.fa-tent-arrows-down::before{content:"\e581"}.fa-exclamation::before{content:"\21"}.fa-arrows-spin::before{content:"\e4bb"}.fa-print::before{content:"\f02f"}.fa-turkish-lira-sign::before{content:"\e2bb"}.fa-try::before{content:"\e2bb"}.fa-turkish-lira::before{content:"\e2bb"}.fa-dollar-sign::before{content:"\24"}.fa-dollar::before{content:"\24"}.fa-usd::before{content:"\24"}.fa-x::before{content:"\58"}.fa-magnifying-glass-dollar::before{content:"\f688"}.fa-search-dollar::before{content:"\f688"}.fa-users-gear::before{content:"\f509"}.fa-users-cog::before{content:"\f509"}.fa-person-military-pointing::before{content:"\e54a"}.fa-building-columns::before{content:"\f19c"}.fa-bank::before{content:"\f19c"}.fa-institution::before{content:"\f19c"}.fa-museum::before{content:"\f19c"}.fa-university::before{content:"\f19c"}.fa-umbrella::before{content:"\f0e9"}.fa-trowel::before{content:"\e589"}.fa-d::before{content:"\44"}.fa-stapler::before{content:"\e5af"}.fa-masks-theater::before{content:"\f630"}.fa-theater-masks::before{content:"\f630"}.fa-kip-sign::before{content:"\e1c4"}.fa-hand-point-left::before{content:"\f0a5"}.fa-handshake-simple::before{content:"\f4c6"}.fa-handshake-alt::before{content:"\f4c6"}.fa-jet-fighter::before{content:"\f0fb"}.fa-fighter-jet::before{content:"\f0fb"}.fa-square-share-nodes::before{content:"\f1e1"}.fa-share-alt-square::before{content:"\f1e1"}.fa-barcode::before{content:"\f02a"}.fa-plus-minus::before{content:"\e43c"}.fa-video::before{content:"\f03d"}.fa-video-camera::before{content:"\f03d"}.fa-graduation-cap::before{content:"\f19d"}.fa-mortar-board::before{content:"\f19d"}.fa-hand-holding-medical::before{content:"\e05c"}.fa-person-circle-check::before{content:"\e53e"}.fa-turn-up::before{content:"\f3bf"}.fa-level-up-alt::before{content:"\f3bf"}.sr-only,.fa-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.sr-only-focusable:not(:focus),.fa-sr-only-focusable:not(:focus){position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}/*!* Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com +* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) +* Copyright 2023 Fonticons, Inc.*/:root,:host{--fa-style-family-classic:'Font Awesome 6 Free';--fa-font-solid:normal 900 1em/1 'Font Awesome 6 Free'}@font-face{font-family:'font awesome 6 free';font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.woff2)format("woff2"),url(../webfonts/fa-solid-900.ttf)format("truetype")}.fas,.td-offline-search-results__close-button:after,.fa-solid{font-weight:900}/*!* Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com +* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) +* Copyright 2023 Fonticons, Inc.*/:root,:host{--fa-style-family-brands:'Font Awesome 6 Brands';--fa-font-brands:normal 400 1em/1 'Font Awesome 6 Brands'}@font-face{font-family:'font awesome 6 brands';font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-brands-400.woff2)format("woff2"),url(../webfonts/fa-brands-400.ttf)format("truetype")}.fab,.fa-brands{font-weight:400}.fa-monero:before{content:"\f3d0"}.fa-hooli:before{content:"\f427"}.fa-yelp:before{content:"\f1e9"}.fa-cc-visa:before{content:"\f1f0"}.fa-lastfm:before{content:"\f202"}.fa-shopware:before{content:"\f5b5"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-aws:before{content:"\f375"}.fa-redhat:before{content:"\f7bc"}.fa-yoast:before{content:"\f2b1"}.fa-cloudflare:before{content:"\e07d"}.fa-ups:before{content:"\f7e0"}.fa-pixiv:before{content:"\e640"}.fa-wpexplorer:before{content:"\f2de"}.fa-dyalog:before{content:"\f399"}.fa-bity:before{content:"\f37a"}.fa-stackpath:before{content:"\f842"}.fa-buysellads:before{content:"\f20d"}.fa-first-order:before{content:"\f2b0"}.fa-modx:before{content:"\f285"}.fa-guilded:before{content:"\e07e"}.fa-vnv:before{content:"\f40b"}.fa-square-js:before{content:"\f3b9"}.fa-js-square:before{content:"\f3b9"}.fa-microsoft:before{content:"\f3ca"}.fa-qq:before{content:"\f1d6"}.fa-orcid:before{content:"\f8d2"}.fa-java:before{content:"\f4e4"}.fa-invision:before{content:"\f7b0"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-centercode:before{content:"\f380"}.fa-glide-g:before{content:"\f2a6"}.fa-drupal:before{content:"\f1a9"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-unity:before{content:"\e049"}.fa-whmcs:before{content:"\f40d"}.fa-rocketchat:before{content:"\f3e8"}.fa-vk:before{content:"\f189"}.fa-untappd:before{content:"\f405"}.fa-mailchimp:before{content:"\f59e"}.fa-css3-alt:before{content:"\f38b"}.fa-square-reddit:before{content:"\f1a2"}.fa-reddit-square:before{content:"\f1a2"}.fa-vimeo-v:before{content:"\f27d"}.fa-contao:before{content:"\f26d"}.fa-square-font-awesome:before{content:"\e5ad"}.fa-deskpro:before{content:"\f38f"}.fa-brave:before{content:"\e63c"}.fa-sistrix:before{content:"\f3ee"}.fa-square-instagram:before{content:"\e055"}.fa-instagram-square:before{content:"\e055"}.fa-battle-net:before{content:"\f835"}.fa-the-red-yeti:before{content:"\f69d"}.fa-square-hacker-news:before{content:"\f3af"}.fa-hacker-news-square:before{content:"\f3af"}.fa-edge:before{content:"\f282"}.fa-threads:before{content:"\e618"}.fa-napster:before{content:"\f3d2"}.fa-square-snapchat:before{content:"\f2ad"}.fa-snapchat-square:before{content:"\f2ad"}.fa-google-plus-g:before{content:"\f0d5"}.fa-artstation:before{content:"\f77a"}.fa-markdown:before{content:"\f60f"}.fa-sourcetree:before{content:"\f7d3"}.fa-google-plus:before{content:"\f2b3"}.fa-diaspora:before{content:"\f791"}.fa-foursquare:before{content:"\f180"}.fa-stack-overflow:before{content:"\f16c"}.fa-github-alt:before{content:"\f113"}.fa-phoenix-squadron:before{content:"\f511"}.fa-pagelines:before{content:"\f18c"}.fa-algolia:before{content:"\f36c"}.fa-red-river:before{content:"\f3e3"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-safari:before{content:"\f267"}.fa-google:before{content:"\f1a0"}.fa-square-font-awesome-stroke:before{content:"\f35c"}.fa-font-awesome-alt:before{content:"\f35c"}.fa-atlassian:before{content:"\f77b"}.fa-linkedin-in:before{content:"\f0e1"}.fa-digital-ocean:before{content:"\f391"}.fa-nimblr:before{content:"\f5a8"}.fa-chromecast:before{content:"\f838"}.fa-evernote:before{content:"\f839"}.fa-hacker-news:before{content:"\f1d4"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-adversal:before{content:"\f36a"}.fa-creative-commons:before{content:"\f25e"}.fa-watchman-monitoring:before{content:"\e087"}.fa-fonticons:before{content:"\f280"}.fa-weixin:before{content:"\f1d7"}.fa-shirtsinbulk:before{content:"\f214"}.fa-codepen:before{content:"\f1cb"}.fa-git-alt:before{content:"\f841"}.fa-lyft:before{content:"\f3c3"}.fa-rev:before{content:"\f5b2"}.fa-windows:before{content:"\f17a"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-square-viadeo:before{content:"\f2aa"}.fa-viadeo-square:before{content:"\f2aa"}.fa-meetup:before{content:"\f2e0"}.fa-centos:before{content:"\f789"}.fa-adn:before{content:"\f170"}.fa-cloudsmith:before{content:"\f384"}.fa-opensuse:before{content:"\e62b"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-square-dribbble:before{content:"\f397"}.fa-dribbble-square:before{content:"\f397"}.fa-codiepie:before{content:"\f284"}.fa-node:before{content:"\f419"}.fa-mix:before{content:"\f3cb"}.fa-steam:before{content:"\f1b6"}.fa-cc-apple-pay:before{content:"\f416"}.fa-scribd:before{content:"\f28a"}.fa-debian:before{content:"\e60b"}.fa-openid:before{content:"\f19b"}.fa-instalod:before{content:"\e081"}.fa-expeditedssl:before{content:"\f23e"}.fa-sellcast:before{content:"\f2da"}.fa-square-twitter:before{content:"\f081"}.fa-twitter-square:before{content:"\f081"}.fa-r-project:before{content:"\f4f7"}.fa-delicious:before{content:"\f1a5"}.fa-freebsd:before{content:"\f3a4"}.fa-vuejs:before{content:"\f41f"}.fa-accusoft:before{content:"\f369"}.fa-ioxhost:before{content:"\f208"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-app-store:before{content:"\f36f"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-itunes-note:before{content:"\f3b5"}.fa-golang:before{content:"\e40f"}.fa-kickstarter:before{content:"\f3bb"}.fa-grav:before{content:"\f2d6"}.fa-weibo:before{content:"\f18a"}.fa-uncharted:before{content:"\e084"}.fa-firstdraft:before{content:"\f3a1"}.fa-square-youtube:before{content:"\f431"}.fa-youtube-square:before{content:"\f431"}.fa-wikipedia-w:before{content:"\f266"}.fa-wpressr:before{content:"\f3e4"}.fa-rendact:before{content:"\f3e4"}.fa-angellist:before{content:"\f209"}.fa-galactic-republic:before{content:"\f50c"}.fa-nfc-directional:before{content:"\e530"}.fa-skype:before{content:"\f17e"}.fa-joget:before{content:"\f3b7"}.fa-fedora:before{content:"\f798"}.fa-stripe-s:before{content:"\f42a"}.fa-meta:before{content:"\e49b"}.fa-laravel:before{content:"\f3bd"}.fa-hotjar:before{content:"\f3b1"}.fa-bluetooth-b:before{content:"\f294"}.fa-square-letterboxd:before{content:"\e62e"}.fa-sticker-mule:before{content:"\f3f7"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-hips:before{content:"\f452"}.fa-behance:before{content:"\f1b4"}.fa-reddit:before{content:"\f1a1"}.fa-discord:before{content:"\f392"}.fa-chrome:before{content:"\f268"}.fa-app-store-ios:before{content:"\f370"}.fa-cc-discover:before{content:"\f1f2"}.fa-wpbeginner:before{content:"\f297"}.fa-confluence:before{content:"\f78d"}.fa-shoelace:before{content:"\e60c"}.fa-mdb:before{content:"\f8ca"}.fa-dochub:before{content:"\f394"}.fa-accessible-icon:before{content:"\f368"}.fa-ebay:before{content:"\f4f4"}.fa-amazon:before{content:"\f270"}.fa-unsplash:before{content:"\e07c"}.fa-yarn:before{content:"\f7e3"}.fa-square-steam:before{content:"\f1b7"}.fa-steam-square:before{content:"\f1b7"}.fa-500px:before{content:"\f26e"}.fa-square-vimeo:before{content:"\f194"}.fa-vimeo-square:before{content:"\f194"}.fa-asymmetrik:before{content:"\f372"}.fa-font-awesome:before{content:"\f2b4"}.fa-font-awesome-flag:before{content:"\f2b4"}.fa-font-awesome-logo-full:before{content:"\f2b4"}.fa-gratipay:before{content:"\f184"}.fa-apple:before{content:"\f179"}.fa-hive:before{content:"\e07f"}.fa-gitkraken:before{content:"\f3a6"}.fa-keybase:before{content:"\f4f5"}.fa-apple-pay:before{content:"\f415"}.fa-padlet:before{content:"\e4a0"}.fa-amazon-pay:before{content:"\f42c"}.fa-square-github:before{content:"\f092"}.fa-github-square:before{content:"\f092"}.fa-stumbleupon:before{content:"\f1a4"}.fa-fedex:before{content:"\f797"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-shopify:before{content:"\e057"}.fa-neos:before{content:"\f612"}.fa-square-threads:before{content:"\e619"}.fa-hackerrank:before{content:"\f5f7"}.fa-researchgate:before{content:"\f4f8"}.fa-swift:before{content:"\f8e1"}.fa-angular:before{content:"\f420"}.fa-speakap:before{content:"\f3f3"}.fa-angrycreative:before{content:"\f36e"}.fa-y-combinator:before{content:"\f23b"}.fa-empire:before{content:"\f1d1"}.fa-envira:before{content:"\f299"}.fa-google-scholar:before{content:"\e63b"}.fa-square-gitlab:before{content:"\e5ae"}.fa-gitlab-square:before{content:"\e5ae"}.fa-studiovinari:before{content:"\f3f8"}.fa-pied-piper:before{content:"\f2ae"}.fa-wordpress:before{content:"\f19a"}.fa-product-hunt:before{content:"\f288"}.fa-firefox:before{content:"\f269"}.fa-linode:before{content:"\f2b8"}.fa-goodreads:before{content:"\f3a8"}.fa-square-odnoklassniki:before{content:"\f264"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-jsfiddle:before{content:"\f1cc"}.fa-sith:before{content:"\f512"}.fa-themeisle:before{content:"\f2b2"}.fa-page4:before{content:"\f3d7"}.fa-hashnode:before{content:"\e499"}.fa-react:before{content:"\f41b"}.fa-cc-paypal:before{content:"\f1f4"}.fa-squarespace:before{content:"\f5be"}.fa-cc-stripe:before{content:"\f1f5"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-bitcoin:before{content:"\f379"}.fa-keycdn:before{content:"\f3ba"}.fa-opera:before{content:"\f26a"}.fa-itch-io:before{content:"\f83a"}.fa-umbraco:before{content:"\f8e8"}.fa-galactic-senate:before{content:"\f50d"}.fa-ubuntu:before{content:"\f7df"}.fa-draft2digital:before{content:"\f396"}.fa-stripe:before{content:"\f429"}.fa-houzz:before{content:"\f27c"}.fa-gg:before{content:"\f260"}.fa-dhl:before{content:"\f790"}.fa-square-pinterest:before{content:"\f0d3"}.fa-pinterest-square:before{content:"\f0d3"}.fa-xing:before{content:"\f168"}.fa-blackberry:before{content:"\f37b"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-playstation:before{content:"\f3df"}.fa-quinscape:before{content:"\f459"}.fa-less:before{content:"\f41d"}.fa-blogger-b:before{content:"\f37d"}.fa-opencart:before{content:"\f23d"}.fa-vine:before{content:"\f1ca"}.fa-signal-messenger:before{content:"\e663"}.fa-paypal:before{content:"\f1ed"}.fa-gitlab:before{content:"\f296"}.fa-typo3:before{content:"\f42b"}.fa-reddit-alien:before{content:"\f281"}.fa-yahoo:before{content:"\f19e"}.fa-dailymotion:before{content:"\e052"}.fa-affiliatetheme:before{content:"\f36b"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-bootstrap:before{content:"\f836"}.fa-odnoklassniki:before{content:"\f263"}.fa-nfc-symbol:before{content:"\e531"}.fa-mintbit:before{content:"\e62f"}.fa-ethereum:before{content:"\f42e"}.fa-speaker-deck:before{content:"\f83c"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-patreon:before{content:"\f3d9"}.fa-avianex:before{content:"\f374"}.fa-ello:before{content:"\f5f1"}.fa-gofore:before{content:"\f3a7"}.fa-bimobject:before{content:"\f378"}.fa-brave-reverse:before{content:"\e63d"}.fa-facebook-f:before{content:"\f39e"}.fa-square-google-plus:before{content:"\f0d4"}.fa-google-plus-square:before{content:"\f0d4"}.fa-mandalorian:before{content:"\f50f"}.fa-first-order-alt:before{content:"\f50a"}.fa-osi:before{content:"\f41a"}.fa-google-wallet:before{content:"\f1ee"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-periscope:before{content:"\f3da"}.fa-fulcrum:before{content:"\f50b"}.fa-cloudscale:before{content:"\f383"}.fa-forumbee:before{content:"\f211"}.fa-mizuni:before{content:"\f3cc"}.fa-schlix:before{content:"\f3ea"}.fa-square-xing:before{content:"\f169"}.fa-xing-square:before{content:"\f169"}.fa-bandcamp:before{content:"\f2d5"}.fa-wpforms:before{content:"\f298"}.fa-cloudversify:before{content:"\f385"}.fa-usps:before{content:"\f7e1"}.fa-megaport:before{content:"\f5a3"}.fa-magento:before{content:"\f3c4"}.fa-spotify:before{content:"\f1bc"}.fa-optin-monster:before{content:"\f23c"}.fa-fly:before{content:"\f417"}.fa-aviato:before{content:"\f421"}.fa-itunes:before{content:"\f3b4"}.fa-cuttlefish:before{content:"\f38c"}.fa-blogger:before{content:"\f37c"}.fa-flickr:before{content:"\f16e"}.fa-viber:before{content:"\f409"}.fa-soundcloud:before{content:"\f1be"}.fa-digg:before{content:"\f1a6"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-letterboxd:before{content:"\e62d"}.fa-symfony:before{content:"\f83d"}.fa-maxcdn:before{content:"\f136"}.fa-etsy:before{content:"\f2d7"}.fa-facebook-messenger:before{content:"\f39f"}.fa-audible:before{content:"\f373"}.fa-think-peaks:before{content:"\f731"}.fa-bilibili:before{content:"\e3d9"}.fa-erlang:before{content:"\f39d"}.fa-x-twitter:before{content:"\e61b"}.fa-cotton-bureau:before{content:"\f89e"}.fa-dashcube:before{content:"\f210"}.fa-42-group:before{content:"\e080"}.fa-innosoft:before{content:"\e080"}.fa-stack-exchange:before{content:"\f18d"}.fa-elementor:before{content:"\f430"}.fa-square-pied-piper:before{content:"\e01e"}.fa-pied-piper-square:before{content:"\e01e"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-palfed:before{content:"\f3d8"}.fa-superpowers:before{content:"\f2dd"}.fa-resolving:before{content:"\f3e7"}.fa-xbox:before{content:"\f412"}.fa-searchengin:before{content:"\f3eb"}.fa-tiktok:before{content:"\e07b"}.fa-square-facebook:before{content:"\f082"}.fa-facebook-square:before{content:"\f082"}.fa-renren:before{content:"\f18b"}.fa-linux:before{content:"\f17c"}.fa-glide:before{content:"\f2a5"}.fa-linkedin:before{content:"\f08c"}.fa-hubspot:before{content:"\f3b2"}.fa-deploydog:before{content:"\f38e"}.fa-twitch:before{content:"\f1e8"}.fa-ravelry:before{content:"\f2d9"}.fa-mixer:before{content:"\e056"}.fa-square-lastfm:before{content:"\f203"}.fa-lastfm-square:before{content:"\f203"}.fa-vimeo:before{content:"\f40a"}.fa-mendeley:before{content:"\f7b3"}.fa-uniregistry:before{content:"\f404"}.fa-figma:before{content:"\f799"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-dropbox:before{content:"\f16b"}.fa-instagram:before{content:"\f16d"}.fa-cmplid:before{content:"\e360"}.fa-upwork:before{content:"\e641"}.fa-facebook:before{content:"\f09a"}.fa-gripfire:before{content:"\f3ac"}.fa-jedi-order:before{content:"\f50e"}.fa-uikit:before{content:"\f403"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-phabricator:before{content:"\f3db"}.fa-ussunnah:before{content:"\f407"}.fa-earlybirds:before{content:"\f39a"}.fa-trade-federation:before{content:"\f513"}.fa-autoprefixer:before{content:"\f41c"}.fa-whatsapp:before{content:"\f232"}.fa-slideshare:before{content:"\f1e7"}.fa-google-play:before{content:"\f3ab"}.fa-viadeo:before{content:"\f2a9"}.fa-line:before{content:"\f3c0"}.fa-google-drive:before{content:"\f3aa"}.fa-servicestack:before{content:"\f3ec"}.fa-simplybuilt:before{content:"\f215"}.fa-bitbucket:before{content:"\f171"}.fa-imdb:before{content:"\f2d8"}.fa-deezer:before{content:"\e077"}.fa-raspberry-pi:before{content:"\f7bb"}.fa-jira:before{content:"\f7b1"}.fa-docker:before{content:"\f395"}.fa-screenpal:before{content:"\e570"}.fa-bluetooth:before{content:"\f293"}.fa-gitter:before{content:"\f426"}.fa-d-and-d:before{content:"\f38d"}.fa-microblog:before{content:"\e01a"}.fa-cc-diners-club:before{content:"\f24c"}.fa-gg-circle:before{content:"\f261"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-yandex:before{content:"\f413"}.fa-readme:before{content:"\f4d5"}.fa-html5:before{content:"\f13b"}.fa-sellsy:before{content:"\f213"}.fa-sass:before{content:"\f41e"}.fa-wirsindhandwerk:before{content:"\e2d0"}.fa-wsh:before{content:"\e2d0"}.fa-buromobelexperte:before{content:"\f37f"}.fa-salesforce:before{content:"\f83b"}.fa-octopus-deploy:before{content:"\e082"}.fa-medapps:before{content:"\f3c6"}.fa-ns8:before{content:"\f3d5"}.fa-pinterest-p:before{content:"\f231"}.fa-apper:before{content:"\f371"}.fa-fort-awesome:before{content:"\f286"}.fa-waze:before{content:"\f83f"}.fa-cc-jcb:before{content:"\f24b"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ab"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-rust:before{content:"\e07a"}.fa-wix:before{content:"\f5cf"}.fa-square-behance:before{content:"\f1b5"}.fa-behance-square:before{content:"\f1b5"}.fa-supple:before{content:"\f3f9"}.fa-webflow:before{content:"\e65c"}.fa-rebel:before{content:"\f1d0"}.fa-css3:before{content:"\f13c"}.fa-staylinked:before{content:"\f3f5"}.fa-kaggle:before{content:"\f5fa"}.fa-space-awesome:before{content:"\e5ac"}.fa-deviantart:before{content:"\f1bd"}.fa-cpanel:before{content:"\f388"}.fa-goodreads-g:before{content:"\f3a9"}.fa-square-git:before{content:"\f1d2"}.fa-git-square:before{content:"\f1d2"}.fa-square-tumblr:before{content:"\f174"}.fa-tumblr-square:before{content:"\f174"}.fa-trello:before{content:"\f181"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-get-pocket:before{content:"\f265"}.fa-perbyte:before{content:"\e083"}.fa-grunt:before{content:"\f3ad"}.fa-weebly:before{content:"\f5cc"}.fa-connectdevelop:before{content:"\f20e"}.fa-leanpub:before{content:"\f212"}.fa-black-tie:before{content:"\f27e"}.fa-themeco:before{content:"\f5c6"}.fa-python:before{content:"\f3e2"}.fa-android:before{content:"\f17b"}.fa-bots:before{content:"\e340"}.fa-free-code-camp:before{content:"\f2c5"}.fa-hornbill:before{content:"\f592"}.fa-js:before{content:"\f3b8"}.fa-ideal:before{content:"\e013"}.fa-git:before{content:"\f1d3"}.fa-dev:before{content:"\f6cc"}.fa-sketch:before{content:"\f7c6"}.fa-yandex-international:before{content:"\f414"}.fa-cc-amex:before{content:"\f1f3"}.fa-uber:before{content:"\f402"}.fa-github:before{content:"\f09b"}.fa-php:before{content:"\f457"}.fa-alipay:before{content:"\f642"}.fa-youtube:before{content:"\f167"}.fa-skyatlas:before{content:"\f216"}.fa-firefox-browser:before{content:"\e007"}.fa-replyd:before{content:"\f3e6"}.fa-suse:before{content:"\f7d6"}.fa-jenkins:before{content:"\f3b6"}.fa-twitter:before{content:"\f099"}.fa-rockrms:before{content:"\f3e9"}.fa-pinterest:before{content:"\f0d2"}.fa-buffer:before{content:"\f837"}.fa-npm:before{content:"\f3d4"}.fa-yammer:before{content:"\f840"}.fa-btc:before{content:"\f15a"}.fa-dribbble:before{content:"\f17d"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-internet-explorer:before{content:"\f26b"}.fa-stubber:before{content:"\e5c7"}.fa-telegram:before{content:"\f2c6"}.fa-telegram-plane:before{content:"\f2c6"}.fa-old-republic:before{content:"\f510"}.fa-odysee:before{content:"\e5c6"}.fa-square-whatsapp:before{content:"\f40c"}.fa-whatsapp-square:before{content:"\f40c"}.fa-node-js:before{content:"\f3d3"}.fa-edge-legacy:before{content:"\e078"}.fa-slack:before{content:"\f198"}.fa-slack-hash:before{content:"\f198"}.fa-medrt:before{content:"\f3c8"}.fa-usb:before{content:"\f287"}.fa-tumblr:before{content:"\f173"}.fa-vaadin:before{content:"\f408"}.fa-quora:before{content:"\f2c4"}.fa-square-x-twitter:before{content:"\e61a"}.fa-reacteurope:before{content:"\f75d"}.fa-medium:before{content:"\f23a"}.fa-medium-m:before{content:"\f23a"}.fa-amilia:before{content:"\f36d"}.fa-mixcloud:before{content:"\f289"}.fa-flipboard:before{content:"\f44d"}.fa-viacoin:before{content:"\f237"}.fa-critical-role:before{content:"\f6c9"}.fa-sitrox:before{content:"\e44a"}.fa-discourse:before{content:"\f393"}.fa-joomla:before{content:"\f1aa"}.fa-mastodon:before{content:"\f4f6"}.fa-airbnb:before{content:"\f834"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-buy-n-large:before{content:"\f8a6"}.fa-gulp:before{content:"\f3ae"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-strava:before{content:"\f428"}.fa-ember:before{content:"\f423"}.fa-canadian-maple-leaf:before{content:"\f785"}.fa-teamspeak:before{content:"\f4f9"}.fa-pushed:before{content:"\f3e1"}.fa-wordpress-simple:before{content:"\f411"}.fa-nutritionix:before{content:"\f3d6"}.fa-wodu:before{content:"\e088"}.fa-google-pay:before{content:"\e079"}.fa-intercom:before{content:"\f7af"}.fa-zhihu:before{content:"\f63f"}.fa-korvue:before{content:"\f42f"}.fa-pix:before{content:"\e43a"}.fa-steam-symbol:before{content:"\f3f6"}.td-border-top{border:none;border-top:1px solid #eee}.td-border-none{border:none}.td-block-padding,.td-default main section{padding-top:4rem;padding-bottom:4rem}@media(min-width:768px){.td-block-padding,.td-default main section{padding-top:5rem;padding-bottom:5rem}}.td-overlay{position:relative}.td-overlay::after{content:"";position:absolute;top:0;right:0;bottom:0;left:0}.td-overlay--dark::after{background-color:rgba(64,63,76,.3)}.td-overlay--light::after{background-color:rgba(211,243,238,.3)}.td-overlay__inner{position:relative;z-index:1}@media(min-width:992px){.td-max-width-on-larger-screens,.td-card.card,.td-content .td-card.highlight,.td-card-group.card-group,.td-content>.tab-content .tab-pane,.td-content .footnotes,.td-content>.alert,.td-content>.highlight,.td-content>.lead,.td-content>.td-table,.td-box .td-content>table,.td-content>table,.td-content>blockquote,.td-content>dl dd,.td-content>h1,.td-content>.h1,.td-content>h2,.td-content>.h2,.td-content>ol,.td-content>p,.td-content>pre,.td-content>ul{max-width:80%}}.-bg-blue{color:#fff;background-color:#0d6efd}.-bg-blue p:not(.p-initial)>a{color:#81b3fe}.-bg-blue p:not(.p-initial)>a:hover{color:#094db1}.-text-blue{color:#0d6efd}.-bg-indigo{color:#fff;background-color:#6610f2}.-bg-indigo p:not(.p-initial)>a{color:#85b6fe}.-bg-indigo p:not(.p-initial)>a:hover{color:#094db1}.-text-indigo{color:#6610f2}.-bg-purple{color:#fff;background-color:#6f42c1}.-bg-purple p:not(.p-initial)>a{color:#84b5fe}.-bg-purple p:not(.p-initial)>a:hover{color:#094db1}.-text-purple{color:#6f42c1}.-bg-pink{color:#fff;background-color:#d63384}.-bg-pink p:not(.p-initial)>a{color:#81b4fe}.-bg-pink p:not(.p-initial)>a:hover{color:#094db1}.-text-pink{color:#d63384}.-bg-red{color:#fff;background-color:#dc3545}.-bg-red p:not(.p-initial)>a{color:#7db1fe}.-bg-red p:not(.p-initial)>a:hover{color:#094db1}.-text-red{color:#dc3545}.-bg-orange{color:#000;background-color:#fd7e14}.-bg-orange p:not(.p-initial)>a{color:#073b87}.-bg-orange p:not(.p-initial)>a:hover{color:#094db1}.-text-orange{color:#fd7e14}.-bg-yellow{color:#000;background-color:#ffc107}.-bg-yellow p:not(.p-initial)>a{color:#073982}.-bg-yellow p:not(.p-initial)>a:hover{color:#094db1}.-text-yellow{color:#ffc107}.-bg-green{color:#fff;background-color:#198754}.-bg-green p:not(.p-initial)>a{color:#b3d2fe}.-bg-green p:not(.p-initial)>a:hover{color:#094db1}.-text-green{color:#198754}.-bg-teal{color:#000;background-color:#20c997}.-bg-teal p:not(.p-initial)>a{color:#063274}.-bg-teal p:not(.p-initial)>a:hover{color:#094db1}.-text-teal{color:#20c997}.-bg-cyan{color:#000;background-color:#0dcaf0}.-bg-cyan p:not(.p-initial)>a{color:#06377e}.-bg-cyan p:not(.p-initial)>a:hover{color:#094db1}.-text-cyan{color:#0dcaf0}.-bg-black{color:#fff;background-color:#000}.-bg-black p:not(.p-initial)>a{color:#fff}.-bg-black p:not(.p-initial)>a:hover{color:#094db1}.-text-black{color:#000}.-bg-white{color:#000;background-color:#fff}.-bg-white p:not(.p-initial)>a{color:#0d6efd}.-bg-white p:not(.p-initial)>a:hover{color:#094db1}.-text-white{color:#fff}.-bg-gray{color:#fff;background-color:#6c757d}.-bg-gray p:not(.p-initial)>a{color:#90bdfe}.-bg-gray p:not(.p-initial)>a:hover{color:#094db1}.-text-gray{color:#6c757d}.-bg-gray-dark{color:#fff;background-color:#343a40}.-bg-gray-dark p:not(.p-initial)>a{color:#c8deff}.-bg-gray-dark p:not(.p-initial)>a:hover{color:#094db1}.-text-gray-dark{color:#343a40}.-bg-primary{color:#fff;background-color:#081b4b}.-bg-primary p:not(.p-initial)>a{color:#d8e7ff}.-bg-primary p:not(.p-initial)>a:hover{color:#094db1}.-text-primary{color:#081b4b}.-bg-secondary{color:#000;background-color:#fff}.-bg-secondary p:not(.p-initial)>a{color:#0d6efd}.-bg-secondary p:not(.p-initial)>a:hover{color:#094db1}.-text-secondary{color:#fff}.-bg-success{color:#000;background-color:#3772ff}.-bg-success p:not(.p-initial)>a{color:#08439a}.-bg-success p:not(.p-initial)>a:hover{color:#094db1}.-text-success{color:#3772ff}.-bg-info{color:#000;background-color:#c0e0de}.-bg-info p:not(.p-initial)>a{color:#0b5ace}.-bg-info p:not(.p-initial)>a:hover{color:#094db1}.-text-info{color:#c0e0de}.-bg-warning{color:#000;background-color:#ed6a5a}.-bg-warning p:not(.p-initial)>a{color:#0847a2}.-bg-warning p:not(.p-initial)>a:hover{color:#094db1}.-text-warning{color:#ed6a5a}.-bg-danger{color:#000;background-color:#ed6a5a}.-bg-danger p:not(.p-initial)>a{color:#0847a2}.-bg-danger p:not(.p-initial)>a:hover{color:#094db1}.-text-danger{color:#ed6a5a}.-bg-light{color:#000;background-color:#d3f3ee}.-bg-light p:not(.p-initial)>a{color:#0c62e1}.-bg-light p:not(.p-initial)>a:hover{color:#094db1}.-text-light{color:#d3f3ee}.-bg-dark{color:#fff;background-color:#403f4c}.-bg-dark p:not(.p-initial)>a{color:#bdd7fe}.-bg-dark p:not(.p-initial)>a:hover{color:#094db1}.-text-dark{color:#403f4c}.-bg-100{color:#000;background-color:#f8f9fa}.-bg-100 p:not(.p-initial)>a{color:#0d6bf7}.-bg-100 p:not(.p-initial)>a:hover{color:#094db1}.-text-100{color:#f8f9fa}.-bg-200{color:#000;background-color:#e9ecef}.-bg-200 p:not(.p-initial)>a{color:#0c66ea}.-bg-200 p:not(.p-initial)>a:hover{color:#094db1}.-text-200{color:#e9ecef}.-bg-300{color:#000;background-color:#dee2e6}.-bg-300 p:not(.p-initial)>a{color:#0c61e0}.-bg-300 p:not(.p-initial)>a:hover{color:#094db1}.-text-300{color:#dee2e6}.-bg-400{color:#000;background-color:#ced4da}.-bg-400 p:not(.p-initial)>a{color:#0b5bd2}.-bg-400 p:not(.p-initial)>a:hover{color:#094db1}.-text-400{color:#ced4da}.-bg-500{color:#000;background-color:#adb5bd}.-bg-500 p:not(.p-initial)>a{color:#094eb4}.-bg-500 p:not(.p-initial)>a:hover{color:#094db1}.-text-500{color:#adb5bd}.-bg-600{color:#fff;background-color:#6c757d}.-bg-600 p:not(.p-initial)>a{color:#90bdfe}.-bg-600 p:not(.p-initial)>a:hover{color:#094db1}.-text-600{color:#6c757d}.-bg-700{color:#fff;background-color:#495057}.-bg-700 p:not(.p-initial)>a{color:#b3d2fe}.-bg-700 p:not(.p-initial)>a:hover{color:#094db1}.-text-700{color:#495057}.-bg-800{color:#fff;background-color:#343a40}.-bg-800 p:not(.p-initial)>a{color:#c8deff}.-bg-800 p:not(.p-initial)>a:hover{color:#094db1}.-text-800{color:#343a40}.-bg-900{color:#fff;background-color:#212529}.-bg-900 p:not(.p-initial)>a{color:#dceaff}.-bg-900 p:not(.p-initial)>a:hover{color:#094db1}.-text-900{color:#212529}.-bg-0{color:#fff;background-color:#403f4c}.-bg-0 p:not(.p-initial)>a{color:#bdd7fe}.-bg-0 p:not(.p-initial)>a:hover{color:#094db1}.-text-0{color:#403f4c}.-bg-1{color:#fff;background-color:#081b4b}.-bg-1 p:not(.p-initial)>a{color:#d8e7ff}.-bg-1 p:not(.p-initial)>a:hover{color:#094db1}.-text-1{color:#081b4b}.-bg-2{color:#000;background-color:#fff}.-bg-2 p:not(.p-initial)>a{color:#0d6efd}.-bg-2 p:not(.p-initial)>a:hover{color:#094db1}.-text-2{color:#fff}.-bg-3{color:#000;background-color:#c0e0de}.-bg-3 p:not(.p-initial)>a{color:#0b5ace}.-bg-3 p:not(.p-initial)>a:hover{color:#094db1}.-text-3{color:#c0e0de}.-bg-4{color:#000;background-color:#fff}.-bg-4 p:not(.p-initial)>a{color:#0d6efd}.-bg-4 p:not(.p-initial)>a:hover{color:#094db1}.-text-4{color:#fff}.-bg-5{color:#fff;background-color:#6c757d}.-bg-5 p:not(.p-initial)>a{color:#90bdfe}.-bg-5 p:not(.p-initial)>a:hover{color:#094db1}.-text-5{color:#6c757d}.-bg-6{color:#000;background-color:#3772ff}.-bg-6 p:not(.p-initial)>a{color:#08439a}.-bg-6 p:not(.p-initial)>a:hover{color:#094db1}.-text-6{color:#3772ff}.-bg-7{color:#000;background-color:#ed6a5a}.-bg-7 p:not(.p-initial)>a{color:#0847a2}.-bg-7 p:not(.p-initial)>a:hover{color:#094db1}.-text-7{color:#ed6a5a}.-bg-8{color:#fff;background-color:#403f4c}.-bg-8 p:not(.p-initial)>a{color:#bdd7fe}.-bg-8 p:not(.p-initial)>a:hover{color:#094db1}.-text-8{color:#403f4c}.-bg-9{color:#000;background-color:#ed6a5a}.-bg-9 p:not(.p-initial)>a{color:#0847a2}.-bg-9 p:not(.p-initial)>a:hover{color:#094db1}.-text-9{color:#ed6a5a}.-bg-10{color:#fff;background-color:#081b4b}.-bg-10 p:not(.p-initial)>a{color:#d8e7ff}.-bg-10 p:not(.p-initial)>a:hover{color:#094db1}.-text-10{color:#081b4b}.-bg-11{color:#000;background-color:#fff}.-bg-11 p:not(.p-initial)>a{color:#0d6efd}.-bg-11 p:not(.p-initial)>a:hover{color:#094db1}.-text-11{color:#fff}.-bg-12{color:#000;background-color:#c0e0de}.-bg-12 p:not(.p-initial)>a{color:#0b5ace}.-bg-12 p:not(.p-initial)>a:hover{color:#094db1}.-text-12{color:#c0e0de}.td-table:not(.td-initial),.td-content table:not(.td-initial),.td-box table:not(.td-initial){display:block}.td-box--height-min{min-height:300px}.td-box--height-med{min-height:400px}.td-box--height-max{min-height:500px}.td-box--height-full{min-height:100vh}@media(min-width:768px){.td-box--height-min{min-height:450px}.td-box--height-med{min-height:500px}.td-box--height-max{min-height:650px}}.td-box .row{padding-left:5vw;padding-right:5vw}.td-box.linkbox{padding:5vh 5vw}.td-box--0{color:#fff;background-color:#403f4c}.td-box--0 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#403f4c transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--0 p>a,.td-box--0 span>a{color:#bdd7fe}.td-box--0 p>a:hover,.td-box--0 span>a:hover{color:#d1e3fe}.td-box--1{color:#fff;background-color:#081b4b}.td-box--1 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#081b4b transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--1 p>a,.td-box--1 span>a{color:#d8e7ff}.td-box--1 p>a:hover,.td-box--1 span>a:hover{color:#e4eeff}.td-box--2{color:#000;background-color:#fff}.td-box--2 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#fff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--2 p>a,.td-box--2 span>a{color:#0d6efd}.td-box--2 p>a:hover,.td-box--2 span>a:hover{color:#094db1}.td-box--3{color:#000;background-color:#c0e0de}.td-box--3 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#c0e0de transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--3 p>a,.td-box--3 span>a{color:#0b5ace}.td-box--3 p>a:hover,.td-box--3 span>a:hover{color:#083f90}.td-box--4{color:#000;background-color:#fff}.td-box--4 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#fff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--4 p>a,.td-box--4 span>a{color:#0d6efd}.td-box--4 p>a:hover,.td-box--4 span>a:hover{color:#094db1}.td-box--5{color:#fff;background-color:#6c757d}.td-box--5 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#6c757d transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--5 p>a,.td-box--5 span>a{color:#90bdfe}.td-box--5 p>a:hover,.td-box--5 span>a:hover{color:#b1d1fe}.td-box--6{color:#000;background-color:#3772ff}.td-box--6 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#3772ff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--6 p>a,.td-box--6 span>a{color:#08439a}.td-box--6 p>a:hover,.td-box--6 span>a:hover{color:#062f6c}.td-box--7{color:#000;background-color:#ed6a5a}.td-box--7 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ed6a5a transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--7 p>a,.td-box--7 span>a{color:#0847a2}.td-box--7 p>a:hover,.td-box--7 span>a:hover{color:#063271}.td-box--8{color:#fff;background-color:#403f4c}.td-box--8 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#403f4c transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--8 p>a,.td-box--8 span>a{color:#bdd7fe}.td-box--8 p>a:hover,.td-box--8 span>a:hover{color:#d1e3fe}.td-box--9{color:#000;background-color:#ed6a5a}.td-box--9 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ed6a5a transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--9 p>a,.td-box--9 span>a{color:#0847a2}.td-box--9 p>a:hover,.td-box--9 span>a:hover{color:#063271}.td-box--10{color:#fff;background-color:#081b4b}.td-box--10 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#081b4b transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--10 p>a,.td-box--10 span>a{color:#d8e7ff}.td-box--10 p>a:hover,.td-box--10 span>a:hover{color:#e4eeff}.td-box--11{color:#000;background-color:#fff}.td-box--11 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#fff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--11 p>a,.td-box--11 span>a{color:#0d6efd}.td-box--11 p>a:hover,.td-box--11 span>a:hover{color:#094db1}.td-box--12{color:#000;background-color:#c0e0de}.td-box--12 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#c0e0de transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--12 p>a,.td-box--12 span>a{color:#0b5ace}.td-box--12 p>a:hover,.td-box--12 span>a:hover{color:#083f90}.td-box--blue{color:#fff;background-color:#0d6efd}.td-box--blue .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#0d6efd transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--blue p>a,.td-box--blue span>a{color:#81b3fe}.td-box--blue p>a:hover,.td-box--blue span>a:hover{color:#a7cafe}.td-box--indigo{color:#fff;background-color:#6610f2}.td-box--indigo .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#6610f2 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--indigo p>a,.td-box--indigo span>a{color:#85b6fe}.td-box--indigo p>a:hover,.td-box--indigo span>a:hover{color:#aaccfe}.td-box--purple{color:#fff;background-color:#6f42c1}.td-box--purple .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#6f42c1 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--purple p>a,.td-box--purple span>a{color:#84b5fe}.td-box--purple p>a:hover,.td-box--purple span>a:hover{color:#a9cbfe}.td-box--pink{color:#fff;background-color:#d63384}.td-box--pink .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#d63384 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--pink p>a,.td-box--pink span>a{color:#81b4fe}.td-box--pink p>a:hover,.td-box--pink span>a:hover{color:#a7cbfe}.td-box--red{color:#fff;background-color:#dc3545}.td-box--red .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#dc3545 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--red p>a,.td-box--red span>a{color:#7db1fe}.td-box--red p>a:hover,.td-box--red span>a:hover{color:#a4c8fe}.td-box--orange{color:#000;background-color:#fd7e14}.td-box--orange .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#fd7e14 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--orange p>a,.td-box--orange span>a{color:#073b87}.td-box--orange p>a:hover,.td-box--orange span>a:hover{color:#05295f}.td-box--yellow{color:#000;background-color:#ffc107}.td-box--yellow .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ffc107 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--yellow p>a,.td-box--yellow span>a{color:#073982}.td-box--yellow p>a:hover,.td-box--yellow span>a:hover{color:#05285b}.td-box--green{color:#fff;background-color:#198754}.td-box--green .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#198754 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--green p>a,.td-box--green span>a{color:#b3d2fe}.td-box--green p>a:hover,.td-box--green span>a:hover{color:#cae0fe}.td-box--teal{color:#000;background-color:#20c997}.td-box--teal .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#20c997 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--teal p>a,.td-box--teal span>a{color:#063274}.td-box--teal p>a:hover,.td-box--teal span>a:hover{color:#042351}.td-box--cyan{color:#000;background-color:#0dcaf0}.td-box--cyan .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#0dcaf0 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--cyan p>a,.td-box--cyan span>a{color:#06377e}.td-box--cyan p>a:hover,.td-box--cyan span>a:hover{color:#042758}.td-box--black{color:#fff;background-color:#000}.td-box--black .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#000 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--black p>a,.td-box--black span>a{color:#fff}.td-box--black p>a:hover,.td-box--black span>a:hover{color:#fff}.td-box--white{color:#000;background-color:#fff}.td-box--white .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#fff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--white p>a,.td-box--white span>a{color:#0d6efd}.td-box--white p>a:hover,.td-box--white span>a:hover{color:#094db1}.td-box--gray{color:#fff;background-color:#6c757d}.td-box--gray .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#6c757d transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--gray p>a,.td-box--gray span>a{color:#90bdfe}.td-box--gray p>a:hover,.td-box--gray span>a:hover{color:#b1d1fe}.td-box--gray-dark{color:#fff;background-color:#343a40}.td-box--gray-dark .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#343a40 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--gray-dark p>a,.td-box--gray-dark span>a{color:#c8deff}.td-box--gray-dark p>a:hover,.td-box--gray-dark span>a:hover{color:#d9e8ff}.td-box--primary{color:#fff;background-color:#081b4b}.td-box--primary .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#081b4b transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--primary p>a,.td-box--primary span>a{color:#d8e7ff}.td-box--primary p>a:hover,.td-box--primary span>a:hover{color:#e4eeff}.td-box--secondary{color:#000;background-color:#fff}.td-box--secondary .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#fff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--secondary p>a,.td-box--secondary span>a{color:#0d6efd}.td-box--secondary p>a:hover,.td-box--secondary span>a:hover{color:#094db1}.td-box--success{color:#000;background-color:#3772ff}.td-box--success .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#3772ff transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--success p>a,.td-box--success span>a{color:#08439a}.td-box--success p>a:hover,.td-box--success span>a:hover{color:#062f6c}.td-box--info{color:#000;background-color:#c0e0de}.td-box--info .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#c0e0de transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--info p>a,.td-box--info span>a{color:#0b5ace}.td-box--info p>a:hover,.td-box--info span>a:hover{color:#083f90}.td-box--warning{color:#000;background-color:#ed6a5a}.td-box--warning .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ed6a5a transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--warning p>a,.td-box--warning span>a{color:#0847a2}.td-box--warning p>a:hover,.td-box--warning span>a:hover{color:#063271}.td-box--danger{color:#000;background-color:#ed6a5a}.td-box--danger .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ed6a5a transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--danger p>a,.td-box--danger span>a{color:#0847a2}.td-box--danger p>a:hover,.td-box--danger span>a:hover{color:#063271}.td-box--light{color:#000;background-color:#d3f3ee}.td-box--light .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#d3f3ee transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--light p>a,.td-box--light span>a{color:#0c62e1}.td-box--light p>a:hover,.td-box--light span>a:hover{color:#08459e}.td-box--dark,.td-footer{color:#fff;background-color:#403f4c}.td-box--dark .td-arrow-down::before,.td-footer .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#403f4c transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--dark p>a,.td-footer p>a,.td-box--dark span>a,.td-footer span>a{color:#bdd7fe}.td-box--dark p>a:hover,.td-footer p>a:hover,.td-box--dark span>a:hover,.td-footer span>a:hover{color:#d1e3fe}.td-box--100{color:#000;background-color:#f8f9fa}.td-box--100 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#f8f9fa transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--100 p>a,.td-box--100 span>a{color:#0d6bf7}.td-box--100 p>a:hover,.td-box--100 span>a:hover{color:#094bad}.td-box--200{color:#000;background-color:#e9ecef}.td-box--200 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#e9ecef transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--200 p>a,.td-box--200 span>a{color:#0c66ea}.td-box--200 p>a:hover,.td-box--200 span>a:hover{color:#0847a4}.td-box--300{color:#000;background-color:#dee2e6}.td-box--300 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#dee2e6 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--300 p>a,.td-box--300 span>a{color:#0c61e0}.td-box--300 p>a:hover,.td-box--300 span>a:hover{color:#08449d}.td-box--400{color:#000;background-color:#ced4da}.td-box--400 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#ced4da transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--400 p>a,.td-box--400 span>a{color:#0b5bd2}.td-box--400 p>a:hover,.td-box--400 span>a:hover{color:#084093}.td-box--500{color:#000;background-color:#adb5bd}.td-box--500 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#adb5bd transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--500 p>a,.td-box--500 span>a{color:#094eb4}.td-box--500 p>a:hover,.td-box--500 span>a:hover{color:#06377e}.td-box--600{color:#fff;background-color:#6c757d}.td-box--600 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#6c757d transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--600 p>a,.td-box--600 span>a{color:#90bdfe}.td-box--600 p>a:hover,.td-box--600 span>a:hover{color:#b1d1fe}.td-box--700{color:#fff;background-color:#495057}.td-box--700 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#495057 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--700 p>a,.td-box--700 span>a{color:#b3d2fe}.td-box--700 p>a:hover,.td-box--700 span>a:hover{color:#cae0fe}.td-box--800{color:#fff;background-color:#343a40}.td-box--800 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#343a40 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--800 p>a,.td-box--800 span>a{color:#c8deff}.td-box--800 p>a:hover,.td-box--800 span>a:hover{color:#d9e8ff}.td-box--900{color:#fff;background-color:#212529}.td-box--900 .td-arrow-down::before{left:50%;margin-left:-30px;bottom:-25px;border-style:solid;border-width:25px 30px 0;border-color:#212529 transparent transparent transparent;z-index:3;position:absolute;content:""}.td-box--900 p>a,.td-box--900 span>a{color:#dceaff}.td-box--900 p>a:hover,.td-box--900 span>a:hover{color:#e7f0ff}.td-blog .td-rss-button{border-radius:2rem;float:right;display:none}.td-blog-posts-list{margin-top:1.5rem!important}.td-blog-posts-list__item{display:flex;align-items:flex-start;margin-bottom:1.5rem!important}.td-blog-posts-list__item__body{flex:1}.td-content .highlight{margin:2rem 0;padding:0;position:relative}.td-content .highlight .click-to-copy{display:block;text-align:right}.td-content .highlight pre{margin:0;padding:1rem;border-radius:inherit}.td-content .highlight pre button.td-click-to-copy{position:absolute;color:#ced4da;border-radius:3px;border-width:0;background-color:inherit;box-shadow:1px 1px #ced4da;right:4px;top:2px}.td-content .highlight pre button.td-click-to-copy:hover{color:#403f4c;background-color:#ced4da}.td-content .highlight pre button.td-click-to-copy:active{color:#403f4c;background-color:#ced4da;transform:translateY(2px)}.td-content p code,.td-content li>code,.td-content table code{color:inherit;padding:.2em .4em;margin:0;font-size:85%;word-break:normal;background-color:rgba(0,0,0,5%);border-radius:.375rem}.td-content p code br,.td-content li>code br,.td-content table code br{display:none}.td-content pre{word-wrap:normal;background-color:#f8f9fa;padding:1rem}.td-content pre>code{background-color:inherit!important;padding:0;margin:0;font-size:100%;word-break:normal;white-space:pre;border:0}.td-content pre.mermaid{background-color:inherit;font-size:0;padding:0}@media(min-width:768px){.td-navbar-cover{background:0 0!important}.td-navbar-cover .nav-link{text-shadow:1px 1px 2px #403f4c}}.td-navbar-cover.navbar-bg-onscroll .nav-link{text-shadow:none}.navbar-bg-onscroll{background:#081b4b!important;opacity:inherit}.td-navbar{background:#081b4b;min-height:4rem;margin:0;z-index:32}.td-navbar .navbar-brand{text-transform:none}.td-navbar .navbar-brand__name{font-weight:700}.td-navbar .navbar-brand svg{display:inline-block;margin:0 10px;height:30px}.td-navbar .navbar-nav{padding-top:.5rem;white-space:nowrap}.td-navbar .nav-link{text-transform:none;font-weight:700}.td-navbar .dropdown{min-width:100px}@media(min-width:768px){.td-navbar{position:fixed;top:0;width:100%}.td-navbar .nav-item{padding-inline-end:.5rem}.td-navbar .navbar-nav{padding-top:0!important}}@media(max-width:991.98px){.td-navbar .td-navbar-nav-scroll{max-width:100%;height:2.5rem;overflow:hidden;font-size:.9rem}.td-navbar .navbar-brand{margin-right:0}.td-navbar .navbar-nav{padding-bottom:2rem;overflow-x:auto}}#main_navbar li i{padding-right:.5em}#main_navbar li i:before{display:inline-block;text-align:center;min-width:1em}#main_navbar .alert{background-color:inherit;padding:0;color:#fff;border:0;font-weight:inherit}#main_navbar .alert:before{display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;-webkit-font-smoothing:antialiased;font-family:"font awesome 6 free";font-weight:900;content:"\f0d9";padding-left:.5em;padding-right:.5em}nav.foldable-nav#td-section-nav{position:relative}nav.foldable-nav#td-section-nav label{margin-bottom:0;width:100%}nav.foldable-nav .td-sidebar-nav__section,nav.foldable-nav .with-child ul{list-style:none;padding:0;margin:0}nav.foldable-nav .ul-1>li{padding-left:1.5em}nav.foldable-nav ul.foldable{display:none}nav.foldable-nav input:checked~ul.foldable{display:block}nav.foldable-nav input[type=checkbox]{display:none}nav.foldable-nav .with-child,nav.foldable-nav .without-child{position:relative;padding-left:1.5em}nav.foldable-nav .ul-1 .with-child>label:before{display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;-webkit-font-smoothing:antialiased;font-family:"font awesome 6 free";font-weight:900;content:"\f0da";position:absolute;left:.1em;padding-left:.4em;padding-right:.4em;font-size:1em;color:#212529;transition:all .5s}nav.foldable-nav .ul-1 .with-child>label:before:hover{transform:rotate(90deg)}nav.foldable-nav .ul-1 .with-child>input:checked~label:before{color:#081b4b;transform:rotate(90deg);transition:transform .5s}nav.foldable-nav .with-child ul{margin-top:.1em}@media(hover:hover) and (pointer:fine){nav.foldable-nav .ul-1 .with-child>label:hover:before{color:#081b4b;transition:color .3s}nav.foldable-nav .ul-1 .with-child>input:checked~label:hover:before{color:#081b4b;transition:color .3s}}.td-sidebar-nav{padding-right:.5rem;margin-right:-15px;margin-left:-15px}@media(min-width:768px){@supports(position:sticky){.td-sidebar-nav{max-height:calc(100vh - 8.5rem);overflow-y:auto}}}@media(min-width:992px){.td-sidebar-nav.td-sidebar-nav--search-disabled{padding-top:1rem}@supports(position:sticky){.td-sidebar-nav.td-sidebar-nav--search-disabled{max-height:calc(calc(100vh - 8.5rem) + 4.5rem)}}}@media(min-width:768px){.td-sidebar-nav{display:block!important}}.td-sidebar-nav__section{padding-left:0}.td-sidebar-nav__section li{list-style:none}.td-sidebar-nav__section.ul-0,.td-sidebar-nav__section ul{padding:0;margin:0}@media(min-width:768px){.td-sidebar-nav__section .ul-1 ul{padding-left:1.5em}}.td-sidebar-nav__section-title{display:block;font-weight:500}.td-sidebar-nav__section-title .active{font-weight:700}.td-sidebar-nav__section-title a{color:#212529}.td-sidebar-nav .td-sidebar-link{display:block;padding-bottom:.375rem}.td-sidebar-nav .td-sidebar-link__page{color:#495057;font-weight:300}.td-sidebar-nav a:focus,.td-sidebar-nav a:hover{color:#0d6efd}.td-sidebar-nav a.active{font-weight:700}.td-sidebar-nav .dropdown a{color:#495057}.td-sidebar-nav .dropdown .nav-link{padding:0 0 1rem}.td-sidebar-nav>.td-sidebar-nav__section{padding-left:1.5rem}.td-sidebar-nav li i{padding-right:.5em}.td-sidebar-nav li i:before{display:inline-block;text-align:center;min-width:1em}.td-sidebar-nav .td-sidebar-link.tree-root{font-weight:700;color:#081b4b;border-bottom:1px #081b4b solid;margin-bottom:1rem}.td-sidebar{padding-bottom:1rem}.td-sidebar a{text-decoration:none}.td-sidebar a:focus,.td-sidebar a:hover{text-decoration:initial}.td-sidebar .btn-link{text-decoration:none}@media(min-width:768px){.td-sidebar{padding-top:4rem;background-color:rgba(8,27,75,3%);padding-right:1rem;border-right:1px solid #dee2e6}}.td-sidebar__toggle{line-height:1;color:#212529;margin:1rem}.td-sidebar__search{padding:1rem 0}.td-sidebar__inner{order:0}@media(min-width:768px){@supports(position:sticky){.td-sidebar__inner{position:sticky;top:4rem;z-index:10;height:calc(100vh - 5rem)}}}@media(min-width:1200px){.td-sidebar__inner{flex:0 1 320px}}.td-sidebar__inner .td-search-box{width:100%}.td-sidebar #content-desktop{display:block}.td-sidebar #content-mobile{display:none}@media(max-width:991.98px){.td-sidebar #content-desktop{display:none}.td-sidebar #content-mobile{display:block}}.td-sidebar-toc{border-left:1px solid #dee2e6;order:2;padding-top:.75rem;padding-bottom:1.5rem;vertical-align:top}.td-sidebar-toc a{text-decoration:none}.td-sidebar-toc a:focus,.td-sidebar-toc a:hover{text-decoration:initial}.td-sidebar-toc .btn-link{text-decoration:none}@supports(position:sticky){.td-sidebar-toc{position:sticky;top:4rem;height:calc(100vh - 4rem);overflow-y:auto}}.td-sidebar-toc .td-page-meta a{display:block;font-weight:500}.td-toc a{display:block;font-weight:300;padding-bottom:.25rem}.td-toc li{list-style:none;display:block}.td-toc li li{margin-left:.5rem}.td-toc #TableOfContents a{color:#6c757d}.td-toc #TableOfContents a:focus,.td-toc #TableOfContents a:hover{color:initial}.td-toc ul{padding-left:0}@media print{.td-breadcrumbs{display:none!important}}.td-breadcrumbs .breadcrumb{background:inherit;padding-left:0;padding-top:0}.alert{font-weight:500;background:#fff;color:inherit;border-radius:0}.alert-primary{border-style:solid;border-color:#081b4b;border-width:0 0 0 4px}.alert-primary .alert-heading{color:#081b4b}.alert-secondary{border-style:solid;border-color:#fff;border-width:0 0 0 4px}.alert-secondary .alert-heading{color:#fff}.alert-success{border-style:solid;border-color:#3772ff;border-width:0 0 0 4px}.alert-success .alert-heading{color:#3772ff}.alert-info{border-style:solid;border-color:#c0e0de;border-width:0 0 0 4px}.alert-info .alert-heading{color:#c0e0de}.alert-warning{border-style:solid;border-color:#ed6a5a;border-width:0 0 0 4px}.alert-warning .alert-heading{color:#ed6a5a}.alert-danger{border-style:solid;border-color:#ed6a5a;border-width:0 0 0 4px}.alert-danger .alert-heading{color:#ed6a5a}.alert-light{border-style:solid;border-color:#d3f3ee;border-width:0 0 0 4px}.alert-light .alert-heading{color:#d3f3ee}.alert-dark{border-style:solid;border-color:#403f4c;border-width:0 0 0 4px}.alert-dark .alert-heading{color:#403f4c}.td-content{order:1}.td-content p,.td-content li,.td-content td{font-weight:400}.td-content>h1,.td-content>.h1{font-weight:700;margin-bottom:1rem}.td-content>h2,.td-content>.h2{margin-bottom:1rem}.td-content>h2:not(:first-child),.td-content>.h2:not(:first-child){margin-top:3rem}.td-content>h2+h3,.td-content>.h2+h3,.td-content>h2+.h3,.td-content>h2+.td-footer__links-item,.td-content>.h2+.h3,.td-content>.h2+.td-footer__links-item{margin-top:1rem}.td-content>h3,.td-content>.h3,.td-content>.td-footer__links-item,.td-content>h4,.td-content>.h4,.td-content>h5,.td-content>.h5,.td-content>h6,.td-content>.h6{margin-bottom:1rem;margin-top:2rem}.td-content blockquote{padding:0 0 0 1rem;margin-bottom:1rem;color:#6c757d;border-left:6px solid #fff}.td-content ul li,.td-content ol li{margin-bottom:.25rem}.td-content strong{font-weight:700}.td-content .alert:not(:first-child){margin-top:2rem;margin-bottom:2rem}.td-content .lead{margin-bottom:1.5rem}.td-title{margin-top:1rem;margin-bottom:.5rem}@media(min-width:576px){.td-title{font-size:3rem}}.td-heading-self-link{font-size:90%;padding-left:.25em;text-decoration:none;visibility:hidden}.td-heading-self-link:before{content:'#'}@media(hover:none) and (pointer:coarse),(max-width:576px){.td-heading-self-link{visibility:visible}}h1:hover>.td-heading-self-link,.h1:hover>.td-heading-self-link{visibility:visible}h2:hover>.td-heading-self-link,.h2:hover>.td-heading-self-link{visibility:visible}h3:hover>.td-heading-self-link,.h3:hover>.td-heading-self-link,.td-footer__links-item:hover>.td-heading-self-link{visibility:visible}h4:hover>.td-heading-self-link,.h4:hover>.td-heading-self-link{visibility:visible}h5:hover>.td-heading-self-link,.h5:hover>.td-heading-self-link{visibility:visible}h6:hover>.td-heading-self-link,.h6:hover>.td-heading-self-link{visibility:visible}.td-search{background:0 0;position:relative;width:100%}.td-search__icon{display:flex;align-items:center;height:100%;position:absolute;left:.75em;pointer-events:none}.td-search__icon:before{content:"\f002"}.td-navbar .td-search__icon{color:rgba(255,255,255,.75)}.td-search__input{width:100%;text-indent:1.25em}.td-search__input:not(:focus){background:0 0}.td-search__input.form-control:focus{border-color:#f3f4f6;box-shadow:0 0 0 2px #6b7693;color:inherit}.td-navbar .td-search__input{border:none;color:rgba(255,255,255,.75)}.td-navbar .td-search__input::-webkit-input-placeholder{color:rgba(255,255,255,.75)}.td-navbar .td-search__input:-moz-placeholder{color:rgba(255,255,255,.75)}.td-navbar .td-search__input::-moz-placeholder{color:rgba(255,255,255,.75)}.td-navbar .td-search__input:-ms-input-placeholder{color:rgba(255,255,255,.75)}.td-search:focus-within .td-search__icon{display:none}.td-search:focus-within .td-search-input{text-indent:0}.td-search:not(:focus-within){color:#6c757d}.td-sidebar .td-search--algolia{display:block;padding:0 .5rem}.td-sidebar .td-search--algolia>button{margin:0;width:100%}.td-search--offline:focus-within .td-search__icon{display:flex;color:#6c757d}.td-offline-search-results{max-width:90%}.td-offline-search-results .card,.td-offline-search-results .td-content .highlight,.td-content .td-offline-search-results .highlight{margin-bottom:.5rem}.td-offline-search-results .card .card-header,.td-offline-search-results .td-content .highlight .card-header,.td-content .td-offline-search-results .highlight .card-header{font-weight:700}.td-offline-search-results__close-button{float:right}.td-offline-search-results__close-button:after{content:"\f00d"}.td-outer{display:flex;flex-direction:column;min-height:100vh}@media(min-width:768px){.td-default main>section:first-of-type{padding-top:8rem}}.td-main{flex-grow:1}.td-404 main,.td-main main{padding-top:1.5rem;padding-bottom:2rem}@media(min-width:768px){.td-404 main,.td-main main{padding-top:5.5rem}}.td-cover-block--height-min{min-height:300px}.td-cover-block--height-med{min-height:400px}.td-cover-block--height-max{min-height:500px}.td-cover-block--height-full{min-height:100vh}@media(min-width:768px){.td-cover-block--height-min{min-height:450px}.td-cover-block--height-med{min-height:500px}.td-cover-block--height-max{min-height:650px}}.td-cover-logo{margin-right:.5em}.td-cover-block{position:relative;padding-top:5rem;padding-bottom:5rem;background-repeat:no-repeat;background-position:50% 0;background-size:cover}.td-cover-block>.byline{position:absolute;bottom:2px;right:4px}.td-bg-arrow-wrapper{position:relative}.section-index .entry{padding:.75rem}.section-index h5,.section-index .h5{margin-bottom:0}.section-index h5 a,.section-index .h5 a{font-weight:700}.section-index p{margin-top:0}.pageinfo{font-weight:500;background:#f8f9fa;color:inherit;border-radius:0;margin:2rem;padding:1.5rem;padding-bottom:.5rem}.pageinfo-primary{border-style:solid;border-color:#081b4b}.pageinfo-secondary{border-style:solid;border-color:#fff}.pageinfo-success{border-style:solid;border-color:#3772ff}.pageinfo-info{border-style:solid;border-color:#c0e0de}.pageinfo-warning{border-style:solid;border-color:#ed6a5a}.pageinfo-danger{border-style:solid;border-color:#ed6a5a}.pageinfo-light{border-style:solid;border-color:#d3f3ee}.pageinfo-dark{border-style:solid;border-color:#403f4c}.td-page-meta__lastmod{margin-top:3rem!important;padding-top:1rem!important}.taxonomy-terms-article{width:100%;clear:both;font-size:.8rem}.taxonomy-terms-article .taxonomy-title{display:inline;font-size:1.25em;height:1em;line-height:1em;margin-right:.5em;padding:0}.taxonomy-terms-cloud{width:100%;clear:both;font-size:.8rem}.taxonomy-terms-cloud .taxonomy-title{display:inline-block;width:100%;font-size:1rem;font-weight:700;color:#081b4b;border-bottom:1px #081b4b solid;margin-bottom:1em;padding-bottom:.375rem;margin-top:1em}.taxonomy-terms-page{max-width:800px;margin:auto}.taxonomy-terms-page h1,.taxonomy-terms-page .h1{margin-bottom:1em}.taxonomy-terms-page .taxonomy-terms-cloud{font-size:1em}.taxonomy-terms-page .taxonomy-terms-cloud li{display:block}.taxonomy-terms-page .taxo-text-tags li+li::before{content:none}.taxonomy-terms-page .taxo-fruits .taxonomy-count,.taxonomy-terms-page .taxo-fruits .taxonomy-label{display:inherit;font-size:1rem;margin:0;padding:0;padding-right:.5em}.taxonomy-terms-page .taxo-fruits .taxonomy-count::before{content:"("}.taxonomy-terms-page .taxo-fruits .taxonomy-count::after{content:")"}.taxonomy-terms{list-style:none;margin:0;overflow:hidden;padding:0;display:inline}.taxonomy-terms li{display:inline;overflow-wrap:break-word;word-wrap:break-word;-ms-word-break:break-all;word-break:break-all;word-break:break-word;-webkit-hyphens:auto;hyphens:auto}.taxonomy-count{font-size:.8em;line-height:1.25em;display:inline-block;padding-left:.6em;padding-right:.6em;margin-left:.6em;text-align:center;border-radius:1em;background-color:#fff}.taxonomy-term{background:#e9ecef;border-width:0;border-radius:0 3px 3px 0;color:#6c757d;display:inline-block;font-size:1em;line-height:1.5em;min-height:1.5em;max-width:100%;padding:0 .5em 0 1em;position:relative;margin:0 .5em .2em 0;text-decoration:none;-webkit-transition:color .2s;clip-path:polygon(100% 0,100% 100%,.8em 100%,0 50%,.8em 0)}.taxonomy-term:hover{background-color:#081b4b;color:#fff}.taxonomy-term:hover .taxonomy-count{color:#403f4c!important}.taxonomy-term:hover::before{background:#081b4b}.taxo-text-tags .taxonomy-term{background:0 0;border-width:0;border-radius:0;color:#6c757d;font-size:1em;line-height:1.5em;min-height:1.5em;max-width:100%;padding:0;position:relative;margin:0;text-decoration:none;clip-path:none}.taxo-text-tags .taxonomy-term:hover{background:0 0;color:#0d6efd}.taxo-text-tags .taxonomy-term:hover .taxonomy-count{color:#403f4c!important}.taxo-text-tags .taxonomy-term:hover::before{background:0 0}.taxo-text-tags li+li::before{content:"|";color:#6c757d;margin-right:.2em}.taxo-text-tags .taxonomy-count{font-size:1em;line-height:1.25em;display:inline-block;padding:0;margin:0;text-align:center;border-radius:0;background:0 0;vertical-align:super;font-size:.75em}.taxo-text-tags .taxonomy-term:hover .taxonomy-count{color:#0d6efd!important}.taxo-fruits .taxonomy-term[data-taxonomy-term]::before{font-style:normal;font-variant:normal;text-rendering:auto;-webkit-font-smoothing:antialiased;font-family:"font awesome 6 free";padding-right:.5em;font-size:2em;min-width:1.5em;display:inline-block}.taxo-fruits .taxonomy-term[data-taxonomy-term=apple]::before{content:"\f5d1";color:red}.taxo-fruits .taxonomy-term[data-taxonomy-term=carrot]::before{content:"\f787";color:orange}.taxo-fruits .taxonomy-term[data-taxonomy-term=lemon]::before{content:"\f094";color:#32cd32}.taxo-fruits .taxonomy-term[data-taxonomy-term=pepper]::before{content:"\f816";color:darkred}.taxo-fruits .taxonomy-term{background:0 0;border-width:0;border-radius:0;color:#6c757d;font-size:1em;line-height:2.5em;max-width:100%;padding:0;position:relative;margin:0;text-decoration:none;clip-path:none}.taxo-fruits .taxonomy-term:hover{background:0 0;color:#0d6efd}.taxo-fruits .taxonomy-term:hover .taxonomy-count{color:#403f4c!important}.taxo-fruits .taxonomy-term:hover::before{background:0 0;text-shadow:0 0 3px #212529}.taxo-fruits .taxonomy-count,.taxo-fruits .taxonomy-label{display:none}.taxo-fruits.taxonomy-terms-article{margin-bottom:1rem}.taxo-fruits.taxonomy-terms-article .taxonomy-title{display:none}.taxonomy-taxonomy-page{max-width:800px;margin:auto}.taxonomy-taxonomy-page h1,.taxonomy-taxonomy-page .h1{margin-bottom:1em}.article-meta{margin-bottom:1.5rem}.article-teaser.article-type-docs h3 a:before,.article-teaser.article-type-docs .h3 a:before,.article-teaser.article-type-docs .td-footer__links-item a:before{display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;-webkit-font-smoothing:antialiased;font-family:"font awesome 6 free";content:"\f02d";padding-right:.5em}.article-teaser.article-type-blog h3 a:before,.article-teaser.article-type-blog .h3 a:before,.article-teaser.article-type-blog .td-footer__links-item a:before{display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;-webkit-font-smoothing:antialiased;font-family:"font awesome 6 free";content:"\f781";padding-right:.5em}.all-taxonomy-terms{font-weight:500;line-height:1.2;font-size:1.5rem}.all-taxonomy-terms:before{display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;-webkit-font-smoothing:antialiased;font-family:"font awesome 6 free";content:"\f122";padding-right:.5em}.article-teaser.card,.td-content .article-teaser.highlight{padding:1em;margin-bottom:1.5em}.article-teaser .breadcrumb{margin-bottom:0;font-size:.85rem}.article-teaser .article-meta{margin-bottom:0}div.drawio{display:inline-block;position:relative}div.drawio button{position:absolute;bottom:5px;right:5px;padding:.4em .5em;font-size:.8em;display:none}div.drawio:hover button{display:inline}div.drawioframe{position:fixed;height:100%;width:100%;top:0;left:0;z-index:1000;background:#000b;border:0}div.drawioframe iframe{position:absolute;height:90%;width:90%;top:5%;left:5%;z-index:1010}.tab-content .tab-pane{margin-top:0;margin-bottom:1.5rem;border-left:1px solid rgba(0,0,0,.125);border-right:1px solid rgba(0,0,0,.125);border-bottom:1px solid rgba(0,0,0,.125)}.tab-content .tab-pane .highlight{margin:0;border:none;max-width:100%}.tab-body{font-weight:500;background:#f8f9fa;color:inherit;border-radius:0;padding:1.5rem}.tab-body>:last-child{margin-bottom:0}.tab-body>.highlight:only-child{margin:-1.5rem;max-width:calc(100% + 3rem)}.tab-body-primary{border-style:solid;border-color:#081b4b}.tab-body-secondary{border-style:solid;border-color:#fff}.tab-body-success{border-style:solid;border-color:#3772ff}.tab-body-info{border-style:solid;border-color:#c0e0de}.tab-body-warning{border-style:solid;border-color:#ed6a5a}.tab-body-danger{border-style:solid;border-color:#ed6a5a}.tab-body-light{border-style:solid;border-color:#d3f3ee}.tab-body-dark{border-style:solid;border-color:#403f4c}.td-card.card .highlight,.td-content .td-card.highlight .highlight{border:none;margin:0}.td-card .card-body.code{background-color:#f8f9fa;padding:0 0 0 1ex}.td-card .card-body pre{margin:0;padding:0 1rem 1rem}.swagger-ui .info .title small pre,.swagger-ui .info .title .small pre,.swagger-ui .info .title .td-footer__center pre,.swagger-ui .info .title .td-cover-block>.byline pre{background:#7d8492}.td-footer{min-height:150px;padding-top:3rem}@media(max-width:991.98px){.td-footer{min-height:200px}}.td-footer__center{text-align:center}.td-footer__right{text-align:right}.td-footer__about{font-size:initial}.td-footer__links-list{margin-bottom:0}.td-footer__links-item a{color:inherit!important}.td-footer__authors,.td-footer__all_rights_reserved{padding-left:.25rem}.td-footer__all_rights_reserved{display:none}@media(min-width:768px){.td-offset-anchor:target{display:block;position:relative;top:-4rem;visibility:hidden}h2[id]:before,[id].h2:before,h3[id]:before,[id].h3:before,[id].td-footer__links-item:before,h4[id]:before,[id].h4:before,h5[id]:before,[id].h5:before{display:block;content:" ";margin-top:-5rem;height:5rem;visibility:hidden}} \ No newline at end of file diff --git a/search/index.html b/search/index.html new file mode 100644 index 000000000..9bea3c31a --- /dev/null +++ b/search/index.html @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + +Search Results | Drycc + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ +
+
+
+
+
+

Search Results

+
+
+ +
+ + +
+ + + + + + \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 000000000..b2a3224bf --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,276 @@ + + + + /docs/users/cli/ + 2024-09-19T20:58:22+08:00 + + /docs/understanding-workflow/concepts/ + 2024-09-19T20:58:22+08:00 + + /docs/reference-guide/creating-a-self-signed-ssl-certificate/ + 2024-09-19T20:58:22+08:00 + + /docs/applications/deploying-apps/ + 2024-09-19T20:58:22+08:00 + + /docs/quickstart/overview/ + 2024-09-19T20:58:22+08:00 + + /docs/contribution-guidelines/overview/ + 2024-09-19T20:58:22+08:00 + + /docs/roadmap/planning-process/ + 2024-09-19T20:58:22+08:00 + + /docs/quickstart/ + 2024-09-19T20:58:22+08:00 + + /docs/installing-workflow/system-requirements/ + 2024-09-19T20:58:22+08:00 + + /docs/troubleshooting/workflow/ + 2024-09-19T20:58:22+08:00 + + /docs/managing-workflow/tuning-component-settings/ + 2024-09-19T20:58:22+08:00 + + /docs/understanding-workflow/architecture/ + 2024-09-19T20:58:22+08:00 + + /docs/applications/using-buildpacks/ + 2024-09-19T20:58:22+08:00 + + /docs/managing-workflow/configuring-dns/ + 2024-09-19T20:58:22+08:00 + + /docs/contribution-guidelines/design-documents/ + 2024-09-19T20:58:22+08:00 + + /docs/quickstart/install-workflow/ + 2024-09-19T20:58:22+08:00 + + /docs/installing-workflow/gateway/ + 2024-09-19T20:58:22+08:00 + + /docs/installing-workflow/workflow/ + 2024-09-19T20:58:22+08:00 + + /docs/roadmap/roadmap/ + 2024-09-19T20:58:22+08:00 + + /docs/troubleshooting/kubectl/ + 2024-09-19T20:58:22+08:00 + + /docs/understanding-workflow/ + 2024-09-19T20:58:22+08:00 + + /docs/users/registration/ + 2024-09-19T20:58:22+08:00 + + /docs/understanding-workflow/components/ + 2024-09-19T20:58:22+08:00 + + /docs/reference-guide/controller-api-v2-0/ + 2024-09-19T20:58:22+08:00 + + /docs/managing-workflow/deploy-hooks/ + 2024-09-19T20:58:22+08:00 + + /docs/applications/using-dockerfiles/ + 2024-09-19T20:58:22+08:00 + + /docs/contribution-guidelines/development-environment/ + 2024-09-19T20:58:22+08:00 + + /docs/quickstart/install-cli-tools/ + 2024-09-19T20:58:22+08:00 + + /docs/installing-workflow/ + 2024-09-19T20:58:22+08:00 + + /docs/roadmap/releases/ + 2024-09-19T20:58:22+08:00 + + /docs/users/ssh-keys/ + 2024-09-19T20:58:22+08:00 + + /docs/troubleshooting/applications/ + 2024-09-19T20:58:22+08:00 + + /docs/installing-workflow/configuring-object-storage/ + 2024-09-19T20:58:22+08:00 + + /docs/applications/using-container-images/ + 2024-09-19T20:58:22+08:00 + + /docs/reference-guide/controller-api-v2-1/ + 2024-09-19T20:58:22+08:00 + + /docs/quickstart/deploy-an-app/ + 2024-09-19T20:58:22+08:00 + + /docs/managing-workflow/platform-logging/ + 2024-09-19T20:58:22+08:00 + + /docs/contribution-guidelines/testing/ + 2024-09-19T20:58:22+08:00 + + /docs/users/ + 2024-09-19T20:58:22+08:00 + + /docs/applications/ + 2024-09-19T20:58:22+08:00 + + /docs/installing-workflow/configuring-postgres/ + 2024-09-19T20:58:22+08:00 + + /docs/installing-workflow/configuring-registry/ + 2024-09-19T20:58:22+08:00 + + /docs/reference-guide/controller-api-v2-2/ + 2024-09-19T20:58:22+08:00 + + /docs/applications/managing-app-processes/ + 2024-09-19T20:58:22+08:00 + + /docs/managing-workflow/ + 2024-09-19T20:58:22+08:00 + + /docs/managing-workflow/platform-monitoring/ + 2024-09-19T20:58:22+08:00 + + /docs/contribution-guidelines/submitting-a-pull-request/ + 2024-09-19T20:58:22+08:00 + + /docs/contribution-guidelines/community/ + 2024-09-19T20:58:22+08:00 + + /docs/reference-guide/controller-api-v2-3/ + 2024-09-19T20:58:22+08:00 + + /docs/applications/managing-app-configuration/ + 2024-09-19T20:58:22+08:00 + + /docs/applications/managing-app-metrics/ + 2024-09-19T20:58:22+08:00 + + /docs/managing-workflow/production-deployments/ + 2024-09-19T20:58:22+08:00 + + /docs/managing-workflow/upgrading-workflow/ + 2024-09-19T20:58:22+08:00 + + /docs/applications/managing-app-lifecycle/ + 2024-09-19T20:58:22+08:00 + + /docs/contribution-guidelines/triaging-issues/ + 2024-09-19T20:58:22+08:00 + + /docs/troubleshooting/ + 2024-09-19T20:58:22+08:00 + + /docs/contribution-guidelines/conduct/ + 2024-09-19T20:58:22+08:00 + + /docs/applications/managing-app-volumes/ + 2024-09-19T20:58:22+08:00 + + /docs/roadmap/ + 2024-09-19T20:58:22+08:00 + + /docs/contribution-guidelines/ + 2024-09-19T20:58:22+08:00 + + /docs/contribution-guidelines/maintainers/ + 2024-09-19T20:58:22+08:00 + + /docs/applications/managing-app-gateway/ + 2024-09-19T20:58:22+08:00 + + /docs/applications/managing-app-resources/ + 2024-09-19T20:58:22+08:00 + + /blog/news/ + 2024-09-19T20:58:22+08:00 + + /docs/reference-guide/ + 2024-09-19T20:58:22+08:00 + + /docs/applications/inter-app-communication/ + 2024-09-19T20:58:22+08:00 + + /docs/applications/managing-resource-limits/ + 2024-09-19T20:58:22+08:00 + + /docs/applications/domains-and-routing/ + 2024-09-19T20:58:22+08:00 + + /docs/applications/ssl-certificates/ + 2024-09-19T20:58:22+08:00 + + /docs/applications/using-dryccfile/ + 2024-09-19T20:58:22+08:00 + + /docs/ + 2024-09-19T20:58:22+08:00 + + /blog/releases/ + 2024-09-19T20:58:22+08:00 + + /blog/2024/05/01/drycc-workflow-v1.7.8/ + 2024-09-19T20:58:22+08:00 + + /blog/2024/04/30/drycc-workflow-v1.7.7/ + 2024-09-19T20:58:22+08:00 + + /blog/2024/02/27/drycc-workflow-v1.7.5/ + 2024-09-19T20:58:22+08:00 + + /blog/2024/02/27/drycc-workflow-v1.7.6/ + 2024-09-19T20:58:22+08:00 + + /blog/2024/01/29/drycc-workflow-v1.7.2/ + 2024-09-19T20:58:22+08:00 + + /blog/2023/12/08/drycc-workflow-v1.7.0/ + 2024-09-19T20:58:22+08:00 + + /blog/2022/10/21/drycc-workflow-v1.6.0/ + 2024-09-19T20:58:22+08:00 + + /blog/2022/10/06/drycc-workflow-v1.5.0/ + 2024-09-19T20:58:22+08:00 + + /blog/2021/10/06/drycc-workflow-v1.4.0/ + 2024-09-19T20:58:22+08:00 + + /blog/2020/10/06/drycc-workflow-v1.3.0/ + 2024-09-19T20:58:22+08:00 + + /blog/2019/10/06/drycc-workflow-v1.2.0/ + 2024-09-19T20:58:22+08:00 + + /blog/2018/10/06/welcome-to-drycc/ + 2024-09-19T20:58:22+08:00 + + /about/ + 2024-09-19T20:58:22+08:00 + + /blog/ + 2024-09-19T20:58:22+08:00 + + /categories/ + + /community/ + 2024-09-19T20:58:22+08:00 + + / + 2024-09-19T20:58:22+08:00 + + /search/ + 2024-09-19T20:58:22+08:00 + + /tags/ + + diff --git a/tags/index.html b/tags/index.html new file mode 100644 index 000000000..cfc6dbbac --- /dev/null +++ b/tags/index.html @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + +Tags | Drycc + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+

Tags

+
+
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/tags/index.xml b/tags/index.xml new file mode 100644 index 000000000..22f24e165 --- /dev/null +++ b/tags/index.xml @@ -0,0 +1,18 @@ + + + Drycc – Tags + /tags/ + Recent content in Tags on Drycc + Hugo -- gohugo.io + en + + + + + + + + + + + diff --git a/uninstall.sh b/uninstall.sh new file mode 100644 index 000000000..4a531a28f --- /dev/null +++ b/uninstall.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +set -eo pipefail +shopt -s expand_aliases + +# clean cilium +ip link delete cilium_host > /dev/null 2>&1 || true +ip link delete cilium_net > /dev/null 2>&1 || true +ip link delete cilium_vxlan > /dev/null 2>&1 || true +ip link delete nodelocaldns > /dev/null 2>&1 || true +iptables-save | grep -iv cilium | iptables-restore || true +ip6tables-save | grep -iv cilium | ip6tables-restore || true + +/usr/local/bin/k3s-killall.sh + +if [[ -x /usr/local/bin/k3s-uninstall.sh ]] ; then + /usr/local/bin/k3s-uninstall.sh +fi + +if [[ -x /usr/local/bin/k3s-agent-uninstall.sh ]] ; then + /usr/local/bin/k3s-agent-uninstall.sh +fi + +if [[ -n "${K3S_DATA_DIR}" ]] ; then + rm -rf "${K3S_DATA_DIR}/rancher" +fi + +iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat && iptables -P FORWARD ACCEPT + +rm -rf /etc/rancher +rm -rf /etc/cni/net.d/* +rm -rf /var/lib/rancher/ +rm -rf /usr/local/bin/*runsc* /usr/local/bin/crun +rm -rf /usr/local/bin/helm ~/.config/helm diff --git a/webfonts/fa-brands-400.ttf b/webfonts/fa-brands-400.ttf new file mode 100644 index 0000000000000000000000000000000000000000..c6897d6802711e55599efa0f1502418071a1ebaa GIT binary patch literal 207972 zcmd4437p+UmH1or``vxNefQhj?R&fXCh6{^Z*MmVS(=alfdG+x(}Yby5uyf(2-pfJ zDvm+f1edrmj-rD*D&w@uAmc=3T*eKxQHZFFrn?go5xd{_RNb3&5XX7{_ul98ew}lx zezn)BQ>RXyI`xavN~w^VP_8PSa@w+?EjwOvwNiQ!p<6F{V=9r=-0P7`v1J iH@IL``U;4`JJNCN%dnxZ` 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


FV5^kp0zbu^up=2LdWwCsC*X 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 literal 0 HcmV?d00001 diff --git a/webfonts/fa-regular-400.ttf b/webfonts/fa-regular-400.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8875b4040365ba6428fe9e5b621a2cd8aae6c142 GIT binary patch literal 68004 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 JSrE0$_5VQIAH4to literal 0 HcmV?d00001 diff --git a/webfonts/fa-regular-400.woff2 b/webfonts/fa-regular-400.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..bf590c9386b8469cc7490d4fc1c64e2aee61db9e GIT binary patch literal 25464 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

V9gi4b^IB>vS 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 -TnbYj) zBc?x?v3{mGtNW~Tvm56On{#9CnRyrHFJ0hW*mvQV#lFR#tcwkMLuFx8ZjW4!E{s*g zKE&51+9qBmH>ax7Bhzc_p7t%EyU`v40O-wG3;+!J@S61@4=uSfYZX(^UIoK}e_@a6l0SyN?nNy>6!T4&r6zdxdEZTbEY@r6`+dQ6ICvSGL@ z(#q8$qcTfUmLuXJWeZnoVcB7!l}aV!+Gi?TA80~>=}4Kq`{)@=ED)w6rPwU9&*PU+ zt1>H`cr>PkHyC6I7lSf zXP)r?uM{9ceq17(9T&3pBG1DsaEKHA2n)P~$l6DOBcyQT892YgZ^91)0{{R3rKuvS literal 0 HcmV?d00001 diff --git a/webfonts/fa-solid-900.ttf b/webfonts/fa-solid-900.ttf new file mode 100644 index 0000000000000000000000000000000000000000..55a68d9d09bd6b39b9db8712296f8d7fc62b0ebb GIT binary patch literal 419720 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 u zFP~0g8R-NsGo92J&88k~RVc&EQmXjr!Vh~nwOsT$nj8(Jwq}Geg__Mm$wTNBYGY{Q z7qdkl0IdXOBMU49{NiUj2WEb<4!mmf71JsuT|nO)aTh@4PQ#1unSy)@Qx68DP{xSn zd}WA~G$nEpZwoAv4w(#hB_Apj3D?`aiY?5?ocfNzDd-a3Ba=D2gxX+|?6bMOxuBgO z+!thgp;fFQJI#aWw=?)wJ4M|HaGFO+7dwcJu?`_NPEb`#s{q1085M|Kl?t>3w(PBQ zfm@afkQaFVbdq1~C9N*>U6zLE0NFe;We8R|orEw8AmGx)+?;n7B(VtM4IIKEYJ@1T zhV&ektq-6MYzmrB)YV_g6&H?YAR0!hl#FLd0)rQWY)b-)&4Mp?E}&E!-s2pbbk*uQYcAbu1L-z-k)$IY*!1RAn6Gv?fNx@5Und&E;iKVH8|&%Z6hF15aS$e01UW{amPum z1%3%-kU2Q%Td@s^#Ha%NNN>cPzHK+9er2+mTSL{4N5(dy@;$I&XbJSeHYX5itd+T2 z8P1$hYXuoi-H4V3na*kX$R1Q~8%EAqd&to$GqNC0AqZPo)ewC#bAQL)Tv>|o!>In&}`+E`VO zuMNKC2rO*V%bJ~>0+NN00c+|koaeH~0GirX0j3`bvzT3xq>5Lpj|WFGbsQEQ6F>lF z`B+|(%;%ei;(rqB(Z>^2oSuQo9A5(=2_{=gfiHrgK;I>ifGM!P#q6zCz2BNA+p{jt zE>GtRI>~IXZjn*RLVgBXL@Zo~O@!HXYA&eF^vrd|S+;P~7B5K#cm$-gLAy zrE*XMyf#wU0PHFPIa-{wW|k`;OJ=2VJTRGGg5DJ3QW@;=@~nR;w}Mf}cgq!UAs~$l zbQkm`K%_)tA5c}OhG09lJ@bRaIugfD-7P|%t4zWVVh+3+{4JmWoQ4Mmm_p+EKz*|| z_XZ?q7qXyRDa;bf2?59NB$vFCc|AXq(A8iNU^7R1MUu|Zd2}^5pR?TwFoUGkST097 zr56&xH>~wp(En)(lxY)87;(V_fGa?^xP8!0%zFivklad;WlNYH7s@%s`e3<8EC>Xq zspZn~2xV%zVuMiRBw9d$!%uUnGgz1kH7YOBanFtp&YgnrA;)p_mE@@>wvFnvcEl(dr273E8#@S!Zv5N#6A;$ue zn~7Vtoq%lilC4m{w6}uK2D1%jx?BWV4AuB*jIPc=xsij$2Mz_8hWP-z2GArCexq^} z0*fv6(2z%}Ii^;%EX#VeEE6anWMA@nIqn7fN4AOpkp|L0l`AHS09NHP3B)!^Wa-o) zkR+sHYCvLaSqW292DPl_W6MiGvZXTAK3R4jaJ0>i@^>W|Zg2?GOMY{0^S@)Z5$rNRn0%K4lE2o{!nSlCPD{6ZOOWpZX>?v>yVrdiAv zxHoojA_#y@c51Fc6JIvK*s^C#7uAGOsH?dtE;sQOi-}Pg1bS&IzhL6Whd=lf;d`p2 z-(My30o@>R0A8CDuqhxObh_`a8omSkAU{LZsX=G{+-a)iKsQ(R+n~N&OyV*9PVSec zRt~v$?m1tDW-M^sa0k-tHA(n+a?%241l$Zb0dUV_yv*6$qQA;6dTln+PXf3GzbeNL z{=>~#Ge?%RMGLGG(#L8E!_tM0*rD&iAm?~ZWrl-#HL<5ogomA#%ve- z7?0+rleRch{}x>s)+{j?$3|0Ws0>ahD;S+wu0ZP3GPGTEh0hq_CTNQ}LvD7Y z{lN_~qS$rjmsp>u%fWz=iyl>h1}q293r@ojIq#c>cuZV|4<0TRdT)5P0K*!8UL}`< z(-vd}SkRzl4@}|-cow3PBZm@7XyzfzU~Mhs$vb8mtOr*jrRf4BJJe^igwd#!p(}+h z3ydN-R@yDx$NnC6l?joB;Z+qJB735_{ctnlk5MKfXotK+w>$>mE>{x4c-OdG(gDBXbEW zP6KQik_CigY&`|cNisP=)eCQ9Ka{IEQ0sCow8ARo43m9zECX`}G}6cPajG%z7|yiAyjOVkx>az$ejEH|tkzQa<5W+h2!>f=HX2z{4Xw=kF4@>NdPB}A&L zF#n^I;Ky&yYIT%Gbh?&jk6BhyF9@*}I2eM436=MXFC~O}CIC44348707gh46=P{H*HUck@-fMJEIaf*~S zD~c{l60YPqKV8669(7XSKYd&VjIR^r{ILL+FyEoeDk}wRI!}`W$9!_QWPt^g7HRro z?+l0+R*D4vo%PLTfuP{q=w-$i9%XLd{0#f+!~WxVCV`KHkq@>=|9pNW542mFj*>vY zp8UGDwFvEV>3E|{SHu)e14GnBtyX|h;;#HK{JxGtVqtp50Mg(}V`0+5^8>l)7kPnL zau5k3ws?ufKv*H_xUv>Y1(F3wxXwY#1=t6^Q6-?tQiQMUTnD(Fj_EA)8u?pkpZJ1( z-%%P_+Heh9b}6^QdUB{a=L%4ekrk_~%JabaL98?A^%yfL=D{H96^ap397F2J&dw4W zPa+F(IgLPL+dXv2JA3l;TPT0Izp^aui|BU z1QE1z0!eLSwClE&$sCkk$R5 zw-WHy<@vs=9caR5mvc?Ec632THuH z_fqQrm2sv^iW@-?-tcgPfMx8k{SZXh{^1BejzAho3p%Xku>AD?vbq}>?;l2D1|fCV zk(HG-O?9w$EXpNDysT}#9U|DtDpgU+KB0%SUtbJqdARA3S)ffid?m~}_7HTB(}ji9gw;oGnB zI+rh;6{CuSn-DeKy`l~S(wKA@_>qyN2`(mH4;aOs;6jH2ehOq?u45ZaH+w9T8`**! z$rb|`*8wXAbhKrg1Hke9r`_WjL=W4n*OD0-V$EH>h!I?6t@xX7A5Z~}CcI8hK!zMs z+fQ%wOC1DmYi`GqecG=z0k#!kDSRe36yvxHM51p@SlzlJq~3{{=b?c24q{bRq#O?< z1H(}7(GuBBW+kkB+{Tc-n?Lb5vyvBIwPQnWWCw7Ry{y~?SYoqmu-N3dH=M}(a2VX}A|5Q5hiaO+t6>FiM#GHKzst!Um)aBUL*_XH%AV^o=6u-R|@o=#9P|=AlAp zd`jW=Cno{^RILJ28?WO%Nc?*~!OCgmsif}5DDxlM`WI}iC_z0HAlz07SSpe67)Iil zqb%eV@>)#-5zRk(W0q~4ACdK;pVON!peMMJe3L60g$XwFXMVN+=J}eRzf&do=l}J) z_oKy)9a!DPdjbDIaWf$%E!8KO2jLH>dToVc!{9c4CfpHwdWwS7a+j0vXzTdnEVmc+*eg)9&);If?1 zxmG_R$`{p+(O|5io^$eQ4Wic)@>ylqxI;Xf2nraa02dBd2>zu0Ol5^YP z`SHk0iH?r)m4~UP`aZ}d`1X#ji9SC9$`_ycTSC<4m8*qs4!3LK3NF;7Sv$oL`Fxvr zbRBqtvE?Ng-NTURMeBtJ6#4v6wPmW^A05tUULUMJ%BJLTf?nx_$u^l~O@O$tsT54` zw6RApBTN|;ECQ=j1Wn=rMPyG`TveZB{Zd`g$ifhbCNZt$E+I6*>kqz;4^UN|=8k|b zXl8XBBRKK!5m6>|`$^%UXJyt2O9rV#W`&GkC(@Nj8i{~!J)tY&qKht9D^@$Z>?i?=RC=1F>C1i2ph?doBP32wC4NDrOw|qp0cQ72 zh**Q|{3$LV=t`ppb&iFg2DFqfMH~d+7WesJL6nf+6T>8t;k)dxA;N9KF+9DsJff{o zwhC*}vTw%vPjqhK33YKlQ9$r~N590siS)IXse0bs-=Oi_|L)UOyx%=1uVM<=0SH&g zC!TYq&-Y%%6o2i1e_n-?rR%INSNT4-!nUSuW{HGkb!Z2eL(QS<5Ub2`p&^_9Be$_? gW4To;NX3fKGHZr2Q5)JJXDjq$ij^{L)_nQ$AMjg2+W-In literal 0 HcmV?d00001 diff --git a/webfonts/fa-solid-900.woff2 b/webfonts/fa-solid-900.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..596c8cb68026fe0ffe7b1783a80be7f3ecd9ec79 GIT binary patch literal 156496 zcmV)UK(N1ePew8T0RR910%K4B3IG5A1{wtb0%HOL1p@#800000000000000000000 z00001HUcCBAO>Iqt2_XKkpjw=!XV45Km~_w2OuQ^4U^UZ&>B`J0064LjfW8_nms&4 zs;Z_X1RU44y{ZZT2!8aFpZ(%jzxmxC{^Za8;;;VZ@BZPR{^j5P54Q58D)ar{SJ z`YihbfYRyweo{siCtyyIcLZ3|tz)y6S!Fcxe=4SwgNY`ciHWq@qGJAXi)bau^aZfU z4ysPBI;dxRjzA_dh{Vj!Wc)iQ4yuKxT1otgKF}&Ts%vMuPY)=P7@6Ao=%DZwy(5tD zFHcwf$<3<;*gZ9!T9_X;79tN%c>Q~3_EROdB9QD$3f`$m5aEGMvuXW=ae5Fzg4N1F z2enr*-4+~r7=KXn!h+yIboIA0{PVq2yH6Thl@lpY*;?R$7f5kqmGEzg;zjr*E@~0T z{a*r{o(cX$Q>(964b|0M&{!o|wk4~rZpRR-EU7zTCF8kG7IU*iUg9igSvSLrnIqH! zv5q)Ltld4p|CdlYA}zJ9p3u|NGd&?8EPw%Kf!WQNodss^_Kr7~_cEA{dkiATqZpD_ zqIjf8Q3Mr9QDIG5(J}=^9z|I`WlFS2C`8-xz3GtNUZ;GP93%(q5ov05^@N_D&=V5E z0z1GgFxY@y%wmDrk=`bp#T4|J5NP<%mt?ld)dC=!xwB{>izj|w)#3( zwCa|ms*>s?ous1OP3TI}5!wi2Fp54NFuWO<6<}R^RhTF2dapS%D?YDR%=vnvYa0H4 znrZ#J52)%DprjI%q?W4NO)9A+wG$_nld(I{b{udV2YVp99#6nafx#Y3GUy@hA@&e= zvPAj3%lVu$`H&@&p#spHvxhKt7xp)IxpmnVE>#5KRs|73uKmGHbeDG!-Q`IX5aB~a zcv@G8ivR^=_!xx<+?oJE9#^@494G=d*8ZIx7|lmp5g3h8jf#rV%s*yh=SLUcR>1%F zu(6K5`%R2!%x;WoX05_zR_xt2GB6su;h(Rr`dfGdFh(l0sz*Q}rZY=XlbK_E0ITnv zcjVcFOA?;1wf`*tKFAQdmkyq)Rq_At3Z3$ZcJJ-mVkj^n;O<$Pd7<}zfKY;50<|v) z4qRNEij|Rib)<`nm#GNh0{`DHExBXHDV}RXa~C%x`<~k2w5t#`iA`?a=5_|7+BJ!LQk;#Zmkjex=-b|2J4y;b#p4^VpgB&GX`r1VPdAEoB~M!#>N-%`I-d9TWP z&wJ(@-}-*nTE_RBZ<<}RE>orbPcs1@7sl)}5EwH{j$a$yEJ6FV5shZ{MX|udzN$kU zXg6KwWkmw%uOidBpNoc32$0yatn_^u^Q)cNR`08b3O(f|oDET{&9(lvQ#O%R5TXpc z#n|HiRsJ~RR8SF?&Eb$)Sv#{%e_r4Do6s}}5RxjyLsYfeNyqw6#UWaRNX#1x`H88% zwVfvI_7_7)MhI@aG4GQg=;`a>^O+~l9!*@@XT<&kz{UT6z5V;MmfX#4`=K3R5Tlw; zxeo2*Hdy3t?%I!)_}2-2pSa(k@00#8x1f{>=7xK%r{_C;pxb&0TpO=ypC!J7G1SBI zahl}Ua<(4cy+g2>smDdy;g*!26K&}qP(T5A?y7>EVFf6%tIDJtM0Vxbl4n`Rt}x z;0pN>|AuiE{yC`_t>B*R*?c#iqJM@x&3+SF@5i8HJYR};;wv9Vv%~beP?5R58SDCF zMaIpY9+6$U%%&8o--E2wm-aPXgs;ZliX2yYbPLQp z=T%laWVeE@qp`t^92{R7S~vd$e!|<+cgzlhir;H$Zof|&446KX<-Yj$EHFLvnQJ_) zY?*z2-SRWCLGZ6yHnOds#LIq(caL!Xczr%SPWcsz9?r%m^1rKmeR$3Xtc-s z+1q#KjA~s{J)fTqD(ywiX|qG~LhFX^$2gvWMtYP2Uz|LM%`N0x9L>g3I<=VVsNc%! zSo?;YCzt-kX*fQhb6zj$RpMG8J)_iV;}^+|@v3&5bCmU8}~??DKWwR#!vZqxow6{p`p? zo~8NHd>#3yEcB)JRp$4T6ngx~zNWdP_UZW$#z|eaelBOv3Cy~=YCO;K?ATM5vtmf# z+?&a7o8QzIr(`QXE6>@^Bov?d`;+J0orrUg7kaY6(!uUhN*jEocNn3ohR!>SQ9I7L zRPSb;rEdv#B{?+M`8LodFyr3zL^FEJHt*TUxnwRks=HcY2#QM=l}n&&oC|C~v zF7FjF_(+=e|6Vge!4M#_KL8TF{V)ho8!a&eqcH|!F%IJ~0TVF^lQ9KTF%8o(12ZuT zvr&aPn2ULsj|EtWMOchOID!*6g|oPdTX>G|I$M|MQr%Lw(uehNeL|nqr}brhUEeWL zv)*hl8_g!O*=#Y}%uRF4JdS2X%dBq$TWl+ArLARa+a0#rzO=9GTl>y_w4dz{`_ulm z|6+H-{o&QHI(!!X4*wAJ=rdp@b6HBwC@n+QVjb3FeYRjrwx?r94&hJ^<8Y4PNRHL;6ZT=`RCioNSS;vaPa7 zWz*WJwTo+))Q;8eRTEc(hv+7bDQyOr31*R5Vm6y?W}i7|j+&e1k$GvH08QY1riq(BLjLOGO21=K)OG(&T= zKnHY0Cv-*+jKC;Nz(h>KWK6+S%)o5S#{w+GBCNn_ticZK!42HT3m61&@OXt!_=<1% zjvx5Xh>XOjjK&y@%{Yw5_)Ny+Ou;lv%Z$v#%*?_Z%+De$!3wO%8m!0qY|IvH&p{l^ zNu0r1oXh!Kz=d4Q<=nwt+|9i_%FDdLM|{jDe99Mm#Si?>ANNK6MGjz7j(fPVWm+1;!rk~@8*{=MogIbXJgp-HoeVgbK9b}v~6cQ*v___onoijS$47A zVK3P$_J+M71rZ}~lc;$RN&7yiM&`L9Hg z=#p5HNgBx{StN(#mBLa=%1afgF14htG?FILLRw2l=_);?pA3*eGF(Q=7#S~_WbC3PuXYL~&~b%k6-SJ%~dja@U>(RFhJ z+!!~(O?9)}61U1-arfOT_s03|kNf}szvp>bylh@xudr9%>*957rF$_BU!|ZnK{J9@ z?K?EMNN|}0Iz4z%@Y=a&nS3yQq*rU3k%6&G-yJvA;*a#__)Glt{$_sNg9 ztd@P8^=h-)sau#QUaBA!!Zu%&TCvlfj;-V9_&R}3OfR*|th4FtUoM|6tV`(% zy0WgNYwO0kg>I?a>CSqDo~masxn!&Ldf%K!^=W-sKj^>LLHhe2)9G*>VLTJv#5Ji* z7E{cWHkD0X)4((~O-z3?#Edp$m|T3=H<-<4mpQ(wE9RQHWgeU7<{evU!`nr*akeUD zTlc#5W{zK+`e1J12c#&Kq%z;OJ$0fk)RTJCU>Z)NXaY^7DKwqt(E?gbE9sx63v~I{ zc|gzTC4Hn2`b^=Rg7b3$F2Y5*B$whUT$PvcCf?3_`52$%vwVqf@dJL$)Q@wEJofC8 zM+!`fJ?ZF>$rpaZ1oC( zp4lzjMRhUyiCj{bV%~Tt-k-#?5g95EsVTaYn2ZOUDv1PfQn6`v3mfU;87!;b;7`AMl;N%{Tc* z-{32Ju`l#lKEZo>S8ta5NnRxvlC#OFKhxVaeC>@H1!l7Wu z5;EFv`)NPyn|-w}_Srt!N5DSVTYF=#?4`Z1=l0B=+7o+h5ABv+vrAe4Xg;8MnhR(S zpxFSRnSf?!8lWk!GbU-`zt=rp;{c5XG)AK}N+Xt7)-XUrHAI6o=r!5^^;I80z12&d z)k*EtR&CPiLbX(jR9lalstKURfEuY`O8)4o4XBoC0;&P1I-qK*sw%3aihwGpJfLza zt1?QIQ#p>{_nb)?0cB8nrR6XF1o(qr_NA7Br5V^?-& zN48@dwqi3jW&>7a1w6#g1jJ6_zx=0v_iq5;o4)A7UhP$0?j>I61)l239`6zE1GuL< zyOnFY2H?^zoiW~luiyfu@gC=<2kP5IJRQ~ z`bWR(hra2nzUZ^w>ZP9RsU8D5s}q2Z13CuiD4-)ctV24e{o1F!+N0gtrJdTLE!w1w z+MxAXtJPYeWtypJnxc^!u0iUnKI*0J>Y{dPt>$W~#%id#s-xPfsj8}^iYl*iDyxzz zq2em0A}Xwc%Bn2NpwvpGb~R;yi8BKJCyn&C?9c&^%4x4&LB( zURPDsR83V<6;)wiDo^nQkEyY$s-~){lFF$PCot2$t2!&OIgjuNk8l?caR(3Z06ViI z_iz>;tEsA}DvPKD->SNb@jIP?U|j~~;UX^LF}~(=KjFvxm>=Owe)O(f!DYUK3%sj$ z_WEAemw02(WGdHj6=!h|clm3d1ONd3{B!a;KI{{_g&TMxV3%U+ItF-Sz)$!Yz)LN0 z!)<^U^FrG@Bi+*feRWg7>i@i(Cwnqr6ZWvPrP_>HEPJmv@Ex|sHmr9=eY;~1w{S&k zz|O_)*xV-A1iyasF@U~_=bHnayq?rOD-ImTt$2*8GgS%B%Gy?D515r(wiytk{n zbQcc!A=95Nt-)C}DLfsmLp_dvV%l+F$ABFIwih0y@8JsWptO4O*R>&>L`Dr7(}bop zqd6^TNh?~@hPJe$Jss#si858>R8t`+=tO6_(3Ng+E{F$!@V* z?Jm2|p0FqFDSOM_w-4+?`^Y}FPwZ3s+`h0c?Hl{nzO$d~XZyu|wLfi!&9Ozc*jCwU zp_*#0mTIe9-PJ?A)L#QMP(w9bV>M3WHA#~-MN_q{w$l#UNxSM;ovc%JhR)Unx=Lb-G@+>2}?#NA#rL)I0i6U+63Sra$$+W@x5nX}0EQuI6dJ7HFXsX|uMv z+&%L;Uf1h+eQ)k9y_HwI@J`;@yLdMrU+7Cy)3jgOKb@OyO1GqY z(nIOt^jvy1eULs(pQO*zSLwU-dzz6Jq%~=CRxhj0BI};@$@*mjsRz(20f27>%0L+~ zAO|XdfG$8+AOm^4EYv5ql1~|mE1rBxXfWusS z;BeOgIKp)Vj&vp9C|3rKc2&SJE(eZv)xdGC0vzuGIKdUbiLMiHlIskd?79G_xURsd zt{ZTg>kgdmdH`qa(i3(hz7elpccah0ez5(_#ly8Ln3gw&N+d=te`1Vk~6}~H!-++2R`Ayhe zQ2q$&4^>TIe?nCU_)^FnngV%(rb6BpF33AUyF%U>_66i!U|&Ms6{#uYx5J)<{9D-P zkk5yG0{H^i2aqp@eG2&!*!z$#hmV4MCEOuj2m1)}^{|g2-w3-2@-5KqQ2jRi7O30@ zwS~$nun(c~EwlqvzJt95m5s7azR6l`tJ87<&}|SV)EvT*^?^u8n;{xQXFxPZRt?b} zstHj-S^!anEFf}Z^&l!p_ds+(`T(LE(sK|!kY0u8iS#+dAf$&O217eRjD%)FjDr4$ z7z53K*aLn##Gdf8AohZv4Y4=;RET}xXF%)=KNI3$*yRw1Kz~A<06htDhQ#wTm3jF& z!k0pv2cH3PK72OB1@KuA7sCICxCs6q#KrKL5H~`{Lfisvg}5Dd3&fpB=R({En*nh@ z)C=MPXb!}K&|HXzpm`7vL$e?rf#yRz3eARi3|av3IJ6Mr31|n1Cne-B2rYtm8~PC9 z9r%e5A4$2)KNjgbh)Q2k5c82ffmi_l17a<*?hqT0zJl0X`@&1h4GTamc_ZAD z3dQpj#5@x^1B%*EcPQ#0{SHN4cm_p1cpWGj!Y4q{7-@efnjq~5MN`;yP&5r$Ohbph6=x(L{i>PFaz>K53T z>K@pH>VDXi>S5T7>UH#=pXvkHoa*!C*n+B$s_C!Q^_(up*3=79FVat|>m`I8sMmrW zskermsCR^&sdt54s1II_U8#?uKDPf=*QdK2dr)6QeQ}?wu5S?broIFAp?(DRrG5tX zqkaMQr+ym_pnew)q<$X`qW&HZrv4cYq5cgHrTz~Nqc?a2htr#i-qbjP-mJh;^cIDq z>75A2(7ObVrFTCZNAF=cp5C)?0=<_;a3Z}|>Ai-N=zRg4LhoBRmA=X0H2Q8I!Rhqf zN#9*KgT7yZvuGB9vuTzc!8tU`)2x7VX?6k5r`h`}x`1Xsn*DJh%|SE=<6@dKfJ6e zd*M@>A7tN~I6u;M@EPqu+Uf8!ZI^a-(iqygXjdmqLc1pI2BZaPH=^C0v?T4GwEK|O zr`?bCc+$qSC(@oy+LiW9+KWj0&|X4&Dd{lUD`>AI9YK2|?M11LQF_v^TG46%VV#Ihz=M&?PkWU~c zASNPRKuioeYY~&6vo0|y(#6DN$omqLkB}}QrXm(2T}mv$2%Y7KC5dH74-?CRd?>Np zi1{F5d15uv~>hah1P;yfAS!aT~cGaR+f1 zc@*&k@fvw7@doiGd1~T4;xqEJM8$IQtVECK8w=IZh<@i0txI1J%SpcwUlKp`;novD z{6b!U_*HZkA$~(Xk@$VYd>!!z@gI3n3d+E7Y+VL9LT3}oV9HSPDwJU?C$B{rP8l&q zT~8TB8BJc3GDdWEq>S@W(sz{cBGUJi2`Q73*QQK{q$?A<4OX)5loh{uGq;sUZlyqLn?lRJa zq>Jb-C*450neIx`tw?t*>9)vNfOI?Q4!Y||_mUnM!<0ymlAfcxh4d2XWxD%F?<(B` zr1vbIzOQr-l0L99)SnMYAJaWV`jqrF-J_)MNk7s(L;6kWo+tfoq4*EdpL8#f{_+qp z7U^%&e{?UAkq6MdM()Xj>E0j@BM+y0hdd5>V!HRplaXf{H})ydL7toLXY#z{`RFov zQSx$hmAt$W-M{3O$Sc$RM_!eJ2=Z#=joyej&pR3sBawF_??a4C-j^w2Eb@Nj{p0BY zN?b=iLOSFVB*r11Xr?DAF)sOJv-niQmsp7WQ^{DE zoXDA2gxtu#5sQ)kL}Cf@e_=TpVt?uq5(iM1k~omMjKo3I6(kO(t}Jl~bybN&scT3aMqRfc z4ySHN-DupK*G-Iwqo|uvHz$s!ZcWKJmbxuc3q5vNo4q3%bVK|P3q zZXxQy)I;tqmZ*nO4=2v09!WihIG=igeT<8#Cs9u(E}@=EJ(IYMdN%bO;%e%}NL)+3 z%#JU;Nr~&IcSOeZ)O)G-6E{#FqCWhjxJP}I`Z#eb^+_e}pgtWDcT!)XzD(RjeS<#6 zJ=C|U9}xFaKc;>{JWTzZ`UUYQ^=qtr#Q#MbN<2;*i#7xCI&DTHj82=0HY@QRZ8jo| zL7Sa67x5EqZX%3En}@b2k!XwYZ>6U#PCJeGn|226BKj3*m(VV!Uz>I%?Hc;^Y1h+k zqu-cz2klP!t!a1D?xo+Bc0cVQ`W4J8_6xmEs2}RZ7CVI zklT|x61S4Okh>9gkb59;H@TO@J>>op_mT&ejQhxg$wP?y$-~IQi3iD}C>alv$B@Sp zkB}#krw~t&7g92wCNCy0Bc36zCa)o0Aa6qACGr-Dm&rRK;uZ2i@*(0?@-ZY{C!dsf zgM2z7-XxzRpC{fTUq<2`@-2yX$#*V^_ehEN$qytxAU~4$ko=@%d_;aheo1^xeoKBw zd`kX^#OLJCCF2Y7ck&P7OY(2>U*ck(t94JjGpsZFWPhzZn|)K;`EY8Pg(b*FZtcBcik7qvI72emJ?AFUU4 zICTWA4|Ozk%(I^obsTj(Z2)y5buw)bb-EF4D0LonK5ZCvA<{-rmq)aTsH>=}X%kb| zatO3Zsq3j5X_Ha6P`A;hr0$^Zq)kITKs`vCj(UW8lr{tP1QBf}>M81J+RW6mM7CL} z=cyNHvr(^5uRcrYQLj^P(&nPxR@%JOy9I4N>LcpYXRAHxd+JBp!qo3dTa5ZEqAgDS zOZ`V%g6be`DXJpc($r{b3~d=kb|a!K$H>OWp0wo|*$3&mh>?B8S&Zyw^V0rCG(9vD zaz)6Mz>k7lg$O?ea&^cxz>kGo3-RM2*N^ZMAh(3v2K+?G9T7hj@&NJEAdeA09r8Hw zGayeAKNIp)@v|T=5I-C8Qt@*juNOZT^6ozRd64%)-Vc60=v(Ef4uu@#`V~55EEZevsI|P$*^Z za4-vHCB7sI<%#Q#LIvV_piq&xo+wlzraTI@i8&vI#>93+p#^ang_gt>D6}TtqtJ%< z5-7AMeiRCwiG2WtF2vk|LJ#7{p)i){9~34KcL0Tn9uKP|el!Yeh^vRfHe&msu#?!w zQP@RXHxv#h`WS^Hh#9$4~6rIU4p_TL?@weDKR@xxR&U06s{xoPZVw@ z?tB#PAof!f?j|}Gg~y29hQi~-%tGM_;ya`8Byr!N@HBC=QFw;vFBG05_83n;-HyU%MCYRL1u@s4@HH|0QTUFy zaVY#qoIxQHU53ITqH9rf#J!GUDdJv6u{3dSqga8s&rqyR+*>F%B(5`xgNZ&vaXc}n zp*Vq<(@~sE>?bHrC$1cd%ZN@yaXGQip}3d04^TXeIFI7-#9oHtDa6i4@hsvSpm;vf z@hD#4h6{DWMf$vOxx{os@k(NzK=E3lhf%zq*kLH%MC|n_-bVZc6z?Ed6z{b6F_Xmy zC1xCo4-r!t#Yc##gW{vaeuUy<9uJR8^b?9t5dDneQ^XvH;?u;eLh%_lyeP2~QGAK$ z5Q;AoTNTAuh^dX@tHl0?;#)-5qxcT7Z=?7Tao?l(F|p%O{DkOV6h9??EQ+5Ib2W;e z6Wywvnc*f>@pM!qO(yvMD#m~e=oqVy_MWe3DDOlNn&TCz#eN2wYyeNn1T%nK;hAi4pi zn#5E?sTMI8qtu+}QjFh;mP#R6#-6)MA_GXmE z5_c;~c8Onu(p|(DlEjS5NJ z6jT`E2BX3f*9R4jxW1_H#Pvf(3E~EzqBOA&p`r|NYfw?1xc;c9M9g$l)Ff^KDrylo z2^F=8n}~|K#0^13J>rI;qCRm$QPGIFil}Hp+)7lmARl5H$ZkW-DadY1%uHmrBjzY% zw30&`vCEOMD{_VcaeRF z__reaFfnChA0uSQK0&^nriBKtM*jz;!dqU(|Um6#)t{f(Hzk^PI5wnTP}n48eLudJ=i)_twV!#Dc8 z@U0%gcX|llOZ-)6-47nZk9r6{=^^~AhwzKOT=-RsXD-s(rp(292sMd6f!qefFCn)v z@t;DjkC+9>ZAHvN}Ysg(jxCXf!iTM(_dx-e~xu=L(j@+}voQmA*#Jd)`uZUTR+}EBK;RlInBlk1$ zjzI1g;@^qfZ^XY0x!;L*HgbOw?^xviBBleme~5lW?qA}~M$QrcL*&MY`5n1&!cNFd z5`P?xo<{t0(dg;Kn}tR%C*}<_dLuDD8hwWNKcmsL|4A_yQ-Z0sma9#fh=dIphCC1Q zde)OR`Wp2t$kTe-lLdKSqc6?!fo7g%&3yB$me$gqtQ?es&9lM!V7+HytJP}NpM3Jk z*2waak&%(clTSW5(wh81QJiSAB#xvgPA0!f;z+ZLq9`W+n_U#`qA1i^w2PuUi6beB zlgUGpIFh0`(QN?U)W1_-v9oTY$`&wvMm@_0`?d(m)t)R#YmK42Io#tn^JaapUJlA> zEnOIfaU6zW7{_6_S=w2tbf#%%rP7&dc^rme7*7$0VHn0@@(@i=lIha)B$=-NXjC4i zzEE4Ya~vnY^jex_wIIkES)MiXW?D<99KoTqR!xF(Uth)%EC=QKV0|#pGmhXE^}*p8 zd9%^T*sqy4(=^C~xe-stL7>XP9e$-Fii5xlXCLz5vT9_^?Ax~FS1DJk)q|@C>o&jA z5zSc^2Z3UqMCtNhV`jaSWpOagTWG~?%a<>I=T!$&RHoXRp*Cm3^r1A%YSn5sWDhs! z8)dXnS`nAHWoZiH=E{1dwK*s^mHA(txFjqby}~`s;=_( z^@_4I#`Kq&k-Dl!W>{B)sh|{F(C5U%R^W^M{`x9dHVzub0;LVH9i zq`8tY$97y6@F>ed(`sUDS$@-4s?kUl=fp{pW~wO_Fr!p#f@cN3;Dlh0a286(C6a;T zc}%RdI%`Sdd)9`alv0sfgix0;&TPjau4}nL5QmOSWB{&5xL9d*R+Gf{tXxovkcH6l zJ1~KJP=>l_A0enl#th3M?-DR>mTEOPsDTt^L0qD=s;e3%41Fo3KIi^o_V3{^{tmP| zoi=>xKrm(KWuJ4O(#7oOP#DwAB#x8KPaRA2nl*yuVmXIfVT$gX*LiJf!lPY6a=a;5 zb7JbjPE}o-(&XDYTAS#Zp!90M86lR%Uhu-evRsex;A$ofK99}4$_tof5mE-Gl#07= zB9_Gh&b-5$3F9oVEcd3nQh(sCi$6~yH~)PBvn+Dc-GWjCC|rIOJ_Og1K?qur?K6{` zE^*U&$-rc7O7D>wn1i|+4a*|W%?QxJrPud$C)cM;4p(PYv^HhI9L8-}V;7;M6oV2CB&4IMZ>yIi*~n7wQGvaA5xS>`KE4T zz0?-9cg~#KI)>rcJs(Z;-b<8GBEF~rwC=)Dqg@rISlaox6`?iX;iY(CBux zhIIJUF-*}RLdmc;rWy=PtM12>xumULSeB;T7AUQa(gRb~N7a#=7X2V2O2t<*O62Y8 zR8azy#i<8%R$3A}w#^u01oO2AwbK+JP1{djc)MQ}l)~ibzIrCFL0OzSRg@5gYc^wy zIJV8~<|?-8S5Go|jZ%RSEPuG1!vx-fP9l_4WsCVX5SLiSEy1a2PrStUtUvGAHsg%B z6GHuHUT%-+9Mg&Tz_Z{5oH5t2ZMOJoDCLz!?&L}#zyFs}nuhbGd)zDI?UJfTbsHOQ zbGEa^Z_i$kpjUfvyV2y%xpvTeaKX<@pW+R;vw`bg?dq>{L%Bjv_p((1lOMXqzyBP@ z@Me^wa~_Bom!w&m^-aGnZeNr|S?kn8g<9@9ihsMh8XRb)Rra40zz;a1_x5nX{+#Wd z@%aYlN;jKYalZ8F@T`C{N&)=$?VJPvT(?6m?(RAF`=1qc#QoIDn>qh~(WvD=!y!!3 zdfpzrQMcGeYm$+l4Jh_KZ|*V1m}R-Y^?NDzaWV`S6J}X1;f%qR%(9m*tkmfKU37?^ zgb)<@74i;cRk1izx(a47EQ_+L$siw8Oeoe5sp^60o4)x|HtK_R$XATnDJip`68f;& zt2$M06CiI00h_&QT=h0Vh(->RFbrF93=qey@xtP;(^-H0>lDs1YO`03Hsh7nn&~>N zm3VVBfjDj*_kyiBhVjoNC&ItPplAi1KqyJIF{+xpj=X{z#LaYY@~Up(d77n-gWaU{ zc+gir;=;~$Zv2MU=Dn2hzz6WgfChZi)Y;p;*vmi0w(ITp`2dtM9^5Y%E?mH^aBBuC zE0;LNVO*hid!dKV8N8}~`~Q7#nQc3SF}9dR01=ECV+5Yd7$djcMi^tvwwvQ~ zZB`@QLNtaC!5C#|r)yUY6RB@>mdQ7=Eor}3Q~@9+Tuj%s13hn>{VLbn}h9D8Roh(g!U_v>G7Nd0qAW^X z@XVp;ma4+Is&2WTDKDKo)$IawyQfZGTHdwQI<~jEIVi)`I~|V?@bht1-7==4!zQ?@ zZn>qZ8hG>BY&mq;PPVaeLOby;+M`rlfve}=QdM|HSocE+;pJla&z~1;pe?2&F0l+T z8>+fC1C3(Z;vYt7tRx@gwbB1fv&_4;<=75qjJfUK={Srr?%4L$we9QIuV1gJJGiL8Re(c)5!)0^kjM?8eXU-U(bL#tt4|~|*t`tJ<9zN`0 zhrUla_rdJ%oAKD}?{lMag&1*%2e2_(*R9Wa+$WtMevUo33jbA@2$8lRvhjd%5=B-ANhVxcA^^yERv@&NhvAWq>ND=|o`)my z)PT+WL@-`Y2>pnYr|_`N3fGi#-v^*u5UbftV2Tb9>Sd!WNKLf2bz@Cy6v)mEz@v^O zdb1JGY&MHmGLY4Ye^g!kxqX&5?FKE|2byXOc0MXM(Fj(kcOs}J0JLsk0%O&_K+ELj zoAb7@jSy(`mPlEe-u4ckXv+|3@J-MWlt#XC=8CXP#CCltE)#)}$WOafubFfH87_|X zEgnq_342raw$~l_aB8Tj?=$ZI((z~fmyw~3Y&ukP8f4cwaeHJdhdu^fk zSvSoB3ws{p!5_Y%c8=}T*Zqq2$g68~%VHFRRbxTv5c|2!V7PfPy%%H6*Vjh+HuXNB zwf|9%+>WE7=jGk9H0!6RYOTcE-!7Db{vGb{qsYJGNv8z`zvjf>{ch}dI-y2@`aL0j zZ}HzZkZG?jxBo|&z}wK~mnC4LF|~1?sD$fo%rXh&I-Al=F21)s41U!O7rzBtVH`eD zo-5((;%~3NWTL!29A;d&Hp*ys1$+!^H6wncc8MhNR^YE^rRO`np2{-S>+LKZ{v6iU zhojS{N5l0s_&DS!Q@vt)yEv}$Z8p=hgF$g@TSy9%8n1VcM z-L@Q?ubsfqY^~^q;I24T-<&j>sbgc{=E#>M;DiFCNy<-lj`>fWI~{SVzB$Mg zAmDzQ`i^t50}tn|l=?IlK&UUnwe`($Lov%E1OqrM;M{d=Y=KK$?1@jUjx*Mpfn%Tf zlAO4fW!bph_9TCJ{0U4^j!6QMi73Prgi$VL3E|kClZs)$uwHVB}Hjf;=+_M=H7Z6iGRta zG|RlHV>=vv#jzc}_+2>39oumjV~a@wkidj7=3HkIUxc@G82fdhy52qctYuu%z3%Xg z2h4fyLp`m%hdy^4zu1mrU#CiwAOCSrDSF*@91g!~I}Ts`J!~ofwfILUxZ~Ik3;1G^ z;SBWRzcQS`ga^#=Y#W!$e}SKXH~ZF(Q)SAf&92t^#)Ge=mwE2gRXDxtF3Pzd0C;bD zQ?sG<7gxzFj7 zXZC~T9PWTAD*UfvaE)`|gDo1T)MJbP`QfRLUCdJIG01-CzRpHTxcE3k&P0iX`x{~b zHbE{86SRY#fl!i-veFtqwl=jH47Aad&LKMiVStE*9v}ldqU6v{9@N#yM<|y@Nlcc8 zm^p|kV)7XcoI7d*w3iVy?v_nY-Z*`FV{=b4W^mWg(Ud2hPQs}^f+NNli}N_M?WKU7 z+f0w#a2#X4wd3L59@cc%ws)!4ukaMk-bK$ux6b*9KYwg#N|Wcr5M3a%Iw3LCb^RyM zJ)K$mM%(Ka5d$5rxWxW#8I7E3aG>=>q6Onm&9JWLg3{=mF{e}<#lUpfEYDF~eskmW z>5V4~O5x*{=UK6pfF&!Q(n}Mo>A9dZCX;w?@9=_F;9{1IBE zJiQ#iv*4RyhSty?8lwlJCwl?hVW5G_^+(KWBv`{Ufk~|pGgIWPDY8m@nayz68`Yq7T;AEs|OB;7%PRL-5w4v zcw;k!QqjSx*KEQbFQ6<=DGZ;abSBcI-@hnCdKHpX&VKidZxN8=K2{3j;qZY9V|8IT zY_~!F4Y^xkXf}Ha<4K(|R{vL1y|bL*UYrgeqDP}w`4n*0rj=Hi^4c=2t9ni^?q_{X zCW;ztq}(^IVh~LT9$l0pQ4P=Hnl!wLyd3a{^qXso;QlM45&~9QXU} z4gjoiuc2p;ZDCjgfKI!=d*eDt3G4W!GRCfSIx{|3?_`vSvCp|b7M_>El^4dCd;3b5 ztx~sNsnsl8dHYr9wEJ%Zz`eoQV_O(+9XmVdVR(DL-GRjsaFK4Xfdr5Pwvh@BW0+j} zDlF!ZB;lCSahN0!)3@;}Uj?8CN@Y3qi^O(m(ej3LQ@_)RNa*ii3MaR$(T|f^&k3vsJFGhD~bowHbgQQkwke7h`%tns5VPvXW zcNce2Ix|JCN7<;Y%h#GqigM5KY?QriQW|pN!6+XgsCaHzSA+i8+9e|E?VX+WI{AG# zugBD%mtfqH5J`|no(EEb=Uo9QK}J_4fRq68>f#O(7B}`9N;URAI2PfWU3*+Hz*4zQ);yRRD zTP1vtu3qov1*M2A7t1f;Tj4j*ucCLM&!XRgC&IJf)d)dBNVS4^FsGokX<1utx^LXf zC28iGG)qlpGGmM}-NAu2rZj0baOdjUDE-!WFgU2SQA4|X^=fa?rRk^a0tOGP!II^(CzJ);|09O*N|O;ixjh(a?;{s4K6)LEbHm(PlWhl_y^i zV!C-(Jl1;qb5@IDNNtQM@*>xyLaVy)>*heK3{2=cj0e8sh0<}Fnd3|DxoPN&fU>~C zzUzgaEdsCrz_GJ6DJ?e)gUq&M=sJKKNyhO9j|fac&yk+Dirr9J*mYx0IQM-TfDA1X zhAg!$`Ro0D-wSvcj>vF4X!UI;UiN#sgeNfxi7P36`NJY1{W$VRUckftL^XaT1f}pr zOG>aTi%Z7~1D|=^^CgX9k1`QZ+lfNk7NKVY2;Z{ckN==>Y{vk6K!d*xrDbP97`m2} zKJ|UhNwQ+OGW4u4cBJKo9tOuJLBKf8R_uf7i?0Ddu~~^G=&NxJztRk!t5>IZ*s z*|D_#Mw^!NxA%OXpO4A!0Kl6b(}55|_VP!|&tnUI6a5-`2l^=b9OCMz4jb1u#c9^p zU!8q^hx%Y{Rwz#&N%I9hwD?Pb!k>|l?E^-bH$ zvLkm|e9UonT9Pr@S_>!rAN#@=zHm)&&l7y@p^SKVb7hIbeegUk!Z7r1 zr9P-ei8terSGhpIMcRH4Mhk=yE%tMmfe=X|1bBow&ZEcU&s!Gvy!m)+ZOEM-dG%^4 zILw@`>EpY_7h#5up~s@9q1$S1P=|#*6aop%QtT3l%?Q(Lf@J!unj=Ob71(2pe!qo- zgSzew@_{j3(>L=I3S)HwtG>d`E5j9TVc!o!@zR$`02xBJ+41A{@;$iHIDPZ(=4%%B zD*lPzb>hT%=#*DjT=&CJa0~m704ej3mDNqe8?QXh`@dD6WjVtWn4!m^SEFA;vucUX zkh+t(@~+cvMFUKjQf^pG>}Q_5Hp9_y6dfN}k)|fpiK;fSyRI?O5v3_hT@EtT4{&bU z?GqauXbqqAnA0Pjwz~i3CN6ESVZ63KP9A&H^I5>cke}J{HVGyKlO`d}*6saSzu)(~ zzQCS`#mn))eA^B)O2rKcAV2i%^oL?JJjZY4Z+dB)`t7z~0Gxjo3q#I=Qy2gsJm3Ou z2uc^9z7yQt3I9}xYd!^i&+9Md+rAqRL7nAia0h-J#i)l4(6iAi(HqgfAOtY9i(VZ- zW(^#Hz$zt9>fxx*RwXW?SYPcjxzXNijHz|)&?7Zby04YC)r&Q$iAx3p!yTV23qn$6 zM7)H;P+kPu2WsJis_OQPF~;PS@k$AKbcmkQBUl<-OfB;Bh@$nCmE&i)I8LLCJ&^d+ zIY;A^AMT8t{{jfRjYcEm0I){ml<&7%EwCNl(KJr^dBPbxQ!0g9Q3SXgd`Mxe9uoir zuT&VTR|WvVFDs1IF9!g@D;37-?#CVvEQ`Q|QXwd%wBn5S^5Uze8Lux5^eN1fm#8(o@!n-iPORqeD1zwPScpH5G zKd;{3u`e}NH(HNexg}248u_c?rHj|Wix;np0|s2A&wh+d5<#sKKH}70vG8d6&&!s%r0jaN!WPO;_=X1`~&nb=gA}$93CtHBn_khkN^lF zclo{Lr}16zyQoGFLQh7|K@)TjLP)WdYgqh7UDr)}nCk?k75M7fX^>YsJ~fqm2PdDG z>uJ99r7!)GFeksiySr=Y<|q{(`)MCNHk;4+Ak#M_+=zz>!^2Nq!y$S&IzrDtFF>zA zx1%>8ROd#ldM9y`nP)p@Oy;A?+C&~YU)H&)KsA)`eUdp8k+Nhbs+tH{!byb&)w2mu zIq?Uwak;LA#kPIUlJq$-;N)4rMS2CRt*M|C!s7r&DZCni1wX$yj#XprySMIp>j!9l zZg8-^4zRa(a~h7AOc?J7D^4*9Q^CPgm{M`MnVx-sc?qYdP?vf4wRgYk-Hq_tdkHyX z{~GRq-$fOAEP5(>9=e85PnSZcNi2;AM(NzB^1CjkG^BYjhk8}*Je=dw=2Pg1HbLs& zUYPCf?s8`*a!P>Mv3*}AKl)I}WHLDUfJg9J7Gqd}(^d>PIk&^Q&!LK+-uZAW1tsV= z{pHb|K4_4uCc(0_6# zV{yrMzw(u@td6Qfx&0texUr#6{Lb(Ej-URr1du=F-y;F!Yk-7Nb}vYt^at<4`9}NA zBAWJn;eFomj(42Ob3xU84vGfgWHl~orHoG%=cpGlk@`xlLN7%&HN9?I`fL?Wkmc0% z1gfdBATAw?gf~T8txDQN%$n4yt|)tybe=8hsw~RfN}ZKWP1I{*Ur$jgW*U8xr@a3%6ZZ^yk0U_m zzNq!&CiL3yt85GE@hn2t@(2E9*dD6TBM?fefho;t1p@`_2^<8cpQ~1T)^(DNvVj?y zysYv8E>#AGsY=9(hN>Qz(chPJrv2;dam6JwE$mF)Ih*wC25+4kqgac5d@bysfv^m0ssJqo`lm*NeHD+ zDfBHt?O)*kzjWzR5ERWOxKWs;X~MF6Elof~5tH(=6(K$?lrmCj=lLe$-IoYw-s)E} z_DVtNZ*jo1v6d#V7Ol6-Vt02JV^TDmV8ve3ij)#*A}}P7xSB)l&oIa&6(MGelCCu<1}>8H`XoX3bzvey-1Oe-cB76R8s?yMIm6F} z-$$%w6F&{zTLp`%l%8!H}o*sb^Y%Ii>2>~kxU^4&os_$-RDd3J}jbo+a{mTI9X7o(+OQS7)R0AcieDIKam*lyqoA|gnHb;pfr%9TALIw zgP>;8b9ydGIXFR9BiD7zqTOWL8&$)nFJHdA)^1x?yS?_Jr_kg?Y;FB6c=^8i!UGpy zgbRx=Qh;_FfNy)w&eMz)pN#3n2}JQ~D~{nq60GPAzl`v1(a)Uw(T{#)`4~U5lw$I zlo~Sw%8kIxzr_Y%nx(CZ;{v!&WvgVG@L(7oPA%keoxXphPls|n3HF?+tsU!d_~cZJ zuQ=FtG)Yk;&9U+8!GBQZhQZ6FN`=cZuT)A%M8@_v;NLhJ^;el=Fb=Z(wK^^kdJ zwg2Cfz99%bVi<0E@ZjEkvzj)$Z|}i_scRUdcTY>*MoVt(LYK`ZIfL@4nyy3lAOz-) zFu3G1lnW$gEJy@X}@1BEU7TP|>ew#oNuHXlw zJs^PkqJn8aJ{srLd?M+)SfFH#&x{HM(*VFmNMVT?PHBP6xrAXB3ZwBT3`45F#Sa>W zV1zVOM04l{RSYNjEf*AIvg~?c1Zodn&3JtmTt2H>EVCL;P9U*82K^vQICl{-%x!c4 zx&9&5p;ET&gO($iSPvi@z6$yARksmODjX4}HigiSV&#UNT5hXe7Y=93tWcUF$m#5r2AOyUM~%?74+Q=O%KN1{kMOA`MW(Z8&DJV`KKU0q*aUBwUvr+msxm5qi&npV6woz!HB1l;!VJLqzB!;y}45}7BVJ@&iy0adeq_<`S|1J+vrK)U5!giZiVOaLg& zX7f5-pPU;T=gysbn*;!F0SfL|g^4S#ys}m*Ng&t3KUj?RpeuxXhx==2oOC;_tee#n znIP0tvgZ=#49R|zSvSkF{w3pos~`B@$vt#$t59eFeo!G;6+q{W@n5w{J78`6J1{r? z9f1%^bgHQKzgUK$X#Dd{m3`oIryD`X(g-)Yy3sSilXY8 zs;cje*5;^C-DQ%+H4&8 z7ze&bUfNf+RXU;j82kDJRc)0aH0t@m9pEha+sgc}jF%NvEoh${K6^dn-cE-QYIlp> zMo+#x2NG;S+!F@mPx2Tj=KNt+jxkb-Q_ z%6@BQWu>&ZSUM!cz29i1t$@y52`UCLjAGF+h*1G)_C5ncV>Ynt)RXF8wl zpVzgYB?TGmdM z<{+fTH5vuEH94|HN}6+fb(K=4vve}Lv4wcp7$+?fc%AcHPE$S#@)ka`A6QvgVItFv zny-L3-|!Q3KH*Slaj}%?q1=j4Q4B*-6l$0XCB!rdp^9lx0m>8SmH-YkFmmfSac4(%cC`#x%(_YZ)bGw5O=g>zx5NhUF z!ZNV>CyNasp-D;Mm=2N%k}cKk+WefV>*^g(xI%hZ(D(F}?k)G&f4(a}L+PFGoUf}x zO7DDHGs4<04aR$}lV4;dRSBWYRbiv#tJTT&OAMAaenhyfIAR)IgOHO^#Qi`%%New7 zshnV^SrIplHlhnzCQm<4UUU`sJ=WjPpDX!|TqSJEw2znl`~_YlhEj zmt}pM{PIHcKl|AeC-N}FhMom-7@^D1VRR+B9^IvZA&3|nbjgWy>}PZnmJ$xmuqL$B zg`Fe~I$kGW=FR|9fZ(KEH#wz8O~y3MKD3)H?OF)jD7Z;F3n}GcyPe|Ii{ByRZDc}u)*TmAE-!6pPg=a+cXs)9iEp%tIz);i$&? z`*~fx17-#=LbE!UeK}bR(833hj2OqCj0>Dh|h6I4%jhpwS_*iJ>p6qA1VK%A%;gtm-w! zDOGdb=}{+Ro)FY&;&r?*zG%MAKQuQFFhAGIy!gdQhJjE` zXKu0RGF_ttFq>S=XUZjjQhDaS*(K7`aL>W4PZb1)e@0P3tjAI2ZWEemdCJZPKRue+GTqp24 zUg^hfDe%1&K#4S<`dJ%qGy+i@HWx6*rS`fGh$jh&M0TPJwDs5z8ljEssCS*mDb0sN zgGU-6i{E^>&nfMbC>fY1ew9;iD?a<#;j>t|>8At@D41=MWmVu;dI{l+xOk}PTDah_*6CP^C43?k&uc#EDh zlIr!k*S;LA1EbTYPs5|v!=r+b^V`q;(e>9~U-at#rfl0F!=r~_G)5SWQERdP5FUj` z2YH?c*6jm$6dom%O~a$Zt$RPSrFB*x!4Q4GO5{F~@VH5r$PvB+=MZxcZwFATvt0U( zzUMoPfOobAiJ!WmGud+1P3KUQn-M$4=Li{HL=rh}#I4R8MELOT$0+_or&zKqpbiF% z0Sh(LmP(cdHb@fKU|A)}HbaatV8FHtmQ^a*Aj`1s&tVAckJ|oNstL2d7O+FXvPwk< zWEtQ++r^)@_orMF_SV^Q>UH6VUhx|k!M9P0cA*XQ281MZjnYnle!^}e94PFtmHJ%5 zGO2nF3&}L$QOaQfY-h*&@?NSuZFn|KI)aZGQ4&+D)>D+8#&r;a9rtxTE&CW<_hGWx zHS@V1y7A9ex$!B3NOX-bM%JiAj480~^0U-+iULKKDmpHGw%eS9DIhDa(#nd_m~-p; z_eS9qSCIpZafm?#L(oB`tKOu#6K~#GPr+`Xa5}=?E=~1x-S_W&b#$6?dAeP^tvy{X z*JOC{xD;Kw3hR%W3Ps1IaqCnV*UJUQ)8#T8o^$qLD3_;~S5$4NS#TA?&!B5_$7Qq| zoke$}`w@cc5#h{)s$t`}Ai0J^a(U_?K$^6oTlcC8L#a}qAuQ=&cAJwI*cRI^o7Zgk zqdF>37WJ$cD&MQHR=J-JyhMyCm~3`0t?gyohATHbx#DS${P@Q|u62K5b^Q0MC_el? zNI>ECOK>xM3tf$Fv@Ja<*rals3w%~jiDO408ELW=x1-#0*-~>W&IrlKsd-UBMlwGj zNh{tKh^%v_ifrHX4A^$fEK0ecnjZLvzhm>2T@vvLsCWtj&-Ll^DDV5RLpHXiV2Az^)$$ zZHu^c+Y2weP@8I2s@C89$AA0>h(8x(eXV1|?Jf8i4AB(~ZqZy4)i+q349Rhg0Jbwr z_;}FOLLZMB1k;GU#JhG$3A46mPSu&io7COw`fZM8=JUZGkyTC86(V4!`eoZvG*0Pk zsRXicwJ8da{oGq7qWPlw)Waen0%n?~E3!cdr97iox~+H#!ztn1Zz{e_N5a869DPd@ z_Y`nTE>V{(%c>_|cMkQn~tH{uE zY!EpJ-j?S%5hQh>N&?9lJLvc+pK{Z9(5Lq39$Hg!d1UKx`<&8IVJ^&U+}L64NxrJ^ zVxH$jrJ$-LSJj7|O_$^oUVwy{UtVaI2iOfA^ZO#_HM8G`>l5Lpo}6q#z=wL6Z%7I3bA)llKHalP(3j$5zC zkM3+$RT*nG8B^8C$uA{%t_%K_IB(Gx7xzw2VrZ-8sVyh?q2n|ftyZJqI6u4GwGC|B z(kGr9zz`k0*Zjz*Czh_4)ae{#b1+My<%?joS_ri4u1kEXH%~pes-BwjW?^WWWj)o( z-Hz{+RLpG|{G%2NO(P`L>yXY^C#k2|Ogr^@J*r}SM}bs>8b;#*491tM#tu#<_jMWu zq2s8g)D|^N!IpCqk%jwhF(xg{tXBt`bs_;Uu9V=PzlA#{M;KE6z3GJ;g% zLv!>;gnua3shBgO`T>Dr}V9G%95X5 zfBp51Vu9*C086XyMJLd8V_b~M#KZC|%|7xm={irt5ONYJY9=5gORtybqZbgl;_h1#<=P?(ZtEk&HEZXFhDvF}) z%VlOJCRBkay3SOAMf+zhF>e9GWV0K!7C?8QwTPiwTN0Qbs{@RfccsLQCKq(33IZW~ zzM{K1c_YA$)pF=Sb5C~w6-=G0b8K~Cp^#_;#{(FSi{)_qA~JT2#GCW=URAtTI`^zj zahub+EDIvj^gximy7k1I@PRP-CEw3Prs=vY3*`KsRX-fh=x@B`Tovu>PrZGqqs{E? zYok`bni=((^EjnYDl6NK&y-8$=vxVCr%qB%LeoOM!Nz}8feT=QHR=muqVx`b(%=}uV zQYjh+kSU1ZeU(Zjf++&PjpF!OFt!Ys7&o`J9xejI1Y>BxyIm>*amWS(Q(LIIATJ*vXYG1R=%*8U;y7j zH|RIlWzvcp|H2})S{H$#*6m;c}37~ZA(KJe7 z5|=|uunR6sU02BA4wjNHtS(QFrTxh~FXwqQBIr*CxzV26A`k0J7-zlFNMTcAN^cC` zSLtt=`4hHXen5k&=)7yK7`_K=qbIVQT*RkVWUoi~Bcwpzwojc(v zTT+574GCS*du}9o1ewL7-yZ*q@8_paPsA1LjGXkGMDN*p_?wax~}UkA^O2Xci(;JpiYRZYXDk#uvD$w zg8vwrI(ef)sB!4**+V8J^q|6+Qo4rdFw}K-{1I2zv1}L^8-|Q^-Gy69qruj0lv2*V zqH_)F06NyWehsDdM_FAER(56w?M27^Qt{xsc}yMWnk#ILS~W@1D9!E~=;R>SVoqs) zb#_)0N)Ie(v$Ly%KYsDW7yDtMz+Qau#TQwj5cb2uroRp!My5Xw&=psrNf_i{*%SGM zZ9yJa!B|mG{uDZcZb5e+Nk@+9v35Jl@i7h~X_We&OQNJB0k@%(q(_Q9M!h%nmZzr! z=NKrDo*o_C38tr)H(q+?nP+;7wP#*_`DK8YpQ$bOo{5HYRG05glSjFyawwH_xh$jV z8fHr+=!a0t6-80PehorC4dpBr?Ny^zLh3XoFJ#sCkVzwo6OuF{0w|BsYdR$ayS|DE z+k!7}A}i1DltIrkUh=#m6aEFbIivYn_B}wY9f~C49lcpenb9E(bC~a>w*!lkvcsYe z?9)AI9HLpY6J2YyO6Xnm5bWVld>kn67%utd;ArmBWc>yKhRJI*CMlwn_hg%Q4}y4E zlq5~pn7m>;P3P@)J22JI2Gr~I#IrYqwKnHlXRKtJ<)T3LmmTs&2F}h>3Y&> zN>II9P#G%)VeF0ZtTh15k|DGT@-?Q%BUlT7Md!nADxg_-Q|L0t8q?Lu=2f#JTYlg8 z4_w_Jo#drOujZdwJ)m=b0Zck&$FyQAAQ`FiySkBliUf5pjd&!$0ZdKTjD|S7j*wGY zgE!l@4WUg6FBJ%Yf}_g=jjakB6*D#7nhtc4gz5Gw+QBr0Yinz3YXLyu2wCF@qbx#W zPsaloW~T`Q30YMbN8DS2)|#y1@zf7Sl#!arlF`MzC2zoT)=m4I(g$>niGnQaPdvJ@ ze0g$G1eJ1~Dss1bvd<|Emd#ARQ=ZiAGz3}Jb&ZK}<;RVF7#fX^qEiK^%9WF8iYevi z$ufPc`Yz}W>IeNNo%5mNF1lQSH8021bil!}rtLV5n{VA?CzcRNI3I*)&|HSO;d(C9 z%*`z`A6a+nI3LdE-zARR)dy(E0M@)mcf)KRS!v63goDDX2nfaZ-@IgfKLfE@d#EhRy#n2a=IE$&x_Y z$iqnpEOUGR*lM*Tsl~A*Vg6{BZ*U%Q*D>IckJmna3w-sCJMJjlQ5Z*xvf>GfB6vFp z+41h=E6|^F!uN5$`RCD+q}F(7IF1o<4v!d)%OlRmZ-JHPC~R!#Nh->Uw~anX9QQ~9 z-$x9+L)V(LsPTyM5;W1dOkF1JO_bFZA;K$+KZugHqhH+;!_PUlto4cK^?i-8N=2(KE5eMS>W8VR>PXA z?Bv|C79_&p1D3`4`un#6r&O!NtqQBo)ET9$+KS%=2NKZtKd4PiFpaUg7-|y}jA=iA zTcz?ZtjG(N#rZBm>-C*)(+i5M<(UqFm*IOzL&wo=n4;ySYEreT!6FDf3Wl4{lJTQA zBvHchfl5^^OJYH}5q+mPCL{&5%}*g0d7ZwGD$|_QD^0iNuJt9+Y~37iU8uZPh-sm4 zNFQD9)5Y`i2P`9-nICd|05(IPFV7J{swo&Vrs+zpY|pa5cV@vdgLiX61VLr`L)FG> z51?VLAGPa_zcv^)##dE>DM7bh{YJ<>^Rozy~LDg8PjS1Wg5oD&5Vhia{#ZdN_Ik24~}L_lhv7 zL`Hb#K>Z%IR;eTdLK@=p9#lgmG=&bMtI$p8HRz4#o#+GTQ|OB}K`KbBfRq4!2L;&3 zU{Vm>uG`{PoZ)A=sNneG6ld$qY)?tU1?-zXo)|Bf=I>3|-~4j@D~iJ4M@&(mQfY%+ z`n!@0?MelH=G~tMbNvkL& zOiy>OG~dLGQ=)+@?UyRs5<`d8tJ@>!>!s+P&1^9&VxbkMV5xh))Xjn^VG65;KD#1_ zreW^5C2nH%^qP;QmpO5*I}7u&3lrCxHi03AEG%ttG?@T`K zvxai)jF%h~i!cF>F{&)0kBVkq3pcX;T!3 z{u++`-n$dEA$7|47|D`osjV4pA5GD=66C(O)@1eSU4&BYoTgpgdKhbzJRx5o!Zl|zE2FtM;<~C2{_2YV2T94Qti7aST>Ef zzzB^&46^NqX^w(MqAu*MfOR$E*&(MRyYDrJI590-BS+@AQ7utogg=nqO5Lc|=LVYW zo2#dApyjst2_PPfDHBTGMzsjTSN20OeFImGOHkn4M?LWSiq@i1De+yq2MdK7c8nAk~t=kTpN-;R`CI9zB)wGoE+#&-((_DatB5Jy0xt=XdI|>LGJKnU)4MP+$ z)|n=XlB^3N0AOz096EE0Oj1>=NF-HtEzh&@v`Ym6P5?}M6bpcDf6Agn!2-sS27OCm zG6*7wGSPL$L_rXN+Flo`g@O*?&Hz*jfyNXf0n=qkt3r;Dso*>WKAcsr2ju)x-5wrr&JO|NtR_JPy~czgtoUZf+1?6F1idIMc1OU z2ssfQFh{{3?dv3QW)9s1&OB>m9U4?QmWf9-(nJ`!5(xQ@Q%gaXgo6M|DL;1+h>ME{ zR|-G4!b`A8sQE%|46(nKd#dD$HXdZtrzPnPEf608eBBeKY1)SNHg|S*MH?JLHGU zc)U_+igBf)dHFf*$hzTV%zTpp=bjjHcB)din%)KYYaQ8&5 z*b9j_CyOLFm}XY0XDYC{oG%fvrOMJ1p0{DLLP z?2u(0VzOi{oUfrI`MV^)5_AER!$+dAJn)qc6D;U(<H zPaUK|5)%?th($(4Y%~wD&Tzj$Zu5Mb!$#mkE2+K&Eiigvp67Y~Kt-@?n;$gHq}gg3 zkU#4O6r&c8-5LJv0v)fDrd|@ITJ?bkz(P6-CX?c3Z5mtl0~|Euv-dfl;W*zkhg&`4 z!4COBWAo8LIb>eB`>3OU@_*I<I{v3)cFH}Fvl*)Br2;UV+p^Sz$btX z?c6!pXiVySRfpL%MxJK5J`#AfEipfEMj8(`#}&Wl!D;MOcjY}jQ>p7-#yLF6Cau`mqAgq$2CRK*tbFJMjzxxH&^p)0E4<$r!)s(!ZYJ5jvhUFPHtTc z^`|sLjIU!)U4HL9e+lLCw5TbHqG+POP8Q$b%m~e(gZ!f?ol~R5I^+g^px+FH%Hs?I zUIAgnqt?s35RxSf>qG7M6^4}Z!OCO=uG^3#mHj6<7z_r3w(h|O6O1{a+M+gp_<&Oy zn+x-o%{QBcYWyT&kPilZ<%7arEZUeBvi%G_z(C$<7dnAni;z>V*MTerUWV@x7UnL1Y5+B?ss^~HejTu9e>nWy+6xCJrM%sSHX*h&Gk6aT zIHjW~p+OUN@!3Q4E9fg!#WTIc4>F2`meGGO4$pRN`4VshxNvAIiH-ryaEtVZ?v8x^ zQaD_rL6UWW92;WRDPp9&aEmf=DtuE%%Tjz3l{WgP=K_|8DpIzLUauYj+fOG^!b585~7W=VFGFrh6pZZ;v@J` zOG=4fiu#Rk=l}li|6<50Idz~`!UsLs8>>;YY4hZ>p?++9$M?SXJxV{8MUEYecIQiA zqg&9U=qZH2(y%gSe;S$if%u+`Ag#<{_M5axm2@dJUFDyOv`nCI_&tP5+uw-?pX`fD z9-tw{y=e?fTfx&PkUCW8HY9N=opvR7e*QqOr)dqx;d-2u!EB@adYn+zHO8h?m9ffh z#?ZybdlSo$*X8Aj&TalhD3_;YQq-x=m5A(^+IX?qlOjy)M6NW;*qW+NF{Y{$yHr(| z#mR$zBRr1Y_q9id?-q7sQ!C*bWjzT@;QC4)vKhW=|-lGCy$5K@uIF~0m z_YswR@VfU)Glj9N-#_ycow?5}`RTodQpl1zGuT{luk=PFUxv@3-RK0m5xoXIhMwmK zIaE+<{@~I@$+w=sLRiu1a33;@L7+LLb{CUSA6gbQ?P1FROt1l=QfQgwZh#PU?wU&{ zbD~j!WJ)H~b zgc8Dd7>1E;0Hb%k+{Ur{W5&PV>s>nNm4KjFjDq6bl#u9u#AWuu2+g3I&^h!Tgqo&a z+p0JERQOEO8G0uz1q?+^(?1#VH3>_)0h+tz`Nxib4z32kbqPyf^EnRru<<7J zLC?{k54*)n+#spgQL3qQDeL;DBzR-(Hg!UkC0(HoXCCnuNK0l)l4UOim()v^>spoS z=UA2{(~OC^MoyAEvV(6sS*HOIR9~!}W15Q7b3br2&2=>}bO~cstD{|>&O80I`q{^H ze66Ns;4TOuhS2uc@gdn;yhIHkR?F0P6jr5n`Q?ydJD<=wjHS$bgb!*uB$bSFa1dc8hl zwDc1)nfI+8jd1VaqM9{Pt<#63kzW~y=po2OgI@~@D z84zoGq|n2{p}MN;Dq2NRUELnxbG#HCdkqtR0sXiQ%X%arp%@i*Xm@TkxR*331#v)* zin^6a05r0J3mpEVAYqx9_^-AIP)xlgov)pXI(KV5$D6Y0i3Q738b)U8l&;$ctI^*x@Z>zcPm*ER3(*KJVG^Lvo{VqZB}H$3*y)i~dRM=Rn4 zjHw#?UShk!8Iw6IHPafqiTV1GMhww+A?Z@kv@9!90iaby{t14c(wV=Rc6fIWz!Q~( zbfe5zbCtxT2qM1g^jyd{KN_1Jj}Vz{2`lmiX}2xdf+3nfJJC8Sp=CppCb}f+KG`5% z;x-7ZqJ%AMtji@baf38zb-I}prIA%8XaHN#T_pS>uzJc4#s;0h~V12d-nUENfH)z-gL`NAGD<^ z7aVaRofvNc3vp9BNur@A5AH~t`B)GoSt8_y?arN)dZIk`ZpYD*o$Yff3d(1}9ch1p zJ7IpG8~pL^x%19D>E#qI^hO81dd_KxBuf{_{};v$u2e*CmZBF8!UE@d2!GmbbjKa{ zH$@~_n%OJ7(u1n}4GB(S8b$jl{{;oNt*+`yUNw7?=3AVq9ABC4u39X_vbTfJceF%B) zC_GAwt2q`YEsfSNQ=(>3QP##G(NAai9sr}%(w2~j%NaQN4Qu$3&m*XlM2_o{48kTA zO$#tnCk@NmLwhF;gEyqLhw}%tVyW3ol4i41)FnyZvrUubuOmYq1BPXBzNZz%tiieU8+@mAHeskwUVao$sLE8IxQre-~T$}>JzQGXU`oC zaBi1DcWv%kUI};y4M3lsx(wn|CyhMn2#MSO)rQ0uP{$fn^tN6D^$AV8&OZ!@a%r(o z4e(QGLW#bgJ|xi=g3zBM6r>f7r-2Y7O7WHf(@@Lz)3SR#Q9?(NbG60n2Th4ACTxpa z5m8x&Bq3CkrLKwgA{R~SPODYya_#`G0trPR$!dC*Pq=vL9wA|R{9krcyGy#ZtvUo$u?=jXi_8;7>9*LD7L-sn%E|=@(rdvn#a@l6iUIGhr9pg9a zx}&=e*EH_9x})npl+g3kb#xgzhB8Ykg5a|eWG|d8q?VJc3R(Y!x*jYn$vYeg~c*!?P0JaU_c^~DO?VXK~gV8tOg)zUsXfXOP!v55hkI&aE zm2=gql}vl0YTMPSZC7(v_RUS$W@(ML9d4jQI&#btbLg1tTij0DvhUTUz%oBjnHN2B)SpZ#aD4~kaR@3kGdMK>vVt#D}I6nO@ZyQmq=z; zI+FDkwu`ngsS|OXK0wu`33TqhA}IB@ZosOl=8Was>!Dy6&}8iYz6%EAW^Ft)!0}HQ zOzY1t=Ck5@z%#A7qWn~=UnA~~e>YN{^QpBTdL*{Z^;2ja z-Gmk6P-iP%Vg{igARGz1BH_pyodiX?eEhA^zN^#xgn=jaH)Oh z7`h7GfbK<4;cVsWs8Yg{EXzay2NMDdYY6@&2xTFZ+`iF7BWT)7(s*wmjTG6o;g+}+ zk@+(W=Xs((=W^CfJ0b4?oj_v0<4ZWDv}++4bYiZR-4h<{_1eAO#a<5{6r~oq2*e>0 zJ}gx7Wx*-UA*{8FiWxS&gJJ$pv?c0RfHI53K;h*qI#<+6gUr9(xo*}CP|EG4C|bpFz_lvX-s$zKRxB4B zr=lqeq|ppp_Alqo|CP;o)3cH7h;!c7q^2m~IF(133$9Z9Zgl|QvPUY81B#+ej{k`N zTGlk5I>_##uIoZ`9R>&=%8O!aQ}OIVN^XWwM+qVBz>T=o>9_Ih%-;6inOWS1N_DP1 zSFJcGEa+y>U-AWAcmBcAb-|Z7r7)!^in4cR7US8Oy^1pDg>-pt?UYGQ>FL|12uNl-OuGN$F;2Sir|R`OaXeNkG0!0llUO40JwXwjuw@7e z_`W3DcB^GOlH~iK2u3S(Bn5lEELp^a2=k6G+w%n3pRyrPMRUcMz?+h4 z7}vxpA0&Up6x9IiDPI;m&t_j*TwF99i#7N7qTjkRsa~aLdSh zg8>^yKKMmjIw`p~`WJe)s!p6S0E{yeAI`C&sw<4m2A=MPViZjuU$Q`rg;ZLr!wVOA z*anzVPxdkQoOQR+z-QQg#wuVKP+{z*9`lN-qOwr@GWr^tC3IkzB3rh^OdS?SdAeK9 z(pk7g{q=_W(Bg!6IyfX(emz=Q-yHB1TUHezHG*UM6<=_<4wqte`*zIImK;3wj5*R519 z^tBQ0{`cguaSCmPlzqT|Fa2=|XmdLAlUo{6&wzeH3r2bk3CqXA-)u3;&=GV7-Gv@T z??&fKhmgB}5=usxQR2&Kvd{?(Djsb)ZbdDC?7d6=)Gu&KbNCd!iH4M%rHYcj%zt+7 zQ_9C7TT$RGg5be+W85 zaTRK<`3gq*$jLSKe;ROm(6oz-wWmI;cvE{OQn0h6j{c$i4e0IYBk1cN1R}*FB0%Rr zE(?8wOY2ZPuPt#92Pb14RKn~}9eI{1%d_l)txOc??*O&MtuNudFhV=f z5r4Zb{1NnC^ep=PEbS0UqR1(flGk2^5R}h4J!k9q9L)p}Uy!wDfsk4^%L0jxt=+7f z&BtDenO0~3cz#CJ7COb8EYsgiF%kP#Jxl3>96)20YM0V(wZb$2{^0F5-gx7Z?_oa7 z?@m5yfe{uI0GMA{nG@$=xxo%6@120p`*ot&md*O~bgLDJV$f<$PuESkeY(|Z{aSfu zddhZ?ukQZ7`v7`hy-i=~ph1LgfU70yD%IX)?L@mebu4^@c_}#mw7skquczngQ9sRX z+lBc<(eBiAkcaaO`tmrK1PsHBn)#FP?$ND)n-yRNSk%FUocn|5TGh5Hvz`HHW0-%< zY^kd8M~13GsT|)LmrHs2OKv)o6BV<+^|if`ZU2RNO!mg#G*nepjq5)JrE-i+G=_cs zo_#{DpN_c_ly`CNS1#}r>_zsc?x39SqRl&(}S^Z?lkZ&`EOIwF&8rIT+NuJEzn zy?y#!L2=9V?(PEynT^d2xoJM)z54dC_!9P=B51zd$9Wir);wU3UUtyhai7*AgTwNiD2rf)a2DZQ$4e;q52+-HTNc;o##s};|%PHmtZkg1?0kVyMWw zk6(>m_y6$ChExHJw+Vc9*0EF2JgBkRp+)t5Xoejvm@wcUD=&!qK(@wOCUvvl%n*pc z*#FgE^{#ili;2!fM`Xt;l}d;q&kfqx8;29B>z3YCay`W&@q~XDMdSEo&fAvt;x7)H z?RJ}U%K}yop}JhP_XAKn9TnKAQ>TpPR4xfD62W`sQ%&Pkfg1)dye0CeP^8U~Naxy| zx7*k2=iL7T*d*3h`OqM%+yc@UW(1h^F{E}SS+Y?$?IkXe_IgJv<2YGUO5>F_npm|+ z`Mda@%%G)c9niMRvkc0f%nkeXw!vku3~W}EiB_z2^}E=J{oZFe=g)8~y!-YS1 z+%k;Twnfrk2cX7A-OO#3G1bn^`i4Q}!EnLXeT=9vHD%C$n3xih*epTdyK*2Z85>vW#M2B z53Jl#f$q+0f&m7sA*^paRCB+EFS<++h@xrQ6>|V{S7@4os&Ur}cu?2^!+=|;6H>}I zIi-CAuzfv--c6J(QM<|jFjk~{9Qt|#5E8eyw@3JOelI@mRp=)4VLW$&$pjv<2iASS z4{TbQ07cmmzIFEGA!64B7Y|xITPIhMyOHLGDZgmVRwNPECOnR50cB@%=g#ITZuJhD zu2gDRloVSWiSuXx9*={qxVDpVgC@w=4jG5NUXRGi4NVtmhUywSxd5GR_f{uFiqh~B>1U@JO zrpK`JY;f_Y%8p9XZ((uZ`!Ufr>XRr#H^~#okSCQhKV-KzL2Cm<2nFzK$e@OlKZ1^i znfAO?@76I|c#ct6D5x#aP1%}ivO+<718F?;w9L7)vus-cHOEUYt<5RGcgk4xT)7(* zMg>>~a%4P;oM1}HV4sS0A5Q6~EL8>DDo;ALTW+s~lafd|NZ6IBhhMyhLkJ-m+n{w4 zEulT=1iIEkTC*e_0a_4JLcnQBdSZLl%>)q6T+;x#2cI*a9bN_@jXk$2L7)YVs^`f# z73}o5p>lcp%67Z0ySCca9h<^oo9@Z|{=v*`pH@4O=U6Z@jbZ>9A~!>7YD3Fq82?GH z*Rv^iUX0gucSkSvW2^lMkq^RVg`Lfv6m%I{N4KK;(A%xgliN(ZFdFH)+j1g@d(7#tvPn8A+=k7$W-je zR{kXy)`KWKMAJzH=Zv|BTEjumd$|dWVFXBH8@GDqHuMjx?i^839?Rf> zhgcH^-V_zR_X>2?0wbb=VZ4Q*M@9u<7_nukx9nrr%P2v|Ef}FlhdypH(1EERGIi}% z6U*&>R@akOyqu9Hr+*jwj~r*G9k)_ma2osnX?dRYN3HFXor(dCR=CvHHTTD z5Qc?<+B@o`zdAk+Beg_Pxfuz!CLcdwUp5uyj(}7CgC})0;-$d% zpt$UlRb;@qN$SbR>-D-I;Rs1U zV~!RRUirZ}rCKTog|b;LSgvaYWvg5egj7?={FvwC(HFZUTEyg0x?U*gx(-V}xXw4a z)*4_-5G+kIMZvVkWPMV%92BtSL`n`lZ;Cc_WWokoZG?|3 z#ZH>`4nre{m*&oWBap!MVnl!VuIQ17p9Se`5nXOO51o9=dW)Nj7pb2&S(aZ?Dk*>8 zUJrf9#tZ|K`osp$1IyiPrW-C3q8~6X`_aEQ&?y~AxDbzj4^;?2*WD>w(@Mmj_#Ro7 zhsYE_S42yqWo%bT<7HRV0hngn%m&Y`9-$euPd6?hB@MC0=dUI0vcV*6{;6)LV{qL} zw^kCfvQ&jQcCl$R=XdU0R8nANH#4A&Oc%fG*H9Iu=(Xsr=mY382sHu8fW5_b+2Qm% z`Dhemcx7;gS`5DzN|u%}gDP#$9vx)mQ8j}ju)CHz8 zO`SE(WdL3x$BtuAYB-KAC9P1Ab?ptHlSHBEb@P9FJ>yb$C@HIkLSXVa>HA{mV!I^M z1xA6+HJgP4^YeIPqEOHX(F%o$vh6r_c})a;c^-pju$1qw=heLpcPLEjG#&Qe+kb=) zz^Bm;bbPf;-u3i|@N?+G5^mW}rW&@_>v^`JW{z#~#M79z zDj0?v6bg=MI)y^u8iug?NBoIV@4&Aat)ZzEm5pYy=ka~U8sucs@>V5+ibb~RZXE2n zTb`r9cDss02UH_L-Pxs+M89en)^xc{Of&hA`KaVno&y>TK*TO{P6fxUjDJ*d9Z=8h z9~y>I`}su5SBn+N6G3qG zsFaUK(}a-!C52k8Ua!>(Fj7@MzB}|>0M`rQ7rCnb@(nlKaD&FVX>x9t)xC!vcYnQ4 z$J;&-=_tjmwWOA1{ja5m|6EG{6>QmtrWv-S_?&pRE#u$&hky8oe~^v$mr=genV7IO z&7PQWik1anSw$oxvi*JdIeZPxpsUdUJ&%3^{d4a}o~o2(;>}c_8z2D2-E2ue_Kf9D zH_MExmi@rxNLZQ_2einY@gt%JX~h5nIT`qY9Na|^)XScapR*CQVyT-tLE|R!9ta`c zX5((wTwd%7XvP-q5#5G~7pp|oy}*M#3R(}jPw+!smIaA1y*{CFU-KqyD#|v>_K`I~ zDBCtT{y=A%(e7P*2W-162#k1U5{uOKH@cB)m2kW*uBy>Ku+BvN>=OLSMSh3IM8f1w z{;;s}AGMEv!!RUS22ghq0ZVKGEOWxu6uXXZsAJ%UEXzQ56D&w<0>HG&o~AhP;Fq;` zi_hsvj8C~ES?c(e1o{WqI%Cp$n*8zGv{tYTNx)<`1zDC^ZLVG_8H(d-cD!oG0sd4; ztIiuV_t}37?}H&)Mwg-c&?5+Ctr1$3d5I%>X7D0KwO#B$EUfbACZ^C#J84J3qL!@_ z0L#m33RDfFj@T7Js?}EtB-Q;r+etfBR4nL^PR=`!INO|$=1&ryA;9#N;tdaQ(^TOc zz}Lg?Hhw3-C2pGP4P_#MnZ)t_+5^LYbrlPGdy|`{`l?cx9FjkMHXAij58Z{{k3NsS zgMQy92B#P6LP%J=8}e)7MW|&i8j_EgV)kn3NUpIQhnI<}Ki=c)qy&pD!Yy_Qb_bV| z0twj#5HhFjd-aO#B=_WTx_;nzP0e`+{LTrdbc26 zT4GOR9=kH9v_~n&zA0cQj+YKBr@eJ4jvXwRK3<4zqHXKBe%wfdVBTn+Bm{-H5kFZT zfIM7Bla+6qO}GyubiZDwZA(=C&A5s}YDrq+Ca`B2yn$Eaz$K=J9J3urt+KC-XyCzY zqScUOI_pS)j3k8ROHth#2(Jn>=BGv0z6O+xig?-skogChZmJWC3q!Mu#k{!a@6b-l zglcehFdyUtp@8yu7zqzjmgK82>HF4Mj`6~?mhVr(DqZfDCf93(nGw@;g#xI{mDXip zcv-8mtO8I)*H~mSqFtZl<2?LFIM2@5tWiTLdJuiXqd<$d*BAtG;F5;Ep`@8gJD}9f z5IK&UwIK5H0iA0uhSV8Ng2eJD#6{VLSSI%8HCK-)kXt?)=z*oJ6PGM4UjCsB!Dx&23z#PZW&2qKXs!kZXVY}lOEv7jsw^RUXgpe?`&?tuF#RKgx zIk%KSV-{{(OoQ?*PH8_Sd@?K=Avn#ILQ?@yEuK0WvtR_ANpO_kSD!p{=8P|SQRIW< zpRsh)HiKd@Fl|$}Zqb-E)tf3isYVH7G|I~r>kFq`u7h*SM0{($Vtn~oSMpoqiCY}d zxqE7%UNmp^Stw(KYN=D6>P=b9{yw#>b0u^m`sB(_(4P7x{{Ou~%DCHzDizzZ>`Eot z`WYJkT@KxbWmT(F~&2j$ZXO<-jJ5 zuH14J58)FC(RR7YMH-_zp0~Hl)gQu$Df;u5CVq*?SiDh-OF>wWIG%blg*L1o@z zRhF$ptY@|j6E0U%aiWXuc7zo5U7JR2>Ju*4TUvF%8#Q8cWIP#;2V4Q?$vhh zIHjeu-sk%}>RV@a?bZV8{LDwwcJDf~n}@$l;w{W~ z@!0lK2u5fTt)SEB^>pw^ZaAj>AWgmCg~QP0PU4Njzfvv7ttcUJ5NAo6c!G+>!C;H- z-*@x=ZZ`}8iiOsO@fe{~gX(F#a{pgE!;>dZh6|B0#R0bZd-h-m!)|x~N~=(WHxNVZ z!LKIiKMTHjyjZ0>*DFHiMc|u9vH})ZFB>e zp-Cy~;t~A&n=OGBGROS*3go(X^N_@}1_rEK1w4}NLaY2tE~Qd*+`oiDI9XaLYl`Y~K4qt~O?=6?W^Z^o04 zj-#mYZx}7rnvO|zI|yq~)ox-ZIY%eYrI=; z#u(#JIlKY*Ai%Z!O7RBJlWuXMT>dy-x+PpP;dcCQ6BFo^o!@o6#Ku5KyyZ(vbc74- zm2mV_^(2WBD>x#ZTNrx1HYnx!lTSYBd0Qq?d|A3WrF<`l2W=RRM;iZoeDr|_9x%-j z_uMt@On-A0ZbC?q2d;k)#pqRjV4Y`K@`I%(@vIf5-pqd|bmLfXamJo*I(qlpg4A&? zShC`q0`{%-mAN*70l@SX*}BkldG?6DZYFZMwJUsG(+1r4;0RzpTVII);0Sm=AB-_fFx%Y6+^C3U* zgRew8JmS6=oVTBcR_xt%T?jk*@M+6fj`2+winj7KJ+TNp_r`<9Jl-v=6pq z(KNmP>FO1h4_nb{-ap%%EJ(~ZTa63&s+#kQOw)EYXFu(O4fSVLH|h?#ZL{g7J&vL4 z(EuUI4LWj1#JOXgJ(wpGGV!FJJ7&Lf3I-I$zx3VyXZ$M-*M%zHv|M?z(B^=HJe~dT zq94^N6V0OC99*(iX_Z;aK6C@xK&YumO_IkdjzhaV&<5dA5IS7g5{y7iY0}NoWl|#1 zI34R-W(Z=8X8^hDM&th|hbaHdeplD0qo_CqFn^MpPwf@PcAIh2Q@+42pf}%a6#%U4 znJ;3?sy-I&CRXm+tg7xZQ>Ukxnidv8DW{+RThV=A;XwAd17FI}l_2e4VI|XAUjAff zN~`N;(I*R+7NUCfwtiEI6$f@U4Y75}p5d0e@Oleq)CX{~9DCceJGHTi1o~@Y1>GE( zq-BR@)=HwpS{rI4K^#~~Di)9ajEGj~D6Nhcu=C^=r<5jptLBvQUw`t+Ct>_Dr!@2x zVs3d}r+T2|Ah~^$#=wB_2=XDPbn1Zz9vFX=Qa%FL<0I2N&%X53RMTdsC|d2v5xN<@ z8GTJ&H?u@(g^^&D_UE{zrF6cMo+2yBBy6BCjyu5fi1Rbq^O7ZxE>~_%>U|u z@kGtx>Q`t*0nqx6(@#mg1zFv7K#>{xU4Y@0mD7hh9b2a8E>i@N27a|!EP^6SiJ;ky z!<3_%ZvX(-CF@soQ4}{#bxqUO#$O=;!Oy1nU}7J&bI0SAu!TKe9)aQB#)aOKQW+@| zGDE|WVwFDf?ATWlc;*bbOPDx(fWV?;OQFq||6Q;#GczLrm}b%M7EKdCnyK1$wQX0g%Cv8P zCKv|z_i4A-N+4ZordgCcgKRkG!Qn|6yrV~;DaXf8xN2m@D)|PP18?Y z<-}E}LsM6alzJ)=(*R>TEnt{LO6!UR3mpbCeuQ(?30=Fb&g+59>2!h)BOE4x3?zDr zYotkqfuI48tNFTfdf|2IK6DOxzXV8kq0)!RW_RGikcI6%xhu(^kA1jW_&b>TR&7!0 z)?DvdMoovfdUPIl%EEK#DfAKa8C1sc2Wh&`r z#Cn0%fM8BY9?EKQY{(7X#)H(vhCE)^O9EPRb1ZHxr`KS~aw}$Q+`oM-;H=wyzVZbX@3m4+zrj3(9yCm~6O|Oo%fTA8&2M=@V|6LBdHd_YCFHYS`m2B6f;;X?uik!+~C}p%mqk z_O4N!oY12Y0Mmfj$0j}@06$GVUCylA9fMi7!}-n4&5CWti75HvgyD51fKq004#2sUfn~8Z z?waZvcV%Wd#+qund<`MI{lD8IEW!v)A#AoSOF148;SvYTD-wL1CTWxkvn6bA_tSP# z0y`v2$x^2SX0Nw?&;73%4;TB7z%Vc7c|Mi5^Qj!5ozasad7wyk8vsT*hj4}I>l+4a zjsB^B2SV<9+S|rM_|Dw7K0-~jFFQG+G_3{<^3VXBsK8@0)r#wqM}9|3T7{3KQ^f)u zyKmZI-ooH}^`DLa2lLkP2nKbFP-an(1?7Gp=;z`sY}I`a`df+jAs6tL8!mk@Q7xr@ zAJeQB@@^9k;Nv+?>assSMMU2jM>yR+N>c4XIx%-r6f(CQx1yIosYQdGOB~jjD&#;2 ze~Ydw;5kY;oP*L<9S`>Yg<&uQgz)h|XR7e_4#?0Ad0Jwp({B$W3dN&q>g@dk+SOFdW2UdWqP%2I9%gaYH9&!iOS{#>E&ecNK)cZv{ zp5LC-tKHbNi?h`#IXpjyakqQL{OW49Qr9%N&(Ow-H&ATUrR|?@|Diu7#I_Z`7CmHp zM=-qUmZE;tvbz+t&M8H$AXB$&x+l)PQ9Z5PSJYZ@6l7F@LIs(Lk}L_d){h`=kR?%U z+#2!*@IN=rT0V6P$(qBu5`|FHV!yf4^fLNXdoz*9-JqtinSh-MAGfbI6b%!x61ZW-rCp@ z8K^-TkRuZ}kSB+(L6jlJ5cu%AV-i8uQ_8+4rvnu~{zF@{GLea7Gg7u@~JFrRid=7Nnf&*jlYPQ#|1=TA<-2;}`-G z{z%0y>^QJF$|Mi*w;5;sjEU-KHBKjI1P?4|Tgs~OT8Txg+0^hBK%)^|uR|!7nQ(?% zu(br&4}(cVX)rzlpN7@(z?-ufZNiQy&4G0>Dx|T4=ww{_+57dd6DIEI?2#y>S1M5L zm1ai+p-ZIJ*#%8_3-V!1Sx!{3?yPj>Xy$Qqsu|!9sJ#=ypdYbS@#q0px^lD+ZXX`V zp360T4G-Y^sEl@?yU_jUQS@PiK!ij2`F57WG?=Y}l^aEtn~vY_IU=M{8XQ$s4q$^| zN+s4*tKAsb1ZAUu0OL$`vu+k~?_*4p4v`=z;Q*(?dkNX=b3VrY=YsJSL9p-KW?%Y~ zpZr7yZus}huIYKEqFusKfnblqUpL>HIRVP=nK@Ba0-s@Wd?5(-JhylQUNz>>cYS|i&dYptL|jcF-Y1=%FqUD=NAN@X;rG4W&uN-^-F0C`oU!3~ zXRdamzim7Xy6;`svej)H;-l?$+ca`^0oRR2~1} z`%v$!GTiv3Hy&GW{J_UtZ}L5XkU@iMPLUimLkG~6=w|d9^d|H{^l|iA^c6HhzllU# zCyfCSw|n>i9P>W#K=tVV3knwveMZ{++ic4PN;#*rAh%6> zr)eh{m9KfI0=QV3X_iWIFwM=G)G;(O*Nu3oRUkVE0NFtbt)%bjIXU1-Vpe z&XkH6Di2*F(=4$~-B=-XrM5?>6o68FPi=*g6+=e|$p~$a@BqGp-j4nY5Kyq8j8M?Z zvZRwNXUNQ{<-mW9<;4cMl;HVwDP79=OVvwmDVXtii(0M7+XB_TcD=W8#@T+3v^aFs za@=GzS}bFXoGJFe6-#juCS~G9*wMt4BrI0bQQ~@=l%0BuVEonbX~4+K}m)UR}^@u#Ca)VraBdZCrc3mw1zlTbhyR< zm4d+JMcP}WXrO*L*Sfc$;GX<$6N-n~$hC_)*g-{SmT$E>*YSA-Y3a3RO*X18S z58iN|Vfx$Xjb|JUo;lk5(lQEh6Z$By6=YJ2z!q2U`ECZS*8F^{72Hj!;*2kI6iV*~ zJ@$RykH2A2X(j6$bbwmFg*T}q??I2EccPEjAs+LRz#b=)o(uxfi zIyUgVxzs5Pj`{DUn|Uaqlw%Ol43-*1$^*g4M|@b6OcgE^jyM*;LnAW0g{>0g{XY=WY=1c%{{5{LI04&>ropHMBC*x7qbDq>K=s5;vPZm%x zSOqsi)PNgtdmiz8%UFSf;} zmTx{EaSR#B(j-VCY|@E|x}g(UDBevJ-&gosvG3yyDHx0`;U#=x|7GQUrDL6GxV$82 zOgHMLsmzSO!5G_MZ-=*prm2V`WBPTW_Lt&Fx@2JdGr|9Zzhs^~=6vv@>#x#@EQo4( zqW(+cN5U`+eeLbHg$HmRX~;$ix*WYqvgU#wLT^T&LYXWeQJ5ezFR3~~O%^SpR@-;5KU#7v`H;^o^7!rJ3p zIi2^}P}Tk&$z z7L0Gol6Jb3k;=}!K}<70le3>v+BLV{G#oC5vfnp=C^0 ztpGGGTWu9)>+rUkV*}VuEh^_`l}86^;~(ElK=94MQtdz#*5N?ZEbKx!wI}Gq%MUR2 zm#*==OOt>{vvs^Z!f%G}pmJniOZTBKAp}xWvc@{mOe6+SshOA*w>$>82lCSRNR||x zfl*l;VT}uGk8%s9F3{ykasRHZYgzxN3_V`)eoPc(qUqZB()g0DX-Voj3+jex_FusT z+*v@MH2^D}>?8iy<#PYnOBqww<>1$b!y(Z$or!|{fe!>+bsmij73CxE*-h4CZt59M zd^<@HZMEH1ro+yq)-~pjkcK>TMQ)m`(M>#U9EzeSRa4BSNMgLMH{7Ai1nxH;19%+| zFPboFvA2fowT~v#%-7e~Ur6Oa06RW5K3~a&;!v_v_x)nE!g$7z#u2CB--iz!%Ks@>%2nx=a%;EWQkbpZ@fxsO^HE7PBLJeK(h9B@Rjs z50VnO&2oS2`OiQZF5mC`VI)0Vl2XQv2npN&xBY8zEXNu;9p$dm&rslx?4|&dMG+&L z^Agt!%(%|PangtrGI*L+ww(1a2s1Sob0~9L^QJ5O?w&n+xZ{|*C=l4Cj{JGN)s|(d z+O|CetVje)D&Ftb!pY-NwdSP)7D2rqJm2?V%MBIfD&xmaojPS=tZ9a6sHy*XDcb<4 zYTJ%2%d`iQtf-ES;nh{kGR=v@lBBAZo)&dY(~BRhwO{?_Tt(=kzL*kgn_Dy5YN+ZS zEUK7#r5A3g`mzMc!3kp6s&XIz(^oOv?6}5%yUzQ1DO3e%skkyF$%GxR)Va*SDNc`n zR@;IP$N?>?%1&-&t*rc zXBwdC{!OWWEU3oAU%Vn-EpPhm3>gAV|)sldS_Hdt+p@S9b&9^kh_iN&xIIrb{+j$GNP2L(^2F@5A2=cU|lACFVi)J2w3|WH;&fA zSL$doHRZ5EP*r(M&7%L^`VxKwM(7ASZF9w~PpA?((w+;J7ZM86mOL3Habn>$-w}SY zR*6s_?a6bOq>0Dv#K-rkgVoXzKgiL*A=8{#h=TMg(ooTKreT3x54~2L-xr}E|+ReAnU3wD}$3wVN+h~nhAXxJWak6>T!W%Oc>${fD3 zcKrP^??%->hh{A&vAkiCC9&8g@?D!7j?B+MAtle(SLMm#)V*e*NCH@WB~i6SozS8l zb-1;)HATG0;4?+eVHlh&T~z(a1C9J9zpMn_s8m)PBA0dNaC$~9-fX1 zt~ekpSRd2J39g1Z!x19LAWtSTAsirDrgXW9<8P}}s8MXDtg zKmS~p8YVYHQ8{6izop-Fr4f8V^a2b<%>e!8h8dO5T~QQeLt~c3v@;(k-t*5tzi_P~ zij*2Af2?BtdYIFQ10V@iwny-n@G|14impKSj<1NzRit!CtS958H9$LXKWAO9oy2Q4 zCX;-#q}n$7gp3@90DSe%v*w&cj$+FGS%=vBpn<{oK!EL!eB>jzL|&r5>UO)ID^4sG z{2Mh{;hbyo3TC1}CIx()ilSi{20cyuNl`7K$GQJyNiGoXb@-4c>c7vx!45_F{{1xm z#cQv<_FjyC&XiA5U6U0>;e8;Q&T>(DjGG3fqG&8r%I_`7!v%Bve^^!?xIgr-$@gkK z%Y?vYs^8?p)UG|Hh*)m5V~4b>L@A9?d4wHK+4cqrGO9(EFP$nxOf@5*hc6^^&uKr) zGHdYmER+@8Zb0@9a{%)-24M3w4?O(v!-9j|q4*g}`9Q#%F1+ON=d4_op7^*7hzZv* zDetnwZM&R5t|+<2by&wxa>1Z;Enho&H3hzixd~u!Q{PLeM#3niU#OQ&udyq$lC0;k z@y;iKxXFd+L&;g#4r9U?Sy5$Tq|B(nAhNn*AO6eBrY2b8D1SC}0^dj4$p6W|8NCKQ zGHXpS9!*3-cinPRE34}gM=haGAY~OH(M@uEv8%IZr@pl=?`YL%{+ng>IN$gS!bQvC zyjLB!_ZCEih4WtTHlVSzu5aJ?>!^rY=x(Y~ zTe`jea?QnD1CnfosI1KG;X4Adt#1{(G>X-) zW};Po+vFr{;ANRx2VOi4s?v*J6U`S`?mgaBtqtGSrR12bSoE)32TaAc6cR< zcx@ug@Knx$X_{M!mxxBeUJY!Si_2Px=-giCw$`;NV5}p4O;HA_jTCxz{@#1Xuk4?d z+v?yqR;}yfzgu5l?*%fS6Xy{j9`iXRM*P4U^gq~XbT9gBi7dlT?YJC{vov!`-7NdV zz*Z4+0b3#AZdb-}%gTeBpquTU8w9C3TG3T=G_?`lR#u z)Ahl(Of#Xg13_{Y-8=k#+F6d{bN8+vGKk){`O|0WU0+4B_MDkw<;(wM^(pju^b-2f z`N_o#G|WV&Lp_lzfAY>~_)#{n(y%Np9Q_G9>mwh+>Qj_`IBjl(=XU}>J#f&lqCWV~ zX>7lQqoQ|96Wrw&VT7o~bUY?H={34B*8RlR`qx3?{9hg~(`ne%bdBV)AZVGU=_JQ6 zCu=9}O}|XmvYIRi+G{jTBOwt5_8L(%7qo`@4TkxMKt57tS^L{N@N;9EVawAEr zO+ie|_Z*v^O>m+En73!Vpa|Ay!(eVzg^Fc)UUULwLo#>V8!XS&MnbJtx#|vy?z4sD z@NA&WUtOixh^7}>&Enium0C?0Z}Ri~ZugZ9OO%JcHqz8(_}$_7cG~-!49Qg#0oB@X zCq8yXYrV-QUgu3M_tkfXrtTK!DpdJzt=pzG{l@4l;=-9zk zS}$_k*sSH(c`T?Z)a=K(Rh|&@PoIjZbNvVL`-v{!_PqWq|A3R8puHOgoij|)n?n20_2?WziXkTPho5=N>uaf=|SdGj?WJF0hQJ{=N zgi)1rat0KWG|GfatT<#W1`T1V2*P~1%=_KSz$^5`v;#BVA7q-v9eh%wb zopvS9`+&IxW-E(%u^^I^D||_RSTGC_&JojcpBzWM^8Dejc^s`V z_d&sRquFDGOHCKk+3}^%!7vJx!f}^rW7iU1Nq)%{u#}y?Cxc6O$M02@+>Uhk@48Ta ztx_o!8Q0Mw>^h=tlELj1qWbsK@U~KH&lSmCQJ`u4k=zAko7yjlRY&W)&=u%xZUCUo zs?4RB)LA{uPQv&;cn~6*YYUs@1K9w%Yv)ZO*C0H0tg6mCCxBrTqTJdw#8sH6%+-i# zdZ)mJmu4;ueyjrJGmyMD3^nGCzeH)lFra+*95n6Xe61#)cA0j(aFm&+PQ+kpuwBpi zRVYTALX0quHzskLBE1=_cZ9LXgL~=%a!?sLyK#GOR;l7180R6*|8Hc-0?+6f!ZA${ z)n9ya>muK>OcVZb{2zstMK(y|-RMxB4X9tY{#_@EtX-wud#3ez-Ad|-C0W)=dkG>i z1b{>^Bu)LG5QZy-(8ECw%GQ_TIt<5s7>@hcyy5V$PzZetgTi{Rw?3LuLP?`=gYrxI zaf}BrC|oUfw&fA#jgW~}P=0WuEE=bZ9JrX)Nl4(3inWm3kuw?Aw6)SLlY$Dr88R9S z28)s?s^3vXQCb`f1_PN?XQsn2B1Yt_@J+{II6YIvf+$uO7Z*9Vti?sk;(Y(cpnsSu z1b`^?a43p)Bg$5;2uI>ecEw5-HEh5FzPNaQJg&0sw)=O{UUVgTHF^*|jXvdd5itaa z|Ke(r*h|)l@D%Xvi08brOMGa8BnqM|3WC2WmaK|BYgjgBb`ix&&GZq61gcCIz!kRr z_&GJj5|{x)H-S9q6q>=Lw=|o@A{cY44#v)-bNAfiKY_#PK;w+I_D;bB!%yy}vy6SM z!;7kVotb=C(_dJ&ZP+=@-t`SYvDlpOLU7&aVVCQ0-HRECK4icEcFpKHkiE0y<%6xW zs>-6B5PPMb^Y(AlkD%wib~uL8yYlR{??&xzyL2C~6Q*zioY?OEd(fB8;DgD64(%uC zWTqyiej?6mYHG{j>+0Px(Lc`J=#A)IK1(D!-r@kqqKG6Q0i1T7%Kin*N|cr`yEkjx z#Zs^W_azn8kJTXD*a#3{{M4CSZD5BNu=c9-Je6*});5DJRyDGXPS=kh?lN)k4npiU&@dH?e!r^OssdNMu8WSg!B(CDT zl&a%PiumK_9{6c>D&eU z1OwOo`gzC=4m7XfnYp+dlrs!5~MUdJoDG<=rgJ2g(*>7+BMq&XR7rLd;*4)%E9$-A~e6YyDv z4Van&STqjC;Ps>~iSqcb1^eq@aWJawUa1B!BWa>oeN&?6Oq=CTW%7Y|r900*eEd^L z4-{H{=u)#i$FDPZq=z9rD-!|)+EZ>{$=H=vYV;qiJ4%TC?s-?J>J?5gzI5>?Q+Ij( zg(C!!@WYfLmxwlP6wGawtvw4ALXQxIOl_1&%9n`no1*;IB8v{Cl2GO6a+~py-vzqJyBs#-fIci&P3VCCPpoyDIun*O%L0F*TdG_ z##1u9T{+E?TPGYFoNNWdgJ;w?1k7eu(K(N=MfYeINts%97j1dqd4ws6utO6j;GM;+ zM{=&*Pi6W8dMtaJ{OXA_EIA z+kkTb*g+c~a~~%_g&}d2{nD)uV1(WpX%bflgjZhOA_dV z7$e6{mP+JC12(G)n=T_U09~O}(E-@O`;~k$=DM98S*VQr=zBe>F0EG3N|A29!E{ME zS7Fy*?19J=sa-o*_Thw`LWJoZ<-i<4!Rpl0Vc0lfEsKUKP-7*4(DW_nB%Pru6?UkE z2!5ujnJ*Bc?kGs=k}VW~es|@}oNLhlgV3GA!P<`pl=CSYJFoQV zmW??KPz6nTd<-}JxF$&T`lwz@e1$tgMzSdJV96`B63)wD^$em>4Ir&o6NB+^w-hO; z6xh*rjqpN-z=K0>PRsS*^<(L;fPv_zzn$7y#EI1499 z2o$2Q?&R?^uwm=%Z-2X5P`p}YZ>zeFjE6;DLgLOFf@KvQzXK126Sn0&u&OSD6&gCh zJSJud$CddbycfQQ;Y!n1HK!t%gf%1!m@r9#M+F4BHxx?StrfxLG_tXvDw0nxuvrXNo z!&CEuFDJ5wRcZii{QQ8*!U5{;G7UF z9#`Y(!BTu-tfjRg-TZSu7>*G1UrQ`cyuYgkl2wNq)M0o6y6*MbBD+atWkX0qwv?P}SumL5bXr0cQ1xFhE?^V?UZT&wFq zfBwq0)1B*mO1ysMbI(~0NSstd9)s_pBHD`(fFEvx=AAlCk4(}cSL|Nz{@BMp#`W{A zNS^xj@EqsEiQ46B4?XmdKnG@N`Up=|*N2B63AXKG3(bvn2Yc8XEyn-}+i1pO1`&bM z^IAzKiHH&95d<7*aiLIP-_ToM6~fU7{~LwJmb@_D?BLo48--13iiZbOTNbeN5lL+2 zPcU3kB_D$4rBU5WtlFZm&S?v!CX0#Xfymw)gah9Jz=&E31wh#Mv7OXt)PibrHR6>e zOe72YiMMI2E8besAe(IUZ{QrhH8vTI*P&a`UFePR+%b+gkyimjL0^koalJVQ)m*Xy zm=OC2!SlDz4J;CSkl73b^fhZ~62!p2&t!2oZq*TaPZP}+*#~X^joPDYn&f$srs;uQ&b)(`%1TdFJ@H zeN-6L=jTU6=tXK8Ec|g8e(}mHue|at9wSZ^$B{#rSFBWu?u0B<_Mmn~@NIM$okV9) zAKiu$Fck{g_of!6Kd6ABucH-5KjD0+iK3)BlyWHqn{WC?fU#c)U$}#z#3^-DNffo=k=51Jo%i1_ zNz$G@((5^6Y$3XLetw=c&KZP)J>VO%+#{N%*=R+oD&QApL@Dptnx>K7cz=>4$!KC? zqSKkUa{vDQtxBcUYVEIFYRCwEdSHZNtpDl%%!kO08`IGuBuz~4J`*f^gKdM z)>=*U{)4ZLLUUr9ob0VAB9i@=8myl^dv>2DO6E3lxGwi3%hvavW$Z@3JmI-+pBV=G z$Fpb8?$vEe?nyeg0a=o$?K{g1gY{k4n<)D?GKLUBBGQwfcwGaBO-I@mIFks*9w=Zj zx*jHQ3%^S$ofS!s3$MtQNf{>B^b)U!7yO%Xh7{Iy0ynM~$Qi>h#~5eJ$TSvNarAI( zRlH6obRDrmE`%4Uz2@UEPcDo7HJeh>R~<*~6Z${z7B-!NfrVSoOO{80yj%S!x(3}M zP2o^EfhCMcyIDCH#xEr-QSLa0|tPmx(bmJIxrA(zI=S0ZL zVMweG2UL56)N_&HU@$n5ZX;@69@L{=W&CfJ#d-W`A7lU1vBD86Mv(b!=Y&&o!bYo* zfP@r;1KNJkInh_Ol5g*Gx4oQOR*Zcg$I4UI>!JMpX?Vj2cA$(&kkIG#_6o9Ak6IHg zu4ieQ<++HR-8C6|9h+b~6Mnt!>$+dB`xA~$xpdPf5 zr_$8TcJ5`m%_)cPA0ZnzUtU{HdwJUKfLOL|$WGV2=g%PYPoF+LJG+&uAlom~TYL(w$6qqBi9ScgcOu!aupvV(T9g>jWJEi=a4b!> zI_-`=`%)|BY}bL~e@-WWYkus3ioNE`^fNov)oa3!Z?0{ZMd;Ym%XV`M!r9r`+0)}o zAKboyRr>5*E8`UacwiD&alhZcn_M1&2jYh@48eb_`2!fCUFcRE z?5#5kDfa<4knqNwa*(j#n}oe^vXdmqSw+Rkss~xVE?F_xqFtOqA=c#T5Yzv#^e<05s_#3{8lzR&NhN#U4GGe~`=OmidFe0u^A( zEr$`VR7!VUF40_(MBKb$N>oBcl7woND0QnLUhy8dsZ^=p3tL-Tb#0bBK}3p)S*@;( zf5|Bhz?0;rEi35(#MH(5XBvyBg;voiSvdXXr(w08fL55ZX1IE)m3K2{scJ#NfijJg z?Tcm68(Q(lUUQaD=Eu59krS3arlJmD5p84@MFbu zE8Om@SgT)gTWU+N``y_Vr&O}rn%-yX9C3Q@*UlF_uQ0z*@VvqT#3$3(AGfClV2!X& zFx3pFTHseH-3xeupSm29UJlN*n?$!4?S{SL=Pgfa|_BnPPy&64$-hqBG zq9C#@7}U|R3^Gz{2otj;k%PMN!P5{q2rShZxzR=B13nvsICGK$LX2A^4m>(w*z--BKPnH3u z_+**uIxm+ET{p^Q-!K3dS7gg7GJXg)iWm&TKg3zlvgDP{!(s%!b_j>o*4EYzuR7+x zpxzE^<$it{m3s_i+h_WXxEz)G-BjJnG_C&>PTv)KFc{T1~q(&4B|y>Xm}UfGj4mIs#y z>wH|?Hw=J#R#sL{i#~HME7Qi=-DFI^>v`%4nOu+ds`d|9!?|^(l+opLQ;OzoXW~pS z48MFf<`w~H>qKs9(brZYa=ik>iLY|Li|Qyv`)gkD!giTWTOZ$N*X^8A?E83d6P@6U zF@4f{o6NoV!S!{ngqTte59`2qWzME`_`z{(UWd&!T*xI--BJTBdL})0p>y%%H&?*Yz>Tw)RX;__w$_f z)+^A*Z(qzQeSU67s~*cwd>Mt5^043U_s8t?K4;+~Dcu*Apq=Ouv>DMdBp?=av*m0# zVah1CJGCAQP0}!OX-P+*QawaI8Jz+0Q>;I3jqX5~tTS81fhDbj!{zey+yslpq-ly` zZnoxmoC!2oTOR@A92m7$8I=vu}GZD06Mq^HQ(Al9Y?d}2bLhb z?wpWS!NM0doNC9Z4lK9+;8$KI@Hx|i=l>rnA4MNVpFkIoZabVUC(9l0V1i%@{h9?W zgxglt(X+8^khp!7CKsSkD1{njvxkTbh1<$s5`$PyyxhKe4FUj5Q@RjplysOZeR*WY zWk)UovE1t|y9>ovQpus8N?OvE=&{qf79ML$hX)*su{df8!Q;7Bt5k%6L(>|2l4>2h zO9-ujX!8z0HDE!p)H-dxFz#zX&xLUX6?W12g$rJQa(PS3}1^gand4ndStrQdQaD=CN0r@uiT*}hj?d2&a;ej%gQp#nqC9& zJZpImFDsz`OGpXxD~GqYw@0uSeuy-5Wvh(G|AYIg z+qP5VQLIZmXoG1A#wUZf=@^)y>!Ae5CY@l3%#(p)a$mw z?IKan2E?~V@Vd0FbqZN-WJtLTarwR@#-oG8$kEx2q!Gig;!WSy^c{${s_ul75=eGD zSFwSneZ_Q5v8__E=2!rOJurQT9#)5#Zl*HrjsGvLqUvTIV1Kr(*)o|empGT{rsy+A zj4;tUm0uDeUZo{Q2(yZ$iqZxwPAl(MQ+g}|;?#-H{&e3ZxIkGqezLKu)kdFEnx#se z9mzrPq_#a}(F|vNw1{4XTqoIHgj)Pdgf9~L_qf;L}di1Dt@MulG4+f@ZS|J~g#Otg*U}Gj2oBOmQ*(5h_!lfJP z{BLR>HTZ4N=i&Fm&%@B}XjV(l?rN`RJ#(E>bFPzgAgmdFCoW*ys>zBX*DM<^K%yjumtFUI0j>T_r`(lx}8i3tHg8~;H# zz(-6EFt7|R8#OZAGS#SF!DfiBsk76>?vuhW9|5&GJn%iz@jA`KOX}Dywy39k1ss<* zQ8lQlOcp06XQrEQsL1(fJc9gvk|cSMheyE+Yg5YamjuQP&KB#AZGTb=g0f_q=8hu> z%b^DNK8(;Q%-+p=d7i~Syz7P?5hZ(V>`|jAKM_ct4BL1VQrt3eJt3ogWPZQjSyZyUS^4jCLcMXm_4LzE zL+fc6f#aCJ_r;yx?iYX0bR2l)>8GE5+8@S6-$qLaf$ycy4ZQ z;0NTtWZm6<5zoabj94$zs2F=s{GSYx7{-(j2<{ZndUro8+UBMe=EW;{3$GmM-BKV}bSDKoLdSeWDMcFY*Gol4M;R z&Lf{N@&nymE2VO_l+n#WH0?bDn##0Uh8&+|vg0^j+g?VvTiU{|nQ)TW?W6vlZAqmE zJ-)=e)b28WcysqPjHL6qSV0ylp$P4c+Kt8Mm?ickAo<`uh6%#f2#Z(QHT(!oj5a25cyLA?Z(h zpM@y_R@W8P_0CUz2IxR%e^s!_Ke}`Q{v9j9`aKAN@7K9;+cU5?SBaA; zBGu>^jW#2Hq83iMvm9q)n2BKX=P>nfgVaONCzoB~`xY*V>Kw*%sz|7$YARoG3z}%S zzVC5SE4V9M)u}|unt#<)Kc^~Ea%tWU+7C4-a&=16b!|%JwxyT`6K#|3sv#%Bq>uH3F-lZRW{PD+ik~7=kJ06zl1}-HJa|NB$lL+^-Rz=W} zxGo@dhe~^7ieJh43~fD|lE+;~_nD>FPET{1dP>~%{>U&Sf?2P|C;XCzJi%?BO}Vih z9C;#T2T$?L5x1LFm1D10FSx~$Gk+^=_)J+`4uwA*kOAIMozkN}9orC5+F6Jt@r-%L znO}LbSopE%`e-J;qajWZSZN5BOAj4EK?wg#9kf_(BTBM21g0hLz{h+*yhFCkVEhx{ zYpkCN6Ow`xJ{4r#Z?V z|3rpZBT0aFZfrzybca?-QP4<6;YK!8n>gwFENYM=+&$+m=0TTC@RCo6Xw&U>yFFrWUD}R#Gi{G(HbotO47}sv zsJnC{E>i`>pzVYt9c2SIl;^7lk2G8Wu3L1n)rzv!gF;JV;rQZ(cY_1dm}r!A>ix`C zD3NTt#4Qui$_R^S_8tpk<>B6AP)7bNbrvE5!9?agw#ZN5iVn~_f~r8qC=|1sq7DOB#o6upQj z&)LJ^Ju(Y&upQ$a2d=WK9C(M}*Z>22c!x^bT>zfryt_1sI?xx;`WqO-C(#sYdiH5d z?)_YNfk2-C^ZkSE_Q@n&ADR~I@#~~t!MI}Us%`?9x~kjoA?joYarJi>mzJhf!!nrf zGs7}e*{)0f0uSIRR6sG>hhAU*p`s5ALl9uqiGx`jgdHzdi##)Xj*?cxUOY9*DnATk zTUYhjTrQWJ)m7czRk3Z`u2_a@v@vcQs$uO+Ue|sm{LqDuG}d-(Z0uN@RSnCiv|4Lx ztyaab4E6G2J!&?idQsJFeeU4FIo;OP%k!f9yRr;;K#2Y#UG+ycemy!hq9@r=52$sE z^I25PXe%VE8Cyk%yGADVlvTGKk*25R*Kl3$gVzG6xTcB zx$^?y>cLXhxAE)Q}Dif@4a`f+nu|OG1I)Q z7>31rO_Q;&KK9sSamSepN#1tBF1#wW;CZ0F4;}J``?a)%ZH_2#V8VIuN(cl`$y6%% zpp@K;vu)H9iu8}*1Spci|XJd+*vFn`M}Joez38`zN*ZXBZ$T0pNvy;|CF z2<5Qs$5VVcYUm9QDtf8L;)*YblIrz0&^u1-oQtqaX;<)G(ydoGtYG{nb_YJqN(a9=+eTGfG==NY28|FFyLHK73$o9xtGs zx|f6#95Ux>c!yM@RJSiA$b+%AM4W+=8)NLpfh`P)>QRU&WvwB$vTr6K zMk&!?y5H{)^H&F~RIM;m>$a+9sf5Enj$V%-uNPMx<_76tF!0*}bzuYJg_;zTL;) zJ5Z2!FksN;IOJcsG5%ke0X{|4#oc_lKkkRxVf3zyud9?xEbGCWB_6p>5t0tH)$t8d zF$Vc?hQ^$&EsmWYlax?~xcsWU4F2@++q`|BByrgdU7fLqnj;Nq5bBZ6RY~I%l44O% zlhUxz9|AiQLnmq38Ud6+M6Q!g4*$#kY+_W4Y;d6);9Y})!F6w&=fkVCi+e%oMIVs2 ztYfAmuO`Ly!NE$mhuVf{3`6-IRvj2la@Nk$B>Udx`Qy$=oBE$NbZ+ne_@^=b;8lg$ zgSn`O+NU%dO1Lh)*XiAy=KVxuY+u3%hDb*>v@XA>Z?CJm{44AFRqp=Pa+f6FuW?^~ z)bJm>+&X{AqOZXkEXq{#!mW3+1v<>A!tlq0hmAb4Y&j-<&YkyTd*m$MGRgP%Z~yDP zkl&9AxrJC0imERDW4gEM7>)Em%0AQ45RcZqjzrDe>!e^@Fhs$q-*Rc;F9!Ei)ss|` z03?Z?yyB32cSg#7)hj%$X-7q#S3a!pym(aZ%#$x~-&;NeiL!hUImjl}GUv>O!O4?f zKMJb){V#v?D131Tqd+}{0m|3h(ox7WHF6ilu1jh@&q(5~k1FJrQr8+@GGJJ%&tR-) znEJV+?R9Sm&=j?|kxi+b%I3h7Q!3SmnJ-7TTO8?*DiCzyi$7B%qOZZyl?I1ibRPrG zn+F?`s*&RbNl~O!5{TZr#E3}l`h{3;3T^1G?Pf)Jdxg?XRntJzlr2Rfl(YwAxW`g@5v)=Y>>zg2;d6pNwLH%% zUspCwEBgiI%e<_xt5tg8x(in*e@Yq+AFI)Lb3J&%G|ShOEzh&8|4p?MOp*CAPcK|| z;g4b9ykuMX-g`4p#mgez=8a=?Z@TdWgoma{&coOoS&3k7I`3Jp6FW*`_hS1Hl`Mf@ z{|1xSD7{^tsHK#qGyf2F!QC{>p&|)}} zQ6HDlAAb#IEE4z!TYm~nTYqZz^`~^(gcrMl$w}%XcQ{m1ABi=hb*N zcE;)g$8;hS&E>)#ZtTW>)NwnV=9^qLG)ghy4>Mx)si%IJALmrZx^2R*9UhsRd*td~ zuQv#CWs$DSBUPeK-ZwuB1NbyD@karDQO2A4^Km4X%K_waIS4!eFPp&on8v2E(G=6z z7AqF?t!LFcp{Px#bOeizFKjPWt!E2Koi5|q-bidLWY@g&iQh6tFgUKXPfr-;@I53` zJQfSld8#I&#UzrRm~vy1d}4E#peQ#*^{CS^PSaNw6=iIE@LaDn(jd~d zw}=7-Ci6r@R4!AF*DTw3@(`TMwf>}GoA9E8A3gW0n-dPghgp+5Z-T@m8wSS8J+ngP zb|p-3;|YAnR}DRjg$Hbjno6ufo4Rd|G1#h#d>u|)w&f_=bT%q8#o1!+L}Y9RM#k9h z5j>O|>sb$yTvb#)HBJD*2$j$bu%LHGnQfQPla$hNSyz7IiSn>C{`D&qj^)Q6F9>JH z2v9oi;L|09Y5+o_>J-iIHA z<>4c``>m!nli#^+#6odN__% zxh^#$tMT%o1bLS15Fe(LJt_y&3(1{Xm=0vO{?&u~DR{JY#&xunjdx%l%!AA(f2}1R z^C|ZAw3mWh)Iz8R04+1_BN`J4D1PnQZ92Bxn*AFn*}sLL%unrUEmkKU6R6qs*F|dx zYWA<7w)V7VE7iqMj~ZtGcIzc*P+jVY$1p&%&p(@X=X(~ub2R!!XeYgr{RqcOJ$it> zbHqP{Q!ClMlm(;D3~ID2PXERk1hxBBeei`3eQ)-o_d)yqKF)0#z{e;y`2J{ZIeNF* zeYLcQa@_FVUGjf!lAm;~HeJr_52ihuj9&@~#g5Nxzz9BxTDWiwGoy8pCY|etDY$6!4s@U`I?W|QPub!!13i@v^*ua!3xG_K z&<@dNyG!5T5$sKVq+EzRq##alo-Xi(WUd;@n)Do12{vQ1ecvqOLojD&}{$z}0%vy~}LH zR*J@|GkfrUP0|J~X47i#!mwLx9M1buWucH4 zj(Bq`#^T~`*x&6=2jF5+;PgTvI0ZeZR+0ij-d|XtUU_k8?S?LI?U}`u6zSD2PLN&}Ef}nwjbPnEr=GsLS>;T>y_RWa^}W|MuGc2xGG~!)2`Cdb&X= zl*;YpJ$u^A}`|H@%YR!bcuLy$T`{7KhwQKI5q6&hV!d%st z4lJvvP#JS-rP7FOo6=l;W7|T?N_ulw4O5$8%do$Z96SD9p@UO%z4vFHUo^(j$`%mOFD@hcWtmEGCg*TNP zN8$NmxMF*LuF`*|v9@crfz3#hj<-&(c`QE_%;)%ZRaT4_nF(91U5C3zVo`YJvFTts zUmy*JSv>L1nhB3{_33iCdZ4euP!C>`abtFuEMK-bQ-U!r?}&F_{l)DG7RGLZX+9tD ztUiz4oMFe^#JvsIt4I7->VSOpPkmBLvEx7av#M90E`Sl(+0aObQ-;1>kHQzPkWKGk zo0I1wN+h(zh^E6ZmSj5eSS%1lVVpBdb6yMnJj|Kp_zeoac>cUry~O3RZ;{9+|^2q$$&`32P;6IWvfME)DJK%sb?yff@(7NpWkk#pa9*fO&&0Mt}Y6(xR|G!CFBH1}h2a zft^&u1;-K@zX^;@77}UXu!1@NlOCP9rv^VUkAd15w`UbRmF6pOR{U>*90zEtI( z8=x@4-H*MdD=^MO{3X0QCg^4@dUCpLUp9NRmiVq4e{M-6SSF>2yO(_eC5mbiAP%-z zHQ)n|s_?VKw)5FU5Nrr|WZ&teXgk6Rh>ITfQ*s`R!y$1F!^)uR_WN>7FIfUW@4z(j zpcCw6hgWw+lc=$P^NvsjA>ZUe@%e^>Lms4l-52DLBSwa7+W`f$jnckF%jbb|5O%7@ z6TAU8dHNWkge1g_sVy??N7tB0eDDpCA)|e;Uvl-;S6>a5RlK8M7wn>knhua{&DcfR zf}tf#QeU>R{>09c^XJb)u4q|c7i=u)V44M9#TdV&dx8C<+RLtSp43oxckCzk1&_x1 z+|%mLS5A_B0!rty=ltzkh59%6!|ak`1S#5uP|Y9Q&TjQyK^t%e!~*crcKe@RKGJiw zcDskfc&iy4pSim$)^NtvP|HH}Xy==u`h>uybQk8AVA+G&g1guYgkjDaYiK9ja2bRL z6}xDUr(MZDEx1ooq}|8M2_e+-ux3KT0D6wVuyPi>V+mJ!&Hrb4dHFN9R~8m3w-0po ze}L;!{WH4O4rtxZS+p#;fVIwe^>8Sk&-Z))KP4oaKwz&jk&cu}{;r@ngk_i2?^LQ-zNb8N6{3>@`S50%Y$FCG1Bx&$BVK) zWjG@5H@Sp0^WS`!{Ahhx)+Hhmq6$=#N;(I?=_N^{f=Y-;Bwco7MUfp@mxv&J{pBPf zKl^0rac%R?8&m#tcEbI+M)u`GNp-kJU9(f)EYn%P!=~cuD^YaQ1d7R!mkJSmWNSoW z1{Kc_x&Wjbu#5v8tv469I@Nek{e1PP9(nFXeo;T35Q&tC8~{ihuT-a)vb5t8w`=z` zcDH+E$CARPstV6h08S)Si~x7LFNeG4mt}oHm#M%35Jd)1MA3(>SFNtnwQvT&7exg? zRtNwmP=zh5ABtllx2JbhawK&?MT!b`yZEiv7ojWE-iMf9PeYB z2L6d}di|yCG2GWL@3sp=nUv3lep|parm8~Z`6`CYfS+aq22s~lQr0{WsBC0oL#6_F zYigNM6z`aYC%n&lrc+L5n#Oc4oqiAhDIO6o=;40oS!_$ErR}tJ{E&eh!OKd(xdc}4 zfEh~*3`1PD;+H$*I~v8`xB_WR07?6l{%jm0?@Awp2?yV6ag@LR@@0Bt+4-F3SF`b! zbZcuH;(N*pO3!c6|W$S zne{MdnLK9jK$5U`U^%V?mL&nl!!U0HW*X=U^hzF{>V``S_NDRGU?rhM5~jrj;R7q7 zpjlpe)=oC9rRp9<*_6%RY5e8?@-N0sCH+rf;QRSJ1*afL#N&x_Jfi+}_!wG_pb=ye zhE?G?F!Vnp+ycX8p*t9VCnidK(=%%go%oBNcuRdFk*R6f=Gxlo!n|WMp65hv(G~x8 zE|}H?#yGuJTV?{MI@UK5PULu=+0OjJ>e`xVTPBsi_Mg_KgE@^8*mA9=bBqZv>Lp{0 z;p-?uxm6I6i+!Yx zpVmc@%gLp;-gx8Aoq&rcbf$?7>c;umxlY3_)}NqJ)A>kxCDe+-TNPT&8NyKyRt=Uu_Uakn@GEOIeF?DzA?W9S2)b)8)$7a;(K_r3O)GaLhozPXGEE&}DfvBJB%9hVt|V zjs!8Hbh-wtDe<~-ymq{jbYt-}clvd&OI9C<7g<_5x_KR=R3hbqU~})@sJ<2rHKJA| zy1ph@Oly}m&z1Mx zci(*t*Xwz1Bj*(KpVW=_ynYQL$||wi?jG4C@|wD>wtyq~E{b%*!Pock&t;8q#%?B4 z&f25#99>$X9Ix%MI4ZN<2FEnH*_1WL>+AhhEH17CU!0%*y;Yt6_U!}5NQv`O;aDBj z&`xv={VpF_3@dHx#BDN9K~j21h>BCZK}V)UR~^5pB@(s74S{QTJ|3i8Q3goID;F=~ znMkYAq_+R@OTl2_uVE(ufGW1CQkwo1wMDhoX-F_8L`m1P_rn0;poeqZy;7GX^*}vl zIfiH&uElV(xv_iSl2W^Uf)i4@NH4CBZ*|&npnTnNdP`!4uZfw9Tvi#az)n)UK_}i` zFFQmCPt<-US%c0Fg99Z|Tm*3~Yw`Z;NvZ!Jd5T1n=aemoSOxOopgY@F7dx!H$mMRF z;tdU?<958Z=ekDQ%SkI%7#oGA@Tmr-w_4?U4M21(DlvyKR44GenAq@)(+BU;BdT{j=%$WqUW=3@Pdv5A8^_ z;zJ*TiU_7C)Q=QjC`c5#`S6WJlitUjZ zLK7L$CGixxzE1*>^ogsO9!OI836>U9D`dJH7RwQ*BD14V5^ERUnSD&jXgbA(5Fnq& z*1w7od@WW`dd90_@fGOR)~DA|%^@L&^IALhT(`DTP||3Op8Vn&d%h=?3>{jyF;V7e zF{MEGiQd#%N&I>=&`}X1x%@Nrs2;Tyruk2dq?@#%$9;+8zQmQzoH-*&XE?5Z`t)g| zv9r10Kf1NGMJ>ZL6~#0Si~jWV>C^r~b7#YN`sai~C6GlD=0YnGhPTP{iUYmI}rH97LBXSZEuN26d4#JfJV9E72noTT!-T~V# zO*x;>m$FM(ST{ew&E|&hN*Kf|1kl%raHU8jPQ=aTMyc>QXUcKUBcG#0C~R+yzQmtz zF9*${6dgxzMrSmd0`omZyVTWP5G0R6FC&N^+(l`)W4Q2^%bnM?!$ej{gE7GH*71P)gf2&*%mn7H2N;wWmT7&56JM#|jx3WiFkL_0;YoUXFwsZiB`3iIqH3g|Q zG3t80c*xOuBxI}#c`;5=>IGrc>xFZLD?KyhwguXx^Hkz`G;9ih$o1z`GZZ81-SO_NT0ddF(OtWT4DK99{Ob*3xXFT-WM!+H(dZf#vrgD=F7jFA(bH`e1T zxB0$Tn#yA(7d3uY#R^_nX-9K&{oLFBikhnM@edDRgc>b3K$-}vokrHGRWfpEocyL} zM7S}#3;I!~+JCCFAVRS?TlT$~ndU~b=>s?2Pe_W^nOb+L8dB3zA19viT<;Ri<9TCd zrbQ1;vg1y$h*F6I?19FN3-~fCm8Sx9i70z;)mWIs-3|l;Px6)Mn|}Z8&^5QvCN2qj zsU1F9wP9S_9|5Vd%&SNZkm*w+Y5~t=QS!D2j>oOnD!-U=Br5L^Lbi1A^(6XGf9kDL(q`XiWz| zpr9yTspS2Ef5#nnc%_o3C?8CJ4K{Z*lA-PTHnTZuNFVfOSWwh7*ZqU{-f_nruB&Mu zO#kLl=_>PLpF3UDE1KYYP^w3|xDszBL&UOG&Df(@i_LCcHv);wmd`FK3Q>(_b&zeN_))A4J@jn^`U)lm(Pb9 zMdlAG>dhk%4B>b&4J!B*_JVk{_24e*L10Vh=f38h*9G`X-m90geMr2=jm(EHR#8=E z4?&Gxn~ol$q{?nD#gaVPB*e1-@{~(ky>c8pX3-}5JvS;It{y#k(5ffeEQ9n+_}qwj zxRyOlAprsYUgH$ni;kl=#o7*|Hy#>&QTf~0k8j|9ZS_6kjDAQnpu3H^xLWQKo%3#T zWYG8@(2zX5M^hBtHWk$_l{^ECu%ev?#c=oJ5_uTIu_N>IX9Jphz#jIpzfe@eRCL?O z1NgR|v+6>lK4Y4$TqP^umbg1Zc#zEhQ;gsO+UGHiqAr9ISC7Of%tF_&Ebc5+WC!CJkzZRl z%n|B_e+J34CJ68qf#b`SRpvN0a99-VH@XST@w}bS*$0vxOpvaSd1w_hCSjgSB^!#I z?Va%gsJ@>9ge4{y(e>$;EKBy+s9V&Sgo#K1Fj%5=B>^xHB5|shOQ(yH{9)9^`d}2} z6S}p)qX#@U3NJU$S~gh&U64I+l~~3gsSOQs1|Lsg32U7(%scedS{8Fd%XjY1@mm?W zV^?o@#k8z|OWN{R!-NZR=t^4+{kdTxh_y@Y`NWb>OX=ueB7oHfINCr+J@)2f(EHb; zj(WWb6h4Q>&6@J4ijW^>iav-DNmzPk3<(MNQrTxg>!axP{r2p>X9ic@bkj|_n{s-@ z{AL&n!CowUW1(M+=oRMS^&hp*yfYeq*6IwypNq4IixPL0fTk0b4D!Ns-ue1wo z)Siovq2F$|uN-9heR=e*V(KnxX$dZ#;N;=_H>QDIu&=Z^ex35@N?VC4$kb3gFijXs z&7NN)`&Qc*it!j60i}ug(u}!r=={vlcI<`(1Gj|g)Pe`T)pk+sk!qHD>jNRwgg;4m zZVJzRbRDq7FJV7QLfvfe z*=KNs(t%;y004eKfxotG47TxS4&VT!Ih$uX;rcN(1O0p_3_|id=p`Fa5sl%-{cwV< z!E%Fg^j*>88|9rk3IR${5zsaiPY=QOd>BdcAKwvIS3nkU+P2;m)LFvsbTmm!+YQxF-08)z8l9bi z!Jw>3oNw;E<-H|4HW-vX^Ebff--9NRFNU6VwLi{(4)gwR)3E&_+W$^m1NZq}@S%+n z4E&oTGDv_ip}hWT2z{NPkn(UY82imx&)N2KK77rz&PvmBrt6x|vGr@pu}`S#CtUM7 z-M@J8VwGIK_;F49c>W5FJ_~;%H?Y{I9&z{$aa&C}uq+fcy$~0AQ7iWkpeiA66B}qh zQ}i0YcZUi|MjhAi<9QYt5Yv-BVP_?ZxOZc1on+O@bwsd7)-?GpN)1`lWd4o(lxObI z=VeWk`;@kRT^C+&t^<65(z|3$lMPDwH}Zdazjw(dl=fv!lUu)Pu-;skS@st!ZhsLz z3EwGoBfqv~e7D}{8Xn*GPZ%fgT57xYHZllx`&UxiwE-DK@@~BX-t8NjKG7Wqo}N;C z9pV&5y23c)k1{Y|X$|RFX6Z$v0+yD3Es*D={*u?cEPv5kx(lWAIYS3&mi2uyAm{&B z|2$cLOgD0W=KE`$w*k753;sjP9wi{q_~WDvAnT9i4E@g-A#A&{-W|*IHC~UnfCbJi zM6e^lbabYJ>P==kV+7=ZOGc#irw|djCoSlv-p!kJ8!2VB20qf_n1V$^>zc5j7@&=|U7w|Fqcppy-d^>6P*qpRJEB<`jN4T@FWj$VRh0Up2pE;Zy)-hf2jB*b*CU_3 zsc~21f^)qSvAg+G){E{+hEQWBi!Ng7<)DzV^}cxi=5yO zJv_#XKoiifRj(dq=gPqfg?Zd;ZZv0RJik0!EP}XD zn#wAgI2#_d#k62kt4SST^44c&44y|2iCu4|H!#dHX;@wA)@I<-#-fq|r$>CkfTV@$g<5}h0pH& zp=;BJhiFCylBiN7({ACMW?|?fLi#N=_mfrB_#M5qFoZ@3!!=i9R-~3e?@kd`z}`AA z&874;lv;|Sh1P_kSOUh9_1gHe6Kk=#dxzc4MXN0urr!`C$Vxx!9M08M^oDO5;u^qS zk?A(n^_;fO#Px@(8TQv_y#-%KuZvF`va={pMl6Ut(j?50xd1I-2H}RQYX>e6v7R+j zpn$_Ap(8Ii#|xrX=yJa03YsYJysBsgM^z!5NrdU?h1PTszwUkUa(wxrI2PB!8BkTH z5CB5g4}?qL2~AOXdN*BJ`EKe))cpirBBtTqy*@vu%@?O2ABBhF|E&*Ic+a7^cu<|6 zU%%TmOd|1usD1wvFlZ)p)s17Mp*mX4G$$p`myphsltMIcc5!1fuEb{C2{rn$03rtZ zKGrDs?A8d#(33+1XxH1K>68@lK^V-rOrQ7caVqa(wgY*lHOK9PXhs44*Pfa}Cxjk1P z1ctD?K$K1)mk82G`ouG}ZfG^3lU{aEz9$W`H0~`J;OCG!3O!k7BDt+#e33-__|Sz- zqXXz>^zIgLXyP=45#>j}NiGhMYzs1jOp#Cuz+)YE1Xw@85oywl+qLZicOHB^vTaIm zZ1PY&3dhdM2{#?pUfmozZ;PJq>`1I92^w>7u;kC*?`O~Jkkh%^PEA^xz4m7|ktc^A=SbCdVcgUv7k3wheq%Dgo6wjm4wxKN2Zr}p z=J((g_2n$2q!B=sr1O^!t+hNgyQ`2vk}XEkmDf$k&OklREEdw7!HgIVD{41<4S5e+p7z z#{?9>=bqUt>Y{z9b!Vxan`_Ftn&r2s&IDf$~pX3(~+~<_@ zXxI3*7VZj<2IHdmy?Es(N_Rs|#n~8wvKILt+tn3Rmgaes=MH zOL1)wDhXYa??COy4oSM^lCLg;sf;2Bw%d;EkX7;j=KcKydoY5O2VK|iZD$=wj>5m~ z<4(Mv$zR=W`pp_c(Rr@zGW=%R-6Lf!Pr&suQJ0R^qY4bD1Or&yXf}A0U)Xklzpi*L zVDqI)8KlQRD9*}gKQoql2{ieNViX}{9NoFjxnzfdOec$S0YS{ z2#@O}?1#(rBI)bho6%%qmHWS_ELfkV=_T}f#5bp?-9k<=mj1Eq#GT4}W)W1Y?bHX- zQr>q+d7@z3S!eqBcC|`ieU@(IBp@q(I6-iDm4stfTIX1J7@)G39#d4Anx)e0Y^h{YMNu5rG1A>P zu2HH8usA*{-I2v#GPJN@HyH|5RL7x$=W$epDtA;#g+blpl*d1UHadu|7EUJ&6;>-P zTWS1jfNKR^mbVlPu*09a2si6y;Rz?LFDSz(h6C%s( zlts|g4o)u8yt3Ss2@bSUmkSMC^#}=)GD1qoNtcH zxps4dEIQgpa-Qtl>QP0&Z1RLjJh2mknwomdkbXMX?H&U(wQU%TU8Qc5R6H3E zU?3q@B*nTOS-RKRqEqju)INz3LIT7Y-^mlfl`rRyqNmX}&@a(nq5tT6wd-Fi|5_hf z;@!^MKlw`77xjR0RP|Z0!LhrS&1D&*N8Y}*4DEiqpOFF&%(fH44oi-0xkLA@CGCYU z$7YJ&-nVTh1lOt5rakv6x*I)!hP>tp<^pUKmYqpF&WYNPs}mASYE1J?wC|&gfJC$! z?p7(aJKXW0{gQTtgNY;T#0quo_AkkcVIzVUo$p3B>9`#+G-myc3K*pa)|0SapP{D4 z0G#TP1M4ZTR*G`bEsTj2shVr&<`kte?K`fj%sQ5)Id(n;RLC)DYAT(sxUPqAe|?6@ z3YNu7RI;+?U8)tTQ@X*WBi`Hx=EnZYewi`0kL^`4q!gzhiu+X#4sq&1B0>tBx?7|K zALfP2jU$g@DjdclzUr|riJZlzNsvl^@H79L&D(;4qwi`SZVyJk&w2pkGPwN@3`CSDk*nH5SpOf`#PtX&1u7 znyT=Fm|)Yy%qFGRT+@X!ef*(;?8kGk&Jy@4CyH8@MkBic#+s_|NJ-_ZuRciA-;On9 zt%1IYwsD2xPa}tdBU9hkFyVjG)h7W}BGwFHou(i`udee`!#tkWXv)iddM(yQm{(Y$y=3ue2o!Fu`m{F zr&jYbGWhDhLP*>Gd-xnYifnu;P^A7~+VDq&8Fn`Ec`?6*b9rS5H`oRvLnWWXTX~W9 zq1P@w>lFw=5@$%DO*!JmJOZ+$Q>i=d`LYC|xx%5EV-vW9e}#P6a3W6CKSu`V~*97NSPpBzr16!!A%A!(5fdk&vRkL-C_hNJCsij7ka`3 z%PJC(a!4FsnXokX9q_a4XExIl#>$bCdV=<%8?-ENq|xx0OgfrZkw`OHCz0=7|0$0| zWDK=8kJz;w`JFyTP|b0ido_*gH;P_hNm4M|=`6hayM8|Jl%?D6SzB8pZoPwD%crNm<>es+GL5^-GR_75pMXIJK~DXgxpzG;u$jbpo8B}$cd;UYDl zF?79q!Q`?#jXvxx5u0V3L{56q19Y9ZcO@i$Q= zvSOJPs%1M4@RlyG*^ZUxx{Yz_-10Jb>)hZvipaP%Pe$#ULzw8g5m=m)VLNZ@NjRln zbB(_AsWRkOy-GHMKbm1=QA!L;bDRUM41(88Tk<={>Kv+-F(8YZvm4Na_FBe9P}{z(X&*@Pb{)JDc|Yz7F@X?KLBpKb%J>1Gsmjr2Oq5^2uA--wAh%h2G z8-%CdM4|{%9IO4HDSgBjiBe_OalVdUgg4I5&s$EnHUmp=u)YAxmK*UAOb12wBdmwl zt^3aGrfRh+!c478YaDmjhj@m-E=*m@Atr#4<~(1=X=7s}js<#k^#%;Eb613t+%mo%A`tz7+69S?}pG z{<)zRXYw z>$0y&as+?`Xg=_zAqa9Nl7#Is_~8faL(|jKnjnxjG9ro{clH?1%`Gp-am^A4#}^7a z1re%OtE%eimi8B;RzF~Srl+Tw#T->tudae9>?{;`jtEvQj+d9`IR4nI+Yv>=ZYF}D zJv+o@Jx@RWF)E-1UT_7GRQ&Wj;K*R3FY)o?jG5*s#!hipyXWp#`uK6vWbBk_o6Rmk0Ho#R<}3e{%7XfL zNaMK6zT;5z7Tt~n(zU!%$^~F8aUE0#Zhtfn(tA1>RN2#PG@Cd`xs)6n+;CmC@b8|m z+1yw*K3gn0#LiQ%XIJ%n^T0zL&h$cuq)6S+L*tm?a!XG&SQkvHz6Y1;EsM>@QUf<; zcP&(_mN#_AW!nyiim;GGJa-bAeG|_9l;_p7Ou0Lqt7;kgD&tq;zNvPQkB*OPCGuoM zT0Lo8)2Px$f}bO)X2W)FuLI*kzS(TIo6US-Dy6zL8v!+0StSa7%>~DLJL8pwg+ifF zSXfw@O1#fy(prs@(Jz&M)naURtn?Uo@!i+-7e;N7)s>@ z4`2Q%FziN8dDt(j^F55cSFWyw1@c+u=k|ISdkf_fVDGN&WGO#$!1+WrQMax>2qqEU zZV`^AWO(|e{)(z<>QGUJs`f0t;+qKDVnie-h^9#=M3FBJ!KZZ7E1aI*h#FGkbAX1Z zHANa}V+GSmEFMm#q<2*;#uPXOPlH(*<1)iAA7^eumZqQsI3vy`x^NDWNkdxRz}=(A zrc6+(RYhRXBhTE?{%B+hFTs7V2{V2vZEeAMyx);07%yGZODK0jLy;60i1G}p>PJ&7 z?YDIhO2%#Q*$y6AQ62q`h2Zdj3+Z?$a%Bo+F-Vmjx?-Q8Se%8nOcElA^Xw0z!^k)+ zpfvGvymGYJhF&u5?~e?CkbOU0ezZfR)q?lj-0$W(0#SveYkG#(1oJD!X)6AV8YEe+ zPSW%7J4(4nDl(M>hG=Ln`y?S;-59V&(&bX@hc4m&EnmM(okFOF?Jt8ssP0g`h@k82 zGB}Oa8trsyw<_u!Q98NUJwSW3_Mp&PTwDx&A2>q=Y+#;K{G98GJRiO(%ep52uB!eX zRr$=l%Io5&JR+-v$N9}q!1u#IBAN-n8%DXjv}?A3cj>ZB-=Y|X@>X9agag@F^44xu z`B^Sa@+VM0EwsM}Vi^MtnmHQRUoTn_uAbOX*{l7|cfM1XWqwuAUPtyrDYf1TdwqFz zb(NQ8{hgZd9UXWlnl$dUXZ52PcRU*#ona!jzrc#4+9kzB_v%KnbV?S9eo-f)d`gmo z%gkE+OE-}Eimm}@y3&{SCFPwq^LyN`kUoBxutW@ibFt)eYc-$7b`qA5F2X)&Cdo62>&he=Oo7Q)bZ+q4eS(GH#a6T-?+&02G3ub z)u@5PIqG^dQ}!ysOjZaS$tZJqHC$JAj`Wc{wWtPFhEOCnXW_v)R%s!N^ z7pqLx>cm=el;VzY_g7csmuZSBaDu44%yGLjHL2DM4OXI(Z1Hg$`Hn9jk1Wlraz%&r z%qtS8&2+oBakJoCHjg=DP+tfgYnaMCum1+V0i&FQh&~{5!UAw-eJ@41s(SlFVm~T~ zzU$>_*oV8CD%I$!VVq8M+$|Z6+GlKL*l^cnNnw<(!(4Db@4m>-zctM(9xNJ^^`rAl#!< z7p6Dw?y^0!0(p(yWR98DQ9rTR)))?x@NPS$YhmSEoEIn}{yCE+5#0!gy>D1KJRJyo0UIkwTL^Cy~T%UvOxFyLJ2X#Zf2tW{Z z@MI_Btv_ILb~+d!;j_9fYrxAbe#LU0UHxQ&2fP>~MC2=Q>*VHS)~gswujp}Xjpq|E~@{VhWWGA2{2jf5mMx-XcyXrZ7H zT(&*$EZLPkp?0u)wM^p5pQ}ePc}8YTK0yJfqH6N>e?79MDina8I7=xTxRlsK^D8)@ zSTp8^jxsPE)ih2|(_}Nec5|RO?!?4|>-vf^R5e{;0IUJCx7cL%QiCOOOI;nlpR?p- zWZ|bWxd1}2Mqw&2RyjB6{>g?T3)Uwl%FsCdV15MobvB|UWBqnJi*?vE)h@w3iF?>M zrmd(=I;IiB+fnGhtu!jbdEF~GWgdQqH6#7^`CQj^C*b|Rzc+j7eK5O+GR*#oGj_;y z5Ibl1V0ynKEA3AU6B)4oxLHa3wF$HFc?svU@%qIu6G~!EOGyJjNbwYSi zFX)i8NgiHo@G=i8a%x3ht?76pzNwkdgO{W}&H1rR;Yr2R$23~-57uKfB}OiED(`ak zyPs2)$mdm3=3DrqAfInG%6rrluCc}~8!&>W(GENL36>qwM5IF8YGap@{DfkSqH{_3 zRl@#=&Y`p)NXCtOnP4u4ZLX?{SoS!1wB{{PRg2;(rqWyRrb@0g2@uhaibd0Ovwtv< z=Z6n`NHk4Xn}|T?ZkhAI)^$PUbxo37u7g=9cUy6OwoGbW)m2sTLlTi>j7R@D9|t;C z&?J#!4APRfVu%4|S{xz^_PQ#RVnAJKniV3%^5O1BJ99aYbrq|>-PeuC(FZ-0wckEDF-josuBRcet3!^0n8>R9^PmWV){Wb)Mf{H{({* z4`0~kisjGhx}~RkBAY>$p`str-%I+}*+lL>(Pp#uSv<5iKib?i->sCh3G&Uley1!+ z8aJ<)PjD_jp)W8gazfa`Q+u>xM zCoc&hQtUEDgV?JieBylw@mY0%%8AQBo94i*G_ijP35X;_VUzu|)$7!wW2O6UoS1C& z7SdGrvQsgE>er_o0CjSup)T_nB!_jAzx$K`?)%9?d=$2QP=E%>p~#eRv-b~phyi#RrNm9QBGcQ-TZ#0-9W(+ zm(jNVD)U`pPfRSZbNzz(LEF`sQ#4Hot8t@L(hn+%Vks(^R&cM+IVd-2L=t;Vvt(b6 zb2R2Wg719zZgWPaBf`DX>2Z1>TfQ;tcHlnTi#!1r7yxM07VoaaRvUaX+a)|$(AqZMsIJJJfrzzIKV^iA z%ZGG5f5Fp#CBQ+`z43RCU`5cXzg z>xxpJo$Y0tK}UuSMKMLuP?azo40SIF!&HMB5^JhuuA7#sad~_mL#R5=H0RTfQ-yo; z`MjYh;%QM)%zH<8mFZ4?u%v|WQu@UOHH~~mqgI=Q*?9t?;oEgksocnuPd@piR0LF% zo)iQ@D8KcsZ0}d4H$>it%xa1dkKjyQjAZI)suP?R9q};zwVMU1X}d(o12@yNb=@=?3O2@zp3l5 z8Vm*={r@=_!_oiTK*Os=@WOC7RC77iRG*2Ab2)WL$e(-npB(;QI2IID$6MLfU-EF$ z1HW;^bt-Wmtp*9H3hQdbEe||xEsO^AM^r|1nn>?dcxj2{PrURAg@LAJKQ;i2r923Z zqDz7x4=9naqDc&jPUR_1Mg1v9|B$9>8h6k`*^f0%CGTGr<6V|*o9{MYLp)DSlX~r> zG~IM;D$9Zif=KsF`fh%<5okL_ozrERFNte6oENjVl)O+0o~!g&myqsbx-391<=Hw~ zM7zAsO5BsOH9g9aby2mNWmy?SL=FHq6#JPCzZq?}sc#3LV2u31E zd5f3yQ)edyeNWM3#@Bas3u(gqpLhUmp?68TE)9rjF?I!GmPrP-<2Wq`LK{z;HpVu_ zdI7L)$g1g3V%nm`h$%9rX&UE-qed$>#`XfXVem0B1+itn(Y6qvSOrkmEk;b&H3_rU zw@pn=P3_0Fh;187jWU3$nue^3k|qN&Ervy+ajt0`+&s2zEZP_$iqICmj4tQHlOD$6 zFY^J;%6Fl!AwXo+sdl81**eiwQ}CF!o4WZ_B@lJe+i@S^b`l^2Wp zZP-oJI&5Yez*1gmkj+x`FvHa<{$8Ogt4%{LSFxEPL<*A_;rS?(&{v3D4dre=A}`>u-J_U=arh-#}A|2Cdbv z*I)BdaL2yV|KWN#g_~9tj|RqZ$b?g=G#ZtPGcjy2rfG6_pdd_QxRGoe*~a&cYr(EA zZn!H>k*3yt3x>X1q3^>YT?*S$4MrWf9UriD%0HiY+)=5YB=*kOe zh~#*47}V&}p1t&M6sF|zxt#WT=o>i}9LM(!F5n-xuv%QSR8aox47(?M|B zvRs`@aFZioZuq|AVByEjtmPD@s<~V~r!Ym!La?fGrb*Ab1M!vpyLNcF^3d<I>~UyI&)cSk-l zvpRDie8aPz?~`&Gz`3eH0#8sqXw{>Z&K@L+nI^#^l^gr2Q&_q>!xzv)^o69qRbE&q zw~Jg?g+TUC83O3#mSS0om365t)ZS7xo#xFm_hdZXx0W*|<)|QN+2iGMSqH&5<;#Jf zX}s8#V7xCur&t7I9v+_tnBHkprWmJPAt#y!Gk0(RUQ(0hb%<8_4iyA-A}G4&!AWhp zZ&An?XL4K9bXv76OEwKD5WQ1|%4Fl1973dpP%L&z!77aj@u9Bk=pee*f5HPa%|IH; z+bw%Yl*X)3dCI_0QEeV>tt9P6lho?DnKu^-1!xsy|1-XPV-!V7K3DxrHJ4W++ovaC zXkg9xL(Z70+P0zR;W2#~IDGi<;lnO~yL$fo`4}HAI8RN}UB^=veC6}3yQWF6dw(w6 zbPn;GJNHp^9l8@eq_44wQ<{vf!O-hDVlW{wyrZHtooVF(CH0-be2(=T?3T8#K8SR_ zF=wnC1jR!%fc#aDlprWaaO6%u^O?{1av}R+LH4nd^KhsdiuSQ$%PN&r{d~!?@WA1D z!99G~1#!5Zwh-tz;xUZ-p~Q`W;~U|=_8`AO6215P`dU$){?Ys1_dbHX{2_|H+F=R% z&cb<_p7F4BxaMJcDDPqNK1r4(c<$+^pQg;ihbZ&#wS;;2&bkuz7`YaEj2^-sqfgWK zF#X}2hbGa^d`SYGltpS-p?&>gK#2%i(@-KgwHNOJV?5Y(BP=!12h6H7!K*ggkGRO1Y1dRTj>rgep3f!5Rwb|!b9zhQ!T;n@V z=k)X`S@be^ei-_mf}?vbUi9%rS=KaJUVOHwYfGnbd~E-pgeQVfYao1j41@t6_%vt7 zC0PCj`-Ci=mPAoG{T3#PVk|Kx>9KUFdF_V^(cKq^oIWux8WQAboD)g*3HHi-BZmF3rqFH!|_X5<+u4M{`&((FPm@??`$7 zg)w7|;=u%EO3(OdS-wgpW%=~!_17{0-#6ZcPUrhr+hs**>q6~DNL4`Qat6q zw!p8~Vi8Sey5|=PzNa%?BULGdt8`SWza=9oL`<>sd0SzsChHp0)O)43owU#167mJQ z#cr972JIjt0(ofUc$dif$@c0Y_h%@f|JYysr8Xf3bANSj>m@dREO77Q~1ipKj ziO~fq{}C^=)4P6Bpea=-lpLU0qNyNJXf&EjhkL#s;I4Sru6QX|F6Wl6TflfhH(h_v zb=U3jT~lAcc!68;jK2uR0puVK* zOB{iwsycbArycG7jhhQl{ZKWoh<5AfIkPLO`ea1WkiLdY*{b(a36K#0Dh z)dDum)6i-zM+%H-F7{ixQ%VJ+6^s#|uqO>kz@G5Bz@Wl?`-%LCZbj}~xXSxoEpOl%R zedDwRCX8(po>SdyXvmZ#R~VFe*AVd!RF%oUKg}FR0i;s64Y#J)Q4$o70Cz0{5XQN?JS7fmuhExmGmE;$Ynq$Ls9xmMluFXk1dSpO~;o1VhA$!1+Wox(%^1gF*tPtAMh_sZW3 z)37S5r(~6yRyn@4)oeEQM_T9%-eQDabokoTL_setT|nnBV-e5Cavb;2Bqik!l4Dx^^9EU z?{}-c6SNn4)`s_`iCkr?ouj5qri#>poOR-am0M?F(YE1gr!;G#Zc_wcuO2|m_l2bu zThigwh{O*7e8V(Nky62$rF7O3s4SSX1c1yws_43c>rMT18#IBj)i;KUpS&VgYAr7VXwOdh^jPjEWD9G7Vd*V|hlyX9V?k)uEU>1TudfRRI@WF!zWlFFe z6bgZj36&2P#bt^Gp%}&~k!6y`VNnn;T^5TUX5;i9v2o60U37@K!z7NV$EPJpl0^9c zAqQkpk~+PXC{uY)+nJT5S*N{6rn1;x=sbY{_W3x#SfrYZCV;tUsu4nnA=ui4Em%hp z>Y}~qgg;+4d;mSeSrEL8EKtBiFKO`;^vY8x^5(S}8S*yQN{|(CU($DJD+mJaRF`*L zbIp$Bs>1`GyV`@JN5Q)~$4TdN#cNPi8w%?RT5@toZ?UY%yv?%=zJGWAIDslr}ZB9f1ygHIX-}w|m?h{>H*n5|V#iT4tLj zm#nYt64*|V_0f`Z-VDwlLg2OLyzgMxah4~;K(?+l@dg71hJcvML%!~dhRa|8GSUNp z5Du(qFYk|WKd56NG7Fp0IJYY2lla<)@{moB!wKOrp}&W_71Z?~2UjxKr?XCXzBVp( z=ivll>Hs`Opl4z*@^7BynU4ea7xwMD^2&Yt78G4mn6iA;Ro7j2)m6(1abX>lQ_E@& zc`a4iagwG<+)6mF!R1r2k#79Y`BJ%Dn$OhJR<^ws0)(~gsh>8>dbrPWLk<4wkc?0p z>|=$bR6PAd@XO8D@&R-Pt)WNI`_VJ#dGww3NpAs>R+oT3W*6GLb(zXro9U9SowUsk zteN!5zHu<%g86Mi=S(7^&XZZ37+OldH5q_%uJn>(1;`j;`yv1INcTPQ8GZ<(QeaVi)9CFZ+_NP(pOqi>pZG_qJ{MFw9#f z=k0EHqS>72cH5j=WXoTg$sllN}THFL%C2cS0^Sa*U$y)A# znFmGMkRF(M5T3qp;exe&EIakZvI~`oiE6o={V-RXobVk}D+UkFJRmiw_~6U~NMDD> zJ@7?jp>EHRiKkh9L@A)TaYN1!@%6Bw;KlP_=)v)+{D&1RXxuW5e`&(2oO|!RceYvq z09n?h3-M)GkE5)mYQ%98k66eY$=zuP1{#}B zk~LB;m2FMC-Pl_T_z$XfFtkyq>WaxI=}AN!mQ)1mb-CUy2HdJmy_30Ij_7fEp(G~~ zB93O}FaA}|eZG1la~-}%n4Tp|7yv|>NB~%rP1iGI5d%n+&OKU^Ezi;%yD06Cc~V`+ z00z1lc|?>XH;P;8*2|ut+m1I-6}Qs5 zdIU}(RVH~7iu6FUu29_;nGIHUU<<(n%*@J*j89;ezYDT81BM{i>kX85D_mDRSy5?Q z;at5+u5SmjOU=Yc3kBGh|6Ja>dUI~p`Tv< z%fI|f1Di*383V%WckkimPoL7%DeyMLGcd7na*?qQmFtJNKag~Oab!g&2paDtE!8so zYNa@E+cr^QG^3|ckp`#g-@aEY2_`EqF@4;b2X5@4=}h|rMWEnvPPcc^f*pGw&qrl{t|=DRWHA7;Sy&NhPZ)ljIvuPAFlj+&eHi-vj1 z?qoiSXrjv}ycv8(uI@TFGbegH3`5OzSSXRSou=1&*x7Ttckd>SQ&@B$0p|#nje57+ zJp|z$cifTe0JqY`gO(Dxu92Sj5f`b3vG(qX=FYSKD#-7fkiEQp`*w$E?v77e>bljE zJIEX6=MPP|ra^rE{Q2{v<83hHQH2g=#OVw9m!Y5X%$v}>I-wzSUMYC959QJMo?S@$ z-NYMRrti{e4Az?-KbN9_(?d7UfsS2jvjd^8jcaxm!V5c=1L%(bXTs5Z6V9W>^I&<$ zg$+h!SGu(Jayw&uZPYyv9g#40m!vU5zZ9B*eavo%xs%td-Z6>wB9{(~Yz&7a%&3c$ z-+&7_uliun+lD@_dY~7CUdm_7bfXjKOmn+|?*SqQ6`Qdve@&)a6=b#V8B>3-`KvxR zZ9`8~3%FTnfo|9)_h}g@8gJ=WOlCoP?lmwB-LzdCM`_r)cNG|bY`R3-+*+MCY58=`OI&)YZxi8 zDSWBw{bmEQN?R^7Fuh}-9nlUFZiHiV&dls zwC}&}hu@n)3+xyc#@o>fKQqt3v)onLK+!q6YeLF7E|Y3UM!52nbSl3SYKa#_Z`_Qv zY$LsH4m@p(f_}b`uaqsFV zT!xISDhW^>xbnP0@|W;1^i7Buh+ zgm7O|6dDzZfMp3TLtc{dps5xogj=dM48w3V4#V+yJPN~l679uvUyW`@kD-tL@h%E} zQMhWWF3s+P#8#rvCZGkv5-y#Vkbp~3;dvMNUVv7GK~k-R!rV{=>!cKt!ARMK3BmB7e*6>S@g?4PM=y3g)r*EH!~ zrJnBAa1p?vy0Uls!;DNIYQesbE5~LWiU7)lunRM+iCWDsw<*nq(blWciGmB+PZkyy z9HzOwj|bR%dbh2rbB|C}d!}68$XQS>&&Vwu2liY48q(0b)KaIq4Jiy8_#77eR!$T> z#ufJq6uA_;jVi`?PgL8`nM3X3$)Er;bjrceSe1&cqNHN)uidi2Sr3RmADWsDATu?n z?>~Qje?3rT2B2$ZIPVke&*YNj?3Jl34~IJ|x+IBWZif7k(lBl^=8Td2$Bc2D|6jX* zB)*54DXY3`sw(Bo0dN?ns%pBrDw_;@K4BWhlEh>Sz>=9HVXU$KbIS)%4V^(KNH;o^ zkuVuXsTl%E*G)!NLI@7$WU{1$kTS3V%UNP?Wdgw5LFwQA-tYY$l} zoYMfb;OM^c>|u@elYZ)epo3WZ9gP%wN3-5H zg3`L8>KZG}&6N@g{FTEXYdrEin3~)Zs@U*V+%q`^p4Tum8L%QB!*F<32CPH?k%ED5 z<6=Y2wOX_L;y8GCq?#=yw%=E;pv3XM*;Xs38mg|bA5^Xa)OBV^lN9ekhw_Oz#rbWk zJd)0Rk5q!%2ps!*OznIQf~-e@(RwF_Z(j?Kshw}eG1MbYJx{jjw>4h7 zH2&kkS&eT;Z?a(!G&Ir{?+cP+lsjNG-BQZ7X>kMx_c8X=byLAa;y1&z3o}NfZP>%c|AmV)Y@*{WQSgj_gv1rNt>c}R$j&GJ8FV(M3Ej*X=dAaSD-%mli%>9|| zmGg-v!i`U(s=ddx8riA055Fs@_@E;9C*YTJHK@)v$^mMZ>gE{nx+4^ML9{*TQO%Ol zOjM!wC_UibExGR{dfRf6=#-@C{V^6tarVP}2J3A?{Vpul=2Y4DaJoug3*vQ$nFQ0? z1g-%z&ckO=mYs5?4ja!Hs*1YD51OJ&YwiPFloVR)cnuT6t_qMFs=n4NEr9joP_I`ed@LM=a7oOVlOl4~_jxyp~)mGhVKpZ2U7l+T63 z5`l_$Qm2SobD#1-uWb(f%k&?eTya5ERs8<1sVsUk%fvr!0qR>J1v7%!L!YD*0z8}_N$gABu%c_JLpL7q1NJKp&DoD|5 zi&)e3a*EG=T8ZO*?~`JpK0E}@wN=hnHO`@q(Y;$=TV-PLTU>;3Q##DfmHAaCAS=L)|^9d96~}Xm7Qo z{VfV5zkawokB!*X%Wud|hrSu}=5ze8 z9}7W6k6wI5={s_Y$MZc)b@~pR=7WLbdeoz?rWdF~(mfY=>I0yHARQqgsm*3;YhZpT z?#Bj7;?W^zY?Cp*8N@qhaK<(>Sv@>DQRofH+|34~Q^D5adINza|}{D{IO zmH~+4H#IP<02e^NgsBn6TesHC;n8^(Eto5wH8>lsCA|<%=8%0HA7vvdF7TrSpH;IT z)Uy$+Q8L^DLkI`f7Yx7;>Ko5A<^VdGL#Q+y*_!t!^EHR2Ab3A%AC}GhJM-~LyF4C` z$I1JX`g-+R0HJp5MZo$#vcoi3&~ z-fP6_)_bt4(0?b`i-q#~7XaXkQAAiF0fo0NL1#B8yjXmbKsQbpa|Tgrcsj!A&H=KW zzyTALu1iuv5inVo3#KXX$G_SE(=5ok%m6cm%L}#Ig3J|$_tj57n!>i7w}wdTFmKxe zW(tqY^qSOaNuKO~9Ih}d?5XkB-Kfj#Z$+O>59|^*whbMZJOUlA$ZEkywPwwX z)vVQOWG76`;zGSirH61xU9XqyPzo!|=_i{u91Gu}Dz2=3U-sz(z%$vW;aK)**)U`{ zCL4w{iU=eoK+h`BMQgjgidSr z_EdXM_dVWwqQaj3*O9X|mq;;-s|`fW{6|y?R`}A%sFe+;WW$hOdJvBPZw9}ec$V4e z(&eS3D!ylBLtx1F$i{z6QW@gQRa1i1Wllb4n0`ur>494D>a1i!QP``{0F}RukX}+i0p-4M*C`!Ec zMGD?Z){bP0!OY+_(Ph?k5YvrW6uuYKCK?}7XN)G&nx3|swCOf-af=lQA7l5hCKo`lWXt46 zlijnnVH9*a!D1-ee=AqwsLllCM%gsw8x?`oqd0rxp+korTY1Blrl=mrQQfKoM{>p{ ztn3FBt9hI;Xj={g`?gmBs@dl2UN;2auUp2`9Q3CRtM2>oXRmwR>t6TH)f>R~WgFKc zeUvQ>O2LnWU;wtnN$;t#qh+KtCb&r>*n3V!gEN4 zuK;IE-7~ju-`pOBJl*w|%nqxns!o*l?JKv(^!Z$VUJs)azbmDCVj3lWZ^TKhPW0XrVVV-%w~tC2r$*l|RnFzg**9dmZy)8)es{c2a&{8q0G&Fkj($_$`%4pl#5>VZ z?J2m7Q);N-Wg%7z)D5f*f`|(Xm~EzR;ZOk@sP&S_QkopWa9tvlsdtJqQL$Ps?_w~# z`l#ZHbF^q*wDW%xp5k1&t!ASork{e?BDQE0f|CWt4)LDBFxqryaeWr~rihtL+9>6s zM`j%)bv`g3U}m07N8Iqe|DDItvCf@uEKkuD%3TA%D9TQywY@!A{x;rbgw@WfDXR0d z=4kqVmF!ex_syc?bF=_spEitY&f||}6$G-E_gUOAYXAVjio@O4bBAu4nyTHs_j>1W zGLLs5h-7|msDjUt^*KCy84F9QrkkdA`>tMDjyQ$2){KzoHkbLyT^Pa$9znb0*`Pa$ zBk!T8TYj0qV@^S0mq~)noD7m^0*6TdUeb}pP#}o+!KWJYvvuvTE=b1SZ<^eYBr2OP z{r$@tPE?ETI9$iN16=$qXf*qG@0yMPS965xf;W(4YMKU@_PpMS5!!(f&WQQK6~(If zm6Ep07*OBLbOi?|HaukU;(2Rt+!o#Kw#~<{tdGdf+j49}@_*2WpEvi>a-^B4N>x4& z6YV@^IzbmW#&!4-;vFCOb@xnr-CCr5wdgK(o09d9wbvSqS`1Xl&uf)mh(7gc>0wh5 zrzDju){(+4EJ;#&?Hr}bGqt*YObFeFgEj@mp&?MJb43+elIM_Z@JZdnibt#ZS4<4- z-8v`!BfdifLF`>h3xr~E3Y@roXdW@F{{~k8HW&Pk3t;~V4|c#(>Ro+e(Yag=)$+-H z*AL+G#L8pH17-+~qGXf?6o@T8$5}^Q=qO$Cxtb^(T}!8_Y23S>uE`uoGM#KR3M&d0 zbZ#2z;uH4b*&!YkPGO>RB*PTF)cV)(N;4fjnlKX!!6#DqB%-ALyn-ADe_u%1O*M`_X z9Wnte^*VJtwYf}o*y1~zk|$c}q94lvEz`kaPo>T=vsYJ!Yt+uOgZ8VI^_`-=7vhwY zi@JhbM41#yI+29-)aZ#Y-Gd;b0;&Q8#KGwZM!K~-js})?)d?ZYm|CO$C9;}5us8nR zg^n6I08tNFKNaWf(5872Ko&84lpNbJ&p?h_enY0qj6p+r^X zk@ADCWf_3Br!PHN6)+J)_}KwM@40-$Z_KqVYdT01--Vblp9Xro=+^7eNW)gkHbK(#-&>RN?aGtit z4@@r~w;ofjZ3dRn3gB(1sjBwW0}_+#j19*4%k{dJ(G#3da?P$s`d68r5xm}Shd48( zMSAiWD^(={ivY-WBPjW571G^J`LSvSfH6c>GK}nuWUj(>mBI`9kY_$F7CWsK67;(1 z>8GC-gs1Npx*iPHO)rkn{x&{q(Fc5XT@$Dgre4TIxfihIEhcnfogACcFOax;k^(i_ z6g^-!c#ujlW3fa(@ai=R8r|>%n-;)>oUt+5x1e0kO0lZOv?rQ2Ib&hC_6WxKU~?E< zFO)~!#9!e7dD03-P9d}0z8Ixc8_QJ=Eh!s<(+&NYiQIxKyC*>*c{}#mPfXn+??(y#3 zEh$K>xZ{ku(TbFePon|1XL;ybhki1yv#em@w{%38QoLsW*H6oz)p}8SbT93`<~DTJ>2e*UpNP zRPc;MAEaZ7%(l(lJn#RQ<7(I2J8riHVwnMy0@EU5%ItCSdd+p%)jz&^x$UG#l37lS zXnM-knDe_A-u%m+&bjWHIA^clb(rQp^;Gun!(p?DBsf-WC}*2{zfcUNq?WXdi!lOK zmx7!%izf=qz^xGi&?Hm`GfV|~X*wARe_%f1snpf-C0v#~kL3hHagO<}RK}%(=1|4c zCZ?t)v>RoUP8Ou_W=~SrQzTXD5^~aKl6Q!ZL!QL^lZ4C@Rf>rD?Up4ef*&@DsIv7u z{H-3LqX*ClJP!M%Be?%v;Wj`*+RDd4e<$A?|2#pf9m!WwZc9l;(g?Z1^|nAR1%Wo_ z`LIglL^S$1pFa?-xJ!;!=5iC&YBh#(UkASjdzr4%`$Qtk_j#XmF62Cay%;G?2c`t7%HxVxY3{klq-{+mQ3_&4>`03QCC30g!~$iC)Q z&XHS3fqzJ%2q_`%r}Gq*BFY^G!1ExZnfI&#r-o=8T>KaL{*{##YI~}3jA@=NuTXAK z@I23(ybk+|gmkwo`Z#73lY&U?8~4uj^>t69w&OUm=B;a>-#$4xIXU#jB;4q)=OX=> z^97CNMUFdY$;ZFogKl{s8g^;n{spO_99l^GT}%Pss*bkWZQNccO;4g~f!!F$_w%j| z{WOK#?x6I~;xP612E4ysic5cqQ~$Nz#+AC?$SG0!zFs;FV~Cr7CzAeMQqPqYKX(2N zj-~&#?iV!4FCv=e4@U?gck35h-@|W(XME+V>v4!{c5C1G7I`A04pFZwY04fF?S zjJ}2b6#Wg7xj<PsA?wX3a`^#HACiHeztZ;OIu7g+b!Oc|~?(TVA-7g(7`P>uNyJ0Kqs<@dO zyqd(Pcj~LJ()#WeAB(Ge32jIBqBo-_(Ql(~B5AQTi4#hcjubG!+$SdY`jS=@CkshE zi6^pi^eLgKR7V2NJGu*npo^0FG)n8IT-0Xhz$-Ve{f>3$0D zk}>EQ0D)+xp%J9J9?SB4OO`MO04yjx`*%r!q!N^;U&N@+-Q1`lu7+UE0CrFBPhu7? zow=KGESE=I^sDypqKCmJzAD+~lLdq(JAH;Pl!QkC7O7?C^QOIQNg9p7S0y1_DI47K zUrm)twYqc9RJr5ki5c@+!fH$mH$I3Gap|e)eY&DxkYzpl+ZX3GcWIUx@M~V>J7ST57MmK>-{u0un!T41O5*E^iI&zoGKu|vcnIx#+ zVRQx3F~YP%I@^*iCQD(T+~x48x`jS5(KZ@a6RiGDJ29J`JrKF(v3g<_c1k1Oe|jpi2_Z8wm*bX(Bq_GAopw;5fP4qv<4j#q zfIQH*Vj=0XeyNsTX+RxVywGk%@QaCwiMxa!lIJmS->`Hk`)`}BRwb+`T$g2Fak3xp zXLiPduu9~QYD1%nqT@g%-DQgy1>po1Q}9 zSaL9S4H8$w+ij7~U6OYlj@Z?0^}YdZAJExq{31%xL3D<01w<|>(*=-98aDw0Bh{Xu zWt~Ljh}Afcn?XAxr8v2X(|!=oxZx#eOc*N|LErP0Rm!sdtzf z953av_st6*zc5kCzW?!0qb>^N+QP#8o|@-nzmRpPoK%$Om>Wf7S& zFewfYATOpz0ELjna+EWT)iqAEe1h(CDCR1^ePctbI<7xcsmxS7uQJm;q+D)J6^m2N za=GbSreS+!)31?d8>Zzq%jKr$*ny(MFx!I7Y)cRnQNWC0ASnUN7^W8~W(*60C<*%8 zaaU4Z6C_c1%8Vc?f>5{7+i}bjSI{x2$eBrx^1&F$3TxXmg;1D;56}_Z}sPeM)Xq$z6tw@00U-)UV`-em`u z+R|Gt1@^n*#000xV%`6kyB|;HUHHfk`{h}hW#qq60WI(oVHkQV>M1WD}3nk!|kWrb*Oi#8^%H3v5FnY!Mtk^l|9< z_y^Fhh)~z%Nt+(qvetRlBzJeLU^9WH(O@vJ?L|-ea*FPc!6Rm=G?UJhN@j7UHa}mRDQ35IJvXCS*Kyq0M?uQJ z8@O{_2c7WE281&+A$+s?siVPl|3DplZ;v-=OU(yX0loL$Kex*@&DDJW#?k0aVP4PB z19VJ7WxlEuhe5`UY-0!#TIAZ_Cai#SW#W6=+h-!9>!~@e2FMFpgJ8MRg=lBCyfjWh z*S$L|oWEWEz6?Ryp55|hZ{h=$WfTSGyNQGBZ;yIWUH4=F`Il+S`NP_Jx`44<8FviI zmT2UwfIxLZ7ndJY$;l>D7-YdfhD-q!i()Q^uK^zjJ$9nuSK0H2Myt%!bYaxgFyy-s z)9_6qh;T&klgt=23T15EyM#Fc;f`Mve{$wURJT#zr!`d|{+q7zzvt=yKJ4jV?z#QH z54-&r0yHjaf9O&@$1^hNS9n8_O%WLmEGjhx^%+`W5l4;sXOYvcc)VWU8E=MQnq;XZ z14+Wg-b4RngVwaFu*Y`9Uk1<>4;mopTjCRQ<0sKG@Sqhx?h``Ap8A$1>rtIZMdQHo zbu(?tnTzH>x9})Rmy}w5 z9ov`-e%&8->awC3<)AVJrpeey5azneVZ*eH-}rp?&7Ix(Ez_T}19?XOJFwM*qHK@* z2gx|JPTtSJ<&un{Ri^IFgY5FYSyDRHDshKHRdB{9^Oe!ceY;5~uJk|^d0hlcQe~^Z z6w|%3q3M25anXS}(WkOO3NbJ%4&m8%8nP5_SAo|xqwMKSbox6|B@0B|2hXiMeR4-V zo&CLG7z6(yS%<5s| z0XV9ls^95&`Sz&J9PFui9+j16;CVGH?5fq~jmmA+YP$rCu|TzHpwGQPqXLd`7SMp> z*A^^0F4S9iRn>J><>N$slWi5`K%cuJSC5vc_T2VTRL>R5Q0yiL_n6J&d%nT!1Dsj&CV7Jln#YUm;P&^Ytr*lJFo{I zXf$7JgHeM+4WJ0F@M?hof+nspJ9g;SnH8 zmJ1yH9rd@P_o0vZJ%ekXA>m`8RM@bWPyrPp?FpZtu8m&YM8!@`y=EhCzgp^%@T3!3 z1NANJc{tX#$qG--BLa~=ScELczwb2$#1{N=N!1b2tEK1sIX`WU_r zVSQOoq#HWM+8*YA$QM5 zF{MgekJPa^(e?d(v_CUOundU2FXDtzs+%Tb@h(epU0%qksw#;br{+C}le~?cJ2yPS zyKY|PI8jnnH7D?{D_OgMg#$g`@g4<3M)>$!w14+5!ne?6uTu?;4~F|4PV#IfazkKO zmzXGd4rhfkHs^Sf$fn-S5N3N4=j;y;#tx(k%DI>v>8~)e?|mBiYZh8cW`KB%ruCAy zN=74&If~3j!&Z{y-#sW!EzHLy$RgjLnVGE?|8793_3!^;sxmt>tYrVKK&olrkVHGomRV-0x!5DN_j}G;Pnz$}X z*`R-sQEF(Mc9zOvF3&TJzqtvY&xJBQt8v zho<`qi`;|?hRDa~)3}|)^JpSrOev*w_!Q19tgWrC8R+^O`kpkNRYcLabAr8rA&Sb} z0@Jhoe2cRxV}R%gjZ7npS}-S#tWPA;!UZ`=J5J2yrn+-srsFg#^g}k#mhf;8I~R=h z$QzJIta2^vb^5$;~R7ZEXe=k@n8^;`q989me7G#N0w~zMY5t0)&-chg^pn&sC=NOS(iA-y?CYF z-y7~ZbLNbqoRJxm<*eZXWtlPgIgwz!rjEK2yz0!EGm2p-XJlDsyLUe4ZYImJ%%_(VBfSBD_D?8A^B#* zjU`S0Fgzc1t9}yUq9jQfV!CSBta#0LY3>C{`dyas3>sJ1_s+Rm0ZRuZL(M}4g5^RpLESI3&nLM=2pXx6a?`7 znJeEIuWe-yoMJKO&(8We5rc9;0r)BqBB`vGaX-r{mMw6c=^0nBo#GeW*>R?ejxD$| z(~bk7ns}sc)(Qo2`-^zHO?JA4=VZgg*feC3SOh;n#?{X3pu?!w^X?hmw4jE`bzB4W zL};CpEc;O!hSAs~4yEFK+VXi<*lXK-Te8vL^?E%b5;h#@M5L*tD3ZBKG>!c5r1UVy zszvo3pnq>E8_O`f_6W$nycstSheK7>K-1JsO1)Poijp2=o6OtB5N~uVW`W)|r9{fPpbx*DCt}4E6Sq;08cUr^YP*G(0 zLG4*ZQTBNL-!a^~HCg6nMB_XD1>g4t>|aGh8ZZoRWsLc|UK?`?c_*^%3&Y`%QdJpJ zs;K%PErMg-sv&?Qeg3CJnCf!aLv(_c*9s$U6lzZM41YdnOBsM;D&_sNNWC zr?C8RdD3;CGW@9{u7D}k@+XgcK%3V^@fbE@$8rNoMDA5o<51auNG1Zy6|ktB zC9+J;Dk9MjXY4}`>*O}34hb2~qzArR<7@)5cr~FCMsWSta6(6e>?UZ@i9}G0H~z7% z3?*qOQmS>VNv$f#U;3{o3!bkrQS*|wnvs1Sl(}=bvFF3l7i-O7mE!~UMQH9K&AhZd zhW+VOh3-Zui%I!1J^OHS9zTmzEKRU+Jk(GF{Y}eLnTc&w12qw-g^(-tF6e42s$USe;+nr zl>YwfG;=3oT`|*xbTH6#q^WeMq^h5Ls`bHmpEa1k2!DfVbfKavQAUWhLOd1QplYF2 zY4(vh4`cHFbi%c$9(~sUsf&OywQ=-lgVOpv!(W2N(W4DT6pcOBg3-!V8y?U@i^L!(rcEnMtg92>9he)r8c-z-X!cr(Gy4)F;d z;|>QCTk!9hJ$u6qHweNFM0PNt-qT}8Ca*cIjhLo|$d3SqLAb!mXF*EhIIEGiV9zjn z_WJ9u7scye#j1@@vKXatTK&PYwI&Hj*?SsWr`S!Fk@t=RqD1THOZKL5YMfUqYC1o_ zl~<1F*YDspv8w4Ax@oMZ?eicRBih``19?oFYMoH%v(I+OU!e2FYiYQ7J(m(TXVJvU z&Tz9}+s3Rd6RS_msbBEm128gN7LPeZ>-cYOM-k+#o%cv$O_VB1EI(w<@4Fu28!2eR=V ziy?(x>QcgN95KZt$<6D-ZS#)Gw?C5hbmz6}xhQb53~`0g4k@fXr2!fB#2TZ=z)FfD zf&w%Q?pnsq^#e>+|zmB)sc#eIoL@WlsfHZWc?57JKZuE}=KiHO-q%j+@e9!SQ;rAOuGk0SW0{ z*+JbO!rH|@K2FiJ`5)#Wm#c3dEj;`3I3NBfrV#h@618Y*$oOYrOZki^lZlN>4YsXk zd;z)Rp{Nm*{dji%=;}-Wsw94%OtKYEEyu04C`o;BBA?i=Yw|lpy`+-9tUON?g*>mw z{kp*Ic#jAmjseCZfcWk;P7sA_t`S7|uq>Z9*fx?RK+HJb;KiN_gn(fHA)xj|o)@mY zR^Smr2>Rmn^{@?9RO1?KB5rROEAf=J7zL%yq1@{lMA;K0_0R6sX5d7Fk25C|7}nu5 zV_@j(``b*a%nXTO4!Hdwgk^hQKMU0o}UR#TM3Mvj{Q4@iM|ejVZ_B{TBSGJ*<1cAsbWB zwvM&f%z6NB2Vu4P?CX6Pqa}KNL}C=VjG!brbgpE*ywCyPl~&X0BU3}{VSC725_ei8 zZVz$U0AuK#X)W|u!loE7d`@lAP z5vWq^et`Bkn&+ug!*;D+&!d0T@EoTDD(PNZb|8-5SW}K)6jr5*zYD49u;NCj)3eb5AV=I@lu&C9W4GYK0i-PM(YrUNA zDGRDmgKy18jq_P}!@}6o0aaIKY6H0toFOMLEPy(wkclV(#7)14R>X}~qk4p|wsqBb zY0K7C2S`D-m>6_mso6yt(+b$oEKFp6pc|wt- z`_<()UHN2LXLv+msDdqny?;ZyWTjWgh<#DFC0rb~13pSWvdsPaSEVuAN1zX{jOI0D zt+}RY!a6?YP87%LvOcvNQQgqDKxx)jvp;(f?#UhuyWO=Ninjpy(!x4gF`-7)J&UqxYiO6K7}#F zc(x-$hDTRJcddGT9$gGQpPs&uuoct0^5OC*Ot#L-Nkc&N?!Jy+zp>cFlxpyGjZ)lP z-1rl3R$n2&&BYCkQcAUr#io5zWNiK}fjzW~o-Vh75rRHrN53JDEfa{V8TL-47_B-a z!o1Pzw0tltf7v0*(we{*Ofz8Yc!b<=hx4K6c=pbY?n-ogC+fhy#1|P0O!Ii8=$+e# zqT|_rEb=Y{p<}(jWTT5VUQ3>XHDa1U>ZFbXPQ0crTQBuV%7SRX`0q6{v?W$_Mnmt9 zg6+@E3s4j7K#@St|D|`@Bp*Di=Q_8ouO<=&`!*1`V6zVy>Jde+wd>40Z5tnAY?j$4 zn(LKJ7yRN|oSG(#*@q1Kw5iwHHC;KP8Xsb|&1PA)*;GwbSA@kNi7~PW?i5kJJA)E2 ztO9|P)%^h7QeJKgv@q%Uj$4DA^xECFgX3!T&PvjVZ+0EO8dgJ0_wq`o)l#ZQ#+xx+ z@luRHb%R!3+a4nM9^0|wl_Gc#0l0yIV89?M=9hbrXR;x1ndZEmUd@sw%6xxK(m5?{ z2Y>mRH0iH^oLE}oen4d|7&6NTqI^E}f_;myP5 z1KNrR4U&FpYq?TC73fscsI~okwtD^a)QJ-(A|QK`V4A!B_Q?}tRV6UJ{LFz{F6RQk zJD*uzSb^^>#JND)F`nihe`3ptV0n4@nf>R!zg#dnapJ_}cHiaGL9&NHbm9~Qxs`?G zXLjP3iK^am;F;xVXnk8uLITl=WKZue9Imtze<(gm=zrETb6_cbA9T{#Q4-8T!k#He zNaoDq(Cz-n4YsCKqQe!gGe3Hs^DT#TlGVHY|2*+N^dT5+4}7*AU20@ylc)`AEz)?{ z#&xL*RKjb>aJ^cC7XD-+nYS_ov7tObr zp{Le_Yk=*AUFyTBsVT{HBe68K;U+&VMP<=W($pxFi}(#Yh(-sbwF&`1~Z#4|Z zIYwZhzcjEOENCOeTG*r>t|8Ao5!PNcicb|49g01$Jxn{Bz2Ba#?$+o>H?vsYXVLQmsOGXI6+ej^m5prR%p#I&D?6Y%N#IFHg_FV z|5iBoAqBd8^3$@TmFj)0k70}kGCK=%0SElhV#dw^;1~9Q`=V$lLO}gyg_NeXSg+Hy z@hiQl-3Z;(S2LfmR82UVZ5|ag)p}yf0T|=Yb~+shI~04_r#(#HUZ!}wd#tIJOrL$0 z%9g5Wg>r6_GnTbG@2`a?tuNW$O>c`kBPCUum^g|mbv)C_qT1by?uH3B2>2c6gv;|~ zswH%&>$=0$ATNl*ysF9|kMaP6vVi;jWACuB>g5{AxAG>6J-Eliw3CfHu&(R6Q+(7? zC|5BSnv_z;$SFJgkYyRNSIyWOQT9E38r#_iPpZ=Cz`*Jl)-p^bG|ct7^3jW3_Jhob z?=DY%^|B}Q`@XJ2xiURnDTA&Dj5CId`i54(jB)vk6np>XVcHpYHhB<~V#@T@mx6#Z z#*5P0npEVB{nv|g%bB`{QnWK3w;Ym!0UiHPC~g!e#t?j{9Mx*4Fi1nx7l(qJS7Ti} zn^HhHW-sY$NY0hr>1kJXbA*^yU~-)+0+wz!vzKp|u%K|An}KDL*R0d_S69@g4vf*q zzA)=P2D6EA(**2$I;T`7s-j-Hq$(w+$?V`*=V@3QLRhu9!nhc;)_L|HAC1REgen^YB6*nsUac8K zjH_?0?@4+ix7?2)w)Hjm1$+h>C_uFc3xFQ?L;;sdx>`SN2lDrg(*WidOF4BKJ7^H~ zMpv}{(z9=#DQZ7;A70VS;!G7=5eoy4&h3wB?c;SUp`#sU1a5zq8DOhILjg@a9s#_5Zl6GynGjSN*YiUOG zTg&ifK*gXmi>4uwM-w3?G1V!gekttRfzguB^W#4yLgrQ~3JBDOCUW&S%$wFbW)0Ka1zulZE zn92$>bSAL*#id+V1jZF+ZKsvNUtb&QcV2h;VED1QGQfL^(> zA_yxhuY5c{ZWUG?S!i8#_uW^Gk#u=%V;Xb+;Zcj`hkafKDBrvAy{Zo7R5!>sQHEwR z(^1k+{MHH((m*1298&vO!~1t-(k?Jv9_jnyl(BK0Vy}D$_86^Ollj|`ee%Bh?vv)G zc6{2!^o@dm#jc8>E+>0`*2;x9K7NRd>y&x;jeT zEs5kg>D9nKUCEU_Iz}>N1iJ4KiMnxyVB%&F-H645tubDKKSVhRW-zZwNIs-&isDpi zwaM>M8(Azija~s7*+d^Um7*l)VXvvP)fdBNt5UIk3_F1Ke}r~btyr7R9{btPeugbc z6nafX)pccwajt|6l)VZlN&_soORR^c4c7^OvIFq{0NuTNcje(NKl|CwR4pn)Ls5?K zb;v@6bGD@Dy2@HTpg=lw50LP>}q^;nK`=;A6|)OW)^;*-coFP&a zcN!9zPa7ejcDjH2_8DXL@D-&lnqdRA<&|SxyFBFKtg#idgn39E4pcL<>%IPef=ja#4eZJu; zN}5`$2#+OjFk4POfYt2s;T8R5^#zMp*Q%GvG@lrbMw=Ae^n&l!!>e#@1f60!N-Uv& zo^36I!C*27n-WQ)I89Nt_7H3ihbR=)VQ2&#tJ8dBIAjr|X46se18bwuD6(n@Kvs^! zVC}j0om1#zQkNn*sACoRqpln*9Mm&FymCoL-?f688D+2B?RLAD?Uf<>h-W z+wi~|8@Rn+Ie-5A2ny%V7hn{Q6FcQV+(1`w(RL%3NiJq<$cU)e7YNCnyx)nE2;MGx zb0w+E>EGaYe>pKRLE6UH(dAnQox2l4?<%1$ly`@*ZQ}%lJ{IHkO@SrLR=_hUTzgJt z&EimfTj;CEf`2P^KNmOc4cp}PTiC}^r?z4`~c>l*$9Ag#hpW5jqUorl2H@F_wqMr-5?m_Z~v0ApeWMt4n*HoR=O* zoALmiJ3CckdgvFbO+oig1WZk5PFrR9xr_8Dm34-*r|JB4C_U8d0#W6oDk`K1rg$vU zTXNf;IYt^fSTFHKXN7>6l)FhwA@a!<%PmS`@?ADVh@`i@XHG4+ACkFajs~94bySB=>+t}ZkP}Ua0$TWI;fh$ z9mg~w`>Gx9d8SM5$1aM2W5Qt+vXoxQrUwOC(@~Bxo?Q8nnVx zFv!3~&6QLYBrg?OOI?{XH6od3EqX)lOozifRBDtukCZEx#iXETd+PI~hR3iqMYQKd zMG;E}DynK#mkVbGSn>+Ml09eLaB;HhhTF!28DOpEbC>1cd)>)lh{fT&eTdB<9VeRo?d$m zf216W?(w1ly&|!V73b03c`%@CmhI`)HVb%|p0<|*_R1h?RM-U0u(Q>~$fXoJ*91h? zBOZ@Nq;|>KRjNs0ku$EZf%0{Q;4uBqoo7Zx5RRPDphDXLfdW8 zffl?=Ggl~j%=RP_CGcC(Lf5q_)r0=*bBU=-tsGb|q?5}$Er;SMqA2p`WKg1M6+o-* zj)kL$qR7uvP@bJ%qmUbIeh%4EfIcrP3UT!m9iNVNd>o^I{5e@s$oMsUEgP-Sj7^k} zNii~(iz5)<3YV8qLj7oy#3R*nLBIi%xU1gzNIt zx~{uU7#iv^VXp!%3YNzPw)=dh-|u7J$4Yok!zvT}uOYQ@lZHWkf3*NYIrnMFisc*E zFk+g;V|3GuN6EgaJ|bu@loR$6Epv^;A`QwUqB!3XDt3^h6}@&=JSq<+fvKfjsCV3& zbcs+`ad5epi458lT-rv1%;7o)PC8?AUUUn=rBU~2Hvdra5EDb_;!_>k-v8!C<6bGu z&w0LoaU5rO^brZPyaM({B)xT09ph0F-|cRigE4eG{#0Y!+cD1#A5D5Ds{{0s_-XpDQ(f;%)aj+ zm*2*@WoEjNh^{N3kMPM$KLWrbRK9(mr_^G$w0OtyY5^p#IG* z{dTWk1Fi=(d?By2Z%fkBl&|W_+#^|it=TWKzk_1-cNW&BCbw^&oYKKGL0@jsum#1h zwUY96tNhXP~x;vN8|$7OAuo>kmxPBm#lqN0sa+9S3#NE@5sOs%nF#X`tDv>c}Y}$w^+FD#MT2 zh%NFljIf_QL80?nv(W@BXD`CCYZ~(Hl61Rlm~QqWsyWUW^Y8A}<*>iF=;O7)U@#c2 zuCA`uU!)Bhp5Q=$Lclll&+LPMBcGxK zEj2{6cyXxKMV-@{yfjZ}sT!El^95^Mg%Z2%hi#bZRh)|Ym7vN?vQbm5YgA7{!4|!{ zCW=qF1}zG!@QrX*s;1Iq16!lJ_sXqYZJd3K7^`hpUqK6gCtcloI5}jx=gLz zN>hLw6S#v&?F5xh!=R4*Us$(G>VN*HDoqk18BYiN_;DUQZAgSn0!h-?IN*Ijp=Bg>@m2~*d_t|)dzT{l0` zAhPUShY%9|fpPc{I*aboK1y)Rxr|c26^Pv^mS+_|lu0nd6V~&)SOi_VtCKYE9RQ@N z7^^Mz2Fyv8Oa%;7kd*0GENsGrXC27JnX0Np>`OQNJ@y)46w~H)v6U$5kZn9K^7#C z0YuZ50VKh&@m_zX9#&NK>qQhKQIZ79rWkV@XaCX8hhe^LoK%uQg<=&+qqy^_tRm|S zaP&%=7U2iXFT227uNaa7zfEz1CUN`(G(|9XsHap4k1yJXy;7$ciP+MZU-(csJu@+3 z6I&-tmH|AkRCM1a3xdQu6FZ4`x(w1R=plCO?L7HwS{Gwy15({mhsHYz70(ZDRO*y%v0*7@gDTB#r0TgGdlN> zc7s^b_w*3WJ-UO&UOibz;$EEi366CED~f6I`{U8um_0lR^Nj8n@*aT2sYEvc05AwG zcn>^_%IKI}VcC{t)1ovxW|}X7q|skQqhM6PwmT5mqW@~^qrM+hDuHbWl}h0I=M`ON z7vQ}iEc$yYNOP5H;QO}i`$4smyH!zc{X=est*AQJg=2IbT1QW|{v%)GoVf0}Jku;o zsUQ;spdST}X&kkp&|olKez>E(elL(stL-F%;US1+OsSiIMMd^R>RY-d3m`BDY$qq+ zyrP=IDo{f9@FrY|c^G5t7yw>Cp}!gx03_MLwi5_Kp6&XO0ZQ57pHx*91nPUDB;m*q zywxHRRXwa51gk#AzAB0U%y%UKpdexZ0YpgxQPILkmxLW3T=vy>!}=`_(2*!ZU4uBwV!{LvZ+f48dm`f8sBz!gFaLf6Jh#!IfO7$w!V()F0`9xw7u(^X!WFRX;fvaX+Re<%#Q<8pT^W9h(CLY7Dr3>x8U4w;l-a#T9 z9x%--ZQr*iL~*U;x?(!Sn)#N%A__0-VluDjxw3i1?xRfr>4IJYL2$Vax})o0n7IeO zDhR@U+xP7&O|t`FTcrntVACrx3i zDqmN{h!6H-nL-y3|7#bTv*(BtwnM-wEl=zu=GF<5y{m)AL(bMza zDv_JD+93^B>k$Mp51n}eAy~kklaab=JJBeCpn*v91h{evOYk*|= z%K15fx%n$)c_cn6%Ww&;F#c5c6~MIerwh(iCnKh;^*TfC?k=gM9EF%W zxuFj-I#u#|Li6YUr&@&zG zB%Sa2kj4R>?GDx`p@lakZLl?>WSvllmN6o9S;^Ji*YCzM#X?w@L&tjqZ8M1X2(RjF2I9B(v$$}7Qe2I)-zh5~h$5TFLw zPJ_xgLB-~^SvBBY?;Hfj`4V)ji`X`vsns-zzGL0m`V#yW?(*DK2sIPh_$u{4+(V7% z1W|>8$8N$TK2GWK9__c=!rib>QT`n%P2uR9dc9F0Qmh~%d zOomGE+QgS*zMH#koLXMiuU=ZHRsjwN`c{P@&MDNda$lRChqRLcM5~u}jas5is_IpuOI0P(I4C1-`zPG|1<&c(YfAS6Rq{DLVYATlm=Mg>iwtL4rh`3bn~GTu*{=2muH z&7En22peAvwJs@`@a}j7VKttshB#Z-jX};qIFcI_x6k|kz9$f>&w3KCa_r4=RTVn| zq56|tRfS0ydp(q-=$fupXU|!FJU#_=x|OcI{`MJjRTcE395aa@)sIxyRZW;&ijeKY z8%MB#_M$6eB02kJs8Zv>j7qp+J<3A6+l3sK=33N-;o)dVgoMJY5GYZf)W;5Rz(zl) zcY>fJGfUsYb@^Gyotm}nRv|(4xRVXcZoBQaM8xykF6MkD_l^&Spb2cdczIQj=J9G3 zLQ+cTH6!q3noPw|54t+CZ{HjU%W6}(5DG5EAh&;A&q!M5cw7oi6l3whgJ1O!FOL9u zrC#?w*F!b2&Dg?61m62B}%6ZD~~JMRc%4NsjSRGIZg2bTcU)9 zz?klL;8`wID+}}*ME>w^N4!v}3Vd;WeO-E!1W#*BmYMcU+L_eOrDXFtZL*U-bBiCI ztu*}`%cDubXCU8IX|N<9x>!k3JzLn7@V{I}a>-u1rM?6H$F}YN*iMqqNxRyMcD?S2 zlEn~)^LJ*_7*ph99HFa@VT@X6fNnx>L+?Ysjwo^>KV&8A=tt03U}?1}uBt2wx}Y%x zO0w(Gw%WDS+V`kciyBqF*Z#rXh;nJP)eba}AU{?qM44xMmD6s|&$ru-CNm~$Ybg13 zRJo<9hcr!hew+{jgaGjf@s@V?CCNY1tyF=@`pp8#4Zm5J8B{CXc-O9Y7ujKppJeNB zs!#wZ6sC+0dU~BPSUDY=rdi`rJ^v?gJnsu*Y2lOZ^z=4eX6b(A0h9G@)6;Gpp#BIL zaZL1BaCXs7(Ql+BrW0N?DaXZA$&#OhnbvhU4xS)Beiw|G)&a5cixcCHx$t)N0*cY$ zne&sfgoPY>sGR^Ble$Avf(6*Vwvs{ZWK%%zGkf;z*=mWoZj?Q)%f9OF`f2Kw1Yt)& zc#j@}0p9GcXP1>iDFkkwtgIjI&f@{GOtVTRnIJVSxI=vpeYjvpbiK5h7GW?B6Z?T5 zwOUrXgiSDs5ijX`GJ#rIK%U1ftr$N@x`jPX4^$bA)3QtjKvfm4FqO%Ypm0UuiXh2MWeQgn754nARQ0bR zT~$>$8|3prkk1Ei%XJ79LpHeS+P0wsroc64ga6lLoK!_Y5LH{FgvgSt8HTA6nQ9u5 zscIUACKFjAM7K0S6a~%F36W%pYNlZ-R3@56Wulsfp;Jkg2+^%Kl}ueXOC^JIqlA!% z(AF352*#*@=FvWM5}}mds&w&8wAzs)PP0L_NlcV@zf))@^xEdT_e#)|1Vhp$k}J-_ z@973VuRi`$i>00Xp@R>lpNa3{1L?*NOP`4GK20khEbFGJ@!vOf8W}xp`$GpGLih8A z1Ra)!Ir;WXqvgW16m_FwMaTAZ5mdiGpi^fxm^+eb?RL}K-u5=;*fmkuNuzejZ^zXN z*rgVbdj}L>II6;JdA8jym6>}0g0R!?)I5N-r}~lE!fVuXSXgw^5YU}7mZEr^W6YjF zCP_HEK)A`|mbF@ld-v0R`XfpDstsTtRUvCgY=R`pA(bTEiC-rBtG8R)K}|cTS@V@D zFs5g3&>4ejWgfl&Fd;gQWNaJ6f4;o!oP`_kEO^jJn!wD6B>iRG z!0nMBbfAh>6vwP&Ubwzje^k;~!b**6qUXea84GsV>dX>AQTHTJ30aI;`m!bi+_NNRrA_m8p^hTr~`xidMPO zy8f=d3C+fKMtAD^PRh17nxJ||w1M?~qoXn8@@c!y8Skj`F zNq-oK>6LLDIOWeo6i-fc zCX3Iv+7|cj+($F-oN_Lep{t(#<7A=mzAf%I8u$Z$wK6w%Hrt4l{ZET*<_B7>K9j#( zCF(tp{Rx>*4(T$(-^QuX52k-Guj5KbKFFjlx@X~WM(AP~f3OSWF-U9HKDP4~JZF=g z3vz|C-{y=tw;PUQ9OC?Tr*NFHc>1J2FsSE(T8*wU#*Y`A+c`gEIF50`_?s(t_Nqy=d+JP*!k0rpFWO(L9-x8qU0=sMNlku zcAMfw7kvzeX#rzFHw={$JViNQ2+;)Ly_1uZIS(tMAYjZCOVc#XQrO%uCOhIjf~jc&#)77q0>CqFy(mqW%kWXE%CaaEMnGoF6g7-7)KNvAlru^!^NC; z|r%QOZDVE+HwtR|-aH34b&Z30e~%z-o7_Tp({m6goh;qMwN3 zGb{+?KZVV^3fmeiux1M?{31Pj72TJVtNfbpe`WASwZ}4l{MD@cjH_6J|B}VQ3~Z^w z)lX9+>#OLiCoV;`u#X{QRS^B_-l%($lH3DM^t^7#08W|;6Um1R0OS4kqXvNSI{Os{ zfN`_Eh1jX0ZA;}idf*rq?pwepEGLsj>#0Eqn$$&pI!!ZjXu34%ru66s5=C1bjSgEh z?5d{nSpPk~bweHPM<|H9U3hWS5w8zy7l>~I&q6UOKTIlax)|p_@OJ-q#Q&Blm5eZ) zZq;hO1u|v%uvRHl%H9#LTq#s)VV+SLEWcK3O^2Z&Q7Y%KBr`DZ`S);2u|&Wf@de7isopCQ29~n)<^A@FL2g1YLn{iE==C8ytZ^h&$4l zPn*497~LW3YoI_Xpuz-NgU_qmKHOTXX0V~0Lz5&4eza`uqrWjR8~Qn$stxh)t7@pC zw5l30O`>Vq5i-qXYoAAf_qJyO4CO4MYI<&kv*YX?O*{ME)f9Ae7Fi0mUF-&>QXr%J zOrz6jXwx%xKrgItc4Yb&dSDm$Zp$9um*|WGP10&Agto1rjrfpG+s4^`+HYg~?Yh)f z@!NIDb--#@#Deffirr5wPt8eSBX5_oYbpCvs;<`}M~Nopu^v z{4NB37>2%I0tW^@4OGH8C|Mc6o2>Q{uUi0Ob<|6`M()+2=4<7EdUCG4kx9 zvG`L&&sO_%S7shSZ$lr_ZZ4oXZML1;7^!Yfl4{W0@+&7Xz71yVA2Y>4$3ze;0PCd| zCks9J1E@obt~7ffs+=xFnbKId=LvyB;2>M*LXRHEdgilW1kKr_5?MZ_X}D?7j(-Ve zA2!Un_C&D-SS~_wq8*=I6oe)~6m2uDE$mO#@(xV-l@OX311z46+Y`kmIQivMrS#)q?yhN9k~P+@5Af7< zI!nYF!fGyW7_v_$QV{awIEgoQ%}l4Krk&sd!^r2V;grRs{@VC+_zm!C(IFTk?cpa& z4L<6kQZMKx^WC_+25_jR7qbh1_X<6%msa>{GoOd-DOD!ieRTDTUzt-pm$o|quynP_ zovk)ptz%-D!F*w|58=QthJ3zR&VDNEx~gE1x83bh#k=v*vt6*~=l2d|SK_|Ts{qU= zGH#iHT%q9QB0MOd4QIYzbvsR*%qOyjPsH80FhB(lE#!$d^xW9A$lfM%uAh-tJ-en_ zFe6!Z0DfRw(hQ)&?j)blIhVJ=NzLE)5`p?ET@;jq3P+a>{wG@Bga28xpQc(|Ij9Jt z{wgFRy__(=s}mjQ5eGMGGMh^K;sn~wlz;U50VYz|UK==U=3N+UYA;OC#Cygb;P~aT z|8~!N`{VF%ziN2#9qVzl5Dlpm?*+D9yhkR)zjx!g{qXCDrpMvu532;+DZaFzqOa9b z&yK#x5v5Yezqd{~vk39iG1IfcD*Hgapvb54*{vpCb{7iFl4RVhF6o|0$5Yg=B3Rm* zjR!mzaBB@N(rC9qeFFQWkQ&Tw2;?@OlTvs(7o0}mhkR+6SYH7pk#3gViIS8PUU|A_ zAxbL36?a~vn-0BgZnZ^~u`$oxQ}@u;aSq^v#?0e1>EN}L{Qlo-BgK1JFn$?CFW&pU zKzF(2d~cGhhP3i@&t-lG-MX@yE{U~hY;E_w?Zm~N@_9lB$#Wlc@V$RK1i8cg8?>7T zq|8m$Lc)EX_F78fQ@a}N_uuo9+$<@@o0;FL9OXA&Ht{d7|07(2_xHc|JZC3(`!bGd z(CS4s8c+5k&UY;c;yf7dJ)ea&r1yfc+RC~)x1l|Er43p40kv+Hx7(=X1cgz)4k~Mz zs2N2AXmqP#=DwgcVFXBSgm!%VB~%;*%^(X-)0EehJo!m=yS>Ds*1jM|KNP!txFF!U ziw6TuH-67ll&pF2U~@pJqEPyXqcf7P>L6@c?YLnwCd`PsZe>rs;uC~0F0L|Jj({wM z?bRK#t!L}-N9{(aDK#ZhO$AL#n>akN0T5#GrcWo!kW)7v%vS}1U|RShaLd}Z@5nA$ z5EL26)uIqkQB*@2$Ql()m?krW!OX>m<9=RMW%A>#tu5kAF-#DLY`0RJ!#I!`TYh8e zSPGki88QtpeX%h&*G*qw%(gb5e+Wt6P#Ghw7Xpv#t9`wYrvXsEj_TkpB=0)8&FZw-hD0feer~=YEW4}>t&GVJ?oC!ZdN*0@tf9RlKSsrsO4V z($zT#qF8J+i=qf)Q7kqaMNt3&xb9B(#ka13{b3cbCVlxK7&BdxWl3k^*&h%@NyAwA zunkzFuBYgdY2=@el*3ZTgw}7VlxKZ^wp@8>C9|Uw{=U!W4O7w;&mkKA >?gxf3W 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 literal 0 HcmV?d00001 diff --git a/webfonts/fa-v4compatibility.ttf b/webfonts/fa-v4compatibility.ttf new file mode 100644 index 0000000000000000000000000000000000000000..32c6f0c2702e5589bc3f22f7785b98b520f80571 GIT binary patch literal 10832 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 aSudfzP+GMumRG!Rb}QI&GL;5w^Zx)-`5fW^ literal 0 HcmV?d00001 diff --git a/webfonts/fa-v4compatibility.woff2 b/webfonts/fa-v4compatibility.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..59b20fe1bd7095888ca979e848c4632c01b770a4 GIT binary patch literal 4792 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 SW@ke+i9ap#|HA+S0001Ss214( literal 0 HcmV?d00001 diff --git a/workflow-cli.txt b/workflow-cli.txt new file mode 100644 index 000000000..e72fc12fb --- /dev/null +++ b/workflow-cli.txt @@ -0,0 +1,8 @@ +https://drycc-mirrors.drycc.cc/drycc/workflow-cli/releases/download/v1.9.0/drycc-v1.9.0-darwin-amd64 +https://drycc-mirrors.drycc.cc/drycc/workflow-cli/releases/download/v1.9.0/drycc-v1.9.0-darwin-arm64 +https://drycc-mirrors.drycc.cc/drycc/workflow-cli/releases/download/v1.9.0/drycc-v1.9.0-linux-386 +https://drycc-mirrors.drycc.cc/drycc/workflow-cli/releases/download/v1.9.0/drycc-v1.9.0-linux-amd64 +https://drycc-mirrors.drycc.cc/drycc/workflow-cli/releases/download/v1.9.0/drycc-v1.9.0-linux-arm +https://drycc-mirrors.drycc.cc/drycc/workflow-cli/releases/download/v1.9.0/drycc-v1.9.0-linux-arm64 +https://drycc-mirrors.drycc.cc/drycc/workflow-cli/releases/download/v1.9.0/drycc-v1.9.0-windows-386 +https://drycc-mirrors.drycc.cc/drycc/workflow-cli/releases/download/v1.9.0/drycc-v1.9.0-windows-amd64

w%MutBr+gZk(B!0n3VCbP%7MOSd4BsSoVD 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 literal 0 HcmV?d00001 diff --git a/webfonts/fa-brands-400.woff2 b/webfonts/fa-brands-400.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..720ed5788cc071fbb95ecab825cc5624d2cd3bca GIT binary patch literal 117400 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

+ +