Compare commits
	
		
			513 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 2b5d907e0f | |||
| fce26a6d52 | |||
| 047c0e6d47 | |||
| fc2d770099 | |||
| 1b85bf3d37 | |||
| 2d6a08a671 | |||
| 316bcd5a68 | |||
| 1a4cf9be17 | |||
| eadb353c2e | |||
| f374b1bfa1 | |||
| 0e6b0e0879 | |||
| 3a353f4062 | |||
| e0258d397b | |||
| e8ac353453 | |||
| 552abdd980 | |||
| 935007dd86 | |||
| 2cd1d053f0 | |||
| a1c8620cc0 | |||
| 39a7fc04fb | |||
| a8b5fb5c1e | |||
| 18e22b24ea | |||
| b53a3ed3f7 | |||
| 112787b3aa | |||
| 4f46ff7ee6 | |||
| 845de093ba | |||
| 65e83ed885 | |||
| b98d69b33e | |||
| d159b98c3c | |||
| 1ef5c3980d | |||
| ffc569e275 | |||
| 0e28af9eb1 | |||
| 4aec218719 | |||
| 07a9b3bd81 | |||
| 78b9b8589e | |||
| be3fd59c8c | |||
| 6480f5e5ff | |||
| 280238d95d | |||
| 44b378abba | |||
| a6d7972bef | |||
| 625d9848a5 | |||
| 3bcb9ea13a | |||
| 72a30b9144 | |||
| f0019ea983 | |||
| d15aad7bcf | |||
| e351615a69 | |||
| 2296ef52fa | |||
| 850c4894e7 | |||
| edf443bed5 | |||
| 6cb6ee6952 | |||
| 762d12b61e | |||
| 0e6aa957a4 | |||
| 150c54da40 | |||
| 75bd599a33 | |||
| f0c80ee5b8 | |||
| 41573c3260 | |||
| 037e08a41a | |||
| f1b76d4313 | |||
| c19c4db897 | |||
| 31fdbccfad | |||
| 208b11af0a | |||
| 5649730446 | |||
| 90eda1dfc1 | |||
| fd97d41524 | |||
| abbe6ddd1a | |||
| acdfa20b2b | |||
| 34dc33a01d | |||
| 4747d9b7fb | |||
| 35f553ae5a | |||
| 8f2fadb3c4 | |||
| 8e6b620e8c | |||
| 523fc2850c | |||
| 968d3809a5 | |||
| 2ccef8948d | |||
| 08de1e0676 | |||
| b2e66a01fc | |||
| 23f8cfc8dd | |||
| 878a26a411 | |||
| 656dd829ca | |||
| 10bcb68c9d | |||
| e0c9c4e5b3 | |||
| d936080393 | |||
| 809ee6e68b | |||
| e0b185b5ef | |||
| 9815230eba | |||
| 8cb556275f | |||
| 48a7bb8c2d | |||
| a26a0d27d7 | |||
| 028c7dbde5 | |||
| 103a4941c7 | |||
| a261114bbc | |||
| e2640fac08 | |||
| 33280f90b3 | |||
| 8b60ece3d4 | |||
| 47efae4e6c | |||
| 25d15c9596 | |||
| 515bd7789d | |||
| 6abb5db6ee | |||
| 699c4e76d5 | |||
| 703889d4ea | |||
| 05cf00d272 | |||
| c531faec52 | |||
| 4e9aefcafd | |||
| fb338b414b | |||
| f1bdbf21c2 | |||
| c3e3f0a1f8 | |||
| df4e5045be | |||
| 4a0889138f | |||
| f717c53e8b | |||
| 0206279894 | |||
| fbb1081ed5 | |||
| aad6f1db6e | |||
| 2599cff4cb | |||
| 25b916d969 | |||
| 37600727a4 | |||
| f4860ec662 | |||
| 20e56a755e | |||
| c60265791e | |||
| 2e159050e9 | |||
| 25090a8129 | |||
| be5383b164 | |||
| 3720ef838d | |||
| 071fcbb96b | |||
| abfb1c6404 | |||
| 0369a18c6e | |||
| 57f74b0d46 | |||
| 93142ba305 | |||
| f289f79ec3 | |||
| 6b0f8a3d45 | |||
| 6f776a8c51 | |||
| 55dc3a1d2a | |||
| 91ccc819d5 | |||
| bf0ed8fd1c | |||
| 8a54fa3f27 | |||
| 26f9e1747f | |||
| 4a3c4ce0c5 | |||
| 903b286d3f | |||
| f4ab771e2a | |||
| cd647f090b | |||
| 85670538c6 | |||
| 90780eab91 | |||
| 1fabae0f48 | |||
| 75af48bc5d | |||
| 0323fbe1c8 | |||
| dbb61b9a46 | |||
| 3a40d27778 | |||
| 1d1329b77e | |||
| d9374dc48e | |||
| a760ef7869 | |||
| 3b9d6a7eb2 | |||
| 663ba19c8b | |||
| 70b2a68f34 | |||
| 2b0f691d5f | |||
| 18f8ea982e | |||
| d6cec2ff1a | |||
| 29e0077edb | |||
| 73c1290c52 | |||
| 26e839ea7b | |||
| e881f8007e | |||
| 6f3f4b6779 | |||
| a5274f123c | |||
| fc12634fbb | |||
| a5ce75a29b | |||
| 701784930b | |||
| aa717c2323 | |||
| 9836d27052 | |||
| e361b493b1 | |||
| b28460cf84 | |||
| 07e3678c78 | |||
| c315ebe319 | |||
| 36dd6b5eff | |||
| 2f1f51bad1 | |||
| bada24f3f6 | |||
| 2d5afd8149 | |||
| dfb949eecc | |||
| 49771980a6 | |||
| 7e31184bd6 | |||
| 49226f1640 | |||
| 4251c32b30 | |||
| ece5385a38 | |||
| 35d5df14aa | |||
| 1c437b99eb | |||
| 9580b2dd7d | |||
| f382765f29 | |||
| f5951add54 | |||
| 2b4efc2c61 | |||
| 8ab854c822 | |||
| 005323ff3c | |||
| 390e918417 | |||
| c5ccfa0fa1 | |||
| 87b71cb9d4 | |||
| 89bd18a76b | |||
| 6e61c08b2c | |||
| 54b6acc46c | |||
| e5e98d536a | |||
| 8df91de3af | |||
| 7557966c98 | |||
| fa5d3ae3a1 | |||
| d68444be9e | |||
| f7bc8efabe | |||
| f5284ba725 | |||
| 293d3ff558 | |||
| c00319ab01 | |||
| 8b4141670c | |||
| 23c852125d | |||
| b4eae2e5e5 | |||
| 9e953319cf | |||
| 0814fa9146 | |||
| 0e1b6c858b | |||
| 28618bd3ac | |||
| b04bfea1c7 | |||
| bc0ef0d6fc | |||
| 16c91fedd1 | |||
| 9f5945094c | |||
| 76513a1f35 | |||
| 86eb8d7fde | |||
| e31b3d3173 | |||
| 58b13d7528 | |||
| b0fca49ecb | |||
| 79dacf557e | |||
| d6caf03301 | |||
| 9b90712d28 | |||
| 1dd3fe6fcd | |||
| 29953c17d9 | |||
| 3b59adfe34 | |||
| 00c8a988e1 | |||
| 524fb6a44c | |||
| e99bedf9e4 | |||
| 0d98c442a2 | |||
| bcc15ecdb0 | |||
| a617629a7a | |||
| f7ae400eb3 | |||
| 7141d364e1 | |||
| 057ce223f1 | |||
| 7511b25e47 | |||
| 62b447d61f | |||
| 88d2a75575 | |||
| 8cb6617a0f | |||
| 1a649c56cb | |||
| fd655274f8 | |||
| 946d1a068d | |||
| e8651976ca | |||
| af52ba1fec | |||
| 499c08c374 | |||
| 08281891a1 | |||
| 5bce042922 | |||
| 3276c9fe47 | |||
| 040374e781 | |||
| 621c8cd5c4 | |||
| 7434b67c34 | |||
| 17306a753b | |||
| 2e3f4cabd8 | |||
| cf2308cdd7 | |||
| eec49d6dd1 | |||
| d6195ad6d7 | |||
| fd04c5a6e9 | |||
| 1c9d7282b2 | |||
| dd9c485c66 | |||
| 99ab5bf369 | |||
| 25a0afed65 | |||
| 44e22db11b | |||
| 3321010089 | |||
| e04c4626f2 | |||
| 65ce949e03 | |||
| 5931cbd791 | |||
| 0bbff91722 | |||
| 7f5e753dfd | |||
| d3776f4424 | |||
| 544c4e86ba | |||
| 516309b478 | |||
| dfd7e29a30 | |||
| bb30fa28da | |||
| 044de5824b | |||
| 00cdce7bd2 | |||
| f163d4b0fa | |||
| e0032fb74a | |||
| 152dfe9349 | |||
| 5a95ae97a0 | |||
| 98e674b8e8 | |||
| b655cf20be | |||
| 5bc702bf96 | |||
| 4bd842db66 | |||
| a8f7faddb9 | |||
| e5b2a426f0 | |||
| 29b22fe162 | |||
| c082645da0 | |||
| 156d5d8fba | |||
| d2cdb11fcc | |||
| cef06a82a6 | |||
| 9a630a0440 | |||
| 1c6651b18b | |||
| 5f7df4694f | |||
| 7feeab24ec | |||
| 1a6688cfbf | |||
| f90e1d154c | |||
| 6cc265e931 | |||
| 854ae23f60 | |||
| 43e7672725 | |||
| 4e913c426d | |||
| 8a08de51e4 | |||
| 1c7a51bce1 | |||
| 5d84cef63c | |||
| eda5198904 | |||
| a4a3dccd66 | |||
| a2d249e3a1 | |||
| dc83baea12 | |||
| d6b4a4744f | |||
| 6ba2657dc1 | |||
| ac6b805cbf | |||
| d4e52a9de3 | |||
| aa59c1ad43 | |||
| 36f1d679ae | |||
| f5c8ee1136 | |||
| 9a17817cc8 | |||
| b2e3292453 | |||
| 13fafb5929 | |||
| 114f99ae2e | |||
| fff4b10a41 | |||
| ab1353603d | |||
| 1600b6277f | |||
| b79e35f982 | |||
| 703dbe0a0f | |||
| 7abb0191e1 | |||
| 886ae5b7f2 | |||
| 5411c85793 | |||
| caa315e361 | |||
| e6b24fe65c | |||
| 81782bb5f0 | |||
| 406b9e374e | |||
| ce0e0e893c | |||
| fac45f276e | |||
| 44d3ac3a1c | |||
| 5da9f26076 | |||
| 4e99cf1ded | |||
| 55324524ca | |||
| b6928959cb | |||
| 8ddb290683 | |||
| 2cb1134a54 | |||
| c4b1ac482e | |||
| 29cc392dff | |||
| 8839bd4595 | |||
| 0179f600f5 | |||
| 15f0233351 | |||
| bbaacb7b9f | |||
| 6761574d74 | |||
| 8384af8b95 | |||
| b9e97688d6 | |||
| 1055805c8d | |||
| 678906cb39 | |||
| 11c50ae98d | |||
| e911ab246b | |||
| 34775f306b | |||
| 375a4dd29d | |||
| 2b951e9f54 | |||
| 01184c313a | |||
| 3936d6afc0 | |||
| 407744827f | |||
| b634b4c668 | |||
| 67cce192df | |||
| 3a9e141b24 | |||
| ebfe7ca4e8 | |||
| fff2fbe819 | |||
| f213c3df5f | |||
| 9b1be33018 | |||
| 6ecf4f287a | |||
| e1d6ff8b73 | |||
| 07d4815a74 | |||
| 33315f6b43 | |||
| f017324431 | |||
| 4339c91cf3 | |||
| 592f515ec4 | |||
| 77ba5652b2 | |||
| fdf6334ed3 | |||
| 73e5e64b9a | |||
| 3f9b4477cd | |||
| 412729aac9 | |||
| 8022a2cb41 | |||
| 35182ed260 | |||
| d90c6ef361 | |||
| 40ca8dfe93 | |||
| 7f009f927b | |||
| e222f4152b | |||
| 893150cdd9 | |||
| 61126f16e1 | |||
| 63c982c550 | |||
| 0d202eedfc | |||
| cb2d563ea0 | |||
| 059968a8cf | |||
| c57069e0af | |||
| 946a527baa | |||
| 89d530a553 | |||
| 25fe6808ad | |||
| 28b2d8ecc7 | |||
| fd735a1310 | |||
| e307286db7 | |||
| dd570e224b | |||
| f495ec0d94 | |||
| b75bce531b | |||
| 0d62f01d5a | |||
| eec55896a4 | |||
| c2a56c6c09 | |||
| 74dfd75fb1 | |||
| e8c0efa91e | |||
| 6bae48431c | |||
| 543072ab37 | |||
| 57e3a34133 | |||
| 33a49a8457 | |||
| 5806e40c1c | |||
| 0d24a8e5cc | |||
| e01f06423e | |||
| 80f06ba0e1 | |||
| f8306b282d | |||
| 2bdfe8baa8 | |||
| b226396764 | |||
| a3cd6d2281 | |||
| 50651aeea1 | |||
| 57e24eaf0a | |||
| 50ca4f8029 | |||
| 0433da3689 | |||
| 3e0b9e9475 | |||
| c6b841de6c | |||
| 2daffc8694 | |||
| b15a214049 | |||
| 8d7194fcce | |||
| 188dc56dd1 | |||
| dbfe6f8097 | |||
| 26b994ab84 | |||
| dba3c391bd | |||
| 5a72ed0cfb | |||
| b5d84d5e0d | |||
| e3983c2440 | |||
| 85b8a4f459 | |||
| 6e38dc35e5 | |||
| 841e4fc61a | |||
| c1d12eacc5 | |||
| 3b730d314b | |||
| 5df3a9fffb | |||
| 3e3fe0e349 | |||
| db766f4aec | |||
| 8909a46d8c | |||
| 8d139d4d28 | |||
| b6b80298c2 | |||
| b1e8ac4498 | |||
| c5785089d6 | |||
| bec3272a41 | |||
| dc3b772b72 | |||
| 07d4f8cbdf | |||
| 37c59a53ef | |||
| 87a54594f6 | |||
| e2e76edaaf | |||
| ab7772e8f7 | |||
| 7304612f5f | |||
| 5a07f08ab3 | |||
| 1e158cce55 | |||
| 2102193df1 | |||
| 1b4258f1ea | |||
| cc060b8546 | |||
| dce46603bf | |||
| 64d04a29ab | |||
| db7eb30447 | |||
| f648b251bf | |||
| 86a790bbe4 | |||
| b423d61fce | |||
| f03c509552 | |||
| e6458e5e60 | |||
| 9580199616 | |||
| b59e902d18 | |||
| c50b1d8760 | |||
| b49b510c43 | |||
| b68bfdfb43 | |||
| 983e4af08c | |||
| 6cf7cf843a | |||
| d37d8a0c66 | |||
| da33064a5f | |||
| be2fffd858 | |||
| 38f0c92bc7 | |||
| c1fbb75657 | |||
| 33fd0eeb8d | |||
| 5955505752 | |||
| e022fe2310 | |||
| 02fa9025dc | |||
| 2250713c05 | |||
| 2b77cfebf9 | |||
| aff01e6741 | |||
| 0eb5d14ad8 | |||
| 6d6208a63c | |||
| 1e059ffe7f | |||
| eb12f2392c | |||
| a13e58c6c0 | |||
| 44c41830a7 | |||
| ae6c2c26ae | |||
| dad72c820a | |||
| eec9a8ba1a | |||
| bf44270b3d | |||
| 4bf1dbd7eb | |||
| 4ca1026c2c | |||
| 891b2cc6c9 | |||
| 4de7f24d8e | |||
| ad1063a0cc | |||
| 4cfe143326 | |||
| 16cc5d9cf7 | |||
| 9d22797dc8 | |||
| 16a09887e6 | |||
| b7757b51b1 | |||
| 3c7c7694bf | |||
| f15dfd9f5f | |||
| 66dcaedfd0 | |||
| 6598aabc37 | |||
| 6759e6a175 | |||
| 8735362580 | |||
| 7223dca951 | |||
| dd9444b036 | |||
| 81e24b6f72 | |||
| 16292df5f6 | 
							
								
								
									
										44
									
								
								.drone.yml
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								.drone.yml
									
									
									
									
									
								
							| @ -3,11 +3,47 @@ kind: pipeline | |||||||
| name: linters | name: linters | ||||||
| steps: | steps: | ||||||
|   - name: run shellcheck |   - name: run shellcheck | ||||||
|     image: debian:buster |     image: koalaman/shellcheck-alpine:v0.7.1 | ||||||
|     commands: |     commands: | ||||||
|       - apt update |       - shellcheck abra | ||||||
|       - apt install -y shellcheck |       - shellcheck bin/*.sh | ||||||
|       - shellcheck abra script.d/* |  | ||||||
|  |   - name: run flake8 | ||||||
|  |     image: alpine/flake8:3.9.0 | ||||||
|  |     commands: | ||||||
|  |       - flake8 --max-line-length 100 bin/app-json.py | ||||||
|  |  | ||||||
|  |   - name: run unit tests | ||||||
|  |     image: decentral1se/docker-dind-bats-kcov | ||||||
|  |     commands: | ||||||
|  |       - bats tests | ||||||
|  |  | ||||||
|  |   - name: collect code coverage | ||||||
|  |     failure: ignore # until we fix this | ||||||
|  |     image: decentral1se/docker-dind-bats-kcov | ||||||
|  |     commands: | ||||||
|  |       - kcov . bats tests || true | ||||||
|  |  | ||||||
|  |   - name: send code coverage report to codecov | ||||||
|  |     failure: ignore # until we fix this | ||||||
|  |     image: plugins/codecov | ||||||
|  |     settings: | ||||||
|  |       token: | ||||||
|  |         from_secret: codecov_token | ||||||
|  |         required: true | ||||||
|  |  | ||||||
|  |   - name: notify rocket chat | ||||||
|  |     image: plugins/slack | ||||||
|  |     settings: | ||||||
|  |       webhook: | ||||||
|  |         from_secret: rc_builds_url | ||||||
|  |       username: comradebritney | ||||||
|  |       channel: "internal.builds" | ||||||
|  |       template: "{{repo.owner}}/{{repo.name}} build failed: {{build.link}}" | ||||||
|  |     when: | ||||||
|  |       status: | ||||||
|  |         - failure | ||||||
|  |  | ||||||
| trigger: | trigger: | ||||||
|   branch: |   branch: | ||||||
|     - main |     - main | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | |||||||
|  | /.venv | ||||||
|  | coverage/ | ||||||
							
								
								
									
										124
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										124
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @ -1,6 +1,128 @@ | |||||||
|  | > 🔥 🔥 🔥 Please note, while we are still in | ||||||
|  | > [public alpha](https://docs.cloud.autonomic.zone/roadmap/), the `abra` release | ||||||
|  | > versioning scheme is not following [semver](https://semver.org/) conventions | ||||||
|  | > because we are still in the exploratory phases of building this tool. Please | ||||||
|  | > read the changes before upgrading your `abra` installation as there are | ||||||
|  | > **most likely** breaking changes coming each release. Sorry for any | ||||||
|  | > inconvenience caused, we're working hard to make this tool stable. Semver | ||||||
|  | > will be respected when we reach public beta. 🔥 🔥 🔥 | ||||||
|  |  | ||||||
|  | # abra x.x.x (UNRELEASED) | ||||||
|  |  | ||||||
|  | - Fix secret length generation ([f537417](https://git.autonomic.zone/coop-cloud/abra/commit/1b85bf3d37280e9632c315d759c0f2d09c039fef)) | ||||||
|  | - Add `app .. volume` commands, fix volume deletion with `app .. delete --volumes` ([#161](https://git.autonomic.zone/coop-cloud/abra/issues/161)) | ||||||
|  |  | ||||||
|  | # abra 0.7.4 (2021-05-10) | ||||||
|  |  | ||||||
|  | - Sort `apps.json` when publishing ([39a7fc0](https://git.autonomic.zone/coop-cloud/abra/commit/39a7fc04fb5df1a6d78b84f51838530ab3eb76db)) | ||||||
|  | - Fix publishing of rating for new apps ([0e28af9](https://git.autonomic.zone/coop-cloud/abra/commit/0e28af9eb1af6c6da705b4614ddd173c60576629)) | ||||||
|  | - Detect compose filenames in `n+1` release generation ([ffc569e](https://git.autonomic.zone/coop-cloud/abra/commit/ffc569e275df7ca784a4db1a3331e17975fd8c87)) | ||||||
|  | - Fix secret generation when specifying length ([3a353f4](https://git.autonomic.zone/coop-cloud/abra/commit/3a353f4062baccde2c9f175b03afb2db6d462ae4)) | ||||||
|  |  | ||||||
|  | # abra 0.7.3 (2021-04-28) | ||||||
|  |  | ||||||
|  | - Only check for pw(q)gen if we're actually trying to use them ([#147](https://git.autonomic.zone/coop-cloud/abra/issues/147)) | ||||||
|  | - Use apps.coopcloud.tech for app data hosting & download ([75bd599](https://git.autonomic.zone/coop-cloud/abra/commit/75bd599)) | ||||||
|  | - Choose latest commit messages for new tags ([#144](https://git.autonomic.zone/coop-cloud/abra/issues/144)) | ||||||
|  | - Handle recipes without an `app` service in `recipe .. release` ([#151](https://git.autonomic.zone/coop-cloud/abra/issues/151)) | ||||||
|  |  | ||||||
|  | # abra 0.7.2 (2021-04-07) | ||||||
|  |  | ||||||
|  | - Fix installation script development installs (again! Thanks Bash!) ([4747d9b7](https://git.autonomic.zone/coop-cloud/abra/commit/4747d9b7fb5fba914f210b6570bfe2db0b53da23)) | ||||||
|  |  | ||||||
|  | # abra 0.7.1 (2021-04-07) | ||||||
|  |  | ||||||
|  | - Fix installation script development installs ([8f2fadb3c](https://git.autonomic.zone/coop-cloud/abra/commit/8f2fadb3c43c5915520f5ea531ea3815c2ba8531)) | ||||||
|  |  | ||||||
|  | # abra 0.7.0 (2021-04-07) | ||||||
|  |  | ||||||
|  | - Add `--force` to the `deploy` command to allow overriding deployment logic ([#105](https://git.autonomic.zone/coop-cloud/abra/issues/105)) | ||||||
|  | - Handle undeployed apps in version summaries when deploying ([#104](https://git.autonomic.zone/coop-cloud/abra/issues/104)) | ||||||
|  | - Add `--force` to `undeploy` command ([e5e98d5](https://git.autonomic.zone/coop-cloud/abra/commit/e5e98d5)) | ||||||
|  | - Rename "app type" back to "stack" in the deployment overview ([54b6acc](https://git.autonomic.zone/coop-cloud/abra/commit/54b6acc)) | ||||||
|  | - Show context connection details on `abra server ls` ([#110](https://git.autonomic.zone/coop-cloud/abra/issues/110)) | ||||||
|  | - Allow to debug the SSH connection details on swarm init ([#109](https://git.autonomic.zone/coop-cloud/abra/issues/109)) | ||||||
|  | - Show correct status for apps deployed on servers with missing context ([#99](https://git.autonomic.zone/coop-cloud/abra/issues/99)) | ||||||
|  | - Search for subcommands in descending order of how many components there are ([#108](https://git.autonomic.zone/coop-cloud/abra/issues/108)) | ||||||
|  | - Add specific app version checking command (`abra app <app> version`) ([#108](https://git.autonomic.zone/coop-cloud/abra/issues/108)) | ||||||
|  | - Add docker version check (guestimating < v19 is a bad idea) ([#15](https://git.autonomic.zone/coop-cloud/abra/issues/15)) | ||||||
|  | - Fix git branch handling when not passing `-b <branch>` ([#122](https://git.autonomic.zone/coop-cloud/abra/issues/122)) | ||||||
|  | - Add work-around to correctly git clone non-master default branch app repositories ([#122](https://git.autonomic.zone/coop-cloud/abra/issues/122)) | ||||||
|  | - Replace `--force` (except for the `deploy` command) with a global `--no-prompt` for avoiding interactive questions ([#118](https://git.autonomic.zone/coop-cloud/abra/issues/118)) | ||||||
|  | - Use [docker-stack-wait-deploy](https://github.com/vitalets/docker-stack-wait-deploy) inspired logic to deploy apps ([#116](https://git.autonomic.zone/coop-cloud/abra/issues/116)) | ||||||
|  | - Add a domain polling check when deploying apps ([#113](https://git.autonomic.zone/coop-cloud/abra/issues/113)) | ||||||
|  | - Recognise when apps are already undeployed with `abra app <app> undeploy` ([#123](https://git.autonomic.zone/coop-cloud/abra/issues/123)) | ||||||
|  | - Add `abra doctor` command to help diagnose setup issues ([#119](https://git.autonomic.zone/coop-cloud/abra/issues/119)) | ||||||
|  | - Add apps version and feature catalogue generation script ([#121](https://git.autonomic.zone/coop-cloud/abra/issues/121)) | ||||||
|  | - New `--skip-version-check` option to `deploy` ([df4e504](https://git.autonomic.zone/coop-cloud/abra/commit/df4e504)) | ||||||
|  | - Look up local available version from compose files instead of `abra.sh` ([#131](https://git.autonomic.zone/coop-cloud/abra/issues/131)) | ||||||
|  | - Improve domain polling logging and allow to skip the check altogether with `--no-domain-poll` ([#140](https://git.autonomic.zone/coop-cloud/abra/issues/140), [#141](https://git.autonomic.zone/coop-cloud/abra/issues/141)) | ||||||
|  | - Support `ABRA_DIR` in the installer script ([4e94a424e94a42](https://git.autonomic.zone/coop-cloud/abra/commit/4e94a424e94a42)) | ||||||
|  | - Support [abra-hetzner](https://git.autonomic.zone/coop-cloud/abra-hetzner) plugin ([#88](https://git.autonomic.zone/coop-cloud/abra/issues/88)) | ||||||
|  |  | ||||||
|  | # abra 0.6.0 (2021-03-17) | ||||||
|  |  | ||||||
|  | - Show version and digest of app if labelled ([98e674b8e8](https://git.autonomic.zone/coop-cloud/abra/commit/98e674b8e83458a83dcbf331e8e34c7188559c4a)) | ||||||
|  | - Implement basic version checking on deployment ([#82](https://git.autonomic.zone/coop-cloud/abra/issues/82)) | ||||||
|  | - New `app-catalogue.sh` script to auto-generate app list for documentation ([f163d4b](https://git.autonomic.zone/coop-cloud/abra/commit/f163d4b0fa920232e9d995a22d20fe78b174b3a9)) | ||||||
|  | - Support app service rollbacks with `abra <app> rollback <service>` ([#76](https://git.autonomic.zone/coop-cloud/abra/issues/76)) | ||||||
|  | - Detect when latest version is deployed and perform a no-op ([#87](https://git.autonomic.zone/coop-cloud/abra/issues/87)) | ||||||
|  | - Allow cloning of app repos with different main branches using `-b, --branch=<branch>` ([#80](https://git.autonomic.zone/coop-cloud/abra/issues/80)) | ||||||
|  | - Protect against lengthy app names which gives Docker trouble later on ([#83](https://git.autonomic.zone/coop-cloud/abra/issues/83)) | ||||||
|  | - Support removal of secrets and volumes when `rm`'ing apps ([#44](https://git.autonomic.zone/coop-cloud/abra/issues/44)) | ||||||
|  | - Always choose the default IPv4 address with `abra server <host> init` ([#91](https://git.autonomic.zone/coop-cloud/abra/issues/91)) | ||||||
|  | - Add `--type=<type>` filtering option to `abra <app> ls` ([0828189](https://git.autonomic.zone/coop-cloud/abra/commit/0828189)) | ||||||
|  | - Check for bash 4+ ([#96](https://git.autonomic.zone/coop-cloud/abra/commit/0828189)) | ||||||
|  | - Add `--dev` option to installer using `git clone` ([88d2a75](https://git.autonomic.zone/coop-cloud/abra/commit/88d2a75)) | ||||||
|  | - Support `--dev` on the `abra upgrade` command also ([bcc15ec](https://git.autonomic.zone/coop-cloud/abra/commit/bcc15ec)) | ||||||
|  | - Vendor [yq](https://github.com/mikefarah/yq/releases) automatically ([3b59adf](https://git.autonomic.zone/coop-cloud/abra/commit/3b59adf)) | ||||||
|  | - Extend version handling logic to support all underlying services ([#90](https://git.autonomic.zone/coop-cloud/abra/issues/90)) | ||||||
|  | - Fix development installation script symlink issue ([#98](https://git.autonomic.zone/coop-cloud/abra/issues/98)) | ||||||
|  | - Add `app-version.sh` script to help packagers version apps ([28618bd](https://git.autonomic.zone/coop-cloud/abra/commit/28618bd)) | ||||||
|  | - Add git digest to `abra version` output ([8b41416](https://git.autonomic.zone/coop-cloud/abra/commit/8b41416)) | ||||||
|  |  | ||||||
|  | # abra 0.5.0 (2021-03-01) | ||||||
|  |  | ||||||
|  | - `secret auto` merged into `secret generate` and `app new --auto` is now `app new --secrets` ([#64](https://git.autonomic.zone/coop-cloud/abra/pulls/64)) | ||||||
|  | - Avoid outputting length during secret generation when not in use ([#67](https://git.autonomic.zone/coop-cloud/abra/issues/67)) | ||||||
|  | - Support graceful failure when missing secret generation commands ([44d3ac3](https://git.autonomic.zone/coop-cloud/abra/commit/44d3ac3a1cb86edc9b9e91eea1a00e70eae14965)) | ||||||
|  | - Fix secret detection when using new `.env` file format in apps ([5532452](https://git.autonomic.zone/coop-cloud/abra/commit/55324524ca77141666ffe6cc41b62cc71cf89ace)) | ||||||
|  | - Support choosing an `$EDITOR` when editing configs ([29cc392](https://git.autonomic.zone/coop-cloud/abra/commit/29cc392dff3e93e48e0e2edd3ce11b405c66a95a)) | ||||||
|  | - "server" shell completion fixed ([8839bd4](https://git.autonomic.zone/coop-cloud/abra/commit/8839bd45951d00dccf4ef81ece445bcc49e13ee6)) | ||||||
|  | - Drop `multilogs` command ([#56](https://git.autonomic.zone/coop-cloud/abra/pulls/56)) | ||||||
|  | - Remove `server use` command ([#51](https://git.autonomic.zone/coop-cloud/abra/issues/51)) | ||||||
|  | - `new <app>` becomes `new <type>` ([#48](https://git.autonomic.zone/coop-cloud/abra/issues/48)) | ||||||
|  | - `check` is run on `deploy` now and configurable ([77ba565](https://git.autonomic.zone/coop-cloud/abra/commit/77ba5652b2fe15820f5edfa0f642636f7b8eae7e)) | ||||||
|  | - App configurations are always updated now ([#42](https://git.autonomic.zone/coop-cloud/abra/issues/42)) | ||||||
|  | - We use docker format `.env` files (no "export" syntax) from now now ([#55](https://git.autonomic.zone/coop-cloud/abra/pulls/55)) | ||||||
|  | - Rename `<domain>` option to `<app>` and `APP` variable to `TYPE`, see ([#47](https://git.autonomic.zone/coop-cloud/abra/issues/47)) | ||||||
|  | - Use Docker-in-Docker (dind), and `dind-bats-kcov` Docker image, for `make test` ([1600b62](https://git.autonomic.zone/coop-cloud/abra/commit/1600b6277fbbffc4c6de1e4ba799c7bbe72ec6a0)) | ||||||
|  | - Add built-in documentation using `abra help <subcommand>...`, see ([#50](https://git.autonomic.zone/coop-cloud/abra/issues/50)) | ||||||
|  | - `version` subcommand ([e6b24fe](https://git.autonomic.zone/coop-cloud/abra/commit/e6b24fe)) | ||||||
|  | - Use `# length=x` comments to generate passwords with `pwgen` and drop `KEY`/`PASSWORD` logic ([#68](https://git.autonomic.zone/coop-cloud/abra/issues/68)) | ||||||
|  | - Global `--skip-update|-U` / `--skip-check|-C` options to make things quicker ([37e8b00](https://git.autonomic.zone/coop-cloud/abra/commit/37e8b00)) | ||||||
|  | - `app backup` and `app restore` commands; requires per-app definition ([#70](https://git.autonomic.zone/coop-cloud/abra/issues/70)) | ||||||
|  | - Rename per-type `abra-commands.sh` to `abra.sh`, and include config versions as type-level instead of app-level config ([#43](https://git.autonomic.zone/coop-cloud/abra/issues/43)) | ||||||
|  | - Show per-subcommand help by adding `-h/--help` to a command line ([#38](https://git.autonomic.zone/coop-cloud/abra/issues/78)) | ||||||
|  |  | ||||||
|  | # abra 0.4.1 (2020-12-24) | ||||||
|  |  | ||||||
|  | - Bug-fixes on `app ls --status` & custom commands | ||||||
|  | - Add `app ls --server=...` and alias | ||||||
|  |  | ||||||
|  | # abra 0.4.0 (2020-12-24) | ||||||
|  |  | ||||||
|  | - New command-line interface based on docopt | ||||||
|  | - `~/.abra` directory instead of expecting local `.env` files | ||||||
|  | - Integration tests & code coverage | ||||||
|  |  | ||||||
|  | # abra 0.3.1 (2020-09-27) | ||||||
|  |  | ||||||
|  | - Fix installer version | ||||||
|  |  | ||||||
| # abra 0.3.0 (2020-09-27) | # abra 0.3.0 (2020-09-27) | ||||||
|  |  | ||||||
| - Add multilogs stack logs implementation ([#8](https://git.autonomic.zone/compose-stacks/abra/issues/8) | - Add multilogs stack logs implementation ([#8](https://git.autonomic.zone/compose-stacks/abra/issues/8)) | ||||||
| - Add beginnings of "monorepo" functionality | - Add beginnings of "monorepo" functionality | ||||||
|  |  | ||||||
| # abra 0.2.0 (2020-09-24) | # abra 0.2.0 (2020-09-24) | ||||||
|  | |||||||
							
								
								
									
										14
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								Makefile
									
									
									
									
									
								
							| @ -1,14 +0,0 @@ | |||||||
| default: install |  | ||||||
|  |  | ||||||
| dev_install: |  | ||||||
| 	ln -sf $(PWD)/abra ~/.local/bin |  | ||||||
|  |  | ||||||
| install: |  | ||||||
| 	install abra /usr/bin/abra |  | ||||||
|  |  | ||||||
| get_yq: |  | ||||||
| 	wget https://github.com/mikefarah/yq/releases/download/3.3.2/yq_linux_amd64 && \ |  | ||||||
| 		chmod +x yq_linux_amd64 && \ |  | ||||||
| 		mv yq_linux_amd64 yq |  | ||||||
|  |  | ||||||
| .PHONY: dev_install install get_yq |  | ||||||
							
								
								
									
										113
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								README.md
									
									
									
									
									
								
							| @ -1,56 +1,93 @@ | |||||||
| # abra | # abra | ||||||
|  |  | ||||||
| [](https://drone.autonomic.zone/autonomic-cooperative/abra) | [](https://drone.autonomic.zone/coop-cloud/abra) | ||||||
|  | [](undefined) | ||||||
|  |  | ||||||
| Docker stack magic 🎩🐇 | > https://coopcloud.tech | ||||||
|  |  | ||||||
| ## Install | The cooperative cloud utility belt 🎩🐇 | ||||||
|  |  | ||||||
| ```sh | `abra` is a command-line tool for managing your own [Co-op Cloud](https://coopcloud.tech). It can provision new servers, create applications, deploy them, run backup and restore operations and a whole lot of other things. It is the go-to tool for day-to-day operations when managing a Co-op Cloud instance. | ||||||
| curl -fsSL https://install.abra.autonomic.zone | bash |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| Specific releases are available via the project [release page](https://git.autonomic.zone/autonomic-cooperative/abra/releases). | ## Change log | ||||||
|  |  | ||||||
| ## Changes | > 🔥 🔥 🔥 Please note, while we are still in [public | ||||||
|  | > alpha](https://docs.coopcloud.tech/roadmap/), the `abra` release | ||||||
|  | > versioning scheme is not following [semver](https://semver.org/) conventions | ||||||
|  | > because we are still in the exploratory phases of building this tool. Please | ||||||
|  | > read the changes before upgrading your `abra` installation as there are | ||||||
|  | > **most likely** breaking changes coming each release. Sorry for any | ||||||
|  | > inconvenience caused, we're working hard to make this tool stable. Semver | ||||||
|  | > will be respected when we reach public beta. 🔥 🔥 🔥 | ||||||
|  |  | ||||||
| See [CHANGELOG.md](./CHANGELOG.md). | See [CHANGELOG.md](./CHANGELOG.md). | ||||||
|  |  | ||||||
| ## Hacking | ## Documentation | ||||||
|  |  | ||||||
|  | > [docs.coopcloud.tech](https://docs.coopcloud.tech) | ||||||
|  |  | ||||||
|  | ## Install | ||||||
|  |  | ||||||
|  | Install the latest stable release: | ||||||
|  |  | ||||||
| ```sh | ```sh | ||||||
| git clone ssh://git@git.autonomic.zone:2222/autonomic-cooperative/abra.git | curl https://install.abra.autonomic.zone | bash | ||||||
| cd abra |  | ||||||
| make dev_install |  | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| See [autonomic-cooperative/installer-scripts](https://git.autonomic.zone/autonomic-cooperative/installer-scripts) for the installer script deployment. To make a release, just add an entry to [CHANGELOG.md](./CHANGELOG.md) (following [semver](https://semver.org/) please) and then `git tag x.x.x && git push origin main --tags`. If you want the [installer-scripts](https://git.autonomic.zone/autonomic-cooperative/installer-scripts) deployment to pick that up, you'll need to change the version number in the [Makefile](https://git.autonomic.zone/autonomic-cooperative/installer-scripts/src/branch/main/Makefile) and run `make` in that repository and push the changes. | or the bleeding-edge development version: | ||||||
|  |  | ||||||
| ## Specify what to deploy where | ```sh | ||||||
|  | curl https://install.abra.autonomic.zone | bash -s -- --dev | ||||||
| You can use `abra` in one of 2 ways: |  | ||||||
|  |  | ||||||
| 1. Clone a `compose-stack`, create an `.envrc` in it, and run `abra` in that |  | ||||||
|    directory. Be sure to set `ABRA_STACK_DIR=.` |  | ||||||
| 2. "Monorepo mode": keep all your `compose-stack`s in one directory and all your `env` files in |  | ||||||
|    another, e.g.: |  | ||||||
|    ``` |  | ||||||
|    $ tree |  | ||||||
|    . |  | ||||||
|    ├── apps |  | ||||||
|    │   ├── mediawiki.demo.autonomic.zone.env |  | ||||||
|    │   ├── wordpress.demo.autonomic.zone.env |  | ||||||
|    └── stacks |  | ||||||
|        ├── gitea |  | ||||||
|        ├── matrix-synapse |  | ||||||
|        ├── mediawiki |  | ||||||
|        ├── nextcloud |  | ||||||
|        ├── swarmpit |  | ||||||
|        ├── traefik |  | ||||||
|        └── wordpress |  | ||||||
|    $ abra -e apps/mediawiki.demo.autonomic.zone.env deploy |  | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| ## Examples | The source for this script is [here](./deploy/install.abra.autonomic.zone/installer). | ||||||
|  |  | ||||||
| - `abra run mariadb mysqldump gitea -p'GdIbMeS09SURRktBnm3jcTufsL5z0MPd' | gzip > ../git.autonomic.zone_mariadb_`date +%F`.sql.gz` | ## Update | ||||||
|  |  | ||||||
|  | Run `abra upgrade` to automatically download and install the latest release | ||||||
|  | version. | ||||||
|  |  | ||||||
|  | To update the development version, run `abra upgrade --dev`. | ||||||
|  |  | ||||||
|  | ## Hack | ||||||
|  |  | ||||||
|  | It's written in Bash version 4 or greater! | ||||||
|  |  | ||||||
|  | Install it via `curl https://install.abra.autonomic.zone | bash -s -- --dev`, then you can hack on the source in `~/.abra/src`. | ||||||
|  |  | ||||||
|  | The command-line interface is generated via [docopt](http://docopt.org/). If you add arguments then you need to run `make docopt` ro regenerate the parser. | ||||||
|  |  | ||||||
|  | Please remember to update the [CHANGELOG](./CHANGELOG.md) when you make a change. | ||||||
|  |  | ||||||
|  | ## Generating a new apps.json | ||||||
|  |  | ||||||
|  | You'll need to install the following requirements: | ||||||
|  |  | ||||||
|  | - [requests](https://docs.python-requests.org/en/master/) (`apt install python3-requests` / `pip install requests`) | ||||||
|  | - [skopeo](https://github.com/containers/skopeo) (check [the install docs](https://github.com/containers/skopeo/blob/master/install.md)) | ||||||
|  | - [jq](https://stedolan.github.io/jq/tutorial/) (`sudo apt-get install jq` or see [the install docs](https://stedolan.github.io/jq/download/)) | ||||||
|  | - [yq](https://mikefarah.gitbook.io/yq/) (see [the install docs](https://mikefarah.gitbook.io/yq/#install)) | ||||||
|  |  | ||||||
|  | Then run `./bin/app-json.py` ([source](./bin/app-json.py)) and it will spit out the JSON file into [deploy/apps.coopcloud.tech/apps.json](./deploy/apps.coopcloud.tech/apps.json). | ||||||
|  |  | ||||||
|  | ## Releasing | ||||||
|  |  | ||||||
|  | ### `abra` | ||||||
|  |  | ||||||
|  | > [install.abra.autonomic.zone](https://install.abra.autonomic.zone) | ||||||
|  |  | ||||||
|  | - Change the `x.x.x` header in [CHANGELOG.md](./CHANGELOG.md) to reflect new version and mark date | ||||||
|  | - Update the version in [abra](./abra) | ||||||
|  | - Update the version in [deploy/install.abra.autonomic.zone/installer](./deploy/install.abra.autonomic.zone/installer) | ||||||
|  | - `git commit` the above changes and then tag it with `git tag <your-new-version>` | ||||||
|  | - `git push` and `git push --tags` | ||||||
|  | - Deploy a new installer script `make release-installer` | ||||||
|  | - Tell the world (CoTech forum, Matrix public channel, Autonomic mastodon, etc.) | ||||||
|  |  | ||||||
|  | ### apps.coopcloud.tech | ||||||
|  |  | ||||||
|  | > [apps.coopcloud.tech](https://apps.coopcloud.tech) | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | $ make release-apps | ||||||
|  | ``` | ||||||
|  | |||||||
							
								
								
									
										103
									
								
								bin/app-catalogue.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										103
									
								
								bin/app-catalogue.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,103 @@ | |||||||
|  | #!/bin/bash | ||||||
|  |  | ||||||
|  | # shellcheck disable=SC2119 | ||||||
|  |  | ||||||
|  | # Usage: ./app-catalogue.sh | ||||||
|  | # | ||||||
|  | # Gather metadata from Co-op Cloud apps in $ABRA_DIR/apps (default | ||||||
|  | # ~/.abra/apps), and format it as a Markdown table for this page: | ||||||
|  | # https://docs.cloud.autonomic.zone/apps/ | ||||||
|  |  | ||||||
|  | stack_dir="${ABRA_DIR:-$HOME/.abra}/apps/" | ||||||
|  |  | ||||||
|  | cd "$stack_dir" || exit | ||||||
|  |  | ||||||
|  | # load all README files into ENV_FILES array | ||||||
|  | mapfile -t readmes < <(find -L . -name "README.md") | ||||||
|  | # FIXME 3wc: requires bash 4, use for loop instead | ||||||
|  |  | ||||||
|  | base_url="https://git.autonomic.zone/coop-cloud" | ||||||
|  |  | ||||||
|  | cat_apps=() | ||||||
|  | cat_development=() | ||||||
|  | cat_utilities=() | ||||||
|  | cat_graveyard=() | ||||||
|  |  | ||||||
|  | get_var() { | ||||||
|  | 	echo "$1" | grep "$2" | sed 's/^[^:]*: //' | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # shellcheck disable=SC2120 | ||||||
|  | trim() { | ||||||
|  | 	# accept input as argument or from STDIN, see here: | ||||||
|  | 	# https://zwbetz.com/passing-input-to-a-bash-function-via-arguments-or-stdin/ | ||||||
|  | 	# shellcheck disable=SC2155 | ||||||
|  | 	local input="$([[ -p /dev/stdin ]] && cat - || echo "$@")" | ||||||
|  | 	[[ -z "$input" ]] && return 1 | ||||||
|  | 	echo "$input" | tr -d ' ' | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # shellcheck disable=SC2120 | ||||||
|  | prettify() { | ||||||
|  | 	# as above | ||||||
|  | 	# shellcheck disable=SC2155 | ||||||
|  | 	local input="$([[ -p /dev/stdin ]] && cat - || echo "$@")" | ||||||
|  | 	[[ -z "$input" ]] && return 1 | ||||||
|  |  | ||||||
|  | 	echo "$input" | sed -e 's/Yes/✅/' -e 's/No/❌/' -e 's/N\/A/⛔/' | ||||||
|  | } | ||||||
|  |  | ||||||
|  | for readme in "${readmes[@]}"; do | ||||||
|  | 	type="$(basename "${readme%README.md}")" | ||||||
|  | 	if [ "$type" = "example" ]; then | ||||||
|  | 		continue | ||||||
|  | 	fi | ||||||
|  | 	title="$(grep '^# ' "$type/README.md" | sed 's/^# //' )" | ||||||
|  | 	# find section between 'metadata' and 'endmetadata' comments | ||||||
|  | 	metadata="$(awk '/-- metadata --/,/-- endmetadata --/' "$type/README.md")" | ||||||
|  | 	status="$(get_var "$metadata" "Status")" | ||||||
|  | 	category="$(get_var "$metadata" "Category" | cut -d',' -f2 | trim)" | ||||||
|  |  | ||||||
|  | 	if [ -z "$category" ]; then | ||||||
|  | 		echo "ERROR: missing category for $type" | ||||||
|  | 		continue | ||||||
|  | 	fi | ||||||
|  |  | ||||||
|  | 	image="$(get_var "$metadata" "Image" | cut -d',' -f2 | trim)" | ||||||
|  | 	healthcheck="$(get_var "$metadata" "Healthcheck" | prettify)" | ||||||
|  | 	backups="$(get_var "$metadata" "Backups" | prettify)" | ||||||
|  | 	email="$(get_var "$metadata" "Email" | prettify)" | ||||||
|  | 	tests="$(get_var "$metadata" "Tests" | prettify)" | ||||||
|  | 	sso="$(get_var "$metadata" "SSO" | prettify)" | ||||||
|  |  | ||||||
|  | 	row="| [$title]($base_url/$type) | $status | $image | $healthcheck | $backups | $email | $tests | $sso |" | ||||||
|  |  | ||||||
|  | 	category_lower="$(echo "$category" | tr '[:upper:]' '[:lower:]')" | ||||||
|  | 	eval "cat_$category_lower+=( '$row' )" | ||||||
|  | done | ||||||
|  |  | ||||||
|  | headers=" | ||||||
|  | | **Name** | **Status** | **Image** | **Healtcheck** | **Backups** | **Email** | **CI** | **Single-Sign-On** | | ||||||
|  | | --- | --- | --- | --- | --- | --- | --- | --- |" | ||||||
|  |  | ||||||
|  | echo "## Applications" | ||||||
|  | echo "$headers" | ||||||
|  | printf '%s\n' "${cat_apps[@]}" | sort | ||||||
|  |  | ||||||
|  | echo | ||||||
|  |  | ||||||
|  | echo "## Developer tools" | ||||||
|  | echo "$headers" | ||||||
|  | printf '%s\n' "${cat_development[@]}" | sort | ||||||
|  |  | ||||||
|  | echo | ||||||
|  |  | ||||||
|  | echo "## Utilities" | ||||||
|  | echo "$headers" | ||||||
|  | printf '%s\n' "${cat_utilities[@]}" | sort | ||||||
|  |  | ||||||
|  | echo | ||||||
|  |  | ||||||
|  | echo "## Graveyard" | ||||||
|  | echo "$headers" | ||||||
|  | printf '%s\n' "${cat_graveyard[@]}" | sort | ||||||
							
								
								
									
										298
									
								
								bin/app-json.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										298
									
								
								bin/app-json.py
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,298 @@ | |||||||
|  | #!/usr/bin/env python3 | ||||||
|  |  | ||||||
|  | # Usage: ./app-json.py | ||||||
|  | # | ||||||
|  | # Gather metadata from Co-op Cloud apps in $ABRA_DIR/apps (default | ||||||
|  | # ~/.abra/apps), and format it as JSON so that it can be hosted here: | ||||||
|  | # https://apps.coopcloud.tech | ||||||
|  |  | ||||||
|  | from json import dump | ||||||
|  | from logging import DEBUG, basicConfig, getLogger | ||||||
|  | from os import chdir, listdir, mkdir | ||||||
|  | from os.path import basename, exists, expanduser | ||||||
|  | from pathlib import Path | ||||||
|  | from re import findall, search | ||||||
|  | from shlex import split | ||||||
|  | from subprocess import DEVNULL, check_output | ||||||
|  | from sys import exit | ||||||
|  |  | ||||||
|  | from requests import get | ||||||
|  |  | ||||||
|  | HOME_PATH = expanduser("~/") | ||||||
|  | CLONES_PATH = Path(f"{HOME_PATH}/.abra/apps").absolute() | ||||||
|  | YQ_PATH = Path(f"{HOME_PATH}/.abra/vendor/yq") | ||||||
|  | SCRIPT_PATH = Path(__file__).absolute().parent | ||||||
|  | REPOS_TO_SKIP = ( | ||||||
|  |     "abra", | ||||||
|  |     "abra-apps", | ||||||
|  |     "abra-gandi", | ||||||
|  |     "abra-hetzner", | ||||||
|  |     "backup-bot", | ||||||
|  |     "coopcloud.tech", | ||||||
|  |     "coturn", | ||||||
|  |     "docker-cp-deploy", | ||||||
|  |     "docker-dind-bats-kcov", | ||||||
|  |     "docs.coopcloud.tech", | ||||||
|  |     "example", | ||||||
|  |     "gardening", | ||||||
|  |     "organising", | ||||||
|  |     "pyabra", | ||||||
|  |     "radicle-seed-node", | ||||||
|  |     "stack-ssh-deploy", | ||||||
|  |     "swarm-cronjob", | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | log = getLogger(__name__) | ||||||
|  | basicConfig() | ||||||
|  | log.setLevel(DEBUG) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def _run_cmd(cmd, shell=False, **kwargs): | ||||||
|  |     """Run a shell command.""" | ||||||
|  |     args = [split(cmd)] | ||||||
|  |  | ||||||
|  |     if shell: | ||||||
|  |         args = [cmd] | ||||||
|  |         kwargs = {"shell": shell} | ||||||
|  |  | ||||||
|  |     try: | ||||||
|  |         return check_output(*args, **kwargs).decode("utf-8").strip() | ||||||
|  |     except Exception as exception: | ||||||
|  |         log.error(f"Failed to run {cmd}, saw {str(exception)}") | ||||||
|  |         exit(1) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def get_repos_json(): | ||||||
|  |     """ Retrieve repo list from Gitea """ | ||||||
|  |  | ||||||
|  |     url = "https://git.autonomic.zone/api/v1/orgs/coop-cloud/repos" | ||||||
|  |  | ||||||
|  |     log.info(f"Retrieving {url}") | ||||||
|  |  | ||||||
|  |     repos = [] | ||||||
|  |     response = True | ||||||
|  |     page = 1 | ||||||
|  |  | ||||||
|  |     try: | ||||||
|  |         while response: | ||||||
|  |             log.info(f"Trying to fetch page {page}") | ||||||
|  |             response = get(url + f"?page={page}", timeout=10).json() | ||||||
|  |             repos.extend(response) | ||||||
|  |             page += 1 | ||||||
|  |  | ||||||
|  |         return repos | ||||||
|  |     except Exception as exception: | ||||||
|  |         log.error(f"Failed to retrieve {url}, saw {str(exception)}") | ||||||
|  |         exit(1) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def get_published_apps_json(): | ||||||
|  |     """Retrieve already published apps json.""" | ||||||
|  |     url = "https://apps.coopcloud.tech" | ||||||
|  |  | ||||||
|  |     log.info(f"Retrieving {url}") | ||||||
|  |  | ||||||
|  |     try: | ||||||
|  |         return get(url, timeout=5).json() | ||||||
|  |     except Exception as exception: | ||||||
|  |         log.error(f"Failed to retrieve {url}, saw {str(exception)}") | ||||||
|  |         return {} | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def clone_all_apps(repos_json): | ||||||
|  |     """Clone all Co-op Cloud apps to ~/.abra/apps.""" | ||||||
|  |     if not exists(CLONES_PATH): | ||||||
|  |         mkdir(CLONES_PATH) | ||||||
|  |  | ||||||
|  |     repos = [[p["name"], p["ssh_url"]] for p in repos_json] | ||||||
|  |  | ||||||
|  |     for name, url in repos: | ||||||
|  |         if name in REPOS_TO_SKIP: | ||||||
|  |             continue | ||||||
|  |  | ||||||
|  |         if not exists(f"{CLONES_PATH}/{name}"): | ||||||
|  |             log.info(f"Retrieving {url}") | ||||||
|  |             _run_cmd(f"git clone {url} {CLONES_PATH}/{name}") | ||||||
|  |  | ||||||
|  |             chdir(f"{CLONES_PATH}/{name}") | ||||||
|  |             if not int(_run_cmd("git branch --list | wc -l", shell=True)): | ||||||
|  |                 log.info(f"Guessing main branch is HEAD for {name}") | ||||||
|  |                 _run_cmd("git checkout main") | ||||||
|  |         else: | ||||||
|  |             log.info(f"Updating {name}") | ||||||
|  |             chdir(f"{CLONES_PATH}/{name}") | ||||||
|  |             _run_cmd("git fetch -a") | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def generate_apps_json(repos_json): | ||||||
|  |     """Generate the abra-apps.json application versions file.""" | ||||||
|  |     apps_json = {} | ||||||
|  |     cached_apps_json = get_published_apps_json() | ||||||
|  |  | ||||||
|  |     for app in listdir(CLONES_PATH): | ||||||
|  |         if app in REPOS_TO_SKIP: | ||||||
|  |             log.info(f"Skipping {app}") | ||||||
|  |             continue | ||||||
|  |  | ||||||
|  |         repo_details = next(filter(lambda x: x["name"] == app, repos_json), {}) | ||||||
|  |  | ||||||
|  |         app_path = f"{CLONES_PATH}/{app}" | ||||||
|  |         chdir(app_path) | ||||||
|  |  | ||||||
|  |         metadata = get_app_metadata(app_path) | ||||||
|  |         name = metadata.pop("name", "") | ||||||
|  |  | ||||||
|  |         log.info(f"Processing {app}") | ||||||
|  |         apps_json[app] = { | ||||||
|  |             "name": name, | ||||||
|  |             "category": metadata.get("category", ""), | ||||||
|  |             "repository": repo_details.get("clone_url", ""), | ||||||
|  |             "default_branch": repo_details.get("default_branch", ""), | ||||||
|  |             "description": repo_details.get("description", ""), | ||||||
|  |             "website": repo_details.get("website", ""), | ||||||
|  |             "features": metadata, | ||||||
|  |             "versions": get_app_versions(app_path, cached_apps_json), | ||||||
|  |             "icon": repo_details.get("avatar_url", ""), | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     return apps_json | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def get_app_metadata(app_path): | ||||||
|  |     """Parse metadata from app repo README files.""" | ||||||
|  |     metadata = {} | ||||||
|  |  | ||||||
|  |     chdir(app_path) | ||||||
|  |  | ||||||
|  |     try: | ||||||
|  |         with open(f"{app_path}/README.md", "r") as handle: | ||||||
|  |             log.info(f"{app_path}/README.md") | ||||||
|  |             contents = handle.read() | ||||||
|  |     except Exception: | ||||||
|  |         log.info(f"No {app_path}/README.md discovered, moving on") | ||||||
|  |         return {} | ||||||
|  |  | ||||||
|  |     try: | ||||||
|  |         for match in findall(r"\*\*.*\s\*", contents): | ||||||
|  |             title = search(r"(?<=\*\*).*(?=\*\*)", match).group().lower() | ||||||
|  |  | ||||||
|  |             if title == "image": | ||||||
|  |                 value = { | ||||||
|  |                     "image": search(r"(?<=`).*(?=`)", match).group(), | ||||||
|  |                     "url": search(r"(?<=\().*(?=\))", match).group(), | ||||||
|  |                     "rating": match.split(",")[1].strip(), | ||||||
|  |                     "source": match.split(",")[-1].replace("*", "").strip(), | ||||||
|  |                 } | ||||||
|  |             elif title == "status": | ||||||
|  |                 value = {"❶💚": 1, "❷💛": 2, "❸🍎": 3, "❹💣": 4, "?": 5, "": 5}[ | ||||||
|  |                     match.split(":")[-1].replace("*", "").strip() | ||||||
|  |                 ] | ||||||
|  |             else: | ||||||
|  |                 value = match.split(":")[-1].replace("*", "").strip() | ||||||
|  |  | ||||||
|  |             metadata[title] = value | ||||||
|  |         metadata["name"] = findall(r"^# (.*)", contents)[0] | ||||||
|  |     except (IndexError, AttributeError): | ||||||
|  |         log.info(f"Can't parse {app_path}/README.md") | ||||||
|  |         return {} | ||||||
|  |     finally: | ||||||
|  |         _run_cmd("git checkout HEAD") | ||||||
|  |  | ||||||
|  |     log.info(f"Parsed {metadata}") | ||||||
|  |  | ||||||
|  |     return metadata | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def get_app_versions(app_path, cached_apps_json): | ||||||
|  |     versions = {} | ||||||
|  |  | ||||||
|  |     chdir(app_path) | ||||||
|  |  | ||||||
|  |     tags = _run_cmd("git tag --list").split() | ||||||
|  |  | ||||||
|  |     if not tags: | ||||||
|  |         log.info("No tags discovered, moving on") | ||||||
|  |         return {} | ||||||
|  |  | ||||||
|  |     initial_branch = _run_cmd("git rev-parse --abbrev-ref HEAD") | ||||||
|  |  | ||||||
|  |     app_name = basename(app_path) | ||||||
|  |  | ||||||
|  |     try: | ||||||
|  |         existing_tags = cached_apps_json[app_name]["versions"].keys() | ||||||
|  |     except KeyError: | ||||||
|  |         existing_tags = [] | ||||||
|  |  | ||||||
|  |     for tag in tags: | ||||||
|  |         _run_cmd(f"git checkout {tag}", stderr=DEVNULL) | ||||||
|  |  | ||||||
|  |         services_cmd = f"{YQ_PATH} e '.services | keys | .[]' compose*.yml" | ||||||
|  |         services = _run_cmd(services_cmd, shell=True).split() | ||||||
|  |  | ||||||
|  |         parsed_services = [] | ||||||
|  |         service_versions = {} | ||||||
|  |         for service in services: | ||||||
|  |             if service in ("null", "---"): | ||||||
|  |                 continue | ||||||
|  |  | ||||||
|  |             if ( | ||||||
|  |                 tag in existing_tags | ||||||
|  |                 and service in cached_apps_json[app_name]["versions"][tag] | ||||||
|  |             ): | ||||||
|  |                 log.info(f"Skipping {tag} because we've already processed it") | ||||||
|  |                 existing_versions = cached_apps_json[app_name]["versions"][tag][service] | ||||||
|  |                 service_versions[service] = existing_versions | ||||||
|  |                 _run_cmd(f"git checkout {initial_branch}") | ||||||
|  |                 continue | ||||||
|  |  | ||||||
|  |             if service in parsed_services: | ||||||
|  |                 log.info(f"Skipped {service}, we've already parsed it locally") | ||||||
|  |                 continue | ||||||
|  |  | ||||||
|  |             services_cmd = f"{YQ_PATH} e '.services.{service}.image' compose*.yml" | ||||||
|  |             images = _run_cmd(services_cmd, shell=True).split() | ||||||
|  |  | ||||||
|  |             for image in images: | ||||||
|  |                 if image in ("null", "---"): | ||||||
|  |                     continue | ||||||
|  |  | ||||||
|  |                 images_cmd = f"skopeo inspect docker://{image} | jq '.Digest'" | ||||||
|  |                 output = _run_cmd(images_cmd, shell=True) | ||||||
|  |  | ||||||
|  |                 service_version_info = { | ||||||
|  |                     "image": image.split(":")[0], | ||||||
|  |                     "tag": image.split(":")[-1], | ||||||
|  |                     "digest": output.split(":")[-1][:8], | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 log.info(f"Parsed {service_version_info}") | ||||||
|  |                 service_versions[service] = service_version_info | ||||||
|  |  | ||||||
|  |             parsed_services.append(service) | ||||||
|  |  | ||||||
|  |         versions[tag] = service_versions | ||||||
|  |  | ||||||
|  |     _run_cmd(f"git checkout {initial_branch}") | ||||||
|  |  | ||||||
|  |     return versions | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def main(): | ||||||
|  |     """Run the script.""" | ||||||
|  |     repos_json = get_repos_json() | ||||||
|  |     clone_all_apps(repos_json) | ||||||
|  |  | ||||||
|  |     target = f"{SCRIPT_PATH}/../deploy/apps.coopcloud.tech/apps.json" | ||||||
|  |     with open(target, "w", encoding="utf-8") as handle: | ||||||
|  |         dump( | ||||||
|  |             generate_apps_json(repos_json), | ||||||
|  |             handle, | ||||||
|  |             ensure_ascii=False, | ||||||
|  |             indent=4, | ||||||
|  |             sort_keys=True, | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     log.info(f"Successfully generated {target}") | ||||||
|  |  | ||||||
|  |  | ||||||
|  | main() | ||||||
							
								
								
									
										52
									
								
								completion/_abra
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								completion/_abra
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | |||||||
|  | #compdef abra | ||||||
|  |  | ||||||
|  | _abra () { | ||||||
|  | 	local context state line curcontext="$curcontext" ret=1 | ||||||
|  | 	_arguments -n : \ | ||||||
|  | 		{-h,--help}'[Help message]' \ | ||||||
|  | 		'1:commands:(app server)' \ | ||||||
|  | 		'*::arguments:->arguments' \ | ||||||
|  | 		&& ret=0 | ||||||
|  |  | ||||||
|  | 	case $state in | ||||||
|  | 		(arguments) | ||||||
|  | 			curcontext="${curcontext%:*:*}:abra-arguments-$words[1]:" | ||||||
|  | 			case $words[1] in | ||||||
|  | 				(app) | ||||||
|  | 					_arguments \ | ||||||
|  | 						'1: :_abra_apps' \ | ||||||
|  | 					&& ret=0 | ||||||
|  | 				;; | ||||||
|  | 				(server) | ||||||
|  | 					_arguments \ | ||||||
|  | 						'1:servers:_abra_servers' \ | ||||||
|  | 					&& ret=0 | ||||||
|  | 				;; | ||||||
|  | 			esac | ||||||
|  | 		;; | ||||||
|  | 	esac | ||||||
|  |  | ||||||
|  | 	return ret | ||||||
|  | } | ||||||
|  |  | ||||||
|  | _abra_servers() { | ||||||
|  | 	_path_files -/W $HOME/.abra/servers | ||||||
|  | } | ||||||
|  |  | ||||||
|  | _abra_apps() | ||||||
|  | { | ||||||
|  | 	local newapps apps=($HOME/.abra/servers/*/*.env) | ||||||
|  | 	typeset -a apps | ||||||
|  | 	newapps=() | ||||||
|  | 	for app in $apps; do | ||||||
|  | 		newapps+=($(_abra_basename "${app}")) | ||||||
|  | 	done | ||||||
|  | 	_describe -t apps 'app' newapps | ||||||
|  | } | ||||||
|  |  | ||||||
|  | _abra_basename() | ||||||
|  | { | ||||||
|  |     printf -- "${1##*/}" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | _abra "$@" | ||||||
							
								
								
									
										117
									
								
								completion/abra.bash
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								completion/abra.bash
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,117 @@ | |||||||
|  | #!/usr/bin/env bash | ||||||
|  |  | ||||||
|  | _abra_basename() | ||||||
|  | { | ||||||
|  |     echo "${1##*/}" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | _abra_servers() | ||||||
|  | { | ||||||
|  |     # FIXME 3wc: copied from abra/get_servers() | ||||||
|  |     shopt -s nullglob dotglob | ||||||
|  |     local SERVERS=(~/.abra/servers/*) | ||||||
|  |     shopt -u nullglob dotglob | ||||||
|  |  | ||||||
|  |     for SERVER in "${SERVERS[@]}"; do | ||||||
|  |         _abra_basename "${SERVER}" | ||||||
|  |     done | ||||||
|  | } | ||||||
|  |  | ||||||
|  | _abra_complete_servers() | ||||||
|  | { | ||||||
|  |     mapfile -t COMPREPLY < <(compgen -W "$(_abra_servers)" -- "$1") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | _abra_apps() | ||||||
|  | { | ||||||
|  |     shopt -s nullglob dotglob | ||||||
|  |     local APPS=(~/.abra/servers/*/*.env) | ||||||
|  |     shopt -u nullglob dotglob | ||||||
|  |  | ||||||
|  |     for APP in "${APPS[@]}"; do | ||||||
|  |         _abra_basename "${APP%.env}" | ||||||
|  |     done | ||||||
|  | } | ||||||
|  |  | ||||||
|  | _abra_complete_apps() | ||||||
|  | { | ||||||
|  |     mapfile -t COMPREPLY < <(compgen -W "$(_abra_apps)" -- "$1") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | _abra_complete() | ||||||
|  | { | ||||||
|  |     compopt +o default +o nospace | ||||||
|  |     COMPREPLY=() | ||||||
|  |  | ||||||
|  |     local -r cmds=' | ||||||
|  |         app | ||||||
|  |         server | ||||||
|  |     ' | ||||||
|  |     local -r short_opts='-e      -h     -s      -v' | ||||||
|  |     local -r long_opts='--env --help --stack --version' | ||||||
|  |  | ||||||
|  |     # Scan through the command line and find the abra command | ||||||
|  |     # (if present), as well as its expected position. | ||||||
|  |     local cmd | ||||||
|  |     local cmd_index=1 # Expected index of the command token. | ||||||
|  |     local i | ||||||
|  |     for (( i = 1; i < ${#COMP_WORDS[@]}; i++ )); do | ||||||
|  |         local word="${COMP_WORDS[i]}" | ||||||
|  |         case "$word" in | ||||||
|  |             -*) | ||||||
|  |                 ((cmd_index++)) | ||||||
|  |                 ;; | ||||||
|  |             *) | ||||||
|  |                 cmd="$word" | ||||||
|  |                 break | ||||||
|  |                 ;; | ||||||
|  |         esac | ||||||
|  |     done | ||||||
|  |  | ||||||
|  |     local cur="${COMP_WORDS[COMP_CWORD]}" | ||||||
|  |  | ||||||
|  |     if (( COMP_CWORD < cmd_index )); then | ||||||
|  |         # Offer option completions. | ||||||
|  |         case "$cur" in | ||||||
|  |             --*) | ||||||
|  |                 mapfile -t COMPREPLY < <(compgen -W "$long_opts" -- "$cur") | ||||||
|  |                 ;; | ||||||
|  |             -*) | ||||||
|  |                 mapfile -t COMPREPLY < <(compgen -W "$short_opts" -- "$cur") | ||||||
|  |                 ;; | ||||||
|  |             *) | ||||||
|  |                 # Skip completion; we should never get here. | ||||||
|  |                 ;; | ||||||
|  |         esac | ||||||
|  |     elif (( COMP_CWORD == cmd_index )); then | ||||||
|  |         # Offer command name completions. | ||||||
|  |         mapfile -t COMPREPLY < <(compgen -W "$cmds" -- "$cur") | ||||||
|  |     else | ||||||
|  |         # Offer command argument completions. | ||||||
|  |         case "$cmd" in | ||||||
|  |             server) | ||||||
|  |                 # Offer exactly one server name completion. | ||||||
|  |                 if (( COMP_CWORD == cmd_index + 1 )); then | ||||||
|  |                     _abra_complete_servers "$cur" | ||||||
|  |                 fi | ||||||
|  |                 ;; | ||||||
|  |             app) | ||||||
|  |                 # Offer exactly one app completion. | ||||||
|  |                 if (( COMP_CWORD == cmd_index + 1 )); then | ||||||
|  |                     _abra_complete_apps "$cur" | ||||||
|  |                 fi | ||||||
|  |                 ;; | ||||||
|  |             #help) | ||||||
|  |             #    # Offer exactly one command name completion. | ||||||
|  |             #    if (( COMP_CWORD == cmd_index + 1 )); then | ||||||
|  |             #        COMPREPLY=($(compgen -W "$cmds" -- "$cur")) | ||||||
|  |             #    fi | ||||||
|  |             #    ;; | ||||||
|  |             *) | ||||||
|  |                 # Unknown command or unknowable argument. | ||||||
|  |                 ;; | ||||||
|  |         esac | ||||||
|  |     fi | ||||||
|  | } | ||||||
|  |  | ||||||
|  | complete -o default -F _abra_complete abra | ||||||
							
								
								
									
										2084
									
								
								deploy/apps.coopcloud.tech/apps.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2084
									
								
								deploy/apps.coopcloud.tech/apps.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										41
									
								
								deploy/apps.coopcloud.tech/compose.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								deploy/apps.coopcloud.tech/compose.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | |||||||
|  | --- | ||||||
|  | version: "3.8" | ||||||
|  |  | ||||||
|  | services: | ||||||
|  |   app: | ||||||
|  |     image: "nginx:stable" | ||||||
|  |     configs: | ||||||
|  |       - source: abra_conf | ||||||
|  |         target: /etc/nginx/conf.d/abra.conf | ||||||
|  |       - source: abra_apps_json | ||||||
|  |         target: /var/www/abra-apps/apps.json | ||||||
|  |     volumes: | ||||||
|  |       - "public:/var/www/abra-apps" | ||||||
|  |     networks: | ||||||
|  |       - proxy | ||||||
|  |     deploy: | ||||||
|  |       update_config: | ||||||
|  |         failure_action: rollback | ||||||
|  |         order: start-first | ||||||
|  |       labels: | ||||||
|  |         - "traefik.enable=true" | ||||||
|  |         - "traefik.http.services.abra-apps.loadbalancer.server.port=80" | ||||||
|  |         - "traefik.http.routers.abra-apps.rule=Host(`apps.coopcloud.tech`, `abra-apps.cloud.autonomic.zone`)" | ||||||
|  |         - "traefik.http.routers.abra-apps.entrypoints=web-secure" | ||||||
|  |         - "traefik.http.routers.abra-apps.tls.certresolver=production" | ||||||
|  |         - "traefik.http.routers.abra-apps.middlewares=abra-apps-redirect" | ||||||
|  |         - "traefik.http.middlewares.abra-apps-redirect.headers.SSLForceHost=true" | ||||||
|  |         - "traefik.http.middlewares.abra-apps-redirect.headers.SSLHost=apps.coopcloud.tech" | ||||||
|  |  | ||||||
|  | configs: | ||||||
|  |   abra_apps_json: | ||||||
|  |     file: apps.json | ||||||
|  |   abra_conf: | ||||||
|  |     file: nginx.conf | ||||||
|  |  | ||||||
|  | networks: | ||||||
|  |   proxy: | ||||||
|  |     external: true | ||||||
|  |  | ||||||
|  | volumes: | ||||||
|  |   public: | ||||||
							
								
								
									
										10
									
								
								deploy/apps.coopcloud.tech/nginx.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								deploy/apps.coopcloud.tech/nginx.conf
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | |||||||
|  | server { | ||||||
|  |   listen         80 default_server; | ||||||
|  |   server_name    apps.coopcloud.tech; | ||||||
|  |  | ||||||
|  |   location / { | ||||||
|  |     root /var/www/abra-apps; | ||||||
|  |     add_header Content-Type application/json; | ||||||
|  |     index apps.json; | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										38
									
								
								deploy/install.abra.autonomic.zone/compose.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								deploy/install.abra.autonomic.zone/compose.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | |||||||
|  | --- | ||||||
|  | version: "3.8" | ||||||
|  |  | ||||||
|  | services: | ||||||
|  |   app: | ||||||
|  |     image: "nginx:stable" | ||||||
|  |     configs: | ||||||
|  |       - source: abra_conf | ||||||
|  |         target: /etc/nginx/conf.d/abra.conf | ||||||
|  |       - source: abra_installer | ||||||
|  |         target: /var/www/abra-installer/installer | ||||||
|  |     volumes: | ||||||
|  |       - "public:/var/www/abra-installer" | ||||||
|  |     networks: | ||||||
|  |       - proxy | ||||||
|  |     deploy: | ||||||
|  |       update_config: | ||||||
|  |         failure_action: rollback | ||||||
|  |         order: start-first | ||||||
|  |       labels: | ||||||
|  |         - "traefik.enable=true" | ||||||
|  |         - "traefik.http.services.abra-installer.loadbalancer.server.port=80" | ||||||
|  |         - "traefik.http.routers.abra-installer.rule=Host(`install.abra.autonomic.zone`)" | ||||||
|  |         - "traefik.http.routers.abra-installer.entrypoints=web-secure" | ||||||
|  |         - "traefik.http.routers.abra-installer.tls.certresolver=production" | ||||||
|  |  | ||||||
|  | configs: | ||||||
|  |   abra_installer: | ||||||
|  |     file: installer | ||||||
|  |   abra_conf: | ||||||
|  |     file: nginx.conf | ||||||
|  |  | ||||||
|  | networks: | ||||||
|  |   proxy: | ||||||
|  |     external: true | ||||||
|  |  | ||||||
|  | volumes: | ||||||
|  |   public: | ||||||
							
								
								
									
										35
									
								
								deploy/install.abra.autonomic.zone/installer
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										35
									
								
								deploy/install.abra.autonomic.zone/installer
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,35 @@ | |||||||
|  | #!/bin/bash | ||||||
|  |  | ||||||
|  | ABRA_VERSION="0.7.4" | ||||||
|  | GIT_URL="https://git.autonomic.zone/coop-cloud/abra" | ||||||
|  | ABRA_SRC="$GIT_URL/raw/tag/$ABRA_VERSION/abra" | ||||||
|  | ABRA_DIR="${ABRA_DIR:-$HOME/.abra/}" | ||||||
|  |  | ||||||
|  | function install_abra_release { | ||||||
|  |   mkdir -p "$HOME/.local/bin" | ||||||
|  |   curl "$ABRA_SRC" > "$HOME/.local/bin/abra" | ||||||
|  |   chmod +x "$HOME/.local/bin/abra" | ||||||
|  |   echo "abra installed to $HOME/.local/bin/abra" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function install_abra_dev { | ||||||
|  |   mkdir -p "$ABRA_DIR/" | ||||||
|  |   if [[ ! -d "$ABRA_DIR/src" ]]; then | ||||||
|  |     git clone "$GIT_URL" "$ABRA_DIR/src" | ||||||
|  |   fi | ||||||
|  |   (cd "$ABRA_DIR/src" && git pull origin main && cd - || exit) | ||||||
|  |   mkdir -p "$HOME/.local/bin" | ||||||
|  |   ln -sf "$ABRA_DIR/src/abra" "$HOME/.local/bin/abra" | ||||||
|  |   echo "abra installed to $HOME/.local/bin/abra (development bleeding edge)" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function run_installation { | ||||||
|  |   if [ "$1" = "--dev" ]; then | ||||||
|  |     install_abra_dev | ||||||
|  |   else | ||||||
|  |     install_abra_release | ||||||
|  |   fi | ||||||
|  | } | ||||||
|  |  | ||||||
|  | run_installation "$@" | ||||||
|  | exit 0 | ||||||
							
								
								
									
										10
									
								
								deploy/install.abra.autonomic.zone/nginx.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								deploy/install.abra.autonomic.zone/nginx.conf
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | |||||||
|  | server { | ||||||
|  |   listen         80 default_server; | ||||||
|  |   server_name    install.abra.autonomic.zone; | ||||||
|  |  | ||||||
|  |   location / { | ||||||
|  |     root /var/www/abra-installer; | ||||||
|  |     add_header Content-Type text/plain; | ||||||
|  |     index installer; | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										58
									
								
								makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,58 @@ | |||||||
|  | .PHONY: test shellcheck docopt kcov codecov release-installer | ||||||
|  |  | ||||||
|  | test: | ||||||
|  | 	@sudo DOCKER_CONTEXT=default docker run \ | ||||||
|  | 		-v $$(pwd):/workdir \ | ||||||
|  | 		--privileged \ | ||||||
|  | 		-d \ | ||||||
|  | 		--name=abra-test-dind \ | ||||||
|  | 		-e DOCKER_TLS_CERTDIR="" \ | ||||||
|  | 		decentral1se/docker-dind-bats-kcov | ||||||
|  | 	@DOCKER_CONTEXT=default docker exec \ | ||||||
|  | 		-it \ | ||||||
|  | 		abra-test-dind \ | ||||||
|  | 		sh -c "cd /workdir && bats /workdir/tests" | ||||||
|  | 	@DOCKER_CONTEXT=default docker stop abra-test-dind | ||||||
|  | 	@DOCKER_CONTEXT=default docker rm abra-test-dind | ||||||
|  |  | ||||||
|  | shellcheck: | ||||||
|  | 	@docker run \ | ||||||
|  | 		-it \ | ||||||
|  | 		--rm \ | ||||||
|  | 		-v $$(pwd):/workdir \ | ||||||
|  | 		koalaman/shellcheck-alpine \ | ||||||
|  | 		shellcheck /workdir/abra && \ | ||||||
|  | 		shellcheck /workdir/bin/*.sh | ||||||
|  |  | ||||||
|  | docopt: | ||||||
|  | 	@if [ ! -d ".venv" ]; then \ | ||||||
|  | 		python3 -m venv .venv && \ | ||||||
|  | 		.venv/bin/pip install -U pip setuptools wheel && \ | ||||||
|  | 		.venv/bin/pip install docopt-sh; \ | ||||||
|  | 	fi | ||||||
|  | 	.venv/bin/docopt.sh abra | ||||||
|  |  | ||||||
|  | kcov: | ||||||
|  | 	@docker run \ | ||||||
|  | 		-it \ | ||||||
|  | 		--rm \ | ||||||
|  | 		-v $$(pwd):/workdir \ | ||||||
|  | 		kcov/kcov:latest \ | ||||||
|  | 		sh -c "kcov /workdir/coverage /workdir/abra || true" | ||||||
|  |  | ||||||
|  | codecov: SHELL:=/bin/bash | ||||||
|  | codecov: | ||||||
|  | 	@bash <(curl -s https://codecov.io/bash) \ | ||||||
|  | 		-s coverage -t $$(pass show hosts/swarm.autonomic.zone/drone/codecov/token) | ||||||
|  |  | ||||||
|  | release-installer: | ||||||
|  | 	@DOCKER_CONTEXT=swarm.autonomic.zone \ | ||||||
|  | 		docker stack rm abra-installer-script && \ | ||||||
|  | 		cd deploy/install.abra.autonomic.zone && \ | ||||||
|  | 		DOCKER_CONTEXT=swarm.autonomic.zone docker stack deploy -c compose.yml abra-installer-script | ||||||
|  |  | ||||||
|  | release-apps: | ||||||
|  | 	@DOCKER_CONTEXT=swarm.autonomic.zone \ | ||||||
|  | 		docker stack rm abra-apps-json && \ | ||||||
|  | 		cd deploy/apps.coopcloud.tech && \ | ||||||
|  | 		DOCKER_CONTEXT=swarm.autonomic.zone docker stack deploy -c compose.yml abra-apps-json | ||||||
| @ -1,18 +0,0 @@ | |||||||
| #!/bin/bash |  | ||||||
|  |  | ||||||
| ABRA_VERSION="0.1.2" |  | ||||||
| ABRA_SRC="https://git.autonomic.zone/autonomic-cooperative/abra/raw/tag/$ABRA_VERSION/abra" |  | ||||||
|  |  | ||||||
| function install_abra { |  | ||||||
|   mkdir -p "$HOME/.local/bin" |  | ||||||
| 	curl "$ABRA_SRC" > "$HOME/.local/bin/abra" |  | ||||||
|   chmod +x "$HOME/.local/bin/abra" |  | ||||||
|   echo "abra installed to $HOME/.loca/bin/abra" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function run_installation { |  | ||||||
|   install_abra |  | ||||||
| } |  | ||||||
|  |  | ||||||
| run_installation |  | ||||||
| exit 0 |  | ||||||
| @ -1,16 +0,0 @@ | |||||||
| #!/bin/sh |  | ||||||
|  |  | ||||||
| install_docker() { |  | ||||||
|   echo "install_docker: TODO" |  | ||||||
| } |  | ||||||
| init_swarm() { |  | ||||||
|   echo "init_swarm: TODO" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| run_installation() { |  | ||||||
|   install_docker |  | ||||||
|   init_swarm |  | ||||||
| } |  | ||||||
|  |  | ||||||
| run_installation |  | ||||||
| exit 0 |  | ||||||
| @ -1,7 +0,0 @@ | |||||||
| --- |  | ||||||
| name: mystack |  | ||||||
| secrets: |  | ||||||
|   foo: |  | ||||||
|   bar: |  | ||||||
|   baz: |  | ||||||
|     length: 128 |  | ||||||
							
								
								
									
										17
									
								
								tests/01_environment.bats
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								tests/01_environment.bats
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | |||||||
|  | #!/usr/bin/env bats | ||||||
|  |  | ||||||
|  | @test "docker is available" { | ||||||
|  |     command -v docker | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @test "abra is executable" { | ||||||
|  |     ./abra --help | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @test "git is available" { | ||||||
|  |     command -v git | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @test "running in a container" { | ||||||
|  |     ls /etc/alpine-release | ||||||
|  | } | ||||||
							
								
								
									
										56
									
								
								tests/02_abra.bats
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								tests/02_abra.bats
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,56 @@ | |||||||
|  | #!/usr/bin/env bats | ||||||
|  |  | ||||||
|  | setup() { | ||||||
|  |     export ABRA_DIR=$(mktemp -d) | ||||||
|  |     mkdir -p $ABRA_DIR/servers/default | ||||||
|  | } | ||||||
|  |  | ||||||
|  | teardown() { | ||||||
|  |     rm -rf "$ABRA_DIR" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | abra() { | ||||||
|  |     ./abra -d $@ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @test "abra server (add|rm)" { | ||||||
|  |     abra server add swarm.test.com | ||||||
|  |     docker context ls | grep swarm.test.com | ||||||
|  |     [ -d $ABRA_DIR/servers/swarm.test.com ] | ||||||
|  |     abra server swarm.test.com rm | ||||||
|  |  | ||||||
|  |     abra server add swarm.test.com foobar 12345 | ||||||
|  |     [ -d $ABRA_DIR/servers/swarm.test.com ] | ||||||
|  |     abra server swarm.test.com rm | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @test "abra server init" { | ||||||
|  |     abra server default init | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @test "abra app (new|rm)" { | ||||||
|  |     abra app new --server default --domain traefik.test.com --app-name traefik_test_com traefik | ||||||
|  |     [ -f $ABRA_DIR/servers/default/traefik_test_com.env ] | ||||||
|  |  | ||||||
|  |     # interactive prompt | ||||||
|  |     echo "y" | abra app traefik_test_com delete | ||||||
|  |     [ ! -f $ABRA_DIR/servers/default/traefik_test_com.env ] | ||||||
|  |  | ||||||
|  |     # --no-prompt | ||||||
|  |     abra app new --server default --domain traefik_test_com --app-name traefik_test_com traefik | ||||||
|  |     abra --no-prompt app traefik_test_com delete | ||||||
|  |     [ ! -f $ABRA_DIR/servers/default/traefik_test_com.env ] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @test "abra app <domain> secret (insert|generate|rm)" { | ||||||
|  |     abra app new --server default --domain traefik_test_com --app-name traefik_test_com traefik | ||||||
|  |  | ||||||
|  |     abra app traefik_test_com secret insert foobar v1 "foobar" | ||||||
|  |  | ||||||
|  |     # interactive prompt | ||||||
|  |     echo "y" | abra app traefik_test_com secret rm foobar | ||||||
|  |  | ||||||
|  |     abra app traefik_test_com secret insert foobar v1 "foobar" | ||||||
|  |     #  prompt | ||||||
|  |     abra --no-prompt app traefik_test_com secret rm foobar | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user
	