git.iko.soy/typeable/octopod
on master help sign in
414 files changed+19602−24036
since splitsnapshots
unifiedsplit
.github/actions/common_setup/action.yaml+40 .github/actions/push_docker_images/action.yaml+26 .github/workflows/build.yaml+152 .github/workflows/build_docker.yaml−64 .github/workflows/build_octo_cli.yaml−69 .github/workflows/check_documentation.yaml+1−1 .gitignore+3 .hlint.yaml+55 .nova/Configuration.json+5 .stylish-haskell.yaml−319 .vscode/settings.json+8−2 Caddyfile−27 CaddyfileGhcid−25 Development_guide.md+5−12 Makefile+18−29 README.md+103−14 Release_checklist.md+6−16 build.sh−66 cabal.project+35 charts/cert-control/.helmignore−22 charts/cert-control/Chart.yaml−5 charts/cert-control/templates/cert-control-clusterrole.yaml−8 charts/cert-control/templates/cert-control-rolebinding.yaml−13 charts/cert-control/values.yaml−3 charts/helm-access/.helmignore−22 charts/helm-access/Chart.yaml−5 charts/helm-access/templates/helm-clusterrole.yaml−11 charts/helm-access/templates/helm-clusterrolebinding.yaml−12 charts/helm-access/values.yaml−2 charts/kubedog-access/Chart.yaml−5 charts/kubedog-access/templates/kubedog-clusterrole.yaml−17 charts/kubedog-access/templates/kubedog-clusterrolebinding.yaml−12 charts/kubedog-access/values.yaml−2 charts/octopod-infra/.helmignore−22 charts/octopod-infra/Chart.yaml−5 charts/octopod-infra/templates/postgres-configmap.yaml−11 charts/octopod-infra/templates/postgres-service.yaml−14 charts/octopod-infra/templates/postgres-statefulset.yaml−51 charts/octopod-infra/values.yaml−20 charts/octopod/.gitignore+1 charts/octopod/.helmignore+1 charts/octopod/Chart.lock+6 charts/octopod/Chart.yaml+19−4 charts/octopod/README.md+182 charts/octopod/index.yaml+37 charts/octopod/templates/NOTES.txt+12 charts/octopod/templates/_helpers.tpl+144−5 charts/octopod/templates/clean-archive-cronjob.yaml−47 charts/octopod/templates/cli-secret.yaml+11 charts/octopod/templates/deployment.yaml+240 charts/octopod/templates/ingress-app.yaml+53 charts/octopod/templates/ingress-powerapp.yaml+47 charts/octopod/templates/ingress-ui.yaml+47 charts/octopod/templates/ingress-ws.yaml+47 charts/octopod/templates/nginx-configmap.yaml+43 charts/octopod/templates/octopod-app-ingress.yaml−32 charts/octopod/templates/octopod-configmap.yaml+24−15 charts/octopod/templates/octopod-deployment.yaml−153 charts/octopod/templates/octopod-ingress.yaml−34 charts/octopod/templates/octopod-issuer.yaml−18 charts/octopod/templates/octopod-migration-job.yaml−75 charts/octopod/templates/octopod-nginx-configmap.yaml−20 charts/octopod/templates/octopod-power-app-ingress.yaml−25 charts/octopod/templates/octopod-service.yaml−23 charts/octopod/templates/octopod-ws-ingress.yaml−26 charts/octopod/templates/rbac.yaml+30 charts/octopod/templates/service.yaml+16 charts/octopod/templates/serviceaccount.yaml+12 charts/octopod/values.yaml+119−38 charts/pvc-control/.helmignore−22 charts/pvc-control/Chart.yaml−5 charts/pvc-control/templates/pvc-control-clusterrole.yaml−8 charts/pvc-control/templates/pvc-control-rolebinding.yaml−13 charts/pvc-control/values.yaml−3 default.nix+76−31 dev/config.json−5 dev/default.nix+220 dev/dev_backend.sh−29 dev/echo.sh−4 dev/info.sh−6 docs/Makefile−9 docs/README.md+6−6 docs/diagrams/images/app-architecture.png docs/diagrams/images/technical-architecture-archive-via-cli.png docs/diagrams/images/technical-architecture-archive-via-ui.png docs/diagrams/images/technical-architecture-archive.png docs/diagrams/images/technical-architecture-cleanup-via-cli.png docs/diagrams/images/technical-architecture-cleanup-via-ui.png docs/diagrams/images/technical-architecture-cleanup.png docs/diagrams/images/technical-architecture-create-via-cli.png docs/diagrams/images/technical-architecture-create-via-ui.png docs/diagrams/images/technical-architecture-create.png docs/diagrams/images/technical-architecture-deployment-states-fsm.png docs/diagrams/images/technical-architecture-restore-via-cli.png docs/diagrams/images/technical-architecture-restore-via-ui.png docs/diagrams/images/technical-architecture-restore.png docs/diagrams/images/technical-architecture-update-via-cli.png docs/diagrams/images/technical-architecture-update-via-ui.png docs/diagrams/images/technical-architecture-update.png docs/diagrams/src/technical-architecture-archive-via-cli.mmd−37 docs/diagrams/src/technical-architecture-archive-via-ui.mmd−36 docs/diagrams/src/technical-architecture-archive.mmd+31 docs/diagrams/src/technical-architecture-cleanup-via-cli.mmd−20 docs/diagrams/src/technical-architecture-cleanup-via-ui.mmd−19 docs/diagrams/src/technical-architecture-cleanup.mmd+14 docs/diagrams/src/technical-architecture-create-via-cli.mmd−41 docs/diagrams/src/technical-architecture-create-via-ui.mmd−40 docs/diagrams/src/technical-architecture-create.mmd+41 docs/diagrams/src/technical-architecture-deployment-states-fsm.mmd+1 docs/diagrams/src/technical-architecture-restore-via-cli.mmd−41 docs/diagrams/src/technical-architecture-restore-via-ui.mmd−40 docs/diagrams/src/technical-architecture-restore.mmd+42 docs/diagrams/src/technical-architecture-update-via-cli.mmd−41 docs/diagrams/src/technical-architecture-update-via-ui.mmd−40 docs/diagrams/src/technical-architecture-update.mmd+46 docs/en/Control_scripts.md+155−132 docs/en/Helm-based_deployment_guide.md+54−133 docs/en/Integration.md+9−8 docs/en/Octo_user_guide.md+31−76 docs/en/Octopod_deployment_guide.md+45−364 docs/en/Overview.md+12−22 docs/en/PM_case_study.md+9−1 docs/en/README.md+1−1 docs/en/Security_model.md+16−78 docs/en/Tech_case_study.md+9−16 docs/en/Technical_architecture.md+18−169 docs/images/dev2.png docs/images/first.png docs/images/hello-octopod-1.png docs/images/hello-octopod-2.png docs/images/hello-octopod-3.png docs/images/octopod_app_keys_list.png docs/images/octopod_archive.png docs/images/octopod_blank.png docs/images/octopod_deployment_blank.png docs/images/octopod_deployment_filled.png docs/images/octopod_filled.png docs/images/octopod_in_octopod_deployment.png docs/images/second.png docs/images/wordpress_blank.png docs/ru/Control_scripts.md−209 docs/ru/Helm-based_deployment_guide.md−165 docs/ru/Octo_user_guide.md−173 docs/ru/Octopod_deployment_with_K8S.md−275 docs/ru/README.md−8 docs/ru/Security_model.md−120 docs/ru/Technical_architecture.md−275 examples/helm-based-control-scripts/Cargo.lock−1244 examples/helm-based-control-scripts/Cargo.toml−46 examples/helm-based-control-scripts/README.md−9 examples/helm-based-control-scripts/docker/Dockerfile−29 examples/helm-based-control-scripts/src/bin/archive.rs−59 examples/helm-based-control-scripts/src/bin/archive_check.rs−59 examples/helm-based-control-scripts/src/bin/check.rs−78 examples/helm-based-control-scripts/src/bin/cleanup.rs−50 examples/helm-based-control-scripts/src/bin/create.rs−237 examples/helm-based-control-scripts/src/bin/info.rs−52 examples/helm-based-control-scripts/src/bin/init.rs−9 examples/helm-based-control-scripts/src/bin/tag_check.rs−91 examples/web-app-v2/.gitignore−1 examples/web-app-v2/Cargo.lock−1935 examples/web-app-v2/Cargo.toml−12 examples/web-app-v2/README.md−5 examples/web-app-v2/charts/web-app/.helmignore−22 examples/web-app-v2/charts/web-app/Chart.yaml−5 examples/web-app-v2/charts/web-app/templates/deployment.yaml−48 examples/web-app-v2/charts/web-app/templates/ingress.yaml−26 examples/web-app-v2/charts/web-app/templates/issuer.yaml−18 examples/web-app-v2/charts/web-app/templates/service.yaml−14 examples/web-app-v2/charts/web-app/values.yaml−8 examples/web-app-v2/docker/Dockerfile−22 examples/web-app-v2/src/main.rs−43 examples/web-app-v2/templates/index.html−16 examples/web-app/.gitignore−1 examples/web-app/Cargo.toml−12 examples/web-app/README.md−5 examples/web-app/charts/web-app/.helmignore−22 examples/web-app/charts/web-app/Chart.yaml−5 examples/web-app/charts/web-app/templates/deployment.yaml−48 examples/web-app/charts/web-app/templates/ingress.yaml−26 examples/web-app/charts/web-app/templates/issuer.yaml−18 examples/web-app/charts/web-app/templates/service.yaml−14 examples/web-app/charts/web-app/values.yaml−8 examples/web-app/docker/Dockerfile−22 examples/web-app/src/main.rs−43 examples/web-app/templates/index.html−14 fourmolu.yaml+8 examples/helm-based-control-scripts/.gitignore → helm-control-scripts/.gitignore examples/web-app/Cargo.lock → helm-control-scripts/Cargo.lock+1203−980 helm-control-scripts/Cargo.toml+82 helm-control-scripts/Dockerfile+26 helm-control-scripts/README.md+70 helm-control-scripts/src/app_keys.rs+31 helm-control-scripts/src/app_overrides.rs+11 helm-control-scripts/src/archive.rs+53 helm-control-scripts/src/archive_check.rs+53 helm-control-scripts/src/check.rs+53 helm-control-scripts/src/cleanup.rs+71 helm-control-scripts/src/config_check.rs+65 helm-control-scripts/src/create_update.rs+41 helm-control-scripts/src/deployment_keys.rs+11 helm-control-scripts/src/deployment_overrides.rs+11 helm-control-scripts/src/info.rs+47 helm-control-scripts/src/init.rs+22 helm-control-scripts/src/lib.rs+1061 helm-control-scripts/src/unarchive.rs+53 img/demo.gif img/logo.svg+1 img/release_workflow.png img/typeable.png img/typeable_logo.svg+1 migrations/deploy/add_detailed_failures.sql+14 migrations/deploy/migrate_2.0.sql+62 migrations/deploy/move_tag_to_overrides.sql+18 migrations/deploy/remove_archived_column.sql+9 migrations/revert/add_detailed_failures.sql+9 migrations/revert/migrate_2.0.sql+12 migrations/revert/move_tag_to_overrides.sql+62 migrations/revert/remove_archived_column.sql+8 migrations/sqitch.plan+4 migrations/verify/add_detailed_failures.sql+10 migrations/verify/migrate_2.0.sql+37 migrations/verify/move_tag_to_overrides.sql+7 migrations/verify/remove_archived_column.sql+7 nix/ci.nix+6 nix/default.nix+90−113 nix/haskell-language-server-overrides.nix−267 nix/octo.nix−35 nix/octopod-overrides.nix−103 nix/sources.json+27−63 nix/sources.nix+4−1 octo-cli/Setup.hs+1 octo-cli/octo-cli.cabal+23−9 octo-cli/src/Main.hs+2−2 octo-cli/src/Octopod/CLI.hs+254−218 octo-cli/src/Octopod/CLI/Args.hs+122−138 octo-cli/src/Octopod/CLI/TLS.hs−39 octo-cli/src/Octopod/PowerAPI/Auth/Client.hs+28 octo-cli/src/Text/Layout/Table/Extras.hs+11−9 octopod-api/Setup.hs+1 octopod-api/octopod-api.cabal+15−3 octopod-api/src/Octopod/API.hs+56−39 octopod-api/src/Octopod/API/WebSocket.hs+8−3 octopod-api/src/Octopod/PowerAPI.hs+53−45 octopod-backend/Setup.hs+2−1 octopod-backend/app/Main.hs+7−3 octopod-backend/octopod-backend.cabal+62−108 octopod-backend/src/Control/CacheMap.hs+89 octopod-backend/src/Control/Octopod/DeploymentLock.hs+50 octopod-backend/src/Octopod/PowerAPI/Auth/Server.hs+23 octopod-backend/src/Octopod/Schema.hs+97 octopod-backend/src/Octopod/Server.hs+1120−1024 octopod-backend/src/Octopod/Server/Args.hs+48−59 octopod-backend/src/Octopod/Server/ControlScriptUtils.hs+256−22 octopod-backend/src/Octopod/Server/Logger.hs−34 octopod-backend/src/Octopod/Server/Logging.hs+121 octopod-backend/src/Octopod/Server/Posix.hs+22−17 octopod-backend/src/Orphans.hs+41−10 octopod-backend/src/TLS.hs−68 octopod-backend/src/Types.hs+50−63 octopod-backend/test/Spec.hs−2 octopod-common/Setup.hs+2−1 octopod-common/octopod-common.cabal+42−3 octopod-common/src/Common/Orphans.hs+20 octopod-common/src/Common/Types.hs+336−210 octopod-common/src/Common/Utils.hs+27−18 octopod-common/src/Common/Validation.hs+16−16 octopod-common/src/Control/Searchable.hs+66 octopod-common/src/Data/ConfigTree.hs+165 octopod-css/default.nix+45 octopod-css/development/layouts/index.html+321−174 octopod-css/development/layouts/staging.html+687−168 octopod-css/development/markups/_action.html+2−1 octopod-css/development/markups/_bar.html+2−1 octopod-css/development/markups/_break.html+2−1 octopod-css/development/markups/_button.html+2−1 octopod-css/development/markups/_collapse.html+277 octopod-css/development/markups/_dash.html+3−2 octopod-css/development/markups/_drop.html+2−1 octopod-css/development/markups/_expander.html+2−1 octopod-css/development/markups/_external.html+2−1 octopod-css/development/markups/_input.html+36−1 octopod-css/development/markups/_keys-and-values.html+373 octopod-css/development/markups/_listing.html+2−1 octopod-css/development/markups/_loading.html+2−1 octopod-css/development/markups/_notification.html+2−1 octopod-css/development/markups/_null.html+2−1 octopod-css/development/markups/_spot.html+2−1 octopod-css/development/markups/_status.html+2−1 octopod-css/development/markups/_title.html+2−1 octopod-css/development/scripts/_collapse.js+18 octopod-css/development/styles/_button.css+35 octopod-css/development/styles/_collapse.css+95 octopod-css/development/styles/_deployment.css+4 octopod-css/development/styles/_editable-row.css+49 octopod-css/development/styles/_has-changes.css+3 octopod-css/development/styles/_input.css+80−2 octopod-css/development/styles/_key-custom-edited.css+4 octopod-css/development/styles/_key-default-edited.css+5 octopod-css/development/styles/_key-default-pristine.css+4 octopod-css/development/styles/_key-deleted.css+6 octopod-css/development/styles/_listing.css+73−1 octopod-css/development/styles/_overrides.css+7−20 octopod-css/development/styles/_padded.css+3 octopod-css/development/styles/_root.css+2 octopod-css/development/styles/_row.css+3 octopod-css/development/styles/_spot.css+11 octopod-css/development/styles/_table.css+21−26 octopod-css/development/styles/_value-deleted.css+5 octopod-css/development/styles/_value-edited.css+4 octopod-css/development/styles/_value-pristine.css+3 octopod-css/development/styles/_value-unknown.css+12 octopod-css/development/styles/style.css+15 octopod-css/development/vectors/button-loader.svg+5 octopod-css/development/vectors/collapse-project.svg+3 octopod-css/development/vectors/spot-loader.svg+3 octopod-css/development/vectors/spot-undo.svg+3 octopod-css/favicons/android-icon-144x144.png octopod-css/favicons/android-icon-192x192.png octopod-css/favicons/android-icon-36x36.png octopod-css/favicons/android-icon-48x48.png octopod-css/favicons/android-icon-72x72.png octopod-css/favicons/android-icon-96x96.png octopod-css/favicons/apple-icon-114x114.png octopod-css/favicons/apple-icon-120x120.png octopod-css/favicons/apple-icon-144x144.png octopod-css/favicons/apple-icon-152x152.png octopod-css/favicons/apple-icon-180x180.png octopod-css/favicons/apple-icon-57x57.png octopod-css/favicons/apple-icon-60x60.png octopod-css/favicons/apple-icon-72x72.png octopod-css/favicons/apple-icon-76x76.png octopod-css/favicons/apple-icon-precomposed.png octopod-css/favicons/apple-icon.png octopod-css/favicons/favicon-16x16.png octopod-css/favicons/favicon-32x32.png octopod-css/favicons/favicon-96x96.png octopod-css/favicons/favicon.ico octopod-css/favicons/ms-icon-144x144.png octopod-css/favicons/ms-icon-150x150.png octopod-css/favicons/ms-icon-310x310.png octopod-css/favicons/ms-icon-70x70.png octopod-css/package-lock.json−6159 octopod-css/package.json+3−2 octopod-css/production/images/dialog-delete.png octopod-css/production/images/dialog-delete@2x.png octopod-css/production/images/null-data.png octopod-css/production/images/null-data@2x.png octopod-css/production/images/null-search.png octopod-css/production/images/null-search@2x.png octopod-css/production/layouts/index.html−888 octopod-css/production/layouts/staging.html−713 octopod-css/production/layouts/standalone-loading.html−46 octopod-css/production/markups/_action.html−112 octopod-css/production/markups/_bar.html−61 octopod-css/production/markups/_break.html−85 octopod-css/production/markups/_button.html−137 octopod-css/production/markups/_dash.html−130 octopod-css/production/markups/_drop.html−112 octopod-css/production/markups/_expander.html−96 octopod-css/production/markups/_external.html−61 octopod-css/production/markups/_input.html−111 octopod-css/production/markups/_listing.html−100 octopod-css/production/markups/_loading.html−136 octopod-css/production/markups/_notification.html−88 octopod-css/production/markups/_null.html−81 octopod-css/production/markups/_spot.html−61 octopod-css/production/markups/_status.html−83 octopod-css/production/markups/_title.html−60 octopod-css/production/scripts/_classic-popup.js−92 octopod-css/production/scripts/_data.js−7 octopod-css/production/scripts/_drop.js−26 octopod-css/production/scripts/_expander.js−8 octopod-css/production/scripts/_popup.js−35 octopod-css/production/scripts/_sort.js−16 octopod-css/production/styles/style.css−1 octopod-css/production/vendors/jquery/jquery-3.2.1.min.js−4 octopod-css/production/vendors/outline/index.html−67 octopod-css/production/vendors/outline/outline.js−37 octopod-css/yarn.lock+4594 octopod-frontend/Setup.hs+2−1 octopod-frontend/index.html+13 octopod-frontend/octopod-frontend.cabal+57−8 octopod-frontend/src/Data/Text/Search.hs+147 octopod-frontend/src/Data/UniqMap.hs+55 octopod-frontend/src/Data/WorkingOverrides.hs+138 octopod-frontend/src/Frontend/API.hs+145−106 octopod-frontend/src/Frontend/Classes.hs+18 octopod-frontend/src/Frontend/GHCJS.hs+46−36 octopod-frontend/src/Frontend/Route.hs+37−37 octopod-frontend/src/Frontend/UIKit.hs+555 octopod-frontend/src/Frontend/UIKit/Button/Action.hs+63 octopod-frontend/src/Frontend/UIKit/Button/Common.hs+101 octopod-frontend/src/Frontend/UIKit/Button/Dash.hs+71 octopod-frontend/src/Frontend/UIKit/Button/Expander.hs+86 octopod-frontend/src/Frontend/UIKit/Button/Large.hs+96 octopod-frontend/src/Frontend/UIKit/Button/Sort.hs+58 octopod-frontend/src/Frontend/UIKit/Button/Static.hs+84 octopod-frontend/src/Frontend/UIKit/Button/Tree.hs+84 octopod-frontend/src/Frontend/Utils.hs+476−424 octopod-frontend/src/Main.hs+210−134 octopod-frontend/src/Page/ClassicPopup.hs+64−48 octopod-frontend/src/Page/Deployment.hs+267−238 octopod-frontend/src/Page/Deployments.hs+419−373 octopod-frontend/src/Page/Elements/Links.hs+30−18 octopod-frontend/src/Page/Popup/EditDeployment.hs+95−178 octopod-frontend/src/Page/Popup/NewDeployment.hs+113−140 octopod-frontend/src/Reflex/Dom/AsyncEvent.hs+30 octopod-frontend/src/Reflex/Dom/Renderable.hs+35 octopod-frontend/src/Reflex/MultiEventWriter/Class.hs+11−10 octopod-frontend/src/Servant/Reflex/Extra.hs+27−9 octopod_local_install.sh+131 shell.nix+11−1 stack.yaml+4−8
.github/actions/common_setup/action.yamlnew file+40
@@ -0,0 +1,40 @@
1+name: "Common setup"
2+description: "Common setup steps"
3+inputs:
4+ authToken:
5+ description: "Cachix auth token"
6+ required: true
7+runs:
8+ using: "composite"
9+ steps:
10+ - name: Install skopeo
11+ shell: bash
12+ run: |
13+ sudo apt-get -y update
14+ sudo apt-get -y install skopeo
15+
16+ - name: Increase swap
17+ shell: bash
18+ run: |
19+ free -h
20+
21+ sudo swapoff /mnt/swapfile
22+ sudo fallocate -l 12G /mnt/swapfile
23+ sudo mkswap /mnt/swapfile
24+ sudo swapon /mnt/swapfile
25+
26+ free -h
27+
28+ - name: Install Nix
29+ uses: cachix/install-nix-action@v16
30+ with:
31+ extra_nix_config: |
32+ trusted-public-keys = hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
33+ substituters = https://hydra.iohk.io https://cache.nixos.org/
34+ system-features = kvm
35+
36+ - name: Login to Cachix
37+ uses: cachix/cachix-action@v10
38+ with:
39+ name: typeable
40+ authToken: ${{ inputs.authToken }}
.github/actions/push_docker_images/action.yamlnew file+26
@@ -0,0 +1,26 @@
1+name: "Push Docker Images"
2+description: "Push Docker Images"
3+inputs:
4+ tag:
5+ description: "The docker image tag to push."
6+ required: true
7+ docker_username:
8+ description: "The Docker Hub username"
9+ required: true
10+ docker_password:
11+ description: "The Docker Hub password"
12+ required: true
13+runs:
14+ using: "composite"
15+ steps:
16+ - name: Login to DockerHub
17+ uses: docker/login-action@v1.10.0
18+ with:
19+ username: ${{ inputs.docker_username }}
20+ password: ${{ inputs.docker_password }}
21+
22+ - name: Push Docker Images to DockerHub
23+ shell: bash
24+ run: |
25+ skopeo copy docker-archive:$(nix-build ./nix -j auto -A octopod-server-container) docker://typeable/octopod:${{ inputs.tag }}
26+ skopeo copy docker-archive:$(nix-build ./nix -j auto -A octo-cli-container) docker://typeable/octo:${{ inputs.tag }}
.github/workflows/build.yamlnew file+152
@@ -0,0 +1,152 @@
1+name: Build and release
2+on:
3+ push:
4+ branches:
5+ - master
6+ - develop
7+ - staging
8+ pull_request:
9+ branches:
10+ - master
11+ - develop
12+ - staging
13+ workflow_dispatch:
14+ inputs:
15+ release:
16+ description: Release the new version?
17+ required: false
18+ default: "true"
19+ version:
20+ description: The version to release
21+ required: true
22+
23+jobs:
24+ check-formatting:
25+ name: Check Haskell formatting
26+ runs-on: ubuntu-latest
27+ steps:
28+ - uses: actions/checkout@v2
29+ - uses: cachix/install-nix-action@v12
30+ - name: Run fourmolu
31+ run: |
32+ nix-shell nix/ci.nix -j auto --run "git ls-files '*.hs' | xargs fourmolu -m inplace --ghc-opt -XRecursiveDo --ghc-opt -XTypeApplications --ghc-opt -XPatternSynonyms"
33+ git diff --exit-code
34+
35+ octo-macOS:
36+ name: macOS octo CLI Release (Stack)
37+ runs-on: macos-latest
38+ steps:
39+ - uses: actions/checkout@v2
40+ - name: Cache stack dependencies
41+ uses: actions/cache@v2
42+ with:
43+ path: ~/.stack
44+ key: octo-cli-stack-${{ runner.os }}
45+ # TODO: Remove this step once https://github.com/actions/cache/issues/445 is resolved.
46+ - name: Fix macOS cache bug
47+ run: rm -rf ~/.stack/setup-exe-cache
48+ - name: Build
49+ run: stack build octo-cli --local-bin-path out --copy-bins
50+ - uses: actions/upload-artifact@v2
51+ with:
52+ name: octo-cli-macos
53+ path: out/octo
54+ octo-linux:
55+ name: Linux octo CLI Release (Nix)
56+ runs-on: ubuntu-latest
57+ timeout-minutes: 600
58+ steps:
59+ - uses: actions/checkout@v2
60+ - name: Common setup
61+ uses: ./.github/actions/common_setup
62+ with:
63+ authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
64+ - name: Build
65+ run: nix-build -A projectCross.musl64.hsPkgs.octo-cli.components.exes.octo --arg prod true -j auto
66+ - uses: actions/upload-artifact@v2
67+ with:
68+ name: octo-cli-linux
69+ path: result/bin/octo
70+ docker-images:
71+ name: Docker Images
72+ runs-on: ubuntu-latest
73+ timeout-minutes: 600
74+ steps:
75+ - uses: actions/checkout@v2
76+
77+ - name: Common setup
78+ uses: ./.github/actions/common_setup
79+ with:
80+ authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
81+
82+ - name: Build Docker Images
83+ run: nix-build ./nix -j auto
84+
85+ - name: Push Nightly Docker Images to DockerHub
86+ if: github.ref == 'refs/heads/master' && github.event_name == 'push'
87+ uses: ./.github/actions/push_docker_images
88+ with:
89+ tag: nightly
90+ docker_username: ${{ secrets.DOCKERHUB_USERNAME }}
91+ docker_password: ${{ secrets.DOCKERHUB_TOKEN }}
92+
93+ - name: Rename Docker image archives
94+ run: |
95+ cp $(nix-build ./nix -j auto -A octo-cli-container) octo-cli-image.tar.gz
96+ cp $(nix-build ./nix -j auto -A octopod-server-container) octopod-server-image.tar.gz
97+
98+ - name: Upload octo CLI Image
99+ uses: actions/upload-artifact@v2
100+ with:
101+ name: octo-cli-image
102+ path: octo-cli-image.tar.gz
103+
104+ - name: Upload Octopod Server Image
105+ uses: actions/upload-artifact@v2
106+ with:
107+ name: octopod-server-image
108+ path: octopod-server-image.tar.gz
109+ release:
110+ name: Release
111+ if: github.event_name == 'workflow_dispatch' && github.event.inputs.release == 'true'
112+ needs: [octo-macOS, octo-linux, docker-images]
113+ runs-on: "ubuntu-latest"
114+ steps:
115+ - uses: actions/checkout@v2
116+ - name: Common setup
117+ uses: ./.github/actions/common_setup
118+ with:
119+ authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
120+ - name: Push Docker Release Images to DockerHub
121+ uses: ./.github/actions/push_docker_images
122+ with:
123+ tag: ${{ github.event.inputs.version }}
124+ docker_username: ${{ secrets.DOCKERHUB_USERNAME }}
125+ docker_password: ${{ secrets.DOCKERHUB_TOKEN }}
126+
127+ - name: Push Docker latest Images to DockerHub
128+ uses: ./.github/actions/push_docker_images
129+ with:
130+ tag: latest
131+ docker_username: ${{ secrets.DOCKERHUB_USERNAME }}
132+ docker_password: ${{ secrets.DOCKERHUB_TOKEN }}
133+
134+ - uses: actions/download-artifact@v2
135+ - name: Zip and move
136+ run: |
137+ chmod +x octo-cli-macos/octo
138+ zip octo-cli-macos octo-cli-macos/octo
139+ chmod +x octo-cli-linux/octo
140+ zip octo-cli-linux octo-cli-linux/octo
141+
142+ mv octo-cli-image/* .
143+ mv octopod-server-image/* .
144+ - uses: "marvinpinto/action-automatic-releases@latest"
145+ with:
146+ repo_token: "${{ secrets.GITHUB_TOKEN }}"
147+ automatic_release_tag: "latest"
148+ prerelease: false
149+ title: "${{ github.event.inputs.version }}"
150+ files: |
151+ *.zip
152+ *.tar.gz
.github/workflows/build_docker.yamldeleted−64
@@ -1,64 +0,0 @@
1−name: Octopod Docker Image
2−on:
3− push:
4− branches:
5− - master
6− - develop
7− pull_request:
8− branches:
9− - master
10− - develop
11−
12−jobs:
13− build:
14− name: build-docker
15− runs-on: ubuntu-latest
16− timeout-minutes: 600
17− steps:
18− - uses: actions/checkout@v2
19− with:
20− repo: Aviora/dm
21−
22− - name: Install Nix
23− uses: cachix/install-nix-action@v12
24−
25− - name: Login to Cachix
26− uses: cachix/cachix-action@v8
27− with:
28− name: octopod
29− signingKey: ${{ secrets.CACHIX_SIGNING_KEY }}
30−
31− - name: Build Docker Images
32− run: |
33− # enable required features (see https://github.com/cachix/install-nix-action/issues/19)
34− mkdir -p ~/.config/nix
35− echo "system-features = kvm" >> ~/.config/nix/nix.conf
36−
37− # build docker images
38− ./build.sh build
39−
40− - name: Login to DockerHub
41− id: login-docker-hub
42− if: github.ref == 'refs/heads/master'
43− uses: docker/login-action@v1
44− with:
45− username: ${{ secrets.DOCKERHUB_USERNAME }}
46− password: ${{ secrets.DOCKERHUB_TOKEN }}
47−
48− - name: Push Docker Images to DockerHub
49− if: github.ref == 'refs/heads/master'
50− run: |
51− # push docker images to DockerHub
52− image_name=`cat octo-docker | docker load | awk '{print $3}'`
53− docker tag $image_name typeable/octo:latest
54− docker push typeable/octo:latest
55−
56− image_name=`cat octopod-server-docker | docker load | awk '{print $3}'`
57− docker tag $image_name typeable/octopod:latest
58− docker push typeable/octopod:latest
59−
60− - name: Clean up
61− if: always()
62− continue-on-error: true
63− run: |
64− docker logout ${{ steps.login-docker-hub.outputs.registry }}
.github/workflows/build_octo_cli.yamldeleted−69
@@ -1,69 +0,0 @@
1−name: octo CLI
2−on:
3− push:
4− branches:
5− - master
6− - develop
7− pull_request:
8− branches:
9− - master
10− - develop
11−
12−jobs:
13− macOS:
14− name: Create macOS octo CLI Release (Stack)
15− runs-on: macos-latest
16− steps:
17− - uses: actions/checkout@v1
18− - name: Cache stack dependencies
19− uses: actions/cache@v2
20− with:
21− path: ~/.stack
22− key: octo-cli-stack-${{ runner.os }}
23− # TODO: Remove this step once https://github.com/actions/cache/issues/445 is resolved.
24− - name: Fix macOS cache bug
25− run: rm -rf ~/.stack/setup-exe-cache
26− - name: Build
27− run: stack build octo-cli --local-bin-path out --copy-bins
28− - uses: actions/upload-artifact@v2
29− with:
30− name: octo-cli-macos
31− path: out/octo
32− linux:
33− name: Create Linux octo CLI Release (Nix)
34− runs-on: ubuntu-latest
35− timeout-minutes: 600
36− steps:
37− - uses: actions/checkout@v1
38− - uses: cachix/install-nix-action@v12
39− - uses: cachix/cachix-action@v8
40− with:
41− name: octopod
42− signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}"
43− - name: Build
44− run: nix-build nix/octo.nix
45− - uses: actions/upload-artifact@v2
46− with:
47− name: octo-cli-linux
48− path: result/bin/octo
49− release:
50− name: "Release"
51− if: github.ref == 'refs/heads/master'
52− runs-on: "ubuntu-latest"
53− needs: [macOS, linux]
54− steps:
55− - uses: actions/download-artifact@v2
56− - name: Zip
57− run: |
58− chmod +x octo-cli-macos/octo
59− zip octo-cli-macos octo-cli-macos/octo
60− chmod +x octo-cli-linux/octo
61− zip octo-cli-linux octo-cli-linux/octo
62− - uses: "marvinpinto/action-automatic-releases@latest"
63− with:
64− repo_token: "${{ secrets.GITHUB_TOKEN }}"
65− automatic_release_tag: "latest"
66− prerelease: true
67− title: "Pre-Release"
68− files: |
69− *.zip
.github/workflows/check_documentation.yaml+1−1
@@ -21,4 +21,4 @@ jobs:
2121
2222 - name: Run linter
2323 run: |
24− yarn run remark -f -u validate-links -u remark-lint-mdash-style -u remark-lint-final-newline -u remark-lint-list-item-bullet-indent -u remark-lint-no-auto-link-without-protocol -u remark-lint-no-blockquote-without-marker -u remark-lint-ordered-list-marker-style -u remark-lint-no-literal-urls -u remark-lint-hard-break-spaces -u remark-lint-no-duplicate-definitions -u remark-lint-no-heading-content-indent -u remark-lint-no-inline-padding -u remark-lint-no-shortcut-reference-image -u remark-lint-no-shortcut-reference-link -u remark-lint-no-undefined-references -u remark-lint-no-unused-definitions -u remark-lint-no-dead-urls docs README.md
24+ yarn run remark -f -u validate-links -u remark-lint-mdash-style -u remark-lint-final-newline -u remark-lint-list-item-bullet-indent -u remark-lint-no-blockquote-without-marker -u remark-lint-ordered-list-marker-style -u remark-lint-no-literal-urls -u remark-lint-hard-break-spaces -u remark-lint-no-duplicate-definitions -u remark-lint-no-heading-content-indent -u remark-lint-no-inline-padding -u remark-lint-no-shortcut-reference-image -u remark-lint-no-shortcut-reference-link -u remark-lint-no-undefined-references -u remark-lint-no-unused-definitions -u remark-lint-no-dead-urls docs README.md charts
.gitignore+3
@@ -8,3 +8,6 @@ octopod-config.json
88frontend-result
99octopod-css/node_modules
1010dev/certs/*
11+tmp/*
12+octopod-css/production
13+.idea/
.hlint.yamlnew file+55
@@ -0,0 +1,55 @@
1+# HLint configuration file
2+# https://github.com/ndmitchell/hlint
3+##########################
4+
5+# This file contains a template configuration file, which is typically
6+# placed as .hlint.yaml in the root of your project
7+
8+# Specify additional command line arguments
9+#
10+# - arguments: [--color, --cpp-simple, -XQuasiQuotes]
11+
12+# Control which extensions/flags/modules/functions can be used
13+#
14+# - extensions:
15+# - default: false # all extension are banned by default
16+# - name: [PatternGuards, ViewPatterns] # only these listed extensions can be used
17+# - {name: CPP, within: CrossPlatform} # CPP can only be used in a given module
18+#
19+# - flags:
20+# - {name: -w, within: []} # -w is allowed nowhere
21+#
22+# - modules:
23+# - {name: [Data.Set, Data.HashSet], as: Set} # if you import Data.Set qualified, it must be as 'Set'
24+# - {name: Control.Arrow, within: []} # Certain modules are banned entirely
25+#
26+# - functions:
27+# - {name: unsafePerformIO, within: []} # unsafePerformIO can only appear in no modules
28+
29+# Add custom hints for this project
30+#
31+# Will suggest replacing "wibbleMany [myvar]" with "wibbleOne myvar"
32+# - error: {lhs: "wibbleMany [x]", rhs: wibbleOne x}
33+
34+# Turn on hints that are off by default
35+#
36+# Ban "module X(module X) where", to require a real export list
37+# - warn: {name: Use explicit module export list}
38+#
39+# Replace a $ b $ c with a . b $ c
40+# - group: {name: dollar, enabled: true}
41+#
42+# Generalise map to fmap, ++ to <>
43+# - group: {name: generalise, enabled: true}
44+
45+# Ignore some builtin hints
46+# - ignore: {name: Use let}
47+# - ignore: {name: Use const, within: SpecialModule} # Only within certain modules
48+
49+- ignore: { name: Replace case with maybe }
50+- ignore: { name: Use if }
51+# Define some custom infix operators
52+# - fixity: infixr 3 ~^#^~
53+
54+# To generate a suitable file for HLint do:
55+# $ hlint --default > .hlint.yaml
.nova/Configuration.jsonnew file+5
@@ -0,0 +1,5 @@
1+{
2+ "env-generator" : "nix-shell --run env",
3+ "haskell.checkProject" : false,
4+ "haskell.formattingProvider" : "fourmolu"
5+}
.stylish-haskell.yamldeleted−319
@@ -1,319 +0,0 @@
1−# stylish-haskell configuration file
2−# ==================================
3−
4−# The stylish-haskell tool is mainly configured by specifying steps. These steps
5−# are a list, so they have an order, and one specific step may appear more than
6−# once (if needed). Each file is processed by these steps in the given order.
7−steps:
8− # Format record definitions. This is disabled by default.
9− #
10− # You can control the layout of record fields. The only rules that can't be configured
11− # are these:
12− #
13− # - "|" is always aligned with "="
14− # - "," in fields is always aligned with "{"
15− # - "}" is likewise always aligned with "{"
16− #
17− # - records:
18− # # How to format equals sign between type constructor and data constructor.
19− # # Possible values:
20− # # - "same_line" -- leave "=" AND data constructor on the same line as the type constructor.
21− # # - "indent N" -- insert a new line and N spaces from the beginning of the next line.
22− # equals: "same_line"
23−
24− # # How to format first field of each record constructor.
25− # # Possible values:
26− # # - "same_line" -- "{" and first field goes on the same line as the data constructor.
27− # # - "indent N" -- insert a new line and N spaces from the beginning of the data constructor
28− # first_field: "indent 2"
29−
30− # # How many spaces to insert between the column with "," and the beginning of the comment in the next line.
31− # field_comment: 2
32−
33− # # # How many spaces to insert before "deriving" clause. Deriving clauses are always on separate lines.
34− # deriving: 2
35−
36− # Align the right hand side of some elements. This is quite conservative
37− # and only applies to statements where each element occupies a single
38− # line. All default to true.
39− - simple_align:
40− cases: false
41− top_level_patterns: false
42− records: false
43−
44− # Import cleanup
45− - imports:
46− # There are different ways we can align names and lists.
47− #
48− # - global: Align the import names and import list throughout the entire
49− # file.
50− #
51− # - file: Like global, but don't add padding when there are no qualified
52− # imports in the file.
53− #
54− # - group: Only align the imports per group (a group is formed by adjacent
55− # import lines).
56− #
57− # - none: Do not perform any alignment.
58− #
59− # Default: global.
60− align: global
61−
62− # The following options affect only import list alignment.
63− #
64− # List align has following options:
65− #
66− # - after_alias: Import list is aligned with end of import including
67− # 'as' and 'hiding' keywords.
68− #
69− # > import qualified Data.List as List (concat, foldl, foldr, head,
70− # > init, last, length)
71− #
72− # - with_alias: Import list is aligned with start of alias or hiding.
73− #
74− # > import qualified Data.List as List (concat, foldl, foldr, head,
75− # > init, last, length)
76− #
77− # - with_module_name: Import list is aligned `list_padding` spaces after
78− # the module name.
79− #
80− # > import qualified Data.List as List (concat, foldl, foldr, head,
81− # init, last, length)
82− #
83− # This is mainly intended for use with `pad_module_names: false`.
84− #
85− # > import qualified Data.List as List (concat, foldl, foldr, head,
86− # init, last, length, scanl, scanr, take, drop,
87− # sort, nub)
88− #
89− # - new_line: Import list starts always on new line.
90− #
91− # > import qualified Data.List as List
92− # > (concat, foldl, foldr, head, init, last, length)
93− #
94− # Default: after_alias
95− list_align: after_alias
96−
97− # Right-pad the module names to align imports in a group:
98− #
99− # - true: a little more readable
100− #
101− # > import qualified Data.List as List (concat, foldl, foldr,
102− # > init, last, length)
103− # > import qualified Data.List.Extra as List (concat, foldl, foldr,
104− # > init, last, length)
105− #
106− # - false: diff-safe
107− #
108− # > import qualified Data.List as List (concat, foldl, foldr, init,
109− # > last, length)
110− # > import qualified Data.List.Extra as List (concat, foldl, foldr,
111− # > init, last, length)
112− #
113− # Default: true
114− pad_module_names: false
115−
116− # Long list align style takes effect when import is too long. This is
117− # determined by 'columns' setting.
118− #
119− # - inline: This option will put as much specs on same line as possible.
120− #
121− # - new_line: Import list will start on new line.
122− #
123− # - new_line_multiline: Import list will start on new line when it's
124− # short enough to fit to single line. Otherwise it'll be multiline.
125− #
126− # - multiline: One line per import list entry.
127− # Type with constructor list acts like single import.
128− #
129− # > import qualified Data.Map as M
130− # > ( empty
131− # > , singleton
132− # > , ...
133− # > , delete
134− # > )
135− #
136− # Default: inline
137− long_list_align: new_line
138−
139− # Align empty list (importing instances)
140− #
141− # Empty list align has following options
142− #
143− # - inherit: inherit list_align setting
144− #
145− # - right_after: () is right after the module name:
146− #
147− # > import Vector.Instances ()
148− #
149− # Default: inherit
150− empty_list_align: right_after
151−
152− # List padding determines indentation of import list on lines after import.
153− # This option affects 'long_list_align'.
154− #
155− # - <integer>: constant value
156− #
157− # - module_name: align under start of module name.
158− # Useful for 'file' and 'group' align settings.
159− #
160− # Default: 4
161− list_padding: 2
162−
163− # Separate lists option affects formatting of import list for type
164− # or class. The only difference is single space between type and list
165− # of constructors, selectors and class functions.
166− #
167− # - true: There is single space between Foldable type and list of it's
168− # functions.
169− #
170− # > import Data.Foldable (Foldable (fold, foldl, foldMap))
171− #
172− # - false: There is no space between Foldable type and list of it's
173− # functions.
174− #
175− # > import Data.Foldable (Foldable(fold, foldl, foldMap))
176− #
177− # Default: true
178− separate_lists: false
179−
180− # Space surround option affects formatting of import lists on a single
181− # line. The only difference is single space after the initial
182− # parenthesis and a single space before the terminal parenthesis.
183− #
184− # - true: There is single space associated with the enclosing
185− # parenthesis.
186− #
187− # > import Data.Foo ( foo )
188− #
189− # - false: There is no space associated with the enclosing parenthesis
190− #
191− # > import Data.Foo (foo)
192− #
193− # Default: false
194− space_surround: false
195−
196− # Language pragmas
197− - language_pragmas:
198− # We can generate different styles of language pragma lists.
199− #
200− # - vertical: Vertical-spaced language pragmas, one per line.
201− #
202− # - compact: A more compact style.
203− #
204− # - compact_line: Similar to compact, but wrap each line with
205− # `{-#LANGUAGE #-}'.
206− #
207− # Default: vertical.
208− style: vertical
209−
210− # Align affects alignment of closing pragma brackets.
211− #
212− # - true: Brackets are aligned in same column.
213− #
214− # - false: Brackets are not aligned together. There is only one space
215− # between actual import and closing bracket.
216− #
217− # Default: true
218− align: false
219−
220− # stylish-haskell can detect redundancy of some language pragmas. If this
221− # is set to true, it will remove those redundant pragmas. Default: true.
222− remove_redundant: true
223−
224− # Language prefix to be used for pragma declaration, this allows you to
225− # use other options non case-sensitive like "language" or "Language".
226− # If a non correct String is provided, it will default to: LANGUAGE.
227− language_prefix: LANGUAGE
228−
229− # Replace tabs by spaces. This is disabled by default.
230− # - tabs:
231− # # Number of spaces to use for each tab. Default: 8, as specified by the
232− # # Haskell report.
233− # spaces: 8
234−
235− # Remove trailing whitespace
236− - trailing_whitespace: {}
237−
238− # Squash multiple spaces between the left and right hand sides of some
239− # elements into single spaces. Basically, this undoes the effect of
240− # simple_align but is a bit less conservative.
241− - squash: {}
242−
243−# A common setting is the number of columns (parts of) code will be wrapped
244−# to. Different steps take this into account.
245−#
246−# Set this to null to disable all line wrapping.
247−#
248−# Default: 80.
249−columns: 80
250−
251−# By default, line endings are converted according to the OS. You can override
252−# preferred format here.
253−#
254−# - native: Native newline format. CRLF on Windows, LF on other OSes.
255−#
256−# - lf: Convert to LF ("\n").
257−#
258−# - crlf: Convert to CRLF ("\r\n").
259−#
260−# Default: native.
261−newline: native
262−
263−# Sometimes, language extensions are specified in a cabal file or from the
264−# command line instead of using language pragmas in the file. stylish-haskell
265−# needs to be aware of these, so it can parse the file correctly.
266−#
267−# No language extensions are enabled by default.
268−language_extensions:
269− - BangPatterns
270− - ConstraintKinds
271− - CPP
272− - DataKinds
273− - DefaultSignatures
274− - DeriveFoldable
275− - DeriveFunctor
276− - DeriveGeneric
277− - DeriveTraversable
278− - DerivingVia
279− - DuplicateRecordFields
280− - ExistentialQuantification
281− - ExplicitNamespaces
282− - FlexibleInstances
283− - FunctionalDependencies
284− - GADTs
285− - GeneralizedNewtypeDeriving
286− - KindSignatures
287− - LambdaCase
288− - MultiParamTypeClasses
289− - MultiWayIf
290− - NamedFieldPuns
291− - NoMonadFailDesugaring
292− - NumDecimals
293− - OverloadedStrings
294− - PartialTypeSignatures
295− - PolyKinds
296− - QuantifiedConstraints
297− - QuasiQuotes
298− - RankNTypes
299− - RecordWildCards
300− - RecursiveDo
301− - RoleAnnotations
302− - ScopedTypeVariables
303− - StandaloneDeriving
304− - TemplateHaskell
305− - TupleSections
306− - TypeApplications
307− - TypeFamilies
308− - TypeInType
309− - TypeOperators
310− - UndecidableInstances
311− - ViewPatterns
312− - OverloadedLabels
313− - FlexibleContexts
314−
315−# Attempt to find the cabal file in ancestors of the current directory, and
316−# parse options (currently only language extensions) from that.
317−#
318−# Default: true
319−cabal: false
.vscode/settings.json+8−2
@@ -1,3 +1,9 @@
11{
2− "nixEnvSelector.nixShellConfig": "${workspaceRoot}/shell.nix"
3−}
2+ "nixEnvSelector.nixFile": "${workspaceRoot}/shell.nix",
3+ "haskell.formattingProvider": "fourmolu",
4+ "haskell.plugin.hlint.diagnosticsOn": false,
5+ "haskell.hlint.logLevel": "none",
6+ "haskell.hlint.run": "never",
7+ "haskell.serverExecutablePath": "haskell-language-server",
8+ "editor.formatOnSave": true
9+}
Caddyfiledeleted−27
@@ -1,27 +0,0 @@
1−http://localhost:8000
2−
3−
4−file_server
5−
6−rewrite /api/* {path}
7−reverse_proxy /api/* localhost:3002
8−
9−@production {
10− path_regexp production /static/(.*)
11−}
12−rewrite @production /octopod-css/production/{http.regexp.production.1}
13−
14−rewrite /config.json /dev/config.json
15−rewrite * /frontend-result/bin/frontend.jsexe/{path}
16−
17−
18−@3003 {
19− not path /octopod-css/* /frontend-result/* /dev/config.json
20−}
21−
22−reverse_proxy @3003 localhost:3003
23−
24−log {
25− output stdout
26− format single_field common_log
27−}
CaddyfileGhciddeleted−25
@@ -1,25 +0,0 @@
1−http://localhost:8000
2−
3−
4−file_server
5−
6−rewrite /api/* {path}
7−reverse_proxy /api/* localhost:3002
8−
9−@production {
10− path_regexp production /static/(.*)
11−}
12−rewrite @production /octopod-css/production/{http.regexp.production.1}
13−
14−rewrite /config.json /dev/config.json
15−
16−@3003 {
17− not path /octopod-css/* /frontend-result/* /dev/config.json
18−}
19−
20−reverse_proxy @3003 localhost:3003
21−
22−log {
23− output stdout
24− format single_field common_log
25−}
Development_guide.md+5−12
@@ -2,14 +2,7 @@
22
33## Git flow
44
5−`master` contains the latest "release version" only.
6−
7−All development should be done in the `develop` branch.
8−
9−Feature PRs are created to the `develop` branch and merged with all commits **squashed**. This leads to us having every commit in the `develop` branch corresponds to exactly one feature or bug fix.
10−
11−When a release is ready, the `develop` branch is merged into the `master` branch using **rebase and merge**. This makes the `master` branch have every commit be a feature or bug fix. Merging to master triggers a CI script that collects all commits since the last merge and creates a new release with a change log of all commits.
12−
5+Feature branches are merged into `master`. There is no `develop` branch.
136## Building
147
158### Nix Installation
@@ -22,13 +15,13 @@ curl https://nixos.org/nix/install | sh
2215
2316### Nix cache
2417
25−#### Reflex platform cache
18+#### Haskell.nix cache
2619
27−To speedup initial project builds you will want to set up the Reflex Platform binary nix cache – append the following to `/etc/nix/nix.conf`:
20+To speedup initial project builds you will want to set up the haskell.nix binary nix cache – append the following to `/etc/nix/nix.conf`:
2821
2922```
30−binary-caches = https://cache.nixos.org https://nixcache.reflex-frp.org
31−binary-cache-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= ryantrinkle.com-1:JJiAKaRv9mWgpVAz8dwewnZe0AzzEAzPkagE9SP5NWI=
23+binary-caches = https://hydra.iohk.io https://cache.nixos.org/
24+binary-cache-public-keys = hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=com-1:JJiAKaRv9mWgpVAz8dwewnZe0AzzEAzPkagE9SP5NWI=
3225binary-caches-parallel-connections = 40
3326```
3427
Makefile+18−29
@@ -1,54 +1,43 @@
1−.PHONY: build-backend build-octo-cli build-frontend docs backend-docs frontend-docs repl shell shell-ghcjs ghcid ghcid-cli ghcid-frontend push-octopod run-backend-dev run-frontend-dev
1+.PHONY: build-backend build-octo-cli build-frontend backend-docs repl shell ghcid ghcid-cli ghcid-frontend push-octopod run-backend-dev run-frontend-dev
22
33build-backend:
4− nix-build . -A ghc.octopod-backend -j auto
4+ nix-build . -A octopod-backend.components.exes.octopod-exe -j auto
55
66build-octo-cli:
7− nix-build . -A ghc.octo-cli -j auto
7+ nix-build . -A octo-cli.components.exes.octo -j auto
88
99build-frontend:
10− nix-build . -A ghcjs.octopod-frontend -o frontend-result -j auto
11−
12−docs: backend-docs frontend-docs
10+ nix-build . -A octopod-frontend-pretty -o frontend-result -j auto
1311
1412backend-docs:
15− nix-build . -A ghc.octopod-backend.doc -j auto
16−
17−frontend-docs:
18− nix-build . -A ghcjs.octopod-frontend.doc -j auto
13+ nix-build . -A octopod-backend.components.library.doc -j auto
1914
2015repl:
21− nix-shell . -A shells.ghc --run "cabal repl lib:octopod-backend" -j auto
16+ nix-shell --run "cabal repl lib:octopod-backend" -j auto
2217
2318shell:
24− nix-shell . -A shells.ghc -j auto
25−
26−shell-ghcjs:
27− nix-shell . -A shells.ghcjs -j auto
19+ nix-shell -j auto
2820
2921ghcid-backend:
30− nix-shell . -A shells.ghc --run 'ghcid -c "cabal new-repl octopod-backend"' -j auto
22+ nix-shell --run 'ghcid -c "cabal new-repl octopod-backend"' -j auto
3123
3224ghcid-cli:
33− nix-shell . -A shells.ghc --run 'ghcid -c "cabal new-repl octo-cli"' -j auto
25+ nix-shell --run 'ghcid -c "cabal new-repl octo-cli"' -j auto
3426
3527ghcid-frontend:
36− nix-shell . -A shells.ghc --run 'ghcid -c "cabal new-repl octopod-frontend -fdevelopment --ghc-options=-Wwarn" --warnings --test 'Main.main'' -j auto
28+ nix-shell --run 'ghcid -c "cabal new-repl octopod-frontend -fdevelopment --ghc-options=-Wwarn" --warnings --test 'Main.main'' -j auto
3729
3830push-octopod:
3931 ./build.sh build-and-push latest
4032
41−run-backend-dev: dev/certs/server_cert.pem dev/certs/server_key.pem
42− ./dev/dev_backend.sh `nix-build . -A ghc.octopod-backend`
43−
44−run-frontend-dev: build-frontend
45− caddy run
33+run-backend-dev:
34+ `nix-build dev -A backend -j auto`
4635
47−dev/certs/server_cert.pem dev/certs/server_key.pem:
48− openssl req -x509 -newkey rsa:4096 -keyout dev/certs/server_key.pem -out dev/certs/server_cert.pem -nodes -subj "/CN=localhost/O=Server"
36+run-frontend-dev:
37+ `nix-build dev -A frontend -j auto`
4938
50−dev/certs/client_csr.pem dev/certs/client_key.pem:
51− openssl req -newkey rsa:4096 -keyout dev/certs/client_key.pem -out dev/certs/client_csr.pem -nodes -subj "/CN=Client"
39+run-frontend-prod:
40+ `nix-build dev -A frontend --arg prod true -j auto`
5241
53−dev/certs/client_cert.pem: dev/certs/client_csr.pem dev/certs/server_cert.pem dev/certs/server_key.pem
54− openssl x509 -req -in dev/certs/client_csr.pem -CA dev/certs/server_cert.pem -CAkey dev/certs/server_key.pem -out dev/certs/client_cert.pem -set_serial 01 -days 3650)
42+run-caddy-for-ghcid:
43+ `nix-build dev -A caddyForGhcid -j auto`
README.md+103−14
@@ -1,13 +1,49 @@
1−# 🐙 Octopod [![Octopod Docker Image](https://github.com/typeable/octopod/workflows/Octopod%20Docker%20Image/badge.svg?branch=master)](https://github.com/typeable/octopod/actions?query=workflow%3A%22Octopod+Docker+Image%22+branch%3Amaster) [![octo CLI](https://github.com/typeable/octopod/workflows/octo%20CLI/badge.svg?branch=master)](https://github.com/typeable/octopod/actions?query=workflow%3A%22octo+CLI%22+branch%3Amaster) [![Documentation](https://github.com/typeable/octopod/workflows/Documentation/badge.svg?branch=master)](https://github.com/typeable/octopod/actions?query=workflow%3ADocumentation+branch%3Amaster)
1+<p align="center">
2+ <a href="#"><img src="img/logo.svg" width="500"></img></a>
3+</p>
24
3−_Octopod_ is a fully open-source self-hosted solution for managing multiple deployments in a _Kubernetes_ cluster with a user-friendly web interface. Managing deployments does not require any technical expertise.
5+<p align="center">
6+ <a href="https://github.com/typeable/octopod/actions?query=workflow%3ABuild"><img src="https://github.com/typeable/octopod/workflows/Build/badge.svg?branch=master" alt="Build"></a>
7+ <a href="https://github.com/typeable/octopod/actions?query=workflow%3ADocumentation+branch%3Amaster"><img src="https://github.com/typeable/octopod/workflows/Documentation/badge.svg?branch=master" alt="Documentation"></a>
8+</p>
49
5−We created _Octopod_ because we believe that everything we release should be rigorously tested, however, such desires greatly [complicate the development workflow](docs/en/PM_case_study.md) leading to longer release cycles. We use _Octopod_ to mitigate the downsides of rigorously testing each feature by deploying every single change we make to a separate staging environment allowing QA to investigate each feature independently and in parallel.
10+_Octopod_ is a fully open-source self-service portal which empowers your team to leverage the full power of Helm without the need for technical expertise.
11+
12+Octopod is a way for you to provide a self-service portal for managing instances of a service in your cluster. Anything you can describe in a Helm Chart, any member of team can deploy. No matter how complex the deployment process is.
13+
14+The recipe is simple: you provide a url to your Helm repo, Octopod then automatically extracts the possible configuration that the Chart can have, and automatically manages the lifecycle of the services. What users see is just a simple web interface:
615
716## 🖥 Demo
817
918<p align="center"><img src="img/demo.gif"></img></p>
1019
20+## 🧑‍🔬 Try it out for yourself
21+
22+You can have the installation from the demo above running on your local machine in minutes by running the following command:
23+
24+```bash
25+/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/typeable/octopod/master/octopod_local_install.sh)"
26+```
27+
28+You can dive deeper into the installation process in our [deployment guide](docs/en/Octopod_deployment_guide.md).
29+
30+<details>
31+<summary>You can remove everything the command above installs by running the following command:</summary>
32+
33+```bash
34+kind delete cluster --name octopod
35+```
36+
37+</details>
38+
39+## Motivation
40+
41+We created _Octopod_ because we believe that everything we release should be rigorously tested, however, such desires greatly [complicate the development workflow](docs/en/PM_case_study.md) leading to longer release cycles.
42+
43+The members of our team that facilitate rigorously testing are also the member that require the most attention from our DevOps engineers to manage the many staging environments required for a proper testing cycle.
44+
45+With Octopod we were able to reduce the reliance on our DevOps teams for testing to practically zero, while increasing the DevOps maneuverability of our QA engineers and process.
46+
1147## 📑 Documentation
1248
1349### 🔭 High-level notes
@@ -16,27 +52,56 @@ We created _Octopod_ because we believe that everything we release should be rig
1652- [🧑‍💻 Technical case study](docs/en/Tech_case_study.md)
1753
1854### 🛠️ Technical documentation
19−- [🏗 Technical architecture](docs/en/Technical_architecture.md) [[RU](docs/ru/Technical_architecture.md)]
20−- [⚙️ Control script guide](docs/en/Control_scripts.md) [[RU](docs/ru/Control_scripts.md)]
21−- [🔧🐙 Octopod deployment guide](docs/en/Octopod_deployment_guide.md) [[RU](docs/ru/Octopod_deployment_with_K8S.md)]
22−- [🔧🚀 Helm-based Octopod project setup](docs/en/Helm-based_deployment_guide.md) [[RU](docs/ru/Helm-based_deployment_guide.md)]
23−- [🐙🎛 octo CLI user guide](docs/en/Octo_user_guide.md) [[RU](docs/ru/Octo_user_guide.md)]
55+- [🏗 Technical architecture](docs/en/Technical_architecture.md)
56+- [⚙️ Control script guide][cs]
57+- [🔧🐙 Octopod deployment guide](docs/en/Octopod_deployment_guide.md)
58+- [🔧🚀 Helm-based Octopod project setup](docs/en/Helm-based_deployment_guide.md)
59+- [🐙🎛 octo CLI user guide][octo]
2460- [🤖 CI integration](docs/en/Integration.md)
25−- [🔒 Octopod security model](docs/en/Security_model.md) [[RU](docs/ru/Security_model.md)]
61+- [🔒 Octopod security model](docs/en/Security_model.md)
2662
2763## ℹ️ FAQ
2864
2965### How long does it take to set up _Octopod_?
3066
31−The longest part of setting up _Octopod_ for your project will probably be writing [_Control Scripts_](docs/en/Control_scripts.md). In total you should be able to get things running in about a day.
67+Deploying Octopod itself can be done in a matter of minutes if you have a Kubernetes cluster at hand. If you want to deploy it locally we have [a handy script](docs/en/Octopod_deployment_guide.md#if-you-want-to-try-it-locally) that sets everything up automatically.
68+
69+After you have Octopod up and running the only thing you need is a Helm Chart that your team might want to deploy. That's it.
3270
3371### Will _Octopod_ work with my project if it uses X?
3472
3573Yes. _Octopod_ is project-agnostic. If you can run your project in a Docker container, then you can use _Octopod_ with that project.
3674
75+### Does _Octopod_ work with "vanilla" Kubernetes projects that don't use Helm?
76+
77+If you do not have Helm Charts for your projects, you will not be able to leverage the simple Octopod installation procedure we have developed.
78+
79+To use _Octopod_ with your project will need to either:
80+
81+- Write Helm Charts for your project
82+- Write a set of [_control scripts_][cs] that deploy "vanilla" Kubernetes services
83+
84+You can always contact us if you need help. A good first place to ask questions is [Octopod Discussions](https://github.com/typeable/octopod/discussions).
85+
3786### What do I need to know to set up Octopod?
3887
39−You need to understand the basics of _Kubernetes_ and be familiar with whatever hosting provider you will be using. There is no need to know any special language – you can write [_Control Scripts_](docs/en/Control_scripts.md) in whatever language you like.
88+You need to understand the basics of _Kubernetes_ and be familiar with whatever hosting provider you will be using.
89+
90+### What separates Octopod from exiting solutions like Gitlab Dynamic Environments?
91+
92+Most existing solutions like Gitlab Dynamic Environments offer you an extension of CI/CD pipelines. All they do is allow you to run bash scripts.
93+
94+This has several drawback the main of which is the fact that you need to understand the under-the-hood details of the deployment process to use them. Existing solutions don't abstract the deployment process. They package up steps of deployment. The user is still responsible for coordinating the steps. You still need to manually manage the state of your deployed services.
95+
96+Observability and transparency of the deployment management process is another drawback. To inspect the state of a deployed system you need to drop down to the Kubernetes level. At that point you alienate anyone without DevOps expertise. This is the problem Octopod solves.
97+
98+Octopod _actually_ abstracts the under-the-hood detail like Helm, Kubernetes and Docker from the user into an intuitive and easy to understand model. This allows anyone to manage and deploy services.
99+
100+### Octopod is great, but my service deployment lifecycle is slightly different.
101+
102+Octopod was developed in a modular way from the very start. It offers specific extension points called _control scripts_ that allow you to modify the behavior of Octopod. The _control scripts_ can be implemented in any programming language, even Bash. You can read more about _control scripts_ in our [_control script guide_][cs].
103+
104+We have developed [a generic set of _control scripts_](helm-control-scripts/) that should work great with any Helm Chart. You can use them as a base for your custom _control scripts_.
40105
41106### Does _Octopod_ work with my CI?
42107
@@ -46,12 +111,36 @@ Yes. If you can run arbitrary executables in your CI, then you will be able to i
46111
47112It's been excluded from the GUI because we don't have a good security story to accompany this feature yet. Some secrets and credentials may leak to the project team using Octopod and, potentially, not everyone should have access to this data.
48113
49−### Why Haskell and Rust?
114+### Octopod says "Failure" next to my deployment. Why is it not working?
115+
116+There are several places where things can go wrong:
117+
118+1. Your DevOps engineer could have made mistakes in one of the [_Control Scripts_][cs] leading to an improper deployment process.
50119
51−We believe that there is a lot to be gained in programming in general by being able to statically ensure invariants in your code. One of the most practical ways of ensuring invariants is a good static type system. Haskell and Rust are both languages that have very strong type systems. This allows us to move fast without breaking things in the process.
120+ To fix this the DevOps engineer can use the [_octo CLI_][octo] to see detailed logs collected during the deployment process and diagnose the issue.
121+2. You could have one of the steps of your deployment failing (for example, a failing database migration).
122+
123+ If you have supplied a [_Kubernetes Dashboard_](https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/) URL to _Octopod_ during deployment, then you will have a "Details" button in the _Web UI_. You can click that button to get a filtered view of the _Kubernetes Dashboard_ where you can see what could have gone wrong and diagnose the issue.
124+
125+
126+## Quotations
127+
128+> Typeable team envisioned an insightful approach to CI/CD, which managed to help us cut the delivery time for new features and projects with Octopod
129+
130+— Wes Iwanski – VP Technology, Downtown Travel
52131
53132## ❓ Still have questions?
54133
55134If you still have questions, be sure to ask them in our [Octopod Discussions](https://github.com/typeable/octopod/discussions).
56135
57−<p align="center"><a href="https://typeable.io"><img src="img/typeable.png" width="177px"></img></a></p>
136+
137+<br />
138+
139+<p align="center">
140+ <i>Star the project of you like it</i>
141+</p>
142+
143+<p align="center"><a href="https://typeable.io"><img src="img/typeable_logo.svg" width="177px"></img></a></p>
144+
145+[cs]: docs/en/Control_scripts.md
146+[octo]: docs/en/Octo_user_guide.md
Release_checklist.md+6−16
@@ -1,18 +1,8 @@
11# Release checklist
22
3−1. Merge the `develop` branch into `master`.
4−2. CI will automatically create a new release in GitHub with _octo CLI_ and update the `latest` tag for both `octo` and `octopod`. Wait for CI to complete.
5−3. Edit the created release in GitHub to match the version you are releasing.
6− 1. Change the release name to the version being released.
7− 2. Uncheck "This is a pre-release"
8−4. Push the new release of `octo` and `octopod`. To do this run `./release.sh <version>`.
9−5. Update the referenced tags in documentation
10−6. If there were changes to the examples:
11− 1. Build and push the new containers:
12− 1. octopod-web-app-example
13− 2. octopod-helm-example
14− 2. Create a new tag incrementing the integer version number of the tag:
15− 1. Pull the image (`docker pull`)
16− 2. Tag it with the new `<integer>` (`docker tag`)
17− 3. Push the new tag (`docker push`)
18− 3. Update docs where the tags are referenced.
3+1. Update the referenced tags in the documentation
4+2. If there were changes to control scripts:
5+ 1. _**\<TODO\>**_
6+3. [Dispatch the "Build and release" workflow](https://github.com/typeable/octopod/actions/workflows/build.yaml), specifying the version you are releasing:
7+
8+ ![](./img/release_workflow.png)
build.shdeleted−66
@@ -1,66 +0,0 @@
1−#!/usr/bin/env bash
2−
3−set -e
4−
5−build_octo_cli_docker_image() {
6− nix build nixpkgs.octo-cli-container \
7− -I nixpkgs=nix \
8− -o "$1"
9−}
10−
11−build_octopod_server_docker_image() {
12− nix build nixpkgs.octopod-server-container \
13− --arg migrations "$1" \
14− -I nixpkgs=nix \
15− -o "$2"
16−}
17−
18−push_docker_images() {
19− outfile=latest-octopod-server-docker
20− for image_name in $octo_cli_docker $octopod_server_docker; do
21− image_type=$(echo "$image_name" | cut -d- -f1)
22− image=$(ls -ls "$image_name" | awk '{print $12}')
23− echo "size: $(du -sh $image)"
24− docker load --input "$image" | tee "$outfile"
25− nixcontainer=$(awk '{print $3}' $outfile)
26− docker tag "$nixcontainer" "typeable/${image_type}:$1"
27− docker push "typeable/${image_type}:$1"
28− echo "Published: ${image_type}:$1"
29− done
30− rm $outfile
31−}
32−
33−build_docker_images() {
34− build_octo_cli_docker_image "$octo_cli_docker"
35− build_octopod_server_docker_image "$migrations" "$octopod_server_docker"
36−}
37−
38−export tag=$(git rev-parse HEAD)
39−export migrations="./migrations"
40−export octo_cli_docker="octo-docker"
41−export octopod_server_docker="octopod-server-docker"
42−
43−case "$1" in
44− build-and-push)
45− echo "$1 mode"
46−
47− if test -z "$2"
48− then
49− echo "Please provide a tag to upload to"
50− exit 1
51− fi
52−
53− build_docker_images
54− push_docker_images $2
55− ;;
56− build)
57− echo "$1 mode"
58− build_docker_images
59− ;;
60− *)
61− echo "usage:"
62− echo " $0 build Builds the docker images."
63− echo " $0 build-and-push <tag> Builds the docker images and uploads it to Docker Hub under the tag <tag>."
64− exit 1
65− ;;
66−esac
cabal.project+35
@@ -4,3 +4,38 @@ packages:
44 octopod-backend/
55 octopod-common/
66 octopod-frontend/
7+
8+allow-newer:
9+ servant-reflex:servant,
10+ servant-reflex:servant-auth,
11+ servant-reflex:reflex
12+
13+source-repository-package
14+ type: git
15+ location: https://github.com/ilyakooo0/obelisk
16+ tag: e3c45d230bfc60351c82e8674bc190349fcfae3a
17+ subdir: lib/route
18+ --sha256: 1syczkabq8yz7fw5jpmax15770bbb12wgdmm3lbgvh4m9qvfmblg
19+
20+source-repository-package
21+ type: git
22+ location: https://github.com/obsidiansystems/obelisk
23+ tag: 7ad33cbe3e84b209e83c505ce25486445bbd602e
24+ subdir: lib/tabulation
25+ --sha256: 0dlk8y6rxc87crw7764zq2py7nqn38lw496ca1y893m9gdq8qdkz
26+
27+source-repository-package
28+ type: git
29+ location: https://github.com/obsidiansystems/obelisk
30+ tag: 7ad33cbe3e84b209e83c505ce25486445bbd602e
31+ subdir: lib/executable-config/lookup
32+ --sha256: 0dlk8y6rxc87crw7764zq2py7nqn38lw496ca1y893m9gdq8qdkz
33+
34+source-repository-package
35+ type: git
36+ location: https://github.com/typeable/ordered-containers.git
37+ tag: 3eb05fb2f44fe482e9092aff447e9c68fbd6a7f6
38+ --sha256: 0q3cp3nar41bqh2ldl1ykzaycf0bjxh0n58za5g19x4g7ab8h9gm
39+
40+package reflex-dom
41+ flags: +use-warp
charts/cert-control/.helmignoredeleted−22
@@ -1,22 +0,0 @@
1−# Patterns to ignore when building packages.
2−# This supports shell glob matching, relative path matching, and
3−# negation (prefixed with !). Only one pattern per line.
4−.DS_Store
5−# Common VCS dirs
6−.git/
7−.gitignore
8−.bzr/
9−.bzrignore
10−.hg/
11−.hgignore
12−.svn/
13−# Common backup files
14−*.swp
15−*.bak
16−*.tmp
17−*~
18−# Various IDEs
19−.project
20−.idea/
21−*.tmproj
22−.vscode/
charts/cert-control/Chart.yamldeleted−5
@@ -1,5 +0,0 @@
1−apiVersion: v1
2−appVersion: "1.0"
3−description: A Helm chart for Kubernetes
4−name: cert-control
5−version: 0.1.0
charts/cert-control/templates/cert-control-clusterrole.yamldeleted−8
@@ -1,8 +0,0 @@
1−apiVersion: rbac.authorization.k8s.io/v1
2−kind: ClusterRole
3−metadata:
4− name: cert-control-clusterrole
5−rules:
6− - apiGroups: ["cert-manager.io"]
7− resources: ["certificates"]
8− verbs: ["list", "delete", "deletecollection"]
charts/cert-control/templates/cert-control-rolebinding.yamldeleted−13
@@ -1,13 +0,0 @@
1−apiVersion: rbac.authorization.k8s.io/v1
2−kind: RoleBinding
3−metadata:
4− name: {{ .Values.serviceaccount }}-cert-control-rolebinding
5− namespace: {{ .Values.namespace }}
6−roleRef:
7− kind: ClusterRole
8− apiGroup: rbac.authorization.k8s.io
9− name: cert-control-clusterrole
10−subjects:
11− - kind: ServiceAccount
12− name: {{ .Values.serviceaccount }}
13− namespace: {{ .Values.octopod_namespace | default .Values.namespace }}
charts/cert-control/values.yamldeleted−3
@@ -1,3 +0,0 @@
1−namespace: deployment
2−octopod_namespace: octopod
3−serviceaccount: octopod
charts/helm-access/.helmignoredeleted−22
@@ -1,22 +0,0 @@
1−# Patterns to ignore when building packages.
2−# This supports shell glob matching, relative path matching, and
3−# negation (prefixed with !). Only one pattern per line.
4−.DS_Store
5−# Common VCS dirs
6−.git/
7−.gitignore
8−.bzr/
9−.bzrignore
10−.hg/
11−.hgignore
12−.svn/
13−# Common backup files
14−*.swp
15−*.bak
16−*.tmp
17−*~
18−# Various IDEs
19−.project
20−.idea/
21−*.tmproj
22−.vscode/
charts/helm-access/Chart.yamldeleted−5
@@ -1,5 +0,0 @@
1−apiVersion: v1
2−appVersion: "1.0"
3−description: A Helm chart for Kubernetes
4−name: helm-access
5−version: 0.1.0
charts/helm-access/templates/helm-clusterrole.yamldeleted−11
@@ -1,11 +0,0 @@
1−apiVersion: rbac.authorization.k8s.io/v1
2−kind: ClusterRole
3−metadata:
4− name: helm-clusterrole
5−rules:
6− - apiGroups: [""]
7− resources: ["pods/portforward"]
8− verbs: ["create"]
9− - apiGroups: [""]
10− resources: ["pods"]
11− verbs: ["list", "get"]
charts/helm-access/templates/helm-clusterrolebinding.yamldeleted−12
@@ -1,12 +0,0 @@
1−apiVersion: rbac.authorization.k8s.io/v1
2−kind: ClusterRoleBinding
3−metadata:
4− name: {{ .Values.serviceaccount }}-helm-clusterrolebinding
5−roleRef:
6− kind: ClusterRole
7− apiGroup: rbac.authorization.k8s.io
8− name: helm-clusterrole
9−subjects:
10− - kind: ServiceAccount
11− name: {{ .Values.serviceaccount }}
12− namespace: {{ .Values.namespace }}
charts/helm-access/values.yamldeleted−2
@@ -1,2 +0,0 @@
1−namespace: octopod
2−serviceaccount: octopod
charts/kubedog-access/Chart.yamldeleted−5
@@ -1,5 +0,0 @@
1−apiVersion: v1
2−appVersion: "1.0"
3−description: A Helm chart for Kubernetes
4−name: helm-access
5−version: 0.1.0
charts/kubedog-access/templates/kubedog-clusterrole.yamldeleted−17
@@ -1,17 +0,0 @@
1−apiVersion: rbac.authorization.k8s.io/v1
2−kind: ClusterRole
3−metadata:
4− name: kubedog-clusterrole
5−rules:
6− - apiGroups: ["apps"]
7− resources: ["deployments"]
8− verbs: ["list", "watch"]
9− - apiGroups: ["apps"]
10− resources: ["statefulsets"]
11− verbs: ["list", "watch"]
12− - apiGroups: ["apps"]
13− resources: ["replicasets"]
14− verbs: ["list", "watch"]
15− - apiGroups: [""]
16− resources: ["events"]
17− verbs: ["list"]
charts/kubedog-access/templates/kubedog-clusterrolebinding.yamldeleted−12
@@ -1,12 +0,0 @@
1−apiVersion: rbac.authorization.k8s.io/v1
2−kind: ClusterRoleBinding
3−metadata:
4− name: {{ .Values.serviceaccount }}-kubedog-clusterrolebinding
5−roleRef:
6− kind: ClusterRole
7− apiGroup: rbac.authorization.k8s.io
8− name: kubedog-clusterrole
9−subjects:
10− - kind: ServiceAccount
11− name: {{ .Values.serviceaccount }}
12− namespace: {{ .Values.namespace }}
charts/kubedog-access/values.yamldeleted−2
@@ -1,2 +0,0 @@
1−namespace: octopod
2−serviceaccount: octopod
charts/octopod-infra/.helmignoredeleted−22
@@ -1,22 +0,0 @@
1−# Patterns to ignore when building packages.
2−# This supports shell glob matching, relative path matching, and
3−# negation (prefixed with !). Only one pattern per line.
4−.DS_Store
5−# Common VCS dirs
6−.git/
7−.gitignore
8−.bzr/
9−.bzrignore
10−.hg/
11−.hgignore
12−.svn/
13−# Common backup files
14−*.swp
15−*.bak
16−*.tmp
17−*~
18−# Various IDEs
19−.project
20−.idea/
21−*.tmproj
22−.vscode/
charts/octopod-infra/Chart.yamldeleted−5
@@ -1,5 +0,0 @@
1−apiVersion: v1
2−appVersion: "1.0"
3−description: A Helm chart for Kubernetes
4−name: octopod-infra
5−version: 0.1.0
charts/octopod-infra/templates/postgres-configmap.yamldeleted−11
@@ -1,11 +0,0 @@
1−apiVersion: v1
2−kind: ConfigMap
3−metadata:
4− name: {{ .Release.Name }}-postgres-config
5− namespace: {{ .Release.Namespace }}
6− labels:
7− app: {{ .Release.Name }}-postgres
8−data:
9− POSTGRES_DB: {{ .Values.postgres_db | default .Release.Name }}
10− POSTGRES_USER: {{ .Values.postgres_user | default "postgres" }}
11− POSTGRES_PASSWORD: {{ .Values.postgres_password | default "password" }}
charts/octopod-infra/templates/postgres-service.yamldeleted−14
@@ -1,14 +0,0 @@
1−apiVersion: v1
2−kind: Service
3−metadata:
4− name: {{ .Release.Name }}-postgres
5− namespace: {{ .Release.Namespace }}
6− labels:
7− name: {{ .Release.Name }}-postgres
8−spec:
9− selector:
10− app: {{ .Release.Name }}-postgres
11− clusterIP: None
12− ports:
13− - port: 5432
14− name: postgres
charts/octopod-infra/templates/postgres-statefulset.yamldeleted−51
@@ -1,51 +0,0 @@
1−apiVersion: apps/v1
2−kind: StatefulSet
3−metadata:
4− name: {{ .Release.Name }}-postgres
5− namespace: {{ .Release.Namespace }}
6−spec:
7− serviceName: {{ .Release.Name }}-postgres
8− replicas: 1
9− selector:
10− matchLabels:
11− app: {{ .Release.Name }}-postgres
12− template:
13− metadata:
14− labels:
15− app: {{ .Release.Name }}-postgres
16− spec:
17− nodeSelector:
18− role: {{ .Values.nodeselector }}
19− terminationGracePeriodSeconds: 120
20− containers:
21− - name: postgres
22− image: postgres:10
23− envFrom:
24− - configMapRef:
25− name: {{ .Release.Name }}-postgres-config
26− resources:
27− requests:
28− cpu: {{ .Values.requests.cpu }}
29− memory: {{ .Values.requests.memory }}
30− limits:
31− cpu: {{ .Values.limits.cpu }}
32− memory: {{ .Values.limits.memory }}
33− ports:
34− - containerPort: 5432
35− name: postgredb
36− volumeMounts:
37− - name: postgredb
38− mountPath: /var/lib/postgresql/data
39− subPath: postgres
40− volumeClaimTemplates:
41− - metadata:
42− name: postgredb
43− labels:
44− app: {{ .Release.Name }}-postgres
45− spec:
46− accessModes:
47− - "ReadWriteOnce"
48− storageClassName: {{ .Values.storage_class | default "default" }}
49− resources:
50− requests:
51− storage: {{ .Values.storage_size }}
charts/octopod-infra/values.yamldeleted−20
@@ -1,20 +0,0 @@
1−global:
2− image_prefix:
3− image: default
4− image_tag:
5−
6−namespace: octopod
7−nodeselector: stand
8−
9−nodeselector: stand
10−namespace: octopod
11−postgres_db: octopod
12−postgres_user: octopod
13−postgres_password: octopod
14−storage_size: 1Gi
15−requests:
16− cpu: 0.2
17− memory: 256Mi
18−limits:
19− cpu: 0.2
20− memory: 512Mi
charts/octopod/.gitignorenew file+1
@@ -0,0 +1 @@
1+charts
charts/octopod/.helmignore+1
@@ -14,6 +14,7 @@
1414*.swp
1515*.bak
1616*.tmp
17+*.orig
1718*~
1819# Various IDEs
1920.project
charts/octopod/Chart.locknew file+6
@@ -0,0 +1,6 @@
1+dependencies:
2+- name: postgresql
3+ repository: https://charts.bitnami.com/bitnami
4+ version: 10.5.3
5+digest: sha256:d8ba564b767cbf73a4ca87cb3b97e0a75bc813ba0a58a1b0bd6c7154a608e783
6+generated: "2021-07-16T15:31:01.633560857+03:00"
charts/octopod/Chart.yaml+19−4
@@ -1,5 +1,20 @@
1−apiVersion: v1
2−appVersion: "1.0"
3−description: A Helm chart for Kubernetes
1+apiVersion: v2
42name: octopod
5−version: 0.1.0
3+description: An opensource self-hosted solution for managing multiple deployments in a Kubernetes cluster.
4+type: application
5+version: 0.6.11
6+appVersion: 1.5.2
7+keywords:
8+ - kubernetes
9+ - octopod
10+home: https://github.com/typeable/octopod
11+sources:
12+ - https://github.com/typeable/octopod
13+maintainers:
14+ - name: Alex Sizov
15+ email: a.sizov@typeable.io
16+dependencies:
17+ - name: postgresql
18+ version: 10.5.3
19+ repository: https://charts.bitnami.com/bitnami
20+ condition: postgresql.enabled
charts/octopod/README.mdnew file+182
@@ -0,0 +1,182 @@
1+# Octopod
2+
3+[Octopod](https://github.com/typeable/octopod) is a fully open-source self-hosted solution for managing multiple deployments in a Kubernetes cluster with a user-friendly web interface. Managing deployments does not require any technical expertise.
4+
5+## TL;DR
6+```console
7+$ helm repo add typeable https://typeable.github.io/octopod/
8+$ helm repo update
9+$ kubectl create namespace octopod-deployment
10+$ helm install octopod typeable/octopod --set octopod.baseDomain="your-domain.com"
11+```
12+
13+## Introduction
14+
15+This chart bootstraps Octopod deployment in a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager.
16+
17+## Prerequisites
18+
19+### Mandatory
20+
21+- Kubernetes version >= 1.12.0 <= 1.22.0
22+- PVC support (for PostgreSQL persistence)
23+- [NGINX Ingress](https://kubernetes.github.io/ingress-nginx/) contoller version <= 0.49.3 installed. NGINX Ingress controller v1.x.x is not currently supported
24+
25+### Optional
26+
27+- Cert Manager ([cert-manager](https://cert-manager.io/docs/installation/)) installed, if you want to get SSL certificates from Let's Encrypt automatically.
28+- Cluster issuer ([ACME Issuer](https://cert-manager.io/docs/configuration/acme/#creating-a-basic-acme-issuer)) created. By default we assume that it would be named `letsencrypt`. You can change it by setting `ingress.tls.clusterIssuer` parameter.
29+
30+
31+## Installing the Chart
32+This chart will not create or delete any namespaces for you.
33+
34+You'll need to create 2 namespaces before installing:
35+
36+1. A namespace in which Octopod itself will be installed:
37+ ```console
38+ $ kubectl create namespace octopod
39+ ```
40+2. A namespace in which Octopod will deploy all your deployments (configured in `octopod.deploymentNamespace`):
41+ ```console
42+ $ kubectl create namespace octopod-deployment
43+ ```
44+
45+To install the chart with the release name `my-release` execute:
46+
47+```console
48+$ helm repo add typeable https://typeable.github.io/octopod/
49+$ helm repo update
50+$ helm -n octopod install my-release typeable/octopod --set octopod.baseDomain="your-domain.com"
51+```
52+
53+The command deploys Octopod on the Kubernetes cluster in the default configuration inside octopod namespace. The [Parameters](#parameters) section lists the parameters that can be configured during installation.
54+
55+## Uninstalling the Chart
56+
57+To uninstall/delete the `my-release` deployment:
58+
59+```console
60+$ helm -n octopod delete my-release
61+```
62+
63+The command removes all the Kubernetes components except PVCs associated with the postgres chart, and deletes the release.
64+
65+## Note about generated values
66+Some values (such as passwords) in this chart (and its dependencies) are generated automatically, but due to [the limitation in Helm](https://github.com/helm/charts/issues/5167) the values are changing on every upgrade. To prevent this you must set these values explicitly by providing them via `--set` flags or in the [values file](https://helm.sh/docs/chart_template_guide/values_files/).
67+
68+These values are:
69+- `postgresql.postgresqlPassword` ― main db password
70+- `postgresql.postgresqlPostgresPassword` ― password for "postgres" user
71+- `octopod.cliAuthSecret` ― auth header for octo cli tool
72+- `octopod.uiAuthSecret` ― basic auth secret for ui->octopod communication
73+
74+Note: if these values are not provided, the `helm upgrade` command can fail or Octopod will not work after the upgrade.
75+
76+## Parameters
77+
78+The following tables lists the configurable parameters of the Octopod chart and their default values.
79+
80+| Key | Type | Default | Description |
81+|-----|------|---------|-------------|
82+| affinity | object | `{}` | Octopod deployment affinity |
83+| controlScripts.image.pullPolicy | string | `"IfNotPresent"` | control scripts image pull policy |
84+| controlScripts.image.repository | string | `"typeable/octopod-helm-example"` | Control scripts image repository (you probably want to use your own control scripts) |
85+| controlScripts.image.tag | float | `1.1` | Control scitpts image tag |
86+| fullnameOverride | string | `""` | Override chart full name |
87+| image.pullPolicy | string | `"IfNotPresent"` | Octopod image pull policy |
88+| image.repository | string | `"typeable/octopod"` | Octopod image repository |
89+| image.tag | string | `""` | Octopod image tag (default values is taken from chart metadata) |
90+| imagePullSecrets | list | `[]` | Pull secrets if you want to use private registry |
91+| ingress.app.annotations | object | `{}` | Additional ingress annotations for app service |
92+| ingress.app.host | string | `null` | Hostname override for app service by default it will be generated using your baseDomain |
93+| ingress.enabled | bool | `true` | Create ingress objects or not |
94+| ingress.ingressClass | string | `"nginx"` | Ingress class |
95+| ingress.powerApp.annotations | object | `{}` | Additional ingress annotations for power-app service |
96+| ingress.powerApp.host | string | `null` | Hostname override for powerapp by default it will be generated using your baseDomain |
97+| ingress.tls.clusterIssuer | string | `"letsencrypt"` | Name of cluster issuer you want to use |
98+| ingress.tls.enabled | bool | `true` | Use https for all services |
99+| ingress.ui.annotations | object | `{}` | Additional ingress annotations for ui service |
100+| ingress.ui.host | string | `null` | Hostname override for main UI by default it will be generated using your baseDomain |
101+| ingress.ws.annotations | object | `{}` | Additional ingress annotations for ws service |
102+| ingress.ws.host | string | `null` | Hostname override for websockets ingress by default it will be generated using your baseDomain |
103+| kubernetesDashboard.enabled | bool | `false` | Set this if you are using kubernetes dashboard and want to enable Details featire of octopod |
104+| kubernetesDashboard.url | bool | `""` | URL to your kubernetes dashboard |
105+| nameOverride | string | `""` | Name ovveride (default is Release.Name) |
106+| nodeSelector | object | `{}` | Node selector if you want octopod to use specific nodes onn your cluster |
107+| octopod.archiveRetention | int | `1209600` | |
108+| octopod.baseDomain | string | `""` | Domain that will be used as a ase for Octopod deploymets and ingress hosts|
109+| octopod.cliAuthSecret | string | `nil` | Auth Header for accessing octopod using octo CLI |
110+| octopod.uiAuthSecret | string | `nil` | Basic auth secret for securing communcation between octopod UI and backend API |
111+| octopod.deploymentNamespace | string | `"octopod-deployment"` | Name of a namespace which will be used for all Octopod deployments (you need to create it yourself) |
112+| octopod.env | object | `{}` | key value map for supplying additional environment variables for octopod or your control scripts |
113+| octopod.migrations.enabled | bool | `true` | Enable or not automatic DB schema migrations |
114+| octopod.projectName | string | `"Octopod"` | Project name |
115+| octopod.statusUpdateTimeout | int | `600` | Time to wait before deployment is marked as failed |
116+| octopod.vaultEnv | object | `{}` | key value map for reference kv secrets stored in Hashicorp's Vault |
117+| podAnnotations | object | `{}` | Additional pod annotations |
118+| podSecurityContext | object | `{}` | Additional security context |
119+| postgresql.enabled | bool | `true` | Use bitnami postgres chart |
120+| postgresql.postgresqlDatabase | string | `"octopod"` | Database name for octopod |
121+| postgresql.postgresqlUsername | string | `"octopod"` | Octopod DB username |
122+| rbac.create | bool | `true` | Creates ClusterRoles and Bindings for Octopod service account |
123+| replicaCount | int | `1` | Number of Octopod replicas |
124+| resources.limits.cpu | string | `"200m"` | CPU limits |
125+| resources.limits.memory | string | `"512Mi"` | Memory limits |
126+| resources.requests.cpu | string | `"200m"` | CPU requests |
127+| resources.requests.memory | string | `"256Mi"` | Memory requests |
128+| securityContext.runAsGroup | int | `1000` | Use non-root GID |
129+| securityContext.runAsUser | int | `1000` | Use non-root UID |
130+| service.ports.app | int | `4000` | App service port |
131+| service.ports.powerApp | int | `4443` | Power app service port |
132+| service.ports.ui | int | `80` | UI service port |
133+| service.ports.ws | int | `4020` | WebSockets service port |
134+| service.type | string | `"ClusterIP"` | Octopod service type |
135+| serviceAccount.annotations | object | `{}` | Additional anotations for Octopod's SA |
136+| serviceAccount.create | bool | `true` | Create ServiceAccount |
137+| serviceAccount.name | string | `""` | ServiceAccount name override |
138+| sqitch.image.pullPolicy | string | `"IfNotPresent"` | squitch image pull policy |
139+| sqitch.image.repository | string | `"typeable/sqitch"` | squitch image repository |
140+| sqitch.image.tag | string | `"v2.0.0"` | squitch image tag |
141+| tolerations | list | `[]` | Octpod deploymet tolerations |
142+| vault.enabled | bool | `false` | Set to true if you want to add Vault agent annotations (vaultEnv must contain at least one reference) |
143+| vault.clusterName | string | `""` | Name of your cluster authentication method in Vault |
144+
145+
146+Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,
147+
148+```console
149+$ helm -n octopod install my-release \
150+ --set controlScripts.image.repository=registry.example.com/control,controlScripts.image.tag=0.0.1 \
151+ .
152+```
153+
154+The above command sets control scripts image to your custom repository
155+
156+Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example,
157+
158+```console
159+$ helm install my-release -f values.yaml .
160+```
161+
162+> **Tip**: You can use the default [values.yaml](values.yaml)
163+
164+## Configuration and installation details
165+
166+If you want to have authentication for Octopod UI you can use project like [Oauth2-Proxy](https://github.com/oauth2-proxy/oauth2-proxy) or directly use your oauth provider.
167+After that you can add following annotations to UI ingress (considering that your oauth provider installed on oauth.example.com):
168+```yaml
169+ingress:
170+ ui:
171+ annotations:
172+ nginx.ingress.kubernetes.io/auth-url: "https://oauth.example.com/oauth2/auth"
173+ nginx.ingress.kubernetes.io/auth-signin: "https://oauth.example.com/oauth2/start?rd=/redirect/$http_host$request_uri"
174+```
175+
176+<br />
177+
178+<p align="center">
179+ <i>Star the project of you like it</i>
180+</p>
181+
182+<p align="center"><a href="https://typeable.io"><img src="../../img/typeable_logo.svg" width="177px"></img></a></p>
charts/octopod/index.yamlnew file+37
@@ -0,0 +1,37 @@
1+apiVersion: v1
2+entries:
3+ postgresql:
4+ - annotations:
5+ category: Database
6+ apiVersion: v2
7+ appVersion: 11.12.0
8+ created: "2022-08-23T14:43:53.959078+03:00"
9+ dependencies:
10+ - name: common
11+ repository: https://charts.bitnami.com/bitnami
12+ version: 1.x.x
13+ description: Chart for PostgreSQL, an object-relational database management system
14+ (ORDBMS) with an emphasis on extensibility and on standards-compliance.
15+ digest: afece60469d73b9cc4b578fff9b7627dd6ae609be50a04dabac5ad0be5105f33
16+ home: https://github.com/bitnami/charts/tree/master/bitnami/postgresql
17+ icon: https://bitnami.com/assets/stacks/postgresql/img/postgresql-stack-220x234.png
18+ keywords:
19+ - postgresql
20+ - postgres
21+ - database
22+ - sql
23+ - replication
24+ - cluster
25+ maintainers:
26+ - email: containers@bitnami.com
27+ name: Bitnami
28+ - email: cedric@desaintmartin.fr
29+ name: desaintmartin
30+ name: postgresql
31+ sources:
32+ - https://github.com/bitnami/bitnami-docker-postgresql
33+ - https://www.postgresql.org/
34+ urls:
35+ - charts/postgresql-10.5.3.tgz
36+ version: 10.5.3
37+generated: "2022-08-23T14:43:53.955624+03:00"
charts/octopod/templates/NOTES.txtnew file+12
@@ -0,0 +1,12 @@
1+🐙 Thank you for installing Octopod!
2+
3+ 🖥️ You can access the Web UI here: {{ include "httpScheme" . }}://{{ include "uiIngressHost" . }}
4+
5+ 🎛 To access Octopod via octo CLI you can use this URL: {{ include "httpScheme" . }}://{{ include "powerAppIngressHost" . }}
6+
7+ 🔑 To get your CLI secret you need to execute this command:
8+ kubectl -n {{ .Release.Namespace }} get secret {{ include "octopodCliAuthSecretName" . }} -o jsonpath='{.data.cli-secret}' | base64 -d
9+
10+{{ if and (not .Values.octopod.cliAuthSecret) (not .Values.vault.enabled) .Release.IsUpgrade }}
11+{{ fail "To upgrade you need to set the octopod.cliAuthSecret variable with your current secret" }}
12+{{- end }}
charts/octopod/templates/_helpers.tpl+144−5
@@ -1,7 +1,146 @@
11{{/*
2−Set dbname
2+Expand the name of the chart.
33*/}}
4−{{- define "dbname" -}}
5−{{- $dbname_release := .Release.Name | replace "." "_" | replace "-" "_" -}}
6−{{- .Values.dbname | default $dbname_release }}
7−{{- end -}}
4+{{- define "octopod.name" -}}
5+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
6+{{- end }}
7+
8+{{/*
9+Create a default fully qualified app name.
10+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
11+If release name contains chart name it will be used as a full name.
12+*/}}
13+{{- define "octopod.fullname" -}}
14+{{- if .Values.fullnameOverride }}
15+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
16+{{- else }}
17+{{- $name := default .Chart.Name .Values.nameOverride }}
18+{{- if contains $name .Release.Name }}
19+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
20+{{- else }}
21+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
22+{{- end }}
23+{{- end }}
24+{{- end }}
25+
26+{{/*
27+Create chart name and version as used by the chart label.
28+*/}}
29+{{- define "octopod.chart" -}}
30+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
31+{{- end }}
32+
33+{{/*
34+Common labels
35+*/}}
36+{{- define "octopod.labels" -}}
37+helm.sh/chart: {{ include "octopod.chart" . }}
38+{{ include "octopod.selectorLabels" . }}
39+{{- if .Chart.AppVersion }}
40+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
41+{{- end }}
42+app.kubernetes.io/managed-by: {{ .Release.Service }}
43+{{- end }}
44+
45+{{/*
46+Selector labels
47+*/}}
48+{{- define "octopod.selectorLabels" -}}
49+app.kubernetes.io/name: {{ include "octopod.name" . }}
50+app.kubernetes.io/instance: {{ .Release.Name }}
51+{{- end }}
52+
53+{{/*
54+Create the name of the service account to use
55+*/}}
56+{{- define "octopod.serviceAccountName" -}}
57+{{- if .Values.serviceAccount.create }}
58+{{- default (include "octopod.fullname" .) .Values.serviceAccount.name }}
59+{{- else }}
60+{{- default "default" .Values.serviceAccount.name }}
61+{{- end }}
62+{{- end }}
63+
64+{{- define "controlScriptsPath" -}}
65+/utils
66+{{- end }}
67+
68+{{- define "octopodAppAuthSecretName" -}}
69+{{- printf "%s-app-auth-secret" (include "octopod.fullname" .) }}
70+{{- end }}
71+
72+{{- define "httpScheme" -}}
73+{{- if .Values.ingress.tls.enabled -}}
74+https
75+{{- else -}}
76+http
77+{{- end }}
78+{{- end }}
79+
80+{{- define "wsScheme" -}}
81+{{- if .Values.ingress.tls.enabled -}}
82+wss
83+{{- else -}}
84+ws
85+{{- end }}
86+{{- end }}
87+
88+{{- define "postgresqlHost" -}}
89+{{ .Release.Name }}-postgresql
90+{{- end }}
91+
92+{{- define "postgresqlSecretName" -}}
93+{{ .Release.Name }}-postgresql
94+{{- end }}
95+
96+{{- define "wsIngressHost" -}}
97+{{- if .Values.ingress.ws.host -}}
98+{{ .Values.ingress.ws.host }}
99+{{- else -}}
100+octopod-ws.{{ .Values.octopod.baseDomain }}
101+{{- end }}
102+{{- end }}
103+
104+{{- define "uiIngressHost" -}}
105+{{- if .Values.ingress.ui.host -}}
106+{{ .Values.ingress.ui.host }}
107+{{- else -}}
108+octopod.{{ .Values.octopod.baseDomain }}
109+{{- end }}
110+{{- end }}
111+
112+{{- define "powerAppIngressHost" -}}
113+{{- if .Values.ingress.powerApp.host -}}
114+{{ .Values.ingress.powerApp.host }}
115+{{- else -}}
116+octopod-powerapp.{{ .Values.octopod.baseDomain }}
117+{{- end }}
118+{{- end }}
119+
120+{{- define "appIngressHost" -}}
121+{{- if .Values.ingress.app.host -}}
122+{{ .Values.ingress.app.host }}
123+{{- else -}}
124+octopod-app.{{ .Values.octopod.baseDomain }}
125+{{- end }}
126+{{- end }}
127+
128+{{- define "octopodCliAuthSecretName" -}}
129+{{- printf "%s-cli-auth-secret" (include "octopod.fullname" .) }}
130+{{- end }}
131+
132+{{- define "octopodCliAuthSecret" -}}
133+{{- if .Values.octopod.cliAuthSecret -}}
134+{{ .Values.octopod.cliAuthSecret }}
135+{{- else }}
136+{{- randAlphaNum 32 }}
137+{{- end }}
138+{{- end }}
139+
140+{{- define "octopodUiAuthSecret" -}}
141+{{- if .Values.octopod.uiAuthSecret -}}
142+{{ .Values.octopod.uiAuthSecret }}
143+{{- else }}
144+{{- randAlphaNum 32 }}
145+{{- end }}
146+{{- end }}
charts/octopod/templates/clean-archive-cronjob.yamldeleted−47
@@ -1,47 +0,0 @@
1−apiVersion: batch/v1beta1
2−kind: CronJob
3−metadata:
4− name: {{ .Release.Name }}-clean-archive-cronjob
5− namespace: {{ .Values.namespace }}
6−spec:
7− schedule: "0 */1 * * *"
8− jobTemplate:
9− spec:
10− template:
11− metadata:
12− labels:
13− app: {{ .Release.Name }}
14− annotations:
15− checksum/config: "{{ .Values.global.deploy_checksum }}"
16− spec:
17− nodeSelector:
18− role: {{ .Values.nodeselector }}
19− containers:
20− - name: octo
21− image: {{ .Values.global.image_prefix }}/{{ .Values.global.octo_image }}:{{ .Values.global.image_tag }}
22− command:
23− - /app/octo
24− args:
25− - clean-archive
26− env:
27− - name: OCTOPOD_URL
28− value: https://{{ .Values.power_app_domain }}:443
29− volumeMounts:
30− - name: certs
31− mountPath: /cert.pem
32− subPath: client_cert.pem
33− - name: certs
34− mountPath: /key.pem
35− subPath: client_key.pem
36− resources:
37− requests:
38− cpu: 0.1
39− memory: 256Mi
40− limits:
41− cpu: 0.1
42− memory: 512Mi
43− restartPolicy: Never
44− volumes:
45− - name: certs
46− configMap:
47− name: octopod-certs
charts/octopod/templates/cli-secret.yamlnew file+11
@@ -0,0 +1,11 @@
1+{{- if not .Values.vault.enabled }}
2+apiVersion: v1
3+kind: Secret
4+type: Opaque
5+metadata:
6+ name: {{ include "octopodCliAuthSecretName" . }}
7+ labels:
8+ {{- include "octopod.labels" . | nindent 4 }}
9+data:
10+ cli-secret: {{ include "octopodCliAuthSecret" . | b64enc }}
11+{{- end }}
charts/octopod/templates/deployment.yamlnew file+240
@@ -0,0 +1,240 @@
1+apiVersion: apps/v1
2+kind: Deployment
3+metadata:
4+ name: {{ include "octopod.fullname" . }}
5+ labels:
6+ {{- include "octopod.labels" . | nindent 4 }}
7+ annotations:
8+ reloader.stakater.com/auto: "true"
9+spec:
10+ replicas: {{ .Values.replicaCount }}
11+ selector:
12+ matchLabels:
13+ {{- include "octopod.selectorLabels" . | nindent 6 }}
14+ template:
15+ metadata:
16+ annotations:
17+ {{- with .Values.podAnnotations }}
18+ {{- toYaml . | nindent 8 }}
19+ {{- end }}
20+ {{- if .Values.vault.enabled }}
21+ vault.hashicorp.com/agent-inject: 'true'
22+ vault.hashicorp.com/agent-init-first: 'true'
23+ vault.hashicorp.com/auth-path: 'auth/{{ .Values.vault.clusterName }}'
24+ vault.hashicorp.com/role: {{ .Values.vault.clusterName | quote}}
25+ {{- range $kv_store, $secret := .Values.octopod.vaultEnv }}
26+ {{- range $secret_name, $secret_values := $secret }}
27+ vault.hashicorp.com/agent-inject-secret-{{ $secret_name }}: '{{ $kv_store }}/{{ $secret_name }}'
28+ vault.hashicorp.com/agent-inject-template-{{ $secret_name }}: |
29+ {{ "{{" }} with secret "{{ $kv_store }}/{{ $secret_name }}" {{ "-}}" }}
30+ {{- range $secret_values }}
31+ export {{ .name }}="{{ "{{" }} .Data.data.{{ .key }} {{ "}}" }}"
32+ {{- end }}
33+ {{ "{{-" }} end {{ "}}" }}
34+ {{- end }}
35+ {{- end }}
36+ {{- end }}
37+ labels:
38+ {{- include "octopod.selectorLabels" . | nindent 8 }}
39+ spec:
40+ {{- with .Values.imagePullSecrets }}
41+ imagePullSecrets:
42+ {{- toYaml . | nindent 8 }}
43+ {{- end }}
44+ serviceAccountName: {{ include "octopod.serviceAccountName" . }}
45+ securityContext:
46+ {{- toYaml .Values.podSecurityContext | nindent 8 }}
47+ initContainers:
48+ - name: copy-migrations
49+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
50+ command:
51+ - "bash"
52+ - "-ec"
53+ - |
54+ set -ex
55+
56+ # copy migrations
57+ cp -av /migrations/* /mymigrations
58+
59+ # create sqitch.conf
60+ echo '[core]' > /mymigrations/sqitch.conf
61+ echo 'engine = pg' >> /mymigrations/sqitch.conf
62+ echo 'plan_file = sqitch.plan' >> /mymigrations/sqitch.conf
63+ echo 'top_dir = .' >> /mymigrations/sqitch.conf
64+ echo '[engine "pg"]' >> /mymigrations/sqitch.conf
65+ echo ' registry = sqitch' >> /mymigrations/sqitch.conf
66+ echo '[deploy]' >> /mymigrations/sqitch.conf
67+ echo ' verify = true' >> /mymigrations/sqitch.conf
68+ echo '[rebase]' >> /mymigrations/sqitch.conf
69+ echo ' verify = true' >> /mymigrations/sqitch.conf
70+ echo '[target "octopod"]' >> /mymigrations/sqitch.conf
71+ echo 'uri = db:pg://{{ .Values.postgresql.postgresqlUsername }}:$(PG_PASS)@{{ include "postgresqlHost" . }}/{{ .Values.postgresql.postgresqlDatabase }}' >> /mymigrations/sqitch.conf
72+ env:
73+ - name: PG_PASS
74+ valueFrom:
75+ secretKeyRef:
76+ name: {{ include "postgresqlSecretName" . }}
77+ key: postgresql-password
78+ volumeMounts:
79+ - name: migrations
80+ mountPath: /mymigrations
81+ - name: run-migrations
82+ image: "{{ .Values.sqitch.image.repository }}:{{ .Values.sqitch.image.tag }}"
83+ command:
84+ - "bash"
85+ - "-c"
86+ - |
87+ set -x
88+ echo 'checking connection to postgresql...'
89+ for i in $(seq 1 6); do psql "postgres://{{ .Values.postgresql.postgresqlUsername }}:$(PG_PASS)@{{ include "postgresqlHost" . }}/{{ .Values.postgresql.postgresqlDatabase }}" -c ''; if [ $? -eq 0 ]; then break; fi; sleep 10; done
90+ set -e
91+ echo 'run migrations...'
92+ cd /migrations && /usr/local/bin/sqitch deploy octopod
93+ env:
94+ - name: PG_PASS
95+ valueFrom:
96+ secretKeyRef:
97+ name: {{ include "postgresqlSecretName" . }}
98+ key: postgresql-password
99+ volumeMounts:
100+ - name: migrations
101+ mountPath: /migrations
102+ - name: copy-control-scripts
103+ image: "{{ .Values.controlScripts.image.repository }}:{{ .Values.controlScripts.image.tag }}"
104+ imagePullPolicy: {{ .Values.controlScripts.image.pullPolicy }}
105+ command:
106+ - sh
107+ - -c
108+ - 'cp /utils/* /copy/'
109+ volumeMounts:
110+ - name: control-scripts
111+ mountPath: /copy
112+
113+ - name: run-init
114+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
115+ command:
116+ - sh
117+ - -c
118+ - |
119+ {{- if .Values.vault.enabled }}
120+ for i in /vault/secrets/*;do source $i;done
121+ {{- end }}
122+ /utils/init
123+ envFrom:
124+ - configMapRef:
125+ name: {{ include "octopod.fullname" . }}
126+ volumeMounts:
127+ - name: home
128+ mountPath: /home/octopod
129+ - name: control-scripts
130+ mountPath: {{ include "controlScriptsPath" . }}
131+ securityContext:
132+ {{- toYaml .Values.securityContext | nindent 12 }}
133+ - name: copy-www
134+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
135+ command:
136+ - sh
137+ - -c
138+ - |
139+ set -ex
140+ cp -a /www/* /copy/
141+ find /www -type f -exec touch {} +
142+ volumeMounts:
143+ - name: www
144+ mountPath: /copy
145+ containers:
146+ - name: octopod
147+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
148+ imagePullPolicy: {{ .Values.image.pullPolicy }}
149+ ports:
150+ - containerPort: 4443
151+ protocol: TCP
152+ - containerPort: 4000
153+ protocol: TCP
154+ command:
155+ - "sh"
156+ - "-ec"
157+ - |
158+ {{- if .Values.vault.enabled }}
159+ for i in /vault/secrets/*;do source $i;done
160+ {{- end }}
161+ exec $ENTRYPOINT \
162+ --port {{ .Values.service.ports.powerApp | quote }} \
163+ --ui-port {{ .Values.service.ports.app | quote }} \
164+ --ws-port {{ .Values.service.ports.ws | quote }} \
165+ --db host="'{{ include "postgresqlHost" . }}' port=5432 user='{{ .Values.postgresql.postgresqlUsername }}' password=$(PG_PASS)" \
166+ --db-pool-size "10"
167+ envFrom:
168+ - configMapRef:
169+ name: {{ include "octopod.fullname" . }}
170+ env:
171+ - name: PG_PASS
172+ valueFrom:
173+ secretKeyRef:
174+ name: {{ include "postgresqlSecretName" . }}
175+ key: postgresql-password
176+ {{- if not .Values.vault.enabled }}
177+ - name: POWER_AUTHORIZATION_HEADER
178+ valueFrom:
179+ secretKeyRef:
180+ name: {{ include "octopodCliAuthSecretName" . }}
181+ key: cli-secret
182+ {{- end }}
183+ volumeMounts:
184+ - name: home
185+ mountPath: /home/octopod
186+ - name: control-scripts
187+ mountPath: {{ include "controlScriptsPath" . }}
188+ readinessProbe:
189+ httpGet:
190+ port: {{ .Values.service.ports.app }}
191+ path: /api/v1/ping
192+ periodSeconds: 20
193+ livenessProbe:
194+ httpGet:
195+ port: {{ .Values.service.ports.app }}
196+ path: /api/v1/ping
197+ initialDelaySeconds: 15
198+ periodSeconds: 5
199+ resources:
200+ {{- toYaml .Values.resources | nindent 12 }}
201+ securityContext:
202+ {{- toYaml .Values.securityContext | nindent 12 }}
203+ - name: nginx
204+ image: nginx:1.17.5
205+ volumeMounts:
206+ - name: nginx-config
207+ mountPath: /etc/nginx/conf.d/app.conf
208+ subPath: app.conf
209+ - name: nginx-config
210+ mountPath: /www/config.json
211+ subPath: config.json
212+ - name: www
213+ mountPath: /www
214+ ports:
215+ - containerPort: {{ .Values.service.ports.ui }}
216+ protocol: TCP
217+ {{- with .Values.nodeSelector }}
218+ nodeSelector:
219+ {{- toYaml . | nindent 8 }}
220+ {{- end }}
221+ {{- with .Values.affinity }}
222+ affinity:
223+ {{- toYaml . | nindent 8 }}
224+ {{- end }}
225+ {{- with .Values.tolerations }}
226+ tolerations:
227+ {{- toYaml . | nindent 8 }}
228+ {{- end }}
229+ volumes:
230+ - name: home
231+ emptyDir: {}
232+ - name: control-scripts
233+ emptyDir: {}
234+ - name: www
235+ emptyDir: {}
236+ - name: migrations
237+ emptyDir: {}
238+ - name: nginx-config
239+ configMap:
240+ name: {{ include "octopod.fullname" . }}-nginx-config
charts/octopod/templates/ingress-app.yamlnew file+53
@@ -0,0 +1,53 @@
1+{{- if .Values.ingress.enabled -}}
2+{{- $fullName := include "octopod.fullname" . -}}
3+{{- $kubeVersion := .Capabilities.KubeVersion.Version }}
4+{{ if semverCompare ">= 1.19.0-0" $kubeVersion }}
5+apiVersion: networking.k8s.io/v1
6+{{ else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" }}
7+apiVersion: networking.k8s.io/v1beta1
8+{{ else }}
9+apiVersion: extensions/v1beta1
10+{{ end }}
11+kind: Ingress
12+metadata:
13+ name: {{ $fullName }}-app
14+ labels:
15+ {{- include "octopod.labels" . | nindent 4 }}
16+ annotations:
17+ {{- if .Values.ingress.tls.enabled }}
18+ kubernetes.io/tls-acme: "true"
19+ cert-manager.io/cluster-issuer: {{ .Values.ingress.tls.clusterIssuer | quote }}
20+ {{- end }}
21+ kubernetes.io/ingress.class: {{ .Values.ingress.ingressClass | quote }}
22+ nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
23+ nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
24+ nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
25+ nginx.ingress.kubernetes.io/proxy-next-upstream: "http_502 error timeout"
26+ nginx.ingress.kubernetes.io/auth-secret: {{ include "octopodAppAuthSecretName" . }}
27+ nginx.ingress.kubernetes.io/auth-secret-type: auth-file
28+ nginx.ingress.kubernetes.io/auth-type: basic
29+ nginx.ingress.kubernetes.io/enable-cors: "true"
30+ nginx.ingress.kubernetes.io/cors-allow-origin: {{ printf "%s://%s" (include "httpScheme" .) (include "uiIngressHost" .) | quote }}
31+ nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, PUT, DELETE, PATCH, OPTIONS"
32+ {{- with .Values.ingress.app.annotations }}
33+ {{- toYaml . | nindent 4 }}
34+ {{- end }}
35+spec:
36+ {{- if .Values.ingress.tls.enabled }}
37+ tls:
38+ - hosts:
39+ - {{ include "appIngressHost" . }}
40+ secretName: {{ $fullName }}-app-tls
41+ {{- end }}
42+ rules:
43+ - host: {{ include "appIngressHost" . }}
44+ http:
45+ paths:
46+ - path: /
47+ pathType: ImplementationSpecific
48+ backend:
49+ service:
50+ name: {{ $fullName }}
51+ port:
52+ number: {{ .Values.service.ports.app }}
53+{{- end }}
charts/octopod/templates/ingress-powerapp.yamlnew file+47
@@ -0,0 +1,47 @@
1+{{- if .Values.ingress.enabled -}}
2+{{- $fullName := include "octopod.fullname" . -}}
3+{{- $kubeVersion := .Capabilities.KubeVersion.Version }}
4+{{ if semverCompare ">= 1.19.0-0" $kubeVersion }}
5+apiVersion: networking.k8s.io/v1
6+{{ else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" }}
7+apiVersion: networking.k8s.io/v1beta1
8+{{ else }}
9+apiVersion: extensions/v1beta1
10+{{ end }}
11+kind: Ingress
12+metadata:
13+ name: {{ $fullName }}-powerapp
14+ labels:
15+ {{- include "octopod.labels" . | nindent 4 }}
16+ annotations:
17+ {{- if .Values.ingress.tls.enabled }}
18+ kubernetes.io/tls-acme: "true"
19+ cert-manager.io/cluster-issuer: {{ .Values.ingress.tls.clusterIssuer | quote }}
20+ {{- end }}
21+ kubernetes.io/ingress.class: {{ .Values.ingress.ingressClass | quote }}
22+ nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
23+ nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
24+ nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
25+ nginx.ingress.kubernetes.io/proxy-next-upstream: "http_502 error timeout"
26+ {{- with .Values.ingress.powerApp.annotations }}
27+ {{- toYaml . | nindent 4 }}
28+ {{- end }}
29+spec:
30+ {{- if .Values.ingress.tls.enabled }}
31+ tls:
32+ - hosts:
33+ - {{ include "powerAppIngressHost" . }}
34+ secretName: {{ $fullName }}-powerapp-tls
35+ {{- end }}
36+ rules:
37+ - host: {{ include "powerAppIngressHost" . }}
38+ http:
39+ paths:
40+ - path: /
41+ pathType: ImplementationSpecific
42+ backend:
43+ service:
44+ name: {{ $fullName }}
45+ port:
46+ number: {{ .Values.service.ports.powerApp }}
47+{{- end }}
charts/octopod/templates/ingress-ui.yamlnew file+47
@@ -0,0 +1,47 @@
1+{{- if .Values.ingress.enabled -}}
2+{{- $fullName := include "octopod.fullname" . -}}
3+{{- $kubeVersion := .Capabilities.KubeVersion.Version }}
4+{{ if semverCompare ">= 1.19.0-0" $kubeVersion }}
5+apiVersion: networking.k8s.io/v1
6+{{ else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" }}
7+apiVersion: networking.k8s.io/v1beta1
8+{{ else }}
9+apiVersion: extensions/v1beta1
10+{{ end }}
11+kind: Ingress
12+metadata:
13+ name: {{ $fullName }}-ui
14+ labels:
15+ {{- include "octopod.labels" . | nindent 4 }}
16+ annotations:
17+ {{- if .Values.ingress.tls.enabled }}
18+ kubernetes.io/tls-acme: "true"
19+ cert-manager.io/cluster-issuer: {{ .Values.ingress.tls.clusterIssuer | quote }}
20+ {{- end }}
21+ kubernetes.io/ingress.class: {{ .Values.ingress.ingressClass | quote }}
22+ nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
23+ nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
24+ nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
25+ nginx.ingress.kubernetes.io/proxy-next-upstream: "http_502 error timeout"
26+ {{- with .Values.ingress.ui.annotations }}
27+ {{- toYaml . | nindent 4 }}
28+ {{- end }}
29+spec:
30+ {{- if .Values.ingress.tls.enabled }}
31+ tls:
32+ - hosts:
33+ - {{ include "uiIngressHost" . }}
34+ secretName: {{ $fullName }}-ui-tls
35+ {{- end }}
36+ rules:
37+ - host: {{ include "uiIngressHost" . }}
38+ http:
39+ paths:
40+ - path: /
41+ pathType: ImplementationSpecific
42+ backend:
43+ service:
44+ name: {{ $fullName }}
45+ port:
46+ number: {{ .Values.service.ports.ui }}
47+{{- end }}
charts/octopod/templates/ingress-ws.yamlnew file+47
@@ -0,0 +1,47 @@
1+{{- if .Values.ingress.enabled -}}
2+{{- $fullName := include "octopod.fullname" . -}}
3+{{- $kubeVersion := .Capabilities.KubeVersion.Version }}
4+{{ if semverCompare ">= 1.19.0-0" $kubeVersion }}
5+apiVersion: networking.k8s.io/v1
6+{{ else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" }}
7+apiVersion: networking.k8s.io/v1beta1
8+{{ else }}
9+apiVersion: extensions/v1beta1
10+{{ end }}
11+kind: Ingress
12+metadata:
13+ name: {{ $fullName }}-ws
14+ labels:
15+ {{- include "octopod.labels" . | nindent 4 }}
16+ annotations:
17+ {{- if .Values.ingress.tls.enabled }}
18+ kubernetes.io/tls-acme: "true"
19+ cert-manager.io/cluster-issuer: {{ .Values.ingress.tls.clusterIssuer | quote }}
20+ {{- end }}
21+ kubernetes.io/ingress.class: {{ .Values.ingress.ingressClass | quote }}
22+ nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
23+ nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
24+ nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
25+ nginx.ingress.kubernetes.io/proxy-next-upstream: "http_502 error timeout"
26+ {{- with .Values.ingress.ws.annotations }}
27+ {{- toYaml . | nindent 4 }}
28+ {{- end }}
29+spec:
30+ {{- if .Values.ingress.tls.enabled }}
31+ tls:
32+ - hosts:
33+ - {{ include "wsIngressHost" . }}
34+ secretName: {{ $fullName }}-ws-tls
35+ {{- end }}
36+ rules:
37+ - host: {{ include "wsIngressHost" . }}
38+ http:
39+ paths:
40+ - path: /
41+ pathType: ImplementationSpecific
42+ backend:
43+ service:
44+ name: {{ $fullName }}
45+ port:
46+ number: {{ .Values.service.ports.ws }}
47+{{- end }}
charts/octopod/templates/nginx-configmap.yamlnew file+43
@@ -0,0 +1,43 @@
1+{{- $octopodAppAuthPassword := include "octopodUiAuthSecret" . -}}
2+{{- $etag := sha256sum (now | date "Mon Jan 2 15:04:05 MSK 2021") -}}
3+apiVersion: v1
4+kind: ConfigMap
5+metadata:
6+ name: {{ include "octopod.fullname" . }}-nginx-config
7+ labels:
8+ {{- include "octopod.labels" . | nindent 4 }}
9+data:
10+ app.conf: |
11+ server {
12+ listen 80 default_server;
13+ server_name _;
14+ root /www;
15+ index index.html;
16+ error_page 404 =200 /index.html;
17+ charset utf-8;
18+ location ~* \.(html|css|js|xml)$ {
19+ gzip_static on;
20+ add_header 'ETag' '{{ $etag }}';
21+ }
22+ }
23+ config.json: |
24+ {
25+ "app_url": "{{ printf "%s://%s" (include "httpScheme" .) (include "appIngressHost" . )}}",
26+ "ws_url": "{{ printf "%s://%s" (include "wsScheme" .) (include "wsIngressHost" .) }}",
27+ "app_auth": "Basic {{ printf "octopod:%s" $octopodAppAuthPassword | b64enc }}",
28+ {{- if .Values.kubernetesDashboard.enabled }}
29+ "kubernetes_dashboard_url_template": "{{ .Values.kubernetesDashboard.url }}/#/search?namespace={{ .Values.octopod.deploymentNamespace }}&q="
30+ {{- else }}
31+ "kubernetes_dashboard_url_template": null
32+ {{- end }}
33+ }
34+---
35+apiVersion: v1
36+kind: Secret
37+type: Opaque
38+metadata:
39+ name: {{ include "octopodAppAuthSecretName" . }}
40+ labels:
41+ {{- include "octopod.labels" . | nindent 4 }}
42+data:
43+ auth: {{ htpasswd "octopod" $octopodAppAuthPassword | b64enc }}
charts/octopod/templates/octopod-app-ingress.yamldeleted−32
@@ -1,32 +0,0 @@
1−apiVersion: extensions/v1beta1
2−kind: Ingress
3−metadata:
4− name: {{ .Release.Name }}-app-nginx-ingress
5− namespace: {{ .Values.namespace }}
6− annotations:
7− kubernetes.io/ingress.class: "nginx"
8− kubernetes.io/tls-acme: "true"
9− cert-manager.io/issuer: "{{ .Release.Name }}-certs"
10− nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
11− nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
12− nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
13− nginx.ingress.kubernetes.io/proxy-next-upstream: "http_502 error timeout"
14− nginx.ingress.kubernetes.io/auth-secret: octopod-basic-auth
15− nginx.ingress.kubernetes.io/auth-secret-type: auth-file
16− nginx.ingress.kubernetes.io/auth-type: basic
17− nginx.ingress.kubernetes.io/enable-cors: "true"
18− nginx.ingress.kubernetes.io/cors-allow-origin: "https://{{ .Values.domain }}"
19− nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, PUT, DELETE, PATCH, OPTIONS"
20−spec:
21− tls:
22− - hosts:
23− - {{ .Values.app_domain }}
24− secretName: {{ .Release.Name }}-app-tls
25− rules:
26− - host: {{ .Values.app_domain }}
27− http:
28− paths:
29− - path: /
30− backend:
31− serviceName: {{ .Release.Name }}
32− servicePort: 81
charts/octopod/templates/octopod-configmap.yaml+24−15
@@ -1,19 +1,28 @@
11apiVersion: v1
22kind: ConfigMap
33metadata:
4− name: {{ .Release.Name }}-config
5− namespace: {{ .Values.namespace }}
4+ name: {{ include "octopod.fullname" . }}
5+ labels:
6+ {{- include "octopod.labels" . | nindent 4 }}
67data:
7− PROJECT_NAME: {{ .Values.project_name }}
8− BASE_DOMAIN: {{ .Values.base_domain }}
9− NAMESPACE: {{ .Values.target_namespace }}
10− STATUS_UPDATE_TIMEOUT: "{{ .Values.status_update_timeout }}"
11− ARCHIVE_RETENTION: "1209600"
12− CREATION_COMMAND: /utils/create
13− UPDATE_COMMAND: /utils/update
14− ARCHIVE_COMMAND: /utils/archive
15− CHECKING_COMMAND: /utils/check
16− CLEANUP_COMMAND: /utils/cleanup
17− ARCHIVE_CHECKING_COMMAND: /utils/archive_check
18− TAG_CHECKING_COMMAND: /utils/tag_check
19− INFO_COMMAND: /utils/info
8+ PROJECT_NAME: {{ .Values.octopod.projectName | quote }}
9+ BASE_DOMAIN: {{ .Values.octopod.baseDomain | quote }}
10+ NAMESPACE: {{ .Values.octopod.deploymentNamespace | quote }}
11+ STATUS_UPDATE_TIMEOUT: {{ .Values.octopod.statusUpdateTimeout | quote }}
12+ ARCHIVE_RETENTION: {{ .Values.octopod.archiveRetention | quote }}
13+ CREATION_COMMAND: {{ printf "%s/create" (include "controlScriptsPath" .) | quote }}
14+ UPDATE_COMMAND: {{ printf "%s/update" (include "controlScriptsPath" .) | quote }}
15+ ARCHIVE_COMMAND: {{ printf "%s/archive" (include "controlScriptsPath" .) | quote }}
16+ CHECKING_COMMAND: {{ printf "%s/check" (include "controlScriptsPath" .) | quote }}
17+ CLEANUP_COMMAND: {{ printf "%s/cleanup" (include "controlScriptsPath" .) | quote }}
18+ ARCHIVE_CHECKING_COMMAND: {{ printf "%s/archive_check" (include "controlScriptsPath" .) | quote }}
19+ CONFIG_CHECKING_COMMAND: {{ printf "%s/config_check" (include "controlScriptsPath" .) | quote }}
20+ INFO_COMMAND: {{ printf "%s/info" (include "controlScriptsPath" .) | quote }}
21+ DEPLOYMENT_CONFIG_COMMAND: {{ printf "%s/deployment_overrides" (include "controlScriptsPath" .) | quote }}
22+ DEPLOYMENT_KEYS_COMMAND: {{ printf "%s/deployment_keys" (include "controlScriptsPath" .) | quote }}
23+ APPLICATION_CONFIG_COMMAND: {{ printf "%s/app_overrides" (include "controlScriptsPath" .) | quote }}
24+ APPLICATION_KEYS_COMMAND: {{ printf "%s/app_keys" (include "controlScriptsPath" .) | quote }}
25+ UNARCHIVE_COMMAND: {{ printf "%s/unarchive" (include "controlScriptsPath" .) | quote }}
26+ {{- range $name, $value := .Values.octopod.env }}
27+ {{ $name }}: {{ $value | quote }}
28+ {{- end }}
charts/octopod/templates/octopod-deployment.yamldeleted−153
@@ -1,153 +0,0 @@
1−apiVersion: apps/v1
2−kind: Deployment
3−metadata:
4− name: {{ .Release.Name }}
5− namespace: {{ .Values.namespace }}
6−spec:
7− replicas: {{ .Values.replicas }}
8− selector:
9− matchLabels:
10− app: {{ .Release.Name }}
11− template:
12− metadata:
13− name: {{ .Release.Name }}
14− labels:
15− app: {{ .Release.Name }}
16− annotations:
17− checksum/config: "{{ .Values.global.deploy_checksum }}"
18− spec:
19− serviceAccountName: {{ .Values.service_account }}
20− nodeSelector:
21− role: {{ .Values.nodeselector }}
22− terminationGracePeriodSeconds: 600
23− initContainers:
24− - name: copy-utils
25− image: {{ .Values.global.utils_image_prefix }}/{{ .Values.global.utils_image }}:{{ .Values.global.utils_image_tag }}
26− command:
27− - sh
28− - -c
29− - 'cp /utils/* /copy/'
30− volumeMounts:
31− - name: utils
32− mountPath: /copy
33−
34− - name: init
35− image: {{ .Values.global.image_prefix }}/{{ .Values.global.image }}:{{ .Values.global.image_tag }}
36− command:
37− - sh
38− - -c
39− - '/utils/init'
40− securityContext:
41− runAsGroup: 1000
42− runAsUser: 1000
43− volumeMounts:
44− - name: home
45− mountPath: /home/octopod
46− - name: utils
47− mountPath: /utils
48−
49− - name: copy-www
50− image: {{ .Values.global.image_prefix }}/{{ .Values.global.image }}:{{ .Values.global.image_tag }}
51− command:
52− - sh
53− - -c
54− - |
55− set -ex
56− cp -a /www/* /copy/
57− find /www -type f -exec touch {} +
58− volumeMounts:
59− - name: www
60− mountPath: /copy
61−
62− containers:
63− - name: main
64− image: {{ .Values.global.image_prefix }}/{{ .Values.global.image }}:{{ .Values.global.image_tag }}
65− ports:
66− - containerPort: {{ .Values.port }}
67− protocol: TCP
68− - containerPort: {{ .Values.ui_port }}
69− protocol: TCP
70− args:
71− - "--port"
72− - "{{ .Values.port }}"
73− - "--ui-port"
74− - "{{ .Values.ui_port }}"
75− - "--ws-port"
76− - "{{ .Values.ws_port }}"
77− - "--db"
78− - "host='{{ .Values.pg_host }}' port=5432 user='octopod' password='octopod'"
79− - "--db-pool-size"
80− - "10"
81− - "--tls-cert-path"
82− - "/tls/server_cert.pem"
83− - "--tls-key-path"
84− - "/tls/server_key.pem"
85− - "--tls-store-path"
86− - "/tls_store"
87− envFrom:
88− - configMapRef:
89− name: {{ .Release.Name }}-config
90− securityContext:
91− runAsGroup: 1000
92− runAsUser: 1000
93− volumeMounts:
94− - name: home
95− mountPath: /home/octopod
96− - name: utils
97− mountPath: /utils
98− - name: certs
99− mountPath: /tls/server_cert.pem
100− subPath: server_cert.pem
101− - name: certs
102− mountPath: /tls/server_key.pem
103− subPath: server_key.pem
104− - name: certs
105− mountPath: /tls_store/server_cert.pem
106− subPath: server_cert.pem
107− resources:
108− requests:
109− cpu: 0.2
110− memory: 256Mi
111− limits:
112− cpu: 0.2
113− memory: 512Mi
114− readinessProbe:
115− httpGet:
116− port: {{ .Values.ui_port }}
117− path: /api/v1/ping
118− periodSeconds: 20
119− livenessProbe:
120− httpGet:
121− port: {{ .Values.ui_port }}
122− path: /api/v1/ping
123− initialDelaySeconds: 15
124− periodSeconds: 5
125−
126− - name: nginx
127− image: nginx:1.17.5
128− volumeMounts:
129− - name: nginx-config
130− mountPath: /etc/nginx/conf.d/app.conf
131− subPath: app.conf
132− - name: nginx-config
133− mountPath: /www/config.json
134− subPath: config.json
135− - name: www
136− mountPath: /www
137− ports:
138− - containerPort: 80
139− protocol: TCP
140−
141− volumes:
142− - name: home
143− emptyDir: {}
144− - name: utils
145− emptyDir: {}
146− - name: www
147− emptyDir: {}
148− - name: nginx-config
149− configMap:
150− name: {{ .Release.Name }}-nginx-config
151− - name: certs
152− configMap:
153− name: octopod-certs
charts/octopod/templates/octopod-ingress.yamldeleted−34
@@ -1,34 +0,0 @@
1−apiVersion: extensions/v1beta1
2−kind: Ingress
3−metadata:
4− name: {{ .Release.Name }}-nginx-ingress
5− namespace: {{ .Values.namespace }}
6− annotations:
7− kubernetes.io/ingress.class: "nginx"
8− kubernetes.io/tls-acme: "true"
9− cert-manager.io/issuer: "{{ .Release.Name }}-certs"
10− nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
11− nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
12− nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
13− nginx.ingress.kubernetes.io/proxy-next-upstream: "http_502 error timeout"
14−
15− {{- if .Values.global.auth_url }}
16− nginx.ingress.kubernetes.io/auth-url: "{{ .Values.global.auth_url }}"
17− {{- end }}
18−
19− {{- if .Values.global.auth_signin }}
20− nginx.ingress.kubernetes.io/auth-signin: "{{ .Values.global.auth_signin }}"
21− {{- end }}
22−spec:
23− tls:
24− - hosts:
25− - {{ .Values.domain }}
26− secretName: {{ .Release.Name }}-tls
27− rules:
28− - host: {{ .Values.domain }}
29− http:
30− paths:
31− - path: /
32− backend:
33− serviceName: {{ .Release.Name }}
34− servicePort: 80
charts/octopod/templates/octopod-issuer.yamldeleted−18
@@ -1,18 +0,0 @@
1−apiVersion: cert-manager.io/v1
2−kind: Issuer
3−metadata:
4− name: {{ .Release.Name }}-certs
5− namespace: {{ .Release.Namespace }}
6−spec:
7− acme:
8− email: {{ .Values.acme_registration_email }}
9− server: https://acme-v02.api.letsencrypt.org/directory
10− privateKeySecretRef:
11− name: {{ .Release.Name }}-letsencrypt
12− # ACME HTTP-01 provider configurations
13− solvers:
14− # An empty 'selector' means that this solver matches all domains
15− - selector: {}
16− http01:
17− ingress:
18− class: nginx
charts/octopod/templates/octopod-migration-job.yamldeleted−75
@@ -1,75 +0,0 @@
1−{{- if .Values.migrations }}
2−apiVersion: batch/v1
3−kind: Job
4−metadata:
5− name: {{ .Release.Name }}-migration-job
6− namespace: {{ .Release.Namespace }}
7−
8− annotations:
9− "helm.sh/hook": pre-install,pre-upgrade
10− "helm.sh/hook-delete-policy": hook-succeeded
11−
12−spec:
13− activeDeadlineSeconds: 600
14− template:
15− spec:
16− containers:
17−
18− - name: copy
19− image: {{ .Values.global.image_prefix }}/{{ .Values.global.image }}:{{ .Values.global.image_tag }}
20− command:
21− - "bash"
22− - "-ec"
23− - |
24− set -ex
25−
26− # copy migrations
27− cp -av /migrations/* /mymigrations
28−
29− # create sqitch.conf
30− echo '[core]' > /mymigrations/sqitch.conf
31− echo 'engine = pg' >> /mymigrations/sqitch.conf
32− echo 'plan_file = sqitch.plan' >> /mymigrations/sqitch.conf
33− echo 'top_dir = .' >> /mymigrations/sqitch.conf
34− echo '[engine "pg"]' >> /mymigrations/sqitch.conf
35− echo ' registry = sqitch' >> /mymigrations/sqitch.conf
36− echo '[deploy]' >> /mymigrations/sqitch.conf
37− echo ' verify = true' >> /mymigrations/sqitch.conf
38− echo '[rebase]' >> /mymigrations/sqitch.conf
39− echo ' verify = true' >> /mymigrations/sqitch.conf
40− echo '[target "octopod"]' >> /mymigrations/sqitch.conf
41− echo 'uri = db:pg://{{ .Values.connections.pg_instance }}/{{ template "dbname" . }}' >> /mymigrations/sqitch.conf
42− volumeMounts:
43− - name: migrations
44− mountPath: /mymigrations
45−
46− - name: migrations
47− image: {{ .Values.global.image_prefix }}/{{ .Values.global.image }}:sqitch-v2.0.0
48− command:
49− - "bash"
50− - "-ec"
51− - |
52− set -ex
53−{{- if .Values.seed }}
54− echo 'check db'
55− POSTGRESQL_CONN="psql postgresql://{{ .Values.connections.pg_instance }}/postgres"
56− DBNAME={{ template "dbname" . }}
57− ($POSTGRESQL_CONN -Atc "SELECT count(*) FROM pg_database WHERE lower(datname) = lower('$DBNAME');" | grep 1) || $POSTGRESQL_CONN -Atc "create database $DBNAME;"
58−{{- end }}
59− echo 'run migrations...'
60− cd /migrations && /usr/local/bin/sqitch deploy octopod
61−{{- if .Values.seed }}
62− echo 'seed'
63− DB_CONN="psql postgresql://{{ .Values.connections.pg_instance }}/{{ template "dbname" . }}"
64− cd /migrations && $DB_CONN -1 -f seeds.sql || echo 'ok'
65−{{- end }}
66− volumeMounts:
67− - name: migrations
68− mountPath: /migrations
69−
70− volumes:
71− - name: migrations
72− emptyDir: {}
73− restartPolicy: Never
74− backoffLimit: 2
75−{{- end }}
charts/octopod/templates/octopod-nginx-configmap.yamldeleted−20
@@ -1,20 +0,0 @@
1−apiVersion: v1
2−kind: ConfigMap
3−metadata:
4− name: {{ .Release.Name }}-nginx-config
5− namespace: {{ .Values.namespace }}
6−data:
7− app.conf: |
8− server {
9− listen 80 default_server;
10− server_name _;
11− root /www;
12− index index.html;
13− error_page 404 =200 /index.html;
14− }
15− config.json: |
16− {
17− "app_url": "https://{{ .Values.app_domain }}",
18− "ws_url": "wss://{{ .Values.ws_domain }}",
19− "app_auth": "Basic {{ .Values.basic_auth_token }}"
20− }
charts/octopod/templates/octopod-power-app-ingress.yamldeleted−25
@@ -1,25 +0,0 @@
1−apiVersion: extensions/v1beta1
2−kind: Ingress
3−metadata:
4− name: {{ .Release.Name }}-power-app-nginx-ingress
5− namespace: {{ .Values.namespace }}
6− annotations:
7− kubernetes.io/ingress.class: "nginx"
8− nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
9− nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
10− nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
11− nginx.ingress.kubernetes.io/proxy-next-upstream: "http_502 error timeout"
12− nginx.ingress.kubernetes.io/ssl-passthrough: "true"
13− nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
14−spec:
15− rules:
16− - host: {{ .Values.power_app_domain }}
17− http:
18− paths:
19− - path: /
20− backend:
21− serviceName: {{ .Release.Name }}
22− servicePort: 443
23− tls:
24− - hosts:
25− - {{ .Values.power_app_domain }}
charts/octopod/templates/octopod-service.yamldeleted−23
@@ -1,23 +0,0 @@
1−apiVersion: v1
2−kind: Service
3−metadata:
4− name: {{ .Release.Name }}
5− namespace: {{ .Values.namespace }}
6− labels:
7− app: {{ .Release.Name }}
8−spec:
9− selector:
10− app: {{ .Release.Name }}
11− ports:
12− - name: octopod-power-app
13− port: 443
14− targetPort: {{ .Values.port }}
15− - name: octopod-ui
16− port: 80
17− targetPort: 80
18− - name: octopod-app
19− port: 81
20− targetPort: {{ .Values.ui_port }}
21− - name: octopod-ws
22− port: 82
23− targetPort: {{ .Values.ws_port }}
charts/octopod/templates/octopod-ws-ingress.yamldeleted−26
@@ -1,26 +0,0 @@
1−apiVersion: extensions/v1beta1
2−kind: Ingress
3−metadata:
4− name: {{ .Release.Name }}-ws-nginx-ingress
5− namespace: {{ .Values.namespace }}
6− annotations:
7− kubernetes.io/ingress.class: "nginx"
8− kubernetes.io/tls-acme: "true"
9− cert-manager.io/issuer: "{{ .Release.Name }}-certs"
10− nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
11− nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
12− nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
13− nginx.ingress.kubernetes.io/proxy-next-upstream: "http_502 error timeout"
14−spec:
15− tls:
16− - hosts:
17− - {{ .Values.ws_domain }}
18− secretName: {{ .Release.Name }}-ws-tls
19− rules:
20− - host: {{ .Values.ws_domain }}
21− http:
22− paths:
23− - path: /
24− backend:
25− serviceName: {{ .Release.Name }}
26− servicePort: 82
charts/octopod/templates/rbac.yamlnew file+30
@@ -0,0 +1,30 @@
1+{{- if and .Values.rbac.create (eq .Values.serviceAccount.create true) -}}
2+apiVersion: rbac.authorization.k8s.io/v1
3+kind: ClusterRole
4+metadata:
5+ name: {{ include "octopod.fullname" . }}
6+ labels:
7+ {{- include "octopod.labels" . | nindent 4 }}
8+rules:
9+- apiGroups:
10+ - '*'
11+ resources:
12+ - '*'
13+ verbs:
14+ - '*'
15+---
16+apiVersion: rbac.authorization.k8s.io/v1
17+kind: ClusterRoleBinding
18+metadata:
19+ name: {{ include "octopod.fullname" . }}
20+ labels:
21+ {{- include "octopod.labels" . | nindent 4 }}
22+roleRef:
23+ kind: ClusterRole
24+ apiGroup: rbac.authorization.k8s.io
25+ name: {{ include "octopod.fullname" . }}
26+subjects:
27+ - kind: ServiceAccount
28+ name: {{ include "octopod.serviceAccountName" . }}
29+ namespace: {{ .Release.Namespace }}
30+{{- end -}}
charts/octopod/templates/service.yamlnew file+16
@@ -0,0 +1,16 @@
1+apiVersion: v1
2+kind: Service
3+metadata:
4+ name: {{ include "octopod.fullname" . }}
5+ labels:
6+ {{- include "octopod.labels" . | nindent 4 }}
7+spec:
8+ type: {{ .Values.service.type }}
9+ ports:
10+{{- range $portName, $portNumber := .Values.service.ports }}
11+ - name: octopod-{{ $portName | lower }}
12+ port: {{ $portNumber }}
13+ targetPort: {{ $portNumber }}
14+{{- end }}
15+ selector:
16+ {{- include "octopod.selectorLabels" . | nindent 4 }}
charts/octopod/templates/serviceaccount.yamlnew file+12
@@ -0,0 +1,12 @@
1+{{- if .Values.serviceAccount.create -}}
2+apiVersion: v1
3+kind: ServiceAccount
4+metadata:
5+ name: {{ include "octopod.serviceAccountName" . }}
6+ labels:
7+ {{- include "octopod.labels" . | nindent 4 }}
8+ {{- with .Values.serviceAccount.annotations }}
9+ annotations:
10+ {{- toYaml . | nindent 4 }}
11+ {{- end }}
12+{{- end }}
charts/octopod/values.yaml+119−38
@@ -1,38 +1,119 @@
1−global:
2− image_prefix:
3− image: octopod
4− octo_image: octo
5− image_tag:
6− utils_image_prefix:
7− utils_image:
8− utils_image_tag:
9−
10−namespace: octopod
11−target_namespace: deployment
12−nodeselector: stand
13−service_account: octopod
14−port: 4443
15−ui_port: 4000
16−ws_port: 4020
17−dbname: octopod
18−seed: false
19−migrations: true
20−replicas: 1
21−domain: octopod.stage.example.com
22−app_domain: octopod-app.stage.example.com
23−ws_domain: octopod-ws.stage.example.com
24−power_app_domain: octopod-power-app.stage.example.com
25−base_domain: stage.example.com
26−project_name: Octopod
27−status_update_timeout: 600
28−acme_registration_email:
29−basic_auth_token:
30−connections:
31− pg_instance: octopod:octopod@octopod-infra-postgres-0.octopod-infra-postgres.octopod:5432
32−pg_host: octopod-infra-postgres-0.octopod-infra-postgres.octopod
33−requests:
34− cpu: 200m
35− memory: 256Mi
36−limits:
37− cpu: 200m
38− memory: 512Mi
1+# Default values for octopod.
2+# This is a YAML-formatted file.
3+# Declare variables to be passed into your templates.
4+
5+replicaCount: 1
6+
7+image:
8+ repository: typeable/octopod
9+ pullPolicy: IfNotPresent
10+ # Overrides the image tag whose default is the chart appVersion.
11+ tag: ""
12+
13+imagePullSecrets: []
14+nameOverride: ""
15+fullnameOverride: ""
16+
17+serviceAccount:
18+ # Specifies whether a service account should be created
19+ create: true
20+ # Annotations to add to the service account
21+ annotations: {}
22+ # The name of the service account to use.
23+ # If not set and create is true, a name is generated using the fullname template
24+ name: ""
25+rbac:
26+ create: true
27+podAnnotations: {}
28+
29+podSecurityContext: {}
30+ # fsGroup: 2000
31+
32+securityContext:
33+ runAsUser: 1000
34+ runAsGroup: 1000
35+ # capabilities:
36+ # drop:
37+ # - ALL
38+ # readOnlyRootFilesystem: true
39+ # runAsNonRoot: true
40+
41+service:
42+ type: ClusterIP
43+ ports:
44+ powerApp: 4443
45+ ui: 80
46+ app: 4000
47+ ws: 4020
48+
49+ingress:
50+ enabled: true
51+ ingressClass: nginx
52+ tls:
53+ enabled: true
54+ clusterIssuer: letsencrypt
55+ powerApp:
56+ annotations: {}
57+ ui:
58+ annotations: {}
59+ app:
60+ annotations: {}
61+ ws:
62+ annotations: {}
63+
64+resources:
65+ limits:
66+ cpu: 200m
67+ memory: 512Mi
68+ requests:
69+ cpu: 200m
70+ memory: 256Mi
71+
72+nodeSelector: {}
73+
74+tolerations: []
75+
76+affinity: {}
77+
78+octopod:
79+ projectName: Octopod
80+ deploymentNamespace: octopod-deployment
81+ baseDomain: ""
82+ statusUpdateTimeout: "600"
83+ archiveRetention: "1209600"
84+ migrations:
85+ enabled: true
86+ env:
87+ HELM_BIN: "/utils/helm"
88+ DEFAULTS: |
89+ {
90+ "chart_name": "wordpress",
91+ "chart_repo_url": "https://charts.bitnami.com/bitnami",
92+ "chart_version": "12.0.0",
93+ "default_overrides": [
94+ "ingress.enabled=true"
95+ ]
96+ }
97+ vaultEnv: {}
98+controlScripts:
99+ image:
100+ repository: typeable/octopod-helm-control-scripts
101+ pullPolicy: IfNotPresent
102+ tag: 0.2.4
103+sqitch:
104+ image:
105+ repository: typeable/sqitch
106+ pullPolicy: IfNotPresent
107+ tag: v2.0.0
108+postgresql:
109+ enabled: true
110+ postgresqlUsername: octopod
111+ postgresqlDatabase: octopod
112+ image:
113+ tag: 12.7.0-debian-10-r51
114+vault:
115+ enabled: false
116+ clusterName: ""
117+kubernetesDashboard:
118+ enabled: false
119+ url: ""
charts/pvc-control/.helmignoredeleted−22
@@ -1,22 +0,0 @@
1−# Patterns to ignore when building packages.
2−# This supports shell glob matching, relative path matching, and
3−# negation (prefixed with !). Only one pattern per line.
4−.DS_Store
5−# Common VCS dirs
6−.git/
7−.gitignore
8−.bzr/
9−.bzrignore
10−.hg/
11−.hgignore
12−.svn/
13−# Common backup files
14−*.swp
15−*.bak
16−*.tmp
17−*~
18−# Various IDEs
19−.project
20−.idea/
21−*.tmproj
22−.vscode/
charts/pvc-control/Chart.yamldeleted−5
@@ -1,5 +0,0 @@
1−apiVersion: v1
2−appVersion: "1.0"
3−description: A Helm chart for Kubernetes
4−name: pvc-control
5−version: 0.1.0
charts/pvc-control/templates/pvc-control-clusterrole.yamldeleted−8
@@ -1,8 +0,0 @@
1−apiVersion: rbac.authorization.k8s.io/v1
2−kind: ClusterRole
3−metadata:
4− name: pvc-control-clusterrole
5−rules:
6− - apiGroups: [""]
7− resources: ["persistentvolumeclaims"]
8− verbs: ["list", "delete", "deletecollection"]
charts/pvc-control/templates/pvc-control-rolebinding.yamldeleted−13
@@ -1,13 +0,0 @@
1−apiVersion: rbac.authorization.k8s.io/v1
2−kind: RoleBinding
3−metadata:
4− name: {{ .Values.serviceaccount }}-pvc-control-rolebinding
5− namespace: {{ .Values.namespace }}
6−roleRef:
7− kind: ClusterRole
8− apiGroup: rbac.authorization.k8s.io
9− name: pvc-control-clusterrole
10−subjects:
11− - kind: ServiceAccount
12− name: {{ .Values.serviceaccount }}
13− namespace: {{ .Values.octopod_namespace | default .Values.namespace }}
charts/pvc-control/values.yamldeleted−3
@@ -1,3 +0,0 @@
1−namespace: deployment
2−octopod_namespace: octopod
3−serviceaccount: octopod
default.nix+76−31
@@ -1,38 +1,83 @@
11{ sources ? import ./nix/sources.nix
2−, reflex-platform ? sources.reflex-platform
3−, hls ? false
2+, haskellNix ? import sources.haskellNix { inherit system; }
3+, pkgsSrc ? import haskellNix.sources.nixpkgs-2105
4+, pkgs ? pkgsSrc (haskellNix.nixpkgsArgs // { inherit system; })
5+, nix-filter ? import sources.nix-filter
6+, system ? builtins.currentSystem
7+, prod ? false
48}:
5−(import reflex-platform { }).project ({ pkgs, ... }:
6− let foldOs = pkgs.lib.foldl' pkgs.lib.composeExtensions (self: super: { });
7− in
8− {
9− useWarp = true;
9+let
10+ octopod-css = import ./octopod-css { inherit pkgsSrc; };
11+ insaneOptimizationFlags = [
12+ "-O2"
13+ "-fexpose-all-unfoldings"
14+ "-fspecialise-aggressively"
15+ ];
16+ addLocalOptions = x:
17+ if prod then x // {
18+ ghcOptions = [ "-Werror" ] ++ insaneOptimizationFlags;
19+ }
20+ else x // { ghcOptions = [ "-O0" ]; };
1021
11− packages = {
12− octopod-common = ./octopod-common;
13− octopod-frontend = ./octopod-frontend;
14− octopod-backend = ./octopod-backend;
15− octo-cli = ./octo-cli;
16− octopod-api = ./octopod-api;
22+ hsPkgs = pkgs.haskell-nix.cabalProject {
23+ src = nix-filter {
24+ root = ./.;
25+ name = "octopod";
26+ include = [
27+ ./octopod-backend/octopod-backend.cabal
28+ ./octo-cli/octo-cli.cabal
29+ ./octopod-api/octopod-api.cabal
30+ ./octopod-common/octopod-common.cabal
31+ ./octopod-frontend/octopod-frontend.cabal
32+ ./cabal.project
33+ ];
1734 };
1835
19− overrides = foldOs [
20− (import ./nix/haskell-language-server-overrides.nix {
21− inherit (pkgs.haskell) lib;
22− inherit sources;
36+ modules = [
37+ {
38+ ghcOptions = insaneOptimizationFlags;
39+ dontStrip = false;
40+ dontPatchELF = false;
41+ enableDeadCodeElimination = true;
42+ packages.octopod-backend = addLocalOptions (
43+ if prod
44+ then {
45+ src = pkgs.runCommand "octopod-backend-src" { }
46+ ''
47+ mkdir -p $out
48+ cp -r ${./octopod-backend}/* $out
49+ cp -r ${builtins.path { path = ./.git; name = "dot-git"; }}/ $out/.git/
50+ '';
51+ components.exes.octopod-exe = {
52+ build-tools =
53+ pkgs.lib.mkForce [ pkgs.buildPackages.buildPackages.gitReallyMinimal ];
54+ extraSrcFiles = [ ".git/**/*" ];
55+ };
56+ }
57+ else { src = ./octopod-backend; }
58+ );
59+ packages.octo-cli = addLocalOptions { src = ./octo-cli; };
60+ packages.octopod-api = addLocalOptions { src = ./octopod-api; };
61+ packages.octopod-frontend = addLocalOptions { src = ./octopod-frontend; };
62+ packages.octopod-common = addLocalOptions { src = ./octopod-common; };
2363 }
24− )
25− (import ./nix/octopod-overrides.nix {
26− inherit (pkgs.haskell) lib;
27− inherit sources;
28− }
29− )
3064 ];
31− shellToolOverrides = ghc: super:
32− if hls then { inherit (ghc) haskell-language-server; }
33− else { };
34− shells = {
35− ghc = [ "octopod-common" "octopod-backend" "octopod-frontend" "octopod-api" "octo-cli" ];
36− ghcjs = [ "octopod-common" "octopod-frontend" ];
37− };
38− })
65+
66+ index-state = "2021-11-22T00:00:00Z";
67+ compiler-nix-name = "ghc8107";
68+ };
69+in
70+hsPkgs // {
71+ octopod-frontend-pretty =
72+ let frontend = hsPkgs.projectCross.ghcjs.hsPkgs.octopod-frontend.components.exes.frontend;
73+ in
74+ pkgs.runCommand "octopod-frontend-pretty"
75+ { } ''
76+ mkdir $out
77+ cp -av ${octopod-css}/* $out
78+ cp ${./octopod-frontend/index.html} $out/index.html
79+ cp ${frontend}/bin/frontend.jsexe/all.js $out/all.js
80+ cp ${frontend}/bin/frontend.jsexe/all.js.externs $out/all.js.externs
81+ '';
82+ inherit pkgsSrc;
83+}
dev/config.jsondeleted−5
@@ -1,5 +0,0 @@
1−{
2− "app_url": "http://localhost:8000",
3− "ws_url": "ws://localhost:4020",
4− "app_auth": ""
5−}
dev/default.nixnew file+220
@@ -0,0 +1,220 @@
1+{ pkgs ? hsPkgs.pkgs
2+, sources ? import ../nix/sources.nix
3+, nix-filter ? import sources.nix-filter
4+, hsPkgs ? import ./.. { inherit prod system; }
5+, migrations ? ../migrations
6+, octopod-css ? import ../octopod-css { inherit pkgsSrc; }
7+, pkgsSrc ? hsPkgs.pkgsSrc
8+, prod ? false
9+, system ? builtins.currentSystem
10+}:
11+let frontendConfig = pkgs.writeTextDir "config.json" ''
12+ {
13+ "app_url": "http://localhost:8000",
14+ "ws_url": "ws://localhost:4020",
15+ "app_auth": "",
16+ "kubernetes_dashboard_url_template": "https://echo-url.github.io/#"
17+ }
18+'';
19+in
20+{
21+ frontend =
22+ let
23+ frontend = hsPkgs.octopod-frontend-pretty;
24+
25+ caddyConfig = pkgs.writeText "caddy-config" ''
26+ http://localhost:8000
27+
28+ header Cache-Control no-cache
29+
30+ reverse_proxy /api/* localhost:3002
31+
32+ file_server /config.json {
33+ root ${frontendConfig}
34+ }
35+
36+ file_server {
37+ root ${frontend}
38+ }
39+
40+ log {
41+ output stdout
42+ format single_field common_log
43+ }
44+ '';
45+
46+ caddyRun = pkgs.writeScript "run-caddy.sh" ''
47+ #!${pkgs.bash}/bin/bash
48+
49+ ${pkgs.caddy}/bin/caddy run --config ${caddyConfig} --adapter caddyfile
50+ '';
51+ in
52+ caddyRun;
53+
54+ caddyForGhcid =
55+ let
56+ caddyConfig = pkgs.writeText "caddy-config" ''
57+ http://localhost:8000
58+
59+ header Cache-Control no-cache
60+
61+ reverse_proxy /api/* localhost:3002
62+
63+ @notStatic {
64+ not file {
65+ root ${octopod-css}
66+ }
67+ not path /config.json
68+ }
69+
70+ reverse_proxy @notStatic localhost:3003
71+
72+ file_server /config.json {
73+ root ${frontendConfig}
74+ }
75+
76+ file_server {
77+ root ${octopod-css}
78+ }
79+
80+ log {
81+ output stdout
82+ format single_field common_log
83+ }
84+ '';
85+
86+ caddyRun = pkgs.writeScript "run-caddy.sh" ''
87+ #!${pkgs.bash}/bin/bash
88+
89+ ${pkgs.caddy}/bin/caddy run --config ${caddyConfig} --adapter caddyfile
90+ '';
91+ in
92+ caddyRun;
93+
94+ backend =
95+ let
96+ echoScript = pkgs.writeScript "echo.sh" ''
97+ #!${pkgs.bash}/bin/bash
98+
99+ echo $0 $@
100+ exit 0
101+ '';
102+
103+ failScript = pkgs.writeScript "fail.sh" ''
104+ #!${pkgs.bash}/bin/bash
105+
106+ echo "You did something wrong :("
107+ echo "You did something wrong twice :("
108+
109+ 1>&2 echo "You did something wrong, but you shouldn't see this."
110+
111+ exit 1
112+ '';
113+
114+ infoScript = pkgs.writeScript "info.sh" ''
115+ #!${pkgs.bash}/bin/bash
116+
117+ sleep 4
118+
119+ echo "foo.vat1.fjij.key1,"
120+
121+ for i in {1..10}
122+ do
123+ for j in {1..10}
124+ do
125+ echo "foo.vat$i.fjij.key$j,value"
126+ done
127+ done
128+
129+ for i in {1..10}
130+ do
131+ echo "fjij.key$i,value"
132+ done
133+
134+ exit 0
135+ '';
136+ smallInfoScript = pkgs.writeScript "info.sh" ''
137+ #!${pkgs.bash}/bin/bash
138+
139+ sleep 4
140+
141+ for i in {1..10}
142+ do
143+ echo "fjij.key$i,value"
144+ done
145+
146+ exit 0
147+ '';
148+
149+ keysScript = pkgs.writeScript "keys.sh" ''
150+ #!${pkgs.bash}/bin/bash
151+
152+ sleep 4
153+
154+ for i in {1..10}
155+ do
156+ echo "foo.vat.fkijf.fjij.key$i"
157+ done
158+ for i in {1..10}
159+ do
160+ echo "foo.vat.fjij.key$i"
161+ done
162+
163+ for i in {1..10}
164+ do
165+ echo "fjij.key$i"
166+ done
167+
168+ exit 0
169+ '';
170+
171+ writeScript = pkgs.writeScript "write.sh" ''
172+ #!${pkgs.bash}/bin/bash
173+
174+ #!/bin/bash
175+
176+ echo $0 $@ >> ./tmp/calls.txt
177+ exit 0
178+ '';
179+
180+ runBackend = pkgs.writeScript "run-backend.sh" ''
181+ #!${pkgs.bash}/bin/bash
182+
183+ ${pkgs.sqitchPg}/bin/sqitch deploy --chdir ${migrations} -t postgresql://octopod:octopod@localhost:5432/octopod
184+
185+ export PROJECT_NAME="Example Project"
186+ export BASE_DOMAIN=octopod.example.com
187+ export NAMESPACE=deployment
188+ export ARCHIVE_RETENTION=60
189+ export STATUS_UPDATE_TIMEOUT=600
190+ export CREATION_COMMAND=${echoScript}
191+ export UPDATE_COMMAND=${echoScript}
192+ export UPDATE_ENVS_COMMAND=${echoScript}
193+ export ARCHIVE_COMMAND=${echoScript}
194+ export CHECKING_COMMAND=${echoScript}
195+ export CLEANUP_COMMAND=${echoScript}
196+ export ARCHIVE_CHECKING_COMMAND=${echoScript}
197+ export CONFIG_CHECKING_COMMAND=${failScript}
198+ export INFO_COMMAND=${smallInfoScript}
199+ export NOTIFICATION_COMMAND=${writeScript}
200+ export DEPLOYMENT_CONFIG_COMMAND=${infoScript}
201+ export DEPLOYMENT_KEYS_COMMAND=${keysScript}
202+ export APPLICATION_CONFIG_COMMAND=${infoScript}
203+ export APPLICATION_KEYS_COMMAND=${keysScript}
204+ export UNARCHIVE_COMMAND=${writeScript}
205+ export POWER_AUTHORIZATION_HEADER="123"
206+ export CACHE_INVALIDATION_TIME="60"
207+ export CACHE_UPDATE_TIME="20"
208+ export CONTROL_SCRIPT_TIMEOUT="10"
209+ export DEBUG=true
210+ export PROD_LOGS=false
211+ ${hsPkgs.octopod-backend.components.exes.octopod-exe}/bin/octopod-exe \
212+ --port 4443 \
213+ --ui-port 3002 \
214+ --ws-port 4020 \
215+ --db "host='127.0.0.1' port=5432 user='octopod' password='octopod'" \
216+ --db-pool-size 10
217+ '';
218+ in
219+ runBackend;
220+}
dev/dev_backend.shdeleted−29
@@ -1,29 +0,0 @@
1−#!/bin/bash
2−
3−(cd migrations && sqitch deploy -t postgresql://octopod:octopod@localhost:5432/octopod)
4−
5−export MOUNT_DIR=./dev
6−
7−export PROJECT_NAME="Example Project"
8−export BASE_DOMAIN=octopod.example.com
9−export NAMESPACE=deployment
10−export ARCHIVE_RETENTION=60
11−export STATUS_UPDATE_TIMEOUT=600
12−export CREATION_COMMAND=$MOUNT_DIR/echo.sh
13−export UPDATE_COMMAND=$MOUNT_DIR/echo.sh
14−export UPDATE_ENVS_COMMAND=$MOUNT_DIR/echo.sh
15−export ARCHIVE_COMMAND=$MOUNT_DIR/echo.sh
16−export CHECKING_COMMAND=$MOUNT_DIR/echo.sh
17−export CLEANUP_COMMAND=$MOUNT_DIR/echo.sh
18−export ARCHIVE_CHECKING_COMMAND=$MOUNT_DIR/echo.sh
19−export TAG_CHECKING_COMMAND=$MOUNT_DIR/echo.sh
20−export INFO_COMMAND=$MOUNT_DIR/info.sh
21−$1/bin/octopod-exe \
22− --port 4443 \
23− --ui-port 3002 \
24− --ws-port 4020 \
25− --db "host='127.0.0.1' port=5432 user='octopod' password='octopod'" \
26− --db-pool-size 10 \
27− --tls-cert-path dev/certs/server_cert.pem \
28− --tls-key-path dev/certs/server_key.pem \
29− --tls-store-path /tmp/tls_store
dev/echo.shdeleted−4
@@ -1,4 +0,0 @@
1−#!/bin/bash
2−
3−echo $0 $@
4−exit 0
dev/info.shdeleted−6
@@ -1,6 +0,0 @@
1−#!/bin/bash
2−
3−echo "key,value"
4−echo "key2,value2"
5−
6−exit 0
docs/Makefile−9
@@ -20,12 +20,3 @@ plantuml:
2020 name=`basename $$src .mmd`; \
2121 plantuml -I $$src -o "../../diagrams/images" -tpng; \
2222 done
23−
24−plantuml:
25− # to install plantuml go to https://plantuml.com/command-line
26− #
27− # plantuml takes output paths relative to input file
28− for src in `ls diagrams/src/*.puml`; do \
29− name=`basename $$src .mmd`; \
30− plantuml -I $$src -o "../../diagrams/images" -tpng; \
31− done
docs/README.md+6−6
@@ -6,10 +6,10 @@
66- [🧑‍💻 Technical case study](en/Tech_case_study.md)
77
88## 🛠️ Technical documentation
9−- [🏗 Technical architecture](en/Technical_architecture.md) [[RU](ru/Technical_architecture.md)]
10−- [⚙️ Control script guide](en/Control_scripts.md) [[RU](ru/Control_scripts.md)]
11−- [🔧🐙 Octopod deployment guide](en/Octopod_deployment_guide.md) [[RU](ru/Octopod_deployment_with_K8S.md)]
12−- [🔧🚀 Helm-based Octopod project setup](en/Helm-based_deployment_guide.md) [[RU](ru/Helm-based_deployment_guide.md)]
13−- [🐙🎛 octo CLI user guide](en/Octo_user_guide.md) [[RU](ru/Octo_user_guide.md)]
9+- [🏗 Technical architecture](en/Technical_architecture.md)
10+- [⚙️ Control script guide](en/Control_scripts.md)
11+- [🔧🐙 Octopod deployment guide](en/Octopod_deployment_guide.md)
12+- [🔧🚀 Helm-based Octopod project setup](en/Helm-based_deployment_guide.md)
13+- [🐙🎛 octo CLI user guide](en/Octo_user_guide.md)
1414- [🤖 CI integration](en/Integration.md)
15−- [🔒 Octopod security model](en/Security_model.md) [[RU](ru/Security_model.md)]
15+- [🔒 Octopod security model](en/Security_model.md)
docs/diagrams/images/app-architecture.png

Binary file not shown.

docs/diagrams/images/technical-architecture-archive-via-cli.pngdeleted

Binary file not shown.

docs/diagrams/images/technical-architecture-archive-via-ui.pngdeleted

Binary file not shown.

docs/diagrams/images/technical-architecture-archive.pngnew file

Binary file not shown.

docs/diagrams/images/technical-architecture-cleanup-via-cli.pngdeleted

Binary file not shown.

docs/diagrams/images/technical-architecture-cleanup-via-ui.pngdeleted

Binary file not shown.

docs/diagrams/images/technical-architecture-cleanup.pngnew file

Binary file not shown.

docs/diagrams/images/technical-architecture-create-via-cli.pngdeleted

Binary file not shown.

docs/diagrams/images/technical-architecture-create-via-ui.pngdeleted

Binary file not shown.

docs/diagrams/images/technical-architecture-create.pngnew file

Binary file not shown.

docs/diagrams/images/technical-architecture-deployment-states-fsm.png

Binary file not shown.

docs/diagrams/images/technical-architecture-restore-via-cli.pngdeleted

Binary file not shown.

docs/diagrams/images/technical-architecture-restore-via-ui.pngdeleted

Binary file not shown.

docs/diagrams/images/technical-architecture-restore.pngnew file

Binary file not shown.

docs/diagrams/images/technical-architecture-update-via-cli.pngdeleted

Binary file not shown.

docs/diagrams/images/technical-architecture-update-via-ui.pngdeleted

Binary file not shown.

docs/diagrams/images/technical-architecture-update.pngnew file

Binary file not shown.

docs/diagrams/src/technical-architecture-archive-via-cli.mmddeleted−37
@@ -1,37 +0,0 @@
1−sequenceDiagram
2− participant octo CLI
3− participant Octopod Server
4− participant PostgreSQL
5− participant UI
6− participant Octopod Server/BgWorker
7− participant Octopod Server/StatusUpdater
8− participant ControlScripts
9− participant KubeAPI
10− octo CLI->>Octopod Server: archive(name)
11− Octopod Server->>PostgreSQL: status=ArchivePending
12− alt name not found
13− PostgreSQL-->>Octopod Server: error: name not found
14− Octopod Server-->>octo CLI: error: name not found
15− else
16− PostgreSQL-->>Octopod Server: ok
17− Octopod Server-xUI: event FrontendPleaseUpdateEverything
18− UI->>Octopod Server: get deployments info
19− Octopod Server-->>UI: deployments info
20− Octopod Server->>Octopod Server/BgWorker: archive
21− Octopod Server-->>octo CLI: done
22− Octopod Server/BgWorker->>ControlScripts: archive
23− ControlScripts->>KubeAPI: archive deployment
24− KubeAPI-->>ControlScripts: done
25− ControlScripts-->>Octopod Server/BgWorker: done
26− Octopod Server/BgWorker->>PostgreSQL: write logs
27− Octopod Server/BgWorker-xUI: event FrontendPleaseUpdateEverything
28− UI->>Octopod Server: get deployments info
29− Octopod Server-->>UI: deployments info
30− Note over Octopod Server/StatusUpdater: wait 5 minutes
31− loop check deployment status every 30 seconds
32− Octopod Server/StatusUpdater->>PostgreSQL: status=Archived/ArchivePending
33− Octopod Server/StatusUpdater-xUI: event FrontendPleaseUpdateEverything
34− UI->>Octopod Server: get deployments info
35− Octopod Server-->>UI: deployments info
36− end
37− end
docs/diagrams/src/technical-architecture-archive-via-ui.mmddeleted−36
@@ -1,36 +0,0 @@
1−sequenceDiagram
2− participant UI
3− participant Octopod Server
4− participant PostgreSQL
5− participant Octopod Server/BgWorker
6− participant Octopod Server/StatusUpdater
7− participant ControlScripts
8− participant KubeAPI
9− UI->>Octopod Server: archive(name)
10− Octopod Server->>PostgreSQL: status=ArchivePending
11− alt name not found
12− PostgreSQL-->>Octopod Server: error: name not found
13− Octopod Server-->>UI: error: name not found
14− else
15− PostgreSQL-->>Octopod Server: ok
16− Octopod Server-xUI: event FrontendPleaseUpdateEverything
17− UI->>Octopod Server: get deployments info
18− Octopod Server-->>UI: deployments info
19− Octopod Server->>Octopod Server/BgWorker: archive
20− Octopod Server-->>UI: done
21− Octopod Server/BgWorker->>ControlScripts: archive
22− ControlScripts->>KubeAPI: archive deployment
23− KubeAPI-->>ControlScripts: done
24− ControlScripts-->>Octopod Server/BgWorker: done
25− Octopod Server/BgWorker->>PostgreSQL: write logs
26− Octopod Server/BgWorker-xUI: event FrontendPleaseUpdateEverything
27− UI->>Octopod Server: get deployments info
28− Octopod Server-->>UI: deployments info
29− Note over Octopod Server/StatusUpdater: wait 5 minutes
30− loop check deployment status every 30 seconds
31− Octopod Server/StatusUpdater->>PostgreSQL: status=Archived/ArchivePending
32− Octopod Server/StatusUpdater-xUI: event FrontendPleaseUpdateEverything
33− UI->>Octopod Server: get deployments info
34− Octopod Server-->>UI: deployments info
35− end
36− end
docs/diagrams/src/technical-architecture-archive.mmdnew file+31
@@ -0,0 +1,31 @@
1+sequenceDiagram
2+ participant User
3+ participant Octopod Frontend
4+ participant Octopod Backend
5+ participant Control Scipts
6+ participant Octopod DB
7+
8+ User ->>+ Octopod Frontend: Archive deployment
9+ activate Octopod Frontend
10+
11+ Octopod Frontend ->>+ Octopod Backend: Archive deployment
12+
13+
14+ Octopod Backend ->>+ Control Scipts: archive – Archive the deployment
15+ Control Scipts -->>- Octopod Backend: Deployment archive started
16+
17+ Octopod Backend ->>+ Octopod DB: Set deployment state to ArchivePending
18+ Octopod DB -->>- Octopod Backend: Deployment status set
19+
20+ loop
21+ Octopod Backend ->>+ Control Scipts: archive_check – Is the deployment archived?
22+ Control Scipts -->>- Octopod Backend: deployment is not archived
23+ end
24+
25+ Octopod Backend ->>+ Control Scipts: archive_check – Is the deployment archived?
26+ Control Scipts -->>- Octopod Backend: deployment is archived!
27+
28+ Octopod Backend ->>+ Octopod DB: Set deployment state to Archived
29+ Octopod DB -->>- Octopod Backend: Deployment status set
30+
31+ deactivate Octopod Backend
docs/diagrams/src/technical-architecture-cleanup-via-cli.mmddeleted−20
@@ -1,20 +0,0 @@
1−sequenceDiagram
2− participant octo CLI
3− participant Octopod Server
4− participant PostgreSQL
5− participant UI
6− participant Octopod Server/BgWorker
7− participant Octopod Server/StatusUpdater
8− participant ControlScripts
9− participant KubeAPI
10− octo CLI->>Octopod Server: cleanup(name)
11− Octopod Server->>Octopod Server/BgWorker: cleanup
12− Octopod Server-->>octo CLI: done
13− Octopod Server/BgWorker->>ControlScripts: cleanup
14− ControlScripts->>KubeAPI: cleanup deployment
15− KubeAPI-->>ControlScripts: done
16− ControlScripts-->>Octopod Server/BgWorker: done
17− Octopod Server->>PostgreSQL: delete config and logs
18− Octopod Server/BgWorker-xUI: event FrontendPleaseUpdateEverything
19− UI->>Octopod Server: get deployments info
20− Octopod Server-->>UI: deployments info
docs/diagrams/src/technical-architecture-cleanup-via-ui.mmddeleted−19
@@ -1,19 +0,0 @@
1−sequenceDiagram
2− participant UI
3− participant Octopod Server
4− participant PostgreSQL
5− participant Octopod Server/BgWorker
6− participant Octopod Server/StatusUpdater
7− participant ControlScripts
8− participant KubeAPI
9− UI->>Octopod Server: cleanup(name)
10− Octopod Server->>Octopod Server/BgWorker: cleanup
11− Octopod Server-->>UI: done
12− Octopod Server/BgWorker->>ControlScripts: cleanup
13− ControlScripts->>KubeAPI: cleanup deployment resources
14− KubeAPI-->>ControlScripts: done
15− ControlScripts-->>Octopod Server/BgWorker: done
16− Octopod Server->>PostgreSQL: delete config and logs
17− Octopod Server/BgWorker-xUI: event FrontendPleaseUpdateEverything
18− UI->>Octopod Server: get deployments info
19− Octopod Server-->>UI: deployments info
docs/diagrams/src/technical-architecture-cleanup.mmdnew file+14
@@ -0,0 +1,14 @@
1+sequenceDiagram
2+ participant Octopod Backend
3+ participant Control Scipts
4+ participant Octopod DB
5+
6+ activate Octopod Backend
7+
8+ Octopod Backend ->>+ Control Scipts: cleanup – Clean up deployment resouces
9+ Control Scipts -->>- Octopod Backend: Deployment resouces cleaned up
10+
11+ Octopod Backend ->>+ Octopod DB: Delete everything related to the deployment
12+ Octopod DB -->>- Octopod Backend: Everything deleted
13+
14+ deactivate Octopod Backend
docs/diagrams/src/technical-architecture-create-via-cli.mmddeleted−41
@@ -1,41 +0,0 @@
1−sequenceDiagram
2− participant octo CLI
3− participant Octopod Server
4− participant PostgreSQL
5− participant UI
6− participant Octopod Server/BgWorker
7− participant Octopod Server/StatusUpdater
8− participant ControlScripts
9− participant KubeAPI
10− octo CLI->>Octopod Server: create(name, tag, [override])
11− Octopod Server->>PostgreSQL: store config, status=CreatePending
12− alt name already exists
13− PostgreSQL->>Octopod Server: error: deployment already exists
14− Octopod Server-->>octo CLI: error: deployment already exists
15− else
16− alt tag not found
17− Octopod Server-->>octo CLI: error: tag not found
18− else
19− PostgreSQL-->>Octopod Server: ok
20− Octopod Server-xUI: event FrontendPleaseUpdateEverything
21− UI->>Octopod Server: get deployments info
22− Octopod Server-->>UI: deployments info
23− Octopod Server->>Octopod Server/BgWorker: create
24− Octopod Server-->>octo CLI: done
25− Octopod Server/BgWorker->>ControlScripts: create
26− ControlScripts->>KubeAPI: create deployment
27− KubeAPI-->>ControlScripts: done
28− ControlScripts-->>Octopod Server/BgWorker: done
29− Octopod Server/BgWorker->>PostgreSQL: write logs
30− Octopod Server/BgWorker-xUI: event FrontendPleaseUpdateEverything
31− UI->>Octopod Server: get deployments info
32− Octopod Server-->>UI: deployments info
33− Note over Octopod Server/StatusUpdater: wait 5 minutes
34− loop check deployment status every 30 seconds
35− Octopod Server/StatusUpdater->>PostgreSQL: status=Running/Failure
36− Octopod Server/StatusUpdater-xUI: event FrontendPleaseUpdateEverything
37− UI->>Octopod Server: get deployments info
38− Octopod Server-->>UI: deployments info
39− end
40− end
41− end
docs/diagrams/src/technical-architecture-create-via-ui.mmddeleted−40
@@ -1,40 +0,0 @@
1−sequenceDiagram
2− participant UI
3− participant Octopod Server
4− participant PostgreSQL
5− participant Octopod Server/BgWorker
6− participant Octopod Server/StatusUpdater
7− participant ControlScripts
8− participant KubeAPI
9− UI->>Octopod Server: create(name, tag, [override])
10− Octopod Server->>PostgreSQL: store config, status=CreatePending
11− alt name already exists
12− PostgreSQL-->>Octopod Server: error: deployment already exists
13− Octopod Server-->>UI: error: deployment already exists
14− else
15− alt tag not found
16− Octopod Server-->>UI: error: tag not found
17− else
18− PostgreSQL-->>Octopod Server: ok
19− Octopod Server-xUI: event FrontendPleaseUpdateEverything
20− UI->>Octopod Server: get deployments info
21− Octopod Server-->>UI: deployments info
22− Octopod Server->>Octopod Server/BgWorker: create
23− Octopod Server-->>UI: done
24− Octopod Server/BgWorker->>ControlScripts: create
25− ControlScripts->>KubeAPI: create deployment
26− KubeAPI-->>ControlScripts: done
27− ControlScripts-->>Octopod Server/BgWorker: done
28− Octopod Server/BgWorker->>PostgreSQL: write logs
29− Octopod Server/BgWorker-xUI: event FrontendPleaseUpdateEverything
30− UI->>Octopod Server: get deployments info
31− Octopod Server-->>UI: deployments info
32− Note over Octopod Server/StatusUpdater: wait 5 minutes
33− loop check deployment status every 30 seconds
34− Octopod Server/StatusUpdater->>PostgreSQL: status=Running/Failure
35− Octopod Server/StatusUpdater-xUI: event FrontendPleaseUpdateEverything
36− UI->>Octopod Server: get deployments info
37− Octopod Server-->>UI: deployments info
38− end
39− end
40− end
docs/diagrams/src/technical-architecture-create.mmdnew file+41
@@ -0,0 +1,41 @@
1+sequenceDiagram
2+ participant User
3+ participant Octopod Frontend
4+ participant Octopod Backend
5+ participant Control Scipts
6+ participant Octopod DB
7+
8+ User ->>+ Octopod Frontend: Create deployment
9+ activate Octopod Frontend
10+
11+ Octopod Frontend ->>+ Octopod Backend: Create deployment
12+ Octopod Backend ->>+ Control Scipts: config_check – Check deployment config
13+ Control Scipts ->>- Octopod Backend: Deployment config OK
14+ Octopod Backend ->>+ Octopod DB: Create deployment
15+ Octopod DB -->>- Octopod Backend: Deployment Created
16+
17+ Octopod Backend -->> Octopod Frontend: Delpoyment created
18+ Octopod Frontend -->>- User: Close deployment popup
19+
20+ Octopod Backend ->>+ Control Scipts: info – Get deployment metadata
21+ Control Scipts -->>- Octopod Backend: Deployment metadata
22+
23+ Octopod Backend ->>+ Octopod DB: Set deployment metadata
24+ Octopod DB -->>- Octopod Backend: Deployment metadata set
25+
26+
27+ Octopod Backend ->>+ Control Scipts: create – Create the delpoyment
28+ Control Scipts -->>- Octopod Backend: Deployment creation started
29+
30+ loop
31+ Octopod Backend ->>+ Control Scipts: check – Is the deployment up?
32+ Control Scipts -->>- Octopod Backend: deployment is not up
33+ end
34+
35+ Octopod Backend ->>+ Control Scipts: check – Is the deployment up?
36+ Control Scipts -->>- Octopod Backend: deployment is up!
37+
38+ Octopod Backend ->>+ Octopod DB: Set deployment state to Running
39+ Octopod DB -->>- Octopod Backend: Deployment status set
40+
41+ deactivate Octopod Backend
docs/diagrams/src/technical-architecture-deployment-states-fsm.mmd+1
@@ -14,3 +14,4 @@ stateDiagram-v2
1414 UpdatePending --> Failure: 5m passed and 'check' said "nok"
1515 ArchivePending --> Archived: 30s passed and 'archive_check' said "ok"
1616 ArchivePending --> ArchivePending: 30s passed and 'archive_check' said "nok"
17+ Archived --> CleanupFailed
docs/diagrams/src/technical-architecture-restore-via-cli.mmddeleted−41
@@ -1,41 +0,0 @@
1−sequenceDiagram
2− participant octo CLI
3− participant Octopod Server
4− participant PostgreSQL
5− participant UI
6− participant Octopod Server/BgWorker
7− participant Octopod Server/StatusUpdater
8− participant ControlScripts
9− participant KubeAPI
10− octo CLI->>Octopod Server: restore(name)
11− Octopod Server->>PostgreSQL: status=CreatePending
12− alt name not found
13− PostgreSQL-->>Octopod Server: error: name not found
14− Octopod Server-->>octo CLI: error: name not found
15− else
16− alt tag not found
17− Octopod Server-->>octo CLI: error: tag not found
18− else
19− PostgreSQL-->>Octopod Server: ok
20− Octopod Server-xUI: event FrontendPleaseUpdateEverything
21− UI->>Octopod Server: get deployments info
22− Octopod Server-->>UI: deployments info
23− Octopod Server->>Octopod Server/BgWorker: create
24− Octopod Server-->>octo CLI: done
25− Octopod Server/BgWorker->>ControlScripts: create
26− ControlScripts->>KubeAPI: restore deployment
27− KubeAPI-->>ControlScripts: done
28− ControlScripts-->>Octopod Server/BgWorker: done
29− Octopod Server/BgWorker->>PostgreSQL: write logs
30− Octopod Server/BgWorker-xUI: event FrontendPleaseUpdateEverything
31− UI->>Octopod Server: get deployments info
32− Octopod Server-->>UI: deployments info
33− Note over Octopod Server/StatusUpdater: wait 5 minutes
34− loop check deployment status every 30 seconds
35− Octopod Server/StatusUpdater->>PostgreSQL: status=Running/Failure
36− Octopod Server/StatusUpdater-xUI: event FrontendPleaseUpdateEverything
37− UI->>Octopod Server: get deployments info
38− Octopod Server-->>UI: deployments info
39− end
40− end
41− end
docs/diagrams/src/technical-architecture-restore-via-ui.mmddeleted−40
@@ -1,40 +0,0 @@
1−sequenceDiagram
2− participant UI
3− participant Octopod Server
4− participant PostgreSQL
5− participant Octopod Server/BgWorker
6− participant Octopod Server/StatusUpdater
7− participant ControlScripts
8− participant KubeAPI
9− UI->>Octopod Server: restore(name)
10− Octopod Server->>PostgreSQL: status=CreatePending
11− alt name not found
12− PostgreSQL-->>Octopod Server: error: name not found
13− Octopod Server-->>UI: error: name not found
14− else
15− alt tag not found
16− Octopod Server-->>UI: error: tag not found
17− else
18− PostgreSQL-->>Octopod Server: ok
19− Octopod Server-xUI: event FrontendPleaseUpdateEverything
20− UI->>Octopod Server: get deployments info
21− Octopod Server-->>UI: deployments info
22− Octopod Server->>Octopod Server/BgWorker: create
23− Octopod Server-->>UI: done
24− Octopod Server/BgWorker->>ControlScripts: create
25− ControlScripts->>KubeAPI: restore deployment
26− KubeAPI-->>ControlScripts: done
27− ControlScripts-->>Octopod Server/BgWorker: done
28− Octopod Server/BgWorker->>PostgreSQL: write logs
29− Octopod Server/BgWorker-xUI: event FrontendPleaseUpdateEverything
30− UI->>Octopod Server: get deployments info
31− Octopod Server-->>UI: deployments info
32− Note over Octopod Server/StatusUpdater: wait 5 minutes
33− loop check deployment status every 30 seconds
34− Octopod Server/StatusUpdater->>PostgreSQL: status=Running/Failure
35− Octopod Server/StatusUpdater-xUI: event FrontendPleaseUpdateEverything
36− UI->>Octopod Server: get deployments info
37− Octopod Server-->>UI: deployments info
38− end
39− end
40− end
docs/diagrams/src/technical-architecture-restore.mmdnew file+42
@@ -0,0 +1,42 @@
1+sequenceDiagram
2+ participant User
3+ participant Octopod Frontend
4+ participant Octopod Backend
5+ participant Control Scipts
6+ participant Octopod DB
7+
8+ User ->>+ Octopod Frontend: Restore deployment
9+ activate Octopod Frontend
10+
11+ Octopod Frontend ->>+ Octopod Backend: Restore deployment
12+ Octopod Backend ->>+ Control Scipts: config_check – Check deployment config
13+ Control Scipts ->>- Octopod Backend: Deployment config OK
14+
15+ Octopod Backend -->> Octopod Frontend: Delpoyment restore started
16+ Octopod Frontend -->>- User: Deployment restore started
17+
18+
19+ Octopod Backend ->>+ Control Scipts: info – Get deployment metadata
20+ Control Scipts -->>- Octopod Backend: Deployment metadata
21+
22+ Octopod Backend ->>+ Octopod DB: Set deployment metadata
23+ Octopod DB -->>- Octopod Backend: Deployment metadata set
24+
25+ Octopod Backend ->>+ Control Scipts: unarchive – Unarchive the delpoyment
26+ Control Scipts -->>- Octopod Backend: Deployment unarchiving started
27+
28+ Octopod Backend ->>+ Octopod DB: Set deployment state to CreatePending
29+ Octopod DB -->>- Octopod Backend: Deployment status set
30+
31+ loop
32+ Octopod Backend ->>+ Control Scipts: check – Is the deployment up?
33+ Control Scipts -->>- Octopod Backend: deployment is not up
34+ end
35+
36+ Octopod Backend ->>+ Control Scipts: check – Is the deployment up?
37+ Control Scipts -->>- Octopod Backend: deployment is up!
38+
39+ Octopod Backend ->>+ Octopod DB: Set deployment state to Running
40+ Octopod DB -->>- Octopod Backend: Deployment status set
41+
42+ deactivate Octopod Backend
docs/diagrams/src/technical-architecture-update-via-cli.mmddeleted−41
@@ -1,41 +0,0 @@
1−sequenceDiagram
2− participant octo CLI
3− participant Octopod Server
4− participant PostgreSQL
5− participant UI
6− participant Octopod Server/BgWorker
7− participant Octopod Server/StatusUpdater
8− participant ControlScripts
9− participant KubeAPI
10− octo CLI->>Octopod Server: create(name, tag, [override])
11− Octopod Server->>PostgreSQL: store config, status=UpdatePending
12− alt name not found
13− PostgreSQL-->>Octopod Server: error: name not found
14− Octopod Server-->>octo CLI: error: name not found
15− else
16− alt tag not found
17− Octopod Server-->>octo CLI: error: tag not found
18− else
19− PostgreSQL-->>Octopod Server: ok
20− Octopod Server-xUI: event FrontendPleaseUpdateEverything
21− UI->>Octopod Server: get deployments info
22− Octopod Server-->UI: deployments info
23− Octopod Server->>Octopod Server/BgWorker: update
24− Octopod Server-->>octo CLI: done
25− Octopod Server/BgWorker->>ControlScripts: update
26− ControlScripts->>KubeAPI: upgrade deployment
27− KubeAPI-->>ControlScripts: done
28− ControlScripts-->>Octopod Server/BgWorker: done
29− Octopod Server/BgWorker->>PostgreSQL: write logs
30− Octopod Server/BgWorker-xUI: event FrontendPleaseUpdateEverything
31− UI->>Octopod Server: get deployments info
32− Octopod Server-->UI: deployments info
33− Note over Octopod Server/StatusUpdater: wait 5 minutes
34− loop check deployment status every 30 seconds
35− Octopod Server/StatusUpdater->>PostgreSQL: status=Running/Failure
36− Octopod Server/StatusUpdater-xUI: event FrontendPleaseUpdateEverything
37− UI->>Octopod Server: get deployments info
38− Octopod Server-->UI: deployments info
39− end
40− end
41− end
docs/diagrams/src/technical-architecture-update-via-ui.mmddeleted−40
@@ -1,40 +0,0 @@
1−sequenceDiagram
2− participant UI
3− participant Octopod Server
4− participant PostgreSQL
5− participant Octopod Server/BgWorker
6− participant Octopod Server/StatusUpdater
7− participant ControlScripts
8− participant KubeAPI
9− UI->>Octopod Server: create(name, tag, [override])
10− Octopod Server->>PostgreSQL: store config, status=UpdatePending
11− alt name not found
12− PostgreSQL-->>Octopod Server: error: name not found
13− Octopod Server-->>UI: error: name not found
14− else
15− alt tag not found
16− Octopod Server-->>UI: error: tag not found
17− else
18− PostgreSQL-->>Octopod Server: ok
19− Octopod Server-xUI: event FrontendPleaseUpdateEverything
20− UI->>Octopod Server: get deployments info
21− Octopod Server-->>UI: deployments info
22− Octopod Server->>Octopod Server/BgWorker: update
23− Octopod Server-->>UI: done
24− Octopod Server/BgWorker->>ControlScripts: update
25− ControlScripts->>KubeAPI: upgrade deployment
26− KubeAPI-->>ControlScripts: done
27− ControlScripts-->>Octopod Server/BgWorker: done
28− Octopod Server/BgWorker->>PostgreSQL: write logs
29− Octopod Server/BgWorker-xUI: event FrontendPleaseUpdateEverything
30− UI->>Octopod Server: get deployments info
31− Octopod Server-->>UI: deployments info
32− Note over Octopod Server/StatusUpdater: wait 5 minutes
33− loop check deployment status every 30 seconds
34− Octopod Server/StatusUpdater->>PostgreSQL: status=Running/Failure
35− Octopod Server/StatusUpdater-xUI: event FrontendPleaseUpdateEverything
36− UI->>Octopod Server: get deployments info
37− Octopod Server-->>UI: deployments info
38− end
39− end
40− end
docs/diagrams/src/technical-architecture-update.mmdnew file+46
@@ -0,0 +1,46 @@
1+sequenceDiagram
2+ participant User
3+ participant Octopod Frontend
4+ participant Octopod Backend
5+ participant Control Scipts
6+ participant Octopod DB
7+
8+ User ->>+ Octopod Frontend: Update deployment
9+ activate Octopod Frontend
10+
11+ Octopod Frontend ->>+ Octopod Backend: Update deployment
12+ Octopod Backend ->>+ Control Scipts: config_check – Check deployment config
13+ Control Scipts ->>- Octopod Backend: Deployment config OK
14+
15+ Octopod Backend -->> Octopod Frontend: Delpoyment update started
16+ Octopod Frontend -->>- User: Close deployment popup
17+
18+
19+ Octopod Backend ->>+ Octopod DB: Update deployment config
20+ Octopod DB -->>- Octopod Backend: Deployment config updated
21+
22+
23+ Octopod Backend ->>+ Control Scipts: info – Get deployment metadata
24+ Control Scipts -->>- Octopod Backend: Deployment metadata
25+
26+ Octopod Backend ->>+ Octopod DB: Set deployment metadata
27+ Octopod DB -->>- Octopod Backend: Deployment metadata set
28+
29+ Octopod Backend ->>+ Control Scipts: update – Update the delpoyment
30+ Control Scipts -->>- Octopod Backend: Deployment update started
31+
32+ Octopod Backend ->>+ Octopod DB: Set deployment state to UpdatePending
33+ Octopod DB -->>- Octopod Backend: Deployment status set
34+
35+ loop
36+ Octopod Backend ->>+ Control Scipts: check – Is the deployment up?
37+ Control Scipts -->>- Octopod Backend: deployment is not up
38+ end
39+
40+ Octopod Backend ->>+ Control Scipts: check – Is the deployment up?
41+ Control Scipts -->>- Octopod Backend: deployment is up!
42+
43+ Octopod Backend ->>+ Octopod DB: Set deployment state to Running
44+ Octopod DB -->>- Octopod Backend: Deployment status set
45+
46+ deactivate Octopod Backend
docs/en/Control_scripts.md+155−132
@@ -1,83 +1,38 @@
11# Control scripts
22
3−<details>
4− <summary>Table of contents</summary>
5−
6−- [General behavior](#general-behavior)
7−- [Scripts](#scripts)
8− - [🔁 init](#-init)
9− - [Description](#description)
10− - [Sample implementation](#sample-implementation)
11− - [✨ create](#-create)
12− - [Description](#description-1)
13− - [Execution example](#execution-example)
14− - [Sample implementation](#sample-implementation-1)
15− - [🔧 update](#-update)
16− - [Description](#description-2)
17− - [Execution example](#execution-example-1)
18− - [Sample implementation](#sample-implementation-2)
19− - [🗃 archive](#-archive)
20− - [Description](#description-3)
21− - [Execution example](#execution-example-2)
22− - [Sample implementation](#sample-implementation-3)
23− - [✅ check](#-check)
24− - [Description](#description-4)
25− - [Execution example](#execution-example-3)
26− - [Sample implementation](#sample-implementation-4)
27− - [🚮 cleanup](#-cleanup)
28− - [Description](#description-5)
29− - [Execution example](#execution-example-4)
30− - [Sample implementation](#sample-implementation-5)
31− - [🗃✅ archive_check](#-archive_check)
32− - [Description](#description-6)
33− - [Execution example](#execution-example-5)
34− - [Sample implementation](#sample-implementation-6)
35− - [🐋✅ tag_check](#-tag_check)
36− - [Description](#description-7)
37− - [Execution example](#execution-example-6)
38− - [👀 info](#-info)
39− - [Description](#description-8)
40− - [Execution example](#execution-example-7)
41− - [Sample implementation](#sample-implementation-7)
42−
43−</details>
443
454## General behavior
465
476All _control scripts_ receive input as CLI arguments. After executing the required logic they must finish with an _exit code_ of `0` if no errors have occurred and the required actions have all completed. If there was an error and some steps were not executed, the *script* should exit with an *exit code* **distinct from `0`**. Any non-zero exit code will indicate an error.
487
49−Everything the _scripts_ write to _stdout_ and _stderr_ will be collected and stored. DevOps engineers can then view these logs from the _octo CLI_, should that be needed.
8+Control scripts can be roughly split into two categories: (1) control scripts involved in the deployment lifecycle and (2) service control scripts which handle everything else.
509
51−> *NOTE: Logs from `check`, `archive_check` and `tag_check` are not collected because they are called very often.*
10+## Deployment lifecycle scripts
5211
53−There are four arguments that are passed to **all** *scripts*. The first three arguments come from the [_Kubernetes ConfigMap_][configmap]:
12+_stdout_ and _stderr_ output from the most important scripts involved in the deployment lifecycle will be collected and stored. DevOps engineers can then view these logs from the _octo CLI_, should that be needed.
13+
14+All of the _scripts_ in this category receive the exact same set of command line arguments.
15+
16+There are four "static" arguments that are passed to all *scripts* in this category. The first three arguments come from the [_Kubernetes ConfigMap_][configmap]:
5417* `--project-name` – the name of the project. It is supplied mostly for informational purposes and can be useful for sending notifications if that is necessary.
5518* `--base-domain` – the base domain. It can be useful for generating the URLs of deployments.
5619* `--namespace` – The namespace in which the deployment should be created.
5720* `--name` – The name of the deployment supplied in the _Web UI_. It can be useful for generating the deployment URL.
5821
59−<a id="star"></a>*NOTE:* If an argument is marked with a ⭐, it means that the argument can be passed any number of times.
60−
61−## Scripts
62−
63−### 🔁 init
64−
65−#### Description
66−
67−This script is called **once** during the creation of the `Octopod Server` *Kubernetes Pod* to set up the proper environment to execute all other scripts.
22+Additionally, _scripts_ in this category receive the deployment configuration – a set of key/value pairs. There are two types of configurations that can be set from the _Web UI_: deployment
23+configuration and application configuration.
6824
69−It is guaranteed that this script will be called **before** any of the other scripts.
25+Both types of configurations can have any number of key/value pairs. Every pair is passed a separate command line argument:
7026
71−You could, for example, set up access to your *version control system*, *cloud providers*, etc. This can be achieved by saving the configuration into files in the `$HOME` directory.
27+* `--application-config <KEY>=<VALUE>` represents an application configuration key/value pair.
28+* `--deployment-config <KEY>=<VALUE>` represents an deployment configuration key/value pair.
7229
73−Unlike all other scripts, this script receives no arguments.
30+Any of these two command line arguments can be passed any number of times.
7431
75−#### Sample implementation
32+So, a _script_ might be called something like this:
7633
7734```bash
78−mkdir $HOME/.ssh
79−echo -e "Host github.com\nHostname github.com\nPort 22\nUser git\nIdentityFile $HOME/.ssh/deploy.key" > $HOME/.ssh/config
80−echo "MY_DEPLOY_KEY" > $HOME/.ssh/deploy.key"
35+create --project-name "Cactus store" --base-domain "cactus-store.com" --namespace "cactus" --name "orange-button" --application-config "EMAIL_TOKEN=123123" --application-config "SECRET_BUTTON_ENABLED=True" --deployment-config "FANCY_DATABASE=True"
8136```
8237
8338### ✨ create
@@ -86,19 +41,6 @@ echo "MY_DEPLOY_KEY" > $HOME/.ssh/deploy.key"
8641
8742Creates a new deployment in the _Kubernetes_ cluster.
8843
89−This script receives the following additional command-line arguments as input:
90−* `--tag` – The _Docker Image tag_ that should be deployed. (In practice you can use some other string that identifies a version of your system to deploy – you will need to process it accordingly in the script.)
91−* `--app-env-override` [⭐](#star) – App-level overrides. These overrides should be passed to the server being deployed. These overrides are specified in the _Web UI_. They are passed in the format of `KEY=VALUE` pairs.
92−* `--deployment-override` [⭐](#star) – Deployment-level overrides. These overrides should be used to set up the deployment environment itself, rather than be passed to the server being deployed. These overrides are specified in the _Web UI_. They are passed in the format of `KEY=VALUE` pairs.
93−
94−#### Execution example
95−
96−The script might be called something like this:
97−
98−```bash
99−create --project-name "Cactus store" --base-domain "cactus-store.com" --namespace "cactus" --name "orange-button" --tag "c9bbc3fcc69e5aa094bca110c6f79419ab7be77a" --app-env-override "EMAIL_TOKEN=123123" --app-env-override "SECRET_BUTTON_ENABLED=True" --deployment-override "FANCY_DATABASE=True"
100−```
101−
10244#### Sample implementation
10345
10446```bash
@@ -112,24 +54,38 @@ helm upgrade --install --namespace "$namespace" "$name" "$deployment_chart" \
11254 --timeout 300
11355```
11456
115−### 🔧 update
57+### 🎛✅ config_check
11658
11759#### Description
11860
119−Updates a deployment in _Kubernetes_ to a new *Docker Image tag*.
61+This script is called right before [`create`](#-create) and [`update`](#-update) scripts to check that the given set of arguments is valid input for other commands. This is run synchronously and the _stdout_ text is report to the user in the _Web UI_. This means that the command should run relatively fast. You can check thing like that the needed arguments are present and that the required docker tags exist in the docker registry.
12062
121−This script receives the same additional command-line arguments as [`create`](#-create):
122−* `--tag` – The _Docker Image tag_ that should be deployed. (In practice you can use some other string that identifies a version of your system to deploy – you will need to process it accordingly in the script.)
123−* `--app-env-override` [⭐](#star) – App-level overrides. These overrides should be passed to the server being deployed. These overrides are specified in the _Web UI_. They are passed in the format of `KEY=VALUE` pairs.
124−* `--deployment-override` [⭐](#star) – Deployment-level overrides. These overrides should be used to set up the deployment environment itself, rather than be passed to the server being deployed. These overrides are specified in the _Web UI_. They are passed in the format of `KEY=VALUE` pairs.
63+As with other commands, exit code `0` indicates that everything is fine and a non-zero exit code indicates that something is wrong and _stdout_ should be shown to the user.
12564
126−#### Execution example
65+### 👀 info
12766
128−The script might be called something like this:
67+#### Description
68+
69+This script returns user-facing metadata about a deployment. Currently, the metadata consists of URLs that are relevant for the deployment. Things like the deployment URL, the URL to view logs, and the database URL.
70+
71+The script should return the metadata as a two-column CSV table to _stdout_:
72+
73+```
74+app,https://foo.example.com
75+api,https://api.foo.example.com
76+```
77+
78+#### Sample implementation
12979
13080```bash
131−update --project-name "Cactus store" --base-domain "cactus-store.com" --namespace "cactus" --name "orange-button" --tag "c9bbc3fcc69e5aa094bca110c6f79419ab7be77a" --app-env-override "EMAIL_TOKEN=123123" --app-env-override "SECRET_BUTTON_ENABLED=True" --deployment-override "FANCY_DATABASE=True"
81+echo "app,https://${name}.example.com"
82+echo "api,https://api.${name}.example.com"
13283```
84+### 🔧 update
85+
86+#### Description
87+
88+Updates a deployment in _Kubernetes_ to a new *Docker Image tag*.
13389
13490#### Sample implementation
13591
@@ -154,15 +110,7 @@ Deleting the _Persistent Volume Claims_ should be done in the [`cleanup`](#-clea
154110
155111This script should in some sense be the inverse of [`create`](#-create) (up to _Persistent Volumes_).
156112
157−This script receives only [the default command-line arguments](#general-behavior) as input.
158−
159−#### Execution example
160−
161−The script might be called something like this:
162−
163−```bash
164−archive --project-name "Cactus store" --base-domain "cactus-store.com" --namespace "cactus" --name "orange-button"
165−```
113+A good way of doing this is to scale the number of replicas of your server to 0.
166114
167115#### Sample implementation
168116
@@ -170,23 +118,24 @@ archive --project-name "Cactus store" --base-domain "cactus-store.com" --namespa
170118helm delete "$name" --purge
171119```
172120
173−### ✅ check
121+### 🗃↩️ unarchive
174122
175123#### Description
176124
177−This script checks the status of the deployment.
125+This command should undo whatever the [`archive`](#-archive) command did. So, if the [`archive`](#-archive) command scaled the server to 0 replicas, this command should scale it back up to the number of replicas required for normal operation.
178126
179−If the script exits with `0`, it means that the deployment is healthy and up. If the script exits with a non-zero exit code, it means that the deployment is not healthy or down.
127+### ✅ check
180128
181−This script receives only [the default command-line arguments](#general-behavior) as input.
129+#### Description
182130
183−#### Execution example
131+This script checks the status of the deployment.
184132
185−The script might be called something like this:
133+If the script exits with `0`, it means that the deployment is healthy and up. If the script exits with a non-zero exit code, it means that the deployment is not healthy or down.
186134
187−```bash
188−check --project-name "Cactus store" --base-domain "cactus-store.com" --namespace "cactus" --name "orange-button"
189−```
135+You can specify exactly what error occured using exit codes:
136+- `1` – a generic failure.
137+- `2` – the deployment is partially down (some containers are unhealthy).
138+- `3` – tag mismatch, the deployment has not been updated to the expected version.
190139
191140#### Sample implementation
192141
@@ -203,16 +152,6 @@ Cleans up any persistent resources a deployment might have allocated, such as _P
203152
204153This script will always be called **after** [`archive`](#-archive) has been called on the given deployment.
205154
206−This script receives only [the default command-line arguments](#general-behavior) as input.
207−
208−#### Execution example
209−
210−The script might be called something like this:
211−
212−```bash
213−cleanup --project-name "Cactus store" --base-domain "cactus-store.com" --namespace "cactus" --name "orange-button"
214−```
215−
216155#### Sample implementation
217156
218157```bash
@@ -227,68 +166,152 @@ This script checks that a given deployment really has been archived and is no lo
227166
228167If the scripts exits with `0`, it means that the deployment has been archived successfully. If the script exits with a non-zero exit code, it means that the deployment has not been archived.
229168
169+#### Sample implementation
230170
231−This script receives only [the default command-line arguments](#general-behavior) as input.
171+```bash
172+helm status $name
173+```
232174
233−#### Execution example
175+## Service control scripts
234176
235−The script might be called something like this:
177+### 🔁 init
236178
237−```bash
238−archive_check --project-name "Cactus store" --base-domain "cactus-store.com" --namespace "cactus" --name "orange-button"
239−```
179+#### Description
180+
181+This script is called **once** during the creation of the `Octopod Server` *Kubernetes Pod* to set up the proper environment to execute all other scripts.
182+
183+It is guaranteed that this script will be called **before** any of the other scripts.
184+
185+You could, for example, set up access to your *version control system*, *cloud providers*, etc. This can be achieved by saving the configuration into files in the `$HOME` directory.
186+
187+Unlike all other scripts, this script receives no arguments.
240188
241189#### Sample implementation
242190
243191```bash
244−helm status $name
192+mkdir $HOME/.ssh
193+echo -e "Host github.com\nHostname github.com\nPort 22\nUser git\nIdentityFile $HOME/.ssh/deploy.key" > $HOME/.ssh/config
194+echo "MY_DEPLOY_KEY" > $HOME/.ssh/deploy.key"
245195```
246196
247−### 🐋✅ tag_check
197+### 🔔 notifications
248198
249199#### Description
250200
251−This script is called right before [`create`](#-create) and [`update`](#-update) scripts to check that a given _Docker Image tag_ exists. This can be useful since it can be very easy to make a typo in the _Docker Image tag_ and deployments are typically not instant. Implementing this script would allow the user of the _Web UI_ to instantly get an error specifically about a wrong _Docker Image tag_.
201+This script gets called every time a deployment changes its status (apart from creation and deletion). It might be useful if you want to send notifications about certain deployment status transitions. The complete list of statuses and their transitions can be found in the [technical architecture document](Technical_architecture.md#️-deployment-state-transitions).
202+
203+It is optional and can be omitted altogether.
252204
253205This script receives the following additional command-line arguments as input:
254−* `--tag` – The _Docker Image tag_ that should be checked.
206+* `--project-name` – the name of the project. It is supplied mostly for informational purposes and can be useful for sending notifications if that is necessary.
207+* `--base-domain` – the base domain. It can be useful for generating the URLs of deployments.
208+* `--namespace` – The namespace in which the deployment should be created.
209+* `--name` – The name of the deployment supplied in the _Web UI_. It can be useful for generating the deployment URL.
210+* `--old-status` – The previous status the deployment was in.
211+* `--new-status` – The new status the deployment transitioned to.
212+
213+The last two arguments can have one of the following values:
214+- `Running`
215+- `GenericFailure`
216+- `TagMismatch`
217+- `PartialAvailability`
218+- `CreatePending`
219+- `UpdatePending`
220+- `ArchivePending`
221+- `Archived`
222+- `CleanupFailed`
255223
256224#### Execution example
257225
258226The script might be called something like this:
259227
260228```bash
261−tag_check --project-name "Cactus store" --base-domain "cactus-store.com" --namespace "cactus" --name "orange-button" --tag "c9bbc3fcc69e5aa094bca110c6f79419ab7be77a"
229+notification --project-name "Cactus store" --base-domain "cactus-store.com" --namespace "cactus" --name "orange-button" --old-status "UpdatePending" --new-status "Running"
262230```
263231
264−### 👀 info
232+### 🎛🔧 deployment_config
265233
266234#### Description
267235
268−This script returns user-facing metadata about a deployment. Currently, the metadata consists of URLs that are relevant for the deployment. Things like the deployment URL, the URL to view logs, and the database URL.
236+This script is used to generate default deployment configuration key/value pairs. This configuration is shown to the user in the _Web UI_ with the ability to modify it.
237+
238+The key/value pairs are read from the _stdout_ stream of the script. It should be formatted as a CSV file with two columns.
269239
270−The script should return the metadata as a two-column CSV table:
240+This script receives the following arguments:
241+
242+* `--project-name` – the name of the project. It is supplied mostly for informational purposes and can be useful for sending notifications if that is necessary.
243+* `--base-domain` – the base domain. It can be useful for generating the URLs of deployments.
244+* `--namespace` – The namespace in which the deployment should be created.
271245
246+#### Sample implementation
247+
248+```bash
249+echo "image.tag,"
250+echo "application_api_version,1.0"
272251```
273−app,https://foo.example.com
274−api,https://api.foo.example.com
252+
253+### 🎛🔧🔑 deployment_config_keys
254+
255+#### Description
256+
257+This script is used to get the set of keys that the deployment configuration can have. This is useful to suggest possible values when the user wants to add new values to in the _Web UI_.
258+
259+The keys are read from the _stdout_ stream of the script. It should be formatted as a CSV file with one column (a list separated by newlines).
260+
261+This script receives the same arguments as the [`deployment_config`](#-deployment_config) command.
262+
263+
264+#### Sample implementation
265+
266+```bash
267+echo "image.tag"
268+echo "application_api_version"
269+echo "database_version"
275270```
276271
277−This script receives only [the default command-line arguments](#general-behavior) as input.
272+### 🎛📱 application_config
278273
279−#### Execution example
274+#### Description
280275
281−The script might be called something like this:
276+This script is used to generate default application configuration key/value pairs. This configuration is shown to the user in the _Web UI_ with the ability to modify it.
277+
278+The key/value pairs are read from the _stdout_ stream of the script. It should be formatted as a CSV file with two columns.
279+
280+This script receives the same arguments as the [`deployment_config`](#-deployment_config) command.
281+
282+Additionally, the script receives the deployment configuration key/value pairs as described in the ["Deployment lifecycle scripts" section](#deployment-lifecycle-scripts): any number of `--deployment-config <KEY>=<VALUE>` arguments.
283+
284+#### Sample implementation
282285
283286```bash
284−info --project-name "Cactus store" --base-domain "cactus-store.com" --namespace "cactus" --name "orange-button"
287+echo "image.tag,"
288+echo "application_api_version,1.0"
285289```
286290
291+### 🎛📱🔑 application_config_keys
292+
293+#### Description
294+
295+This script is used to get the set of keys that the application configuration can have. This is useful to suggest possible values when the user wants to add new values to in the _Web UI_.
296+
297+The keys are read from the _stdout_ stream of the script. It should be formatted as a CSV file with one column (a list separated by newlines).
298+
299+This script receives the same arguments as the [`application_config` script](#-application_config).
300+
287301#### Sample implementation
288302
289303```bash
290−echo "app,https://${name}.example.com"
291−echo "api,https://api.${name}.example.com"
304+echo "image.tag"
305+echo "application_api_version"
306+echo "database_version"
292307```
293308
309+<br />
310+
311+<p align="center">
312+ <i>Star the project of you like it</i>
313+</p>
314+
315+<p align="center"><a href="https://typeable.io"><img src="../../img/typeable_logo.svg" width="177px"></img></a></p>
316+
294317[configmap]: https://kubernetes.io/docs/concepts/configuration/configmap/
docs/en/Helm-based_deployment_guide.md+54−133
@@ -1,177 +1,98 @@
11# Helm-based deployment guide
22
3−<details>
4− <summary>Table of contents</summary>
3+In this guide we'll show you how to deploy bitnami's [wordpress chart](https://github.com/bitnami/charts/tree/master/bitnami/wordpress) with Octopod.
54
6−- [The web application](#the-web-application)
7−- [Setting up Octopod](#setting-up-octopod)
8− - [Control scripts](#control-scripts)
9− - [A word about TLS](#a-word-about-tls)
10− - [Deploying Octopod](#deploying-octopod)
11−- [Testing out the deployment](#testing-out-the-deployment)
12− - [Setting up _octo CLI_](#setting-up-octo-cli)
13− - [Setting up certificates](#setting-up-certificates)
14− - [Setting up the API URL](#setting-up-the-api-url)
15− - [Creating a deployment](#creating-a-deployment)
16− - [Adding an override](#adding-an-override)
17− - [Updating the deployment version](#updating-the-deployment-version)
18− - [Changing the number of replicas](#changing-the-number-of-replicas)
5+## Your first deployment
196
20−</details>
7+### Install Octopod
218
22−In this guide, we will examine a very simple web application and explore setting up _Octopod_ to deploy it.
9+Make sure that you have Octopod installed before going further. If you haven't, go check our [Octopod deployment guide](Octopod_deployment_guide.md).
2310
24−## The web application
11+Note: In this guide we assume that you have octopod installed on your local machine.
12+Open up Octopod in your browser and you'll see something like this:
2513
26−The web application we will be using is a very simple application that serves a single endpoint `/`. The returned HTML markup contains the environment variables the executable has read from the environment. The only variables returned are the ones whose name starts with `APP_ENV`.
14+![](../images/octopod_blank.png)
2715
28−![](../images/first.png)
16+### Create the deployment
2917
30−The source code can be found in the [examples/web-app](../../examples/web-app) folder of this repository.
18+Click on the _New Deployment_ button:
3119
32−You can also find a second version of the server in the [examples/web-app-v2](../../examples/web-app-v2) folder of this repository. The second version is identical to the first version with the only difference being that it returns the variables as an unordered list.
20+![](../images/octopod_deployment_blank.png)
3321
34−![](../images/second.png)
22+### The config
3523
36−We have already built and pushed the two versions of the application into the [typeable/octopod-web-app-example](https://hub.docker.com/repository/docker/typeable/octopod-web-app-example) DockerHub registry under the `v1` and `v2` tags.
24+As you can see we filled some parameters for you ― it's very convinient, because you don't want fill URL to your private helm repo over and over again, right?
3725
38−## Setting up Octopod
26+All these parameters can be modified at the chart level, [here](../../charts/octopod/values.yaml#L90) is an example. Or you can, of course, override them manually from the Octopod UI.
3927
40−### Control scripts
28+One thing is left to fill, though.
4129
42−The only thing you need to do to configure _Octopod_ to work with your application is to write appropriate [_control scripts_](Control_scripts.md) to manipulate your deployments. We have already written the appropriate _control scripts_ for this application. You can find them in the [examples/helm-based-control-scripts](../../examples/helm-based-control-scripts) folder of this repository. The scripts are written in the _Rust_ programming language.
30+![](../images/octopod_deployment_filled.png)
4331
44−The most interesting of them all is the [create.rs](../../examples/helm-based-control-scripts/src/bin/create.rs) script. The basic order of operations is:
32+**Name** ― we've chosen `wordpress`, but you can choose whatever name you like.
4533
46−1. Read the passed command-line arguments
47−2. Clone the repo to get the _charts_ used to deploy the application with _helm_
48−3. Generate the arguments that should be passed to _helm_
49−4. Call _helm_ with the downloaded _charts_ and the generated arguments
34+Octopod loads all overrides from the [chart values](https://github.com/bitnami/charts/blob/master/bitnami/wordpress/values.yaml) dynamically for each chart you want to deploy.
5035
51−> 💡 **NOTE:** You might have noticed that there is no `update.rs`. That is because our application is stateless and packaged up into a single _chart_. This allows us to simply reuse the same script for both creating and updating a deployment. If you have a more complicated setup with a database, for example, you will most likely need a distinct implementation for `update`.
36+Try to add new App override to see list of available keys for the wordpress chart.
5237
53−### A word about TLS
38+![](../images/octopod_app_keys_list.png)
5439
55−If you are deploying Web applications, as we are here, you probably want to use TLS to encrypt your connections to your deployment. The most straightforward way of doing this is generating a separate TLS certificate for every deployment (for every subdomain). [_Cert Manager_][cert-manager] creates TLS certificates through [_Let’s Encrypt_][lets-encrypt] and [_Let’s Encrypt_][lets-encrypt] has [a limit on the amount of certificates][lets-encrypt-rate-limits] you can issue within a given time interval. If you exceed this limit you will start getting a _too many registrations for this IP_ error. If that is the case moving the [_Cert Manager_][cert-manager] _Pod_ might help.
40+### Deploy
5641
57−### Deploying Octopod
42+When you have it all filled out. Click _Save_ button and wait until the deployment transitions to a _running_ state:
43+![](../images/octopod_deployment_filled.png)
5844
59−To deploy _Octopod_ you will need to follow the [_Octopod_ deployment guide](Octopod_deployment_guide.md). The only modification will be that you will replace the "Control Scripts Setup" section in the last step with the appropriate values.
45+Now you can click on a _wordpress_ link in the _links_ section and you'll be redirected to your wordpress instance:
46+![](../images/wordpress_blank.png)
6047
61−These values point to a docker registry where we have already packaged up these _control scripts_ into a _Docker Image_.
48+So here you have it, your first Octopod deployment!
6249
63−```bash
64−#################################################
65−# Control Scripts Setup
66−#
67−# if you are just testing things out you can paste the values
68−# from the Helm Deployment Guide example
69−#################################################
50+## Going further
7051
71−# The name of the registry with control scripts
72−utils_registry="typeable"
52+As we said earlier you can override all default parameters using Octopod UI. Let's dive right in!
7353
74−# The name of the image with control scripts
75−utils_image="octopod-helm-example"
54+First, let's archive our wordpress deployment:
7655
77−# The tag of the image to use
78−utils_image_tag="1.0"
79−```
56+![](../images/octopod_archive.png)
8057
81−## Testing out the deployment
58+### The config
8259
83−### Setting up _octo CLI_
60+And create one more deployment, this time using a different set of overrides:
8461
85−Using the Web UI is fairly straightforward, so we will examine creating deployments with the [_octo CLI_](Octo_user_guide.md).
62+![](../images/octopod_in_octopod_deployment.png)
8663
87−#### Setting up certificates
64+**Name:** octopod-internal
8865
89−You will need to get the paths to `client_cert.pem` and `client_key.pem` generated in the [Creating SSL certificates](Octopod_deployment_guide.md#creating-ssl-certificates) step and place them into `TLS_CERT_PATH` and `TLS_KEY_PATH` environment variables:
66+**App Overrides:**
9067
91−```bash
92−export TLS_CERT_PATH=/tmp/octopod/certs/client_cert.pem
93−export TLS_KEY_PATH=/tmp/octopod/certs/client_key.pem
94−```
68+| Key | Value |
69+| --------------------: | ------------------------- |
70+| `octopod.baseDomain` | `octopod-internal.lvh.me` |
71+| `ingress.tls.enabled` | `false` |
9572
96−#### Setting up the API URL
9773
98−You will also need to set the power API URL (the `power_app_domain` value from the [Installing _Octopod Server_](Octopod_deployment_guide.md#installing-octopod-server) section) as the `OCTOPOD_URL` environment variable:
74+**Deployment Overrides:**
9975
100−```bash
101−export OCTOPOD_URL=<power_app_domain>
102−```
76+| Key | Value |
77+| ---------------: | ------------------------------------- |
78+| `chart_name` | `octopod` |
79+| `chart_repo_url` | `https://typeable.github.io/octopod/` |
80+| `chart_version` | `0.6.0` |
10381
104−### Creating a deployment
82+## Where can I get these values?
10583
106−To create a deployment you can now run:
84+As in the previous example Octopod parsed the _App Overrides_ from the [chart values](../../charts/octopod/values.yaml), but the _Deployment Overrides_ are passed as configuration to the control scripts. You can read more about these parameters in the [control script docs](../../helm-control-scripts/README.md).
10785
108−```bash
109−$ octo create -n hello-octopod -t v1 -e APP_ENV_KEY1=VALUE1
110−```
86+`chart_repo_url`, `chart_name` parameters are usually provided by the chart developer. Version however is usually skipped and you encouraged to take the last one, but we think about this as a bad practice.
11187
112−The options are:
113−- `-n hello-octopod` – specifies that the name (subdomain) of the deployment should be `hello-octopod`
114−- `-t v1` specifies the version (Docker Image Tag) of the application to deploy to be `v1`
115−- `-e APP_ENV_KEY1=VALUE1` specifies adds an application-level key-value pair `APP_ENV_KEY1=VALUE1`
88+If you're not sure where to get the `chart_version` parameter you can add repo locally using `helm repo add` and then execute `helm search repo <CHART_NAME> -l` too see the whole list of available chart versions.
11689
117−> 💡 **NOTE:** For more detail on _octo CLI_ options please see the [octo CLI user guide](Octo_user_guide.md).
90+Now you have Octopod inside Octopod! Try to install your own chart with Octopod!
11891
119−This will run the `create` _control script_, which in turn will call `helm`. After waiting a couple of seconds you can visit `http://hello-octopod.<base_domain>` to see the running application:
92+<br />
12093
121−![](../images/hello-octopod-1.png)
94+<p align="center">
95+ <i>Star the project of you like it</i>
96+</p>
12297
123−You can also see the deployed pod in the cluster using `kubectl`:
124−
125−```bash
126−$ kubectl get pods -n deployment
127−NAME READY STATUS RESTARTS AGE
128−app-hello-octopod-8965856-qbwvq 1/1 Running 0 15s
129−```
130−
131−### Adding an override
132−
133−You can modify deployments by adding or removing overrides. To add a new application-level override run:
134−
135−```bash
136−$ octo update -n hello-octopod -t v1 -e APP_ENV_KEY2=VALUE2
137−```
138−
139−This will run the `update` _control script_ (which is identical to the `create` script in our case), which in turn will call `helm`. After waiting a few seconds you visit the deployment URL again and see the redeployed version:
140−
141−![](../images/hello-octopod-2.png)
142−
143−### Updating the deployment version
144−
145−You can change the version (_Docker Image Tag_) of your deployment like so:
146−
147−```bash
148−$ octo update -n hello-octopod -t v2
149−```
150−
151−After waiting a few seconds you visit the deployment URL again and see the redeployed version:
152−
153−![](../images/hello-octopod-3.png)
154−
155−### Changing the number of replicas
156−
157−You can change the number of replicas of your deployment (this is [essentially implemented in the _charts_ that we use](../../examples/web-app/charts/web-app/templates/deployment.yaml#L7)) like so:
158−
159−```bash
160−$ octo update -n hello-octopod -t v2 -o replicas=3
161−```
162−
163−`-o replicas=3` adds a deployment-level key-value pair (override) `replicas=3`.
164−
165−You can verify that the new replicas have been deployed using `kubectl`:
166−
167−```bash
168−$ kubectl get pods -n deployment
169−NAME READY STATUS RESTARTS AGE
170−app-hello-octopod-8965856-qbwvq 1/1 Running 0 97m
171−app-hello-octopod-8965856-v585c 1/1 Running 0 15s
172−app-hello-octopod-8965856-v88md 1/1 Running 0 15s
173−```
174−
175−[cert-manager]: https://cert-manager.io/docs
176−[lets-encrypt]: https://letsencrypt.org
177−[lets-encrypt-rate-limits]: https://letsencrypt.org/docs/rate-limits
98+<p align="center"><a href="https://typeable.io"><img src="../../img/typeable_logo.svg" width="177px"></img></a></p>
docs/en/Integration.md+9−8
@@ -1,12 +1,5 @@
11# Integration into existing CI/CD pipelines
22
3−<details>
4− <summary>Table of contents</summary>
5−
6−- [✨ Creating deployments](#-creating-deployments)
7−- [🚀 Updating deployments](#-updating-deployments)
8−
9−</details>
103
114You likely already have some form of CI integration with your version control system, such as *GitHub Action* or *Travis CI*, to run various checks on your code. Most of these services are set up by providing what is essentially just a shell script that is run under specific conditions.
125
@@ -28,8 +21,16 @@ octo create -n $NAME -t $IMAGE_TAG
2821
2922## 🚀 Updating deployments
3023
31−Updating deployments is done using the same arguments, but you need to call `create` command, instead of the `update` command:
24+Updating deployments is done using the same arguments, but you need to call the `create` command, instead of the `update` command:
3225
3326```bash
3427octo update -n $NAME -t $IMAGE_TAG
3528```
29+
30+<br />
31+
32+<p align="center">
33+ <i>Star the project of you like it</i>
34+</p>
35+
36+<p align="center"><a href="https://typeable.io"><img src="../../img/typeable_logo.svg" width="177px"></img></a></p>
docs/en/Octo_user_guide.md+31−76
@@ -1,66 +1,20 @@
11# Octo CLI User Guide
22
3−<details>
4− <summary>Table of contents</summary>
5−
6−- [Environment variables](#environment-variables)
7− - [`OCTOPOD_URL`](#octopod_url)
8− - [`TLS_CERT_PATH` and `TLS_KEY_PATH`](#tls_cert_path-and-tls_key_path)
9−- [Commands](#commands)
10− - [create](#create)
11− - [Description](#description)
12− - [Options](#options)
13− - [Usage example](#usage-example)
14− - [list](#list)
15− - [Description](#description-1)
16− - [Options](#options-1)
17− - [Usage example](#usage-example-1)
18− - [archive](#archive)
19− - [Description](#description-2)
20− - [Options](#options-2)
21− - [Usage example](#usage-example-2)
22− - [update](#update)
23− - [Description](#description-3)
24− - [Options](#options-3)
25− - [Usage example](#usage-example-3)
26− - [info](#info)
27− - [Description](#description-4)
28− - [Options](#options-4)
29− - [Usage example](#usage-example-4)
30− - [cleanup](#cleanup)
31− - [Description](#description-5)
32− - [Options](#options-5)
33− - [Usage example](#usage-example-5)
34− - [restore](#restore)
35− - [Description](#description-6)
36− - [Options](#options-6)
37− - [Usage example](#usage-example-6)
38− - [clean-archive](#clean-archive)
39− - [Description](#description-7)
40− - [Options](#options-7)
41− - [Usage example](#usage-example-7)
42− - [logs](#logs)
43− - [Description](#description-8)
44− - [Options](#options-8)
45− - [Usage example](#usage-example-8)
46−
47−</details>
48−
493## Environment variables
504
515All commands _octo CLI_ executes require the executable to send authenticated requests to the _Octopod Server_. For this purpose _octo CLI_ needs both a way to reach your particular instance of _Octopod Server_, and a way for _Octopod Server_ to identify that you are allowed to make the given request.
526
537### `OCTOPOD_URL`
548
55−> **_NOTE:_** this argument is **required** for _octo CLI_ to function.
56−
57−`OCTOPOD_URL` is an environment variable _octo CLI_ reads to find your particular _Octopod Server_ installation. For example, it could contain `https://octopod-power-app.example.com:443`.
9+`OCTOPOD_URL` is an environment variable _octo CLI_ reads to find your particular _Octopod Server_ installation. For example, it could contain `https://octopod-powerapp.example.com:443`.
5810
59−### `TLS_CERT_PATH` and `TLS_KEY_PATH`
11+### `OCTO_AUTHORIZATION_HEADER`
6012
61−`TLS_CERT_PATH` should contain the path to the TLS certificate you generated when setting up _Octopod Server_ and `TLS_KEY_PATH` should contain the path to the TLS key you generated when setting up _Octopod Server_. These files are used to authenticate the requests to _Octopod Server_.
13+`OCTO_AUTHORIZATION_HEADER` is an environment variable that should contain the `Authorization` header to use to authenticate requests to your Octopod server. You can obtain the header value by running the following command after installing Octopod:
6214
63−If these variables are not set, then _octo CLI_ tries to read the certificate from the path `./cert.pem`, and the key from the path `./key.pem`.
15+```bash
16+kubectl -n octopod get secret <HELM_RELEASE_NAME>-cli-auth-secret -o jsonpath='{.data.cli-secret}' | base64 -d
17+```
6418
6519## Commands
6620
@@ -76,8 +30,8 @@ Creates a new deployment.
7630
7731- `-n,--name ARG` – The name of the deployment to create
7832- `-t,--tag ARG` – The _Docker tag_ to deploy
79−- `-e,--set-app-env-override ARG` [⭐](#star) – Set an application-level override. Expects a string in the format `KEY=VALUE`.
80−- `-o,--set-deployment-override ARG` [⭐](#star) – Set a deployment-level override. Expects a string in the format `KEY=VALUE`.
33+- `-e,--set-app-config ARG` [⭐](#star) – Set an application-level configuration. Expects a string in the format `KEY=VALUE`.
34+- `-o,--set-deployment-config ARG` [⭐](#star) – Set a deployment-level configuration. Expects a string in the format `KEY=VALUE`.
8135
8236#### Usage example
8337
@@ -130,10 +84,10 @@ Updates the parameters of a given deployment.
13084
13185- `-n,--name ARG` – The name of the deployment to update
13286- `-t,--tag ARG` – The new _Docker tag_ to update the deployment to
133−- `-e,--set-app-env-override ARG` [⭐](#star) – Add a new or replace an existing application-level override. Expects a string in the format `KEY=VALUE`.
134−- `-E,--unset-app-env-override ARG` [⭐](#star) – Removes an existing application-level override.
135−- `-o,--set-deployment-override ARG` [⭐](#star) – Add a new or replace an existing deployment-level override. Expects a string in the format `KEY=VALUE`.
136−- `-O,--unset-deployment-override` [⭐](#star) – Removes an existing deployment-level override.
87+- `-e,--set-app-config ARG` [⭐](#star) – Add a new or replace an existing application-level configuration. Expects a string in the format `KEY=VALUE`.
88+- `-E,--unset-app-env-configuration ARG` [⭐](#star) – Removes an existing application-level configuration.
89+- `-o,--set-deployment-config ARG` [⭐](#star) – Add a new or replace an existing deployment-level configuration. Expects a string in the format `KEY=VALUE`.
90+- `-O,--unset-deployment-configuration` [⭐](#star) – Removes an existing deployment-level configuration.
13791
13892#### Usage example
13993
@@ -157,21 +111,21 @@ Gets detailed information about a deployment, including a log of all preformed a
157111$ octo info -n hello-octopod
158112Current settings:
159113tag: v1
160−application overrides: app=1 (Public)
114+application configurations: app=1 (Public)
161115
162−deployment overrides: dep=2 (Public)
116+deployment configurations: dep=2 (Public)
163117
164118metadata:
165119 app: https://ree.lvh.me
166120
167121Last logs:
168−┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━┳━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
169−┃ Created at ┃ Action id ┃ Action ┃ Tag ┃ App overrides ┃ Deployment overrides ┃ Exit code ┃
170−┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━╇━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
171−│ 2020-11-02T17:14:03 │ 7 │ create │ v1 │ app=1 (Public) │ dep=2 (Public) │ 1 │
172−├─────────────────────┼───────────┼────────┼─────┼────────────────┼──────────────────────┼───────────┤
173−│ 2020-11-02T19:01:02 │ 8 │ update │ v1 │ app=1 (Public) │ dep=2 (Public) │ 1 │
174−└─────────────────────┴───────────┴────────┴─────┴────────────────┴──────────────────────┴───────────┘
122+┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
123+┃ Created at ┃ Action id ┃ Action ┃ App configurations ┃ Deployment configurations ┃ Exit code ┃
124+┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
125+│ 2020-11-02T17:14:03 │ 7 │ create │ app=1 (Public) │ dep=2 (Public) │ 1 │
126+├─────────────────────┼───────────┼────────┼────────────────┼──────────────────────┼───────────┤
127+│ 2020-11-02T19:01:02 │ 8 │ update │ app=1 (Public) │ dep=2 (Public) │ 1 │
128+└─────────────────────┴───────────┴────────┴────────────────┴──────────────────────┴───────────┘
175129```
176130
177131### cleanup
@@ -205,13 +159,6 @@ Restores a previously archived deployment.
205159```bash
206160$ octo restore -n hello-octopod
207161```
208−
209−### clean-archive
210−
211−#### Description
212−
213−Calls `octo cleanup` on all deployments that were archived more than two weeks ago. This command is used in a cronjob which is automatically set up when deploying _Octopod Server_.
214−
215162#### Options
216163
217164This command does not have any options.
@@ -242,10 +189,18 @@ $ octo logs -a 13
242189
243190 stderr:
244191
245−error: Found argument '--deployment-override' which wasn't expected, or isn't valid in this context
192+error: Found argument '--deployment-configuration' which wasn't expected, or isn't valid in this context
246193
247194USAGE:
248− update --app-env-override <app-env-override>... --base-domain <base-domain> --name <name> --namespace <namespace> --project-name <project-name> --tag <tag>
195+ update --app-env-configuration <app-env-configuration>... --base-domain <base-domain> --name <name> --namespace <namespace> --project-name <project-name> --tag <tag>
249196
250197For more information try --help
251198```
199+
200+<br />
201+
202+<p align="center">
203+ <i>Star the project of you like it</i>
204+</p>
205+
206+<p align="center"><a href="https://typeable.io"><img src="../../img/typeable_logo.svg" width="177px"></img></a></p>
docs/en/Octopod_deployment_guide.md+45−364
@@ -1,399 +1,80 @@
11# Octopod Server deployment guide
22
3−<details>
4− <summary>Table of contents</summary>
3+## Installation options
4+There are several options to install Octopod depending on your needs.
55
6−- [Installing required utilities](#installing-required-utilities)
7−- [Setting up your cluster](#setting-up-your-cluster)
8− - [General utilities](#general-utilities)
9− - [Tiller (Helm)](#tiller-helm)
10− - [Cluster access privileges](#cluster-access-privileges)
11− - [A word about TLS](#a-word-about-tls)
12−- [Downloading project sources code](#downloading-project-sources-code)
13−- [Creating required namespaces](#creating-required-namespaces)
14−- [Creating required _Service Accounts_](#creating-required-service-accounts)
15− - [Creating the actual service account](#creating-the-actual-service-account)
16− - [Giving the appropriate _Service Account_ roles](#giving-the-appropriate-service-account-roles)
17−- [Web UI authentication secrets](#web-ui-authentication-secrets)
18−- [_octo CLI_ authentication certificates](#octo-cli-authentication-certificates)
19− - [Creating SSL certificates](#creating-ssl-certificates)
20− - [Enabling SSL passthrough](#enabling-ssl-passthrough)
21−- [Setting up DNS](#setting-up-dns)
22− - [Deploying _Octopod_ on localhost](#deploying-octopod-on-localhost)
23−- [Installing _Octopod_ infrastructure](#installing-octopod-infrastructure)
24− - [Installing the appropriate _Storage Class_](#installing-the-appropriate-storage-class)
25− - [Installing the actual infrastructure](#installing-the-actual-infrastructure)
26−- [Installing _Octopod Server_](#installing-octopod-server)
6+### If you have a Kubernetes cluster
7+You can install Octopod in any Kubernetes cluster using our [Helm chart](../../charts/octopod).
278
28−</details>
299
30−## Installing required utilities
10+Your cluster must satisfy the following requirements:
3111
32−Installing _Octopod Server_ in your cluster will require that you have the following tools installed on your system:
33−1. [_kubectl_][kubectl]
34−2. [_helm 2_][helm]
12+#### Mandatory requirements
3513
36−## Setting up your cluster
14+- Kubernetes version >= 1.12.0 <= 1.22.0
15+- PVC support (for PostgreSQL persistence)
16+- [NGINX Ingress](https://kubernetes.github.io/ingress-nginx/) contoller version <= 0.49.3 installed. NGINX Ingress controller v1.x.x is not currently supported
3717
38−### General utilities
18+#### Optional requirements
3919
40−_Octopod Server_ requires the following utilities to be installed in your cluster:
20+- Cert Manager ([cert-manager](https://cert-manager.io/docs/installation/)) installed, if you want to get SSL certificates from Let's Encrypt automatically.
4121
42−1. [_Ingress Nginx_][ingress-nginx]
43−2. [_Cert Manager_][cert-manager]
22+After ensuring that your cluster satisfies the requirements you can follow [the Helm installation instruction](../../charts/octopod/README.md) provided with our Helm chart.
4423
45−_Octopod Server_ require the following minimal resources to function properly: 2 CPU, 2 GB of RAM. Make sure you have sufficient resources in your cluster.
24+### Running Octopod in production considerations.
4625
47−By default _Octopod Server_ will be deployed on nodes with the `role=stand` label. Please make sue you have the appropriate label set in your cluster:
26+You must consider several things before running Octopod in production and onboarding your team.
4827
49−```bash
50−kubectl label node <your_node> role=stand
51−```
52−
53−### Tiller (Helm)
54−
55−[_Tiller_][tiller] is a cluster-side service used by [_helm 2_][helm] to manage deployments. The easiest way to install it is using the following command:
56−
57−```bash
58−helm init
59−```
60−
61−#### Cluster access privileges
62−
63−When installing _Octopod Server_ you might encounter [a problem with cluster access privileges](https://github.com/helm/helm/issues/5100) related to [_Tiller_][tiller].
64−
65−To give sufficient privileges to [_Tiller_][tiller] you can use the following commands:
66−
67−```bash
68−kubectl create -n kube-system serviceaccount tiller
69−kubectl --namespace kube-system create clusterrolebinding tiller-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
70−kubectl --namespace kube-system patch deploy tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'
71−```
72−
73−### A word about TLS
74−
75−To function properly _Octopod_ needs to generate three TLS certificates for the three subdomains it will be using. [_Cert Manager_][cert-manager] creates TLS certificates through [_Let’s Encrypt_][lets-encrypt] and [_Let’s Encrypt_][lets-encrypt] has [a limit on the amount of certificates][lets-encrypt-rate-limits] you can issue within a given time interval. If you exceed this limit you will start getting a _too many registrations for this IP_ error. If that is the case moving the [_Cert Manager_][cert-manager] _Pod_ might help.
76−
77−## Downloading project sources code
78−
79−To download the source code required to install _Octopod Sever_ you will need to clone the git repository:
80−
81−```bash
82−git clone --branch master https://github.com/typeable/octopod.git /tmp/octopod
83−```
84−
85−## Creating required namespaces
86−
87−_Octopod_ uses the following namespaces in your cluster:
88−
89−1. `deployment` – as the name would suggest your deployments will be installed in this namespace
90−2. `octopod` – this namespace will be used to install the _Octopod_ infrastructure
91−
92−To create the two namespaces you can use these commands:
93−
94−```bash
95−kubectl create namespace deployment
96−kubectl create namespace octopod
97−```
98−
99−## Creating required [_Service Accounts_][kubernetes-service-account]
100−
101−### Creating the actual service account
102−
103−_Octopod Server_ requires an `octopod` [_Service Account_][kubernetes-service-account] to function. You can create it using the following command:
104−
105−```bash
106−kubectl create -n octopod serviceaccount octopod
107−```
108−
109−### Giving the appropriate _Service Account_ roles
110−
111−1. If you are planning to use [_helm 2_][helm] in your [_Control scripts_](Control_scripts.md) to deploy your deployments, you will need to give appropriate permissions to the `octopod` _Service Account_:
112− ```bash
113− cd /tmp/octopod/charts
114− helm install --name octopod-helm-access ./helm-access
115− ```
116−
117−2. If you are planning to delete [_Persistent Volumes Claims_][kubernetes-pvc] in your [_Control scripts_](Control_scripts.md) (might be useful for the `cleanup` script), you will need to give appropriate permissions to the `octopod` _Service Account_:
118−
119− ```bash
120− cd /tmp/octopod/charts
121− helm install --name octopod-pvc-control ./pvc-control
122− ```
123−
124−3. If you are planning to use _Octopod_ to delete unused certificates in your [_Control scripts_](Control_scripts.md) (might be useful for the `cleanup` script), you will need to give appropriate permissions to the `octopod` _Service Account_:
125−
126− ```bash
127− cd /tmp/octopod/charts
128− helm install --name octopod-cert-control ./cert-control
129− ```
130−
131−4. If you are planning to use [_kubedog_][kubedog] to check the state of your deployments in your [_Control scripts_](Control_scripts.md) (might be useful for the `check` script), you will need to give appropriate permissions to the `octopod` _Service Account_:
28+#### DNS records
13229
133− ```bash
134− cd /tmp/octopod/charts
135− helm install --name octopod-kubedog-access ./kubedog-access
136− ```
30+Octopod will create a lot of on-demand environments and they must be reachable for your team. Usually it implies creating a lot of DNS records, pointing to Octopod managed environments. This process must be automated.
13731
138−## Web UI authentication secrets
32+We highly recommend you to use [ExternalDNS](https://github.com/kubernetes-sigs/external-dns) as a very versatile solution for DNS records automation.
33+In certain cases, however, it isn't possible to use ExternalDNS. In this case you can use a wildcard DNS record, pointing to the service endpoint of your ingress controller. We do not recommend using wildcard DNS records. Even though they are much easier to implement, they could lead to hard-to-trace errors and they are also implementation-dependent.
13934
140−[Authentication](Security_model.md#web-ui-authentication) between _Octopod Server_ and the _Web UI_ is done through _Basic Auth_. This implies that there needs to be a username and password associated with it.
35+#### Certificates
14136
142−You can generate the username and password, and push into your cluster using the following command (of course you will want to generate a secure pair):
143−
144−```bash
145−username="octopod"
146−password="password" # Please change it to a more secure password
147−kubectl create secret generic octopod-basic-auth -n octopod --from-literal=auth=$(htpasswd -bn $username $password)
148−```
149−
150−## _octo CLI_ authentication certificates
151−
152−### Creating SSL certificates
153−
154−[Authentication](Security_model.md#octo-cli-authentication) between _octo CLI_ and _Octopod Server_ is performed through self-signed SSL certificates.
155−
156−You can generate the certificates and push them into your cluster using the following commands:
157−
158−```bash
159−mkdir certs
160−(cd certs && \
161−openssl req -x509 -newkey rsa:4096 -keyout server_key.pem -out server_cert.pem -nodes -subj "/CN=localhost/O=Server" && \
162−openssl req -newkey rsa:4096 -keyout client_key.pem -out client_csr.pem -nodes -subj "/CN=Client" && \
163−openssl x509 -req -in client_csr.pem -CA server_cert.pem -CAkey server_key.pem -out client_cert.pem -set_serial 01 -days 3650)
164−kubectl create configmap octopod-certs -n octopod --from-file=./certs
165−```
166−
167−After executing these command you will find a new `certs` directory containing the certificates used for authentication between _octo CLI_ and _Octopod Server_. `client_key.pem` and `client_cert.pem` should then be [passed to _octo CLI_ through environment variables](Octo_user_guide.md#tls_cert_path-and-tls_key_path).
168−
169−### Enabling SSL passthrough
170−
171−Since we use custom self-signed SSL certificates for authentication, we will need the certificates used with requests to be passed to the server as-is without any modification. This is not support in default [_ingress-nginx_][ingress-nginx] configurations so you will most likely need to modify it manually.
172−
173−Enabling SSL passthrough in [_ingress-nginx_][ingress-nginx] can be done by adding the `--enable-ssl-passthrough` command-line argument to the [_ingress-nginx_][ingress-nginx] config in your cluster.
174−
175−To do this you can execute a command similar to this (you will need to lookup the names of the namespace and the deployment in your particular cluster):
176−
177−```bash
178−kubectl edit deploy -n ingress-nginx ingress-nginx-controller
179−```
180−
181−An editor with a YAML config should open up. You will need to modify to it have, among other things, this parameter:
182−
183−```yaml
184−spec:
185− ...
186− template:
187− ...
188− spec:
189− ...
190− containers:
191− ...
192− - args:
193− ...
194− - --enable-ssl-passthrough
195−```
37+If you want to request SSL certificates dynamically from Let's Encrypt you must be aware of their [limits](https://letsencrypt.org/docs/rate-limits/). Because of these limits we recommend you to use a wildcard certificate for all Octopod deployments. The wildcard certificate has its limitations, like being valid only for one subdomain. This implies a need for planning your deployments DNS naming.
19638
39+#### Resources
19740
198−## Setting up DNS
41+This is the most obvious one of the three, but you need to plan your cluster capacity based on your team needs. Setting [resource limits](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) for your workloads is one of the best practices of using Kubernetes, and you probably have done this already.
42+Also consider using autoscaling since it really helps to reduce costs in highly dynamic environments.
19943
200−You will need to set up DNS records to point subdomains of your domain to the IP address of your cluster. The DNS record should look something like this:
20144
202−```
203−*.octo.example.com A 1.2.3.4
204−octo.example.com A 1.2.3.4
205−```
206−
207−### Deploying _Octopod_ on localhost
208−
209−If you are deploying locally and don't have a separate domain you are trying set up, the lvh.me domain can be useful – it is set up to point to `localhost` and you can use it to work with subdomains. Even so, deploying a fully-functional version of _Octopod_ on `localhost` is non-trivial and will require modifying the deployment _Charts_ to disable HTTPS redirects. (This guide does not cover that.)
210−
211−## Installing _Octopod_ infrastructure
212−
213−### Installing the appropriate _Storage Class_
214−
215−Before installing the infrastructure you will first need to make sure you have a [_Storage Class_][kubernetes-storage-classes] named `default` installed in your cluster. You can check installed [_Storage Classes_][kubernetes-storage-classes] with the following command:
216−
217−```bash
218−kubectl get storageclass
219−```
45+### If you want to try it locally
22046
221−If you do not have it, you will need to install it. Installing the [_Storage Class_][kubernetes-storage-classes] in [_minikube_][minikube] can be done with the following command (you will need to modify it to suit your cluster hosting provider):
47+You can use [octopod_local_install.sh](../../octopod_local_install.sh) script to bootstrap kind cluster with octopod installed in it.
22248
223−```bash
224−cat <<EOF | kubectl apply -f-
225−---
226−apiVersion: storage.k8s.io/v1
227−kind: StorageClass
228−metadata:
229− name: default
230−provisioner: k8s.io/minikube-hostpath
231−reclaimPolicy: Delete
232−volumeBindingMode: Immediate
233−EOF
234−```
49+Before running the script make sure that you have following tools installed:
50+- [docker](https://docs.docker.com/engine/install/)
51+- [kind](https://kind.sigs.k8s.io/docs/user/quick-start/#installation)
52+- [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl)
53+- [helm 3](https://helm.sh/docs/intro/quickstart/#install-helm)
23554
236−### Installing the actual infrastructure
55+> **ℹ️ NOTE:** using Octopod involves deploying many instances of some service (many instances of Wordpress in our example). This means, it will use up a lot of resources. Many local installations of Docker and Kubenetes have resource limits set quite low by default. If you experience performance issues you should try increasing the resource limits. Here are some useful links:
56+> - Docker resource limits in Docker Desktop for Mac – [docs.docker.com/desktop/mac/#resources](https://docs.docker.com/desktop/mac/#resources)
57+> - Docker resource limits in Docker Desktop for Windows – [docs.docker.com/desktop/windows/#resources](https://docs.docker.com/desktop/windows/#resources)
58+> - General Docker resource constraint documentation – [docs.docker.com/config/containers/resource_constraints](https://docs.docker.com/config/containers/resource_constraints/)
23759
238−The only infrastructure _Octopod_ currently requires is _PostgreSQL_. You can install it in your cluster using the following command:
60+After you have all of the necessary tools installed, you can run the script:
23961
24062```bash
241−cd /tmp/octopod/charts
242−helm upgrade --install octopod-infra ./octopod-infra --namespace octopod\
243− --wait --timeout 600 --debug
63+/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/typeable/octopod/master/octopod_local_install.sh)"
24464```
24565
246−## Installing _Octopod Server_
247−
248−To install _Octopod Server_ in your cluster you will need to customize the variables in the following script and run it:
249−
250− ```bash
251−cd /tmp/octopod/charts
252−
253−#################################################
254−# Octopod Images Setup
255−#
256−# you probably don't need to change it
257−#################################################
258−
259−registry="typeable"
260−tag="1.0"
261−image="octopod"
262−octo_image="octo"
263−
264−
265−#################################################
266−# General Octopod Setup
267−#################################################
268−
269−# The name of your project – only used to display in the Web UI
270−project_name="MyProject"
271−
272−# The email used to register Let's Encrypt SSL certificates
273−acme_registration_email="certbot@example.com"
66+Script will expose octopod ui at `octopod.lvh.me`.
27467
68+`lvh.me` it's a special domain name which always resolves to `127.0.0.1`.
27569
276−#################################################
277−# Control Scripts Setup
278−#
279−# if you are just testing things out you can paste the values
280−# from the Helm Deployment Guide example
281−#################################################
70+## What next?
28271
283−# The name of the registry with control scripts
284−utils_registry="registry_name"
72+Now you may want to check how to [install Helm charts](Helm-based_deployment_guide.md) with Octopod.
28573
286−# The name of the image with control scripts
287−utils_image="utils"
74+<br />
28875
289−# The tag of the image to use
290−utils_image_tag="1.0"
76+<p align="center">
77+ <i>Star the project of you like it</i>
78+</p>
29179
292−
293−#################################################
294−# Web UI OAuth Authentication
295−#
296−# These parameters are passed to ingress-nginx to
297−# enable authentication for user accessing the
298−# Web UI.
299−#
300−# You can use OAuth2 Proxy to provide OAuth2 authentication.
301−#
302−# For more information see the Security Model doc.
303−#
304−# You can leave both these variables blank to disable
305−# authentication in your Web UI altogether.
306−#################################################
307−
308−# URL for the OAuth authentication service
309−auth_url="https://oauth.exmaple.com/oauth2/auth"
310−
311−# URL for the login page on the OAuth authentication service
312−auth_signin="https://oauth.exmaple.com/oauth2/start?rd=/redirect/$http_host$request_uri"
313−
314−
315−#################################################
316−# Domain Setup
317−#################################################
318−
319−# The domain from which the Web UI should be served
320−domain="octo.example.com"
321−
322−# The domain from which the user API should be served
323−# (used by the Web UI)
324−app_domain="api.octo.example.com"
325−
326−# The domain from which the WebSocket notification service should be served
327−# (used by the Web UI)
328−ws_domain="ws.octo.example.com"
329−
330−# The domain from which the power user API should be served
331−# (used by octo CLI)
332−power_app_domain="power.octo.example.com"
333−
334−# The domain under which deployment subdomains should be created
335−base_domain="octo.example.com"
336−
337−
338−#################################################
339−# Basic Auth Setup
340−#
341−# These parameters should match the ones used in the
342−# "Web UI authentication secrets" step
343−#################################################
344−
345−username="octopod"
346−password="password"
347−
348−
349−#################################################
350−# Other Setup
351−#################################################
352−
353−# NOTE: on macOS you will need to replace `sha256sum` with `shasum -a 256`
354−sha256_sum=$(sha256sum octopod/values.yaml octopod/templates/* | awk '{print $1}' | sha256sum | awk '{print $1}')
355−
356−base64_of_username_and_password=$(echo -n "$username:$password" | base64)
357−status_update_timeout=600
358−
359−
360−#################################################
361−# Actual installation in the cluster
362−#################################################
363−
364−helm upgrade --install octopod ./octopod \
365− --namespace octopod \
366− --set "global.deploy_checksum=$sha256_sum" \
367− --set "global.image_prefix=$registry" \
368− --set "global.image_tag=$tag" \
369− --set "global.image=$image" \
370− --set "global.octo_image=$octo_image" \
371− --set "global.utils_image_prefix=$utils_registry" \
372− --set "global.utils_image=$utils_image" \
373− --set "global.utils_image_tag=$utils_image_tag" \
374− --set "global.acme_registration_email=$acme_registration_email" \
375− --set "global.auth_url=$auth_url" \
376− --set "global.auth_signin=$auth_signin" \
377− --set "basic_auth_token=$base64_of_username_and_password" \
378− --set "project_name=$project_name" \
379− --set "domain=$domain" \
380− --set "app_domain=$app_domain" \
381− --set "ws_domain=$ws_domain" \
382− --set "power_app_domain=$power_app_domain" \
383− --set "base_domain=$base_domain" \
384− --set "status_update_timeout=$status_update_timeout" \
385− --wait --timeout 600 --debug
386− ```
387−
388−[kubectl]: https://kubernetes.io/docs/tasks/tools/install-kubectl/
389−[helm]: https://v2.helm.sh/docs/using_helm/#installing-helm
390−[ingress-nginx]: https://kubernetes.github.io/ingress-nginx
391−[cert-manager]: https://cert-manager.io/docs/
392−[kubernetes-service-account]: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account
393−[kubernetes-pvc]: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#expanding-persistent-volumes-claims
394−[kubernetes-storage-classes]: https://kubernetes.io/docs/concepts/storage/storage-classes
395−[minikube]: https://kubernetes.io/ru/docs/tasks/tools/install-minikube/
396−[tiller]: https://v2.helm.sh/docs/install/
397−[kubedog]: https://github.com/werf/kubedog
398−[lets-encrypt]: https://letsencrypt.org
399−[lets-encrypt-rate-limits]: https://letsencrypt.org/docs/rate-limits
80+<p align="center"><a href="https://typeable.io"><img src="../../img/typeable_logo.svg" width="177px"></img></a></p>
docs/en/Overview.md+12−22
@@ -1,22 +1,5 @@
11# Octopod overview
22
3−<details>
4− <summary>Table of contents</summary>
5−
6−- [Intro](#intro)
7−- [🎯 The aim of Octopod](#-the-aim-of-octopod)
8−- [🔬 Example](#-example)
9− - [💽 The server](#-the-server)
10− - [🎨 Changing button colors](#-changing-button-colors)
11− - [😖 Why have such a complicated staging deployment?](#-why-have-such-a-complicated-staging-deployment)
12−- [🛠 The way Octopod is set up](#-the-way-octopod-is-set-up)
13−- [🎛️ CLI](#️-cli)
14−- [🔒 Authentication in the UI](#-authentication-in-the-ui)
15−- [🤖 Automatic deployment / CD](#-automatic-deployment--cd)
16−- [📗 Glossary](#-glossary)
17−
18−</details>
19−
203**NOTE: it is not recommended to use Octopod for managing production environments**
214
225## Intro
@@ -25,7 +8,7 @@ _Octopod_ is a tool which implements the multi-staging deployment model (MSDM) o
258
269_Octopod_ exists to reduce the overhead in deploying and maintaining per-feature staging environments. This responsibility may otherwise fall to:
2710
28−1. **DevOps engineers** – this might seem natural since deploying and updating systems in new environments is typically the task of a DevOps engineer who has experience in system administration. However, developers and QA engineers would be blocked for additional periods while DevOps engineers deal with the additional load.
11+1. **DevOps engineers** – this might seem natural since deploying and updating systems in new environments is typically the task of a DevOps engineer who has experience in system administration. However, developers and QA engineers would be blocked for extended periods while DevOps engineers deal with the additional load.
29122. **Developers** – they might take on the responsibility for deploying and maintaining their feature stagings ― this would most likely waste a lot of time since developers might not have the required experience.
3013
3114The process of deploying and updating stagings is likely to be extremely similar across different developed features ― changing the behavior of a button and updating pricing calculations would probably be identical from the point of view of system administration ― a new version of the system needs to be deployed with the same default configuration (the staging configuration, as opposed to a production configuration).
@@ -38,7 +21,7 @@ Octopod aims to extract the mentioned similarity between deploying different sta
3821
3922### 💽 The server
4023
41−You are developing a server, which is accessed through [_nginx_](https://www.nginx.com), and the server needs access to a [*Postgres*](https://www.postgresql.org) database and a [*Redis*](https://redis.io) database
24+You are developing a server, which is accessed through _nginx_, and the server needs access to a [*Postgres*](https://www.postgresql.org) database and a [*Redis*](https://redis.io) database
4225
4326![](../diagrams/images/sample_architecture.png)
4427
@@ -50,13 +33,13 @@ Now imagine that two different developers each completed one of the tasks, and y
5033
5134A way to mitigate this situation is to test each feature separately, in its own staging deployment, and verify which change made the page background pink, and ideally, you would check each feature before merging them into the final product (merging it into the `master` branch, for example).
5235
53−To check each feature before merging would require every developer to build the new version of the server, and set up all required services: [_nginx_](https://www.nginx.com), [*Postgres*](https://www.postgresql.org), [*Redis*](https://redis.io). Developers would also have to manage access to the set up environments ― set up SSL certificates, set up subdomains, make sure databases are not exposed, and make sure the connection between every component is secure and authenticated.
36+To check each feature before merging would require every developer to build the new version of the server, and set up all required services: _nginx_, [*Postgres*](https://www.postgresql.org), [*Redis*](https://redis.io). Developers would also have to manage access to the set up environments ― set up SSL certificates, set up subdomains, make sure databases are not exposed, and make sure the connection between every component is secure and authenticated.
5437
5538This is **a lot** of overhead just to test the color of a button. Note that most of the described work would be identical across the vast majority of features ― changing the deployment architecture is a relatively rare task in most projects. Databases, load balancing, caching, and proxying would be set up in much the same way for the majority of feature-specific stagings. The server itself is probably also compiled in exactly the same way for most features.
5639
5740_Octopod_ aims to factor out the common parts of creating and deploying a staging.
5841
59−If developers were using _Octopod_ to deploy stagings, literally the only thing needed from them would be to specify the git commit hash in the _Web UI_ of _Octopod_. The common infrastructure (shown in **blue**) which is the same across different stagings would not require any additional setup. The only difference between the two button feature staging would be the actual server that required changing the color. And that server is most likely also built in a uniform way, meaning it can be done automatically.
42+If developers were using _Octopod_ to deploy stagings, literally the only thing needed from them would be to specify the git commit hash (if you use git commit hashes as tags for your docker images) in the _Web UI_ of _Octopod_. The common infrastructure (shown in **blue**) which is the same across different stagings would not require any additional setup. The only difference between the two button feature staging would be the actual server that required changing the color. And that server is most likely also built in a uniform way, meaning it can be done automatically.
6043
6144![](../diagrams/images/sample_deployment.png)
6245
@@ -95,4 +78,11 @@ Fot more information see the [integration guide](Integration.md).
9578- _Octopod Server_ ― the server responsible for managing deployments
9679- _deployment control scripts_ ― scripts used to interact with your specific environment setup
9780- _web UI_ ― the interface developers, project managers, QA engineers, etc. use to manage stagings.
98−- <a id="overrides"></a>_overrides_ ― a set of environment variable key-value pairs, which have precedence over the default pairs set up by DevOps engineer. These environment variables are passed to your system during deployment.
81+
82+<br />
83+
84+<p align="center">
85+ <i>Star the project of you like it</i>
86+</p>
87+
88+<p align="center"><a href="https://typeable.io"><img src="../../img/typeable_logo.svg" width="177px"></img></a></p>
docs/en/PM_case_study.md+9−1
@@ -56,7 +56,7 @@ guarantee that the feature won’t unexpectedly break someone else’s code.
5656If a critical part of the application, like authentication, gets broken,
5757this may block the testing process completely until the problem is
5858resolved. And to top it off, when this happens, it might not be
59−immediately clear who’s change is to blame. Thus, everyone who did
59+immediately clear whose change is to blame. Thus, everyone who did
6060recent merges begin looking into their code trying to see whether it was
6161their check-in that broke the server. Of course, it takes time and
6262blocks the development process as well until the culprit merge is found
@@ -120,3 +120,11 @@ that, once installed and set up, supports your multi-tier development
120120workflow at a level that does not require deep technical knowledge. Octopod
121121simplifies the procedure of creating new servers and allows the
122122implementation of common CD solutions in just a few clicks.
123+
124+<br />
125+
126+<p align="center">
127+ <i>Star the project of you like it</i>
128+</p>
129+
130+<p align="center"><a href="https://typeable.io"><img src="../../img/typeable_logo.svg" width="177px"></img></a></p>
docs/en/README.md+1−1
@@ -7,7 +7,7 @@
77
88## 🛠️ Technical documentation
99- [🏗 Technical architecture](Technical_architecture.md)
10−- [⚙️ Control script guide](Control_scripts.md)
10+- [⚙️ Control scripts guide](Control_scripts.md)
1111- [🔧🐙 Octopod deployment guide](Octopod_deployment_guide.md)
1212- [🔧🚀 Helm-based Octopod project setup](Helm-based_deployment_guide.md)
1313- [🐙🎛 octo CLI user guide](Octo_user_guide.md)
docs/en/Security_model.md+16−78
@@ -1,18 +1,5 @@
11# Security model
22
3−<details>
4− <summary>Table of contents</summary>
5−
6−- [Octopod roles](#octopod-roles)
7−- [Kubernetes role-based access control](#kubernetes-role-based-access-control)
8− - [Privileges to delete certificates](#privileges-to-delete-certificates)
9− - [Privileges to delete _Persistent Volumes Claims_](#privileges-to-delete-persistent-volumes-claims)
10−- [Web UI authentication](#web-ui-authentication)
11−- [Web UI OAuth](#web-ui-oauth)
12−- [octo CLI authentication](#octo-cli-authentication)
13−
14−</details>
15−
163## Octopod roles
174
185There are two user roles in _Octopod_:
@@ -28,87 +15,38 @@ _Web UI_ users have the _user_ role.
2815
2916_octo CLI_ users have the _admin_ role.
3017
31−There is currently no way to give someone access to _octo CLI_ without giving them the _admin_ role since authentication is done through SSL certificates instead of through OAuth.
18+There is currently no way to give someone access to _octo CLI_ without giving them the _admin_ role since authentication is not done through OAuth.
3219
3320## Kubernetes role-based access control
3421
3522_Octopod Server_ is deployed in the `octopod` _Kubernetes_ namespace. Deployments are deployed in the `deployments` namespace.
3623_Octopod Server_ uses the `octopod` [_Service Account_][kubernetes-service-account].
3724
38−Freeing resources might require _Octopod Server_ / _control scripts_ to have privileges to delete certificates and [_Persistent Volumes Claims_][kubernetes-pvc]. (It depends on the specifics of the _Kubernetes_ setup and _control scripts_)
39−
40−Access can be configured through [_RBAC_][kubernetes-rbac]:
41−
42−### Privileges to delete certificates
43−
44−```yaml
45−---
46−apiVersion: rbac.authorization.k8s.io/v1
47−kind: ClusterRole
48−metadata:
49− name: cert-control-clusterrole
50−rules:
51− - apiGroups: ["cert-manager.io"]
52− resources: ["certificates"]
53− verbs: ["list", "delete", "deletecollection"]
54−---
55−apiVersion: rbac.authorization.k8s.io/v1
56−kind: RoleBinding
57−metadata:
58− name: octopod-cert-control-rolebinding
59− namespace: deployments
60−roleRef:
61− kind: ClusterRole
62− apiGroup: rbac.authorization.k8s.io
63− name: cert-control-clusterrole
64−subjects:
65− - kind: ServiceAccount
66− name: octopod
67− namespace: octopod
68−```
69−
70−### Privileges to delete _Persistent Volumes Claims_
71−
72−```yaml
73−---
74−apiVersion: rbac.authorization.k8s.io/v1
75−kind: ClusterRole
76−metadata:
77− name: pvc-control-clusterrole
78−rules:
79− - apiGroups: [""]
80− resources: ["persistentvolumeclaims"]
81− verbs: ["list", "delete", "deletecollection"]
82−---
83−apiVersion: rbac.authorization.k8s.io/v1
84−kind: RoleBinding
85−metadata:
86− name: octopod-pvc-control-rolebinding
87− namespace: deployments
88−roleRef:
89− kind: ClusterRole
90− apiGroup: rbac.authorization.k8s.io
91− name: pvc-control-clusterrole
92−subjects:
93− - kind: ServiceAccount
94− name: octopod
95− namespace: octopod
96−```
25+Octopod needs sufficient permissions to run Helm inside Kubernetes and create all resources described in the Helm chart it is installing. Thus permissions are quite extensive.
26+
27+[RBAC][kubernetes-rbac] rules to describe permissions needed are added automatically by [the Octopod Helm Chart](../../charts/octopod/templates/rbac.yaml).
9728
9829## Web UI authentication
9930
100−Authentication between the _Web UI_ and _Octopod Server_ is done through _Basic Auth_. The _Bearer token_ is read by the _Web UI_ after the page is loaded as part of [the config](../../charts/octopod/templates/octopod-nginx-configmap.yaml#L15-L20). By default, everything, including the config, can be accessed without any authentication. For ways of mitigating this please see the next section.
31+Authentication between the _Web UI_ and _Octopod Server_ is done through _Basic Auth_. The _Bearer token_ is read by the _Web UI_ after the page is loaded as part of [the config](../../charts/octopod/templates/nginx-configmap.yaml#L23-L33). By default, everything, including the config, can be accessed without any authentication. For ways of mitigating this please see the next section.
10132
10233## Web UI OAuth
10334
104−The [_Web UI_](Technical_architecture.md#-web-ui) on its own does not have any authentication whatsoever, meaning that anyone can open it and manage your deployments. Luckily, _Kubernetes_ [can be configured](../../charts/octopod/templates/octopod-ingress.yaml#L15-L21) to authenticate users before they get access to the _Web UI_. It can be set up to authenticate users through [_Ingress_](https://kubernetes.io/docs/concepts/services-networking/ingress/) which [supports external authentication services][kubernetes-ingress-nginx-external-auth]. You can set up [_OAuth2 Proxy_][oauth2-proxy] in your cluster to support numerous OAuth services. For example, if you use GitHub, you can set up [_OAuth2 Proxy_][oauth2-proxy] to use GitHub to automatically grant users access to Octopod when you add them to your organization in GitHub.
35+The [_Web UI_](Technical_architecture.md#-web-ui) on its own does not have any authentication whatsoever, meaning that anyone can open it and manage your deployments. Luckily, _Kubernetes_ [can be configured](../../charts/octopod/README.md#configuration-and-installation-details) to authenticate users before they get access to the _Web UI_. It can be set up to authenticate users through [_Ingress_](https://kubernetes.io/docs/concepts/services-networking/ingress/) which [supports external authentication services][kubernetes-ingress-nginx-external-auth]. You can set up [_OAuth2 Proxy_][oauth2-proxy] in your cluster to support numerous OAuth services. For example, if you use GitHub, you can set up [_OAuth2 Proxy_][oauth2-proxy] to use GitHub to automatically grant users access to Octopod when you add them to your organization in GitHub.
10536
10637## octo CLI authentication
10738
108−Authentication between _octo CLI_ and _Octopod Server_ is done through an SSL certificate that is generated [when deploying _Octopod_](../en/Octopod_deployment_guide.md#creating-ssl-certificates).
39+Authentication between _octo CLI_ and _Octopod Server_ is done through special token which is generated automatically or specified by user in `octopod.cliAuthSecret` parameter, as described [here](../../charts/octopod/README.md#parameters).
10940
11041[kubernetes-service-account]: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account
111−[kubernetes-rbac]: https://kubernetes.io/docs/reference/access-authn-authz/rbac
112−[kubernetes-pvc]: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#expanding-persistent-volumes-claims
11342[kubernetes-ingress-nginx-external-auth]: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#external-authentication
43+[kubernetes-rbac]: https://kubernetes.io/docs/reference/access-authn-authz/rbac
11444[oauth2-proxy]: https://oauth2-proxy.github.io/oauth2-proxy
45+
46+<br />
47+
48+<p align="center">
49+ <i>Star the project of you like it</i>
50+</p>
51+
52+<p align="center"><a href="https://typeable.io"><img src="../../img/typeable_logo.svg" width="177px"></img></a></p>
docs/en/Tech_case_study.md+9−16
@@ -1,20 +1,5 @@
11# Octopod technical case study
22
3−<details>
4− <summary>Table of contents</summary>
5−
6−- [Single staging model](#single-staging-model)
7−- [The multi-staging model](#the-multi-staging-model)
8−- [Implications](#implications)
9− - [Isolation – separate configurations](#isolation--separate-configurations)
10− - [Isolation – more information](#isolation--more-information)
11− - [Isolation – independent state](#isolation--independent-state)
12− - [Isolation – freedom to experiment](#isolation--freedom-to-experiment)
13− - [Infrastructure reuse](#infrastructure-reuse)
14− - [Continuous staging deployment](#continuous-staging-deployment)
15−
16−</details>
17−
183In this case study, we consider developing a system that is mostly comprised of a server.
194
205## Single staging model
@@ -37,7 +22,7 @@ It is sometimes the case that certain features need a "special" environment to b
3722
3823"Current" is used here to denote features that have been completed after the last time QA engineers had the opportunity to test the staging of the given project. It is assumed that the completed features are merged into something analogous to a `master` branch in git.
3924
40−A way to mitigate the issue might be to have fine-grained control over what features are allowed to be merged into the `master` branch so that when we deploy it, we will have only the one feature which needs the "special" environment, in a sense, batching features based on the environment they require. The main problem with this is that the payment processor is in all likelihood a tiny sliver, a single dimension of the whole space of possible environment setups. Trying to capture and institutionalize the whole breadth of a production environment in your development workflow seems like a futile endeavor.
25+A way to mitigate the issue might be to have fine-grained control over what features are allowed to be merged into the `master` branch so that when we deploy it, we will have only the feature which needs the "special" environment, in a sense, batching features based on the environment they require. The main problem with this is that the payment processor is in all likelihood a tiny sliver, a single dimension of the whole space of possible environment setups. Trying to capture and institutionalize the whole breadth of a production environment in your development workflow seems like a futile endeavor.
4126
4227Having per-feature stagings allow you to have completely separate and independent configurations for every single feature you develop and test at no additional cost.
4328
@@ -72,3 +57,11 @@ When setting up Octopod you will need to implement the exact steps required to s
7257It is easy to set up continuous deployment procedures with Octopod. (Continuous deployment here refers to the process of automatically deploying branches of your repository when they are updated.) This allows you to optimize your development workflow even further.
7358
7459A not-so-obvious usage might be to set up a staging to be automatically updated with the `master` branch of your project repository. This has the advantage that anyone can at any time easily test the behavior of the `master` branch.
60+
61+<br />
62+
63+<p align="center">
64+ <i>Star the project of you like it</i>
65+</p>
66+
67+<p align="center"><a href="https://typeable.io"><img src="../../img/typeable_logo.svg" width="177px"></img></a></p>
docs/en/Technical_architecture.md+18−169
@@ -1,29 +1,5 @@
11# Technical architecture
22
3−<details>
4− <summary>Table of contents</summary>
5−
6−- [⚒️ Used tools](#️-used-tools)
7−- [📐 App architecture](#-app-architecture)
8− - [🖥 Web UI](#-web-ui)
9− - [🐙 Octopod Server](#-octopod-server)
10− - [🐘 PostgreSQL](#-postgresql)
11− - [🎛 octo CLI](#-octo-cli)
12− - [📑 Control scripts](#-control-scripts)
13− - [🚮⏲ Clean Archive CronJob](#-clean-archive-cronjob)
14− - [Kube API Server](#kube-api-server)
15−- [📦 Octopod Distribution model](#-octopod-distribution-model)
16−- [Process view](#process-view)
17− - [✨ Create](#-create)
18− - [🔧 Update](#-update)
19− - [🗃 Archive](#-archive)
20− - [🚮 Cleanup](#-cleanup)
21− - [🔁 Restore](#-restore)
22−- [👨‍💻👩‍💻 How we use it](#-how-we-use-it)
23−- [🗂️ Deployment state transitions](#️-deployment-state-transitions)
24−
25−</details>
26−
273## ⚒️ Used tools
284
295The main goal of _Octopod_ is to simplify deployment in [_Kubernetes_][kube].
@@ -61,7 +37,7 @@ The server receives commands from the [_octo CLI_](#-octo-cli) and the [_Web UI_
6137
6238### 🎛 octo CLI
6339
64−_octo CLI_ – a command-line interface used to manage deployments. It sends HTTP/1.1 requests to [_Octopod Server_](#-octopod-server). The requests are [authenticated through SSL certificates](Security_model.md#octo-cli-authentication).
40+_octo CLI_ – a command-line interface used to manage deployments. It sends HTTP/1.1 requests to [_Octopod Server_](#-octopod-server). The requests are [authenticated through the `Authorization` header](Security_model.md#octo-cli-authentication).
6541
6642It can perform all actions available in the [_Web UI_](#-web-ui), but also has access to view deployment logs.
6743
@@ -75,13 +51,8 @@ This is necessary to make _Octopod_ itself independent from any particular deplo
7551
7652When the [_Octopod Server_](#-octopod-server) _Pod_ starts, the contents of the *control scripts* container are copied into the _Octopod Server_ container file system. This means that the executables need to be either statically linked or interpreted through _Bash_ since it needs to be executed in the _Octopod Server_ container environment.
7753
78−These [scripts need to be implemented](Control_scripts.md) to deploy _Octopod_.
79−
80−### 🚮⏲ Clean Archive CronJob
81−
82−_Clean Archive CronJob_ – a CronJob which is run every hour. It deletes archived deployments older than 14 days. It is done by calling [_octo CLI_](#-octo-cli).
54+These [scripts need to be implemented](Control_scripts.md) to deploy _Octopod_ unless the set of generic scripts is used.
8355
84−It is necessary because "deleting" (archiving) deployments should only free the occupied computational resources, _Persistent Volumes_ should not be freed when deleting a deployment. This gives us a window of time in which a deployment can be recovered in the state it was in before being archived.
8556
8657### Kube API Server
8758
@@ -97,156 +68,29 @@ A _Docker Image_ with [_control scripts_](#-control-scripts) should be provided
9768
9869## Process view
9970
100−Here we provide sequence diagrams for every basic operation that can be performed in _Octopod_. These operations call [_control scripts_](#-control-scripts). On the diagrams, they are labeled as _ControlScripts_.
101−
102−### ✨ Create
103−
104−_Create_ – creates a new deployment. The main inputs include the name of the deployment, the _Docker Image tag_ and optional overrides. A more detailed description can be found in the [control scripts documentation](Control_scripts.md#-create).
105−
106−The arguments are forwarded to the [_create_](Control_scripts.md#-create) script which in turn creates the deployment in the _Kubernetes cluster_. It might call something like:
107−
108−```bash
109−helm upgrade --install --namespace "$namespace" "$name" "$deployment_chart" \
110− --set "global.project-name=$project_name" \
111− --set "global.base-domain=$base-domain" \
112− --set "app.tag=$tag" \
113− --set "app.env.foo=$app_env_override_1" \
114− --set "app.bar=$deployment_override_1" \
115− --wait \
116− --timeout 300
117−```
118−
119−<details>
120− <summary>Create via CLI sequence diagram</summary>
121−
122−![Create](../diagrams/images/technical-architecture-create-via-cli.png)
123−
124−</details>
125−
126−<details>
127− <summary>Create via UI sequence diagram</summary>
128−
129−![Create](../diagrams/images/technical-architecture-create-via-ui.png)
71+Here we provide sequence diagrams for every basic operation that can be performed in _Octopod_. These operations call [_control scripts_](#-control-scripts). On the diagrams, they are labeled as _Control Scripts_.
13072
131−</details>
73+### ✨ Deployment creation
13274
133−### 🔧 Update
75+![Create](../diagrams/images/technical-architecture-create.png)
13476
135−_Update_ – updates an existing deployment. The main inputs include the name of the deployment, the _Docker Image tag_ and optional overrides. A more detailed description can be found in the [control scripts documentation](Control_scripts.md#-update).
13677
137−[_Overrides_](Overview.md#overrides) are read from the database and merged with the new changes. All arguments are forwarded to the [_update_](Control_scripts.md#-update) script which in turn updates the specified deployment with the new parameters in the _Kubernetes cluster_. It might call something like:
78+### 🔧 Deployment update
13879
139−```bash
140−helm upgrade --install --namespace "$namespace" "$name" "$deployment_chart" \
141− --set "global.project-name=$project_name" \
142− --set "global.base-domain=$base-domain" \
143− --set "app.tag=$tag" \
144− --set "app.env.foo=$app_env_override_1" \
145− --set "app.bar=$deployment_override_1" \
146− --wait \
147− --timeout 300
148−```
149−
150−
151−<details>
152− <summary>Update via CLI sequence diagram</summary>
153−
154−![Update](../diagrams/images/technical-architecture-update-via-cli.png)
155−
156−</details>
157−
158−<details>
159− <summary>Update via UI sequence diagram</summary>
160−
161−![Update](../diagrams/images/technical-architecture-update-via-ui.png)
162−
163−</details>
80+![Update](../diagrams/images/technical-architecture-update.png)
16481
16582### 🗃 Archive
16683
167−_Delete_ – archives a deployment. It should only free the computational resources (_Pods_). _Persistent Volumes_ should not be deleted ― they are cleared in the [_cleanup_](#-cleanup) process. This operation can be undone with the [_restore_](#-restore) command.
168−
169−The main argument is the name that identifies the deployment. A more detailed description can be found in the [control scripts documentation](Control_scripts.md#-archive).
170−
171−The arguments are forwarded to the [_delete_](Control_scripts.md#-archive) script which in turn frees the computational resources. It might call something like:
172−
173−```bash
174−helm delete "$name" --purge
175−```
176−
177−<details>
178− <summary>Archive via CLI sequence diagram</summary>
179−
180−![Archive](../diagrams/images/technical-architecture-archive-via-cli.png)
181−
182−</details>
183−
184−<details>
185− <summary>Archive via UI sequence diagram</summary>
186−
187−![Archive](../diagrams/images/technical-architecture-archive-via-ui.png)
188−
189−</details>
84+![Archive](../diagrams/images/technical-architecture-archive.png)
19085
19186### 🚮 Cleanup
19287
193−_Cleanup_ – releases **all** resources captured by the deployment.
194−
195−The main argument is the name that identifies the deployment. A more detailed description can be found in the [control scripts documentation](Control_scripts.md#-cleanup). It can only be called after [_archive_](#-archive) has been executed.
196−
197−The arguments are forwarded to the [_cleanup_](Control_scripts.md#-cleanup) script which in turn frees all resources captured by the given deployment. It might call something like:
198−
199−```bash
200−kubectl delete pvc -n "$namespace" "$name-postgres-pvc"
201−kubectl delete certificate -n "$namespace" "$name-postgres-cert"
202−```
203−
204−<details>
205− <summary>Cleanup via CLI sequence diagram</summary>
206−
207−![Cleanup](../diagrams/images/technical-architecture-cleanup-via-cli.png)
208−
209−</details>
210−
211−<details>
212− <summary>Cleanup via UI sequence diagram</summary>
213−
214−![Cleanup](../diagrams/images/technical-architecture-cleanup-via-ui.png)
21588
216−</details>
89+![Cleanup](../diagrams/images/technical-architecture-cleanup.png)
21790
21891### 🔁 Restore
21992
220−_restore_ – restores an archived deployment in the state it was last in. Calls the same _script_ that is called in [_create_](#-create).
221−
222−The main argument is the name that identifies the deployment. A more detailed description can be found in the [control scripts documentation](Control_scripts.md#-create). It can only be called after [_archive_](#-archive) has been executed.
223−
224−All necessary setup information is read from the database: [_overrides_](Overview.md#overrides) and the _Docker Image tag_. The arguments are forwarded to the [_create_](Control_scripts.md#-create) script which in turn recreates the deployment. It might call something like:
225−
226−```bash
227−helm upgrade --install --namespace "$namespace" "$name" "$deployment_chart" \
228− --set "global.project-name=$project_name" \
229− --set "global.base-domain=$base-domain" \
230− --set "app.tag=$tag" \
231− --set "app.env.foo=$app_env_override_1" \
232− --set "app.bar=$deployment_override_1" \
233− --wait \
234− --timeout 300
235−```
236−
237−<details>
238− <summary>Restore via CLI sequence diagram</summary>
239−
240−![Restore](../diagrams/images/technical-architecture-restore-via-cli.png)
241−
242−</details>
243−
244−<details>
245− <summary>Restore via UI sequence diagram</summary>
246−
247−![Restore](../diagrams/images/technical-architecture-restore-via-ui.png)
248−
249−</details>
93+![Restore](../diagrams/images/technical-architecture-restore.png)
25094
25195## 👨‍💻👩‍💻 How we use it
25296
@@ -284,9 +128,14 @@ _Running_, _Failure_, _Archived_ states are "permanent", meaning the deployment
284128
285129![Deployment Statuses](../diagrams/images/technical-architecture-deployment-states-fsm.png)
286130
287−<!-- [kubectl]: https://kubernetes.io/docs/reference/kubectl/ -->
288−<!-- [helm]: https://helm.sh -->
289−<!-- [kubedog]: https://github.com/werf/kubedog -->
290131[kube]: https://kubernetes.io
291132[chart]: https://helm.sh/docs/topics/charts/
292133[ingress]: https://kubernetes.io/docs/concepts/services-networking/ingress/
134+
135+<br />
136+
137+<p align="center">
138+ <i>Star the project of you like it</i>
139+</p>
140+
141+<p align="center"><a href="https://typeable.io"><img src="../../img/typeable_logo.svg" width="177px"></img></a></p>
docs/images/dev2.png

Binary file not shown.

docs/images/first.pngdeleted

Binary file not shown.

docs/images/hello-octopod-1.pngdeleted

Binary file not shown.

docs/images/hello-octopod-2.pngdeleted

Binary file not shown.

docs/images/hello-octopod-3.pngdeleted

Binary file not shown.

docs/images/octopod_app_keys_list.pngnew file

Binary file not shown.

docs/images/octopod_archive.pngnew file

Binary file not shown.

docs/images/octopod_blank.pngnew file

Binary file not shown.

docs/images/octopod_deployment_blank.pngnew file

Binary file not shown.

docs/images/octopod_deployment_filled.pngnew file

Binary file not shown.

docs/images/octopod_filled.pngnew file

Binary file not shown.

docs/images/octopod_in_octopod_deployment.pngnew file

Binary file not shown.

docs/images/second.pngdeleted

Binary file not shown.

docs/images/wordpress_blank.pngnew file

Binary file not shown.

docs/ru/Control_scripts.mddeleted−209
@@ -1,209 +0,0 @@
1−# Control scripts
2−
3−<details>
4− <summary>Table of contents</summary>
5−
6−- [create](#create)
7−- [update](#update)
8−- [archive](#archive)
9−- [check](#check)
10−- [cleanup](#cleanup)
11−- [archive_check](#archive_check)
12−- [tag_check](#tag_check)
13−- [init](#init)
14−- [info](#info)
15−
16−</details>
17−
18−## create
19−
20−Реализация создания нового развертывания.
21−
22−Получает на вход следующие аргументы:
23−* `--project-name` – название проекта
24−* `--base-domain` – базовый домен
25−* `--namespace` – namespace
26−* `--name` – имя развертывания
27−* `--tag` – тег развертывания
28−* `--app-env-override` – override уровня приложения (формат значения `FOO=BAR`, может быть передано 0 или более раз)
29−* `--deployment-override` – override уровня развертывания (формат значения `FOO=BAR`, может быть передано 0 или более раз)
30−
31−Успешность операции определяется по exit code (`0` – успех).
32−
33−Например `create` с полученными аргументами может выполнять:
34−
35−```bash
36−helm upgrade --install --namespace "$namespace" "$name" "$deployment_chart" \
37− --set "global.project-name=$project_name" \
38− --set "global.base-domain=$base-domain" \
39− --set "app.tag=$tag" \
40− --set "app.env.foo=$app_env_override_1" \
41− --set "app.bar=$deployment_override_1" \
42− --wait \
43− --timeout 300
44−```
45−
46−## update
47−
48−Реализация обновления развертывания.
49−
50−Получает на вход следующие аргументы:
51−* `--project-name` – название проекта
52−* `--base-domain` – базовый домен
53−* `--namespace` – namespace
54−* `--name` – имя развертывания
55−* `--tag` – тег развертывания
56−* `--app-env-override` – override уровня приложения (формат значения `FOO=BAR`, может быть передано 0 или более раз)
57−* `--deployment-override` – override уровня развертывания (формат значения `FOO=BAR`, может быть передано 0 или более раз)
58−
59−Успешность операции определяется по exit code (`0` – успех).
60−
61−Например `update` с полученными аргументами может выполнять:
62−
63−```bash
64−helm upgrade --install --namespace "$namespace" "$name" "$deployment_chart" \
65− --set "global.project-name=$project_name" \
66− --set "global.base-domain=$base-domain" \
67− --set "app.tag=$tag" \
68− --set "app.env.foo=$app_env_override_1" \
69− --set "app.bar=$deployment_override_1" \
70− --wait \
71− --timeout 300
72−```
73−
74−## archive
75−
76−Реализация удаления развертывания.
77−
78−Получает на вход следующие аргументы:
79−* `--project-name` – название проекта
80−* `--base-domain` – базовый домен
81−* `--namespace` – namespace
82−* `--name` – имя развертывания
83−
84−Успешность операции определяется по exit code (`0` – успех).
85−
86−Например `archive` с полученными аргументами может выполнять:
87−
88−```bash
89−helm delete "$name" --purge
90−```
91−
92−## check
93−
94−Реализация проверки состояния развертывания.
95−
96−Получает на вход следующие аргументы:
97−* `--project-name` – название проекта
98−* `--base-domain` – базовый домен
99−* `--namespace` – namespace
100−* `--name` – имя развертывания
101−
102−Успешность операции определяется по exit code (`0` – успех).
103−
104−Например `check` с полученными аргументами может выполнять:
105−
106−```bash
107−echo "{\"Deployments\": [{\"ResourceName\": \"app-${name}\", \"Namespace\": \"${namespace}\"}], \"StatefulSets\": [{\"ResourceName\": \"db-${name}\", \"Namespace\": \"${namespace}\"}]}" | \
108− kubedog multitrack -t 3
109−```
110−
111−В примере выше используется [_Kubedog_][kubedog].
112−Предполагается, что пользователь сам установит [_Kubedog_][kubedog]: сохранит его в `/` контейнера с _Control scripts_ или установит его в `$HOME` из [init](#init).
113−
114−## cleanup
115−
116−Реализация очистки ресурсов развертывания.
117−
118−Получает на вход следующие аргументы:
119−* `--project-name` – название проекта
120−* `--base-domain` – базовый домен
121−* `--namespace` – namespace
122−* `--name` – имя развертывания
123−
124−Успешность операции определяется по exit code (`0` – успех).
125−
126−Например `cleanup` с полученными аргументами может выполнять:
127−
128−```bash
129−kubectl delete pvc -n $namespace -l "app=$name"
130−```
131−
132−## archive_check
133−
134−Реализация проверки успешности удаления развертывания.
135−
136−Получает на вход следующие аргументы:
137−* `--project-name` – название проекта
138−* `--base-domain` – базовый домен
139−* `--namespace` – namespace
140−* `--name` – имя развертывания
141−
142−Успешность операции определяется по exit code (`0` – успех).
143−
144−Например `archive_check` с полученными аргументами может выполнять:
145−
146−```bash
147−helm status $name
148−```
149−
150−## tag_check
151−
152−Реализация проверки существования тега развертывания.
153−
154−Получает на вход следующие аргументы:
155−* `--project-name` – название проекта
156−* `--base-domain` – базовый домен
157−* `--namespace` – namespace
158−* `--name` – имя развертывания
159−* `--tag` – тег развертывания
160−
161−Успешность операции определяется по exit code (`0` – успех).
162−
163−## init
164−
165−Реализация инициализации рабочего окружения для будущих запусков *Control Scripts*.
166−
167−В этом скрипте предлагается настроить доступ к системам контроля версий, облачным провайдерам и т.д.
168−Для этого можно сохранить настройки в файлы в $HOME.
169−
170−Этот скрипт однократно запускается во время создания пода `Octopod Server`.
171−
172−Успешность операции определяется по exit code (`0` – успех).
173−
174−Например `init` может выполнять:
175−
176−```bash
177−mkdir $HOME/.ssh
178−echo -e "Host github.com\nHostname github.com\nPort 22\nUser git\nIdentityFile $HOME/.ssh/deploy.key" > $HOME/.ssh/config
179−echo "MY_DEPLOY_KEY" > $HOME/.ssh/deploy.key"
180−```
181−
182−## info
183−
184−Реализация получения метаданных о deployment. Содержимое _stdout_ будет использованно в качестве дополнительной информации о deployment в _CLI/UI_.
185−Ожидаемый формат _stdout_ ― _CSV_ `ключ,значение`:
186−
187−```
188−app,https://foo.example.com
189−api,https://api.foo.example.com
190−```
191−
192−Ожидается, что `ключ` не может содержать символ `,`, ограничений на `значение` нет. Пробельные символы остаются без изменений.
193−
194−Получает на вход следующие аргументы:
195−* `--project-name` – название проекта
196−* `--base-domain` – базовый домен
197−* `--namespace` – namespace
198−* `--name` – имя стейджинга
199−
200−Успешность операции определяется по exit code (`0` – успех).
201−
202−Например `info` с полученными аргументами может выполнять:
203−
204−```bash
205−echo "app,https://${name}.example.com"
206−echo "api,https://api.${name}.example.com"
207−```
208−
209−[kubedog]: https://github.com/werf/kubedog
docs/ru/Helm-based_deployment_guide.mddeleted−165
@@ -1,165 +0,0 @@
1−# Helm-based deployment guide
2−
3−## Подгодовка
4−
5−Предполагается, что у вас в системе уже установлен Docker,
6−а также Вы установили _Octopod_. Если Вы _Octopod_ не установили, то пожалуйста воспользуйтесь [инструкцией по установке _Octopod_](Octopod_deployment_with_K8S.md).
7−При установке _Octopod_ потребуется указать название образа с [control scripts](Control_scripts.md):
8−```bash
9−--set "global.utils_image_prefix=typeable" \
10−--set "global.utils_image=octopod-helm-example" \
11−--set "global.utils_image_tag=1.0" \
12−```
13−
14−В итоге должно получиться что-то вроде:
15−
16−```bash
17−helm upgrade octopod ./octopod \
18− --install \
19− --namespace octopod \
20− --set "global.deploy_checksum=$sha256_sum" \
21− --set "global.image_prefix=typeable" \
22− --set "global.image_tag=1.0" \
23− --set "global.utils_image_prefix=typeable" \
24− --set "global.utils_image=octopod-helm-example" \
25− --set "global.utils_image_tag=1.0" \
26− --set "global.acme_registration_email=certbot@example.com" \
27− --set "global.auth_url=https://oauth.exmaple.com/oauth2/auth" \
28− --set "global.auth_signin=https://oauth.exmaple.com/oauth2/start?rd=/redirect/$http_host$request_uri" \
29− --set "project_name=MyProject" \
30− --set "domain=octopod.example.com" \
31− --set "app_domain=octopod-app.example.com" \
32− --set "power_app_domain=octopod-power-app.example.com" \
33− --set "ws_domain=octopod-ws.example.com" \
34− --set "base_domain=example.com" \
35− --set "status_update_timeout=600" \
36− --wait \
37− --timeout 600 \
38− --debug
39−```
40−
41−Для того чтобы развернуть приложение с помощью _Octopod_ потребуется само приложение и набор [control scripts](Control_scripts.md).
42−Разворачивать можно через _Web UI_ или _octo CLI_. В этом примере мы будем использовать только _octo CLI_.
43−Также потребуется Docker для запуска контейнера с _octo CLI_.
44−Перед использованием _octo CLI_ необходимо настроить доступ к _Octopod_, пожалуйста воспользуйтесь [руководством пользователя _octo CLI_](Octo_user_guide.md).
45−
46−В качестве примера мы будем использовать простое веб приложение, которое обслуживает единственный endpoint `/`.
47−По запросу на `/` будет возвращаться список переменных окружения, имена которых начинаются с `APP_ENV`, в HTML разметке.
48−С исходным кодом приложения можно ознакомиться, перейдя по ссылке [web-app](../../examples/web-app).
49−Это приложение было упаковано в докер образ и отправлено в регистри:
50−```bash
51−docker build -f docker/Dockerfile -t typeable/octopod-web-app-example:v1 .
52−docker push typeable/octopod-web-app-example:v1
53−```
54−
55−Также мы будем производить обновление приложения до более новой версии.
56−В новой версии изменена HTML разметка: каждая переменная окружения выводится не в отдельном `div`, а в виде элемента списка `li`.
57−С исходным кодом обновленного приложения можно ознакомиться, перейдя по ссылке [web-app-v2](../../examples/web-app-v2).
58−Это приложение было упаковано в докер образ и отправлено в регистри:
59−```bash
60−docker build -f docker/Dockerfile -t typeable/octopod-web-app-example:v2 .
61−docker push typeable/octopod-web-app-example:v2
62−```
63−
64−Для работы веб приложению нужен 1 TLS сертификат для каждого развертывания. [_Cert Manager_][cert-manager] создает сертификаты через [_Let’s Encrypt_][lets-encrypt].
65−У [_Let’s Encrypt_][lets-encrypt] есть лимиты на создание сертификатов [_Let’s Encrypt Rate Limits_][lets-encrypt-rate-limits].
66−При достижении лимита `too many registrations for this IP` может помочь перемещение Pod [_Cert Manager_][cert-manager] на другую ноду.
67−
68−Набор [control scripts](Control_scripts.md) будет использовать helm v2.x, kubectl, kubedog для управления и проверки статуса деплойментов.
69−С исходным кодом [control scripts](Control_scripts.md) можно ознакомиться, перейдя по ссылке [helm-based-control-scripts](../../examples/helm-based-control-scripts).
70−Набор [control scripts](Control_scripts.md) был упакован в докер образ и отправлен в регистри:
71−
72−```bash
73−docker build -f docker/Dockerfile -t typeable/octopod-helm-example:1.0 .
74−docker push typeable/octopod-helm-example:1.0
75−```
76−**Примечание:**
77−В нашем примере используется Stateless приложение упакованное в один chart.
78−Так что для создания и обновления необходимо выполнить один набор команд (`helm upgrade --install ...`).
79−Поэтому [control scripts](Control_scripts.md) реализован только `create`, и он же используется вместо `update`.
80−В случае более сложного приложения упакованного в несколько chart-ов, возможно потребуется выполнить различный набор команд,
81−это потребует реализации различных `create` и `update` скриптов.
82−
83−## Создание нового deployment
84−
85−Для создания достаточно выполнить
86−```bash
87−octo create -n hello-octopod -t v1 -e APP_ENV_KEY1=VALUE1
88−```
89−
90−- `-n hello-octopod` ― название deployment.
91−- `-t v1` ― тег deployment.
92−- `-e APP_ENV_KEY1=VALUE1` ― переменная окружения уровня приложения.
93−
94−Эта команда вызовет `create` из [control scripts](Control_scripts.md), a `create` вызовет `helm`.
95−Спустя некоторое время Вы увидите созданный _Pod_ нового deployment
96−```
97−$ kubectl get pods -n deployment
98−NAME READY STATUS RESTARTS AGE
99−app-hello-octopod-8965856-qbwvq 1/1 Running 0 15s
100−```
101−
102−Если откроете в браузере `http://hello-octopod.<домен, указанный при развертывании Octopod>` Вы увидите
103−
104−![После создания](../images/hello-octopod-1.png)
105−
106−## Добавление новой переменной окружения уровня приложения
107−
108−Для добавления новой переменной уровня приложения достаточно выполнить
109−```bash
110−octo update -n hello-octopod -t v1 -e APP_ENV_KEY2=VALUE2
111−```
112−
113−- `-n hello-octopod` ― название deployment.
114−- `-t v1` ― тег deployment.
115−- `-e APP_ENV_KEY2=VALUE2` ― переменная окружения уровня приложения.
116−
117−Эта команда вызовет `create` из [control scripts](Control_scripts.md), `create` вызовет `helm` (Смотри примечание раздела _Подготовка_).
118−Спустя несколько секунд, если откроете в браузере `http://hello-octopod.<домен указанный при развертывании Octopod>` Вы увидите новую переменную окружения уровня приложения:
119−
120−![После установки новой переменной окружения уровня приложения](../images/hello-octopod-2.png)
121−
122−## Обновление версии приложения
123−
124−Для обновления приложения до новой версии достаточно выполнить
125−```bash
126−octo update -n hello-octopod -t v2
127−```
128−
129−- `-n hello-octopod` ― название deployment.
130−- `-t v2` ― тег deployment.
131−
132−Эта команда вызовет `create` из [control scripts](Control_scripts.md), `create` вызовет `helm` (Смотри примечание раздела _Подготовка_).
133−Спустя несколько секунд, если откроете в браузере `http://hello-octopod.<домен указанный при развертывании Octopod>` Вы увидите обновленную HTML разметку:
134−
135−![После создания](../images/hello-octopod-3.png)
136−
137−## Увеличение количества реплик через установку переменной окружения уровня deployment
138−
139−Для добавления новой переменной достаточно выполнить
140−```bash
141−octo update -n hello-octopod -t v2 -o replicas=3
142−```
143−
144−- `-n hello-octopod` ― название deployment.
145−- `-t v1` ― тег deployment.
146−- `-o replicas=3` ― переменная окружения уровня deployment.
147−
148−Эта команда вызовет `create` из [control scripts](Control_scripts.md), `create` вызовет `helm` (Смотри примечание раздела _Подготовка_).
149−
150−Спустя некоторое время Вы увидите, что количество _Pod_-ов стало 3
151−```bash
152−$ kubectl get pods -n deployment
153−NAME READY STATUS RESTARTS AGE
154−app-hello-octopod-8965856-qbwvq 1/1 Running 0 97m
155−app-hello-octopod-8965856-v585c 1/1 Running 0 15s
156−app-hello-octopod-8965856-v88md 1/1 Running 0 15s
157−```
158−
159−Если откроете в браузере `http://hello-octopod.<домен указанный при развертывании Octopod>`, Вы увидите, что приложение продолжает обсуживать запросы:
160−
161−![После обновления переменной окружения уровня deployment](../images/hello-octopod-3.png)
162−
163−[cert-manager]: https://cert-manager.io/docs
164−[lets-encrypt]: https://letsencrypt.org
165−[lets-encrypt-rate-limits]: https://letsencrypt.org/docs/rate-limits
docs/ru/Octo_user_guide.mddeleted−173
@@ -1,173 +0,0 @@
1−# Octo user guide
2−
3−_octo CLI_ – консольная утилита для управления deployments через отправку команд в _Octopod Server_.
4−
5−## Environment variables
6−
7−`OCTOPOD_URL` – URL к _Octopod Server_, например `https://octopod-power-app.example.com:443`, **необходимо определить, иначе _octo CLI_ не будет работать**.
8−
9−`TLS_CERT_PATH` – путь к файлу сертификата, который используется для аутентификации в _Octopod Server_, если не определенно, то используется `./cert.pem`.
10−
11−`TLS_KEY_PATH` – путь к файлу ключа, который используется для аутентификации в _Octopod Server_, если не определенно, то используется `./key.pem`.
12−
13−## Subcommands
14−
15−### create
16−
17−Создать новый deployment.
18−
19−Аргументы:
20−
21−* `-n` или `--name` – название deployment
22−* `-t` или `--tag` – тег deployment
23−* `-e` или `--set-app-env-override` – override уровна приложения, формат: КЛЮЧ=ЗНАЧЕНИЕ, можно использовать 0 и более раз
24−* `-o` или `--set-deployment-override` – override увроня deployment, формат: КЛЮЧ=ЗНАЧЕНИЕ, можно использовать 0 и более раз
25−
26−Пример:
27−
28−```bash
29−$ octo create -n hello-octopod -t ca5fd1fe08389f6422a506a59b68a5272ac37ba6 -e KEY1=VALUE1 -e KEY2=VALUE2
30−```
31−
32−### list
33−
34−Получить список всех deployments.
35−
36−Данная subcommand не требует передачи аргументов.
37−
38−Пример:
39−
40−```bash
41−$ octo list
42−hello-octopod
43−```
44−
45−### archive
46−
47−Удалить deployment.
48−
49−Аргументы:
50−
51−* `-n` или `--name` – название deployment
52−
53−Пример:
54−
55−```bash
56−$ octo archive -n hello-octopod
57−```
58−
59−### update
60−
61−Обновить deployment.
62−
63−Аргументы:
64−
65−* `-n` или `--name` – название deployment
66−* `-t` или `--tag` – тег deployment
67−* `-e` или `--set-app-env-override` – override уровна приложения, формат: КЛЮЧ=ЗНАЧЕНИЕ, можно использовать 0 и более раз
68−* `-E` или `--unset-app-env-override` – override уровна приложения, которое надо удалить, формат: КЛЮЧ, можно использовать 0 и более раз
69−* `-o` или `--set-deployment-override` – override увроня deployment, формат: КЛЮЧ=ЗНАЧЕНИЕ, можно использовать 0 и более раз
70−* `-O` или `--unset-deployment-override` – override увроня deployment, которое надо удалить, формат: КЛЮЧ, можно использовать 0 и более раз
71−
72−Пример:
73−
74−```bash
75−$ octo update -n octopod -t 015f16ecf398fcadaac508c1855ae160af0969c4 -E KEY1 -e KEY2=VALUE22222
76−```
77−
78−### info
79−
80−Получить информацию о deployment.
81−
82−Аргументы:
83−
84−* `-n` или `--name` – название deployment
85−
86−Пример:
87−
88−```bash
89−$ octo info -n hello-octopod
90−Current settings:
91−tag: v1
92−application overrides: app=1 (Public)
93−
94−deployment overrides: dep=2 (Public)
95−
96−metadata:
97− app: https://ree.lvh.me
98−
99−Last logs:
100−┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━┳━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
101−┃ Created at ┃ Action id ┃ Action ┃ Tag ┃ App overrides ┃ Deployment overrides ┃ Exit code ┃
102−┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━╇━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
103−│ 2020-11-02T17:14:03 │ 7 │ create │ v1 │ app=1 (Public) │ dep=2 (Public) │ 1 │
104−├─────────────────────┼───────────┼────────┼─────┼────────────────┼──────────────────────┼───────────┤
105−│ 2020-11-02T19:01:02 │ 8 │ update │ v1 │ app=1 (Public) │ dep=2 (Public) │ 1 │
106−└─────────────────────┴───────────┴────────┴─────┴────────────────┴──────────────────────┴───────────┘
107−```
108−
109−### cleanup
110−
111−Очистить ресурсы от deployment.
112−
113−Аргументы:
114−
115−* `-n` или `--name` – название deployment
116−
117−Пример:
118−
119−```bash
120−$ octo cleanup -n hello-octopod
121−```
122−
123−### restore
124−
125−Восстановить deployment.
126−
127−Аргументы:
128−
129−* `-n` или `--name` – название deployment
130−
131−Пример:
132−
133−```bash
134−$ octo restore -n hello-octopod
135−```
136−
137−### clean-archive
138−
139−Удалить архивные deployments старее 2х недель.
140−
141−Данная subcommand не требует передачи аргументов.
142−
143−Пример:
144−
145−```bash
146−$ octo clean-archive
147−```
148−
149−### logs
150−
151−Печатает логи выбранного деплоя.
152−
153−Аргументы:
154−
155−* `-a` или `--action` – action id, который вернулся из команды `octo info`.
156−* `-l` или `--log-type` – Какие логи необходимо вернуть. Значения: `stdout`, `stderr`, `all`. По умолчанию будет `all`
157−
158−Пример:
159−
160−```
161−$ octo logs -a 13
162− stdout:
163−
164−
165− stderr:
166−
167−error: Found argument '--deployment-override' which wasn't expected, or isn't valid in this context
168−
169−USAGE:
170− update --app-env-override <app-env-override>... --base-domain <base-domain> --name <name> --namespace <namespace> --project-name <project-name> --tag <tag>
171−
172−For more information try --help
173−```
docs/ru/Octopod_deployment_with_K8S.mddeleted−275
@@ -1,275 +0,0 @@
1−# Octopod deployment with K8S
2−
3−1. Установка необходимых утилит
4−
5− Для установки потребуется [_kubectl_][kubectl] и [_helm_][helm] версии 2.
6−
7−2. Настройка кластера
8−
9− _Octopod_ использует [_Ingress Nginx_][ingress-nginx], [_Cert Manager_][cert-manager]. Убедитесь, что они установленны в вашем кластере.
10−
11− Для работы _Octopod_ нужны 3 TLS сертификата. [_Cert Manager_][cert-manager] создает сертификаты через [_Let’s Encrypt_][lets-encrypt].
12− У [_Let’s Encrypt_][lets-encrypt] есть лимиты на создание сертификатов [_Let’s Encrypt Rate Limits_][lets-encrypt-rate-limits].
13− При достижении лимита `too many registrations for this IP` может помочь перемещение Pod [_Cert Manager_][cert-manager] на другую ноду.
14−
15− _Octopod_ необходимо не более 2 CPU и 2Gb оперативной памяти, пожалуйста убедитесь что у вас есть необходимые ресурсы.
16−
17− _Octopod_ будет развернут на ноду с label `role=stand`, пожалуйста добавте label:
18− ```
19− kubectl label node <your_node> role=stand
20− ```
21−
22−3. Также вам потребуется [_Tiller_][tiller] – сервис на стороне кластера, который необходим для работы [_helm 2_][helm]. Самый простой способ его установить это:
23−
24− ```bash
25− helm init
26− ```
27−
28− Если Вы установили [_Tiller_][tiller], у вас может возникнуть [проблемы с правами доступа](https://github.com/helm/helm/issues/5100) у [_Tiller_][tiller].
29−
30− Чтобы выдать ему необходимые права будет достаточно выполнить следующие команды:
31−
32− ```bash
33− kubectl create -n kube-system serviceaccount tiller
34− kubectl --namespace kube-system create clusterrolebinding tiller-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
35− kubectl --namespace kube-system patch deploy tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'
36− ```
37−
38−
39−4. Скачивание исходного кода проекта
40−
41− ```bash
42− git clone --branch master https://github.com/typeable/octopod.git /tmp/octopod
43− ```
44−
45−5. Создание namespace `deployment` и `octopod`
46−
47− ```bash
48− kubectl create namespace deployment
49− kubectl create namespace octopod
50− ```
51−
52−6. Создание [_Service Account_][kubernetes-service-account] `octopod`
53−
54− ```bash
55− kubectl create -n octopod serviceaccount octopod
56− ```
57−
58−7. Создание секрета, который будет использоваться для Basic Auth между _Web UI_ и _Octopod Server_
59−
60− ```bash
61− username="octopod"
62− password="password" # пожалуйста поменяйте на более безопасный пароль
63− kubectl create secret generic octopod-basic-auth -n octopod --from-literal=auth=$(htpasswd -bn $username $password)
64− ```
65−
66−8. Создание ConfigMap с сертификатами и ключами, которые будут использоваться для аутентификации между _octo CLI_ и _Octopod Server_
67−
68− ```bash
69− mkdir certs
70− (cd certs && \
71− openssl req -x509 -newkey rsa:4096 -keyout server_key.pem -out server_cert.pem -nodes -subj "/CN=localhost/O=Server" && \
72− openssl req -newkey rsa:4096 -keyout client_key.pem -out client_csr.pem -nodes -subj "/CN=Client" && \
73− openssl x509 -req -in client_csr.pem -CA server_cert.pem -CAkey server_key.pem -out client_cert.pem -set_serial 01 -days 3650)
74− kubectl create configmap octopod-certs -n octopod --from-file=./certs
75− ```
76−
77− После этого директория `certs` будет содержать сертификаты, используемый для авторизации между _octo CLI_ и _Octopod Server_. `client_key.pem` и `client_cert.pem` необходимо будет [через переменные окружения передать в _octo CLI_](Octo_user_guide.md).
78−
79−9. Далее Вам необходимо будет настроить DNS чтобы поддомены вашего домена указывали на адрес вашего кластера:
80−
81− ```
82− *.octo.example.com A 1.2.3.4
83− ```
84−
85−10. Так как авторизация между _octo CLI_ и _Octopod Server_ будет производиться через SSL сертификаты, которые мы только что сами создали, нужно чтобы используемый в кластере [_ingress-nginx_][ingress-nginx] поддерживал _SSL passthrough_ – чтобы мы могли ему сказать "не трогай сертификаты".
86−
87− Чтобы этого добиться нам необходимо добавить `--enable-ssl-passthrough` в аргументы запуска [_ingress-nginx_][ingress-nginx] контроллера. Сделать это можно с командой вроде этой (конкретный namespace и название деплоймента нужно будет смотреть в вашем конкретном кластере):
88−
89− ```bash
90− kubectl edit deploy -n ingress-nginx nginx-ingress-ingress-nginx-controller
91− ```
92−
93− Помимо всех прочих параметров необходимо чтобы там был указан этот:
94−
95− ```yaml
96− spec:
97− ...
98− template:
99− ...
100− spec:
101− ...
102− containers:
103− ...
104− - args:
105− ...
106− - --enable-ssl-passthrough
107−
108− ```
109−
110−11. Установка инфраструктуры Octopod
111−
112− Перед началом установки убедитесь, что у вас в кластере есть [_Storage Class_][kubernetes-storage-classes] `default`.
113− Для [_minikube_][minikube] вы можете создать [_Storage Class_][kubernetes-storage-classes] `default` так:
114−
115− ```bash
116− cat <<EOF | kubectl apply -f-
117− ---
118− apiVersion: storage.k8s.io/v1
119− kind: StorageClass
120− metadata:
121− name: default
122− provisioner: k8s.io/minikube-hostpath
123− reclaimPolicy: Delete
124− volumeBindingMode: Immediate
125− EOF
126− ```
127−
128− ```bash
129− cd /tmp/octopod/charts
130−
131− helm upgrade --install octopod-infra ./octopod-infra --namespace octopod \
132− --wait --timeout 600 --debug
133− ```
134−
135−12. Выдача прав [_Service Account_][kubernetes-service-account] `octopod`
136−
137− 1. Eсли вы планируете использовать helm версии 2 для развертывания стейджингов,
138− то для этого необходимо выдать права [_Service Account_][kubernetes-service-account] `octopod`:
139− ```bash
140− cd /tmp/octopod/charts
141− helm install --name octopod-helm-access ./helm-access
142− ```
143−
144− 2. Eсли вы планируете в `cleanup` из [_Control scripts_](Control_scripts.md) удалять [_Persistent Volumes Claims_][kubernetes-pvc], то для этого необходимо выдать права [_Service Account_][kubernetes-service-account] `octopod`:
145− ```bash
146− cd /tmp/octopod/charts
147− helm install --name octopod-pvc-control ./pvc-control
148− ```
149−
150− 3. Eсли вы используете [_Cert Manager_][cert-manager] и планируете в `cleanup` из [_Control scripts_](Control_scripts.md) удалять сертификаты созданные [_cert-manager_][cert-manager], то для этого необходимо выдать права [_Service Account_][kubernetes-service-account] `octopod`:
151− ```bash
152− cd /tmp/octopod/charts
153− helm install --name octopod-cert-control ./cert-control
154− ```
155−
156− 4. Если Вы планируете использовать [_kubedog_][kubedog] в `check` из [_Control scripts_](Control_scripts.md) для проверки состояния развертывания, то Вам необходимо будет выдать соответствующие права [_Service Account_][kubernetes-service-account] `octopod`:
157−
158− ```bash
159− cd /tmp/octopod/charts
160− helm install --name octopod-kubedog-access ./kubedog-access
161− ```
162−
163−13. Установка сервера Octopod
164−
165− ```bash
166− cd /tmp/octopod/charts
167−
168− # название проекта
169− project_name="MyProject"
170−
171− # Название вашего docker registry, где находятся docker образы с Octopod Server, octo CLI, Control scripts, sqitch
172− registry="typeable"
173−
174− # tag Octopod Server
175− tag="1.0"
176−
177− # название docker образа Octopod Server
178− image="octopod"
179−
180− # название docker образа _octo CLI_
181− octo_image="octo"
182−
183− # Название вашего docker registry, где находится docker образ написанными Вами Control Scripts.
184− utils_registry="registry_name"
185−
186− # название docker образа _Control scripts_
187− utils_image="utils"
188−
189− # tag _Control scripts_
190− utils_image_tag="1.0"
191−
192− # email используемый для регистрации в Let’s Encrypt
193− acme_registration_email="certbot@example.com"
194−
195− # Это не обязательный параметр, если не определить, то доступ к Web UI не будет ограничен аутентификацией.
196− # Этот парамет работает в паре с auth_signin, надо либо оба не определять, либо оба определять.
197− # Если этот параметр определен, то он передается в ingress-nginx и используется для ограничения доступа через через внешний сервис, например OAuth.
198− # Для ограничения доступа через OAuth можно использовать OAuth2 Proxy (Смотри примечание ниже).
199− auth_url="https://oauth.exmaple.com/oauth2/auth"
200−
201− # Это не обязательный параметр, если не определить, то доступ к Web UI не будет ограничен аутентификацией.
202− # Этот парамет работает в паре с auth_url, надо либо оба не определять, либо оба определять.
203− # Если этот параметр определен, то он передается в ingress-nginx и используется для ограничения доступа через через внешний сервис, например OAuth.
204− # Для ограничения доступа через OAuth можно использовать OAuth2 Proxy (Смотри примечание ниже).
205− auth_signin="https://oauth.exmaple.com/oauth2/start?rd=/redirect/$http_host$request_uri"
206−
207− # domain по которому будет доступен UI Web
208− domain="octo.example.com"
209−
210− # домен по которому будет доступен Octopod Server для HTTP запросов
211− app_domain="api.octo.example.com"
212−
213− # домен по которому будет доступен Octopod Server для WebSocket запросов
214− ws_domain="ws.octo.example.com"
215−
216− # домен по которому будет доступен Octopod Server для HTTP запросов от octo CLI
217− power_app_domain="power.octo.example.com"
218−
219− # домен который будет использоваться для создания доменов deployment-ов
220− base_domain="octo.example.com"
221−
222− # таймаут в секундах после которого обновление состояния deployment считается неудачным
223− status_update_timeout=600
224−
225− # контрольная сумма chart'а
226− # NOTE: на macOS нужно будет `sha256sum` заменить на `shasum -a 256`
227− sha256_sum=$(sha256sum octopod/values.yaml octopod/templates/* | awk '{print $1}' | sha256sum | awk '{print $1}')
228−
229− # имя пользователя, должно совпадать с именем пользователя из шага 7
230− username="octopod"
231−
232− # пароль, должен совпадать с паролем из шага 7
233− password="password"
234−
235− # base64 от имя пользователя и пароля
236− base64_of_username_and_password=$(echo -n "$username:$password" | base64)
237−
238− helm upgrade --install octopod ./octopod \
239− --namespace octopod \
240− --set "global.deploy_checksum=$sha256_sum" \
241− --set "global.image_prefix=$registry" \
242− --set "global.image_tag=$tag" \
243− --set "global.image=$image" \
244− --set "global.octo_image=$octo_image" \
245− --set "global.utils_image_prefix=$utils_registry" \
246− --set "global.utils_image=$utils_image" \
247− --set "global.utils_image_tag=$utils_image_tag" \
248− --set "global.acme_registration_email=$acme_registration_email" \
249− --set "global.auth_url=$auth_url" \
250− --set "global.auth_signin=$auth_signin" \
251− --set "basic_auth_token=$base64_of_username_and_password" \
252− --set "project_name=$project_name" \
253− --set "domain=$domain" \
254− --set "app_domain=$app_domain" \
255− --set "ws_domain=$ws_domain" \
256− --set "power_app_domain=$power_app_domain" \
257− --set "base_domain=$base_domain" \
258− --set "status_update_timeout=$status_update_timeout" \
259− --wait --timeout 600 --debug
260− ```
261−
262−**Примечание**: Более подробно про настройку OAuth описано в [_Security model_](Security_model.md#users-auth-example-with-oauth)
263−
264−[kubectl]: https://kubernetes.io/docs/tasks/tools/install-kubectl
265−[helm]: https://v2.helm.sh/docs/using_helm/#installing-helm
266−[ingress-nginx]: https://kubernetes.github.io/ingress-nginx
267−[cert-manager]: https://cert-manager.io/docs
268−[lets-encrypt]: https://letsencrypt.org
269−[lets-encrypt-rate-limits]: https://letsencrypt.org/docs/rate-limits
270−[kubernetes-service-account]: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account
271−[kubernetes-pvc]: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#expanding-persistent-volumes-claims
272−[kubernetes-storage-classes]: https://kubernetes.io/docs/concepts/storage/storage-classes
273−[minikube]: https://kubernetes.io/ru/docs/tasks/tools/install-minikube
274−[tiller]: https://v2.helm.sh/docs/install
275−[kubedog]: https://github.com/werf/kubedog
docs/ru/README.mddeleted−8
@@ -1,8 +0,0 @@
1−# 🐙📑 Документация Octopod
2−
3−- [🏗 Техническая архитектура](Technical_architecture.md)
4−- [⚙️ Гайд по скриптам управления развертываниямия](Control_scripts.md)
5−- [🔧🐙 Гайд по делою самого Octopod](Octopod_deployment_with_K8S.md)
6−- [🔧🚀 Гайд по интеграции проекта с Octopod](Helm-based_deployment_guide.md)
7−- [🐙🎛 Гайд по использованию octo CLI](Octo_user_guide.md)
8−- [🔒 Модель безопасности Octopod](Security_model.md)
docs/ru/Security_model.mddeleted−120
@@ -1,120 +0,0 @@
1−# Security model
2−
3−<details>
4− <summary>Table of contents</summary>
5−
6−- [Octopod roles](#octopod-roles)
7−- [Kubernetes role-based access control](#kubernetes-role-based-access-control)
8− - [Права на удаление сертификатов](#права-на-удаление-сертификатов)
9− - [Права на удаление Persistent Volumes Claims](#права-на-удаление-persistent-volumes-claims)
10−- [Users auth example with OAuth](#users-auth-example-with-oauth)
11−- [CLI client Auth](#cli-client-auth)
12−- [UI Auth](#ui-auth)
13−
14−</details>
15−
16−## Octopod roles
17−
18−В _Octopod_ есть 2 роли:
19−* _user_
20−* _admin_
21−
22−| role | управление развертываниями | просмотр логов развертываний |
23−| :---: | :------------------------: | :--------------------------: |
24−| user | ✅ | ❌ |
25−| admin | ✅ | ✅ |
26−
27−Пользователи _UI_ работают с правами _user_.
28−
29−Пользователи _octo CLI_ работают с правами _admin_.
30−
31−## Kubernetes role-based access control
32−
33−_Octopod Server_ разворачивается в `octopod` namespace. _Octopod Server_ разворачивает развертывания в `deployments` namespace.
34−_Octopod Server_ использует `octopod` [_Service Account_][kubernetes-service-account].
35−
36−Для очистки ресурсов _Octopod Server_ / _Контейнеру с утилитами (control scripts)_ может потребоваться
37−(зависит от настроект _Kubernetes_ и релизации _Контейнера с утилитами_)
38−доступ для удаления сертификатов и [_Persistent Volumes Claims_][kubernetes-pvc].
39−
40−Доступ можно выдать через [_RBAC_][kubernetes-rbac]:
41−
42−### Права на удаление сертификатов
43−
44−```yaml
45−---
46−apiVersion: rbac.authorization.k8s.io/v1
47−kind: ClusterRole
48−metadata:
49− name: cert-control-clusterrole
50−rules:
51− - apiGroups: ["cert-manager.io"]
52− resources: ["certificates"]
53− verbs: ["list", "delete", "deletecollection"]
54−---
55−apiVersion: rbac.authorization.k8s.io/v1
56−kind: RoleBinding
57−metadata:
58− name: octopod-cert-control-rolebinding
59− namespace: deployments
60−roleRef:
61− kind: ClusterRole
62− apiGroup: rbac.authorization.k8s.io
63− name: cert-control-clusterrole
64−subjects:
65− - kind: ServiceAccount
66− name: octopod
67− namespace: octopod
68−```
69−
70−### Права на удаление Persistent Volumes Claims
71−
72−```yaml
73−---
74−apiVersion: rbac.authorization.k8s.io/v1
75−kind: ClusterRole
76−metadata:
77− name: pvc-control-clusterrole
78−rules:
79− - apiGroups: [""]
80− resources: ["persistentvolumeclaims"]
81− verbs: ["list", "delete", "deletecollection"]
82−---
83−apiVersion: rbac.authorization.k8s.io/v1
84−kind: RoleBinding
85−metadata:
86− name: octopod-pvc-control-rolebinding
87− namespace: deployments
88−roleRef:
89− kind: ClusterRole
90− apiGroup: rbac.authorization.k8s.io
91− name: pvc-control-clusterrole
92−subjects:
93− - kind: ServiceAccount
94− name: octopod
95− namespace: octopod
96−```
97−
98−## Users auth example with OAuth
99−
100−Доступ к _UI_ по умолчанию не ограничен.
101−Но вы можете добавить аутентификацию через GitHub OAuth в [_Kubernetes Ingress Nginx_][kubernetes-ingress-nginx-external-auth],
102−для этого потребуется дополнительно развернуть [_OAuth2 Proxy_][oauth2-proxy] в кластере.
103−
104−Более подробно описано в примере [_External OAUTH Authentication_][oauth-external-auth].
105−
106−## CLI client Auth
107−
108−Для аутентификации _octo CLI_ в _Octopod Server_ используется сертификат.
109−
110−## UI Auth
111−
112−Для аутентификации _UI_ в _Octopod Server_ используется Basic Auth.
113−
114−
115−[kubernetes-service-account]: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account
116−[kubernetes-rbac]: https://kubernetes.io/docs/reference/access-authn-authz/rbac
117−[kubernetes-pvc]: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#expanding-persistent-volumes-claims
118−[kubernetes-ingress-nginx-external-auth]: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#external-authentication
119−[oauth2-proxy]: https://oauth2-proxy.github.io/oauth2-proxy
120−[oauth-external-auth]: https://kubernetes.github.io/ingress-nginx/examples/auth/oauth-external-auth
docs/ru/Technical_architecture.mddeleted−275
@@ -1,275 +0,0 @@
1−# Technical architecture
2−
3−<details>
4− <summary>Table of contents</summary>
5−
6−- [Used tools](#used-tools)
7−- [App architecture](#app-architecture)
8− - [UI](#ui)
9− - [Octopod Server](#octopod-server)
10− - [PostgreSQL](#postgresql)
11− - [octo CLI](#octo-cli)
12− - [Скрипты управления развертываниями (control scripts)](#скрипты-управления-развертываниями-control-scripts)
13− - [Clean Archive CronJob](#clean-archive-cronjob)
14− - [Kube API Server](#kube-api-server)
15−- [Octopod Distribution model](#octopod-distribution-model)
16−- [Process view](#process-view)
17− - [Create](#create)
18− - [Create via CLI](#create-via-cli)
19− - [Create via UI](#create-via-ui)
20− - [Update](#update)
21− - [Update via CLI](#update-via-cli)
22− - [Update via UI](#update-via-ui)
23− - [Archive](#archive)
24− - [Archive via CLI](#archive-via-cli)
25− - [Archive via UI](#archive-via-ui)
26− - [Cleanup](#cleanup)
27− - [Cleanup via CLI](#cleanup-via-cli)
28− - [Cleanup via UI](#cleanup-via-ui)
29− - [Restore](#restore)
30− - [Restore via CLI](#restore-via-cli)
31− - [Restore via UI](#restore-via-ui)
32−- [How we use it](#how-we-use-it)
33−- [Deployment state transitions](#deployment-state-transitions)
34−
35−</details>
36−
37−## Used tools
38−
39−Основная цель *Octopod* ― упрощение управления разными развертываниями сервисов в [_Kubernetes_][kube].
40−
41−При разработке рассчитывалось, что сам _Octopod_ тоже будет разворачиваться при помощи [_Kubernetes_][kube].
42−
43−## App architecture
44−
45−Взаимодействовать с _Octopod_ возможно либо через веб-интерфейс (рассчитано на использование разработчиками, PM, QA и т. д.), либо через консольный клиент [_octo CLI_](#octopod-server) (рассчитано на использования DevOps инженерами и программно, например в CI).
46−
47−Все взаимодействие _Octopod_ с самими развертываниями производится через [_скрипты управления развертываниями (control scripts)_](#скрипты-управления-развертываниями-control-scripts), которые передаются ему при запуске. Это позволяет сделать _Octopod_ очень гибким ― его возможно настроить для работы с практически в любой организацией развертываний.
48−
49−Все данные об окружениях развертываний и всех операция совершаемых над ними _Octopod_ хранит в базе данных [_PostgreSQL_](#postgresql).
50−
51−![App architecture](../diagrams/images/app-architecture.png)
52−
53−### UI
54−
55−_UI_ – веб интерфейс,
56−используется для управления развертываниями посредством отправки команд управления развертываниями.
57−Взаимодействует с [_Octopod Server_](#octopod-server) посредством отправки HTTP/1.1 запросов, а также получает
58−события от [_Octopod Server_](#octopod-server) по _Websocket_. Между _UI_ и [_Octopod Server_](#octopod-server) Basic Auth. Написан на Haskell и Reflex-Dom.
59−
60−В интерфейсе нет технических деталей системной администрации и оркестрации ― работа с развертываниями производится очень просто. Интерфейс рассчитан на использование разработчиками любого уровня, QA инженерами, PM, а так же людьми без ИТ образования.
61−
62−### Octopod Server
63−
64−_Octopod Server_ – непосредственно сам сервер, который обрабатывает запросы работы с развертываниями и делегирует базовые операции, модифицирующие развертывания, [_скриптам управления стеджингами (control scripts)_](#скрипты-управления-развертываниями-control-scripts).
65−
66−Сервер обрабатывает
67−команды управления развертываниями от [_octo CLI_](#octopod-server) и [_UI_](#ui), обновляет состояние развертываний.
68−[_octo CLI_](#octopod-server) и [_UI_](#ui) взаимодействуют с ним путем отправки HTTP/1.1 запросов.
69−Сервер шлет событие обновления на [_UI_](#ui) по _Websocket_. Сервер взаимодействует с [_Kube API Server_](#kube-api-server)
70−через [_скрипты управления развертываниями (control scripts)_](#скрипты-управления-развертываниями-control-scripts). Для хранения настроек и статусов развертываний,
71−и логов действий пользователей используется [_PostgreSQL_](#postgresql). Написан на Haskell. Для работы
72−с развертываниями использует [_скрипты управления развертываниями (control scripts)_](#скрипты-управления-развертываниями-control-scripts).
73−
74−### PostgreSQL
75−
76−[_PostgreSQL_](https://www.postgresql.org) – РСУБД для хранения настроек и статусов развертываний, и логов
77−действий пользователей.
78−
79−### octo CLI
80−
81−_octo CLI_ – консольный клиент
82−используется для управления развертываниями посредством отправки команд управления
83−развертываниями. Взаимодействует с [_Octopod Server_](#octopod-server) посредством отправки HTTP/1.1 запросов.
84−Написан на Haskell. Между _octo CLI_ и [_Octopod Server_](#octopod-server) аутентификация по сертификату,
85−новый сертификаты создается вовремя каждой сборки и упаковываются в контейнеры с _octo CLI_ и [_Octopod Server_](#octopod-server).
86−
87−В нем можно делать все операции, которые можно делать в [_UI_](#ui), но также есть доступ к расширенным операциям над развертываниями, таким как просмотр логов деплоя, что может быть полезно при диагностике возникающих проблем.
88−
89−Этот клиент рассчитан на использование DevOps инженерами.
90−
91−Его также можно использовать если необходимо автоматизировать управление развертываниями. Например, при настройке автоматического обновления развертываний при успешно пройденном CI.
92−
93−### Скрипты управления развертываниями (control scripts)
94−
95−_Скрипты управления развертываниями (control scripts)_ – контейнер с исполняемыми файлами, в которые инкапсулирована
96−логика работы с [_Kube API Server_](#kube-api-server), облачными провайдерами, развертываниями, системами контроля версий и т.д.
97−
98−Они нужны для того, чтобы _Octopod_ не был завязан на какую-то конкретную организацию развертываний ― его можно настроить для работы с практически любой организацией развертываний.
99−
100−Во время старта пода [_Octopod Server_](#octopod-server) содержимое контейнера с утилитами копируется в ФС контейнера с [_Octopod Server_](#octopod-server),
101−поэтому исполняемые файлы должны быть либо интерпретируемы через _Bash_, либо статически слинкованны.
102−Логику исполняемых файлов предлагается реализовать пользователям _Octopod_ (смотри [_Control scripts_](Control_scripts.md)).
103−
104−### Clean Archive CronJob
105−
106−_Clean Archive CronJob_ – CronJob, которая запускается раз в час и через [_octo CLI_](#octopod-server) удаляет заархивированные развертывания старее 14 дней.
107−
108−Это сделано из-за того что при архивировании развертываний удаляются только вычислительные его части, _persistent volumes_ не удаляются, и при необходимости развертывание возможно восстановить в том виде, в котором он был до архивирования. Такая возможность пропадает по истечению 14 дней с момент его архивирования.
109−
110−### Kube API Server
111−
112−[Kube API Server](https://kubernetes.io/docs/concepts/overview/kubernetes-api/) – сервис на стороне [_Kubernetes_][kube], к которому должны обращаться [_скрипты управления развертываниями (control scripts)_](#скрипты-управления-развертываниями-control-scripts).
113−
114−## Octopod Distribution model
115−
116−[_octo CLI_](#octo-cli) в виде статически слинкованного исполняемого файла. Собранные исполняемые файлы доступны во вкладке "Releases" этого проекта на GitHub.
117−
118−[_Octopod Server_](#octopod-server) и [_UI_](#ui) поставляются упаковынными в один Docker образ. Для [развертывания](Octopod_deployment_with_K8S.md) в [_Kubernetes_][kube] используется набор [_Chart_][chart]-ов. Образы доступны в [нашем registry на _Docker Hub_](https://hub.docker.com/orgs/typeable/repositories).
119−
120−Docker образ [_скриптов управления развертываниями (control scripts)_](#скрипты-управления-развертываниями-control-scripts) пользователь _Octopod_ собирает сам.
121−
122−## Process view
123−
124−Далее здесь для справки приводятся схемы последовательностей для каждой из базовых операция работы с развертываниями. При их исполнении вызываются [_скрипты управления развертываниями (control scripts)_](#скрипты-управления-развертываниями-control-scripts). На схеме они помечены как _ControlScripts_.
125−
126−### Create
127−
128−_create_ – создание нового развертывания.
129− В качестве аргументов принимаются `name`, `tag` и опциональные `overrides` (уровня App или Deployment, открытие или секретные).
130−
131− Переданные аргументы вместе с `project-name`, `base-domain`, `namespace` передаются в качестве аргументов в `create` из [_скриптов управления развертываниями (control scripts)_](#скрипты-управления-развертываниями-control-scripts).
132− `create` создает новое развертывание в кластере используя полученные аргументы.
133− Например, он может выполнять:
134−
135−```bash
136−helm upgrade --install --namespace "$namespace" "$name" "$deployment_chart" \
137− --set "global.project-name=$project_name" \
138− --set "global.base-domain=$base-domain" \
139− --set "app.tag=$tag" \
140− --set "app.env.foo=$app_env_override_1" \
141− --set "app.bar=$deployment_override_1" \
142− --wait \
143− --timeout 300
144−```
145−
146−#### Create via CLI
147−![Create](../diagrams/images/technical-architecture-create-via-cli.png)
148−
149−#### Create via UI
150−![Create](../diagrams/images/technical-architecture-create-via-ui.png)
151−
152−### Update
153−
154−_update_ – обновление существующего развертывания.
155− В качестве аргументов принимаются `name`, `tag` и опционально изменения `overrides` (уровня App или Deployment, открытие или секретные).
156−
157− Затем из базы достаются `overrides` (уровня App или Deployment, открытие или секретные), они мерджатся с изменениями `overrides`
158− и передаются вместе с `project-name`, `base-domain`, `namespace` в качестве аргументов в `update` из [_скриптов управления развертываниями (control scripts)_](#скрипты-управления-развертываниями-control-scripts).
159− `update` обновляет существующее развертывание в кластере используя полученные аргументы.
160− Например, он может выполнять:
161−
162−```bash
163−helm upgrade --install --namespace "$namespace" "$name" "$deployment_chart" \
164− --set "global.project-name=$project_name" \
165− --set "global.base-domain=$base-domain" \
166− --set "app.tag=$tag" \
167− --set "app.env.foo=$app_env_override_1" \
168− --set "app.bar=$deployment_override_1" \
169− --wait \
170− --timeout 300
171−```
172−
173−
174−#### Update via CLI
175−![Update](../diagrams/images/technical-architecture-update-via-cli.png)
176−
177−#### Update via UI
178−![Update](../diagrams/images/technical-architecture-update-via-ui.png)
179−
180−### Archive
181−
182−_delete_ – архивирование существующего развертывания.
183− Производится удаление только подов, Persistent Volumes (диски) сохраняются. Отменить действие этой команды можно с помощью команды restore.
184− В качестве аргументов принимается `name`.
185−
186− `name` вместе с `project-name`, `base-domain`, `namespace` передаются в качестве аргументов в `archive` из [_скриптов управления развертываниями (control scripts)_](#скрипты-управления-развертываниями-control-scripts).
187− `archive` удаляет существующее развертывание в кластере, используя полученные аргументы.
188− Например он может выполнять:
189−
190−```bash
191−helm delete "$name" --purge
192−```
193−
194−
195−#### Archive via CLI
196−![Archive](../diagrams/images/technical-architecture-archive-via-cli.png)
197−
198−#### Archive via UI
199−![Archive](../diagrams/images/technical-architecture-archive-via-ui.png)
200−
201−### Cleanup
202−
203−_cleanup_ – полная очистка развертывания.
204− В качестве аргументов принимаeтся `name`.
205−
206− Например, можно удалять сертификаты, Persistent Volume Claim и Persistent Volumes.
207−
208− `name` вместе с `project-name`, `base-domain`, `namespace` передаются в качестве аргументов в `cleanup` из [_скриптов управления развертываниями (control scripts)_](#скрипты-управления-развертываниями-control-scripts).
209− `cleanup` выполняет освобождение ресурсов в кластере, которые ранее использовались одним из удаленных развертываний.
210− Например, он может выполнять:
211−
212−```bash
213−kubectl delete pvc -n "$namespace" "$name-postgres-pvc"
214−kubectl delete certificate -n "$namespace" "$name-postgres-cert"
215−```
216−
217−#### Cleanup via CLI
218−![Cleanup](../diagrams/images/technical-architecture-cleanup-via-cli.png)
219−
220−#### Cleanup via UI
221−![Cleanup](../diagrams/images/technical-architecture-cleanup-via-ui.png)
222−
223−### Restore
224−
225−_restore_ – восстановление заархивированного развертывания с последними настройками.
226− В качестве аргументов принимается `name`.
227−
228− Из базы достаются недостающие для восстановления `tag` и опциональные `overrides` (уровня App или Deployment, открытие или секретные). Они передаются вместе с `project-name`, `base-domain`, `namespace` в качестве аргументов в `restore` из [_скриптов управления развертываниями (control scripts)_](#скрипты-управления-развертываниями-control-scripts).
229− `restore` выполняет восстановление в кластере ранее удаленного развертывания используя полученные аргументы.
230− Например, он может выполнять:
231−
232−```bash
233−helm upgrade --install --namespace "$namespace" "$name" "$deployment_chart" \
234− --set "global.project-name=$project_name" \
235− --set "global.base-domain=$base-domain" \
236− --set "app.tag=$tag" \
237− --set "app.env.foo=$app_env_override_1" \
238− --set "app.bar=$deployment_override_1" \
239− --wait \
240− --timeout 300
241−```
242−
243−#### Restore via CLI
244−![Restore](../diagrams/images/technical-architecture-restore-via-cli.png)
245−
246−#### Restore via UI
247−![Restore](../diagrams/images/technical-architecture-restore-via-ui.png)
248−
249−## How we use it
250−
251−Мы используем несколько кластеров [_Kubernetes_][kube]: отдельный кластер для каждого приложения, а так же разделяем по кластерам _production_ и _deployment_ окружения.
252−
253−В каждый _deployment_ кластер мы устанавливаем _Octopod_, через _Octopod_ осуществляем разворачивание различных версий deployment'ов необходимых для QA.
254−
255−## Deployment state transitions
256−
257−Существует 6 статусов развертываний:
258−1. *Running*
259−2. *Failure*
260−3. *CreatePending*
261−4. *UpdatePending*
262−5. *DeletePending*
263−6. *Archived*
264−
265−_Running_, _Failure_, _Archived_ являются постоянными, т.е. развертывание уже не находится в режиме выполнения команды.
266−
267−*CreatePending*, *UpdatePending*, *DeletePending* являются переходными, т.е. развертывание находится в режиме выполнения команды.
268−
269−![Deployment Statuses](../diagrams/images/technical-architecture-deployment-states-fsm.png)
270−
271−<!-- [kubectl]: https://kubernetes.io/docs/reference/kubectl/ -->
272−<!-- [helm]: https://helm.sh -->
273−<!-- [kubedog]: https://github.com/werf/kubedog -->
274−[kube]: https://kubernetes.io
275−[chart]: https://helm.sh/docs/topics/charts/
examples/helm-based-control-scripts/Cargo.lockdeleted−1244
@@ -1,1244 +0,0 @@
1−# This file is automatically @generated by Cargo.
2−# It is not intended for manual editing.
3−[[package]]
4−name = "ansi_term"
5−version = "0.11.0"
6−source = "registry+https://github.com/rust-lang/crates.io-index"
7−checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
8−dependencies = [
9− "winapi 0.3.9",
10−]
11−
12−[[package]]
13−name = "atty"
14−version = "0.2.14"
15−source = "registry+https://github.com/rust-lang/crates.io-index"
16−checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
17−dependencies = [
18− "hermit-abi",
19− "libc",
20− "winapi 0.3.9",
21−]
22−
23−[[package]]
24−name = "autocfg"
25−version = "1.0.1"
26−source = "registry+https://github.com/rust-lang/crates.io-index"
27−checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
28−
29−[[package]]
30−name = "base64"
31−version = "0.12.3"
32−source = "registry+https://github.com/rust-lang/crates.io-index"
33−checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
34−
35−[[package]]
36−name = "base64"
37−version = "0.13.0"
38−source = "registry+https://github.com/rust-lang/crates.io-index"
39−checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
40−
41−[[package]]
42−name = "bitflags"
43−version = "1.2.1"
44−source = "registry+https://github.com/rust-lang/crates.io-index"
45−checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
46−
47−[[package]]
48−name = "bumpalo"
49−version = "3.4.0"
50−source = "registry+https://github.com/rust-lang/crates.io-index"
51−checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820"
52−
53−[[package]]
54−name = "bytes"
55−version = "0.5.6"
56−source = "registry+https://github.com/rust-lang/crates.io-index"
57−checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
58−
59−[[package]]
60−name = "cc"
61−version = "1.0.65"
62−source = "registry+https://github.com/rust-lang/crates.io-index"
63−checksum = "95752358c8f7552394baf48cd82695b345628ad3f170d607de3ca03b8dacca15"
64−
65−[[package]]
66−name = "cfg-if"
67−version = "0.1.10"
68−source = "registry+https://github.com/rust-lang/crates.io-index"
69−checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
70−
71−[[package]]
72−name = "cfg-if"
73−version = "1.0.0"
74−source = "registry+https://github.com/rust-lang/crates.io-index"
75−checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
76−
77−[[package]]
78−name = "clap"
79−version = "2.33.3"
80−source = "registry+https://github.com/rust-lang/crates.io-index"
81−checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
82−dependencies = [
83− "ansi_term",
84− "atty",
85− "bitflags",
86− "strsim",
87− "textwrap",
88− "unicode-width",
89− "vec_map",
90−]
91−
92−[[package]]
93−name = "console_error_panic_hook"
94−version = "0.1.6"
95−source = "registry+https://github.com/rust-lang/crates.io-index"
96−checksum = "b8d976903543e0c48546a91908f21588a680a8c8f984df9a5d69feccb2b2a211"
97−dependencies = [
98− "cfg-if 0.1.10",
99− "wasm-bindgen",
100−]
101−
102−[[package]]
103−name = "encoding_rs"
104−version = "0.8.26"
105−source = "registry+https://github.com/rust-lang/crates.io-index"
106−checksum = "801bbab217d7f79c0062f4f7205b5d4427c6d1a7bd7aafdd1475f7c59d62b283"
107−dependencies = [
108− "cfg-if 1.0.0",
109−]
110−
111−[[package]]
112−name = "fnv"
113−version = "1.0.7"
114−source = "registry+https://github.com/rust-lang/crates.io-index"
115−checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
116−
117−[[package]]
118−name = "form_urlencoded"
119−version = "1.0.0"
120−source = "registry+https://github.com/rust-lang/crates.io-index"
121−checksum = "ece68d15c92e84fa4f19d3780f1294e5ca82a78a6d515f1efaabcc144688be00"
122−dependencies = [
123− "matches",
124− "percent-encoding",
125−]
126−
127−[[package]]
128−name = "fuchsia-zircon"
129−version = "0.3.3"
130−source = "registry+https://github.com/rust-lang/crates.io-index"
131−checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
132−dependencies = [
133− "bitflags",
134− "fuchsia-zircon-sys",
135−]
136−
137−[[package]]
138−name = "fuchsia-zircon-sys"
139−version = "0.3.3"
140−source = "registry+https://github.com/rust-lang/crates.io-index"
141−checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
142−
143−[[package]]
144−name = "futures-channel"
145−version = "0.3.8"
146−source = "registry+https://github.com/rust-lang/crates.io-index"
147−checksum = "4b7109687aa4e177ef6fe84553af6280ef2778bdb7783ba44c9dc3399110fe64"
148−dependencies = [
149− "futures-core",
150−]
151−
152−[[package]]
153−name = "futures-core"
154−version = "0.3.8"
155−source = "registry+https://github.com/rust-lang/crates.io-index"
156−checksum = "847ce131b72ffb13b6109a221da9ad97a64cbe48feb1028356b836b47b8f1748"
157−
158−[[package]]
159−name = "futures-macro"
160−version = "0.3.8"
161−source = "registry+https://github.com/rust-lang/crates.io-index"
162−checksum = "77408a692f1f97bcc61dc001d752e00643408fbc922e4d634c655df50d595556"
163−dependencies = [
164− "proc-macro-hack",
165− "proc-macro2",
166− "quote",
167− "syn",
168−]
169−
170−[[package]]
171−name = "futures-sink"
172−version = "0.3.8"
173−source = "registry+https://github.com/rust-lang/crates.io-index"
174−checksum = "f878195a49cee50e006b02b93cf7e0a95a38ac7b776b4c4d9cc1207cd20fcb3d"
175−
176−[[package]]
177−name = "futures-task"
178−version = "0.3.8"
179−source = "registry+https://github.com/rust-lang/crates.io-index"
180−checksum = "7c554eb5bf48b2426c4771ab68c6b14468b6e76cc90996f528c3338d761a4d0d"
181−dependencies = [
182− "once_cell",
183−]
184−
185−[[package]]
186−name = "futures-util"
187−version = "0.3.8"
188−source = "registry+https://github.com/rust-lang/crates.io-index"
189−checksum = "d304cff4a7b99cfb7986f7d43fbe93d175e72e704a8860787cc95e9ffd85cbd2"
190−dependencies = [
191− "futures-core",
192− "futures-macro",
193− "futures-task",
194− "pin-project 1.0.2",
195− "pin-utils",
196− "proc-macro-hack",
197− "proc-macro-nested",
198− "slab",
199−]
200−
201−[[package]]
202−name = "getrandom"
203−version = "0.1.15"
204−source = "registry+https://github.com/rust-lang/crates.io-index"
205−checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6"
206−dependencies = [
207− "cfg-if 0.1.10",
208− "libc",
209− "wasi",
210−]
211−
212−[[package]]
213−name = "h2"
214−version = "0.2.7"
215−source = "registry+https://github.com/rust-lang/crates.io-index"
216−checksum = "5e4728fd124914ad25e99e3d15a9361a879f6620f63cb56bbb08f95abb97a535"
217−dependencies = [
218− "bytes",
219− "fnv",
220− "futures-core",
221− "futures-sink",
222− "futures-util",
223− "http",
224− "indexmap",
225− "slab",
226− "tokio",
227− "tokio-util",
228− "tracing",
229− "tracing-futures",
230−]
231−
232−[[package]]
233−name = "hashbrown"
234−version = "0.9.1"
235−source = "registry+https://github.com/rust-lang/crates.io-index"
236−checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
237−
238−[[package]]
239−name = "helm-based-control-scripts"
240−version = "0.1.0"
241−dependencies = [
242− "clap",
243− "rand",
244− "reqwest",
245− "serde",
246− "serde_derive",
247− "serde_json",
248− "tokio",
249−]
250−
251−[[package]]
252−name = "hermit-abi"
253−version = "0.1.17"
254−source = "registry+https://github.com/rust-lang/crates.io-index"
255−checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8"
256−dependencies = [
257− "libc",
258−]
259−
260−[[package]]
261−name = "http"
262−version = "0.2.1"
263−source = "registry+https://github.com/rust-lang/crates.io-index"
264−checksum = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9"
265−dependencies = [
266− "bytes",
267− "fnv",
268− "itoa",
269−]
270−
271−[[package]]
272−name = "http-body"
273−version = "0.3.1"
274−source = "registry+https://github.com/rust-lang/crates.io-index"
275−checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b"
276−dependencies = [
277− "bytes",
278− "http",
279−]
280−
281−[[package]]
282−name = "httparse"
283−version = "1.3.4"
284−source = "registry+https://github.com/rust-lang/crates.io-index"
285−checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
286−
287−[[package]]
288−name = "httpdate"
289−version = "0.3.2"
290−source = "registry+https://github.com/rust-lang/crates.io-index"
291−checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47"
292−
293−[[package]]
294−name = "hyper"
295−version = "0.13.9"
296−source = "registry+https://github.com/rust-lang/crates.io-index"
297−checksum = "f6ad767baac13b44d4529fcf58ba2cd0995e36e7b435bc5b039de6f47e880dbf"
298−dependencies = [
299− "bytes",
300− "futures-channel",
301− "futures-core",
302− "futures-util",
303− "h2",
304− "http",
305− "http-body",
306− "httparse",
307− "httpdate",
308− "itoa",
309− "pin-project 1.0.2",
310− "socket2",
311− "tokio",
312− "tower-service",
313− "tracing",
314− "want",
315−]
316−
317−[[package]]
318−name = "hyper-rustls"
319−version = "0.21.0"
320−source = "registry+https://github.com/rust-lang/crates.io-index"
321−checksum = "37743cc83e8ee85eacfce90f2f4102030d9ff0a95244098d781e9bee4a90abb6"
322−dependencies = [
323− "bytes",
324− "futures-util",
325− "hyper",
326− "log",
327− "rustls",
328− "tokio",
329− "tokio-rustls",
330− "webpki",
331−]
332−
333−[[package]]
334−name = "idna"
335−version = "0.2.0"
336−source = "registry+https://github.com/rust-lang/crates.io-index"
337−checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
338−dependencies = [
339− "matches",
340− "unicode-bidi",
341− "unicode-normalization",
342−]
343−
344−[[package]]
345−name = "indexmap"
346−version = "1.6.0"
347−source = "registry+https://github.com/rust-lang/crates.io-index"
348−checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2"
349−dependencies = [
350− "autocfg",
351− "hashbrown",
352−]
353−
354−[[package]]
355−name = "iovec"
356−version = "0.1.4"
357−source = "registry+https://github.com/rust-lang/crates.io-index"
358−checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
359−dependencies = [
360− "libc",
361−]
362−
363−[[package]]
364−name = "ipnet"
365−version = "2.3.0"
366−source = "registry+https://github.com/rust-lang/crates.io-index"
367−checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135"
368−
369−[[package]]
370−name = "itoa"
371−version = "0.4.6"
372−source = "registry+https://github.com/rust-lang/crates.io-index"
373−checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
374−
375−[[package]]
376−name = "js-sys"
377−version = "0.3.46"
378−source = "registry+https://github.com/rust-lang/crates.io-index"
379−checksum = "cf3d7383929f7c9c7c2d0fa596f325832df98c3704f2c60553080f7127a58175"
380−dependencies = [
381− "wasm-bindgen",
382−]
383−
384−[[package]]
385−name = "kernel32-sys"
386−version = "0.2.2"
387−source = "registry+https://github.com/rust-lang/crates.io-index"
388−checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
389−dependencies = [
390− "winapi 0.2.8",
391− "winapi-build",
392−]
393−
394−[[package]]
395−name = "lazy_static"
396−version = "1.4.0"
397−source = "registry+https://github.com/rust-lang/crates.io-index"
398−checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
399−
400−[[package]]
401−name = "libc"
402−version = "0.2.80"
403−source = "registry+https://github.com/rust-lang/crates.io-index"
404−checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
405−
406−[[package]]
407−name = "log"
408−version = "0.4.11"
409−source = "registry+https://github.com/rust-lang/crates.io-index"
410−checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
411−dependencies = [
412− "cfg-if 0.1.10",
413−]
414−
415−[[package]]
416−name = "matches"
417−version = "0.1.8"
418−source = "registry+https://github.com/rust-lang/crates.io-index"
419−checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
420−
421−[[package]]
422−name = "memchr"
423−version = "2.3.4"
424−source = "registry+https://github.com/rust-lang/crates.io-index"
425−checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
426−
427−[[package]]
428−name = "mime"
429−version = "0.3.16"
430−source = "registry+https://github.com/rust-lang/crates.io-index"
431−checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
432−
433−[[package]]
434−name = "mime_guess"
435−version = "2.0.3"
436−source = "registry+https://github.com/rust-lang/crates.io-index"
437−checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212"
438−dependencies = [
439− "mime",
440− "unicase",
441−]
442−
443−[[package]]
444−name = "mio"
445−version = "0.6.23"
446−source = "registry+https://github.com/rust-lang/crates.io-index"
447−checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4"
448−dependencies = [
449− "cfg-if 0.1.10",
450− "fuchsia-zircon",
451− "fuchsia-zircon-sys",
452− "iovec",
453− "kernel32-sys",
454− "libc",
455− "log",
456− "miow 0.2.2",
457− "net2",
458− "slab",
459− "winapi 0.2.8",
460−]
461−
462−[[package]]
463−name = "mio-named-pipes"
464−version = "0.1.7"
465−source = "registry+https://github.com/rust-lang/crates.io-index"
466−checksum = "0840c1c50fd55e521b247f949c241c9997709f23bd7f023b9762cd561e935656"
467−dependencies = [
468− "log",
469− "mio",
470− "miow 0.3.6",
471− "winapi 0.3.9",
472−]
473−
474−[[package]]
475−name = "mio-uds"
476−version = "0.6.8"
477−source = "registry+https://github.com/rust-lang/crates.io-index"
478−checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0"
479−dependencies = [
480− "iovec",
481− "libc",
482− "mio",
483−]
484−
485−[[package]]
486−name = "miow"
487−version = "0.2.2"
488−source = "registry+https://github.com/rust-lang/crates.io-index"
489−checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d"
490−dependencies = [
491− "kernel32-sys",
492− "net2",
493− "winapi 0.2.8",
494− "ws2_32-sys",
495−]
496−
497−[[package]]
498−name = "miow"
499−version = "0.3.6"
500−source = "registry+https://github.com/rust-lang/crates.io-index"
501−checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897"
502−dependencies = [
503− "socket2",
504− "winapi 0.3.9",
505−]
506−
507−[[package]]
508−name = "net2"
509−version = "0.2.36"
510−source = "registry+https://github.com/rust-lang/crates.io-index"
511−checksum = "d7cf75f38f16cb05ea017784dc6dbfd354f76c223dba37701734c4f5a9337d02"
512−dependencies = [
513− "cfg-if 0.1.10",
514− "libc",
515− "winapi 0.3.9",
516−]
517−
518−[[package]]
519−name = "num_cpus"
520−version = "1.13.0"
521−source = "registry+https://github.com/rust-lang/crates.io-index"
522−checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
523−dependencies = [
524− "hermit-abi",
525− "libc",
526−]
527−
528−[[package]]
529−name = "once_cell"
530−version = "1.5.2"
531−source = "registry+https://github.com/rust-lang/crates.io-index"
532−checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
533−
534−[[package]]
535−name = "percent-encoding"
536−version = "2.1.0"
537−source = "registry+https://github.com/rust-lang/crates.io-index"
538−checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
539−
540−[[package]]
541−name = "pin-project"
542−version = "0.4.27"
543−source = "registry+https://github.com/rust-lang/crates.io-index"
544−checksum = "2ffbc8e94b38ea3d2d8ba92aea2983b503cd75d0888d75b86bb37970b5698e15"
545−dependencies = [
546− "pin-project-internal 0.4.27",
547−]
548−
549−[[package]]
550−name = "pin-project"
551−version = "1.0.2"
552−source = "registry+https://github.com/rust-lang/crates.io-index"
553−checksum = "9ccc2237c2c489783abd8c4c80e5450fc0e98644555b1364da68cc29aa151ca7"
554−dependencies = [
555− "pin-project-internal 1.0.2",
556−]
557−
558−[[package]]
559−name = "pin-project-internal"
560−version = "0.4.27"
561−source = "registry+https://github.com/rust-lang/crates.io-index"
562−checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895"
563−dependencies = [
564− "proc-macro2",
565− "quote",
566− "syn",
567−]
568−
569−[[package]]
570−name = "pin-project-internal"
571−version = "1.0.2"
572−source = "registry+https://github.com/rust-lang/crates.io-index"
573−checksum = "f8e8d2bf0b23038a4424865103a4df472855692821aab4e4f5c3312d461d9e5f"
574−dependencies = [
575− "proc-macro2",
576− "quote",
577− "syn",
578−]
579−
580−[[package]]
581−name = "pin-project-lite"
582−version = "0.1.11"
583−source = "registry+https://github.com/rust-lang/crates.io-index"
584−checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b"
585−
586−[[package]]
587−name = "pin-project-lite"
588−version = "0.2.0"
589−source = "registry+https://github.com/rust-lang/crates.io-index"
590−checksum = "6b063f57ec186e6140e2b8b6921e5f1bd89c7356dda5b33acc5401203ca6131c"
591−
592−[[package]]
593−name = "pin-utils"
594−version = "0.1.0"
595−source = "registry+https://github.com/rust-lang/crates.io-index"
596−checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
597−
598−[[package]]
599−name = "ppv-lite86"
600−version = "0.2.10"
601−source = "registry+https://github.com/rust-lang/crates.io-index"
602−checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
603−
604−[[package]]
605−name = "proc-macro-hack"
606−version = "0.5.19"
607−source = "registry+https://github.com/rust-lang/crates.io-index"
608−checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
609−
610−[[package]]
611−name = "proc-macro-nested"
612−version = "0.1.6"
613−source = "registry+https://github.com/rust-lang/crates.io-index"
614−checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a"
615−
616−[[package]]
617−name = "proc-macro2"
618−version = "1.0.24"
619−source = "registry+https://github.com/rust-lang/crates.io-index"
620−checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
621−dependencies = [
622− "unicode-xid",
623−]
624−
625−[[package]]
626−name = "quote"
627−version = "1.0.7"
628−source = "registry+https://github.com/rust-lang/crates.io-index"
629−checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
630−dependencies = [
631− "proc-macro2",
632−]
633−
634−[[package]]
635−name = "rand"
636−version = "0.7.3"
637−source = "registry+https://github.com/rust-lang/crates.io-index"
638−checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
639−dependencies = [
640− "getrandom",
641− "libc",
642− "rand_chacha",
643− "rand_core",
644− "rand_hc",
645−]
646−
647−[[package]]
648−name = "rand_chacha"
649−version = "0.2.2"
650−source = "registry+https://github.com/rust-lang/crates.io-index"
651−checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
652−dependencies = [
653− "ppv-lite86",
654− "rand_core",
655−]
656−
657−[[package]]
658−name = "rand_core"
659−version = "0.5.1"
660−source = "registry+https://github.com/rust-lang/crates.io-index"
661−checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
662−dependencies = [
663− "getrandom",
664−]
665−
666−[[package]]
667−name = "rand_hc"
668−version = "0.2.0"
669−source = "registry+https://github.com/rust-lang/crates.io-index"
670−checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
671−dependencies = [
672− "rand_core",
673−]
674−
675−[[package]]
676−name = "redox_syscall"
677−version = "0.1.57"
678−source = "registry+https://github.com/rust-lang/crates.io-index"
679−checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
680−
681−[[package]]
682−name = "reqwest"
683−version = "0.10.9"
684−source = "registry+https://github.com/rust-lang/crates.io-index"
685−checksum = "fb15d6255c792356a0f578d8a645c677904dc02e862bebe2ecc18e0c01b9a0ce"
686−dependencies = [
687− "base64 0.13.0",
688− "bytes",
689− "encoding_rs",
690− "futures-core",
691− "futures-util",
692− "http",
693− "http-body",
694− "hyper",
695− "hyper-rustls",
696− "ipnet",
697− "js-sys",
698− "lazy_static",
699− "log",
700− "mime",
701− "mime_guess",
702− "percent-encoding",
703− "pin-project-lite 0.2.0",
704− "rustls",
705− "serde",
706− "serde_json",
707− "serde_urlencoded",
708− "tokio",
709− "tokio-rustls",
710− "url",
711− "wasm-bindgen",
712− "wasm-bindgen-futures",
713− "wasm-bindgen-test",
714− "web-sys",
715− "webpki-roots",
716− "winreg",
717−]
718−
719−[[package]]
720−name = "ring"
721−version = "0.16.19"
722−source = "registry+https://github.com/rust-lang/crates.io-index"
723−checksum = "024a1e66fea74c66c66624ee5622a7ff0e4b73a13b4f5c326ddb50c708944226"
724−dependencies = [
725− "cc",
726− "libc",
727− "once_cell",
728− "spin",
729− "untrusted",
730− "web-sys",
731− "winapi 0.3.9",
732−]
733−
734−[[package]]
735−name = "rustls"
736−version = "0.18.1"
737−source = "registry+https://github.com/rust-lang/crates.io-index"
738−checksum = "5d1126dcf58e93cee7d098dbda643b5f92ed724f1f6a63007c1116eed6700c81"
739−dependencies = [
740− "base64 0.12.3",
741− "log",
742− "ring",
743− "sct",
744− "webpki",
745−]
746−
747−[[package]]
748−name = "ryu"
749−version = "1.0.5"
750−source = "registry+https://github.com/rust-lang/crates.io-index"
751−checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
752−
753−[[package]]
754−name = "scoped-tls"
755−version = "1.0.0"
756−source = "registry+https://github.com/rust-lang/crates.io-index"
757−checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
758−
759−[[package]]
760−name = "sct"
761−version = "0.6.0"
762−source = "registry+https://github.com/rust-lang/crates.io-index"
763−checksum = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c"
764−dependencies = [
765− "ring",
766− "untrusted",
767−]
768−
769−[[package]]
770−name = "serde"
771−version = "1.0.117"
772−source = "registry+https://github.com/rust-lang/crates.io-index"
773−checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a"
774−
775−[[package]]
776−name = "serde_derive"
777−version = "1.0.117"
778−source = "registry+https://github.com/rust-lang/crates.io-index"
779−checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e"
780−dependencies = [
781− "proc-macro2",
782− "quote",
783− "syn",
784−]
785−
786−[[package]]
787−name = "serde_json"
788−version = "1.0.60"
789−source = "registry+https://github.com/rust-lang/crates.io-index"
790−checksum = "1500e84d27fe482ed1dc791a56eddc2f230046a040fa908c08bda1d9fb615779"
791−dependencies = [
792− "itoa",
793− "ryu",
794− "serde",
795−]
796−
797−[[package]]
798−name = "serde_urlencoded"
799−version = "0.7.0"
800−source = "registry+https://github.com/rust-lang/crates.io-index"
801−checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9"
802−dependencies = [
803− "form_urlencoded",
804− "itoa",
805− "ryu",
806− "serde",
807−]
808−
809−[[package]]
810−name = "signal-hook-registry"
811−version = "1.2.2"
812−source = "registry+https://github.com/rust-lang/crates.io-index"
813−checksum = "ce32ea0c6c56d5eacaeb814fbed9960547021d3edd010ded1425f180536b20ab"
814−dependencies = [
815− "libc",
816−]
817−
818−[[package]]
819−name = "slab"
820−version = "0.4.2"
821−source = "registry+https://github.com/rust-lang/crates.io-index"
822−checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
823−
824−[[package]]
825−name = "socket2"
826−version = "0.3.17"
827−source = "registry+https://github.com/rust-lang/crates.io-index"
828−checksum = "2c29947abdee2a218277abeca306f25789c938e500ea5a9d4b12a5a504466902"
829−dependencies = [
830− "cfg-if 1.0.0",
831− "libc",
832− "redox_syscall",
833− "winapi 0.3.9",
834−]
835−
836−[[package]]
837−name = "spin"
838−version = "0.5.2"
839−source = "registry+https://github.com/rust-lang/crates.io-index"
840−checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
841−
842−[[package]]
843−name = "strsim"
844−version = "0.8.0"
845−source = "registry+https://github.com/rust-lang/crates.io-index"
846−checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
847−
848−[[package]]
849−name = "syn"
850−version = "1.0.53"
851−source = "registry+https://github.com/rust-lang/crates.io-index"
852−checksum = "8833e20724c24de12bbaba5ad230ea61c3eafb05b881c7c9d3cfe8638b187e68"
853−dependencies = [
854− "proc-macro2",
855− "quote",
856− "unicode-xid",
857−]
858−
859−[[package]]
860−name = "textwrap"
861−version = "0.11.0"
862−source = "registry+https://github.com/rust-lang/crates.io-index"
863−checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
864−dependencies = [
865− "unicode-width",
866−]
867−
868−[[package]]
869−name = "tinyvec"
870−version = "1.1.0"
871−source = "registry+https://github.com/rust-lang/crates.io-index"
872−checksum = "ccf8dbc19eb42fba10e8feaaec282fb50e2c14b2726d6301dbfeed0f73306a6f"
873−dependencies = [
874− "tinyvec_macros",
875−]
876−
877−[[package]]
878−name = "tinyvec_macros"
879−version = "0.1.0"
880−source = "registry+https://github.com/rust-lang/crates.io-index"
881−checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
882−
883−[[package]]
884−name = "tokio"
885−version = "0.2.23"
886−source = "registry+https://github.com/rust-lang/crates.io-index"
887−checksum = "a6d7ad61edd59bfcc7e80dababf0f4aed2e6d5e0ba1659356ae889752dfc12ff"
888−dependencies = [
889− "bytes",
890− "fnv",
891− "futures-core",
892− "iovec",
893− "lazy_static",
894− "libc",
895− "memchr",
896− "mio",
897− "mio-named-pipes",
898− "mio-uds",
899− "num_cpus",
900− "pin-project-lite 0.1.11",
901− "signal-hook-registry",
902− "slab",
903− "tokio-macros",
904− "winapi 0.3.9",
905−]
906−
907−[[package]]
908−name = "tokio-macros"
909−version = "0.2.6"
910−source = "registry+https://github.com/rust-lang/crates.io-index"
911−checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a"
912−dependencies = [
913− "proc-macro2",
914− "quote",
915− "syn",
916−]
917−
918−[[package]]
919−name = "tokio-rustls"
920−version = "0.14.1"
921−source = "registry+https://github.com/rust-lang/crates.io-index"
922−checksum = "e12831b255bcfa39dc0436b01e19fea231a37db570686c06ee72c423479f889a"
923−dependencies = [
924− "futures-core",
925− "rustls",
926− "tokio",
927− "webpki",
928−]
929−
930−[[package]]
931−name = "tokio-util"
932−version = "0.3.1"
933−source = "registry+https://github.com/rust-lang/crates.io-index"
934−checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499"
935−dependencies = [
936− "bytes",
937− "futures-core",
938− "futures-sink",
939− "log",
940− "pin-project-lite 0.1.11",
941− "tokio",
942−]
943−
944−[[package]]
945−name = "tower-service"
946−version = "0.3.0"
947−source = "registry+https://github.com/rust-lang/crates.io-index"
948−checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860"
949−
950−[[package]]
951−name = "tracing"
952−version = "0.1.22"
953−source = "registry+https://github.com/rust-lang/crates.io-index"
954−checksum = "9f47026cdc4080c07e49b37087de021820269d996f581aac150ef9e5583eefe3"
955−dependencies = [
956− "cfg-if 1.0.0",
957− "log",
958− "pin-project-lite 0.2.0",
959− "tracing-core",
960−]
961−
962−[[package]]
963−name = "tracing-core"
964−version = "0.1.17"
965−source = "registry+https://github.com/rust-lang/crates.io-index"
966−checksum = "f50de3927f93d202783f4513cda820ab47ef17f624b03c096e86ef00c67e6b5f"
967−dependencies = [
968− "lazy_static",
969−]
970−
971−[[package]]
972−name = "tracing-futures"
973−version = "0.2.4"
974−source = "registry+https://github.com/rust-lang/crates.io-index"
975−checksum = "ab7bb6f14721aa00656086e9335d363c5c8747bae02ebe32ea2c7dece5689b4c"
976−dependencies = [
977− "pin-project 0.4.27",
978− "tracing",
979−]
980−
981−[[package]]
982−name = "try-lock"
983−version = "0.2.3"
984−source = "registry+https://github.com/rust-lang/crates.io-index"
985−checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
986−
987−[[package]]
988−name = "unicase"
989−version = "2.6.0"
990−source = "registry+https://github.com/rust-lang/crates.io-index"
991−checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
992−dependencies = [
993− "version_check",
994−]
995−
996−[[package]]
997−name = "unicode-bidi"
998−version = "0.3.4"
999−source = "registry+https://github.com/rust-lang/crates.io-index"
1000−checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
1001−dependencies = [
1002− "matches",
1003−]
1004−
1005−[[package]]
1006−name = "unicode-normalization"
1007−version = "0.1.16"
1008−source = "registry+https://github.com/rust-lang/crates.io-index"
1009−checksum = "a13e63ab62dbe32aeee58d1c5408d35c36c392bba5d9d3142287219721afe606"
1010−dependencies = [
1011− "tinyvec",
1012−]
1013−
1014−[[package]]
1015−name = "unicode-width"
1016−version = "0.1.8"
1017−source = "registry+https://github.com/rust-lang/crates.io-index"
1018−checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
1019−
1020−[[package]]
1021−name = "unicode-xid"
1022−version = "0.2.1"
1023−source = "registry+https://github.com/rust-lang/crates.io-index"
1024−checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
1025−
1026−[[package]]
1027−name = "untrusted"
1028−version = "0.7.1"
1029−source = "registry+https://github.com/rust-lang/crates.io-index"
1030−checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
1031−
1032−[[package]]
1033−name = "url"
1034−version = "2.2.0"
1035−source = "registry+https://github.com/rust-lang/crates.io-index"
1036−checksum = "5909f2b0817350449ed73e8bcd81c8c3c8d9a7a5d8acba4b27db277f1868976e"
1037−dependencies = [
1038− "form_urlencoded",
1039− "idna",
1040− "matches",
1041− "percent-encoding",
1042−]
1043−
1044−[[package]]
1045−name = "vec_map"
1046−version = "0.8.2"
1047−source = "registry+https://github.com/rust-lang/crates.io-index"
1048−checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
1049−
1050−[[package]]
1051−name = "version_check"
1052−version = "0.9.2"
1053−source = "registry+https://github.com/rust-lang/crates.io-index"
1054−checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
1055−
1056−[[package]]
1057−name = "want"
1058−version = "0.3.0"
1059−source = "registry+https://github.com/rust-lang/crates.io-index"
1060−checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
1061−dependencies = [
1062− "log",
1063− "try-lock",
1064−]
1065−
1066−[[package]]
1067−name = "wasi"
1068−version = "0.9.0+wasi-snapshot-preview1"
1069−source = "registry+https://github.com/rust-lang/crates.io-index"
1070−checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
1071−
1072−[[package]]
1073−name = "wasm-bindgen"
1074−version = "0.2.69"
1075−source = "registry+https://github.com/rust-lang/crates.io-index"
1076−checksum = "3cd364751395ca0f68cafb17666eee36b63077fb5ecd972bbcd74c90c4bf736e"
1077−dependencies = [
1078− "cfg-if 1.0.0",
1079− "serde",
1080− "serde_json",
1081− "wasm-bindgen-macro",
1082−]
1083−
1084−[[package]]
1085−name = "wasm-bindgen-backend"
1086−version = "0.2.69"
1087−source = "registry+https://github.com/rust-lang/crates.io-index"
1088−checksum = "1114f89ab1f4106e5b55e688b828c0ab0ea593a1ea7c094b141b14cbaaec2d62"
1089−dependencies = [
1090− "bumpalo",
1091− "lazy_static",
1092− "log",
1093− "proc-macro2",
1094− "quote",
1095− "syn",
1096− "wasm-bindgen-shared",
1097−]
1098−
1099−[[package]]
1100−name = "wasm-bindgen-futures"
1101−version = "0.4.19"
1102−source = "registry+https://github.com/rust-lang/crates.io-index"
1103−checksum = "1fe9756085a84584ee9457a002b7cdfe0bfff169f45d2591d8be1345a6780e35"
1104−dependencies = [
1105− "cfg-if 1.0.0",
1106− "js-sys",
1107− "wasm-bindgen",
1108− "web-sys",
1109−]
1110−
1111−[[package]]
1112−name = "wasm-bindgen-macro"
1113−version = "0.2.69"
1114−source = "registry+https://github.com/rust-lang/crates.io-index"
1115−checksum = "7a6ac8995ead1f084a8dea1e65f194d0973800c7f571f6edd70adf06ecf77084"
1116−dependencies = [
1117− "quote",
1118− "wasm-bindgen-macro-support",
1119−]
1120−
1121−[[package]]
1122−name = "wasm-bindgen-macro-support"
1123−version = "0.2.69"
1124−source = "registry+https://github.com/rust-lang/crates.io-index"
1125−checksum = "b5a48c72f299d80557c7c62e37e7225369ecc0c963964059509fbafe917c7549"
1126−dependencies = [
1127− "proc-macro2",
1128− "quote",
1129− "syn",
1130− "wasm-bindgen-backend",
1131− "wasm-bindgen-shared",
1132−]
1133−
1134−[[package]]
1135−name = "wasm-bindgen-shared"
1136−version = "0.2.69"
1137−source = "registry+https://github.com/rust-lang/crates.io-index"
1138−checksum = "7e7811dd7f9398f14cc76efd356f98f03aa30419dea46aa810d71e819fc97158"
1139−
1140−[[package]]
1141−name = "wasm-bindgen-test"
1142−version = "0.3.19"
1143−source = "registry+https://github.com/rust-lang/crates.io-index"
1144−checksum = "0355fa0c1f9b792a09b6dcb6a8be24d51e71e6d74972f9eb4a44c4c004d24a25"
1145−dependencies = [
1146− "console_error_panic_hook",
1147− "js-sys",
1148− "scoped-tls",
1149− "wasm-bindgen",
1150− "wasm-bindgen-futures",
1151− "wasm-bindgen-test-macro",
1152−]
1153−
1154−[[package]]
1155−name = "wasm-bindgen-test-macro"
1156−version = "0.3.19"
1157−source = "registry+https://github.com/rust-lang/crates.io-index"
1158−checksum = "27e07b46b98024c2ba2f9e83a10c2ef0515f057f2da299c1762a2017de80438b"
1159−dependencies = [
1160− "proc-macro2",
1161− "quote",
1162−]
1163−
1164−[[package]]
1165−name = "web-sys"
1166−version = "0.3.46"
1167−source = "registry+https://github.com/rust-lang/crates.io-index"
1168−checksum = "222b1ef9334f92a21d3fb53dc3fd80f30836959a90f9274a626d7e06315ba3c3"
1169−dependencies = [
1170− "js-sys",
1171− "wasm-bindgen",
1172−]
1173−
1174−[[package]]
1175−name = "webpki"
1176−version = "0.21.4"
1177−source = "registry+https://github.com/rust-lang/crates.io-index"
1178−checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea"
1179−dependencies = [
1180− "ring",
1181− "untrusted",
1182−]
1183−
1184−[[package]]
1185−name = "webpki-roots"
1186−version = "0.20.0"
1187−source = "registry+https://github.com/rust-lang/crates.io-index"
1188−checksum = "0f20dea7535251981a9670857150d571846545088359b28e4951d350bdaf179f"
1189−dependencies = [
1190− "webpki",
1191−]
1192−
1193−[[package]]
1194−name = "winapi"
1195−version = "0.2.8"
1196−source = "registry+https://github.com/rust-lang/crates.io-index"
1197−checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
1198−
1199−[[package]]
1200−name = "winapi"
1201−version = "0.3.9"
1202−source = "registry+https://github.com/rust-lang/crates.io-index"
1203−checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
1204−dependencies = [
1205− "winapi-i686-pc-windows-gnu",
1206− "winapi-x86_64-pc-windows-gnu",
1207−]
1208−
1209−[[package]]
1210−name = "winapi-build"
1211−version = "0.1.1"
1212−source = "registry+https://github.com/rust-lang/crates.io-index"
1213−checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
1214−
1215−[[package]]
1216−name = "winapi-i686-pc-windows-gnu"
1217−version = "0.4.0"
1218−source = "registry+https://github.com/rust-lang/crates.io-index"
1219−checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
1220−
1221−[[package]]
1222−name = "winapi-x86_64-pc-windows-gnu"
1223−version = "0.4.0"
1224−source = "registry+https://github.com/rust-lang/crates.io-index"
1225−checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
1226−
1227−[[package]]
1228−name = "winreg"
1229−version = "0.7.0"
1230−source = "registry+https://github.com/rust-lang/crates.io-index"
1231−checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69"
1232−dependencies = [
1233− "winapi 0.3.9",
1234−]
1235−
1236−[[package]]
1237−name = "ws2_32-sys"
1238−version = "0.2.1"
1239−source = "registry+https://github.com/rust-lang/crates.io-index"
1240−checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
1241−dependencies = [
1242− "winapi 0.2.8",
1243− "winapi-build",
1244−]
examples/helm-based-control-scripts/Cargo.tomldeleted−46
@@ -1,46 +0,0 @@
1−[package]
2−name = "helm-based-control-scripts"
3−version = "0.1.0"
4−authors = ["Typeable LLC <octopod@typeable.io>"]
5−edition = "2018"
6−
7−[dependencies]
8−clap = "2.33.3"
9−rand = "0.7.3"
10−serde = "1.0.117"
11−serde_derive = "1.0.117"
12−serde_json = "1.0.60"
13−tokio = { version = "0.2.22", default_features = false, features = ["full"] }
14−reqwest = { version = "0.10.9", default_features = false, features = ["json", "rustls-tls"] }
15−
16−[[bin]]
17−name = "create"
18−path = "src/bin/create.rs"
19−
20−[[bin]]
21−name = "archive"
22−path = "src/bin/archive.rs"
23−
24−[[bin]]
25−name = "check"
26−path = "src/bin/check.rs"
27−
28−[[bin]]
29−name = "cleanup"
30−path = "src/bin/cleanup.rs"
31−
32−[[bin]]
33−name = "archive_check"
34−path = "src/bin/archive_check.rs"
35−
36−[[bin]]
37−name = "tag_check"
38−path = "src/bin/tag_check.rs"
39−
40−[[bin]]
41−name = "init"
42−path = "src/bin/init.rs"
43−
44−[[bin]]
45−name = "info"
46−path = "src/bin/info.rs"
examples/helm-based-control-scripts/README.mddeleted−9
@@ -1,9 +0,0 @@
1−# helm-based-control-scripts
2−
3−An Example of Helm-based control scripts.
4−
5−## Build Docker image
6−
7−```bash
8−docker build -f docker/Dockerfile -t typeable/octopod-helm-example:1.0 .
9−```
examples/helm-based-control-scripts/docker/Dockerfiledeleted−29
@@ -1,29 +0,0 @@
1−FROM ekidd/rust-musl-builder:1.46.0 as builder
2−
3−RUN sudo mkdir /app && \
4− sudo chown -R rust:rust /app
5−WORKDIR /app
6−RUN USER=root cargo new helm-based-control-scripts
7−COPY Cargo.toml /app/helm-based-control-scripts/
8−COPY Cargo.lock /app/helm-based-control-scripts/
9−COPY src /app/helm-based-control-scripts/src
10−WORKDIR /app/helm-based-control-scripts
11−RUN cargo build --release
12−
13−FROM typeable/kube-things as base-utils
14−
15−FROM busybox
16−
17−COPY --from=builder /app/helm-based-control-scripts/target/x86_64-unknown-linux-musl/release/create /utils/create
18−COPY --from=builder /app/helm-based-control-scripts/target/x86_64-unknown-linux-musl/release/create /utils/update
19−COPY --from=builder /app/helm-based-control-scripts/target/x86_64-unknown-linux-musl/release/archive /utils/archive
20−COPY --from=builder /app/helm-based-control-scripts/target/x86_64-unknown-linux-musl/release/check /utils/check
21−COPY --from=builder /app/helm-based-control-scripts/target/x86_64-unknown-linux-musl/release/cleanup /utils/cleanup
22−COPY --from=builder /app/helm-based-control-scripts/target/x86_64-unknown-linux-musl/release/archive_check /utils/archive_check
23−COPY --from=builder /app/helm-based-control-scripts/target/x86_64-unknown-linux-musl/release/tag_check /utils/tag_check
24−COPY --from=builder /app/helm-based-control-scripts/target/x86_64-unknown-linux-musl/release/init /utils/init
25−COPY --from=builder /app/helm-based-control-scripts/target/x86_64-unknown-linux-musl/release/info /utils/info
26−
27−COPY --from=base-utils /utils/kubectl /utils/kubectl
28−COPY --from=base-utils /utils/helm2 /utils/helm
29−COPY --from=base-utils /utils/kubedog /utils/kubedog
examples/helm-based-control-scripts/src/bin/archive.rsdeleted−59
@@ -1,59 +0,0 @@
1−use clap::{App, Arg};
2−use std::process::{exit, Command};
3−
4−fn main() -> std::io::Result<()> {
5− let matches = App::new("archive")
6− .version("0.1")
7− .arg(
8− Arg::with_name("project-name")
9− .long("project-name")
10− .short("p")
11− .required(true)
12− .takes_value(true),
13− )
14− .arg(
15− Arg::with_name("base-domain")
16− .long("base-domain")
17− .short("d")
18− .required(true)
19− .takes_value(true),
20− )
21− .arg(
22− Arg::with_name("namespace")
23− .long("namespace")
24− .short("s")
25− .required(true)
26− .takes_value(true),
27− )
28− .arg(
29− Arg::with_name("name")
30− .long("name")
31− .short("n")
32− .required(true)
33− .takes_value(true),
34− )
35− .get_matches();
36−
37− let _project_name = matches
38− .value_of("project-name")
39− .expect("could not get project-name");
40− let _base_domain = matches
41− .value_of("base-domain")
42− .expect("could not get base-domain");
43− let _namespace = matches
44− .value_of("namespace")
45− .expect("could not get namepace");
46− let name = matches.value_of("name").expect("could not get name");
47−
48− let output = Command::new("helm")
49− .args(&["delete", &format!("app-{}", name), "--purge"])
50− .output()
51− .expect("could not delete app");
52− let success = output.status.success();
53−
54− if !success {
55− exit(1)
56− }
57−
58− Ok(())
59−}
examples/helm-based-control-scripts/src/bin/archive_check.rsdeleted−59
@@ -1,59 +0,0 @@
1−use clap::{App, Arg};
2−use std::process::{exit, Command};
3−
4−fn main() -> std::io::Result<()> {
5− let matches = App::new("archive_check")
6− .version("0.1")
7− .arg(
8− Arg::with_name("project-name")
9− .long("project-name")
10− .short("p")
11− .required(true)
12− .takes_value(true),
13− )
14− .arg(
15− Arg::with_name("base-domain")
16− .long("base-domain")
17− .short("d")
18− .required(true)
19− .takes_value(true),
20− )
21− .arg(
22− Arg::with_name("namespace")
23− .long("namespace")
24− .short("s")
25− .required(true)
26− .takes_value(true),
27− )
28− .arg(
29− Arg::with_name("name")
30− .long("name")
31− .short("n")
32− .required(true)
33− .takes_value(true),
34− )
35− .get_matches();
36−
37− let _project_name = matches
38− .value_of("project-name")
39− .expect("could not get project-name");
40− let _base_domain = matches
41− .value_of("base-domain")
42− .expect("could not get base-domain");
43− let _namespace = matches
44− .value_of("namespace")
45− .expect("could not get namepace");
46− let name = matches.value_of("name").expect("could not get name");
47−
48− let output = Command::new("helm")
49− .args(&["status", name])
50− .output()
51− .expect("could not get status");
52− let success = output.status.success();
53−
54− if success {
55− exit(1)
56− }
57−
58− Ok(())
59−}
examples/helm-based-control-scripts/src/bin/check.rsdeleted−78
@@ -1,78 +0,0 @@
1−use clap::{App, Arg};
2−use serde_json::json;
3−use std::io::Write;
4−use std::process::{exit, Command, Stdio};
5−
6−const KUBEDOG_TIMEOUT: usize = 3;
7−
8−fn main() -> std::io::Result<()> {
9− let matches = App::new("check")
10− .version("0.1")
11− .arg(
12− Arg::with_name("project-name")
13− .long("project-name")
14− .short("p")
15− .required(true)
16− .takes_value(true),
17− )
18− .arg(
19− Arg::with_name("base-domain")
20− .long("base-domain")
21− .short("d")
22− .required(true)
23− .takes_value(true),
24− )
25− .arg(
26− Arg::with_name("namespace")
27− .long("namespace")
28− .short("s")
29− .required(true)
30− .takes_value(true),
31− )
32− .arg(
33− Arg::with_name("name")
34− .long("name")
35− .short("n")
36− .required(true)
37− .takes_value(true),
38− )
39− .get_matches();
40−
41− let _project_name = matches
42− .value_of("project-name")
43− .expect("could not get project-name");
44− let _base_domain = matches
45− .value_of("base-domain")
46− .expect("could not get base-domain");
47− let namespace = matches
48− .value_of("namespace")
49− .expect("could not get namepace");
50− let name = matches.value_of("name").expect("could not get name");
51−
52− let kubedog_stdin = json!({
53− "Deployments": [{"ResourceName": format!("app-{}", name), "Namespace": namespace}]
54− })
55− .to_string();
56−
57− let mut child = Command::new("kubedog")
58− .args(&["multitrack", "-t", &KUBEDOG_TIMEOUT.to_string()])
59− .stdin(Stdio::piped())
60− .spawn()
61− .expect("failed to call kubedog");
62−
63− {
64− let stdin = child.stdin.as_mut().expect("failed to open stdin");
65− stdin
66− .write_all(kubedog_stdin.as_bytes())
67− .expect("failed to write to stdin");
68− }
69−
70− let output = child.wait_with_output().expect("failed to read stdout");
71− let success = output.status.success();
72−
73− if !success {
74− exit(1)
75− }
76−
77− Ok(())
78−}
examples/helm-based-control-scripts/src/bin/cleanup.rsdeleted−50
@@ -1,50 +0,0 @@
1−use clap::{App, Arg};
2−
3−fn main() -> std::io::Result<()> {
4− let matches = App::new("cleanup")
5− .version("0.1")
6− .arg(
7− Arg::with_name("project-name")
8− .long("project-name")
9− .short("p")
10− .required(true)
11− .takes_value(true),
12− )
13− .arg(
14− Arg::with_name("base-domain")
15− .long("base-domain")
16− .short("d")
17− .required(true)
18− .takes_value(true),
19− )
20− .arg(
21− Arg::with_name("namespace")
22− .long("namespace")
23− .short("s")
24− .required(true)
25− .takes_value(true),
26− )
27− .arg(
28− Arg::with_name("name")
29− .long("name")
30− .short("n")
31− .required(true)
32− .takes_value(true),
33− )
34− .get_matches();
35−
36− let _project_name = matches
37− .value_of("project-name")
38− .expect("could not get project-name");
39− let _base_domain = matches
40− .value_of("base-domain")
41− .expect("could not get base-domain");
42− let _namespace = matches
43− .value_of("namespace")
44− .expect("could not get namepace");
45− let _name = matches.value_of("name").expect("could not get name");
46−
47− // nop
48−
49− Ok(())
50−}
examples/helm-based-control-scripts/src/bin/create.rsdeleted−237
@@ -1,237 +0,0 @@
1−use clap::{App, Arg};
2−use rand::{
3− distributions::{Alphanumeric, Distribution},
4− thread_rng,
5−};
6−use std::convert::TryFrom;
7−use std::convert::TryInto;
8−use std::fs;
9−use std::path::Path;
10−use std::path::PathBuf;
11−use std::process::{exit, Command};
12−
13−static REGISTRY: &str = "typeable";
14−static IMAGE: &str = "octopod-web-app-example";
15−static GIT_REPOSITORY: &str = "https://github.com/typeable/octopod.git";
16−
17−struct TmpDirGuard(PathBuf);
18−
19−impl TmpDirGuard {
20− pub fn new(tmp_dir: &PathBuf) -> Self {
21− TmpDirGuard(tmp_dir.clone())
22− }
23−}
24−
25−impl Drop for TmpDirGuard {
26− fn drop(&mut self) {
27− match fs::remove_dir_all(&self.0) {
28− Ok(_) => (),
29− Err(err) => eprintln!("remove_dir_all error: {:?}", err),
30− };
31− }
32−}
33−
34−#[derive(Debug, Clone)]
35−struct Override {
36− pub key: String,
37− pub value: String,
38−}
39−
40−impl TryFrom<&str> for Override {
41− type Error = &'static str;
42− fn try_from(s: &str) -> Result<Self, Self::Error> {
43− let parts = s.split('=').collect::<Vec<_>>();
44− if parts.len() == 2 {
45− Ok(Override {
46− key: parts[0].to_string(),
47− value: parts[1].to_string(),
48− })
49− } else {
50− Err("Malformed environment key-value pair, should be similar to FOO=bar")
51− }
52− }
53−}
54−
55−impl ToString for Override {
56− fn to_string(&self) -> String {
57− format!("{}={}", self.key, self.value)
58− }
59−}
60−
61−fn main() -> std::io::Result<()> {
62− let matches = App::new("create")
63− .version("0.1")
64− .arg(
65− Arg::with_name("project-name")
66− .long("project-name")
67− .short("p")
68− .required(true)
69− .takes_value(true),
70− )
71− .arg(
72− Arg::with_name("base-domain")
73− .long("base-domain")
74− .short("d")
75− .required(true)
76− .takes_value(true),
77− )
78− .arg(
79− Arg::with_name("namespace")
80− .long("namespace")
81− .short("s")
82− .required(true)
83− .takes_value(true),
84− )
85− .arg(
86− Arg::with_name("name")
87− .long("name")
88− .short("n")
89− .required(true)
90− .takes_value(true),
91− )
92− .arg(
93− Arg::with_name("tag")
94− .long("tag")
95− .short("t")
96− .required(true)
97− .takes_value(true),
98− )
99− .arg(
100− Arg::with_name("app-env-override")
101− .long("app-env-override")
102− .short("e")
103− .required(false)
104− .multiple(true)
105− .takes_value(true),
106− )
107− .arg(
108− Arg::with_name("deployment-override")
109− .long("deployment-override")
110− .short("o")
111− .required(false)
112− .multiple(true)
113− .takes_value(true),
114− )
115− .get_matches();
116−
117− let _project_name = matches
118− .value_of("project-name")
119− .expect("could not get project-name");
120− let base_domain = matches
121− .value_of("base-domain")
122− .expect("could not get base-domain");
123− let namespace = matches
124− .value_of("namespace")
125− .expect("could not get namepace");
126− let name = matches.value_of("name").expect("could not get name");
127− let tag = matches.value_of("tag").expect("could not get tag");
128− let app_env_overrides = matches
129− .values_of("app-env-override")
130− .unwrap_or_else(Default::default)
131− .map(|e| e.try_into().expect("could not get valid key=value"))
132− .collect::<Vec<Override>>();
133− let deployment_overrides = matches
134− .values_of("deployment-override")
135− .unwrap_or_else(Default::default)
136− .map(|e| e.try_into().expect("could not get valid key=value"))
137− .collect::<Vec<Override>>();
138−
139− let tmp_dir = tmp_dir();
140− let work_dir = Path::new("/tmp").join(tmp_dir);
141−
142− let _guard = TmpDirGuard::new(&work_dir);
143− fs::create_dir(&work_dir)?;
144−
145− let success = clone_and_prepare_repo(&work_dir);
146−
147− let output = Command::new("helm")
148− .args(command_args(
149− base_domain,
150− namespace,
151− name,
152− tag,
153− app_env_overrides,
154− deployment_overrides,
155− ))
156− .current_dir(&work_dir)
157− .output()
158− .expect("could not create app");
159− let success2 = output.status.success();
160−
161− if !(success && success2) {
162− exit(1)
163− }
164−
165− Ok(())
166−}
167−
168−fn tmp_dir() -> String {
169− const LENGTH: usize = 10;
170−
171− let rng = thread_rng();
172− let random_string: String = Alphanumeric.sample_iter(rng).take(LENGTH).collect();
173− format!("octopod-{}", random_string)
174−}
175−
176−fn clone_and_prepare_repo(work_dir: &PathBuf) -> bool {
177− let output = Command::new("git")
178− .args(&["clone", "--recursive", "--depth=1", GIT_REPOSITORY, "."])
179− .current_dir(work_dir)
180− .output()
181− .expect("could not clone repo");
182− output.status.success()
183−}
184−
185−fn command_args(
186− domain: &str,
187− namespace: &str,
188− name: &str,
189− tag: &str,
190− app_env_overrides: Vec<Override>,
191− deployment_overrides: Vec<Override>,
192−) -> Vec<String> {
193− let mut args = vec![
194− "upgrade",
195− "--install",
196− "--namespace",
197− namespace,
198− &format!("app-{}", name),
199− "examples/web-app/charts/web-app",
200− "--set",
201− &format!("image_prefix={}", REGISTRY),
202− "--set",
203− &format!("image={}", IMAGE),
204− "--set",
205− &format!("image_tag={}", tag),
206− "--set",
207− &format!("domain={}.{}", name, domain),
208− "--wait",
209− "--timeout",
210− "300",
211− "--debug",
212− ]
213− .iter()
214− .map(ToString::to_string)
215− .collect::<Vec<_>>();
216−
217− let mut app_args = app_env_overrides
218− .into_iter()
219− .map(|e| {
220− vec![
221− "--set".to_string(),
222− format!("env.{}", e.to_string()),
223− ]
224− })
225− .flatten()
226− .collect::<Vec<_>>();
227− args.append(&mut app_args);
228−
229− let mut deployment_args = deployment_overrides
230− .into_iter()
231− .map(|e| vec!["--set".to_string(), e.to_string()])
232− .flatten()
233− .collect::<Vec<_>>();
234− args.append(&mut deployment_args);
235−
236− args
237−}
examples/helm-based-control-scripts/src/bin/info.rsdeleted−52
@@ -1,52 +0,0 @@
1−use clap::{App, Arg};
2−
3−fn main() -> std::io::Result<()> {
4− let matches = App::new("cleanup")
5− .version("0.1")
6− .arg(
7− Arg::with_name("project-name")
8− .long("project-name")
9− .short("p")
10− .required(true)
11− .takes_value(true),
12− )
13− .arg(
14− Arg::with_name("base-domain")
15− .long("base-domain")
16− .short("d")
17− .required(true)
18− .takes_value(true),
19− )
20− .arg(
21− Arg::with_name("namespace")
22− .long("namespace")
23− .short("s")
24− .required(true)
25− .takes_value(true),
26− )
27− .arg(
28− Arg::with_name("name")
29− .long("name")
30− .short("n")
31− .required(true)
32− .takes_value(true),
33− )
34− .get_matches();
35−
36− let _project_name = matches
37− .value_of("project-name")
38− .expect("could not get project-name");
39− let base_domain = matches
40− .value_of("base-domain")
41− .expect("could not get base-domain");
42− let _namespace = matches
43− .value_of("namespace")
44− .expect("could not get namepace");
45− let name = matches.value_of("name").expect("could not get name");
46−
47− [("app", format!("https://{}.{}", name, base_domain))]
48− .iter()
49− .for_each(|(key, value)| println!("{},{}", key, value));
50−
51− Ok(())
52−}
examples/helm-based-control-scripts/src/bin/init.rsdeleted−9
@@ -1,9 +0,0 @@
1−use std::env;
2−
3−fn main() -> std::io::Result<()> {
4− let _home = env::var("HOME").expect("could not get $HOME");
5−
6− // nop
7−
8− Ok(())
9−}
examples/helm-based-control-scripts/src/bin/tag_check.rsdeleted−91
@@ -1,91 +0,0 @@
1−use clap::{App, Arg};
2−use serde_derive::Deserialize;
3−use std::process::exit;
4−
5−static REGISTRY: &str = "typeable";
6−static REPOSITORY: &str = "octopod-web-app-example";
7−
8−#[derive(Debug, Deserialize)]
9−struct Resp {
10− results: Vec<Tag>,
11−}
12−
13−#[derive(Debug, Deserialize)]
14−struct Tag {
15− name: String,
16−}
17−
18−async fn do_request() -> reqwest::Result<Resp> {
19− let url = format!(
20− "https://hub.docker.com/v2/repositories/{}/{}/tags",
21− REGISTRY, REPOSITORY
22− );
23− let body = reqwest::get(&url).await?.json::<Resp>().await?;
24− Ok(body)
25−}
26−
27−#[tokio::main]
28−async fn main() -> std::io::Result<()> {
29− let matches = App::new("tag_check")
30− .version("0.1")
31− .arg(
32− Arg::with_name("project-name")
33− .long("project-name")
34− .short("p")
35− .required(true)
36− .takes_value(true),
37− )
38− .arg(
39− Arg::with_name("base-domain")
40− .long("base-domain")
41− .short("d")
42− .required(true)
43− .takes_value(true),
44− )
45− .arg(
46− Arg::with_name("namespace")
47− .long("namespace")
48− .short("s")
49− .required(true)
50− .takes_value(true),
51− )
52− .arg(
53− Arg::with_name("name")
54− .long("name")
55− .short("n")
56− .required(true)
57− .takes_value(true),
58− )
59− .arg(
60− Arg::with_name("tag")
61− .long("tag")
62− .short("t")
63− .required(true)
64− .takes_value(true),
65− )
66− .get_matches();
67−
68− let _project_name = matches
69− .value_of("project-name")
70− .expect("could not get project-name");
71− let _base_domain = matches
72− .value_of("base-domain")
73− .expect("could not get base-domain");
74− let _namespace = matches
75− .value_of("namespace")
76− .expect("could not get namepace");
77− let _name = matches.value_of("name").expect("could not get name");
78− let tag = matches.value_of("tag").expect("could not get tag");
79−
80− let mut tag_found = false;
81− match do_request().await {
82− Ok(resp) => tag_found = resp.results.iter().any(|t| t.name == tag),
83− Err(err) => eprintln!("could not get tags, reason: {:?}", err),
84− }
85−
86− if !tag_found {
87− exit(1)
88− }
89−
90− Ok(())
91−}
examples/web-app-v2/.gitignoredeleted−1
@@ -1 +0,0 @@
1−/target
examples/web-app-v2/Cargo.lockdeleted−1935
@@ -1,1935 +0,0 @@
1−# This file is automatically @generated by Cargo.
2−# It is not intended for manual editing.
3−[[package]]
4−name = "actix-codec"
5−version = "0.3.0"
6−source = "registry+https://github.com/rust-lang/crates.io-index"
7−checksum = "78d1833b3838dbe990df0f1f87baf640cf6146e898166afe401839d1b001e570"
8−dependencies = [
9− "bitflags",
10− "bytes",
11− "futures-core",
12− "futures-sink",
13− "log",
14− "pin-project 0.4.27",
15− "tokio",
16− "tokio-util",
17−]
18−
19−[[package]]
20−name = "actix-connect"
21−version = "2.0.0"
22−source = "registry+https://github.com/rust-lang/crates.io-index"
23−checksum = "177837a10863f15ba8d3ae3ec12fac1099099529ed20083a27fdfe247381d0dc"
24−dependencies = [
25− "actix-codec",
26− "actix-rt",
27− "actix-service",
28− "actix-utils",
29− "derive_more",
30− "either",
31− "futures-util",
32− "http",
33− "log",
34− "trust-dns-proto",
35− "trust-dns-resolver",
36−]
37−
38−[[package]]
39−name = "actix-http"
40−version = "2.2.0"
41−source = "registry+https://github.com/rust-lang/crates.io-index"
42−checksum = "452299e87817ae5673910e53c243484ca38be3828db819b6011736fc6982e874"
43−dependencies = [
44− "actix-codec",
45− "actix-connect",
46− "actix-rt",
47− "actix-service",
48− "actix-threadpool",
49− "actix-utils",
50− "base64",
51− "bitflags",
52− "brotli2",
53− "bytes",
54− "cookie",
55− "copyless",
56− "derive_more",
57− "either",
58− "encoding_rs",
59− "flate2",
60− "futures-channel",
61− "futures-core",
62− "futures-util",
63− "fxhash",
64− "h2",
65− "http",
66− "httparse",
67− "indexmap",
68− "itoa",
69− "language-tags",
70− "lazy_static",
71− "log",
72− "mime",
73− "percent-encoding",
74− "pin-project 1.0.2",
75− "rand",
76− "regex",
77− "serde",
78− "serde_json",
79− "serde_urlencoded",
80− "sha-1",
81− "slab",
82− "time",
83−]
84−
85−[[package]]
86−name = "actix-macros"
87−version = "0.1.3"
88−source = "registry+https://github.com/rust-lang/crates.io-index"
89−checksum = "b4ca8ce00b267af8ccebbd647de0d61e0674b6e61185cc7a592ff88772bed655"
90−dependencies = [
91− "quote",
92− "syn",
93−]
94−
95−[[package]]
96−name = "actix-router"
97−version = "0.2.5"
98−source = "registry+https://github.com/rust-lang/crates.io-index"
99−checksum = "bbd1f7dbda1645bf7da33554db60891755f6c01c1b2169e2f4c492098d30c235"
100−dependencies = [
101− "bytestring",
102− "http",
103− "log",
104− "regex",
105− "serde",
106−]
107−
108−[[package]]
109−name = "actix-rt"
110−version = "1.1.1"
111−source = "registry+https://github.com/rust-lang/crates.io-index"
112−checksum = "143fcc2912e0d1de2bcf4e2f720d2a60c28652ab4179685a1ee159e0fb3db227"
113−dependencies = [
114− "actix-macros",
115− "actix-threadpool",
116− "copyless",
117− "futures-channel",
118− "futures-util",
119− "smallvec",
120− "tokio",
121−]
122−
123−[[package]]
124−name = "actix-server"
125−version = "1.0.4"
126−source = "registry+https://github.com/rust-lang/crates.io-index"
127−checksum = "45407e6e672ca24784baa667c5d32ef109ccdd8d5e0b5ebb9ef8a67f4dfb708e"
128−dependencies = [
129− "actix-codec",
130− "actix-rt",
131− "actix-service",
132− "actix-utils",
133− "futures-channel",
134− "futures-util",
135− "log",
136− "mio",
137− "mio-uds",
138− "num_cpus",
139− "slab",
140− "socket2",
141−]
142−
143−[[package]]
144−name = "actix-service"
145−version = "1.0.6"
146−source = "registry+https://github.com/rust-lang/crates.io-index"
147−checksum = "0052435d581b5be835d11f4eb3bce417c8af18d87ddf8ace99f8e67e595882bb"
148−dependencies = [
149− "futures-util",
150− "pin-project 0.4.27",
151−]
152−
153−[[package]]
154−name = "actix-testing"
155−version = "1.0.1"
156−source = "registry+https://github.com/rust-lang/crates.io-index"
157−checksum = "47239ca38799ab74ee6a8a94d1ce857014b2ac36f242f70f3f75a66f691e791c"
158−dependencies = [
159− "actix-macros",
160− "actix-rt",
161− "actix-server",
162− "actix-service",
163− "log",
164− "socket2",
165−]
166−
167−[[package]]
168−name = "actix-threadpool"
169−version = "0.3.3"
170−source = "registry+https://github.com/rust-lang/crates.io-index"
171−checksum = "d209f04d002854b9afd3743032a27b066158817965bf5d036824d19ac2cc0e30"
172−dependencies = [
173− "derive_more",
174− "futures-channel",
175− "lazy_static",
176− "log",
177− "num_cpus",
178− "parking_lot",
179− "threadpool",
180−]
181−
182−[[package]]
183−name = "actix-tls"
184−version = "2.0.0"
185−source = "registry+https://github.com/rust-lang/crates.io-index"
186−checksum = "24789b7d7361cf5503a504ebe1c10806896f61e96eca9a7350e23001aca715fb"
187−dependencies = [
188− "actix-codec",
189− "actix-service",
190− "actix-utils",
191− "futures-util",
192−]
193−
194−[[package]]
195−name = "actix-utils"
196−version = "2.0.0"
197−source = "registry+https://github.com/rust-lang/crates.io-index"
198−checksum = "2e9022dec56632d1d7979e59af14f0597a28a830a9c1c7fec8b2327eb9f16b5a"
199−dependencies = [
200− "actix-codec",
201− "actix-rt",
202− "actix-service",
203− "bitflags",
204− "bytes",
205− "either",
206− "futures-channel",
207− "futures-sink",
208− "futures-util",
209− "log",
210− "pin-project 0.4.27",
211− "slab",
212−]
213−
214−[[package]]
215−name = "actix-web"
216−version = "3.3.2"
217−source = "registry+https://github.com/rust-lang/crates.io-index"
218−checksum = "e641d4a172e7faa0862241a20ff4f1f5ab0ab7c279f00c2d4587b77483477b86"
219−dependencies = [
220− "actix-codec",
221− "actix-http",
222− "actix-macros",
223− "actix-router",
224− "actix-rt",
225− "actix-server",
226− "actix-service",
227− "actix-testing",
228− "actix-threadpool",
229− "actix-tls",
230− "actix-utils",
231− "actix-web-codegen",
232− "awc",
233− "bytes",
234− "derive_more",
235− "encoding_rs",
236− "futures-channel",
237− "futures-core",
238− "futures-util",
239− "fxhash",
240− "log",
241− "mime",
242− "pin-project 1.0.2",
243− "regex",
244− "serde",
245− "serde_json",
246− "serde_urlencoded",
247− "socket2",
248− "time",
249− "tinyvec",
250− "url",
251−]
252−
253−[[package]]
254−name = "actix-web-codegen"
255−version = "0.4.0"
256−source = "registry+https://github.com/rust-lang/crates.io-index"
257−checksum = "ad26f77093333e0e7c6ffe54ebe3582d908a104e448723eec6d43d08b07143fb"
258−dependencies = [
259− "proc-macro2",
260− "quote",
261− "syn",
262−]
263−
264−[[package]]
265−name = "addr2line"
266−version = "0.14.0"
267−source = "registry+https://github.com/rust-lang/crates.io-index"
268−checksum = "7c0929d69e78dd9bf5408269919fcbcaeb2e35e5d43e5815517cdc6a8e11a423"
269−dependencies = [
270− "gimli",
271−]
272−
273−[[package]]
274−name = "adler"
275−version = "0.2.3"
276−source = "registry+https://github.com/rust-lang/crates.io-index"
277−checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
278−
279−[[package]]
280−name = "aho-corasick"
281−version = "0.7.15"
282−source = "registry+https://github.com/rust-lang/crates.io-index"
283−checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
284−dependencies = [
285− "memchr",
286−]
287−
288−[[package]]
289−name = "arrayvec"
290−version = "0.5.2"
291−source = "registry+https://github.com/rust-lang/crates.io-index"
292−checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
293−
294−[[package]]
295−name = "askama"
296−version = "0.10.5"
297−source = "registry+https://github.com/rust-lang/crates.io-index"
298−checksum = "d298738b6e47e1034e560e5afe63aa488fea34e25ec11b855a76f0d7b8e73134"
299−dependencies = [
300− "askama_derive",
301− "askama_escape",
302− "askama_shared",
303−]
304−
305−[[package]]
306−name = "askama_derive"
307−version = "0.10.5"
308−source = "registry+https://github.com/rust-lang/crates.io-index"
309−checksum = "ca2925c4c290382f9d2fa3d1c1b6a63fa1427099721ecca4749b154cc9c25522"
310−dependencies = [
311− "askama_shared",
312− "proc-macro2",
313− "syn",
314−]
315−
316−[[package]]
317−name = "askama_escape"
318−version = "0.10.1"
319−source = "registry+https://github.com/rust-lang/crates.io-index"
320−checksum = "90c108c1a94380c89d2215d0ac54ce09796823cca0fd91b299cfff3b33e346fb"
321−
322−[[package]]
323−name = "askama_shared"
324−version = "0.11.1"
325−source = "registry+https://github.com/rust-lang/crates.io-index"
326−checksum = "2582b77e0f3c506ec4838a25fa8a5f97b9bed72bb6d3d272ea1c031d8bd373bc"
327−dependencies = [
328− "askama_escape",
329− "humansize",
330− "nom",
331− "num-traits",
332− "percent-encoding",
333− "proc-macro2",
334− "quote",
335− "serde",
336− "syn",
337− "toml",
338−]
339−
340−[[package]]
341−name = "async-trait"
342−version = "0.1.42"
343−source = "registry+https://github.com/rust-lang/crates.io-index"
344−checksum = "8d3a45e77e34375a7923b1e8febb049bb011f064714a8e17a1a616fef01da13d"
345−dependencies = [
346− "proc-macro2",
347− "quote",
348− "syn",
349−]
350−
351−[[package]]
352−name = "autocfg"
353−version = "1.0.1"
354−source = "registry+https://github.com/rust-lang/crates.io-index"
355−checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
356−
357−[[package]]
358−name = "awc"
359−version = "2.0.3"
360−source = "registry+https://github.com/rust-lang/crates.io-index"
361−checksum = "b381e490e7b0cfc37ebc54079b0413d8093ef43d14a4e4747083f7fa47a9e691"
362−dependencies = [
363− "actix-codec",
364− "actix-http",
365− "actix-rt",
366− "actix-service",
367− "base64",
368− "bytes",
369− "cfg-if 1.0.0",
370− "derive_more",
371− "futures-core",
372− "log",
373− "mime",
374− "percent-encoding",
375− "rand",
376− "serde",
377− "serde_json",
378− "serde_urlencoded",
379−]
380−
381−[[package]]
382−name = "backtrace"
383−version = "0.3.55"
384−source = "registry+https://github.com/rust-lang/crates.io-index"
385−checksum = "ef5140344c85b01f9bbb4d4b7288a8aa4b3287ccef913a14bcc78a1063623598"
386−dependencies = [
387− "addr2line",
388− "cfg-if 1.0.0",
389− "libc",
390− "miniz_oxide",
391− "object",
392− "rustc-demangle",
393−]
394−
395−[[package]]
396−name = "base-x"
397−version = "0.2.8"
398−source = "registry+https://github.com/rust-lang/crates.io-index"
399−checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b"
400−
401−[[package]]
402−name = "base64"
403−version = "0.13.0"
404−source = "registry+https://github.com/rust-lang/crates.io-index"
405−checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
406−
407−[[package]]
408−name = "bitflags"
409−version = "1.2.1"
410−source = "registry+https://github.com/rust-lang/crates.io-index"
411−checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
412−
413−[[package]]
414−name = "bitvec"
415−version = "0.19.4"
416−source = "registry+https://github.com/rust-lang/crates.io-index"
417−checksum = "a7ba35e9565969edb811639dbebfe34edc0368e472c5018474c8eb2543397f81"
418−dependencies = [
419− "funty",
420− "radium",
421− "tap",
422− "wyz",
423−]
424−
425−[[package]]
426−name = "block-buffer"
427−version = "0.9.0"
428−source = "registry+https://github.com/rust-lang/crates.io-index"
429−checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
430−dependencies = [
431− "generic-array",
432−]
433−
434−[[package]]
435−name = "brotli-sys"
436−version = "0.3.2"
437−source = "registry+https://github.com/rust-lang/crates.io-index"
438−checksum = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd"
439−dependencies = [
440− "cc",
441− "libc",
442−]
443−
444−[[package]]
445−name = "brotli2"
446−version = "0.3.2"
447−source = "registry+https://github.com/rust-lang/crates.io-index"
448−checksum = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e"
449−dependencies = [
450− "brotli-sys",
451− "libc",
452−]
453−
454−[[package]]
455−name = "bumpalo"
456−version = "3.4.0"
457−source = "registry+https://github.com/rust-lang/crates.io-index"
458−checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820"
459−
460−[[package]]
461−name = "byteorder"
462−version = "1.3.4"
463−source = "registry+https://github.com/rust-lang/crates.io-index"
464−checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
465−
466−[[package]]
467−name = "bytes"
468−version = "0.5.6"
469−source = "registry+https://github.com/rust-lang/crates.io-index"
470−checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
471−
472−[[package]]
473−name = "bytestring"
474−version = "0.1.5"
475−source = "registry+https://github.com/rust-lang/crates.io-index"
476−checksum = "fc7c05fa5172da78a62d9949d662d2ac89d4cc7355d7b49adee5163f1fb3f363"
477−dependencies = [
478− "bytes",
479−]
480−
481−[[package]]
482−name = "cc"
483−version = "1.0.65"
484−source = "registry+https://github.com/rust-lang/crates.io-index"
485−checksum = "95752358c8f7552394baf48cd82695b345628ad3f170d607de3ca03b8dacca15"
486−
487−[[package]]
488−name = "cfg-if"
489−version = "0.1.10"
490−source = "registry+https://github.com/rust-lang/crates.io-index"
491−checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
492−
493−[[package]]
494−name = "cfg-if"
495−version = "1.0.0"
496−source = "registry+https://github.com/rust-lang/crates.io-index"
497−checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
498−
499−[[package]]
500−name = "cloudabi"
501−version = "0.1.0"
502−source = "registry+https://github.com/rust-lang/crates.io-index"
503−checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467"
504−dependencies = [
505− "bitflags",
506−]
507−
508−[[package]]
509−name = "const_fn"
510−version = "0.4.3"
511−source = "registry+https://github.com/rust-lang/crates.io-index"
512−checksum = "c478836e029dcef17fb47c89023448c64f781a046e0300e257ad8225ae59afab"
513−
514−[[package]]
515−name = "cookie"
516−version = "0.14.3"
517−source = "registry+https://github.com/rust-lang/crates.io-index"
518−checksum = "784ad0fbab4f3e9cef09f20e0aea6000ae08d2cb98ac4c0abc53df18803d702f"
519−dependencies = [
520− "percent-encoding",
521− "time",
522− "version_check",
523−]
524−
525−[[package]]
526−name = "copyless"
527−version = "0.1.5"
528−source = "registry+https://github.com/rust-lang/crates.io-index"
529−checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536"
530−
531−[[package]]
532−name = "cpuid-bool"
533−version = "0.1.2"
534−source = "registry+https://github.com/rust-lang/crates.io-index"
535−checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634"
536−
537−[[package]]
538−name = "crc32fast"
539−version = "1.2.1"
540−source = "registry+https://github.com/rust-lang/crates.io-index"
541−checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
542−dependencies = [
543− "cfg-if 1.0.0",
544−]
545−
546−[[package]]
547−name = "derive_more"
548−version = "0.99.11"
549−source = "registry+https://github.com/rust-lang/crates.io-index"
550−checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c"
551−dependencies = [
552− "proc-macro2",
553− "quote",
554− "syn",
555−]
556−
557−[[package]]
558−name = "digest"
559−version = "0.9.0"
560−source = "registry+https://github.com/rust-lang/crates.io-index"
561−checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
562−dependencies = [
563− "generic-array",
564−]
565−
566−[[package]]
567−name = "discard"
568−version = "1.0.4"
569−source = "registry+https://github.com/rust-lang/crates.io-index"
570−checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
571−
572−[[package]]
573−name = "either"
574−version = "1.6.1"
575−source = "registry+https://github.com/rust-lang/crates.io-index"
576−checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
577−
578−[[package]]
579−name = "encoding_rs"
580−version = "0.8.26"
581−source = "registry+https://github.com/rust-lang/crates.io-index"
582−checksum = "801bbab217d7f79c0062f4f7205b5d4427c6d1a7bd7aafdd1475f7c59d62b283"
583−dependencies = [
584− "cfg-if 1.0.0",
585−]
586−
587−[[package]]
588−name = "enum-as-inner"
589−version = "0.3.3"
590−source = "registry+https://github.com/rust-lang/crates.io-index"
591−checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595"
592−dependencies = [
593− "heck",
594− "proc-macro2",
595− "quote",
596− "syn",
597−]
598−
599−[[package]]
600−name = "flate2"
601−version = "1.0.19"
602−source = "registry+https://github.com/rust-lang/crates.io-index"
603−checksum = "7411863d55df97a419aa64cb4d2f167103ea9d767e2c54a1868b7ac3f6b47129"
604−dependencies = [
605− "cfg-if 1.0.0",
606− "crc32fast",
607− "libc",
608− "miniz_oxide",
609−]
610−
611−[[package]]
612−name = "fnv"
613−version = "1.0.7"
614−source = "registry+https://github.com/rust-lang/crates.io-index"
615−checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
616−
617−[[package]]
618−name = "form_urlencoded"
619−version = "1.0.0"
620−source = "registry+https://github.com/rust-lang/crates.io-index"
621−checksum = "ece68d15c92e84fa4f19d3780f1294e5ca82a78a6d515f1efaabcc144688be00"
622−dependencies = [
623− "matches",
624− "percent-encoding",
625−]
626−
627−[[package]]
628−name = "fuchsia-zircon"
629−version = "0.3.3"
630−source = "registry+https://github.com/rust-lang/crates.io-index"
631−checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
632−dependencies = [
633− "bitflags",
634− "fuchsia-zircon-sys",
635−]
636−
637−[[package]]
638−name = "fuchsia-zircon-sys"
639−version = "0.3.3"
640−source = "registry+https://github.com/rust-lang/crates.io-index"
641−checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
642−
643−[[package]]
644−name = "funty"
645−version = "1.0.1"
646−source = "registry+https://github.com/rust-lang/crates.io-index"
647−checksum = "0ba62103ce691c2fd80fbae2213dfdda9ce60804973ac6b6e97de818ea7f52c8"
648−
649−[[package]]
650−name = "futures"
651−version = "0.3.8"
652−source = "registry+https://github.com/rust-lang/crates.io-index"
653−checksum = "9b3b0c040a1fe6529d30b3c5944b280c7f0dcb2930d2c3062bca967b602583d0"
654−dependencies = [
655− "futures-channel",
656− "futures-core",
657− "futures-io",
658− "futures-sink",
659− "futures-task",
660− "futures-util",
661−]
662−
663−[[package]]
664−name = "futures-channel"
665−version = "0.3.8"
666−source = "registry+https://github.com/rust-lang/crates.io-index"
667−checksum = "4b7109687aa4e177ef6fe84553af6280ef2778bdb7783ba44c9dc3399110fe64"
668−dependencies = [
669− "futures-core",
670− "futures-sink",
671−]
672−
673−[[package]]
674−name = "futures-core"
675−version = "0.3.8"
676−source = "registry+https://github.com/rust-lang/crates.io-index"
677−checksum = "847ce131b72ffb13b6109a221da9ad97a64cbe48feb1028356b836b47b8f1748"
678−
679−[[package]]
680−name = "futures-io"
681−version = "0.3.8"
682−source = "registry+https://github.com/rust-lang/crates.io-index"
683−checksum = "611834ce18aaa1bd13c4b374f5d653e1027cf99b6b502584ff8c9a64413b30bb"
684−
685−[[package]]
686−name = "futures-macro"
687−version = "0.3.8"
688−source = "registry+https://github.com/rust-lang/crates.io-index"
689−checksum = "77408a692f1f97bcc61dc001d752e00643408fbc922e4d634c655df50d595556"
690−dependencies = [
691− "proc-macro-hack",
692− "proc-macro2",
693− "quote",
694− "syn",
695−]
696−
697−[[package]]
698−name = "futures-sink"
699−version = "0.3.8"
700−source = "registry+https://github.com/rust-lang/crates.io-index"
701−checksum = "f878195a49cee50e006b02b93cf7e0a95a38ac7b776b4c4d9cc1207cd20fcb3d"
702−
703−[[package]]
704−name = "futures-task"
705−version = "0.3.8"
706−source = "registry+https://github.com/rust-lang/crates.io-index"
707−checksum = "7c554eb5bf48b2426c4771ab68c6b14468b6e76cc90996f528c3338d761a4d0d"
708−dependencies = [
709− "once_cell",
710−]
711−
712−[[package]]
713−name = "futures-util"
714−version = "0.3.8"
715−source = "registry+https://github.com/rust-lang/crates.io-index"
716−checksum = "d304cff4a7b99cfb7986f7d43fbe93d175e72e704a8860787cc95e9ffd85cbd2"
717−dependencies = [
718− "futures-channel",
719− "futures-core",
720− "futures-io",
721− "futures-macro",
722− "futures-sink",
723− "futures-task",
724− "memchr",
725− "pin-project 1.0.2",
726− "pin-utils",
727− "proc-macro-hack",
728− "proc-macro-nested",
729− "slab",
730−]
731−
732−[[package]]
733−name = "fxhash"
734−version = "0.2.1"
735−source = "registry+https://github.com/rust-lang/crates.io-index"
736−checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
737−dependencies = [
738− "byteorder",
739−]
740−
741−[[package]]
742−name = "generic-array"
743−version = "0.14.4"
744−source = "registry+https://github.com/rust-lang/crates.io-index"
745−checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
746−dependencies = [
747− "typenum",
748− "version_check",
749−]
750−
751−[[package]]
752−name = "getrandom"
753−version = "0.1.15"
754−source = "registry+https://github.com/rust-lang/crates.io-index"
755−checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6"
756−dependencies = [
757− "cfg-if 0.1.10",
758− "libc",
759− "wasi",
760−]
761−
762−[[package]]
763−name = "gimli"
764−version = "0.23.0"
765−source = "registry+https://github.com/rust-lang/crates.io-index"
766−checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce"
767−
768−[[package]]
769−name = "h2"
770−version = "0.2.7"
771−source = "registry+https://github.com/rust-lang/crates.io-index"
772−checksum = "5e4728fd124914ad25e99e3d15a9361a879f6620f63cb56bbb08f95abb97a535"
773−dependencies = [
774− "bytes",
775− "fnv",
776− "futures-core",
777− "futures-sink",
778− "futures-util",
779− "http",
780− "indexmap",
781− "slab",
782− "tokio",
783− "tokio-util",
784− "tracing",
785− "tracing-futures",
786−]
787−
788−[[package]]
789−name = "hashbrown"
790−version = "0.9.1"
791−source = "registry+https://github.com/rust-lang/crates.io-index"
792−checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
793−
794−[[package]]
795−name = "heck"
796−version = "0.3.1"
797−source = "registry+https://github.com/rust-lang/crates.io-index"
798−checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
799−dependencies = [
800− "unicode-segmentation",
801−]
802−
803−[[package]]
804−name = "hermit-abi"
805−version = "0.1.17"
806−source = "registry+https://github.com/rust-lang/crates.io-index"
807−checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8"
808−dependencies = [
809− "libc",
810−]
811−
812−[[package]]
813−name = "hostname"
814−version = "0.3.1"
815−source = "registry+https://github.com/rust-lang/crates.io-index"
816−checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867"
817−dependencies = [
818− "libc",
819− "match_cfg",
820− "winapi 0.3.9",
821−]
822−
823−[[package]]
824−name = "http"
825−version = "0.2.1"
826−source = "registry+https://github.com/rust-lang/crates.io-index"
827−checksum = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9"
828−dependencies = [
829− "bytes",
830− "fnv",
831− "itoa",
832−]
833−
834−[[package]]
835−name = "httparse"
836−version = "1.3.4"
837−source = "registry+https://github.com/rust-lang/crates.io-index"
838−checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
839−
840−[[package]]
841−name = "humansize"
842−version = "1.1.0"
843−source = "registry+https://github.com/rust-lang/crates.io-index"
844−checksum = "b6cab2627acfc432780848602f3f558f7e9dd427352224b0d9324025796d2a5e"
845−
846−[[package]]
847−name = "idna"
848−version = "0.2.0"
849−source = "registry+https://github.com/rust-lang/crates.io-index"
850−checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
851−dependencies = [
852− "matches",
853− "unicode-bidi",
854− "unicode-normalization",
855−]
856−
857−[[package]]
858−name = "indexmap"
859−version = "1.6.0"
860−source = "registry+https://github.com/rust-lang/crates.io-index"
861−checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2"
862−dependencies = [
863− "autocfg",
864− "hashbrown",
865−]
866−
867−[[package]]
868−name = "instant"
869−version = "0.1.9"
870−source = "registry+https://github.com/rust-lang/crates.io-index"
871−checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
872−dependencies = [
873− "cfg-if 1.0.0",
874−]
875−
876−[[package]]
877−name = "iovec"
878−version = "0.1.4"
879−source = "registry+https://github.com/rust-lang/crates.io-index"
880−checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
881−dependencies = [
882− "libc",
883−]
884−
885−[[package]]
886−name = "ipconfig"
887−version = "0.2.2"
888−source = "registry+https://github.com/rust-lang/crates.io-index"
889−checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7"
890−dependencies = [
891− "socket2",
892− "widestring",
893− "winapi 0.3.9",
894− "winreg",
895−]
896−
897−[[package]]
898−name = "itoa"
899−version = "0.4.6"
900−source = "registry+https://github.com/rust-lang/crates.io-index"
901−checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
902−
903−[[package]]
904−name = "kernel32-sys"
905−version = "0.2.2"
906−source = "registry+https://github.com/rust-lang/crates.io-index"
907−checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
908−dependencies = [
909− "winapi 0.2.8",
910− "winapi-build",
911−]
912−
913−[[package]]
914−name = "language-tags"
915−version = "0.2.2"
916−source = "registry+https://github.com/rust-lang/crates.io-index"
917−checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
918−
919−[[package]]
920−name = "lazy_static"
921−version = "1.4.0"
922−source = "registry+https://github.com/rust-lang/crates.io-index"
923−checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
924−
925−[[package]]
926−name = "lexical-core"
927−version = "0.7.4"
928−source = "registry+https://github.com/rust-lang/crates.io-index"
929−checksum = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616"
930−dependencies = [
931− "arrayvec",
932− "bitflags",
933− "cfg-if 0.1.10",
934− "ryu",
935− "static_assertions",
936−]
937−
938−[[package]]
939−name = "libc"
940−version = "0.2.80"
941−source = "registry+https://github.com/rust-lang/crates.io-index"
942−checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
943−
944−[[package]]
945−name = "linked-hash-map"
946−version = "0.5.3"
947−source = "registry+https://github.com/rust-lang/crates.io-index"
948−checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
949−
950−[[package]]
951−name = "lock_api"
952−version = "0.4.2"
953−source = "registry+https://github.com/rust-lang/crates.io-index"
954−checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312"
955−dependencies = [
956− "scopeguard",
957−]
958−
959−[[package]]
960−name = "log"
961−version = "0.4.11"
962−source = "registry+https://github.com/rust-lang/crates.io-index"
963−checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
964−dependencies = [
965− "cfg-if 0.1.10",
966−]
967−
968−[[package]]
969−name = "lru-cache"
970−version = "0.1.2"
971−source = "registry+https://github.com/rust-lang/crates.io-index"
972−checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
973−dependencies = [
974− "linked-hash-map",
975−]
976−
977−[[package]]
978−name = "match_cfg"
979−version = "0.1.0"
980−source = "registry+https://github.com/rust-lang/crates.io-index"
981−checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
982−
983−[[package]]
984−name = "matches"
985−version = "0.1.8"
986−source = "registry+https://github.com/rust-lang/crates.io-index"
987−checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
988−
989−[[package]]
990−name = "memchr"
991−version = "2.3.4"
992−source = "registry+https://github.com/rust-lang/crates.io-index"
993−checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
994−
995−[[package]]
996−name = "mime"
997−version = "0.3.16"
998−source = "registry+https://github.com/rust-lang/crates.io-index"
999−checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
1000−
1001−[[package]]
1002−name = "miniz_oxide"
1003−version = "0.4.3"
1004−source = "registry+https://github.com/rust-lang/crates.io-index"
1005−checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d"
1006−dependencies = [
1007− "adler",
1008− "autocfg",
1009−]
1010−
1011−[[package]]
1012−name = "mio"
1013−version = "0.6.23"
1014−source = "registry+https://github.com/rust-lang/crates.io-index"
1015−checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4"
1016−dependencies = [
1017− "cfg-if 0.1.10",
1018− "fuchsia-zircon",
1019− "fuchsia-zircon-sys",
1020− "iovec",
1021− "kernel32-sys",
1022− "libc",
1023− "log",
1024− "miow",
1025− "net2",
1026− "slab",
1027− "winapi 0.2.8",
1028−]
1029−
1030−[[package]]
1031−name = "mio-uds"
1032−version = "0.6.8"
1033−source = "registry+https://github.com/rust-lang/crates.io-index"
1034−checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0"
1035−dependencies = [
1036− "iovec",
1037− "libc",
1038− "mio",
1039−]
1040−
1041−[[package]]
1042−name = "miow"
1043−version = "0.2.2"
1044−source = "registry+https://github.com/rust-lang/crates.io-index"
1045−checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d"
1046−dependencies = [
1047− "kernel32-sys",
1048− "net2",
1049− "winapi 0.2.8",
1050− "ws2_32-sys",
1051−]
1052−
1053−[[package]]
1054−name = "net2"
1055−version = "0.2.36"
1056−source = "registry+https://github.com/rust-lang/crates.io-index"
1057−checksum = "d7cf75f38f16cb05ea017784dc6dbfd354f76c223dba37701734c4f5a9337d02"
1058−dependencies = [
1059− "cfg-if 0.1.10",
1060− "libc",
1061− "winapi 0.3.9",
1062−]
1063−
1064−[[package]]
1065−name = "nom"
1066−version = "6.0.1"
1067−source = "registry+https://github.com/rust-lang/crates.io-index"
1068−checksum = "88034cfd6b4a0d54dd14f4a507eceee36c0b70e5a02236c4e4df571102be17f0"
1069−dependencies = [
1070− "bitvec",
1071− "lexical-core",
1072− "memchr",
1073− "version_check",
1074−]
1075−
1076−[[package]]
1077−name = "num-traits"
1078−version = "0.2.14"
1079−source = "registry+https://github.com/rust-lang/crates.io-index"
1080−checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
1081−dependencies = [
1082− "autocfg",
1083−]
1084−
1085−[[package]]
1086−name = "num_cpus"
1087−version = "1.13.0"
1088−source = "registry+https://github.com/rust-lang/crates.io-index"
1089−checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
1090−dependencies = [
1091− "hermit-abi",
1092− "libc",
1093−]
1094−
1095−[[package]]
1096−name = "object"
1097−version = "0.22.0"
1098−source = "registry+https://github.com/rust-lang/crates.io-index"
1099−checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397"
1100−
1101−[[package]]
1102−name = "once_cell"
1103−version = "1.5.2"
1104−source = "registry+https://github.com/rust-lang/crates.io-index"
1105−checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
1106−
1107−[[package]]
1108−name = "opaque-debug"
1109−version = "0.3.0"
1110−source = "registry+https://github.com/rust-lang/crates.io-index"
1111−checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
1112−
1113−[[package]]
1114−name = "parking_lot"
1115−version = "0.11.1"
1116−source = "registry+https://github.com/rust-lang/crates.io-index"
1117−checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
1118−dependencies = [
1119− "instant",
1120− "lock_api",
1121− "parking_lot_core",
1122−]
1123−
1124−[[package]]
1125−name = "parking_lot_core"
1126−version = "0.8.0"
1127−source = "registry+https://github.com/rust-lang/crates.io-index"
1128−checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b"
1129−dependencies = [
1130− "cfg-if 0.1.10",
1131− "cloudabi",
1132− "instant",
1133− "libc",
1134− "redox_syscall",
1135− "smallvec",
1136− "winapi 0.3.9",
1137−]
1138−
1139−[[package]]
1140−name = "percent-encoding"
1141−version = "2.1.0"
1142−source = "registry+https://github.com/rust-lang/crates.io-index"
1143−checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
1144−
1145−[[package]]
1146−name = "pin-project"
1147−version = "0.4.27"
1148−source = "registry+https://github.com/rust-lang/crates.io-index"
1149−checksum = "2ffbc8e94b38ea3d2d8ba92aea2983b503cd75d0888d75b86bb37970b5698e15"
1150−dependencies = [
1151− "pin-project-internal 0.4.27",
1152−]
1153−
1154−[[package]]
1155−name = "pin-project"
1156−version = "1.0.2"
1157−source = "registry+https://github.com/rust-lang/crates.io-index"
1158−checksum = "9ccc2237c2c489783abd8c4c80e5450fc0e98644555b1364da68cc29aa151ca7"
1159−dependencies = [
1160− "pin-project-internal 1.0.2",
1161−]
1162−
1163−[[package]]
1164−name = "pin-project-internal"
1165−version = "0.4.27"
1166−source = "registry+https://github.com/rust-lang/crates.io-index"
1167−checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895"
1168−dependencies = [
1169− "proc-macro2",
1170− "quote",
1171− "syn",
1172−]
1173−
1174−[[package]]
1175−name = "pin-project-internal"
1176−version = "1.0.2"
1177−source = "registry+https://github.com/rust-lang/crates.io-index"
1178−checksum = "f8e8d2bf0b23038a4424865103a4df472855692821aab4e4f5c3312d461d9e5f"
1179−dependencies = [
1180− "proc-macro2",
1181− "quote",
1182− "syn",
1183−]
1184−
1185−[[package]]
1186−name = "pin-project-lite"
1187−version = "0.1.11"
1188−source = "registry+https://github.com/rust-lang/crates.io-index"
1189−checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b"
1190−
1191−[[package]]
1192−name = "pin-project-lite"
1193−version = "0.2.0"
1194−source = "registry+https://github.com/rust-lang/crates.io-index"
1195−checksum = "6b063f57ec186e6140e2b8b6921e5f1bd89c7356dda5b33acc5401203ca6131c"
1196−
1197−[[package]]
1198−name = "pin-utils"
1199−version = "0.1.0"
1200−source = "registry+https://github.com/rust-lang/crates.io-index"
1201−checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
1202−
1203−[[package]]
1204−name = "ppv-lite86"
1205−version = "0.2.10"
1206−source = "registry+https://github.com/rust-lang/crates.io-index"
1207−checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
1208−
1209−[[package]]
1210−name = "proc-macro-hack"
1211−version = "0.5.19"
1212−source = "registry+https://github.com/rust-lang/crates.io-index"
1213−checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
1214−
1215−[[package]]
1216−name = "proc-macro-nested"
1217−version = "0.1.6"
1218−source = "registry+https://github.com/rust-lang/crates.io-index"
1219−checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a"
1220−
1221−[[package]]
1222−name = "proc-macro2"
1223−version = "1.0.24"
1224−source = "registry+https://github.com/rust-lang/crates.io-index"
1225−checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
1226−dependencies = [
1227− "unicode-xid",
1228−]
1229−
1230−[[package]]
1231−name = "quick-error"
1232−version = "1.2.3"
1233−source = "registry+https://github.com/rust-lang/crates.io-index"
1234−checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
1235−
1236−[[package]]
1237−name = "quote"
1238−version = "1.0.7"
1239−source = "registry+https://github.com/rust-lang/crates.io-index"
1240−checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
1241−dependencies = [
1242− "proc-macro2",
1243−]
1244−
1245−[[package]]
1246−name = "radium"
1247−version = "0.5.3"
1248−source = "registry+https://github.com/rust-lang/crates.io-index"
1249−checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
1250−
1251−[[package]]
1252−name = "rand"
1253−version = "0.7.3"
1254−source = "registry+https://github.com/rust-lang/crates.io-index"
1255−checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
1256−dependencies = [
1257− "getrandom",
1258− "libc",
1259− "rand_chacha",
1260− "rand_core",
1261− "rand_hc",
1262−]
1263−
1264−[[package]]
1265−name = "rand_chacha"
1266−version = "0.2.2"
1267−source = "registry+https://github.com/rust-lang/crates.io-index"
1268−checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
1269−dependencies = [
1270− "ppv-lite86",
1271− "rand_core",
1272−]
1273−
1274−[[package]]
1275−name = "rand_core"
1276−version = "0.5.1"
1277−source = "registry+https://github.com/rust-lang/crates.io-index"
1278−checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
1279−dependencies = [
1280− "getrandom",
1281−]
1282−
1283−[[package]]
1284−name = "rand_hc"
1285−version = "0.2.0"
1286−source = "registry+https://github.com/rust-lang/crates.io-index"
1287−checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
1288−dependencies = [
1289− "rand_core",
1290−]
1291−
1292−[[package]]
1293−name = "redox_syscall"
1294−version = "0.1.57"
1295−source = "registry+https://github.com/rust-lang/crates.io-index"
1296−checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
1297−
1298−[[package]]
1299−name = "regex"
1300−version = "1.4.2"
1301−source = "registry+https://github.com/rust-lang/crates.io-index"
1302−checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c"
1303−dependencies = [
1304− "aho-corasick",
1305− "memchr",
1306− "regex-syntax",
1307− "thread_local",
1308−]
1309−
1310−[[package]]
1311−name = "regex-syntax"
1312−version = "0.6.21"
1313−source = "registry+https://github.com/rust-lang/crates.io-index"
1314−checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
1315−
1316−[[package]]
1317−name = "resolv-conf"
1318−version = "0.7.0"
1319−source = "registry+https://github.com/rust-lang/crates.io-index"
1320−checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00"
1321−dependencies = [
1322− "hostname",
1323− "quick-error",
1324−]
1325−
1326−[[package]]
1327−name = "rustc-demangle"
1328−version = "0.1.18"
1329−source = "registry+https://github.com/rust-lang/crates.io-index"
1330−checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232"
1331−
1332−[[package]]
1333−name = "rustc_version"
1334−version = "0.2.3"
1335−source = "registry+https://github.com/rust-lang/crates.io-index"
1336−checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
1337−dependencies = [
1338− "semver",
1339−]
1340−
1341−[[package]]
1342−name = "ryu"
1343−version = "1.0.5"
1344−source = "registry+https://github.com/rust-lang/crates.io-index"
1345−checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
1346−
1347−[[package]]
1348−name = "scopeguard"
1349−version = "1.1.0"
1350−source = "registry+https://github.com/rust-lang/crates.io-index"
1351−checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
1352−
1353−[[package]]
1354−name = "semver"
1355−version = "0.9.0"
1356−source = "registry+https://github.com/rust-lang/crates.io-index"
1357−checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
1358−dependencies = [
1359− "semver-parser",
1360−]
1361−
1362−[[package]]
1363−name = "semver-parser"
1364−version = "0.7.0"
1365−source = "registry+https://github.com/rust-lang/crates.io-index"
1366−checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
1367−
1368−[[package]]
1369−name = "serde"
1370−version = "1.0.117"
1371−source = "registry+https://github.com/rust-lang/crates.io-index"
1372−checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a"
1373−dependencies = [
1374− "serde_derive",
1375−]
1376−
1377−[[package]]
1378−name = "serde_derive"
1379−version = "1.0.117"
1380−source = "registry+https://github.com/rust-lang/crates.io-index"
1381−checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e"
1382−dependencies = [
1383− "proc-macro2",
1384− "quote",
1385− "syn",
1386−]
1387−
1388−[[package]]
1389−name = "serde_json"
1390−version = "1.0.60"
1391−source = "registry+https://github.com/rust-lang/crates.io-index"
1392−checksum = "1500e84d27fe482ed1dc791a56eddc2f230046a040fa908c08bda1d9fb615779"
1393−dependencies = [
1394− "itoa",
1395− "ryu",
1396− "serde",
1397−]
1398−
1399−[[package]]
1400−name = "serde_urlencoded"
1401−version = "0.7.0"
1402−source = "registry+https://github.com/rust-lang/crates.io-index"
1403−checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9"
1404−dependencies = [
1405− "form_urlencoded",
1406− "itoa",
1407− "ryu",
1408− "serde",
1409−]
1410−
1411−[[package]]
1412−name = "sha-1"
1413−version = "0.9.2"
1414−source = "registry+https://github.com/rust-lang/crates.io-index"
1415−checksum = "ce3cdf1b5e620a498ee6f2a171885ac7e22f0e12089ec4b3d22b84921792507c"
1416−dependencies = [
1417− "block-buffer",
1418− "cfg-if 1.0.0",
1419− "cpuid-bool",
1420− "digest",
1421− "opaque-debug",
1422−]
1423−
1424−[[package]]
1425−name = "sha1"
1426−version = "0.6.0"
1427−source = "registry+https://github.com/rust-lang/crates.io-index"
1428−checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
1429−
1430−[[package]]
1431−name = "signal-hook-registry"
1432−version = "1.2.2"
1433−source = "registry+https://github.com/rust-lang/crates.io-index"
1434−checksum = "ce32ea0c6c56d5eacaeb814fbed9960547021d3edd010ded1425f180536b20ab"
1435−dependencies = [
1436− "libc",
1437−]
1438−
1439−[[package]]
1440−name = "slab"
1441−version = "0.4.2"
1442−source = "registry+https://github.com/rust-lang/crates.io-index"
1443−checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
1444−
1445−[[package]]
1446−name = "smallvec"
1447−version = "1.5.0"
1448−source = "registry+https://github.com/rust-lang/crates.io-index"
1449−checksum = "7acad6f34eb9e8a259d3283d1e8c1d34d7415943d4895f65cc73813c7396fc85"
1450−
1451−[[package]]
1452−name = "socket2"
1453−version = "0.3.17"
1454−source = "registry+https://github.com/rust-lang/crates.io-index"
1455−checksum = "2c29947abdee2a218277abeca306f25789c938e500ea5a9d4b12a5a504466902"
1456−dependencies = [
1457− "cfg-if 1.0.0",
1458− "libc",
1459− "redox_syscall",
1460− "winapi 0.3.9",
1461−]
1462−
1463−[[package]]
1464−name = "standback"
1465−version = "0.2.13"
1466−source = "registry+https://github.com/rust-lang/crates.io-index"
1467−checksum = "cf906c8b8fc3f6ecd1046e01da1d8ddec83e48c8b08b84dcc02b585a6bedf5a8"
1468−dependencies = [
1469− "version_check",
1470−]
1471−
1472−[[package]]
1473−name = "static_assertions"
1474−version = "1.1.0"
1475−source = "registry+https://github.com/rust-lang/crates.io-index"
1476−checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
1477−
1478−[[package]]
1479−name = "stdweb"
1480−version = "0.4.20"
1481−source = "registry+https://github.com/rust-lang/crates.io-index"
1482−checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5"
1483−dependencies = [
1484− "discard",
1485− "rustc_version",
1486− "stdweb-derive",
1487− "stdweb-internal-macros",
1488− "stdweb-internal-runtime",
1489− "wasm-bindgen",
1490−]
1491−
1492−[[package]]
1493−name = "stdweb-derive"
1494−version = "0.5.3"
1495−source = "registry+https://github.com/rust-lang/crates.io-index"
1496−checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
1497−dependencies = [
1498− "proc-macro2",
1499− "quote",
1500− "serde",
1501− "serde_derive",
1502− "syn",
1503−]
1504−
1505−[[package]]
1506−name = "stdweb-internal-macros"
1507−version = "0.2.9"
1508−source = "registry+https://github.com/rust-lang/crates.io-index"
1509−checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
1510−dependencies = [
1511− "base-x",
1512− "proc-macro2",
1513− "quote",
1514− "serde",
1515− "serde_derive",
1516− "serde_json",
1517− "sha1",
1518− "syn",
1519−]
1520−
1521−[[package]]
1522−name = "stdweb-internal-runtime"
1523−version = "0.1.5"
1524−source = "registry+https://github.com/rust-lang/crates.io-index"
1525−checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
1526−
1527−[[package]]
1528−name = "syn"
1529−version = "1.0.53"
1530−source = "registry+https://github.com/rust-lang/crates.io-index"
1531−checksum = "8833e20724c24de12bbaba5ad230ea61c3eafb05b881c7c9d3cfe8638b187e68"
1532−dependencies = [
1533− "proc-macro2",
1534− "quote",
1535− "unicode-xid",
1536−]
1537−
1538−[[package]]
1539−name = "tap"
1540−version = "1.0.0"
1541−source = "registry+https://github.com/rust-lang/crates.io-index"
1542−checksum = "36474e732d1affd3a6ed582781b3683df3d0563714c59c39591e8ff707cf078e"
1543−
1544−[[package]]
1545−name = "thiserror"
1546−version = "1.0.22"
1547−source = "registry+https://github.com/rust-lang/crates.io-index"
1548−checksum = "0e9ae34b84616eedaaf1e9dd6026dbe00dcafa92aa0c8077cb69df1fcfe5e53e"
1549−dependencies = [
1550− "thiserror-impl",
1551−]
1552−
1553−[[package]]
1554−name = "thiserror-impl"
1555−version = "1.0.22"
1556−source = "registry+https://github.com/rust-lang/crates.io-index"
1557−checksum = "9ba20f23e85b10754cd195504aebf6a27e2e6cbe28c17778a0c930724628dd56"
1558−dependencies = [
1559− "proc-macro2",
1560− "quote",
1561− "syn",
1562−]
1563−
1564−[[package]]
1565−name = "thread_local"
1566−version = "1.0.1"
1567−source = "registry+https://github.com/rust-lang/crates.io-index"
1568−checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
1569−dependencies = [
1570− "lazy_static",
1571−]
1572−
1573−[[package]]
1574−name = "threadpool"
1575−version = "1.8.1"
1576−source = "registry+https://github.com/rust-lang/crates.io-index"
1577−checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
1578−dependencies = [
1579− "num_cpus",
1580−]
1581−
1582−[[package]]
1583−name = "time"
1584−version = "0.2.23"
1585−source = "registry+https://github.com/rust-lang/crates.io-index"
1586−checksum = "bcdaeea317915d59b2b4cd3b5efcd156c309108664277793f5351700c02ce98b"
1587−dependencies = [
1588− "const_fn",
1589− "libc",
1590− "standback",
1591− "stdweb",
1592− "time-macros",
1593− "version_check",
1594− "winapi 0.3.9",
1595−]
1596−
1597−[[package]]
1598−name = "time-macros"
1599−version = "0.1.1"
1600−source = "registry+https://github.com/rust-lang/crates.io-index"
1601−checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1"
1602−dependencies = [
1603− "proc-macro-hack",
1604− "time-macros-impl",
1605−]
1606−
1607−[[package]]
1608−name = "time-macros-impl"
1609−version = "0.1.1"
1610−source = "registry+https://github.com/rust-lang/crates.io-index"
1611−checksum = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa"
1612−dependencies = [
1613− "proc-macro-hack",
1614− "proc-macro2",
1615− "quote",
1616− "standback",
1617− "syn",
1618−]
1619−
1620−[[package]]
1621−name = "tinyvec"
1622−version = "1.1.0"
1623−source = "registry+https://github.com/rust-lang/crates.io-index"
1624−checksum = "ccf8dbc19eb42fba10e8feaaec282fb50e2c14b2726d6301dbfeed0f73306a6f"
1625−dependencies = [
1626− "tinyvec_macros",
1627−]
1628−
1629−[[package]]
1630−name = "tinyvec_macros"
1631−version = "0.1.0"
1632−source = "registry+https://github.com/rust-lang/crates.io-index"
1633−checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
1634−
1635−[[package]]
1636−name = "tokio"
1637−version = "0.2.23"
1638−source = "registry+https://github.com/rust-lang/crates.io-index"
1639−checksum = "a6d7ad61edd59bfcc7e80dababf0f4aed2e6d5e0ba1659356ae889752dfc12ff"
1640−dependencies = [
1641− "bytes",
1642− "futures-core",
1643− "iovec",
1644− "lazy_static",
1645− "libc",
1646− "memchr",
1647− "mio",
1648− "mio-uds",
1649− "pin-project-lite 0.1.11",
1650− "signal-hook-registry",
1651− "slab",
1652− "winapi 0.3.9",
1653−]
1654−
1655−[[package]]
1656−name = "tokio-util"
1657−version = "0.3.1"
1658−source = "registry+https://github.com/rust-lang/crates.io-index"
1659−checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499"
1660−dependencies = [
1661− "bytes",
1662− "futures-core",
1663− "futures-sink",
1664− "log",
1665− "pin-project-lite 0.1.11",
1666− "tokio",
1667−]
1668−
1669−[[package]]
1670−name = "toml"
1671−version = "0.5.7"
1672−source = "registry+https://github.com/rust-lang/crates.io-index"
1673−checksum = "75cf45bb0bef80604d001caaec0d09da99611b3c0fd39d3080468875cdb65645"
1674−dependencies = [
1675− "serde",
1676−]
1677−
1678−[[package]]
1679−name = "tracing"
1680−version = "0.1.22"
1681−source = "registry+https://github.com/rust-lang/crates.io-index"
1682−checksum = "9f47026cdc4080c07e49b37087de021820269d996f581aac150ef9e5583eefe3"
1683−dependencies = [
1684− "cfg-if 1.0.0",
1685− "log",
1686− "pin-project-lite 0.2.0",
1687− "tracing-core",
1688−]
1689−
1690−[[package]]
1691−name = "tracing-core"
1692−version = "0.1.17"
1693−source = "registry+https://github.com/rust-lang/crates.io-index"
1694−checksum = "f50de3927f93d202783f4513cda820ab47ef17f624b03c096e86ef00c67e6b5f"
1695−dependencies = [
1696− "lazy_static",
1697−]
1698−
1699−[[package]]
1700−name = "tracing-futures"
1701−version = "0.2.4"
1702−source = "registry+https://github.com/rust-lang/crates.io-index"
1703−checksum = "ab7bb6f14721aa00656086e9335d363c5c8747bae02ebe32ea2c7dece5689b4c"
1704−dependencies = [
1705− "pin-project 0.4.27",
1706− "tracing",
1707−]
1708−
1709−[[package]]
1710−name = "trust-dns-proto"
1711−version = "0.19.6"
1712−source = "registry+https://github.com/rust-lang/crates.io-index"
1713−checksum = "53861fcb288a166aae4c508ae558ed18b53838db728d4d310aad08270a7d4c2b"
1714−dependencies = [
1715− "async-trait",
1716− "backtrace",
1717− "enum-as-inner",
1718− "futures",
1719− "idna",
1720− "lazy_static",
1721− "log",
1722− "rand",
1723− "smallvec",
1724− "thiserror",
1725− "tokio",
1726− "url",
1727−]
1728−
1729−[[package]]
1730−name = "trust-dns-resolver"
1731−version = "0.19.6"
1732−source = "registry+https://github.com/rust-lang/crates.io-index"
1733−checksum = "6759e8efc40465547b0dfce9500d733c65f969a4cbbfbe3ccf68daaa46ef179e"
1734−dependencies = [
1735− "backtrace",
1736− "cfg-if 0.1.10",
1737− "futures",
1738− "ipconfig",
1739− "lazy_static",
1740− "log",
1741− "lru-cache",
1742− "resolv-conf",
1743− "smallvec",
1744− "thiserror",
1745− "tokio",
1746− "trust-dns-proto",
1747−]
1748−
1749−[[package]]
1750−name = "typenum"
1751−version = "1.12.0"
1752−source = "registry+https://github.com/rust-lang/crates.io-index"
1753−checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
1754−
1755−[[package]]
1756−name = "unicode-bidi"
1757−version = "0.3.4"
1758−source = "registry+https://github.com/rust-lang/crates.io-index"
1759−checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
1760−dependencies = [
1761− "matches",
1762−]
1763−
1764−[[package]]
1765−name = "unicode-normalization"
1766−version = "0.1.16"
1767−source = "registry+https://github.com/rust-lang/crates.io-index"
1768−checksum = "a13e63ab62dbe32aeee58d1c5408d35c36c392bba5d9d3142287219721afe606"
1769−dependencies = [
1770− "tinyvec",
1771−]
1772−
1773−[[package]]
1774−name = "unicode-segmentation"
1775−version = "1.7.1"
1776−source = "registry+https://github.com/rust-lang/crates.io-index"
1777−checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
1778−
1779−[[package]]
1780−name = "unicode-xid"
1781−version = "0.2.1"
1782−source = "registry+https://github.com/rust-lang/crates.io-index"
1783−checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
1784−
1785−[[package]]
1786−name = "url"
1787−version = "2.2.0"
1788−source = "registry+https://github.com/rust-lang/crates.io-index"
1789−checksum = "5909f2b0817350449ed73e8bcd81c8c3c8d9a7a5d8acba4b27db277f1868976e"
1790−dependencies = [
1791− "form_urlencoded",
1792− "idna",
1793− "matches",
1794− "percent-encoding",
1795−]
1796−
1797−[[package]]
1798−name = "version_check"
1799−version = "0.9.2"
1800−source = "registry+https://github.com/rust-lang/crates.io-index"
1801−checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
1802−
1803−[[package]]
1804−name = "wasi"
1805−version = "0.9.0+wasi-snapshot-preview1"
1806−source = "registry+https://github.com/rust-lang/crates.io-index"
1807−checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
1808−
1809−[[package]]
1810−name = "wasm-bindgen"
1811−version = "0.2.69"
1812−source = "registry+https://github.com/rust-lang/crates.io-index"
1813−checksum = "3cd364751395ca0f68cafb17666eee36b63077fb5ecd972bbcd74c90c4bf736e"
1814−dependencies = [
1815− "cfg-if 1.0.0",
1816− "wasm-bindgen-macro",
1817−]
1818−
1819−[[package]]
1820−name = "wasm-bindgen-backend"
1821−version = "0.2.69"
1822−source = "registry+https://github.com/rust-lang/crates.io-index"
1823−checksum = "1114f89ab1f4106e5b55e688b828c0ab0ea593a1ea7c094b141b14cbaaec2d62"
1824−dependencies = [
1825− "bumpalo",
1826− "lazy_static",
1827− "log",
1828− "proc-macro2",
1829− "quote",
1830− "syn",
1831− "wasm-bindgen-shared",
1832−]
1833−
1834−[[package]]
1835−name = "wasm-bindgen-macro"
1836−version = "0.2.69"
1837−source = "registry+https://github.com/rust-lang/crates.io-index"
1838−checksum = "7a6ac8995ead1f084a8dea1e65f194d0973800c7f571f6edd70adf06ecf77084"
1839−dependencies = [
1840− "quote",
1841− "wasm-bindgen-macro-support",
1842−]
1843−
1844−[[package]]
1845−name = "wasm-bindgen-macro-support"
1846−version = "0.2.69"
1847−source = "registry+https://github.com/rust-lang/crates.io-index"
1848−checksum = "b5a48c72f299d80557c7c62e37e7225369ecc0c963964059509fbafe917c7549"
1849−dependencies = [
1850− "proc-macro2",
1851− "quote",
1852− "syn",
1853− "wasm-bindgen-backend",
1854− "wasm-bindgen-shared",
1855−]
1856−
1857−[[package]]
1858−name = "wasm-bindgen-shared"
1859−version = "0.2.69"
1860−source = "registry+https://github.com/rust-lang/crates.io-index"
1861−checksum = "7e7811dd7f9398f14cc76efd356f98f03aa30419dea46aa810d71e819fc97158"
1862−
1863−[[package]]
1864−name = "web-app"
1865−version = "0.2.0"
1866−dependencies = [
1867− "actix-rt",
1868− "actix-web",
1869− "askama",
1870−]
1871−
1872−[[package]]
1873−name = "widestring"
1874−version = "0.4.3"
1875−source = "registry+https://github.com/rust-lang/crates.io-index"
1876−checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c"
1877−
1878−[[package]]
1879−name = "winapi"
1880−version = "0.2.8"
1881−source = "registry+https://github.com/rust-lang/crates.io-index"
1882−checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
1883−
1884−[[package]]
1885−name = "winapi"
1886−version = "0.3.9"
1887−source = "registry+https://github.com/rust-lang/crates.io-index"
1888−checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
1889−dependencies = [
1890− "winapi-i686-pc-windows-gnu",
1891− "winapi-x86_64-pc-windows-gnu",
1892−]
1893−
1894−[[package]]
1895−name = "winapi-build"
1896−version = "0.1.1"
1897−source = "registry+https://github.com/rust-lang/crates.io-index"
1898−checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
1899−
1900−[[package]]
1901−name = "winapi-i686-pc-windows-gnu"
1902−version = "0.4.0"
1903−source = "registry+https://github.com/rust-lang/crates.io-index"
1904−checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
1905−
1906−[[package]]
1907−name = "winapi-x86_64-pc-windows-gnu"
1908−version = "0.4.0"
1909−source = "registry+https://github.com/rust-lang/crates.io-index"
1910−checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
1911−
1912−[[package]]
1913−name = "winreg"
1914−version = "0.6.2"
1915−source = "registry+https://github.com/rust-lang/crates.io-index"
1916−checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9"
1917−dependencies = [
1918− "winapi 0.3.9",
1919−]
1920−
1921−[[package]]
1922−name = "ws2_32-sys"
1923−version = "0.2.1"
1924−source = "registry+https://github.com/rust-lang/crates.io-index"
1925−checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
1926−dependencies = [
1927− "winapi 0.2.8",
1928− "winapi-build",
1929−]
1930−
1931−[[package]]
1932−name = "wyz"
1933−version = "0.2.0"
1934−source = "registry+https://github.com/rust-lang/crates.io-index"
1935−checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
examples/web-app-v2/Cargo.tomldeleted−12
@@ -1,12 +0,0 @@
1−[package]
2−name = "web-app"
3−version = "0.2.0"
4−authors = ["Typeable LLC <octopod@typeable.io>"]
5−edition = "2018"
6−
7−# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8−
9−[dependencies]
10−actix-web = "3.3.2"
11−actix-rt = "1.1.1"
12−askama = "0.10.5"
examples/web-app-v2/README.mddeleted−5
@@ -1,5 +0,0 @@
1−# Build Docker image
2−
3−```bash
4−docker build -f docker/Dockerfile -t typeable/octopod-web-app-example:v2 .
5−```
examples/web-app-v2/charts/web-app/.helmignoredeleted−22
@@ -1,22 +0,0 @@
1−# Patterns to ignore when building packages.
2−# This supports shell glob matching, relative path matching, and
3−# negation (prefixed with !). Only one pattern per line.
4−.DS_Store
5−# Common VCS dirs
6−.git/
7−.gitignore
8−.bzr/
9−.bzrignore
10−.hg/
11−.hgignore
12−.svn/
13−# Common backup files
14−*.swp
15−*.bak
16−*.tmp
17−*~
18−# Various IDEs
19−.project
20−.idea/
21−*.tmproj
22−.vscode/
examples/web-app-v2/charts/web-app/Chart.yamldeleted−5
@@ -1,5 +0,0 @@
1−apiVersion: v1
2−appVersion: "1.0"
3−description: A Helm chart for Kubernetes
4−name: web-app
5−version: 0.1.0
examples/web-app-v2/charts/web-app/templates/deployment.yamldeleted−48
@@ -1,48 +0,0 @@
1−apiVersion: apps/v1
2−kind: Deployment
3−metadata:
4− name: {{ .Release.Name }}
5− namespace: {{ .Values.namespace }}
6−spec:
7− replicas: {{ .Values.replicas }}
8− selector:
9− matchLabels:
10− app: {{ .Release.Name }}
11− template:
12− metadata:
13− name: {{ .Release.Name }}
14− labels:
15− app: {{ .Release.Name }}
16− spec:
17− nodeSelector:
18− role: {{ .Values.nodeselector }}
19− terminationGracePeriodSeconds: 60
20− containers:
21− - name: main
22− image: {{ .Values.image_prefix }}/{{ .Values.image }}:{{ .Values.image_tag }}
23− env:
24− {{- range $key, $value := .Values.env }}
25− - name: {{ $key | quote }}
26− value: {{ $value | quote }}
27− {{- end }}
28− ports:
29− - containerPort: 8080
30− protocol: TCP
31− resources:
32− requests:
33− cpu: 0.1
34− memory: 64Mi
35− limits:
36− cpu: 0.1
37− memory: 128Mi
38− readinessProbe:
39− httpGet:
40− port: 8080
41− path: /
42− periodSeconds: 20
43− livenessProbe:
44− httpGet:
45− port: 8080
46− path: /
47− initialDelaySeconds: 15
48− periodSeconds: 5
examples/web-app-v2/charts/web-app/templates/ingress.yamldeleted−26
@@ -1,26 +0,0 @@
1−apiVersion: extensions/v1beta1
2−kind: Ingress
3−metadata:
4− name: {{ .Release.Name }}-nginx-ingress
5− namespace: {{ .Values.namespace }}
6− annotations:
7− kubernetes.io/ingress.class: "nginx"
8− kubernetes.io/tls-acme: "true"
9− cert-manager.io/issuer: "{{ .Release.Name }}-certs"
10− nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
11− nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
12− nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
13− nginx.ingress.kubernetes.io/proxy-next-upstream: "http_502 error timeout"
14−spec:
15− tls:
16− - hosts:
17− - {{ .Values.domain }}
18− secretName: {{ .Release.Name }}-tls
19− rules:
20− - host: {{ .Values.domain }}
21− http:
22− paths:
23− - path: /
24− backend:
25− serviceName: {{ .Release.Name }}
26− servicePort: 80
examples/web-app-v2/charts/web-app/templates/issuer.yamldeleted−18
@@ -1,18 +0,0 @@
1−apiVersion: cert-manager.io/v1
2−kind: Issuer
3−metadata:
4− name: {{ .Release.Name }}-certs
5− namespace: {{ .Release.Namespace }}
6−spec:
7− acme:
8− email: {{ .Values.acme_registration_email }}
9− server: https://acme-v02.api.letsencrypt.org/directory
10− privateKeySecretRef:
11− name: {{ .Release.Name }}-letsencrypt
12− # ACME HTTP-01 provider configurations
13− solvers:
14− # An empty 'selector' means that this solver matches all domains
15− - selector: {}
16− http01:
17− ingress:
18− class: nginx
examples/web-app-v2/charts/web-app/templates/service.yamldeleted−14
@@ -1,14 +0,0 @@
1−apiVersion: v1
2−kind: Service
3−metadata:
4− name: {{ .Release.Name }}
5− namespace: {{ .Values.namespace }}
6− labels:
7− app: {{ .Release.Name }}
8−spec:
9− selector:
10− app: {{ .Release.Name }}
11− ports:
12− - name: app
13− port: 80
14− targetPort: 8080
examples/web-app-v2/charts/web-app/values.yamldeleted−8
@@ -1,8 +0,0 @@
1−image_prefix:
2−image: web-app-example
3−image_tag:
4−namespace: deployment
5−domain:
6−nodeselector: stand
7−replicas: 1
8−env:
examples/web-app-v2/docker/Dockerfiledeleted−22
@@ -1,22 +0,0 @@
1−FROM ekidd/rust-musl-builder:1.48.0 as builder
2−
3−RUN sudo mkdir /app && \
4− sudo chown -R rust:rust /app
5−WORKDIR /app
6−RUN USER=root cargo new web-app
7−WORKDIR /app/web-app
8−COPY Cargo.toml /app/web-app/
9−COPY Cargo.lock /app/web-app/
10−RUN cargo build --release
11−COPY src /app/web-app/src
12−COPY templates /app/web-app/templates
13−RUN rm -r ./target/x86_64-unknown-linux-musl/release/deps/web_app* && \
14− cargo build --release --frozen
15−
16−FROM alpine:3.12.1
17−
18−COPY --from=builder /app/web-app/target/x86_64-unknown-linux-musl/release/web-app /app/web-app
19−RUN addgroup -g 1000 user && \
20− adduser -D -s /bin/sh -g 1000 -G user user
21−
22−ENTRYPOINT ["/app/web-app"]
examples/web-app-v2/src/main.rsdeleted−43
@@ -1,43 +0,0 @@
1−use actix_web::{get, web, App, HttpResponse, HttpServer, Responder};
2−use askama::Template;
3−
4−#[derive(Template)]
5−#[template(path = "index.html")]
6−struct IndexTemplate {
7− envs: Vec<Env>,
8−}
9−
10−#[derive(Debug, Clone, Template)]
11−#[template(source = "{{ key }} = {{ value }}", ext = "txt")]
12−struct Env {
13− key: String,
14− value: String,
15−}
16−
17−#[get("/")]
18−async fn index(state: web::Data<Vec<Env>>) -> impl Responder {
19− let body = IndexTemplate {
20− envs: state.to_vec(),
21− }
22− .render()
23− .expect("could not render template");
24− HttpResponse::Ok().body(body)
25−}
26−
27−#[actix_rt::main]
28−async fn main() -> std::io::Result<()> {
29− HttpServer::new(|| App::new().data(get_app_envs()).service(index))
30− .bind("0.0.0.0:8080")?
31− .run()
32− .await
33−}
34−
35−fn get_app_envs() -> Vec<Env> {
36− std::env::vars()
37− .filter(|env| env.0.starts_with("APP_ENV"))
38− .map(|env| Env {
39− key: env.0,
40− value: env.1,
41− })
42− .collect::<Vec<_>>()
43−}
examples/web-app-v2/templates/index.htmldeleted−16
@@ -1,16 +0,0 @@
1−<!DOCTYPE html>
2−<html lang="en">
3− <head>
4− <meta name="title" content="Web App" />
5− <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6− </head>
7− <body>
8− <div>
9− <ul>
10− {% for env in envs %}
11− <li>{{ env }}</li>
12− {% endfor %}
13− </ul>
14− </div>
15− </body>
16−</html>
examples/web-app/.gitignoredeleted−1
@@ -1 +0,0 @@
1−/target
examples/web-app/Cargo.tomldeleted−12
@@ -1,12 +0,0 @@
1−[package]
2−name = "web-app"
3−version = "0.1.0"
4−authors = ["Typeable <octopod@typeable.io>"]
5−edition = "2018"
6−
7−# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8−
9−[dependencies]
10−actix-web = "3.3.0"
11−actix-rt = "1.1.1"
12−askama = "0.10.5"
examples/web-app/README.mddeleted−5
@@ -1,5 +0,0 @@
1−# Build Docker image
2−
3−```bash
4−docker build -f docker/Dockerfile -t typeable/octopod-web-app-example:v1 .
5−```
examples/web-app/charts/web-app/.helmignoredeleted−22
@@ -1,22 +0,0 @@
1−# Patterns to ignore when building packages.
2−# This supports shell glob matching, relative path matching, and
3−# negation (prefixed with !). Only one pattern per line.
4−.DS_Store
5−# Common VCS dirs
6−.git/
7−.gitignore
8−.bzr/
9−.bzrignore
10−.hg/
11−.hgignore
12−.svn/
13−# Common backup files
14−*.swp
15−*.bak
16−*.tmp
17−*~
18−# Various IDEs
19−.project
20−.idea/
21−*.tmproj
22−.vscode/
examples/web-app/charts/web-app/Chart.yamldeleted−5
@@ -1,5 +0,0 @@
1−apiVersion: v1
2−appVersion: "1.0"
3−description: A Helm chart for Kubernetes
4−name: web-app
5−version: 0.1.0
examples/web-app/charts/web-app/templates/deployment.yamldeleted−48
@@ -1,48 +0,0 @@
1−apiVersion: apps/v1
2−kind: Deployment
3−metadata:
4− name: {{ .Release.Name }}
5− namespace: {{ .Values.namespace }}
6−spec:
7− replicas: {{ .Values.replicas }}
8− selector:
9− matchLabels:
10− app: {{ .Release.Name }}
11− template:
12− metadata:
13− name: {{ .Release.Name }}
14− labels:
15− app: {{ .Release.Name }}
16− spec:
17− nodeSelector:
18− role: {{ .Values.nodeselector }}
19− terminationGracePeriodSeconds: 60
20− containers:
21− - name: main
22− image: {{ .Values.image_prefix }}/{{ .Values.image }}:{{ .Values.image_tag }}
23− env:
24− {{- range $key, $value := .Values.env }}
25− - name: {{ $key | quote }}
26− value: {{ $value | quote }}
27− {{- end }}
28− ports:
29− - containerPort: 8080
30− protocol: TCP
31− resources:
32− requests:
33− cpu: 0.1
34− memory: 64Mi
35− limits:
36− cpu: 0.1
37− memory: 128Mi
38− readinessProbe:
39− httpGet:
40− port: 8080
41− path: /
42− periodSeconds: 20
43− livenessProbe:
44− httpGet:
45− port: 8080
46− path: /
47− initialDelaySeconds: 15
48− periodSeconds: 5
examples/web-app/charts/web-app/templates/ingress.yamldeleted−26
@@ -1,26 +0,0 @@
1−apiVersion: extensions/v1beta1
2−kind: Ingress
3−metadata:
4− name: {{ .Release.Name }}-nginx-ingress
5− namespace: {{ .Values.namespace }}
6− annotations:
7− kubernetes.io/ingress.class: "nginx"
8− kubernetes.io/tls-acme: "true"
9− cert-manager.io/issuer: "{{ .Release.Name }}-certs"
10− nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
11− nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
12− nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
13− nginx.ingress.kubernetes.io/proxy-next-upstream: "http_502 error timeout"
14−spec:
15− tls:
16− - hosts:
17− - {{ .Values.domain }}
18− secretName: {{ .Release.Name }}-tls
19− rules:
20− - host: {{ .Values.domain }}
21− http:
22− paths:
23− - path: /
24− backend:
25− serviceName: {{ .Release.Name }}
26− servicePort: 80
examples/web-app/charts/web-app/templates/issuer.yamldeleted−18
@@ -1,18 +0,0 @@
1−apiVersion: cert-manager.io/v1
2−kind: Issuer
3−metadata:
4− name: {{ .Release.Name }}-certs
5− namespace: {{ .Release.Namespace }}
6−spec:
7− acme:
8− email: {{ .Values.acme_registration_email }}
9− server: https://acme-v02.api.letsencrypt.org/directory
10− privateKeySecretRef:
11− name: {{ .Release.Name }}-letsencrypt
12− # ACME HTTP-01 provider configurations
13− solvers:
14− # An empty 'selector' means that this solver matches all domains
15− - selector: {}
16− http01:
17− ingress:
18− class: nginx
examples/web-app/charts/web-app/templates/service.yamldeleted−14
@@ -1,14 +0,0 @@
1−apiVersion: v1
2−kind: Service
3−metadata:
4− name: {{ .Release.Name }}
5− namespace: {{ .Values.namespace }}
6− labels:
7− app: {{ .Release.Name }}
8−spec:
9− selector:
10− app: {{ .Release.Name }}
11− ports:
12− - name: app
13− port: 80
14− targetPort: 8080
examples/web-app/charts/web-app/values.yamldeleted−8
@@ -1,8 +0,0 @@
1−image_prefix:
2−image: web-app-example
3−image_tag:
4−namespace: deployment
5−domain:
6−nodeselector: stand
7−replicas: 1
8−env:
examples/web-app/docker/Dockerfiledeleted−22
@@ -1,22 +0,0 @@
1−FROM ekidd/rust-musl-builder:1.48.0 as builder
2−
3−RUN sudo mkdir /app && \
4− sudo chown -R rust:rust /app
5−WORKDIR /app
6−RUN USER=root cargo new web-app
7−WORKDIR /app/web-app
8−COPY Cargo.toml /app/web-app/
9−COPY Cargo.lock /app/web-app/
10−RUN cargo build --release
11−COPY src /app/web-app/src
12−COPY templates /app/web-app/templates
13−RUN rm -r ./target/x86_64-unknown-linux-musl/release/deps/web_app* && \
14− cargo build --release --frozen
15−
16−FROM alpine:3.12.1
17−
18−COPY --from=builder /app/web-app/target/x86_64-unknown-linux-musl/release/web-app /app/web-app
19−RUN addgroup -g 1000 user && \
20− adduser -D -s /bin/sh -g 1000 -G user user
21−
22−ENTRYPOINT ["/app/web-app"]
examples/web-app/src/main.rsdeleted−43
@@ -1,43 +0,0 @@
1−use actix_web::{get, web, App, HttpResponse, HttpServer, Responder};
2−use askama::Template;
3−
4−#[derive(Template)]
5−#[template(path = "index.html")]
6−struct IndexTemplate {
7− envs: Vec<Env>,
8−}
9−
10−#[derive(Debug, Clone, Template)]
11−#[template(source = "{{ key }} = {{ value }}", ext = "txt")]
12−struct Env {
13− key: String,
14− value: String,
15−}
16−
17−#[get("/")]
18−async fn index(state: web::Data<Vec<Env>>) -> impl Responder {
19− let body = IndexTemplate {
20− envs: state.to_vec(),
21− }
22− .render()
23− .expect("could not render template");
24− HttpResponse::Ok().body(body)
25−}
26−
27−#[actix_rt::main]
28−async fn main() -> std::io::Result<()> {
29− HttpServer::new(|| App::new().data(get_app_envs()).service(index))
30− .bind("0.0.0.0:8080")?
31− .run()
32− .await
33−}
34−
35−fn get_app_envs() -> Vec<Env> {
36− std::env::vars()
37− .filter(|env| env.0.starts_with("APP_ENV"))
38− .map(|env| Env {
39− key: env.0,
40− value: env.1,
41− })
42− .collect::<Vec<_>>()
43−}
examples/web-app/templates/index.htmldeleted−14
@@ -1,14 +0,0 @@
1−<!DOCTYPE html>
2−<html lang="en">
3− <head>
4− <meta name="title" content="Web App" />
5− <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6− </head>
7− <body>
8− <div>
9− {% for env in envs %}
10− <div>{{ env }}</div>
11− {% endfor %}
12− </div>
13− </body>
14−</html>
fourmolu.yamlnew file+8
@@ -0,0 +1,8 @@
1+indentation: 2
2+comma-style: leading # for lists, tuples etc. - can also be 'trailing'
3+record-brace-space: true # rec {x = 1} vs. rec{x = 1}
4+indent-wheres: true # 'false' means save space by only half-indenting the 'where' keyword
5+diff-friendly-import-export: false # 'false' uses Ormolu-style lists
6+respectful: true # don't be too opinionated about newlines etc.
7+haddock-style: single-line # '--' vs. '{-'
8+newlines-between-decls: 1 # number of newlines between top-level declarations
examples/helm-based-control-scripts/.gitignore → helm-control-scripts/.gitignorerenamed

The content is the same.

examples/web-app/Cargo.lock → helm-control-scripts/Cargo.lockrenamed+1203−980
@@ -1,573 +1,298 @@
11# This file is automatically @generated by Cargo.
22# It is not intended for manual editing.
33[[package]]
4−name = "actix-codec"
5−version = "0.3.0"
6−source = "registry+https://github.com/rust-lang/crates.io-index"
7−checksum = "78d1833b3838dbe990df0f1f87baf640cf6146e898166afe401839d1b001e570"
8−dependencies = [
9− "bitflags",
10− "bytes",
11− "futures-core",
12− "futures-sink",
13− "log",
14− "pin-project 0.4.27",
15− "tokio",
16− "tokio-util",
17−]
18−
19−[[package]]
20−name = "actix-connect"
21−version = "2.0.0"
4+name = "adler32"
5+version = "1.2.0"
226source = "registry+https://github.com/rust-lang/crates.io-index"
23−checksum = "177837a10863f15ba8d3ae3ec12fac1099099529ed20083a27fdfe247381d0dc"
24−dependencies = [
25− "actix-codec",
26− "actix-rt",
27− "actix-service",
28− "actix-utils",
29− "derive_more",
30− "either",
31− "futures-util",
32− "http",
33− "log",
34− "trust-dns-proto",
35− "trust-dns-resolver",
36−]
7+checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
378
389[[package]]
39−name = "actix-http"
40−version = "2.2.0"
10+name = "aho-corasick"
11+version = "0.7.18"
4112source = "registry+https://github.com/rust-lang/crates.io-index"
42−checksum = "452299e87817ae5673910e53c243484ca38be3828db819b6011736fc6982e874"
13+checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
4314dependencies = [
44− "actix-codec",
45− "actix-connect",
46− "actix-rt",
47− "actix-service",
48− "actix-threadpool",
49− "actix-utils",
50− "base64",
51− "bitflags",
52− "brotli2",
53− "bytes",
54− "cookie",
55− "copyless",
56− "derive_more",
57− "either",
58− "encoding_rs",
59− "flate2",
60− "futures-channel",
61− "futures-core",
62− "futures-util",
63− "fxhash",
64− "h2",
65− "http",
66− "httparse",
67− "indexmap",
68− "itoa",
69− "language-tags",
70− "lazy_static",
71− "log",
72− "mime",
73− "percent-encoding",
74− "pin-project 1.0.2",
75− "rand",
76− "regex",
77− "serde",
78− "serde_json",
79− "serde_urlencoded",
80− "sha-1",
81− "slab",
82− "time",
15+ "memchr",
8316]
8417
8518[[package]]
86−name = "actix-macros"
87−version = "0.1.2"
19+name = "ansi_term"
20+version = "0.11.0"
8821source = "registry+https://github.com/rust-lang/crates.io-index"
89−checksum = "a60f9ba7c4e6df97f3aacb14bb5c0cd7d98a49dcbaed0d7f292912ad9a6a3ed2"
22+checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
9023dependencies = [
91− "quote",
92− "syn",
24+ "winapi",
9325]
9426
9527[[package]]
96−name = "actix-router"
97−version = "0.2.5"
28+name = "async-stream"
29+version = "0.3.2"
9830source = "registry+https://github.com/rust-lang/crates.io-index"
99−checksum = "bbd1f7dbda1645bf7da33554db60891755f6c01c1b2169e2f4c492098d30c235"
31+checksum = "171374e7e3b2504e0e5236e3b59260560f9fe94bfe9ac39ba5e4e929c5590625"
10032dependencies = [
101− "bytestring",
102− "http",
103− "log",
104− "regex",
105− "serde",
33+ "async-stream-impl",
34+ "futures-core",
10635]
10736
10837[[package]]
109−name = "actix-rt"
110−version = "1.1.1"
38+name = "async-stream-impl"
39+version = "0.3.2"
11140source = "registry+https://github.com/rust-lang/crates.io-index"
112−checksum = "143fcc2912e0d1de2bcf4e2f720d2a60c28652ab4179685a1ee159e0fb3db227"
41+checksum = "648ed8c8d2ce5409ccd57453d9d1b214b342a0d69376a6feda1fd6cae3299308"
11342dependencies = [
114− "actix-macros",
115− "actix-threadpool",
116− "copyless",
117− "futures-channel",
118− "futures-util",
119− "smallvec",
120− "tokio",
43+ "proc-macro2",
44+ "quote",
45+ "syn",
12146]
12247
12348[[package]]
124−name = "actix-server"
125−version = "1.0.4"
49+name = "async-trait"
50+version = "0.1.51"
12651source = "registry+https://github.com/rust-lang/crates.io-index"
127−checksum = "45407e6e672ca24784baa667c5d32ef109ccdd8d5e0b5ebb9ef8a67f4dfb708e"
52+checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e"
12853dependencies = [
129− "actix-codec",
130− "actix-rt",
131− "actix-service",
132− "actix-utils",
133− "futures-channel",
134− "futures-util",
135− "log",
136− "mio",
137− "mio-uds",
138− "num_cpus",
139− "slab",
140− "socket2",
54+ "proc-macro2",
55+ "quote",
56+ "syn",
14157]
14258
14359[[package]]
144−name = "actix-service"
145−version = "1.0.6"
60+name = "atty"
61+version = "0.2.14"
14662source = "registry+https://github.com/rust-lang/crates.io-index"
147−checksum = "0052435d581b5be835d11f4eb3bce417c8af18d87ddf8ace99f8e67e595882bb"
63+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
14864dependencies = [
149− "futures-util",
150− "pin-project 0.4.27",
65+ "hermit-abi",
66+ "libc",
67+ "winapi",
15168]
15269
15370[[package]]
154−name = "actix-testing"
71+name = "autocfg"
15572version = "1.0.1"
15673source = "registry+https://github.com/rust-lang/crates.io-index"
157−checksum = "47239ca38799ab74ee6a8a94d1ce857014b2ac36f242f70f3f75a66f691e791c"
158−dependencies = [
159− "actix-macros",
160− "actix-rt",
161− "actix-server",
162− "actix-service",
163− "log",
164− "socket2",
165−]
166−
167−[[package]]
168−name = "actix-threadpool"
169−version = "0.3.3"
170−source = "registry+https://github.com/rust-lang/crates.io-index"
171−checksum = "d209f04d002854b9afd3743032a27b066158817965bf5d036824d19ac2cc0e30"
172−dependencies = [
173− "derive_more",
174− "futures-channel",
175− "lazy_static",
176− "log",
177− "num_cpus",
178− "parking_lot",
179− "threadpool",
180−]
181−
182−[[package]]
183−name = "actix-tls"
184−version = "2.0.0"
185−source = "registry+https://github.com/rust-lang/crates.io-index"
186−checksum = "24789b7d7361cf5503a504ebe1c10806896f61e96eca9a7350e23001aca715fb"
187−dependencies = [
188− "actix-codec",
189− "actix-service",
190− "actix-utils",
191− "futures-util",
192−]
193−
194−[[package]]
195−name = "actix-utils"
196−version = "2.0.0"
197−source = "registry+https://github.com/rust-lang/crates.io-index"
198−checksum = "2e9022dec56632d1d7979e59af14f0597a28a830a9c1c7fec8b2327eb9f16b5a"
199−dependencies = [
200− "actix-codec",
201− "actix-rt",
202− "actix-service",
203− "bitflags",
204− "bytes",
205− "either",
206− "futures-channel",
207− "futures-sink",
208− "futures-util",
209− "log",
210− "pin-project 0.4.27",
211− "slab",
212−]
213−
214−[[package]]
215−name = "actix-web"
216−version = "3.3.2"
217−source = "registry+https://github.com/rust-lang/crates.io-index"
218−checksum = "e641d4a172e7faa0862241a20ff4f1f5ab0ab7c279f00c2d4587b77483477b86"
219−dependencies = [
220− "actix-codec",
221− "actix-http",
222− "actix-macros",
223− "actix-router",
224− "actix-rt",
225− "actix-server",
226− "actix-service",
227− "actix-testing",
228− "actix-threadpool",
229− "actix-tls",
230− "actix-utils",
231− "actix-web-codegen",
232− "awc",
233− "bytes",
234− "derive_more",
235− "encoding_rs",
236− "futures-channel",
237− "futures-core",
238− "futures-util",
239− "fxhash",
240− "log",
241− "mime",
242− "pin-project 1.0.2",
243− "regex",
244− "serde",
245− "serde_json",
246− "serde_urlencoded",
247− "socket2",
248− "time",
249− "tinyvec",
250− "url",
251−]
252−
253−[[package]]
254−name = "actix-web-codegen"
255−version = "0.4.0"
256−source = "registry+https://github.com/rust-lang/crates.io-index"
257−checksum = "ad26f77093333e0e7c6ffe54ebe3582d908a104e448723eec6d43d08b07143fb"
258−dependencies = [
259− "proc-macro2",
260− "quote",
261− "syn",
262−]
74+checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
26375
26476[[package]]
265−name = "addr2line"
266−version = "0.14.0"
77+name = "base64"
78+version = "0.13.0"
26779source = "registry+https://github.com/rust-lang/crates.io-index"
268−checksum = "7c0929d69e78dd9bf5408269919fcbcaeb2e35e5d43e5815517cdc6a8e11a423"
269−dependencies = [
270− "gimli",
271−]
80+checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
27281
27382[[package]]
274−name = "adler"
275−version = "0.2.3"
83+name = "bitflags"
84+version = "1.3.2"
27685source = "registry+https://github.com/rust-lang/crates.io-index"
277−checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
86+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
27887
27988[[package]]
280−name = "aho-corasick"
281−version = "0.7.15"
89+name = "block-buffer"
90+version = "0.9.0"
28291source = "registry+https://github.com/rust-lang/crates.io-index"
283−checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
92+checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
28493dependencies = [
285− "memchr",
94+ "generic-array",
28695]
28796
28897[[package]]
289−name = "arrayvec"
290−version = "0.5.2"
98+name = "bumpalo"
99+version = "3.8.0"
291100source = "registry+https://github.com/rust-lang/crates.io-index"
292−checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
101+checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
293102
294103[[package]]
295−name = "askama"
296−version = "0.10.5"
104+name = "bytes"
105+version = "1.1.0"
297106source = "registry+https://github.com/rust-lang/crates.io-index"
298−checksum = "d298738b6e47e1034e560e5afe63aa488fea34e25ec11b855a76f0d7b8e73134"
299−dependencies = [
300− "askama_derive",
301− "askama_escape",
302− "askama_shared",
303−]
107+checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
304108
305109[[package]]
306−name = "askama_derive"
307−version = "0.10.5"
110+name = "cc"
111+version = "1.0.71"
308112source = "registry+https://github.com/rust-lang/crates.io-index"
309−checksum = "ca2925c4c290382f9d2fa3d1c1b6a63fa1427099721ecca4749b154cc9c25522"
310−dependencies = [
311− "askama_shared",
312− "proc-macro2",
313− "syn",
314−]
113+checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd"
315114
316115[[package]]
317−name = "askama_escape"
318−version = "0.10.1"
116+name = "cfg-if"
117+version = "1.0.0"
319118source = "registry+https://github.com/rust-lang/crates.io-index"
320−checksum = "90c108c1a94380c89d2215d0ac54ce09796823cca0fd91b299cfff3b33e346fb"
119+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
321120
322121[[package]]
323−name = "askama_shared"
324−version = "0.11.1"
122+name = "chrono"
123+version = "0.4.19"
325124source = "registry+https://github.com/rust-lang/crates.io-index"
326−checksum = "2582b77e0f3c506ec4838a25fa8a5f97b9bed72bb6d3d272ea1c031d8bd373bc"
125+checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
327126dependencies = [
328− "askama_escape",
329− "humansize",
330− "nom",
127+ "libc",
128+ "num-integer",
331129 "num-traits",
332− "percent-encoding",
333− "proc-macro2",
334− "quote",
335130 "serde",
336− "syn",
337− "toml",
338−]
339−
340−[[package]]
341−name = "async-trait"
342−version = "0.1.42"
343−source = "registry+https://github.com/rust-lang/crates.io-index"
344−checksum = "8d3a45e77e34375a7923b1e8febb049bb011f064714a8e17a1a616fef01da13d"
345−dependencies = [
346− "proc-macro2",
347− "quote",
348− "syn",
131+ "time",
132+ "winapi",
349133]
350134
351135[[package]]
352−name = "autocfg"
353−version = "1.0.1"
136+name = "clap"
137+version = "2.33.3"
354138source = "registry+https://github.com/rust-lang/crates.io-index"
355−checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
356−
357−[[package]]
358−name = "awc"
359−version = "2.0.3"
360−source = "registry+https://github.com/rust-lang/crates.io-index"
361−checksum = "b381e490e7b0cfc37ebc54079b0413d8093ef43d14a4e4747083f7fa47a9e691"
139+checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
362140dependencies = [
363− "actix-codec",
364− "actix-http",
365− "actix-rt",
366− "actix-service",
367− "base64",
368− "bytes",
369− "cfg-if 1.0.0",
370− "derive_more",
371− "futures-core",
372− "log",
373− "mime",
374− "percent-encoding",
375− "rand",
376− "serde",
377− "serde_json",
378− "serde_urlencoded",
141+ "ansi_term",
142+ "atty",
143+ "bitflags",
144+ "strsim 0.8.0",
145+ "textwrap",
146+ "unicode-width",
147+ "vec_map",
379148]
380149
381150[[package]]
382−name = "backtrace"
383−version = "0.3.55"
151+name = "core-foundation"
152+version = "0.9.2"
384153source = "registry+https://github.com/rust-lang/crates.io-index"
385−checksum = "ef5140344c85b01f9bbb4d4b7288a8aa4b3287ccef913a14bcc78a1063623598"
154+checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3"
386155dependencies = [
387− "addr2line",
388− "cfg-if 1.0.0",
156+ "core-foundation-sys",
389157 "libc",
390− "miniz_oxide",
391− "object",
392− "rustc-demangle",
393158]
394159
395160[[package]]
396−name = "base-x"
397−version = "0.2.8"
161+name = "core-foundation-sys"
162+version = "0.8.3"
398163source = "registry+https://github.com/rust-lang/crates.io-index"
399−checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b"
400−
401−[[package]]
402−name = "base64"
403−version = "0.13.0"
404−source = "registry+https://github.com/rust-lang/crates.io-index"
405−checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
164+checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
406165
407166[[package]]
408−name = "bitflags"
409−version = "1.2.1"
410−source = "registry+https://github.com/rust-lang/crates.io-index"
411−checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
412−
413−[[package]]
414−name = "bitvec"
415−version = "0.19.4"
167+name = "cpufeatures"
168+version = "0.2.1"
416169source = "registry+https://github.com/rust-lang/crates.io-index"
417−checksum = "a7ba35e9565969edb811639dbebfe34edc0368e472c5018474c8eb2543397f81"
170+checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469"
418171dependencies = [
419− "funty",
420− "radium",
421− "tap",
422− "wyz",
172+ "libc",
423173]
424174
425175[[package]]
426−name = "block-buffer"
427−version = "0.9.0"
176+name = "crc32fast"
177+version = "1.2.1"
428178source = "registry+https://github.com/rust-lang/crates.io-index"
429−checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
179+checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
430180dependencies = [
431− "generic-array",
181+ "cfg-if",
432182]
433183
434184[[package]]
435−name = "brotli-sys"
436−version = "0.3.2"
185+name = "crypto-mac"
186+version = "0.11.1"
437187source = "registry+https://github.com/rust-lang/crates.io-index"
438−checksum = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd"
188+checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714"
439189dependencies = [
440− "cc",
441− "libc",
190+ "generic-array",
191+ "subtle",
442192]
443193
444194[[package]]
445−name = "brotli2"
446−version = "0.3.2"
195+name = "darling"
196+version = "0.12.4"
447197source = "registry+https://github.com/rust-lang/crates.io-index"
448−checksum = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e"
198+checksum = "5f2c43f534ea4b0b049015d00269734195e6d3f0f6635cb692251aca6f9f8b3c"
449199dependencies = [
450− "brotli-sys",
451− "libc",
200+ "darling_core",
201+ "darling_macro",
452202]
453203
454204[[package]]
455−name = "bumpalo"
456−version = "3.4.0"
457−source = "registry+https://github.com/rust-lang/crates.io-index"
458−checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820"
459−
460−[[package]]
461−name = "byteorder"
462−version = "1.3.4"
463−source = "registry+https://github.com/rust-lang/crates.io-index"
464−checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
465−
466−[[package]]
467−name = "bytes"
468−version = "0.5.6"
205+name = "darling_core"
206+version = "0.12.4"
469207source = "registry+https://github.com/rust-lang/crates.io-index"
470−checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
471−
472−[[package]]
473−name = "bytestring"
474−version = "0.1.5"
475−source = "registry+https://github.com/rust-lang/crates.io-index"
476−checksum = "fc7c05fa5172da78a62d9949d662d2ac89d4cc7355d7b49adee5163f1fb3f363"
208+checksum = "8e91455b86830a1c21799d94524df0845183fa55bafd9aa137b01c7d1065fa36"
477209dependencies = [
478− "bytes",
210+ "fnv",
211+ "ident_case",
212+ "proc-macro2",
213+ "quote",
214+ "strsim 0.10.0",
215+ "syn",
479216]
480217
481218[[package]]
482−name = "cc"
483−version = "1.0.65"
484−source = "registry+https://github.com/rust-lang/crates.io-index"
485−checksum = "95752358c8f7552394baf48cd82695b345628ad3f170d607de3ca03b8dacca15"
486−
487−[[package]]
488−name = "cfg-if"
489−version = "0.1.10"
490−source = "registry+https://github.com/rust-lang/crates.io-index"
491−checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
492−
493−[[package]]
494−name = "cfg-if"
495−version = "1.0.0"
219+name = "darling_macro"
220+version = "0.12.4"
496221source = "registry+https://github.com/rust-lang/crates.io-index"
497−checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
498−
499−[[package]]
500−name = "cloudabi"
501−version = "0.1.0"
502−source = "registry+https://github.com/rust-lang/crates.io-index"
503−checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467"
222+checksum = "29b5acf0dea37a7f66f7b25d2c5e93fd46f8f6968b1a5d7a3e02e97768afc95a"
504223dependencies = [
505− "bitflags",
224+ "darling_core",
225+ "quote",
226+ "syn",
506227]
507228
508229[[package]]
509−name = "const_fn"
510−version = "0.4.3"
511−source = "registry+https://github.com/rust-lang/crates.io-index"
512−checksum = "c478836e029dcef17fb47c89023448c64f781a046e0300e257ad8225ae59afab"
513−
514−[[package]]
515−name = "cookie"
516−version = "0.14.3"
230+name = "digest"
231+version = "0.9.0"
517232source = "registry+https://github.com/rust-lang/crates.io-index"
518−checksum = "784ad0fbab4f3e9cef09f20e0aea6000ae08d2cb98ac4c0abc53df18803d702f"
233+checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
519234dependencies = [
520− "percent-encoding",
521− "time",
522− "version_check",
235+ "generic-array",
523236]
524237
525238[[package]]
526−name = "copyless"
527−version = "0.1.5"
528−source = "registry+https://github.com/rust-lang/crates.io-index"
529−checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536"
530−
531−[[package]]
532−name = "cpuid-bool"
533−version = "0.1.2"
239+name = "dirs-next"
240+version = "2.0.0"
534241source = "registry+https://github.com/rust-lang/crates.io-index"
535−checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634"
242+checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
243+dependencies = [
244+ "cfg-if",
245+ "dirs-sys-next",
246+]
536247
537248[[package]]
538−name = "crc32fast"
539−version = "1.2.1"
249+name = "dirs-sys-next"
250+version = "0.1.2"
540251source = "registry+https://github.com/rust-lang/crates.io-index"
541−checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
252+checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
542253dependencies = [
543− "cfg-if 1.0.0",
254+ "libc",
255+ "redox_users",
256+ "winapi",
544257]
545258
546259[[package]]
547−name = "derive_more"
548−version = "0.99.11"
549−source = "registry+https://github.com/rust-lang/crates.io-index"
550−checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c"
260+name = "dkregistry"
261+version = "0.5.1-alpha.0"
262+source = "git+https://github.com/camallo/dkregistry-rs?rev=854d0da53bef5dd85b5e901123e85d43af97c74e#854d0da53bef5dd85b5e901123e85d43af97c74e"
551263dependencies = [
552− "proc-macro2",
553− "quote",
554− "syn",
264+ "async-stream",
265+ "base64",
266+ "futures",
267+ "http",
268+ "libflate",
269+ "log",
270+ "mime",
271+ "regex",
272+ "reqwest",
273+ "serde",
274+ "serde_ignored",
275+ "serde_json",
276+ "sha2",
277+ "strum",
278+ "strum_macros",
279+ "tar",
280+ "thiserror",
281+ "tokio",
282+ "url",
555283]
556284
557285[[package]]
558−name = "digest"
559−version = "0.9.0"
286+name = "dtoa"
287+version = "0.4.8"
560288source = "registry+https://github.com/rust-lang/crates.io-index"
561−checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
562−dependencies = [
563− "generic-array",
564−]
289+checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0"
565290
566291[[package]]
567−name = "discard"
292+name = "dyn-clone"
568293version = "1.0.4"
569294source = "registry+https://github.com/rust-lang/crates.io-index"
570−checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
295+checksum = "ee2626afccd7561a06cf1367e2950c4718ea04565e20fb5029b6c7d8ad09abcf"
571296
572297[[package]]
573298name = "either"
@@ -577,35 +302,45 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
577302
578303[[package]]
579304name = "encoding_rs"
580−version = "0.8.26"
305+version = "0.8.29"
581306source = "registry+https://github.com/rust-lang/crates.io-index"
582−checksum = "801bbab217d7f79c0062f4f7205b5d4427c6d1a7bd7aafdd1475f7c59d62b283"
307+checksum = "a74ea89a0a1b98f6332de42c95baff457ada66d1cb4030f9ff151b2041a1c746"
583308dependencies = [
584− "cfg-if 1.0.0",
309+ "cfg-if",
585310]
586311
587312[[package]]
588−name = "enum-as-inner"
589−version = "0.3.3"
313+name = "env_logger"
314+version = "0.8.4"
590315source = "registry+https://github.com/rust-lang/crates.io-index"
591−checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595"
316+checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3"
592317dependencies = [
593− "heck",
594− "proc-macro2",
595− "quote",
596− "syn",
318+ "atty",
319+ "humantime",
320+ "log",
321+ "regex",
322+ "termcolor",
597323]
598324
599325[[package]]
600−name = "flate2"
601−version = "1.0.19"
326+name = "envy"
327+version = "0.4.2"
602328source = "registry+https://github.com/rust-lang/crates.io-index"
603−checksum = "7411863d55df97a419aa64cb4d2f167103ea9d767e2c54a1868b7ac3f6b47129"
329+checksum = "3f47e0157f2cb54f5ae1bd371b30a2ae4311e1c028f575cd4e81de7353215965"
604330dependencies = [
605− "cfg-if 1.0.0",
606− "crc32fast",
331+ "serde",
332+]
333+
334+[[package]]
335+name = "filetime"
336+version = "0.2.15"
337+source = "registry+https://github.com/rust-lang/crates.io-index"
338+checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98"
339+dependencies = [
340+ "cfg-if",
607341 "libc",
608− "miniz_oxide",
342+ "redox_syscall",
343+ "winapi",
609344]
610345
611346[[package]]
@@ -615,45 +350,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
615350checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
616351
617352[[package]]
618−name = "form_urlencoded"
619−version = "1.0.0"
620−source = "registry+https://github.com/rust-lang/crates.io-index"
621−checksum = "ece68d15c92e84fa4f19d3780f1294e5ca82a78a6d515f1efaabcc144688be00"
622−dependencies = [
623− "matches",
624− "percent-encoding",
625−]
626−
627−[[package]]
628−name = "fuchsia-zircon"
629−version = "0.3.3"
353+name = "foreign-types"
354+version = "0.3.2"
630355source = "registry+https://github.com/rust-lang/crates.io-index"
631−checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
356+checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
632357dependencies = [
633− "bitflags",
634− "fuchsia-zircon-sys",
358+ "foreign-types-shared",
635359]
636360
637361[[package]]
638−name = "fuchsia-zircon-sys"
639−version = "0.3.3"
362+name = "foreign-types-shared"
363+version = "0.1.1"
640364source = "registry+https://github.com/rust-lang/crates.io-index"
641−checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
365+checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
642366
643367[[package]]
644−name = "funty"
368+name = "form_urlencoded"
645369version = "1.0.1"
646370source = "registry+https://github.com/rust-lang/crates.io-index"
647−checksum = "0ba62103ce691c2fd80fbae2213dfdda9ce60804973ac6b6e97de818ea7f52c8"
371+checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
372+dependencies = [
373+ "matches",
374+ "percent-encoding",
375+]
648376
649377[[package]]
650378name = "futures"
651−version = "0.3.8"
379+version = "0.3.17"
652380source = "registry+https://github.com/rust-lang/crates.io-index"
653−checksum = "9b3b0c040a1fe6529d30b3c5944b280c7f0dcb2930d2c3062bca967b602583d0"
381+checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca"
654382dependencies = [
655383 "futures-channel",
656384 "futures-core",
385+ "futures-executor",
657386 "futures-io",
658387 "futures-sink",
659388 "futures-task",
@@ -662,9 +391,9 @@ dependencies = [
662391
663392[[package]]
664393name = "futures-channel"
665−version = "0.3.8"
394+version = "0.3.17"
666395source = "registry+https://github.com/rust-lang/crates.io-index"
667−checksum = "4b7109687aa4e177ef6fe84553af6280ef2778bdb7783ba44c9dc3399110fe64"
396+checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888"
668397dependencies = [
669398 "futures-core",
670399 "futures-sink",
@@ -672,22 +401,34 @@ dependencies = [
672401
673402[[package]]
674403name = "futures-core"
675−version = "0.3.8"
404+version = "0.3.17"
405+source = "registry+https://github.com/rust-lang/crates.io-index"
406+checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d"
407+
408+[[package]]
409+name = "futures-executor"
410+version = "0.3.17"
676411source = "registry+https://github.com/rust-lang/crates.io-index"
677−checksum = "847ce131b72ffb13b6109a221da9ad97a64cbe48feb1028356b836b47b8f1748"
412+checksum = "45025be030969d763025784f7f355043dc6bc74093e4ecc5000ca4dc50d8745c"
413+dependencies = [
414+ "futures-core",
415+ "futures-task",
416+ "futures-util",
417+]
678418
679419[[package]]
680420name = "futures-io"
681−version = "0.3.8"
421+version = "0.3.17"
682422source = "registry+https://github.com/rust-lang/crates.io-index"
683−checksum = "611834ce18aaa1bd13c4b374f5d653e1027cf99b6b502584ff8c9a64413b30bb"
423+checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377"
684424
685425[[package]]
686426name = "futures-macro"
687−version = "0.3.8"
427+version = "0.3.17"
688428source = "registry+https://github.com/rust-lang/crates.io-index"
689−checksum = "77408a692f1f97bcc61dc001d752e00643408fbc922e4d634c655df50d595556"
429+checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb"
690430dependencies = [
431+ "autocfg",
691432 "proc-macro-hack",
692433 "proc-macro2",
693434 "quote",
@@ -696,25 +437,23 @@ dependencies = [
696437
697438[[package]]
698439name = "futures-sink"
699−version = "0.3.8"
440+version = "0.3.17"
700441source = "registry+https://github.com/rust-lang/crates.io-index"
701−checksum = "f878195a49cee50e006b02b93cf7e0a95a38ac7b776b4c4d9cc1207cd20fcb3d"
442+checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11"
702443
703444[[package]]
704445name = "futures-task"
705−version = "0.3.8"
446+version = "0.3.17"
706447source = "registry+https://github.com/rust-lang/crates.io-index"
707−checksum = "7c554eb5bf48b2426c4771ab68c6b14468b6e76cc90996f528c3338d761a4d0d"
708−dependencies = [
709− "once_cell",
710−]
448+checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99"
711449
712450[[package]]
713451name = "futures-util"
714−version = "0.3.8"
452+version = "0.3.17"
715453source = "registry+https://github.com/rust-lang/crates.io-index"
716−checksum = "d304cff4a7b99cfb7986f7d43fbe93d175e72e704a8860787cc95e9ffd85cbd2"
454+checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481"
717455dependencies = [
456+ "autocfg",
718457 "futures-channel",
719458 "futures-core",
720459 "futures-io",
@@ -722,22 +461,13 @@ dependencies = [
722461 "futures-sink",
723462 "futures-task",
724463 "memchr",
725− "pin-project 1.0.2",
464+ "pin-project-lite",
726465 "pin-utils",
727466 "proc-macro-hack",
728467 "proc-macro-nested",
729468 "slab",
730469]
731470
732−[[package]]
733−name = "fxhash"
734−version = "0.2.1"
735−source = "registry+https://github.com/rust-lang/crates.io-index"
736−checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
737−dependencies = [
738− "byteorder",
739−]
740−
741471[[package]]
742472name = "generic-array"
743473version = "0.14.4"
@@ -750,26 +480,20 @@ dependencies = [
750480
751481[[package]]
752482name = "getrandom"
753−version = "0.1.15"
483+version = "0.2.3"
754484source = "registry+https://github.com/rust-lang/crates.io-index"
755−checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6"
485+checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
756486dependencies = [
757− "cfg-if 0.1.10",
487+ "cfg-if",
758488 "libc",
759489 "wasi",
760490]
761491
762−[[package]]
763−name = "gimli"
764−version = "0.23.0"
765−source = "registry+https://github.com/rust-lang/crates.io-index"
766−checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce"
767−
768492[[package]]
769493name = "h2"
770−version = "0.2.7"
494+version = "0.3.6"
771495source = "registry+https://github.com/rust-lang/crates.io-index"
772−checksum = "5e4728fd124914ad25e99e3d15a9361a879f6620f63cb56bbb08f95abb97a535"
496+checksum = "6c06815895acec637cd6ed6e9662c935b866d20a106f8361892893a7d9234964"
773497dependencies = [
774498 "bytes",
775499 "fnv",
@@ -782,72 +506,171 @@ dependencies = [
782506 "tokio",
783507 "tokio-util",
784508 "tracing",
785− "tracing-futures",
786509]
787510
788511[[package]]
789512name = "hashbrown"
790−version = "0.9.1"
513+version = "0.11.2"
791514source = "registry+https://github.com/rust-lang/crates.io-index"
792−checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
515+checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
793516
794517[[package]]
795518name = "heck"
796−version = "0.3.1"
519+version = "0.3.3"
797520source = "registry+https://github.com/rust-lang/crates.io-index"
798−checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
521+checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
799522dependencies = [
800523 "unicode-segmentation",
801524]
802525
526+[[package]]
527+name = "helm-control-scripts"
528+version = "0.2.3"
529+dependencies = [
530+ "dkregistry",
531+ "env_logger",
532+ "envy",
533+ "json-patch",
534+ "k8s-openapi",
535+ "kube",
536+ "log",
537+ "regex",
538+ "rusoto_core",
539+ "rusoto_ecr",
540+ "schemars",
541+ "serde",
542+ "serde_json",
543+ "serde_yaml",
544+ "structopt",
545+ "tokio",
546+ "yaml-rust",
547+]
548+
803549[[package]]
804550name = "hermit-abi"
805−version = "0.1.17"
551+version = "0.1.19"
806552source = "registry+https://github.com/rust-lang/crates.io-index"
807−checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8"
553+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
808554dependencies = [
809555 "libc",
810556]
811557
812558[[package]]
813−name = "hostname"
814−version = "0.3.1"
559+name = "hex"
560+version = "0.4.3"
561+source = "registry+https://github.com/rust-lang/crates.io-index"
562+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
563+
564+[[package]]
565+name = "hmac"
566+version = "0.11.0"
815567source = "registry+https://github.com/rust-lang/crates.io-index"
816−checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867"
568+checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b"
817569dependencies = [
818− "libc",
819− "match_cfg",
820− "winapi 0.3.9",
570+ "crypto-mac",
571+ "digest",
821572]
822573
823574[[package]]
824575name = "http"
825−version = "0.2.1"
576+version = "0.2.5"
826577source = "registry+https://github.com/rust-lang/crates.io-index"
827−checksum = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9"
578+checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b"
828579dependencies = [
829580 "bytes",
830581 "fnv",
831582 "itoa",
832583]
833584
585+[[package]]
586+name = "http-body"
587+version = "0.4.3"
588+source = "registry+https://github.com/rust-lang/crates.io-index"
589+checksum = "399c583b2979440c60be0821a6199eca73bc3c8dcd9d070d75ac726e2c6186e5"
590+dependencies = [
591+ "bytes",
592+ "http",
593+ "pin-project-lite",
594+]
595+
834596[[package]]
835597name = "httparse"
836−version = "1.3.4"
598+version = "1.5.1"
837599source = "registry+https://github.com/rust-lang/crates.io-index"
838−checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
600+checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503"
839601
840602[[package]]
841−name = "humansize"
842−version = "1.1.0"
603+name = "httpdate"
604+version = "1.0.1"
605+source = "registry+https://github.com/rust-lang/crates.io-index"
606+checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440"
607+
608+[[package]]
609+name = "humantime"
610+version = "2.1.0"
611+source = "registry+https://github.com/rust-lang/crates.io-index"
612+checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
613+
614+[[package]]
615+name = "hyper"
616+version = "0.14.13"
617+source = "registry+https://github.com/rust-lang/crates.io-index"
618+checksum = "15d1cfb9e4f68655fa04c01f59edb405b6074a0f7118ea881e5026e4a1cd8593"
619+dependencies = [
620+ "bytes",
621+ "futures-channel",
622+ "futures-core",
623+ "futures-util",
624+ "h2",
625+ "http",
626+ "http-body",
627+ "httparse",
628+ "httpdate",
629+ "itoa",
630+ "pin-project-lite",
631+ "socket2",
632+ "tokio",
633+ "tower-service",
634+ "tracing",
635+ "want",
636+]
637+
638+[[package]]
639+name = "hyper-timeout"
640+version = "0.4.1"
641+source = "registry+https://github.com/rust-lang/crates.io-index"
642+checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1"
643+dependencies = [
644+ "hyper",
645+ "pin-project-lite",
646+ "tokio",
647+ "tokio-io-timeout",
648+]
649+
650+[[package]]
651+name = "hyper-tls"
652+version = "0.5.0"
653+source = "registry+https://github.com/rust-lang/crates.io-index"
654+checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
655+dependencies = [
656+ "bytes",
657+ "hyper",
658+ "native-tls",
659+ "tokio",
660+ "tokio-native-tls",
661+]
662+
663+[[package]]
664+name = "ident_case"
665+version = "1.0.1"
843666source = "registry+https://github.com/rust-lang/crates.io-index"
844−checksum = "b6cab2627acfc432780848602f3f558f7e9dd427352224b0d9324025796d2a5e"
667+checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
845668
846669[[package]]
847670name = "idna"
848−version = "0.2.0"
671+version = "0.2.3"
849672source = "registry+https://github.com/rust-lang/crates.io-index"
850−checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
673+checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
851674dependencies = [
852675 "matches",
853676 "unicode-bidi",
@@ -856,9 +679,9 @@ dependencies = [
856679
857680[[package]]
858681name = "indexmap"
859−version = "1.6.0"
682+version = "1.7.0"
860683source = "registry+https://github.com/rust-lang/crates.io-index"
861−checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2"
684+checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
862685dependencies = [
863686 "autocfg",
864687 "hashbrown",
@@ -866,55 +689,136 @@ dependencies = [
866689
867690[[package]]
868691name = "instant"
869−version = "0.1.9"
692+version = "0.1.12"
870693source = "registry+https://github.com/rust-lang/crates.io-index"
871−checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
694+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
872695dependencies = [
873− "cfg-if 1.0.0",
696+ "cfg-if",
874697]
875698
876699[[package]]
877−name = "iovec"
878−version = "0.1.4"
700+name = "ipnet"
701+version = "2.3.1"
702+source = "registry+https://github.com/rust-lang/crates.io-index"
703+checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9"
704+
705+[[package]]
706+name = "itoa"
707+version = "0.4.8"
708+source = "registry+https://github.com/rust-lang/crates.io-index"
709+checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
710+
711+[[package]]
712+name = "js-sys"
713+version = "0.3.55"
879714source = "registry+https://github.com/rust-lang/crates.io-index"
880−checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
715+checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84"
881716dependencies = [
882− "libc",
717+ "wasm-bindgen",
883718]
884719
885720[[package]]
886−name = "ipconfig"
887−version = "0.2.2"
721+name = "json-patch"
722+version = "0.2.6"
888723source = "registry+https://github.com/rust-lang/crates.io-index"
889−checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7"
724+checksum = "f995a3c8f2bc3dd52a18a583e90f9ec109c047fa1603a853e46bcda14d2e279d"
890725dependencies = [
891− "socket2",
892− "widestring",
893− "winapi 0.3.9",
894− "winreg",
726+ "serde",
727+ "serde_json",
728+ "treediff",
895729]
896730
897731[[package]]
898−name = "itoa"
899−version = "0.4.6"
732+name = "jsonpath_lib"
733+version = "0.3.0"
734+source = "registry+https://github.com/rust-lang/crates.io-index"
735+checksum = "eaa63191d68230cccb81c5aa23abd53ed64d83337cacbb25a7b8c7979523774f"
736+dependencies = [
737+ "log",
738+ "serde",
739+ "serde_json",
740+]
741+
742+[[package]]
743+name = "k8s-openapi"
744+version = "0.12.0"
900745source = "registry+https://github.com/rust-lang/crates.io-index"
901−checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
746+checksum = "fbff78f6da26dde0d74188966d23fc763431d730d0f766ecf7699209f8fc243c"
747+dependencies = [
748+ "base64",
749+ "bytes",
750+ "chrono",
751+ "http",
752+ "percent-encoding",
753+ "serde",
754+ "serde-value",
755+ "serde_json",
756+ "url",
757+]
902758
903759[[package]]
904−name = "kernel32-sys"
905−version = "0.2.2"
760+name = "kube"
761+version = "0.58.1"
906762source = "registry+https://github.com/rust-lang/crates.io-index"
907−checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
763+checksum = "21d3c79fb97a822a63ce9422f7302484748032c808954898ba248705e99ea110"
908764dependencies = [
909− "winapi 0.2.8",
910− "winapi-build",
765+ "base64",
766+ "bytes",
767+ "chrono",
768+ "dirs-next",
769+ "either",
770+ "futures",
771+ "http",
772+ "http-body",
773+ "hyper",
774+ "hyper-timeout",
775+ "hyper-tls",
776+ "jsonpath_lib",
777+ "k8s-openapi",
778+ "kube-core",
779+ "kube-derive",
780+ "openssl",
781+ "pem",
782+ "pin-project",
783+ "serde",
784+ "serde_json",
785+ "serde_yaml",
786+ "thiserror",
787+ "tokio",
788+ "tokio-native-tls",
789+ "tokio-util",
790+ "tower",
791+ "tower-http",
792+ "tracing",
911793]
912794
913795[[package]]
914−name = "language-tags"
915−version = "0.2.2"
796+name = "kube-core"
797+version = "0.58.1"
798+source = "registry+https://github.com/rust-lang/crates.io-index"
799+checksum = "ffbce0d890efc42abb31e974419e25a643a97ab7c6b3b9498bda686d10b55f8d"
800+dependencies = [
801+ "form_urlencoded",
802+ "http",
803+ "json-patch",
804+ "k8s-openapi",
805+ "serde",
806+ "serde_json",
807+ "thiserror",
808+]
809+
810+[[package]]
811+name = "kube-derive"
812+version = "0.58.1"
916813source = "registry+https://github.com/rust-lang/crates.io-index"
917−checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
814+checksum = "95a28be5ca4f233b5dd872f426fdc75d6765c34576b590c44564982c05fdb400"
815+dependencies = [
816+ "darling",
817+ "proc-macro2",
818+ "quote",
819+ "serde_json",
820+ "syn",
821+]
918822
919823[[package]]
920824name = "lazy_static"
@@ -923,74 +827,77 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
923827checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
924828
925829[[package]]
926−name = "lexical-core"
927−version = "0.7.4"
830+name = "libc"
831+version = "0.2.104"
832+source = "registry+https://github.com/rust-lang/crates.io-index"
833+checksum = "7b2f96d100e1cf1929e7719b7edb3b90ab5298072638fccd77be9ce942ecdfce"
834+
835+[[package]]
836+name = "libflate"
837+version = "1.1.1"
928838source = "registry+https://github.com/rust-lang/crates.io-index"
929−checksum = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616"
839+checksum = "16364af76ebb39b5869bb32c81fa93573267cd8c62bb3474e28d78fac3fb141e"
930840dependencies = [
931− "arrayvec",
932− "bitflags",
933− "cfg-if 0.1.10",
934− "ryu",
935− "static_assertions",
841+ "adler32",
842+ "crc32fast",
843+ "libflate_lz77",
936844]
937845
938846[[package]]
939−name = "libc"
940−version = "0.2.80"
847+name = "libflate_lz77"
848+version = "1.1.0"
941849source = "registry+https://github.com/rust-lang/crates.io-index"
942−checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
850+checksum = "39a734c0493409afcd49deee13c006a04e3586b9761a03543c6272c9c51f2f5a"
851+dependencies = [
852+ "rle-decode-fast",
853+]
943854
944855[[package]]
945856name = "linked-hash-map"
946−version = "0.5.3"
857+version = "0.5.4"
947858source = "registry+https://github.com/rust-lang/crates.io-index"
948−checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
859+checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
949860
950861[[package]]
951862name = "lock_api"
952−version = "0.4.2"
863+version = "0.4.5"
953864source = "registry+https://github.com/rust-lang/crates.io-index"
954−checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312"
865+checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109"
955866dependencies = [
956867 "scopeguard",
957868]
958869
959870[[package]]
960871name = "log"
961−version = "0.4.11"
962−source = "registry+https://github.com/rust-lang/crates.io-index"
963−checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
964−dependencies = [
965− "cfg-if 0.1.10",
966−]
967−
968−[[package]]
969−name = "lru-cache"
970−version = "0.1.2"
872+version = "0.4.14"
971873source = "registry+https://github.com/rust-lang/crates.io-index"
972−checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
874+checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
973875dependencies = [
974− "linked-hash-map",
876+ "cfg-if",
975877]
976878
977879[[package]]
978−name = "match_cfg"
979−version = "0.1.0"
880+name = "matches"
881+version = "0.1.9"
980882source = "registry+https://github.com/rust-lang/crates.io-index"
981−checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
883+checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
982884
983885[[package]]
984−name = "matches"
985−version = "0.1.8"
886+name = "md-5"
887+version = "0.9.1"
986888source = "registry+https://github.com/rust-lang/crates.io-index"
987−checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
889+checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15"
890+dependencies = [
891+ "block-buffer",
892+ "digest",
893+ "opaque-debug",
894+]
988895
989896[[package]]
990897name = "memchr"
991−version = "2.3.4"
898+version = "2.4.1"
992899source = "registry+https://github.com/rust-lang/crates.io-index"
993−checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
900+checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
994901
995902[[package]]
996903name = "mime"
@@ -998,79 +905,63 @@ version = "0.3.16"
998905source = "registry+https://github.com/rust-lang/crates.io-index"
999906checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
1000907
1001−[[package]]
1002−name = "miniz_oxide"
1003−version = "0.4.3"
1004−source = "registry+https://github.com/rust-lang/crates.io-index"
1005−checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d"
1006−dependencies = [
1007− "adler",
1008− "autocfg",
1009−]
1010−
1011908[[package]]
1012909name = "mio"
1013−version = "0.6.23"
910+version = "0.7.14"
1014911source = "registry+https://github.com/rust-lang/crates.io-index"
1015−checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4"
912+checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc"
1016913dependencies = [
1017− "cfg-if 0.1.10",
1018− "fuchsia-zircon",
1019− "fuchsia-zircon-sys",
1020− "iovec",
1021− "kernel32-sys",
1022914 "libc",
1023915 "log",
1024916 "miow",
1025− "net2",
1026− "slab",
1027− "winapi 0.2.8",
917+ "ntapi",
918+ "winapi",
1028919]
1029920
1030921[[package]]
1031−name = "mio-uds"
1032−version = "0.6.8"
922+name = "miow"
923+version = "0.3.7"
1033924source = "registry+https://github.com/rust-lang/crates.io-index"
1034−checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0"
925+checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
1035926dependencies = [
1036− "iovec",
1037− "libc",
1038− "mio",
927+ "winapi",
1039928]
1040929
1041930[[package]]
1042−name = "miow"
1043−version = "0.2.2"
931+name = "native-tls"
932+version = "0.2.8"
1044933source = "registry+https://github.com/rust-lang/crates.io-index"
1045−checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d"
934+checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d"
1046935dependencies = [
1047− "kernel32-sys",
1048− "net2",
1049− "winapi 0.2.8",
1050− "ws2_32-sys",
936+ "lazy_static",
937+ "libc",
938+ "log",
939+ "openssl",
940+ "openssl-probe",
941+ "openssl-sys",
942+ "schannel",
943+ "security-framework",
944+ "security-framework-sys",
945+ "tempfile",
1051946]
1052947
1053948[[package]]
1054−name = "net2"
1055−version = "0.2.36"
949+name = "ntapi"
950+version = "0.3.6"
1056951source = "registry+https://github.com/rust-lang/crates.io-index"
1057−checksum = "d7cf75f38f16cb05ea017784dc6dbfd354f76c223dba37701734c4f5a9337d02"
952+checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
1058953dependencies = [
1059− "cfg-if 0.1.10",
1060− "libc",
1061− "winapi 0.3.9",
954+ "winapi",
1062955]
1063956
1064957[[package]]
1065−name = "nom"
1066−version = "6.0.1"
958+name = "num-integer"
959+version = "0.1.44"
1067960source = "registry+https://github.com/rust-lang/crates.io-index"
1068−checksum = "88034cfd6b4a0d54dd14f4a507eceee36c0b70e5a02236c4e4df571102be17f0"
961+checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
1069962dependencies = [
1070− "bitvec",
1071− "lexical-core",
1072− "memchr",
1073− "version_check",
963+ "autocfg",
964+ "num-traits",
1074965]
1075966
1076967[[package]]
@@ -1092,17 +983,11 @@ dependencies = [
1092983 "libc",
1093984]
1094985
1095−[[package]]
1096−name = "object"
1097−version = "0.22.0"
1098−source = "registry+https://github.com/rust-lang/crates.io-index"
1099−checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397"
1100−
1101986[[package]]
1102987name = "once_cell"
1103−version = "1.5.2"
988+version = "1.8.0"
1104989source = "registry+https://github.com/rust-lang/crates.io-index"
1105−checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
990+checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
1106991
1107992[[package]]
1108993name = "opaque-debug"
@@ -1110,11 +995,53 @@ version = "0.3.0"
1110995source = "registry+https://github.com/rust-lang/crates.io-index"
1111996checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
1112997
998+[[package]]
999+name = "openssl"
1000+version = "0.10.36"
1001+source = "registry+https://github.com/rust-lang/crates.io-index"
1002+checksum = "8d9facdb76fec0b73c406f125d44d86fdad818d66fef0531eec9233ca425ff4a"
1003+dependencies = [
1004+ "bitflags",
1005+ "cfg-if",
1006+ "foreign-types",
1007+ "libc",
1008+ "once_cell",
1009+ "openssl-sys",
1010+]
1011+
1012+[[package]]
1013+name = "openssl-probe"
1014+version = "0.1.4"
1015+source = "registry+https://github.com/rust-lang/crates.io-index"
1016+checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a"
1017+
1018+[[package]]
1019+name = "openssl-sys"
1020+version = "0.9.67"
1021+source = "registry+https://github.com/rust-lang/crates.io-index"
1022+checksum = "69df2d8dfc6ce3aaf44b40dec6f487d5a886516cf6879c49e98e0710f310a058"
1023+dependencies = [
1024+ "autocfg",
1025+ "cc",
1026+ "libc",
1027+ "pkg-config",
1028+ "vcpkg",
1029+]
1030+
1031+[[package]]
1032+name = "ordered-float"
1033+version = "2.8.0"
1034+source = "registry+https://github.com/rust-lang/crates.io-index"
1035+checksum = "97c9d06878b3a851e8026ef94bf7fef9ba93062cd412601da4d9cf369b1cc62d"
1036+dependencies = [
1037+ "num-traits",
1038+]
1039+
11131040[[package]]
11141041name = "parking_lot"
1115−version = "0.11.1"
1042+version = "0.11.2"
11161043source = "registry+https://github.com/rust-lang/crates.io-index"
1117−checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
1044+checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
11181045dependencies = [
11191046 "instant",
11201047 "lock_api",
@@ -1123,59 +1050,49 @@ dependencies = [
11231050
11241051[[package]]
11251052name = "parking_lot_core"
1126−version = "0.8.0"
1053+version = "0.8.5"
11271054source = "registry+https://github.com/rust-lang/crates.io-index"
1128−checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b"
1055+checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
11291056dependencies = [
1130− "cfg-if 0.1.10",
1131− "cloudabi",
1057+ "cfg-if",
11321058 "instant",
11331059 "libc",
11341060 "redox_syscall",
11351061 "smallvec",
1136− "winapi 0.3.9",
1062+ "winapi",
11371063]
11381064
11391065[[package]]
1140−name = "percent-encoding"
1141−version = "2.1.0"
1142−source = "registry+https://github.com/rust-lang/crates.io-index"
1143−checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
1144−
1145−[[package]]
1146−name = "pin-project"
1147−version = "0.4.27"
1066+name = "pem"
1067+version = "0.8.3"
11481068source = "registry+https://github.com/rust-lang/crates.io-index"
1149−checksum = "2ffbc8e94b38ea3d2d8ba92aea2983b503cd75d0888d75b86bb37970b5698e15"
1069+checksum = "fd56cbd21fea48d0c440b41cd69c589faacade08c992d9a54e471b79d0fd13eb"
11501070dependencies = [
1151− "pin-project-internal 0.4.27",
1071+ "base64",
1072+ "once_cell",
1073+ "regex",
11521074]
11531075
11541076[[package]]
1155−name = "pin-project"
1156−version = "1.0.2"
1077+name = "percent-encoding"
1078+version = "2.1.0"
11571079source = "registry+https://github.com/rust-lang/crates.io-index"
1158−checksum = "9ccc2237c2c489783abd8c4c80e5450fc0e98644555b1364da68cc29aa151ca7"
1159−dependencies = [
1160− "pin-project-internal 1.0.2",
1161−]
1080+checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
11621081
11631082[[package]]
1164−name = "pin-project-internal"
1165−version = "0.4.27"
1083+name = "pin-project"
1084+version = "1.0.8"
11661085source = "registry+https://github.com/rust-lang/crates.io-index"
1167−checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895"
1086+checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08"
11681087dependencies = [
1169− "proc-macro2",
1170− "quote",
1171− "syn",
1088+ "pin-project-internal",
11721089]
11731090
11741091[[package]]
11751092name = "pin-project-internal"
1176−version = "1.0.2"
1093+version = "1.0.8"
11771094source = "registry+https://github.com/rust-lang/crates.io-index"
1178−checksum = "f8e8d2bf0b23038a4424865103a4df472855692821aab4e4f5c3312d461d9e5f"
1095+checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389"
11791096dependencies = [
11801097 "proc-macro2",
11811098 "quote",
@@ -1184,15 +1101,9 @@ dependencies = [
11841101
11851102[[package]]
11861103name = "pin-project-lite"
1187−version = "0.1.11"
1188−source = "registry+https://github.com/rust-lang/crates.io-index"
1189−checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b"
1190−
1191−[[package]]
1192−name = "pin-project-lite"
1193−version = "0.2.0"
1104+version = "0.2.7"
11941105source = "registry+https://github.com/rust-lang/crates.io-index"
1195−checksum = "6b063f57ec186e6140e2b8b6921e5f1bd89c7356dda5b33acc5401203ca6131c"
1106+checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"
11961107
11971108[[package]]
11981109name = "pin-utils"
@@ -1200,11 +1111,41 @@ version = "0.1.0"
12001111source = "registry+https://github.com/rust-lang/crates.io-index"
12011112checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
12021113
1114+[[package]]
1115+name = "pkg-config"
1116+version = "0.3.20"
1117+source = "registry+https://github.com/rust-lang/crates.io-index"
1118+checksum = "7c9b1041b4387893b91ee6746cddfc28516aff326a3519fb2adf820932c5e6cb"
1119+
12031120[[package]]
12041121name = "ppv-lite86"
1205−version = "0.2.10"
1122+version = "0.2.14"
1123+source = "registry+https://github.com/rust-lang/crates.io-index"
1124+checksum = "c3ca011bd0129ff4ae15cd04c4eef202cadf6c51c21e47aba319b4e0501db741"
1125+
1126+[[package]]
1127+name = "proc-macro-error"
1128+version = "1.0.4"
1129+source = "registry+https://github.com/rust-lang/crates.io-index"
1130+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
1131+dependencies = [
1132+ "proc-macro-error-attr",
1133+ "proc-macro2",
1134+ "quote",
1135+ "syn",
1136+ "version_check",
1137+]
1138+
1139+[[package]]
1140+name = "proc-macro-error-attr"
1141+version = "1.0.4"
12061142source = "registry+https://github.com/rust-lang/crates.io-index"
1207−checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
1143+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
1144+dependencies = [
1145+ "proc-macro2",
1146+ "quote",
1147+ "version_check",
1148+]
12081149
12091150[[package]]
12101151name = "proc-macro-hack"
@@ -1214,47 +1155,34 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
12141155
12151156[[package]]
12161157name = "proc-macro-nested"
1217−version = "0.1.6"
1158+version = "0.1.7"
12181159source = "registry+https://github.com/rust-lang/crates.io-index"
1219−checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a"
1160+checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
12201161
12211162[[package]]
12221163name = "proc-macro2"
1223−version = "1.0.24"
1164+version = "1.0.30"
12241165source = "registry+https://github.com/rust-lang/crates.io-index"
1225−checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
1166+checksum = "edc3358ebc67bc8b7fa0c007f945b0b18226f78437d61bec735a9eb96b61ee70"
12261167dependencies = [
12271168 "unicode-xid",
12281169]
12291170
1230−[[package]]
1231−name = "quick-error"
1232−version = "1.2.3"
1233−source = "registry+https://github.com/rust-lang/crates.io-index"
1234−checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
1235−
12361171[[package]]
12371172name = "quote"
1238−version = "1.0.7"
1173+version = "1.0.10"
12391174source = "registry+https://github.com/rust-lang/crates.io-index"
1240−checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
1175+checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
12411176dependencies = [
12421177 "proc-macro2",
12431178]
12441179
1245−[[package]]
1246−name = "radium"
1247−version = "0.5.3"
1248−source = "registry+https://github.com/rust-lang/crates.io-index"
1249−checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
1250−
12511180[[package]]
12521181name = "rand"
1253−version = "0.7.3"
1182+version = "0.8.4"
12541183source = "registry+https://github.com/rust-lang/crates.io-index"
1255−checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
1184+checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
12561185dependencies = [
1257− "getrandom",
12581186 "libc",
12591187 "rand_chacha",
12601188 "rand_core",
@@ -1263,9 +1191,9 @@ dependencies = [
12631191
12641192[[package]]
12651193name = "rand_chacha"
1266−version = "0.2.2"
1194+version = "0.3.1"
12671195source = "registry+https://github.com/rust-lang/crates.io-index"
1268−checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
1196+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
12691197dependencies = [
12701198 "ppv-lite86",
12711199 "rand_core",
@@ -1273,67 +1201,196 @@ dependencies = [
12731201
12741202[[package]]
12751203name = "rand_core"
1276−version = "0.5.1"
1204+version = "0.6.3"
12771205source = "registry+https://github.com/rust-lang/crates.io-index"
1278−checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
1206+checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
12791207dependencies = [
12801208 "getrandom",
12811209]
12821210
12831211[[package]]
12841212name = "rand_hc"
1285−version = "0.2.0"
1213+version = "0.3.1"
12861214source = "registry+https://github.com/rust-lang/crates.io-index"
1287−checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
1215+checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
12881216dependencies = [
12891217 "rand_core",
12901218]
12911219
12921220[[package]]
12931221name = "redox_syscall"
1294−version = "0.1.57"
1222+version = "0.2.10"
1223+source = "registry+https://github.com/rust-lang/crates.io-index"
1224+checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
1225+dependencies = [
1226+ "bitflags",
1227+]
1228+
1229+[[package]]
1230+name = "redox_users"
1231+version = "0.4.0"
12951232source = "registry+https://github.com/rust-lang/crates.io-index"
1296−checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
1233+checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
1234+dependencies = [
1235+ "getrandom",
1236+ "redox_syscall",
1237+]
12971238
12981239[[package]]
12991240name = "regex"
1300−version = "1.4.2"
1241+version = "1.5.4"
13011242source = "registry+https://github.com/rust-lang/crates.io-index"
1302−checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c"
1243+checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
13031244dependencies = [
13041245 "aho-corasick",
13051246 "memchr",
13061247 "regex-syntax",
1307− "thread_local",
13081248]
13091249
13101250[[package]]
13111251name = "regex-syntax"
1312−version = "0.6.21"
1252+version = "0.6.25"
13131253source = "registry+https://github.com/rust-lang/crates.io-index"
1314−checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
1254+checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
13151255
13161256[[package]]
1317−name = "resolv-conf"
1318−version = "0.7.0"
1257+name = "remove_dir_all"
1258+version = "0.5.3"
13191259source = "registry+https://github.com/rust-lang/crates.io-index"
1320−checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00"
1260+checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
13211261dependencies = [
1322− "hostname",
1323− "quick-error",
1262+ "winapi",
13241263]
13251264
13261265[[package]]
1327−name = "rustc-demangle"
1328−version = "0.1.18"
1266+name = "reqwest"
1267+version = "0.11.6"
1268+source = "registry+https://github.com/rust-lang/crates.io-index"
1269+checksum = "66d2927ca2f685faf0fc620ac4834690d29e7abb153add10f5812eef20b5e280"
1270+dependencies = [
1271+ "base64",
1272+ "bytes",
1273+ "encoding_rs",
1274+ "futures-core",
1275+ "futures-util",
1276+ "http",
1277+ "http-body",
1278+ "hyper",
1279+ "hyper-tls",
1280+ "ipnet",
1281+ "js-sys",
1282+ "lazy_static",
1283+ "log",
1284+ "mime",
1285+ "native-tls",
1286+ "percent-encoding",
1287+ "pin-project-lite",
1288+ "serde",
1289+ "serde_json",
1290+ "serde_urlencoded",
1291+ "tokio",
1292+ "tokio-native-tls",
1293+ "url",
1294+ "wasm-bindgen",
1295+ "wasm-bindgen-futures",
1296+ "web-sys",
1297+ "winreg",
1298+]
1299+
1300+[[package]]
1301+name = "rle-decode-fast"
1302+version = "1.0.1"
1303+source = "registry+https://github.com/rust-lang/crates.io-index"
1304+checksum = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac"
1305+
1306+[[package]]
1307+name = "rusoto_core"
1308+version = "0.47.0"
1309+source = "registry+https://github.com/rust-lang/crates.io-index"
1310+checksum = "5b4f000e8934c1b4f70adde180056812e7ea6b1a247952db8ee98c94cd3116cc"
1311+dependencies = [
1312+ "async-trait",
1313+ "base64",
1314+ "bytes",
1315+ "crc32fast",
1316+ "futures",
1317+ "http",
1318+ "hyper",
1319+ "hyper-tls",
1320+ "lazy_static",
1321+ "log",
1322+ "rusoto_credential",
1323+ "rusoto_signature",
1324+ "rustc_version",
1325+ "serde",
1326+ "serde_json",
1327+ "tokio",
1328+ "xml-rs",
1329+]
1330+
1331+[[package]]
1332+name = "rusoto_credential"
1333+version = "0.47.0"
1334+source = "registry+https://github.com/rust-lang/crates.io-index"
1335+checksum = "6a46b67db7bb66f5541e44db22b0a02fed59c9603e146db3a9e633272d3bac2f"
1336+dependencies = [
1337+ "async-trait",
1338+ "chrono",
1339+ "dirs-next",
1340+ "futures",
1341+ "hyper",
1342+ "serde",
1343+ "serde_json",
1344+ "shlex",
1345+ "tokio",
1346+ "zeroize",
1347+]
1348+
1349+[[package]]
1350+name = "rusoto_ecr"
1351+version = "0.47.0"
1352+source = "registry+https://github.com/rust-lang/crates.io-index"
1353+checksum = "93ec4a28e4fb276307c2129abb16cf7d5573da4ec24d9e3895cc5c8a8bc21a4d"
1354+dependencies = [
1355+ "async-trait",
1356+ "bytes",
1357+ "futures",
1358+ "rusoto_core",
1359+ "serde",
1360+ "serde_json",
1361+]
1362+
1363+[[package]]
1364+name = "rusoto_signature"
1365+version = "0.47.0"
13291366source = "registry+https://github.com/rust-lang/crates.io-index"
1330−checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232"
1367+checksum = "6264e93384b90a747758bcc82079711eacf2e755c3a8b5091687b5349d870bcc"
1368+dependencies = [
1369+ "base64",
1370+ "bytes",
1371+ "chrono",
1372+ "digest",
1373+ "futures",
1374+ "hex",
1375+ "hmac",
1376+ "http",
1377+ "hyper",
1378+ "log",
1379+ "md-5",
1380+ "percent-encoding",
1381+ "pin-project-lite",
1382+ "rusoto_credential",
1383+ "rustc_version",
1384+ "serde",
1385+ "sha2",
1386+ "tokio",
1387+]
13311388
13321389[[package]]
13331390name = "rustc_version"
1334−version = "0.2.3"
1391+version = "0.4.0"
13351392source = "registry+https://github.com/rust-lang/crates.io-index"
1336−checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
1393+checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
13371394dependencies = [
13381395 "semver",
13391396]
@@ -1345,52 +1402,131 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
13451402checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
13461403
13471404[[package]]
1348−name = "scopeguard"
1349−version = "1.1.0"
1405+name = "schannel"
1406+version = "0.1.19"
1407+source = "registry+https://github.com/rust-lang/crates.io-index"
1408+checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
1409+dependencies = [
1410+ "lazy_static",
1411+ "winapi",
1412+]
1413+
1414+[[package]]
1415+name = "schemars"
1416+version = "0.8.6"
1417+source = "registry+https://github.com/rust-lang/crates.io-index"
1418+checksum = "d7a48d098c2a7fdf5740b19deb1181b4fb8a9e68e03ae517c14cde04b5725409"
1419+dependencies = [
1420+ "dyn-clone",
1421+ "schemars_derive",
1422+ "serde",
1423+ "serde_json",
1424+]
1425+
1426+[[package]]
1427+name = "schemars_derive"
1428+version = "0.8.6"
1429+source = "registry+https://github.com/rust-lang/crates.io-index"
1430+checksum = "4a9ea2a613fe4cd7118b2bb101a25d8ae6192e1975179b67b2f17afd11e70ac8"
1431+dependencies = [
1432+ "proc-macro2",
1433+ "quote",
1434+ "serde_derive_internals",
1435+ "syn",
1436+]
1437+
1438+[[package]]
1439+name = "scopeguard"
1440+version = "1.1.0"
1441+source = "registry+https://github.com/rust-lang/crates.io-index"
1442+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
1443+
1444+[[package]]
1445+name = "security-framework"
1446+version = "2.4.2"
1447+source = "registry+https://github.com/rust-lang/crates.io-index"
1448+checksum = "525bc1abfda2e1998d152c45cf13e696f76d0a4972310b22fac1658b05df7c87"
1449+dependencies = [
1450+ "bitflags",
1451+ "core-foundation",
1452+ "core-foundation-sys",
1453+ "libc",
1454+ "security-framework-sys",
1455+]
1456+
1457+[[package]]
1458+name = "security-framework-sys"
1459+version = "2.4.2"
1460+source = "registry+https://github.com/rust-lang/crates.io-index"
1461+checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e"
1462+dependencies = [
1463+ "core-foundation-sys",
1464+ "libc",
1465+]
1466+
1467+[[package]]
1468+name = "semver"
1469+version = "1.0.4"
13501470source = "registry+https://github.com/rust-lang/crates.io-index"
1351−checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
1471+checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012"
13521472
13531473[[package]]
1354−name = "semver"
1355−version = "0.9.0"
1474+name = "serde"
1475+version = "1.0.130"
13561476source = "registry+https://github.com/rust-lang/crates.io-index"
1357−checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
1477+checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
13581478dependencies = [
1359− "semver-parser",
1479+ "serde_derive",
13601480]
13611481
13621482[[package]]
1363−name = "semver-parser"
1483+name = "serde-value"
13641484version = "0.7.0"
13651485source = "registry+https://github.com/rust-lang/crates.io-index"
1366−checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
1486+checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c"
1487+dependencies = [
1488+ "ordered-float",
1489+ "serde",
1490+]
13671491
13681492[[package]]
1369−name = "serde"
1370−version = "1.0.117"
1493+name = "serde_derive"
1494+version = "1.0.130"
13711495source = "registry+https://github.com/rust-lang/crates.io-index"
1372−checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a"
1496+checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
13731497dependencies = [
1374− "serde_derive",
1498+ "proc-macro2",
1499+ "quote",
1500+ "syn",
13751501]
13761502
13771503[[package]]
1378−name = "serde_derive"
1379−version = "1.0.117"
1504+name = "serde_derive_internals"
1505+version = "0.25.0"
13801506source = "registry+https://github.com/rust-lang/crates.io-index"
1381−checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e"
1507+checksum = "1dbab34ca63057a1f15280bdf3c39f2b1eb1b54c17e98360e511637aef7418c6"
13821508dependencies = [
13831509 "proc-macro2",
13841510 "quote",
13851511 "syn",
13861512]
13871513
1514+[[package]]
1515+name = "serde_ignored"
1516+version = "0.1.2"
1517+source = "registry+https://github.com/rust-lang/crates.io-index"
1518+checksum = "1c2c7d39d14f2f2ea82239de71594782f186fd03501ac81f0ce08e674819ff2f"
1519+dependencies = [
1520+ "serde",
1521+]
1522+
13881523[[package]]
13891524name = "serde_json"
1390−version = "1.0.59"
1525+version = "1.0.68"
13911526source = "registry+https://github.com/rust-lang/crates.io-index"
1392−checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95"
1527+checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8"
13931528dependencies = [
1529+ "indexmap",
13941530 "itoa",
13951531 "ryu",
13961532 "serde",
@@ -1409,126 +1545,132 @@ dependencies = [
14091545]
14101546
14111547[[package]]
1412−name = "sha-1"
1413−version = "0.9.2"
1548+name = "serde_yaml"
1549+version = "0.8.21"
1550+source = "registry+https://github.com/rust-lang/crates.io-index"
1551+checksum = "d8c608a35705a5d3cdc9fbe403147647ff34b921f8e833e49306df898f9b20af"
1552+dependencies = [
1553+ "dtoa",
1554+ "indexmap",
1555+ "serde",
1556+ "yaml-rust",
1557+]
1558+
1559+[[package]]
1560+name = "sha2"
1561+version = "0.9.8"
14141562source = "registry+https://github.com/rust-lang/crates.io-index"
1415−checksum = "ce3cdf1b5e620a498ee6f2a171885ac7e22f0e12089ec4b3d22b84921792507c"
1563+checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa"
14161564dependencies = [
14171565 "block-buffer",
1418− "cfg-if 1.0.0",
1419− "cpuid-bool",
1566+ "cfg-if",
1567+ "cpufeatures",
14201568 "digest",
14211569 "opaque-debug",
14221570]
14231571
14241572[[package]]
1425−name = "sha1"
1426−version = "0.6.0"
1573+name = "shlex"
1574+version = "1.1.0"
14271575source = "registry+https://github.com/rust-lang/crates.io-index"
1428−checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
1576+checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
14291577
14301578[[package]]
14311579name = "signal-hook-registry"
1432−version = "1.2.2"
1580+version = "1.4.0"
14331581source = "registry+https://github.com/rust-lang/crates.io-index"
1434−checksum = "ce32ea0c6c56d5eacaeb814fbed9960547021d3edd010ded1425f180536b20ab"
1582+checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
14351583dependencies = [
14361584 "libc",
14371585]
14381586
14391587[[package]]
14401588name = "slab"
1441−version = "0.4.2"
1589+version = "0.4.5"
14421590source = "registry+https://github.com/rust-lang/crates.io-index"
1443−checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
1591+checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
14441592
14451593[[package]]
14461594name = "smallvec"
1447−version = "1.5.0"
1595+version = "1.7.0"
14481596source = "registry+https://github.com/rust-lang/crates.io-index"
1449−checksum = "7acad6f34eb9e8a259d3283d1e8c1d34d7415943d4895f65cc73813c7396fc85"
1597+checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
14501598
14511599[[package]]
14521600name = "socket2"
1453−version = "0.3.17"
1601+version = "0.4.2"
14541602source = "registry+https://github.com/rust-lang/crates.io-index"
1455−checksum = "2c29947abdee2a218277abeca306f25789c938e500ea5a9d4b12a5a504466902"
1603+checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516"
14561604dependencies = [
1457− "cfg-if 1.0.0",
14581605 "libc",
1459− "redox_syscall",
1460− "winapi 0.3.9",
1606+ "winapi",
14611607]
14621608
14631609[[package]]
1464−name = "standback"
1465−version = "0.2.13"
1610+name = "strsim"
1611+version = "0.8.0"
14661612source = "registry+https://github.com/rust-lang/crates.io-index"
1467−checksum = "cf906c8b8fc3f6ecd1046e01da1d8ddec83e48c8b08b84dcc02b585a6bedf5a8"
1468−dependencies = [
1469− "version_check",
1470−]
1613+checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
14711614
14721615[[package]]
1473−name = "static_assertions"
1474−version = "1.1.0"
1616+name = "strsim"
1617+version = "0.10.0"
14751618source = "registry+https://github.com/rust-lang/crates.io-index"
1476−checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
1619+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
14771620
14781621[[package]]
1479−name = "stdweb"
1480−version = "0.4.20"
1622+name = "structopt"
1623+version = "0.3.25"
14811624source = "registry+https://github.com/rust-lang/crates.io-index"
1482−checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5"
1625+checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c"
14831626dependencies = [
1484− "discard",
1485− "rustc_version",
1486− "stdweb-derive",
1487− "stdweb-internal-macros",
1488− "stdweb-internal-runtime",
1489− "wasm-bindgen",
1627+ "clap",
1628+ "lazy_static",
1629+ "structopt-derive",
14901630]
14911631
14921632[[package]]
1493−name = "stdweb-derive"
1494−version = "0.5.3"
1633+name = "structopt-derive"
1634+version = "0.4.18"
14951635source = "registry+https://github.com/rust-lang/crates.io-index"
1496−checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
1636+checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
14971637dependencies = [
1638+ "heck",
1639+ "proc-macro-error",
14981640 "proc-macro2",
14991641 "quote",
1500− "serde",
1501− "serde_derive",
15021642 "syn",
15031643]
15041644
15051645[[package]]
1506−name = "stdweb-internal-macros"
1507−version = "0.2.9"
1646+name = "strum"
1647+version = "0.20.0"
1648+source = "registry+https://github.com/rust-lang/crates.io-index"
1649+checksum = "7318c509b5ba57f18533982607f24070a55d353e90d4cae30c467cdb2ad5ac5c"
1650+
1651+[[package]]
1652+name = "strum_macros"
1653+version = "0.20.1"
15081654source = "registry+https://github.com/rust-lang/crates.io-index"
1509−checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
1655+checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149"
15101656dependencies = [
1511− "base-x",
1657+ "heck",
15121658 "proc-macro2",
15131659 "quote",
1514− "serde",
1515− "serde_derive",
1516− "serde_json",
1517− "sha1",
15181660 "syn",
15191661]
15201662
15211663[[package]]
1522−name = "stdweb-internal-runtime"
1523−version = "0.1.5"
1664+name = "subtle"
1665+version = "2.4.1"
15241666source = "registry+https://github.com/rust-lang/crates.io-index"
1525−checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
1667+checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
15261668
15271669[[package]]
15281670name = "syn"
1529−version = "1.0.53"
1671+version = "1.0.80"
15301672source = "registry+https://github.com/rust-lang/crates.io-index"
1531−checksum = "8833e20724c24de12bbaba5ad230ea61c3eafb05b881c7c9d3cfe8638b187e68"
1673+checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194"
15321674dependencies = [
15331675 "proc-macro2",
15341676 "quote",
@@ -1536,92 +1678,84 @@ dependencies = [
15361678]
15371679
15381680[[package]]
1539−name = "tap"
1540−version = "1.0.0"
1541−source = "registry+https://github.com/rust-lang/crates.io-index"
1542−checksum = "36474e732d1affd3a6ed582781b3683df3d0563714c59c39591e8ff707cf078e"
1543−
1544−[[package]]
1545−name = "thiserror"
1546−version = "1.0.22"
1681+name = "tar"
1682+version = "0.4.37"
15471683source = "registry+https://github.com/rust-lang/crates.io-index"
1548−checksum = "0e9ae34b84616eedaaf1e9dd6026dbe00dcafa92aa0c8077cb69df1fcfe5e53e"
1684+checksum = "d6f5515d3add52e0bbdcad7b83c388bb36ba7b754dda3b5f5bc2d38640cdba5c"
15491685dependencies = [
1550− "thiserror-impl",
1686+ "filetime",
1687+ "libc",
1688+ "xattr",
15511689]
15521690
15531691[[package]]
1554−name = "thiserror-impl"
1555−version = "1.0.22"
1692+name = "tempfile"
1693+version = "3.2.0"
15561694source = "registry+https://github.com/rust-lang/crates.io-index"
1557−checksum = "9ba20f23e85b10754cd195504aebf6a27e2e6cbe28c17778a0c930724628dd56"
1695+checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
15581696dependencies = [
1559− "proc-macro2",
1560− "quote",
1561− "syn",
1697+ "cfg-if",
1698+ "libc",
1699+ "rand",
1700+ "redox_syscall",
1701+ "remove_dir_all",
1702+ "winapi",
15621703]
15631704
15641705[[package]]
1565−name = "thread_local"
1566−version = "1.0.1"
1706+name = "termcolor"
1707+version = "1.1.2"
15671708source = "registry+https://github.com/rust-lang/crates.io-index"
1568−checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
1709+checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
15691710dependencies = [
1570− "lazy_static",
1711+ "winapi-util",
15711712]
15721713
15731714[[package]]
1574−name = "threadpool"
1575−version = "1.8.1"
1715+name = "textwrap"
1716+version = "0.11.0"
15761717source = "registry+https://github.com/rust-lang/crates.io-index"
1577−checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
1718+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
15781719dependencies = [
1579− "num_cpus",
1720+ "unicode-width",
15801721]
15811722
15821723[[package]]
1583−name = "time"
1584−version = "0.2.23"
1724+name = "thiserror"
1725+version = "1.0.30"
15851726source = "registry+https://github.com/rust-lang/crates.io-index"
1586−checksum = "bcdaeea317915d59b2b4cd3b5efcd156c309108664277793f5351700c02ce98b"
1727+checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
15871728dependencies = [
1588− "const_fn",
1589− "libc",
1590− "standback",
1591− "stdweb",
1592− "time-macros",
1593− "version_check",
1594− "winapi 0.3.9",
1729+ "thiserror-impl",
15951730]
15961731
15971732[[package]]
1598−name = "time-macros"
1599−version = "0.1.1"
1733+name = "thiserror-impl"
1734+version = "1.0.30"
16001735source = "registry+https://github.com/rust-lang/crates.io-index"
1601−checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1"
1736+checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
16021737dependencies = [
1603− "proc-macro-hack",
1604− "time-macros-impl",
1738+ "proc-macro2",
1739+ "quote",
1740+ "syn",
16051741]
16061742
16071743[[package]]
1608−name = "time-macros-impl"
1609−version = "0.1.1"
1744+name = "time"
1745+version = "0.1.44"
16101746source = "registry+https://github.com/rust-lang/crates.io-index"
1611−checksum = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa"
1747+checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
16121748dependencies = [
1613− "proc-macro-hack",
1614− "proc-macro2",
1615− "quote",
1616− "standback",
1617− "syn",
1749+ "libc",
1750+ "wasi",
1751+ "winapi",
16181752]
16191753
16201754[[package]]
16211755name = "tinyvec"
1622−version = "1.1.0"
1756+version = "1.5.0"
16231757source = "registry+https://github.com/rust-lang/crates.io-index"
1624−checksum = "ccf8dbc19eb42fba10e8feaaec282fb50e2c14b2726d6301dbfeed0f73306a6f"
1758+checksum = "f83b2a3d4d9091d0abd7eba4dc2710b1718583bd4d8992e2190720ea38f391f7"
16251759dependencies = [
16261760 "tinyvec_macros",
16271761]
@@ -1634,159 +1768,208 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
16341768
16351769[[package]]
16361770name = "tokio"
1637−version = "0.2.23"
1771+version = "1.12.0"
16381772source = "registry+https://github.com/rust-lang/crates.io-index"
1639−checksum = "a6d7ad61edd59bfcc7e80dababf0f4aed2e6d5e0ba1659356ae889752dfc12ff"
1773+checksum = "c2c2416fdedca8443ae44b4527de1ea633af61d8f7169ffa6e72c5b53d24efcc"
16401774dependencies = [
1775+ "autocfg",
16411776 "bytes",
1642− "futures-core",
1643− "iovec",
1644− "lazy_static",
16451777 "libc",
16461778 "memchr",
16471779 "mio",
1648− "mio-uds",
1649− "pin-project-lite 0.1.11",
1780+ "num_cpus",
1781+ "once_cell",
1782+ "parking_lot",
1783+ "pin-project-lite",
16501784 "signal-hook-registry",
1651− "slab",
1652− "winapi 0.3.9",
1785+ "tokio-macros",
1786+ "winapi",
1787+]
1788+
1789+[[package]]
1790+name = "tokio-io-timeout"
1791+version = "1.1.1"
1792+source = "registry+https://github.com/rust-lang/crates.io-index"
1793+checksum = "90c49f106be240de154571dd31fbe48acb10ba6c6dd6f6517ad603abffa42de9"
1794+dependencies = [
1795+ "pin-project-lite",
1796+ "tokio",
1797+]
1798+
1799+[[package]]
1800+name = "tokio-macros"
1801+version = "1.5.0"
1802+source = "registry+https://github.com/rust-lang/crates.io-index"
1803+checksum = "b2dd85aeaba7b68df939bd357c6afb36c87951be9e80bf9c859f2fc3e9fca0fd"
1804+dependencies = [
1805+ "proc-macro2",
1806+ "quote",
1807+ "syn",
1808+]
1809+
1810+[[package]]
1811+name = "tokio-native-tls"
1812+version = "0.3.0"
1813+source = "registry+https://github.com/rust-lang/crates.io-index"
1814+checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b"
1815+dependencies = [
1816+ "native-tls",
1817+ "tokio",
16531818]
16541819
16551820[[package]]
16561821name = "tokio-util"
1657−version = "0.3.1"
1822+version = "0.6.8"
16581823source = "registry+https://github.com/rust-lang/crates.io-index"
1659−checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499"
1824+checksum = "08d3725d3efa29485e87311c5b699de63cde14b00ed4d256b8318aa30ca452cd"
16601825dependencies = [
16611826 "bytes",
16621827 "futures-core",
16631828 "futures-sink",
16641829 "log",
1665− "pin-project-lite 0.1.11",
1830+ "pin-project-lite",
16661831 "tokio",
16671832]
16681833
16691834[[package]]
1670−name = "toml"
1671−version = "0.5.7"
1835+name = "tower"
1836+version = "0.4.10"
16721837source = "registry+https://github.com/rust-lang/crates.io-index"
1673−checksum = "75cf45bb0bef80604d001caaec0d09da99611b3c0fd39d3080468875cdb65645"
1838+checksum = "c00e500fff5fa1131c866b246041a6bf96da9c965f8fe4128cb1421f23e93c00"
16741839dependencies = [
1675− "serde",
1840+ "futures-core",
1841+ "futures-util",
1842+ "pin-project",
1843+ "pin-project-lite",
1844+ "tokio",
1845+ "tokio-util",
1846+ "tower-layer",
1847+ "tower-service",
1848+ "tracing",
16761849]
16771850
16781851[[package]]
1679−name = "tracing"
1680−version = "0.1.22"
1852+name = "tower-http"
1853+version = "0.1.1"
16811854source = "registry+https://github.com/rust-lang/crates.io-index"
1682−checksum = "9f47026cdc4080c07e49b37087de021820269d996f581aac150ef9e5583eefe3"
1855+checksum = "0b7b56efe69aa0ad2b5da6b942e57ea9f6fe683b7a314d4ff48662e2c8838de1"
16831856dependencies = [
1684− "cfg-if 1.0.0",
1685− "log",
1686− "pin-project-lite 0.2.0",
1687− "tracing-core",
1857+ "base64",
1858+ "bytes",
1859+ "futures-core",
1860+ "futures-util",
1861+ "http",
1862+ "http-body",
1863+ "pin-project",
1864+ "tower-layer",
1865+ "tower-service",
1866+ "tracing",
16881867]
16891868
16901869[[package]]
1691−name = "tracing-core"
1692−version = "0.1.17"
1870+name = "tower-layer"
1871+version = "0.3.1"
1872+source = "registry+https://github.com/rust-lang/crates.io-index"
1873+checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62"
1874+
1875+[[package]]
1876+name = "tower-service"
1877+version = "0.3.1"
1878+source = "registry+https://github.com/rust-lang/crates.io-index"
1879+checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
1880+
1881+[[package]]
1882+name = "tracing"
1883+version = "0.1.29"
16931884source = "registry+https://github.com/rust-lang/crates.io-index"
1694−checksum = "f50de3927f93d202783f4513cda820ab47ef17f624b03c096e86ef00c67e6b5f"
1885+checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105"
16951886dependencies = [
1696− "lazy_static",
1887+ "cfg-if",
1888+ "log",
1889+ "pin-project-lite",
1890+ "tracing-attributes",
1891+ "tracing-core",
16971892]
16981893
16991894[[package]]
1700−name = "tracing-futures"
1701−version = "0.2.4"
1895+name = "tracing-attributes"
1896+version = "0.1.18"
17021897source = "registry+https://github.com/rust-lang/crates.io-index"
1703−checksum = "ab7bb6f14721aa00656086e9335d363c5c8747bae02ebe32ea2c7dece5689b4c"
1898+checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e"
17041899dependencies = [
1705− "pin-project 0.4.27",
1706− "tracing",
1900+ "proc-macro2",
1901+ "quote",
1902+ "syn",
17071903]
17081904
17091905[[package]]
1710−name = "trust-dns-proto"
1711−version = "0.19.6"
1906+name = "tracing-core"
1907+version = "0.1.21"
17121908source = "registry+https://github.com/rust-lang/crates.io-index"
1713−checksum = "53861fcb288a166aae4c508ae558ed18b53838db728d4d310aad08270a7d4c2b"
1909+checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4"
17141910dependencies = [
1715− "async-trait",
1716− "backtrace",
1717− "enum-as-inner",
1718− "futures",
1719− "idna",
17201911 "lazy_static",
1721− "log",
1722− "rand",
1723− "smallvec",
1724− "thiserror",
1725− "tokio",
1726− "url",
17271912]
17281913
17291914[[package]]
1730−name = "trust-dns-resolver"
1731−version = "0.19.6"
1915+name = "treediff"
1916+version = "3.0.2"
17321917source = "registry+https://github.com/rust-lang/crates.io-index"
1733−checksum = "6759e8efc40465547b0dfce9500d733c65f969a4cbbfbe3ccf68daaa46ef179e"
1918+checksum = "761e8d5ad7ce14bb82b7e61ccc0ca961005a275a060b9644a2431aa11553c2ff"
17341919dependencies = [
1735− "backtrace",
1736− "cfg-if 0.1.10",
1737− "futures",
1738− "ipconfig",
1739− "lazy_static",
1740− "log",
1741− "lru-cache",
1742− "resolv-conf",
1743− "smallvec",
1744− "thiserror",
1745− "tokio",
1746− "trust-dns-proto",
1920+ "serde_json",
17471921]
17481922
1923+[[package]]
1924+name = "try-lock"
1925+version = "0.2.3"
1926+source = "registry+https://github.com/rust-lang/crates.io-index"
1927+checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
1928+
17491929[[package]]
17501930name = "typenum"
1751−version = "1.12.0"
1931+version = "1.14.0"
17521932source = "registry+https://github.com/rust-lang/crates.io-index"
1753−checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
1933+checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec"
17541934
17551935[[package]]
17561936name = "unicode-bidi"
1757−version = "0.3.4"
1937+version = "0.3.7"
17581938source = "registry+https://github.com/rust-lang/crates.io-index"
1759−checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
1760−dependencies = [
1761− "matches",
1762−]
1939+checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f"
17631940
17641941[[package]]
17651942name = "unicode-normalization"
1766−version = "0.1.16"
1943+version = "0.1.19"
17671944source = "registry+https://github.com/rust-lang/crates.io-index"
1768−checksum = "a13e63ab62dbe32aeee58d1c5408d35c36c392bba5d9d3142287219721afe606"
1945+checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9"
17691946dependencies = [
17701947 "tinyvec",
17711948]
17721949
17731950[[package]]
17741951name = "unicode-segmentation"
1775−version = "1.7.1"
1952+version = "1.8.0"
1953+source = "registry+https://github.com/rust-lang/crates.io-index"
1954+checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
1955+
1956+[[package]]
1957+name = "unicode-width"
1958+version = "0.1.9"
17761959source = "registry+https://github.com/rust-lang/crates.io-index"
1777−checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
1960+checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
17781961
17791962[[package]]
17801963name = "unicode-xid"
1781−version = "0.2.1"
1964+version = "0.2.2"
17821965source = "registry+https://github.com/rust-lang/crates.io-index"
1783−checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
1966+checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
17841967
17851968[[package]]
17861969name = "url"
1787−version = "2.2.0"
1970+version = "2.2.2"
17881971source = "registry+https://github.com/rust-lang/crates.io-index"
1789−checksum = "5909f2b0817350449ed73e8bcd81c8c3c8d9a7a5d8acba4b27db277f1868976e"
1972+checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c"
17901973dependencies = [
17911974 "form_urlencoded",
17921975 "idna",
@@ -1794,33 +1977,55 @@ dependencies = [
17941977 "percent-encoding",
17951978]
17961979
1980+[[package]]
1981+name = "vcpkg"
1982+version = "0.2.15"
1983+source = "registry+https://github.com/rust-lang/crates.io-index"
1984+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
1985+
1986+[[package]]
1987+name = "vec_map"
1988+version = "0.8.2"
1989+source = "registry+https://github.com/rust-lang/crates.io-index"
1990+checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
1991+
17971992[[package]]
17981993name = "version_check"
1799−version = "0.9.2"
1994+version = "0.9.3"
1995+source = "registry+https://github.com/rust-lang/crates.io-index"
1996+checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
1997+
1998+[[package]]
1999+name = "want"
2000+version = "0.3.0"
18002001source = "registry+https://github.com/rust-lang/crates.io-index"
1801−checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
2002+checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
2003+dependencies = [
2004+ "log",
2005+ "try-lock",
2006+]
18022007
18032008[[package]]
18042009name = "wasi"
1805−version = "0.9.0+wasi-snapshot-preview1"
2010+version = "0.10.0+wasi-snapshot-preview1"
18062011source = "registry+https://github.com/rust-lang/crates.io-index"
1807−checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
2012+checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
18082013
18092014[[package]]
18102015name = "wasm-bindgen"
1811−version = "0.2.69"
2016+version = "0.2.78"
18122017source = "registry+https://github.com/rust-lang/crates.io-index"
1813−checksum = "3cd364751395ca0f68cafb17666eee36b63077fb5ecd972bbcd74c90c4bf736e"
2018+checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce"
18142019dependencies = [
1815− "cfg-if 1.0.0",
2020+ "cfg-if",
18162021 "wasm-bindgen-macro",
18172022]
18182023
18192024[[package]]
18202025name = "wasm-bindgen-backend"
1821−version = "0.2.69"
2026+version = "0.2.78"
18222027source = "registry+https://github.com/rust-lang/crates.io-index"
1823−checksum = "1114f89ab1f4106e5b55e688b828c0ab0ea593a1ea7c094b141b14cbaaec2d62"
2028+checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b"
18242029dependencies = [
18252030 "bumpalo",
18262031 "lazy_static",
@@ -1831,11 +2036,23 @@ dependencies = [
18312036 "wasm-bindgen-shared",
18322037]
18332038
2039+[[package]]
2040+name = "wasm-bindgen-futures"
2041+version = "0.4.28"
2042+source = "registry+https://github.com/rust-lang/crates.io-index"
2043+checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39"
2044+dependencies = [
2045+ "cfg-if",
2046+ "js-sys",
2047+ "wasm-bindgen",
2048+ "web-sys",
2049+]
2050+
18342051[[package]]
18352052name = "wasm-bindgen-macro"
1836−version = "0.2.69"
2053+version = "0.2.78"
18372054source = "registry+https://github.com/rust-lang/crates.io-index"
1838−checksum = "7a6ac8995ead1f084a8dea1e65f194d0973800c7f571f6edd70adf06ecf77084"
2055+checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9"
18392056dependencies = [
18402057 "quote",
18412058 "wasm-bindgen-macro-support",
@@ -1843,9 +2060,9 @@ dependencies = [
18432060
18442061[[package]]
18452062name = "wasm-bindgen-macro-support"
1846−version = "0.2.69"
2063+version = "0.2.78"
18472064source = "registry+https://github.com/rust-lang/crates.io-index"
1848−checksum = "b5a48c72f299d80557c7c62e37e7225369ecc0c963964059509fbafe917c7549"
2065+checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab"
18492066dependencies = [
18502067 "proc-macro2",
18512068 "quote",
@@ -1856,31 +2073,20 @@ dependencies = [
18562073
18572074[[package]]
18582075name = "wasm-bindgen-shared"
1859−version = "0.2.69"
2076+version = "0.2.78"
18602077source = "registry+https://github.com/rust-lang/crates.io-index"
1861−checksum = "7e7811dd7f9398f14cc76efd356f98f03aa30419dea46aa810d71e819fc97158"
2078+checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc"
18622079
18632080[[package]]
1864−name = "web-app"
1865−version = "0.1.0"
2081+name = "web-sys"
2082+version = "0.3.55"
2083+source = "registry+https://github.com/rust-lang/crates.io-index"
2084+checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb"
18662085dependencies = [
1867− "actix-rt",
1868− "actix-web",
1869− "askama",
2086+ "js-sys",
2087+ "wasm-bindgen",
18702088]
18712089
1872−[[package]]
1873−name = "widestring"
1874−version = "0.4.3"
1875−source = "registry+https://github.com/rust-lang/crates.io-index"
1876−checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c"
1877−
1878−[[package]]
1879−name = "winapi"
1880−version = "0.2.8"
1881−source = "registry+https://github.com/rust-lang/crates.io-index"
1882−checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
1883−
18842090[[package]]
18852091name = "winapi"
18862092version = "0.3.9"
@@ -1891,18 +2097,21 @@ dependencies = [
18912097 "winapi-x86_64-pc-windows-gnu",
18922098]
18932099
1894−[[package]]
1895−name = "winapi-build"
1896−version = "0.1.1"
1897−source = "registry+https://github.com/rust-lang/crates.io-index"
1898−checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
1899−
19002100[[package]]
19012101name = "winapi-i686-pc-windows-gnu"
19022102version = "0.4.0"
19032103source = "registry+https://github.com/rust-lang/crates.io-index"
19042104checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
19052105
2106+[[package]]
2107+name = "winapi-util"
2108+version = "0.1.5"
2109+source = "registry+https://github.com/rust-lang/crates.io-index"
2110+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
2111+dependencies = [
2112+ "winapi",
2113+]
2114+
19062115[[package]]
19072116name = "winapi-x86_64-pc-windows-gnu"
19082117version = "0.4.0"
@@ -1911,25 +2120,39 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
19112120
19122121[[package]]
19132122name = "winreg"
1914−version = "0.6.2"
2123+version = "0.7.0"
19152124source = "registry+https://github.com/rust-lang/crates.io-index"
1916−checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9"
2125+checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69"
19172126dependencies = [
1918− "winapi 0.3.9",
2127+ "winapi",
19192128]
19202129
19212130[[package]]
1922−name = "ws2_32-sys"
1923−version = "0.2.1"
2131+name = "xattr"
2132+version = "0.2.2"
2133+source = "registry+https://github.com/rust-lang/crates.io-index"
2134+checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c"
2135+dependencies = [
2136+ "libc",
2137+]
2138+
2139+[[package]]
2140+name = "xml-rs"
2141+version = "0.8.4"
2142+source = "registry+https://github.com/rust-lang/crates.io-index"
2143+checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3"
2144+
2145+[[package]]
2146+name = "yaml-rust"
2147+version = "0.4.5"
19242148source = "registry+https://github.com/rust-lang/crates.io-index"
1925−checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
2149+checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
19262150dependencies = [
1927− "winapi 0.2.8",
1928− "winapi-build",
2151+ "linked-hash-map",
19292152]
19302153
19312154[[package]]
1932−name = "wyz"
1933−version = "0.2.0"
2155+name = "zeroize"
2156+version = "1.4.2"
19342157source = "registry+https://github.com/rust-lang/crates.io-index"
1935−checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
2158+checksum = "bf68b08513768deaa790264a7fac27a58cbf2705cfcdc9448362229217d7e970"
helm-control-scripts/Cargo.tomlnew file+82
@@ -0,0 +1,82 @@
1+[package]
2+name = "helm-control-scripts"
3+version = "0.2.3"
4+authors = ["Aleksei Sizov <a.sizov@typeable.io>"]
5+edition = "2018"
6+
7+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8+
9+[dependencies]
10+structopt = "0.3"
11+log = "0.4"
12+env_logger = "0.8.4"
13+serde = { version = "1.0", features = ["derive"] }
14+serde_json = "1.0"
15+serde_yaml = "0.8"
16+envy = "0.4"
17+yaml-rust = "0.4"
18+kube = { version = "0.58.1", features = ["derive", "jsonpatch"]}
19+k8s-openapi = { version = "0.12.0", features = ["v1_19"]}
20+tokio = { version = "1.7.0", features = ["full"] }
21+dkregistry = { git = "https://github.com/camallo/dkregistry-rs", rev = "854d0da53bef5dd85b5e901123e85d43af97c74e"} # Version in crates uses old tokio
22+regex = "1"
23+rusoto_core = "0.47.0"
24+rusoto_ecr = "0.47.0"
25+schemars = "0.8.6"
26+json-patch = "0.2.6"
27+
28+[[bin]]
29+name = "create"
30+path = "src/create_update.rs"
31+
32+[[bin]]
33+name = "update"
34+path = "src/create_update.rs"
35+
36+[[bin]]
37+name = "archive"
38+path = "src/archive.rs"
39+
40+[[bin]]
41+name = "info"
42+path = "src/info.rs"
43+
44+[[bin]]
45+name = "cleanup"
46+path = "src/cleanup.rs"
47+
48+[[bin]]
49+name = "check"
50+path = "src/check.rs"
51+
52+[[bin]]
53+name = "archive_check"
54+path = "src/archive_check.rs"
55+
56+[[bin]]
57+name = "init"
58+path = "src/init.rs"
59+
60+[[bin]]
61+name = "config_check"
62+path = "src/config_check.rs"
63+
64+[[bin]]
65+name = "app_overrides"
66+path = "src/app_overrides.rs"
67+
68+[[bin]]
69+name = "deployment_overrides"
70+path = "src/deployment_overrides.rs"
71+
72+[[bin]]
73+name = "deployment_keys"
74+path = "src/deployment_keys.rs"
75+
76+[[bin]]
77+name = "app_keys"
78+path = "src/app_keys.rs"
79+
80+[[bin]]
81+name = "unarchive"
82+path = "src/unarchive.rs"
helm-control-scripts/Dockerfilenew file+26
@@ -0,0 +1,26 @@
1+FROM alpine:3
2+ARG HELM_BIN=/utils/helm
3+ENV HELM_BIN=$HELM_BIN
4+
5+ADD https://get.helm.sh/helm-v3.6.0-linux-amd64.tar.gz /tmp/helm.tar.gz
6+
7+RUN tar -xf /tmp/helm.tar.gz -C /tmp &&\
8+ mkdir -p /utils &&\
9+ cp /tmp/linux-amd64/helm $HELM_BIN &&\
10+ chmod +x $HELM_BIN &&\
11+ rm -r /tmp/*
12+
13+ADD target/x86_64-unknown-linux-musl/release/archive /utils/
14+ADD target/x86_64-unknown-linux-musl/release/archive_check /utils/
15+ADD target/x86_64-unknown-linux-musl/release/check /utils/
16+ADD target/x86_64-unknown-linux-musl/release/cleanup /utils/
17+ADD target/x86_64-unknown-linux-musl/release/create /utils/
18+ADD target/x86_64-unknown-linux-musl/release/info /utils/
19+ADD target/x86_64-unknown-linux-musl/release/update /utils/
20+ADD target/x86_64-unknown-linux-musl/release/init /utils/
21+ADD target/x86_64-unknown-linux-musl/release/config_check /utils/
22+ADD target/x86_64-unknown-linux-musl/release/app_overrides /utils/
23+ADD target/x86_64-unknown-linux-musl/release/app_keys /utils/
24+ADD target/x86_64-unknown-linux-musl/release/deployment_overrides /utils/
25+ADD target/x86_64-unknown-linux-musl/release/deployment_keys /utils/
26+ADD target/x86_64-unknown-linux-musl/release/unarchive /utils/
helm-control-scripts/README.mdnew file+70
@@ -0,0 +1,70 @@
1+# Generic scripts
2+
3+This is a complete suite of Octopod control scripts to deploy helm charts.
4+You can get pre-built docker images from [typeable/octopod-helm-control-scripts](https://hub.docker.com/repository/docker/typeable/octopod-helm-control-scripts).
5+
6+### Contents
7+
8+- create – a script to install a helm release
9+- update – a script to upgrade a helm release
10+- archive – a script to scale to zero all deployments and statefulsets
11+- archive_check – a script to check if all resources scaled to zero correctly
12+- unarchive - scale all deployments and statefulsets back (right now it will only scale to 1 and not to previous value)
13+- info – a script to print comma-separated pairs which will be placed as links in the Octopod Web UI
14+- cleanup – a script to delete dangling PVCs and letsencrypt certs left after `helm uninstall` command
15+- check – a script to check if resources created by helm are healthy. Right now only deployments and statefuls sets are checked
16+- init – a script to initialize something. This is the only script not run by Octopod, but as an init container.
17+- config_check – a script to check that configuration (such as image tag name) passed to Octopod is correct. This script is invoked before deployment creation.
18+- app_overrides - a scirpt which returns a list of default app overrides wichh were passed in default_overrides parameter described below.
19+- deployment_overrides - a scirpt which returns a list of default deployment overrides from default paramaters option.
20+- deployment_keys - a scripts which returns a list of the possible deployment overrides keys user can use.
21+- app_keys - a scripts which returns a list of the possible app overrides keys. These are parsed from an output of the `helm show values` command.
22+
23+### Parameters
24+
25+All scipts accept common parametes which are passed by Octopod when it invokes them.
26+
27+Also, several environment variables are used to parametrize the default behavior:
28+
29+- HELM_BIN – the path to the `helm` executable
30+- HELM_USER – the (optional) user for a private helm registry
31+- HELM_PASS – the (optional) password for a private helm registry
32+- DEFAUTLS – the json with the default parameters (described below)
33+- HELM_ON_INIT_ONLY - run helm add and update repository as a part of init script execution only. Otherwise `helm repo add` and `helm repo update` will be executed every time before any other helm command.
34+- INGRESS_HOST_KEY - key name which will be populated with domain name generated for the Octopod deployment. Defaults to `ingress.hostname`.
35+
36+#### Default parameters
37+- default_overrides – an array with key-value pairs which will be passed as a `--set` flags for helm for each deployment
38+- chart_repo_url – the url for a chart repo
39+- chart_version – the version of a chart you want to install
40+- chart_name – the name of a chart you want to install
41+
42+These parameters, if set up in the `DEFAULTS` variable, will be passed to every deployment unless overridden in the "deployment overrides" section of an Octopod deployment configuration.
43+
44+### Authorization notes
45+
46+Most of the control scripts require that credentials for various services be passed to them to function properly. Some credentials, like the Helm ones, are quite obvious, but others are not.
47+
48+`config_check`, in addition to the Helm credentials, requires access to your docker registry to check the availability of the docker image tags.
49+
50+Right now only plain docker registries and ECR are supported. ECR clients need to have valid AWS credentials set via [environment variables](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html). You can provide any environment variables to Octopod by adding them to [env map](../charts/octopod/values.yaml#L86) in the Octopod helm chart.
51+
52+Note that if you are using EKS you don't need to add any additional configuration.
53+
54+Private registries, like Harbor with authorization haven't been tested with this set of scripts. If you are using a private registry and have troubles with the `config_check` script, please file an issue.
55+
56+#### Note about CRD support
57+
58+Right now these control scripts support `Posgresql` CRD from [postgres operator](https://github.com/zalando/postgres-operator) and `Kafka` CRD from [Strimzi](https://strimzi.io/). Explicit support is needed for the proper scaling of the resources, created by those CRDs. For example: just scaling stateful sets created by Kafka CRD won't work because the controller will keep scaling them back again.
59+
60+Explicit support for every CRD is necessary because the configurations are not standardized, and every CRD is implemented slightly differently.
61+
62+We'll keep supporting those CRDs, because we're using them in-house. If you want to support another CRD, you can file an issue or even a PR.
63+
64+<br />
65+
66+<p align="center">
67+ <i>Star the project of you like it</i>
68+</p>
69+
70+<p align="center"><a href="https://typeable.io"><img src="../img/typeable_logo.svg" width="177px"></img></a></p>
helm-control-scripts/src/app_keys.rsnew file+31
@@ -0,0 +1,31 @@
1+use helm_control_scripts::lib::*;
2+
3+fn main() {
4+ let mut log_builder = Builder::from_default_env();
5+ log_builder.target(Target::Stderr).filter(None, LevelFilter::Info).init();
6+ info!("Utils version {}", env!("CARGO_PKG_VERSION"));
7+ let envs = EnvVars::parse();
8+ info!("Env variables received {:?}", &envs);
9+ let cli_opts = CliOpts::from_args();
10+ info!("Cli options received {:?}", &cli_opts);
11+ let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &envs);
12+ helm_init(&envs, &deployment_parameters);
13+ let helm_values = HelmCmd {
14+ name: envs.helm_bin,
15+ mode: HelmMode::ShowValues,
16+ release_name: String::from(""),
17+ namespace: String::from(""),
18+ deployment_parameters: deployment_parameters,
19+ overrides: vec![],
20+ };
21+ info!("Generated Helm args: {:?}", &helm_values.args());
22+ match helm_values.run_stdout() {
23+ Ok(status) => {
24+ print!("{}", print_keys(helm_values_as_keys(status)));
25+ }
26+ Err(status) => {
27+ error!("Error during helm execution");
28+ panic!("{:?}", status);
29+ }
30+ }
31+}
helm-control-scripts/src/app_overrides.rsnew file+11
@@ -0,0 +1,11 @@
1+use helm_control_scripts::lib::*;
2+
3+fn main() {
4+ let mut log_builder = Builder::from_default_env();
5+ log_builder.target(Target::Stderr).filter(None, LevelFilter::Info).init();
6+ info!("Utils version {}", env!("CARGO_PKG_VERSION"));
7+ let envs = EnvVars::parse();
8+ info!("Env variables received {:?}", &envs);
9+ let default_values: DefaultValues = serde_json::from_str(&envs.defaults).unwrap();
10+ print!("{}", print_kv(default_values.app_overrides()));
11+}
helm-control-scripts/src/archive.rsnew file+53
@@ -0,0 +1,53 @@
1+use helm_control_scripts::lib::*;
2+
3+fn main() {
4+ let mut log_builder = Builder::from_default_env();
5+ log_builder.target(Target::Stdout).filter(None, LevelFilter::Info).init();
6+ info!("Utils version {}", env!("CARGO_PKG_VERSION"));
7+ let envs = EnvVars::parse();
8+ info!("Env variables received {:?}", &envs);
9+ let cli_opts = CliOpts::from_args();
10+ info!("Cli options received {:?}", &cli_opts);
11+ let overrides = match overrides(&cli_opts, &envs) {
12+ Some(inner) => inner,
13+ None => vec![],
14+ };
15+
16+ let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &envs);
17+ let namespace = String::from(&cli_opts.namespace);
18+ let release_name = match cli_opts.name {
19+ Some(name) => name,
20+ None => {
21+ error!("mandatory name argument was not provided");
22+ panic!();
23+ }
24+ };
25+ let helm_template = HelmCmd {
26+ name: envs.helm_bin,
27+ mode: HelmMode::Template,
28+ release_name: release_name,
29+ namespace: cli_opts.namespace,
30+ deployment_parameters: deployment_parameters,
31+ overrides: overrides,
32+ };
33+ info!("Generated Helm args: {:?}", &helm_template.args());
34+ match helm_template.run_stdout() {
35+ Ok(status) => {
36+ let (deployments, statefulsets, _ingresses, _old_ingresses, postgresqls, kafkas) = match parse_to_k8s(status) {
37+ Ok((deployments, statefulsets, ingresses, old_ingresses, postgresqls, kafkas)) => (deployments, statefulsets, ingresses, old_ingresses, postgresqls, kafkas),
38+ Err(err) => panic!("{}", err)
39+ };
40+ match scale(deployments, statefulsets, postgresqls, kafkas, namespace, 0) {
41+ Ok(_status) => info!("Success!"),
42+ Err(status) => {
43+ error!("Error checking statuses");
44+ panic!("{}", status);
45+ }
46+ }
47+ }
48+ Err(status) => {
49+ error!("Error during helm execution");
50+ panic!("{:?}", status);
51+ }
52+ }
53+}
helm-control-scripts/src/archive_check.rsnew file+53
@@ -0,0 +1,53 @@
1+use helm_control_scripts::lib::*;
2+
3+fn main() {
4+ let mut log_builder = Builder::from_default_env();
5+ log_builder.target(Target::Stdout).filter(None, LevelFilter::Info).init();
6+ info!("Utils version {}", env!("CARGO_PKG_VERSION"));
7+ let envs = EnvVars::parse();
8+ info!("Env variables received {:?}", &envs);
9+ let cli_opts = CliOpts::from_args();
10+ info!("Cli options received {:?}", &cli_opts);
11+ let overrides = match overrides(&cli_opts, &envs) {
12+ Some(inner) => inner,
13+ None => vec![],
14+ };
15+
16+ let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &envs);
17+ let namespace = String::from(&cli_opts.namespace);
18+ let release_name = match cli_opts.name {
19+ Some(name) => name,
20+ None => {
21+ error!("mandatory name argument was not provided");
22+ panic!();
23+ }
24+ };
25+ let helm_template = HelmCmd {
26+ name: envs.helm_bin,
27+ mode: HelmMode::Template,
28+ release_name: release_name,
29+ namespace: cli_opts.namespace,
30+ deployment_parameters: deployment_parameters,
31+ overrides: overrides,
32+ };
33+ info!("Generated Helm args: {:?}", &helm_template.args());
34+ match helm_template.run_stdout() {
35+ Ok(status) => {
36+ let (deployments, statefulsets, _ingresses, _old_ingresses, _postgresqls, _kafkas) = match parse_to_k8s(status) {
37+ Ok((deployments, statefulsets, ingresses, old_ingresses, postgresqls, kafkas)) => (deployments, statefulsets, ingresses, old_ingresses, postgresqls, kafkas),
38+ Err(err) => panic!("{}", err)
39+ };
40+ match check_all(deployments, statefulsets, namespace) {
41+ Ok(status) => {
42+ error!("Deployment hasn't scaled down correctly");
43+ panic!("{:?}", status);
44+ },
45+ Err(_status) => info!("Success!")
46+ }
47+ }
48+ Err(status) => {
49+ error!("Error during helm execution");
50+ panic!("{:?}", status);
51+ }
52+ }
53+}
helm-control-scripts/src/check.rsnew file+53
@@ -0,0 +1,53 @@
1+use helm_control_scripts::lib::*;
2+
3+fn main() {
4+ let mut log_builder = Builder::from_default_env();
5+ log_builder.target(Target::Stdout).filter(None, LevelFilter::Info).init();
6+ info!("Utils version {}", env!("CARGO_PKG_VERSION"));
7+ let envs = EnvVars::parse();
8+ info!("Env variables received {:?}", &envs);
9+ let cli_opts = CliOpts::from_args();
10+ info!("Cli options received {:?}", &cli_opts);
11+ let overrides = match overrides(&cli_opts, &envs) {
12+ Some(inner) => inner,
13+ None => vec![],
14+ };
15+
16+ let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &envs);
17+ let namespace = String::from(&cli_opts.namespace);
18+ let release_name = match cli_opts.name {
19+ Some(name) => name,
20+ None => {
21+ error!("mandatory name argument was not provided");
22+ panic!();
23+ }
24+ };
25+ let helm_template = HelmCmd {
26+ name: envs.helm_bin,
27+ mode: HelmMode::Template,
28+ release_name: release_name,
29+ namespace: cli_opts.namespace,
30+ deployment_parameters: deployment_parameters,
31+ overrides: overrides,
32+ };
33+ info!("Generated Helm args: {:?}", &helm_template.args());
34+ match helm_template.run_stdout() {
35+ Ok(status) => {
36+ let (deployments, statefulsets, _ingresses, _old_ingresses, _postgresqls, _kafkas) = match parse_to_k8s(status) {
37+ Ok((deployments, statefulsets, ingresses, old_ingresses, postgresqls, kafkas)) => (deployments, statefulsets, ingresses, old_ingresses, postgresqls, kafkas),
38+ Err(err) => panic!("{}", err)
39+ };
40+ match check_all(deployments, statefulsets, namespace) {
41+ Ok(_status) => info!("Success!"),
42+ Err(status) => {
43+ error!("Error checking statuses");
44+ panic!("{:?}", status);
45+ }
46+ }
47+ }
48+ Err(status) => {
49+ error!("Error during helm execution");
50+ panic!("{:?}", status);
51+ }
52+ }
53+}
helm-control-scripts/src/cleanup.rsnew file+71
@@ -0,0 +1,71 @@
1+use helm_control_scripts::lib::*;
2+
3+fn main() {
4+ let mut log_builder = Builder::from_default_env();
5+ log_builder.target(Target::Stdout).filter(None, LevelFilter::Info).init();
6+ info!("Utils version {}", env!("CARGO_PKG_VERSION"));
7+ let envs = EnvVars::parse();
8+ info!("Env variables received {:?}", &envs);
9+ let cli_opts = CliOpts::from_args();
10+ info!("Cli options received {:?}", &cli_opts);
11+ let overrides = match overrides(&cli_opts, &envs) {
12+ Some(inner) => inner,
13+ None => vec![],
14+ };
15+
16+ let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &envs);
17+ let namespace = String::from(&cli_opts.namespace);
18+ let release_name = match cli_opts.name {
19+ Some(name) => name,
20+ None => {
21+ error!("mandatory name argument was not provided");
22+ panic!();
23+ }
24+ };
25+ helm_init(&envs, &deployment_parameters);
26+ let helm_cmd = HelmCmd {
27+ name: envs.helm_bin.clone(),
28+ mode: HelmMode::Uninstall,
29+ release_name: release_name.clone(),
30+ namespace: cli_opts.namespace.clone(),
31+ deployment_parameters: deployment_parameters.clone(),
32+ overrides: vec![],
33+ };
34+ let helm_template = HelmCmd {
35+ name: envs.helm_bin,
36+ mode: HelmMode::Template,
37+ release_name: release_name.clone(),
38+ namespace: cli_opts.namespace,
39+ deployment_parameters: deployment_parameters,
40+ overrides: overrides,
41+ };
42+ info!("Generated Helm args: {:?}", &helm_cmd.args());
43+ match helm_template.run_stdout() {
44+ Ok(status) => {
45+ let (_deployments, _statefulsets, ingresses, old_ingresses, _postgresqls, _kafkas) = match parse_to_k8s(status) {
46+ Ok((deployments, statefulsets, ingresses, old_ingresses, postgresqls, kafkas)) => (deployments, statefulsets, ingresses, old_ingresses, postgresqls, kafkas),
47+ Err(err) => panic!("{}", err)
48+ };
49+ match helm_cmd.run() {
50+ Ok(_status) => {
51+ match delete_pvcs(&namespace, &format!("app.kubernetes.io/instance={}", release_name)) {
52+ Ok(_status) => info!("All pvcs were deleted successfully"),
53+ Err(err) => {
54+ error!("Error deleting pvcs");
55+ panic!("{:?}", err);
56+ }
57+ }
58+ info!("Success!");
59+ },
60+ Err(status) => {
61+ error!("Error during helm uninstall");
62+ panic!("{:?}", status);
63+ }
64+ }
65+ }
66+ Err(status) => {
67+ error!("Error during helm templating");
68+ panic!("{:?}", status);
69+ }
70+ }
71+}
helm-control-scripts/src/config_check.rsnew file+65
@@ -0,0 +1,65 @@
1+use helm_control_scripts::lib::*;
2+
3+fn main() {
4+ let mut log_builder = Builder::from_default_env();
5+ log_builder.target(Target::Stderr).filter(None, LevelFilter::Info).init();
6+ info!("Utils version {}", env!("CARGO_PKG_VERSION"));
7+ let envs = EnvVars::parse();
8+ info!("Env variables received {:?}", &envs);
9+ let cli_opts = CliOpts::from_args();
10+ info!("Cli options received {:?}", &cli_opts);
11+ let overrides = match overrides(&cli_opts, &envs) {
12+ Some(inner) => inner,
13+ None => vec![],
14+ };
15+
16+ let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &envs);
17+ helm_init(&envs, &deployment_parameters);
18+ let release_name = match cli_opts.name {
19+ Some(name) => name,
20+ None => {
21+ error!("mandatory name argument was not provided");
22+ panic!();
23+ }
24+ };
25+ let helm_template = HelmCmd {
26+ name: envs.helm_bin,
27+ mode: HelmMode::Template,
28+ release_name: release_name,
29+ namespace: cli_opts.namespace,
30+ deployment_parameters: deployment_parameters,
31+ overrides: overrides,
32+ };
33+ info!("Generated Helm args: {:?}", &helm_template.args());
34+ match helm_template.run_stdout() {
35+ Ok(status) => {
36+ let (deployments, statefulsets, _ingresses, _old_ingresses, _postgresqls, _kafkas) = match parse_to_k8s(status) {
37+ Ok((deployments, statefulsets, ingresses, old_ingresses, postgresqls, kafkas)) => (deployments, statefulsets, ingresses, old_ingresses, postgresqls, kafkas),
38+ Err(err) => {
39+ println!("Something went wrong: {}", err);
40+ panic!("{}", err);
41+ }
42+ };
43+ match deployments_statefulsets_to_images(deployments, statefulsets) {
44+ Some(images) => {
45+ match check_images(images) {
46+ Ok(_) => info!("Success!"),
47+ Err(err) => {
48+ println!("Error checking images. Are they present in the registry?");
49+ panic!("{}", err);
50+ }
51+ }
52+ },
53+ None => {
54+ println!("No images found in pods' declarations");
55+ panic!("No images found!");
56+ }
57+ }
58+ }
59+ Err((status, err)) => {
60+ println!("{:#}", err);
61+ error!("Error during helm execution");
62+ panic!("{:?}", status);
63+ }
64+ }
65+}
helm-control-scripts/src/create_update.rsnew file+41
@@ -0,0 +1,41 @@
1+use helm_control_scripts::lib::*;
2+
3+fn main() {
4+ let mut log_builder = Builder::from_default_env();
5+ log_builder.target(Target::Stdout).filter(None, LevelFilter::Info).init();
6+ info!("Utils version {}", env!("CARGO_PKG_VERSION"));
7+ let envs = EnvVars::parse();
8+ info!("Env variables received {:?}", &envs);
9+ let cli_opts = CliOpts::from_args();
10+ info!("Cli options received {:?}", &cli_opts);
11+ let overrides = match overrides(&cli_opts, &envs) {
12+ Some(inner) => inner,
13+ None => vec![],
14+ };
15+
16+ let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &envs);
17+ helm_init(&envs, &deployment_parameters);
18+ let release_name = match cli_opts.name {
19+ Some(name) => name,
20+ None => {
21+ error!("mandatory name argument was not provided");
22+ panic!();
23+ }
24+ };
25+ let helm_cmd = HelmCmd {
26+ name: envs.helm_bin,
27+ mode: HelmMode::UpgradeInstall,
28+ release_name: release_name,
29+ namespace: cli_opts.namespace,
30+ deployment_parameters: deployment_parameters,
31+ overrides: overrides,
32+ };
33+ info!("Generated Helm args: {:?}", &helm_cmd.args());
34+ match helm_cmd.run() {
35+ Ok(_status) => info!("Success!"),
36+ Err(status) => {
37+ error!("Error during helm execution");
38+ panic!("{:?}", status);
39+ }
40+ }
41+}
helm-control-scripts/src/deployment_keys.rsnew file+11
@@ -0,0 +1,11 @@
1+use helm_control_scripts::lib::*;
2+
3+fn main() {
4+ let mut log_builder = Builder::from_default_env();
5+ log_builder.target(Target::Stderr).filter(None, LevelFilter::Info).init();
6+ info!("Utils version {}", env!("CARGO_PKG_VERSION"));
7+ let envs = EnvVars::parse();
8+ info!("Env variables received {:?}", &envs);
9+ let default_values: DefaultValues = serde_json::from_str(&envs.defaults).unwrap();
10+ print!("{}", print_keys(Some(default_values.deployment_keys())));
11+}
helm-control-scripts/src/deployment_overrides.rsnew file+11
@@ -0,0 +1,11 @@
1+use helm_control_scripts::lib::*;
2+
3+fn main() {
4+ let mut log_builder = Builder::from_default_env();
5+ log_builder.target(Target::Stderr).filter(None, LevelFilter::Info).init();
6+ info!("Utils version {}", env!("CARGO_PKG_VERSION"));
7+ let envs = EnvVars::parse();
8+ info!("Env variables received {:?}", &envs);
9+ let default_values: DefaultValues = serde_json::from_str(&envs.defaults).unwrap();
10+ print!("{}", print_kv(Some(default_values.deployment_overrides())));
11+}
helm-control-scripts/src/info.rsnew file+47
@@ -0,0 +1,47 @@
1+use helm_control_scripts::lib::*;
2+
3+fn main() {
4+ let mut log_builder = Builder::from_default_env();
5+ log_builder.target(Target::Stderr).filter(None, LevelFilter::Info).init();
6+ info!("Utils version {}", env!("CARGO_PKG_VERSION"));
7+ let envs = EnvVars::parse();
8+ info!("Env variables received {:?}", &envs);
9+ let cli_opts = CliOpts::from_args();
10+ info!("Cli options received {:?}", &cli_opts);
11+ let overrides = match overrides(&cli_opts, &envs) {
12+ Some(inner) => inner,
13+ None => vec![],
14+ };
15+
16+ let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &envs);
17+ helm_init(&envs, &deployment_parameters);
18+ let release_name = match cli_opts.name {
19+ Some(name) => name,
20+ None => {
21+ error!("mandatory name argument was not provided");
22+ panic!();
23+ }
24+ };
25+ let default_name = String::from(&release_name);
26+ let helm_template = HelmCmd {
27+ name: envs.helm_bin,
28+ mode: HelmMode::Template,
29+ release_name: release_name,
30+ namespace: cli_opts.namespace,
31+ deployment_parameters: deployment_parameters,
32+ overrides: overrides,
33+ };
34+ match helm_template.run_stdout() {
35+ Ok(status) => {
36+ let (_deployments, _statefulsets, ingresses, old_ingresses, _postgresqls, _kafkas) = match parse_to_k8s(status) {
37+ Ok((deployments, statefulsets, ingresses, old_ingresses, postgresqls, kafkas)) => (deployments, statefulsets, ingresses, old_ingresses, postgresqls, kafkas),
38+ Err(err) => panic!("{}", err)
39+ };
40+ print!("{}", print_kv(ingresses_to_hosts(ingresses, old_ingresses, default_name)));
41+ }
42+ Err(status) => {
43+ error!("Error during helm execution");
44+ panic!("{:?}", status);
45+ }
46+ }
47+}
helm-control-scripts/src/init.rsnew file+22
@@ -0,0 +1,22 @@
1+use helm_control_scripts::lib::*;
2+
3+fn main() {
4+ let mut log_builder = Builder::from_default_env();
5+ log_builder.target(Target::Stdout).filter(None, LevelFilter::Info).init();
6+ info!("Utils version {}", env!("CARGO_PKG_VERSION"));
7+ let envs = EnvVars::parse();
8+ info!("Env variables received {:?}", &envs);
9+ let default_values: DefaultValues = serde_json::from_str(&envs.defaults).unwrap();
10+ let deployment_parameters = HelmDeploymentParameters::new_env_only(&default_values, &envs);
11+ match &envs.helm_on_init_only {
12+ Some(enabled) => {
13+ if *enabled {
14+ helm_repo_add_update(&envs, &deployment_parameters);
15+ } else {
16+ info!("Skipping helm initialization since HELM_ON_INIT_ONLY is false");
17+ }
18+ },
19+ None => info!("Skipping helm initialization since HELM_ON_INIT_ONLY is not set"),
20+ }
21+ info!("Success!");
22+}
helm-control-scripts/src/lib.rsnew file+1061
@@ -0,0 +1,1061 @@
1+pub mod lib {
2+ pub use std::io::prelude::*;
3+ pub use std::process::{Command, ExitStatus, Stdio};
4+ pub use std::error::Error;
5+ pub use std::fmt;
6+ pub use structopt::StructOpt;
7+ pub use env_logger::{Builder, Target};
8+ pub use log::{LevelFilter, info, warn, error};
9+ pub use serde::{Serialize, Deserialize};
10+ pub use serde_json::json;
11+ pub use std::error;
12+ pub use yaml_rust::{YamlLoader, YamlEmitter, Yaml};
13+ pub use k8s_openapi::api::{
14+ apps::v1::{Deployment, StatefulSet},
15+ networking::v1::Ingress,
16+ networking::v1beta1::Ingress as OldIngress,
17+ core::v1::{PersistentVolumeClaim, Secret}
18+ };
19+ pub use kube::{
20+ api::{Api, ListParams, ResourceExt, Patch, PatchParams, DeleteParams, PostParams},
21+ Client,CustomResource
22+ };
23+ pub use dkregistry::{
24+ v2::Client as RegClient,
25+ errors::Error as RegError,
26+ };
27+ pub use regex::Regex;
28+ pub use rusoto_core::{Region, RusotoError};
29+ pub use rusoto_ecr::{Ecr, EcrClient, DescribeImagesRequest, ImageIdentifier, DescribeImagesError};
30+ pub use schemars::JsonSchema;
31+ pub use tokio::task;
32+
33+ #[derive(Debug,StructOpt)]
34+ #[structopt(rename_all = "kebab-case")]
35+ pub struct CliOpts {
36+ #[structopt(long)]
37+ pub project_name: String,
38+ #[structopt(long)]
39+ pub base_domain: String,
40+ #[structopt(long)]
41+ pub namespace: String,
42+ #[structopt(long)]
43+ pub name: Option<String>,
44+ #[structopt(long)]
45+ pub tag: Option<String>,
46+ #[structopt(long)]
47+ pub application_config: Vec<String>,
48+ #[structopt(long)]
49+ pub deployment_config: Vec<String>,
50+ }
51+
52+ #[derive(Deserialize, Debug)]
53+ pub struct EnvVars {
54+ pub helm_bin: String,
55+ pub defaults: String, //json of DefaultValues
56+ #[serde(default)]
57+ pub helm_user: String,
58+ #[serde(default)]
59+ pub helm_pass: String,
60+ pub helm_on_init_only: Option<bool>,
61+ pub ingress_host_key: Option<String>,
62+ }
63+
64+ impl EnvVars {
65+ pub fn parse() -> Self {
66+ let envs = match envy::from_env::<Self>() {
67+ Ok(config) => config,
68+ Err(error) => {
69+ error!("Can't find mandatory environment variable set");
70+ panic!("{:?}", error);
71+ }
72+ };
73+ return envs;
74+ }
75+ }
76+
77+ #[derive(Debug, Serialize, Deserialize)]
78+ struct HelmRepo {
79+ name: String,
80+ url: String
81+ }
82+
83+ #[derive(Deserialize, Debug)]
84+ pub struct DefaultValues {
85+ pub default_overrides: Vec<String>,
86+ pub chart_repo_url: String,
87+ pub chart_version: String,
88+ pub chart_name: String,
89+ }
90+
91+ impl DefaultValues {
92+ pub fn app_overrides(&self) -> Option<Vec<(String,String)>> {
93+ if self.default_overrides.is_empty() {
94+ None
95+ } else {
96+ let mut overrides: Vec<(String,String)> = Vec::new();
97+ for app_override in &self.default_overrides {
98+ let split_override = app_override.split('=').collect::<Vec<_>>();
99+ overrides.push((split_override.first().unwrap().to_string(), split_override.last().unwrap().to_string()));
100+ }
101+ Some(overrides)
102+ }
103+ }
104+ pub fn deployment_overrides(&self) -> Vec<(String,String)> {
105+ vec![
106+ (String::from("chart_repo_url"), self.chart_repo_url.clone()),
107+ (String::from("chart_version"), self.chart_version.clone()),
108+ (String::from("chart_name"), self.chart_name.clone()),
109+ ]
110+ }
111+ pub fn deployment_keys(&self) -> Vec<String> {
112+ let mut keys: Vec<String> = vec![
113+ String::from("chart_repo_url"),
114+ String::from("chart_version"),
115+ String::from("chart_name"),
116+ String::from("chart_repo_user"),
117+ String::from("chart_repo_pass"),
118+ ];
119+ keys.sort();
120+ keys
121+ }
122+ }
123+
124+ #[derive(Debug, Clone, Default)]
125+ pub struct HelmDeploymentParameters {
126+ pub chart_repo_url: String,
127+ pub chart_repo_user: String,
128+ pub chart_repo_pass: String,
129+ pub chart_version: String,
130+ pub chart_name: String,
131+ }
132+
133+ impl HelmDeploymentParameters {
134+ pub fn new(cli_opts: &CliOpts, envs: &EnvVars) -> Self {
135+ let mut deployment_parameters = Self::default();
136+ deployment_parameters.chart_repo_user = envs.helm_user.clone();
137+ deployment_parameters.chart_repo_pass = envs.helm_pass.clone();
138+ for deployment_override in cli_opts.deployment_config.clone().into_iter() {
139+ let split_override = deployment_override.split('=').collect::<Vec<_>>();
140+ match split_override.first().unwrap().as_ref() {
141+ "chart_repo_url" => deployment_parameters.chart_repo_url = split_override.last().unwrap().to_string(),
142+ "chart_version" => deployment_parameters.chart_version = split_override.last().unwrap().to_string(),
143+ "chart_name" => deployment_parameters.chart_name = split_override.last().unwrap().to_string(),
144+ "chart_repo_user" => deployment_parameters.chart_repo_user = split_override.last().unwrap().to_string(),
145+ "chart_repo_pass" => deployment_parameters.chart_repo_pass = split_override.last().unwrap().to_string(),
146+ _ => continue,
147+ }
148+ }
149+ return deployment_parameters;
150+ }
151+ pub fn new_env_only(default_values: &DefaultValues, envs: &EnvVars) -> Self {
152+ Self {
153+ chart_repo_url: default_values.chart_repo_url.clone(),
154+ chart_repo_user: envs.helm_user.clone(),
155+ chart_repo_pass: envs.helm_pass.clone(),
156+ chart_version: default_values.chart_version.clone(),
157+ chart_name: default_values.chart_name.clone(),
158+ }
159+ }
160+ }
161+ pub struct HelmCmd {
162+ pub name: String,
163+ pub mode: HelmMode,
164+ pub release_name: String,
165+ pub namespace: String,
166+ pub deployment_parameters: HelmDeploymentParameters,
167+ pub overrides: Vec<String>,
168+ }
169+
170+ impl HelmCmd {
171+ pub fn args(&self) -> Vec<String> {
172+ let mut args: Vec<String> = Vec::new();
173+ let chart_repo_name = url_to_name(&self.deployment_parameters.chart_repo_url);
174+ let chart_location = format!("{}/{}", chart_repo_name, self.deployment_parameters.chart_name);
175+ let chart_version = vec![String::from("--version"), self.deployment_parameters.chart_version.clone()];
176+ let namespace = vec![String::from("-n"), String::from(&self.namespace),];
177+ let common_args = vec![
178+ String::from("--debug"),
179+ ];
180+ match self.mode {
181+ HelmMode::Uninstall => {
182+ args.extend(namespace);
183+ args.push(String::from("uninstall"));
184+ args.push(String::from(&self.release_name));
185+ },
186+ HelmMode::UpgradeInstall => {
187+ args.extend(namespace);
188+ args.push(String::from("upgrade"));
189+ args.push(String::from("-i"));
190+ args.push(String::from(&self.release_name));
191+ args.push(chart_location);
192+ args.extend(chart_version);
193+ args.extend(self.set_flag_values());
194+ args.extend(common_args);
195+ },
196+ HelmMode::Template => {
197+ args.extend(namespace);
198+ args.push(String::from("template"));
199+ args.push(String::from(&self.release_name));
200+ args.push(chart_location);
201+ args.extend(chart_version);
202+ args.extend(self.set_flag_values());
203+ },
204+ HelmMode::ShowValues => {
205+ args.extend(namespace);
206+ args.push(String::from("show"));
207+ args.push(String::from("values"));
208+ args.push(chart_location);
209+ args.extend(chart_version);
210+ },
211+ HelmMode::RepoAdd => {
212+ args.push(String::from("repo"));
213+ args.push(String::from("add"));
214+ args.push(String::from("--force-update"));
215+ args.push(String::from(&chart_repo_name));
216+ args.push(String::from(&self.deployment_parameters.chart_repo_url));
217+ args.extend(vec![String::from("--username"), String::from(&self.deployment_parameters.chart_repo_user)]);
218+ args.extend(vec![String::from("--password"), String::from(&self.deployment_parameters.chart_repo_pass)]);
219+ },
220+ HelmMode::RepoUpdate => {
221+ args.push(String::from("repo"));
222+ args.push(String::from("update"));
223+ },
224+ HelmMode::RepoList => {
225+ args.push(String::from("repo"));
226+ args.push(String::from("list"));
227+ args.push(String::from("-o"));
228+ args.push(String::from("json"));
229+ },
230+ }
231+
232+ return args;
233+ }
234+ fn set_flag_values(&self) -> Vec<String> {
235+ let mut values = Vec::new();
236+ let mut set_values = Vec::new();
237+ values.extend(self.overrides.clone());
238+ for value in values.into_iter() {
239+ set_values.push(String::from("--set"));
240+ set_values.push(value);
241+ }
242+ return set_values;
243+ }
244+ pub fn run(&self) -> Result<ExitStatus, ExitStatus> {
245+ let helm = Command::new(&self.name)
246+ .args(&self.args())
247+ .output()
248+ .expect("Failed to run");
249+ info!("helm stdout:\n {}", String::from_utf8(helm.stdout).unwrap());
250+ info!("helm stderr:\n {}", String::from_utf8(helm.stderr).unwrap());
251+ if helm.status.success() {
252+ Ok(helm.status)
253+ } else {
254+ Err(helm.status)
255+ }
256+ }
257+ pub fn run_stdout(&self) -> Result<String, (ExitStatus, String)> {
258+ let helm = Command::new(&self.name)
259+ .args(&self.args())
260+ .output()
261+ .expect("Failed to run");
262+ if helm.status.success() {
263+ Ok(String::from_utf8(helm.stdout).unwrap())
264+ } else {
265+ let stdout = String::from_utf8(helm.stdout).unwrap();
266+ let stderr = String::from_utf8(helm.stderr).unwrap();
267+ info!("helm stdout:\n {}", stdout);
268+ info!("helm stderr:\n {}", stderr);
269+ Err((helm.status, stderr))
270+ }
271+ }
272+ }
273+ pub enum HelmMode {
274+ Uninstall,
275+ UpgradeInstall,
276+ Template,
277+ RepoAdd,
278+ RepoUpdate,
279+ RepoList,
280+ ShowValues,
281+ }
282+ #[derive(CustomResource, Debug, Serialize, Deserialize, Default, Clone, JsonSchema)]
283+ #[kube(group = "acid.zalan.do", version = "v1", kind = "Postgresql", namespaced)]
284+ pub struct PosgresqlSpec {
285+ numberOfInstances: i32
286+ }
287+ #[derive(CustomResource, Debug, Serialize, Deserialize, Default, Clone, JsonSchema)]
288+ #[kube(group = "kafka.strimzi.io", version = "v1beta2", kind = "Kafka", namespaced)]
289+ pub struct KafkaSpec {
290+ kafka: KafkaConfig,
291+ zookeeper: ZookeeperConfig
292+ }
293+ #[derive(Debug, Serialize, Deserialize, Default, Clone, JsonSchema)]
294+ struct KafkaConfig {
295+ replicas: i32
296+ }
297+ #[derive(Debug, Serialize, Deserialize, Default, Clone, JsonSchema)]
298+ struct ZookeeperConfig {
299+ replicas: i32
300+ }
301+ fn check_value(value: String) -> Result<String, String> {
302+ let re = Regex::new(r"^([^=]*)=(.*)$").unwrap();
303+ match re.captures(&value) {
304+ Some(_) => return Ok(value),
305+ None => return Err(format!("Override value {} is malformed", value)),
306+ }
307+ }
308+ pub fn overrides(cli_opts: &CliOpts, envs: &EnvVars) -> Option<Vec<String>> {
309+ let mut overrides_opts = Vec::new();
310+ overrides_opts.extend(&cli_opts.application_config);
311+ let ingress_override = match &envs.ingress_host_key {
312+ Some(key) => format!("{}={}", &key, domain_name(&cli_opts)),
313+ None => format!("ingress.hostname={}", domain_name(&cli_opts)),
314+ };
315+ overrides_opts.push(&ingress_override);
316+ if overrides_opts.is_empty() {
317+ None
318+ } else {
319+ Some(overrides_opts
320+ .into_iter()
321+ .map(|value| check_value(value.to_string()).unwrap())
322+ .collect::<Vec<_>>()
323+ )
324+ }
325+ }
326+ fn domain_name(cli_opts: &CliOpts) -> String {
327+ match &cli_opts.name {
328+ Some(name) => {
329+ return format!("{}.{}", name, &cli_opts.base_domain);
330+ },
331+ None => panic!("No name argument provided")
332+ }
333+ }
334+ pub fn parse_to_k8s(yaml: String) -> Result<(Vec<Deployment>, Vec<StatefulSet>, Vec<Ingress>, Vec<OldIngress>, Vec<Postgresql>, Vec<Kafka>), serde_yaml::Error> {
335+ let docs = YamlLoader::load_from_str(&yaml).unwrap();
336+ let mut deployments: Vec<Deployment> = Vec::new();
337+ let mut statefulsets: Vec<StatefulSet> = Vec::new();
338+ let mut ingresses: Vec<Ingress> = Vec::new();
339+ let mut old_ingresses: Vec<OldIngress> = Vec::new();
340+ let mut postgresqls: Vec<Postgresql> = Vec::new();
341+ let mut kafkas: Vec<Kafka> = Vec::new();
342+ for doc in docs {
343+ match doc["kind"].as_str().unwrap() {
344+ "Deployment" => {
345+ let mut deployment_str = String::new();
346+ let mut emitter = YamlEmitter::new(&mut deployment_str);
347+ emitter.dump(&doc).unwrap();
348+ let deployment: Deployment = serde_yaml::from_str(&deployment_str)?;
349+ deployments.push(deployment);
350+ },
351+ "StatefulSet" => {
352+ let mut statefulset_str = String::new();
353+ let mut emitter = YamlEmitter::new(&mut statefulset_str);
354+ emitter.dump(&doc).unwrap();
355+ let statefulset: StatefulSet = serde_yaml::from_str(&statefulset_str)?;
356+ statefulsets.push(statefulset);
357+ },
358+ "Ingress" => {
359+ let mut ingress_str = String::new();
360+ let mut emitter = YamlEmitter::new(&mut ingress_str);
361+ emitter.dump(&doc).unwrap();
362+ if doc["apiVersion"].as_str().unwrap() == "networking.k8s.io/v1beta1" {
363+ let ingress: OldIngress = serde_yaml::from_str(&ingress_str)?;
364+ old_ingresses.push(ingress);
365+ }else{
366+ let ingress: Ingress = serde_yaml::from_str(&ingress_str)?;
367+ ingresses.push(ingress);
368+ }
369+ },
370+ "postgresql" => {
371+ let mut postgresql_str = String::new();
372+ let mut emitter = YamlEmitter::new(&mut postgresql_str);
373+ emitter.dump(&doc).unwrap();
374+ let postgresql: Postgresql = serde_yaml::from_str(&postgresql_str)?;
375+ postgresqls.push(postgresql);
376+ },
377+ "Kafka" => {
378+ let mut kafka_str = String::new();
379+ let mut emitter = YamlEmitter::new(&mut kafka_str);
380+ emitter.dump(&doc).unwrap();
381+ let kafka: Kafka = serde_yaml::from_str(&kafka_str)?;
382+ kafkas.push(kafka);
383+ },
384+ _ => continue,
385+ }
386+ }
387+ if deployments.is_empty() && statefulsets.is_empty() {
388+ panic!("Got no deployment or stateful sets. Nothing to check");
389+ }
390+ return Ok((deployments, statefulsets, ingresses, old_ingresses, postgresqls, kafkas));
391+ }
392+
393+ #[derive(Debug)]
394+ pub struct NoReplicasError(String);
395+
396+ impl fmt::Display for NoReplicasError {
397+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
398+ write!(f, "Deployment {} doesn't have any replicas", self.0)
399+ }
400+ }
401+ impl Error for NoReplicasError {}
402+
403+ #[derive(Debug)]
404+ pub enum KubeError {
405+ NoReplicasError(NoReplicasError),
406+ KubeApiError(kube::Error),
407+ }
408+
409+ impl From<NoReplicasError> for KubeError {
410+ fn from(error: NoReplicasError) -> Self {
411+ KubeError::NoReplicasError(error)
412+ }
413+ }
414+
415+ impl From<kube::Error> for KubeError {
416+ fn from(error: kube::Error) -> Self {
417+ KubeError::KubeApiError(error)
418+ }
419+ }
420+
421+ #[tokio::main]
422+ async fn check_deployment(namespace: &str, name: &str) -> Result<(), KubeError> {
423+ let client = Client::try_default().await?;
424+ let api: Api<Deployment> = Api::namespaced(client, &namespace);
425+ let deployment = api.get(&name).await?;
426+ match deployment.status {
427+ Some(status) => {
428+ match status.available_replicas {
429+ Some(replicas) => {
430+ if !replicas >= 1 {
431+ return Err(KubeError::NoReplicasError(NoReplicasError(name.to_string())));
432+ }
433+ },
434+ None => {
435+ return Err(KubeError::NoReplicasError(NoReplicasError(name.to_string())));
436+ }
437+ }
438+ },
439+ None => {
440+ return Err(KubeError::NoReplicasError(NoReplicasError(name.to_string())));
441+ }
442+ }
443+ Ok(())
444+ }
445+ #[tokio::main]
446+ async fn check_statefulset(namespace: &str, name: &str) -> Result<(), KubeError> {
447+ let client = Client::try_default().await?;
448+ let api: Api<StatefulSet> = Api::namespaced(client, &namespace);
449+ let statefulset = api.get(&name).await?;
450+ match statefulset.status {
451+ Some(status) => {
452+ match status.current_replicas {
453+ Some(replicas) => {
454+ if !replicas >= 1 {
455+ return Err(KubeError::NoReplicasError(NoReplicasError(name.to_string())));
456+ }
457+ },
458+ None => {
459+ return Err(KubeError::NoReplicasError(NoReplicasError(name.to_string())));
460+ }
461+ }
462+ },
463+ None => {
464+ return Err(KubeError::NoReplicasError(NoReplicasError(name.to_string())));
465+ }
466+ }
467+ Ok(())
468+ }
469+ pub fn check_all(deployments: Vec<Deployment>, statefulsets: Vec<StatefulSet>, namespace: String) -> Result<(), KubeError> {
470+ if deployments.is_empty() {
471+ info!("No deployments to check");
472+ }else{
473+ for deploy in deployments {
474+ match check_deployment(&namespace, &deploy.name()) {
475+ Ok(status) => status,
476+ Err(err) => {
477+ return Err(err);
478+ }
479+ }
480+ }
481+ }
482+
483+ if statefulsets.is_empty() {
484+ info!("No statefulsets to check");
485+ }else{
486+ for statefulset in statefulsets {
487+ match check_statefulset(&namespace, &statefulset.name()) {
488+ Ok(status) => status,
489+ Err(err) => {
490+ return Err(err);
491+ }
492+ }
493+ }
494+ }
495+ Ok(())
496+ }
497+ //TODO: We seriously need a generic here
498+ pub fn ingresses_to_hosts(new_ingresses: Vec<Ingress>, old_ingresses: Vec<OldIngress>, default_name: String) -> Option<Vec<(String, String)>> {
499+ let mut hosts: Vec<(String, String)> = Vec::new();
500+ if new_ingresses.is_empty() {
501+ for ingress in old_ingresses {
502+ let ingress_name = match &ingress.metadata.name {
503+ Some(name) => name,
504+ None => {
505+ warn!("Can't parse ingress name");
506+ &default_name
507+ }
508+ };
509+ match &ingress.spec {
510+ Some(spec) => {
511+ let scheme = if spec.tls.is_empty() {
512+ "http"
513+ }else{
514+ "https"
515+ };
516+ for rule in &spec.rules {
517+ match &rule.host {
518+ Some(host) => hosts.push((ingress_name.to_string(), format!("{}://{}",scheme, host))),
519+ None => continue
520+ }
521+ }
522+ },
523+ None => continue
524+ }
525+ }
526+ }else{
527+ for ingress in new_ingresses {
528+ let ingress_name = match &ingress.metadata.name {
529+ Some(name) => name,
530+ None => {
531+ warn!("Can't parse ingress name");
532+ &default_name
533+ }
534+ };
535+ match &ingress.spec {
536+ Some(spec) => {
537+ let scheme = if spec.tls.is_empty() {
538+ "http"
539+ }else{
540+ "https"
541+ };
542+ for rule in &spec.rules {
543+ match &rule.host {
544+ Some(host) => hosts.push((ingress_name.to_string(), format!("{}://{}",scheme, host))),
545+ None => continue
546+ }
547+ }
548+ },
549+ None => continue
550+ }
551+ }
552+ }
553+ if hosts.is_empty() {
554+ None
555+ }else{
556+ Some(hosts)
557+ }
558+ }
559+ pub fn print_kv(kv: Option<Vec<(String,String)>>) -> String {
560+ let mut out_string = String::from("");
561+ match kv {
562+ Some(values) => {
563+ for value in values {
564+ out_string.push_str(&format!("{},{}\n", value.0, value.1));
565+ }
566+ },
567+ None => return out_string
568+ }
569+ return out_string;
570+ }
571+ pub fn print_keys(vals: Option<Vec<String>>) -> String {
572+ let mut out_string = String::from("");
573+ match vals {
574+ Some(values) => {
575+ for value in values {
576+ out_string.push_str(&format!("{}\n", value));
577+ }
578+ },
579+ None => return out_string
580+ }
581+ return out_string;
582+ }
583+ //TODO: Generics!!!
584+ pub fn deployments_statefulsets_to_images(deployments: Vec<Deployment>, statefulsets: Vec<StatefulSet>) -> Option<Vec<String>> {
585+ let mut images: Vec<String> = Vec::new();
586+ if deployments.is_empty() {
587+ info!("No deployments to extract images from");
588+ }else{
589+ for deployment in deployments {
590+ let deployment_name = match &deployment.metadata.name {
591+ Some(name) => name,
592+ None => "NoName!"
593+ };
594+ match &deployment.spec {
595+ Some(spec) => match &spec.template.spec {
596+ Some(podspec) => {
597+ for container in &podspec.containers {
598+ match &container.image {
599+ Some(image) => images.push(String::from(image)),
600+ None => warn!("No Image found for container {}", container.name)
601+ }
602+ }
603+ },
604+ None => warn!("No podspec in deployment {}", &deployment_name),
605+ },
606+ None => warn!("No deployment spec in deployment {}", &deployment_name),
607+ }
608+ }
609+ }
610+ if statefulsets.is_empty() {
611+ info!("No statefulsets to extract images from");
612+ }else{
613+ for statefulset in statefulsets {
614+ let statefulset_name = match &statefulset.metadata.name {
615+ Some(name) => name,
616+ None => "NoName!"
617+ };
618+ match &statefulset.spec {
619+ Some(spec) => match &spec.template.spec {
620+ Some(podspec) => {
621+ for container in &podspec.containers {
622+ match &container.image {
623+ Some(image) => images.push(String::from(image)),
624+ None => warn!("No Image found for container {}", container.name)
625+ }
626+ }
627+ },
628+ None => warn!("No podspec in statefulset {}", &statefulset_name),
629+ },
630+ None => warn!("No statefulset spec in statefulset {}", &statefulset_name),
631+ }
632+ }
633+ }
634+ if images.is_empty() {
635+ None
636+ }else{
637+ Some(images)
638+ }
639+ }
640+ #[tokio::main]
641+ async fn check_image(registry: &str, repository: &str, tag: &str) -> Result<(), RegError> {
642+ let client = RegClient::configure()
643+ .insecure_registry(false)
644+ .registry(registry)
645+ .build()?;
646+ let aclient = client.authenticate(&[&format!("repository:{}:pull", repository)]).await?;
647+ match aclient.has_manifest(repository, tag, None).await? {
648+ Some(_) => return Ok(()),
649+ None => panic!("Image not found: {} {} {}", registry, repository, tag),
650+ }
651+ }
652+ #[tokio::main]
653+ pub async fn check_ecr_image(registry: &str, repository: &str, tag: &str) -> Result<(), DescribeImagesError>{
654+ let re = Regex::new(r"^[0-9]*.dkr.ecr.(.*).amazonaws.com$").unwrap();
655+ let captures = re.captures(&registry).unwrap();
656+ let region_string = String::from(&captures[1]);
657+ let region: Region = region_string.parse().unwrap();
658+ let client = EcrClient::new(region);
659+ let image_id = ImageIdentifier {
660+ image_tag: Some(String::from(tag)),
661+ image_digest: None,
662+ };
663+ let describe_request = DescribeImagesRequest {
664+ repository_name: String::from(repository),
665+ image_ids: Some(vec![image_id]),
666+ filter: None,
667+ max_results: None,
668+ next_token: None,
669+ registry_id: None,
670+ };
671+ match client.describe_images(describe_request).await {
672+ Ok(_) => return Ok(()),
673+ Err(err) => panic!("Image not found in ECR: {} {} {}\n {}", registry, repository, tag, err),
674+ }
675+ }
676+ fn parse_image_name(image_name: &str) -> (String, String, String) {
677+ let mut registry = String::new();
678+ let mut repository = String::new();
679+ let re = Regex::new(r"^([^/:]*)/??([^/:]*)/??([^/:]*):??([^/:]*)$").unwrap();
680+ let captures = re.captures(&image_name).unwrap();
681+ let tag = String::from(&captures[4]);
682+ if &captures[2] == "" && &captures[3] == "" {
683+ registry = String::from("registry-1.docker.io");
684+ repository = format!("library/{}", &captures[1])
685+ } else if &captures[2] == "" {
686+ registry = String::from(&captures[1]);
687+ repository = String::from(&captures[3]);
688+ } else {
689+ if &captures[1] == "docker.io" {
690+ registry = String::from("registry-1.docker.io");
691+ }else{
692+ registry = String::from(&captures[1]);
693+ }
694+ repository = format!("{}/{}", &captures[2], &captures[3]);
695+ }
696+ info!("Checking image: {} {} {}", registry, repository, tag);
697+ (registry, repository, tag)
698+ }
699+ pub fn check_images(images: Vec<String>) -> Result<(), Box<dyn error::Error>> {
700+ for image in images {
701+ let (registry, repository, tag) = parse_image_name(&image);
702+ if registry.contains("dkr.ecr") {
703+ match check_ecr_image(&registry, &repository, &tag) {
704+ Ok(_) => (),
705+ Err(err) => return Err(Box::new(err)),
706+ }
707+ } else {
708+ match check_image(&registry, &repository, &tag) {
709+ Ok(_) => (),
710+ Err(err) => return Err(Box::new(err)),
711+ }
712+ }
713+ }
714+ Ok(())
715+ }
716+ pub fn helm_repo_add_update(envs: &EnvVars, deployment_parameters: &HelmDeploymentParameters) {
717+ let helm_repo_add = HelmCmd {
718+ name: String::from(&envs.helm_bin),
719+ mode: HelmMode::RepoAdd,
720+ release_name: String::from(""),
721+ namespace: String::from(""),
722+ deployment_parameters: deployment_parameters.clone(),
723+ overrides: vec![],
724+ };
725+ let helm_repo_update = HelmCmd {
726+ name: String::from(&envs.helm_bin),
727+ mode: HelmMode::RepoUpdate,
728+ release_name: String::from(""),
729+ namespace: String::from(""),
730+ deployment_parameters: deployment_parameters.clone(),
731+ overrides: vec![],
732+ };
733+ match helm_repo_add.run() {
734+ Ok(_status) => info!("Repo add success!"),
735+ Err(status) => {
736+ println!("Couldn't add repo.");
737+ error!("Error during helm execution");
738+ panic!("{:?}", status);
739+ }
740+ }
741+ match helm_repo_update.run() {
742+ Ok(_status) => info!("Repo update success!"),
743+ Err(status) => {
744+ println!("Couldn't update repo.");
745+ error!("Error during helm execution");
746+ panic!("{:?}", status);
747+ }
748+ }
749+ }
750+ pub fn helm_init(envs: &EnvVars, deployment_parameters: &HelmDeploymentParameters) {
751+ match &envs.helm_on_init_only {
752+ Some(enabled) => {
753+ if *enabled {
754+ info!("Skipping helm initialization, it must be initialied on init");
755+ } else {
756+ if helm_repo_exists(&envs, &deployment_parameters) {
757+ info!("Skipping helm initialization, because requested repo was already added");
758+ } else {
759+ info!("Starting helm initialization");
760+ helm_repo_add_update(&envs, &deployment_parameters);
761+ }
762+ }
763+ },
764+ None => {
765+ if helm_repo_exists(&envs, &deployment_parameters) {
766+ info!("Skipping helm initialization, because requested repo was already added");
767+ } else {
768+ info!("Starting helm initialization");
769+ helm_repo_add_update(&envs, &deployment_parameters);
770+ }
771+ }
772+ }
773+ }
774+
775+ fn helm_repo_exists(envs: &EnvVars, deployment_parameters: &HelmDeploymentParameters) -> bool {
776+ let chart_repo_url = String::from(&deployment_parameters.chart_repo_url);
777+ let chart_repo_name = url_to_name(&deployment_parameters.chart_repo_url);
778+ let helm_repo_list = HelmCmd {
779+ name: String::from(&envs.helm_bin),
780+ mode: HelmMode::RepoList,
781+ release_name: String::from(""),
782+ namespace: String::from(""),
783+ deployment_parameters: deployment_parameters.clone(),
784+ overrides: vec![],
785+ };
786+ match helm_repo_list.run_stdout() {
787+ Ok(list) => {
788+ let helm_repos: Vec<HelmRepo> = serde_json::from_str(&list).unwrap();
789+ for repo in helm_repos {
790+ if repo.name == chart_repo_name && repo.url == chart_repo_url {
791+ return true;
792+ } else {
793+ continue
794+ }
795+ }
796+ },
797+ Err(_err) => {
798+ return false;
799+ }
800+ }
801+ false
802+ }
803+ pub fn helm_values_as_keys(yaml: String) -> Option<Vec<String>> {
804+ let mut keys: Vec<String> = Vec::new();
805+ let docs = YamlLoader::load_from_str(&yaml).unwrap();
806+ let docs_hash = &docs[0].clone().into_hash().unwrap();
807+ for doc in docs_hash {
808+ match doc.1.as_hash() {
809+ Some(hash) => {
810+ if hash.is_empty() {
811+ keys.push(format!("{}", doc.0.as_str().unwrap()));
812+ }else{
813+ for doc_2 in hash {
814+ match doc_2.1.as_hash() {
815+ Some(hash_2) => {
816+ if hash_2.is_empty() {
817+ keys.push(format!("{}.{}", doc.0.as_str().unwrap(), doc_2.0.as_str().unwrap()));
818+ }else{
819+ for key in hash_2.keys() {
820+ keys.push(format!("{}.{}.{}", doc.0.as_str().unwrap(), doc_2.0.as_str().unwrap(), key.as_str().unwrap()));
821+ }
822+ }
823+ },
824+ None => keys.push(format!("{}.{}", doc.0.as_str().unwrap(), doc_2.0.as_str().unwrap()))
825+ }
826+ }
827+ }
828+ },
829+ None => keys.push(format!("{}", doc.0.as_str().unwrap())),
830+ }
831+ }
832+ if keys.is_empty() {
833+ None
834+ }else{
835+ keys.sort();
836+ Some(keys)
837+ }
838+ }
839+ #[tokio::main]
840+ async fn scale_deployment(namespace: &str, name: &str, replicas: i32) -> Result<(), kube::Error> {
841+ let client = Client::try_default().await?;
842+ let api: Api<Deployment> = Api::namespaced(client, &namespace);
843+ let deployment = api.get(&name).await?;
844+ let mut spec = match deployment.spec {
845+ Some(spec) => spec,
846+ None => panic!("Deployment without any spec!")
847+ };
848+ spec.replicas = Some(replicas);
849+ let patched_deployment = Deployment {
850+ metadata: deployment.metadata,
851+ spec: Some(spec),
852+ status: None
853+ };
854+ let patch = Patch::Merge(patched_deployment);
855+ let patch_params = PatchParams::apply("octopod");
856+ api.patch(&name, &patch_params, &patch).await?;
857+ Ok(())
858+ }
859+ #[tokio::main]
860+ async fn scale_statefulset(namespace: &str, name: &str, replicas: i32) -> Result<(), kube::Error> {
861+ let client = Client::try_default().await?;
862+ let api: Api<StatefulSet> = Api::namespaced(client, &namespace);
863+ let statefulset = api.get(&name).await?;
864+ let mut spec = match statefulset.spec {
865+ Some(spec) => spec,
866+ None => panic!("StatefulSet without any spec!")
867+ };
868+ spec.replicas = Some(replicas);
869+ let patched_statefulset = StatefulSet {
870+ metadata: statefulset.metadata,
871+ spec: Some(spec),
872+ status: None
873+ };
874+ let patch = Patch::Merge(patched_statefulset);
875+ let patch_params = PatchParams::apply("octopod");
876+ api.patch(&name, &patch_params, &patch).await?;
877+ Ok(())
878+ }
879+ #[tokio::main]
880+ async fn scale_postgresql(namespace: &str, name: &str, replicas: i32) -> Result<(), kube::Error> {
881+ let client = Client::try_default().await?;
882+ let api: Api<Postgresql> = Api::namespaced(client, &namespace);
883+ let postgres = api.get(&name).await?;
884+ println!("{:#?}", postgres);
885+ let mut spec = postgres.spec;
886+ spec.numberOfInstances = replicas;
887+ let patched_postgres = Postgresql {
888+ api_version: postgres.api_version,
889+ kind: postgres.kind,
890+ metadata: postgres.metadata,
891+ spec: spec,
892+ };
893+ let patch = Patch::Merge(patched_postgres);
894+ let patch_params = PatchParams::apply("octopod");
895+ api.patch(&name, &patch_params, &patch).await?;
896+ Ok(())
897+ }
898+ #[tokio::main]
899+ async fn scale_kafka(namespace: &str, name: &str, replicas: i32) -> Result<(), kube::Error> {
900+ let client = Client::try_default().await?;
901+ let api: Api<Kafka> = Api::namespaced(client.clone(), &namespace);
902+ let kafka = api.get(&name).await?;
903+ let metadata = kafka.metadata;
904+ if replicas > 0 {
905+ if metadata.annotations.contains_key("strimzi.io/pause-reconciliation") {
906+ println!("deleting pause-reconciliation annotation");
907+ let remove_op = json_patch::RemoveOperation {
908+ path: String::from("/metadata/annotations/strimzi.io~1pause-reconciliation")
909+ };
910+ let patch_op = json_patch::PatchOperation::Remove(remove_op);
911+ let json_patch = json_patch::Patch(vec![patch_op]);
912+ let patch = Patch::Json::<()>(json_patch);
913+ let patch_params = PatchParams::apply("octopod");
914+ api.patch(&name, &patch_params, &patch).await?;
915+ }
916+ } else {
917+ if !metadata.annotations.contains_key("strimzi.io/pause-reconciliation") {
918+ println!("adding pause-reconciliation annotation");
919+ let add_op = json_patch::AddOperation {
920+ path: String::from("/metadata/annotations/strimzi.io~1pause-reconciliation"),
921+ value: serde_json::value::Value::String("true".to_string())
922+ };
923+ let patch_op = json_patch::PatchOperation::Add(add_op);
924+ let json_patch = json_patch::Patch(vec![patch_op]);
925+ let patch = Patch::Json::<()>(json_patch);
926+ let patch_params = PatchParams::apply("octopod");
927+ api.patch(&name, &patch_params, &patch).await?;
928+ }
929+ }
930+
931+ let kafka_sts: Api<StatefulSet> = Api::namespaced(client, &namespace);
932+ let sts_list = ListParams::default().labels(&format!("strimzi.io/cluster={}", name));
933+ for sts in kafka_sts.list(&sts_list).await? {
934+ let sts_namespace = String::from(namespace);
935+ let sts_replicas = replicas.clone();
936+ task::spawn_blocking(move || {
937+ scale_statefulset(&sts_namespace, &sts.name(), sts_replicas);
938+ }).await.expect("Failed to run thread")
939+ }
940+ Ok(())
941+ }
942+ pub fn scale(deployments: Vec<Deployment>, statefulsets: Vec<StatefulSet>, postgresqls: Vec<Postgresql>, kafkas: Vec<Kafka>, namespace: String, replicas: i32) -> Result<(), Box<dyn error::Error>> {
943+ if deployments.is_empty() {
944+ info!("No deployments to check");
945+ }else{
946+ for deploy in deployments {
947+ match scale_deployment(&namespace, &deploy.name(), replicas) {
948+ Ok(status) => status,
949+ Err(err) => {
950+ return Err(Box::new(err));
951+ }
952+ }
953+ }
954+ }
955+
956+ if statefulsets.is_empty() {
957+ info!("No statefulsets to check");
958+ }else{
959+ for statefulset in statefulsets {
960+ match scale_statefulset(&namespace, &statefulset.name(), replicas) {
961+ Ok(status) => status,
962+ Err(err) => {
963+ return Err(Box::new(err));
964+ }
965+ }
966+ }
967+ }
968+
969+ if postgresqls.is_empty() {
970+ info!("No postgresqls to check");
971+ }else{
972+ for postgres in postgresqls {
973+ match scale_postgresql(&namespace, &postgres.name(), replicas) {
974+ Ok(status) => status,
975+ Err(err) => {
976+ return Err(Box::new(err));
977+ }
978+ }
979+ }
980+ }
981+
982+ if kafkas.is_empty() {
983+ info!("No kafkas to check");
984+ }else{
985+ for kafka in kafkas {
986+ match scale_kafka(&namespace, &kafka.name(), replicas) {
987+ Ok(status) => status,
988+ Err(err) => {
989+ return Err(Box::new(err));
990+ }
991+ }
992+ }
993+ }
994+ Ok(())
995+ }
996+ pub fn ingresses_to_secrets(new_ingresses: Vec<Ingress>, old_ingresses: Vec<OldIngress>) -> Option<Vec<String>> {
997+ let mut secrets: Vec<String> = Vec::new();
998+ if new_ingresses.is_empty() {
999+ for ingress in old_ingresses {
1000+ match &ingress.spec {
1001+ Some(spec) => {
1002+ if spec.tls.is_empty() {
1003+ continue
1004+ }else{
1005+ for tls in &spec.tls {
1006+ match &tls.secret_name {
1007+ Some(secret) => secrets.push(String::from(secret)),
1008+ None => continue
1009+ }
1010+ }
1011+ }
1012+ },
1013+ None => continue
1014+ }
1015+ }
1016+ }else{
1017+ for ingress in new_ingresses {
1018+ match &ingress.spec {
1019+ Some(spec) => {
1020+ if spec.tls.is_empty() {
1021+ continue
1022+ }else{
1023+ for tls in &spec.tls {
1024+ match &tls.secret_name {
1025+ Some(secret) => secrets.push(String::from(secret)),
1026+ None => continue
1027+ }
1028+ }
1029+ }
1030+ },
1031+ None => continue
1032+ }
1033+ }
1034+ }
1035+ if secrets.is_empty() {
1036+ None
1037+ }else{
1038+ Some(secrets)
1039+ }
1040+ }
1041+ #[tokio::main]
1042+ pub async fn delete_pvcs(namespace: &str, selector: &str) -> Result<(), kube::Error> {
1043+ let client = Client::try_default().await?;
1044+ let api: Api<PersistentVolumeClaim> = Api::namespaced(client, &namespace);
1045+ let pvc_list = ListParams::default().labels(selector);
1046+ api.delete_collection(&DeleteParams::default(), &pvc_list).await?;
1047+ Ok(())
1048+ }
1049+ #[tokio::main]
1050+ pub async fn delete_secret(namespace: &str, secret: &str) -> Result<(), kube::Error> {
1051+ let client = Client::try_default().await?;
1052+ let api: Api<Secret> = Api::namespaced(client, &namespace);
1053+ api.delete(&secret, &DeleteParams::default()).await?;
1054+ Ok(())
1055+ }
1056+ fn url_to_name(url: &str) -> String {
1057+ let re_not_letters = Regex::new(r"\W").unwrap();
1058+ let name: String = re_not_letters.replace_all(url, "-").to_string();
1059+ return name;
1060+ }
1061+}
helm-control-scripts/src/unarchive.rsnew file+53
@@ -0,0 +1,53 @@
1+use helm_control_scripts::lib::*;
2+
3+fn main() {
4+ let mut log_builder = Builder::from_default_env();
5+ log_builder.target(Target::Stdout).filter(None, LevelFilter::Info).init();
6+ info!("Utils version {}", env!("CARGO_PKG_VERSION"));
7+ let envs = EnvVars::parse();
8+ info!("Env variables received {:?}", &envs);
9+ let cli_opts = CliOpts::from_args();
10+ info!("Cli options received {:?}", &cli_opts);
11+ let overrides = match overrides(&cli_opts, &envs) {
12+ Some(inner) => inner,
13+ None => vec![],
14+ };
15+
16+ let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &envs);
17+ let namespace = String::from(&cli_opts.namespace);
18+ let release_name = match cli_opts.name {
19+ Some(name) => name,
20+ None => {
21+ error!("mandatory name argument was not provided");
22+ panic!();
23+ }
24+ };
25+ let helm_template = HelmCmd {
26+ name: envs.helm_bin,
27+ mode: HelmMode::Template,
28+ release_name: release_name,
29+ namespace: cli_opts.namespace,
30+ deployment_parameters: deployment_parameters,
31+ overrides: overrides,
32+ };
33+ info!("Generated Helm args: {:?}", &helm_template.args());
34+ match helm_template.run_stdout() {
35+ Ok(status) => {
36+ let (deployments, statefulsets, _ingresses, _old_ingresses, postgresqls, kafkas) = match parse_to_k8s(status) {
37+ Ok((deployments, statefulsets, ingresses, old_ingresses, postgresqls, kafkas)) => (deployments, statefulsets, ingresses, old_ingresses, postgresqls, kafkas),
38+ Err(err) => panic!("{}", err)
39+ };
40+ match scale(deployments, statefulsets, postgresqls, kafkas, namespace, 1) {
41+ Ok(_status) => info!("Success!"),
42+ Err(status) => {
43+ error!("Error checking statuses");
44+ panic!("{}", status);
45+ }
46+ }
47+ }
48+ Err(status) => {
49+ error!("Error during helm execution");
50+ panic!("{:?}", status);
51+ }
52+ }
53+}
img/demo.gif

Binary file not shown.

img/logo.svgnew file+1
@@ -0,0 +1 @@
1+<svg xmlns="http://www.w3.org/2000/svg" width="139" height="48.096" viewBox="-5.553 0 139 48.096"><path fill="#FFF" d="M-5.5-.183h138.559v48.549H-5.5V-.183z"/><path fill="#8594F8" d="M21.214 17.557a.953.953 0 0 0 .734-.828l1.659-.771 1.238-2.479-3.467 2.25a.976.976 0 0 0-1.263.412.98.98 0 0 0 .108 1.095l-.213 1.025-.219 1.618-1.121 1.104.624 1.172.311.076-.353-1.188.858-.447.85.49-.289 1.174.323-.062.562-1.145-1-.965.436-1.483.222-1.048zm-.455-.554a.425.425 0 0 1 .406-.744c.206.114.28.371.169.577a.423.423 0 0 1-.575.167z"/><path fill="#8594F8" d="M36.404 18.802l-.447-1.879-.394-1.178.005-.006c.305-.557.1-1.254-.456-1.559a1.127 1.127 0 0 0-1.104.024l-2.715-1.247h.907v-1.384h.003V9.399a4.074 4.074 0 0 0-3.34-4.005v-.516a.256.256 0 0 0-.256-.258h-.203V2.936l.432-.431a.212.212 0 0 0 0-.3l-.562-.564a.214.214 0 0 0-.302 0l-.562.565a.208.208 0 0 0 0 .3l.43.431v1.688h-.201a.257.257 0 0 0-.258.257V5.4a4.077 4.077 0 0 0-3.338 4.004v2.15h-.001v1.406h1.677l-.565.969-1.511 3.115a1.412 1.412 0 0 0-1.065.727 1.43 1.43 0 0 0 .566 1.938c.032.018.065.026.1.041l.486 1.6.354.811-1.863.316-.492 1.832.324.34.853-1.684 1.84.168 1.15 1.412-.912 1.782.513.023 1.24-1.576-1.415-2.809-.172-.957-.437-1.437a1.425 1.425 0 0 0 .392-1.747l1.898-2.697.706-1.206.617 1.282 2.123 3.862c-.326.525-.303 1.215.135 1.695.116.129.255.219.399.295l.007 1.5.206 1.877-1.958 1.455.393 1.855.442.154v-1.893l1.713-.679 1.66.679v2.061l.469-.211.39-1.967-2.029-1.49.174-1.748-.008-1.695c.052-.034.11-.051.158-.094a1.43 1.43 0 0 0 .1-2.016c-.203-.225-.467-.342-.741-.405l-1.214-3.117-1.614-1.464 1.442.504 2.859.891c.022.382.216.746.575.941.091.05.188.065.283.089l.341 1.019.764 1.782-1.283 1.168.804 1.455.418.088-.435-1.48 1.183-.59 1.132.59-.434 1.48.442-.088.802-1.453-1.62-1.451zm-12.057-.096a.617.617 0 1 1-.245-.837c.3.164.408.538.245.837zm6.899.611a.614.614 0 0 1 .87.043.615.615 0 1 1-.87-.043zm-3.372-6.335l-.038-.021h.086l-.048.021zm.248-1.69a1.896 1.896 0 1 1 0-3.792 1.896 1.896 0 0 1 0 3.792zm6.885 4.16a.493.493 0 0 1-.672.198.493.493 0 0 1-.198-.673.498.498 0 0 1 .674-.198c.24.133.326.434.196.673z"/><path fill="#8594F8" d="M28.832 9.506a.625.625 0 1 1-.387-1.116 1.14 1.14 0 0 0-.358-.062 1.151 1.151 0 1 0 1.152 1.151c0-.04-.008-.078-.013-.117a.615.615 0 0 1-.394.144zM14.606 29.644h2.992v2.992h-2.992v-2.992zm25.008 0h2.993v2.992h-2.993v-2.992zm-4.288 0h2.993v2.992h-2.993v-2.992zm8.516 0h2.995v2.992h-2.995v-2.992zm-4.228-4.107h2.993v2.994h-2.993v-2.994zm4.228 0h2.995v2.994h-2.995v-2.994zm0-4.101h2.995v2.994h-2.995v-2.994zm-17.237 8.208h2.992v2.992h-2.992v-2.992zm-2.331-2.672l-2.427-1.247 1.247-2.427 2.426 1.246-1.246 2.428zm6.104-.807h2.729v2.729h-2.729v-2.729zm-11.399 3.479h2.992v2.992h-2.992v-2.992z"/><path fill="#201600" d="M55.412 23.787a4.766 4.766 0 0 0-2.358-.6c-1.363 0-2.517.459-3.427 1.367a6.587 6.587 0 0 0-.762 1.024c-.397.66-.6 1.455-.6 2.358-.044 1.326.404 2.467 1.333 3.395.347.348.692.615 1.029.797a4.68 4.68 0 0 0 2.196.6h.396c1.28-.045 2.354-.504 3.189-1.365.328-.322.586-.662.765-.996.398-.686.602-1.479.602-2.355.021-1.349-.43-2.499-1.334-3.428a6.204 6.204 0 0 0-1.029-.797zm-.57 4.222c0 .52-.18.965-.533 1.318a1.583 1.583 0 0 1-1.151.479c-.054 0-.108-.002-.171-.008a1.81 1.81 0 0 1-1.319-.533c-.358-.338-.512-.77-.469-1.32 0-.521.179-.965.532-1.322.314-.312.728-.47 1.224-.47h.1c.52 0 .965.183 1.317.533.332.351.492.798.47 1.323zm10.044-.037c-.043.564-.224 1.012-.536 1.326-.312.311-.732.471-1.254.471-.03 0-.062 0-.099-.002-.479 0-.914-.168-1.286-.498-.354-.396-.523-.854-.508-1.338.023-.094.037-.189.037-.283a.6.6 0 0 1 .062-.245c.062-.27.212-.545.438-.812.336-.336.775-.484 1.351-.469l.078.002V23.19l-.166-.002c-1.305 0-2.427.459-3.331 1.363a4.183 4.183 0 0 0-.8 1 5.128 5.128 0 0 0-.563 1.819 1.53 1.53 0 0 0-.032.291v.246c-.022 1.346.435 2.494 1.357 3.424.159.18.323.328.487.447.157.119.329.234.513.352.688.396 1.479.602 2.362.602 1.362 0 2.516-.459 3.417-1.363.178-.15.328-.314.453-.484.123-.166.24-.34.35-.516.396-.686.599-1.488.599-2.393V27.9h-2.924l-.005.072zm6.306-6.745h-2.933v6.946c0 .598.123 1.18.362 1.727.178.486.502.971.968 1.436.352.352.698.617 1.032.797.66.375 1.396.576 2.194.6h.238V29.8h-.103c-.547-.043-.981-.223-1.293-.531a1.682 1.682 0 0 1-.47-1.096v-2.148h1.864v-2.93h-1.864v-1.867l.005-.001zm9.446 2.56a4.772 4.772 0 0 0-2.359-.6c-1.365 0-2.518.459-3.428 1.367a6.572 6.572 0 0 0-.759 1.024c-.397.662-.602 1.457-.602 2.36-.043 1.324.405 2.465 1.332 3.393.348.35.693.617 1.028.797.663.375 1.4.576 2.197.6h.396c1.279-.045 2.354-.504 3.189-1.365.333-.33.59-.666.767-.996.396-.686.599-1.479.599-2.355.021-1.346-.424-2.499-1.332-3.428a6.24 6.24 0 0 0-1.028-.797zm-.568 4.222c0 .518-.18.963-.531 1.318a1.598 1.598 0 0 1-1.324.471 1.82 1.82 0 0 1-1.321-.533c-.357-.338-.511-.771-.469-1.32 0-.52.181-.965.532-1.322.32-.316.722-.47 1.227-.47h.099c.521 0 .965.183 1.318.533.329.351.486.798.469 1.323zm11.707-3.456c-.902-.906-2.023-1.365-3.328-1.365l-.093.002c-.881 0-1.676.199-2.358.596a3.568 3.568 0 0 0-1 .802c-.928.928-1.385 2.08-1.361 3.423v6.941h2.933v-2.547a4.54 4.54 0 0 0 1.703.328l.149-.002c.902 0 1.699-.203 2.357-.6a4.455 4.455 0 0 0 1.029-.799c.905-.885 1.365-2.023 1.365-3.393 0-.88-.201-1.685-.604-2.397a8.91 8.91 0 0 0-.792-.989zm-1.567 3.394c.021.549-.135.982-.471 1.32-.312.311-.756.49-1.324.531-.539.049-.981-.123-1.317-.504-.312-.289-.491-.727-.53-1.287-.022-.572.132-1.015.466-1.355.336-.332.781-.5 1.328-.5l.09-.002c.479 0 .894.158 1.226.471.354.358.532.802.532 1.326zm10.461-4.16a4.766 4.766 0 0 0-2.358-.6c-1.363 0-2.517.459-3.427 1.367a6.714 6.714 0 0 0-.762 1.024c-.397.664-.6 1.46-.6 2.358-.043 1.326.403 2.465 1.332 3.395a4.5 4.5 0 0 0 1.028.797 4.702 4.702 0 0 0 2.195.6h.399c1.278-.045 2.354-.504 3.189-1.365.328-.328.588-.664.766-.996.396-.686.599-1.479.599-2.355.022-1.346-.425-2.499-1.332-3.428a6.29 6.29 0 0 0-1.029-.797zm-.57 4.222c0 .52-.181.967-.533 1.318a1.581 1.581 0 0 1-1.15.479c-.053 0-.107-.002-.17-.008-.521 0-.965-.182-1.32-.533-.358-.336-.514-.77-.471-1.32 0-.529.176-.959.535-1.322.313-.312.726-.47 1.224-.47h.099c.521 0 .968.183 1.319.533.33.351.488.798.467 1.323zm9.922-7.041v2.545a4.546 4.546 0 0 0-1.855-.322c-.9 0-1.707.199-2.396.601-.161.104-.33.215-.515.348a4.533 4.533 0 0 0-.48.416c-.796.797-1.242 1.748-1.328 2.818a1.628 1.628 0 0 0-.033.31v.295c0 .902.201 1.709.6 2.393.104.17.217.338.349.518.121.166.272.33.446.479.908.906 2.06 1.365 3.425 1.365.858 0 1.652-.201 2.359-.6.181-.111.354-.23.514-.35.166-.121.331-.271.481-.447.928-.928 1.387-2.08 1.365-3.424V20.97l-2.932-.002zm-.467 8.295a1.943 1.943 0 0 1-1.33.504c-.548.043-.978-.111-1.314-.469-.354-.355-.533-.799-.535-1.336a.863.863 0 0 1-.016-.271 4.32 4.32 0 0 1 .049-.286c.062-.268.209-.521.438-.75.312-.312.762-.491 1.324-.532a1.733 1.733 0 0 1 1.316.465c.229.27.391.547.475.817.017.073.035.159.047.239s.019.17.019.27c.011.525-.147.978-.473 1.349z"/><path fill="#8594F8" d="M68.259 17.246h2.995v2.995h-2.995v-2.995z"/><g><path fill="#8594F8" d="M102.093 45.353a1.568 1.568 0 0 0-.075-.133 1.04 1.04 0 0 1-.411.41c-.576.301-1.162-.161-1.433-.679-.267-.509-.548-1.354.15-1.718.158-.083.344-.124.514-.114-.127-.3-.291-.646-.455-.961-.059-.112-.115-.221-.172-.316.129-.04.232-.07.387-.071l1.761 3.5-.266.082zm-1.018-1.813a.507.507 0 0 0-.528-.023c-.49.257-.188.988.01 1.366.182.347.458.712.895.483.202-.105.396-.282.378-.416l-.755-1.41zm1.137-1.31c.604-.315 1.28.178 1.575.741.252.482.432 1.289-.162 1.655-.596.22-1.117-.075-1.402-.62-.209-.399-.569-1.485-.011-1.776zm.364 1.673c.167.319.585.536.841.402.383-.2.206-.944.046-1.25-.238-.456-.673-.772-1.104-.61-.322.22.074 1.182.217 1.458zm2.454-.195a.362.362 0 0 1-.139.119.826.826 0 0 1-.17.061c-.333-.716-.835-1.599-1.146-2.326l.221-.058.145.239a.843.843 0 0 1 .405-.526c.56-.293.786-.154 1.88 1.885-.022.022-.059.041-.095.061a.719.719 0 0 1-.27.087 1.165 1.165 0 0 1-.141-.224c-.094-.18-.209-.435-.337-.678-.256-.491-.581-.97-.938-.787-.297.155-.31.23-.345.415l.93 1.732zm.149-3.264c.169-.181.232-.322.159-.462-.017-.032-.044-.063-.071-.096-.029.021-.054.041-.081.055-.126.066-.3-.132-.354-.234-.062-.121-.054-.247.045-.299.249-.13.561.171.674.388.137.262.083.564-.296.786l-.076-.138zm2.383-.496c-.232.146-.451.333-.685.479.432.594.693 1.645 1.319 1.317.099-.052.193-.125.299-.23.073.053.124.095.243.17a2.398 2.398 0 0 1-.637.493c-.459.24-.87-.416-1.191-1.029-.115-.22-.22-.429-.307-.596-.076.051-.312.17-.391.216-.079-.119-.138-.198-.191-.29a.35.35 0 0 0 .104-.042c.08-.042.164-.103.253-.149.032-.017.065-.029.088-.041-.119-.248-.264-.55-.373-.803l.221-.058c.133.229.264.48.393.718.239-.103.467-.228.706-.328l.149.173zm2.936-1.266c-.182.137-.416.26-.595.398.266.508.591 1.13.884 1.625.024.137-.02.228-.087.264-.076.039-.188.012-.265-.08-.17-.324-.516-1.062-.817-1.638l-.344.164c-.027-.043-.051-.089-.159-.296.097-.033.256-.101.354-.133-.059-.147-.13-.281-.196-.409-.312-.599-.427-.883.028-1.121.198-.104.453-.173.619-.163l.056.172c-.129.062-.262.113-.369.17-.212.11-.334.25-.167.57.066.126.106.19.139.253.045.086.085.163.181.357.135-.07.266-.126.384-.188.075-.04.143-.079.209-.127l.145.182zm.536-1.064c.604-.315 1.28.178 1.575.741.252.482.433 1.288-.162 1.655-.596.22-1.116-.076-1.401-.62-.209-.4-.57-1.485-.012-1.776zm.365 1.673c.167.319.585.536.842.401.382-.199.206-.944.046-1.25-.238-.455-.673-.771-1.104-.61-.322.221.072 1.184.216 1.459zm2.521-2.355c-.167-.148-.313-.152-.439-.087-.208.108-.316.339-.427.567-.003.006.791 1.525.852 1.584.021.116-.02.184-.082.216-.104.055-.269.013-.359-.095-.31-.691-.682-1.512-.967-2.21l.222-.06.166.285c.074-.176.202-.427.396-.528.293-.152.641-.167.796.13.016.031.035.067.045.107l-.203.091zm1.594-1.632c.031.06.068.13.113.205.176.314.437.769.685 1.242.105.202.229.419.342.635.367.702.626 1.428-.152 1.834-.225.118-.472.207-.711.297-.058-.089-.098-.12-.128-.179-.014-.027-.033-.063-.04-.11.231-.093.47-.166.663-.267.355-.187.544-.474.173-1.203a1.03 1.03 0 0 1-.387.356c-.685.357-1.198-.286-1.499-.862-.302-.576-.345-1.241.264-1.559.152-.08.343-.122.57-.104a2.458 2.458 0 0 0-.066-.137l.173-.148zm.007.594c-.1-.091-.355-.032-.557.073-.335.175-.316.623-.114 1.012.179.341.62 1.046 1.116.786a.51.51 0 0 0 .282-.445l-.727-1.426zm3.295.329c-.186.214-.75.702-1.013.839-.536.28-1.082-.425-1.308-.857-.335-.64-.313-1.236.42-1.619.298-.155.709-.105.885.231.284.545-.613 1.054-.983 1.356.204.358.48.753.939.513.36-.188.861-.6.919-.634l.141.171zm-1.335-1.205c-.133-.153-.233-.228-.382-.149-.351.184-.548.63-.407 1.02.221-.213.6-.618.789-.871zm1.874-1.238c-.234.146-.451.333-.686.479.433.594.694 1.645 1.32 1.317.099-.052.193-.125.298-.23.073.054.124.096.244.17a2.377 2.377 0 0 1-.637.493c-.459.24-.872-.415-1.192-1.028-.115-.221-.219-.43-.306-.597-.076.051-.312.17-.392.216-.08-.118-.138-.197-.19-.29a.344.344 0 0 0 .104-.042c.081-.042.163-.102.254-.149.032-.017.064-.029.088-.041-.119-.248-.264-.55-.374-.802l.222-.059c.132.229.264.48.393.718.239-.102.467-.228.705-.328l.149.173zm2.897-1.513c-.233.145-.451.332-.685.478.431.595.693 1.645 1.318 1.317.1-.052.194-.124.299-.23.073.054.125.096.243.171a2.366 2.366 0 0 1-.637.493c-.459.239-.87-.416-1.19-1.029-.115-.221-.22-.43-.307-.596-.076.051-.312.169-.391.215-.08-.119-.138-.197-.192-.289.037-.007.067-.023.104-.042.081-.042.164-.104.254-.15.031-.017.065-.029.087-.041-.117-.248-.264-.549-.372-.802l.222-.059c.131.229.263.481.393.718.238-.102.466-.227.704-.328l.15.174zm.715-.89c.603-.315 1.28.179 1.574.741.252.482.433 1.289-.161 1.655-.597.22-1.116-.075-1.401-.62-.209-.4-.571-1.484-.012-1.776zm.364 1.673c.167.319.584.536.84.402.384-.2.206-.944.046-1.25-.237-.455-.673-.771-1.104-.61-.32.22.075 1.183.218 1.458zm3.701-3.3c-.247.021-.525.051-.754.17-.262.137-.356.251-.206.538.317.608 1.374-.224 1.77.532.185.355.085.854-.372 1.1a1.165 1.165 0 0 1-.971.054l.056-.2c.307-.028.439.004.713-.139.271-.142.405-.366.286-.596-.283-.541-1.28.314-1.74-.564-.171-.328-.142-.71.224-.9.288-.15.688-.166.947-.193l.047.198zm1.649-.844c-.232.145-.451.332-.684.477.431.595.693 1.646 1.318 1.318.1-.052.193-.124.299-.23.073.054.124.095.243.17a2.362 2.362 0 0 1-.637.493c-.459.24-.87-.416-1.19-1.029-.115-.22-.219-.43-.306-.596-.078.052-.313.17-.393.216-.079-.119-.138-.197-.191-.289a.382.382 0 0 0 .104-.043c.081-.041.164-.103.253-.149.032-.017.066-.029.088-.041-.117-.249-.264-.55-.372-.802l.222-.059c.131.229.263.48.392.717.239-.102.467-.227.705-.327l.149.174zm.361-.437c.073-.232.275-.459.506-.578.652-.341 1.132.354 1.414.895.181.348.323.709.502 1.051.025.112-.007.183-.065.213-.1.052-.278-.017-.347-.146-.008-.015-.017-.031-.019-.047-.082.248-.239.463-.441.568a.657.657 0 0 1-.881-.28c-.284-.544-.058-1.327.483-1.61.036-.018.073-.033.116-.049-.147-.24-.363-.465-.674-.303-.153.08-.284.247-.392.469l-.202-.183zm1.607.605c-.065-.125-.136-.248-.201-.363l-.037.019c-.394.212-.646.769-.411 1.219.101.193.299.233.452.153.188-.099.332-.364.434-.555-.076-.152-.155-.314-.237-.473zm1.615-1.731c-.168-.146-.313-.151-.44-.085-.207.108-.316.337-.426.566-.003.007.791 1.525.852 1.584.02.115-.02.184-.082.216-.104.055-.27.013-.359-.095-.311-.691-.682-1.512-.967-2.21l.221-.06.167.286c.074-.176.201-.426.396-.527.292-.154.64-.169.795.128a.444.444 0 0 1 .045.108l-.202.089zm-20.759 17.415c-.234.146-.451.332-.686.478.431.595.692 1.644 1.319 1.316.1-.052.193-.123.298-.229.074.053.125.095.245.169a2.401 2.401 0 0 1-.637.494c-.461.24-.872-.416-1.192-1.029-.115-.22-.219-.43-.306-.596-.076.051-.313.17-.392.216-.08-.119-.138-.198-.192-.29a.355.355 0 0 0 .104-.042c.082-.042.164-.104.254-.151.031-.016.065-.027.089-.04-.119-.248-.266-.549-.374-.802l.222-.059c.131.229.263.481.393.718.239-.102.466-.227.705-.328l.15.175zm.026-1.516c.196.321.429.777.622 1.103a.87.87 0 0 1 .436-.549c.379-.198.887-.103 1.144.389l.755 1.445a.439.439 0 0 1-.134.104.886.886 0 0 1-.186.073c-.038-.072-.07-.146-.107-.218-.201-.384-.431-.757-.703-1.279-.205-.271-.434-.289-.617-.193a.736.736 0 0 0-.366.54c.303.514.593 1.113.89 1.624-.051.037-.108.079-.172.112a.656.656 0 0 1-.197.069c-.105-.221-.226-.451-.348-.685-.416-.797-.9-1.657-1.274-2.472l.257-.063zm5.018 1.039c-.187.214-.751.702-1.012.839-.536.28-1.083-.426-1.309-.857-.334-.641-.313-1.235.421-1.619.297-.155.707-.104.883.231.285.545-.611 1.054-.981 1.356.204.357.479.753.939.513.359-.188.861-.6.918-.635l.141.172zm-1.335-1.205c-.132-.154-.233-.228-.382-.149-.352.184-.548.631-.407 1.02.222-.212.6-.618.789-.871zm2.008-1.736c.023.045.047.09.074.132.114-.197.258-.329.41-.409.577-.301 1.163.161 1.434.679.266.509.547 1.354-.151 1.718a1.025 1.025 0 0 1-.514.114c.207.374.415.753.629 1.129.021.113-.019.181-.082.214-.104.054-.268.014-.358-.094l-1.709-3.4.267-.083zm1.017 1.813a.512.512 0 0 0 .527.022c.49-.257.188-.987-.009-1.365-.183-.348-.459-.713-.896-.484-.202.105-.396.282-.378.416l.756 1.411zm2.242-2.778c-.168-.146-.313-.151-.44-.085-.206.107-.315.338-.425.566-.003.006.791 1.525.852 1.584.02.116-.02.184-.084.217-.103.054-.268.012-.357-.095-.311-.692-.682-1.513-.967-2.211l.221-.06.166.285c.075-.176.201-.426.396-.527.292-.153.64-.168.795.129a.407.407 0 0 1 .044.108l-.201.089zm.763-1.223c.604-.316 1.28.179 1.574.741.252.482.433 1.287-.16 1.654-.597.221-1.117-.074-1.402-.619-.209-.401-.57-1.484-.012-1.776zm.365 1.672c.167.318.584.536.842.402.382-.2.206-.945.046-1.251-.238-.455-.673-.771-1.104-.61-.322.22.072 1.184.216 1.459zm1.095-2.923c.063.121.049.248-.059.305-.171.09-.355-.032-.441-.198-.064-.122-.055-.247.045-.299.166-.088.368.025.455.192zm.858 3.857c.49-.412.19-1.062-.09-1.599-.19-.365-.391-.725-.785-1.471-.057-.142-.025-.233.042-.269.086-.044.228-.005.312.135.128.244.262.488.403.759.023.046.072.129.136.25.873 1.671.745 2.042.273 2.288a.622.622 0 0 1-.207.067l-.084-.16zm2.62-2.512c-.186.214-.751.703-1.012.839-.536.28-1.083-.425-1.309-.857-.335-.64-.312-1.235.421-1.619.297-.155.708-.105.884.231.285.545-.613 1.055-.983 1.356.204.358.479.753.94.513.359-.188.861-.6.918-.634l.141.171zm-1.336-1.205c-.132-.153-.232-.228-.382-.149-.351.184-.548.631-.406 1.021.221-.214.599-.619.788-.872zm2.057-1.406a2.477 2.477 0 0 0-.33.138c-.644.337-.524 1.06-.237 1.609.171.328.424.656.834.441.135-.07.282-.184.45-.333a.453.453 0 0 1 .13-.113c.072-.038.136-.002.255.182a2.744 2.744 0 0 1-.652.495c-.671.351-.996.09-1.339-.567-.396-.756-.543-1.476.263-1.896.189-.1.395-.167.55-.155l.076.199zm1.577-.75c-.233.146-.451.333-.685.479.432.594.693 1.643 1.318 1.315.1-.052.194-.123.3-.229.073.054.123.097.243.171a2.398 2.398 0 0 1-.637.493c-.459.24-.87-.416-1.191-1.029-.114-.221-.219-.429-.306-.596-.077.051-.312.169-.393.216-.079-.119-.138-.197-.19-.29a.344.344 0 0 0 .104-.042c.08-.042.162-.104.253-.15.031-.017.066-.029.088-.04-.118-.248-.264-.55-.374-.802l.222-.059c.133.229.265.48.393.718.24-.103.468-.228.706-.329l.149.174z"/></g></svg>
img/release_workflow.pngnew file

Binary file not shown.

img/typeable.pngdeleted

Binary file not shown.

img/typeable_logo.svgnew file+1
@@ -0,0 +1 @@
1+<svg enable-background="new 0 0 294.907 62.023" height="62.023" viewBox="0 0 294.907 62.023" width="294.907" xmlns="http://www.w3.org/2000/svg"><path d="m15.886 22.642h7.715v23.163h6.721v-23.163h7.827v-5.46h-22.263z"/><path d="m100.99 19.746c-1.914-1.701-4.551-2.563-7.84-2.563h-11.094v28.623h6.721v-8.689h4.373c3.288 0 5.926-.855 7.838-2.543 1.897-1.673 2.877-3.899 2.916-6.615.001-.056.002-1.356.002-1.413 0-2.793-.982-5.08-2.916-6.8zm-4.803 10.849c-.667.703-1.688 1.06-3.037 1.06h-4.373v-9.013h4.373c1.356 0 2.379.366 3.037 1.088.674.739 1.017 1.699 1.017 2.851 0 .055-.001 1.354-.003 1.407-.031 1.064-.364 1.919-1.014 2.607z"/><path d="m124.167 33.762h12.028v-5.46h-12.028v-5.66h13.909v-5.46h-20.629v28.623h20.667v-5.442h-13.947z"/><path d="m159.432 17.182-10.896 28.623h6.633l2.215-5.908h10.924l2.387 5.908h6.725l-11.48-28.623zm6.638 17.179h-6.543l3.146-8.405z"/><path d="m206.916 30.738c.703-.473 1.281-1.053 1.729-1.729.715-1.089 1.078-2.335 1.078-3.706 0-2.684-1-4.742-2.973-6.119-1.902-1.328-4.559-2.001-7.895-2.001h-9.588v28.623h11.207c3.297 0 5.898-.725 7.732-2.152 1.879-1.463 2.834-3.629 2.834-6.439 0-1.684-.479-3.18-1.422-4.448-.669-.907-1.577-1.588-2.702-2.029zm-4.857-2.856c-.678.516-1.691.777-3.016.777h-3.055v-6.018h2.867c1.436 0 2.512.262 3.195.779.641.484.951 1.24.951 2.314.001.963-.308 1.664-.942 2.148zm-6.071 5.806h4.428c1.35 0 2.354.305 2.984.904.623.592.938 1.473.938 2.621 0 1.061-.303 1.826-.924 2.342-.65.537-1.639.809-2.939.809h-4.486v-6.676z"/><path d="m230.91 17.182h-6.721v28.623h18.989v-5.442h-12.268z"/><path d="m261.578 33.762h12.029v-5.46h-12.029v-5.66h13.91v-5.46h-20.629v28.623h20.666v-5.442h-13.947z"/><path d="m58.742 29.827h.119l5.766-12.645h7.276l-9.821 18.769v10.18h-6.701v-10.479l-9.663-18.47h7.277z" fill="#eaa213"/></svg>
migrations/deploy/add_detailed_failures.sqlnew file+14
@@ -0,0 +1,14 @@
1+-- Deploy octopod:add_detailed_failures to pg
2+ BEGIN;
3+
4+
5+ALTER TYPE statuses RENAME VALUE 'Failure' TO 'GenericFailure';
6+
7+
8+ALTER TYPE statuses ADD VALUE IF NOT EXISTS 'TagMismatch';
9+
10+
11+ALTER TYPE statuses ADD VALUE IF NOT EXISTS 'PartialAvailability';
12+
13+
14+COMMIT;
migrations/deploy/migrate_2.0.sqlnew file+62
@@ -0,0 +1,62 @@
1+-- Deploy octopod:migrate_2.0 to pg
2+
3+BEGIN;
4+
5+-- XXX Add DDLs here.
6+
7+ALTER TABLE deployments ADD COLUMN app_overrides jsonb;
8+UPDATE deployments AS d SET app_overrides =
9+ ( SELECT COALESCE(jsonb_agg(jsonb_build_array("do".key, jsonb_build_object('tag', 'ValueAdded', 'contents', "do".value))), jsonb_build_array())
10+ FROM deployment_overrides as "do"
11+ WHERE d.id = "do".deployment_id AND scope = 'ApplicationScope'
12+ );
13+ALTER TABLE deployments ALTER COLUMN app_overrides SET NOT NULL;
14+
15+ALTER TABLE deployments ADD COLUMN deployment_overrides jsonb;
16+UPDATE deployments AS d SET deployment_overrides =
17+ ( SELECT COALESCE(jsonb_agg(jsonb_build_array("do".key, jsonb_build_object('tag', 'ValueAdded', 'contents', "do".value))), jsonb_build_array())
18+ FROM deployment_overrides as "do"
19+ WHERE d.id = "do".deployment_id AND scope = 'DeploymentScope'
20+ );
21+ALTER TABLE deployments ALTER COLUMN deployment_overrides SET NOT NULL;
22+
23+ALTER TABLE deployments ADD COLUMN links jsonb;
24+UPDATE deployments AS d SET links =
25+ ( SELECT COALESCE(jsonb_agg(jsonb_build_object('name', "dm".key, 'link', "dm".value)), jsonb_build_array())
26+ FROM deployment_metadata as "dm"
27+ WHERE d.id = "dm".deployment_id
28+ );
29+ALTER TABLE deployments ALTER COLUMN links SET NOT NULL;
30+
31+ALTER TABLE deployments ALTER COLUMN "status" DROP DEFAULT;
32+ALTER TABLE deployments ALTER COLUMN "status" TYPE text;
33+
34+DROP TABLE deployment_overrides;
35+DROP TABLE deployment_metadata;
36+
37+
38+ALTER TABLE deployment_logs ALTER COLUMN "action" TYPE text;
39+
40+ALTER TABLE deployment_logs ALTER COLUMN "duration" DROP DEFAULT;
41+ALTER TABLE deployment_logs ALTER COLUMN "duration" TYPE interval USING (duration || ' seconds') :: interval;
42+
43+ALTER TABLE deployment_logs ADD COLUMN deployment_overrides jsonb;
44+UPDATE deployment_logs AS d SET deployment_overrides =
45+ ( SELECT COALESCE(jsonb_agg(jsonb_build_array("do".key, jsonb_build_object('tag', 'ValueAdded', 'contents', "do".value))), jsonb_build_array())
46+ FROM deployment_log_overrides as "do"
47+ WHERE d.id = "do".deployment_log_id AND scope = 'DeploymentScope'
48+ );
49+ALTER TABLE deployment_logs ALTER COLUMN deployment_overrides SET NOT NULL;
50+
51+ALTER TABLE deployment_logs ADD COLUMN app_overrides jsonb;
52+UPDATE deployment_logs AS d SET app_overrides =
53+ ( SELECT COALESCE(jsonb_agg(jsonb_build_array("do".key, jsonb_build_object('tag', 'ValueAdded', 'contents', "do".value))), jsonb_build_array())
54+ FROM deployment_log_overrides as "do"
55+ WHERE d.id = "do".deployment_log_id AND scope = 'ApplicationScope'
56+ );
57+ALTER TABLE deployment_logs ALTER COLUMN app_overrides SET NOT NULL;
58+
59+DROP TABLE deployment_log_overrides;
60+
61+
62+COMMIT;
migrations/deploy/move_tag_to_overrides.sqlnew file+18
@@ -0,0 +1,18 @@
1+-- Deploy octopod:move_tag_to_overrides to pg
2+
3+BEGIN;
4+
5+
6+UPDATE deployments as d
7+ SET app_overrides = d.app_overrides ||
8+ jsonb_build_array(jsonb_build_array('image.tag', jsonb_build_object('tag', 'ValueAdded', 'contents', d.tag)));
9+
10+ALTER TABLE "deployments" DROP COLUMN "tag";
11+
12+UPDATE deployment_logs as d
13+ SET app_overrides = d.app_overrides ||
14+ jsonb_build_array(jsonb_build_array('image.tag', jsonb_build_object('tag', 'ValueAdded', 'contents', d.tag)));
15+
16+ALTER TABLE "deployment_logs" DROP COLUMN "tag";
17+
18+COMMIT;
migrations/deploy/remove_archived_column.sqlnew file+9
@@ -0,0 +1,9 @@
1+-- Deploy octopod:remove_archived_column to pg
2+ BEGIN;
3+
4+
5+ALTER TABLE "public"."deployments"
6+DROP COLUMN "archived";
7+
8+
9+COMMIT;
migrations/revert/add_detailed_failures.sqlnew file+9
@@ -0,0 +1,9 @@
1+-- Revert octopod:add_detailed_failures from pg
2+ BEGIN;
3+
4+
5+ALTER TYPE statuses RENAME VALUE 'GenericFailure' TO 'Failure';
6+
7+-- NOTE: not a full revert. Removing enum values is a pain.
8+
9+COMMIT;
migrations/revert/migrate_2.0.sqlnew file+12
@@ -0,0 +1,12 @@
1+-- Revert octopod:migrate_2.0 from pg
2+
3+BEGIN;
4+
5+DO LANGUAGE 'plpgsql'
6+$$
7+BEGIN
8+RAISE EXCEPTION 'Revert not supported for this migration';
9+END
10+$$;
11+
12+COMMIT;
migrations/revert/move_tag_to_overrides.sqlnew file+62
@@ -0,0 +1,62 @@
1+-- Revert octopod:move_tag_to_overrides from pg
2+BEGIN;
3+ALTER TABLE deployments
4+ADD COLUMN tag text;
5+UPDATE deployments AS d
6+SET tag = COALESCE(
7+ (
8+ WITH appOvs AS (
9+ SELECT jsonb_array_elements(d."app_overrides") AS res
10+ )
11+ SELECT a.res->1->>'contents'
12+ FROM appOvs AS a
13+ WHERE (a.res->>0) = 'image.tag'
14+ ),
15+ ''
16+ );
17+UPDATE deployments AS d
18+SET app_overrides = COALESCE(
19+ (
20+ WITH appOvs AS (
21+ SELECT jsonb_array_elements(d."app_overrides") AS res
22+ )
23+ SELECT jsonb_agg(a.res)
24+ FROM appOvs AS a
25+ WHERE (a.res->>0) != 'image.tag'
26+ ),
27+ '[]'
28+ );
29+ALTER TABLE deployments
30+ALTER COLUMN tag
31+SET NOT NULL;
32+--
33+ALTER TABLE deployment_logs
34+ADD COLUMN tag text;
35+UPDATE deployment_logs AS d
36+SET tag = COALESCE(
37+ (
38+ WITH appOvs AS (
39+ SELECT jsonb_array_elements(d."app_overrides") AS res
40+ )
41+ SELECT a.res->1->>'contents'
42+ FROM appOvs AS a
43+ WHERE (a.res->>0) = 'image.tag'
44+ ),
45+ ''
46+ );
47+UPDATE deployment_logs AS d
48+SET app_overrides = COALESCE(
49+ (
50+ WITH appOvs AS (
51+ SELECT jsonb_array_elements(d."app_overrides") AS res
52+ )
53+ SELECT jsonb_agg(a.res)
54+ FROM appOvs AS a
55+ WHERE (a.res->>0) != 'image.tag'
56+ ),
57+ '[]'
58+ );
59+ALTER TABLE deployment_logs
60+ALTER COLUMN tag
61+SET NOT NULL;
62+COMMIT;
migrations/revert/remove_archived_column.sqlnew file+8
@@ -0,0 +1,8 @@
1+-- Revert octopod:remove_archived_column from pg
2+ BEGIN;
3+
4+
5+ALTER TABLE "public"."deployments" ADD COLUMN "archived" bool NOT NULL DEFAULT 'false';
6+
7+
8+COMMIT;
migrations/sqitch.plan+4
@@ -13,3 +13,7 @@ create_deployment_metadata 2020-08-14T12:11:42Z Typeable LLC <octopod@typeable.i
1313rename_elements_of_scope_enum 2020-08-19T09:38:40Z Typeable LLC <octopod@typeable.io> # Rename elements of 'scope' enum
1414rename-delete-to-archive 2020-11-23T10:53:10Z Ilya <octopod@typeable.io> # Renamed delete to archive
1515rename_delete_to_archive_2 2020-11-26T08:28:58Z Typeable LLC <octopod@typeable.io> # Renamed delete to archive
16+add_detailed_failures 2021-02-04T11:01:15Z Typeable LLC <octopod@typeable.io> # Added more failure states
17+remove_archived_column 2021-01-28T18:44:54Z Typeable LLC <octopod@typeable.io> # Removed 'archived' column
18+migrate_2.0 2021-08-11T17:09:37Z Typeable LLC <octopod@typeable.io> # Migrate to 2.0-style tables. (Less tables)
19+move_tag_to_overrides 2021-09-25T14:29:43Z Typeable LLC <octopod@typeable.io> # Remove tag as a special field, making it an override field.
migrations/verify/add_detailed_failures.sqlnew file+10
@@ -0,0 +1,10 @@
1+-- Verify octopod:add_detailed_failures on pg
2+ BEGIN;
3+
4+
5+SELECT ('GenericFailure'::statuses,
6+ 'TagMismatch'::statuses,
7+ 'PartialAvailability'::statuses);
8+
9+
10+ROLLBACK;
migrations/verify/migrate_2.0.sqlnew file+37
@@ -0,0 +1,37 @@
1+-- Verify octopod:migrate_2.0 on pg
2+
3+BEGIN;
4+
5+SELECT
6+ id,
7+ name,
8+ tag,
9+ app_overrides,
10+ deployment_overrides,
11+ created_at,
12+ updated_at,
13+ archived_at,
14+ status,
15+ status_updated_at,
16+ checked_at,
17+ links
18+FROM deployments
19+WHERE false;
20+
21+SELECT
22+ id,
23+ deployment_id,
24+ action,
25+ tag,
26+ exit_code,
27+ created_at,
28+ archived,
29+ duration,
30+ stdout,
31+ stderr,
32+ app_overrides,
33+ deployment_overrides
34+FROM deployment_logs
35+WHERE false;
36+
37+ROLLBACK;
migrations/verify/move_tag_to_overrides.sqlnew file+7
@@ -0,0 +1,7 @@
1+-- Verify octopod:move_tag_to_overrides on pg
2+
3+BEGIN;
4+
5+-- XXX Add verifications here.
6+
7+ROLLBACK;
migrations/verify/remove_archived_column.sqlnew file+7
@@ -0,0 +1,7 @@
1+-- Verify octopod:remove_archived_column on pg
2+
3+BEGIN;
4+
5+-- XXX Add verifications here.
6+
7+ROLLBACK;
nix/ci.nixnew file+6
@@ -0,0 +1,6 @@
1+{ sources ? import ./sources.nix
2+, pkgs ? import sources.nixpkgs { }
3+}:
4+pkgs.mkShell {
5+ packages = [ pkgs.haskellPackages.fourmolu ];
6+}
nix/default.nix+90−113
@@ -1,122 +1,99 @@
11{ sources ? import ./sources.nix
2−
3−, octopod-css ? ../octopod-css
4−
5−, migrations ? "please use '--arg migration <value>'"
2+, octopod-css ? import ../octopod-css { inherit pkgsSrc system; }
3+, migrations ? ../migrations
4+, system ? builtins.currentSystem
5+, hsPkgs ? import ./.. { inherit system prod; }
6+, pkgs ? hsPkgs.pkgs
7+, pkgsSrc ? hsPkgs.pkgsSrc
8+, prod ? true
69}:
7−with {
8− overlay = _: pkgs:
9− with pkgs; rec {
10− octo-cli = haskellPackages.octo-cli-static;
11− octopod-backend = haskellPackages.octopod-server-static;
12− octopod-frontend = haskellPackages.octopod-frontend-static;
13−
14− cacert' = cacert.overrideAttrs (o: {
15− fixupPhase = ''
16− cat $out/etc/ssl/certs/* > $out/etc/ssl/certs/ca-certificates.crt
17− '';
18− });
19−
20− octopod-server-container = dockerTools.buildImage {
21− name = "octopod-server-container-slim";
22− contents = [
23− octopod-backend
24− octopod-frontend
25− git
26− coreutils
27− bash
28− openssh
29− gnugrep
30− cacert'
31− shadow
32− findutils
10+let
11+ octo-cli = hsPkgs.octo-cli.components.exes.octo;
12+ octopod-backend = hsPkgs.octopod-backend.components.exes.octopod-exe;
13+
14+ closurecompiler = (import sources.nixpkgs { inherit system; }).closurecompiler;
15+
16+ octopod-frontend-ugly =
17+ let frontend = hsPkgs.octopod-frontend-pretty;
18+ in
19+ pkgs.runCommand "octopod-frontend-ugly"
20+ { } ''
21+ shopt -s globstar
22+ mkdir $out
23+ cp -av ${frontend}/* $out
24+ rm $out/all.js
25+
26+ chmod +w -R $out
27+
28+ ${closurecompiler}/bin/closure-compiler --compilation_level ADVANCED --jscomp_off=checkVars --warning_level QUIET --js ${frontend}/all.js --externs ${frontend}/all.js.externs --js_output_file $out/all.js
29+ ${pkgs.zopfli}/bin/zopfli $out/**/*.{js,css,json,html}
30+ '';
31+
32+ octopod-server-container = pkgs.dockerTools.buildImage {
33+ name = "octopod-server-container-slim";
34+ contents = with pkgs; [
35+ git
36+ coreutils
37+ bash
38+ openssh
39+ gnugrep
40+ cacert
41+ shadow
42+ findutils
43+ ];
44+
45+ runAsRoot = ''
46+ mkdir /tmp
47+ chmod 777 /tmp
48+
49+ mkdir -p /home/octopod
50+ useradd octopod -d /home/octopod
51+ chown octopod.octopod /home/octopod
52+
53+ mkdir -p /migrations/{deploy,revert,verify}
54+ cp -av ${migrations}/* /migrations/
55+
56+ mkdir /www
57+ cp -av ${octopod-frontend-ugly}/* /www
58+ '';
59+
60+ config =
61+ let entrypoint = "${octopod-backend}/bin/octopod-exe"; in
62+ {
63+ Entrypoint = [ entrypoint ];
64+ Cmd = [
65+ "--port"
66+ "4443"
67+ "--ui-port"
68+ "4000"
69+ "--ws-port"
70+ "4020"
71+ "--db"
72+ "host='127.0.0.1' port=5432 user='octopod' password='octopod'"
73+ "--db-pool-size"
74+ "10"
75+ ];
76+ Env = [
77+ "PATH=/utils:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
78+ "USER=octopod"
79+ "ENTRYPOINT=${entrypoint}"
3380 ];
34−
35− runAsRoot = ''
36− mkdir /tmp
37− chmod 777 /tmp
38−
39− mkdir -p /home/octopod
40− useradd octopod -d /home/octopod
41− chown octopod.octopod /home/octopod
42−
43− mkdir /app
44− cp -av ${octopod-backend}/bin/octopod-exe /app/octopod-exe
45−
46− mkdir -p /migrations/{deploy,revert,verify}
47− cp -av ${migrations}/* /migrations/
48−
49− mkdir /tls /tls_store
50−
51− mkdir -p /www/static/{images,styles,vendors/outline}
52− cp -av ${octopod-frontend}/bin/frontend.jsexe/* /www/
53− cp -av ${octopod-css}/production/images/* /www/static/images/
54− cp -av ${octopod-css}/production/styles/* /www/static/styles/
55− cp -av ${octopod-css}/production/vendors/outline/* /www/static/vendors/outline/
56− cp -av ${octopod-css}/favicons/* /www/
57− '';
58−
59− config = {
60− Entrypoint = [ "/app/octopod-exe" ];
61− Cmd = [
62− "--port"
63− "4443"
64− "--ui-port"
65− "4000"
66− "--ws-port"
67− "4020"
68− "--db"
69− "host='127.0.0.1' port=5432 user='octopod' password='octopod'"
70− "--db-pool-size"
71− "10"
72− "--tls-cert-path"
73− "/tls/server_cert.pem"
74− "--tls-key-path"
75− "/tls/server_key.pem"
76− "--tls-store-path"
77− "/tls_store"
78− ];
79− Env = [
80− "PATH=/utils:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
81− "USER=octopod"
82− ];
83− };
84− };
85−
86− octo-cli-container = dockerTools.buildImage {
87− name = "octo-cli-container-slim";
88− contents = [ octo-cli coreutils bash ];
89−
90− runAsRoot = ''
91− mkdir /app
92− cp -av ${octo-cli}/bin/octo /app/octo
93− '';
94−
95− config = {
96− Entrypoint = [ "/app/octo" ];
97− Env = [ "EDITOR=${vim}/bin/vim" ];
98− };
9981 };
82+ };
10083
101− niv = import sources.niv { };
102−
103− haskellPackages = pkgs.haskellPackages.override {
104− overrides = hself: hsuper: {
105− octo-cli-static = haskell.lib.justStaticExecutables
106− (hsuper.callPackage ../default.nix { }).ghc.octo-cli;
84+ octo-cli-container = pkgs.dockerTools.buildImage {
85+ name = "octo-cli-container-slim";
86+ contents = with pkgs; [ cacert ];
10787
108− octopod-server-static = haskell.lib.justStaticExecutables
109− (hsuper.callPackage ../default.nix { }).ghc.octopod-backend;
110−
111− octopod-frontend-static = haskell.lib.justStaticExecutables
112− (hsuper.callPackage ../default.nix { }).ghcjs.octopod-frontend;
113− };
88+ config = let entrypoint = "${octo-cli}/bin/octo"; in
89+ {
90+ Entrypoint = [ entrypoint ];
91+ Env = [
92+ "ENTRYPOINT=${entrypoint}"
93+ ];
11494 };
115− };
116−};
117−import
118− sources.nixpkgs # and use them again!
95+ };
96+in
11997{
120− overlays = [ overlay ];
121− config = { };
98+ inherit octo-cli-container octopod-server-container octopod-frontend-ugly;
12299}
nix/haskell-language-server-overrides.nixdeleted−267
@@ -1,267 +0,0 @@
1−{ lib, sources ? import ./sources.nix }: hself: hsuper:
2−{
3− haskell-language-server = lib.dontCheck (hsuper.callCabal2nix "haskell-language-server" (sources.haskell-language-server) { });
4− hls-hlint-plugin = hsuper.callCabal2nix "hls-hlint-plugin" (sources.haskell-language-server + "/plugins/hls-hlint-plugin") { };
5− hls-explicit-imports-plugin = hsuper.callCabal2nix "hls-explicit-imports-plugin" (sources.haskell-language-server + "/plugins/hls-explicit-imports-plugin") { };
6− hls-retrie-plugin = hsuper.callCabal2nix "hls-retrie-plugin" (sources.haskell-language-server + "/plugins/hls-retrie-plugin") { };
7− hls-plugin-api = hsuper.callCabal2nix "hls-plugin-api" (sources.haskell-language-server + "/hls-plugin-api") { };
8− hls-tactics-plugin = hsuper.callCabal2nix "hls-tactics-plugin" (sources.haskell-language-server + "/plugins/tactics") { };
9− hls-class-plugin = hsuper.callCabal2nix "hls-class-plugin" (sources.haskell-language-server + "/plugins/hls-class-plugin") { };
10− hls-eval-plugin = hsuper.callCabal2nix "hls-eval-plugin" (sources.haskell-language-server + "/plugins/hls-eval-plugin") { };
11− hls-haddock-comments-plugin = hsuper.callCabal2nix "hls-haddock-comments-plugin" (sources.haskell-language-server + "/plugins/hls-haddock-comments-plugin") { };
12− hls-splice-plugin = hsuper.callCabal2nix "hls-splice-plugin" (sources.haskell-language-server + "/plugins/hls-splice-plugin") { };
13− shake-bench = hsuper.callCabal2nix "shake-bench" (sources.haskell-language-server + "/shake-bench") { };
14− ghcide = lib.dontCheck (hsuper.callCabal2nix "ghcide" (sources.haskell-language-server + "/ghcide") { });
15− hie-compat = hsuper.callCabal2nix "hie-compat" (sources.haskell-language-server + "/hie-compat") { };
16− hls-exactprint-utils = hsuper.callCabal2nix "hls-exactprint-utils" (sources.haskell-language-server + "/hls-exactprint-utils") { };
17− with-utf8 = (hsuper.callHackageDirect
18− {
19− pkg = "with-utf8";
20− ver = "1.0.2.1";
21− sha256 = "1hpqc0ljk1c1vl4671zb290hbvdcjpg66bcxmf1cz8h0vb382xp7";
22− } { }
23− );
24− fourmolu = lib.doJailbreak (hsuper.callHackageDirect
25− {
26− pkg = "fourmolu";
27− ver = "0.3.0.0";
28− sha256 = "sha256-SFBwhkXfDArITiBSxGSp2qf8gl+yBpWHglBB5aKeaBU=";
29− } { }
30− );
31− heapsize = lib.doJailbreak (hsuper.callHackageDirect
32− {
33− pkg = "heapsize";
34− ver = "0.3.0.1";
35− sha256 = "0c8lqndpbx9ahjrqyfxjkj0z4yhm1zlcn8al0ir4ldlahql2xv3r";
36− } { }
37− );
38− opentelemetry = hsuper.callHackageDirect
39− {
40− pkg = "opentelemetry";
41− ver = "0.6.1";
42− sha256 = "08k71z7bns0i6r89nmxqsl00kyksicq619rqy6pf5m7hq1r4zs9m";
43− } { };
44− ghc-trace-events = hsuper.callHackageDirect
45− {
46− pkg = "ghc-trace-events";
47− ver = "0.1.2.1";
48− sha256 = "10vrm7hmg97fn8xf0r79d9vfph0j2s105lsgm0hgqay1qz1x7sp7";
49− } { };
50− haskell-lsp = hsuper.callHackageDirect
51− {
52− pkg = "haskell-lsp";
53− ver = "0.23.0.0";
54− sha256 = "0d9bk1cqkk41frm81j683h2vd1hghl4hlvj8g17690d2qk5pq3c0";
55− } { };
56− haskell-lsp-types = hsuper.callHackageDirect
57− {
58− pkg = "haskell-lsp-types";
59− ver = "0.23.0.0";
60− sha256 = "17mfc2zxkbwipxiy0g3qwqnyp8ds4mrg0z1v7jchcm89hnf8mmmq";
61− } { };
62− ormolu =
63− hsuper.callHackageDirect
64− {
65− pkg = "ormolu";
66− ver = "0.1.4.1";
67− sha256 = "07gfag591dsys33q2i80f3afxjqny2zpiq4z35d1ajyp7di73m7z";
68− } { };
69− ghc-check =
70− hsuper.callHackageDirect
71− {
72− pkg = "ghc-check";
73− ver = "0.5.0.1";
74− sha256 = "1zlbss7h6infzhhpilvkpk50gxypkb2li8fspi69jlll5l7wqi3d";
75− } { };
76− implicit-hie-cradle =
77− hsuper.callHackageDirect
78− {
79− pkg = "implicit-hie-cradle";
80− ver = "0.3.0.2";
81− sha256 = "1fhc8zccd7g7ixka05cba3cd4qf5jvq1zif29bhn593dfkzy89lz";
82− } { };
83− implicit-hie =
84− hsuper.callHackageDirect
85− {
86− pkg = "implicit-hie";
87− ver = "0.1.2.5";
88− sha256 = "1l0rz4r4hamvmqlb68a7y4s3n73y6xx76zyprksd0pscd9axznnv";
89− } { };
90− lsp-test = lib.dontCheck (hsuper.callHackageDirect
91− {
92− pkg = "lsp-test";
93− ver = "0.11.0.7";
94− sha256 = "sha256-buHcgRbLIn2zr5GK4gHrKuUiyYJK7Nzqc1y+WosaHJg=";
95− } { }
96− );
97− floskell = lib.dontCheck (
98− hsuper.callHackageDirect
99− {
100− pkg = "floskell";
101− ver = "0.10.4";
102− sha256 = "0n1gy6yf7lzzh9l67712rr7bjliyifi9xjnc6i9rppiv5adj2xyf";
103− } { }
104− );
105− monad-dijkstra = lib.dontCheck (lib.doJailbreak (
106− hsuper.callHackageDirect
107− {
108− pkg = "monad-dijkstra";
109− ver = "0.1.1.2";
110− sha256 = "1vyw7az18yy5s9jwi3icq76zvi9myr0y9gja3jaywlykcdn6frsz";
111− } { }
112− ));
113− HsYAML-aeson = lib.doJailbreak (
114− hsuper.callHackageDirect
115− {
116− pkg = "HsYAML-aeson";
117− ver = "0.2.0.0";
118− sha256 = "0zgcp93y93h7rsg9dv202hf3l6sqr95iadd67lmfclb0npfs640m";
119− } { }
120− );
121− ghc-lib-parser-ex =
122− hsuper.callHackageDirect
123− {
124− pkg = "ghc-lib-parser-ex";
125− ver = "8.10.0.16";
126− sha256 = "0dp8plj708ss3im6rmp41kpj0df71kjzpw1kqkpn0dhms9yr1g0x";
127− } { };
128− retrie = lib.doJailbreak (lib.dontCheck (
129− hsuper.callHackageDirect
130− {
131− pkg = "retrie";
132− ver = "0.1.1.1";
133− sha256 = "0gnp6j35jnk1gcglrymvvn13sawir0610vh0z8ya6599kyddmw7l";
134− } { }
135− ));
136− ghc-lib =
137− hsuper.callHackageDirect
138− {
139− pkg = "ghc-lib";
140− ver = "8.10.2.20200916";
141− sha256 = "1gx0ijay9chachmd1fbb61md3zlvj24kk63fk3dssx8r9c2yp493";
142− } { };
143− ghc-lib-parser =
144− hsuper.callHackageDirect
145− {
146− pkg = "ghc-lib-parser";
147− ver = "8.10.2.20200916";
148− sha256 = "1apm9zn484sm6b8flbh6a2kqnv1wjan4l58b81cic5fc1jsqnyjk";
149− } { };
150− parser-combinators =
151− hsuper.callHackageDirect
152− {
153− pkg = "parser-combinators";
154− ver = "1.2.1";
155− sha256 = "1990d6c1zm2wq4w9521bx7l3arg4ly02hq1ass9n19gs273bxx5h";
156− } { };
157− regex-tdfa =
158− hsuper.callHackageDirect
159− {
160− pkg = "regex-tdfa";
161− ver = "1.3.1.0";
162− sha256 = "1a0l7kdjzp98smfp969mgkwrz60ph24xy0kh2dajnymnr8vd7b8g";
163− } { };
164− regex-posix =
165− hsuper.callHackageDirect
166− {
167− pkg = "regex-posix";
168− ver = "0.96.0.0";
169− sha256 = "0js977ahpz10642sbpb55mw9h01pilai6z201wgkncgkg2d69hl3";
170− } { };
171− ansi-terminal =
172− hsuper.callHackageDirect
173− {
174− pkg = "ansi-terminal";
175− ver = "0.10.3";
176− sha256 = "1aa8lh7pl054kz7i59iym49s8w473nhdqgc3pq16cp5v4358hw5k";
177− } { };
178− ghc-exactprint =
179− hsuper.callHackageDirect
180− {
181− pkg = "ghc-exactprint";
182− ver = "0.6.3.2";
183− sha256 = "0l9piqqgdi8xd46nj1jizp0r0v526d7f61y05xm8k4aamjaj59d0";
184− } { };
185− stylish-haskell =
186− hsuper.callHackageDirect
187− {
188− pkg = "stylish-haskell";
189− ver = "0.12.2.0";
190− sha256 = "1ck8i550rvzbvzrm7dvgir73slai8zmvfppg3n5v4igi7y3jy0mr";
191− } { };
192− shake = lib.dontCheck (
193− hsuper.callHackageDirect
194− {
195− pkg = "shake";
196− ver = "0.19.2";
197− sha256 = "03p5hq0sg13ii39j9hf3nvy8v20mkh8czb59djn6zrg7fypy9ivv";
198− } { }
199− );
200− regex-base =
201− hsuper.callHackageDirect
202− {
203− pkg = "regex-base";
204− ver = "0.94.0.0";
205− sha256 = "0x2ip8kn3sv599r7yc9dmdx7hgh5x632m45ga99ib5rnbn6kvn8x";
206− } { };
207− extra =
208− hsuper.callHackageDirect
209− {
210− pkg = "extra";
211− ver = "1.7.3";
212− sha256 = "08j4gg2n5cl7ycr943hmyfimgby0xhf5vp8nwrwflg6lrn1s388c";
213− } { };
214− quickcheck-instances =
215− hsuper.callHackageDirect
216− {
217− pkg = "quickcheck-instances";
218− ver = "0.3.22";
219− sha256 = "05mam3x4x7c881bqbq8lcbclmz914yziqh6s04icxzp12zq7c7ks";
220− } { };
221− apply-refact = lib.doJailbreak (hsuper.callHackageDirect
222− {
223− pkg = "apply-refact";
224− ver = "0.8.2.1";
225− sha256 = "0nnprv5lbk7c8w1pa4kywk0cny6prjaml4vnw70s8v6c1r1dx2rx";
226− } { }
227− );
228− hlint =
229− hsuper.callHackageDirect
230− {
231− pkg = "hlint";
232− ver = "3.2";
233− sha256 = "0y2agj9y4nwhypv9ss97n26mc28pcynfynwilcyj2lwfabhr9pzc";
234− } { };
235− Diff =
236− hsuper.callHackageDirect
237− {
238− pkg = "Diff";
239− ver = "0.4.0";
240− sha256 = "1phz4cz7i53jx3d1bj0xnx8vpkk482g4ph044zv5c6ssirnzq3ng";
241− } { };
242− refinery = lib.dontCheck (
243− hsuper.callHackageDirect
244− {
245− pkg = "refinery";
246− ver = "0.3.0.0";
247− sha256 = "08s5pw6j3ncz96zfc2j0cna2zbf4vy7045d6jpzmq2sa161qnpgi";
248− } { }
249− );
250− hie-bios = lib.dontCheck (
251− hsuper.callHackageDirect
252− {
253− pkg = "hie-bios";
254− ver = "0.7.1";
255− sha256 = "137f1dy0fmlrzngwcmgnxghcih7f2rfq5bdnizbwy9534dn4dr42";
256− } { }
257− );
258− test-framework = lib.doJailbreak hsuper.test-framework;
259− aeson = lib.dontCheck hsuper.aeson;
260− tree-diff = lib.doJailbreak hsuper.tree-diff;
261− brittany = hsuper.callHackageDirect
262− {
263− pkg = "brittany";
264− ver = "0.13.1.0";
265− sha256 = "172mg0ch2awfzhz8vzvjrfdjylfzawrbgfr5z82l1qzjh6g9z295";
266− } { };
267−}
nix/octo.nixdeleted−35
@@ -1,35 +0,0 @@
1−{ sources ? import ./sources.nix
2−, compiler ? "ghc865"
3−, pkgs-expr ? sources.nixpkgs
4−, static-haskell-nix ? sources.static-haskell-nix
5−}:
6−let
7− foldOs = normalPkgs.lib.foldl' normalPkgs.lib.composeExtensions (self: super: { });
8− normalPkgs = import pkgs-expr {
9− overlays = [
10− (self: super: {
11− haskell = super.haskell // {
12− packages = super.haskell.packages // {
13− "${compiler}" = super.haskell.packages."${compiler}".override {
14− overrides =
15− foldOs [
16− (import ./octopod-overrides.nix {
17− inherit (normalPkgs.haskell) lib;
18− inherit sources;
19− }
20− )
21− (hself: hsuper: {
22− octo-cli = hsuper.callCabal2nix "octo-cli" ../octo-cli { };
23− octopod-api = hsuper.callCabal2nix "octopod-api" ../octopod-api { };
24− octopod-common = hsuper.callCabal2nix "octopod-common" ../octopod-common { };
25− })
26− ];
27− };
28− };
29− };
30− })
31− ];
32− };
33− static-haskell = import "${static-haskell-nix}/survey" { inherit normalPkgs compiler; };
34−in
35−static-haskell.haskellPackages.octo-cli
nix/octopod-overrides.nixdeleted−103
@@ -1,103 +0,0 @@
1−{ lib, sources ? import ./sources.nix }: hself: hsuper:
2−{
3− tabulation = hsuper.callCabal2nix "tabulation" "${sources.obelisk}/lib/tabulation" { };
4− obelisk-executable-config-lookup = hsuper.callCabal2nix "obelisk-executable-config-lookup" "${sources.obelisk}/lib/executable-config/lookup" { };
5− obelisk-route = hsuper.callCabal2nix "obelisk-route" "${sources.obelisk}/lib/route" { };
6− hspec-webdriver = hsuper.callCabal2nix "hspec-webdriver" sources.hspec-webdriver-clone { };
7− servant-reflex = lib.doJailbreak (hsuper.callHackageDirect
8− {
9− pkg = "servant-reflex";
10− ver = "0.3.5";
11− sha256 = "1cj5b7hl4jhsqxfg8vdw50z8zvfxkj42f41hmyx217w6bv3s3fdb";
12− } { }
13− );
14− servant = hsuper.callHackageDirect
15− {
16− pkg = "servant";
17− ver = "0.18.2";
18− sha256 = "0l2k895nxvw2ngr9201g3br6s9zab7mk5mhpjibyg8mxfbv75a8y";
19− } { };
20− servant-client-core = hsuper.callHackageDirect
21− {
22− pkg = "servant-client-core";
23− ver = "0.18.2";
24− sha256 = "1hazxk1laklpm2c65zgkk2gn8mvlp682437071s04bqggk9b59sx";
25− } { };
26− servant-server = hsuper.callHackageDirect
27− {
28− pkg = "servant-server";
29− ver = "0.18.2";
30− sha256 = "1kynxl7qg5z45bhi0k61sxn79xkgnq1z97ccqqs39wjyf45fj5yy";
31− } { };
32− servant-client = hsuper.callHackageDirect
33− {
34− pkg = "servant-client";
35− ver = "0.18.2";
36− sha256 = "0yip2s63ivrlrpficdipq60j2a6czg8agn18lpkkaxf3n55j4jr3";
37− } { };
38− servant-websockets = hsuper.callHackageDirect
39− {
40− pkg = "servant-websockets";
41− ver = "2.0.0";
42− sha256 = "01bmwg3ysj8gijcqghykxfsd62sqz1pfby2irpzh5ybwyh285pvg";
43− } { };
44− deriving-aeson = hsuper.callHackageDirect
45− {
46− pkg = "deriving-aeson";
47− ver = "0.2.3";
48− sha256 = "0ckwdi9pr4aqp9psag4mdbx30nygxkkpdf21rg9rfz16cz8079j7";
49− } { };
50− table-layout = hsuper.callHackageDirect
51− {
52− pkg = "table-layout";
53− ver = "0.9.0.1";
54− sha256 = "12nllfnh6b5mjda9qxfy192v0r0sx181w9zc9j70kvjdn7hgrb0y";
55− } { };
56− data-default-instances-base = hsuper.callHackageDirect
57− {
58− pkg = "data-default-instances-base";
59− ver = "0.1.0.1";
60− sha256 = "18basdy4qjn246phw008ll9zbi3rpdn6bh2dk0i81a60gsmyn58q";
61− } { };
62− postgresql-simple = hsuper.callHackageDirect
63− {
64− pkg = "postgresql-simple";
65− ver = "0.6.3";
66− sha256 = "16kk1bc23gc23cd79c2iy90zh03x5n6b9r2kinjspy7hl9jlzs2a";
67− } { };
68− concurrent-output = hsuper.callHackageDirect
69− {
70− pkg = "concurrent-output";
71− ver = "1.10.12";
72− sha256 = "1ysvahlf6frjfxpv6lwzxn05ps6b4zy1f5xb0yg6z688wbw1f6a7";
73− } { };
74− hspec-wai = hsuper.callHackageDirect
75− {
76− pkg = "hspec-wai";
77− ver = "0.11.0";
78− sha256 = "1kqbk2by70smhd9p1zff6ilimvvxc54dkh2l0wpn03zqvydjnwl2";
79− } { };
80− patch = lib.doJailbreak (hsuper.callHackageDirect
81− {
82− pkg = "patch";
83− ver = "0.0.3.2";
84− sha256 = "10alg64zwx72lz42z9i5hfwdpk0r79zfli57l41akyznj4pwrvgh";
85− } { }
86− );
87− path = hsuper.callHackageDirect
88− {
89− pkg = "path";
90− ver = "0.8.0";
91− sha256 = "0isldidz2gypw2pz399g6rn77x9mppd1mvj5h6ify4pj4mpla0pb";
92− } { };
93− path-io = hsuper.callHackageDirect
94− {
95− pkg = "path-io";
96− ver = "1.6.2";
97− sha256 = "1s7cahx8cf85kwz9l8cm6x6kvjwsv0spwv78pybsspb1ap5q287p";
98− } { };
99− reflex = lib.dontCheck (lib.doJailbreak hsuper.reflex);
100− reflex-dom-core = lib.dontCheck hsuper.reflex-dom-core;
101− chronos = lib.doJailbreak hsuper.chronos;
102− hedgehog = lib.doJailbreak hsuper.hedgehog;
103−}
nix/sources.json+27−63
@@ -1,26 +1,14 @@
11{
2− "haskell-language-server": {
3− "branch": "master",
4− "description": "Integration point for ghcide and haskell-ide-engine. One IDE to rule them all.",
5− "homepage": "",
6− "owner": "haskell",
7− "repo": "haskell-language-server",
8− "rev": "fde10fa5e4cb74ca4b64c43250297b36a9bbbd7e",
9− "sha256": "03frszid12dcmqg0m6wkc1nf561kdap3y3yqrp1x13gvbkvb9xwn",
10− "type": "tarball",
11− "url": "https://github.com/haskell/haskell-language-server/archive/fde10fa5e4cb74ca4b64c43250297b36a9bbbd7e.tar.gz",
12− "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
13− },
14− "hspec-webdriver-clone": {
15− "branch": "master",
16− "description": "Clone of hspec-webdriver, as the original source is inaccesible",
17− "homepage": null,
18− "owner": "dfordivam",
19− "repo": "hspec-webdriver-clone",
20− "rev": "0d748b7bb7cd74dce0a55a1ec86b01dbb8a71cd8",
21− "sha256": "1criynifhvmnqwhrshmzylikqkvlgq98xf72w9cdd2zpjw539qf0",
2+ "haskellNix": {
3+ "branch": "iko/ghcjs-patch",
4+ "description": "Alternative Haskell Infrastructure for Nixpkgs",
5+ "homepage": "https://input-output-hk.github.io/haskell.nix",
6+ "owner": "ilyakooo0",
7+ "repo": "haskell.nix",
8+ "rev": "8cdc0f62f31be4f55bc7db88bdc0cec44bfd8ab9",
9+ "sha256": "0l0xg0s2vn0lpc2m1gavrlzk691sgifjf6l6k5sfsnhw2xq77g48",
2210 "type": "tarball",
23− "url": "https://github.com/dfordivam/hspec-webdriver-clone/archive/0d748b7bb7cd74dce0a55a1ec86b01dbb8a71cd8.tar.gz",
11+ "url": "https://github.com/ilyakooo0/haskell.nix/archive/8cdc0f62f31be4f55bc7db88bdc0cec44bfd8ab9.tar.gz",
2412 "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
2513 },
2614 "niv": {
@@ -29,58 +17,34 @@
2917 "homepage": "https://github.com/nmattia/niv",
3018 "owner": "nmattia",
3119 "repo": "niv",
32− "rev": "ba57d5a29b4e0f2085917010380ef3ddc3cf380f",
33− "sha256": "1kpsvc53x821cmjg1khvp1nz7906gczq8mp83664cr15h94sh8i4",
20+ "rev": "5830a4dd348d77e39a0f3c4c762ff2663b602d4c",
21+ "sha256": "1d3lsrqvci4qz2hwjrcnd8h5vfkg8aypq3sjd4g3izbc8frwz5sm",
3422 "type": "tarball",
35− "url": "https://github.com/nmattia/niv/archive/ba57d5a29b4e0f2085917010380ef3ddc3cf380f.tar.gz",
23+ "url": "https://github.com/nmattia/niv/archive/5830a4dd348d77e39a0f3c4c762ff2663b602d4c.tar.gz",
3624 "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
3725 },
38− "nixpkgs": {
39− "branch": "63ad5ab28ee380a4c6a974c9f70639f81a15f6ad",
40− "description": "A read-only mirror of NixOS/nixpkgs tracking the released channels. Send issues and PRs to",
41− "homepage": "https://github.com/NixOS/nixpkgs",
42− "owner": "NixOS",
43− "repo": "nixpkgs",
44− "rev": "63ad5ab28ee380a4c6a974c9f70639f81a15f6ad",
45− "sha256": "1lppx6rsr52hdd1bp25ni4d6c8b76ip6lvr0iphfv0d1jjdf9r4h",
46− "type": "tarball",
47− "url": "https://github.com/NixOS/nixpkgs/archive/63ad5ab28ee380a4c6a974c9f70639f81a15f6ad.tar.gz",
48− "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
49− },
50− "obelisk": {
26+ "nix-filter": {
5127 "branch": "master",
52− "description": "Functional reactive web and mobile applications, with batteries included.",
53− "homepage": "https://reflex-frp.org",
54− "owner": "obsidiansystems",
55− "repo": "obelisk",
56− "rev": "11beb6e8cd2419b2429925b76a98f24035e40985",
57− "sha256": "0b4m33b7yyzsbkvfz2kwg4v9hlnvbjlmjikbvwd7pg52vy84and0",
58− "type": "tarball",
59− "url": "https://github.com/obsidiansystems/obelisk/archive/11beb6e8cd2419b2429925b76a98f24035e40985.tar.gz",
60− "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
61− },
62− "reflex-platform": {
63− "branch": "rc/0.6.0.0",
64− "description": "A curated package set and set of tools that let you build Haskell packages so they can run on a variety of platforms. reflex-platform is built on top of the nix package manager.",
65− "homepage": "https://reflex-frp.org",
66− "owner": "reflex-frp",
67− "repo": "reflex-platform",
68− "rev": "8d421e9e06b0477cbc065346aaf596c9db6cc387",
69− "sha256": "06fy5b0mk5k2ps1h78yihf4j76cb855r86y9p4jv5d91nfyl2dck",
28+ "description": "a small self-container source filtering lib",
29+ "homepage": "",
30+ "owner": "numtide",
31+ "repo": "nix-filter",
32+ "rev": "3c9e33ed627e009428197b07216613206f06ed80",
33+ "sha256": "19w142crrkywxynmyw4rhz4nglrg64yjawfkw3j91qwkwbfjds84",
7034 "type": "tarball",
71− "url": "https://github.com/reflex-frp/reflex-platform/archive/8d421e9e06b0477cbc065346aaf596c9db6cc387.tar.gz",
35+ "url": "https://github.com/numtide/nix-filter/archive/3c9e33ed627e009428197b07216613206f06ed80.tar.gz",
7236 "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
7337 },
74− "static-haskell-nix": {
38+ "nixpkgs": {
7539 "branch": "master",
76− "description": "easily build most Haskell programs into fully static Linux executables",
40+ "description": "Nix Packages collection",
7741 "homepage": "",
78− "owner": "nh2",
79− "repo": "static-haskell-nix",
80− "rev": "382150290ba43b6eb41981c1ab3b32aa31798140",
81− "sha256": "0zsyplzf1k235rl26irm27y5ljd8ciayw80q575msxa69a9y2nvd",
42+ "owner": "NixOS",
43+ "repo": "nixpkgs",
44+ "rev": "bb9bd465b625bfc971908c5d3d84ce517e1c0691",
45+ "sha256": "1q558hjfxhbcj6n6kbahswvii95kz6gs5bbzh7ky86cmc2b0l38x",
8246 "type": "tarball",
83− "url": "https://github.com/nh2/static-haskell-nix/archive/382150290ba43b6eb41981c1ab3b32aa31798140.tar.gz",
47+ "url": "https://github.com/NixOS/nixpkgs/archive/bb9bd465b625bfc971908c5d3d84ce517e1c0691.tar.gz",
8448 "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
8549 }
8650}
nix/sources.nix+4−1
@@ -98,7 +98,10 @@ let
9898 saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name;
9999 ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}";
100100 in
101− if ersatz == "" then drv else ersatz;
101+ if ersatz == "" then drv else
102+ # this turns the string into an actual Nix path (for both absolute and
103+ # relative paths)
104+ if builtins.substring 0 1 ersatz == "/" then /. + ersatz else /. + builtins.getEnv "PWD" + "/${ersatz}";
102105
103106 # Ports of functions for older nix versions
104107
octo-cli/Setup.hs+1
@@ -1,2 +1,3 @@
11import Distribution.Simple
2+
23main = defaultMain
octo-cli/octo-cli.cabal+23−9
@@ -15,8 +15,8 @@ executable octo
1515 other-modules:
1616 Octopod.CLI
1717 Octopod.CLI.Args
18− Octopod.CLI.TLS
1918 Text.Layout.Table.Extras
19+ Octopod.PowerAPI.Auth.Client
2020 default-extensions:
2121 BlockArguments
2222 ConstraintKinds
@@ -34,17 +34,20 @@ executable octo
3434 TypeApplications
3535 TypeOperators
3636 OverloadedLabels
37+ FlexibleInstances
38+ TypeFamilies
39+ MultiParamTypeClasses
40+ FunctionalDependencies
41+ UndecidableInstances
42+ ViewPatterns
3743 build-depends:
3844 aeson,
39− base ^>=4.12.0.0,
45+ base,
4046 bytestring,
41− chronos,
42− connection,
47+ time,
4348 data-default-class,
4449 generic-lens,
4550 http-client-tls,
46− http-client,
47− http-types,
4851 lens,
4952 octopod-api,
5053 octopod-common,
@@ -53,11 +56,22 @@ executable octo
5356 servant-client,
5457 servant,
5558 text,
56− tls,
5759 transformers,
5860 table-layout ^>= 0.9.0.0,
61+ servant-auth,
62+ http-types,
5963 hs-source-dirs: src
6064 default-language: Haskell2010
6165 ghc-options:
62− -Wall
63− -Werror
66+ -Weverything
67+ -Wno-implicit-prelude
68+ -Wno-missing-safe-haskell-mode
69+ -Wno-safe
70+ -Wno-prepositive-qualified-module
71+ -Wno-missing-import-lists
72+ -Wno-all-missed-specialisations
73+ -Wno-missing-local-signatures
74+ -Wno-partial-fields
75+ -Wno-unsafe
76+ -Wno-monomorphism-restriction
77+ -Wno-missed-specialisations
octo-cli/src/Main.hs+2−2
@@ -1,6 +1,6 @@
1−module Main where
1+module Main (main) where
22
3−import Octopod.CLI
3+import Octopod.CLI
44
55main :: IO ()
66main = runOcto
octo-cli/src/Octopod/CLI.hs+254−218
@@ -1,271 +1,290 @@
1+{-# LANGUAGE PartialTypeSignatures #-}
2+
13module Octopod.CLI (runOcto) where
24
3−import Chronos
4−import Control.Lens hiding (List)
5−import Control.Monad
6−import Control.Monad.IO.Class
7−import Control.Monad.Trans.Reader (ReaderT, ask, runReaderT)
8−import Data.Aeson (decode)
5+import Common.Types hiding (stderr)
6+import Common.Utils (dfiName)
7+import Control.Exception
8+import Control.Lens hiding (List)
9+import Control.Monad
10+import Control.Monad.IO.Class
11+import Control.Monad.Trans.Reader (ReaderT, ask, runReaderT)
12+import Data.Aeson (decode)
913import qualified Data.ByteString.Char8 as BSC
1014import qualified Data.ByteString.Lazy.Char8 as LBSC
11−import Data.Coerce
12−import Data.Generics.Labels ()
13−import Data.Generics.Product
14−import Data.Proxy
15−import Data.Text (Text)
15+import Data.Coerce
16+import qualified Data.ConfigTree as CT
17+import Data.Foldable
18+import Data.Generics.Labels ()
19+import Data.Generics.Product
20+import Data.Maybe
21+import Data.Proxy
22+import Data.Text (Text)
1623import qualified Data.Text as T
1724import qualified Data.Text.IO as T
18−import Data.Text.Lens
19−import GHC.IO.Encoding
20−import Network.HTTP.Client (Manager)
21−import Prelude as P
22−import Servant.API
23−import Servant.Client
24− (BaseUrl(..), ClientEnv, ClientError, ClientM, client, mkClientEnv,
25− runClientM)
26−import Servant.Client.Core
27− (ClientError(FailureResponse), ResponseF(..), parseBaseUrl)
28−import System.Environment (lookupEnv)
29−import System.Exit
30−
31−import Common.Types
32−import Common.Utils (dfiName)
33−import Octopod.CLI.Args
34−import Octopod.CLI.TLS (makeClientManager)
35−import Octopod.PowerAPI
36−import Text.Layout.Table
37−import Text.Layout.Table.Extras ()
25+import Data.Text.Lens
26+import Data.Time
27+import GHC.IO.Encoding
28+import Network.HTTP.Client.TLS
29+import Network.HTTP.Types.Status
30+import Octopod.CLI.Args
31+import Octopod.PowerAPI
32+import Octopod.PowerAPI.Auth.Client
33+import Servant.API
34+import Servant.Client
35+import System.Environment (lookupEnv)
36+import System.Exit
37+import System.IO
38+import Text.Layout.Table
39+import Text.Layout.Table.Extras ()
40+import Prelude as P
41+
42+dieT :: MonadIO m => Text -> m a
43+dieT = liftIO . die . T.unpack
3844
3945-- | Runs the octo CLI.
4046runOcto :: IO ()
4147runOcto = do
4248 setLocaleEncoding utf8
49+ (AuthHeaderAuthCtx -> auth) <-
50+ lookupEnv "OCTO_AUTHORIZATION_HEADER"
51+ >>= maybe (die "OCTO_AUTHORIZATION_HEADER is not set") pure
4352 args <- parseArgs
4453 env <- getBaseUrl
45− manager <- initClientManager env
46− let clientEnv = mkClientEnv manager env
54+ mngr <- newTlsManager
55+ let clientEnv = mkClientEnv mngr env
4756 flip runReaderT clientEnv $
4857 case args of
49− Create tName tTag tSetAp tSetDep tSetPAp tSetPDep -> do
50− setApp <- liftIO $ parseSetApplicationOverrides Public tSetAp
51− setDep <- liftIO $ parseSetDeploymentOverrides Public tSetDep
52− setPApp <- liftIO $ parseSetApplicationOverrides Private tSetPAp
53− setPDep <- liftIO $ parseSetDeploymentOverrides Private tSetPDep
54− let
55− appOvs = setApp ++ setPApp
56− depOvs = setDep ++ setPDep
57− handleCreate $ Deployment (coerce tName) (coerce tTag) appOvs depOvs
58− List ->
59− handleList
60− Archive tName ->
61− handleArchive . coerce $ tName
62− Update tName tTag tSetAp tUnsAp tSetD tUnsD tSetPAp tSetPD -> do
63− setApp <- liftIO $ parseSetApplicationOverrides Public tSetAp
64− setDep <- liftIO $ parseSetDeploymentOverrides Public tSetD
65− unsetApp <- liftIO $ parseUnsetApplicationOverrides Public tUnsAp
66− unsetDep <- liftIO $ parseUnsetDeploymentOverrides Public tUnsD
67− setPApp <- liftIO $ parseSetApplicationOverrides Private tSetPAp
68− setPDep <- liftIO $ parseSetDeploymentOverrides Private tSetPD
69− let
70− appOvs = setApp ++ setPApp
71− depOvs = setDep ++ setPDep
72− tName' = coerce tName
73− tTag' = coerce tTag
74− handleUpdate tName' tTag' appOvs unsetApp depOvs unsetDep
58+ Create tName tSetAp tSetDep -> do
59+ appOvs <- either dieT pure $ parseSetOverrides tSetAp
60+ depOvs <- either dieT pure $ parseSetOverrides tSetDep
61+ handleCreate auth $ Deployment (coerce tName) appOvs depOvs
62+ List -> handleList auth
63+ Archive tName -> handleArchive auth . coerce $ tName
64+ Update tName tSetAp unsetApp tSetD unsetDep -> do
65+ appOvs <- either dieT pure $ parseSetOverrides tSetAp
66+ depOvs <- either dieT pure $ parseSetOverrides tSetD
67+ let tName' = coerce tName
68+ handleUpdate auth tName' appOvs unsetApp depOvs unsetDep
7569 Info tName ->
76− handleInfo . coerce $ tName
70+ handleInfo auth . coerce $ tName
7771 Cleanup tName ->
78− handleCleanup . coerce $ tName
72+ handleCleanup auth . coerce $ tName
7973 Restore tName ->
80− handleRestore . coerce $ tName
81− CleanArchive ->
82− handleCleanArchive
83− GetActionLogs aId l -> handleGetActionInfo aId l
84−
85−-- | Initializes the HTTP connection manager.
86−initClientManager :: BaseUrl -> IO Manager
87−initClientManager baseURL = do
88− let
89− cert <- lookupEnv "TLS_CERT_PATH"
90− >>= maybe (pure $ TLSCertPath "cert.pem") (pure . TLSCertPath . BSC.pack)
91− key <- lookupEnv "TLS_KEY_PATH"
92− >>= maybe (pure $ TLSKeyPath "key.pem") (pure . TLSKeyPath . BSC.pack)
93− makeClientManager (baseUrlHost baseURL) cert key
74+ handleRestore auth . coerce $ tName
75+ GetActionLogs aId l -> handleGetActionInfo auth aId l
76+ Delete tName ->
77+ handleDelete auth . coerce $ tName
9478
9579-- | Returns BaseUrl from 'OCTOPOD_URL' environment variable
9680-- or exit with exit_code=1.
9781getBaseUrl :: IO BaseUrl
9882getBaseUrl = do
99− octopodURL <- lookupEnv "OCTOPOD_URL"
100− >>= maybe (die "OCTOPOD_URL is not set") pure
83+ octopodURL <-
84+ lookupEnv "OCTOPOD_URL"
85+ >>= maybe (die "OCTOPOD_URL is not set") pure
10186 case parseBaseUrl octopodURL of
10287 Just url -> pure url
10388 Nothing -> die "could not parse OCTOPOD_URL"
10489
10590-- | Handles the 'create' subcommand.
106−handleCreate :: Deployment -> ReaderT ClientEnv IO ()
107−handleCreate createCmd = do
91+handleCreate :: AuthContext AuthHeaderAuth -> Deployment -> ReaderT ClientEnv IO ()
92+handleCreate auth createCmd = do
10893 clientEnv <- ask
10994 liftIO $ do
110− response <- runClientM (createH createCmd) clientEnv
95+ response <- runClientM (createH auth createCmd) clientEnv
11196 handleResponse (const $ pure ()) response
11297
11398-- | Handles the 'list' subcommand.
114−handleList :: ReaderT ClientEnv IO ()
115−handleList = do
99+handleList :: AuthContext AuthHeaderAuth -> ReaderT ClientEnv IO ()
100+handleList auth = do
116101 clientEnv <- ask
117102 liftIO $ do
118− resp <- runClientM listH clientEnv
119− let
120− getName dep = dep ^.dfiName
121− names = T.unlines . coerce . (getName <$>) <$> resp
103+ resp <- runClientM (listH auth) clientEnv
104+ let getName dep = dep ^. dfiName
105+ names = T.unlines . coerce . (getName <$>) <$> resp
122106 handleResponse T.putStr names
123107
124108-- | Handles the 'archive' subcommand.
125−handleArchive :: DeploymentName -> ReaderT ClientEnv IO ()
126−handleArchive dName = do
109+handleArchive :: AuthContext AuthHeaderAuth -> DeploymentName -> ReaderT ClientEnv IO ()
110+handleArchive auth dName = do
127111 clientEnv <- ask
128112 liftIO $
129− handleResponse (const $ pure ()) =<< runClientM (archiveH dName) clientEnv
113+ handleResponse (const $ pure ()) =<< runClientM (archiveH auth dName) clientEnv
130114
131115-- | Handles the 'update' subcommand.
132−handleUpdate
133− :: DeploymentName
134− -> DeploymentTag
135− -> ApplicationOverrides
136− -> ApplicationOverrides
137− -> DeploymentOverrides
138− -> DeploymentOverrides
139− -> ReaderT ClientEnv IO ()
140−handleUpdate dName dTag dNewAppOvs dOldAppOvs dNewDepOvs dOldDepOvs = do
116+handleUpdate ::
117+ AuthContext AuthHeaderAuth ->
118+ DeploymentName ->
119+ Overrides 'ApplicationLevel ->
120+ [Text] ->
121+ Overrides 'DeploymentLevel ->
122+ [Text] ->
123+ ReaderT ClientEnv IO ()
124+handleUpdate auth dName dNewAppOvs removedAppOvs dNewDepOvs removedDepOvs = do
141125 clientEnv <- ask
126+ dep <- runClientM' (_fullInfoH auth dName) clientEnv
127+ let removeAll :: [Text] -> Overrides l -> (Overrides l)
128+ removeAll ks (Overrides (CT.toFlatList -> m)) = Overrides $ CT.fromFlatList $ filter (flip elem ks . fst) m
129+ appOverrides' = dNewAppOvs <> (removeAll removedAppOvs $ dep ^. #deployment . #appOverrides)
130+ deploymentOverrides' = dNewDepOvs <> (removeAll removedDepOvs $ dep ^. #deployment . #deploymentOverrides)
142131 liftIO $ do
143− let
144− dUpdate = DeploymentUpdate
145− { newTag = dTag
146− , newAppOverrides = dNewAppOvs
147− , oldAppOverrides = dOldAppOvs
148− , newDeploymentOverrides = dNewDepOvs
149− , oldDeploymentOverrides = dOldDepOvs
150− }
151− response <- runClientM (updateH dName dUpdate) clientEnv
132+ let dUpdate =
133+ DeploymentUpdate
134+ { appOverrides = appOverrides'
135+ , deploymentOverrides = deploymentOverrides'
136+ }
137+ response <- runClientM (updateH auth dName dUpdate) clientEnv
152138 handleResponse (const $ pure ()) response
153139
140+runClientM' :: MonadIO m => ClientM a -> ClientEnv -> m a
141+runClientM' req env = liftIO $ runClientM req env >>= either (die . displayException) pure
142+
154143-- | Handles the 'info' subcommand.
155−handleInfo :: DeploymentName -> ReaderT ClientEnv IO ()
156−handleInfo dName = do
144+handleInfo :: AuthContext AuthHeaderAuth -> DeploymentName -> ReaderT ClientEnv IO ()
145+handleInfo auth dName = do
157146 clientEnv <- ask
158147 liftIO $ do
159− res <- runClientM (infoH dName) clientEnv
148+ res <- runClientM (infoH auth dName) clientEnv
160149 case res of
161150 Right (i : _) -> printInfo i
162151 Right [] -> putStrLn notFoundMsg
163− Left err -> putStrLn $ "request failed, reason: " ++ show err
164− where
165− notFoundMsg = "deployment " ++ T.unpack (coerce dName) ++ " not found"
152+ other -> handleResponse (const $ pure ()) other
153+ where
154+ notFoundMsg = "Deployment " ++ T.unpack (coerce dName) ++ " not found"
166155
167156-- | Handles the 'cleanup' subcommand.
168−handleCleanup :: DeploymentName -> ReaderT ClientEnv IO ()
169−handleCleanup dName = do
157+handleCleanup :: AuthContext AuthHeaderAuth -> DeploymentName -> ReaderT ClientEnv IO ()
158+handleCleanup auth dName = do
170159 clientEnv <- ask
171160 liftIO $
172− handleResponse (const $ pure ()) =<< runClientM (cleanupH dName) clientEnv
161+ handleResponse (const $ pure ()) =<< runClientM (cleanupH auth dName) clientEnv
173162
174−-- | Handles the 'restore' subcommand.
175−handleRestore :: DeploymentName -> ReaderT ClientEnv IO ()
176−handleRestore dName = do
163+-- | Handles the 'delete' subcommand.
164+handleDelete :: AuthContext AuthHeaderAuth -> DeploymentName -> ReaderT ClientEnv IO ()
165+handleDelete auth dName = do
177166 clientEnv <- ask
178167 liftIO $
179− handleResponse (const $ pure ()) =<< runClientM (restoreH dName) clientEnv
168+ handleResponse (const $ pure ()) =<< runClientM (deleteH auth dName) clientEnv
180169
181−-- | Handles the 'clean-archive' subcommand.
182−handleCleanArchive :: ReaderT ClientEnv IO ()
183−handleCleanArchive = do
170+-- | Handles the 'restore' subcommand.
171+handleRestore :: AuthContext AuthHeaderAuth -> DeploymentName -> ReaderT ClientEnv IO ()
172+handleRestore auth dName = do
184173 clientEnv <- ask
185174 liftIO $
186− handleResponse (const $ pure ()) =<< runClientM cleanArchiveH clientEnv
175+ handleResponse (const $ pure ()) =<< runClientM (restoreH auth dName) clientEnv
187176
188177-- | Handles the 'logs' subcommand.
189−handleGetActionInfo :: ActionId -> LogOutput -> ReaderT ClientEnv IO ()
190−handleGetActionInfo aId l = do
178+handleGetActionInfo :: AuthContext AuthHeaderAuth -> ActionId -> LogOutput -> ReaderT ClientEnv IO ()
179+handleGetActionInfo auth aId l = do
191180 clientEnv <- ask
192181 liftIO $ do
193− runClientM (getActionInfoH aId) clientEnv >>= \case
194− Left err -> print err
195− Right x -> case l of
196− Out -> T.putStrLn $ x ^. #stdout
197− Err -> T.putStrLn $ x ^. #stderr
198− ErrOut -> do
199− T.putStrLn "\t\tstdout:\n"
200− T.putStrLn $ x ^. #stdout
201− T.putStrLn "\t\tstderr:\n"
202− T.putStrLn $ x ^. #stderr
203−
204−
205−listH :: ClientM [DeploymentFullInfo]
206−
207−createH :: Deployment -> ClientM CommandResponse
208−
209−archiveH :: DeploymentName -> ClientM CommandResponse
210−
211−updateH :: DeploymentName -> DeploymentUpdate -> ClientM CommandResponse
212−
213−infoH :: DeploymentName -> ClientM [DeploymentInfo]
214−
215−_fullInfoH :: DeploymentName -> ClientM DeploymentFullInfo
216−
217−_statusH :: DeploymentName -> ClientM CurrentDeploymentStatus
218−
219−cleanupH :: DeploymentName -> ClientM CommandResponse
220−
221−restoreH :: DeploymentName -> ClientM CommandResponse
222−
223−getActionInfoH :: ActionId -> ClientM ActionInfo
224−
225−cleanArchiveH :: ClientM CommandResponse
226−
182+ runClientM (getActionInfoH auth aId) clientEnv >>= handleResponse \x -> case l of
183+ Out -> T.putStrLn . unStdout $ x ^. #stdout
184+ Err -> T.putStrLn . unStderr $ x ^. #stderr
185+ ErrOut -> do
186+ T.putStrLn "\t\tstdout:\n"
187+ T.putStrLn . unStdout $ x ^. #stdout
188+ T.putStrLn "\t\tstderr:\n"
189+ T.putStrLn . unStderr $ x ^. #stderr
190+
191+listH :: AuthContext AuthHeaderAuth -> ClientM [DeploymentFullInfo]
192+createH :: AuthContext AuthHeaderAuth -> Deployment -> ClientM CommandResponse
193+archiveH :: AuthContext AuthHeaderAuth -> DeploymentName -> ClientM CommandResponse
194+updateH :: AuthContext AuthHeaderAuth -> DeploymentName -> DeploymentUpdate -> ClientM CommandResponse
195+infoH :: AuthContext AuthHeaderAuth -> DeploymentName -> ClientM [DeploymentInfo]
196+_fullInfoH :: AuthContext AuthHeaderAuth -> DeploymentName -> ClientM DeploymentFullInfo
197+_statusH :: AuthContext AuthHeaderAuth -> DeploymentName -> ClientM CurrentDeploymentStatus
198+cleanupH :: AuthContext AuthHeaderAuth -> DeploymentName -> ClientM CommandResponse
199+restoreH :: AuthContext AuthHeaderAuth -> DeploymentName -> ClientM CommandResponse
200+getActionInfoH :: AuthContext AuthHeaderAuth -> ActionId -> ClientM ActionInfo
201+deleteH :: AuthContext AuthHeaderAuth -> DeploymentName -> ClientM CommandResponse
227202( listH
228− :<|> createH
229− :<|> archiveH
230− :<|> updateH
231− :<|> infoH
232− :<|> _fullInfoH
233− :<|> _statusH
234− :<|> cleanupH
235− :<|> restoreH)
236− :<|> getActionInfoH
237− :<|> cleanArchiveH = client (Proxy @PowerAPI)
203+ :<|> createH
204+ :<|> archiveH
205+ :<|> updateH
206+ :<|> infoH
207+ :<|> _fullInfoH
208+ :<|> _statusH
209+ :<|> cleanupH
210+ :<|> restoreH
211+ :<|> deleteH
212+ )
213+ :<|> getActionInfoH = pushArrowIntoServantAlt $ client (Proxy @PowerAPI)
214+
215+type PushArrowIntoServantAlt a b = PushArrowIntoServantAlt' a b (CanPushArrow a)
216+
217+class CanPushArrow x ~ f => PushArrowIntoServantAlt' x y (f :: Bool) | x f -> y where
218+ pushArrowIntoServantAlt :: x -> y
219+
220+type family CanPushArrow x :: Bool where
221+ CanPushArrow (_ -> (_ :<|> _)) = 'True
222+ CanPushArrow _ = 'False
223+
224+instance (PushArrowIntoServantAlt (x -> a) a', PushArrowIntoServantAlt (x -> b) b') => PushArrowIntoServantAlt' (x -> (a :<|> b)) (a' :<|> b') 'True where
225+ pushArrowIntoServantAlt f =
226+ pushArrowIntoServantAlt (\x -> let (a :<|> _) = f x in a)
227+ :<|> pushArrowIntoServantAlt (\x -> let (_ :<|> b) = f x in b)
228+
229+instance CanPushArrow (x -> y) ~ 'False => PushArrowIntoServantAlt' (x -> y) (x -> y) 'False where
230+ pushArrowIntoServantAlt x = x
238231
239232-- | Handles response from Octopod Server.
240233handleResponse :: (a -> IO ()) -> Either ClientError a -> IO ()
241234handleResponse f (Right result) = f result
242−handleResponse _ (Left (FailureResponse _req res)) =
243− T.putStrLn . decodeError $ responseBody res
244−handleResponse _ (Left err) =
245− T.putStrLn $ "command failed due to unknown reason: " <> T.pack (show err)
246−
247−decodeError :: LBSC.ByteString -> Text
235+handleResponse _ (Left cErr) = do
236+ case cErr of
237+ (ConnectionError exc) -> do
238+ hPutStrLn stderr "Connection error"
239+ hPutStrLn stderr $ displayException exc
240+ (FailureResponse _ res) -> do
241+ showResponseStatus res
242+ case decodeError $ responseBody res of
243+ Just errT -> do T.hPutStrLn stderr errT
244+ Nothing | not . LBSC.null $ responseBody res -> do
245+ LBSC.hPutStrLn stderr $ responseBody res
246+ pure ()
247+ Nothing -> pure ()
248+ (InvalidContentTypeHeader res) -> do
249+ showResponseStatus res
250+ hPutStrLn stderr "Invalid content type header received"
251+ (UnsupportedContentType ctype res) -> do
252+ showResponseStatus res
253+ hPutStrLn stderr $ "Unsupported content type header received: " <> show ctype
254+ (DecodeFailure err res) -> do
255+ showResponseStatus res
256+ hPutStrLn stderr $ "The response body could not be decoded: "
257+ T.hPutStrLn stderr err
258+ exitFailure
259+
260+showResponseStatus :: Response -> IO ()
261+showResponseStatus Response {responseStatusCode = (Status code body)} = do
262+ hPutStr stderr $ show code <> " "
263+ BSC.hPutStrLn stderr body
264+ pure ()
265+
266+decodeError :: LBSC.ByteString -> Maybe Text
248267decodeError body =
249− case decode body of
250− Just (ValidationError nameErrors tagErrors) ->
251− T.concat ((<> "\n") <$> nameErrors) <> T.concat ((<> "\n") <$> tagErrors)
252− Just (AppError errorMsg) -> errorMsg
253− Just Success -> "ok"
254− _ -> "error: " <> (T.pack . LBSC.unpack $ body)
268+ decode body <&> \case
269+ (ValidationError nameErrors) ->
270+ T.concat ((<> "\n") <$> nameErrors)
271+ (AppError errorMsg) -> errorMsg
272+ Success -> "ok"
255273
256274-- | Pretty-prints the 'info' subcommand result.
257275printInfo :: DeploymentInfo -> IO ()
258−printInfo (DeploymentInfo (Deployment _ dTag dAppOvs dStOvs) dMeta dLogs) = do
276+printInfo (DeploymentInfo (Deployment _ dAppOvs dStOvs) (DeploymentMetadata dMeta) dLogs) = do
259277 T.putStrLn "Current settings:"
260− T.putStrLn $ "tag: " <> coerce dTag
261− T.putStrLn $ "application overrides: "
262− <> (formatOverrides $ coerce <$> dAppOvs)
263− T.putStrLn $ "deployment overrides: "
264− <> (formatOverrides $ coerce <$> dStOvs)
265− T.putStrLn $ "metadata: "
266− forM_ dMeta $ \m ->
278+ T.putStrLn "Application config:"
279+ putStrLn $ unlines $ formatOverrides False dAppOvs
280+ T.putStrLn ""
281+ T.putStrLn "Deployment config: "
282+ putStrLn $ unlines $ formatOverrides False dStOvs
283+ T.putStrLn ""
284+ T.putStrLn $ "Metadata: "
285+ for_ dMeta $ \m ->
267286 T.putStrLn $
268− " " <> deploymentMetadataKey m <> ": " <> deploymentMetadataValue m
287+ " " <> m ^. #name <> ": " <> m ^. #link
269288 T.putStrLn ""
270289 T.putStrLn "Last logs:"
271290 ppDeploymentLogs dLogs
@@ -274,38 +293,55 @@ ppDeploymentLogs :: [DeploymentLog] -> IO ()
274293ppDeploymentLogs ds =
275294 putStrLn
276295 . tableString
277− [ column expand right noAlign def
296+ [ column expand center noAlign def
297+ , column expand center noAlign def
278298 , column expand center noAlign def
279299 , column expand center noAlign def
280300 , column expand center noAlign def
281− , column expand left (charAlign '=') def
282− , column expand left (charAlign '=') def
283301 , column expand center noAlign def
284302 ]
285− unicodeBoldHeaderS
286− (titlesH
287− [ "Created at"
288− , "Action id"
289− , "Action"
290− , "Tag"
291− , "App overrides"
292− , "Deployment overrides"
293− , "Exit code"
294− ])
303+ unicodeDoubleFrameS
304+ ( titlesH
305+ [ "Created at"
306+ , "Action id"
307+ , "Action"
308+ , "App config"
309+ , "Deployment config"
310+ , "Exit code"
311+ ]
312+ )
295313 $ ppDeploymentLogRow <$> ds
296314
297315-- | Pretty-prints the deployment log.
298−ppDeploymentLogRow :: DeploymentLog -> RowGroup Text
299−ppDeploymentLogRow dLog = colsAllG top
300− [ [encode_YmdHMS SubsecondPrecisionAuto w3c
301− (timeToDatetime . Time . fromIntegral
302− $ dLog ^. field @"createdAt" * 10 ^ (9 :: Int))]
303− , [dLog ^. field @"actionId" . to unActionId . re _Show . packed]
304− , [dLog ^. field @"action" . coerced]
305− , [dLog ^. field @"deploymentTag" . coerced]
306− , dLog ^. field @"deploymentAppOverrides"
307− . to (fmap $ formatOverride . coerce)
308− , dLog ^. field @"deploymentDepOverrides"
309− . to (fmap $ formatOverride . coerce)
310− , [dLog ^. field @"exitCode" . re _Show . packed]
311− ]
316+ppDeploymentLogRow :: DeploymentLog -> RowGroup String
317+ppDeploymentLogRow dLog =
318+ colsAllG
319+ top
320+ [
321+ [ formatTime defaultTimeLocale (iso8601DateFormat (Just "%H:%M:%S")) $
322+ dLog ^. field @"createdAt"
323+ ]
324+ , [dLog ^. field @"actionId" . to unActionId . re _Show . packed]
325+ , [dLog ^. field @"action" . to (T.unpack . actionToText)]
326+ , dLog ^. field @"deploymentAppOverrides" . to (stripBorder . formatOverrides True)
327+ , dLog ^. field @"deploymentDepOverrides" . to (stripBorder . formatOverrides True)
328+ , [dLog ^. field @"exitCode" . re _Show . packed]
329+ ]
330+
331+stripBorder :: [String] -> [String]
332+stripBorder = fmap (init . tail) . init . tail
333+
334+formatOverrides :: Bool -> Overrides l -> [String]
335+formatOverrides splitlines (Overrides m) =
336+ tableLines
337+ [ column expand right noAlign def
338+ , column expand left noAlign def
339+ ]
340+ unicodeS
341+ def
342+ $ showOverride <$> (reverse . CT.toFlatList) m
343+ where
344+ showOverride (k, v) =
345+ colsAllG top $ [if splitlines then T.chunksOf 15 k else [k], showValue v]
346+ showValue (ValueAdded v) = if splitlines then T.chunksOf 25 v else [v]
347+ showValue ValueDeleted = ["<<REMOVED>>"]
octo-cli/src/Octopod/CLI/Args.hs+122−138
@@ -1,72 +1,61 @@
1−{-|
2−Module : Octopod.CLI.Args
3−Description : octo CLI arguments parser utils.
4−-}
1+{-# OPTIONS_GHC -Wno-missing-export-lists #-}
52
3+-- |
4+--Module : Octopod.CLI.Args
5+--Description : octo CLI arguments parser utils.
66module Octopod.CLI.Args where
77
8−import Common.Types
9−import Data.Semigroup ((<>))
10−import Data.Text
11−import Options.Applicative
8+import Common.Types
9+import Data.Text
10+import Options.Applicative
1211
1312-- | octo CLI subcommands and arguments definition.
1413data Args
1514 = Create
16− { name :: Text
17− -- ^ deployment name
18− , tag :: Text
19− -- ^ deployment tag
20− , setAppOverrides :: [Text]
21− -- ^ application-level overrides to set
22− , setDeploymentOverrides :: [Text]
23− -- ^ deployment-level overrides to set
24− , setAppPrivateOverrides :: [Text]
25− -- ^ application-level private overrides to set
26− , setDeploymentPrivateOverrides :: [Text]
27− -- ^ deployment-level private overrides to set
28− }
15+ { -- | deployment name
16+ name :: Text
17+ , -- | application-level overrides to set
18+ setAppOverrides :: [Text]
19+ , -- | deployment-level overrides to set
20+ setDeploymentOverrides :: [Text]
21+ }
2922 | List
3023 | Archive
31− { name :: Text
32− -- ^ deployment name
33− }
24+ { -- | deployment name
25+ name :: Text
26+ }
3427 | Update
35− { name :: Text
36− -- ^ deployment name
37− , tag :: Text
38− -- ^ deployment tag
39− , setAppOverrides :: [Text]
40− -- ^ application-level overrides to set
41− , unsetAppOverrides :: [Text]
42− -- ^ application-level overrides to unset
43− , setDeploymentOverrides :: [Text]
44− -- ^ deployment-level overrides to set
45− , unsetDeploymentOverrides :: [Text]
46− -- ^ deployment-level overrides to unset
47− , setAppPrivateOverrides :: [Text]
48− -- ^ application-level private overrides to set
49− , setDeploymentPrivateOverrides :: [Text]
50− -- ^ deployment-level private overrides to set
51− }
28+ { -- | deployment name
29+ name :: Text
30+ , -- | application-level overrides to set
31+ setAppOverrides :: [Text]
32+ , -- | application-level overrides to unset
33+ unsetAppOverrides :: [Text]
34+ , -- | deployment-level overrides to set
35+ setDeploymentOverrides :: [Text]
36+ , -- | deployment-level overrides to unset
37+ unsetDeploymentOverrides :: [Text]
38+ }
5239 | Info
53− { name :: Text
54− -- ^ deployment name
55− }
40+ { -- | deployment name
41+ name :: Text
42+ }
5643 | Cleanup
57− { name :: Text
58− -- ^ deployment name
59− }
44+ { -- | deployment name
45+ name :: Text
46+ }
6047 | Restore
61− { name :: Text
62− -- ^ deployment name
63− }
64− | CleanArchive
48+ { -- | deployment name
49+ name :: Text
50+ }
6551 | GetActionLogs ActionId LogOutput
52+ | Delete
53+ { name :: Text
54+ }
6655 deriving stock (Show)
6756
6857data LogOutput = Err | Out | ErrOut
69− deriving stock Show
58+ deriving stock (Show)
7059
7160readLogOutput :: String -> Maybe LogOutput
7261readLogOutput "stderr" = Just Err
@@ -79,48 +68,45 @@ readLogOutput _ = Nothing
7968
8069-- | Parses octo CLI subcommands and arguments.
8170parseArgs :: IO Args
82−parseArgs = execParser $ info (commandArgs <**> helper) fullDesc
71+parseArgs =
72+ customExecParser (prefs showHelpOnError) $ info (commandArgs <**> helper) fullDesc
8373
8474-- | Parses octo CLI subcommands.
8575commandArgs :: Parser Args
8676commandArgs =
87− hsubparser (
88− command "create" (info createArgs (progDesc "create a new deployment"))
89− <> command "list" (info listArgs (progDesc "get names all deployments"))
90− <> command "archive" (info archiveArgs (progDesc "archive the deployment"))
91− <> command "update" (info updateArgs (progDesc "update the deployment"))
92− <> command "info" (info infoArgs (progDesc "get the deployment info"))
93− <> command "cleanup" (info cleanupArgs (progDesc "cleanup the deployment"))
94− <> command "restore" (info restoreArgs (progDesc "restore the deployment"))
95− <> command "clean-archive"
96− (info cleanupArchiveArgs (progDesc "cleanup all archived deployments"))
97− <> command "logs"
98− (info actionLogsArgs (progDesc "get deployment logs of a given action")))
77+ hsubparser
78+ ( command "create" (info createArgs (progDesc "create a new deployment"))
79+ <> command "list" (info listArgs (progDesc "get names all deployments"))
80+ <> command "archive" (info archiveArgs (progDesc "archive the deployment"))
81+ <> command "update" (info updateArgs (progDesc "update the deployment"))
82+ <> command "info" (info infoArgs (progDesc "get the deployment info"))
83+ <> command "cleanup" (info cleanupArgs (progDesc "cleanup the deployment"))
84+ <> command "restore" (info restoreArgs (progDesc "restore the deployment"))
85+ <> command
86+ "logs"
87+ (info actionLogsArgs (progDesc "get deployment logs of a given action"))
88+ <> command "delete" (info deleteArgs (progDesc "delete the deployment from Octopod. Does no cleanup."))
89+ )
9990
10091-- | Parses arguments of 'create' subcommand.
10192createArgs :: Parser Args
10293createArgs =
10394 Create
104− <$> strOption (long "name" <> short 'n' <> help "deployment name")
105− <*> strOption (long "tag" <> short 't' <> help "deployment tag")
106− <*> many (strOption
107− (long "set-app-env-override"
108− <> short 'e'
109− <> help "set application level override"))
110− <*> many (strOption
111− (long "set-deployment-override"
112− <> short 'o'
113− <> help "set deployment level override"))
114− <*> many (strOption
115− (long "set-app-env-private-override"
116− <> short 'a'
117− <> help "set application level private override"
118− <> internal))
119− <*> many (strOption
120− (long "set-deployment-private-override"
121− <> short 's'
122− <> help "set deployment level private override"
123− <> internal))
95+ <$> deploymentNameArgument
96+ <*> many
97+ ( strOption
98+ ( long "set-app-config"
99+ <> short 'e'
100+ <> help "set application level override"
101+ )
102+ )
103+ <*> many
104+ ( strOption
105+ ( long "set-deployment-config"
106+ <> short 'o'
107+ <> help "set deployment level override"
108+ )
109+ )
124110
125111-- | Parses arguments of 'list' subcommand.
126112listArgs :: Parser Args
@@ -129,72 +115,70 @@ listArgs =
129115
130116-- | Parses arguments of 'archive' subcommand.
131117archiveArgs :: Parser Args
132−archiveArgs =
133− Archive
134− <$> strOption (long "name" <> short 'n' <> help "deployment name")
118+archiveArgs = Archive <$> deploymentNameArgument
135119
136120-- | Parses arguments of 'update' subcommand.
137121updateArgs :: Parser Args
138122updateArgs =
139123 Update
140− <$> strOption (long "name" <> short 'n' <> help "deployment name")
141− <*> strOption (long "tag" <> short 't' <> help "deployment tag")
142− <*> many (strOption
143− (long "set-app-env-override"
144− <> short 'e'
145− <> help "set application level override"))
146− <*> many (strOption
147− (long "unset-app-env-override"
148− <> short 'E'
149− <> help "unset an application level override"))
150− <*> many (strOption
151− (long "set-deployment-override"
152− <> short 'o'
153− <> help "set deployment level override"))
154− <*> many (strOption
155− (long "unset-deployment-override"
156− <> short 'O'
157− <> help "unset a deployment level override"))
158− <*> many (strOption
159− (long "set-app-env-private-override"
160− <> short 'a'
161− <> help "set application level private override"
162− <> internal))
163− <*> many (strOption
164− (long "set-deployment-private-override"
165− <> short 's'
166− <> help "set deployment level private override"
167− <> internal))
124+ <$> deploymentNameArgument
125+ <*> many
126+ ( strOption
127+ ( long "set-app-config"
128+ <> short 'e'
129+ <> help "set application level override"
130+ )
131+ )
132+ <*> many
133+ ( strOption
134+ ( long "unset-app-env-override"
135+ <> short 'E'
136+ <> help "unset an application level override"
137+ )
138+ )
139+ <*> many
140+ ( strOption
141+ ( long "set-deployment-config"
142+ <> short 'o'
143+ <> help "set deployment level override"
144+ )
145+ )
146+ <*> many
147+ ( strOption
148+ ( long "unset-deployment-override"
149+ <> short 'O'
150+ <> help "unset a deployment level override"
151+ )
152+ )
168153
169154-- | Parses arguments of 'info' subcommand.
170155infoArgs :: Parser Args
171−infoArgs =
172− Info
173− <$> strOption (long "name" <> short 'n' <> help "deployment name")
156+infoArgs = Info <$> deploymentNameArgument
174157
175158-- | Parses arguments of 'cleanup' subcommand.
176159cleanupArgs :: Parser Args
177−cleanupArgs =
178− Cleanup
179− <$> strOption (long "name" <> short 'n' <> help "deployment name")
160+cleanupArgs = Cleanup <$> deploymentNameArgument
161+
162+-- | Parses arguments of 'delete' subcommand.
163+deleteArgs :: Parser Args
164+deleteArgs = Delete <$> deploymentNameArgument
180165
181166-- | Parses arguments of 'restore' subcommand.
182167restoreArgs :: Parser Args
183−restoreArgs =
184− Restore
185− <$> strOption (long "name" <> short 'n' <> help "deployment name")
186−
187−-- | Parses arguments of 'clean-archive' subcommand.
188−cleanupArchiveArgs :: Parser Args
189−cleanupArchiveArgs =
190− pure CleanArchive
168+restoreArgs = Restore <$> deploymentNameArgument
191169
192170actionLogsArgs :: Parser Args
193−actionLogsArgs = GetActionLogs
194− <$> (ActionId <$> option auto (long "action" <> short 'a' <> help "action id"))
195− <*> option (maybeReader readLogOutput)
196− ( long "log-type"
197− <> short 'l'
198− <> help "log types to print. Values are: stdout, stderr, all"
199− <> value ErrOut
200− <> completeWith ["stdout", "stderr", "all"])
171+actionLogsArgs =
172+ GetActionLogs
173+ <$> (ActionId <$> option auto (long "action" <> short 'a' <> help "action id"))
174+ <*> option
175+ (maybeReader readLogOutput)
176+ ( long "log-type"
177+ <> short 'l'
178+ <> help "log types to print. Values are: stdout, stderr, all"
179+ <> value ErrOut
180+ <> completeWith ["stdout", "stderr", "all"]
181+ )
182+
183+deploymentNameArgument :: Parser Text
184+deploymentNameArgument = strOption (long "name" <> short 'n' <> help "deployment name")
octo-cli/src/Octopod/CLI/TLS.hsdeleted−39
@@ -1,39 +0,0 @@
1−module Octopod.CLI.TLS
2− ( makeClientManager
3− ) where
4−
5−import Common.Types
6−import qualified Data.ByteString.Char8 as BSC
7−import Data.Coerce
8−import Data.Default.Class (def)
9−import Network.Connection
10−import Network.HTTP.Client
11− (Manager, managerResponseTimeout, newManager, responseTimeoutMicro)
12−import Network.HTTP.Client.TLS
13−import Network.TLS
14− (ClientHooks(..), clientHooks, clientSupported, credentialLoadX509,
15− defaultParamsClient, supportedCiphers)
16−import Network.TLS.Extra.Cipher
17−
18−-- | Initializes the HTTP client using TLS
19−makeClientManager :: String -> TLSCertPath -> TLSKeyPath -> IO Manager
20−makeClientManager octopodHostName cert key = do
21− creds <- do
22− let
23− cert' = BSC.unpack . coerce $ cert
24− key' = BSC.unpack . coerce $ key
25− either error Just <$> credentialLoadX509 cert' key'
26− let
27− hooks = def
28− { onCertificateRequest = \_ -> return creds
29− , onServerCertificate = \_ _ _ _ -> return []
30− }
31− clientParams = (defaultParamsClient octopodHostName "")
32− { clientHooks = hooks
33− , clientSupported = def { supportedCiphers = ciphersuite_default }
34− }
35− tlsSettings = TLSSettings clientParams
36− timeout = 20 * 60 * 10 ^ (6 :: Int)
37− tlsManagerSettings' = (mkManagerSettings tlsSettings Nothing)
38− { managerResponseTimeout = responseTimeoutMicro timeout }
39− in newManager tlsManagerSettings'
octo-cli/src/Octopod/PowerAPI/Auth/Client.hsnew file+28
@@ -0,0 +1,28 @@
1+{-# OPTIONS_GHC -Wno-orphans #-}
2+
3+module Octopod.PowerAPI.Auth.Client
4+ ( IsAuth (..),
5+ AuthContext (..),
6+ )
7+where
8+
9+import Data.Proxy
10+import Octopod.PowerAPI
11+import Servant.API hiding (addHeader)
12+import Servant.Auth
13+import Servant.Client.Core
14+
15+class IsAuth a where
16+ data AuthContext a
17+ applyAuth :: AuthContext a -> Request -> Request
18+
19+instance (IsAuth a, HasClient m api) => HasClient m (Auth '[a] x :> api) where
20+ type Client m (Auth '[a] x :> api) = AuthContext a -> Client m api
21+ clientWithRoute pm Proxy req val =
22+ clientWithRoute pm (Proxy :: Proxy api) (applyAuth val req)
23+
24+ hoistClientMonad pm _ f cl = hoistClientMonad pm (Proxy :: Proxy api) f . cl
25+
26+instance IsAuth AuthHeaderAuth where
27+ data AuthContext AuthHeaderAuth = AuthHeaderAuthCtx String
28+ applyAuth (AuthHeaderAuthCtx h) req = addHeader "Authorization" h req
octo-cli/src/Text/Layout/Table/Extras.hs+11−9
@@ -2,23 +2,25 @@
22
33module Text.Layout.Table.Extras
44 (
5− ) where
5+ )
6+where
67
7−import Data.Text
8+import Data.Text
89import qualified Data.Text as T
9−import Text.Layout.Table.Cell
10−import Text.Layout.Table.Primitives.AlignInfo
11−import Text.Layout.Table.StringBuilder
10+import Text.Layout.Table.Cell
11+import Text.Layout.Table.Primitives.AlignInfo
12+import Text.Layout.Table.StringBuilder
1213
1314instance Cell Text where
1415 dropLeft = T.drop
1516 dropRight = T.dropEnd
1617 visibleLength = T.length
1718 measureAlignment p xs = case T.break p xs of
18− (ls, rs) -> AlignInfo (T.length ls) $
19− if T.null rs
20− then Nothing
21− else Just $ T.length rs - 1
19+ (ls, rs) ->
20+ AlignInfo (T.length ls) $
21+ if T.null rs
22+ then Nothing
23+ else Just $ T.length rs - 1
2224 buildCell = stringB . T.unpack
2325
2426instance StringBuilder Text where
octopod-api/Setup.hs+1
@@ -1,2 +1,3 @@
11import Distribution.Simple
2+
23main = defaultMain
octopod-api/octopod-api.cabal+15−3
@@ -32,9 +32,11 @@ library
3232 TypeApplications
3333 TypeOperators
3434 build-depends:
35− base ^>=4.12.0.0,
35+ base,
3636 servant,
3737 octopod-common,
38+ servant-auth,
39+ text,
3840 if !impl(ghcjs)
3941 build-depends:
4042 servant-websockets,
@@ -42,5 +44,15 @@ library
4244 hs-source-dirs: src
4345 default-language: Haskell2010
4446 ghc-options:
45− -Wall
46− -Werror
47+ -Weverything
48+ -Wno-implicit-prelude
49+ -Wno-missing-safe-haskell-mode
50+ -Wno-safe
51+ -Wno-prepositive-qualified-module
52+ -Wno-missing-import-lists
53+ -Wno-all-missed-specialisations
54+ -Wno-missing-local-signatures
55+ -Wno-partial-fields
56+ -Wno-unsafe
57+ -Wno-monomorphism-restriction
58+ -Wno-missed-specialisations
octopod-api/src/Octopod/API.hs+56−39
@@ -1,20 +1,19 @@
1−{-|
2−Module : Octopod.API
3−Description : Backend endpoints.
4−
5−This module contains backend endpoints.
6−-}
7−
8−
1+-- |
2+--Module : Octopod.API
3+--Description : Backend endpoints.
4+--
5+--This module contains backend endpoints.
96module Octopod.API
10− ( module Octopod.API.WebSocket
11− , API
12− ) where
7+ ( module Octopod.API.WebSocket,
8+ API,
9+ )
10+where
1311
14−import Servant.API
12+import Servant.API
1513
16−import Common.Types
17−import Octopod.API.WebSocket
14+import Common.Types
15+import Data.Text (Text)
16+import Octopod.API.WebSocket
1817
1918type CaptureName = Capture "name" DeploymentName
2019
@@ -30,35 +29,53 @@ type StatusEndpoint c = c :> "status" :> Get '[JSON] CurrentDeploymentStatus
3029type RestoreEndpoint c =
3130 c :> "restore" :> Patch '[JSON] CommandResponse
3231
33−type PingEndpoint = "ping" :> GetNoContent
32+type DefaultDeploymentOverrideKeys =
33+ "deployment_override_keys" :> Get '[JSON] [Text]
34+type DefaultDeploymentOverrides =
35+ "deployment_overrides" :> Get '[JSON] (DefaultConfig 'DeploymentLevel)
36+type DefaultApplicationOverrideKeys =
37+ "application_override_keys"
38+ :> ReqBody '[JSON] (Config 'DeploymentLevel)
39+ :> Post '[JSON] [Text]
40+type DefaultApplicationOverrides =
41+ "application_overrides"
42+ :> ReqBody '[JSON] (Config 'DeploymentLevel)
43+ :> Post '[JSON] (DefaultConfig 'ApplicationLevel)
44+
45+type PingEndpoint = "ping" :> Get '[PlainText] Text
3446type ProjectNameEndpoint =
3547 "project_name" :> Get '[JSON] ProjectName
3648
3749type DeploymentAPI' c =
38− "api" :> "v1" :>
39− ( "deployments" :>
40− ( ListEndpoint
41− -- endpoint to get deployment list
42− :<|> CreateEndpoint
43− -- endpoint to create a new deployment
44− :<|> ArchiveEndpoint c
45− -- endpoint to archive existing deployment
46− :<|> UpdateEndpoint c
47− -- endpoint to update exists deployment
48− :<|> InfoEndpoint c
49− -- endpoint to get deployment info
50− :<|> FullInfoEndpoint c
51− -- endpoint to get deployment full info
52− :<|> StatusEndpoint c
53− -- endpoint to get deployment status
54− :<|> RestoreEndpoint c
55− -- endpoint to restore deployment
56− )
57− :<|> PingEndpoint
58− -- endpoint to liveness probe
59− :<|> ProjectNameEndpoint
60− -- endpoint to get project name
61− )
50+ "api" :> "v1"
51+ :> ( DefaultDeploymentOverrideKeys
52+ :<|> DefaultDeploymentOverrides
53+ :<|> DefaultApplicationOverrideKeys
54+ :<|> DefaultApplicationOverrides
55+ :<|> ( "deployments"
56+ :> ( ListEndpoint
57+ -- endpoint to get deployment list
58+ :<|> CreateEndpoint
59+ -- endpoint to create a new deployment
60+ :<|> ArchiveEndpoint c
61+ -- endpoint to archive existing deployment
62+ :<|> UpdateEndpoint c
63+ -- endpoint to update exists deployment
64+ :<|> InfoEndpoint c
65+ -- endpoint to get deployment info
66+ :<|> FullInfoEndpoint c
67+ -- endpoint to get deployment full info
68+ :<|> StatusEndpoint c
69+ -- endpoint to get deployment status
70+ :<|> RestoreEndpoint c
71+ -- endpoint to restore deployment
72+ )
73+ :<|> PingEndpoint
74+ -- endpoint to liveness probe
75+ :<|> ProjectNameEndpoint
76+ -- endpoint to get project name
77+ )
78+ )
6279
6380-- | API for frontend
6481type API = DeploymentAPI' CaptureName
octopod-api/src/Octopod/API/WebSocket.hs+8−3
@@ -1,6 +1,13 @@
1+{- ORMOLU_DISABLE -}
12{-# LANGUAGE CPP #-}
23
3−module Octopod.API.WebSocket where
4+module Octopod.API.WebSocket
5+ ( ApiWSPath,
6+#ifndef ghcjs_HOST_OS
7+ WebSocketAPI,
8+#endif
9+ )
10+where
411
512#ifndef ghcjs_HOST_OS
613
@@ -10,10 +17,8 @@ import Servant.API.WebSocketConduit
1017
1118#endif
1219
13−
1420type ApiWSPath = "event"
1521
16−
1722#ifndef ghcjs_HOST_OS
1823
1924-- | WS API
octopod-api/src/Octopod/PowerAPI.hs+53−45
@@ -1,71 +1,79 @@
1−{-|
2−Module : Octopod.PowerAPI
3−Description : Backend endpoints.
4−
5−This module contains backend endpoints.
6−-}
7−
8−
1+-- |
2+-- Module : Octopod.PowerAPI
3+-- Description : Backend endpoints.
4+--
5+-- This module contains backend endpoints.
96module Octopod.PowerAPI
10− ( module Octopod.API.WebSocket
11− , PowerAPI
12− ) where
13−
14−import Servant.API
7+ ( module Octopod.API.WebSocket,
8+ PowerAPI,
9+ AuthHeaderAuth,
10+ )
11+where
1512
16−import Common.Types
17−import Octopod.API.WebSocket
13+import Common.Types
14+import Octopod.API.WebSocket
15+import Servant.API
16+import Servant.Auth
1817
1918type CaptureName = Capture "name" DeploymentName
2019
2120type ListEndpoint = Get '[JSON] [DeploymentFullInfo]
21+
2222type CreateEndpoint =
2323 ReqBody '[JSON] Deployment :> Post '[JSON] CommandResponse
24+
2425type ArchiveEndpoint c = c :> Delete '[JSON] CommandResponse
26+
2527type UpdateEndpoint c =
2628 c :> ReqBody '[JSON] DeploymentUpdate :> Put '[JSON] CommandResponse
29+
2730type InfoEndpoint c = c :> "info" :> Get '[JSON] [DeploymentInfo]
31+
2832type FullInfoEndpoint c = c :> "full_info" :> Get '[JSON] DeploymentFullInfo
33+
2934type StatusEndpoint c = c :> "status" :> Get '[JSON] CurrentDeploymentStatus
35+
3036type CleanupEndpoint c =
3137 c :> "cleanup" :> Delete '[JSON] CommandResponse
38+
39+type DeleteEndpoint c =
40+ c :> "delete" :> Delete '[JSON] CommandResponse
41+
3242type RestoreEndpoint c =
3343 c :> "restore" :> Patch '[JSON] CommandResponse
3444
3545type GetActionInfoEndpoint =
3646 "log" :> Capture "action_id" ActionId :> Get '[JSON] ActionInfo
3747
38−type CleanArchiveEndpoint =
39− "clean_archive" :> Delete '[JSON] CommandResponse
40−
4148type DeploymentAPI' c =
42− "api" :> "v1" :>
43− ( "deployments" :>
44− ( ListEndpoint
45− -- endpoint to get deployment list
46− :<|> CreateEndpoint
47− -- endpoint to create a new deployment
48− :<|> ArchiveEndpoint c
49− -- endpoint to archive an existing deployment
50− :<|> UpdateEndpoint c
51− -- endpoint to update an existing deployment
52− :<|> InfoEndpoint c
53− -- endpoint to get deployment info
54− :<|> FullInfoEndpoint c
55− -- endpoint to get full deployment info
56− :<|> StatusEndpoint c
57− -- endpoint to get deployment status
58− :<|> CleanupEndpoint c
59− -- endpoint to clean up resources of an archived deployment
60− :<|> RestoreEndpoint c
61− -- endpoint to restore an archived deployment
62− )
63− :<|> GetActionInfoEndpoint
64− -- endpoint to get action logs
65− :<|> CleanArchiveEndpoint
66− -- endpoint to clean up resources of all archived deployments
67− -- according to the archive retention policy
68− )
49+ Auth '[AuthHeaderAuth] () :> "api" :> "v1"
50+ :> ( "deployments"
51+ :> ( ListEndpoint
52+ -- endpoint to get deployment list
53+ :<|> CreateEndpoint
54+ -- endpoint to create a new deployment
55+ :<|> ArchiveEndpoint c
56+ -- endpoint to archive an existing deployment
57+ :<|> UpdateEndpoint c
58+ -- endpoint to update an existing deployment
59+ :<|> InfoEndpoint c
60+ -- endpoint to get deployment info
61+ :<|> FullInfoEndpoint c
62+ -- endpoint to get full deployment info
63+ :<|> StatusEndpoint c
64+ -- endpoint to get deployment status
65+ :<|> CleanupEndpoint c
66+ -- endpoint to clean up resources of an archived deployment
67+ :<|> RestoreEndpoint c
68+ -- endpoint to restore an archived deployment
69+ :<|> DeleteEndpoint c
70+ -- endpoint to clean up resources of an archived deployment
71+ )
72+ :<|> GetActionInfoEndpoint
73+ -- endpoint to get action logs
74+ )
75+
76+data AuthHeaderAuth
6977
7078-- | API for the octo CLI
7179type PowerAPI = DeploymentAPI' CaptureName
octopod-backend/Setup.hs+2−1
@@ -1,2 +1,3 @@
1−import Distribution.Simple
1+import Distribution.Simple
2+
23main = defaultMain
octopod-backend/app/Main.hs+7−3
@@ -1,6 +1,10 @@
1−module Main where
1+{-# LANGUAGE TemplateHaskell #-}
22
3−import Octopod.Server
3+module Main (main) where
4+
5+import qualified Data.Text as T
6+import Development.GitRev
7+import Octopod.Server
48
59main :: IO ()
6−main = runOctopodServer
10+main = runOctopodServer (T.pack $gitHash)
octopod-backend/octopod-backend.cabal+62−108
@@ -18,8 +18,19 @@ source-repository head
1818 location: https://github.com/typeable/octopod
1919
2020library
21− ghc-options: -Wall
22− -Werror
21+ ghc-options:
22+ -Weverything
23+ -Wno-implicit-prelude
24+ -Wno-missing-safe-haskell-mode
25+ -Wno-safe
26+ -Wno-prepositive-qualified-module
27+ -Wno-missing-import-lists
28+ -Wno-all-missed-specialisations
29+ -Wno-missing-local-signatures
30+ -Wno-partial-fields
31+ -Wno-unsafe
32+ -Wno-monomorphism-restriction
33+ -Wno-missed-specialisations
2334 default-extensions: BlockArguments
2435 , ConstraintKinds
2536 , DataKinds
@@ -35,15 +46,31 @@ library
3546 , StandaloneDeriving
3647 , TypeApplications
3748 , TypeOperators
49+ , OverloadedLabels
50+ , UndecidableInstances
51+ , MultiParamTypeClasses
52+ , FunctionalDependencies
53+ , RankNTypes
54+ , TypeFamilies
55+ , QuantifiedConstraints
56+ , DeriveAnyClass
57+ , ViewPatterns
58+ , TupleSections
59+ , GADTs
60+ , TypeSynonymInstances
61+ , FlexibleInstances
3862 exposed-modules:
3963 Octopod.Server
4064 Octopod.Server.Args
4165 Octopod.Server.ControlScriptUtils
42− Octopod.Server.Logger
66+ Octopod.Server.Logging
4367 Octopod.Server.Posix
4468 Orphans
45− TLS
4669 Types
70+ Control.Octopod.DeploymentLock
71+ Octopod.PowerAPI.Auth.Server
72+ Octopod.Schema
73+ Control.CacheMap
4774 hs-source-dirs:
4875 src
4976 build-depends:
@@ -51,19 +78,12 @@ library
5178 , async
5279 , base >=4.7 && <5
5380 , bytestring
54− , chronos
81+ , cassava
5582 , conduit
56− , connection
57− , data-default-class
58− , deriving-aeson
59− , directory
6083 , octopod-common
61− , fast-logger
62− , filepath
84+ , katip
6385 , generic-lens
6486 , http-api-data
65− , http-client
66− , http-client-tls
6787 , lens
6888 , mtl
6989 , network-uri
@@ -71,119 +91,53 @@ library
7191 , optparse-applicative
7292 , optparse-generic
7393 , postgresql-error-codes
74− , postgresql-simple
7594 , resource-pool
7695 , servant
77− , servant-client
78− , servant-client-core
7996 , servant-server
8097 , servant-websockets
8198 , stm
82− , temporary
8399 , text
84− , tls
85100 , transformers
86101 , transformers-base
87102 , typed-process
88103 , unix
89104 , warp
90− , warp-tls
91− , x509
92− , x509-store
93− , x509-validation
105+ , containers
106+ , monad-control
107+ , lifted-base
108+ , containers
109+ , servant-auth-server
110+ , wai
111+ , jose
112+ , rel8
113+ , time
114+ , hasql
115+ , hasql-transaction
116+ , unordered-containers
117+ , vector
118+ , process
94119 default-language: Haskell2010
95120
96121executable octopod-exe
97122 main-is: Main.hs
98− ghc-options: -Wall
99− -Werror
123+ ghc-options:
124+ -Weverything
125+ -Wno-implicit-prelude
126+ -Wno-missing-safe-haskell-mode
127+ -Wno-safe
128+ -Wno-prepositive-qualified-module
129+ -Wno-missing-import-lists
130+ -Wno-all-missed-specialisations
131+ -Wno-missing-local-signatures
132+ -Wno-partial-fields
133+ -Wno-unsafe
134+ -Wno-monomorphism-restriction
135+ -Wno-missed-specialisations
100136 hs-source-dirs: app
101137 ghc-options: -threaded -rtsopts -with-rtsopts=-N
102138 build-depends:
103− aeson
104− , async
105− , base >=4.7 && <5
106− , bytestring
107− , chronos
108− , conduit
109− , connection
110− , data-default-class
111− , directory
139+ base >=4.7 && <5
112140 , octopod-backend
113− , fast-logger
114− , http-client
115− , http-client-tls
116− , mtl
117− , network-uri
118− , optparse-applicative
119− , optparse-generic
120− , postgresql-error-codes
121− , postgresql-simple
122− , resource-pool
123− , servant
124− , servant-client
125− , servant-client-core
126− , servant-server
127− , servant-websockets
128− , stm
129− , temporary
141+ , gitrev
130142 , text
131− , tls
132− , transformers
133− , transformers-base
134− , typed-process
135− , unix
136− , warp
137− , warp-tls
138− , x509
139− , x509-store
140− , x509-validation
141− default-language: Haskell2010
142−
143−test-suite octopod-test
144− type: exitcode-stdio-1.0
145− main-is: Spec.hs
146− hs-source-dirs:
147− test
148− ghc-options: -threaded -rtsopts -with-rtsopts=-N
149− build-depends:
150− aeson
151− , async
152− , base >=4.7 && <5
153− , bytestring
154− , chronos
155− , conduit
156− , connection
157− , data-default-class
158− , directory
159− , octopod-backend
160− , fast-logger
161− , filepath
162− , http-client
163− , http-client-tls
164− , mtl
165− , network-uri
166− , optparse-applicative
167− , optparse-generic
168− , postgresql-error-codes
169− , postgresql-simple
170− , resource-pool
171− , servant
172− , servant-client
173− , servant-client-core
174− , servant-server
175− , servant-websockets
176− , stm
177− , temporary
178− , text
179− , tls
180− , transformers
181− , transformers-base
182− , typed-process
183− , unix
184− , warp
185− , warp-tls
186− , x509
187− , x509-store
188− , x509-validation
189143 default-language: Haskell2010
octopod-backend/src/Control/CacheMap.hsnew file+89
@@ -0,0 +1,89 @@
1+module Control.CacheMap
2+ ( CacheMap,
3+ initCacheMap,
4+ lookupBlocking,
5+ )
6+where
7+
8+import Control.Arrow
9+import Control.Concurrent.Lifted
10+import Control.Monad
11+import Control.Monad.Base
12+import Control.Monad.Except
13+import Control.Monad.Trans.Control
14+import Data.Fixed
15+import Data.Foldable
16+import Data.IORef.Lifted
17+import Data.Map.Strict (Map)
18+import qualified Data.Map.Strict as M
19+import Data.Time
20+import System.Mem.Weak
21+
22+data CacheMap e c k v = CacheMap !(InternalCacheMap e k v) (forall m. c m => k -> m v) !NominalDiffTime
23+
24+type InternalCacheMap e k v = IORef (Map k (UTCTime, MVar (Either e v)))
25+
26+initCacheMap ::
27+ forall c e k v m.
28+ MonadBase IO m =>
29+ -- | Time after which a value is considered "invalid" (removed from cache). Not exact.
30+ NominalDiffTime ->
31+ -- | Time after which the value should be updated: upon query the old value would be returned, but
32+ -- a background computation for the new value would be started.
33+ NominalDiffTime ->
34+ (forall n. c n => k -> n v) ->
35+ m (CacheMap e c k v)
36+initCacheMap invalid update createValue = do
37+ ref <- newIORef M.empty
38+ wRef <- liftBase $ mkWeak ref ref Nothing
39+ void $ liftBase $ fork $ removeInvalidCaches invalid wRef
40+ pure $ CacheMap ref createValue update
41+
42+removeInvalidCaches ::
43+ -- | Time after which a value is considered invalid. Not exact.
44+ NominalDiffTime ->
45+ Weak (InternalCacheMap e k v) ->
46+ IO ()
47+removeInvalidCaches invalid wRef = do
48+ threadDelayMicro (realToFrac $ invalid / 10)
49+ cutoff <- addUTCTime (negate invalid) <$> getCurrentTime
50+ deRefWeak wRef >>= \case
51+ Nothing -> pure ()
52+ Just ref -> do
53+ atomicModifyIORef' ref (M.filter (\(t, _) -> t > cutoff) &&& const ())
54+ removeInvalidCaches invalid wRef
55+ where
56+ threadDelayMicro :: Micro -> IO ()
57+ threadDelayMicro (MkFixed i) = threadDelay (fromInteger i)
58+
59+lookupBlocking ::
60+ (MonadBaseControl IO m, MonadError e m, c m, Ord k) =>
61+ CacheMap e c k v ->
62+ k ->
63+ m v
64+lookupBlocking (CacheMap ref createValue update) k = do
65+ now <- liftBase getCurrentTime
66+ blank <- newEmptyMVar
67+ -- Return the var with an error or result and a bool indicating whether it needs to be updated
68+ -- If there's no var or if needs to be updated, the update goes into 'blank'
69+ mVar <- atomicModifyIORef' ref $ \m -> case M.lookup k m of
70+ Nothing -> (M.insert k (now, blank) m, Nothing)
71+ Just (timeCreated, var) ->
72+ if timeCreated < addUTCTime (negate update) now
73+ then (M.insert k (now, blank) m, Just (var, True))
74+ else (m, Just (var, False))
75+ -- Return the var from where the *current* result should be read,
76+ -- and optionally the var where the recomputation should write to
77+ (rVar, mwVar) <- case mVar of
78+ Nothing -> pure (blank, Just blank)
79+ Just (var, recompute) ->
80+ takeMVar var >>= \case
81+ Left _ -> pure $ if recompute then (blank, Just blank) else (var, Just var)
82+ res@(Right _) -> do
83+ putMVar var res
84+ pure $ (var, if recompute then Just blank else Nothing)
85+ for_ mwVar $ \wVar -> do
86+ fork $ do
87+ v <- (Right <$> createValue k) `catchError` (pure . Left)
88+ putMVar wVar v
89+ readMVar rVar >>= liftEither
octopod-backend/src/Control/Octopod/DeploymentLock.hsnew file+50
@@ -0,0 +1,50 @@
1+module Control.Octopod.DeploymentLock
2+ ( LockedDeployments,
3+ initLockedDeployments,
4+ withLockedDeployment,
5+ isDeploymentLocked,
6+ )
7+where
8+
9+import Common.Types
10+import Control.Arrow
11+import Control.Exception.Lifted
12+import Control.Monad.Base
13+import Control.Monad.Reader
14+import Control.Monad.Trans.Control
15+import Data.Generics.Product.Typed
16+import Data.IORef.Lifted
17+import Data.Set (Set)
18+import qualified Data.Set as S
19+
20+newtype LockedDeployments = LockedDeployments (IORef (Set DeploymentName))
21+
22+initLockedDeployments :: MonadBase IO m => m LockedDeployments
23+initLockedDeployments = LockedDeployments <$> newIORef S.empty
24+
25+withLockedDeployment ::
26+ ( MonadReader r m
27+ , HasType LockedDeployments r
28+ , MonadBaseControl IO m
29+ ) =>
30+ DeploymentName ->
31+ -- | The conflict handler. Gets called if the deployment is
32+ -- already being processed.
33+ m a ->
34+ -- | The actions to be performed when the deployment is locked.
35+ m a ->
36+ m a
37+withLockedDeployment dName conflict act = do
38+ LockedDeployments ref <- asks getTyped
39+ bracket
40+ (atomicModifyIORef' ref (S.insert dName &&& S.notMember dName))
41+ (\ok -> when ok $ atomicModifyIORef' ref (S.delete dName &&& const ()))
42+ (\ok -> if ok then act else conflict)
43+
44+isDeploymentLocked ::
45+ (MonadReader r m, HasType LockedDeployments r, MonadBase IO m) =>
46+ DeploymentName ->
47+ m Bool
48+isDeploymentLocked dName = do
49+ LockedDeployments ref <- asks getTyped
50+ S.member dName <$> readIORef ref
octopod-backend/src/Octopod/PowerAPI/Auth/Server.hsnew file+23
@@ -0,0 +1,23 @@
1+{-# OPTIONS_GHC -Wno-orphans #-}
2+
3+module Octopod.PowerAPI.Auth.Server
4+ ( AuthHeader (..),
5+ )
6+where
7+
8+import Data.ByteString (ByteString)
9+import Network.Wai
10+import Octopod.PowerAPI
11+import Servant.Auth.Server
12+import Servant.Auth.Server.Internal.Class
13+
14+newtype AuthHeader = AuthHeader ByteString
15+
16+instance IsAuth AuthHeaderAuth () where
17+ type AuthArgs AuthHeaderAuth = '[AuthHeader]
18+ runAuth _ _ (AuthHeader h) = AuthCheck $ \req ->
19+ pure $ case lookup "Authorization" $ requestHeaders req of
20+ Just v | v == h -> Authenticated ()
21+ _ -> Indefinite
22+
23+deriving anyclass instance ToJWT ()
octopod-backend/src/Octopod/Schema.hsnew file+97
@@ -0,0 +1,97 @@
1+module Octopod.Schema
2+ ( DeploymentSchema (..),
3+ deploymentSchema,
4+ extractDeployment,
5+ DeploymentLogSchema (..),
6+ deploymentLogSchema,
7+ extractDeploymentLog,
8+ )
9+where
10+
11+import Data.Generics.Product
12+import Data.Int
13+import Data.Time
14+import GHC.Generics (Generic)
15+import Orphans ()
16+import Rel8
17+import Types
18+
19+deploymentSchema :: TableSchema (DeploymentSchema Name)
20+deploymentSchema =
21+ TableSchema
22+ { name = "deployments"
23+ , schema = Nothing
24+ , columns =
25+ DeploymentSchema
26+ { id_ = "id"
27+ , name = "name"
28+ , appOverrides = "app_overrides"
29+ , deploymentOverrides = "deployment_overrides"
30+ , createdAt = "created_at"
31+ , updatedAt = "updated_at"
32+ , archivedAt = "archived_at"
33+ , status = "status"
34+ , statusUpdatedAt = "status_updated_at"
35+ , checkedAt = "checked_at"
36+ , metadata = "links"
37+ }
38+ }
39+
40+data DeploymentSchema f = DeploymentSchema
41+ { id_ :: Column f DeploymentId
42+ , name :: Column f DeploymentName
43+ , appOverrides :: Column f (Overrides 'ApplicationLevel)
44+ , deploymentOverrides :: Column f (Overrides 'DeploymentLevel)
45+ , createdAt :: Column f UTCTime
46+ , updatedAt :: Column f UTCTime
47+ , archivedAt :: Column f (Maybe UTCTime)
48+ , status :: Column f DeploymentStatus
49+ , statusUpdatedAt :: Column f UTCTime
50+ , checkedAt :: Column f UTCTime
51+ , metadata :: Column f DeploymentMetadata
52+ }
53+ deriving stock (Generic)
54+ deriving anyclass (Rel8able)
55+
56+extractDeployment :: DeploymentSchema Result -> Deployment
57+extractDeployment = upcast
58+
59+data DeploymentLogSchema f = DeploymentLogSchema
60+ { actionId :: Column f ActionId
61+ , deploymentId :: Column f DeploymentId
62+ , action :: Column f Action
63+ , exitCode :: Column f Int64
64+ , createdAt :: Column f UTCTime
65+ , archived :: Column f Bool
66+ , duration :: Column f Duration
67+ , stdout :: Column f Stdout
68+ , stderr :: Column f Stderr
69+ , deploymentAppOverrides :: Column f (Overrides 'ApplicationLevel)
70+ , deploymentDepOverrides :: Column f (Overrides 'DeploymentLevel)
71+ }
72+ deriving stock (Generic)
73+ deriving anyclass (Rel8able)
74+
75+deploymentLogSchema :: TableSchema (DeploymentLogSchema Name)
76+deploymentLogSchema =
77+ TableSchema
78+ { name = "deployment_logs"
79+ , schema = Nothing
80+ , columns =
81+ DeploymentLogSchema
82+ { actionId = "id"
83+ , deploymentId = "deployment_id"
84+ , action = "action"
85+ , exitCode = "exit_code"
86+ , createdAt = "created_at"
87+ , archived = "archived"
88+ , duration = "duration"
89+ , stdout = "stdout"
90+ , stderr = "stderr"
91+ , deploymentAppOverrides = "app_overrides"
92+ , deploymentDepOverrides = "deployment_overrides"
93+ }
94+ }
95+
96+extractDeploymentLog :: DeploymentLogSchema Result -> DeploymentLog
97+extractDeploymentLog = upcast
octopod-backend/src/Octopod/Server.hs+1120−1024

This diff is too big to show here.

octopod-backend/src/Octopod/Server/Args.hs+48−59

This diff is too big to show here.

octopod-backend/src/Octopod/Server/ControlScriptUtils.hs+256−22

This diff is too big to show here.

octopod-backend/src/Octopod/Server/Logger.hsdeleted−34

This diff is too big to show here.

octopod-backend/src/Octopod/Server/Logging.hsnew file+121

This diff is too big to show here.

octopod-backend/src/Octopod/Server/Posix.hs+22−17

This diff is too big to show here.

octopod-backend/src/Orphans.hs+41−10

This diff is too big to show here.

octopod-backend/src/TLS.hsdeleted−68

This diff is too big to show here.

octopod-backend/src/Types.hs+50−63

This diff is too big to show here.

octopod-backend/test/Spec.hsdeleted−2

This diff is too big to show here.

octopod-common/Setup.hs+2−1

This diff is too big to show here.

octopod-common/octopod-common.cabal+42−3

This diff is too big to show here.

octopod-common/src/Common/Orphans.hsnew file+20

This diff is too big to show here.

octopod-common/src/Common/Types.hs+336−210

This diff is too big to show here.

octopod-common/src/Common/Utils.hs+27−18

This diff is too big to show here.

octopod-common/src/Common/Validation.hs+16−16

This diff is too big to show here.

octopod-common/src/Control/Searchable.hsnew file+66

This diff is too big to show here.

octopod-common/src/Data/ConfigTree.hsnew file+165

This diff is too big to show here.

octopod-css/default.nixnew file+45

This diff is too big to show here.

octopod-css/development/layouts/index.html+321−174

This diff is too big to show here.

octopod-css/development/layouts/staging.html+687−168

This diff is too big to show here.

octopod-css/development/markups/_action.html+2−1

This diff is too big to show here.

octopod-css/development/markups/_bar.html+2−1

This diff is too big to show here.

octopod-css/development/markups/_break.html+2−1

This diff is too big to show here.

octopod-css/development/markups/_button.html+2−1

This diff is too big to show here.

octopod-css/development/markups/_collapse.htmlnew file+277

This diff is too big to show here.

octopod-css/development/markups/_dash.html+3−2

This diff is too big to show here.

octopod-css/development/markups/_drop.html+2−1

This diff is too big to show here.

octopod-css/development/markups/_expander.html+2−1

This diff is too big to show here.

octopod-css/development/markups/_external.html+2−1

This diff is too big to show here.

octopod-css/development/markups/_input.html+36−1

This diff is too big to show here.

octopod-css/development/markups/_keys-and-values.htmlnew file+373

This diff is too big to show here.

octopod-css/development/markups/_listing.html+2−1

This diff is too big to show here.

octopod-css/development/markups/_loading.html+2−1

This diff is too big to show here.

octopod-css/development/markups/_notification.html+2−1

This diff is too big to show here.

octopod-css/development/markups/_null.html+2−1

This diff is too big to show here.

octopod-css/development/markups/_spot.html+2−1

This diff is too big to show here.

octopod-css/development/markups/_status.html+2−1

This diff is too big to show here.

octopod-css/development/markups/_title.html+2−1

This diff is too big to show here.

octopod-css/development/scripts/_collapse.jsnew file+18

This diff is too big to show here.

octopod-css/development/styles/_button.css+35

This diff is too big to show here.

octopod-css/development/styles/_collapse.cssnew file+95

This diff is too big to show here.

octopod-css/development/styles/_deployment.css+4

This diff is too big to show here.

octopod-css/development/styles/_editable-row.cssnew file+49

This diff is too big to show here.

octopod-css/development/styles/_has-changes.cssnew file+3

This diff is too big to show here.

octopod-css/development/styles/_input.css+80−2

This diff is too big to show here.

octopod-css/development/styles/_key-custom-edited.cssnew file+4

This diff is too big to show here.

octopod-css/development/styles/_key-default-edited.cssnew file+5

This diff is too big to show here.

octopod-css/development/styles/_key-default-pristine.cssnew file+4

This diff is too big to show here.

octopod-css/development/styles/_key-deleted.cssnew file+6

This diff is too big to show here.

octopod-css/development/styles/_listing.css+73−1

This diff is too big to show here.

octopod-css/development/styles/_overrides.css+7−20

This diff is too big to show here.

octopod-css/development/styles/_padded.cssnew file+3

This diff is too big to show here.

octopod-css/development/styles/_root.css+2

This diff is too big to show here.

octopod-css/development/styles/_row.cssnew file+3

This diff is too big to show here.

octopod-css/development/styles/_spot.css+11

This diff is too big to show here.

octopod-css/development/styles/_table.css+21−26

This diff is too big to show here.

octopod-css/development/styles/_value-deleted.cssnew file+5

This diff is too big to show here.

octopod-css/development/styles/_value-edited.cssnew file+4

This diff is too big to show here.

octopod-css/development/styles/_value-pristine.cssnew file+3

This diff is too big to show here.

octopod-css/development/styles/_value-unknown.cssnew file+12

This diff is too big to show here.

octopod-css/development/styles/style.css+15

This diff is too big to show here.

octopod-css/development/vectors/button-loader.svgnew file+5

This diff is too big to show here.

octopod-css/development/vectors/collapse-project.svgnew file+3

This diff is too big to show here.

octopod-css/development/vectors/spot-loader.svgnew file+3

This diff is too big to show here.

octopod-css/development/vectors/spot-undo.svgnew file+3

This diff is too big to show here.

octopod-css/favicons/android-icon-144x144.png

Binary file not shown.

octopod-css/favicons/android-icon-192x192.png

Binary file not shown.

octopod-css/favicons/android-icon-36x36.png

Binary file not shown.

octopod-css/favicons/android-icon-48x48.png

Binary file not shown.

octopod-css/favicons/android-icon-72x72.png

Binary file not shown.

octopod-css/favicons/android-icon-96x96.png

Binary file not shown.

octopod-css/favicons/apple-icon-114x114.png

Binary file not shown.

octopod-css/favicons/apple-icon-120x120.png

Binary file not shown.

octopod-css/favicons/apple-icon-144x144.png

Binary file not shown.

octopod-css/favicons/apple-icon-152x152.png

Binary file not shown.

octopod-css/favicons/apple-icon-180x180.png

Binary file not shown.

octopod-css/favicons/apple-icon-57x57.png

Binary file not shown.

octopod-css/favicons/apple-icon-60x60.png

Binary file not shown.

octopod-css/favicons/apple-icon-72x72.png

Binary file not shown.

octopod-css/favicons/apple-icon-76x76.png

Binary file not shown.

octopod-css/favicons/apple-icon-precomposed.png

Binary file not shown.

octopod-css/favicons/apple-icon.png

Binary file not shown.

octopod-css/favicons/favicon-16x16.png

Binary file not shown.

octopod-css/favicons/favicon-32x32.png

Binary file not shown.

octopod-css/favicons/favicon-96x96.png

Binary file not shown.

octopod-css/favicons/favicon.ico

Binary file not shown.

octopod-css/favicons/ms-icon-144x144.png

Binary file not shown.

octopod-css/favicons/ms-icon-150x150.png

Binary file not shown.

octopod-css/favicons/ms-icon-310x310.png

Binary file not shown.

octopod-css/favicons/ms-icon-70x70.png

Binary file not shown.

octopod-css/package-lock.jsondeleted−6159

This diff is too big to show here.

octopod-css/package.json+3−2

This diff is too big to show here.

octopod-css/production/images/dialog-delete.pngdeleted

Binary file not shown.

octopod-css/production/images/dialog-delete@2x.pngdeleted

Binary file not shown.

octopod-css/production/images/null-data.pngdeleted

Binary file not shown.

octopod-css/production/images/null-data@2x.pngdeleted

Binary file not shown.

octopod-css/production/images/null-search.pngdeleted

Binary file not shown.

octopod-css/production/images/null-search@2x.pngdeleted

Binary file not shown.

octopod-css/production/layouts/index.htmldeleted−888

This diff is too big to show here.

octopod-css/production/layouts/staging.htmldeleted−713

This diff is too big to show here.

octopod-css/production/layouts/standalone-loading.htmldeleted−46

This diff is too big to show here.

octopod-css/production/markups/_action.htmldeleted−112

This diff is too big to show here.

octopod-css/production/markups/_bar.htmldeleted−61

This diff is too big to show here.

octopod-css/production/markups/_break.htmldeleted−85

This diff is too big to show here.

octopod-css/production/markups/_button.htmldeleted−137

This diff is too big to show here.

octopod-css/production/markups/_dash.htmldeleted−130

This diff is too big to show here.

octopod-css/production/markups/_drop.htmldeleted−112

This diff is too big to show here.

octopod-css/production/markups/_expander.htmldeleted−96

This diff is too big to show here.

octopod-css/production/markups/_external.htmldeleted−61

This diff is too big to show here.

octopod-css/production/markups/_input.htmldeleted−111

This diff is too big to show here.

octopod-css/production/markups/_listing.htmldeleted−100

This diff is too big to show here.

octopod-css/production/markups/_loading.htmldeleted−136

This diff is too big to show here.

octopod-css/production/markups/_notification.htmldeleted−88

This diff is too big to show here.

octopod-css/production/markups/_null.htmldeleted−81

This diff is too big to show here.

octopod-css/production/markups/_spot.htmldeleted−61

This diff is too big to show here.

octopod-css/production/markups/_status.htmldeleted−83

This diff is too big to show here.

octopod-css/production/markups/_title.htmldeleted−60

This diff is too big to show here.

octopod-css/production/scripts/_classic-popup.jsdeleted−92

This diff is too big to show here.

octopod-css/production/scripts/_data.jsdeleted−7

This diff is too big to show here.

octopod-css/production/scripts/_drop.jsdeleted−26

This diff is too big to show here.

octopod-css/production/scripts/_expander.jsdeleted−8

This diff is too big to show here.

octopod-css/production/scripts/_popup.jsdeleted−35

This diff is too big to show here.

octopod-css/production/scripts/_sort.jsdeleted−16

This diff is too big to show here.

octopod-css/production/styles/style.cssdeleted−1

This diff is too big to show here.

octopod-css/production/vendors/jquery/jquery-3.2.1.min.jsdeleted−4

This diff is too big to show here.

octopod-css/production/vendors/outline/index.htmldeleted−67

This diff is too big to show here.

octopod-css/production/vendors/outline/outline.jsdeleted−37

This diff is too big to show here.

octopod-css/yarn.locknew file+4594

This diff is too big to show here.

octopod-frontend/Setup.hs+2−1

This diff is too big to show here.

octopod-frontend/index.htmlnew file+13

This diff is too big to show here.

octopod-frontend/octopod-frontend.cabal+57−8

This diff is too big to show here.

octopod-frontend/src/Data/Text/Search.hsnew file+147

This diff is too big to show here.

octopod-frontend/src/Data/UniqMap.hsnew file+55

This diff is too big to show here.

octopod-frontend/src/Data/WorkingOverrides.hsnew file+138

This diff is too big to show here.

octopod-frontend/src/Frontend/API.hs+145−106

This diff is too big to show here.

octopod-frontend/src/Frontend/Classes.hsnew file+18

This diff is too big to show here.

octopod-frontend/src/Frontend/GHCJS.hs+46−36

This diff is too big to show here.

octopod-frontend/src/Frontend/Route.hs+37−37

This diff is too big to show here.

octopod-frontend/src/Frontend/UIKit.hsnew file+555

This diff is too big to show here.

octopod-frontend/src/Frontend/UIKit/Button/Action.hsnew file+63

This diff is too big to show here.

octopod-frontend/src/Frontend/UIKit/Button/Common.hsnew file+101

This diff is too big to show here.

octopod-frontend/src/Frontend/UIKit/Button/Dash.hsnew file+71

This diff is too big to show here.

octopod-frontend/src/Frontend/UIKit/Button/Expander.hsnew file+86

This diff is too big to show here.

octopod-frontend/src/Frontend/UIKit/Button/Large.hsnew file+96

This diff is too big to show here.

octopod-frontend/src/Frontend/UIKit/Button/Sort.hsnew file+58

This diff is too big to show here.

octopod-frontend/src/Frontend/UIKit/Button/Static.hsnew file+84

This diff is too big to show here.

octopod-frontend/src/Frontend/UIKit/Button/Tree.hsnew file+84

This diff is too big to show here.

octopod-frontend/src/Frontend/Utils.hs+476−424

This diff is too big to show here.

octopod-frontend/src/Main.hs+210−134

This diff is too big to show here.

octopod-frontend/src/Page/ClassicPopup.hs+64−48

This diff is too big to show here.

octopod-frontend/src/Page/Deployment.hs+267−238

This diff is too big to show here.

octopod-frontend/src/Page/Deployments.hs+419−373

This diff is too big to show here.

octopod-frontend/src/Page/Elements/Links.hs+30−18

This diff is too big to show here.

octopod-frontend/src/Page/Popup/EditDeployment.hs+95−178

This diff is too big to show here.

octopod-frontend/src/Page/Popup/NewDeployment.hs+113−140

This diff is too big to show here.

octopod-frontend/src/Reflex/Dom/AsyncEvent.hsnew file+30

This diff is too big to show here.

octopod-frontend/src/Reflex/Dom/Renderable.hsnew file+35

This diff is too big to show here.

octopod-frontend/src/Reflex/MultiEventWriter/Class.hs+11−10

This diff is too big to show here.

octopod-frontend/src/Servant/Reflex/Extra.hs+27−9

This diff is too big to show here.

octopod_local_install.shnew file+131

This diff is too big to show here.

shell.nix+11−1

This diff is too big to show here.

stack.yaml+4−8

This diff is too big to show here.