mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
Compare commits
417 commits
debian/11.
...
dev
Author | SHA1 | Date | |
---|---|---|---|
|
a5049a8a13 | ||
|
6e84e3532a | ||
|
917cf251fb | ||
|
8a5f2808a1 | ||
68f35831e7 | |||
b91e9dd8f4 | |||
38b39ebaea | |||
ef17082768 | |||
e3ddb1dc4d | |||
|
5b37936d11 | ||
|
e82d20aa7b | ||
|
aff885e6b7 | ||
|
7a04462ccd | ||
|
606e246ec4 | ||
|
e3e8b903c7 | ||
|
488f563b45 | ||
|
3d4804be68 | ||
|
d4f774ad72 | ||
|
d8ab3e68a9 | ||
|
71b50549f5 | ||
|
a40874c305 | ||
|
9223d30a83 | ||
|
5ad9962757 | ||
|
4dfcc13a3f | ||
|
e11b61f49e | ||
|
243a34d2d5 | ||
|
ca2572d00b | ||
|
518c3bbbe2 | ||
|
9517b26c63 | ||
|
a6785d34bc | ||
|
7c79060467 | ||
|
007c13ce42 | ||
|
2102242a61 | ||
|
c409888a4b | ||
|
c14ebc8be4 | ||
|
9b0553580b | ||
|
bc2ed45e9d | ||
|
a76cd05e87 | ||
|
eb14e404d6 | ||
|
aae24614c4 | ||
|
51787a2f8b | ||
|
c5953b5420 | ||
|
4afff118e4 | ||
|
6113fde48a | ||
|
b734e2ea89 | ||
|
0a44d7cea4 | ||
|
5d3280c0fd | ||
|
8dc521a528 | ||
|
2e70143da2 | ||
|
3095496fe9 | ||
|
586d1c7f63 | ||
|
d63c61e0df | ||
|
4248b27b26 | ||
|
0f662d069c | ||
|
7ca710685e | ||
|
31d10079c7 | ||
|
980777ebf1 | ||
|
436826abf9 | ||
|
477fa63f46 | ||
|
9a6f7dac3b | ||
|
498006cab6 | ||
|
2f186b6f7f | ||
|
5708776df6 | ||
|
abdbb7efcd | ||
|
658ef88e47 | ||
|
4d5cc62540 | ||
|
f88e4cacdf | ||
|
36b9188aec | ||
|
c104dc6449 | ||
|
938e400865 | ||
|
de9980f31e | ||
|
f02d4a4376 | ||
|
92f4a605b8 | ||
|
df320a44cf | ||
|
6733526bee | ||
|
d0df3caed4 | ||
|
9083a5cc3d | ||
|
764fe6a7ba | ||
|
200f0272d5 | ||
|
9915559c40 | ||
|
760256f85d | ||
|
684c3d9b2c | ||
|
90c4034908 | ||
|
3deffdbd57 | ||
|
9f6f5f92fb | ||
|
e88ba3428c | ||
|
fe524dd866 | ||
|
65ea34d7cb | ||
|
d766f7cdda | ||
|
423e79bd57 | ||
|
44529b6d92 | ||
|
f4727d3cb6 | ||
|
8705dfcf5c | ||
|
ad98a10fa8 | ||
|
d376677db6 | ||
|
8b56983171 | ||
|
2d3dddc51a | ||
|
c861ef2ae6 | ||
|
53427e8c14 | ||
|
e5d74d420d | ||
|
cd30a2acc0 | ||
|
9e1b0561e3 | ||
|
843771ea05 | ||
|
ddf3e32c1c | ||
|
6d21e9fced | ||
|
d881d1a505 | ||
|
ebaecfcbd6 | ||
|
eeee096f3a | ||
|
fc168c54a1 | ||
|
b010219814 | ||
|
67c5edc40e | ||
|
437189d8c1 | ||
|
b2492ffc3d | ||
|
34861f906d | ||
|
a7edbc0cc7 | ||
|
b1d1f9f907 | ||
|
c90a691448 | ||
|
f6c270e1d2 | ||
|
3d53cf0467 | ||
|
7ee1734265 | ||
|
179daf68df | ||
|
57b4e240e1 | ||
|
bfbc7035dd | ||
|
239819b6da | ||
|
357896cd55 | ||
|
ded4892b9e | ||
|
9721685001 | ||
|
8395b066bc | ||
|
ac4ff0fc2d | ||
|
04101862ac | ||
|
0242ecd0e7 | ||
|
6e5c555e37 | ||
|
ebcf3c79ff | ||
|
f11f11973b | ||
|
67d6baa151 | ||
|
97bb6bde09 | ||
|
ca59886303 | ||
|
a8fd6afeee | ||
|
a5868733d7 | ||
|
079cdc2624 | ||
|
4232fc7c4b | ||
|
845a14bfe1 | ||
|
73e0d6c271 | ||
|
14312a9ec4 | ||
|
8a65053a59 | ||
|
64c8d9e853 | ||
|
22201863a1 | ||
|
bb20020c5a | ||
|
771a4b3446 | ||
|
beeddc7819 | ||
|
0907411efc | ||
|
d71d8fe7b3 | ||
|
9e8c7e704e | ||
|
85c5c04b15 | ||
|
a0bc7926c4 | ||
|
27ccd2918e | ||
|
588742f31b | ||
|
4112deda0c | ||
|
1e70577d23 | ||
|
623bd151d6 | ||
|
d87fe9fb4c | ||
|
bf8271e383 | ||
|
818fd78a3d | ||
|
eb012de188 | ||
|
725b41d2a3 | ||
|
85239f74f6 | ||
|
0b438eab02 | ||
|
3c992c894a | ||
|
a97c82d1c2 | ||
|
566213ecd5 | ||
|
5fb54936ba | ||
|
0b5c5a5f4d | ||
|
e8c171fd83 | ||
|
0bffcbae76 | ||
|
fbe42f1867 | ||
|
7121ed6836 | ||
|
e339006c69 | ||
|
a66890ddd8 | ||
|
e54e99bfb7 | ||
|
ab8e0e6619 | ||
|
401ccf69c7 | ||
|
e5bc94b9cf | ||
|
9c22d36c6f | ||
|
b266e398ff | ||
|
c8a18129df | ||
|
8be726b993 | ||
b96c530d2b | |||
bb25c6b15d | |||
|
a735a6d296 | ||
49961145ca | |||
b289de3eca | |||
26fba087d6 | |||
|
f6fbd69c39 | ||
|
1bb81e8f69 | ||
|
0f34d7e10f | ||
|
2763e04012 | ||
90d4cd99b9 | |||
f344cb037b | |||
|
c694ea2cbc | ||
|
772e772b24 | ||
|
b5e6f02d7d | ||
|
30286bc811 | ||
|
62f7e022ff | ||
|
ffde5cbf87 | ||
|
c6aec680b9 | ||
|
395dc6b843 | ||
|
fe8fcaefef | ||
|
d6aa310c21 | ||
|
5fcb1c6188 | ||
|
22d8c0c70a | ||
|
8de0a4cdcb | ||
|
6f73a82a2d | ||
|
ab742e55bb | ||
|
5d15c00d92 | ||
|
9a5aff9715 | ||
|
3e20cdd59e | ||
|
2edb6ad625 | ||
|
41ca422210 | ||
|
e55c914974 | ||
|
7c7e763a74 | ||
|
0f85ddbcff | ||
|
131760e30c | ||
|
7e55a791b6 | ||
|
2640dd3171 | ||
|
4e3f30ef82 | ||
|
bc3e36abb3 | ||
|
92807afb16 | ||
|
1ed56952e6 | ||
|
6b77e19bbd | ||
|
50034aabdd | ||
|
ef622ffe4d | ||
|
40a3205add | ||
|
7b0383f865 | ||
|
0783af306d | ||
|
36b3b00166 | ||
|
e75b4b3b3b | ||
|
1c62960e25 | ||
|
1e1409c7d7 | ||
|
fcaa366e91 | ||
|
f2b5f0f22c | ||
|
4b43d8d99d | ||
|
636c9e563e | ||
|
c0bccc3ac9 | ||
|
9727765ecf | ||
|
5ef0c84c0f | ||
|
c965f13f50 | ||
|
20741c63aa | ||
|
a48bfa67de | ||
|
3f973669fc | ||
|
a18d5f26f2 | ||
|
c2271ab731 | ||
|
eee84c5f66 | ||
|
6ed167bfaf | ||
|
eaf00103dd | ||
|
ff78f3ada7 | ||
|
fcbb971792 | ||
|
dbf579b7b4 | ||
|
e5b575901a | ||
|
d47c87e57d | ||
|
28603da4f1 | ||
|
c2d69f7f84 | ||
|
a349fc0334 | ||
|
3e1c9ebaf7 | ||
|
1ab3a79d39 | ||
|
44bbc34967 | ||
|
7b2959a3eb | ||
|
1dfc47d1d7 | ||
|
9cd7c86641 | ||
|
ef68485c5f | ||
|
656ff823a9 | ||
|
ae3018cdd0 | ||
|
8b8768fd77 | ||
|
75d7042974 | ||
|
3b26ccc2a5 | ||
|
3608c5678c | ||
|
d9d404a5b2 | ||
8846381d47 | |||
650481a58a | |||
|
87eedc2a36 | ||
|
feb9a095b3 | ||
|
997388dc79 | ||
|
9982a77582 | ||
|
2a7fefaecb | ||
|
7347b08e49 | ||
|
6851d740f7 | ||
|
2d26935079 | ||
|
094cd9ddd6 | ||
|
29ae71acad | ||
|
c9b76fde35 | ||
|
e3bebeac98 | ||
|
ed426f05ba | ||
|
2af4c157d9 | ||
|
0aad13cd2f | ||
|
2895d4d99b | ||
|
1fb80e5d24 | ||
|
30467f8bc3 | ||
|
d8c3ff4c8a | ||
|
0e4495f11e | ||
|
2b1f74268f | ||
|
5f6df6a859 | ||
|
b3409729a6 | ||
|
9298738d06 | ||
|
262453f132 | ||
|
d4857834f3 | ||
|
3942ea12ae | ||
|
a2ac77fa91 | ||
|
6ee40ac06a | ||
|
f26565d6de | ||
|
2e05b0894b | ||
|
18092db1c8 | ||
|
ecb82ec693 | ||
|
31ae5d1eaa | ||
|
be3df69326 | ||
|
7caf7e8b3e | ||
|
e558513609 | ||
|
3d728d90ce | ||
|
0bd69e5622 | ||
|
1b5074d857 | ||
|
dd8db1883a | ||
|
06c8fbc881 | ||
|
a25033bba5 | ||
|
2f933b5bf2 | ||
|
90dfccf278 | ||
|
b1b3c6eff8 | ||
|
2ee8d93f67 | ||
|
6605df6eb2 | ||
|
41b958113a | ||
e0a9bafde2 | |||
|
eab36d069d | ||
|
b47aedc932 | ||
|
f22c6ec3e9 | ||
|
d9b9aa1884 | ||
e12d79390f | |||
|
b8a1a3a660 | ||
|
6b6580a919 | ||
|
11e2b6d63c | ||
|
218bf107fb | ||
|
ec354d443d | ||
|
8f8070983d | ||
|
bd43a4504e | ||
|
156f9e54ba | ||
|
5a6a8e6c73 | ||
|
800f93d12e | ||
|
3584e6a5b1 | ||
|
50a4d08add | ||
|
d501131b34 | ||
|
66f667e48a | ||
|
47b2a5695f | ||
|
66508d5fd6 | ||
|
a8cd94d3db | ||
|
b4b420d694 | ||
|
fca26ead78 | ||
|
eb8ce2088b | ||
|
8c376c2ae4 | ||
|
0c319cbeba | ||
|
c5815fb1ef | ||
|
480366d5a1 | ||
|
50eea8fc14 | ||
|
4dc59049ef | ||
|
d1e1fd5e35 | ||
|
8c3ca4a0f4 | ||
|
0ceb77ec34 | ||
|
a123149bef | ||
|
8ad3a3bc6f | ||
|
2a6a8af0f7 | ||
|
fa848ff1c4 | ||
|
1b2d13f96a | ||
|
14ba98a232 | ||
|
29d6dd685a | ||
|
51d1011c47 | ||
259c7ac4a7 | |||
|
4d5ae9d32c | ||
|
05a02221b9 | ||
|
576e35321f | ||
|
f2f8b3e319 | ||
|
cbc68afea4 | ||
|
6e2b36d957 | ||
|
ef7da9e70f | ||
|
9b6ccb7b1f | ||
|
0273ee34b1 | ||
|
67477473e8 | ||
|
0eda746af5 | ||
|
701828bf45 | ||
|
307ed10c41 | ||
|
8117f438d4 | ||
|
5c461d6058 | ||
|
eb8db04629 | ||
|
727b0e093a | ||
|
3a1c8287b4 | ||
|
c6a7d3a591 | ||
|
80f07a9974 | ||
|
6835a664c7 | ||
|
346f42643b | ||
|
7c1b07ee0f | ||
|
88684c7937 | ||
|
84a7b23e8a | ||
|
70f5154130 | ||
|
3a500d8457 | ||
|
a240fb2316 | ||
|
f895724a25 | ||
|
8b59e315bf | ||
|
b79ff15d32 | ||
|
6b577bdd23 | ||
|
94c12c6409 | ||
|
1b03058858 | ||
|
422e02244d | ||
|
365d0b25af | ||
|
aa6634fd22 | ||
|
0915a6a70b | ||
|
4a74a7c51d | ||
|
6e13a4db1b | ||
|
b914ad9093 | ||
|
084ecd6578 | ||
|
204800e878 | ||
|
1c7e139c74 | ||
|
383fd6f5d4 | ||
|
bc30805c7d |
150 changed files with 9998 additions and 2484 deletions
|
@ -38,12 +38,17 @@ workflow:
|
|||
- if: $CI_COMMIT_TAG # For tags
|
||||
- if: $CI_COMMIT_REF_NAME == "ci-format-$CI_DEFAULT_BRANCH" # Ignore black formatting branch created by the CI
|
||||
when: never
|
||||
- if: $CI_COMMIT_REF_NAME == "actions/black" # Ignore black formatting branch created by the CI
|
||||
when: never
|
||||
- if: $CI_COMMIT_REF_NAME != $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "push" # If it's not the default branch and if it's a push, then do not trigger a build
|
||||
when: never
|
||||
- when: always
|
||||
|
||||
variables:
|
||||
YNH_BUILD_DIR: "/ynh-build"
|
||||
GIT_CLONE_PATH: '$CI_BUILDS_DIR/$CI_COMMIT_SHA/$CI_JOB_ID'
|
||||
YNH_SOURCE: "https://github.com/yunohost"
|
||||
YNH_DEBIAN: "bullseye"
|
||||
YNH_SKIP_DIAGNOSIS_DURING_UPGRADE: "true"
|
||||
|
||||
include:
|
||||
- template: Code-Quality.gitlab-ci.yml
|
||||
|
|
|
@ -1,21 +1,19 @@
|
|||
.build-stage:
|
||||
stage: build
|
||||
image: "before-install"
|
||||
image: "build-and-lint"
|
||||
variables:
|
||||
YNH_SOURCE: "https://github.com/yunohost"
|
||||
YNH_BUILD_DIR: "$GIT_CLONE_PATH/build"
|
||||
before_script:
|
||||
- mkdir -p $YNH_BUILD_DIR
|
||||
- DEBIAN_FRONTEND=noninteractive apt update
|
||||
artifacts:
|
||||
paths:
|
||||
- ./*.deb
|
||||
|
||||
.build_script: &build_script
|
||||
- DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" install devscripts --no-install-recommends
|
||||
- cd $YNH_BUILD_DIR/$PACKAGE
|
||||
- VERSION=$(dpkg-parsechangelog -S Version 2>/dev/null)
|
||||
- VERSION_NIGHTLY="${VERSION}+$(date +%Y%m%d%H%M)"
|
||||
- dch --package "${PACKAGE}" --force-bad-version -v "${VERSION_NIGHTLY}" -D "unstable" --force-distribution "Daily build."
|
||||
- VERSION_TIMESTAMPED="${VERSION}+$(date +%Y%m%d%H%M)"
|
||||
- dch --package "${PACKAGE}" --force-bad-version -v "${VERSION_TIMESTAMPED}" -D "unstable" --force-distribution "CI build."
|
||||
- debuild --no-lintian -us -uc
|
||||
- cp $YNH_BUILD_DIR/*.deb ${CI_PROJECT_DIR}/
|
||||
- cd ${CI_PROJECT_DIR}
|
||||
|
@ -36,14 +34,12 @@ build-yunohost:
|
|||
- DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $YNH_BUILD_DIR/$PACKAGE
|
||||
- *build_script
|
||||
|
||||
|
||||
build-ssowat:
|
||||
extends: .build-stage
|
||||
variables:
|
||||
PACKAGE: "ssowat"
|
||||
script:
|
||||
- DEBIAN_DEPENDS=$(cat debian/control | tr "," "\n" | grep -Po "ssowat \([>,=,<]+ .*\)" | grep -Po "[0-9\.]+")
|
||||
- git clone $YNH_SOURCE/$PACKAGE -b $CI_COMMIT_REF_NAME $YNH_BUILD_DIR/$PACKAGE --depth 1 || git clone $YNH_SOURCE/$PACKAGE -b $DEBIAN_DEPENDS $YNH_BUILD_DIR/$PACKAGE --depth 1 || git clone $YNH_SOURCE/$PACKAGE $YNH_BUILD_DIR/$PACKAGE --depth 1
|
||||
- git clone $YNH_SOURCE/$PACKAGE -b $CI_COMMIT_REF_NAME $YNH_BUILD_DIR/$PACKAGE --depth 1 || git clone $YNH_SOURCE/$PACKAGE -b $YNH_DEBIAN $YNH_BUILD_DIR/$PACKAGE --depth 1 || git clone $YNH_SOURCE/$PACKAGE $YNH_BUILD_DIR/$PACKAGE --depth 1
|
||||
- DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $YNH_BUILD_DIR/$PACKAGE
|
||||
- *build_script
|
||||
|
||||
|
@ -52,7 +48,6 @@ build-moulinette:
|
|||
variables:
|
||||
PACKAGE: "moulinette"
|
||||
script:
|
||||
- DEBIAN_DEPENDS=$(cat debian/control | tr "," "\n" | grep -Po "moulinette \([>,=,<]+ .*\)" | grep -Po "[0-9\.]+")
|
||||
- git clone $YNH_SOURCE/$PACKAGE -b $CI_COMMIT_REF_NAME $YNH_BUILD_DIR/$PACKAGE --depth 1 || git clone $YNH_SOURCE/$PACKAGE -b $DEBIAN_DEPENDS $YNH_BUILD_DIR/$PACKAGE --depth 1 || git clone $YNH_SOURCE/$PACKAGE $YNH_BUILD_DIR/$PACKAGE --depth 1
|
||||
- git clone $YNH_SOURCE/$PACKAGE -b $CI_COMMIT_REF_NAME $YNH_BUILD_DIR/$PACKAGE --depth 1 || git clone $YNH_SOURCE/$PACKAGE -b $YNH_DEBIAN $YNH_BUILD_DIR/$PACKAGE --depth 1 || git clone $YNH_SOURCE/$PACKAGE $YNH_BUILD_DIR/$PACKAGE --depth 1
|
||||
- DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $YNH_BUILD_DIR/$PACKAGE
|
||||
- *build_script
|
||||
|
|
|
@ -4,18 +4,19 @@
|
|||
|
||||
generate-helpers-doc:
|
||||
stage: doc
|
||||
image: "before-install"
|
||||
image: "build-and-lint"
|
||||
needs: []
|
||||
before_script:
|
||||
- apt-get update -y && apt-get install git hub -y
|
||||
- git config --global user.email "yunohost@yunohost.org"
|
||||
- git config --global user.name "$GITHUB_USER"
|
||||
script:
|
||||
- cd doc
|
||||
- python3 generate_helper_doc.py
|
||||
- python3 generate_helper_doc.py 2
|
||||
- python3 generate_helper_doc.py 2.1
|
||||
- python3 generate_resource_doc.py > resources.md
|
||||
- hub clone https://$GITHUB_TOKEN:x-oauth-basic@github.com/YunoHost/doc.git doc_repo
|
||||
- cp helpers.md doc_repo/pages/06.contribute/10.packaging_apps/20.scripts/10.helpers/packaging_app_scripts_helpers.md
|
||||
- cp helpers.v2.md doc_repo/pages/06.contribute/10.packaging_apps/20.scripts/10.helpers/packaging_app_scripts_helpers.md
|
||||
- cp helpers.v2.1.md doc_repo/pages/06.contribute/10.packaging_apps/20.scripts/12.helpers21/packaging_app_scripts_helpers_v21.md
|
||||
- cp resources.md doc_repo/pages/06.contribute/10.packaging_apps/10.manifest/10.appresources/packaging_app_manifest_resources.md
|
||||
- cd doc_repo
|
||||
# replace ${CI_COMMIT_REF_NAME} with ${CI_COMMIT_TAG} ?
|
||||
|
|
|
@ -14,9 +14,8 @@
|
|||
|
||||
upgrade:
|
||||
extends: .install-stage
|
||||
image: "after-install"
|
||||
image: "core-tests"
|
||||
script:
|
||||
- apt-get update -o Acquire::Retries=3
|
||||
- DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ${CI_PROJECT_DIR}/*.deb
|
||||
|
||||
|
||||
|
@ -24,6 +23,5 @@ install-postinstall:
|
|||
extends: .install-stage
|
||||
image: "before-install"
|
||||
script:
|
||||
- apt-get update -o Acquire::Retries=3
|
||||
- DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ${CI_PROJECT_DIR}/*.deb
|
||||
- yunohost tools postinstall -d domain.tld -u syssa -F 'Syssa Mine' -p the_password --ignore-dyndns --force-diskspace
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
lint39:
|
||||
stage: lint
|
||||
image: "before-install"
|
||||
image: "build-and-lint"
|
||||
needs: []
|
||||
allow_failure: true
|
||||
script:
|
||||
|
@ -13,14 +13,14 @@ lint39:
|
|||
|
||||
invalidcode39:
|
||||
stage: lint
|
||||
image: "before-install"
|
||||
image: "build-and-lint"
|
||||
needs: []
|
||||
script:
|
||||
- tox -e py39-invalidcode
|
||||
|
||||
mypy:
|
||||
stage: lint
|
||||
image: "before-install"
|
||||
image: "build-and-lint"
|
||||
needs: []
|
||||
script:
|
||||
- tox -e py39-mypy
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
.install_debs: &install_debs
|
||||
- apt-get update -o Acquire::Retries=3
|
||||
- DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ${CI_PROJECT_DIR}/*.deb
|
||||
- pip3 install -U mock pip pytest pytest-cov pytest-mock pytest-sugar requests-mock tox ansi2html black jinja2 "packaging<22"
|
||||
|
||||
.test-stage:
|
||||
stage: test
|
||||
image: "after-install"
|
||||
image: "core-tests"
|
||||
variables:
|
||||
PYTEST_ADDOPTS: "--color=yes"
|
||||
before_script:
|
||||
|
@ -34,6 +32,7 @@ full-tests:
|
|||
PYTEST_ADDOPTS: "--color=yes"
|
||||
before_script:
|
||||
- *install_debs
|
||||
- pip install mock pip pyOpenSSL pytest pytest-cov pytest-mock pytest-sugar requests-mock "packaging<22"
|
||||
- yunohost tools postinstall -d domain.tld -u syssa -F 'Syssa Mine' -p the_password --ignore-dyndns --force-diskspace
|
||||
script:
|
||||
- python3 -m pytest --cov=yunohost tests/ src/tests/ --junitxml=report.xml
|
||||
|
@ -57,14 +56,17 @@ test-actionmap:
|
|||
changes:
|
||||
- share/actionsmap.yml
|
||||
|
||||
test-helpers:
|
||||
test-helpers2:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- cd tests
|
||||
- bash test_helpers.sh
|
||||
# only:
|
||||
# changes:
|
||||
# - helpers/*
|
||||
|
||||
test-helpers2.1:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- cd tests
|
||||
- bash test_helpers.sh 2.1
|
||||
|
||||
test-domains:
|
||||
extends: .test-stage
|
||||
|
|
|
@ -13,10 +13,9 @@ test-i18n-keys:
|
|||
|
||||
autofix-translated-strings:
|
||||
stage: translation
|
||||
image: "before-install"
|
||||
image: "build-and-lint"
|
||||
needs: []
|
||||
before_script:
|
||||
- apt-get update -y && apt-get install git hub -y
|
||||
- git config --global user.email "yunohost@yunohost.org"
|
||||
- git config --global user.name "$GITHUB_USER"
|
||||
- hub clone --branch ${CI_COMMIT_REF_NAME} "https://$GITHUB_TOKEN:x-oauth-basic@github.com/YunoHost/yunohost.git" github_repo
|
||||
|
|
|
@ -69,7 +69,7 @@ then
|
|||
You should now proceed with YunoHost post-installation. This is where you will
|
||||
be asked for:
|
||||
- the main domain of your server;
|
||||
- the administration password.
|
||||
- the username and password for the first admin
|
||||
|
||||
You can perform this step:
|
||||
- from your web browser, by accessing: https://yunohost.local/ or ${local_ip}
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
VirtualHost "{{ domain }}"
|
||||
enable = true
|
||||
ssl = {
|
||||
key = "/etc/yunohost/certs/{{ domain }}/key.pem";
|
||||
certificate = "/etc/yunohost/certs/{{ domain }}/crt.pem";
|
||||
}
|
||||
authentication = "ldap2"
|
||||
ldap = {
|
||||
hostname = "localhost",
|
||||
user = {
|
||||
basedn = "ou=users,dc=yunohost,dc=org",
|
||||
filter = "(&(objectClass=posixAccount)(mail=*@{{ domain }})(permission=cn=xmpp.main,ou=permission,dc=yunohost,dc=org))",
|
||||
usernamefield = "mail",
|
||||
namefield = "cn",
|
||||
},
|
||||
}
|
||||
enable = true
|
||||
ssl = {
|
||||
key = "/etc/yunohost/certs/{{ domain }}/key.pem";
|
||||
certificate = "/etc/yunohost/certs/{{ domain }}/crt.pem";
|
||||
}
|
||||
authentication = "ldap2"
|
||||
ldap = {
|
||||
hostname = "localhost",
|
||||
user = {
|
||||
basedn = "ou=users,dc=yunohost,dc=org",
|
||||
filter = "(&(objectClass=posixAccount)(mail=*@{{ domain }})(permission=cn=xmpp.main,ou=permission,dc=yunohost,dc=org))",
|
||||
usernamefield = "mail",
|
||||
namefield = "cn",
|
||||
},
|
||||
}
|
||||
|
||||
-- Discovery items
|
||||
disco_items = {
|
||||
{ "muc.{{ domain }}" },
|
||||
{ "pubsub.{{ domain }}" },
|
||||
{ "jabber.{{ domain }}" },
|
||||
{ "vjud.{{ domain }}" },
|
||||
{ "xmpp-upload.{{ domain }}" },
|
||||
};
|
||||
-- Discovery items
|
||||
disco_items = {
|
||||
{ "muc.{{ domain }}" },
|
||||
{ "pubsub.{{ domain }}" },
|
||||
{ "jabber.{{ domain }}" },
|
||||
{ "vjud.{{ domain }}" },
|
||||
{ "xmpp-upload.{{ domain }}" },
|
||||
};
|
||||
|
||||
-- contact_info = {
|
||||
-- abuse = { "mailto:abuse@{{ domain }}", "xmpp:admin@{{ domain }}" };
|
||||
|
@ -35,41 +35,41 @@ VirtualHost "{{ domain }}"
|
|||
|
||||
---Set up a MUC (multi-user chat) room server
|
||||
Component "muc.{{ domain }}" "muc"
|
||||
name = "{{ domain }} Chatrooms"
|
||||
name = "{{ domain }} Chatrooms"
|
||||
|
||||
modules_enabled = {
|
||||
"muc_limits";
|
||||
"muc_log";
|
||||
"muc_log_mam";
|
||||
"muc_log_http";
|
||||
"muc_vcard";
|
||||
}
|
||||
modules_enabled = {
|
||||
"muc_limits";
|
||||
"muc_log";
|
||||
"muc_log_mam";
|
||||
"muc_log_http";
|
||||
"muc_vcard";
|
||||
}
|
||||
|
||||
muc_event_rate = 0.5
|
||||
muc_burst_factor = 10
|
||||
room_default_config = {
|
||||
logging = true,
|
||||
persistent = true
|
||||
};
|
||||
muc_event_rate = 0.5
|
||||
muc_burst_factor = 10
|
||||
room_default_config = {
|
||||
logging = true,
|
||||
persistent = true
|
||||
};
|
||||
|
||||
---Set up a PubSub server
|
||||
Component "pubsub.{{ domain }}" "pubsub"
|
||||
name = "{{ domain }} Publish/Subscribe"
|
||||
name = "{{ domain }} Publish/Subscribe"
|
||||
|
||||
unrestricted_node_creation = true -- Anyone can create a PubSub node (from any server)
|
||||
unrestricted_node_creation = true -- Anyone can create a PubSub node (from any server)
|
||||
|
||||
---Set up a HTTP Upload service
|
||||
Component "xmpp-upload.{{ domain }}" "http_upload"
|
||||
name = "{{ domain }} Sharing Service"
|
||||
name = "{{ domain }} Sharing Service"
|
||||
|
||||
http_file_path = "/var/xmpp-upload/{{ domain }}/upload"
|
||||
http_external_url = "https://xmpp-upload.{{ domain }}:443"
|
||||
http_file_base_path = "/upload"
|
||||
http_file_size_limit = 6*1024*1024
|
||||
http_file_quota = 60*1024*1024
|
||||
http_upload_file_size_limit = 100 * 1024 * 1024 -- bytes
|
||||
http_upload_quota = 10 * 1024 * 1024 * 1024 -- bytes
|
||||
http_file_path = "/var/xmpp-upload/{{ domain }}/upload"
|
||||
http_external_url = "https://xmpp-upload.{{ domain }}:443"
|
||||
http_file_base_path = "/upload"
|
||||
http_file_size_limit = 6*1024*1024
|
||||
http_file_quota = 60*1024*1024
|
||||
http_upload_file_size_limit = 100 * 1024 * 1024 -- bytes
|
||||
http_upload_quota = 10 * 1024 * 1024 * 1024 -- bytes
|
||||
|
||||
---Set up a VJUD service
|
||||
Component "vjud.{{ domain }}" "vjud"
|
||||
vjud_disco_name = "{{ domain }} User Directory"
|
||||
vjud_disco_name = "{{ domain }} User Directory"
|
||||
|
|
|
@ -1,72 +1,72 @@
|
|||
-- ** Metronome's config file example **
|
||||
--
|
||||
--
|
||||
-- The format is exactly equal to Prosody's:
|
||||
--
|
||||
-- Lists are written { "like", "this", "one" }
|
||||
-- Lists can also be of { 1, 2, 3 } numbers, etc.
|
||||
-- Lists are written { "like", "this", "one" }
|
||||
-- Lists can also be of { 1, 2, 3 } numbers, etc.
|
||||
-- Either commas, or semi-colons; may be used as seperators.
|
||||
--
|
||||
-- A table is a list of values, except each value has a name. An
|
||||
-- A table is a list of values, except each value has a name. An
|
||||
-- example would be:
|
||||
--
|
||||
-- ssl = { key = "keyfile.key", certificate = "certificate.cert" }
|
||||
--
|
||||
-- Tip: You can check that the syntax of this file is correct when you have finished
|
||||
-- by running: luac -p metronome.cfg.lua
|
||||
-- If there are any errors, it will let you know what and where they are, otherwise it
|
||||
-- If there are any errors, it will let you know what and where they are, otherwise it
|
||||
-- will keep quiet.
|
||||
|
||||
-- Global settings go in this section
|
||||
|
||||
|
||||
-- This is the list of modules Metronome will load on startup.
|
||||
-- It looks for mod_modulename.lua in the plugins folder, so make sure that exists too.
|
||||
|
||||
modules_enabled = {
|
||||
-- Generally required
|
||||
"roster"; -- Allow users to have a roster. Recommended.
|
||||
"saslauth"; -- Authentication for clients. Recommended if you want to log in.
|
||||
"tls"; -- Add support for secure TLS on c2s/s2s connections
|
||||
"disco"; -- Service discovery
|
||||
|
||||
-- Not essential, but recommended
|
||||
"private"; -- Private XML storage (for room bookmarks, etc.)
|
||||
"vcard"; -- Allow users to set vCards
|
||||
"pep"; -- Allows setting of mood, tune, etc.
|
||||
"pubsub"; -- Publish-subscribe XEP-0060
|
||||
"posix"; -- POSIX functionality, sends server to background, enables syslog, etc.
|
||||
"bidi"; -- Enables Bidirectional Server-to-Server Streams.
|
||||
|
||||
-- Nice to have
|
||||
"version"; -- Replies to server version requests
|
||||
"uptime"; -- Report how long server has been running
|
||||
"time"; -- Let others know the time here on this server
|
||||
"ping"; -- Replies to XMPP pings with pongs
|
||||
"register"; -- Allow users to register on this server using a client and change passwords
|
||||
"stream_management"; -- Allows clients and servers to use Stream Management
|
||||
"stanza_optimizations"; -- Allows clients to use Client State Indication and SIFT
|
||||
"message_carbons"; -- Allows clients to enable carbon copies of messages
|
||||
"mam"; -- Enable server-side message archives using Message Archive Management
|
||||
"push"; -- Enable Push Notifications via PubSub using XEP-0357
|
||||
"lastactivity"; -- Enables clients to know the last presence status of an user
|
||||
"adhoc_cm"; -- Allow to set client certificates to login through SASL External via adhoc
|
||||
"admin_adhoc"; -- administration adhoc commands
|
||||
"bookmarks"; -- XEP-0048 Bookmarks synchronization between PEP and Private Storage
|
||||
"sec_labels"; -- Allows to use a simplified version XEP-0258 Security Labels and related ACDFs.
|
||||
"privacy"; -- Add privacy lists and simple blocking command support
|
||||
-- Generally required
|
||||
"roster"; -- Allow users to have a roster. Recommended.
|
||||
"saslauth"; -- Authentication for clients. Recommended if you want to log in.
|
||||
"tls"; -- Add support for secure TLS on c2s/s2s connections
|
||||
"disco"; -- Service discovery
|
||||
|
||||
-- Other specific functionality
|
||||
--"admin_telnet"; -- administration console, telnet to port 5582
|
||||
--"admin_web"; -- administration web interface
|
||||
"bosh"; -- Enable support for BOSH clients, aka "XMPP over Bidirectional Streams over Synchronous HTTP"
|
||||
--"compression"; -- Allow clients to enable Stream Compression
|
||||
--"spim_block"; -- Require authorization via OOB form for messages from non-contacts and block unsollicited messages
|
||||
--"gate_guard"; -- Enable config-based blacklisting and hit-based auto-banning features
|
||||
--"incidents_handling"; -- Enable Incidents Handling support (can be administered via adhoc commands)
|
||||
--"server_presence"; -- Enables Server Buddies extension support
|
||||
--"service_directory"; -- Enables Service Directories extension support
|
||||
--"public_service"; -- Enables Server vCard support for public services in directories and advertises in features
|
||||
--"register_api"; -- Provides secure API for both Out-Of-Band and In-Band registration for E-Mail verification
|
||||
"websocket"; -- Enable support for WebSocket clients, aka "XMPP over WebSockets"
|
||||
-- Not essential, but recommended
|
||||
"private"; -- Private XML storage (for room bookmarks, etc.)
|
||||
"vcard"; -- Allow users to set vCards
|
||||
"pep"; -- Allows setting of mood, tune, etc.
|
||||
"pubsub"; -- Publish-subscribe XEP-0060
|
||||
"posix"; -- POSIX functionality, sends server to background, enables syslog, etc.
|
||||
"bidi"; -- Enables Bidirectional Server-to-Server Streams.
|
||||
|
||||
-- Nice to have
|
||||
"version"; -- Replies to server version requests
|
||||
"uptime"; -- Report how long server has been running
|
||||
"time"; -- Let others know the time here on this server
|
||||
"ping"; -- Replies to XMPP pings with pongs
|
||||
"register"; -- Allow users to register on this server using a client and change passwords
|
||||
"stream_management"; -- Allows clients and servers to use Stream Management
|
||||
"stanza_optimizations"; -- Allows clients to use Client State Indication and SIFT
|
||||
"message_carbons"; -- Allows clients to enable carbon copies of messages
|
||||
"mam"; -- Enable server-side message archives using Message Archive Management
|
||||
"push"; -- Enable Push Notifications via PubSub using XEP-0357
|
||||
"lastactivity"; -- Enables clients to know the last presence status of an user
|
||||
"adhoc_cm"; -- Allow to set client certificates to login through SASL External via adhoc
|
||||
"admin_adhoc"; -- administration adhoc commands
|
||||
"bookmarks"; -- XEP-0048 Bookmarks synchronization between PEP and Private Storage
|
||||
"sec_labels"; -- Allows to use a simplified version XEP-0258 Security Labels and related ACDFs.
|
||||
"privacy"; -- Add privacy lists and simple blocking command support
|
||||
|
||||
-- Other specific functionality
|
||||
--"admin_telnet"; -- administration console, telnet to port 5582
|
||||
--"admin_web"; -- administration web interface
|
||||
"bosh"; -- Enable support for BOSH clients, aka "XMPP over Bidirectional Streams over Synchronous HTTP"
|
||||
--"compression"; -- Allow clients to enable Stream Compression
|
||||
--"spim_block"; -- Require authorization via OOB form for messages from non-contacts and block unsollicited messages
|
||||
--"gate_guard"; -- Enable config-based blacklisting and hit-based auto-banning features
|
||||
--"incidents_handling"; -- Enable Incidents Handling support (can be administered via adhoc commands)
|
||||
--"server_presence"; -- Enables Server Buddies extension support
|
||||
--"service_directory"; -- Enables Service Directories extension support
|
||||
--"public_service"; -- Enables Server vCard support for public services in directories and advertises in features
|
||||
--"register_api"; -- Provides secure API for both Out-Of-Band and In-Band registration for E-Mail verification
|
||||
"websocket"; -- Enable support for WebSocket clients, aka "XMPP over WebSockets"
|
||||
};
|
||||
|
||||
-- Server PID
|
||||
|
@ -102,10 +102,10 @@ csi_config_queue_all_muc_messages_but_mentions = false;
|
|||
|
||||
-- Logging configuration
|
||||
log = {
|
||||
info = "/var/log/metronome/metronome.log"; -- Change 'info' to 'debug' for verbose logging
|
||||
error = "/var/log/metronome/metronome.err";
|
||||
-- "*syslog"; -- Uncomment this for logging to syslog
|
||||
-- "*console"; -- Log to the console, useful for debugging with daemonize=false
|
||||
info = "/var/log/metronome/metronome.log"; -- Change 'info' to 'debug' for verbose logging
|
||||
error = "/var/log/metronome/metronome.err";
|
||||
-- "*syslog"; -- Uncomment this for logging to syslog
|
||||
-- "*console"; -- Log to the console, useful for debugging with daemonize=false
|
||||
}
|
||||
|
||||
------ Components ------
|
||||
|
@ -114,7 +114,7 @@ log = {
|
|||
|
||||
---Set up a local BOSH service
|
||||
Component "localhost" "http"
|
||||
modules_enabled = { "bosh" }
|
||||
modules_enabled = { "bosh" }
|
||||
|
||||
----------- Virtual hosts -----------
|
||||
-- You need to add a VirtualHost entry for each domain you wish Metronome to serve.
|
||||
|
|
|
@ -23,68 +23,68 @@ if not ldap then
|
|||
end
|
||||
|
||||
function new_default_provider(host)
|
||||
local provider = { name = "ldap2" };
|
||||
log("debug", "initializing ldap2 authentication provider for host '%s'", host);
|
||||
local provider = { name = "ldap2" };
|
||||
log("debug", "initializing ldap2 authentication provider for host '%s'", host);
|
||||
|
||||
function provider.test_password(username, password)
|
||||
return ldap.bind(username, password);
|
||||
end
|
||||
function provider.test_password(username, password)
|
||||
return ldap.bind(username, password);
|
||||
end
|
||||
|
||||
function provider.user_exists(username)
|
||||
local params = ldap.getparams()
|
||||
function provider.user_exists(username)
|
||||
local params = ldap.getparams()
|
||||
|
||||
local filter = ldap.filter.combine_and(params.user.filter, params.user.usernamefield .. '=' .. username);
|
||||
if params.user.usernamefield == 'mail' then
|
||||
filter = ldap.filter.combine_and(params.user.filter, 'mail=' .. username .. '@*');
|
||||
end
|
||||
local filter = ldap.filter.combine_and(params.user.filter, params.user.usernamefield .. '=' .. username);
|
||||
if params.user.usernamefield == 'mail' then
|
||||
filter = ldap.filter.combine_and(params.user.filter, 'mail=' .. username .. '@*');
|
||||
end
|
||||
|
||||
return ldap.singlematch {
|
||||
base = params.user.basedn,
|
||||
filter = filter,
|
||||
};
|
||||
end
|
||||
return ldap.singlematch {
|
||||
base = params.user.basedn,
|
||||
filter = filter,
|
||||
};
|
||||
end
|
||||
|
||||
function provider.get_password(username)
|
||||
return nil, "Passwords unavailable for LDAP.";
|
||||
end
|
||||
function provider.get_password(username)
|
||||
return nil, "Passwords unavailable for LDAP.";
|
||||
end
|
||||
|
||||
function provider.set_password(username, password)
|
||||
return nil, "Passwords unavailable for LDAP.";
|
||||
end
|
||||
function provider.set_password(username, password)
|
||||
return nil, "Passwords unavailable for LDAP.";
|
||||
end
|
||||
|
||||
function provider.create_user(username, password)
|
||||
return nil, "Account creation/modification not available with LDAP.";
|
||||
end
|
||||
function provider.create_user(username, password)
|
||||
return nil, "Account creation/modification not available with LDAP.";
|
||||
end
|
||||
|
||||
function provider.get_sasl_handler(session)
|
||||
local testpass_authentication_profile = {
|
||||
session = session,
|
||||
plain_test = function(sasl, username, password, realm)
|
||||
return provider.test_password(username, password), true;
|
||||
end,
|
||||
order = { "plain_test" },
|
||||
};
|
||||
return new_sasl(module.host, testpass_authentication_profile);
|
||||
end
|
||||
function provider.get_sasl_handler(session)
|
||||
local testpass_authentication_profile = {
|
||||
session = session,
|
||||
plain_test = function(sasl, username, password, realm)
|
||||
return provider.test_password(username, password), true;
|
||||
end,
|
||||
order = { "plain_test" },
|
||||
};
|
||||
return new_sasl(module.host, testpass_authentication_profile);
|
||||
end
|
||||
|
||||
function provider.is_admin(jid)
|
||||
local admin_config = ldap.getparams().admin;
|
||||
function provider.is_admin(jid)
|
||||
local admin_config = ldap.getparams().admin;
|
||||
|
||||
if not admin_config then
|
||||
return;
|
||||
end
|
||||
if not admin_config then
|
||||
return;
|
||||
end
|
||||
|
||||
local ld = ldap:getconnection();
|
||||
local username = jsplit(jid);
|
||||
local filter = ldap.filter.combine_and(admin_config.filter, admin_config.namefield .. '=' .. username);
|
||||
local ld = ldap:getconnection();
|
||||
local username = jsplit(jid);
|
||||
local filter = ldap.filter.combine_and(admin_config.filter, admin_config.namefield .. '=' .. username);
|
||||
|
||||
return ldap.singlematch {
|
||||
base = admin_config.basedn,
|
||||
filter = filter,
|
||||
};
|
||||
end
|
||||
return ldap.singlematch {
|
||||
base = admin_config.basedn,
|
||||
filter = filter,
|
||||
};
|
||||
end
|
||||
|
||||
return provider;
|
||||
return provider;
|
||||
end
|
||||
|
||||
module:add_item("auth-provider", new_default_provider(module.host));
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
-- Prosody IM
|
||||
-- Copyright (C) 2008-2010 Matthew Wild
|
||||
-- Copyright (C) 2008-2010 Waqas Hussain
|
||||
--
|
||||
--
|
||||
-- This project is MIT/X11 licensed. Please see the
|
||||
-- COPYING file in the source package for more information.
|
||||
--
|
||||
|
@ -12,8 +12,8 @@ local st = require "util.stanza";
|
|||
local t_concat = table.concat;
|
||||
|
||||
local secure_auth_only = module:get_option("c2s_require_encryption")
|
||||
or module:get_option("require_encryption")
|
||||
or not(module:get_option("allow_unencrypted_plain_auth"));
|
||||
or module:get_option("require_encryption")
|
||||
or not(module:get_option("allow_unencrypted_plain_auth"));
|
||||
|
||||
local sessionmanager = require "core.sessionmanager";
|
||||
local usermanager = require "core.usermanager";
|
||||
|
@ -22,66 +22,65 @@ local resourceprep = require "util.encodings".stringprep.resourceprep;
|
|||
|
||||
module:add_feature("jabber:iq:auth");
|
||||
module:hook("stream-features", function(event)
|
||||
local origin, features = event.origin, event.features;
|
||||
if secure_auth_only and not origin.secure then
|
||||
-- Sorry, not offering to insecure streams!
|
||||
return;
|
||||
elseif not origin.username then
|
||||
features:tag("auth", {xmlns='http://jabber.org/features/iq-auth'}):up();
|
||||
end
|
||||
local origin, features = event.origin, event.features;
|
||||
if secure_auth_only and not origin.secure then
|
||||
-- Sorry, not offering to insecure streams!
|
||||
return;
|
||||
elseif not origin.username then
|
||||
features:tag("auth", {xmlns='http://jabber.org/features/iq-auth'}):up();
|
||||
end
|
||||
end);
|
||||
|
||||
module:hook("stanza/iq/jabber:iq:auth:query", function(event)
|
||||
local session, stanza = event.origin, event.stanza;
|
||||
local session, stanza = event.origin, event.stanza;
|
||||
|
||||
if session.type ~= "c2s_unauthed" then
|
||||
(session.sends2s or session.send)(st.error_reply(stanza, "cancel", "service-unavailable", "Legacy authentication is only allowed for unauthenticated client connections."));
|
||||
return true;
|
||||
end
|
||||
if session.type ~= "c2s_unauthed" then
|
||||
(session.sends2s or session.send)(st.error_reply(stanza, "cancel", "service-unavailable", "Legacy authentication is only allowed for unauthenticated client connections."));
|
||||
return true;
|
||||
end
|
||||
|
||||
if secure_auth_only and not session.secure then
|
||||
session.send(st.error_reply(stanza, "modify", "not-acceptable", "Encryption (SSL or TLS) is required to connect to this server"));
|
||||
return true;
|
||||
end
|
||||
|
||||
local username = stanza.tags[1]:child_with_name("username");
|
||||
local password = stanza.tags[1]:child_with_name("password");
|
||||
local resource = stanza.tags[1]:child_with_name("resource");
|
||||
if not (username and password and resource) then
|
||||
local reply = st.reply(stanza);
|
||||
session.send(reply:query("jabber:iq:auth")
|
||||
:tag("username"):up()
|
||||
:tag("password"):up()
|
||||
:tag("resource"):up());
|
||||
else
|
||||
username, password, resource = t_concat(username), t_concat(password), t_concat(resource);
|
||||
username = nodeprep(username);
|
||||
resource = resourceprep(resource)
|
||||
if not (username and resource) then
|
||||
session.send(st.error_reply(stanza, "modify", "bad-request"));
|
||||
return true;
|
||||
end
|
||||
if usermanager.test_password(username, session.host, password) then
|
||||
-- Authentication successful!
|
||||
local success, err = sessionmanager.make_authenticated(session, username);
|
||||
if success then
|
||||
local err_type, err_msg;
|
||||
success, err_type, err, err_msg = sessionmanager.bind_resource(session, resource);
|
||||
if not success then
|
||||
session.send(st.error_reply(stanza, err_type, err, err_msg));
|
||||
session.username, session.type = nil, "c2s_unauthed"; -- FIXME should this be placed in sessionmanager?
|
||||
return true;
|
||||
elseif resource ~= session.resource then -- server changed resource, not supported by legacy auth
|
||||
session.send(st.error_reply(stanza, "cancel", "conflict", "The requested resource could not be assigned to this session."));
|
||||
session:close(); -- FIXME undo resource bind and auth instead of closing the session?
|
||||
return true;
|
||||
end
|
||||
end
|
||||
session.send(st.reply(stanza));
|
||||
else
|
||||
session.send(st.error_reply(stanza, "auth", "not-authorized"));
|
||||
end
|
||||
end
|
||||
return true;
|
||||
if secure_auth_only and not session.secure then
|
||||
session.send(st.error_reply(stanza, "modify", "not-acceptable", "Encryption (SSL or TLS) is required to connect to this server"));
|
||||
return true;
|
||||
end
|
||||
|
||||
local username = stanza.tags[1]:child_with_name("username");
|
||||
local password = stanza.tags[1]:child_with_name("password");
|
||||
local resource = stanza.tags[1]:child_with_name("resource");
|
||||
if not (username and password and resource) then
|
||||
local reply = st.reply(stanza);
|
||||
session.send(reply:query("jabber:iq:auth")
|
||||
:tag("username"):up()
|
||||
:tag("password"):up()
|
||||
:tag("resource"):up());
|
||||
else
|
||||
username, password, resource = t_concat(username), t_concat(password), t_concat(resource);
|
||||
username = nodeprep(username);
|
||||
resource = resourceprep(resource)
|
||||
if not (username and resource) then
|
||||
session.send(st.error_reply(stanza, "modify", "bad-request"));
|
||||
return true;
|
||||
end
|
||||
if usermanager.test_password(username, session.host, password) then
|
||||
-- Authentication successful!
|
||||
local success, err = sessionmanager.make_authenticated(session, username);
|
||||
if success then
|
||||
local err_type, err_msg;
|
||||
success, err_type, err, err_msg = sessionmanager.bind_resource(session, resource);
|
||||
if not success then
|
||||
session.send(st.error_reply(stanza, err_type, err, err_msg));
|
||||
session.username, session.type = nil, "c2s_unauthed"; -- FIXME should this be placed in sessionmanager?
|
||||
return true;
|
||||
elseif resource ~= session.resource then -- server changed resource, not supported by legacy auth
|
||||
session.send(st.error_reply(stanza, "cancel", "conflict", "The requested resource could not be assigned to this session."));
|
||||
session:close(); -- FIXME undo resource bind and auth instead of closing the session?
|
||||
return true;
|
||||
end
|
||||
end
|
||||
session.send(st.reply(stanza));
|
||||
else
|
||||
session.send(st.error_reply(stanza, "auth", "not-authorized"));
|
||||
end
|
||||
end
|
||||
return true;
|
||||
end);
|
||||
|
||||
|
|
|
@ -43,35 +43,35 @@ end
|
|||
local get_alias_for_user;
|
||||
|
||||
do
|
||||
local user_cache;
|
||||
local last_fetch_time;
|
||||
local user_cache;
|
||||
local last_fetch_time;
|
||||
|
||||
local function populate_user_cache()
|
||||
local user_c = get_config(module.host, 'ldap').user;
|
||||
if not user_c then return; end
|
||||
local function populate_user_cache()
|
||||
local user_c = get_config(module.host, 'ldap').user;
|
||||
if not user_c then return; end
|
||||
|
||||
local ld = ldap.getconnection();
|
||||
local ld = ldap.getconnection();
|
||||
|
||||
local usernamefield = user_c.usernamefield;
|
||||
local namefield = user_c.namefield;
|
||||
local usernamefield = user_c.usernamefield;
|
||||
local namefield = user_c.namefield;
|
||||
|
||||
user_cache = {};
|
||||
user_cache = {};
|
||||
|
||||
for _, attrs in ld:search { base = user_c.basedn, scope = 'onelevel', filter = user_c.filter } do
|
||||
user_cache[attrs[usernamefield]] = attrs[namefield];
|
||||
end
|
||||
last_fetch_time = gettime();
|
||||
end
|
||||
for _, attrs in ld:search { base = user_c.basedn, scope = 'onelevel', filter = user_c.filter } do
|
||||
user_cache[attrs[usernamefield]] = attrs[namefield];
|
||||
end
|
||||
last_fetch_time = gettime();
|
||||
end
|
||||
|
||||
function get_alias_for_user(user)
|
||||
if last_fetch_time and last_fetch_time + CACHE_EXPIRY < gettime() then
|
||||
user_cache = nil;
|
||||
end
|
||||
if not user_cache then
|
||||
populate_user_cache();
|
||||
end
|
||||
return user_cache[user];
|
||||
end
|
||||
function get_alias_for_user(user)
|
||||
if last_fetch_time and last_fetch_time + CACHE_EXPIRY < gettime() then
|
||||
user_cache = nil;
|
||||
end
|
||||
if not user_cache then
|
||||
populate_user_cache();
|
||||
end
|
||||
return user_cache[user];
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------
|
||||
|
@ -79,18 +79,18 @@ end
|
|||
----------------------------------------
|
||||
|
||||
local function ldap_store(config)
|
||||
local self = {};
|
||||
local config = config;
|
||||
local self = {};
|
||||
local config = config;
|
||||
|
||||
function self:get(username)
|
||||
return nil, "Data getting is not available for this storage backend";
|
||||
end
|
||||
function self:get(username)
|
||||
return nil, "Data getting is not available for this storage backend";
|
||||
end
|
||||
|
||||
function self:set(username, data)
|
||||
return nil, "Data setting is not available for this storage backend";
|
||||
end
|
||||
function self:set(username, data)
|
||||
return nil, "Data setting is not available for this storage backend";
|
||||
end
|
||||
|
||||
return self;
|
||||
return self;
|
||||
end
|
||||
|
||||
local adapters = {};
|
||||
|
@ -100,60 +100,60 @@ local adapters = {};
|
|||
----------------------------------------
|
||||
|
||||
adapters.roster = function (config)
|
||||
-- Validate configuration requirements
|
||||
if not config.groups then return nil; end
|
||||
-- Validate configuration requirements
|
||||
if not config.groups then return nil; end
|
||||
|
||||
local self = ldap_store(config)
|
||||
local self = ldap_store(config)
|
||||
|
||||
function self:get(username)
|
||||
local ld = ldap.getconnection();
|
||||
local contacts = {};
|
||||
function self:get(username)
|
||||
local ld = ldap.getconnection();
|
||||
local contacts = {};
|
||||
|
||||
local memberfield = config.groups.memberfield;
|
||||
local namefield = config.groups.namefield;
|
||||
local filter = memberfield .. '=' .. tostring(username);
|
||||
local memberfield = config.groups.memberfield;
|
||||
local namefield = config.groups.namefield;
|
||||
local filter = memberfield .. '=' .. tostring(username);
|
||||
|
||||
local groups = {};
|
||||
for _, config in ipairs(config.groups) do
|
||||
groups[ config[namefield] ] = config.name;
|
||||
end
|
||||
local groups = {};
|
||||
for _, config in ipairs(config.groups) do
|
||||
groups[ config[namefield] ] = config.name;
|
||||
end
|
||||
|
||||
log("debug", "Found %d group(s) for user %s", select('#', groups), username)
|
||||
log("debug", "Found %d group(s) for user %s", select('#', groups), username)
|
||||
|
||||
-- XXX this kind of relies on the way we do groups at INOC
|
||||
for _, attrs in ld:search { base = config.groups.basedn, scope = 'onelevel', filter = filter } do
|
||||
if groups[ attrs[namefield] ] then
|
||||
local members = attrs[memberfield];
|
||||
-- XXX this kind of relies on the way we do groups at INOC
|
||||
for _, attrs in ld:search { base = config.groups.basedn, scope = 'onelevel', filter = filter } do
|
||||
if groups[ attrs[namefield] ] then
|
||||
local members = attrs[memberfield];
|
||||
|
||||
for _, user in ipairs(members) do
|
||||
if user ~= username then
|
||||
local jid = user .. '@' .. module.host;
|
||||
local record = contacts[jid];
|
||||
for _, user in ipairs(members) do
|
||||
if user ~= username then
|
||||
local jid = user .. '@' .. module.host;
|
||||
local record = contacts[jid];
|
||||
|
||||
if not record then
|
||||
record = {
|
||||
subscription = 'both',
|
||||
groups = {},
|
||||
name = get_alias_for_user(user),
|
||||
};
|
||||
contacts[jid] = record;
|
||||
end
|
||||
if not record then
|
||||
record = {
|
||||
subscription = 'both',
|
||||
groups = {},
|
||||
name = get_alias_for_user(user),
|
||||
};
|
||||
contacts[jid] = record;
|
||||
end
|
||||
|
||||
record.groups[ groups[ attrs[namefield] ] ] = true;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
record.groups[ groups[ attrs[namefield] ] ] = true;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return contacts;
|
||||
end
|
||||
return contacts;
|
||||
end
|
||||
|
||||
function self:set(username, data)
|
||||
log("warn", "Setting data in Roster LDAP storage is not supported yet")
|
||||
return nil, "not supported";
|
||||
end
|
||||
function self:set(username, data)
|
||||
log("warn", "Setting data in Roster LDAP storage is not supported yet")
|
||||
return nil, "not supported";
|
||||
end
|
||||
|
||||
return self;
|
||||
return self;
|
||||
end
|
||||
|
||||
----------------------------------------
|
||||
|
@ -161,35 +161,35 @@ end
|
|||
----------------------------------------
|
||||
|
||||
adapters.vcard = function (config)
|
||||
-- Validate configuration requirements
|
||||
if not config.vcard_format or not config.user then return nil; end
|
||||
-- Validate configuration requirements
|
||||
if not config.vcard_format or not config.user then return nil; end
|
||||
|
||||
local self = ldap_store(config)
|
||||
local self = ldap_store(config)
|
||||
|
||||
function self:get(username)
|
||||
local ld = ldap.getconnection();
|
||||
local filter = config.user.usernamefield .. '=' .. tostring(username);
|
||||
function self:get(username)
|
||||
local ld = ldap.getconnection();
|
||||
local filter = config.user.usernamefield .. '=' .. tostring(username);
|
||||
|
||||
log("debug", "Retrieving vCard for user '%s'", username);
|
||||
log("debug", "Retrieving vCard for user '%s'", username);
|
||||
|
||||
local match = ldap.singlematch {
|
||||
base = config.user.basedn,
|
||||
filter = filter,
|
||||
};
|
||||
if match then
|
||||
match.jid = username .. '@' .. module.host
|
||||
return st.preserialize(ldap_record_to_vcard(match, config.vcard_format));
|
||||
else
|
||||
return nil, "username not found";
|
||||
end
|
||||
end
|
||||
local match = ldap.singlematch {
|
||||
base = config.user.basedn,
|
||||
filter = filter,
|
||||
};
|
||||
if match then
|
||||
match.jid = username .. '@' .. module.host
|
||||
return st.preserialize(ldap_record_to_vcard(match, config.vcard_format));
|
||||
else
|
||||
return nil, "username not found";
|
||||
end
|
||||
end
|
||||
|
||||
function self:set(username, data)
|
||||
log("warn", "Setting data in vCard LDAP storage is not supported yet")
|
||||
return nil, "not supported";
|
||||
end
|
||||
function self:set(username, data)
|
||||
log("warn", "Setting data in vCard LDAP storage is not supported yet")
|
||||
return nil, "not supported";
|
||||
end
|
||||
|
||||
return self;
|
||||
return self;
|
||||
end
|
||||
|
||||
----------------------------------------
|
||||
|
|
|
@ -135,28 +135,28 @@ function builder_methods:build()
|
|||
end
|
||||
|
||||
local function new_builder(params)
|
||||
local vcard_tag = st.stanza('vCard', { xmlns = VCARD_NS });
|
||||
local vcard_tag = st.stanza('vCard', { xmlns = VCARD_NS });
|
||||
|
||||
local object = {
|
||||
vcard = vcard_tag,
|
||||
__index = builder_methods,
|
||||
};
|
||||
local object = {
|
||||
vcard = vcard_tag,
|
||||
__index = builder_methods,
|
||||
};
|
||||
|
||||
for k, v in pairs(params) do
|
||||
object[k] = v;
|
||||
end
|
||||
for k, v in pairs(params) do
|
||||
object[k] = v;
|
||||
end
|
||||
|
||||
setmetatable(object, object);
|
||||
setmetatable(object, object);
|
||||
|
||||
return object;
|
||||
return object;
|
||||
end
|
||||
|
||||
local _M = {};
|
||||
|
||||
function _M.create(params)
|
||||
local builder = new_builder(params);
|
||||
local builder = new_builder(params);
|
||||
|
||||
return builder:build();
|
||||
return builder:build();
|
||||
end
|
||||
|
||||
return _M;
|
||||
|
|
|
@ -107,12 +107,11 @@ virtual_alias_domains =
|
|||
virtual_minimum_uid = 100
|
||||
virtual_uid_maps = static:vmail
|
||||
virtual_gid_maps = static:mail
|
||||
smtpd_sender_login_maps=
|
||||
smtpd_sender_login_maps = unionmap:{
|
||||
# Regular Yunohost accounts
|
||||
ldap:/etc/postfix/ldap-accounts.cf,
|
||||
# Extra maps for app system users who need to send emails
|
||||
hash:/etc/postfix/app_senders_login_maps
|
||||
|
||||
hash:/etc/postfix/app_senders_login_maps }
|
||||
|
||||
# Dovecot LDA
|
||||
virtual_transport = dovecot
|
||||
|
@ -212,3 +211,11 @@ smtp_sasl_security_options = noanonymous
|
|||
# where to find sasl_passwd
|
||||
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
|
||||
{% endif %}
|
||||
|
||||
{% if backup_mx_domains != "" %}
|
||||
# Backup MX (secondary MX)
|
||||
relay_domains = $mydestination {{backup_mx_domains}}
|
||||
relay_recipient_maps = hash:/etc/postfix/relay_recipients
|
||||
maximal_queue_lifetime = 20d
|
||||
{% endif %}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ SLAPD_PIDFILE=
|
|||
# sockets.
|
||||
# Example usage:
|
||||
# SLAPD_SERVICES="ldap://127.0.0.1:389/ ldaps:/// ldapi:///"
|
||||
SLAPD_SERVICES="ldap://127.0.0.1:389/ ldaps:/// ldapi:///"
|
||||
SLAPD_SERVICES="ldap://localhost:389/ ldaps:/// ldapi:///"
|
||||
|
||||
# If SLAPD_NO_START is set, the init script will not start or restart
|
||||
# slapd (but stop will still work). Uncomment this if you are
|
||||
|
|
|
@ -84,7 +84,7 @@ Subsystem sftp internal-sftp
|
|||
|
||||
# Apply following instructions to user with sftp perm only
|
||||
Match Group sftp.main,!ssh.main
|
||||
ForceCommand internal-sftp
|
||||
ForceCommand internal-sftp -u 0002
|
||||
# We can't restrict to /home/%u because the chroot base must be owned by root
|
||||
# So we chroot only on /home
|
||||
# See https://serverfault.com/questions/584986/bad-ownership-or-modes-for-chroot-directory-component
|
||||
|
@ -97,7 +97,7 @@ Match Group sftp.main,!ssh.main
|
|||
PermitUserRC no
|
||||
|
||||
Match Group sftp.app,!ssh.app
|
||||
ForceCommand internal-sftp
|
||||
ForceCommand internal-sftp -u 0002
|
||||
ChrootDirectory %h
|
||||
AllowTcpForwarding no
|
||||
AllowStreamLocalForwarding no
|
||||
|
|
240
debian/changelog
vendored
240
debian/changelog
vendored
|
@ -1,3 +1,243 @@
|
|||
yunohost (11.2.30) stable; urgency=low
|
||||
|
||||
- helpers v2.1: check if patches dir exists before getting realpath ([#1938](http://github.com/YunoHost/yunohost/pull/1938))
|
||||
- helpers v2.1: ynh_add_swap and ynh_smart_mktemp (aff885e6b)
|
||||
- helpers v2.1: fix ynh_restore_everything ([#1943](http://github.com/YunoHost/yunohost/pull/1943))
|
||||
- helpers v2.1: fix typo in docs: ynh_install_app_dependencies -> ynh_apt_install_dependencies ([#1939](http://github.com/YunoHost/yunohost/pull/1939))
|
||||
- helpers: fix syntax, disambiguate subshell syntax ([#1940](http://github.com/YunoHost/yunohost/pull/1940))
|
||||
- quality: Add maintenante/shfmt.sh for shell script formatting (68f35831e)
|
||||
- quality: Apply shfmt everywhere, fix tabs/space/indent (8a5f2808a, e3ddb1dc4, ef1708276, 38b39ebae, b91e9dd8f)
|
||||
|
||||
Thanks to all contributors <3 ! (Félix Piédallu, Josué Tille, OniriCorpe, selfhoster1312)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sat, 31 Aug 2024 19:26:59 +0200
|
||||
|
||||
yunohost (11.2.29) stable; urgency=low
|
||||
|
||||
- apps: generalize replacing __INSTALL_DIR__ and __APP__ in config panel 'bind' statement to any setting (9b0553580)
|
||||
- apps/config panels: move the computation of the actual 'bind' value to the python core (a6785d34b)
|
||||
- perf: add cache for _get_app_settings() (c14ebc8be, 7c7906046)
|
||||
- quality: use _assert_is_installed for consistency instead of if not _is_intalled(app): raise (c409888a4)
|
||||
- i18n: Translations updated for Basque, French, Galician, Greek, Indonesian
|
||||
|
||||
Thanks to all contributors <3 ! (cjdw, craftrac, José M, ppr, xabirequejo)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Tue, 27 Aug 2024 14:46:26 +0200
|
||||
|
||||
yunohost (11.2.28) stable; urgency=low
|
||||
|
||||
- ci: various changes due to CI infrastructure changes (200f0272d, 764fe6a7b, 9083a5cc3, d0df3caed, 6733526be, df320a44c, 92f4a605b, f02d4a437, c5953b542)
|
||||
- apps: exclude .well-known subpaths from conflict checks ([#1647](http://github.com/YunoHost/yunohost/pull/1647))
|
||||
- apps: in apt resource, fix empty string in packages_from_raw_bash breaking dpkg-build (a76cd05e8)
|
||||
- sftp: Tweak umask for SFTP ([#1384](http://github.com/YunoHost/yunohost/pull/1384))
|
||||
- mail: Be able to use postfix as a backup ("secondary") MX hosts ([#1253](http://github.com/YunoHost/yunohost/pull/1253))
|
||||
- diagnosis: Add check regarding rfkill blocking Wi-Fi card on RPi ([#1841](http://github.com/YunoHost/yunohost/pull/1841))
|
||||
- users: trigger hooks when adding or removing user into group (51787a2f8)
|
||||
- i18n: Translations updated for Basque, French, Indonesian, Russian
|
||||
|
||||
Thanks to all contributors <3 ! (cjdw, Emmanuel Averty, Ivan Davydov, ljf, ppr, Tagada, tituspijean, xabirequejo)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sun, 25 Aug 2024 13:17:43 +0200
|
||||
|
||||
yunohost (11.2.27) stable; urgency=low
|
||||
|
||||
- apt resource: fix handling of empty 'packages' list breaking dpkg-deb call (3deffdbd5)
|
||||
- i18n: Translations updated for Indonesian, Turkish
|
||||
|
||||
Thanks to all contributors <3 ! (Ali Çırçır, cjdw)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sat, 03 Aug 2024 18:41:27 +0200
|
||||
|
||||
yunohost (11.2.26) stable; urgency=low
|
||||
|
||||
- bullseye->bookworm: encourage apt to remove luajit if it's installed because for some reason it's causing issues (423e79bd5)
|
||||
- bullseye->bookworm: have a specific step dedicated to upgrade python3.9 to 3.11 because apt(itude) is derping about it sometimes... (d766f7cdd)
|
||||
- bullseye->bookworm: boring tweak to remove chattr +i from /etc/resolv.conf otherwise resolvconf will later explode and complain about it (65ea34d7c)
|
||||
- Fix yunomprompt not being enable after ISO install (fe524dd86)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 01 Aug 2024 18:05:33 +0200
|
||||
|
||||
yunohost (11.2.25) stable; urgency=low
|
||||
|
||||
- diagnosis: be more robust when diagnosis DMARC records not containing '=' (d376677db)
|
||||
- bullseye->bookworm: explicitly import _strptime at the beginning to try to prevent "No module named '_strptime'" during migration (2d3dddc51)
|
||||
- bullseye->bookworm: explicitly validate that we're on yunohost 12.x at the end of the migration (8b5698317)
|
||||
- bullseye->bookworm: make sure the non-free / non-free-firmware stuff is idempotent (ad98a10fa)
|
||||
- bullseye->bookworm: in debian control, add rule that moulinette and ssowat must be < 12 to prevent situation in bullseye->bookworm transition where moulinette gets upgrade but yunohost doesnt and everything explodes (8705dfcf5)
|
||||
- bullseye->bookworm: more stuff to try to prevent aptitude derping about python dependencies (f4727d3cb)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Tue, 30 Jul 2024 17:12:12 +0200
|
||||
|
||||
yunohost (11.2.24) stable; urgency=low
|
||||
|
||||
- ci: we don't care about mypy in tests/ folder (ebaecfcbd)
|
||||
- helpers: fix install from equivs ([#1921](http://github.com/YunoHost/yunohost/pull/1921))
|
||||
- bullseye->bookworm: re-add tweak about libluajit2 + be more robust about full-upgrade that may fail if python3.9-venv aint installed (9e1b0561e)
|
||||
- i18n: Translations updated for Indonesian
|
||||
|
||||
Thanks to all contributors <3 ! (cjdw, Kayou)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Fri, 26 Jul 2024 21:01:23 +0200
|
||||
|
||||
yunohost (11.2.23) stable; urgency=low
|
||||
|
||||
- helpers2.1: force sourcing getopts before the other helpers to prevent stupid issues (in particular when renaming phpversion to php_version) (3d53cf04)
|
||||
- diagnosis: Remove SenderScore from the dnsbl_list.yml file ([#1918](http://github.com/YunoHost/yunohost/pull/1918))
|
||||
- ldap: make slapd listen also on ipv6 ([#1916](http://github.com/YunoHost/yunohost/pull/1916))
|
||||
- log: zzz fix log list again (b2492ffc)
|
||||
- i18n: Translations updated for Galician, Indonesian, Slovak
|
||||
|
||||
Thanks to all contributors <3 ! (cjdw, Étienne Deparis, José M, Jose Riha, Josué Tille)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Tue, 23 Jul 2024 19:07:20 +0200
|
||||
|
||||
yunohost (11.2.22) stable; urgency=low
|
||||
|
||||
- logs: fix "log list" : use root_dir for iglob / make sure we use absolute paths ([#1913](http://github.com/YunoHost/yunohost/pull/1913))
|
||||
- bullseye->bookworm: remove pkg_resources from pip freeze ([#1912](http://github.com/YunoHost/yunohost/pull/1912))
|
||||
- bullseye->bookworm: explicitly install yunohost-portal (4232fc7c)
|
||||
- bullseye->bookworm: explicitly remove python3.9 and python3.9-venv which seems to confuse aptitude... (079cdc26)
|
||||
- bullseye->bookworm: try the yunohost upgrade without unholding the app-ynh-deps virtual packages, then after unholding if it didnt work for some reason (a8fd6afe)
|
||||
- bullseye->bookworm: automatically add non-free-firmware if non-free is enabled (97bb6bde)
|
||||
- bullseye->bookworm: trigger the 'new' migrations from inside the bullseye->bookworm migration (f11f1197)
|
||||
- i18n: Translations updated for Basque, French, Indonesian
|
||||
|
||||
Thanks to all contributors <3 ! (Anonymous, cjdw, Kayou, ppr, xabirequejo)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Fri, 19 Jul 2024 16:51:55 +0200
|
||||
|
||||
yunohost (11.2.21.2) stable; urgency=low
|
||||
|
||||
- bullseye->bookworm migration: tweak message to reflect the fact that metronome and rspamd will be applications starting with bookworm (64c8d9e8)
|
||||
- helpers/apt: unbound variable (8a65053a)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 15 Jul 2024 23:07:08 +0200
|
||||
|
||||
yunohost (11.2.21.1) stable; urgency=low
|
||||
|
||||
- helpers2.1: forgot to patch ynh_remove_fpm_config -> ynh_config_remove_phpfpm (bb20020c)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 15 Jul 2024 22:13:39 +0200
|
||||
|
||||
yunohost (11.2.21) stable; urgency=low
|
||||
|
||||
- log: optimize log list perf by creating a 'cache' symlink pointing to the log's parent ([#1907](http://github.com/YunoHost/yunohost/pull/1907))
|
||||
- log: small hack when dumping log right after script failure, prevent a weird edge case where it'll dump the log of the resource provisioning instead of the script (1bb81e8f)
|
||||
- debian: Bullseye->Bookworm migration ('hidden' but easier to test) ([#1759](http://github.com/YunoHost/yunohost/pull/1759), ab8e0e66, e54e99bf)
|
||||
- helpers/apt: rely on simpler dpkg-deb --build rather than equivs to create .deb for app virtual dependencies (f6fbd69c, 8be726b9)
|
||||
- helpers/apt: Support apt repositories with [trusted=yes] ([#1903](http://github.com/YunoHost/yunohost/pull/1903))
|
||||
- backups: one should be able to restore a backup archive by providing a path to the archive without moving it to /home/yunohost.backup/archives/ (c8a18129, b266e398)
|
||||
- backups: yunohost should not ask confirmation that 'YunoHost is already installed' when restoring only apps (9c22d36c)
|
||||
- i18n: translate _diagnosis_ignore function ([#1894](http://github.com/YunoHost/yunohost/pull/1894))
|
||||
- i18n: Translations updated for Basque, Catalan, French, Galician, German, Indonesian, Japanese, Russian, Spanish, Ukrainian
|
||||
|
||||
Thanks to all contributors <3 ! (alexAubin, Anonymous, cjdw, Félix Piédallu, Ivan Davydov, José M, Kayou, OniriCorpe, ppr, Zwiebel)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 15 Jul 2024 16:22:26 +0200
|
||||
|
||||
yunohost (11.2.20.2) stable; urgency=low
|
||||
|
||||
- Fix service enable/disable auto-ignoring diagnosis entries ([#1886](http://github.com/YunoHost/yunohost/pull/1886))
|
||||
|
||||
Thanks to all contributors <3 ! (OniriCorpe)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Wed, 03 Jul 2024 21:51:50 +0200
|
||||
|
||||
yunohost (11.2.20.1) stable; urgency=low
|
||||
|
||||
- helpers2.1: typo (1ed56952e)
|
||||
- helpers2.1: add unit tests (92807afb1)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 01 Jul 2024 23:38:29 +0200
|
||||
|
||||
yunohost (11.2.20) stable; urgency=low
|
||||
|
||||
- helpers2.1: fix automigration of phpversion to php_version (3f973669)
|
||||
- helpers2.1: change source patches location + raise an error instead of a warning when a patch fails to apply on CI (a48bfa67)
|
||||
- helpers2.1: when using ynh_die, also return the error via YNH_STDRETURN such that it can be obtained from the python and displayed in the main error message, to increase the chance that people may read it and have something more useful than "An error happened in the script" (f2b5f0f2)
|
||||
- helpers2.1: remove the ynh_clean_setup mechanism underused/useless.. (1c62960e)
|
||||
- helpers2.1: switch to posisional args for ynh_multimedia_addaccess because that's what 99% of apps already do (ef622ffe)
|
||||
- helpers2.1: add support for downloading .tar files ([#1889](http://github.com/YunoHost/yunohost/pull/1889))
|
||||
- services/diagnosis: automatically ignore the service in diagnosis if it has been deactivated with the ynh cli ([#1886](http://github.com/YunoHost/yunohost/pull/1886))
|
||||
|
||||
Thanks to all contributors <3 ! (alexAubin, OniriCorpe, Sebastian Gumprich)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 01 Jul 2024 18:46:52 +0200
|
||||
|
||||
yunohost (11.2.19) stable; urgency=low
|
||||
|
||||
- apps: tweaks to be more robust and prevent the stupid flood of 'sh: 0: getcwd() failed: No such file or directory' when running an app upgrade/remove from /var/www/$app, sometimes making it look like the upgrade failed when it didnt (a349fc03)
|
||||
- apps: be more robust when an app upgrade succeeds but for some reason is marked with 'broke the system' ... ending up in inconsistent state between the app settings vs the app scritpts (for example in v1->v2 transitions but not only) (e5b57590)
|
||||
- helpers2.1: Fix getopts error handling ... (3e1c9eba)
|
||||
- helpers2.1: also run _ynh_apply_default_permissions in ynh_restore to be consistent (also because the user uid on the new system may be different than in the archive etc) (eee84c5f)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sat, 29 Jun 2024 23:55:52 +0200
|
||||
|
||||
yunohost (11.2.18) stable; urgency=low
|
||||
|
||||
- helpers2.1: Rework _ynh_apply_default_permissions to hopefully remove the necessity to chown/chmod in the app scripts ([#1883](http://github.com/YunoHost/yunohost/pull/1883))
|
||||
- helpers2.1: in logrotate, make sure to also chown $app the log dir (1dfc47d1d)
|
||||
- helpers2.1: forgot to rename the apt call in mongodb helpers (7b2959a3e)
|
||||
- helpers2.1: in ynh_safe_rm, check if target is not a broken symlink before erorring out ([#1716](http://github.com/YunoHost/yunohost/pull/1716))
|
||||
|
||||
Thanks to all contributors <3 ! (Félix Piédallu)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sat, 29 Jun 2024 18:05:04 +0200
|
||||
|
||||
yunohost (11.2.17.1) stable; urgency=low
|
||||
|
||||
- helpers2.1: fix __PATH__/ handling (997388dc)
|
||||
- ci: Fix helpers 2.1 doc location (7347b08e)
|
||||
- helpers/doc: De-hide some helpers v1 in documentation now that the structure is less bloated sort of ? (2a7fefae)
|
||||
- helpers/doc: fix detail block, cant use the HTML <details> because grav doesnt interpret markdown in it (feb9a095)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Tue, 25 Jun 2024 14:19:58 +0200
|
||||
|
||||
yunohost (11.2.17) stable; urgency=low
|
||||
|
||||
- helpers: Misc cleaning / reorganizing to prepare new doc (2895d4d9)
|
||||
- helpers: rework helper doc now that we have multiple versions of helpers in parallel + improve structure (group helper file in categories) (094cd9dd)
|
||||
- helpers/mongo: less noisy output when checking the avx flag is here in /proc/cpuinfo (2af4c157)
|
||||
- apps/helpers2.1: fix app env in resource upgrade context ending up in incorrect helper version being used (ed426f05)
|
||||
- helpers2.1: forgot to propagate the 'goenv latest' fix from helpers v1 (d8c3ff4c)
|
||||
- helpers2.1: drop ynh_apps helper because only a single app is using it ... (1fb80e5d)
|
||||
- helpers2.1: other typo fixes
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 24 Jun 2024 22:36:32 +0200
|
||||
|
||||
yunohost (11.2.16) stable; urgency=low
|
||||
|
||||
- apps/logs: fix some information not being redacted because of the packaging v2 flows (a25033bb)
|
||||
- logs: misc ad-hoc tweaks to limit the noise in log sharing (06c8fbc8)
|
||||
- helpers: (1/2/2.1) add a new ynh_app_setting_set_default to replace the unecessarily complex 'if [ -z ${foo:-} ]' trick ([#1873](http://github.com/YunoHost/yunohost/pull/1873))
|
||||
- helpers2.1: drop unused 'local source' mechanism from ynh_setup_source (dd8db188)
|
||||
- helpers2.1: fix positional arg parsing in ynh_psql_create_user (e5585136)
|
||||
- helpers2.1: rework the fpm usage/footprint madness ([#1874](http://github.com/YunoHost/yunohost/pull/1874))
|
||||
- helpers2.1: fix ynh_config_add_logrotate when no arg is passed (3942ea12)
|
||||
- helpers2.1: sudo -u$app -> sudo -u $app (d4857834)
|
||||
- helpers2.1: change default timeout of ynh_systemctl to 60s instead of 300s (262453f1)
|
||||
- helpers2.1: display 100 lines instead of 20 in CI context when service fails to start (9298738d)
|
||||
- helpers2.1: when using ynh_systemctl to reload/start/restart a service with a wait_until and it timesout, handle it as a failure rather than keep going (b3409729)
|
||||
- helpers2.1: for some reason sudo -E doesn't preserve PATH even though it's exported, so we gotta explicitly use --preserve-env=PATH (5f6df6a8)
|
||||
- helpers2.1: var rename / cosmetic etc for nodejs/ruby/go version and install directories (2b1f7426)
|
||||
- i18n: Translations updated for Basque, Slovak
|
||||
|
||||
Thanks to all contributors <3 ! (alexAubin, Jose Riha, xabirequejo)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sun, 23 Jun 2024 15:30:22 +0200
|
||||
|
||||
yunohost (11.2.15) stable; urgency=low
|
||||
|
||||
- apps: new experimentals "2.1" helpers ([#1855](http://github.com/YunoHost/yunohost/pull/1855))
|
||||
- apps: when removing an app with --purge, also remove /var/log/{app}
|
||||
- apps: drop clumsy auto-update of nodejs via cron job which fills up disk space with nodejs copies and doesnt actually restart the app services...
|
||||
- apps: fix apt resources when multiple extras are set ([#1869](http://github.com/YunoHost/yunohost/pull/1869))
|
||||
- mail: allow aliases for sender addresses of apps ([#1843](http://github.com/YunoHost/yunohost/pull/1843))
|
||||
|
||||
Thanks to all contributors <3 ! (alexAubin, Chris Vogel, Félix Piédallu)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 20 Jun 2024 21:20:47 +0200
|
||||
|
||||
yunohost (11.2.14.1) stable; urgency=low
|
||||
|
||||
- helpers: Fix typo in ynh_read_manifest documentation ([#1866](http://github.com/YunoHost/yunohost/pull/1866))
|
||||
|
|
6
debian/control
vendored
6
debian/control
vendored
|
@ -10,14 +10,14 @@ Package: yunohost
|
|||
Essential: yes
|
||||
Architecture: all
|
||||
Depends: ${python3:Depends}, ${misc:Depends}
|
||||
, moulinette (>= 11.1), ssowat (>= 11.1)
|
||||
, moulinette (>= 11.1), moulinette (<< 12.0), ssowat (>= 11.1), ssowat (<< 12.0)
|
||||
, python3-psutil, python3-requests, python3-dnspython, python3-openssl
|
||||
, python3-miniupnpc, python3-dbus, python3-jinja2
|
||||
, python3-toml, python3-packaging, python3-publicsuffix2
|
||||
, python3-ldap, python3-zeroconf (>= 0.36), python3-lexicon,
|
||||
, python-is-python3
|
||||
, nginx, nginx-extras (>=1.18)
|
||||
, apt, apt-transport-https, apt-utils, dirmngr
|
||||
, apt, apt-transport-https, apt-utils, aptitude, dirmngr
|
||||
, openssh-server, iptables, fail2ban, bind9-dnsutils
|
||||
, openssl, ca-certificates, netcat-openbsd, iproute2
|
||||
, slapd, ldap-utils, sudo-ldap, libnss-ldapd, unscd, libpam-ldapd
|
||||
|
@ -28,7 +28,7 @@ Depends: ${python3:Depends}, ${misc:Depends}
|
|||
, redis-server
|
||||
, acl
|
||||
, git, curl, wget, cron, unzip, jq, bc, at, procps, j2cli
|
||||
, lsb-release, haveged, fake-hwclock, equivs, lsof, whois
|
||||
, lsb-release, haveged, fake-hwclock, lsof, whois
|
||||
Recommends: yunohost-admin
|
||||
, ntp, inetutils-ping | iputils-ping
|
||||
, bash-completion, rsyslog
|
||||
|
|
2
debian/postinst
vendored
2
debian/postinst
vendored
|
@ -27,7 +27,7 @@ do_configure() {
|
|||
yunohost tools migrations run --auto
|
||||
|
||||
echo "Re-diagnosing server health..."
|
||||
yunohost diagnosis run --force
|
||||
[[ -n "${YNH_SKIP_DIAGNOSIS_DURING_UPGRADE:-}" ]] && echo "(Skipping)" || yunohost diagnosis run --force
|
||||
|
||||
echo "Refreshing app catalog..."
|
||||
yunohost tools update apps --output-as none || true
|
||||
|
|
|
@ -1,10 +1,55 @@
|
|||
#!/usr/env/python3
|
||||
|
||||
import sys
|
||||
import os
|
||||
import glob
|
||||
import datetime
|
||||
import subprocess
|
||||
|
||||
tree = {
|
||||
"sources": {
|
||||
"title": "Sources",
|
||||
"notes": "This is coupled to the 'sources' resource in the manifest.toml",
|
||||
"subsections": ["sources"],
|
||||
},
|
||||
"tech": {
|
||||
"title": "App technologies",
|
||||
"notes": "These allow to install specific version of the technology required to run some apps",
|
||||
"subsections": ["nodejs", "ruby", "go", "composer"],
|
||||
},
|
||||
"db": {
|
||||
"title": "Databases",
|
||||
"notes": "This is coupled to the 'database' resource in the manifest.toml - at least for mysql/postgresql. Mongodb/redis may have better integration in the future.",
|
||||
"subsections": ["mysql", "postgresql", "mongodb", "redis"],
|
||||
},
|
||||
"conf": {
|
||||
"title": "Configurations / templating",
|
||||
"subsections": [
|
||||
"templating",
|
||||
"nginx",
|
||||
"php",
|
||||
"systemd",
|
||||
"fail2ban",
|
||||
"logrotate",
|
||||
],
|
||||
},
|
||||
"misc": {
|
||||
"title": "Misc tools",
|
||||
"subsections": [
|
||||
"utils",
|
||||
"setting",
|
||||
"string",
|
||||
"backup",
|
||||
"logging",
|
||||
"multimedia",
|
||||
],
|
||||
},
|
||||
"meh": {
|
||||
"title": "Deprecated or handled by the core / app resources since v2",
|
||||
"subsections": ["permission", "apt", "systemuser"],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def get_current_commit():
|
||||
p = subprocess.Popen(
|
||||
|
@ -19,14 +64,7 @@ def get_current_commit():
|
|||
return current_commit
|
||||
|
||||
|
||||
def render(helpers):
|
||||
current_commit = get_current_commit()
|
||||
|
||||
data = {
|
||||
"helpers": helpers,
|
||||
"date": datetime.datetime.now().strftime("%d/%m/%Y"),
|
||||
"version": open("../debian/changelog").readlines()[0].split()[1].strip("()"),
|
||||
}
|
||||
def render(tree, helpers_version):
|
||||
|
||||
from jinja2 import Template
|
||||
from ansi2html import Ansi2HTMLConverter
|
||||
|
@ -42,12 +80,15 @@ def render(helpers):
|
|||
t = Template(template)
|
||||
t.globals["now"] = datetime.datetime.utcnow
|
||||
result = t.render(
|
||||
current_commit=current_commit,
|
||||
data=data,
|
||||
tree=tree,
|
||||
date=datetime.datetime.now().strftime("%d/%m/%Y"),
|
||||
version=open("../debian/changelog").readlines()[0].split()[1].strip("()"),
|
||||
helpers_version=helpers_version,
|
||||
current_commit=get_current_commit(),
|
||||
convert=shell_to_html,
|
||||
shell_css=shell_css,
|
||||
)
|
||||
open("helpers.md", "w").write(result)
|
||||
open(f"helpers.v{helpers_version}.md", "w").write(result)
|
||||
|
||||
|
||||
##############################################################################
|
||||
|
@ -87,7 +128,7 @@ class Parser:
|
|||
# We're still in a comment bloc
|
||||
assert line.startswith("# ") or line == "#", malformed_error(i)
|
||||
current_block["comments"].append(line[2:])
|
||||
elif line.strip() == "":
|
||||
elif line.strip() == "" or line.startswith("_ynh"):
|
||||
# Well eh that was not an actual helper definition ... start over ?
|
||||
current_reading = "void"
|
||||
current_block = {
|
||||
|
@ -121,7 +162,11 @@ class Parser:
|
|||
# (we ignore helpers containing [internal] ...)
|
||||
if (
|
||||
"[packagingv1]" not in current_block["comments"]
|
||||
and "[internal]" not in current_block["comments"]
|
||||
and not any(
|
||||
line.startswith("[internal]")
|
||||
for line in current_block["comments"]
|
||||
)
|
||||
and not current_block["name"].startswith("_")
|
||||
):
|
||||
self.blocks.append(current_block)
|
||||
current_block = {
|
||||
|
@ -212,23 +257,27 @@ def malformed_error(line_number):
|
|||
|
||||
|
||||
def main():
|
||||
helper_files = sorted(glob.glob("../helpers/*"))
|
||||
helpers = []
|
||||
|
||||
for helper_file in helper_files:
|
||||
if not os.path.isfile(helper_file):
|
||||
continue
|
||||
if len(sys.argv) == 1:
|
||||
print("This script needs the helper version (1, 2, 2.1) as an argument")
|
||||
sys.exit(1)
|
||||
|
||||
category_name = os.path.basename(helper_file)
|
||||
print("Parsing %s ..." % category_name)
|
||||
p = Parser(helper_file)
|
||||
p.parse_blocks()
|
||||
for b in p.blocks:
|
||||
p.parse_block(b)
|
||||
version = sys.argv[1]
|
||||
|
||||
helpers.append((category_name, p.blocks))
|
||||
for section in tree.values():
|
||||
section["helpers"] = {}
|
||||
for subsection in section["subsections"]:
|
||||
print(f"Parsing {subsection} ...")
|
||||
helper_file = f"../helpers/helpers.v{version}.d/{subsection}"
|
||||
assert os.path.isfile(helper_file), f"Uhoh, {file} doesn't exists?"
|
||||
p = Parser(helper_file)
|
||||
p.parse_blocks()
|
||||
for b in p.blocks:
|
||||
p.parse_block(b)
|
||||
|
||||
render(helpers)
|
||||
section["helpers"][subsection] = p.blocks
|
||||
|
||||
render(tree, version)
|
||||
|
||||
|
||||
main()
|
||||
|
|
|
@ -1,18 +1,26 @@
|
|||
---
|
||||
title: App helpers
|
||||
title: App helpers (v{{ helpers_version }})
|
||||
template: docs
|
||||
taxonomy:
|
||||
category: docs
|
||||
routes:
|
||||
default: '/packaging_apps_helpers'
|
||||
default: '/packaging_apps_helpers{% if helpers_version not in ["1", "2"] %}_v{{ helpers_version }}{% endif %}'
|
||||
---
|
||||
|
||||
Doc auto-generated by [this script](https://github.com/YunoHost/yunohost/blob/{{ current_commit }}/doc/generate_helper_doc.py) on {{data.date}} (YunoHost version {{data.version}})
|
||||
Doc auto-generated by [this script](https://github.com/YunoHost/yunohost/blob/{{ current_commit }}/doc/generate_helper_doc.py) on {{date}} (YunoHost version {{version}})
|
||||
|
||||
|
||||
{% for section_id, section in tree.items() %}
|
||||
## {{ section["title"].title() }}
|
||||
|
||||
{% if section['notes'] %}<p>{{ section['notes'] }}</p>{% endif %}
|
||||
|
||||
{% for subsection, helpers in section["helpers"].items() %}
|
||||
|
||||
### {{ subsection.upper() }}
|
||||
{% for h in helpers %}
|
||||
#### {{ h.name }}
|
||||
|
||||
{% for category, helpers in data.helpers %}
|
||||
## {{ category.upper() }}
|
||||
{% for h in helpers %}
|
||||
### {{ h.name }}
|
||||
[details summary="<i>{{ h.brief }}</i>" class="helper-card-subtitle text-muted"]
|
||||
|
||||
**Usage**: `{{ h.usage }}`
|
||||
|
@ -51,9 +59,9 @@ Doc auto-generated by [this script](https://github.com/YunoHost/yunohost/blob/{{
|
|||
**Details**:
|
||||
{{ h.details }}
|
||||
{%- endif %}
|
||||
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/{{ current_commit }}/helpers/{{ category }}#L{{ h.line + 1 }})
|
||||
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/{{ current_commit }}/helpers/helpers.v{{ helpers_version if helpers_version != "2" else "1" }}.d/{{ subsection }}#L{{ h.line + 1 }})
|
||||
[/details]
|
||||
|
||||
{% endfor %}
|
||||
---
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env bash
|
||||
# Entrypoint for the helpers scripts
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)
|
||||
|
||||
# Helpers version can be specified via an environment variable or default to 1.
|
||||
YNH_HELPERS_VERSION=${YNH_HELPERS_VERSION:-1}
|
||||
|
@ -11,8 +11,9 @@ set +x
|
|||
|
||||
YNH_HELPERS_DIR="$SCRIPT_DIR/helpers.v${YNH_HELPERS_VERSION}.d"
|
||||
case "$YNH_HELPERS_VERSION" in
|
||||
"1" | "2")
|
||||
"1" | "2" | "2.1")
|
||||
readarray -t HELPERS < <(find -L "$YNH_HELPERS_DIR" -mindepth 1 -maxdepth 1 -type f)
|
||||
source $YNH_HELPERS_DIR/getopts
|
||||
for helper in "${HELPERS[@]}"; do
|
||||
[ -r "$helper" ] && source "$helper"
|
||||
done
|
||||
|
@ -20,6 +21,7 @@ case "$YNH_HELPERS_VERSION" in
|
|||
*)
|
||||
echo "Helpers are not available in version '$YNH_HELPERS_VERSION'." >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
eval "$XTRACE_ENABLE"
|
||||
|
|
|
@ -7,52 +7,49 @@
|
|||
#
|
||||
# Requires YunoHost version *.*.* or higher.
|
||||
ynh_install_apps() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=a
|
||||
local -A args_array=([a]=apps=)
|
||||
local apps
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=a
|
||||
local -A args_array=([a]=apps=)
|
||||
local apps
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
# Split the list of apps in an array
|
||||
local apps_list=($(echo $apps | tr " " "\n"))
|
||||
local apps_dependencies=""
|
||||
|
||||
# For each app
|
||||
for one_app_and_its_args in "${apps_list[@]}"
|
||||
do
|
||||
# Retrieve the name of the app (part before ?)
|
||||
local one_app=$(cut -d "?" -f1 <<< "$one_app_and_its_args")
|
||||
[ -z "$one_app" ] && ynh_die --message="You didn't provided a YunoHost app to install"
|
||||
# Split the list of apps in an array
|
||||
local apps_list=($(echo $apps | tr " " "\n"))
|
||||
local apps_dependencies=""
|
||||
|
||||
yunohost tools update apps
|
||||
|
||||
# Installing or upgrading the app depending if it's installed or not
|
||||
if ! yunohost app list --output-as json --quiet | jq -e --arg id $one_app '.apps[] | select(.id == $id)' >/dev/null
|
||||
then
|
||||
# Retrieve the arguments of the app (part after ?)
|
||||
local one_argument=""
|
||||
if [[ "$one_app_and_its_args" == *"?"* ]]; then
|
||||
one_argument=$(cut -d "?" -f2- <<< "$one_app_and_its_args")
|
||||
one_argument="--args $one_argument"
|
||||
fi
|
||||
|
||||
# Install the app with its arguments
|
||||
yunohost app install $one_app $one_argument
|
||||
else
|
||||
# Upgrade the app
|
||||
yunohost app upgrade $one_app
|
||||
fi
|
||||
# For each app
|
||||
for one_app_and_its_args in "${apps_list[@]}"; do
|
||||
# Retrieve the name of the app (part before ?)
|
||||
local one_app=$(cut -d "?" -f1 <<< "$one_app_and_its_args")
|
||||
[ -z "$one_app" ] && ynh_die --message="You didn't provided a YunoHost app to install"
|
||||
|
||||
if [ ! -z "$apps_dependencies" ]
|
||||
then
|
||||
apps_dependencies="$apps_dependencies, $one_app"
|
||||
else
|
||||
apps_dependencies="$one_app"
|
||||
fi
|
||||
done
|
||||
yunohost tools update apps
|
||||
|
||||
ynh_app_setting_set --app=$app --key=apps_dependencies --value="$apps_dependencies"
|
||||
# Installing or upgrading the app depending if it's installed or not
|
||||
if ! yunohost app list --output-as json --quiet | jq -e --arg id $one_app '.apps[] | select(.id == $id)' > /dev/null; then
|
||||
# Retrieve the arguments of the app (part after ?)
|
||||
local one_argument=""
|
||||
if [[ "$one_app_and_its_args" == *"?"* ]]; then
|
||||
one_argument=$(cut -d "?" -f2- <<< "$one_app_and_its_args")
|
||||
one_argument="--args $one_argument"
|
||||
fi
|
||||
|
||||
# Install the app with its arguments
|
||||
yunohost app install $one_app $one_argument
|
||||
else
|
||||
# Upgrade the app
|
||||
yunohost app upgrade $one_app
|
||||
fi
|
||||
|
||||
if [ ! -z "$apps_dependencies" ]; then
|
||||
apps_dependencies="$apps_dependencies, $one_app"
|
||||
else
|
||||
apps_dependencies="$one_app"
|
||||
fi
|
||||
done
|
||||
|
||||
ynh_app_setting_set --app=$app --key=apps_dependencies --value="$apps_dependencies"
|
||||
}
|
||||
|
||||
# Remove other YunoHost apps
|
||||
|
@ -63,53 +60,47 @@ ynh_install_apps() {
|
|||
#
|
||||
# Requires YunoHost version *.*.* or higher.
|
||||
ynh_remove_apps() {
|
||||
# Retrieve the apps dependencies of the app
|
||||
local apps_dependencies=$(ynh_app_setting_get --app=$app --key=apps_dependencies)
|
||||
ynh_app_setting_delete --app=$app --key=apps_dependencies
|
||||
# Retrieve the apps dependencies of the app
|
||||
local apps_dependencies=$(ynh_app_setting_get --app=$app --key=apps_dependencies)
|
||||
ynh_app_setting_delete --app=$app --key=apps_dependencies
|
||||
|
||||
if [ ! -z "$apps_dependencies" ]
|
||||
then
|
||||
# Split the list of apps dependencies in an array
|
||||
local apps_dependencies_list=($(echo $apps_dependencies | tr ", " "\n"))
|
||||
|
||||
# For each apps dependencies
|
||||
for one_app in "${apps_dependencies_list[@]}"
|
||||
do
|
||||
# Retrieve the list of installed apps
|
||||
local installed_apps_list=$(yunohost app list --output-as json --quiet | jq -r .apps[].id)
|
||||
local required_by=""
|
||||
local installed_app_required_by=""
|
||||
if [ ! -z "$apps_dependencies" ]; then
|
||||
# Split the list of apps dependencies in an array
|
||||
local apps_dependencies_list=($(echo $apps_dependencies | tr ", " "\n"))
|
||||
|
||||
# For each other installed app
|
||||
for one_installed_app in $installed_apps_list
|
||||
do
|
||||
# Retrieve the other apps dependencies
|
||||
one_installed_apps_dependencies=$(ynh_app_setting_get --app=$one_installed_app --key=apps_dependencies)
|
||||
if [ ! -z "$one_installed_apps_dependencies" ]
|
||||
then
|
||||
one_installed_apps_dependencies_list=($(echo $one_installed_apps_dependencies | tr ", " "\n"))
|
||||
# For each apps dependencies
|
||||
for one_app in "${apps_dependencies_list[@]}"; do
|
||||
# Retrieve the list of installed apps
|
||||
local installed_apps_list=$(yunohost app list --output-as json --quiet | jq -r .apps[].id)
|
||||
local required_by=""
|
||||
local installed_app_required_by=""
|
||||
|
||||
# For each dependency of the other apps
|
||||
for one_installed_app_dependency in "${one_installed_apps_dependencies_list[@]}"
|
||||
do
|
||||
if [[ $one_installed_app_dependency == $one_app ]]; then
|
||||
required_by="$required_by $one_installed_app"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
# For each other installed app
|
||||
for one_installed_app in $installed_apps_list; do
|
||||
# Retrieve the other apps dependencies
|
||||
one_installed_apps_dependencies=$(ynh_app_setting_get --app=$one_installed_app --key=apps_dependencies)
|
||||
if [ ! -z "$one_installed_apps_dependencies" ]; then
|
||||
one_installed_apps_dependencies_list=($(echo $one_installed_apps_dependencies | tr ", " "\n"))
|
||||
|
||||
# If $one_app is no more required
|
||||
if [[ -z "$required_by" ]]
|
||||
then
|
||||
# Remove $one_app
|
||||
ynh_print_info --message="Removing of $one_app"
|
||||
yunohost app remove $one_app --purge
|
||||
else
|
||||
ynh_print_info --message="$one_app was not removed because it's still required by${required_by}"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
# For each dependency of the other apps
|
||||
for one_installed_app_dependency in "${one_installed_apps_dependencies_list[@]}"; do
|
||||
if [[ $one_installed_app_dependency == $one_app ]]; then
|
||||
required_by="$required_by $one_installed_app"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
|
||||
# If $one_app is no more required
|
||||
if [[ -z "$required_by" ]]; then
|
||||
# Remove $one_app
|
||||
ynh_print_info --message="Removing of $one_app"
|
||||
yunohost app remove $one_app --purge
|
||||
else
|
||||
ynh_print_info --message="$one_app was not removed because it's still required by${required_by}"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
# Spawn a Bash shell with the app environment loaded
|
||||
|
@ -126,90 +117,83 @@ ynh_remove_apps() {
|
|||
# from the app's service configuration file (defaults to $app.service, overridable by the packager with `service` setting).
|
||||
# If the app relies on a specific PHP version, then `php` will be aliased that version. The PHP command will also be appended with the `phpflags` settings.
|
||||
ynh_spawn_app_shell() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=a
|
||||
local -A args_array=([a]=app=)
|
||||
local app
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=a
|
||||
local -A args_array=([a]=app=)
|
||||
local app
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
# Force Bash to be used to run this helper
|
||||
if [[ ! $0 =~ \/?bash$ ]]
|
||||
then
|
||||
ynh_print_err --message="Please use Bash as shell"
|
||||
exit 1
|
||||
fi
|
||||
# Force Bash to be used to run this helper
|
||||
if [[ ! $0 =~ \/?bash$ ]]; then
|
||||
ynh_print_err --message="Please use Bash as shell"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Make sure the app is installed
|
||||
local installed_apps_list=($(yunohost app list --output-as json --quiet | jq -r .apps[].id))
|
||||
if [[ " ${installed_apps_list[*]} " != *" ${app} "* ]]
|
||||
then
|
||||
ynh_print_err --message="$app is not in the apps list"
|
||||
exit 1
|
||||
fi
|
||||
# Make sure the app is installed
|
||||
local installed_apps_list=($(yunohost app list --output-as json --quiet | jq -r .apps[].id))
|
||||
if [[ " ${installed_apps_list[*]} " != *" ${app} "* ]]; then
|
||||
ynh_print_err --message="$app is not in the apps list"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Make sure the app has its own user
|
||||
if ! id -u "$app" &>/dev/null; then
|
||||
ynh_print_err --message="There is no \"$app\" system user"
|
||||
exit 1
|
||||
fi
|
||||
# Make sure the app has its own user
|
||||
if ! id -u "$app" &> /dev/null; then
|
||||
ynh_print_err --message="There is no \"$app\" system user"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Make sure the app has an install_dir setting
|
||||
local install_dir=$(ynh_app_setting_get --app=$app --key=install_dir)
|
||||
if [ -z "$install_dir" ]
|
||||
then
|
||||
ynh_print_err --message="$app has no install_dir setting (does it use packaging format >=2?)"
|
||||
exit 1
|
||||
fi
|
||||
# Make sure the app has an install_dir setting
|
||||
local install_dir=$(ynh_app_setting_get --app=$app --key=install_dir)
|
||||
if [ -z "$install_dir" ]; then
|
||||
ynh_print_err --message="$app has no install_dir setting (does it use packaging format >=2?)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Load the app's service name, or default to $app
|
||||
local service=$(ynh_app_setting_get --app=$app --key=service)
|
||||
[ -z "$service" ] && service=$app;
|
||||
# Load the app's service name, or default to $app
|
||||
local service=$(ynh_app_setting_get --app=$app --key=service)
|
||||
[ -z "$service" ] && service=$app
|
||||
|
||||
# Export HOME variable
|
||||
export HOME=$install_dir;
|
||||
# Export HOME variable
|
||||
export HOME=$install_dir
|
||||
|
||||
# Load the Environment variables from the app's service
|
||||
local env_var=$(systemctl show $service.service -p "Environment" --value)
|
||||
[ -n "$env_var" ] && export $env_var;
|
||||
# Load the Environment variables from the app's service
|
||||
local env_var=$(systemctl show $service.service -p "Environment" --value)
|
||||
[ -n "$env_var" ] && export $env_var
|
||||
|
||||
# Force `php` to its intended version
|
||||
# We use `eval`+`export` since `alias` is not propagated to subshells, even with `export`
|
||||
local phpversion=$(ynh_app_setting_get --app=$app --key=phpversion)
|
||||
local phpflags=$(ynh_app_setting_get --app=$app --key=phpflags)
|
||||
if [ -n "$phpversion" ]
|
||||
then
|
||||
eval "php() { php${phpversion} ${phpflags} \"\$@\"; }"
|
||||
export -f php
|
||||
fi
|
||||
# Force `php` to its intended version
|
||||
# We use `eval`+`export` since `alias` is not propagated to subshells, even with `export`
|
||||
local phpversion=$(ynh_app_setting_get --app=$app --key=phpversion)
|
||||
local phpflags=$(ynh_app_setting_get --app=$app --key=phpflags)
|
||||
if [ -n "$phpversion" ]; then
|
||||
eval "php() { php${phpversion} ${phpflags} \"\$@\"; }"
|
||||
export -f php
|
||||
fi
|
||||
|
||||
# Source the EnvironmentFiles from the app's service
|
||||
local env_files=($(systemctl show $service.service -p "EnvironmentFiles" --value))
|
||||
if [ ${#env_files[*]} -gt 0 ]
|
||||
then
|
||||
# set -/+a enables and disables new variables being automatically exported. Needed when using `source`.
|
||||
set -a
|
||||
for file in ${env_files[*]}
|
||||
do
|
||||
[[ $file = /* ]] && source $file
|
||||
done
|
||||
set +a
|
||||
fi
|
||||
# Source the EnvironmentFiles from the app's service
|
||||
local env_files=($(systemctl show $service.service -p "EnvironmentFiles" --value))
|
||||
if [ ${#env_files[*]} -gt 0 ]; then
|
||||
# set -/+a enables and disables new variables being automatically exported. Needed when using `source`.
|
||||
set -a
|
||||
for file in ${env_files[*]}; do
|
||||
[[ $file = /* ]] && source $file
|
||||
done
|
||||
set +a
|
||||
fi
|
||||
|
||||
# Activate the Python environment, if it exists
|
||||
if [ -f $install_dir/venv/bin/activate ]
|
||||
then
|
||||
# set -/+a enables and disables new variables being automatically exported. Needed when using `source`.
|
||||
set -a
|
||||
source $install_dir/venv/bin/activate
|
||||
set +a
|
||||
fi
|
||||
# Activate the Python environment, if it exists
|
||||
if [ -f $install_dir/venv/bin/activate ]; then
|
||||
# set -/+a enables and disables new variables being automatically exported. Needed when using `source`.
|
||||
set -a
|
||||
source $install_dir/venv/bin/activate
|
||||
set +a
|
||||
fi
|
||||
|
||||
# cd into the WorkingDirectory set in the service, or default to the install_dir
|
||||
local env_dir=$(systemctl show $service.service -p "WorkingDirectory" --value)
|
||||
[ -z $env_dir ] && env_dir=$install_dir;
|
||||
cd $env_dir
|
||||
# cd into the WorkingDirectory set in the service, or default to the install_dir
|
||||
local env_dir=$(systemctl show $service.service -p "WorkingDirectory" --value)
|
||||
[ -z $env_dir ] && env_dir=$install_dir
|
||||
cd $env_dir
|
||||
|
||||
# Spawn the app shell
|
||||
su -s /bin/bash $app
|
||||
# Spawn the app shell
|
||||
su -s /bin/bash $app
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ ynh_wait_dpkg_free() {
|
|||
# With seq 1 17, timeout will be almost 30 minutes
|
||||
for try in $(seq 1 17); do
|
||||
# Check if /var/lib/dpkg/lock is used by another process
|
||||
if lsof /var/lib/dpkg/lock >/dev/null; then
|
||||
if lsof /var/lib/dpkg/lock > /dev/null; then
|
||||
echo "apt is already in use..."
|
||||
# Sleep an exponential time at each round
|
||||
sleep $((try * try))
|
||||
|
@ -32,7 +32,7 @@ ynh_wait_dpkg_free() {
|
|||
set -o xtrace # set -x
|
||||
return 1
|
||||
fi
|
||||
done 9<<<"$(ls -1 $dpkg_dir)"
|
||||
done 9<<< "$(ls -1 $dpkg_dir)"
|
||||
set -o xtrace # set -x
|
||||
return 0
|
||||
fi
|
||||
|
@ -58,8 +58,8 @@ ynh_package_is_installed() {
|
|||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
dpkg-query --show --showformat='${Status}' "$package" 2>/dev/null \
|
||||
| grep --count "ok installed" &>/dev/null
|
||||
dpkg-query --show --showformat='${Status}' "$package" 2> /dev/null \
|
||||
| grep --count "ok installed" &> /dev/null
|
||||
}
|
||||
|
||||
# Get the version of an installed package
|
||||
|
@ -82,7 +82,7 @@ ynh_package_version() {
|
|||
ynh_handle_getopts_args "$@"
|
||||
|
||||
if ynh_package_is_installed "$package"; then
|
||||
dpkg-query --show --showformat='${Version}' "$package" 2>/dev/null
|
||||
dpkg-query --show --showformat='${Version}' "$package" 2> /dev/null
|
||||
else
|
||||
echo ''
|
||||
fi
|
||||
|
@ -186,22 +186,25 @@ ynh_package_install_from_equivs() {
|
|||
|
||||
# Build and install the package
|
||||
local TMPDIR=$(mktemp --directory)
|
||||
|
||||
# Make sure to delete the legacy compat file
|
||||
# It's now handle somewhat magically through the control file
|
||||
rm -f /usr/share/equivs/template/debian/compat
|
||||
mkdir -p ${TMPDIR}/${pkgname}/DEBIAN/
|
||||
# For some reason, dpkg-deb insists for folder perm to be 755 and sometimes it's 777 o_O?
|
||||
chmod -R 755 ${TMPDIR}/${pkgname}
|
||||
|
||||
# Note that the cd executes into a sub shell
|
||||
# Create a fake deb package with equivs-build and the given control file
|
||||
# Install the fake package without its dependencies with dpkg
|
||||
# Install missing dependencies with ynh_package_install
|
||||
ynh_wait_dpkg_free
|
||||
cp "$controlfile" "${TMPDIR}/control"
|
||||
(
|
||||
cd "$TMPDIR"
|
||||
LC_ALL=C equivs-build ./control 2>&1
|
||||
LC_ALL=C dpkg --force-depends --install "./${pkgname}_${pkgversion}_all.deb" 2>&1 | tee ./dpkg_log
|
||||
)
|
||||
|
||||
cp "$controlfile" "${TMPDIR}/${pkgname}/DEBIAN/control"
|
||||
|
||||
# Install the fake package without its dependencies with dpkg --force-depends
|
||||
if ! LC_ALL=C dpkg-deb --build "${TMPDIR}/${pkgname}" "${TMPDIR}/${pkgname}.deb" > "${TMPDIR}/dpkg_log" 2>&1; then
|
||||
cat "${TMPDIR}/dpkg_log" >&2
|
||||
ynh_die --message="Unable to install dependencies"
|
||||
fi
|
||||
# Don't crash in case of error, because is nicely covered by the following line
|
||||
LC_ALL=C dpkg --force-depends --install "${TMPDIR}/${pkgname}.deb" 2>&1 | tee "${TMPDIR}/dpkg_log" || true
|
||||
|
||||
ynh_package_install --fix-broken \
|
||||
|| { # If the installation failed
|
||||
|
@ -224,8 +227,6 @@ YNH_INSTALL_APP_DEPENDENCIES_REPLACE="true"
|
|||
|
||||
# Define and install dependencies with a equivs control file
|
||||
#
|
||||
# [packagingv1]
|
||||
#
|
||||
# This helper can/should only be called once per app
|
||||
#
|
||||
# example : ynh_install_app_dependencies dep1 dep2 "dep3|dep4|dep5"
|
||||
|
@ -265,8 +266,7 @@ ynh_install_app_dependencies() {
|
|||
# The (?<=php) syntax corresponds to lookbehind ;)
|
||||
local specific_php_version=$(echo $dependencies | grep -oP '(?<=php)[0-9.]+(?=-|\>|)' | sort -u)
|
||||
|
||||
if [[ -n "$specific_php_version" ]]
|
||||
then
|
||||
if [[ -n "$specific_php_version" ]]; then
|
||||
# Cover a small edge case where a packager could have specified "php7.4-pwet php5-gni" which is confusing
|
||||
[[ $(echo $specific_php_version | wc -l) -eq 1 ]] \
|
||||
|| ynh_die --message="Inconsistent php versions in dependencies ... found : $specific_php_version"
|
||||
|
@ -280,8 +280,7 @@ ynh_install_app_dependencies() {
|
|||
local old_php_fpm_config_dir=$(ynh_app_setting_get --app=$app --key=fpm_config_dir)
|
||||
local old_php_finalphpconf="$old_php_fpm_config_dir/pool.d/$app.conf"
|
||||
|
||||
if [[ -f "$old_php_finalphpconf" ]]
|
||||
then
|
||||
if [[ -f "$old_php_finalphpconf" ]]; then
|
||||
ynh_backup_if_checksum_is_different --file="$old_php_finalphpconf"
|
||||
ynh_remove_fpm_config
|
||||
fi
|
||||
|
@ -290,8 +289,7 @@ ynh_install_app_dependencies() {
|
|||
ynh_app_setting_set --app=$app --key=phpversion --value=$specific_php_version
|
||||
|
||||
# Set the default php version back as the default version for php-cli.
|
||||
if test -e /usr/bin/php$YNH_DEFAULT_PHP_VERSION
|
||||
then
|
||||
if test -e /usr/bin/php$YNH_DEFAULT_PHP_VERSION; then
|
||||
update-alternatives --set php /usr/bin/php$YNH_DEFAULT_PHP_VERSION
|
||||
fi
|
||||
elif grep --quiet 'php' <<< "$dependencies"; then
|
||||
|
@ -305,26 +303,25 @@ ynh_install_app_dependencies() {
|
|||
# upgrade script where ynh_install_app_dependencies is called with this
|
||||
# expected effect) Otherwise, any subsequent call will add dependencies
|
||||
# to those already present in the equivs control file.
|
||||
if [[ $YNH_INSTALL_APP_DEPENDENCIES_REPLACE == "true" ]]
|
||||
then
|
||||
if [[ $YNH_INSTALL_APP_DEPENDENCIES_REPLACE == "true" ]]; then
|
||||
YNH_INSTALL_APP_DEPENDENCIES_REPLACE="false"
|
||||
else
|
||||
local current_dependencies=""
|
||||
if ynh_package_is_installed --package="${dep_app}-ynh-deps"
|
||||
then
|
||||
if ynh_package_is_installed --package="${dep_app}-ynh-deps"; then
|
||||
current_dependencies="$(dpkg-query --show --showformat='${Depends}' ${dep_app}-ynh-deps) "
|
||||
current_dependencies=${current_dependencies// | /|}
|
||||
fi
|
||||
dependencies="$current_dependencies, $dependencies"
|
||||
fi
|
||||
|
||||
cat >/tmp/${dep_app}-ynh-deps.control <<EOF # Make a control file for equivs-build
|
||||
cat > /tmp/${dep_app}-ynh-deps.control << EOF # Make a control file for equivs-build
|
||||
Section: misc
|
||||
Priority: optional
|
||||
Package: ${dep_app}-ynh-deps
|
||||
Version: ${version}
|
||||
Depends: ${dependencies}
|
||||
Depends: ${dependencies//,,/,}
|
||||
Architecture: all
|
||||
Maintainer: root@localhost
|
||||
Description: Fake package for ${app} (YunoHost app) dependencies
|
||||
This meta-package is only responsible of installing its dependencies.
|
||||
EOF
|
||||
|
@ -335,8 +332,7 @@ EOF
|
|||
|
||||
# Trigger postgresql regenconf if we may have just installed postgresql
|
||||
local psql_installed2="$(ynh_package_is_installed "postgresql-$PSQL_VERSION" && echo yes || echo no)"
|
||||
if [[ "$psql_installed" != "$psql_installed2" ]]
|
||||
then
|
||||
if [[ "$psql_installed" != "$psql_installed2" ]]; then
|
||||
yunohost tools regen-conf postgresql
|
||||
fi
|
||||
|
||||
|
@ -364,15 +360,13 @@ ynh_add_app_dependencies() {
|
|||
|
||||
# Remove fake package and its dependencies
|
||||
#
|
||||
# [packagingv1]
|
||||
#
|
||||
# Dependencies will removed only if no other package need them.
|
||||
#
|
||||
# usage: ynh_remove_app_dependencies
|
||||
#
|
||||
# Requires YunoHost version 2.6.4 or higher.
|
||||
ynh_remove_app_dependencies() {
|
||||
local dep_app=${app//_/-} # Replace all '_' by '-'
|
||||
local dep_app=${app//_/-} # Replace all '_' by '-'
|
||||
|
||||
local current_dependencies=""
|
||||
if ynh_package_is_installed --package="${dep_app}-ynh-deps"; then
|
||||
|
@ -382,24 +376,20 @@ ynh_remove_app_dependencies() {
|
|||
|
||||
# Edge case where the app dep may be on hold,
|
||||
# cf https://forum.yunohost.org/t/migration-error-cause-of-ffsync/20675/4
|
||||
if apt-mark showhold | grep -q -w ${dep_app}-ynh-deps
|
||||
then
|
||||
if apt-mark showhold | grep -q -w ${dep_app}-ynh-deps; then
|
||||
apt-mark unhold ${dep_app}-ynh-deps
|
||||
fi
|
||||
|
||||
# Remove the fake package and its dependencies if they not still used.
|
||||
# (except if dpkg doesn't know anything about the package,
|
||||
# which should be symptomatic of a failed install, and we don't want bash to report an error)
|
||||
if dpkg-query --show ${dep_app}-ynh-deps &>/dev/null
|
||||
then
|
||||
if dpkg-query --show ${dep_app}-ynh-deps &> /dev/null; then
|
||||
ynh_package_autopurge ${dep_app}-ynh-deps
|
||||
fi
|
||||
}
|
||||
|
||||
# Install packages from an extra repository properly.
|
||||
#
|
||||
# [packagingv1]
|
||||
#
|
||||
# usage: ynh_install_extra_app_dependencies --repo="repo" --package="dep1 dep2" [--key=key_url] [--name=name]
|
||||
# | arg: -r, --repo= - Complete url of the extra repository.
|
||||
# | arg: -p, --package= - The packages to install from this extra repository
|
||||
|
@ -476,21 +466,31 @@ ynh_install_extra_repo() {
|
|||
wget_append="tee"
|
||||
fi
|
||||
|
||||
# Split the repository into uri, suite and components.
|
||||
if [[ "$key" == "trusted=yes" ]]; then
|
||||
trusted="--trusted"
|
||||
else
|
||||
trusted=""
|
||||
fi
|
||||
|
||||
IFS=', ' read -r -a repo_parts <<< "$repo"
|
||||
index=0
|
||||
|
||||
# Remove "deb " at the beginning of the repo.
|
||||
repo="${repo#deb }"
|
||||
|
||||
# Get the uri
|
||||
local uri="$(echo "$repo" | awk '{ print $1 }')"
|
||||
|
||||
# Get the suite
|
||||
local suite="$(echo "$repo" | awk '{ print $2 }')"
|
||||
if [[ "${repo_parts[0]}" == "deb" ]]; then
|
||||
index=1
|
||||
fi
|
||||
uri="${repo_parts[$index]}"
|
||||
index=$((index + 1))
|
||||
suite="${repo_parts[$index]}"
|
||||
index=$((index + 1))
|
||||
|
||||
# Get the components
|
||||
local component="${repo##$uri $suite }"
|
||||
if (("${#repo_parts[@]}" > 0)); then
|
||||
component="${repo_parts[*]:$index}"
|
||||
fi
|
||||
|
||||
# Add the repository into sources.list.d
|
||||
ynh_add_repo --uri="$uri" --suite="$suite" --component="$component" --name="$name" $append
|
||||
ynh_add_repo --uri="$uri" --suite="$suite" --component="$component" --name="$name" $append $trusted
|
||||
|
||||
# Pin the new repo with the default priority, so it won't be used for upgrades.
|
||||
# Build $pin from the uri without http and any sub path
|
||||
|
@ -503,10 +503,10 @@ ynh_install_extra_repo() {
|
|||
ynh_pin_repo --package="*" --pin="origin \"$pin\"" $priority --name="$name" $append
|
||||
|
||||
# Get the public key for the repo
|
||||
if [ -n "$key" ]; then
|
||||
if [ -n "$key" ] && [[ "$key" != "trusted=yes" ]]; then
|
||||
mkdir --parents "/etc/apt/trusted.gpg.d"
|
||||
# Timeout option is here to enforce the timeout on dns query and tcp connect (c.f. man wget)
|
||||
wget --timeout 900 --quiet "$key" --output-document=- | gpg --dearmor | $wget_append /etc/apt/trusted.gpg.d/$name.gpg >/dev/null
|
||||
wget --timeout 900 --quiet "$key" --output-document=- | gpg --dearmor | $wget_append /etc/apt/trusted.gpg.d/$name.gpg > /dev/null
|
||||
fi
|
||||
|
||||
# Update the list of package with the new repo
|
||||
|
@ -556,6 +556,7 @@ ynh_remove_extra_repo() {
|
|||
# | arg: -c, --component= - Component of the repository.
|
||||
# | arg: -n, --name= - Name for the files for this repo, $app as default value.
|
||||
# | arg: -a, --append - Do not overwrite existing files.
|
||||
# | arg: -t, --trusted - Add trusted=yes to the repository (not recommended)
|
||||
#
|
||||
# Example for a repo like deb http://forge.yunohost.org/debian/ stretch stable
|
||||
# uri suite component
|
||||
|
@ -564,27 +565,34 @@ ynh_remove_extra_repo() {
|
|||
# Requires YunoHost version 3.8.1 or higher.
|
||||
ynh_add_repo() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=uscna
|
||||
local -A args_array=([u]=uri= [s]=suite= [c]=component= [n]=name= [a]=append)
|
||||
local legacy_args=uscnat
|
||||
local -A args_array=([u]=uri= [s]=suite= [c]=component= [n]=name= [a]=append [t]=trusted)
|
||||
local uri
|
||||
local suite
|
||||
local component
|
||||
local name
|
||||
local append
|
||||
local trusted
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
name="${name:-$app}"
|
||||
append=${append:-0}
|
||||
trusted=${trusted:-0}
|
||||
|
||||
if [ $append -eq 1 ]; then
|
||||
append="tee --append"
|
||||
else
|
||||
append="tee"
|
||||
fi
|
||||
if [[ "$trusted" -eq 1 ]]; then
|
||||
trust="[trusted=yes]"
|
||||
else
|
||||
trust=""
|
||||
fi
|
||||
|
||||
mkdir --parents "/etc/apt/sources.list.d"
|
||||
# Add the new repo in sources.list.d
|
||||
echo "deb $uri $suite $component" \
|
||||
echo "deb $trust $uri $suite $component" \
|
||||
| $append "/etc/apt/sources.list.d/$name.list"
|
||||
}
|
||||
|
||||
|
|
|
@ -162,7 +162,7 @@ ynh_backup() {
|
|||
# ==============================================================================
|
||||
local src=$(echo "${src_path}" | sed --regexp-extended 's/"/\"\"/g')
|
||||
local dest=$(echo "${dest_path}" | sed --regexp-extended 's/"/\"\"/g')
|
||||
echo "\"${src}\",\"${dest}\"" >>"${YNH_BACKUP_CSV}"
|
||||
echo "\"${src}\",\"${dest}\"" >> "${YNH_BACKUP_CSV}"
|
||||
|
||||
# ==============================================================================
|
||||
|
||||
|
@ -289,8 +289,7 @@ ynh_restore_file() {
|
|||
# Boring hack for nginx conf file mapped to php7.3
|
||||
# Note that there's no need to patch the fpm config because most php apps
|
||||
# will call "ynh_add_fpm_config" during restore, effectively recreating the file from scratch
|
||||
if [[ "${dest_path}" == "/etc/nginx/conf.d/"* ]] && grep 'php7.3.*sock' "${dest_path}"
|
||||
then
|
||||
if [[ "${dest_path}" == "/etc/nginx/conf.d/"* ]] && grep 'php7.3.*sock' "${dest_path}"; then
|
||||
sed -i 's/php7.3/php7.4/g' "${dest_path}"
|
||||
fi
|
||||
}
|
||||
|
@ -376,8 +375,7 @@ ynh_backup_if_checksum_is_different() {
|
|||
echo "$backup_file_checksum" # Return the name of the backup file
|
||||
if [ ${PACKAGE_CHECK_EXEC:-0} -eq 1 ]; then
|
||||
local file_path_base64=$(echo "$file" | base64 -w0)
|
||||
if test -e /var/cache/yunohost/appconfbackup/original_${file_path_base64}
|
||||
then
|
||||
if test -e /var/cache/yunohost/appconfbackup/original_${file_path_base64}; then
|
||||
ynh_print_warn "Diff with the original file:"
|
||||
diff --report-identical-files --unified --color=always /var/cache/yunohost/appconfbackup/original_${file_path_base64} $file >&2 || true
|
||||
fi
|
||||
|
@ -412,7 +410,7 @@ ynh_delete_file_checksum() {
|
|||
#
|
||||
ynh_backup_archive_exists() {
|
||||
yunohost backup list --output-as json --quiet \
|
||||
| jq -e --arg archive "$1" '.archives | index($archive)' >/dev/null
|
||||
| jq -e --arg archive "$1" '.archives | index($archive)' > /dev/null
|
||||
}
|
||||
|
||||
# Make a backup in case of failed upgrade
|
||||
|
@ -455,7 +453,7 @@ ynh_backup_before_upgrade() {
|
|||
# If the backup succeeded, remove the previous backup
|
||||
if ynh_backup_archive_exists "$app_bck-pre-upgrade$old_backup_number"; then
|
||||
# Remove the previous backup only if it exists
|
||||
yunohost backup delete $app_bck-pre-upgrade$old_backup_number >/dev/null
|
||||
yunohost backup delete $app_bck-pre-upgrade$old_backup_number > /dev/null
|
||||
fi
|
||||
else
|
||||
ynh_die --message="Backup failed, the upgrade process was aborted."
|
||||
|
@ -494,8 +492,7 @@ ynh_restore_upgradebackup() {
|
|||
yunohost app remove $app
|
||||
# Restore the backup
|
||||
yunohost backup restore $app_bck-pre-upgrade$backup_number --apps $app --force --debug
|
||||
if [[ -d /etc/yunohost/apps/$app ]]
|
||||
then
|
||||
if [[ -d /etc/yunohost/apps/$app ]]; then
|
||||
ynh_die --message="The app was restored to the way it was before the failed upgrade."
|
||||
else
|
||||
ynh_die --message="Uhoh ... Yunohost failed to restore the app to the way it was before the failed upgrade :|"
|
||||
|
|
82
helpers/helpers.v1.d/composer
Normal file
82
helpers/helpers.v1.d/composer
Normal file
|
@ -0,0 +1,82 @@
|
|||
#!/bin/bash
|
||||
|
||||
readonly YNH_DEFAULT_COMPOSER_VERSION=1.10.17
|
||||
# Declare the actual composer version to use.
|
||||
# A packager willing to use another version of composer can override the variable into its _common.sh.
|
||||
YNH_COMPOSER_VERSION=${YNH_COMPOSER_VERSION:-$YNH_DEFAULT_COMPOSER_VERSION}
|
||||
|
||||
# Execute a command with Composer
|
||||
#
|
||||
# usage: ynh_composer_exec [--phpversion=phpversion] [--workdir=$install_dir] --commands="commands"
|
||||
# | arg: -v, --phpversion - PHP version to use with composer
|
||||
# | arg: -w, --workdir - The directory from where the command will be executed. Default $install_dir or $final_path
|
||||
# | arg: -c, --commands - Commands to execute.
|
||||
#
|
||||
# Requires YunoHost version 4.2 or higher.
|
||||
ynh_composer_exec() {
|
||||
local _globalphpversion=${phpversion-:}
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=vwc
|
||||
declare -Ar args_array=([v]=phpversion= [w]=workdir= [c]=commands=)
|
||||
local phpversion
|
||||
local workdir
|
||||
local commands
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
workdir="${workdir:-${install_dir:-$final_path}}"
|
||||
|
||||
if dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} lt 2; then
|
||||
phpversion="${phpversion:-$YNH_PHP_VERSION}"
|
||||
else
|
||||
phpversion="${phpversion:-$_globalphpversion}"
|
||||
fi
|
||||
|
||||
COMPOSER_HOME="$workdir/.composer" COMPOSER_MEMORY_LIMIT=-1 \
|
||||
php${phpversion} "$workdir/composer.phar" $commands \
|
||||
-d "$workdir" --no-interaction --no-ansi 2>&1
|
||||
}
|
||||
|
||||
# Install and initialize Composer in the given directory
|
||||
#
|
||||
# usage: ynh_install_composer [--phpversion=phpversion] [--workdir=$install_dir] [--install_args="--optimize-autoloader"] [--composerversion=composerversion]
|
||||
# | arg: -v, --phpversion - PHP version to use with composer
|
||||
# | arg: -w, --workdir - The directory from where the command will be executed. Default $install_dir.
|
||||
# | arg: -a, --install_args - Additional arguments provided to the composer install. Argument --no-dev already include
|
||||
# | arg: -c, --composerversion - Composer version to install
|
||||
#
|
||||
# Requires YunoHost version 4.2 or higher.
|
||||
ynh_install_composer() {
|
||||
local _globalphpversion=${phpversion-:}
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=vwac
|
||||
declare -Ar args_array=([v]=phpversion= [w]=workdir= [a]=install_args= [c]=composerversion=)
|
||||
local phpversion
|
||||
local workdir
|
||||
local install_args
|
||||
local composerversion
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
if dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} lt 2; then
|
||||
workdir="${workdir:-$final_path}"
|
||||
else
|
||||
workdir="${workdir:-$install_dir}"
|
||||
fi
|
||||
|
||||
if dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} lt 2; then
|
||||
phpversion="${phpversion:-$YNH_PHP_VERSION}"
|
||||
else
|
||||
phpversion="${phpversion:-$_globalphpversion}"
|
||||
fi
|
||||
|
||||
install_args="${install_args:-}"
|
||||
composerversion="${composerversion:-$YNH_COMPOSER_VERSION}"
|
||||
|
||||
curl -sS https://getcomposer.org/installer \
|
||||
| COMPOSER_HOME="$workdir/.composer" \
|
||||
php${phpversion} -- --quiet --install-dir="$workdir" --version=$composerversion \
|
||||
|| ynh_die --message="Unable to install Composer."
|
||||
|
||||
# install dependencies
|
||||
ynh_composer_exec --phpversion="${phpversion}" --workdir="$workdir" --commands="install --no-dev $install_args" \
|
||||
|| ynh_die --message="Unable to install core dependencies with Composer."
|
||||
}
|
|
@ -6,11 +6,11 @@ _ynh_app_config_get_one() {
|
|||
local bind="$3"
|
||||
local getter="get__${short_setting}"
|
||||
# Get value from getter if exists
|
||||
if type -t $getter 2>/dev/null | grep -q '^function$' 2>/dev/null; then
|
||||
if type -t $getter 2> /dev/null | grep -q '^function$' 2> /dev/null; then
|
||||
old[$short_setting]="$($getter)"
|
||||
formats[${short_setting}]="yaml"
|
||||
|
||||
elif [[ "$bind" == *"("* ]] && type -t "get__${bind%%(*}" 2>/dev/null | grep -q '^function$' 2>/dev/null; then
|
||||
elif [[ "$bind" == *"("* ]] && type -t "get__${bind%%(*}" 2> /dev/null | grep -q '^function$' 2> /dev/null; then
|
||||
old[$short_setting]="$("get__${bind%%(*}" $short_setting $type $bind)"
|
||||
formats[${short_setting}]="yaml"
|
||||
|
||||
|
@ -22,7 +22,7 @@ _ynh_app_config_get_one() {
|
|||
if [[ "$bind" == "settings" ]]; then
|
||||
ynh_die --message="File '${short_setting}' can't be stored in settings"
|
||||
fi
|
||||
old[$short_setting]="$(ls "$(echo $bind | sed s@__INSTALL_DIR__@$install_dir@ | sed s@__FINALPATH__@$final_path@ | sed s/__APP__/$app/)" 2>/dev/null || echo YNH_NULL)"
|
||||
old[$short_setting]="$(ls "$bind" 2> /dev/null || echo YNH_NULL)"
|
||||
file_hash[$short_setting]="true"
|
||||
|
||||
# Get multiline text from settings or from a full file
|
||||
|
@ -32,7 +32,7 @@ _ynh_app_config_get_one() {
|
|||
elif [[ "$bind" == *":"* ]]; then
|
||||
ynh_die --message="For technical reasons, multiline text '${short_setting}' can't be stored automatically in a variable file, you have to create custom getter/setter"
|
||||
else
|
||||
old[$short_setting]="$(cat $(echo $bind | sed s@__INSTALL_DIR__@$install_dir@ | sed s@__FINALPATH__@$final_path@ | sed s/__APP__/$app/) 2>/dev/null || echo YNH_NULL)"
|
||||
old[$short_setting]="$(cat "$bind" 2> /dev/null || echo YNH_NULL)"
|
||||
fi
|
||||
|
||||
# Get value from a kind of key/value file
|
||||
|
@ -47,7 +47,7 @@ _ynh_app_config_get_one() {
|
|||
bind_after="$(echo "${bind_key_}" | cut -d'>' -f1)"
|
||||
bind_key_="$(echo "${bind_key_}" | cut -d'>' -f2)"
|
||||
fi
|
||||
local bind_file="$(echo "$bind" | cut -d: -f2 | sed s@__INSTALL_DIR__@$install_dir@ | sed s@__FINALPATH__@$final_path@ | sed s/__APP__/$app/)"
|
||||
local bind_file="$(echo "$bind" | cut -d: -f2)"
|
||||
old[$short_setting]="$(ynh_read_var_in_file --file="${bind_file}" --key="${bind_key_}" --after="${bind_after}")"
|
||||
|
||||
fi
|
||||
|
@ -59,10 +59,10 @@ _ynh_app_config_apply_one() {
|
|||
local type="${types[$short_setting]}"
|
||||
if [ "${changed[$short_setting]}" == "true" ]; then
|
||||
# Apply setter if exists
|
||||
if type -t $setter 2>/dev/null | grep -q '^function$' 2>/dev/null; then
|
||||
if type -t $setter 2> /dev/null | grep -q '^function$' 2> /dev/null; then
|
||||
$setter
|
||||
|
||||
elif [[ "$bind" == *"("* ]] && type -t "set__${bind%%(*}" 2>/dev/null | grep -q '^function$' 2>/dev/null; then
|
||||
elif [[ "$bind" == *"("* ]] && type -t "set__${bind%%(*}" 2> /dev/null | grep -q '^function$' 2> /dev/null; then
|
||||
"set__${bind%%(*}" $short_setting $type $bind
|
||||
|
||||
elif [[ "$bind" == "null" ]]; then
|
||||
|
@ -73,7 +73,7 @@ _ynh_app_config_apply_one() {
|
|||
if [[ "$bind" == "settings" ]]; then
|
||||
ynh_die --message="File '${short_setting}' can't be stored in settings"
|
||||
fi
|
||||
local bind_file="$(echo "$bind" | sed s@__INSTALL_DIR__@$install_dir@ | sed s@__FINALPATH__@$final_path@ | sed s/__APP__/$app/)"
|
||||
local bind_file="$bind"
|
||||
if [[ "${!short_setting}" == "" ]]; then
|
||||
ynh_backup_if_checksum_is_different --file="$bind_file"
|
||||
ynh_secure_remove --file="$bind_file"
|
||||
|
@ -98,9 +98,9 @@ _ynh_app_config_apply_one() {
|
|||
if [[ "$bind" == *":"* ]]; then
|
||||
ynh_die --message="For technical reasons, multiline text '${short_setting}' can't be stored automatically in a variable file, you have to create custom getter/setter"
|
||||
fi
|
||||
local bind_file="$(echo "$bind" | sed s@__INSTALL_DIR__@$install_dir@ | sed s@__FINALPATH__@$final_path@ | sed s/__APP__/$app/)"
|
||||
local bind_file="$bind"
|
||||
ynh_backup_if_checksum_is_different --file="$bind_file"
|
||||
echo "${!short_setting}" >"$bind_file"
|
||||
echo "${!short_setting}" > "$bind_file"
|
||||
ynh_store_file_checksum --file="$bind_file" --update_only
|
||||
ynh_print_info --message="File '$bind_file' overwritten with the content provided in question '${short_setting}'"
|
||||
|
||||
|
@ -113,7 +113,7 @@ _ynh_app_config_apply_one() {
|
|||
bind_key_="$(echo "${bind_key_}" | cut -d'>' -f2)"
|
||||
fi
|
||||
bind_key_=${bind_key_:-$short_setting}
|
||||
local bind_file="$(echo "$bind" | cut -d: -f2 | sed s@__INSTALL_DIR__@$install_dir@ | sed s@__FINALPATH__@$final_path@ | sed s/__APP__/$app/)"
|
||||
local bind_file="$(echo "$bind" | cut -d: -f2)"
|
||||
|
||||
ynh_backup_if_checksum_is_different --file="$bind_file"
|
||||
ynh_write_var_in_file --file="${bind_file}" --key="${bind_key_}" --value="${!short_setting}" --after="${bind_after}"
|
||||
|
@ -126,69 +126,17 @@ _ynh_app_config_apply_one() {
|
|||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
_ynh_app_config_get() {
|
||||
# From settings
|
||||
local lines
|
||||
lines=$(
|
||||
python3 <<EOL
|
||||
import toml
|
||||
from collections import OrderedDict
|
||||
with open("../config_panel.toml", "r") as f:
|
||||
file_content = f.read()
|
||||
loaded_toml = toml.loads(file_content, _dict=OrderedDict)
|
||||
|
||||
for panel_name, panel in loaded_toml.items():
|
||||
if not isinstance(panel, dict): continue
|
||||
bind_panel = panel.get('bind')
|
||||
for section_name, section in panel.items():
|
||||
if not isinstance(section, dict): continue
|
||||
bind_section = section.get('bind')
|
||||
if not bind_section:
|
||||
bind_section = bind_panel
|
||||
elif bind_section[-1] == ":" and bind_panel and ":" in bind_panel:
|
||||
regex, bind_panel_file = bind_panel.split(":")
|
||||
if ">" in bind_section:
|
||||
bind_section = bind_section + bind_panel_file
|
||||
else:
|
||||
bind_section = regex + bind_section + bind_panel_file
|
||||
|
||||
for name, param in section.items():
|
||||
if not isinstance(param, dict):
|
||||
continue
|
||||
|
||||
bind = param.get('bind')
|
||||
|
||||
if not bind:
|
||||
if bind_section:
|
||||
bind = bind_section
|
||||
else:
|
||||
bind = 'settings'
|
||||
elif bind[-1] == ":" and bind_section and ":" in bind_section:
|
||||
regex, bind_file = bind_section.split(":")
|
||||
if ">" in bind:
|
||||
bind = bind + bind_file
|
||||
else:
|
||||
bind = regex + bind + bind_file
|
||||
if bind == "settings" and param.get('type', 'string') == 'file':
|
||||
bind = 'null'
|
||||
|
||||
print('|'.join([
|
||||
name,
|
||||
param.get('type', 'string'),
|
||||
bind
|
||||
]))
|
||||
EOL
|
||||
)
|
||||
for line in $lines; do
|
||||
for line in $YNH_APP_CONFIG_PANEL_OPTIONS_TYPES_AND_BINDS; do
|
||||
# Split line into short_setting, type and bind
|
||||
IFS='|' read short_setting type bind <<<"$line"
|
||||
IFS='|' read short_setting type bind <<< "$line"
|
||||
binds[${short_setting}]="$bind"
|
||||
types[${short_setting}]="$type"
|
||||
file_hash[${short_setting}]=""
|
||||
formats[${short_setting}]=""
|
||||
ynh_app_config_get_one $short_setting $type $bind
|
||||
done
|
||||
|
||||
}
|
||||
|
||||
_ynh_app_config_apply() {
|
||||
|
@ -258,9 +206,9 @@ _ynh_app_config_validate() {
|
|||
for short_setting in "${!old[@]}"; do
|
||||
[[ "${changed[$short_setting]}" == "false" ]] && continue
|
||||
local result=""
|
||||
if type -t validate__$short_setting | grep -q '^function$' 2>/dev/null; then
|
||||
if type -t validate__$short_setting | grep -q '^function$' 2> /dev/null; then
|
||||
result="$(validate__$short_setting)"
|
||||
elif [[ "$bind" == *"("* ]] && type -t "validate__${bind%%(*}" 2>/dev/null | grep -q '^function$' 2>/dev/null; then
|
||||
elif [[ "$bind" == *"("* ]] && type -t "validate__${bind%%(*}" 2> /dev/null | grep -q '^function$' 2> /dev/null; then
|
||||
"validate__${bind%%(*}" $short_setting
|
||||
fi
|
||||
if [ -n "$result" ]; then
|
||||
|
@ -315,7 +263,7 @@ ynh_app_config_apply() {
|
|||
ynh_app_action_run() {
|
||||
local runner="run__$1"
|
||||
# Get value from getter if exists
|
||||
if type -t "$runner" 2>/dev/null | grep -q '^function$' 2>/dev/null; then
|
||||
if type -t "$runner" 2> /dev/null | grep -q '^function$' 2> /dev/null; then
|
||||
$runner
|
||||
#ynh_return "result:"
|
||||
#ynh_return "$(echo "${result}" | sed 's/^/ /g')"
|
||||
|
@ -333,22 +281,23 @@ ynh_app_config_run() {
|
|||
declare -Ag formats=()
|
||||
|
||||
case $1 in
|
||||
show)
|
||||
ynh_app_config_get
|
||||
ynh_app_config_show
|
||||
;;
|
||||
apply)
|
||||
max_progression=4
|
||||
ynh_script_progression --message="Reading config panel description and current configuration..."
|
||||
ynh_app_config_get
|
||||
show)
|
||||
ynh_app_config_get
|
||||
ynh_app_config_show
|
||||
;;
|
||||
apply)
|
||||
max_progression=4
|
||||
ynh_script_progression --message="Reading config panel description and current configuration..."
|
||||
ynh_app_config_get
|
||||
|
||||
ynh_app_config_validate
|
||||
ynh_app_config_validate
|
||||
|
||||
ynh_script_progression --message="Applying the new configuration..."
|
||||
ynh_app_config_apply
|
||||
ynh_script_progression --message="Configuration of $app completed" --last
|
||||
;;
|
||||
*)
|
||||
ynh_app_action_run $1
|
||||
ynh_script_progression --message="Applying the new configuration..."
|
||||
ynh_app_config_apply
|
||||
ynh_script_progression --message="Configuration of $app completed" --last
|
||||
;;
|
||||
*)
|
||||
ynh_app_action_run $1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
|
|
@ -40,9 +40,7 @@
|
|||
# ignoreregex =
|
||||
# ```
|
||||
#
|
||||
# -----------------------------------------------------------------------------
|
||||
#
|
||||
# Note about the "failregex" option:
|
||||
# ##### Note about the "failregex" option:
|
||||
#
|
||||
# regex to match the password failure messages in the logfile. The host must be
|
||||
# matched by a group named "`host`". The tag "`<HOST>`" can be used for standard
|
||||
|
@ -84,7 +82,7 @@ port = __PORTS__
|
|||
filter = __APP__
|
||||
logpath = __LOGPATH__
|
||||
maxretry = __MAX_RETRY__
|
||||
" >"$YNH_APP_BASEDIR/conf/f2b_jail.conf"
|
||||
" > "$YNH_APP_BASEDIR/conf/f2b_jail.conf"
|
||||
|
||||
echo "
|
||||
[INCLUDES]
|
||||
|
@ -92,7 +90,7 @@ before = common.conf
|
|||
[Definition]
|
||||
failregex = __FAILREGEX__
|
||||
ignoreregex =
|
||||
" >"$YNH_APP_BASEDIR/conf/f2b_filter.conf"
|
||||
" > "$YNH_APP_BASEDIR/conf/f2b_filter.conf"
|
||||
fi
|
||||
|
||||
ynh_add_config --template="f2b_jail.conf" --destination="/etc/fail2ban/jail.d/$app.conf"
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
# | arg: $@ - Simply "$@" to tranfert all the positionnal arguments to the function
|
||||
#
|
||||
# This helper need an array, named "args_array" with all the arguments used by the helper
|
||||
# that want to use ynh_handle_getopts_args
|
||||
# that want to use ynh_handle_getopts_args
|
||||
# Be carreful, this array has to be an associative array, as the following example:
|
||||
# local -A args_array=( [a]=arg1 [b]=arg2= [c]=arg3 )
|
||||
# Let's explain this array:
|
||||
|
@ -180,7 +180,7 @@ ynh_handle_getopts_args() {
|
|||
# If not, enter in legacy mode and manage the arguments as positionnal ones..
|
||||
# Dot not echo, to prevent to go through a helper output. But print only in the log.
|
||||
set -x
|
||||
echo "! Helper used in legacy mode !" >/dev/null
|
||||
echo "! Helper used in legacy mode !" > /dev/null
|
||||
set +x
|
||||
local i
|
||||
for i in $(seq 0 $((${#arguments[@]} - 1))); do
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
ynh_go_try_bash_extension() {
|
||||
if [ -x src/configure ]; then
|
||||
src/configure && make -C src || {
|
||||
ynh_print_info --message="Optional bash extension failed to build, but things will still work normally."
|
||||
}
|
||||
fi
|
||||
if [ -x src/configure ]; then
|
||||
src/configure && make -C src || {
|
||||
ynh_print_info --message="Optional bash extension failed to build, but things will still work normally."
|
||||
}
|
||||
fi
|
||||
}
|
||||
|
||||
goenv_install_dir="/opt/goenv"
|
||||
|
@ -51,7 +51,7 @@ export GOENV_ROOT="$goenv_install_dir"
|
|||
# usage: ynh_use_go
|
||||
#
|
||||
# Requires YunoHost version 3.2.2 or higher.
|
||||
ynh_use_go () {
|
||||
ynh_use_go() {
|
||||
go_version=$(ynh_app_setting_get --app=$app --key=go_version)
|
||||
|
||||
# Get the absolute path of this version of Go
|
||||
|
@ -73,7 +73,7 @@ ynh_use_go () {
|
|||
|
||||
# Sets the local application-specific Go version
|
||||
pushd $install_dir
|
||||
$goenv_install_dir/bin/goenv local $go_version
|
||||
$goenv_install_dir/bin/goenv local $go_version
|
||||
popd
|
||||
}
|
||||
|
||||
|
@ -93,10 +93,10 @@ ynh_use_go () {
|
|||
# | arg: -v, --go_version= - Version of go to install.
|
||||
#
|
||||
# Requires YunoHost version 3.2.2 or higher.
|
||||
ynh_install_go () {
|
||||
ynh_install_go() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=v
|
||||
local -A args_array=( [v]=go_version= )
|
||||
local -A args_array=([v]=go_version=)
|
||||
local go_version
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
@ -113,34 +113,34 @@ ynh_install_go () {
|
|||
# Install or update goenv
|
||||
mkdir -p $goenv_install_dir
|
||||
pushd "$goenv_install_dir"
|
||||
if ! [ -x "$goenv_install_dir/bin/goenv" ]; then
|
||||
ynh_print_info --message="Downloading goenv..."
|
||||
git init -q
|
||||
git remote add origin https://github.com/syndbg/goenv.git
|
||||
else
|
||||
ynh_print_info --message="Updating goenv..."
|
||||
fi
|
||||
git fetch -q --tags --prune origin
|
||||
local git_latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)")
|
||||
git checkout -q "$git_latest_tag"
|
||||
ynh_go_try_bash_extension
|
||||
goenv=$goenv_install_dir/bin/goenv
|
||||
if ! [ -x "$goenv_install_dir/bin/goenv" ]; then
|
||||
ynh_print_info --message="Downloading goenv..."
|
||||
git init -q
|
||||
git remote add origin https://github.com/syndbg/goenv.git
|
||||
else
|
||||
ynh_print_info --message="Updating goenv..."
|
||||
fi
|
||||
git fetch -q --tags --prune origin
|
||||
local git_latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)")
|
||||
git checkout -q "$git_latest_tag"
|
||||
ynh_go_try_bash_extension
|
||||
goenv=$goenv_install_dir/bin/goenv
|
||||
popd
|
||||
|
||||
# Install or update xxenv-latest
|
||||
goenv_latest_dir="$goenv_install_dir/plugins/xxenv-latest"
|
||||
mkdir -p "$goenv_latest_dir"
|
||||
pushd "$goenv_latest_dir"
|
||||
if ! [ -x "$goenv_latest_dir/bin/goenv-latest" ]; then
|
||||
ynh_print_info --message="Downloading xxenv-latest..."
|
||||
git init -q
|
||||
git remote add origin https://github.com/momo-lab/xxenv-latest.git
|
||||
else
|
||||
ynh_print_info --message="Updating xxenv-latest..."
|
||||
fi
|
||||
git fetch -q --tags --prune origin
|
||||
local git_latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)")
|
||||
git checkout -q "$git_latest_tag"
|
||||
if ! [ -x "$goenv_latest_dir/bin/goenv-latest" ]; then
|
||||
ynh_print_info --message="Downloading xxenv-latest..."
|
||||
git init -q
|
||||
git remote add origin https://github.com/momo-lab/xxenv-latest.git
|
||||
else
|
||||
ynh_print_info --message="Updating xxenv-latest..."
|
||||
fi
|
||||
git fetch -q --tags --prune origin
|
||||
local git_latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)")
|
||||
git checkout -q "$git_latest_tag"
|
||||
popd
|
||||
|
||||
# Enable caching
|
||||
|
@ -167,7 +167,7 @@ ynh_install_go () {
|
|||
ynh_cleanup_go
|
||||
|
||||
# Set environment for Go users
|
||||
echo "#goenv
|
||||
echo "#goenv
|
||||
export GOENV_ROOT=$goenv_install_dir
|
||||
export PATH=\"$goenv_install_dir/bin:$PATH\"
|
||||
eval \"\$(goenv init -)\"
|
||||
|
@ -182,7 +182,7 @@ eval \"\$(goenv init -)\"
|
|||
# This helper will also cleanup Go versions
|
||||
#
|
||||
# usage: ynh_remove_go
|
||||
ynh_remove_go () {
|
||||
ynh_remove_go() {
|
||||
local go_version=$(ynh_app_setting_get --app="$app" --key="go_version")
|
||||
|
||||
# Load goenv path in PATH
|
||||
|
@ -205,34 +205,29 @@ ynh_remove_go () {
|
|||
# If no app uses Go, goenv will be also removed.
|
||||
#
|
||||
# usage: ynh_cleanup_go
|
||||
ynh_cleanup_go () {
|
||||
ynh_cleanup_go() {
|
||||
|
||||
# List required Go versions
|
||||
local installed_apps=$(yunohost app list --output-as json --quiet | jq -r .apps[].id)
|
||||
local required_go_versions=""
|
||||
for installed_app in $installed_apps
|
||||
do
|
||||
for installed_app in $installed_apps; do
|
||||
local installed_app_go_version=$(ynh_app_setting_get --app=$installed_app --key="go_version")
|
||||
if [[ $installed_app_go_version ]]
|
||||
then
|
||||
if [[ $installed_app_go_version ]]; then
|
||||
required_go_versions="${installed_app_go_version}\n${required_go_versions}"
|
||||
fi
|
||||
done
|
||||
|
||||
# Remove no more needed Go versions
|
||||
local installed_go_versions=$(goenv versions --bare --skip-aliases | grep -Ev '/')
|
||||
for installed_go_version in $installed_go_versions
|
||||
do
|
||||
if ! `echo ${required_go_versions} | grep "${installed_go_version}" 1>/dev/null 2>&1`
|
||||
then
|
||||
for installed_go_version in $installed_go_versions; do
|
||||
if ! $(echo ${required_go_versions} | grep "${installed_go_version}" 1> /dev/null 2>&1); then
|
||||
ynh_print_info --message="Removing of Go-$installed_go_version"
|
||||
$goenv_install_dir/bin/goenv uninstall --force "$installed_go_version"
|
||||
fi
|
||||
done
|
||||
|
||||
# If none Go version is required
|
||||
if [[ ! $required_go_versions ]]
|
||||
then
|
||||
if [[ ! $required_go_versions ]]; then
|
||||
# Remove goenv environment configuration
|
||||
ynh_print_info --message="Removing of goenv"
|
||||
ynh_secure_remove --file="$goenv_install_dir"
|
||||
|
|
|
@ -93,8 +93,7 @@ ynh_exec_err() {
|
|||
# Boring legacy handling for when people calls ynh_exec_* wrapping the command in quotes,
|
||||
# (because in the past eval was used) ...
|
||||
# we detect this by checking that there's no 2nd arg, and $1 contains a space
|
||||
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]
|
||||
then
|
||||
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]; then
|
||||
ynh_print_err --message="$(eval $@)"
|
||||
else
|
||||
# Note that "$@" is used and not $@, c.f. https://unix.stackexchange.com/a/129077
|
||||
|
@ -114,8 +113,7 @@ ynh_exec_warn() {
|
|||
# Boring legacy handling for when people calls ynh_exec_* wrapping the command in quotes,
|
||||
# (because in the past eval was used) ...
|
||||
# we detect this by checking that there's no 2nd arg, and $1 contains a space
|
||||
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]
|
||||
then
|
||||
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]; then
|
||||
ynh_print_warn --message="$(eval $@)"
|
||||
else
|
||||
# Note that "$@" is used and not $@, c.f. https://unix.stackexchange.com/a/129077
|
||||
|
@ -135,8 +133,7 @@ ynh_exec_warn_less() {
|
|||
# Boring legacy handling for when people calls ynh_exec_* wrapping the command in quotes,
|
||||
# (because in the past eval was used) ...
|
||||
# we detect this by checking that there's no 2nd arg, and $1 contains a space
|
||||
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]
|
||||
then
|
||||
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]; then
|
||||
eval $@ 2>&1
|
||||
else
|
||||
# Note that "$@" is used and not $@, c.f. https://unix.stackexchange.com/a/129077
|
||||
|
@ -156,8 +153,7 @@ ynh_exec_quiet() {
|
|||
# Boring legacy handling for when people calls ynh_exec_* wrapping the command in quotes,
|
||||
# (because in the past eval was used) ...
|
||||
# we detect this by checking that there's no 2nd arg, and $1 contains a space
|
||||
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]
|
||||
then
|
||||
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]; then
|
||||
eval $@ > /dev/null
|
||||
else
|
||||
# Note that "$@" is used and not $@, c.f. https://unix.stackexchange.com/a/129077
|
||||
|
@ -177,8 +173,7 @@ ynh_exec_fully_quiet() {
|
|||
# Boring legacy handling for when people calls ynh_exec_* wrapping the command in quotes,
|
||||
# (because in the past eval was used) ...
|
||||
# we detect this by checking that there's no 2nd arg, and $1 contains a space
|
||||
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]
|
||||
then
|
||||
if [[ "$#" -eq 1 ]] && [[ "$1" == *" "* ]]; then
|
||||
eval $@ > /dev/null 2>&1
|
||||
else
|
||||
# Note that "$@" is used and not $@, c.f. https://unix.stackexchange.com/a/129077
|
||||
|
@ -199,7 +194,7 @@ ynh_exec_and_print_stderr_only_if_error() {
|
|||
rc=0
|
||||
# Note that "$@" is used and not $@, c.f. https://unix.stackexchange.com/a/129077
|
||||
"$@" 2> "$logfile" || rc="$?"
|
||||
if (( rc != 0 )); then
|
||||
if ((rc != 0)); then
|
||||
ynh_exec_warn cat "$logfile"
|
||||
ynh_secure_remove "$logfile"
|
||||
return "$rc"
|
||||
|
@ -216,7 +211,7 @@ ynh_exec_and_print_stderr_only_if_error() {
|
|||
#
|
||||
# Requires YunoHost version 3.2.0 or higher.
|
||||
ynh_print_OFF() {
|
||||
exec {BASH_XTRACEFD}>/dev/null
|
||||
exec {BASH_XTRACEFD}> /dev/null
|
||||
}
|
||||
|
||||
# Restore the logging after ynh_print_OFF
|
||||
|
@ -229,7 +224,7 @@ ynh_print_OFF() {
|
|||
ynh_print_ON() {
|
||||
exec {BASH_XTRACEFD}>&1
|
||||
# Print an echo only for the log, to be able to know that ynh_print_ON has been called.
|
||||
echo ynh_print_ON >/dev/null
|
||||
echo ynh_print_ON > /dev/null
|
||||
}
|
||||
|
||||
# Initial definitions for ynh_script_progression
|
||||
|
@ -271,9 +266,9 @@ ynh_script_progression() {
|
|||
|
||||
# Always activate time when running inside CI tests
|
||||
if [ ${PACKAGE_CHECK_EXEC:-0} -eq 1 ]; then
|
||||
time=${time:-1}
|
||||
time=${time:-1}
|
||||
else
|
||||
time=${time:-0}
|
||||
time=${time:-0}
|
||||
fi
|
||||
|
||||
last=${last:-0}
|
||||
|
@ -298,8 +293,8 @@ ynh_script_progression() {
|
|||
local weight_values=$(($(echo "$weight_valuesA" "$weight_valuesB" | grep -v -E '^\s*$' | tr '\n' '+' | sed 's/+$/+0/g')))
|
||||
|
||||
# max_progression is a total number of calls to this helper.
|
||||
# Less the number of calls with a weight value.
|
||||
# Plus the total of weight values
|
||||
# Less the number of calls with a weight value.
|
||||
# Plus the total of weight values
|
||||
max_progression=$(($helper_calls - $weight_calls + $weight_values))
|
||||
fi
|
||||
|
||||
|
@ -329,7 +324,7 @@ ynh_script_progression() {
|
|||
|
||||
local print_exec_time=""
|
||||
if [ $time -eq 1 ] && [ "$exec_time" -gt 10 ]; then
|
||||
print_exec_time=" [$(bc <<< "scale=1; $exec_time / 60" ) minutes]"
|
||||
print_exec_time=" [$(bc <<< "scale=1; $exec_time / 60") minutes]"
|
||||
fi
|
||||
|
||||
ynh_print_info "[$progression_bar] > ${message}${print_exec_time}"
|
||||
|
@ -343,5 +338,5 @@ ynh_script_progression() {
|
|||
#
|
||||
# Requires YunoHost version 3.6.0 or higher.
|
||||
ynh_return() {
|
||||
echo "$1" >>"$YNH_STDRETURN"
|
||||
echo "$1" >> "$YNH_STDRETURN"
|
||||
}
|
||||
|
|
|
@ -16,11 +16,9 @@ ynh_use_logrotate() {
|
|||
|
||||
# Stupid patch to ignore legacy --non-append and --nonappend
|
||||
# which was never properly understood and improperly used and kind of bullshit
|
||||
local all_args=( ${@} )
|
||||
for I in $(seq 0 $(($# - 1)))
|
||||
do
|
||||
if [[ "${all_args[$I]}" == "--non-append" ]] || [[ "${all_args[$I]}" == "--nonappend" ]]
|
||||
then
|
||||
local all_args=(${@})
|
||||
for I in $(seq 0 $(($# - 1))); do
|
||||
if [[ "${all_args[$I]}" == "--non-append" ]] || [[ "${all_args[$I]}" == "--nonappend" ]]; then
|
||||
unset all_args[$I]
|
||||
fi
|
||||
done
|
||||
|
@ -43,8 +41,7 @@ ynh_use_logrotate() {
|
|||
fi
|
||||
set +o noglob
|
||||
|
||||
for stuff in $logfile
|
||||
do
|
||||
for stuff in $logfile; do
|
||||
mkdir --parents $(dirname "$stuff")
|
||||
done
|
||||
|
||||
|
@ -54,7 +51,7 @@ ynh_use_logrotate() {
|
|||
fi
|
||||
|
||||
local tempconf="$(mktemp)"
|
||||
cat << EOF >$tempconf
|
||||
cat << EOF > $tempconf
|
||||
$logfile {
|
||||
# Rotate if the logfile exceeds 100Mo
|
||||
size 100M
|
||||
|
@ -76,8 +73,7 @@ $logfile {
|
|||
}
|
||||
EOF
|
||||
|
||||
if [[ "$FIRST_CALL_TO_LOGROTATE" == "true" ]]
|
||||
then
|
||||
if [[ "$FIRST_CALL_TO_LOGROTATE" == "true" ]]; then
|
||||
cat $tempconf > /etc/logrotate.d/$app
|
||||
else
|
||||
cat $tempconf >> /etc/logrotate.d/$app
|
||||
|
|
|
@ -6,100 +6,92 @@
|
|||
# example: ynh_mongo_exec --command="db.getMongo().getDBNames().indexOf(\"wekan\")"
|
||||
#
|
||||
# usage: ynh_mongo_exec [--user=user] [--password=password] [--authenticationdatabase=authenticationdatabase] [--database=database] [--host=host] [--port=port] --command="command" [--eval]
|
||||
# | arg: -u, --user= - The user name to connect as
|
||||
# | arg: -p, --password= - The user password
|
||||
# | arg: -d, --authenticationdatabase= - The authenticationdatabase to connect to
|
||||
# | arg: -d, --database= - The database to connect to
|
||||
# | arg: -h, --host= - The host to connect to
|
||||
# | arg: -P, --port= - The port to connect to
|
||||
# | arg: -c, --command= - The command to evaluate
|
||||
# | arg: -e, --eval - Evaluate instead of execute the command.
|
||||
# | arg: -u, --user= - The user name to connect as
|
||||
# | arg: -p, --password= - The user password
|
||||
# | arg: -d, --authenticationdatabase= - The authenticationdatabase to connect to
|
||||
# | arg: -d, --database= - The database to connect to
|
||||
# | arg: -h, --host= - The host to connect to
|
||||
# | arg: -P, --port= - The port to connect to
|
||||
# | arg: -c, --command= - The command to evaluate
|
||||
# | arg: -e, --eval - Evaluate instead of execute the command.
|
||||
#
|
||||
#
|
||||
ynh_mongo_exec() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=upadhPce
|
||||
local -A args_array=( [u]=user= [p]=password= [a]=authenticationdatabase= [d]=database= [h]=host= [P]=port= [c]=command= [e]=eval )
|
||||
local user
|
||||
local password
|
||||
local authenticationdatabase
|
||||
local database
|
||||
local host
|
||||
local port
|
||||
local command
|
||||
local eval
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
user="${user:-}"
|
||||
password="${password:-}"
|
||||
authenticationdatabase="${authenticationdatabase:-}"
|
||||
database="${database:-}"
|
||||
host="${host:-}"
|
||||
port="${port:-}"
|
||||
eval=${eval:-0}
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=upadhPce
|
||||
local -A args_array=([u]=user= [p]=password= [a]=authenticationdatabase= [d]=database= [h]=host= [P]=port= [c]=command= [e]=eval)
|
||||
local user
|
||||
local password
|
||||
local authenticationdatabase
|
||||
local database
|
||||
local host
|
||||
local port
|
||||
local command
|
||||
local eval
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
user="${user:-}"
|
||||
password="${password:-}"
|
||||
authenticationdatabase="${authenticationdatabase:-}"
|
||||
database="${database:-}"
|
||||
host="${host:-}"
|
||||
port="${port:-}"
|
||||
eval=${eval:-0}
|
||||
|
||||
# If user is provided
|
||||
if [ -n "$user" ]
|
||||
then
|
||||
user="--username=$user"
|
||||
# If user is provided
|
||||
if [ -n "$user" ]; then
|
||||
user="--username=$user"
|
||||
|
||||
# If password is provided
|
||||
if [ -n "$password" ]
|
||||
then
|
||||
password="--password=$password"
|
||||
fi
|
||||
# If password is provided
|
||||
if [ -n "$password" ]; then
|
||||
password="--password=$password"
|
||||
fi
|
||||
|
||||
# If authenticationdatabase is provided
|
||||
if [ -n "$authenticationdatabase" ]
|
||||
then
|
||||
authenticationdatabase="--authenticationDatabase=$authenticationdatabase"
|
||||
else
|
||||
authenticationdatabase="--authenticationDatabase=admin"
|
||||
fi
|
||||
else
|
||||
password=""
|
||||
authenticationdatabase=""
|
||||
fi
|
||||
# If authenticationdatabase is provided
|
||||
if [ -n "$authenticationdatabase" ]; then
|
||||
authenticationdatabase="--authenticationDatabase=$authenticationdatabase"
|
||||
else
|
||||
authenticationdatabase="--authenticationDatabase=admin"
|
||||
fi
|
||||
else
|
||||
password=""
|
||||
authenticationdatabase=""
|
||||
fi
|
||||
|
||||
# If host is provided
|
||||
if [ -n "$host" ]
|
||||
then
|
||||
host="--host=$host"
|
||||
fi
|
||||
# If host is provided
|
||||
if [ -n "$host" ]; then
|
||||
host="--host=$host"
|
||||
fi
|
||||
|
||||
# If port is provided
|
||||
if [ -n "$port" ]
|
||||
then
|
||||
port="--port=$port"
|
||||
fi
|
||||
# If port is provided
|
||||
if [ -n "$port" ]; then
|
||||
port="--port=$port"
|
||||
fi
|
||||
|
||||
# If eval is not provided
|
||||
if [ $eval -eq 0 ]
|
||||
then
|
||||
# If database is provided
|
||||
if [ -n "$database" ]
|
||||
then
|
||||
database="use $database"
|
||||
else
|
||||
database=""
|
||||
fi
|
||||
# If eval is not provided
|
||||
if [ $eval -eq 0 ]; then
|
||||
# If database is provided
|
||||
if [ -n "$database" ]; then
|
||||
database="use $database"
|
||||
else
|
||||
database=""
|
||||
fi
|
||||
|
||||
mongosh --quiet --username $user --password $password --authenticationDatabase $authenticationdatabase --host $host --port $port <<EOF
|
||||
mongosh --quiet --username $user --password $password --authenticationDatabase $authenticationdatabase --host $host --port $port << EOF
|
||||
$database
|
||||
${command}
|
||||
quit()
|
||||
EOF
|
||||
else
|
||||
# If database is provided
|
||||
if [ -n "$database" ]
|
||||
then
|
||||
database="$database"
|
||||
else
|
||||
database=""
|
||||
fi
|
||||
else
|
||||
# If database is provided
|
||||
if [ -n "$database" ]; then
|
||||
database="$database"
|
||||
else
|
||||
database=""
|
||||
fi
|
||||
|
||||
mongosh --quiet $database --username $user --password $password --authenticationDatabase $authenticationdatabase --host $host --port $port --eval="$command"
|
||||
fi
|
||||
mongosh --quiet $database --username $user --password $password --authenticationDatabase $authenticationdatabase --host $host --port $port --eval="$command"
|
||||
fi
|
||||
}
|
||||
|
||||
# Drop a database
|
||||
|
@ -110,18 +102,18 @@ EOF
|
|||
# consider using ynh_mongo_remove_db instead.
|
||||
#
|
||||
# usage: ynh_mongo_drop_db --database=database
|
||||
# | arg: -d, --database= - The database name to drop
|
||||
# | arg: -d, --database= - The database name to drop
|
||||
#
|
||||
#
|
||||
ynh_mongo_drop_db() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=d
|
||||
local -A args_array=( [d]=database= )
|
||||
local database
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=d
|
||||
local -A args_array=([d]=database=)
|
||||
local database
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
ynh_mongo_exec --database="$database" --command='db.runCommand({dropDatabase: 1})'
|
||||
ynh_mongo_exec --database="$database" --command='db.runCommand({dropDatabase: 1})'
|
||||
}
|
||||
|
||||
# Dump a database
|
||||
|
@ -129,19 +121,19 @@ ynh_mongo_drop_db() {
|
|||
# example: ynh_mongo_dump_db --database=wekan > ./dump.bson
|
||||
#
|
||||
# usage: ynh_mongo_dump_db --database=database
|
||||
# | arg: -d, --database= - The database name to dump
|
||||
# | arg: -d, --database= - The database name to dump
|
||||
# | ret: the mongodump output
|
||||
#
|
||||
#
|
||||
ynh_mongo_dump_db() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=d
|
||||
local -A args_array=( [d]=database= )
|
||||
local database
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=d
|
||||
local -A args_array=([d]=database=)
|
||||
local database
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
mongodump --quiet --db="$database" --archive
|
||||
mongodump --quiet --db="$database" --archive
|
||||
}
|
||||
|
||||
# Create a user
|
||||
|
@ -149,49 +141,48 @@ ynh_mongo_dump_db() {
|
|||
# [internal]
|
||||
#
|
||||
# usage: ynh_mongo_create_user --db_user=user --db_pwd=pwd --db_name=name
|
||||
# | arg: -u, --db_user= - The user name to create
|
||||
# | arg: -p, --db_pwd= - The password to identify user by
|
||||
# | arg: -n, --db_name= - Name of the database to grant privilegies
|
||||
# | arg: -u, --db_user= - The user name to create
|
||||
# | arg: -p, --db_pwd= - The password to identify user by
|
||||
# | arg: -n, --db_name= - Name of the database to grant privilegies
|
||||
#
|
||||
#
|
||||
ynh_mongo_create_user() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=unp
|
||||
local -A args_array=( [u]=db_user= [n]=db_name= [p]=db_pwd= )
|
||||
local db_user
|
||||
local db_name
|
||||
local db_pwd
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=unp
|
||||
local -A args_array=([u]=db_user= [n]=db_name= [p]=db_pwd=)
|
||||
local db_user
|
||||
local db_name
|
||||
local db_pwd
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
# Create the user and set the user as admin of the db
|
||||
ynh_mongo_exec --database="$db_name" --command='db.createUser( { user: "'${db_user}'", pwd: "'${db_pwd}'", roles: [ { role: "readWrite", db: "'${db_name}'" } ] } );'
|
||||
# Create the user and set the user as admin of the db
|
||||
ynh_mongo_exec --database="$db_name" --command='db.createUser( { user: "'${db_user}'", pwd: "'${db_pwd}'", roles: [ { role: "readWrite", db: "'${db_name}'" } ] } );'
|
||||
|
||||
# Add clustermonitoring rights
|
||||
ynh_mongo_exec --database="$db_name" --command='db.grantRolesToUser("'${db_user}'",[{ role: "clusterMonitor", db: "admin" }]);'
|
||||
# Add clustermonitoring rights
|
||||
ynh_mongo_exec --database="$db_name" --command='db.grantRolesToUser("'${db_user}'",[{ role: "clusterMonitor", db: "admin" }]);'
|
||||
}
|
||||
|
||||
# Check if a mongo database exists
|
||||
#
|
||||
# usage: ynh_mongo_database_exists --database=database
|
||||
# | arg: -d, --database= - The database for which to check existence
|
||||
# | arg: -d, --database= - The database for which to check existence
|
||||
# | exit: Return 1 if the database doesn't exist, 0 otherwise
|
||||
#
|
||||
#
|
||||
ynh_mongo_database_exists() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=d
|
||||
local -A args_array=([d]=database=)
|
||||
local database
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=d
|
||||
local -A args_array=([d]=database=)
|
||||
local database
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
if [ $(ynh_mongo_exec --command='db.getMongo().getDBNames().indexOf("'${database}'")' --eval) -lt 0 ]
|
||||
then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
if [ $(ynh_mongo_exec --command='db.getMongo().getDBNames().indexOf("'${database}'")' --eval) -lt 0 ]; then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# Restore a database
|
||||
|
@ -199,18 +190,18 @@ ynh_mongo_database_exists() {
|
|||
# example: ynh_mongo_restore_db --database=wekan < ./dump.bson
|
||||
#
|
||||
# usage: ynh_mongo_restore_db --database=database
|
||||
# | arg: -d, --database= - The database name to restore
|
||||
# | arg: -d, --database= - The database name to restore
|
||||
#
|
||||
#
|
||||
ynh_mongo_restore_db() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=d
|
||||
local -A args_array=( [d]=database= )
|
||||
local database
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=d
|
||||
local -A args_array=([d]=database=)
|
||||
local database
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
mongorestore --quiet --db="$database" --archive
|
||||
mongorestore --quiet --db="$database" --archive
|
||||
}
|
||||
|
||||
# Drop a user
|
||||
|
@ -218,120 +209,120 @@ ynh_mongo_restore_db() {
|
|||
# [internal]
|
||||
#
|
||||
# usage: ynh_mongo_drop_user --db_user=user --db_name=name
|
||||
# | arg: -u, --db_user= - The user to drop
|
||||
# | arg: -n, --db_name= - Name of the database
|
||||
# | arg: -u, --db_user= - The user to drop
|
||||
# | arg: -n, --db_name= - Name of the database
|
||||
#
|
||||
#
|
||||
ynh_mongo_drop_user() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=un
|
||||
local -A args_array=( [u]=db_user= [n]=db_name= )
|
||||
local db_user
|
||||
local db_name
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=un
|
||||
local -A args_array=([u]=db_user= [n]=db_name=)
|
||||
local db_user
|
||||
local db_name
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
ynh_mongo_exec --database="$db_name" --command='db.dropUser("'$db_user'", {w: "majority", wtimeout: 5000})'
|
||||
ynh_mongo_exec --database="$db_name" --command='db.dropUser("'$db_user'", {w: "majority", wtimeout: 5000})'
|
||||
}
|
||||
|
||||
# Create a database, an user and its password. Then store the password in the app's config
|
||||
#
|
||||
# usage: ynh_mongo_setup_db --db_user=user --db_name=name [--db_pwd=pwd]
|
||||
# | arg: -u, --db_user= - Owner of the database
|
||||
# | arg: -n, --db_name= - Name of the database
|
||||
# | arg: -p, --db_pwd= - Password of the database. If not provided, a password will be generated
|
||||
# | arg: -u, --db_user= - Owner of the database
|
||||
# | arg: -n, --db_name= - Name of the database
|
||||
# | arg: -p, --db_pwd= - Password of the database. If not provided, a password will be generated
|
||||
#
|
||||
# After executing this helper, the password of the created database will be available in $db_pwd
|
||||
# It will also be stored as "mongopwd" into the app settings.
|
||||
#
|
||||
#
|
||||
ynh_mongo_setup_db() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=unp
|
||||
local -A args_array=( [u]=db_user= [n]=db_name= [p]=db_pwd= )
|
||||
local db_user
|
||||
local db_name
|
||||
db_pwd=""
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=unp
|
||||
local -A args_array=([u]=db_user= [n]=db_name= [p]=db_pwd=)
|
||||
local db_user
|
||||
local db_name
|
||||
db_pwd=""
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
local new_db_pwd=$(ynh_string_random) # Generate a random password
|
||||
# If $db_pwd is not provided, use new_db_pwd instead for db_pwd
|
||||
db_pwd="${db_pwd:-$new_db_pwd}"
|
||||
local new_db_pwd=$(ynh_string_random) # Generate a random password
|
||||
# If $db_pwd is not provided, use new_db_pwd instead for db_pwd
|
||||
db_pwd="${db_pwd:-$new_db_pwd}"
|
||||
|
||||
# Create the user and grant access to the database
|
||||
ynh_mongo_create_user --db_user="$db_user" --db_pwd="$db_pwd" --db_name="$db_name"
|
||||
# Create the user and grant access to the database
|
||||
ynh_mongo_create_user --db_user="$db_user" --db_pwd="$db_pwd" --db_name="$db_name"
|
||||
|
||||
# Store the password in the app's config
|
||||
ynh_app_setting_set --app=$app --key=db_pwd --value=$db_pwd
|
||||
# Store the password in the app's config
|
||||
ynh_app_setting_set --app=$app --key=db_pwd --value=$db_pwd
|
||||
}
|
||||
|
||||
# Remove a database if it exists, and the associated user
|
||||
#
|
||||
# usage: ynh_mongo_remove_db --db_user=user --db_name=name
|
||||
# | arg: -u, --db_user= - Owner of the database
|
||||
# | arg: -n, --db_name= - Name of the database
|
||||
# | arg: -u, --db_user= - Owner of the database
|
||||
# | arg: -n, --db_name= - Name of the database
|
||||
#
|
||||
#
|
||||
ynh_mongo_remove_db() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=un
|
||||
local -A args_array=( [u]=db_user= [n]=db_name= )
|
||||
local db_user
|
||||
local db_name
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=un
|
||||
local -A args_array=([u]=db_user= [n]=db_name=)
|
||||
local db_user
|
||||
local db_name
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
if ynh_mongo_database_exists --database=$db_name; then # Check if the database exists
|
||||
ynh_mongo_drop_db --database=$db_name # Remove the database
|
||||
else
|
||||
ynh_print_warn --message="Database $db_name not found"
|
||||
fi
|
||||
if ynh_mongo_database_exists --database=$db_name; then # Check if the database exists
|
||||
ynh_mongo_drop_db --database=$db_name # Remove the database
|
||||
else
|
||||
ynh_print_warn --message="Database $db_name not found"
|
||||
fi
|
||||
|
||||
# Remove mongo user if it exists
|
||||
ynh_mongo_drop_user --db_user=$db_user --db_name=$db_name
|
||||
# Remove mongo user if it exists
|
||||
ynh_mongo_drop_user --db_user=$db_user --db_name=$db_name
|
||||
}
|
||||
|
||||
# Install MongoDB and integrate MongoDB service in YunoHost
|
||||
#
|
||||
# usage: ynh_install_mongo [--mongo_version=mongo_version]
|
||||
# | arg: -m, --mongo_version= - Version of MongoDB to install
|
||||
# | arg: -m, --mongo_version= - Version of MongoDB to install
|
||||
#
|
||||
#
|
||||
ynh_install_mongo() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=m
|
||||
local -A args_array=([m]=mongo_version=)
|
||||
local mongo_version
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
mongo_version="${mongo_version:-$YNH_MONGO_VERSION}"
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=m
|
||||
local -A args_array=([m]=mongo_version=)
|
||||
local mongo_version
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
mongo_version="${mongo_version:-$YNH_MONGO_VERSION}"
|
||||
|
||||
ynh_print_info --message="Installing MongoDB Community Edition ..."
|
||||
local mongo_debian_release=$(ynh_get_debian_release)
|
||||
ynh_print_info --message="Installing MongoDB Community Edition ..."
|
||||
local mongo_debian_release=$(ynh_get_debian_release)
|
||||
|
||||
if [[ $(cat /proc/cpuinfo) != *"avx"* && "$mongo_version" != "4.4" ]]; then
|
||||
ynh_print_warn --message="Installing Mongo 4.4 as $mongo_version is not compatible with your cpu (see https://docs.mongodb.com/manual/administration/production-notes/#x86_64)."
|
||||
mongo_version="4.4"
|
||||
fi
|
||||
if [[ "$mongo_version" == "4.4" ]]; then
|
||||
ynh_print_warn --message="Switched to buster install as Mongo 4.4 is not compatible with $mongo_debian_release."
|
||||
mongo_debian_release=buster
|
||||
fi
|
||||
if [[ "$(grep '^flags' /proc/cpuinfo | uniq)" != *"avx"* && "$mongo_version" != "4.4" ]]; then
|
||||
ynh_print_warn --message="Installing Mongo 4.4 as $mongo_version is not compatible with your cpu (see https://docs.mongodb.com/manual/administration/production-notes/#x86_64)."
|
||||
mongo_version="4.4"
|
||||
fi
|
||||
if [[ "$mongo_version" == "4.4" ]]; then
|
||||
ynh_print_warn --message="Switched to buster install as Mongo 4.4 is not compatible with $mongo_debian_release."
|
||||
mongo_debian_release=buster
|
||||
fi
|
||||
|
||||
ynh_install_extra_app_dependencies --repo="deb http://repo.mongodb.org/apt/debian $mongo_debian_release/mongodb-org/$mongo_version main" --package="mongodb-org mongodb-org-server mongodb-org-tools mongodb-mongosh" --key="https://www.mongodb.org/static/pgp/server-$mongo_version.asc"
|
||||
mongodb_servicename=mongod
|
||||
ynh_install_extra_app_dependencies --repo="deb http://repo.mongodb.org/apt/debian $mongo_debian_release/mongodb-org/$mongo_version main" --package="mongodb-org mongodb-org-server mongodb-org-tools mongodb-mongosh" --key="https://www.mongodb.org/static/pgp/server-$mongo_version.asc"
|
||||
mongodb_servicename=mongod
|
||||
|
||||
# Make sure MongoDB is started and enabled
|
||||
systemctl enable $mongodb_servicename --quiet
|
||||
systemctl daemon-reload --quiet
|
||||
ynh_systemd_action --service_name=$mongodb_servicename --action=restart --line_match="aiting for connections" --log_path="/var/log/mongodb/$mongodb_servicename.log"
|
||||
# Make sure MongoDB is started and enabled
|
||||
systemctl enable $mongodb_servicename --quiet
|
||||
systemctl daemon-reload --quiet
|
||||
ynh_systemd_action --service_name=$mongodb_servicename --action=restart --line_match="aiting for connections" --log_path="/var/log/mongodb/$mongodb_servicename.log"
|
||||
|
||||
# Integrate MongoDB service in YunoHost
|
||||
yunohost service add $mongodb_servicename --description="MongoDB daemon" --log="/var/log/mongodb/$mongodb_servicename.log"
|
||||
# Integrate MongoDB service in YunoHost
|
||||
yunohost service add $mongodb_servicename --description="MongoDB daemon" --log="/var/log/mongodb/$mongodb_servicename.log"
|
||||
|
||||
# Store mongo_version into the config of this app
|
||||
ynh_app_setting_set --app=$app --key=mongo_version --value=$mongo_version
|
||||
# Store mongo_version into the config of this app
|
||||
ynh_app_setting_set --app=$app --key=mongo_version --value=$mongo_version
|
||||
}
|
||||
|
||||
# Remove MongoDB
|
||||
|
@ -342,14 +333,13 @@ ynh_install_mongo() {
|
|||
#
|
||||
#
|
||||
ynh_remove_mongo() {
|
||||
# Only remove the mongodb service if it is not installed.
|
||||
if ! ynh_package_is_installed --package="mongodb*"
|
||||
then
|
||||
ynh_print_info --message="Removing MongoDB service..."
|
||||
mongodb_servicename=mongod
|
||||
# Remove the mongodb service
|
||||
yunohost service remove $mongodb_servicename
|
||||
ynh_secure_remove --file="/var/lib/mongodb"
|
||||
ynh_secure_remove --file="/var/log/mongodb"
|
||||
fi
|
||||
# Only remove the mongodb service if it is not installed.
|
||||
if ! ynh_package_is_installed --package="mongodb*"; then
|
||||
ynh_print_info --message="Removing MongoDB service..."
|
||||
mongodb_servicename=mongod
|
||||
# Remove the mongodb service
|
||||
yunohost service remove $mongodb_servicename
|
||||
ynh_secure_remove --file="/var/lib/mongodb"
|
||||
ynh_secure_remove --file="/var/log/mongodb"
|
||||
fi
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ ynh_mysql_execute_as_root() {
|
|||
database="--database=$database"
|
||||
fi
|
||||
|
||||
mysql -B "$database" <<<"$sql"
|
||||
mysql -B "$database" <<< "$sql"
|
||||
}
|
||||
|
||||
# Execute a command from a file as root user
|
||||
|
@ -71,7 +71,7 @@ ynh_mysql_execute_file_as_root() {
|
|||
database="--database=$database"
|
||||
fi
|
||||
|
||||
mysql -B "$database" <"$file"
|
||||
mysql -B "$database" < "$file"
|
||||
}
|
||||
|
||||
# Create a database and grant optionnaly privilegies to a user
|
||||
|
@ -174,6 +174,19 @@ ynh_mysql_user_exists() {
|
|||
fi
|
||||
}
|
||||
|
||||
# Check if a mysql database exists
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# usage: ynh_mysql_database_exists database
|
||||
# | arg: database - the database for which to check existence
|
||||
# | exit: Return 1 if the database doesn't exist, 0 otherwise
|
||||
#
|
||||
ynh_mysql_database_exists() {
|
||||
local database=$1
|
||||
mysqlshow | grep -qE "^|\s+$database\s+|"
|
||||
}
|
||||
|
||||
# Drop a user
|
||||
#
|
||||
# [internal]
|
||||
|
@ -236,7 +249,7 @@ ynh_mysql_remove_db() {
|
|||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
if mysqlshow | grep -q "^| $db_name "; then
|
||||
if ynh_mysql_database_exists "$db_name"; then
|
||||
ynh_mysql_drop_db $db_name
|
||||
else
|
||||
ynh_print_warn --message="Database $db_name not found"
|
||||
|
|
|
@ -79,7 +79,7 @@ ynh_validate_ip() {
|
|||
|
||||
[ "$family" == "4" ] || [ "$family" == "6" ] || return 1
|
||||
|
||||
python3 /dev/stdin <<EOF
|
||||
python3 /dev/stdin << EOF
|
||||
import socket
|
||||
import sys
|
||||
family = { "4" : socket.AF_INET, "6" : socket.AF_INET6 }
|
||||
|
|
|
@ -43,7 +43,6 @@ ynh_remove_nginx_config() {
|
|||
ynh_systemd_action --service_name=nginx --action=reload
|
||||
}
|
||||
|
||||
|
||||
# Regen the nginx config in a change url context
|
||||
#
|
||||
# usage: ynh_change_url_nginx_config
|
||||
|
@ -53,7 +52,7 @@ ynh_change_url_nginx_config() {
|
|||
|
||||
# Make a backup of the original NGINX config file if manually modified
|
||||
# (nb: this is possibly different from the same instruction called by
|
||||
# ynh_add_config inside ynh_add_nginx_config because the path may have
|
||||
# ynh_add_config inside ynh_add_nginx_config because the path may have
|
||||
# changed if we're changing the domain too...)
|
||||
local old_nginx_conf_path=/etc/nginx/conf.d/$old_domain.d/$app.conf
|
||||
ynh_backup_if_checksum_is_different --file="$old_nginx_conf_path"
|
||||
|
|
|
@ -83,7 +83,7 @@ ynh_use_nodejs() {
|
|||
# ynh_install_nodejs will install the version of node provided as argument by using n.
|
||||
#
|
||||
# usage: ynh_install_nodejs --nodejs_version=nodejs_version
|
||||
# | arg: -n, --nodejs_version= - Version of node to install. When possible, your should prefer to use major version number (e.g. 8 instead of 8.10.0). The crontab will then handle the update of minor versions when needed.
|
||||
# | arg: -n, --nodejs_version= - Version of node to install. When possible, your should prefer to use major version number (e.g. 8 instead of 8.10.0).
|
||||
#
|
||||
# `n` (Node version management) uses the `PATH` variable to store the path of the version of node it is going to use.
|
||||
# That's how it changes the version
|
||||
|
@ -149,9 +149,6 @@ ynh_install_nodejs() {
|
|||
# Store nodejs_version into the config of this app
|
||||
ynh_app_setting_set --app=$app --key=nodejs_version --value=$nodejs_version
|
||||
|
||||
# Build the update script and set the cronjob
|
||||
ynh_cron_upgrade_node
|
||||
|
||||
ynh_use_nodejs
|
||||
}
|
||||
|
||||
|
@ -180,62 +177,5 @@ ynh_remove_nodejs() {
|
|||
ynh_secure_remove --file="$n_install_dir"
|
||||
ynh_secure_remove --file="/usr/local/n"
|
||||
sed --in-place "/N_PREFIX/d" /root/.bashrc
|
||||
rm --force /etc/cron.daily/node_update
|
||||
fi
|
||||
}
|
||||
|
||||
# Set a cron design to update your node versions
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# This cron will check and update all minor node versions used by your apps.
|
||||
#
|
||||
# usage: ynh_cron_upgrade_node
|
||||
#
|
||||
# Requires YunoHost version 2.7.12 or higher.
|
||||
ynh_cron_upgrade_node() {
|
||||
# Build the update script
|
||||
cat >"$n_install_dir/node_update.sh" <<EOF
|
||||
#!/bin/bash
|
||||
|
||||
version_path="$node_version_path"
|
||||
n_install_dir="$n_install_dir"
|
||||
|
||||
# Log the date
|
||||
date
|
||||
|
||||
# List all real installed version of node
|
||||
all_real_version="\$(find \$version_path/* -maxdepth 0 -type d | sed "s@\$version_path/@@g")"
|
||||
|
||||
# Keep only the major version number of each line
|
||||
all_real_version=\$(echo "\$all_real_version" | sed 's/\..*\$//')
|
||||
|
||||
# Remove double entries
|
||||
all_real_version=\$(echo "\$all_real_version" | sort --unique)
|
||||
|
||||
# Read each major version
|
||||
while read version
|
||||
do
|
||||
echo "Update of the version \$version"
|
||||
sudo \$n_install_dir/bin/n \$version
|
||||
|
||||
# Find the last "real" version for this major version of node.
|
||||
real_nodejs_version=\$(find \$version_path/\$version* -maxdepth 0 | sort --version-sort | tail --lines=1)
|
||||
real_nodejs_version=\$(basename \$real_nodejs_version)
|
||||
|
||||
# Update the symbolic link for this version
|
||||
sudo ln --symbolic --force --no-target-directory \$version_path/\$real_nodejs_version \$version_path/\$version
|
||||
done <<< "\$(echo "\$all_real_version")"
|
||||
EOF
|
||||
|
||||
chmod +x "$n_install_dir/node_update.sh"
|
||||
|
||||
# Build the cronjob
|
||||
cat >"/etc/cron.daily/node_update" <<EOF
|
||||
#!/bin/bash
|
||||
|
||||
$n_install_dir/node_update.sh >> $n_install_dir/node_update.log
|
||||
EOF
|
||||
|
||||
chmod +x "/etc/cron.daily/node_update"
|
||||
}
|
||||
|
|
|
@ -36,8 +36,6 @@
|
|||
# | arg: -t, --show_tile= - (optional) Define if a tile will be shown in the SSO. If yes the name of the tile will be the 'label' parameter. Defaults to false for the permission different than 'main'.
|
||||
# | arg: -P, --protected= - (optional) Define if this permission is protected. If it is protected the administrator won't be able to add or remove the visitors group of this permission. Defaults to 'false'.
|
||||
#
|
||||
# [packagingv1]
|
||||
#
|
||||
# If provided, 'url' or 'additional_urls' is assumed to be relative to the app domain/path if they
|
||||
# start with '/'. For example:
|
||||
# / -> domain.tld/app
|
||||
|
@ -145,8 +143,6 @@ ynh_permission_create() {
|
|||
|
||||
# Remove a permission for the app (note that when the app is removed all permission is automatically removed)
|
||||
#
|
||||
# [packagingv1]
|
||||
#
|
||||
# example: ynh_permission_delete --permission=editors
|
||||
#
|
||||
# usage: ynh_permission_delete --permission="permission"
|
||||
|
@ -165,8 +161,6 @@ ynh_permission_delete() {
|
|||
|
||||
# Check if a permission exists
|
||||
#
|
||||
# [packagingv1]
|
||||
#
|
||||
# usage: ynh_permission_exists --permission=permission
|
||||
# | arg: -p, --permission= - the permission to check
|
||||
# | exit: Return 1 if the permission doesn't exist, 0 otherwise
|
||||
|
@ -180,13 +174,11 @@ ynh_permission_exists() {
|
|||
ynh_handle_getopts_args "$@"
|
||||
|
||||
yunohost user permission list "$app" --output-as json --quiet \
|
||||
| jq -e --arg perm "$app.$permission" '.permissions[$perm]' >/dev/null
|
||||
| jq -e --arg perm "$app.$permission" '.permissions[$perm]' > /dev/null
|
||||
}
|
||||
|
||||
# Redefine the url associated to a permission
|
||||
#
|
||||
# [packagingv1]
|
||||
#
|
||||
# usage: ynh_permission_url --permission "permission" [--url="url"] [--add_url="new-url" [ "other-new-url" ]] [--remove_url="old-url" [ "other-old-url" ]]
|
||||
# [--auth_header=true|false] [--clear_urls]
|
||||
# | arg: -p, --permission= - the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
|
||||
|
@ -255,8 +247,6 @@ ynh_permission_url() {
|
|||
|
||||
# Update a permission for the app
|
||||
#
|
||||
# [packagingv1]
|
||||
#
|
||||
# usage: ynh_permission_update --permission "permission" [--add="group" ["group" ...]] [--remove="group" ["group" ...]]
|
||||
# [--label="label"] [--show_tile=true|false] [--protected=true|false]
|
||||
# | arg: -p, --permission= - the name for the permission (by default a permission named "main" already exist)
|
||||
|
@ -352,7 +342,7 @@ ynh_permission_has_user() {
|
|||
# Check both allowed and corresponding_users sections in the json
|
||||
for section in "allowed" "corresponding_users"; do
|
||||
if yunohost user permission info "$app.$permission" --output-as json --quiet \
|
||||
| jq -e --arg user $user --arg section $section '.[$section] | index($user)' >/dev/null; then
|
||||
| jq -e --arg user $user --arg section $section '.[$section] | index($user)' > /dev/null; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
@ -362,8 +352,6 @@ ynh_permission_has_user() {
|
|||
|
||||
# Check if a legacy permissions exist
|
||||
#
|
||||
# [packagingv1]
|
||||
#
|
||||
# usage: ynh_legacy_permissions_exists
|
||||
# | exit: Return 1 if the permission doesn't exist, 0 otherwise
|
||||
#
|
||||
|
@ -379,8 +367,6 @@ ynh_legacy_permissions_exists() {
|
|||
|
||||
# Remove all legacy permissions
|
||||
#
|
||||
# [packagingv1]
|
||||
#
|
||||
# usage: ynh_legacy_permissions_delete_all
|
||||
#
|
||||
# example:
|
||||
|
|
|
@ -11,19 +11,19 @@ YNH_PHP_VERSION=${YNH_PHP_VERSION:-$YNH_DEFAULT_PHP_VERSION}
|
|||
#
|
||||
# Case 1 (recommended) : your provided a snippet conf/extra_php-fpm.conf
|
||||
#
|
||||
# The actual PHP configuration will be automatically generated,
|
||||
# The actual PHP configuration will be automatically generated,
|
||||
# and your extra_php-fpm.conf will be appended (typically contains PHP upload limits)
|
||||
#
|
||||
# The resulting configuration will be deployed to the appropriate place, /etc/php/$phpversion/fpm/pool.d/$app.conf
|
||||
#
|
||||
# Performance-related options in the PHP conf, such as :
|
||||
# Performance-related options in the PHP conf, such as :
|
||||
# pm.max_children, pm.start_servers, pm.min_spare_servers pm.max_spare_servers
|
||||
# are computed from two parameters called "usage" and "footprint" which can be set to low/medium/high. (cf details below)
|
||||
#
|
||||
# If you wish to tweak those, please initialize the settings `fpm_usage` and `fpm_footprint`
|
||||
# If you wish to tweak those, please initialize the settings `fpm_usage` and `fpm_footprint`
|
||||
# *prior* to calling this helper. Otherwise, "low" will be used as a default for both values.
|
||||
#
|
||||
# Otherwise, if you want the user to have control over these, we encourage to create a config panel
|
||||
# Otherwise, if you want the user to have control over these, we encourage to create a config panel
|
||||
# (which should ultimately be standardized by the core ...)
|
||||
#
|
||||
# Case 2 (deprecate) : you provided an entire conf/php-fpm.conf
|
||||
|
@ -33,7 +33,7 @@ YNH_PHP_VERSION=${YNH_PHP_VERSION:-$YNH_DEFAULT_PHP_VERSION}
|
|||
# The resulting configuration will be deployed to the appropriate place, /etc/php/$phpversion/fpm/pool.d/$app.conf
|
||||
#
|
||||
# ----------------------
|
||||
#
|
||||
#
|
||||
# fpm_footprint: Memory footprint of the service (low/medium/high).
|
||||
# low - Less than 20 MB of RAM by pool.
|
||||
# medium - Between 20 MB and 40 MB of RAM by pool.
|
||||
|
@ -92,16 +92,14 @@ ynh_add_fpm_config() {
|
|||
|
||||
# If no usage provided, default to the value existing in setting ... or to low
|
||||
local fpm_usage_in_setting=$(ynh_app_setting_get --app=$app --key=fpm_usage)
|
||||
if [ -z "$usage" ]
|
||||
then
|
||||
if [ -z "$usage" ]; then
|
||||
usage=${fpm_usage_in_setting:-low}
|
||||
ynh_app_setting_set --app=$app --key=fpm_usage --value=$usage
|
||||
fi
|
||||
|
||||
# If no footprint provided, default to the value existing in setting ... or to low
|
||||
local fpm_footprint_in_setting=$(ynh_app_setting_get --app=$app --key=fpm_footprint)
|
||||
if [ -z "$footprint" ]
|
||||
then
|
||||
if [ -z "$footprint" ]; then
|
||||
footprint=${fpm_footprint_in_setting:-low}
|
||||
ynh_app_setting_set --app=$app --key=fpm_footprint --value=$footprint
|
||||
fi
|
||||
|
@ -125,8 +123,7 @@ ynh_add_fpm_config() {
|
|||
local old_php_fpm_config_dir=$(ynh_app_setting_get --app=$app --key=fpm_config_dir)
|
||||
local old_php_finalphpconf="$old_php_fpm_config_dir/pool.d/$app.conf"
|
||||
|
||||
if [[ -f "$old_php_finalphpconf" ]]
|
||||
then
|
||||
if [[ -f "$old_php_finalphpconf" ]]; then
|
||||
ynh_backup_if_checksum_is_different --file="$old_php_finalphpconf"
|
||||
ynh_remove_fpm_config
|
||||
fi
|
||||
|
@ -200,24 +197,24 @@ pm = __PHP_PM__
|
|||
pm.max_children = __PHP_MAX_CHILDREN__
|
||||
pm.max_requests = 500
|
||||
request_terminate_timeout = 1d
|
||||
" >"$phpfpm_path"
|
||||
" > "$phpfpm_path"
|
||||
|
||||
if [ "$php_pm" = "dynamic" ]; then
|
||||
echo "
|
||||
pm.start_servers = __PHP_START_SERVERS__
|
||||
pm.min_spare_servers = __PHP_MIN_SPARE_SERVERS__
|
||||
pm.max_spare_servers = __PHP_MAX_SPARE_SERVERS__
|
||||
" >>"$phpfpm_path"
|
||||
" >> "$phpfpm_path"
|
||||
|
||||
elif [ "$php_pm" = "ondemand" ]; then
|
||||
echo "
|
||||
pm.process_idle_timeout = 10s
|
||||
" >>"$phpfpm_path"
|
||||
" >> "$phpfpm_path"
|
||||
fi
|
||||
|
||||
# Concatene the extra config.
|
||||
if [ -e $YNH_APP_BASEDIR/conf/extra_php-fpm.conf ]; then
|
||||
cat $YNH_APP_BASEDIR/conf/extra_php-fpm.conf >>"$phpfpm_path"
|
||||
cat $YNH_APP_BASEDIR/conf/extra_php-fpm.conf >> "$phpfpm_path"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
@ -238,7 +235,7 @@ pid = /run/php/php__PHPVERSION__-fpm-__APP__.pid
|
|||
error_log = /var/log/php/fpm-php.__APP__.log
|
||||
syslog.ident = php-fpm-__APP__
|
||||
include = __FINALPHPCONF__
|
||||
" >$YNH_APP_BASEDIR/conf/php-fpm-$app.conf
|
||||
" > $YNH_APP_BASEDIR/conf/php-fpm-$app.conf
|
||||
|
||||
ynh_add_config --template="php-fpm-$app.conf" --destination="$globalphpconf"
|
||||
|
||||
|
@ -255,7 +252,7 @@ ExecReload=/bin/kill -USR2 \$MAINPID
|
|||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
" >$YNH_APP_BASEDIR/conf/$fpm_service
|
||||
" > $YNH_APP_BASEDIR/conf/$fpm_service
|
||||
|
||||
# Create this dedicated PHP-FPM service
|
||||
ynh_add_systemd_config --service=$fpm_service --template=$fpm_service
|
||||
|
@ -267,7 +264,7 @@ WantedBy=multi-user.target
|
|||
ynh_systemd_action --service_name=$fpm_service --action=restart
|
||||
else
|
||||
# Validate that the new php conf doesn't break php-fpm entirely
|
||||
if ! php-fpm${phpversion} --test 2>/dev/null; then
|
||||
if ! php-fpm${phpversion} --test 2> /dev/null; then
|
||||
php-fpm${phpversion} --test || true
|
||||
ynh_secure_remove --file="$finalphpconf"
|
||||
ynh_die --message="The new configuration broke php-fpm?"
|
||||
|
@ -360,7 +357,7 @@ ynh_install_php() {
|
|||
# usage: ynh_remove_php
|
||||
#
|
||||
# Requires YunoHost version 3.8.1 or higher.
|
||||
ynh_remove_php () {
|
||||
ynh_remove_php() {
|
||||
ynh_remove_app_dependencies
|
||||
}
|
||||
|
||||
|
@ -500,84 +497,3 @@ ynh_get_scalable_phpfpm() {
|
|||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
readonly YNH_DEFAULT_COMPOSER_VERSION=1.10.17
|
||||
# Declare the actual composer version to use.
|
||||
# A packager willing to use another version of composer can override the variable into its _common.sh.
|
||||
YNH_COMPOSER_VERSION=${YNH_COMPOSER_VERSION:-$YNH_DEFAULT_COMPOSER_VERSION}
|
||||
|
||||
# Execute a command with Composer
|
||||
#
|
||||
# usage: ynh_composer_exec [--phpversion=phpversion] [--workdir=$install_dir] --commands="commands"
|
||||
# | arg: -v, --phpversion - PHP version to use with composer
|
||||
# | arg: -w, --workdir - The directory from where the command will be executed. Default $install_dir or $final_path
|
||||
# | arg: -c, --commands - Commands to execute.
|
||||
#
|
||||
# Requires YunoHost version 4.2 or higher.
|
||||
ynh_composer_exec() {
|
||||
local _globalphpversion=${phpversion-:}
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=vwc
|
||||
declare -Ar args_array=([v]=phpversion= [w]=workdir= [c]=commands=)
|
||||
local phpversion
|
||||
local workdir
|
||||
local commands
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
workdir="${workdir:-${install_dir:-$final_path}}"
|
||||
|
||||
if dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} lt 2; then
|
||||
phpversion="${phpversion:-$YNH_PHP_VERSION}"
|
||||
else
|
||||
phpversion="${phpversion:-$_globalphpversion}"
|
||||
fi
|
||||
|
||||
COMPOSER_HOME="$workdir/.composer" COMPOSER_MEMORY_LIMIT=-1 \
|
||||
php${phpversion} "$workdir/composer.phar" $commands \
|
||||
-d "$workdir" --no-interaction --no-ansi 2>&1
|
||||
}
|
||||
|
||||
# Install and initialize Composer in the given directory
|
||||
#
|
||||
# usage: ynh_install_composer [--phpversion=phpversion] [--workdir=$install_dir] [--install_args="--optimize-autoloader"] [--composerversion=composerversion]
|
||||
# | arg: -v, --phpversion - PHP version to use with composer
|
||||
# | arg: -w, --workdir - The directory from where the command will be executed. Default $install_dir.
|
||||
# | arg: -a, --install_args - Additional arguments provided to the composer install. Argument --no-dev already include
|
||||
# | arg: -c, --composerversion - Composer version to install
|
||||
#
|
||||
# Requires YunoHost version 4.2 or higher.
|
||||
ynh_install_composer() {
|
||||
local _globalphpversion=${phpversion-:}
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=vwac
|
||||
declare -Ar args_array=([v]=phpversion= [w]=workdir= [a]=install_args= [c]=composerversion=)
|
||||
local phpversion
|
||||
local workdir
|
||||
local install_args
|
||||
local composerversion
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
if dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} lt 2; then
|
||||
workdir="${workdir:-$final_path}"
|
||||
else
|
||||
workdir="${workdir:-$install_dir}"
|
||||
fi
|
||||
|
||||
if dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} lt 2; then
|
||||
phpversion="${phpversion:-$YNH_PHP_VERSION}"
|
||||
else
|
||||
phpversion="${phpversion:-$_globalphpversion}"
|
||||
fi
|
||||
|
||||
install_args="${install_args:-}"
|
||||
composerversion="${composerversion:-$YNH_COMPOSER_VERSION}"
|
||||
|
||||
curl -sS https://getcomposer.org/installer \
|
||||
| COMPOSER_HOME="$workdir/.composer" \
|
||||
php${phpversion} -- --quiet --install-dir="$workdir" --version=$composerversion \
|
||||
|| ynh_die --message="Unable to install Composer."
|
||||
|
||||
# install dependencies
|
||||
ynh_composer_exec --phpversion="${phpversion}" --workdir="$workdir" --commands="install --no-dev $install_args" \
|
||||
|| ynh_die --message="Unable to install core dependencies with Composer."
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ ynh_psql_execute_as_root() {
|
|||
fi
|
||||
|
||||
ynh_psql_connect_as --user="postgres" --password="$(cat $PSQL_ROOT_PWD_FILE)" \
|
||||
$database <<<"$sql"
|
||||
$database <<< "$sql"
|
||||
}
|
||||
|
||||
# Execute a command from a file as root user
|
||||
|
@ -76,7 +76,7 @@ ynh_psql_execute_file_as_root() {
|
|||
fi
|
||||
|
||||
ynh_psql_connect_as --user="postgres" --password="$(cat $PSQL_ROOT_PWD_FILE)" \
|
||||
$database <"$file"
|
||||
$database < "$file"
|
||||
}
|
||||
|
||||
# Create a database and grant optionnaly privilegies to a user
|
||||
|
@ -199,10 +199,9 @@ ynh_psql_database_exists() {
|
|||
|
||||
# if psql is not there, we cannot check the db
|
||||
# though it could exists.
|
||||
if ! command -v psql
|
||||
then
|
||||
ynh_print_err -m "PostgreSQL is not installed, impossible to check for db existence."
|
||||
return 1
|
||||
if ! command -v psql; then
|
||||
ynh_print_err -m "PostgreSQL is not installed, impossible to check for db existence."
|
||||
return 1
|
||||
elif ! sudo --login --user=postgres PGUSER="postgres" PGPASSWORD="$(cat $PSQL_ROOT_PWD_FILE)" psql -tAc "SELECT datname FROM pg_database WHERE datname='$database';" | grep --quiet "$database"; then
|
||||
return 1
|
||||
else
|
||||
|
|
|
@ -5,27 +5,25 @@
|
|||
# usage: ynh_redis_get_free_db
|
||||
# | returns: the database number to use
|
||||
ynh_redis_get_free_db() {
|
||||
local result max db
|
||||
result=$(redis-cli INFO keyspace)
|
||||
local result max db
|
||||
result=$(redis-cli INFO keyspace)
|
||||
|
||||
# get the num
|
||||
max=$(cat /etc/redis/redis.conf | grep ^databases | grep -Eow "[0-9]+")
|
||||
# get the num
|
||||
max=$(cat /etc/redis/redis.conf | grep ^databases | grep -Eow "[0-9]+")
|
||||
|
||||
db=0
|
||||
# default Debian setting is 15 databases
|
||||
for i in $(seq 0 "$max")
|
||||
do
|
||||
if ! echo "$result" | grep -q "db$i"
|
||||
then
|
||||
db=$i
|
||||
break 1
|
||||
fi
|
||||
db=-1
|
||||
done
|
||||
db=0
|
||||
# default Debian setting is 15 databases
|
||||
for i in $(seq 0 "$max"); do
|
||||
if ! echo "$result" | grep -q "db$i"; then
|
||||
db=$i
|
||||
break 1
|
||||
fi
|
||||
db=-1
|
||||
done
|
||||
|
||||
test "$db" -eq -1 && ynh_die --message="No available Redis databases..."
|
||||
test "$db" -eq -1 && ynh_die --message="No available Redis databases..."
|
||||
|
||||
echo "$db"
|
||||
echo "$db"
|
||||
}
|
||||
|
||||
# Create a master password and set up global settings
|
||||
|
@ -34,6 +32,6 @@ ynh_redis_get_free_db() {
|
|||
# usage: ynh_redis_remove_db database
|
||||
# | arg: database - the database to erase
|
||||
ynh_redis_remove_db() {
|
||||
local db=$1
|
||||
redis-cli -n "$db" flushdb
|
||||
local db=$1
|
||||
redis-cli -n "$db" flushdb
|
||||
}
|
||||
|
|
|
@ -8,8 +8,8 @@ export RBENV_ROOT="$rbenv_install_dir"
|
|||
export rbenv_root="$rbenv_install_dir"
|
||||
|
||||
if dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} lt 2; then
|
||||
build_ruby_dependencies="libjemalloc-dev curl build-essential libreadline-dev zlib1g-dev libsqlite3-dev libssl-dev libxml2-dev libxslt-dev autoconf automake bison libtool"
|
||||
build_pkg_dependencies="${build_pkg_dependencies:-} $build_ruby_dependencies"
|
||||
build_ruby_dependencies="libjemalloc-dev curl build-essential libreadline-dev zlib1g-dev libsqlite3-dev libssl-dev libxml2-dev libxslt-dev autoconf automake bison libtool"
|
||||
build_pkg_dependencies="${build_pkg_dependencies:-} $build_ruby_dependencies"
|
||||
fi
|
||||
|
||||
# Load the version of Ruby for an app, and set variables.
|
||||
|
@ -50,7 +50,7 @@ fi
|
|||
# usage: ynh_use_ruby
|
||||
#
|
||||
# Requires YunoHost version 3.2.2 or higher.
|
||||
ynh_use_ruby () {
|
||||
ynh_use_ruby() {
|
||||
ruby_version=$(ynh_app_setting_get --app=$app --key=ruby_version)
|
||||
|
||||
# Get the absolute path of this version of Ruby
|
||||
|
@ -75,7 +75,7 @@ ynh_use_ruby () {
|
|||
|
||||
# Sets the local application-specific Ruby version
|
||||
pushd ${install_dir:-$final_path}
|
||||
$rbenv_install_dir/bin/rbenv local $ruby_version
|
||||
$rbenv_install_dir/bin/rbenv local $ruby_version
|
||||
popd
|
||||
}
|
||||
|
||||
|
@ -95,10 +95,10 @@ ynh_use_ruby () {
|
|||
# | arg: -v, --ruby_version= - Version of ruby to install.
|
||||
#
|
||||
# Requires YunoHost version 3.2.2 or higher.
|
||||
ynh_install_ruby () {
|
||||
ynh_install_ruby() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=v
|
||||
local -A args_array=( [v]=ruby_version= )
|
||||
local -A args_array=([v]=ruby_version=)
|
||||
local ruby_version
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
@ -117,31 +117,31 @@ ynh_install_ruby () {
|
|||
rbenv="$(command -v rbenv $rbenv_install_dir/bin/rbenv | grep "$rbenv_install_dir/bin/rbenv" | head -1)"
|
||||
if [ -n "$rbenv" ]; then
|
||||
pushd "${rbenv%/*/*}"
|
||||
if git remote -v 2>/dev/null | grep "https://github.com/rbenv/rbenv.git"; then
|
||||
ynh_print_info --message="Updating rbenv..."
|
||||
git pull -q --tags origin master
|
||||
ynh_ruby_try_bash_extension
|
||||
else
|
||||
ynh_print_info --message="Reinstalling rbenv..."
|
||||
cd ..
|
||||
ynh_secure_remove --file=$rbenv_install_dir
|
||||
mkdir -p $rbenv_install_dir
|
||||
cd $rbenv_install_dir
|
||||
git init -q
|
||||
git remote add -f -t master origin https://github.com/rbenv/rbenv.git > /dev/null 2>&1
|
||||
git checkout -q -b master origin/master
|
||||
ynh_ruby_try_bash_extension
|
||||
rbenv=$rbenv_install_dir/bin/rbenv
|
||||
fi
|
||||
popd
|
||||
else
|
||||
ynh_print_info --message="Installing rbenv..."
|
||||
pushd $rbenv_install_dir
|
||||
if git remote -v 2> /dev/null | grep "https://github.com/rbenv/rbenv.git"; then
|
||||
ynh_print_info --message="Updating rbenv..."
|
||||
git pull -q --tags origin master
|
||||
ynh_ruby_try_bash_extension
|
||||
else
|
||||
ynh_print_info --message="Reinstalling rbenv..."
|
||||
cd ..
|
||||
ynh_secure_remove --file=$rbenv_install_dir
|
||||
mkdir -p $rbenv_install_dir
|
||||
cd $rbenv_install_dir
|
||||
git init -q
|
||||
git remote add -f -t master origin https://github.com/rbenv/rbenv.git > /dev/null 2>&1
|
||||
git checkout -q -b master origin/master
|
||||
ynh_ruby_try_bash_extension
|
||||
rbenv=$rbenv_install_dir/bin/rbenv
|
||||
fi
|
||||
popd
|
||||
else
|
||||
ynh_print_info --message="Installing rbenv..."
|
||||
pushd $rbenv_install_dir
|
||||
git init -q
|
||||
git remote add -f -t master origin https://github.com/rbenv/rbenv.git > /dev/null 2>&1
|
||||
git checkout -q -b master origin/master
|
||||
ynh_ruby_try_bash_extension
|
||||
rbenv=$rbenv_install_dir/bin/rbenv
|
||||
popd
|
||||
fi
|
||||
|
||||
|
@ -150,10 +150,10 @@ ynh_install_ruby () {
|
|||
ruby_build="$(command -v "$rbenv_install_dir"/plugins/*/bin/rbenv-install rbenv-install | head -1)"
|
||||
if [ -n "$ruby_build" ]; then
|
||||
pushd "${ruby_build%/*/*}"
|
||||
if git remote -v 2>/dev/null | grep "https://github.com/rbenv/ruby-build.git"; then
|
||||
ynh_print_info --message="Updating ruby-build..."
|
||||
git pull -q origin master
|
||||
fi
|
||||
if git remote -v 2> /dev/null | grep "https://github.com/rbenv/ruby-build.git"; then
|
||||
ynh_print_info --message="Updating ruby-build..."
|
||||
git pull -q origin master
|
||||
fi
|
||||
popd
|
||||
else
|
||||
ynh_print_info --message="Installing ruby-build..."
|
||||
|
@ -163,10 +163,10 @@ ynh_install_ruby () {
|
|||
rbenv_alias="$(command -v "$rbenv_install_dir"/plugins/*/bin/rbenv-alias rbenv-alias | head -1)"
|
||||
if [ -n "$rbenv_alias" ]; then
|
||||
pushd "${rbenv_alias%/*/*}"
|
||||
if git remote -v 2>/dev/null | grep "https://github.com/tpope/rbenv-aliases.git"; then
|
||||
ynh_print_info --message="Updating rbenv-aliases..."
|
||||
git pull -q origin master
|
||||
fi
|
||||
if git remote -v 2> /dev/null | grep "https://github.com/tpope/rbenv-aliases.git"; then
|
||||
ynh_print_info --message="Updating rbenv-aliases..."
|
||||
git pull -q origin master
|
||||
fi
|
||||
popd
|
||||
else
|
||||
ynh_print_info --message="Installing rbenv-aliases..."
|
||||
|
@ -176,10 +176,10 @@ ynh_install_ruby () {
|
|||
rbenv_latest="$(command -v "$rbenv_install_dir"/plugins/*/bin/rbenv-latest rbenv-latest | head -1)"
|
||||
if [ -n "$rbenv_latest" ]; then
|
||||
pushd "${rbenv_latest%/*/*}"
|
||||
if git remote -v 2>/dev/null | grep "https://github.com/momo-lab/xxenv-latest.git"; then
|
||||
ynh_print_info --message="Updating xxenv-latest..."
|
||||
git pull -q origin master
|
||||
fi
|
||||
if git remote -v 2> /dev/null | grep "https://github.com/momo-lab/xxenv-latest.git"; then
|
||||
ynh_print_info --message="Updating xxenv-latest..."
|
||||
git pull -q origin master
|
||||
fi
|
||||
popd
|
||||
else
|
||||
ynh_print_info --message="Installing xxenv-latest..."
|
||||
|
@ -210,8 +210,7 @@ ynh_install_ruby () {
|
|||
ynh_app_setting_set --app=$app --key=ruby_version --value=$final_ruby_version
|
||||
|
||||
# Remove app virtualenv
|
||||
if rbenv alias --list | grep --quiet "$app "
|
||||
then
|
||||
if rbenv alias --list | grep --quiet "$app "; then
|
||||
rbenv alias $app --remove
|
||||
fi
|
||||
|
||||
|
@ -222,7 +221,7 @@ ynh_install_ruby () {
|
|||
ynh_cleanup_ruby
|
||||
|
||||
# Set environment for Ruby users
|
||||
echo "#rbenv
|
||||
echo "#rbenv
|
||||
export RBENV_ROOT=$rbenv_install_dir
|
||||
export PATH=\"$rbenv_install_dir/bin:$PATH\"
|
||||
eval \"\$(rbenv init -)\"
|
||||
|
@ -237,7 +236,7 @@ eval \"\$(rbenv init -)\"
|
|||
# This helper will also cleanup Ruby versions
|
||||
#
|
||||
# usage: ynh_remove_ruby
|
||||
ynh_remove_ruby () {
|
||||
ynh_remove_ruby() {
|
||||
local ruby_version=$(ynh_app_setting_get --app=$app --key=ruby_version)
|
||||
|
||||
# Load rbenv path in PATH
|
||||
|
@ -262,34 +261,29 @@ ynh_remove_ruby () {
|
|||
# If no app uses Ruby, rbenv will be also removed.
|
||||
#
|
||||
# usage: ynh_cleanup_ruby
|
||||
ynh_cleanup_ruby () {
|
||||
ynh_cleanup_ruby() {
|
||||
|
||||
# List required Ruby versions
|
||||
local installed_apps=$(yunohost app list | grep -oP 'id: \K.*$')
|
||||
local required_ruby_versions=""
|
||||
for installed_app in $installed_apps
|
||||
do
|
||||
for installed_app in $installed_apps; do
|
||||
local installed_app_ruby_version=$(ynh_app_setting_get --app=$installed_app --key="ruby_version")
|
||||
if [[ -n "$installed_app_ruby_version" ]]
|
||||
then
|
||||
if [[ -n "$installed_app_ruby_version" ]]; then
|
||||
required_ruby_versions="${installed_app_ruby_version}\n${required_ruby_versions}"
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
# Remove no more needed Ruby versions
|
||||
local installed_ruby_versions=$(rbenv versions --bare --skip-aliases | grep -Ev '/')
|
||||
for installed_ruby_version in $installed_ruby_versions
|
||||
do
|
||||
if ! echo ${required_ruby_versions} | grep -q "${installed_ruby_version}"
|
||||
then
|
||||
for installed_ruby_version in $installed_ruby_versions; do
|
||||
if ! echo ${required_ruby_versions} | grep -q "${installed_ruby_version}"; then
|
||||
ynh_print_info --message="Removing Ruby-$installed_ruby_version"
|
||||
$rbenv_install_dir/bin/rbenv uninstall --force $installed_ruby_version
|
||||
fi
|
||||
done
|
||||
|
||||
# If none Ruby version is required
|
||||
if [[ -z "$required_ruby_versions" ]]
|
||||
then
|
||||
if [[ -z "$required_ruby_versions" ]]; then
|
||||
# Remove rbenv environment configuration
|
||||
ynh_print_info --message="Removing rbenv"
|
||||
ynh_secure_remove --file="$rbenv_install_dir"
|
||||
|
@ -298,9 +292,9 @@ ynh_cleanup_ruby () {
|
|||
}
|
||||
|
||||
ynh_ruby_try_bash_extension() {
|
||||
if [ -x src/configure ]; then
|
||||
src/configure && make -C src || {
|
||||
ynh_print_info --message="Optional bash extension failed to build, but things will still work normally."
|
||||
}
|
||||
fi
|
||||
if [ -x src/configure ]; then
|
||||
src/configure && make -C src || {
|
||||
ynh_print_info --message="Optional bash extension failed to build, but things will still work normally."
|
||||
}
|
||||
fi
|
||||
}
|
||||
|
|
|
@ -52,6 +52,42 @@ ynh_app_setting_set() {
|
|||
fi
|
||||
}
|
||||
|
||||
# Set an application setting but only if the "$key" variable ain't set yet
|
||||
#
|
||||
# Note that it doesn't just define the setting but ALSO define the $foobar variable
|
||||
#
|
||||
# Hence it's meant as a replacement for this legacy overly complex syntax:
|
||||
#
|
||||
# if [ -z "${foo:-}" ]
|
||||
# then
|
||||
# foo="bar"
|
||||
# ynh_app_setting_set --key="foo" --value="$foo"
|
||||
# fi
|
||||
#
|
||||
# usage: ynh_app_setting_set_default --app=app --key=key --value=value
|
||||
# | arg: -a, --app= - the application id
|
||||
# | arg: -k, --key= - the setting name to set
|
||||
# | arg: -v, --value= - the default setting value to set
|
||||
#
|
||||
# Requires YunoHost version 11.1.16 or higher.
|
||||
ynh_app_setting_set_default() {
|
||||
local _globalapp=${app-:}
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=akv
|
||||
local -A args_array=([a]=app= [k]=key= [v]=value=)
|
||||
local app
|
||||
local key
|
||||
local value
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
app="${app:-$_globalapp}"
|
||||
|
||||
if [ -z "${!key:-}" ]; then
|
||||
eval $key=\$value
|
||||
ynh_app_setting "set" "$app" "$key" "$value"
|
||||
fi
|
||||
}
|
||||
|
||||
# Delete an application setting
|
||||
#
|
||||
# usage: ynh_app_setting_delete --app=app --key=key
|
||||
|
@ -84,7 +120,7 @@ ynh_app_setting_delete() {
|
|||
#
|
||||
ynh_app_setting() {
|
||||
set +o xtrace # set +x
|
||||
ACTION="$1" APP="$2" KEY="$3" VALUE="${4:-}" python3 - <<EOF
|
||||
ACTION="$1" APP="$2" KEY="$3" VALUE="${4:-}" python3 - << EOF
|
||||
import os, yaml, sys
|
||||
app, action = os.environ['APP'], os.environ['ACTION'].lower()
|
||||
key, value = os.environ['KEY'], os.environ.get('VALUE', None)
|
||||
|
|
286
helpers/helpers.v1.d/sources
Normal file
286
helpers/helpers.v1.d/sources
Normal file
|
@ -0,0 +1,286 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Download, check integrity, uncompress and patch the source from app.src
|
||||
#
|
||||
# usage: ynh_setup_source --dest_dir=dest_dir [--source_id=source_id] [--keep="file1 file2"] [--full_replace]
|
||||
# | arg: -d, --dest_dir= - Directory where to setup sources
|
||||
# | arg: -s, --source_id= - Name of the source, defaults to `main` (when the sources resource exists in manifest.toml) or (legacy) `app` otherwise
|
||||
# | arg: -k, --keep= - Space-separated list of files/folders that will be backup/restored in $dest_dir, such as a config file you don't want to overwrite. For example 'conf.json secrets.json logs' (no trailing `/` for folders)
|
||||
# | arg: -r, --full_replace= - Remove previous sources before installing new sources (can be 1 or 0, default to 0)
|
||||
#
|
||||
# ##### New 'sources' resources
|
||||
#
|
||||
# (See also the resources documentation which may be more complete?)
|
||||
#
|
||||
# This helper will read infos from the 'sources' resources in the manifest.toml of the app
|
||||
# and expect a structure like:
|
||||
#
|
||||
# ```toml
|
||||
# [resources.sources]
|
||||
# [resources.sources.main]
|
||||
# url = "https://some.address.to/download/the/app/archive"
|
||||
# sha256 = "0123456789abcdef" # The sha256 sum of the asset obtained from the URL
|
||||
# ```
|
||||
#
|
||||
# ##### Optional flags
|
||||
#
|
||||
# ```text
|
||||
# format = "tar.gz"/xz/bz2 # automatically guessed from the extension of the URL, but can be set explicitly. Will use `tar` to extract
|
||||
# "zip" # automatically guessed from the extension of the URL, but can be set explicitly. Will use `unzip` to extract
|
||||
# "docker" # useful to extract files from an already-built docker image (instead of rebuilding them locally). Will use `docker-image-extract` to extract
|
||||
# "whatever" # an arbitrary value, not really meaningful except to imply that the file won't be extracted
|
||||
#
|
||||
# in_subdir = true # default, there's an intermediate subdir in the archive before accessing the actual files
|
||||
# false # sources are directly in the archive root
|
||||
# n # (special cases) an integer representing a number of subdirs levels to get rid of
|
||||
#
|
||||
# extract = true # default if file is indeed an archive such as .zip, .tar.gz, .tar.bz2, ...
|
||||
# = false # default if file 'format' is not set and the file is not to be extracted because it is not an archive but a script or binary or whatever asset.
|
||||
# # in which case the file will only be `mv`ed to the location possibly renamed using the `rename` value
|
||||
#
|
||||
# rename = "whatever_your_want" # to be used for convenience when `extract` is false and the default name of the file is not practical
|
||||
# platform = "linux/amd64" # (defaults to "linux/$YNH_ARCH") to be used in conjonction with `format = "docker"` to specify which architecture to extract for
|
||||
# ```
|
||||
#
|
||||
# You may also define assets url and checksum per-architectures such as:
|
||||
# ```toml
|
||||
# [resources.sources]
|
||||
# [resources.sources.main]
|
||||
# amd64.url = "https://some.address.to/download/the/app/archive/when/amd64"
|
||||
# amd64.sha256 = "0123456789abcdef"
|
||||
# armhf.url = "https://some.address.to/download/the/app/archive/when/armhf"
|
||||
# armhf.sha256 = "fedcba9876543210"
|
||||
# ```
|
||||
#
|
||||
# In which case `ynh_setup_source --dest_dir="$install_dir"` will automatically pick the appropriate source depending on the arch
|
||||
#
|
||||
# The helper will:
|
||||
# - Download the specific URL if there is no local archive
|
||||
# - Check the integrity with the specific sha256 sum
|
||||
# - Uncompress the archive to `$dest_dir`.
|
||||
# - If `in_subdir` is true, the first level directory of the archive will be removed.
|
||||
# - If `in_subdir` is a numeric value, the N first level directories will be removed.
|
||||
# - Patches named `sources/patches/${src_id}-*.patch` will be applied to `$dest_dir`
|
||||
# - Extra files in `sources/extra_files/$src_id` will be copied to dest_dir
|
||||
#
|
||||
# Requires YunoHost version 2.6.4 or higher.
|
||||
ynh_setup_source() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=dsk
|
||||
local -A args_array=([d]=dest_dir= [s]=source_id= [k]=keep= [r]=full_replace=)
|
||||
local dest_dir
|
||||
local source_id
|
||||
local keep
|
||||
local full_replace
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
keep="${keep:-}"
|
||||
full_replace="${full_replace:-0}"
|
||||
|
||||
if test -e $YNH_APP_BASEDIR/manifest.toml && cat $YNH_APP_BASEDIR/manifest.toml | toml_to_json | jq -e '.resources.sources' > /dev/null; then
|
||||
source_id="${source_id:-main}"
|
||||
local sources_json=$(cat $YNH_APP_BASEDIR/manifest.toml | toml_to_json | jq ".resources.sources[\"$source_id\"]")
|
||||
if jq -re ".url" <<< "$sources_json"; then
|
||||
local arch_prefix=""
|
||||
else
|
||||
local arch_prefix=".$YNH_ARCH"
|
||||
fi
|
||||
|
||||
local src_url="$(jq -r "$arch_prefix.url" <<< "$sources_json" | sed 's/^null$//')"
|
||||
local src_sum="$(jq -r "$arch_prefix.sha256" <<< "$sources_json" | sed 's/^null$//')"
|
||||
local src_sumprg="sha256sum"
|
||||
local src_format="$(jq -r ".format" <<< "$sources_json" | sed 's/^null$//')"
|
||||
local src_in_subdir="$(jq -r ".in_subdir" <<< "$sources_json" | sed 's/^null$//')"
|
||||
local src_extract="$(jq -r ".extract" <<< "$sources_json" | sed 's/^null$//')"
|
||||
local src_platform="$(jq -r ".platform" <<< "$sources_json" | sed 's/^null$//')"
|
||||
local src_rename="$(jq -r ".rename" <<< "$sources_json" | sed 's/^null$//')"
|
||||
|
||||
[[ -n "$src_url" ]] || ynh_die "No URL defined for source $source_id$arch_prefix ?"
|
||||
[[ -n "$src_sum" ]] || ynh_die "No sha256 sum defined for source $source_id$arch_prefix ?"
|
||||
|
||||
if [[ -z "$src_format" ]]; then
|
||||
if [[ "$src_url" =~ ^.*\.zip$ ]] || [[ "$src_url" =~ ^.*/zipball/.*$ ]]; then
|
||||
src_format="zip"
|
||||
elif [[ "$src_url" =~ ^.*\.tar\.gz$ ]] || [[ "$src_url" =~ ^.*\.tgz$ ]] || [[ "$src_url" =~ ^.*/tar\.gz/.*$ ]] || [[ "$src_url" =~ ^.*/tarball/.*$ ]]; then
|
||||
src_format="tar.gz"
|
||||
elif [[ "$src_url" =~ ^.*\.tar\.xz$ ]]; then
|
||||
src_format="tar.xz"
|
||||
elif [[ "$src_url" =~ ^.*\.tar\.bz2$ ]]; then
|
||||
src_format="tar.bz2"
|
||||
elif [[ -z "$src_extract" ]]; then
|
||||
src_extract="false"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
source_id="${source_id:-app}"
|
||||
local src_file_path="$YNH_APP_BASEDIR/conf/${source_id}.src"
|
||||
|
||||
# Load value from configuration file (see above for a small doc about this file
|
||||
# format)
|
||||
local src_url=$(grep 'SOURCE_URL=' "$src_file_path" | cut --delimiter='=' --fields=2-)
|
||||
local src_sum=$(grep 'SOURCE_SUM=' "$src_file_path" | cut --delimiter='=' --fields=2-)
|
||||
local src_sumprg=$(grep 'SOURCE_SUM_PRG=' "$src_file_path" | cut --delimiter='=' --fields=2-)
|
||||
local src_format=$(grep 'SOURCE_FORMAT=' "$src_file_path" | cut --delimiter='=' --fields=2-)
|
||||
local src_in_subdir=$(grep 'SOURCE_IN_SUBDIR=' "$src_file_path" | cut --delimiter='=' --fields=2-)
|
||||
local src_rename=$(grep 'SOURCE_FILENAME=' "$src_file_path" | cut --delimiter='=' --fields=2-)
|
||||
local src_extract=$(grep 'SOURCE_EXTRACT=' "$src_file_path" | cut --delimiter='=' --fields=2-)
|
||||
local src_platform=$(grep 'SOURCE_PLATFORM=' "$src_file_path" | cut --delimiter='=' --fields=2-)
|
||||
fi
|
||||
|
||||
# Default value
|
||||
src_sumprg=${src_sumprg:-sha256sum}
|
||||
src_in_subdir=${src_in_subdir:-true}
|
||||
src_format=${src_format:-tar.gz}
|
||||
src_format=$(echo "$src_format" | tr '[:upper:]' '[:lower:]')
|
||||
src_extract=${src_extract:-true}
|
||||
|
||||
if [[ "$src_extract" != "true" ]] && [[ "$src_extract" != "false" ]]; then
|
||||
ynh_die "For source $source_id, expected either 'true' or 'false' for the extract parameter"
|
||||
fi
|
||||
|
||||
# (Unused?) mecanism where one can have the file in a special local cache to not have to download it...
|
||||
local local_src="/opt/yunohost-apps-src/${YNH_APP_ID}/${source_id}"
|
||||
|
||||
# Gotta use this trick with 'dirname' because source_id may contain slashes x_x
|
||||
mkdir -p $(dirname /var/cache/yunohost/download/${YNH_APP_ID}/${source_id})
|
||||
src_filename="/var/cache/yunohost/download/${YNH_APP_ID}/${source_id}"
|
||||
|
||||
if [ "$src_format" = "docker" ]; then
|
||||
src_platform="${src_platform:-"linux/$YNH_ARCH"}"
|
||||
else
|
||||
if test -e "$local_src"; then
|
||||
cp $local_src $src_filename
|
||||
fi
|
||||
|
||||
[ -n "$src_url" ] || ynh_die "Couldn't parse SOURCE_URL from $src_file_path ?"
|
||||
|
||||
# If the file was prefetched but somehow doesn't match the sum, rm and redownload it
|
||||
if [ -e "$src_filename" ] && ! echo "${src_sum} ${src_filename}" | ${src_sumprg} --check --status; then
|
||||
rm -f "$src_filename"
|
||||
fi
|
||||
|
||||
# Only redownload the file if it wasnt prefetched
|
||||
if [ ! -e "$src_filename" ]; then
|
||||
# NB. we have to declare the var as local first,
|
||||
# otherwise 'local foo=$(false) || echo 'pwet'" does'nt work
|
||||
# because local always return 0 ...
|
||||
local out
|
||||
# Timeout option is here to enforce the timeout on dns query and tcp connect (c.f. man wget)
|
||||
out=$(wget --tries 3 --no-dns-cache --timeout 900 --no-verbose --output-document=$src_filename $src_url 2>&1) \
|
||||
|| ynh_die --message="$out"
|
||||
fi
|
||||
|
||||
# Check the control sum
|
||||
if ! echo "${src_sum} ${src_filename}" | ${src_sumprg} --check --status; then
|
||||
local actual_sum="$(${src_sumprg} ${src_filename} | cut --delimiter=' ' --fields=1)"
|
||||
local actual_size="$(du -hs ${src_filename} | cut --fields=1)"
|
||||
rm -f ${src_filename}
|
||||
ynh_die --message="Corrupt source for ${src_url}: Expected sha256sum to be ${src_sum} but got ${actual_sum} (size: ${actual_size})."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Keep files to be backup/restored at the end of the helper
|
||||
# Assuming $dest_dir already exists
|
||||
rm -rf /var/cache/yunohost/files_to_keep_during_setup_source/
|
||||
if [ -n "$keep" ] && [ -e "$dest_dir" ]; then
|
||||
local keep_dir=/var/cache/yunohost/files_to_keep_during_setup_source/${YNH_APP_ID}
|
||||
mkdir -p $keep_dir
|
||||
local stuff_to_keep
|
||||
for stuff_to_keep in $keep; do
|
||||
if [ -e "$dest_dir/$stuff_to_keep" ]; then
|
||||
mkdir --parents "$(dirname "$keep_dir/$stuff_to_keep")"
|
||||
cp --archive "$dest_dir/$stuff_to_keep" "$keep_dir/$stuff_to_keep"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "$full_replace" -eq 1 ]; then
|
||||
ynh_secure_remove --file="$dest_dir"
|
||||
fi
|
||||
|
||||
# Extract source into the app dir
|
||||
mkdir --parents "$dest_dir"
|
||||
|
||||
if [ -n "${install_dir:-}" ] && [ "$dest_dir" == "$install_dir" ]; then
|
||||
_ynh_apply_default_permissions $dest_dir
|
||||
fi
|
||||
if [ -n "${final_path:-}" ] && [ "$dest_dir" == "$final_path" ]; then
|
||||
_ynh_apply_default_permissions $dest_dir
|
||||
fi
|
||||
|
||||
if [[ "$src_extract" == "false" ]]; then
|
||||
if [[ -z "$src_rename" ]]; then
|
||||
mv $src_filename $dest_dir
|
||||
else
|
||||
mv $src_filename $dest_dir/$src_rename
|
||||
fi
|
||||
elif [[ "$src_format" == "docker" ]]; then
|
||||
"$YNH_HELPERS_DIR/vendor/docker-image-extract/docker-image-extract" -p $src_platform -o $dest_dir $src_url 2>&1
|
||||
elif [[ "$src_format" == "zip" ]]; then
|
||||
# Zip format
|
||||
# Using of a temp directory, because unzip doesn't manage --strip-components
|
||||
if $src_in_subdir; then
|
||||
local tmp_dir=$(mktemp --directory)
|
||||
unzip -quo $src_filename -d "$tmp_dir"
|
||||
cp --archive $tmp_dir/*/. "$dest_dir"
|
||||
ynh_secure_remove --file="$tmp_dir"
|
||||
else
|
||||
unzip -quo $src_filename -d "$dest_dir"
|
||||
fi
|
||||
ynh_secure_remove --file="$src_filename"
|
||||
else
|
||||
local strip=""
|
||||
if [ "$src_in_subdir" != "false" ]; then
|
||||
if [ "$src_in_subdir" == "true" ]; then
|
||||
local sub_dirs=1
|
||||
else
|
||||
local sub_dirs="$src_in_subdir"
|
||||
fi
|
||||
strip="--strip-components $sub_dirs"
|
||||
fi
|
||||
if [[ "$src_format" =~ ^tar.gz|tar.bz2|tar.xz$ ]]; then
|
||||
tar --extract --file=$src_filename --directory="$dest_dir" $strip
|
||||
else
|
||||
ynh_die --message="Archive format unrecognized."
|
||||
fi
|
||||
ynh_secure_remove --file="$src_filename"
|
||||
fi
|
||||
|
||||
# Apply patches
|
||||
if [ -d "$YNH_APP_BASEDIR/sources/patches/" ]; then
|
||||
local patches_folder=$(realpath $YNH_APP_BASEDIR/sources/patches/)
|
||||
if (($(find $patches_folder -type f -name "${source_id}-*.patch" 2> /dev/null | wc --lines) > "0")); then
|
||||
pushd "$dest_dir"
|
||||
for p in $patches_folder/${source_id}-*.patch; do
|
||||
echo $p
|
||||
patch --strip=1 < $p || ynh_print_warn --message="Packagers /!\\ patch $p failed to apply"
|
||||
done
|
||||
popd
|
||||
fi
|
||||
fi
|
||||
|
||||
# Add supplementary files
|
||||
if test -e "$YNH_APP_BASEDIR/sources/extra_files/${source_id}"; then
|
||||
cp --archive $YNH_APP_BASEDIR/sources/extra_files/$source_id/. "$dest_dir"
|
||||
fi
|
||||
|
||||
# Keep files to be backup/restored at the end of the helper
|
||||
# Assuming $dest_dir already exists
|
||||
if [ -n "$keep" ]; then
|
||||
local keep_dir=/var/cache/yunohost/files_to_keep_during_setup_source/${YNH_APP_ID}
|
||||
local stuff_to_keep
|
||||
for stuff_to_keep in $keep; do
|
||||
if [ -e "$keep_dir/$stuff_to_keep" ]; then
|
||||
mkdir --parents "$(dirname "$dest_dir/$stuff_to_keep")"
|
||||
|
||||
# We add "--no-target-directory" (short option is -T) to handle the special case
|
||||
# when we "keep" a folder, but then the new setup already contains the same dir (but possibly empty)
|
||||
# in which case a regular "cp" will create a copy of the directory inside the directory ...
|
||||
# resulting in something like /var/www/$app/data/data instead of /var/www/$app/data
|
||||
# cf https://unix.stackexchange.com/q/94831 for a more elaborate explanation on the option
|
||||
cp --archive --no-target-directory "$keep_dir/$stuff_to_keep" "$dest_dir/$stuff_to_keep"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
rm -rf /var/cache/yunohost/files_to_keep_during_setup_source/
|
||||
}
|
|
@ -21,7 +21,7 @@ ynh_string_random() {
|
|||
length=${length:-24}
|
||||
filter=${filter:-'A-Za-z0-9'}
|
||||
|
||||
dd if=/dev/urandom bs=1 count=1000 2>/dev/null \
|
||||
dd if=/dev/urandom bs=1 count=1000 2> /dev/null \
|
||||
| tr --complement --delete "$filter" \
|
||||
| sed --quiet 's/\(.\{'"$length"'\}\).*/\1/p'
|
||||
}
|
||||
|
|
|
@ -94,12 +94,12 @@ ynh_systemd_action() {
|
|||
# Following the starting of the app in its log
|
||||
if [ "$log_path" == "systemd" ]; then
|
||||
# Read the systemd journal
|
||||
journalctl --unit=$service_name --follow --since=-0 --quiet >"$templog" &
|
||||
journalctl --unit=$service_name --follow --since=-0 --quiet > "$templog" &
|
||||
# Get the PID of the journalctl command
|
||||
local pid_tail=$!
|
||||
else
|
||||
# Read the specified log file
|
||||
tail --follow=name --retry --lines=0 "$log_path" >"$templog" 2>&1 &
|
||||
tail --follow=name --retry --lines=0 "$log_path" > "$templog" 2>&1 &
|
||||
# Get the PID of the tail command
|
||||
local pid_tail=$!
|
||||
fi
|
||||
|
@ -149,8 +149,7 @@ ynh_systemd_action() {
|
|||
# Also check the timeout using actual timestamp, because sometimes for some reason,
|
||||
# journalctl may take a huge time to run, and we end up waiting literally an entire hour
|
||||
# instead of 5 min ...
|
||||
if [[ "$(( $(date +%s) - $starttime))" -gt "$timeout" ]]
|
||||
then
|
||||
if [[ "$(($(date +%s) - $starttime))" -gt "$timeout" ]]; then
|
||||
i=$timeout
|
||||
break
|
||||
fi
|
||||
|
|
|
@ -1,59 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Check if a YunoHost user exists
|
||||
#
|
||||
# usage: ynh_user_exists --username=username
|
||||
# | arg: -u, --username= - the username to check
|
||||
# | ret: 0 if the user exists, 1 otherwise.
|
||||
#
|
||||
# example: ynh_user_exists 'toto' || echo "User does not exist"
|
||||
#
|
||||
# Requires YunoHost version 2.2.4 or higher.
|
||||
ynh_user_exists() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=u
|
||||
local -A args_array=([u]=username=)
|
||||
local username
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
yunohost user list --output-as json --quiet | jq -e ".users.\"${username}\"" >/dev/null
|
||||
}
|
||||
|
||||
# Retrieve a YunoHost user information
|
||||
#
|
||||
# usage: ynh_user_get_info --username=username --key=key
|
||||
# | arg: -u, --username= - the username to retrieve info from
|
||||
# | arg: -k, --key= - the key to retrieve
|
||||
# | ret: the value associate to that key
|
||||
#
|
||||
# example: mail=$(ynh_user_get_info --username="toto" --key=mail)
|
||||
#
|
||||
# Requires YunoHost version 2.2.4 or higher.
|
||||
ynh_user_get_info() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=uk
|
||||
local -A args_array=([u]=username= [k]=key=)
|
||||
local username
|
||||
local key
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
yunohost user info "$username" --output-as json --quiet | jq -r ".$key"
|
||||
}
|
||||
|
||||
# Get the list of YunoHost users
|
||||
#
|
||||
# usage: ynh_user_list
|
||||
# | ret: one username per line as strings
|
||||
#
|
||||
# example: for u in $(ynh_user_list); do ... ; done
|
||||
#
|
||||
# Requires YunoHost version 2.4.0 or higher.
|
||||
ynh_user_list() {
|
||||
yunohost user list --output-as json --quiet | jq -r ".users | keys[]"
|
||||
}
|
||||
|
||||
# Check if a user exists on the system
|
||||
#
|
||||
# [packagingv1]
|
||||
|
@ -71,7 +17,7 @@ ynh_system_user_exists() {
|
|||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
getent passwd "$username" &>/dev/null
|
||||
getent passwd "$username" &> /dev/null
|
||||
}
|
||||
|
||||
# Check if a group exists on the system
|
||||
|
@ -91,13 +37,11 @@ ynh_system_group_exists() {
|
|||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
getent group "$group" &>/dev/null
|
||||
getent group "$group" &> /dev/null
|
||||
}
|
||||
|
||||
# Create a system user
|
||||
#
|
||||
# [packagingv1]
|
||||
#
|
||||
# usage: ynh_system_user_create --username=user_name [--home_dir=home_dir] [--use_shell] [--groups="group1 group2"]
|
||||
# | arg: -u, --username= - Name of the system user that will be create
|
||||
# | arg: -h, --home_dir= - Path of the home dir for the user. Usually the final path of the app. If this argument is omitted, the user will be created without home
|
||||
|
@ -152,8 +96,6 @@ ynh_system_user_create() {
|
|||
|
||||
# Delete a system user
|
||||
#
|
||||
# [packagingv1]
|
||||
#
|
||||
# usage: ynh_system_user_delete --username=user_name
|
||||
# | arg: -u, --username= - Name of the system user that will be create
|
||||
#
|
406
helpers/helpers.v1.d/templating
Normal file
406
helpers/helpers.v1.d/templating
Normal file
|
@ -0,0 +1,406 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Create a dedicated config file from a template
|
||||
#
|
||||
# usage: ynh_add_config --template="template" --destination="destination"
|
||||
# | arg: -t, --template= - Template config file to use
|
||||
# | arg: -d, --destination= - Destination of the config file
|
||||
# | arg: -j, --jinja - Use jinja template instead of the simple `__MY_VAR__` templating format
|
||||
#
|
||||
# examples:
|
||||
# ynh_add_config --template=".env" --destination="$install_dir/.env" # (use the template file "conf/.env" from the app's package)
|
||||
# ynh_add_config --jinja --template="config.j2" --destination="$install_dir/config" # (use the template file "conf/config.j2" from the app's package)
|
||||
#
|
||||
# The template can be by default the name of a file in the conf directory
|
||||
# of a YunoHost Package, a relative path or an absolute path.
|
||||
#
|
||||
# The helper will use the template `template` to generate a config file
|
||||
# `destination` by replacing the following keywords with global variables
|
||||
# that should be defined before calling this helper :
|
||||
# ```
|
||||
# __PATH__ by $path_url
|
||||
# __NAME__ by $app
|
||||
# __NAMETOCHANGE__ by $app
|
||||
# __USER__ by $app
|
||||
# __FINALPATH__ by $final_path
|
||||
# __PHPVERSION__ by $YNH_PHP_VERSION (packaging v1 only, packaging v2 uses phpversion setting implicitly set by apt resource)
|
||||
# __YNH_NODE_LOAD_PATH__ by $ynh_node_load_PATH
|
||||
# ```
|
||||
# And any dynamic variables that should be defined before calling this helper like:
|
||||
# ```
|
||||
# __DOMAIN__ by $domain
|
||||
# __APP__ by $app
|
||||
# __VAR_1__ by $var_1
|
||||
# __VAR_2__ by $var_2
|
||||
# ```
|
||||
#
|
||||
# ##### When --jinja is enabled
|
||||
#
|
||||
# This option is meant for advanced use-cases where the "simple" templating
|
||||
# mode ain't enough because you need conditional blocks or loops.
|
||||
#
|
||||
# For a full documentation of jinja's syntax you can refer to:
|
||||
# https://jinja.palletsprojects.com/en/3.1.x/templates/
|
||||
#
|
||||
# Note that in YunoHost context, all variables are from shell variables and therefore are strings
|
||||
#
|
||||
# ##### Keeping track of manual changes by the admin
|
||||
#
|
||||
# The helper will verify the checksum and backup the destination file
|
||||
# if it's different before applying the new template.
|
||||
#
|
||||
# And it will calculate and store the destination file checksum
|
||||
# into the app settings when configuration is done.
|
||||
#
|
||||
# Requires YunoHost version 4.1.0 or higher.
|
||||
ynh_add_config() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=tdj
|
||||
local -A args_array=([t]=template= [d]=destination= [j]=jinja)
|
||||
local template
|
||||
local destination
|
||||
local jinja
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
local template_path
|
||||
jinja="${jinja:-0}"
|
||||
|
||||
if [ -f "$YNH_APP_BASEDIR/conf/$template" ]; then
|
||||
template_path="$YNH_APP_BASEDIR/conf/$template"
|
||||
elif [ -f "$template" ]; then
|
||||
template_path=$template
|
||||
else
|
||||
ynh_die --message="The provided template $template doesn't exist"
|
||||
fi
|
||||
|
||||
ynh_backup_if_checksum_is_different --file="$destination"
|
||||
|
||||
# Make sure to set the permissions before we copy the file
|
||||
# This is to cover a case where an attacker could have
|
||||
# created a file beforehand to have control over it
|
||||
# (cp won't overwrite ownership / modes by default...)
|
||||
touch $destination
|
||||
chmod 640 $destination
|
||||
_ynh_apply_default_permissions $destination
|
||||
|
||||
if [[ "$jinja" == 1 ]]; then
|
||||
# This is ran in a subshell such that the "export" does not "contaminate" the main process
|
||||
(
|
||||
export $(compgen -v)
|
||||
j2 "$template_path" -f env -o $destination
|
||||
)
|
||||
else
|
||||
cp -f "$template_path" "$destination"
|
||||
ynh_replace_vars --file="$destination"
|
||||
fi
|
||||
|
||||
ynh_store_file_checksum --file="$destination"
|
||||
}
|
||||
|
||||
# Replace variables in a file
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# usage: ynh_replace_vars --file="file"
|
||||
# | arg: -f, --file= - File where to replace variables
|
||||
#
|
||||
# The helper will replace the following keywords with global variables
|
||||
# that should be defined before calling this helper :
|
||||
# __PATH__ by $path_url
|
||||
# __NAME__ by $app
|
||||
# __NAMETOCHANGE__ by $app
|
||||
# __USER__ by $app
|
||||
# __FINALPATH__ by $final_path
|
||||
# __PHPVERSION__ by $YNH_PHP_VERSION (packaging v1 only, packaging v2 uses phpversion setting implicitly set by apt resource)
|
||||
# __YNH_NODE_LOAD_PATH__ by $ynh_node_load_PATH
|
||||
#
|
||||
# And any dynamic variables that should be defined before calling this helper like:
|
||||
# __DOMAIN__ by $domain
|
||||
# __APP__ by $app
|
||||
# __VAR_1__ by $var_1
|
||||
# __VAR_2__ by $var_2
|
||||
#
|
||||
# Requires YunoHost version 4.1.0 or higher.
|
||||
ynh_replace_vars() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=f
|
||||
local -A args_array=([f]=file=)
|
||||
local file
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
# Replace specific YunoHost variables
|
||||
if test -n "${path_url:-}"; then
|
||||
# path_url_slash_less is path_url, or a blank value if path_url is only '/'
|
||||
local path_url_slash_less=${path_url%/}
|
||||
ynh_replace_string --match_string="__PATH__/" --replace_string="$path_url_slash_less/" --target_file="$file"
|
||||
ynh_replace_string --match_string="__PATH__" --replace_string="$path_url" --target_file="$file"
|
||||
fi
|
||||
if test -n "${app:-}"; then
|
||||
ynh_replace_string --match_string="__NAME__" --replace_string="$app" --target_file="$file"
|
||||
ynh_replace_string --match_string="__NAMETOCHANGE__" --replace_string="$app" --target_file="$file"
|
||||
ynh_replace_string --match_string="__USER__" --replace_string="$app" --target_file="$file"
|
||||
fi
|
||||
# Legacy
|
||||
if test -n "${final_path:-}"; then
|
||||
ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="$file"
|
||||
ynh_replace_string --match_string="__INSTALL_DIR__" --replace_string="$final_path" --target_file="$file"
|
||||
fi
|
||||
# Legacy / Packaging v1 only
|
||||
if dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} lt 2 && test -n "${YNH_PHP_VERSION:-}"; then
|
||||
ynh_replace_string --match_string="__PHPVERSION__" --replace_string="$YNH_PHP_VERSION" --target_file="$file"
|
||||
fi
|
||||
if test -n "${ynh_node_load_PATH:-}"; then
|
||||
ynh_replace_string --match_string="__YNH_NODE_LOAD_PATH__" --replace_string="$ynh_node_load_PATH" --target_file="$file"
|
||||
fi
|
||||
|
||||
# Replace others variables
|
||||
|
||||
# List other unique (__ __) variables in $file
|
||||
local uniques_vars=($(grep -oP '__[A-Z0-9]+?[A-Z0-9_]*?[A-Z0-9]*?__' $file | sort --unique | sed "s@__\([^.]*\)__@\L\1@g"))
|
||||
|
||||
set +o xtrace # set +x
|
||||
|
||||
# Do the replacement
|
||||
local delimit=@
|
||||
for one_var in "${uniques_vars[@]}"; do
|
||||
# Validate that one_var is indeed defined
|
||||
# -v checks if the variable is defined, for example:
|
||||
# -v FOO tests if $FOO is defined
|
||||
# -v $FOO tests if ${!FOO} is defined
|
||||
# More info: https://stackoverflow.com/questions/3601515/how-to-check-if-a-variable-is-set-in-bash/17538964#comment96392525_17538964
|
||||
[[ -v "${one_var:-}" ]] || ynh_die --message="Variable \$$one_var wasn't initialized when trying to replace __${one_var^^}__ in $file"
|
||||
|
||||
# Escape delimiter in match/replace string
|
||||
match_string="__${one_var^^}__"
|
||||
match_string=${match_string//${delimit}/"\\${delimit}"}
|
||||
replace_string="${!one_var}"
|
||||
replace_string=${replace_string//\\/\\\\}
|
||||
replace_string=${replace_string//${delimit}/"\\${delimit}"}
|
||||
|
||||
# Actually replace (sed is used instead of ynh_replace_string to avoid triggering an epic amount of debug logs)
|
||||
sed --in-place "s${delimit}${match_string}${delimit}${replace_string}${delimit}g" "$file"
|
||||
done
|
||||
set -o xtrace # set -x
|
||||
}
|
||||
|
||||
# Get a value from heterogeneous file (yaml, json, php, python...)
|
||||
#
|
||||
# usage: ynh_read_var_in_file --file=PATH --key=KEY
|
||||
# | arg: -f, --file= - the path to the file
|
||||
# | arg: -k, --key= - the key to get
|
||||
# | arg: -a, --after= - the line just before the key (in case of multiple lines with the name of the key in the file)
|
||||
#
|
||||
# This helpers match several var affectation use case in several languages
|
||||
# We don't use jq or equivalent to keep comments and blank space in files
|
||||
# This helpers work line by line, it is not able to work correctly
|
||||
# if you have several identical keys in your files
|
||||
#
|
||||
# Example of line this helpers can managed correctly
|
||||
# .yml
|
||||
# title: YunoHost documentation
|
||||
# email: 'yunohost@yunohost.org'
|
||||
# .json
|
||||
# "theme": "colib'ris",
|
||||
# "port": 8102
|
||||
# "some_boolean": false,
|
||||
# "user": null
|
||||
# .ini
|
||||
# some_boolean = On
|
||||
# action = "Clear"
|
||||
# port = 20
|
||||
# .php
|
||||
# $user=
|
||||
# user => 20
|
||||
# .py
|
||||
# USER = 8102
|
||||
# user = 'https://donate.local'
|
||||
# CUSTOM['user'] = 'YunoHost'
|
||||
#
|
||||
# Requires YunoHost version 4.3 or higher.
|
||||
ynh_read_var_in_file() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=fka
|
||||
local -A args_array=([f]=file= [k]=key= [a]=after=)
|
||||
local file
|
||||
local key
|
||||
local after
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
after="${after:-}"
|
||||
|
||||
[[ -f $file ]] || ynh_die --message="File $file does not exists"
|
||||
|
||||
set +o xtrace # set +x
|
||||
|
||||
# Get the line number after which we search for the variable
|
||||
local line_number=1
|
||||
if [[ -n "$after" ]]; then
|
||||
line_number=$(grep -m1 -n $after $file | cut -d: -f1)
|
||||
if [[ -z "$line_number" ]]; then
|
||||
set -o xtrace # set -x
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
local filename="$(basename -- "$file")"
|
||||
local ext="${filename##*.}"
|
||||
local endline=',;'
|
||||
local assign="=>|:|="
|
||||
local comments="#"
|
||||
local string="\"'"
|
||||
if [[ "$ext" =~ ^ini|env|toml|yml|yaml$ ]]; then
|
||||
endline='#'
|
||||
fi
|
||||
if [[ "$ext" =~ ^ini|env$ ]]; then
|
||||
comments="[;#]"
|
||||
fi
|
||||
if [[ "php" == "$ext" ]] || [[ "$ext" == "js" ]]; then
|
||||
comments="//"
|
||||
fi
|
||||
local list='\[\s*['$string']?\w+['$string']?\]'
|
||||
local var_part='^\s*((const|var|let)\s+)?\$?(\w+('$list')*(->|\.|\[))*\s*'
|
||||
var_part+="[$string]?${key}[$string]?"
|
||||
var_part+='\s*\]?\s*'
|
||||
var_part+="($assign)"
|
||||
var_part+='\s*'
|
||||
|
||||
# Extract the part after assignation sign
|
||||
local expression_with_comment="$( (tail +$line_number ${file} | grep -i -o -P $var_part'\K.*$' || echo YNH_NULL) | head -n1)"
|
||||
if [[ "$expression_with_comment" == "YNH_NULL" ]]; then
|
||||
set -o xtrace # set -x
|
||||
echo YNH_NULL
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Remove comments if needed
|
||||
local expression="$(echo "$expression_with_comment" | sed "s@${comments}[^$string]*\$@@g" | sed "s@\s*[$endline]*\s*]*\$@@")"
|
||||
|
||||
local first_char="${expression:0:1}"
|
||||
if [[ "$first_char" == '"' ]]; then
|
||||
echo "$expression" | grep -m1 -o -P '"\K([^"](\\")?)*[^\\](?=")' | head -n1 | sed 's/\\"/"/g'
|
||||
elif [[ "$first_char" == "'" ]]; then
|
||||
echo "$expression" | grep -m1 -o -P "'\K([^'](\\\\')?)*[^\\\\](?=')" | head -n1 | sed "s/\\\\'/'/g"
|
||||
else
|
||||
echo "$expression"
|
||||
fi
|
||||
set -o xtrace # set -x
|
||||
}
|
||||
|
||||
# Set a value into heterogeneous file (yaml, json, php, python...)
|
||||
#
|
||||
# usage: ynh_write_var_in_file --file=PATH --key=KEY --value=VALUE
|
||||
# | arg: -f, --file= - the path to the file
|
||||
# | arg: -k, --key= - the key to set
|
||||
# | arg: -v, --value= - the value to set
|
||||
# | arg: -a, --after= - the line just before the key (in case of multiple lines with the name of the key in the file)
|
||||
#
|
||||
# Requires YunoHost version 4.3 or higher.
|
||||
ynh_write_var_in_file() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=fkva
|
||||
local -A args_array=([f]=file= [k]=key= [v]=value= [a]=after=)
|
||||
local file
|
||||
local key
|
||||
local value
|
||||
local after
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
after="${after:-}"
|
||||
|
||||
[[ -f $file ]] || ynh_die --message="File $file does not exists"
|
||||
|
||||
set +o xtrace # set +x
|
||||
|
||||
# Get the line number after which we search for the variable
|
||||
local after_line_number=1
|
||||
if [[ -n "$after" ]]; then
|
||||
after_line_number=$(grep -m1 -n $after $file | cut -d: -f1)
|
||||
if [[ -z "$after_line_number" ]]; then
|
||||
set -o xtrace # set -x
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
local filename="$(basename -- "$file")"
|
||||
local ext="${filename##*.}"
|
||||
local endline=',;'
|
||||
local assign="=>|:|="
|
||||
local comments="#"
|
||||
local string="\"'"
|
||||
if [[ "$ext" =~ ^ini|env|toml|yml|yaml$ ]]; then
|
||||
endline='#'
|
||||
fi
|
||||
if [[ "$ext" =~ ^ini|env$ ]]; then
|
||||
comments="[;#]"
|
||||
fi
|
||||
if [[ "php" == "$ext" ]] || [[ "$ext" == "js" ]]; then
|
||||
comments="//"
|
||||
fi
|
||||
local list='\[\s*['$string']?\w+['$string']?\]'
|
||||
local var_part='^\s*((const|var|let)\s+)?\$?(\w+('$list')*(->|\.|\[))*\s*'
|
||||
var_part+="[$string]?${key}[$string]?"
|
||||
var_part+='\s*\]?\s*'
|
||||
var_part+="($assign)"
|
||||
var_part+='\s*'
|
||||
|
||||
# Extract the part after assignation sign
|
||||
local expression_with_comment="$( (tail +$after_line_number ${file} | grep -i -o -P $var_part'\K.*$' || echo YNH_NULL) | head -n1)"
|
||||
if [[ "$expression_with_comment" == "YNH_NULL" ]]; then
|
||||
set -o xtrace # set -x
|
||||
return 1
|
||||
fi
|
||||
local value_line_number="$(tail +$after_line_number ${file} | grep -m1 -n -i -P $var_part'\K.*$' | cut -d: -f1)"
|
||||
value_line_number=$((after_line_number + value_line_number))
|
||||
local range="${after_line_number},${value_line_number} "
|
||||
|
||||
# Remove comments if needed
|
||||
local expression="$(echo "$expression_with_comment" | sed "s@${comments}[^$string]*\$@@g" | sed "s@\s*[$endline]*\s*]*\$@@")"
|
||||
endline=${expression_with_comment#"$expression"}
|
||||
endline="$(echo "$endline" | sed 's/\\/\\\\/g')"
|
||||
value="$(echo "$value" | sed 's/\\/\\\\/g')"
|
||||
value=${value//&/"\&"}
|
||||
local first_char="${expression:0:1}"
|
||||
delimiter=$'\001'
|
||||
if [[ "$first_char" == '"' ]]; then
|
||||
# \ and sed is quite complex you need 2 \\ to get one in a sed
|
||||
# So we need \\\\ to go through 2 sed
|
||||
value="$(echo "$value" | sed 's/"/\\\\"/g')"
|
||||
sed -ri "${range}s$delimiter"'(^'"${var_part}"'")([^"]|\\")*("[\s;,]*)(\s*'$comments'.*)?$'$delimiter'\1'"${value}"'"'"${endline}${delimiter}i" ${file}
|
||||
elif [[ "$first_char" == "'" ]]; then
|
||||
# \ and sed is quite complex you need 2 \\ to get one in a sed
|
||||
# However double quotes implies to double \\ to
|
||||
# So we need \\\\\\\\ to go through 2 sed and 1 double quotes str
|
||||
value="$(echo "$value" | sed "s/'/\\\\\\\\'/g")"
|
||||
sed -ri "${range}s$delimiter(^${var_part}')([^']|\\')*('"'[\s,;]*)(\s*'$comments'.*)?$'$delimiter'\1'"${value}'${endline}${delimiter}i" ${file}
|
||||
else
|
||||
if [[ "$value" == *"'"* ]] || [[ "$value" == *'"'* ]] || [[ "$ext" =~ ^php|py|json|js$ ]]; then
|
||||
value='\"'"$(echo "$value" | sed 's/"/\\\\"/g')"'\"'
|
||||
fi
|
||||
if [[ "$ext" =~ ^yaml|yml$ ]]; then
|
||||
value=" $value"
|
||||
fi
|
||||
sed -ri "${range}s$delimiter(^${var_part}).*\$$delimiter\1${value}${endline}${delimiter}i" ${file}
|
||||
fi
|
||||
set -o xtrace # set -x
|
||||
}
|
||||
|
||||
# Render templates with Jinja2
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# Attention : Variables should be exported before calling this helper to be
|
||||
# accessible inside templates.
|
||||
#
|
||||
# usage: ynh_render_template some_template output_path
|
||||
# | arg: some_template - Template file to be rendered
|
||||
# | arg: output_path - The path where the output will be redirected to
|
||||
ynh_render_template() {
|
||||
local template_path=$1
|
||||
local output_path=$2
|
||||
mkdir -p "$(dirname $output_path)"
|
||||
# Taken from https://stackoverflow.com/a/35009576
|
||||
python3 -c 'import os, sys, jinja2; sys.stdout.write(
|
||||
jinja2.Template(sys.stdin.read()
|
||||
).render(os.environ));' < $template_path > $output_path
|
||||
}
|
|
@ -22,8 +22,7 @@ YNH_APP_BASEDIR=${YNH_APP_BASEDIR:-$(realpath ..)}
|
|||
ynh_exit_properly() {
|
||||
local exit_code=$?
|
||||
|
||||
if [[ "${YNH_APP_ACTION:-}" =~ ^install$|^upgrade$|^restore$ ]]
|
||||
then
|
||||
if [[ "${YNH_APP_ACTION:-}" =~ ^install$|^upgrade$|^restore$ ]]; then
|
||||
rm -rf "/var/cache/yunohost/download/"
|
||||
fi
|
||||
|
||||
|
@ -39,7 +38,7 @@ ynh_exit_properly() {
|
|||
# Small tempo to avoid the next message being mixed up with other DEBUG messages
|
||||
sleep 0.5
|
||||
|
||||
if type -t ynh_clean_setup >/dev/null; then # Check if the function exist in the app script.
|
||||
if type -t ynh_clean_setup > /dev/null; then # Check if the function exist in the app script.
|
||||
ynh_clean_setup # Call the function to do specific cleaning for the app.
|
||||
fi
|
||||
|
||||
|
@ -67,327 +66,10 @@ ynh_abort_if_errors() {
|
|||
}
|
||||
|
||||
# When running an app script with packaging format >= 2, auto-enable ynh_abort_if_errors except for remove script
|
||||
if [[ "${YNH_CONTEXT:-}" != "regenconf" ]] && dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} ge 2 && [[ ${YNH_APP_ACTION} != "remove" ]]
|
||||
then
|
||||
if [[ "${YNH_CONTEXT:-}" != "regenconf" ]] && dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} ge 2 && [[ ${YNH_APP_ACTION} != "remove" ]]; then
|
||||
ynh_abort_if_errors
|
||||
fi
|
||||
|
||||
# Download, check integrity, uncompress and patch the source from app.src
|
||||
#
|
||||
# usage: ynh_setup_source --dest_dir=dest_dir [--source_id=source_id] [--keep="file1 file2"] [--full_replace]
|
||||
# | arg: -d, --dest_dir= - Directory where to setup sources
|
||||
# | arg: -s, --source_id= - Name of the source, defaults to `main` (when the sources resource exists in manifest.toml) or (legacy) `app` otherwise
|
||||
# | arg: -k, --keep= - Space-separated list of files/folders that will be backup/restored in $dest_dir, such as a config file you don't want to overwrite. For example 'conf.json secrets.json logs' (no trailing `/` for folders)
|
||||
# | arg: -r, --full_replace= - Remove previous sources before installing new sources (can be 1 or 0, default to 0)
|
||||
#
|
||||
# #### New 'sources' resources
|
||||
#
|
||||
# (See also the resources documentation which may be more complete?)
|
||||
#
|
||||
# This helper will read infos from the 'sources' resources in the manifest.toml of the app
|
||||
# and expect a structure like:
|
||||
#
|
||||
# ```toml
|
||||
# [resources.sources]
|
||||
# [resources.sources.main]
|
||||
# url = "https://some.address.to/download/the/app/archive"
|
||||
# sha256 = "0123456789abcdef" # The sha256 sum of the asset obtained from the URL
|
||||
# ```
|
||||
#
|
||||
# ##### Optional flags
|
||||
#
|
||||
# ```text
|
||||
# format = "tar.gz"/xz/bz2 # automatically guessed from the extension of the URL, but can be set explicitly. Will use `tar` to extract
|
||||
# "zip" # automatically guessed from the extension of the URL, but can be set explicitly. Will use `unzip` to extract
|
||||
# "docker" # useful to extract files from an already-built docker image (instead of rebuilding them locally). Will use `docker-image-extract` to extract
|
||||
# "whatever" # an arbitrary value, not really meaningful except to imply that the file won't be extracted
|
||||
#
|
||||
# in_subdir = true # default, there's an intermediate subdir in the archive before accessing the actual files
|
||||
# false # sources are directly in the archive root
|
||||
# n # (special cases) an integer representing a number of subdirs levels to get rid of
|
||||
#
|
||||
# extract = true # default if file is indeed an archive such as .zip, .tar.gz, .tar.bz2, ...
|
||||
# = false # default if file 'format' is not set and the file is not to be extracted because it is not an archive but a script or binary or whatever asset.
|
||||
# # in which case the file will only be `mv`ed to the location possibly renamed using the `rename` value
|
||||
#
|
||||
# rename = "whatever_your_want" # to be used for convenience when `extract` is false and the default name of the file is not practical
|
||||
# platform = "linux/amd64" # (defaults to "linux/$YNH_ARCH") to be used in conjonction with `format = "docker"` to specify which architecture to extract for
|
||||
# ```
|
||||
#
|
||||
# You may also define assets url and checksum per-architectures such as:
|
||||
# ```toml
|
||||
# [resources.sources]
|
||||
# [resources.sources.main]
|
||||
# amd64.url = "https://some.address.to/download/the/app/archive/when/amd64"
|
||||
# amd64.sha256 = "0123456789abcdef"
|
||||
# armhf.url = "https://some.address.to/download/the/app/archive/when/armhf"
|
||||
# armhf.sha256 = "fedcba9876543210"
|
||||
# ```
|
||||
#
|
||||
# In which case ynh_setup_source --dest_dir="$install_dir" will automatically pick the appropriate source depending on the arch
|
||||
#
|
||||
#
|
||||
#
|
||||
# #### Legacy format '.src'
|
||||
#
|
||||
# This helper will read `conf/${source_id}.src`, download and install the sources.
|
||||
#
|
||||
# The src file need to contains:
|
||||
# ```
|
||||
# SOURCE_URL=Address to download the app archive
|
||||
# SOURCE_SUM=Sha256 sum
|
||||
# SOURCE_FORMAT=tar.gz
|
||||
# SOURCE_IN_SUBDIR=false
|
||||
# SOURCE_FILENAME=example.tar.gz
|
||||
# SOURCE_EXTRACT=(true|false)
|
||||
# SOURCE_PLATFORM=linux/arm64/v8
|
||||
# ```
|
||||
#
|
||||
# The helper will:
|
||||
# - Download the specific URL if there is no local archive
|
||||
# - Check the integrity with the specific sha256 sum
|
||||
# - Uncompress the archive to `$dest_dir`.
|
||||
# - If `in_subdir` is true, the first level directory of the archive will be removed.
|
||||
# - If `in_subdir` is a numeric value, the N first level directories will be removed.
|
||||
# - Patches named `sources/patches/${src_id}-*.patch` will be applied to `$dest_dir`
|
||||
# - Extra files in `sources/extra_files/$src_id` will be copied to dest_dir
|
||||
#
|
||||
# Requires YunoHost version 2.6.4 or higher.
|
||||
ynh_setup_source() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=dsk
|
||||
local -A args_array=([d]=dest_dir= [s]=source_id= [k]=keep= [r]=full_replace=)
|
||||
local dest_dir
|
||||
local source_id
|
||||
local keep
|
||||
local full_replace
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
keep="${keep:-}"
|
||||
full_replace="${full_replace:-0}"
|
||||
|
||||
if test -e $YNH_APP_BASEDIR/manifest.toml && cat $YNH_APP_BASEDIR/manifest.toml | toml_to_json | jq -e '.resources.sources' >/dev/null
|
||||
then
|
||||
source_id="${source_id:-main}"
|
||||
local sources_json=$(cat $YNH_APP_BASEDIR/manifest.toml | toml_to_json | jq ".resources.sources[\"$source_id\"]")
|
||||
if jq -re ".url" <<< "$sources_json"
|
||||
then
|
||||
local arch_prefix=""
|
||||
else
|
||||
local arch_prefix=".$YNH_ARCH"
|
||||
fi
|
||||
|
||||
local src_url="$(jq -r "$arch_prefix.url" <<< "$sources_json" | sed 's/^null$//')"
|
||||
local src_sum="$(jq -r "$arch_prefix.sha256" <<< "$sources_json" | sed 's/^null$//')"
|
||||
local src_sumprg="sha256sum"
|
||||
local src_format="$(jq -r ".format" <<< "$sources_json" | sed 's/^null$//')"
|
||||
local src_in_subdir="$(jq -r ".in_subdir" <<< "$sources_json" | sed 's/^null$//')"
|
||||
local src_extract="$(jq -r ".extract" <<< "$sources_json" | sed 's/^null$//')"
|
||||
local src_platform="$(jq -r ".platform" <<< "$sources_json" | sed 's/^null$//')"
|
||||
local src_rename="$(jq -r ".rename" <<< "$sources_json" | sed 's/^null$//')"
|
||||
|
||||
[[ -n "$src_url" ]] || ynh_die "No URL defined for source $source_id$arch_prefix ?"
|
||||
[[ -n "$src_sum" ]] || ynh_die "No sha256 sum defined for source $source_id$arch_prefix ?"
|
||||
|
||||
if [[ -z "$src_format" ]]
|
||||
then
|
||||
if [[ "$src_url" =~ ^.*\.zip$ ]] || [[ "$src_url" =~ ^.*/zipball/.*$ ]]
|
||||
then
|
||||
src_format="zip"
|
||||
elif [[ "$src_url" =~ ^.*\.tar\.gz$ ]] || [[ "$src_url" =~ ^.*\.tgz$ ]] || [[ "$src_url" =~ ^.*/tar\.gz/.*$ ]] || [[ "$src_url" =~ ^.*/tarball/.*$ ]]
|
||||
then
|
||||
src_format="tar.gz"
|
||||
elif [[ "$src_url" =~ ^.*\.tar\.xz$ ]]
|
||||
then
|
||||
src_format="tar.xz"
|
||||
elif [[ "$src_url" =~ ^.*\.tar\.bz2$ ]]
|
||||
then
|
||||
src_format="tar.bz2"
|
||||
elif [[ -z "$src_extract" ]]
|
||||
then
|
||||
src_extract="false"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
source_id="${source_id:-app}"
|
||||
local src_file_path="$YNH_APP_BASEDIR/conf/${source_id}.src"
|
||||
|
||||
# Load value from configuration file (see above for a small doc about this file
|
||||
# format)
|
||||
local src_url=$(grep 'SOURCE_URL=' "$src_file_path" | cut --delimiter='=' --fields=2-)
|
||||
local src_sum=$(grep 'SOURCE_SUM=' "$src_file_path" | cut --delimiter='=' --fields=2-)
|
||||
local src_sumprg=$(grep 'SOURCE_SUM_PRG=' "$src_file_path" | cut --delimiter='=' --fields=2-)
|
||||
local src_format=$(grep 'SOURCE_FORMAT=' "$src_file_path" | cut --delimiter='=' --fields=2-)
|
||||
local src_in_subdir=$(grep 'SOURCE_IN_SUBDIR=' "$src_file_path" | cut --delimiter='=' --fields=2-)
|
||||
local src_rename=$(grep 'SOURCE_FILENAME=' "$src_file_path" | cut --delimiter='=' --fields=2-)
|
||||
local src_extract=$(grep 'SOURCE_EXTRACT=' "$src_file_path" | cut --delimiter='=' --fields=2-)
|
||||
local src_platform=$(grep 'SOURCE_PLATFORM=' "$src_file_path" | cut --delimiter='=' --fields=2-)
|
||||
fi
|
||||
|
||||
# Default value
|
||||
src_sumprg=${src_sumprg:-sha256sum}
|
||||
src_in_subdir=${src_in_subdir:-true}
|
||||
src_format=${src_format:-tar.gz}
|
||||
src_format=$(echo "$src_format" | tr '[:upper:]' '[:lower:]')
|
||||
src_extract=${src_extract:-true}
|
||||
|
||||
if [[ "$src_extract" != "true" ]] && [[ "$src_extract" != "false" ]]
|
||||
then
|
||||
ynh_die "For source $source_id, expected either 'true' or 'false' for the extract parameter"
|
||||
fi
|
||||
|
||||
|
||||
# (Unused?) mecanism where one can have the file in a special local cache to not have to download it...
|
||||
local local_src="/opt/yunohost-apps-src/${YNH_APP_ID}/${source_id}"
|
||||
|
||||
# Gotta use this trick with 'dirname' because source_id may contain slashes x_x
|
||||
mkdir -p $(dirname /var/cache/yunohost/download/${YNH_APP_ID}/${source_id})
|
||||
src_filename="/var/cache/yunohost/download/${YNH_APP_ID}/${source_id}"
|
||||
|
||||
if [ "$src_format" = "docker" ]; then
|
||||
src_platform="${src_platform:-"linux/$YNH_ARCH"}"
|
||||
else
|
||||
if test -e "$local_src"; then
|
||||
cp $local_src $src_filename
|
||||
fi
|
||||
|
||||
[ -n "$src_url" ] || ynh_die "Couldn't parse SOURCE_URL from $src_file_path ?"
|
||||
|
||||
# If the file was prefetched but somehow doesn't match the sum, rm and redownload it
|
||||
if [ -e "$src_filename" ] && ! echo "${src_sum} ${src_filename}" | ${src_sumprg} --check --status
|
||||
then
|
||||
rm -f "$src_filename"
|
||||
fi
|
||||
|
||||
# Only redownload the file if it wasnt prefetched
|
||||
if [ ! -e "$src_filename" ]
|
||||
then
|
||||
# NB. we have to declare the var as local first,
|
||||
# otherwise 'local foo=$(false) || echo 'pwet'" does'nt work
|
||||
# because local always return 0 ...
|
||||
local out
|
||||
# Timeout option is here to enforce the timeout on dns query and tcp connect (c.f. man wget)
|
||||
out=$(wget --tries 3 --no-dns-cache --timeout 900 --no-verbose --output-document=$src_filename $src_url 2>&1) \
|
||||
|| ynh_die --message="$out"
|
||||
fi
|
||||
|
||||
# Check the control sum
|
||||
if ! echo "${src_sum} ${src_filename}" | ${src_sumprg} --check --status
|
||||
then
|
||||
local actual_sum="$(${src_sumprg} ${src_filename} | cut --delimiter=' ' --fields=1)"
|
||||
local actual_size="$(du -hs ${src_filename} | cut --fields=1)"
|
||||
rm -f ${src_filename}
|
||||
ynh_die --message="Corrupt source for ${src_url}: Expected sha256sum to be ${src_sum} but got ${actual_sum} (size: ${actual_size})."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Keep files to be backup/restored at the end of the helper
|
||||
# Assuming $dest_dir already exists
|
||||
rm -rf /var/cache/yunohost/files_to_keep_during_setup_source/
|
||||
if [ -n "$keep" ] && [ -e "$dest_dir" ]; then
|
||||
local keep_dir=/var/cache/yunohost/files_to_keep_during_setup_source/${YNH_APP_ID}
|
||||
mkdir -p $keep_dir
|
||||
local stuff_to_keep
|
||||
for stuff_to_keep in $keep; do
|
||||
if [ -e "$dest_dir/$stuff_to_keep" ]; then
|
||||
mkdir --parents "$(dirname "$keep_dir/$stuff_to_keep")"
|
||||
cp --archive "$dest_dir/$stuff_to_keep" "$keep_dir/$stuff_to_keep"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "$full_replace" -eq 1 ]; then
|
||||
ynh_secure_remove --file="$dest_dir"
|
||||
fi
|
||||
|
||||
# Extract source into the app dir
|
||||
mkdir --parents "$dest_dir"
|
||||
|
||||
if [ -n "${install_dir:-}" ] && [ "$dest_dir" == "$install_dir" ]; then
|
||||
_ynh_apply_default_permissions $dest_dir
|
||||
fi
|
||||
if [ -n "${final_path:-}" ] && [ "$dest_dir" == "$final_path" ]; then
|
||||
_ynh_apply_default_permissions $dest_dir
|
||||
fi
|
||||
|
||||
if [[ "$src_extract" == "false" ]]; then
|
||||
if [[ -z "$src_rename" ]]
|
||||
then
|
||||
mv $src_filename $dest_dir
|
||||
else
|
||||
mv $src_filename $dest_dir/$src_rename
|
||||
fi
|
||||
elif [[ "$src_format" == "docker" ]]; then
|
||||
"$YNH_HELPERS_DIR/vendor/docker-image-extract/docker-image-extract" -p $src_platform -o $dest_dir $src_url 2>&1
|
||||
elif [[ "$src_format" == "zip" ]]; then
|
||||
# Zip format
|
||||
# Using of a temp directory, because unzip doesn't manage --strip-components
|
||||
if $src_in_subdir; then
|
||||
local tmp_dir=$(mktemp --directory)
|
||||
unzip -quo $src_filename -d "$tmp_dir"
|
||||
cp --archive $tmp_dir/*/. "$dest_dir"
|
||||
ynh_secure_remove --file="$tmp_dir"
|
||||
else
|
||||
unzip -quo $src_filename -d "$dest_dir"
|
||||
fi
|
||||
ynh_secure_remove --file="$src_filename"
|
||||
else
|
||||
local strip=""
|
||||
if [ "$src_in_subdir" != "false" ]; then
|
||||
if [ "$src_in_subdir" == "true" ]; then
|
||||
local sub_dirs=1
|
||||
else
|
||||
local sub_dirs="$src_in_subdir"
|
||||
fi
|
||||
strip="--strip-components $sub_dirs"
|
||||
fi
|
||||
if [[ "$src_format" =~ ^tar.gz|tar.bz2|tar.xz$ ]]; then
|
||||
tar --extract --file=$src_filename --directory="$dest_dir" $strip
|
||||
else
|
||||
ynh_die --message="Archive format unrecognized."
|
||||
fi
|
||||
ynh_secure_remove --file="$src_filename"
|
||||
fi
|
||||
|
||||
# Apply patches
|
||||
if [ -d "$YNH_APP_BASEDIR/sources/patches/" ]; then
|
||||
local patches_folder=$(realpath $YNH_APP_BASEDIR/sources/patches/)
|
||||
if (($(find $patches_folder -type f -name "${source_id}-*.patch" 2>/dev/null | wc --lines) > "0")); then
|
||||
pushd "$dest_dir"
|
||||
for p in $patches_folder/${source_id}-*.patch; do
|
||||
echo $p
|
||||
patch --strip=1 <$p || ynh_print_warn --message="Packagers /!\\ patch $p failed to apply"
|
||||
done
|
||||
popd
|
||||
fi
|
||||
fi
|
||||
|
||||
# Add supplementary files
|
||||
if test -e "$YNH_APP_BASEDIR/sources/extra_files/${source_id}"; then
|
||||
cp --archive $YNH_APP_BASEDIR/sources/extra_files/$source_id/. "$dest_dir"
|
||||
fi
|
||||
|
||||
# Keep files to be backup/restored at the end of the helper
|
||||
# Assuming $dest_dir already exists
|
||||
if [ -n "$keep" ]; then
|
||||
local keep_dir=/var/cache/yunohost/files_to_keep_during_setup_source/${YNH_APP_ID}
|
||||
local stuff_to_keep
|
||||
for stuff_to_keep in $keep; do
|
||||
if [ -e "$keep_dir/$stuff_to_keep" ]; then
|
||||
mkdir --parents "$(dirname "$dest_dir/$stuff_to_keep")"
|
||||
|
||||
# We add "--no-target-directory" (short option is -T) to handle the special case
|
||||
# when we "keep" a folder, but then the new setup already contains the same dir (but possibly empty)
|
||||
# in which case a regular "cp" will create a copy of the directory inside the directory ...
|
||||
# resulting in something like /var/www/$app/data/data instead of /var/www/$app/data
|
||||
# cf https://unix.stackexchange.com/q/94831 for a more elaborate explanation on the option
|
||||
cp --archive --no-target-directory "$keep_dir/$stuff_to_keep" "$dest_dir/$stuff_to_keep"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
rm -rf /var/cache/yunohost/files_to_keep_during_setup_source/
|
||||
}
|
||||
|
||||
# Curl abstraction to help with POST requests to local pages (such as installation forms)
|
||||
#
|
||||
# usage: ynh_local_curl "page_uri" "key1=value1" "key2=value2" ...
|
||||
|
@ -447,435 +129,6 @@ ynh_local_curl() {
|
|||
fi
|
||||
}
|
||||
|
||||
# Create a dedicated config file from a template
|
||||
#
|
||||
# usage: ynh_add_config --template="template" --destination="destination"
|
||||
# | arg: -t, --template= - Template config file to use
|
||||
# | arg: -d, --destination= - Destination of the config file
|
||||
# | arg: -j, --jinja - Use jinja template instead of legacy __MY_VAR__
|
||||
#
|
||||
# examples:
|
||||
# ynh_add_config --template=".env" --destination="$install_dir/.env" use the template file "../conf/.env"
|
||||
# ynh_add_config --jinja --template="config.j2" --destination="$install_dir/config" use the template file "../conf/config.j2"
|
||||
# ynh_add_config --template="/etc/nginx/sites-available/default" --destination="etc/nginx/sites-available/mydomain.conf"
|
||||
#
|
||||
##
|
||||
## How it works in "legacy" mode
|
||||
##
|
||||
# The template can be by default the name of a file in the conf directory
|
||||
# of a YunoHost Package, a relative path or an absolute path.
|
||||
#
|
||||
# The helper will use the template `template` to generate a config file
|
||||
# `destination` by replacing the following keywords with global variables
|
||||
# that should be defined before calling this helper :
|
||||
# ```
|
||||
# __PATH__ by $path_url
|
||||
# __NAME__ by $app
|
||||
# __NAMETOCHANGE__ by $app
|
||||
# __USER__ by $app
|
||||
# __FINALPATH__ by $final_path
|
||||
# __PHPVERSION__ by $YNH_PHP_VERSION (packaging v1 only, packaging v2 uses phpversion setting implicitly set by apt resource)
|
||||
# __YNH_NODE_LOAD_PATH__ by $ynh_node_load_PATH
|
||||
# ```
|
||||
# And any dynamic variables that should be defined before calling this helper like:
|
||||
# ```
|
||||
# __DOMAIN__ by $domain
|
||||
# __APP__ by $app
|
||||
# __VAR_1__ by $var_1
|
||||
# __VAR_2__ by $var_2
|
||||
# ```
|
||||
#
|
||||
##
|
||||
## When --jinja is enabled
|
||||
##
|
||||
# For a full documentation of the template you can refer to: https://jinja.palletsprojects.com/en/3.1.x/templates/
|
||||
# In Yunohost context there are no really some specificity except that all variable passed are of type string.
|
||||
# So here are some example of recommended usage:
|
||||
#
|
||||
# If you need a conditional block
|
||||
#
|
||||
# {% if should_my_block_be_shown == 'true' %}
|
||||
# ...
|
||||
# {% endif %}
|
||||
#
|
||||
# or
|
||||
#
|
||||
# {% if should_my_block_be_shown == '1' %}
|
||||
# ...
|
||||
# {% endif %}
|
||||
#
|
||||
# If you need to iterate with loop:
|
||||
#
|
||||
# {% for yolo in var_with_multiline_value.splitlines() %}
|
||||
# ...
|
||||
# {% endfor %}
|
||||
#
|
||||
# or
|
||||
#
|
||||
# {% for jail in my_var_with_coma.split(',') %}
|
||||
# ...
|
||||
# {% endfor %}
|
||||
#
|
||||
# The helper will verify the checksum and backup the destination file
|
||||
# if it's different before applying the new template.
|
||||
#
|
||||
# And it will calculate and store the destination file checksum
|
||||
# into the app settings when configuration is done.
|
||||
#
|
||||
# Requires YunoHost version 4.1.0 or higher.
|
||||
ynh_add_config() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=tdj
|
||||
local -A args_array=([t]=template= [d]=destination= [j]=jinja)
|
||||
local template
|
||||
local destination
|
||||
local jinja
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
local template_path
|
||||
jinja="${jinja:-0}"
|
||||
|
||||
if [ -f "$YNH_APP_BASEDIR/conf/$template" ]; then
|
||||
template_path="$YNH_APP_BASEDIR/conf/$template"
|
||||
elif [ -f "$template" ]; then
|
||||
template_path=$template
|
||||
else
|
||||
ynh_die --message="The provided template $template doesn't exist"
|
||||
fi
|
||||
|
||||
ynh_backup_if_checksum_is_different --file="$destination"
|
||||
|
||||
# Make sure to set the permissions before we copy the file
|
||||
# This is to cover a case where an attacker could have
|
||||
# created a file beforehand to have control over it
|
||||
# (cp won't overwrite ownership / modes by default...)
|
||||
touch $destination
|
||||
chmod 640 $destination
|
||||
_ynh_apply_default_permissions $destination
|
||||
|
||||
if [[ "$jinja" == 1 ]]
|
||||
then
|
||||
# This is ran in a subshell such that the "export" does not "contaminate" the main process
|
||||
(
|
||||
export $(compgen -v)
|
||||
j2 "$template_path" -f env -o $destination
|
||||
)
|
||||
else
|
||||
cp -f "$template_path" "$destination"
|
||||
ynh_replace_vars --file="$destination"
|
||||
fi
|
||||
|
||||
ynh_store_file_checksum --file="$destination"
|
||||
}
|
||||
|
||||
# Replace variables in a file
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# usage: ynh_replace_vars --file="file"
|
||||
# | arg: -f, --file= - File where to replace variables
|
||||
#
|
||||
# The helper will replace the following keywords with global variables
|
||||
# that should be defined before calling this helper :
|
||||
# __PATH__ by $path_url
|
||||
# __NAME__ by $app
|
||||
# __NAMETOCHANGE__ by $app
|
||||
# __USER__ by $app
|
||||
# __FINALPATH__ by $final_path
|
||||
# __PHPVERSION__ by $YNH_PHP_VERSION (packaging v1 only, packaging v2 uses phpversion setting implicitly set by apt resource)
|
||||
# __YNH_NODE_LOAD_PATH__ by $ynh_node_load_PATH
|
||||
#
|
||||
# And any dynamic variables that should be defined before calling this helper like:
|
||||
# __DOMAIN__ by $domain
|
||||
# __APP__ by $app
|
||||
# __VAR_1__ by $var_1
|
||||
# __VAR_2__ by $var_2
|
||||
#
|
||||
# Requires YunoHost version 4.1.0 or higher.
|
||||
ynh_replace_vars() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=f
|
||||
local -A args_array=([f]=file=)
|
||||
local file
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
# Replace specific YunoHost variables
|
||||
if test -n "${path_url:-}"; then
|
||||
# path_url_slash_less is path_url, or a blank value if path_url is only '/'
|
||||
local path_url_slash_less=${path_url%/}
|
||||
ynh_replace_string --match_string="__PATH__/" --replace_string="$path_url_slash_less/" --target_file="$file"
|
||||
ynh_replace_string --match_string="__PATH__" --replace_string="$path_url" --target_file="$file"
|
||||
fi
|
||||
if test -n "${app:-}"; then
|
||||
ynh_replace_string --match_string="__NAME__" --replace_string="$app" --target_file="$file"
|
||||
ynh_replace_string --match_string="__NAMETOCHANGE__" --replace_string="$app" --target_file="$file"
|
||||
ynh_replace_string --match_string="__USER__" --replace_string="$app" --target_file="$file"
|
||||
fi
|
||||
# Legacy
|
||||
if test -n "${final_path:-}"; then
|
||||
ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="$file"
|
||||
ynh_replace_string --match_string="__INSTALL_DIR__" --replace_string="$final_path" --target_file="$file"
|
||||
fi
|
||||
# Legacy / Packaging v1 only
|
||||
if dpkg --compare-versions ${YNH_APP_PACKAGING_FORMAT:-0} lt 2 && test -n "${YNH_PHP_VERSION:-}"; then
|
||||
ynh_replace_string --match_string="__PHPVERSION__" --replace_string="$YNH_PHP_VERSION" --target_file="$file"
|
||||
fi
|
||||
if test -n "${ynh_node_load_PATH:-}"; then
|
||||
ynh_replace_string --match_string="__YNH_NODE_LOAD_PATH__" --replace_string="$ynh_node_load_PATH" --target_file="$file"
|
||||
fi
|
||||
|
||||
# Replace others variables
|
||||
|
||||
# List other unique (__ __) variables in $file
|
||||
local uniques_vars=($(grep -oP '__[A-Z0-9]+?[A-Z0-9_]*?[A-Z0-9]*?__' $file | sort --unique | sed "s@__\([^.]*\)__@\L\1@g"))
|
||||
|
||||
set +o xtrace # set +x
|
||||
|
||||
# Do the replacement
|
||||
local delimit=@
|
||||
for one_var in "${uniques_vars[@]}"; do
|
||||
# Validate that one_var is indeed defined
|
||||
# -v checks if the variable is defined, for example:
|
||||
# -v FOO tests if $FOO is defined
|
||||
# -v $FOO tests if ${!FOO} is defined
|
||||
# More info: https://stackoverflow.com/questions/3601515/how-to-check-if-a-variable-is-set-in-bash/17538964#comment96392525_17538964
|
||||
[[ -v "${one_var:-}" ]] || ynh_die --message="Variable \$$one_var wasn't initialized when trying to replace __${one_var^^}__ in $file"
|
||||
|
||||
# Escape delimiter in match/replace string
|
||||
match_string="__${one_var^^}__"
|
||||
match_string=${match_string//${delimit}/"\\${delimit}"}
|
||||
replace_string="${!one_var}"
|
||||
replace_string=${replace_string//\\/\\\\}
|
||||
replace_string=${replace_string//${delimit}/"\\${delimit}"}
|
||||
|
||||
# Actually replace (sed is used instead of ynh_replace_string to avoid triggering an epic amount of debug logs)
|
||||
sed --in-place "s${delimit}${match_string}${delimit}${replace_string}${delimit}g" "$file"
|
||||
done
|
||||
set -o xtrace # set -x
|
||||
}
|
||||
|
||||
# Get a value from heterogeneous file (yaml, json, php, python...)
|
||||
#
|
||||
# usage: ynh_read_var_in_file --file=PATH --key=KEY
|
||||
# | arg: -f, --file= - the path to the file
|
||||
# | arg: -k, --key= - the key to get
|
||||
# | arg: -a, --after= - the line just before the key (in case of multiple lines with the name of the key in the file)
|
||||
#
|
||||
# This helpers match several var affectation use case in several languages
|
||||
# We don't use jq or equivalent to keep comments and blank space in files
|
||||
# This helpers work line by line, it is not able to work correctly
|
||||
# if you have several identical keys in your files
|
||||
#
|
||||
# Example of line this helpers can managed correctly
|
||||
# .yml
|
||||
# title: YunoHost documentation
|
||||
# email: 'yunohost@yunohost.org'
|
||||
# .json
|
||||
# "theme": "colib'ris",
|
||||
# "port": 8102
|
||||
# "some_boolean": false,
|
||||
# "user": null
|
||||
# .ini
|
||||
# some_boolean = On
|
||||
# action = "Clear"
|
||||
# port = 20
|
||||
# .php
|
||||
# $user=
|
||||
# user => 20
|
||||
# .py
|
||||
# USER = 8102
|
||||
# user = 'https://donate.local'
|
||||
# CUSTOM['user'] = 'YunoHost'
|
||||
#
|
||||
# Requires YunoHost version 4.3 or higher.
|
||||
ynh_read_var_in_file() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=fka
|
||||
local -A args_array=([f]=file= [k]=key= [a]=after=)
|
||||
local file
|
||||
local key
|
||||
local after
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
after="${after:-}"
|
||||
|
||||
[[ -f $file ]] || ynh_die --message="File $file does not exists"
|
||||
|
||||
set +o xtrace # set +x
|
||||
|
||||
# Get the line number after which we search for the variable
|
||||
local line_number=1
|
||||
if [[ -n "$after" ]]; then
|
||||
line_number=$(grep -m1 -n $after $file | cut -d: -f1)
|
||||
if [[ -z "$line_number" ]]; then
|
||||
set -o xtrace # set -x
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
local filename="$(basename -- "$file")"
|
||||
local ext="${filename##*.}"
|
||||
local endline=',;'
|
||||
local assign="=>|:|="
|
||||
local comments="#"
|
||||
local string="\"'"
|
||||
if [[ "$ext" =~ ^ini|env|toml|yml|yaml$ ]]; then
|
||||
endline='#'
|
||||
fi
|
||||
if [[ "$ext" =~ ^ini|env$ ]]; then
|
||||
comments="[;#]"
|
||||
fi
|
||||
if [[ "php" == "$ext" ]] || [[ "$ext" == "js" ]]; then
|
||||
comments="//"
|
||||
fi
|
||||
local list='\[\s*['$string']?\w+['$string']?\]'
|
||||
local var_part='^\s*((const|var|let)\s+)?\$?(\w+('$list')*(->|\.|\[))*\s*'
|
||||
var_part+="[$string]?${key}[$string]?"
|
||||
var_part+='\s*\]?\s*'
|
||||
var_part+="($assign)"
|
||||
var_part+='\s*'
|
||||
|
||||
# Extract the part after assignation sign
|
||||
local expression_with_comment="$((tail +$line_number ${file} | grep -i -o -P $var_part'\K.*$' || echo YNH_NULL) | head -n1)"
|
||||
if [[ "$expression_with_comment" == "YNH_NULL" ]]; then
|
||||
set -o xtrace # set -x
|
||||
echo YNH_NULL
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Remove comments if needed
|
||||
local expression="$(echo "$expression_with_comment" | sed "s@${comments}[^$string]*\$@@g" | sed "s@\s*[$endline]*\s*]*\$@@")"
|
||||
|
||||
local first_char="${expression:0:1}"
|
||||
if [[ "$first_char" == '"' ]]; then
|
||||
echo "$expression" | grep -m1 -o -P '"\K([^"](\\")?)*[^\\](?=")' | head -n1 | sed 's/\\"/"/g'
|
||||
elif [[ "$first_char" == "'" ]]; then
|
||||
echo "$expression" | grep -m1 -o -P "'\K([^'](\\\\')?)*[^\\\\](?=')" | head -n1 | sed "s/\\\\'/'/g"
|
||||
else
|
||||
echo "$expression"
|
||||
fi
|
||||
set -o xtrace # set -x
|
||||
}
|
||||
|
||||
# Set a value into heterogeneous file (yaml, json, php, python...)
|
||||
#
|
||||
# usage: ynh_write_var_in_file --file=PATH --key=KEY --value=VALUE
|
||||
# | arg: -f, --file= - the path to the file
|
||||
# | arg: -k, --key= - the key to set
|
||||
# | arg: -v, --value= - the value to set
|
||||
# | arg: -a, --after= - the line just before the key (in case of multiple lines with the name of the key in the file)
|
||||
#
|
||||
# Requires YunoHost version 4.3 or higher.
|
||||
ynh_write_var_in_file() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=fkva
|
||||
local -A args_array=([f]=file= [k]=key= [v]=value= [a]=after=)
|
||||
local file
|
||||
local key
|
||||
local value
|
||||
local after
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
after="${after:-}"
|
||||
|
||||
[[ -f $file ]] || ynh_die --message="File $file does not exists"
|
||||
|
||||
set +o xtrace # set +x
|
||||
|
||||
# Get the line number after which we search for the variable
|
||||
local after_line_number=1
|
||||
if [[ -n "$after" ]]; then
|
||||
after_line_number=$(grep -m1 -n $after $file | cut -d: -f1)
|
||||
if [[ -z "$after_line_number" ]]; then
|
||||
set -o xtrace # set -x
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
local filename="$(basename -- "$file")"
|
||||
local ext="${filename##*.}"
|
||||
local endline=',;'
|
||||
local assign="=>|:|="
|
||||
local comments="#"
|
||||
local string="\"'"
|
||||
if [[ "$ext" =~ ^ini|env|toml|yml|yaml$ ]]; then
|
||||
endline='#'
|
||||
fi
|
||||
if [[ "$ext" =~ ^ini|env$ ]]; then
|
||||
comments="[;#]"
|
||||
fi
|
||||
if [[ "php" == "$ext" ]] || [[ "$ext" == "js" ]]; then
|
||||
comments="//"
|
||||
fi
|
||||
local list='\[\s*['$string']?\w+['$string']?\]'
|
||||
local var_part='^\s*((const|var|let)\s+)?\$?(\w+('$list')*(->|\.|\[))*\s*'
|
||||
var_part+="[$string]?${key}[$string]?"
|
||||
var_part+='\s*\]?\s*'
|
||||
var_part+="($assign)"
|
||||
var_part+='\s*'
|
||||
|
||||
# Extract the part after assignation sign
|
||||
local expression_with_comment="$((tail +$after_line_number ${file} | grep -i -o -P $var_part'\K.*$' || echo YNH_NULL) | head -n1)"
|
||||
if [[ "$expression_with_comment" == "YNH_NULL" ]]; then
|
||||
set -o xtrace # set -x
|
||||
return 1
|
||||
fi
|
||||
local value_line_number="$(tail +$after_line_number ${file} | grep -m1 -n -i -P $var_part'\K.*$' | cut -d: -f1)"
|
||||
value_line_number=$((after_line_number + value_line_number))
|
||||
local range="${after_line_number},${value_line_number} "
|
||||
|
||||
# Remove comments if needed
|
||||
local expression="$(echo "$expression_with_comment" | sed "s@${comments}[^$string]*\$@@g" | sed "s@\s*[$endline]*\s*]*\$@@")"
|
||||
endline=${expression_with_comment#"$expression"}
|
||||
endline="$(echo "$endline" | sed 's/\\/\\\\/g')"
|
||||
value="$(echo "$value" | sed 's/\\/\\\\/g')"
|
||||
value=${value//&/"\&"}
|
||||
local first_char="${expression:0:1}"
|
||||
delimiter=$'\001'
|
||||
if [[ "$first_char" == '"' ]]; then
|
||||
# \ and sed is quite complex you need 2 \\ to get one in a sed
|
||||
# So we need \\\\ to go through 2 sed
|
||||
value="$(echo "$value" | sed 's/"/\\\\"/g')"
|
||||
sed -ri "${range}s$delimiter"'(^'"${var_part}"'")([^"]|\\")*("[\s;,]*)(\s*'$comments'.*)?$'$delimiter'\1'"${value}"'"'"${endline}${delimiter}i" ${file}
|
||||
elif [[ "$first_char" == "'" ]]; then
|
||||
# \ and sed is quite complex you need 2 \\ to get one in a sed
|
||||
# However double quotes implies to double \\ to
|
||||
# So we need \\\\\\\\ to go through 2 sed and 1 double quotes str
|
||||
value="$(echo "$value" | sed "s/'/\\\\\\\\'/g")"
|
||||
sed -ri "${range}s$delimiter(^${var_part}')([^']|\\')*('"'[\s,;]*)(\s*'$comments'.*)?$'$delimiter'\1'"${value}'${endline}${delimiter}i" ${file}
|
||||
else
|
||||
if [[ "$value" == *"'"* ]] || [[ "$value" == *'"'* ]] || [[ "$ext" =~ ^php|py|json|js$ ]]; then
|
||||
value='\"'"$(echo "$value" | sed 's/"/\\\\"/g')"'\"'
|
||||
fi
|
||||
if [[ "$ext" =~ ^yaml|yml$ ]]; then
|
||||
value=" $value"
|
||||
fi
|
||||
sed -ri "${range}s$delimiter(^${var_part}).*\$$delimiter\1${value}${endline}${delimiter}i" ${file}
|
||||
fi
|
||||
set -o xtrace # set -x
|
||||
}
|
||||
|
||||
# Render templates with Jinja2
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# Attention : Variables should be exported before calling this helper to be
|
||||
# accessible inside templates.
|
||||
#
|
||||
# usage: ynh_render_template some_template output_path
|
||||
# | arg: some_template - Template file to be rendered
|
||||
# | arg: output_path - The path where the output will be redirected to
|
||||
ynh_render_template() {
|
||||
local template_path=$1
|
||||
local output_path=$2
|
||||
mkdir -p "$(dirname $output_path)"
|
||||
# Taken from https://stackoverflow.com/a/35009576
|
||||
python3 -c 'import os, sys, jinja2; sys.stdout.write(
|
||||
jinja2.Template(sys.stdin.read()
|
||||
).render(os.environ));' <$template_path >$output_path
|
||||
}
|
||||
|
||||
# Fetch the Debian release codename
|
||||
#
|
||||
# [packagingv1]
|
||||
|
@ -894,8 +147,7 @@ _acceptable_path_to_delete() {
|
|||
local forbidden_paths=$(ls -d / /* /{var,home,usr}/* /etc/{default,sudoers.d,yunohost,cron*} /etc/yunohost/{apps,domains,hooks.d} /opt/yunohost 2> /dev/null)
|
||||
|
||||
# Legacy : A couple apps still have data in /home/$app ...
|
||||
if [[ -n "${app:-}" ]]
|
||||
then
|
||||
if [[ -n "${app:-}" ]]; then
|
||||
forbidden_paths=$(echo "$forbidden_paths" | grep -v "/home/$app")
|
||||
fi
|
||||
|
||||
|
@ -960,19 +212,16 @@ ynh_read_manifest() {
|
|||
|
||||
if [ ! -e "${manifest:-}" ]; then
|
||||
# If the manifest isn't found, try the common place for backup and restore script.
|
||||
if [ -e "$YNH_APP_BASEDIR/manifest.json" ]
|
||||
then
|
||||
if [ -e "$YNH_APP_BASEDIR/manifest.json" ]; then
|
||||
manifest="$YNH_APP_BASEDIR/manifest.json"
|
||||
elif [ -e "$YNH_APP_BASEDIR/manifest.toml" ]
|
||||
then
|
||||
elif [ -e "$YNH_APP_BASEDIR/manifest.toml" ]; then
|
||||
manifest="$YNH_APP_BASEDIR/manifest.toml"
|
||||
else
|
||||
ynh_die --message "No manifest found !?"
|
||||
fi
|
||||
fi
|
||||
|
||||
if echo "$manifest" | grep -q '\.json$'
|
||||
then
|
||||
if echo "$manifest" | grep -q '\.json$'; then
|
||||
jq ".$manifest_key" "$manifest" --raw-output
|
||||
else
|
||||
cat "$manifest" | python3 -c 'import json, toml, sys; print(json.dumps(toml.load(sys.stdin)))' | jq ".$manifest_key" --raw-output
|
||||
|
@ -1132,8 +381,7 @@ _ynh_apply_default_permissions() {
|
|||
# Crons should be owned by root
|
||||
# Also we don't want systemd conf, nginx conf or others stuff to be owned by the app,
|
||||
# otherwise they could self-edit their own systemd conf and escalate privilege
|
||||
if grep -qE '^(/etc/cron|/etc/php|/etc/nginx/conf.d|/etc/fail2ban|/etc/systemd/system)' <<< "$target"
|
||||
then
|
||||
if grep -qE '^(/etc/cron|/etc/php|/etc/nginx/conf.d|/etc/fail2ban|/etc/systemd/system)' <<< "$target"; then
|
||||
chmod 400 $target
|
||||
chown root:root $target
|
||||
fi
|
||||
|
@ -1146,3 +394,57 @@ int_to_bool() {
|
|||
toml_to_json() {
|
||||
python3 -c 'import toml, json, sys; print(json.dumps(toml.load(sys.stdin)))'
|
||||
}
|
||||
|
||||
# Check if a YunoHost user exists
|
||||
#
|
||||
# usage: ynh_user_exists --username=username
|
||||
# | arg: -u, --username= - the username to check
|
||||
# | ret: 0 if the user exists, 1 otherwise.
|
||||
#
|
||||
# example: ynh_user_exists 'toto' || echo "User does not exist"
|
||||
#
|
||||
# Requires YunoHost version 2.2.4 or higher.
|
||||
ynh_user_exists() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=u
|
||||
local -A args_array=([u]=username=)
|
||||
local username
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
yunohost user list --output-as json --quiet | jq -e ".users.\"${username}\"" > /dev/null
|
||||
}
|
||||
|
||||
# Retrieve a YunoHost user information
|
||||
#
|
||||
# usage: ynh_user_get_info --username=username --key=key
|
||||
# | arg: -u, --username= - the username to retrieve info from
|
||||
# | arg: -k, --key= - the key to retrieve
|
||||
# | ret: the value associate to that key
|
||||
#
|
||||
# example: mail=$(ynh_user_get_info --username="toto" --key=mail)
|
||||
#
|
||||
# Requires YunoHost version 2.2.4 or higher.
|
||||
ynh_user_get_info() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=uk
|
||||
local -A args_array=([u]=username= [k]=key=)
|
||||
local username
|
||||
local key
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
yunohost user info "$username" --output-as json --quiet | jq -r ".$key"
|
||||
}
|
||||
|
||||
# Get the list of YunoHost users
|
||||
#
|
||||
# usage: ynh_user_list
|
||||
# | ret: one username per line as strings
|
||||
#
|
||||
# example: for u in $(ynh_user_list); do ... ; done
|
||||
#
|
||||
# Requires YunoHost version 2.4.0 or higher.
|
||||
ynh_user_list() {
|
||||
yunohost user list --output-as json --quiet | jq -r ".users | keys[]"
|
||||
}
|
||||
|
|
330
helpers/helpers.v2.1.d/apt
Normal file
330
helpers/helpers.v2.1.d/apt
Normal file
|
@ -0,0 +1,330 @@
|
|||
#!/bin/bash
|
||||
|
||||
YNH_APT_INSTALL_DEPENDENCIES_REPLACE="true"
|
||||
|
||||
# Define and install dependencies with a equivs control file
|
||||
#
|
||||
# example : ynh_apt_install_dependencies dep1 dep2 "dep3|dep4|dep5"
|
||||
#
|
||||
# usage: ynh_apt_install_dependencies dep [dep [...]]
|
||||
# | arg: dep - the package name to install in dependence.
|
||||
# | arg: "dep1|dep2|…" - You can specify alternatives. It will require to install (dep1 or dep2, etc).
|
||||
#
|
||||
ynh_apt_install_dependencies() {
|
||||
|
||||
# Add a comma for each space between packages. But not add a comma if the space separate a version specification. (See below)
|
||||
local dependencies="$(sed 's/\([^\<=\>]\)\ \([^(]\)/\1, \2/g' <<< "$@" | sed 's/|/ | /')"
|
||||
local version=$(ynh_read_manifest "version")
|
||||
local app_ynh_deps="${app//_/-}-ynh-deps" # Replace all '_' by '-', and append -ynh-deps
|
||||
|
||||
# Handle specific versions
|
||||
if grep '[<=>]' <<< "$dependencies"; then
|
||||
# Replace version specifications by relationships syntax
|
||||
# https://www.debian.org/doc/debian-policy/ch-relationships.html
|
||||
# Sed clarification
|
||||
# [^(\<=\>] ignore if it begins by ( or < = >. To not apply twice.
|
||||
# [\<=\>] matches < = or >
|
||||
# \+ matches one or more occurence of the previous characters, for >= or >>.
|
||||
# [^,]\+ matches all characters except ','
|
||||
# Ex: 'package>=1.0' will be replaced by 'package (>= 1.0)'
|
||||
dependencies="$(sed 's/\([^(\<=\>]\)\([\<=\>]\+\)\([^,]\+\)/\1 (\2 \3)/g' <<< "$dependencies")"
|
||||
fi
|
||||
|
||||
# ############################## #
|
||||
# Specific tweaks related to PHP #
|
||||
# ############################## #
|
||||
|
||||
# Check for specific php dependencies which requires sury
|
||||
# This grep will for example return "7.4" if dependencies is "foo bar php7.4-pwet php-gni"
|
||||
# The (?<=php) syntax corresponds to lookbehind ;)
|
||||
local specific_php_version=$(grep -oP '(?<=php)[0-9.]+(?=-|\>|)' <<< "$dependencies" | sort -u)
|
||||
|
||||
if [[ -n "$specific_php_version" ]]; then
|
||||
# Cover a small edge case where a packager could have specified "php7.4-pwet php5-gni" which is confusing
|
||||
[[ $(echo $specific_php_version | wc -l) -eq 1 ]] \
|
||||
|| ynh_die "Inconsistent php versions in dependencies ... found : $specific_php_version"
|
||||
|
||||
dependencies+=", php${specific_php_version}, php${specific_php_version}-fpm, php${specific_php_version}-common"
|
||||
|
||||
local old_php_version=$(ynh_app_setting_get --key=php_version)
|
||||
|
||||
# If the PHP version changed, remove the old fpm conf
|
||||
if [ -n "$old_php_version" ] && [ "$old_php_version" != "$specific_php_version" ]; then
|
||||
if [[ -f "/etc/php/$php_version/fpm/pool.d/$app.conf" ]]; then
|
||||
ynh_backup_if_checksum_is_different "/etc/php/$php_version/fpm/pool.d/$app.conf"
|
||||
ynh_config_remove_phpfpm
|
||||
fi
|
||||
fi
|
||||
# Store php_version into the config of this app
|
||||
ynh_app_setting_set --key=php_version --value=$specific_php_version
|
||||
|
||||
# Set the default php version back as the default version for php-cli.
|
||||
if test -e /usr/bin/php$YNH_DEFAULT_PHP_VERSION; then
|
||||
update-alternatives --set php /usr/bin/php$YNH_DEFAULT_PHP_VERSION
|
||||
fi
|
||||
elif grep --quiet 'php' <<< "$dependencies"; then
|
||||
ynh_app_setting_set --key=php_version --value=$YNH_DEFAULT_PHP_VERSION
|
||||
fi
|
||||
|
||||
# Specific tweak related to Postgresql (cf end of the helper)
|
||||
local psql_installed="$(_ynh_apt_package_is_installed "postgresql-$PSQL_VERSION" && echo yes || echo no)"
|
||||
|
||||
# The first time we run ynh_apt_install_dependencies, we will replace the
|
||||
# entire control file (This is in particular meant to cover the case of
|
||||
# upgrade script where ynh_apt_install_dependencies is called with this
|
||||
# expected effect) Otherwise, any subsequent call will add dependencies
|
||||
# to those already present in the equivs control file.
|
||||
if [[ $YNH_APT_INSTALL_DEPENDENCIES_REPLACE == "true" ]]; then
|
||||
YNH_APT_INSTALL_DEPENDENCIES_REPLACE="false"
|
||||
else
|
||||
local current_dependencies=""
|
||||
if _ynh_apt_package_is_installed "${app_ynh_deps}"; then
|
||||
current_dependencies="$(dpkg-query --show --showformat='${Depends}' ${app_ynh_deps}) "
|
||||
current_dependencies=${current_dependencies// | /|}
|
||||
fi
|
||||
dependencies="$current_dependencies, $dependencies"
|
||||
fi
|
||||
|
||||
# ################
|
||||
# Actual install #
|
||||
# ################
|
||||
|
||||
# Prepare the virtual-dependency control file for dpkg-deb --build
|
||||
local TMPDIR=$(mktemp --directory)
|
||||
mkdir -p ${TMPDIR}/${app_ynh_deps}/DEBIAN
|
||||
# For some reason, dpkg-deb insists for folder perm to be 755 and sometimes it's 777 o_O?
|
||||
chmod -R 755 ${TMPDIR}/${app_ynh_deps}
|
||||
|
||||
cat > ${TMPDIR}/${app_ynh_deps}/DEBIAN/control << EOF
|
||||
Section: misc
|
||||
Priority: optional
|
||||
Package: ${app_ynh_deps}
|
||||
Version: ${version}
|
||||
Depends: ${dependencies//,,/,}
|
||||
Architecture: all
|
||||
Maintainer: root@localhost
|
||||
Description: Fake package for ${app} (YunoHost app) dependencies
|
||||
This meta-package is only responsible of installing its dependencies.
|
||||
EOF
|
||||
|
||||
_ynh_apt update
|
||||
|
||||
_ynh_wait_dpkg_free
|
||||
|
||||
# Install the fake package without its dependencies with dpkg --force-depends
|
||||
if ! LC_ALL=C dpkg-deb --build "${TMPDIR}/${app_ynh_deps}" "${TMPDIR}/${app_ynh_deps}.deb" > "${TMPDIR}/dpkg_log" 2>&1; then
|
||||
cat "${TMPDIR}/dpkg_log" >&2
|
||||
ynh_die --message="Unable to install dependencies"
|
||||
fi
|
||||
# Don't crash in case of error, because is nicely covered by the following line
|
||||
LC_ALL=C dpkg --force-depends --install "${TMPDIR}/${app_ynh_deps}.deb" 2>&1 | tee "${TMPDIR}/dpkg_log" || true
|
||||
|
||||
# Then install the missing dependencies with apt install
|
||||
_ynh_apt_install --fix-broken || {
|
||||
# If the installation failed
|
||||
# (the following is ran inside { } to not start a subshell otherwise ynh_die wouldnt exit the original process)
|
||||
# Parse the list of problematic dependencies from dpkg's log ...
|
||||
# (relevant lines look like: "foo-ynh-deps depends on bar; however:")
|
||||
cat $TMPDIR/dpkg_log
|
||||
local problematic_dependencies="$(grep -oP '(?<=-ynh-deps depends on ).*(?=; however)' $TMPDIR/dpkg_log | tr '\n' ' ')"
|
||||
# Fake an install of those dependencies to see the errors
|
||||
# The sed command here is, Print only from 'Reading state info' to the end.
|
||||
[[ -n "$problematic_dependencies" ]] && _ynh_apt_install $problematic_dependencies --dry-run 2>&1 | sed --quiet '/Reading state info/,$p' | grep -v "fix-broken\|Reading state info" >&2
|
||||
ynh_die "Unable to install apt dependencies"
|
||||
}
|
||||
rm --recursive --force "$TMPDIR" # Remove the temp dir.
|
||||
|
||||
# check if the package is actually installed
|
||||
_ynh_apt_package_is_installed "${app_ynh_deps}" || ynh_die "Unable to install apt dependencies"
|
||||
|
||||
# Specific tweak related to Postgresql
|
||||
# -> trigger postgresql regenconf if we may have just installed postgresql
|
||||
local psql_installed2="$(_ynh_apt_package_is_installed "postgresql-$PSQL_VERSION" && echo yes || echo no)"
|
||||
if [[ "$psql_installed" != "$psql_installed2" ]]; then
|
||||
yunohost tools regen-conf postgresql
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
# Remove fake package and its dependencies
|
||||
#
|
||||
# Dependencies will removed only if no other package need them.
|
||||
#
|
||||
# usage: ynh_apt_remove_dependencies
|
||||
ynh_apt_remove_dependencies() {
|
||||
local app_ynh_deps="${app//_/-}-ynh-deps" # Replace all '_' by '-', and append -ynh-deps
|
||||
|
||||
local current_dependencies=""
|
||||
if _ynh_apt_package_is_installed "${app_ynh_deps}"; then
|
||||
current_dependencies="$(dpkg-query --show --showformat='${Depends}' ${app_ynh_deps}) "
|
||||
current_dependencies=${current_dependencies// | /|}
|
||||
fi
|
||||
|
||||
# Edge case where the app dep may be on hold,
|
||||
# cf https://forum.yunohost.org/t/migration-error-cause-of-ffsync/20675/4
|
||||
if apt-mark showhold | grep -q -w ${app_ynh_deps}; then
|
||||
apt-mark unhold ${app_ynh_deps}
|
||||
fi
|
||||
|
||||
# Remove the fake package and its dependencies if they not still used.
|
||||
# (except if dpkg doesn't know anything about the package,
|
||||
# which should be symptomatic of a failed install, and we don't want bash to report an error)
|
||||
if dpkg-query --show ${app_ynh_deps} &> /dev/null; then
|
||||
_ynh_apt autoremove --purge ${app_ynh_deps}
|
||||
fi
|
||||
}
|
||||
|
||||
# Install packages from an extra repository properly.
|
||||
#
|
||||
# usage: ynh_apt_install_dependencies_from_extra_repository --repo="repo" --package="dep1 dep2" --key=key_url
|
||||
# | arg: --repo= - Complete url of the extra repository.
|
||||
# | arg: --package= - The packages to install from this extra repository
|
||||
# | arg: --key= - url to get the public key.
|
||||
#
|
||||
ynh_apt_install_dependencies_from_extra_repository() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([r]=repo= [p]=package= [k]=key=)
|
||||
local repo
|
||||
local package
|
||||
local key
|
||||
ynh_handle_getopts_args "$@"
|
||||
# ===========================================
|
||||
|
||||
# Split the repository into uri, suite and components.
|
||||
IFS=', ' read -r -a repo_parts <<< "$repo"
|
||||
index=0
|
||||
|
||||
# Remove "deb " at the beginning of the repo.
|
||||
if [[ "${repo_parts[0]}" == "deb" ]]; then
|
||||
index=1
|
||||
fi
|
||||
uri="${repo_parts[$index]}"
|
||||
index=$((index + 1))
|
||||
suite="${repo_parts[$index]}"
|
||||
index=$((index + 1))
|
||||
|
||||
# Get the components
|
||||
if (("${#repo_parts[@]}" > 0)); then
|
||||
component="${repo_parts[*]:$index}"
|
||||
fi
|
||||
|
||||
if [[ "$key" == "trusted=yes" ]]; then
|
||||
trust="[trusted=yes]"
|
||||
else
|
||||
trust=""
|
||||
fi
|
||||
|
||||
# Add the new repo in sources.list.d
|
||||
mkdir --parents "/etc/apt/sources.list.d"
|
||||
echo "deb $trust $uri $suite $component" > "/etc/apt/sources.list.d/$app.list"
|
||||
|
||||
# Pin the new repo with the default priority, so it won't be used for upgrades.
|
||||
# Build $pin from the uri without http and any sub path
|
||||
local pin="${uri#*://}"
|
||||
pin="${pin%%/*}"
|
||||
|
||||
# Pin repository
|
||||
mkdir --parents "/etc/apt/preferences.d"
|
||||
cat << EOF > "/etc/apt/preferences.d/$app"
|
||||
Package: *
|
||||
Pin: origin $pin
|
||||
Pin-Priority: 995
|
||||
EOF
|
||||
|
||||
if [ -n "$key" ] && [[ "$key" != "trusted=yes" ]]; then
|
||||
mkdir --parents "/etc/apt/trusted.gpg.d"
|
||||
# Timeout option is here to enforce the timeout on dns query and tcp connect (c.f. man wget)
|
||||
wget --timeout 900 --quiet "$key" --output-document=- | gpg --dearmor > /etc/apt/trusted.gpg.d/$app.gpg
|
||||
fi
|
||||
|
||||
# Update the list of package with the new repo NB: we use -o
|
||||
# Dir::Etc::sourcelist to only refresh this repo, because
|
||||
# ynh_apt_install_dependencies will also call an ynh_apt update on its own
|
||||
# and it's good to limit unecessary requests ... Here we mainly want to
|
||||
# validate that the url+key is correct before going further
|
||||
_ynh_apt update -o Dir::Etc::sourcelist="/etc/apt/sources.list.d/$app.list"
|
||||
|
||||
# Install requested dependencies from this extra repository.
|
||||
# NB: because of the mechanism with $ynh_apt_install_DEPENDENCIES_REPLACE,
|
||||
# this will usually only *append* to the existing list of dependency, not
|
||||
# replace the existing $app-ynh-deps
|
||||
ynh_apt_install_dependencies "$package"
|
||||
|
||||
# Force to upgrade to the last version...
|
||||
# Without doing apt install, an already installed dep is not upgraded
|
||||
local apps_auto_installed="$(apt-mark showauto $package)"
|
||||
_ynh_apt_install "$package"
|
||||
[ -z "$apps_auto_installed" ] || apt-mark auto $apps_auto_installed
|
||||
|
||||
# Remove this extra repository after packages are installed
|
||||
ynh_safe_rm "/etc/apt/sources.list.d/$app.list"
|
||||
ynh_safe_rm "/etc/apt/preferences.d/$app"
|
||||
ynh_safe_rm "/etc/apt/trusted.gpg.d/$app.gpg"
|
||||
_ynh_apt update
|
||||
}
|
||||
|
||||
# #####################
|
||||
# Internal misc utils #
|
||||
# #####################
|
||||
|
||||
# Check if apt is free to use, or wait, until timeout.
|
||||
_ynh_wait_dpkg_free() {
|
||||
local try
|
||||
set +o xtrace # set +x
|
||||
# With seq 1 17, timeout will be almost 30 minutes
|
||||
for try in $(seq 1 17); do
|
||||
# Check if /var/lib/dpkg/lock is used by another process
|
||||
if lsof /var/lib/dpkg/lock > /dev/null; then
|
||||
echo "apt is already in use..."
|
||||
# Sleep an exponential time at each round
|
||||
sleep $((try * try))
|
||||
else
|
||||
# Check if dpkg hasn't been interrupted and is fully available.
|
||||
# See this for more information: https://sources.debian.org/src/apt/1.4.9/apt-pkg/deb/debsystem.cc/#L141-L174
|
||||
local dpkg_dir="/var/lib/dpkg/updates/"
|
||||
|
||||
# For each file in $dpkg_dir
|
||||
while read dpkg_file <&9; do
|
||||
# Check if the name of this file contains only numbers.
|
||||
if echo "$dpkg_file" | grep --perl-regexp --quiet "^[[:digit:]]+$"; then
|
||||
# If so, that a remaining of dpkg.
|
||||
ynh_print_warn "dpkg was interrupted, you must manually run 'sudo dpkg --configure -a' to correct the problem."
|
||||
set -o xtrace # set -x
|
||||
return 1
|
||||
fi
|
||||
done 9<<< "$(ls -1 $dpkg_dir)"
|
||||
set -o xtrace # set -x
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
echo "apt still used, but timeout reached !"
|
||||
set -o xtrace # set -x
|
||||
}
|
||||
|
||||
# Check either a package is installed or not
|
||||
_ynh_apt_package_is_installed() {
|
||||
local package=$1
|
||||
dpkg-query --show --showformat='${db:Status-Status}' "$package" 2> /dev/null \
|
||||
| grep --quiet "^installed$" &> /dev/null
|
||||
}
|
||||
|
||||
# Return the installed version of an apt package, if installed
|
||||
_ynh_apt_package_version() {
|
||||
if _ynh_apt_package_is_installed "$package"; then
|
||||
dpkg-query --show --showformat='${Version}' "$package" 2> /dev/null
|
||||
else
|
||||
echo ''
|
||||
fi
|
||||
}
|
||||
|
||||
# APT wrapper for non-interactive operation
|
||||
_ynh_apt() {
|
||||
_ynh_wait_dpkg_free
|
||||
LC_ALL=C DEBIAN_FRONTEND=noninteractive apt-get --assume-yes --quiet -o=Acquire::Retries=3 -o=Dpkg::Use-Pty=0 $@
|
||||
}
|
||||
|
||||
# Wrapper around "apt install" with the appropriate options
|
||||
_ynh_apt_install() {
|
||||
_ynh_apt --no-remove --option Dpkg::Options::=--force-confdef \
|
||||
--option Dpkg::Options::=--force-confold install $@
|
||||
}
|
272
helpers/helpers.v2.1.d/backup
Normal file
272
helpers/helpers.v2.1.d/backup
Normal file
|
@ -0,0 +1,272 @@
|
|||
#!/bin/bash
|
||||
|
||||
CAN_BIND=${CAN_BIND:-1}
|
||||
|
||||
# Add a file or a directory to the list of paths to backup
|
||||
#
|
||||
# usage: ynh_backup /path/to/stuff
|
||||
#
|
||||
# NB : note that this helper does *NOT* perform any copy in itself, it only
|
||||
# declares stuff to be backuped via a CSV which is later picked up by the core
|
||||
#
|
||||
# NB 2 : there is a specific behavior for $data_dir (or childs of $data_dir) and
|
||||
# /var/log/$app which are *NOT* backedup during safety-backup-before-upgrade,
|
||||
# OR if the setting "do_not_backup_data" is equals 1 for that app
|
||||
#
|
||||
# The rationale is that these directories are usually too heavy to be integrated in every backup
|
||||
# (think for example about Nextcloud with quite a lot of data, or an app with a lot of media files...)
|
||||
#
|
||||
# This is coupled to the fact that $data_dir and the log dir won't be (and
|
||||
# should NOT) be deleted during remove, unless --purge is used. Hence, if the
|
||||
# upgrade fails and the script is removed prior to restoring the backup, the
|
||||
# data/logs are not destroyed.
|
||||
#
|
||||
ynh_backup() {
|
||||
|
||||
local target="$1"
|
||||
local is_data=false
|
||||
|
||||
# If the path starts with /var/log/$app or $data_dir
|
||||
if ([[ -n "${app:-}" ]] && [[ "$target" == "/var/log/$app*" ]]) || ([[ -n "${data_dir:-}" ]] && [[ "$target" == "$data_dir*" ]]); then
|
||||
is_data=true
|
||||
fi
|
||||
|
||||
if [[ -n "${app:-}" ]]; then
|
||||
local do_not_backup_data=$(ynh_app_setting_get --key=do_not_backup_data)
|
||||
fi
|
||||
|
||||
# If backing up core only (used by ynh_backup_before_upgrade),
|
||||
# don't backup big data items
|
||||
if [[ "$is_data" == true ]] && ([[ ${do_not_backup_data:-0} -eq 1 ]] || [[ ${BACKUP_CORE_ONLY:-0} -eq 1 ]]); then
|
||||
if [ $BACKUP_CORE_ONLY -eq 1 ]; then
|
||||
ynh_print_info "$target will not be saved, because 'BACKUP_CORE_ONLY' is set."
|
||||
else
|
||||
ynh_print_info "$target will not be saved, because 'do_not_backup_data' is set."
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# Format correctly source and destination paths
|
||||
# ==============================================================================
|
||||
# Be sure the source path is not empty
|
||||
if [ ! -e "$target" ]; then
|
||||
ynh_print_warn "File or folder '${target}' to be backed up does not exist"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Transform the source path as an absolute path
|
||||
# If it's a dir remove the ending /
|
||||
src_path=$(realpath "$target")
|
||||
|
||||
# Initialize the dest path with the source path relative to "/".
|
||||
# eg: src_path=/etc/yunohost -> dest_path=etc/yunohost
|
||||
dest_path="${src_path#/}"
|
||||
|
||||
# Check if dest_path already exists in tmp archive
|
||||
if [[ -e "${dest_path}" ]]; then
|
||||
ynh_print_warn "Destination path '${dest_path}' already exist"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Add the relative current working directory to the destination path
|
||||
local rel_dir="${YNH_CWD#$YNH_BACKUP_DIR}"
|
||||
rel_dir="${rel_dir%/}/"
|
||||
dest_path="${rel_dir}${dest_path}"
|
||||
dest_path="${dest_path#/}"
|
||||
# ==============================================================================
|
||||
|
||||
# ==============================================================================
|
||||
# Write file to backup into backup_list
|
||||
# ==============================================================================
|
||||
local src=$(echo "${src_path}" | sed --regexp-extended 's/"/\"\"/g')
|
||||
local dest=$(echo "${dest_path}" | sed --regexp-extended 's/"/\"\"/g')
|
||||
echo "\"${src}\",\"${dest}\"" >> "${YNH_BACKUP_CSV}"
|
||||
|
||||
# ==============================================================================
|
||||
|
||||
# Create the parent dir of the destination path
|
||||
# It's for retro compatibility, some script consider ynh_backup creates this dir
|
||||
mkdir --parents $(dirname "$YNH_BACKUP_DIR/${dest_path}")
|
||||
}
|
||||
|
||||
# Return the path in the archive where has been stocked the origin path
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# usage: _get_archive_path ORIGIN_PATH
|
||||
_get_archive_path() {
|
||||
# For security reasons we use csv python library to read the CSV
|
||||
python3 -c "
|
||||
import sys
|
||||
import csv
|
||||
with open(sys.argv[1], 'r') as backup_file:
|
||||
backup_csv = csv.DictReader(backup_file, fieldnames=['source', 'dest'])
|
||||
for row in backup_csv:
|
||||
if row['source']==sys.argv[2].strip('\"'):
|
||||
print(row['dest'])
|
||||
sys.exit(0)
|
||||
raise Exception('Original path for %s not found' % sys.argv[2])
|
||||
" "${YNH_BACKUP_CSV}" "$1"
|
||||
return $?
|
||||
}
|
||||
|
||||
# Restore a file or a directory from the backup archive
|
||||
#
|
||||
# usage: ynh_restore /path/to/stuff
|
||||
#
|
||||
# examples:
|
||||
# ynh_restore "/etc/nginx/conf.d/$domain.d/$app.conf"
|
||||
#
|
||||
# If the file or dir to be restored already exists on the system and is lighter
|
||||
# than 500 Mo, it is backed up in `/var/cache/yunohost/appconfbackup/`.
|
||||
# Otherwise, the existing file or dir is removed.
|
||||
#
|
||||
# if `apps/$app/etc/nginx/conf.d/$domain.d/$app.conf` exists, restore it into
|
||||
# `/etc/nginx/conf.d/$domain.d/$app.conf`
|
||||
# otheriwse, search for a match in the csv (eg: conf/nginx.conf) and restore it into
|
||||
# `/etc/nginx/conf.d/$domain.d/$app.conf`
|
||||
ynh_restore() {
|
||||
target="$1"
|
||||
|
||||
local archive_path="$YNH_CWD${target}"
|
||||
|
||||
# If the path starts with /var/log/$app or $data_dir
|
||||
local is_data=false
|
||||
if ([[ -n "${app:-}" ]] && [[ "$target" == "/var/log/$app*" ]]) || ([[ -n "${data_dir:-}" ]] && [[ "$target" == "$data_dir*" ]]); then
|
||||
is_data=true
|
||||
fi
|
||||
|
||||
# If archive_path doesn't exist, search for a corresponding path in CSV
|
||||
if [ ! -d "$archive_path" ] && [ ! -f "$archive_path" ] && [ ! -L "$archive_path" ]; then
|
||||
if [[ "$is_data" == true ]]; then
|
||||
ynh_print_info "Skipping $target which doesn't exists in the archive, probably because restoring from a safety-backup-before-upgrade"
|
||||
# Assume it's not a big deal, we may be restoring a safety-backup-before-upgrade which doesnt contain those
|
||||
return 0
|
||||
else
|
||||
# (get_archive_path will raise an exception if no match found)
|
||||
archive_path="$YNH_BACKUP_DIR/$(_get_archive_path \"$target\")"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Move the old directory if it already exists
|
||||
if [[ -e "${target}" ]]; then
|
||||
# Check if the file/dir size is less than 500 Mo
|
||||
if [[ $(du --summarize --bytes ${target} | cut --delimiter="/" --fields=1) -le "500000000" ]]; then
|
||||
local backup_file="/var/cache/yunohost/appconfbackup/${target}.backup.$(date '+%Y%m%d.%H%M%S')"
|
||||
mkdir --parents "$(dirname "$backup_file")"
|
||||
mv "${target}" "$backup_file" # Move the current file or directory
|
||||
else
|
||||
ynh_safe_rm "${target}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Restore target into target
|
||||
mkdir --parents $(dirname "$target")
|
||||
|
||||
# Do a copy if it's just a mounting point
|
||||
if mountpoint --quiet $YNH_BACKUP_DIR; then
|
||||
if [[ -d "${archive_path}" ]]; then
|
||||
archive_path="${archive_path}/."
|
||||
mkdir --parents "$target"
|
||||
fi
|
||||
cp --archive "$archive_path" "${target}"
|
||||
# Do a move if YNH_BACKUP_DIR is already a copy
|
||||
else
|
||||
mv "$archive_path" "${target}"
|
||||
fi
|
||||
|
||||
_ynh_apply_default_permissions "$target"
|
||||
}
|
||||
|
||||
# Restore all files that were previously backuped in an app backup script
|
||||
#
|
||||
# usage: ynh_restore_everything
|
||||
ynh_restore_everything() {
|
||||
# Deduce the relative path of $YNH_CWD
|
||||
local REL_DIR="${YNH_CWD#$YNH_BACKUP_DIR/}"
|
||||
REL_DIR="${REL_DIR%/}/"
|
||||
|
||||
# For each destination path begining by $REL_DIR
|
||||
cat ${YNH_BACKUP_CSV} | tr --delete $'\r' | grep --only-matching --no-filename --perl-regexp "^\".*\",\"$REL_DIR.*\"$" \
|
||||
| while read line; do
|
||||
local ARCHIVE_PATH=$(echo "$line" | grep --only-matching --no-filename --perl-regexp "^\"\K.*(?=\",\"$REL_DIR.*\"$)")
|
||||
ynh_restore "$ARCHIVE_PATH"
|
||||
done
|
||||
}
|
||||
|
||||
_ynh_file_checksum_exists() {
|
||||
local file=$1
|
||||
local checksum_setting_name=checksum_${file//[\/ ]/_} # Replace all '/' and ' ' by '_'
|
||||
[[ -n "$(ynh_app_setting_get --key=$checksum_setting_name)" ]]
|
||||
}
|
||||
|
||||
# Calculate and store a file checksum into the app settings
|
||||
#
|
||||
# usage: ynh_store_file_checksum /path/to/file
|
||||
ynh_store_file_checksum() {
|
||||
set +o xtrace # set +x
|
||||
local file=$1
|
||||
local checksum_setting_name=checksum_${file//[\/ ]/_} # Replace all '/' and ' ' by '_'
|
||||
|
||||
ynh_app_setting_set --key=$checksum_setting_name --value=$(md5sum "$file" | cut --delimiter=' ' --fields=1)
|
||||
|
||||
if ynh_in_ci_tests; then
|
||||
# Using a base64 is in fact more reversible than "replace / and space by _" ... So we can in fact obtain the original file path in an easy reliable way ...
|
||||
local file_path_base64=$(echo "$file" | base64 -w0)
|
||||
mkdir -p /var/cache/yunohost/appconfbackup/
|
||||
cat $file > /var/cache/yunohost/appconfbackup/original_${file_path_base64}
|
||||
fi
|
||||
|
||||
# If backup_file_checksum isn't empty, ynh_backup_if_checksum_is_different has made a backup
|
||||
if [ -n "${backup_file_checksum-}" ]; then
|
||||
# Print the diff between the previous file and the new one.
|
||||
# diff return 1 if the files are different, so the || true
|
||||
diff --report-identical-files --unified --color=always $backup_file_checksum $file >&2 || true
|
||||
fi
|
||||
# Unset the variable, so it wouldn't trig a ynh_store_file_checksum without a ynh_backup_if_checksum_is_different before it.
|
||||
unset backup_file_checksum
|
||||
set -o xtrace # set -x
|
||||
}
|
||||
|
||||
# Verify the checksum and backup the file if it's different
|
||||
#
|
||||
# usage: ynh_backup_if_checksum_is_different /path/to/file
|
||||
#
|
||||
# This helper is primarily meant to allow to easily backup personalised/manually
|
||||
# modified config files.
|
||||
ynh_backup_if_checksum_is_different() {
|
||||
set +o xtrace # set +x
|
||||
local file=$1
|
||||
local checksum_setting_name=checksum_${file//[\/ ]/_} # Replace all '/' and ' ' by '_'
|
||||
local checksum_value=$(ynh_app_setting_get --key=$checksum_setting_name)
|
||||
# backup_file_checksum isn't declare as local, so it can be reuse by ynh_store_file_checksum
|
||||
backup_file_checksum=""
|
||||
if [ -n "$checksum_value" ]; then # Proceed only if a value was stored into the app settings
|
||||
if [ -e $file ] && ! echo "$checksum_value $file" | md5sum --check --status; then # If the checksum is now different
|
||||
|
||||
backup_file_checksum="/var/cache/yunohost/appconfbackup/$file.backup.$(date '+%Y%m%d.%H%M%S')"
|
||||
mkdir --parents "$(dirname "$backup_file_checksum")"
|
||||
cp --archive "$file" "$backup_file_checksum" # Backup the current file
|
||||
ynh_print_warn "File $file has been manually modified since the installation or last upgrade. So it has been duplicated in $backup_file_checksum"
|
||||
echo "$backup_file_checksum" # Return the name of the backup file
|
||||
if ynh_in_ci_tests; then
|
||||
local file_path_base64=$(echo "$file" | base64 -w0)
|
||||
if test -e /var/cache/yunohost/appconfbackup/original_${file_path_base64}; then
|
||||
ynh_print_warn "Diff with the original file:"
|
||||
diff --report-identical-files --unified --color=always /var/cache/yunohost/appconfbackup/original_${file_path_base64} $file >&2 || true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
set -o xtrace # set -x
|
||||
}
|
||||
|
||||
# Delete a file checksum from the app settings
|
||||
#
|
||||
# usage: ynh_delete_file_checksum /path/to/file
|
||||
ynh_delete_file_checksum() {
|
||||
local file=$1
|
||||
local checksum_setting_name=checksum_${file//[\/ ]/_} # Replace all '/' and ' ' by '_'
|
||||
ynh_app_setting_delete --key=$checksum_setting_name
|
||||
}
|
45
helpers/helpers.v2.1.d/composer
Normal file
45
helpers/helpers.v2.1.d/composer
Normal file
|
@ -0,0 +1,45 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Install and initialize Composer in the given directory
|
||||
#
|
||||
# The installed version is defined by `$composer_version` which should be defined
|
||||
# as global prior to calling this helper.
|
||||
#
|
||||
# Will use `$install_dir` as workdir unless `$composer_workdir` exists (but that shouldnt be necessary)
|
||||
#
|
||||
# usage: ynh_composer_install
|
||||
ynh_composer_install() {
|
||||
local workdir="${composer_workdir:-$install_dir}"
|
||||
|
||||
[[ -n "${composer_version}" ]] || ynh_die "\$composer_version should be defined before calling ynh_composer_install. (In the past, this was called \$YNH_COMPOSER_VERSION)"
|
||||
|
||||
[[ ! -e "$workdir/composer.phar" ]] || ynh_safe_rm $workdir/composer.phar
|
||||
|
||||
local composer_url="https://getcomposer.org/download/$composer_version/composer.phar"
|
||||
|
||||
# NB. we have to declare the var as local first,
|
||||
# otherwise 'local foo=$(false) || echo 'pwet'" does'nt work
|
||||
# because local always return 0 ...
|
||||
local out
|
||||
# Timeout option is here to enforce the timeout on dns query and tcp connect (c.f. man wget)
|
||||
out=$(wget --tries 3 --no-dns-cache --timeout 900 --no-verbose --output-document=$workdir/composer.phar $composer_url 2>&1) \
|
||||
|| ynh_die "$out"
|
||||
}
|
||||
|
||||
# Execute a command with Composer
|
||||
#
|
||||
# Will use `$install_dir` as workdir unless `$composer_workdir` exists (but that shouldnt be necessary)
|
||||
#
|
||||
# You may also define `composer_user=root` prior to call this helper if you
|
||||
# absolutely need composer to run as root, but this is discouraged...
|
||||
#
|
||||
# usage: ynh_composer_exec commands
|
||||
ynh_composer_exec() {
|
||||
local workdir="${composer_workdir:-$install_dir}"
|
||||
|
||||
COMPOSER_HOME="$workdir/.composer" \
|
||||
COMPOSER_MEMORY_LIMIT=-1 \
|
||||
sudo -E -u "${composer_user:-$app}" \
|
||||
php${php_version} "$workdir/composer.phar" $@ \
|
||||
-d "$workdir" --no-interaction --no-ansi 2>&1
|
||||
}
|
309
helpers/helpers.v2.1.d/config
Normal file
309
helpers/helpers.v2.1.d/config
Normal file
|
@ -0,0 +1,309 @@
|
|||
#!/bin/bash
|
||||
|
||||
_ynh_app_config_get_one() {
|
||||
local short_setting="$1"
|
||||
local type="$2"
|
||||
local bind="$3"
|
||||
local getter="get__${short_setting}"
|
||||
# Get value from getter if exists
|
||||
if type -t $getter 2> /dev/null | grep -q '^function$' 2> /dev/null; then
|
||||
old[$short_setting]="$($getter)"
|
||||
formats[${short_setting}]="yaml"
|
||||
|
||||
elif [[ "$bind" == *"("* ]] && type -t "get__${bind%%(*}" 2> /dev/null | grep -q '^function$' 2> /dev/null; then
|
||||
old[$short_setting]="$("get__${bind%%(*}" $short_setting $type $bind)"
|
||||
formats[${short_setting}]="yaml"
|
||||
|
||||
elif [[ "$bind" == "null" ]]; then
|
||||
old[$short_setting]="YNH_NULL"
|
||||
|
||||
# Get value from app settings or from another file
|
||||
elif [[ "$type" == "file" ]]; then
|
||||
if [[ "$bind" == "settings" ]]; then
|
||||
ynh_die "File '${short_setting}' can't be stored in settings"
|
||||
fi
|
||||
old[$short_setting]="$(ls "$bind" 2> /dev/null || echo YNH_NULL)"
|
||||
file_hash[$short_setting]="true"
|
||||
|
||||
# Get multiline text from settings or from a full file
|
||||
elif [[ "$type" == "text" ]]; then
|
||||
if [[ "$bind" == "settings" ]]; then
|
||||
old[$short_setting]="$(ynh_app_setting_get $app $short_setting)"
|
||||
elif [[ "$bind" == *":"* ]]; then
|
||||
ynh_die "For technical reasons, multiline text '${short_setting}' can't be stored automatically in a variable file, you have to create custom getter/setter"
|
||||
else
|
||||
old[$short_setting]="$(cat "$bind" 2> /dev/null || echo YNH_NULL)"
|
||||
fi
|
||||
|
||||
# Get value from a kind of key/value file
|
||||
else
|
||||
local bind_after=""
|
||||
if [[ "$bind" == "settings" ]]; then
|
||||
bind=":/etc/yunohost/apps/$app/settings.yml"
|
||||
fi
|
||||
local bind_key_="$(echo "$bind" | cut -d: -f1)"
|
||||
bind_key_=${bind_key_:-$short_setting}
|
||||
if [[ "$bind_key_" == *">"* ]]; then
|
||||
bind_after="$(echo "${bind_key_}" | cut -d'>' -f1)"
|
||||
bind_key_="$(echo "${bind_key_}" | cut -d'>' -f2)"
|
||||
fi
|
||||
local bind_file="$(echo "$bind" | cut -d: -f2)"
|
||||
old[$short_setting]="$(ynh_read_var_in_file --file="${bind_file}" --key="${bind_key_}" --after="${bind_after}")"
|
||||
|
||||
fi
|
||||
}
|
||||
_ynh_app_config_apply_one() {
|
||||
local short_setting="$1"
|
||||
local setter="set__${short_setting}"
|
||||
local bind="${binds[$short_setting]}"
|
||||
local type="${types[$short_setting]}"
|
||||
if [ "${changed[$short_setting]}" == "true" ]; then
|
||||
# Apply setter if exists
|
||||
if type -t $setter 2> /dev/null | grep -q '^function$' 2> /dev/null; then
|
||||
$setter
|
||||
|
||||
elif [[ "$bind" == *"("* ]] && type -t "set__${bind%%(*}" 2> /dev/null | grep -q '^function$' 2> /dev/null; then
|
||||
"set__${bind%%(*}" $short_setting $type $bind
|
||||
|
||||
elif [[ "$bind" == "null" ]]; then
|
||||
return
|
||||
|
||||
# Save in a file
|
||||
elif [[ "$type" == "file" ]]; then
|
||||
if [[ "$bind" == "settings" ]]; then
|
||||
ynh_die "File '${short_setting}' can't be stored in settings"
|
||||
fi
|
||||
local bind_file="$bind"
|
||||
if [[ "${!short_setting}" == "" ]]; then
|
||||
ynh_backup_if_checksum_is_different "$bind_file"
|
||||
ynh_safe_rm "$bind_file"
|
||||
ynh_delete_file_checksum "$bind_file"
|
||||
ynh_print_info "File '$bind_file' removed"
|
||||
else
|
||||
ynh_backup_if_checksum_is_different "$bind_file"
|
||||
if [[ "${!short_setting}" != "$bind_file" ]]; then
|
||||
cp "${!short_setting}" "$bind_file"
|
||||
fi
|
||||
if _ynh_file_checksum_exists "$bind_file"; then
|
||||
ynh_store_file_checksum "$bind_file"
|
||||
fi
|
||||
ynh_print_info "File '$bind_file' overwritten with ${!short_setting}"
|
||||
fi
|
||||
|
||||
# Save value in app settings
|
||||
elif [[ "$bind" == "settings" ]]; then
|
||||
ynh_app_setting_set --key=$short_setting --value="${!short_setting}"
|
||||
ynh_print_info "Configuration key '$short_setting' edited in app settings"
|
||||
|
||||
# Save multiline text in a file
|
||||
elif [[ "$type" == "text" ]]; then
|
||||
if [[ "$bind" == *":"* ]]; then
|
||||
ynh_die "For technical reasons, multiline text '${short_setting}' can't be stored automatically in a variable file, you have to create custom getter/setter"
|
||||
fi
|
||||
local bind_file="$bind"
|
||||
ynh_backup_if_checksum_is_different "$bind_file"
|
||||
echo "${!short_setting}" > "$bind_file"
|
||||
if _ynh_file_checksum_exists "$bind_file"; then
|
||||
ynh_store_file_checksum "$bind_file"
|
||||
fi
|
||||
ynh_print_info "File '$bind_file' overwritten with the content provided in question '${short_setting}'"
|
||||
|
||||
# Set value into a kind of key/value file
|
||||
else
|
||||
local bind_after=""
|
||||
local bind_key_="$(echo "$bind" | cut -d: -f1)"
|
||||
if [[ "$bind_key_" == *">"* ]]; then
|
||||
bind_after="$(echo "${bind_key_}" | cut -d'>' -f1)"
|
||||
bind_key_="$(echo "${bind_key_}" | cut -d'>' -f2)"
|
||||
fi
|
||||
bind_key_=${bind_key_:-$short_setting}
|
||||
local bind_file="$(echo "$bind" | cut -d: -f2)"
|
||||
|
||||
ynh_backup_if_checksum_is_different "$bind_file"
|
||||
ynh_write_var_in_file --file="${bind_file}" --key="${bind_key_}" --value="${!short_setting}" --after="${bind_after}"
|
||||
if _ynh_file_checksum_exists "$bind_file"; then
|
||||
ynh_store_file_checksum "$bind_file"
|
||||
fi
|
||||
|
||||
# We stored the info in settings in order to be able to upgrade the app
|
||||
ynh_app_setting_set --key=$short_setting --value="${!short_setting}"
|
||||
ynh_print_info "Configuration key '$bind_key_' edited into $bind_file"
|
||||
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
_ynh_app_config_get() {
|
||||
for line in $YNH_APP_CONFIG_PANEL_OPTIONS_TYPES_AND_BINDS; do
|
||||
# Split line into short_setting, type and bind
|
||||
IFS='|' read short_setting type bind <<< "$line"
|
||||
binds[${short_setting}]="$bind"
|
||||
types[${short_setting}]="$type"
|
||||
file_hash[${short_setting}]=""
|
||||
formats[${short_setting}]=""
|
||||
ynh_app_config_get_one $short_setting $type $bind
|
||||
done
|
||||
}
|
||||
|
||||
_ynh_app_config_apply() {
|
||||
for short_setting in "${!old[@]}"; do
|
||||
ynh_app_config_apply_one $short_setting
|
||||
done
|
||||
}
|
||||
|
||||
_ynh_app_config_show() {
|
||||
for short_setting in "${!old[@]}"; do
|
||||
if [[ "${old[$short_setting]}" != YNH_NULL ]]; then
|
||||
if [[ "${formats[$short_setting]}" == "yaml" ]]; then
|
||||
ynh_return "${short_setting}:"
|
||||
ynh_return "$(echo "${old[$short_setting]}" | sed 's/^/ /g')"
|
||||
else
|
||||
ynh_return "${short_setting}: '$(echo "${old[$short_setting]}" | sed "s/'/''/g" | sed ':a;N;$!ba;s/\n/\n\n/g')'"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
_ynh_app_config_validate() {
|
||||
# Change detection
|
||||
ynh_script_progression "Checking what changed in the new configuration..."
|
||||
local nothing_changed=true
|
||||
local changes_validated=true
|
||||
for short_setting in "${!old[@]}"; do
|
||||
changed[$short_setting]=false
|
||||
if [ -z ${!short_setting+x} ]; then
|
||||
# Assign the var with the old value in order to allows multiple
|
||||
# args validation
|
||||
declare -g "$short_setting"="${old[$short_setting]}"
|
||||
continue
|
||||
fi
|
||||
if [ ! -z "${file_hash[${short_setting}]}" ]; then
|
||||
file_hash[old__$short_setting]=""
|
||||
file_hash[new__$short_setting]=""
|
||||
if [ -f "${old[$short_setting]}" ]; then
|
||||
file_hash[old__$short_setting]=$(sha256sum "${old[$short_setting]}" | cut -d' ' -f1)
|
||||
if [ -z "${!short_setting}" ]; then
|
||||
changed[$short_setting]=true
|
||||
nothing_changed=false
|
||||
fi
|
||||
fi
|
||||
if [ -f "${!short_setting}" ]; then
|
||||
file_hash[new__$short_setting]=$(sha256sum "${!short_setting}" | cut -d' ' -f1)
|
||||
if [[ "${file_hash[old__$short_setting]}" != "${file_hash[new__$short_setting]}" ]]; then
|
||||
changed[$short_setting]=true
|
||||
nothing_changed=false
|
||||
fi
|
||||
fi
|
||||
else
|
||||
if [[ "${!short_setting}" != "${old[$short_setting]}" ]]; then
|
||||
changed[$short_setting]=true
|
||||
nothing_changed=false
|
||||
fi
|
||||
fi
|
||||
done
|
||||
if [[ "$nothing_changed" == "true" ]]; then
|
||||
ynh_print_info "Nothing has changed"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Run validation if something is changed
|
||||
ynh_script_progression "Validating the new configuration..."
|
||||
|
||||
for short_setting in "${!old[@]}"; do
|
||||
[[ "${changed[$short_setting]}" == "false" ]] && continue
|
||||
local result=""
|
||||
if type -t validate__$short_setting | grep -q '^function$' 2> /dev/null; then
|
||||
result="$(validate__$short_setting)"
|
||||
elif [[ "$bind" == *"("* ]] && type -t "validate__${bind%%(*}" 2> /dev/null | grep -q '^function$' 2> /dev/null; then
|
||||
"validate__${bind%%(*}" $short_setting
|
||||
fi
|
||||
if [ -n "$result" ]; then
|
||||
#
|
||||
# Return a yaml such as:
|
||||
#
|
||||
# validation_errors:
|
||||
# some_key: "An error message"
|
||||
# some_other_key: "Another error message"
|
||||
#
|
||||
# We use changes_validated to know if this is
|
||||
# the first validation error
|
||||
if [[ "$changes_validated" == true ]]; then
|
||||
ynh_return "validation_errors:"
|
||||
fi
|
||||
ynh_return " ${short_setting}: \"$result\""
|
||||
changes_validated=false
|
||||
fi
|
||||
done
|
||||
|
||||
# If validation failed, exit the script right now (instead of going into apply)
|
||||
# Yunohost core will pick up the errors returned via ynh_return previously
|
||||
if [[ "$changes_validated" == "false" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
ynh_app_config_get_one() {
|
||||
_ynh_app_config_get_one $1 $2 $3
|
||||
}
|
||||
|
||||
ynh_app_config_get() {
|
||||
_ynh_app_config_get
|
||||
}
|
||||
|
||||
ynh_app_config_show() {
|
||||
_ynh_app_config_show
|
||||
}
|
||||
|
||||
ynh_app_config_validate() {
|
||||
_ynh_app_config_validate
|
||||
}
|
||||
|
||||
ynh_app_config_apply_one() {
|
||||
_ynh_app_config_apply_one $1
|
||||
}
|
||||
ynh_app_config_apply() {
|
||||
_ynh_app_config_apply
|
||||
}
|
||||
|
||||
ynh_app_action_run() {
|
||||
local runner="run__$1"
|
||||
# Get value from getter if exists
|
||||
if type -t "$runner" 2> /dev/null | grep -q '^function$' 2> /dev/null; then
|
||||
$runner
|
||||
#ynh_return "result:"
|
||||
#ynh_return "$(echo "${result}" | sed 's/^/ /g')"
|
||||
else
|
||||
ynh_die "No handler defined in app's script for action $1. If you are the maintainer of this app, you should define '$runner'"
|
||||
fi
|
||||
}
|
||||
|
||||
ynh_app_config_run() {
|
||||
declare -Ag old=()
|
||||
declare -Ag changed=()
|
||||
declare -Ag file_hash=()
|
||||
declare -Ag binds=()
|
||||
declare -Ag types=()
|
||||
declare -Ag formats=()
|
||||
|
||||
case $1 in
|
||||
show)
|
||||
ynh_app_config_get
|
||||
ynh_app_config_show
|
||||
;;
|
||||
apply)
|
||||
max_progression=4
|
||||
ynh_script_progression "Reading config panel description and current configuration..."
|
||||
ynh_app_config_get
|
||||
|
||||
ynh_app_config_validate
|
||||
|
||||
ynh_script_progression "Applying the new configuration..."
|
||||
ynh_app_config_apply
|
||||
ynh_script_progression "Configuration of $app completed"
|
||||
;;
|
||||
*)
|
||||
ynh_app_action_run $1
|
||||
;;
|
||||
esac
|
||||
}
|
118
helpers/helpers.v2.1.d/fail2ban
Normal file
118
helpers/helpers.v2.1.d/fail2ban
Normal file
|
@ -0,0 +1,118 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Create a dedicated fail2ban config (jail and filter conf files)
|
||||
#
|
||||
# usage: ynh_config_add_fail2ban --logpath=log_file --failregex=filter
|
||||
# | arg: --logpath= - Log file to be checked by fail2ban
|
||||
# | arg: --failregex= - Failregex to be looked for by fail2ban
|
||||
#
|
||||
# If --logpath / --failregex are provided, the helper will generate the appropriate conf using these.
|
||||
#
|
||||
# Otherwise, it will assume that the app provided templates, namely
|
||||
# `../conf/f2b_jail.conf` and `../conf/f2b_filter.conf`
|
||||
#
|
||||
# They will typically look like (for example here for synapse):
|
||||
# ```
|
||||
# f2b_jail.conf:
|
||||
# [__APP__]
|
||||
# enabled = true
|
||||
# port = http,https
|
||||
# filter = __APP__
|
||||
# logpath = /var/log/__APP__/logfile.log
|
||||
# maxretry = 5
|
||||
# ```
|
||||
# ```
|
||||
# f2b_filter.conf:
|
||||
# [INCLUDES]
|
||||
# before = common.conf
|
||||
# [Definition]
|
||||
#
|
||||
# # Part of regex definition (just used to make more easy to make the global regex)
|
||||
# __synapse_start_line = .? \- synapse\..+ \-
|
||||
#
|
||||
# # Regex definition.
|
||||
# failregex = ^%(__synapse_start_line)s INFO \- POST\-(\d+)\- <HOST> \- \d+ \- Received request\: POST /_matrix/client/r0/login\??<SKIPLINES>%(__synapse_start_line)s INFO \- POST\-\1\- Got login request with identifier: \{u'type': u'm.id.user', u'user'\: u'(.+?)'\}, medium\: None, address: None, user\: u'\5'<SKIPLINES>%(__synapse_start_line)s WARNING \- \- (Attempted to login as @\5\:.+ but they do not exist|Failed password login for user @\5\:.+)$
|
||||
#
|
||||
# ignoreregex =
|
||||
# ```
|
||||
#
|
||||
# ##### Regarding the the `failregex` option:
|
||||
#
|
||||
# regex to match the password failure messages in the logfile. The host must be
|
||||
# matched by a group named "`host`". The tag "`<HOST>`" can be used for standard
|
||||
# IP/hostname matching and is only an alias for `(?:::f{4,6}:)?(?P<host>[\w\-.^_]+)`
|
||||
#
|
||||
# You can find some more explainations about how to make a regex here :
|
||||
# https://www.fail2ban.org/wiki/index.php/MANUAL_0_8#Filters
|
||||
#
|
||||
# To validate your regex you can test with this command:
|
||||
# ```
|
||||
# fail2ban-regex /var/log/YOUR_LOG_FILE_PATH /etc/fail2ban/filter.d/YOUR_APP.conf
|
||||
# ```
|
||||
ynh_config_add_fail2ban() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([l]=logpath= [r]=failregex=)
|
||||
local logpath
|
||||
local failregex
|
||||
ynh_handle_getopts_args "$@"
|
||||
# ===========================================
|
||||
|
||||
# If failregex is provided, Build a config file on-the-fly using $logpath and $failregex
|
||||
if [[ -n "${failregex:-}" ]]; then
|
||||
test -n "$logpath" || ynh_die "ynh_config_add_fail2ban expects a logfile path as first argument and received nothing."
|
||||
|
||||
echo "
|
||||
[__APP__]
|
||||
enabled = true
|
||||
port = http,https
|
||||
filter = __APP__
|
||||
logpath = __LOGPATH__
|
||||
maxretry = 5
|
||||
" > "$YNH_APP_BASEDIR/conf/f2b_jail.conf"
|
||||
|
||||
echo "
|
||||
[INCLUDES]
|
||||
before = common.conf
|
||||
[Definition]
|
||||
failregex = __FAILREGEX__
|
||||
ignoreregex =
|
||||
" > "$YNH_APP_BASEDIR/conf/f2b_filter.conf"
|
||||
fi
|
||||
|
||||
ynh_config_add --template="f2b_jail.conf" --destination="/etc/fail2ban/jail.d/$app.conf"
|
||||
ynh_config_add --template="f2b_filter.conf" --destination="/etc/fail2ban/filter.d/$app.conf"
|
||||
|
||||
# if "$logpath" doesn't exist (as if using --use_template argument), assign
|
||||
# "$logpath" using the one in the previously generated fail2ban conf file
|
||||
if [ -z "${logpath:-}" ]; then
|
||||
# the first sed deletes possibles spaces and the second one extract the path
|
||||
logpath=$(grep "^logpath" "/etc/fail2ban/jail.d/$app.conf" | sed "s/ //g" | sed "s/logpath=//g")
|
||||
fi
|
||||
|
||||
# Create the folder and logfile if they doesn't exist,
|
||||
# as fail2ban require an existing logfile before configuration
|
||||
mkdir -p "/var/log/$app"
|
||||
if [ ! -f "$logpath" ]; then
|
||||
touch "$logpath"
|
||||
fi
|
||||
# Make sure log folder's permissions are correct
|
||||
chown -R "$app:$app" "/var/log/$app"
|
||||
chmod -R u=rwX,g=rX,o= "/var/log/$app"
|
||||
|
||||
ynh_systemctl --service=fail2ban --action=reload --wait_until="(Started|Reloaded) Fail2Ban Service" --log_path=systemd
|
||||
|
||||
local fail2ban_error="$(journalctl --no-hostname --unit=fail2ban | tail --lines=50 | grep "WARNING.*$app.*")"
|
||||
if [[ -n "$fail2ban_error" ]]; then
|
||||
ynh_print_warn "Fail2ban failed to load the jail for $app"
|
||||
ynh_print_warn "${fail2ban_error#*WARNING}"
|
||||
fi
|
||||
}
|
||||
|
||||
# Remove the dedicated fail2ban config (jail and filter conf files)
|
||||
#
|
||||
# usage: ynh_config_remove_fail2ban
|
||||
ynh_config_remove_fail2ban() {
|
||||
ynh_safe_rm "/etc/fail2ban/jail.d/$app.conf"
|
||||
ynh_safe_rm "/etc/fail2ban/filter.d/$app.conf"
|
||||
ynh_systemctl --service=fail2ban --action=reload
|
||||
}
|
186
helpers/helpers.v2.1.d/getopts
Normal file
186
helpers/helpers.v2.1.d/getopts
Normal file
|
@ -0,0 +1,186 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Internal helper design to allow helpers to use getopts to manage their arguments
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# example: function my_helper()
|
||||
# {
|
||||
# local -A args_array=( [a]=arg1= [b]=arg2= [c]=arg3 )
|
||||
# local arg1
|
||||
# local arg2
|
||||
# local arg3
|
||||
# ynh_handle_getopts_args "$@"
|
||||
#
|
||||
# [...]
|
||||
# }
|
||||
# my_helper --arg1 "val1" -b val2 -c
|
||||
#
|
||||
# usage: ynh_handle_getopts_args "$@"
|
||||
# | arg: $@ - Simply "$@" to tranfert all the positionnal arguments to the function
|
||||
#
|
||||
# This helper need an array, named "args_array" with all the arguments used by the helper
|
||||
# that want to use ynh_handle_getopts_args
|
||||
# Be carreful, this array has to be an associative array, as the following example:
|
||||
# local -A args_array=( [a]=arg1 [b]=arg2= [c]=arg3 )
|
||||
# Let's explain this array:
|
||||
# a, b and c are short options, -a, -b and -c
|
||||
# arg1, arg2 and arg3 are the long options associated to the previous short ones. --arg1, --arg2 and --arg3
|
||||
# For each option, a short and long version has to be defined.
|
||||
# Let's see something more significant
|
||||
# local -A args_array=( [u]=user [f]=finalpath= [d]=database )
|
||||
#
|
||||
# NB: Because we're using 'declare' without -g, the array will be declared as a local variable.
|
||||
#
|
||||
# Please keep in mind that the long option will be used as a variable to store the values for this option.
|
||||
# For the previous example, that means that $finalpath will be fill with the value given as argument for this option.
|
||||
#
|
||||
# Also, in the previous example, finalpath has a '=' at the end. That means this option need a value.
|
||||
# So, the helper has to be call with --finalpath /final/path, --finalpath=/final/path or -f /final/path, the variable $finalpath will get the value /final/path
|
||||
# If there's many values for an option, -f /final /path, the value will be separated by a ';' $finalpath=/final;/path
|
||||
# For an option without value, like --user in the example, the helper can be called only with --user or -u. $user will then get the value 1.
|
||||
#
|
||||
ynh_handle_getopts_args() {
|
||||
# Trick to only re-enable debugging if it was set before
|
||||
local xtrace_enable=$(set +o | grep xtrace)
|
||||
|
||||
# Manage arguments only if there's some provided
|
||||
set +o xtrace # set +x
|
||||
if [ $# -eq 0 ]; then
|
||||
eval "$xtrace_enable"
|
||||
return
|
||||
# Validate that the first char is - because it should be something like --option=value or -o ...
|
||||
elif [[ "${1:0:1}" != "-" ]]; then
|
||||
ynh_die "It looks like you called the helper using positional arguments instead of keyword arguments ?"
|
||||
fi
|
||||
|
||||
# Store arguments in an array to keep each argument separated
|
||||
local arguments=("$@")
|
||||
|
||||
# For each option in the array, reduce to short options for getopts (e.g. for [u]=user, --user will be -u)
|
||||
# And built parameters string for getopts
|
||||
# ${!args_array[@]} is the list of all option_flags in the array (An option_flag is 'u' in [u]=user, user is a value)
|
||||
local getopts_parameters=""
|
||||
local option_flag=""
|
||||
for option_flag in "${!args_array[@]}"; do
|
||||
# Concatenate each option_flags of the array to build the string of arguments for getopts
|
||||
# Will looks like 'abcd' for -a -b -c -d
|
||||
# If the value of an option_flag finish by =, it's an option with additionnal values. (e.g. --user bob or -u bob)
|
||||
# Check the last character of the value associate to the option_flag
|
||||
if [ "${args_array[$option_flag]: -1}" = "=" ]; then
|
||||
# For an option with additionnal values, add a ':' after the letter for getopts.
|
||||
getopts_parameters="${getopts_parameters}${option_flag}:"
|
||||
else
|
||||
getopts_parameters="${getopts_parameters}${option_flag}"
|
||||
fi
|
||||
# Check each argument given to the function
|
||||
local arg=""
|
||||
# ${#arguments[@]} is the size of the array
|
||||
for arg in $(seq 0 $((${#arguments[@]} - 1))); do
|
||||
# Escape options' values starting with -. Otherwise the - will be considered as another option.
|
||||
arguments[arg]="${arguments[arg]//--${args_array[$option_flag]}-/--${args_array[$option_flag]}\\TOBEREMOVED\\-}"
|
||||
# And replace long option (value of the option_flag) by the short option, the option_flag itself
|
||||
# (e.g. for [u]=user, --user will be -u)
|
||||
# Replace long option with = (match the beginning of the argument)
|
||||
arguments[arg]="$(printf '%s\n' "${arguments[arg]}" | sed "s/^--${args_array[$option_flag]}/-${option_flag} /")"
|
||||
# And long option without = (match the whole line)
|
||||
arguments[arg]="$(printf '%s\n' "${arguments[arg]}" | sed "s/^--${args_array[$option_flag]%=}$/-${option_flag} /")"
|
||||
done
|
||||
done
|
||||
|
||||
# Read and parse all the arguments
|
||||
# Use a function here, to use standart arguments $@ and be able to use shift.
|
||||
parse_arg() {
|
||||
# Read all arguments, until no arguments are left
|
||||
while [ $# -ne 0 ]; do
|
||||
# Initialize the index of getopts
|
||||
OPTIND=1
|
||||
# Parse with getopts only if the argument begin by -, that means the argument is an option
|
||||
# getopts will fill $parameter with the letter of the option it has read.
|
||||
local parameter=""
|
||||
getopts ":$getopts_parameters" parameter || true
|
||||
|
||||
if [ "$parameter" = "?" ]; then
|
||||
ynh_die "Invalid argument: ${1:-}"
|
||||
elif [ "$parameter" = ":" ]; then
|
||||
ynh_die "${1:-} parameter requires an argument."
|
||||
else
|
||||
local shift_value=1
|
||||
# Use the long option, corresponding to the short option read by getopts, as a variable
|
||||
# (e.g. for [u]=user, 'user' will be used as a variable)
|
||||
# Also, remove '=' at the end of the long option
|
||||
# The variable name will be stored in 'option_var'
|
||||
local option_var="${args_array[$parameter]%=}"
|
||||
# If this option doesn't take values
|
||||
# if there's a '=' at the end of the long option name, this option takes values
|
||||
if [ "${args_array[$parameter]: -1}" != "=" ]; then
|
||||
# 'eval ${option_var}' will use the content of 'option_var'
|
||||
eval ${option_var}=1
|
||||
else
|
||||
# Read all other arguments to find multiple value for this option.
|
||||
# Load args in a array
|
||||
local all_args=("$@")
|
||||
|
||||
# If the first argument is longer than 2 characters,
|
||||
# There's a value attached to the option, in the same array cell
|
||||
if [ ${#all_args[0]} -gt 2 ]; then
|
||||
# Remove the option and the space, so keep only the value itself.
|
||||
all_args[0]="${all_args[0]#-${parameter} }"
|
||||
|
||||
# At this point, if all_args[0] start with "-", then the argument is not well formed
|
||||
if [ "${all_args[0]:0:1}" == "-" ]; then
|
||||
ynh_die "Argument \"${all_args[0]}\" not valid! Did you use a single \"-\" instead of two?"
|
||||
fi
|
||||
# Reduce the value of shift, because the option has been removed manually
|
||||
shift_value=$((shift_value - 1))
|
||||
fi
|
||||
|
||||
# Declare the content of option_var as a variable.
|
||||
eval ${option_var}=""
|
||||
# Then read the array value per value
|
||||
local i
|
||||
for i in $(seq 0 $((${#all_args[@]} - 1))); do
|
||||
# If this argument is an option, end here.
|
||||
if [ "${all_args[$i]:0:1}" == "-" ]; then
|
||||
# Ignore the first value of the array, which is the option itself
|
||||
if [ "$i" -ne 0 ]; then
|
||||
break
|
||||
fi
|
||||
else
|
||||
# Ignore empty parameters
|
||||
if [ -n "${all_args[$i]}" ]; then
|
||||
# Else, add this value to this option
|
||||
# Each value will be separated by ';'
|
||||
if [ -n "${!option_var}" ]; then
|
||||
# If there's already another value for this option, add a ; before adding the new value
|
||||
eval ${option_var}+="\;"
|
||||
fi
|
||||
|
||||
# Remove the \ that escape - at beginning of values.
|
||||
all_args[i]="${all_args[i]//\\TOBEREMOVED\\/}"
|
||||
|
||||
# For the record.
|
||||
# We're using eval here to get the content of the variable stored itself as simple text in $option_var...
|
||||
# Other ways to get that content would be to use either ${!option_var} or declare -g ${option_var}
|
||||
# But... ${!option_var} can't be used as left part of an assignation.
|
||||
# declare -g ${option_var} will create a local variable (despite -g !) and will not be available for the helper itself.
|
||||
# So... Stop fucking arguing each time that eval is evil... Go find an other working solution if you can find one!
|
||||
|
||||
eval ${option_var}+='"${all_args[$i]}"'
|
||||
fi
|
||||
shift_value=$((shift_value + 1))
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
# Shift the parameter and its argument(s)
|
||||
shift $shift_value
|
||||
done
|
||||
}
|
||||
|
||||
# Call parse_arg and pass the modified list of args as an array of arguments.
|
||||
parse_arg "${arguments[@]}"
|
||||
|
||||
eval "$xtrace_enable"
|
||||
}
|
190
helpers/helpers.v2.1.d/go
Normal file
190
helpers/helpers.v2.1.d/go
Normal file
|
@ -0,0 +1,190 @@
|
|||
#!/bin/bash
|
||||
|
||||
readonly GOENV_INSTALL_DIR="/opt/goenv"
|
||||
# goenv_ROOT is the directory of goenv, it needs to be loaded as a environment variable.
|
||||
export GOENV_ROOT="$GOENV_INSTALL_DIR"
|
||||
|
||||
_ynh_load_go_in_path_and_other_tweaks() {
|
||||
|
||||
# Get the absolute path of this version of go
|
||||
go_dir="$GOENV_INSTALL_DIR/versions/$app/bin"
|
||||
|
||||
# Load the path of this version of go in $PATH
|
||||
if [[ :$PATH: != *":$go_dir"* ]]; then
|
||||
PATH="$go_dir:$PATH"
|
||||
fi
|
||||
|
||||
# Export PATH such that it's available through sudo -E / ynh_exec_as $app
|
||||
export PATH
|
||||
|
||||
# This is in full lowercase such that it gets replaced in templates
|
||||
path_with_go="$PATH"
|
||||
PATH_with_go="$PATH"
|
||||
|
||||
# Sets the local application-specific go version
|
||||
pushd ${install_dir}
|
||||
$GOENV_INSTALL_DIR/bin/goenv local $go_version
|
||||
popd
|
||||
}
|
||||
|
||||
# Install a specific version of Go using goenv
|
||||
#
|
||||
# The installed version is defined by `$go_version` which should be defined as global prior to calling this helper
|
||||
#
|
||||
# usage: ynh_go_install
|
||||
#
|
||||
# The helper adds the appropriate, specific version of go to the `$PATH` variable (which
|
||||
# is preserved when calling `ynh_exec_as_app`). Also defines:
|
||||
# - `$path_with_go` (the value of the modified `$PATH`, but you dont really need it?)
|
||||
# - `$go_dir` (the directory containing the specific go version)
|
||||
#
|
||||
# This helper also creates a /etc/profile.d/goenv.sh that configures PATH environment for goenv
|
||||
ynh_go_install() {
|
||||
|
||||
[[ -n "${go_version:-}" ]] || ynh_die "\$go_version should be defined prior to calling ynh_go_install"
|
||||
|
||||
# Load goenv path in PATH
|
||||
local CLEAR_PATH="$GOENV_INSTALL_DIR/bin:$PATH"
|
||||
|
||||
# Remove /usr/local/bin in PATH in case of Go prior installation
|
||||
PATH=$(echo $CLEAR_PATH | sed 's@/usr/local/bin:@@')
|
||||
|
||||
# Move an existing Go binary, to avoid to block goenv
|
||||
test -x /usr/bin/go && mv /usr/bin/go /usr/bin/go_goenv
|
||||
|
||||
# Install or update goenv
|
||||
mkdir -p $GOENV_INSTALL_DIR
|
||||
pushd "$GOENV_INSTALL_DIR"
|
||||
if ! [ -x "$GOENV_INSTALL_DIR/bin/goenv" ]; then
|
||||
ynh_print_info "Downloading goenv..."
|
||||
git init -q
|
||||
git remote add origin https://github.com/syndbg/goenv.git
|
||||
else
|
||||
ynh_print_info "Updating goenv..."
|
||||
fi
|
||||
git fetch -q --tags --prune origin
|
||||
local git_latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)")
|
||||
git checkout -q "$git_latest_tag"
|
||||
_ynh_go_try_bash_extension
|
||||
goenv=$GOENV_INSTALL_DIR/bin/goenv
|
||||
popd
|
||||
|
||||
# Install or update xxenv-latest
|
||||
mkdir -p "$GOENV_INSTALL_DIR/plugins/xxenv-latest"
|
||||
pushd "$GOENV_INSTALL_DIR/plugins/xxenv-latest"
|
||||
if ! [ -x "$GOENV_INSTALL_DIR/plugins/xxenv-latest/bin/goenv-latest" ]; then
|
||||
ynh_print_info "Downloading xxenv-latest..."
|
||||
git init -q
|
||||
git remote add origin https://github.com/momo-lab/xxenv-latest.git
|
||||
else
|
||||
ynh_print_info "Updating xxenv-latest..."
|
||||
fi
|
||||
git fetch -q --tags --prune origin
|
||||
local git_latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)")
|
||||
git checkout -q "$git_latest_tag"
|
||||
popd
|
||||
|
||||
# Enable caching
|
||||
mkdir -p "${GOENV_INSTALL_DIR}/cache"
|
||||
|
||||
# Create shims directory if needed
|
||||
mkdir -p "${GOENV_INSTALL_DIR}/shims"
|
||||
|
||||
# Restore /usr/local/bin in PATH
|
||||
PATH=$CLEAR_PATH
|
||||
|
||||
# And replace the old Go binary
|
||||
test -x /usr/bin/go_goenv && mv /usr/bin/go_goenv /usr/bin/go
|
||||
|
||||
# Install the requested version of Go
|
||||
local final_go_version=$("$GOENV_INSTALL_DIR/plugins/xxenv-latest/bin/goenv-latest" --print "$go_version")
|
||||
ynh_print_info "Installation of Go-$final_go_version"
|
||||
goenv install --quiet --skip-existing "$final_go_version" 2>&1
|
||||
|
||||
# Store go_version into the config of this app
|
||||
ynh_app_setting_set --app="$app" --key="go_version" --value="$final_go_version"
|
||||
go_version=$final_go_version
|
||||
|
||||
# Cleanup Go versions
|
||||
_ynh_go_cleanup
|
||||
|
||||
# Set environment for Go users
|
||||
echo "#goenv
|
||||
export GOENV_ROOT=$GOENV_INSTALL_DIR
|
||||
export PATH=\"$GOENV_INSTALL_DIR/bin:$PATH\"
|
||||
eval \"\$(goenv init -)\"
|
||||
#goenv" > /etc/profile.d/goenv.sh
|
||||
|
||||
# Load the environment
|
||||
eval "$(goenv init -)"
|
||||
|
||||
_ynh_load_go_in_path_and_other_tweaks
|
||||
}
|
||||
|
||||
# Remove the version of Go used by the app.
|
||||
#
|
||||
# This helper will also cleanup Go versions
|
||||
#
|
||||
# usage: ynh_go_remove
|
||||
ynh_go_remove() {
|
||||
local go_version=$(ynh_app_setting_get --key="go_version")
|
||||
|
||||
# Load goenv path in PATH
|
||||
local CLEAR_PATH="$GOENV_INSTALL_DIR/bin:$PATH"
|
||||
|
||||
# Remove /usr/local/bin in PATH in case of Go prior installation
|
||||
PATH=$(echo $CLEAR_PATH | sed 's@/usr/local/bin:@@')
|
||||
|
||||
# Remove the line for this app
|
||||
ynh_app_setting_delete --key="go_version"
|
||||
|
||||
# Cleanup Go versions
|
||||
_ynh_go_cleanup
|
||||
}
|
||||
|
||||
# Remove no more needed versions of Go used by the app.
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# This helper will check what Go version are no more required,
|
||||
# and uninstall them
|
||||
# If no app uses Go, goenv will be also removed.
|
||||
#
|
||||
# usage: _ynh_go_cleanup
|
||||
_ynh_go_cleanup() {
|
||||
|
||||
# List required Go versions
|
||||
local installed_apps=$(yunohost app list --output-as json --quiet | jq -r .apps[].id)
|
||||
local required_go_versions=""
|
||||
for installed_app in $installed_apps; do
|
||||
local installed_app_go_version=$(ynh_app_setting_get --app=$installed_app --key="go_version")
|
||||
if [[ $installed_app_go_version ]]; then
|
||||
required_go_versions="${installed_app_go_version}\n${required_go_versions}"
|
||||
fi
|
||||
done
|
||||
|
||||
# Remove no more needed Go versions
|
||||
local installed_go_versions=$(goenv versions --bare --skip-aliases | grep -Ev '/')
|
||||
for installed_go_version in $installed_go_versions; do
|
||||
if ! $(echo ${required_go_versions} | grep "${installed_go_version}" 1> /dev/null 2>&1); then
|
||||
ynh_print_info "Removing of Go-$installed_go_version"
|
||||
$GOENV_INSTALL_DIR/bin/goenv uninstall --force "$installed_go_version"
|
||||
fi
|
||||
done
|
||||
|
||||
# If none Go version is required
|
||||
if [[ ! $required_go_versions ]]; then
|
||||
# Remove goenv environment configuration
|
||||
ynh_print_info "Removing of goenv"
|
||||
ynh_safe_rm "$GOENV_INSTALL_DIR"
|
||||
ynh_safe_rm "/etc/profile.d/goenv.sh"
|
||||
fi
|
||||
}
|
||||
|
||||
_ynh_go_try_bash_extension() {
|
||||
if [ -x src/configure ]; then
|
||||
src/configure && make -C src || {
|
||||
ynh_print_info "Optional bash extension failed to build, but things will still work normally."
|
||||
}
|
||||
fi
|
||||
}
|
117
helpers/helpers.v2.1.d/logging
Normal file
117
helpers/helpers.v2.1.d/logging
Normal file
|
@ -0,0 +1,117 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Print a message to stderr and terminate the current script
|
||||
#
|
||||
# usage: ynh_die "Some message"
|
||||
ynh_die() {
|
||||
set +o xtrace # set +x
|
||||
if [[ -n "${1:-}" ]]; then
|
||||
if [[ -n "${YNH_STDRETURN:-}" ]]; then
|
||||
python3 -c 'import yaml, sys; print(yaml.dump({"error": sys.stdin.read()}))' <<< "${1:-}" >> "$YNH_STDRETURN"
|
||||
fi
|
||||
echo "${1:-}" 1>&2
|
||||
fi
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Print an "INFO" message
|
||||
#
|
||||
# usage: ynh_print_info "Some message"
|
||||
ynh_print_info() {
|
||||
echo "$1" >&$YNH_STDINFO
|
||||
}
|
||||
|
||||
# Print a warning on stderr
|
||||
#
|
||||
# usage: ynh_print_warn "Some message"
|
||||
ynh_print_warn() {
|
||||
echo "$1" >&2
|
||||
}
|
||||
|
||||
# Execute a command and redirect stderr to stdout
|
||||
#
|
||||
# usage: ynh_hide_warnings your command and args
|
||||
# | arg: command - command to execute
|
||||
#
|
||||
ynh_hide_warnings() {
|
||||
# Note that "$@" is used and not $@, c.f. https://unix.stackexchange.com/a/129077
|
||||
"$@" 2>&1
|
||||
}
|
||||
|
||||
# Execute a command and redirect stderr in /dev/null. Print stderr on error.
|
||||
#
|
||||
# usage: ynh_exec_and_print_stderr_only_if_error your command and args
|
||||
# | arg: command - command to execute
|
||||
#
|
||||
# Note that you should NOT quote the command but only prefix it with ynh_exec_and_print_stderr_only_if_error
|
||||
ynh_exec_and_print_stderr_only_if_error() {
|
||||
logfile="$(mktemp)"
|
||||
rc=0
|
||||
# Note that "$@" is used and not $@, c.f. https://unix.stackexchange.com/a/129077
|
||||
"$@" 2> "$logfile" || rc="$?"
|
||||
if ((rc != 0)); then
|
||||
cat "$logfile" >&2
|
||||
ynh_safe_rm "$logfile"
|
||||
return "$rc"
|
||||
fi
|
||||
}
|
||||
|
||||
# Return data to the YunoHost core for later processing
|
||||
# (to be used by special hooks like app config panel and core diagnosis)
|
||||
#
|
||||
# usage: ynh_return somedata
|
||||
ynh_return() {
|
||||
echo "$1" >> "$YNH_STDRETURN"
|
||||
}
|
||||
|
||||
# Initial definitions for ynh_script_progression
|
||||
increment_progression=0
|
||||
previous_weight=0
|
||||
max_progression=-1
|
||||
# Set the scale of the progression bar
|
||||
# progress_string(0,1,2) should have the size of the scale.
|
||||
progress_scale=20
|
||||
progress_string2="####################"
|
||||
progress_string1="++++++++++++++++++++"
|
||||
progress_string0="...................."
|
||||
|
||||
# Print a progress bar showing the progression of an app script
|
||||
#
|
||||
# usage: ynh_script_progression "Some message"
|
||||
ynh_script_progression() {
|
||||
set +o xtrace # set +x
|
||||
|
||||
# Compute $max_progression (if we didn't already)
|
||||
if [ "$max_progression" = -1 ]; then
|
||||
# Get the number of occurrences of 'ynh_script_progression' in the script. Except those are commented.
|
||||
local helper_calls=
|
||||
max_progression="$(grep --count "^[^#]*ynh_script_progression" $0)"
|
||||
fi
|
||||
|
||||
# Increment each execution of ynh_script_progression in this script by the weight of the previous call.
|
||||
increment_progression=$(($increment_progression + $previous_weight))
|
||||
# Store the weight of the current call in $previous_weight for next call
|
||||
previous_weight=1
|
||||
|
||||
# Reduce $increment_progression to the size of the scale
|
||||
local effective_progression=$(($increment_progression * $progress_scale / $max_progression))
|
||||
|
||||
# If last is specified, fill immediately the progression_bar
|
||||
|
||||
# Build $progression_bar from progress_string(0,1,2) according to $effective_progression and the weight of the current task
|
||||
# expected_progression is the progression expected after the current task
|
||||
local expected_progression="$((($increment_progression + 1) * $progress_scale / $max_progression - $effective_progression))"
|
||||
|
||||
# Hack for the "--last" message
|
||||
if grep -qw 'completed' <<< "$1"; then
|
||||
effective_progression=$progress_scale
|
||||
expected_progression=0
|
||||
fi
|
||||
# left_progression is the progression not yet done
|
||||
local left_progression="$(($progress_scale - $effective_progression - $expected_progression))"
|
||||
# Build the progression bar with $effective_progression, work done, $expected_progression, current work and $left_progression, work to be done.
|
||||
local progression_bar="${progress_string2:0:$effective_progression}${progress_string1:0:$expected_progression}${progress_string0:0:$left_progression}"
|
||||
|
||||
echo "[$progression_bar] > ${1}" >&$YNH_STDINFO
|
||||
set -o xtrace # set -x
|
||||
}
|
73
helpers/helpers.v2.1.d/logrotate
Normal file
73
helpers/helpers.v2.1.d/logrotate
Normal file
|
@ -0,0 +1,73 @@
|
|||
#!/bin/bash
|
||||
|
||||
FIRST_CALL_TO_LOGROTATE="true"
|
||||
|
||||
# Add a logrotate configuration to manage log files / log directory
|
||||
#
|
||||
# usage: ynh_config_add_logrotate [/path/to/log/file/or/folder]
|
||||
#
|
||||
# If not argument is provided, `/var/log/$app/*.log` is used as default.
|
||||
#
|
||||
# The configuration is autogenerated by YunoHost
|
||||
# (ie it doesnt come from a specific app template like nginx or systemd conf)
|
||||
ynh_config_add_logrotate() {
|
||||
|
||||
local logfile="${1:-}"
|
||||
|
||||
set -o noglob
|
||||
if [[ -z "$logfile" ]]; then
|
||||
logfile="/var/log/${app}/*.log"
|
||||
elif [[ "${logfile##*.}" != "log" ]] && [[ "${logfile##*.}" != "txt" ]]; then
|
||||
logfile="$logfile/*.log"
|
||||
fi
|
||||
set +o noglob
|
||||
|
||||
for stuff in $logfile; do
|
||||
# Make sure the permissions of the parent dir are correct (otherwise the config file could be ignored and the corresponding logs never rotated)
|
||||
local dir=$(dirname "$stuff")
|
||||
mkdir --parents $dir
|
||||
chmod 750 $dir
|
||||
chown $app:$app $dir
|
||||
done
|
||||
|
||||
local tempconf="$(mktemp)"
|
||||
cat << EOF > $tempconf
|
||||
$logfile {
|
||||
# Rotate if the logfile exceeds 100Mo
|
||||
size 100M
|
||||
# Keep 12 old log maximum
|
||||
rotate 12
|
||||
# Compress the logs with gzip
|
||||
compress
|
||||
# Compress the log at the next cycle. So keep always 2 non compressed logs
|
||||
delaycompress
|
||||
# Copy and truncate the log to allow to continue write on it. Instead of moving the log.
|
||||
copytruncate
|
||||
# Do not trigger an error if the log is missing
|
||||
missingok
|
||||
# Do not rotate if the log is empty
|
||||
notifempty
|
||||
# Keep old logs in the same dir
|
||||
noolddir
|
||||
}
|
||||
EOF
|
||||
|
||||
if [[ "$FIRST_CALL_TO_LOGROTATE" == "true" ]]; then
|
||||
cat $tempconf > /etc/logrotate.d/$app
|
||||
else
|
||||
cat $tempconf >> /etc/logrotate.d/$app
|
||||
fi
|
||||
|
||||
FIRST_CALL_TO_LOGROTATE="false"
|
||||
|
||||
chmod 644 "/etc/logrotate.d/$app"
|
||||
}
|
||||
|
||||
# Remove the app's logrotate config.
|
||||
#
|
||||
# usage:ynh_config_remove_logrotate
|
||||
ynh_config_remove_logrotate() {
|
||||
if [ -e "/etc/logrotate.d/$app" ]; then
|
||||
rm "/etc/logrotate.d/$app"
|
||||
fi
|
||||
}
|
271
helpers/helpers.v2.1.d/mongodb
Normal file
271
helpers/helpers.v2.1.d/mongodb
Normal file
|
@ -0,0 +1,271 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Execute a mongo command
|
||||
#
|
||||
# example: ynh_mongo_exec --command='db.getMongo().getDBNames().indexOf("wekan")'
|
||||
# example: ynh_mongo_exec --command="db.getMongo().getDBNames().indexOf(\"wekan\")"
|
||||
#
|
||||
# usage: ynh_mongo_exec [--database=database] --command="command"
|
||||
# | arg: --database= - The database to connect to
|
||||
# | arg: --command= - The command to evaluate
|
||||
#
|
||||
#
|
||||
ynh_mongo_exec() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([d]=database= [c]=command=)
|
||||
local database
|
||||
local command
|
||||
ynh_handle_getopts_args "$@"
|
||||
database="${database:-}"
|
||||
# ===========================================
|
||||
|
||||
if [ -n "$database" ]; then
|
||||
mongosh --quiet << EOF
|
||||
use $database
|
||||
${command}
|
||||
quit()
|
||||
EOF
|
||||
else
|
||||
mongosh --quiet --eval="$command"
|
||||
fi
|
||||
}
|
||||
|
||||
# Drop a database
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# If you intend to drop the database *and* the associated user,
|
||||
# consider using ynh_mongo_remove_db instead.
|
||||
#
|
||||
# usage: ynh_mongo_drop_db --database=database
|
||||
# | arg: --database= - The database name to drop
|
||||
#
|
||||
#
|
||||
ynh_mongo_drop_db() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([d]=database=)
|
||||
local database
|
||||
ynh_handle_getopts_args "$@"
|
||||
# ===========================================
|
||||
|
||||
ynh_mongo_exec --database="$database" --command='db.runCommand({dropDatabase: 1})'
|
||||
}
|
||||
|
||||
# Dump a database
|
||||
#
|
||||
# example: ynh_mongo_dump_db --database=wekan > ./dump.bson
|
||||
#
|
||||
# usage: ynh_mongo_dump_db --database=database
|
||||
# | arg: --database= - The database name to dump
|
||||
# | ret: the mongodump output
|
||||
#
|
||||
#
|
||||
ynh_mongo_dump_db() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([d]=database=)
|
||||
local database
|
||||
ynh_handle_getopts_args "$@"
|
||||
# ===========================================
|
||||
|
||||
mongodump --quiet --db="$database" --archive
|
||||
}
|
||||
|
||||
# Create a user
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# usage: ynh_mongo_create_user --db_user=user --db_pwd=pwd --db_name=name
|
||||
# | arg: --db_user= - The user name to create
|
||||
# | arg: --db_pwd= - The password to identify user by
|
||||
# | arg: --db_name= - Name of the database to grant privilegies
|
||||
#
|
||||
#
|
||||
ynh_mongo_create_user() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([u]=db_user= [n]=db_name= [p]=db_pwd=)
|
||||
local db_user
|
||||
local db_name
|
||||
local db_pwd
|
||||
ynh_handle_getopts_args "$@"
|
||||
# ===========================================
|
||||
|
||||
# Create the user and set the user as admin of the db
|
||||
ynh_mongo_exec --database="$db_name" --command='db.createUser( { user: "'${db_user}'", pwd: "'${db_pwd}'", roles: [ { role: "readWrite", db: "'${db_name}'" } ] } );'
|
||||
|
||||
# Add clustermonitoring rights
|
||||
ynh_mongo_exec --database="$db_name" --command='db.grantRolesToUser("'${db_user}'",[{ role: "clusterMonitor", db: "admin" }]);'
|
||||
}
|
||||
|
||||
# Check if a mongo database exists
|
||||
#
|
||||
# usage: ynh_mongo_database_exists --database=database
|
||||
# | arg: --database= - The database for which to check existence
|
||||
# | exit: Return 1 if the database doesn't exist, 0 otherwise
|
||||
#
|
||||
#
|
||||
ynh_mongo_database_exists() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([d]=database=)
|
||||
local database
|
||||
ynh_handle_getopts_args "$@"
|
||||
# ===========================================
|
||||
|
||||
if [ $(ynh_mongo_exec --command='db.getMongo().getDBNames().indexOf("'${database}'")') -lt 0 ]; then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# Restore a database
|
||||
#
|
||||
# example: ynh_mongo_restore_db --database=wekan < ./dump.bson
|
||||
#
|
||||
# usage: ynh_mongo_restore_db --database=database
|
||||
# | arg: --database= - The database name to restore
|
||||
#
|
||||
#
|
||||
ynh_mongo_restore_db() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([d]=database=)
|
||||
local database
|
||||
ynh_handle_getopts_args "$@"
|
||||
# ===========================================
|
||||
|
||||
mongorestore --quiet --db="$database" --archive
|
||||
}
|
||||
|
||||
# Drop a user
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# usage: ynh_mongo_drop_user --db_user=user --db_name=name
|
||||
# | arg: --db_user= - The user to drop
|
||||
# | arg: --db_name= - Name of the database
|
||||
#
|
||||
#
|
||||
ynh_mongo_drop_user() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([u]=db_user= [n]=db_name=)
|
||||
local db_user
|
||||
local db_name
|
||||
ynh_handle_getopts_args "$@"
|
||||
# ===========================================
|
||||
|
||||
ynh_mongo_exec --database="$db_name" --command='db.dropUser("'$db_user'", {w: "majority", wtimeout: 5000})'
|
||||
}
|
||||
|
||||
# Create a database, an user and its password. Then store the password in the app's config
|
||||
#
|
||||
# usage: ynh_mongo_setup_db --db_user=user --db_name=name [--db_pwd=pwd]
|
||||
# | arg: --db_user= - Owner of the database
|
||||
# | arg: --db_name= - Name of the database
|
||||
# | arg: --db_pwd= - Password of the database. If not provided, a password will be generated
|
||||
#
|
||||
# After executing this helper, the password of the created database will be available in $db_pwd
|
||||
# It will also be stored as "mongopwd" into the app settings.
|
||||
#
|
||||
#
|
||||
ynh_mongo_setup_db() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([u]=db_user= [n]=db_name= [p]=db_pwd=)
|
||||
local db_user
|
||||
local db_name
|
||||
db_pwd=""
|
||||
ynh_handle_getopts_args "$@"
|
||||
# ===========================================
|
||||
|
||||
local new_db_pwd=$(ynh_string_random) # Generate a random password
|
||||
# If $db_pwd is not provided, use new_db_pwd instead for db_pwd
|
||||
db_pwd="${db_pwd:-$new_db_pwd}"
|
||||
|
||||
# Create the user and grant access to the database
|
||||
ynh_mongo_create_user --db_user="$db_user" --db_pwd="$db_pwd" --db_name="$db_name"
|
||||
|
||||
# Store the password in the app's config
|
||||
ynh_app_setting_set --key=db_pwd --value=$db_pwd
|
||||
}
|
||||
|
||||
# Remove a database if it exists, and the associated user
|
||||
#
|
||||
# usage: ynh_mongo_remove_db --db_user=user --db_name=name
|
||||
# | arg: --db_user= - Owner of the database
|
||||
# | arg: --db_name= - Name of the database
|
||||
#
|
||||
#
|
||||
ynh_mongo_remove_db() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([u]=db_user= [n]=db_name=)
|
||||
local db_user
|
||||
local db_name
|
||||
ynh_handle_getopts_args "$@"
|
||||
# ===========================================
|
||||
|
||||
if ynh_mongo_database_exists --database=$db_name; then # Check if the database exists
|
||||
ynh_mongo_drop_db --database=$db_name # Remove the database
|
||||
else
|
||||
ynh_print_warn "Database $db_name not found"
|
||||
fi
|
||||
|
||||
# Remove mongo user if it exists
|
||||
ynh_mongo_drop_user --db_user=$db_user --db_name=$db_name
|
||||
}
|
||||
|
||||
# Install MongoDB and integrate MongoDB service in YunoHost
|
||||
#
|
||||
# The installed version is defined by $mongo_version which should be defined as global prior to calling this helper
|
||||
#
|
||||
# usage: ynh_install_mongo
|
||||
#
|
||||
ynh_install_mongo() {
|
||||
|
||||
[[ -n "${mongo_version:-}" ]] || ynh_die "\$mongo_version should be defined prior to calling ynh_install_mongo"
|
||||
|
||||
ynh_print_info "Installing MongoDB Community Edition ..."
|
||||
local mongo_debian_release=$YNH_DEBIAN_VERSION
|
||||
|
||||
if [[ "$(grep '^flags' /proc/cpuinfo | uniq)" != *"avx"* && "$mongo_version" != "4.4" ]]; then
|
||||
ynh_print_warn "Installing Mongo 4.4 as $mongo_version is not compatible with your cpu (see https://docs.mongodb.com/manual/administration/production-notes/#x86_64)."
|
||||
mongo_version="4.4"
|
||||
fi
|
||||
if [[ "$mongo_version" == "4.4" ]]; then
|
||||
ynh_print_warn "Switched to buster install as Mongo 4.4 is not compatible with $mongo_debian_release."
|
||||
mongo_debian_release=buster
|
||||
fi
|
||||
|
||||
ynh_apt_install_dependencies_from_extra_repository \
|
||||
--repo="deb http://repo.mongodb.org/apt/debian $mongo_debian_release/mongodb-org/$mongo_version main" \
|
||||
--package="mongodb-org mongodb-org-server mongodb-org-tools mongodb-mongosh" \
|
||||
--key="https://www.mongodb.org/static/pgp/server-$mongo_version.asc"
|
||||
mongodb_servicename=mongod
|
||||
|
||||
# Make sure MongoDB is started and enabled
|
||||
systemctl enable $mongodb_servicename --quiet
|
||||
systemctl daemon-reload --quiet
|
||||
ynh_systemctl --service=$mongodb_servicename --action=restart --wait_until="aiting for connections" --log_path="/var/log/mongodb/$mongodb_servicename.log"
|
||||
|
||||
# Integrate MongoDB service in YunoHost
|
||||
yunohost service add $mongodb_servicename --description="MongoDB daemon" --log="/var/log/mongodb/$mongodb_servicename.log"
|
||||
|
||||
# Store mongo_version into the config of this app
|
||||
ynh_app_setting_set --key=mongo_version --value=$mongo_version
|
||||
}
|
||||
|
||||
# Remove MongoDB
|
||||
# Only remove the MongoDB service integration in YunoHost for now
|
||||
# if MongoDB package as been removed
|
||||
#
|
||||
# usage: ynh_remove_mongo
|
||||
#
|
||||
#
|
||||
ynh_remove_mongo() {
|
||||
# Only remove the mongodb service if it is not installed.
|
||||
if ! _ynh_apt_package_is_installed "mongodb*"; then
|
||||
ynh_print_info "Removing MongoDB service..."
|
||||
mongodb_servicename=mongod
|
||||
# Remove the mongodb service
|
||||
yunohost service remove $mongodb_servicename
|
||||
ynh_safe_rm "/var/lib/mongodb"
|
||||
ynh_safe_rm "/var/log/mongodb"
|
||||
fi
|
||||
}
|
89
helpers/helpers.v2.1.d/multimedia
Normal file
89
helpers/helpers.v2.1.d/multimedia
Normal file
|
@ -0,0 +1,89 @@
|
|||
#!/bin/bash
|
||||
|
||||
readonly MEDIA_GROUP=multimedia
|
||||
readonly MEDIA_DIRECTORY=/home/yunohost.multimedia
|
||||
|
||||
# Initialize the multimedia directory system
|
||||
#
|
||||
# usage: ynh_multimedia_build_main_dir
|
||||
ynh_multimedia_build_main_dir() {
|
||||
|
||||
## Création du groupe multimedia
|
||||
groupadd -f $MEDIA_GROUP
|
||||
|
||||
## Création des dossiers génériques
|
||||
mkdir -p "$MEDIA_DIRECTORY"
|
||||
mkdir -p "$MEDIA_DIRECTORY/share"
|
||||
mkdir -p "$MEDIA_DIRECTORY/share/Music"
|
||||
mkdir -p "$MEDIA_DIRECTORY/share/Picture"
|
||||
mkdir -p "$MEDIA_DIRECTORY/share/Video"
|
||||
mkdir -p "$MEDIA_DIRECTORY/share/eBook"
|
||||
|
||||
## Création des dossiers utilisateurs
|
||||
for user in $(yunohost user list --output-as json | jq -r '.users | keys[]'); do
|
||||
mkdir -p "$MEDIA_DIRECTORY/$user"
|
||||
mkdir -p "$MEDIA_DIRECTORY/$user/Music"
|
||||
mkdir -p "$MEDIA_DIRECTORY/$user/Picture"
|
||||
mkdir -p "$MEDIA_DIRECTORY/$user/Video"
|
||||
mkdir -p "$MEDIA_DIRECTORY/$user/eBook"
|
||||
ln -sfn "$MEDIA_DIRECTORY/share" "$MEDIA_DIRECTORY/$user/Share"
|
||||
# Création du lien symbolique dans le home de l'utilisateur.
|
||||
#link will only be created if the home directory of the user exists and if it's located in '/home' folder
|
||||
local user_home="$(getent passwd $user | cut -d: -f6 | grep '^/home/')"
|
||||
if [[ -d "$user_home" ]]; then
|
||||
ln -sfn "$MEDIA_DIRECTORY/$user" "$user_home/Multimedia"
|
||||
fi
|
||||
# Propriétaires des dossiers utilisateurs.
|
||||
chown -R $user "$MEDIA_DIRECTORY/$user"
|
||||
done
|
||||
# Default yunohost hooks for post_user_create,delete will take care
|
||||
# of creating/deleting corresponding multimedia folders when users
|
||||
# are created/deleted in the future...
|
||||
|
||||
## Application des droits étendus sur le dossier multimedia.
|
||||
# Droit d'écriture pour le groupe et le groupe multimedia en acl et droit de lecture pour other:
|
||||
setfacl -RnL -m g:$MEDIA_GROUP:rwX,g::rwX,o:r-X "$MEDIA_DIRECTORY" || true
|
||||
# Application de la même règle que précédemment, mais par défaut pour les nouveaux fichiers.
|
||||
setfacl -RnL -m d:g:$MEDIA_GROUP:rwX,g::rwX,o:r-X "$MEDIA_DIRECTORY" || true
|
||||
# Réglage du masque par défaut. Qui garantie (en principe...) un droit maximal à rwx. Donc pas de restriction de droits par l'acl.
|
||||
setfacl -RL -m m::rwx "$MEDIA_DIRECTORY" || true
|
||||
}
|
||||
|
||||
# Add a directory in yunohost.multimedia
|
||||
#
|
||||
# usage: ynh_multimedia_addfolder --source_dir="source_dir" --dest_dir="dest_dir"
|
||||
#
|
||||
# | arg: --source_dir= - Source directory - The real directory which contains your medias.
|
||||
# | arg: --dest_dir= - Destination directory - The name and the place of the symbolic link, relative to "/home/yunohost.multimedia"
|
||||
#
|
||||
# This "directory" will be a symbolic link to a existing directory.
|
||||
ynh_multimedia_addfolder() {
|
||||
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([s]=source_dir= [d]=dest_dir=)
|
||||
local source_dir
|
||||
local dest_dir
|
||||
ynh_handle_getopts_args "$@"
|
||||
# ===========================================
|
||||
|
||||
# Ajout d'un lien symbolique vers le dossier à partager
|
||||
ln -sfn "$source_dir" "$MEDIA_DIRECTORY/$dest_dir"
|
||||
|
||||
## Application des droits étendus sur le dossier ajouté
|
||||
# Droit d'écriture pour le groupe et le groupe multimedia en acl et droit de lecture pour other:
|
||||
setfacl -RnL -m g:$MEDIA_GROUP:rwX,g::rwX,o:r-X "$source_dir"
|
||||
# Application de la même règle que précédemment, mais par défaut pour les nouveaux fichiers.
|
||||
setfacl -RnL -m d:g:$MEDIA_GROUP:rwX,g::rwX,o:r-X "$source_dir"
|
||||
# Réglage du masque par défaut. Qui garantie (en principe...) un droit maximal à rwx. Donc pas de restriction de droits par l'acl.
|
||||
setfacl -RL -m m::rwx "$source_dir"
|
||||
}
|
||||
|
||||
# Add an user to the multimedia group, in turn having write permission in multimedia directories
|
||||
#
|
||||
# usage: ynh_multimedia_addaccess user_name
|
||||
#
|
||||
# | arg: user_name - The name of the user which gain this access.
|
||||
ynh_multimedia_addaccess() {
|
||||
groupadd -f $MEDIA_GROUP
|
||||
usermod -a -G $MEDIA_GROUP $1
|
||||
}
|
116
helpers/helpers.v2.1.d/mysql
Normal file
116
helpers/helpers.v2.1.d/mysql
Normal file
|
@ -0,0 +1,116 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Run SQL instructions in a database ($db_name by default)
|
||||
#
|
||||
# usage: ynh_mysql_db_shell [database] <<< "instructions"
|
||||
# | arg: database= - the database to connect to (by default, $db_name)
|
||||
#
|
||||
# examples:
|
||||
# ynh_mysql_db_shell $db_name <<< "UPDATE ...;"
|
||||
# ynh_mysql_db_shell < /path/to/file.sql
|
||||
#
|
||||
ynh_mysql_db_shell() {
|
||||
local database=${1:-$db_name}
|
||||
mysql -B $database
|
||||
}
|
||||
|
||||
# Create a database and grant optionnaly privilegies to a user
|
||||
#
|
||||
# [internal] ... handled by the core / "database resource"
|
||||
#
|
||||
# usage: ynh_mysql_create_db db [user [pwd]]
|
||||
# | arg: db - the database name to create
|
||||
# | arg: user - the user to grant privilegies
|
||||
# | arg: pwd - the password to identify user by
|
||||
#
|
||||
ynh_mysql_create_db() {
|
||||
local db=$1
|
||||
|
||||
local sql="CREATE DATABASE ${db};"
|
||||
|
||||
# grant all privilegies to user
|
||||
if [[ $# -gt 1 ]]; then
|
||||
sql+=" GRANT ALL PRIVILEGES ON ${db}.* TO '${2}'@'localhost'"
|
||||
if [[ -n ${3:-} ]]; then
|
||||
sql+=" IDENTIFIED BY '${3}'"
|
||||
fi
|
||||
sql+=" WITH GRANT OPTION;"
|
||||
fi
|
||||
|
||||
mysql -B <<< "$sql"
|
||||
}
|
||||
|
||||
# Drop a database
|
||||
#
|
||||
# [internal] ... handled by the core / "database resource"
|
||||
#
|
||||
# If you intend to drop the database *and* the associated user,
|
||||
# consider using ynh_mysql_remove_db instead.
|
||||
#
|
||||
# usage: ynh_mysql_drop_db db
|
||||
# | arg: db - the database name to drop
|
||||
#
|
||||
ynh_mysql_drop_db() {
|
||||
mysql -B <<< "DROP DATABASE ${1};"
|
||||
}
|
||||
|
||||
# Dump a database
|
||||
#
|
||||
# usage: ynh_mysql_dump_db database
|
||||
# | arg: database - the database name to dump (by default, $db_name)
|
||||
# | ret: The mysqldump output
|
||||
#
|
||||
# example: ynh_mysql_dump_db "roundcube" > ./dump.sql
|
||||
#
|
||||
ynh_mysql_dump_db() {
|
||||
local database=${1:-$db_name}
|
||||
mysqldump --single-transaction --skip-dump-date --routines "$database"
|
||||
}
|
||||
|
||||
# Create a user
|
||||
#
|
||||
# [internal] ... handled by the core / "database resource"
|
||||
#
|
||||
# usage: ynh_mysql_create_user user pwd [host]
|
||||
# | arg: user - the user name to create
|
||||
# | arg: pwd - the password to identify user by
|
||||
#
|
||||
ynh_mysql_create_user() {
|
||||
mysql -B <<< "CREATE USER '${1}'@'localhost' IDENTIFIED BY '${2}';"
|
||||
}
|
||||
|
||||
# Check if a mysql user exists
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# usage: ynh_mysql_user_exists user
|
||||
# | arg: user - the user for which to check existence
|
||||
# | ret: 0 if the user exists, 1 otherwise.
|
||||
ynh_mysql_user_exists() {
|
||||
local user=$1
|
||||
[[ -n "$(mysql -B <<< "SELECT User from mysql.user WHERE User = '$user';")" ]]
|
||||
}
|
||||
|
||||
# Check if a mysql database exists
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# usage: ynh_mysql_database_exists database
|
||||
# | arg: database - the database for which to check existence
|
||||
# | exit: Return 1 if the database doesn't exist, 0 otherwise
|
||||
#
|
||||
ynh_mysql_database_exists() {
|
||||
local database=$1
|
||||
mysqlshow | grep -q "^| $database "
|
||||
}
|
||||
|
||||
# Drop a user
|
||||
#
|
||||
# [internal] ... handled by the core / "database resource"
|
||||
#
|
||||
# usage: ynh_mysql_drop_user user
|
||||
# | arg: user - the user name to drop
|
||||
#
|
||||
ynh_mysql_drop_user() {
|
||||
mysql -B <<< "DROP USER '${1}'@'localhost';"
|
||||
}
|
58
helpers/helpers.v2.1.d/nginx
Normal file
58
helpers/helpers.v2.1.d/nginx
Normal file
|
@ -0,0 +1,58 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Create a dedicated nginx config
|
||||
#
|
||||
# usage: ynh_config_add_nginx
|
||||
#
|
||||
# This will use a template in `../conf/nginx.conf`
|
||||
# See the documentation of `ynh_config_add` for a description of the template
|
||||
# format and how placeholders are replaced with actual variables.
|
||||
#
|
||||
# Additionally, ynh_config_add_nginx will replace:
|
||||
# - `#sub_path_only` by empty string if `path` is not `'/'`
|
||||
# - `#root_path_only` by empty string if `path` *is* `'/'`
|
||||
#
|
||||
# This allows to enable/disable specific behaviors dependenging on the install
|
||||
# location
|
||||
ynh_config_add_nginx() {
|
||||
|
||||
local finalnginxconf="/etc/nginx/conf.d/$domain.d/$app.conf"
|
||||
|
||||
ynh_config_add --template="nginx.conf" --destination="$finalnginxconf"
|
||||
|
||||
if [ "${path:-}" != "/" ]; then
|
||||
ynh_replace --match="^#sub_path_only" --replace="" --file="$finalnginxconf"
|
||||
else
|
||||
ynh_replace --match="^#root_path_only" --replace="" --file="$finalnginxconf"
|
||||
fi
|
||||
|
||||
ynh_store_file_checksum "$finalnginxconf"
|
||||
|
||||
ynh_systemctl --service=nginx --action=reload
|
||||
}
|
||||
|
||||
# Remove the dedicated nginx config
|
||||
#
|
||||
# usage: ynh_config_remove_nginx
|
||||
ynh_config_remove_nginx() {
|
||||
ynh_safe_rm "/etc/nginx/conf.d/$domain.d/$app.conf"
|
||||
ynh_systemctl --service=nginx --action=reload
|
||||
}
|
||||
|
||||
# Regen the nginx config in a change url context
|
||||
#
|
||||
# usage: ynh_config_change_url_nginx
|
||||
ynh_config_change_url_nginx() {
|
||||
|
||||
# Make a backup of the original NGINX config file if manually modified
|
||||
# (nb: this is possibly different from the same instruction called by
|
||||
# ynh_config_add inside ynh_config_add_nginx because the path may have
|
||||
# changed if we're changing the domain too...)
|
||||
local old_nginx_conf_path=/etc/nginx/conf.d/$old_domain.d/$app.conf
|
||||
ynh_backup_if_checksum_is_different "$old_nginx_conf_path"
|
||||
ynh_delete_file_checksum "$old_nginx_conf_path"
|
||||
ynh_safe_rm "$old_nginx_conf_path"
|
||||
|
||||
# Regen the nginx conf
|
||||
ynh_config_add_nginx
|
||||
}
|
124
helpers/helpers.v2.1.d/nodejs
Normal file
124
helpers/helpers.v2.1.d/nodejs
Normal file
|
@ -0,0 +1,124 @@
|
|||
#!/bin/bash
|
||||
|
||||
readonly N_INSTALL_DIR="/opt/node_n"
|
||||
# N_PREFIX is the directory of n, it needs to be loaded as a environment variable.
|
||||
export N_PREFIX="$N_INSTALL_DIR"
|
||||
|
||||
# [internal]
|
||||
_ynh_load_nodejs_in_path_and_other_tweaks() {
|
||||
|
||||
# Get the absolute path of this version of node
|
||||
nodejs_dir="$N_INSTALL_DIR/n/versions/node/$nodejs_version/bin"
|
||||
|
||||
# Load the path of this version of node in $PATH
|
||||
if [[ :$PATH: != *":$nodejs_dir"* ]]; then
|
||||
PATH="$nodejs_dir:$PATH"
|
||||
fi
|
||||
|
||||
# Export PATH such that it's available through sudo -E / ynh_exec_as $app
|
||||
export PATH
|
||||
|
||||
# This is in full lowercase such that it gets replaced in templates
|
||||
path_with_nodejs="$PATH"
|
||||
PATH_with_nodejs="$PATH"
|
||||
|
||||
# Prevent yet another Node and Corepack madness, with Corepack wanting the user to confirm download of Yarn
|
||||
export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
|
||||
}
|
||||
|
||||
# Install a specific version of nodejs, using 'n'
|
||||
#
|
||||
# The installed version is defined by `$nodejs_version` which should be defined as global prior to calling this helper
|
||||
#
|
||||
# usage: ynh_nodejs_install
|
||||
#
|
||||
# `n` (Node version management) uses the `PATH` variable to store the path of the version of node it is going to use.
|
||||
# That's how it changes the version
|
||||
#
|
||||
# The helper adds the appropriate, specific version of nodejs to the `$PATH` variable (which
|
||||
# is preserved when calling ynh_exec_as_app). Also defines:
|
||||
# - `$path_with_nodejs` to be used in the systemd config (`Environment="PATH=__PATH_WITH_NODEJS__"`)
|
||||
# - `$nodejs_dir`, the directory containing the specific version of nodejs, which may be used in the systemd config too (e.g. `ExecStart=__NODEJS_DIR__/node foo bar`)
|
||||
ynh_nodejs_install() {
|
||||
# Use n, https://github.com/tj/n to manage the nodejs versions
|
||||
|
||||
[[ -n "${nodejs_version:-}" ]] || ynh_die "\$nodejs_version should be defined prior to calling ynh_nodejs_install"
|
||||
|
||||
# Create $N_INSTALL_DIR
|
||||
mkdir --parents "$N_INSTALL_DIR"
|
||||
|
||||
# Load n path in PATH
|
||||
CLEAR_PATH="$N_INSTALL_DIR/bin:$PATH"
|
||||
# Remove /usr/local/bin in PATH in case of node prior installation
|
||||
PATH=$(echo $CLEAR_PATH | sed 's@/usr/local/bin:@@')
|
||||
|
||||
# Move an existing node binary, to avoid to block n.
|
||||
test -x /usr/bin/node && mv /usr/bin/node /usr/bin/node_n
|
||||
test -x /usr/bin/npm && mv /usr/bin/npm /usr/bin/npm_n
|
||||
|
||||
# Install (or update if YunoHost vendor/ folder updated since last install) n
|
||||
mkdir -p $N_INSTALL_DIR/bin/
|
||||
cp "$YNH_HELPERS_DIR/vendor/n/n" $N_INSTALL_DIR/bin/n
|
||||
# Tweak for n to understand it's installed in $N_PREFIX
|
||||
ynh_replace --match="^N_PREFIX=\${N_PREFIX-.*}$" --replace="N_PREFIX=\${N_PREFIX-$N_PREFIX}" --file="$N_INSTALL_DIR/bin/n"
|
||||
|
||||
# Restore /usr/local/bin in PATH
|
||||
PATH=$CLEAR_PATH
|
||||
|
||||
# And replace the old node binary.
|
||||
test -x /usr/bin/node_n && mv /usr/bin/node_n /usr/bin/node
|
||||
test -x /usr/bin/npm_n && mv /usr/bin/npm_n /usr/bin/npm
|
||||
|
||||
# Install the requested version of nodejs
|
||||
uname=$(uname --machine)
|
||||
if [[ $uname =~ aarch64 || $uname =~ arm64 ]]; then
|
||||
n $nodejs_version --arch=arm64
|
||||
else
|
||||
n $nodejs_version
|
||||
fi
|
||||
|
||||
# Find the last "real" version for this major version of node.
|
||||
real_nodejs_version=$(find $N_INSTALL_DIR/n/versions/node/$nodejs_version* -maxdepth 0 | sort --version-sort | tail --lines=1)
|
||||
real_nodejs_version=$(basename $real_nodejs_version)
|
||||
|
||||
# Create a symbolic link for this major version if the file doesn't already exist
|
||||
if [ ! -e "$N_INSTALL_DIR/n/versions/node/$nodejs_version" ]; then
|
||||
ln --symbolic --force --no-target-directory \
|
||||
$N_INSTALL_DIR/n/versions/node/$real_nodejs_version \
|
||||
$N_INSTALL_DIR/n/versions/node/$nodejs_version
|
||||
fi
|
||||
|
||||
# Store the ID of this app and the version of node requested for it
|
||||
echo "$YNH_APP_INSTANCE_NAME:$nodejs_version" | tee --append "$N_INSTALL_DIR/ynh_app_version"
|
||||
|
||||
# Store nodejs_version into the config of this app
|
||||
ynh_app_setting_set --key=nodejs_version --value=$nodejs_version
|
||||
|
||||
_ynh_load_nodejs_in_path_and_other_tweaks
|
||||
}
|
||||
|
||||
# Remove the version of node used by the app.
|
||||
#
|
||||
# usage: ynh_nodejs_remove
|
||||
#
|
||||
# This helper will check if another app uses the same version of node.
|
||||
# - If not, this version of node will be removed.
|
||||
# - If no other app uses node, n will be also removed.
|
||||
ynh_nodejs_remove() {
|
||||
|
||||
[[ -n "${nodejs_version:-}" ]] || ynh_die "\$nodejs_version should be defined prior to calling ynh_nodejs_remove"
|
||||
|
||||
# Remove the line for this app
|
||||
sed --in-place "/$YNH_APP_INSTANCE_NAME:$nodejs_version/d" "$N_INSTALL_DIR/ynh_app_version"
|
||||
|
||||
# If no other app uses this version of nodejs, remove it.
|
||||
if ! grep --quiet "$nodejs_version" "$N_INSTALL_DIR/ynh_app_version"; then
|
||||
$N_INSTALL_DIR/bin/n rm $nodejs_version
|
||||
fi
|
||||
|
||||
# If no other app uses n, remove n
|
||||
if [ ! -s "$N_INSTALL_DIR/ynh_app_version" ]; then
|
||||
ynh_safe_rm "$N_INSTALL_DIR"
|
||||
sed --in-place "/N_PREFIX/d" /root/.bashrc
|
||||
fi
|
||||
}
|
310
helpers/helpers.v2.1.d/permission
Normal file
310
helpers/helpers.v2.1.d/permission
Normal file
|
@ -0,0 +1,310 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Create a new permission for the app
|
||||
#
|
||||
# Example 1: `ynh_permission_create --permission=admin --url=/admin --additional_urls=domain.tld/admin /superadmin --allowed=alice bob \
|
||||
# --label="My app admin" --show_tile=true`
|
||||
#
|
||||
# This example will create a new permission permission with this following effect:
|
||||
# - A tile named "My app admin" in the SSO will be available for the users alice and bob. This tile will point to the relative url '/admin'.
|
||||
# - Only the user alice and bob will have the access to theses following url: /admin, domain.tld/admin, /superadmin
|
||||
#
|
||||
#
|
||||
# Example 2:
|
||||
#
|
||||
# ynh_permission_create --permission=api --url=domain.tld/api --auth_header=false --allowed=visitors \
|
||||
# --label="MyApp API" --protected=true
|
||||
#
|
||||
# This example will create a new protected permission. So the admin won't be able to add/remove the visitors group of this permission.
|
||||
# In case of an API with need to be always public it avoid that the admin break anything.
|
||||
# With this permission all client will be allowed to access to the url 'domain.tld/api'.
|
||||
# Note that in this case no tile will be show on the SSO.
|
||||
# Note that the auth_header parameter is to 'false'. So no authentication header will be passed to the application.
|
||||
# Generally the API is requested by an application and enabling the auth_header has no advantage and could bring some issues in some case.
|
||||
# So in this case it's better to disable this option for all API.
|
||||
#
|
||||
#
|
||||
# usage: ynh_permission_create --permission="permission" [--url="url"] [--additional_urls="second-url" [ "third-url" ]] [--auth_header=true|false]
|
||||
# [--allowed=group1 [ group2 ]] [--label="label"] [--show_tile=true|false]
|
||||
# [--protected=true|false]
|
||||
# | arg: --permission= - the name for the permission (by default a permission named "main" already exist)
|
||||
# | arg: --url= - (optional) URL for which access will be allowed/forbidden. Note that if 'show_tile' is enabled, this URL will be the URL of the tile.
|
||||
# | arg: --additional_urls= - (optional) List of additional URL for which access will be allowed/forbidden
|
||||
# | arg: --auth_header= - (optional) Define for the URL of this permission, if SSOwat pass the authentication header to the application. Default is true
|
||||
# | arg: --allowed= - (optional) A list of group/user to allow for the permission
|
||||
# | arg: --label= - (optional) Define a name for the permission. This label will be shown on the SSO and in the admin. Default is "APP_LABEL (permission name)".
|
||||
# | arg: --show_tile= - (optional) Define if a tile will be shown in the SSO. If yes the name of the tile will be the 'label' parameter. Defaults to false for the permission different than 'main'.
|
||||
# | arg: --protected= - (optional) Define if this permission is protected. If it is protected the administrator won't be able to add or remove the visitors group of this permission. Defaults to 'false'.
|
||||
#
|
||||
# [packagingv1]
|
||||
#
|
||||
# If provided, 'url' or 'additional_urls' is assumed to be relative to the app domain/path if they
|
||||
# start with '/'. For example:
|
||||
# / -> domain.tld/app
|
||||
# /admin -> domain.tld/app/admin
|
||||
# domain.tld/app/api -> domain.tld/app/api
|
||||
#
|
||||
# 'url' or 'additional_urls' can be treated as a PCRE (not lua) regex if it starts with "re:".
|
||||
# For example:
|
||||
# re:/api/[A-Z]*$ -> domain.tld/app/api/[A-Z]*$
|
||||
# re:domain.tld/app/api/[A-Z]*$ -> domain.tld/app/api/[A-Z]*$
|
||||
#
|
||||
# Note that globally the parameter 'url' and 'additional_urls' are same. The only difference is:
|
||||
# - 'url' is only one url, 'additional_urls' can be a list of urls. There are no limitation of 'additional_urls'
|
||||
# - 'url' is used for the url of tile in the SSO (if enabled with the 'show_tile' parameter)
|
||||
#
|
||||
#
|
||||
# About the authentication header (auth_header parameter).
|
||||
# The SSO pass (by default) to the application theses following HTTP header (linked to the authenticated user) to the application:
|
||||
# - "Auth-User": username
|
||||
# - "Remote-User": username
|
||||
# - "Email": user email
|
||||
#
|
||||
# Generally this feature is usefull to authenticate automatically the user in the application but in some case the application don't work with theses header and theses header need to be disabled to have the application to work correctly.
|
||||
# See https://github.com/YunoHost/issues/issues/1420 for more informations
|
||||
ynh_permission_create() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([p]=permission= [u]=url= [A]=additional_urls= [h]=auth_header= [a]=allowed= [l]=label= [t]=show_tile= [P]=protected=)
|
||||
local permission
|
||||
local url
|
||||
local additional_urls
|
||||
local auth_header
|
||||
local allowed
|
||||
local label
|
||||
local show_tile
|
||||
local protected
|
||||
ynh_handle_getopts_args "$@"
|
||||
url=${url:-}
|
||||
additional_urls=${additional_urls:-}
|
||||
auth_header=${auth_header:-}
|
||||
allowed=${allowed:-}
|
||||
label=${label:-}
|
||||
show_tile=${show_tile:-}
|
||||
protected=${protected:-}
|
||||
# ===========================================
|
||||
|
||||
if [[ -n $url ]]; then
|
||||
url=",url='$url'"
|
||||
fi
|
||||
|
||||
if [[ -n $additional_urls ]]; then
|
||||
# Convert a list from getopts to python list
|
||||
# Note that getopts separate the args with ';'
|
||||
# By example:
|
||||
# --additional_urls /urlA /urlB
|
||||
# will be:
|
||||
# additional_urls=['/urlA', '/urlB']
|
||||
additional_urls=",additional_urls=['${additional_urls//;/\',\'}']"
|
||||
fi
|
||||
|
||||
if [[ -n $auth_header ]]; then
|
||||
if [ $auth_header == "true" ]; then
|
||||
auth_header=",auth_header=True"
|
||||
else
|
||||
auth_header=",auth_header=False"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n $allowed ]]; then
|
||||
# Convert a list from getopts to python list
|
||||
# Note that getopts separate the args with ';'
|
||||
# By example:
|
||||
# --allowed alice bob
|
||||
# will be:
|
||||
# allowed=['alice', 'bob']
|
||||
allowed=",allowed=['${allowed//;/\',\'}']"
|
||||
fi
|
||||
|
||||
if [[ -n ${label:-} ]]; then
|
||||
label=",label='$label'"
|
||||
else
|
||||
label=",label='$permission'"
|
||||
fi
|
||||
|
||||
if [[ -n ${show_tile:-} ]]; then
|
||||
if [ $show_tile == "true" ]; then
|
||||
show_tile=",show_tile=True"
|
||||
else
|
||||
show_tile=",show_tile=False"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n ${protected:-} ]]; then
|
||||
if [ $protected == "true" ]; then
|
||||
protected=",protected=True"
|
||||
else
|
||||
protected=",protected=False"
|
||||
fi
|
||||
fi
|
||||
|
||||
yunohost tools shell -c "from yunohost.permission import permission_create; permission_create('$app.$permission' $url $additional_urls $auth_header $allowed $label $show_tile $protected)"
|
||||
}
|
||||
|
||||
# Remove a permission for the app (note that when the app is removed all permission is automatically removed)
|
||||
#
|
||||
# example: ynh_permission_delete --permission=editors
|
||||
#
|
||||
# usage: ynh_permission_delete --permission="permission"
|
||||
# | arg: --permission= - the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
|
||||
ynh_permission_delete() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([p]=permission=)
|
||||
local permission
|
||||
ynh_handle_getopts_args "$@"
|
||||
# ===========================================
|
||||
|
||||
yunohost tools shell -c "from yunohost.permission import permission_delete; permission_delete('$app.$permission')"
|
||||
}
|
||||
|
||||
# Check if a permission exists
|
||||
#
|
||||
# usage: ynh_permission_exists --permission=permission
|
||||
# | arg: --permission= - the permission to check
|
||||
# | exit: Return 1 if the permission doesn't exist, 0 otherwise
|
||||
ynh_permission_exists() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([p]=permission=)
|
||||
local permission
|
||||
ynh_handle_getopts_args "$@"
|
||||
# ===========================================
|
||||
|
||||
yunohost user permission list "$app" --output-as json --quiet \
|
||||
| jq -e --arg perm "$app.$permission" '.permissions[$perm]' > /dev/null
|
||||
}
|
||||
|
||||
# Redefine the url associated to a permission
|
||||
#
|
||||
# usage: ynh_permission_url --permission "permission" [--url="url"] [--add_url="new-url" [ "other-new-url" ]] [--remove_url="old-url" [ "other-old-url" ]]
|
||||
# [--auth_header=true|false] [--clear_urls]
|
||||
# | arg: --permission= - the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
|
||||
# | arg: --url= - (optional) URL for which access will be allowed/forbidden. Note that if you want to remove url you can pass an empty sting as arguments ("").
|
||||
# | arg: --add_url= - (optional) List of additional url to add for which access will be allowed/forbidden.
|
||||
# | arg: --remove_url= - (optional) List of additional url to remove for which access will be allowed/forbidden
|
||||
# | arg: --auth_header= - (optional) Define for the URL of this permission, if SSOwat pass the authentication header to the application
|
||||
# | arg: --clear_urls - (optional) Clean all urls (url and additional_urls)
|
||||
ynh_permission_url() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([p]=permission= [u]=url= [a]=add_url= [r]=remove_url= [h]=auth_header= [c]=clear_urls)
|
||||
local permission
|
||||
local url
|
||||
local add_url
|
||||
local remove_url
|
||||
local auth_header
|
||||
local clear_urls
|
||||
ynh_handle_getopts_args "$@"
|
||||
url=${url:-}
|
||||
add_url=${add_url:-}
|
||||
remove_url=${remove_url:-}
|
||||
auth_header=${auth_header:-}
|
||||
clear_urls=${clear_urls:-}
|
||||
# ===========================================
|
||||
|
||||
if [[ -n $url ]]; then
|
||||
url=",url='$url'"
|
||||
fi
|
||||
|
||||
if [[ -n $add_url ]]; then
|
||||
# Convert a list from getopts to python list
|
||||
# Note that getopts separate the args with ';'
|
||||
# For example:
|
||||
# --add_url /urlA /urlB
|
||||
# will be:
|
||||
# add_url=['/urlA', '/urlB']
|
||||
add_url=",add_url=['${add_url//;/\',\'}']"
|
||||
fi
|
||||
|
||||
if [[ -n $remove_url ]]; then
|
||||
# Convert a list from getopts to python list
|
||||
# Note that getopts separate the args with ';'
|
||||
# For example:
|
||||
# --remove_url /urlA /urlB
|
||||
# will be:
|
||||
# remove_url=['/urlA', '/urlB']
|
||||
remove_url=",remove_url=['${remove_url//;/\',\'}']"
|
||||
fi
|
||||
|
||||
if [[ -n $auth_header ]]; then
|
||||
if [ $auth_header == "true" ]; then
|
||||
auth_header=",auth_header=True"
|
||||
else
|
||||
auth_header=",auth_header=False"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n $clear_urls ]] && [ $clear_urls -eq 1 ]; then
|
||||
clear_urls=",clear_urls=True"
|
||||
fi
|
||||
|
||||
yunohost tools shell -c "from yunohost.permission import permission_url; permission_url('$app.$permission' $url $add_url $remove_url $auth_header $clear_urls)"
|
||||
}
|
||||
|
||||
# Update a permission for the app
|
||||
#
|
||||
# usage: ynh_permission_update --permission "permission" [--add="group" ["group" ...]] [--remove="group" ["group" ...]]
|
||||
#
|
||||
# | arg: --permission= - the name for the permission (by default a permission named "main" already exist)
|
||||
# | arg: --add= - the list of group or users to enable add to the permission
|
||||
# | arg: --remove= - the list of group or users to remove from the permission
|
||||
ynh_permission_update() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([p]=permission= [a]=add= [r]=remove=)
|
||||
local permission
|
||||
local add
|
||||
local remove
|
||||
ynh_handle_getopts_args "$@"
|
||||
add=${add:-}
|
||||
remove=${remove:-}
|
||||
# ===========================================
|
||||
|
||||
if [[ -n $add ]]; then
|
||||
# Convert a list from getopts to python list
|
||||
# Note that getopts separate the args with ';'
|
||||
# For example:
|
||||
# --add alice bob
|
||||
# will be:
|
||||
# add=['alice', 'bob']
|
||||
add=",add=['${add//';'/"','"}']"
|
||||
fi
|
||||
if [[ -n $remove ]]; then
|
||||
# Convert a list from getopts to python list
|
||||
# Note that getopts separate the args with ';'
|
||||
# For example:
|
||||
# --remove alice bob
|
||||
# will be:
|
||||
# remove=['alice', 'bob']
|
||||
remove=",remove=['${remove//';'/"','"}']"
|
||||
fi
|
||||
|
||||
yunohost tools shell -c "from yunohost.permission import user_permission_update; user_permission_update('$app.$permission' $add $remove , force=True)"
|
||||
}
|
||||
|
||||
# Check if a permission has an user
|
||||
#
|
||||
# example: ynh_permission_has_user --permission=main --user=visitors
|
||||
#
|
||||
# usage: ynh_permission_has_user --permission=permission --user=user
|
||||
# | arg: --permission= - the permission to check
|
||||
# | arg: --user= - the user seek in the permission
|
||||
# | exit: Return 1 if the permission doesn't have that user or doesn't exist, 0 otherwise
|
||||
ynh_permission_has_user() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([p]=permission= [u]=user=)
|
||||
local permission
|
||||
local user
|
||||
ynh_handle_getopts_args "$@"
|
||||
# ===========================================
|
||||
|
||||
if ! ynh_permission_exists --permission=$permission; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Check both allowed and corresponding_users sections in the json
|
||||
for section in "allowed" "corresponding_users"; do
|
||||
if yunohost user permission info "$app.$permission" --output-as json --quiet \
|
||||
| jq -e --arg user $user --arg section $section '.[$section] | index($user)' > /dev/null; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
149
helpers/helpers.v2.1.d/php
Normal file
149
helpers/helpers.v2.1.d/php
Normal file
|
@ -0,0 +1,149 @@
|
|||
#!/bin/bash
|
||||
|
||||
# (this is used in the apt helpers, big meh ...)
|
||||
readonly YNH_DEFAULT_PHP_VERSION=7.4
|
||||
|
||||
# Create a dedicated PHP-FPM config
|
||||
#
|
||||
# usage: ynh_config_add_phpfpm
|
||||
#
|
||||
# This will automatically generate an appropriate PHP-FPM configuration for this app.
|
||||
#
|
||||
# The resulting configuration will be deployed to the appropriate place:
|
||||
# `/etc/php/$php_version/fpm/pool.d/$app.conf`
|
||||
#
|
||||
# If the app provides a `conf/extra_php-fpm.conf` template, it will be appended
|
||||
# to the generated configuration. (In the vast majority of cases, this shouldnt
|
||||
# be necessary)
|
||||
#
|
||||
# $php_version should be defined prior to calling this helper, but there should
|
||||
# be no reason to manually set it, as it is automatically set by the apt
|
||||
# helpers/resources when installing phpX.Y dependencies (PHP apps should at
|
||||
# least install phpX.Y-fpm using the `apt` helper/resource)
|
||||
#
|
||||
# `$php_group` can be defined as a global (from `_common.sh`) if the worker
|
||||
# processes should run with a different group than `$app`
|
||||
#
|
||||
# Additional "pm" and "php_admin_value" settings which are meant to be possibly
|
||||
# configurable by admins from a future standard config panel at some point,
|
||||
# related to performance and availability of the app, for which tweaking may be
|
||||
# required if the app is used by "plenty" of users and other memory/CPU load
|
||||
# considerations....
|
||||
#
|
||||
# If you have good reasons to be willing to use different
|
||||
# defaults than the one set by this helper (while still allowing admin to
|
||||
# override it) you should use `ynh_app_setting_set_default`
|
||||
#
|
||||
# - `$php_upload_max_filezise`: corresponds upload_max_filesize and post_max_size. Defaults to 50M
|
||||
# - `$php_process_management`: corresponds to "pm" (ondemand, dynamic, static). Defaults to ondemand
|
||||
# - `$php_max_children`: by default, computed from "total RAM" divided by 40, cf `_default_php_max_children`
|
||||
# - `$php_memory_limit`: by default, 128M (from global php.ini)
|
||||
#
|
||||
# Note that if $php_process_management is set to "dynamic", then these
|
||||
# variables MUST be defined prior to calling the helper (no default value) ...
|
||||
# Check PHP-FPM's manual for more info on what these are (: ...
|
||||
#
|
||||
# - `$php_start_servers`
|
||||
# - `$php_min_spare_servers`
|
||||
# - `$php_max_spare_servers`
|
||||
#
|
||||
ynh_config_add_phpfpm() {
|
||||
|
||||
[[ -n "${php_version:-}" ]] || ynh_die "\$php_version should be defined prior to calling ynh_config_add_phpfpm. You should not need to define it manually, it is automatically set by the apt helper when installing the phpX.Y- depenencies"
|
||||
|
||||
# Apps may define $php_group as a global (e.g. from _common.sh) to change this
|
||||
# (this is not meant to be overridable by users)
|
||||
local php_group=${php_group:-$app}
|
||||
|
||||
# Meant to be overridable by users from a standard config panel at some point ...
|
||||
# Apps willing to tweak these should use ynh_setting_set_default_value (in install and upgrade?)
|
||||
#
|
||||
local php_upload_max_filesize=${php_upload_max_filesize:-50M}
|
||||
local php_process_management=${php_process_management:-ondemand} # alternatively 'dynamic' or 'static'
|
||||
local php_max_children=${php_max_children:-$(_default_php_max_children)}
|
||||
local php_memory_limit=${php_memory_limit:-128M} # default value is from global php.ini
|
||||
|
||||
local phpfpm_template=$(mktemp)
|
||||
cat << EOF > $phpfpm_template
|
||||
[__APP__]
|
||||
|
||||
user = __APP__
|
||||
group = __PHP_GROUP__
|
||||
|
||||
chdir = __INSTALL_DIR__
|
||||
|
||||
listen = /var/run/php/php__PHP_VERSION__-fpm-__APP__.sock
|
||||
listen.owner = www-data
|
||||
listen.group = www-data
|
||||
|
||||
pm = __PHP_PROCESS_MANAGEMENT__
|
||||
pm.max_children = __PHP_MAX_CHILDREN__
|
||||
pm.max_requests = 500
|
||||
request_terminate_timeout = 1d
|
||||
|
||||
EOF
|
||||
if [ "$php_process_management" = "dynamic" ]; then
|
||||
cat << EOF >> $phpfpm_template
|
||||
pm.start_servers = __PHP_START_SERVERS__
|
||||
pm.min_spare_servers = __PHP_MIN_SPARE_SERVERS__
|
||||
pm.max_spare_servers = __PHP_MAX_SPARE_SERVERS__
|
||||
EOF
|
||||
elif [ "$php_process_management" = "ondemand" ]; then
|
||||
cat << EOF >> $phpfpm_template
|
||||
pm.process_idle_timeout = 10s
|
||||
EOF
|
||||
fi
|
||||
|
||||
cat << EOF >> $phpfpm_template
|
||||
php_admin_value[upload_max_filesize] = __PHP_UPLOAD_MAX_FILESIZE__
|
||||
php_admin_value[post_max_size] = __PHP_UPLOAD_MAX_FILESIZE__
|
||||
php_admin_value[memory_limit] = __PHP_MEMORY_LIMIT__
|
||||
EOF
|
||||
|
||||
# Concatene the extra config
|
||||
if [ -e $YNH_APP_BASEDIR/conf/extra_php-fpm.conf ]; then
|
||||
cat $YNH_APP_BASEDIR/conf/extra_php-fpm.conf >> "$phpfpm_template"
|
||||
fi
|
||||
|
||||
# Make sure the fpm pool dir exists
|
||||
mkdir --parents "/etc/php/$php_version/fpm/pool.d"
|
||||
# And hydrate configuration
|
||||
ynh_config_add --template="$phpfpm_template" --destination="/etc/php/$php_version/fpm/pool.d/$app.conf"
|
||||
|
||||
# Validate that the new php conf doesn't break php-fpm entirely
|
||||
if ! php-fpm${php_version} --test 2> /dev/null; then
|
||||
php-fpm${php_version} --test || true
|
||||
ynh_safe_rm "/etc/php/$php_version/fpm/pool.d/$app.conf"
|
||||
ynh_die "The new configuration broke php-fpm?"
|
||||
fi
|
||||
|
||||
ynh_systemctl --service=php${php_version}-fpm --action=reload
|
||||
}
|
||||
|
||||
# Remove the dedicated PHP-FPM config
|
||||
#
|
||||
# usage: ynh_config_remove_phpfpm
|
||||
ynh_config_remove_phpfpm() {
|
||||
ynh_safe_rm "/etc/php/$php_version/fpm/pool.d/$app.conf"
|
||||
ynh_systemctl --service="php${php_version}-fpm" --action=reload
|
||||
}
|
||||
|
||||
_default_php_max_children() {
|
||||
# Get the total of RAM available
|
||||
local total_ram=$(ynh_get_ram --total)
|
||||
|
||||
# The value of pm.max_children is the total amount of ram divide by 2,
|
||||
# divide again by 20MB (= a default, classic worker footprint) This is
|
||||
# designed such that if PHP-FPM start the maximum of children, it won't
|
||||
# exceed half of the ram.
|
||||
local php_max_children="$(($total_ram / 40))"
|
||||
# Make sure we get at least max_children = 1
|
||||
if [ $php_max_children -le 0 ]; then
|
||||
php_max_children=1
|
||||
# To not overload the proc, limit the number of children to 4 times the number of cores.
|
||||
elif [ $php_max_children -gt "$(($(nproc) * 4))" ]; then
|
||||
php_max_children="$(($(nproc) * 4))"
|
||||
fi
|
||||
|
||||
echo "$php_max_children"
|
||||
}
|
124
helpers/helpers.v2.1.d/postgresql
Normal file
124
helpers/helpers.v2.1.d/postgresql
Normal file
|
@ -0,0 +1,124 @@
|
|||
#!/bin/bash
|
||||
|
||||
PSQL_ROOT_PWD_FILE=/etc/yunohost/psql
|
||||
PSQL_VERSION=13
|
||||
|
||||
# Run SQL instructions in a database ($db_name by default)
|
||||
#
|
||||
# usage: ynh_psql_db_shell database <<< "instructions"
|
||||
# | arg: database - the database to connect to (by default, $db_name)
|
||||
#
|
||||
# examples:
|
||||
# ynh_psql_db_shell $db_name <<< "UPDATE ...;"
|
||||
# ynh_psql_db_shell < /path/to/file.sql
|
||||
#
|
||||
ynh_psql_db_shell() {
|
||||
local database="${1:-$db_name}"
|
||||
sudo --login --user=postgres psql "$database"
|
||||
}
|
||||
|
||||
# Create a database and grant optionnaly privilegies to a user
|
||||
#
|
||||
# [internal] ... handled by the core / "database resource"
|
||||
#
|
||||
# usage: ynh_psql_create_db db [user]
|
||||
# | arg: db - the database name to create
|
||||
# | arg: user - the user to grant privilegies
|
||||
#
|
||||
ynh_psql_create_db() {
|
||||
local db=$1
|
||||
local user=${2:-}
|
||||
|
||||
local sql="CREATE DATABASE ${db};"
|
||||
|
||||
# grant all privilegies to user
|
||||
if [ -n "$user" ]; then
|
||||
sql+="ALTER DATABASE ${db} OWNER TO ${user};"
|
||||
sql+="GRANT ALL PRIVILEGES ON DATABASE ${db} TO ${user} WITH GRANT OPTION;"
|
||||
fi
|
||||
|
||||
sudo --login --user=postgres psql <<< "$sql"
|
||||
}
|
||||
|
||||
# Drop a database
|
||||
#
|
||||
# [internal] ... handled by the core / "database resource"
|
||||
#
|
||||
# If you intend to drop the database *and* the associated user,
|
||||
# consider using ynh_psql_remove_db instead.
|
||||
#
|
||||
# usage: ynh_psql_drop_db db
|
||||
# | arg: db - the database name to drop
|
||||
#
|
||||
ynh_psql_drop_db() {
|
||||
local db=$1
|
||||
# First, force disconnection of all clients connected to the database
|
||||
# https://stackoverflow.com/questions/17449420/postgresql-unable-to-drop-database-because-of-some-auto-connections-to-db
|
||||
sudo --login --user=postgres psql $db <<< "REVOKE CONNECT ON DATABASE $db FROM public;"
|
||||
sudo --login --user=postgres psql $db <<< "SELECT pg_terminate_backend (pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '$db' AND pid <> pg_backend_pid();"
|
||||
sudo --login --user=postgres dropdb $db
|
||||
}
|
||||
|
||||
# Dump a database
|
||||
#
|
||||
# usage: ynh_psql_dump_db database
|
||||
# | arg: database - the database name to dump (by default, $db_name)
|
||||
# | ret: the psqldump output
|
||||
#
|
||||
# example: ynh_psql_dump_db 'roundcube' > ./dump.sql
|
||||
#
|
||||
ynh_psql_dump_db() {
|
||||
local database="${1:-$db_name}"
|
||||
sudo --login --user=postgres pg_dump "$database"
|
||||
}
|
||||
|
||||
# Create a user
|
||||
#
|
||||
# [internal] ... handled by the core / "database resource"
|
||||
#
|
||||
# usage: ynh_psql_create_user user pwd
|
||||
# | arg: user - the user name to create
|
||||
# | arg: pwd - the password to identify user by
|
||||
#
|
||||
ynh_psql_create_user() {
|
||||
local user=$1
|
||||
local pwd=$2
|
||||
sudo --login --user=postgres psql <<< "CREATE USER $user WITH ENCRYPTED PASSWORD '$pwd'"
|
||||
}
|
||||
|
||||
# Check if a psql user exists
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# usage: ynh_psql_user_exists user
|
||||
# | arg: user= - the user for which to check existence
|
||||
# | exit: Return 1 if the user doesn't exist, 0 otherwise
|
||||
#
|
||||
ynh_psql_user_exists() {
|
||||
local user=$1
|
||||
sudo --login --user=postgres psql -tAc "SELECT rolname FROM pg_roles WHERE rolname='$user';" | grep --quiet "$user"
|
||||
}
|
||||
|
||||
# Check if a psql database exists
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# usage: ynh_psql_database_exists database
|
||||
# | arg: database - the database for which to check existence
|
||||
# | exit: Return 1 if the database doesn't exist, 0 otherwise
|
||||
#
|
||||
ynh_psql_database_exists() {
|
||||
local database=$1
|
||||
sudo --login --user=postgres psql -tAc "SELECT datname FROM pg_database WHERE datname='$database';" | grep --quiet "$database"
|
||||
}
|
||||
|
||||
# Drop a user
|
||||
#
|
||||
# [internal] ... handled by the core / "database resource"
|
||||
#
|
||||
# usage: ynh_psql_drop_user user
|
||||
# | arg: user - the user name to drop
|
||||
#
|
||||
ynh_psql_drop_user() {
|
||||
sudo --login --user=postgres psql <<< "DROP USER ${1};"
|
||||
}
|
37
helpers/helpers.v2.1.d/redis
Normal file
37
helpers/helpers.v2.1.d/redis
Normal file
|
@ -0,0 +1,37 @@
|
|||
#!/bin/bash
|
||||
|
||||
# get the first available redis database
|
||||
#
|
||||
# usage: ynh_redis_get_free_db
|
||||
# | returns: the database number to use
|
||||
ynh_redis_get_free_db() {
|
||||
local result max db
|
||||
result=$(redis-cli INFO keyspace)
|
||||
|
||||
# get the num
|
||||
max=$(cat /etc/redis/redis.conf | grep ^databases | grep -Eow "[0-9]+")
|
||||
|
||||
db=0
|
||||
# default Debian setting is 15 databases
|
||||
for i in $(seq 0 "$max"); do
|
||||
if ! echo "$result" | grep -q "db$i"; then
|
||||
db=$i
|
||||
break 1
|
||||
fi
|
||||
db=-1
|
||||
done
|
||||
|
||||
test "$db" -eq -1 && ynh_die "No available Redis databases..."
|
||||
|
||||
echo "$db"
|
||||
}
|
||||
|
||||
# Create a master password and set up global settings
|
||||
# Please always call this script in install and restore scripts
|
||||
#
|
||||
# usage: ynh_redis_remove_db database
|
||||
# | arg: database - the database to erase
|
||||
ynh_redis_remove_db() {
|
||||
local db=$1
|
||||
redis-cli -n "$db" flushdb
|
||||
}
|
246
helpers/helpers.v2.1.d/ruby
Normal file
246
helpers/helpers.v2.1.d/ruby
Normal file
|
@ -0,0 +1,246 @@
|
|||
#!/bin/bash
|
||||
|
||||
readonly RBENV_INSTALL_DIR="/opt/rbenv"
|
||||
|
||||
# RBENV_ROOT is the directory of rbenv, it needs to be loaded as a environment variable.
|
||||
export RBENV_ROOT="$RBENV_INSTALL_DIR"
|
||||
export rbenv_root="$RBENV_INSTALL_DIR"
|
||||
|
||||
_ynh_load_ruby_in_path_and_other_tweaks() {
|
||||
|
||||
# Get the absolute path of this version of Ruby
|
||||
ruby_dir="$RBENV_INSTALL_DIR/versions/$app/bin"
|
||||
|
||||
# Load the path of this version of ruby in $PATH
|
||||
if [[ :$PATH: != *":$ruby_dir"* ]]; then
|
||||
PATH="$ruby_dir:$PATH"
|
||||
fi
|
||||
|
||||
# Export PATH such that it's available through sudo -E / ynh_exec_as $app
|
||||
export PATH
|
||||
|
||||
# This is in full lowercase such that it gets replaced in templates
|
||||
path_with_ruby="$PATH"
|
||||
PATH_with_ruby="$PATH"
|
||||
|
||||
# Sets the local application-specific Ruby version
|
||||
pushd ${install_dir}
|
||||
$RBENV_INSTALL_DIR/bin/rbenv local $ruby_version
|
||||
popd
|
||||
}
|
||||
|
||||
# Install a specific version of Ruby using rbenv
|
||||
#
|
||||
# The installed version is defined by `$ruby_version` which should be defined as global prior to calling this helper
|
||||
#
|
||||
# usage: ynh_ruby_install
|
||||
#
|
||||
# The helper adds the appropriate, specific version of ruby to the `$PATH` variable (which
|
||||
# is preserved when calling ynh_exec_as_app). Also defines:
|
||||
# - `$path_with_ruby` to be used in the systemd config (`Environment="PATH=__PATH_WITH_RUBY__"`)
|
||||
# - `$ruby_dir`, the directory containing the specific version of ruby, which may be used in the systemd config too (e.g. `ExecStart=__RUBY_DIR__/ruby foo bar`)
|
||||
#
|
||||
# This helper also creates a /etc/profile.d/rbenv.sh that configures PATH environment for rbenv
|
||||
ynh_ruby_install() {
|
||||
|
||||
[[ -n "${ruby_version:-}" ]] || ynh_die "\$ruby_version should be defined prior to calling ynh_ruby_install"
|
||||
|
||||
# Load rbenv path in PATH
|
||||
local CLEAR_PATH="$RBENV_INSTALL_DIR/bin:$PATH"
|
||||
|
||||
# Remove /usr/local/bin in PATH in case of Ruby prior installation
|
||||
PATH=$(echo $CLEAR_PATH | sed 's@/usr/local/bin:@@')
|
||||
|
||||
# Move an existing Ruby binary, to avoid to block rbenv
|
||||
test -x /usr/bin/ruby && mv /usr/bin/ruby /usr/bin/ruby_rbenv
|
||||
|
||||
# Install or update rbenv
|
||||
mkdir -p $RBENV_INSTALL_DIR
|
||||
rbenv="$(command -v rbenv $RBENV_INSTALL_DIR/bin/rbenv | grep "$RBENV_INSTALL_DIR/bin/rbenv" | head -1)"
|
||||
if [ -n "$rbenv" ]; then
|
||||
pushd "${rbenv%/*/*}"
|
||||
if git remote -v 2> /dev/null | grep "https://github.com/rbenv/rbenv.git"; then
|
||||
echo "Updating rbenv..."
|
||||
git pull -q --tags origin master
|
||||
_ynh_ruby_try_bash_extension
|
||||
else
|
||||
echo "Reinstalling rbenv..."
|
||||
cd ..
|
||||
ynh_safe_rm $RBENV_INSTALL_DIR
|
||||
mkdir -p $RBENV_INSTALL_DIR
|
||||
cd $RBENV_INSTALL_DIR
|
||||
git init -q
|
||||
git remote add -f -t master origin https://github.com/rbenv/rbenv.git > /dev/null 2>&1
|
||||
git checkout -q -b master origin/master
|
||||
_ynh_ruby_try_bash_extension
|
||||
rbenv=$RBENV_INSTALL_DIR/bin/rbenv
|
||||
fi
|
||||
popd
|
||||
else
|
||||
echo "Installing rbenv..."
|
||||
pushd $RBENV_INSTALL_DIR
|
||||
git init -q
|
||||
git remote add -f -t master origin https://github.com/rbenv/rbenv.git > /dev/null 2>&1
|
||||
git checkout -q -b master origin/master
|
||||
_ynh_ruby_try_bash_extension
|
||||
rbenv=$RBENV_INSTALL_DIR/bin/rbenv
|
||||
popd
|
||||
fi
|
||||
|
||||
mkdir -p "${RBENV_INSTALL_DIR}/plugins"
|
||||
|
||||
ruby_build="$(command -v "$RBENV_INSTALL_DIR"/plugins/*/bin/rbenv-install rbenv-install | head -1)"
|
||||
if [ -n "$ruby_build" ]; then
|
||||
pushd "${ruby_build%/*/*}"
|
||||
if git remote -v 2> /dev/null | grep "https://github.com/rbenv/ruby-build.git"; then
|
||||
echo "Updating ruby-build..."
|
||||
git pull -q origin master
|
||||
fi
|
||||
popd
|
||||
else
|
||||
echo "Installing ruby-build..."
|
||||
git clone -q https://github.com/rbenv/ruby-build.git "${RBENV_INSTALL_DIR}/plugins/ruby-build"
|
||||
fi
|
||||
|
||||
rbenv_alias="$(command -v "$RBENV_INSTALL_DIR"/plugins/*/bin/rbenv-alias rbenv-alias | head -1)"
|
||||
if [ -n "$rbenv_alias" ]; then
|
||||
pushd "${rbenv_alias%/*/*}"
|
||||
if git remote -v 2> /dev/null | grep "https://github.com/tpope/rbenv-aliases.git"; then
|
||||
echo "Updating rbenv-aliases..."
|
||||
git pull -q origin master
|
||||
fi
|
||||
popd
|
||||
else
|
||||
echo "Installing rbenv-aliases..."
|
||||
git clone -q https://github.com/tpope/rbenv-aliases.git "${RBENV_INSTALL_DIR}/plugins/rbenv-aliase"
|
||||
fi
|
||||
|
||||
rbenv_latest="$(command -v "$RBENV_INSTALL_DIR"/plugins/*/bin/rbenv-latest rbenv-latest | head -1)"
|
||||
if [ -n "$rbenv_latest" ]; then
|
||||
pushd "${rbenv_latest%/*/*}"
|
||||
if git remote -v 2> /dev/null | grep "https://github.com/momo-lab/xxenv-latest.git"; then
|
||||
echo "Updating xxenv-latest..."
|
||||
git pull -q origin master
|
||||
fi
|
||||
popd
|
||||
else
|
||||
echo "Installing xxenv-latest..."
|
||||
git clone -q https://github.com/momo-lab/xxenv-latest.git "${RBENV_INSTALL_DIR}/plugins/xxenv-latest"
|
||||
fi
|
||||
|
||||
# Enable caching
|
||||
mkdir -p "${RBENV_INSTALL_DIR}/cache"
|
||||
|
||||
# Create shims directory if needed
|
||||
mkdir -p "${RBENV_INSTALL_DIR}/shims"
|
||||
|
||||
# Restore /usr/local/bin in PATH
|
||||
PATH=$CLEAR_PATH
|
||||
|
||||
# And replace the old Ruby binary
|
||||
test -x /usr/bin/ruby_rbenv && mv /usr/bin/ruby_rbenv /usr/bin/ruby
|
||||
|
||||
# Install the requested version of Ruby
|
||||
local final_ruby_version=$(rbenv latest --print $ruby_version)
|
||||
if ! [ -n "$final_ruby_version" ]; then
|
||||
final_ruby_version=$ruby_version
|
||||
fi
|
||||
echo "Installing Ruby $final_ruby_version"
|
||||
RUBY_CONFIGURE_OPTS="--disable-install-doc --with-jemalloc" MAKE_OPTS="-j2" rbenv install --skip-existing $final_ruby_version > /dev/null 2>&1
|
||||
|
||||
# Store ruby_version into the config of this app
|
||||
ynh_app_setting_set --key=ruby_version --value=$final_ruby_version
|
||||
ruby_version=$final_ruby_version
|
||||
|
||||
# Remove app virtualenv
|
||||
if rbenv alias --list | grep --quiet "$app "; then
|
||||
rbenv alias $app --remove
|
||||
fi
|
||||
|
||||
# Create app virtualenv
|
||||
rbenv alias $app $final_ruby_version
|
||||
|
||||
# Cleanup Ruby versions
|
||||
_ynh_ruby_cleanup
|
||||
|
||||
# Set environment for Ruby users
|
||||
echo "#rbenv
|
||||
export RBENV_ROOT=$RBENV_INSTALL_DIR
|
||||
export PATH=\"$RBENV_INSTALL_DIR/bin:$PATH\"
|
||||
eval \"\$(rbenv init -)\"
|
||||
#rbenv" > /etc/profile.d/rbenv.sh
|
||||
|
||||
# Load the environment
|
||||
eval "$(rbenv init -)"
|
||||
|
||||
_ynh_load_ruby_in_path_and_other_tweaks
|
||||
}
|
||||
|
||||
# Remove the version of Ruby used by the app.
|
||||
#
|
||||
# This helper will also cleanup unused Ruby versions
|
||||
#
|
||||
# usage: ynh_ruby_remove
|
||||
ynh_ruby_remove() {
|
||||
|
||||
[[ -n "${ruby_version:-}" ]] || ynh_die "\$ruby_version should be defined prior to calling ynh_ruby_remove"
|
||||
|
||||
# Load rbenv path in PATH
|
||||
local CLEAR_PATH="$RBENV_INSTALL_DIR/bin:$PATH"
|
||||
|
||||
# Remove /usr/local/bin in PATH in case of Ruby prior installation
|
||||
PATH=$(echo $CLEAR_PATH | sed 's@/usr/local/bin:@@')
|
||||
|
||||
rbenv alias $app --remove
|
||||
|
||||
# Remove the line for this app
|
||||
ynh_app_setting_delete --key=ruby_version
|
||||
|
||||
# Cleanup Ruby versions
|
||||
_ynh_ruby_cleanup
|
||||
}
|
||||
|
||||
# Remove no more needed versions of Ruby used by the app.
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# This helper will check what Ruby version are no more required,
|
||||
# and uninstall them
|
||||
# If no app uses Ruby, rbenv will be also removed.
|
||||
_ynh_ruby_cleanup() {
|
||||
|
||||
# List required Ruby versions
|
||||
local installed_apps=$(yunohost app list | grep -oP 'id: \K.*$')
|
||||
local required_ruby_versions=""
|
||||
for installed_app in $installed_apps; do
|
||||
local installed_app_ruby_version=$(ynh_app_setting_get --app=$installed_app --key="ruby_version")
|
||||
if [[ -n "$installed_app_ruby_version" ]]; then
|
||||
required_ruby_versions="${installed_app_ruby_version}\n${required_ruby_versions}"
|
||||
fi
|
||||
done
|
||||
|
||||
# Remove no more needed Ruby versions
|
||||
local installed_ruby_versions=$(rbenv versions --bare --skip-aliases | grep -Ev '/')
|
||||
for installed_ruby_version in $installed_ruby_versions; do
|
||||
if ! echo ${required_ruby_versions} | grep -q "${installed_ruby_version}"; then
|
||||
echo "Removing Ruby-$installed_ruby_version"
|
||||
$RBENV_INSTALL_DIR/bin/rbenv uninstall --force $installed_ruby_version
|
||||
fi
|
||||
done
|
||||
|
||||
# If none Ruby version is required
|
||||
if [[ -z "$required_ruby_versions" ]]; then
|
||||
# Remove rbenv environment configuration
|
||||
echo "Removing rbenv"
|
||||
ynh_safe_rm "$RBENV_INSTALL_DIR"
|
||||
ynh_safe_rm "/etc/profile.d/rbenv.sh"
|
||||
fi
|
||||
}
|
||||
|
||||
_ynh_ruby_try_bash_extension() {
|
||||
if [ -x src/configure ]; then
|
||||
src/configure && make -C src 2>&1 || {
|
||||
ynh_print_info "Optional bash extension failed to build, but things will still work normally."
|
||||
}
|
||||
fi
|
||||
}
|
135
helpers/helpers.v2.1.d/setting
Normal file
135
helpers/helpers.v2.1.d/setting
Normal file
|
@ -0,0 +1,135 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Get an application setting
|
||||
#
|
||||
# usage: ynh_app_setting_get --key=key
|
||||
# | arg: --app= - the application id (global $app by default)
|
||||
# | arg: --key= - the setting to get
|
||||
ynh_app_setting_get() {
|
||||
# ============ Argument parsing =============
|
||||
local _globalapp=${app-:}
|
||||
local -A args_array=([a]=app= [k]=key=)
|
||||
local app
|
||||
local key
|
||||
ynh_handle_getopts_args "$@"
|
||||
app="${app:-$_globalapp}"
|
||||
# ===========================================
|
||||
|
||||
ynh_app_setting "get" "$app" "$key"
|
||||
}
|
||||
|
||||
# Set an application setting
|
||||
#
|
||||
# usage: ynh_app_setting_set --key=key --value=value
|
||||
# | arg: --app= - the application id (global $app by default)
|
||||
# | arg: --key= - the setting name to set
|
||||
# | arg: --value= - the setting value to set
|
||||
ynh_app_setting_set() {
|
||||
# ============ Argument parsing =============
|
||||
local _globalapp=${app-:}
|
||||
local -A args_array=([a]=app= [k]=key= [v]=value=)
|
||||
local app
|
||||
local key
|
||||
local value
|
||||
ynh_handle_getopts_args "$@"
|
||||
app="${app:-$_globalapp}"
|
||||
# ===========================================
|
||||
|
||||
ynh_app_setting "set" "$app" "$key" "$value"
|
||||
}
|
||||
|
||||
# Set an application setting but only if the "$key" variable ain't set yet
|
||||
#
|
||||
# Note that it doesn't just define the setting but ALSO define the $foobar variable
|
||||
#
|
||||
# Hence it's meant as a replacement for this legacy overly complex syntax:
|
||||
#
|
||||
# if [ -z "${foo:-}" ]
|
||||
# then
|
||||
# foo="bar"
|
||||
# ynh_app_setting_set --key="foo" --value="$foo"
|
||||
# fi
|
||||
#
|
||||
# usage: ynh_app_setting_set_default --key=key --value=value
|
||||
# | arg: --app= - the application id (global $app by default)
|
||||
# | arg: --key= - the setting name to set
|
||||
# | arg: --value= - the default setting value to set
|
||||
ynh_app_setting_set_default() {
|
||||
# ============ Argument parsing =============
|
||||
local _globalapp=${app-:}
|
||||
local -A args_array=([a]=app= [k]=key= [v]=value=)
|
||||
local app
|
||||
local key
|
||||
local value
|
||||
ynh_handle_getopts_args "$@"
|
||||
app="${app:-$_globalapp}"
|
||||
# ===========================================
|
||||
|
||||
if [ -z "${!key:-}" ]; then
|
||||
eval $key=\$value
|
||||
ynh_app_setting "set" "$app" "$key" "$value"
|
||||
fi
|
||||
}
|
||||
|
||||
# Delete an application setting
|
||||
#
|
||||
# usage: ynh_app_setting_delete --key=key
|
||||
# | arg: --app= - the application id (global $app by default)
|
||||
# | arg: --key= - the setting to delete
|
||||
ynh_app_setting_delete() {
|
||||
# ============ Argument parsing =============
|
||||
local _globalapp=${app-:}
|
||||
local -A args_array=([a]=app= [k]=key=)
|
||||
local app
|
||||
local key
|
||||
ynh_handle_getopts_args "$@"
|
||||
app="${app:-$_globalapp}"
|
||||
# ===========================================
|
||||
|
||||
ynh_app_setting "delete" "$app" "$key"
|
||||
}
|
||||
|
||||
# Small "hard-coded" interface to avoid calling "yunohost app" directly each
|
||||
# time dealing with a setting is needed (which may be so slow on ARM boards)
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
ynh_app_setting() {
|
||||
# Trick to only re-enable debugging if it was set before
|
||||
local xtrace_enable=$(set +o | grep xtrace)
|
||||
set +o xtrace # set +x
|
||||
ACTION="$1" APP="$2" KEY="$3" VALUE="${4:-}" python3 - << EOF
|
||||
import os, yaml, sys
|
||||
app, action = os.environ['APP'], os.environ['ACTION'].lower()
|
||||
key, value = os.environ['KEY'], os.environ.get('VALUE', None)
|
||||
setting_file = "/etc/yunohost/apps/%s/settings.yml" % app
|
||||
assert os.path.exists(setting_file), "Setting file %s does not exists ?" % setting_file
|
||||
with open(setting_file) as f:
|
||||
settings = yaml.safe_load(f)
|
||||
if action == "get":
|
||||
if key in settings:
|
||||
print(settings[key])
|
||||
else:
|
||||
if action == "delete":
|
||||
if key in settings:
|
||||
del settings[key]
|
||||
elif action == "set":
|
||||
settings[key] = value
|
||||
else:
|
||||
raise ValueError("action should either be get, set or delete")
|
||||
with open(setting_file, "w") as f:
|
||||
yaml.safe_dump(settings, f, default_flow_style=False)
|
||||
EOF
|
||||
eval "$xtrace_enable"
|
||||
}
|
||||
|
||||
# Legacy: auto-convert phpversion to php_version (for consistency with nodejs_version, ruby_version, ...)
|
||||
# This has to be here and not in the "php" code file because ynh_app_setting_set/delete need to be defined @_@
|
||||
if [[ -n "${app:-}" ]] && [[ -n "${phpversion:-}" ]]; then
|
||||
if [[ -z "${php_version:-}" ]]; then
|
||||
php_version=$phpversion
|
||||
ynh_app_setting_set --key=php_version --value=$php_version
|
||||
fi
|
||||
ynh_app_setting_delete --key=phpversion
|
||||
unset phpversion
|
||||
fi
|
253
helpers/helpers.v2.1.d/sources
Normal file
253
helpers/helpers.v2.1.d/sources
Normal file
|
@ -0,0 +1,253 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Download, check integrity, uncompress and patch upstream sources
|
||||
#
|
||||
# usage: ynh_setup_source --dest_dir=dest_dir [--source_id=source_id] [--keep="file1 file2"] [--full_replace]
|
||||
# | arg: --dest_dir= - Directory where to setup sources
|
||||
# | arg: --source_id= - Name of the source, defaults to `main` (when the sources resource exists in manifest.toml) or (legacy) `app` otherwise
|
||||
# | arg: --keep= - Space-separated list of files/folders that will be backup/restored in $dest_dir, such as a config file you don't want to overwrite. For example 'conf.json secrets.json logs' (no trailing `/` for folders)
|
||||
# | arg: --full_replace= - Remove previous sources before installing new sources (can be 1 or 0, default to 0)
|
||||
#
|
||||
# This helper will read infos from the 'sources' resources in the `manifest.toml` of the app
|
||||
# and expect a structure like:
|
||||
#
|
||||
# ```toml
|
||||
# [resources.sources]
|
||||
# [resources.sources.main]
|
||||
# url = "https://some.address.to/download/the/app/archive"
|
||||
# sha256 = "0123456789abcdef" # The sha256 sum of the asset obtained from the URL
|
||||
# ```
|
||||
#
|
||||
# (See also the resources documentation which may be more complete?)
|
||||
#
|
||||
# ##### Optional flags in the 'sources' resource
|
||||
#
|
||||
# ```text
|
||||
# format = "tar.gz"/xz/bz2/tar # automatically guessed from the extension of the URL, but can be set explicitly. Will use `tar` to extract
|
||||
# "zip" # automatically guessed from the extension of the URL, but can be set explicitly. Will use `unzip` to extract
|
||||
# "docker" # useful to extract files from an already-built docker image (instead of rebuilding them locally). Will use `docker-image-extract` to extract
|
||||
# "whatever" # an arbitrary value, not really meaningful except to imply that the file won't be extracted
|
||||
#
|
||||
# in_subdir = true # default, there's an intermediate subdir in the archive before accessing the actual files
|
||||
# false # sources are directly in the archive root
|
||||
# n # (special cases) an integer representing a number of subdirs levels to get rid of
|
||||
#
|
||||
# extract = true # default if file is indeed an archive such as .zip, .tar.gz, .tar.bz2, ...
|
||||
# = false # default if file 'format' is not set and the file is not to be extracted because it is not an archive but a script or binary or whatever asset.
|
||||
# # in which case the file will only be `mv`ed to the location possibly renamed using the `rename` value
|
||||
#
|
||||
# rename = "whatever_your_want" # to be used for convenience when `extract` is false and the default name of the file is not practical
|
||||
# platform = "linux/amd64" # (defaults to "linux/$YNH_ARCH") to be used in conjonction with `format = "docker"` to specify which architecture to extract for
|
||||
# ```
|
||||
#
|
||||
# You may also define assets url and checksum per-architectures such as:
|
||||
# ```toml
|
||||
# [resources.sources]
|
||||
# [resources.sources.main]
|
||||
# amd64.url = "https://some.address.to/download/the/app/archive/when/amd64"
|
||||
# amd64.sha256 = "0123456789abcdef"
|
||||
# armhf.url = "https://some.address.to/download/the/app/archive/when/armhf"
|
||||
# armhf.sha256 = "fedcba9876543210"
|
||||
# ```
|
||||
#
|
||||
# In which case `ynh_setup_source --dest_dir="$install_dir"` will automatically pick the appropriate source depending on the arch
|
||||
#
|
||||
# The helper will:
|
||||
# - Download the specific URL if there is no local archive
|
||||
# - Check the integrity with the specific sha256 sum
|
||||
# - Uncompress the archive to `$dest_dir`.
|
||||
# - If `in_subdir` is true, the first level directory of the archive will be removed.
|
||||
# - If `in_subdir` is a numeric value, the N first level directories will be removed.
|
||||
# - Patches named `patches/${src_id}/*.patch` will be applied to `$dest_dir`
|
||||
# - Apply sane default permissions (see _ynh_apply_default_permissions)
|
||||
ynh_setup_source() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([d]=dest_dir= [s]=source_id= [k]=keep= [r]=full_replace)
|
||||
local dest_dir
|
||||
local source_id
|
||||
local keep
|
||||
local full_replace
|
||||
ynh_handle_getopts_args "$@"
|
||||
keep="${keep:-}"
|
||||
full_replace="${full_replace:-0}"
|
||||
source_id="${source_id:-main}"
|
||||
# ===========================================
|
||||
|
||||
local sources_json=$(ynh_read_manifest "resources.sources[\"$source_id\"]")
|
||||
if jq -re ".url" <<< "$sources_json"; then
|
||||
local arch_prefix=""
|
||||
else
|
||||
local arch_prefix=".$YNH_ARCH"
|
||||
fi
|
||||
|
||||
local src_url="$(jq -r "$arch_prefix.url" <<< "$sources_json" | sed 's/^null$//')"
|
||||
local src_sum="$(jq -r "$arch_prefix.sha256" <<< "$sources_json" | sed 's/^null$//')"
|
||||
local src_format="$(jq -r ".format" <<< "$sources_json" | sed 's/^null$//')"
|
||||
local src_in_subdir="$(jq -r ".in_subdir" <<< "$sources_json" | sed 's/^null$//')"
|
||||
src_in_subdir=${src_in_subdir:-true}
|
||||
local src_extract="$(jq -r ".extract" <<< "$sources_json" | sed 's/^null$//')"
|
||||
local src_platform="$(jq -r ".platform" <<< "$sources_json" | sed 's/^null$//')"
|
||||
local src_rename="$(jq -r ".rename" <<< "$sources_json" | sed 's/^null$//')"
|
||||
|
||||
[[ -n "$src_url" ]] || ynh_die "No URL defined for source $source_id$arch_prefix ?"
|
||||
[[ -n "$src_sum" ]] || ynh_die "No sha256 sum defined for source $source_id$arch_prefix ?"
|
||||
|
||||
if [[ -z "$src_format" ]]; then
|
||||
if [[ "$src_url" =~ ^.*\.zip$ ]] || [[ "$src_url" =~ ^.*/zipball/.*$ ]]; then
|
||||
src_format="zip"
|
||||
elif [[ "$src_url" =~ ^.*\.tar\.gz$ ]] || [[ "$src_url" =~ ^.*\.tgz$ ]] || [[ "$src_url" =~ ^.*/tar\.gz/.*$ ]] || [[ "$src_url" =~ ^.*/tarball/.*$ ]]; then
|
||||
src_format="tar.gz"
|
||||
elif [[ "$src_url" =~ ^.*\.tar\.xz$ ]]; then
|
||||
src_format="tar.xz"
|
||||
elif [[ "$src_url" =~ ^.*\.tar\.bz2$ ]]; then
|
||||
src_format="tar.bz2"
|
||||
elif [[ "$src_url" =~ ^.*\.tar$ ]]; then
|
||||
src_format="tar"
|
||||
elif [[ -z "$src_extract" ]]; then
|
||||
src_extract="false"
|
||||
fi
|
||||
fi
|
||||
|
||||
src_format=${src_format:-tar.gz}
|
||||
src_format=$(echo "$src_format" | tr '[:upper:]' '[:lower:]')
|
||||
src_extract=${src_extract:-true}
|
||||
|
||||
if [[ "$src_extract" != "true" ]] && [[ "$src_extract" != "false" ]]; then
|
||||
ynh_die "For source $source_id, expected either 'true' or 'false' for the extract parameter"
|
||||
fi
|
||||
|
||||
# Gotta use this trick with 'dirname' because source_id may contain slashes x_x
|
||||
mkdir -p $(dirname /var/cache/yunohost/download/${YNH_APP_ID}/${source_id})
|
||||
src_filename="/var/cache/yunohost/download/${YNH_APP_ID}/${source_id}"
|
||||
|
||||
if [ "$src_format" = "docker" ]; then
|
||||
src_platform="${src_platform:-"linux/$YNH_ARCH"}"
|
||||
else
|
||||
[ -n "$src_url" ] || ynh_die "Couldn't parse SOURCE_URL from $src_file_path ?"
|
||||
|
||||
# If the file was prefetched but somehow doesn't match the sum, rm and redownload it
|
||||
if [ -e "$src_filename" ] && ! echo "${src_sum} ${src_filename}" | sha256sum --check --status; then
|
||||
rm -f "$src_filename"
|
||||
fi
|
||||
|
||||
# Only redownload the file if it wasnt prefetched
|
||||
if [ ! -e "$src_filename" ]; then
|
||||
# NB. we have to declare the var as local first,
|
||||
# otherwise 'local foo=$(false) || echo 'pwet'" does'nt work
|
||||
# because local always return 0 ...
|
||||
local out
|
||||
# Timeout option is here to enforce the timeout on dns query and tcp connect (c.f. man wget)
|
||||
out=$(wget --tries 3 --no-dns-cache --timeout 900 --no-verbose --output-document=$src_filename $src_url 2>&1) \
|
||||
|| ynh_die "$out"
|
||||
fi
|
||||
|
||||
# Check the control sum
|
||||
if ! echo "${src_sum} ${src_filename}" | sha256sum --check --status; then
|
||||
local actual_sum="$(sha256sum ${src_filename} | cut --delimiter=' ' --fields=1)"
|
||||
local actual_size="$(du -hs ${src_filename} | cut --fields=1)"
|
||||
rm -f ${src_filename}
|
||||
ynh_die "Corrupt source for ${src_url}: Expected sha256sum to be ${src_sum} but got ${actual_sum} (size: ${actual_size})."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Keep files to be backup/restored at the end of the helper
|
||||
# Assuming $dest_dir already exists
|
||||
rm -rf /var/cache/yunohost/files_to_keep_during_setup_source/
|
||||
if [ -n "$keep" ] && [ -e "$dest_dir" ]; then
|
||||
local keep_dir=/var/cache/yunohost/files_to_keep_during_setup_source/${YNH_APP_ID}
|
||||
mkdir -p $keep_dir
|
||||
local stuff_to_keep
|
||||
for stuff_to_keep in $keep; do
|
||||
if [ -e "$dest_dir/$stuff_to_keep" ]; then
|
||||
mkdir --parents "$(dirname "$keep_dir/$stuff_to_keep")"
|
||||
cp --archive "$dest_dir/$stuff_to_keep" "$keep_dir/$stuff_to_keep"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "$full_replace" -eq 1 ]; then
|
||||
ynh_safe_rm "$dest_dir"
|
||||
fi
|
||||
|
||||
# Extract source into the app dir
|
||||
mkdir --parents "$dest_dir"
|
||||
|
||||
if [[ "$src_extract" == "false" ]]; then
|
||||
if [[ -z "$src_rename" ]]; then
|
||||
mv $src_filename $dest_dir
|
||||
else
|
||||
mv $src_filename $dest_dir/$src_rename
|
||||
fi
|
||||
elif [[ "$src_format" == "docker" ]]; then
|
||||
"$YNH_HELPERS_DIR/vendor/docker-image-extract/docker-image-extract" -p $src_platform -o $dest_dir $src_url 2>&1
|
||||
elif [[ "$src_format" == "zip" ]]; then
|
||||
# Zip format
|
||||
# Using of a temp directory, because unzip doesn't manage --strip-components
|
||||
if $src_in_subdir; then
|
||||
local tmp_dir=$(mktemp --directory)
|
||||
unzip -quo $src_filename -d "$tmp_dir"
|
||||
cp --archive $tmp_dir/*/. "$dest_dir"
|
||||
ynh_safe_rm "$tmp_dir"
|
||||
else
|
||||
unzip -quo $src_filename -d "$dest_dir"
|
||||
fi
|
||||
ynh_safe_rm "$src_filename"
|
||||
else
|
||||
local strip=""
|
||||
if [ "$src_in_subdir" != "false" ]; then
|
||||
if [ "$src_in_subdir" == "true" ]; then
|
||||
local sub_dirs=1
|
||||
else
|
||||
local sub_dirs="$src_in_subdir"
|
||||
fi
|
||||
strip="--strip-components $sub_dirs"
|
||||
fi
|
||||
if [[ "$src_format" =~ ^tar.gz|tar.bz2|tar.xz|tar$ ]]; then
|
||||
tar --extract --file=$src_filename --directory="$dest_dir" $strip
|
||||
else
|
||||
ynh_die "Archive format unrecognized."
|
||||
fi
|
||||
ynh_safe_rm "$src_filename"
|
||||
fi
|
||||
|
||||
# Apply patches
|
||||
if [ -d "$YNH_APP_BASEDIR/patches/" ]; then
|
||||
local patches_folder=$(realpath "$YNH_APP_BASEDIR/patches/$source_id")
|
||||
pushd "$dest_dir"
|
||||
for patchfile in "$patches_folder/"*.patch; do
|
||||
echo "Applying $patchfile"
|
||||
if ! patch --strip=1 < "$patchfile"; then
|
||||
if ynh_in_ci_tests; then
|
||||
ynh_die "Patch $patchfile failed to apply!"
|
||||
else
|
||||
ynh_print_warn "Warn your packagers /!\\ Patch $patchfile failed to apply"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
popd
|
||||
fi
|
||||
|
||||
# Keep files to be backup/restored at the end of the helper
|
||||
# Assuming $dest_dir already exists
|
||||
if [ -n "$keep" ]; then
|
||||
local keep_dir=/var/cache/yunohost/files_to_keep_during_setup_source/${YNH_APP_ID}
|
||||
local stuff_to_keep
|
||||
for stuff_to_keep in $keep; do
|
||||
if [ -e "$keep_dir/$stuff_to_keep" ]; then
|
||||
mkdir --parents "$(dirname "$dest_dir/$stuff_to_keep")"
|
||||
|
||||
# We add "--no-target-directory" (short option is -T) to handle the special case
|
||||
# when we "keep" a folder, but then the new setup already contains the same dir (but possibly empty)
|
||||
# in which case a regular "cp" will create a copy of the directory inside the directory ...
|
||||
# resulting in something like /var/www/$app/data/data instead of /var/www/$app/data
|
||||
# cf https://unix.stackexchange.com/q/94831 for a more elaborate explanation on the option
|
||||
cp --archive --no-target-directory "$keep_dir/$stuff_to_keep" "$dest_dir/$stuff_to_keep"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
rm -rf /var/cache/yunohost/files_to_keep_during_setup_source/
|
||||
|
||||
if [ -n "${install_dir:-}" ] && [ "$dest_dir" == "$install_dir" ]; then
|
||||
_ynh_apply_default_permissions $dest_dir
|
||||
fi
|
||||
}
|
129
helpers/helpers.v2.1.d/string
Normal file
129
helpers/helpers.v2.1.d/string
Normal file
|
@ -0,0 +1,129 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Generate a random string
|
||||
#
|
||||
# usage: ynh_string_random [--length=string_length]
|
||||
# | arg: --length= - the string length to generate (default: 24)
|
||||
# | arg: --filter= - the kind of characters accepted in the output (default: 'A-Za-z0-9')
|
||||
# | ret: the generated string
|
||||
#
|
||||
# example: pwd=$(ynh_string_random --length=8)
|
||||
ynh_string_random() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([l]=length= [f]=filter=)
|
||||
local length
|
||||
local filter
|
||||
ynh_handle_getopts_args "$@"
|
||||
length=${length:-24}
|
||||
filter=${filter:-'A-Za-z0-9'}
|
||||
# ===========================================
|
||||
|
||||
dd if=/dev/urandom bs=1 count=1000 2> /dev/null \
|
||||
| tr --complement --delete "$filter" \
|
||||
| sed --quiet 's/\(.\{'"$length"'\}\).*/\1/p'
|
||||
}
|
||||
|
||||
# Substitute/replace a string (or expression) by another in a file
|
||||
#
|
||||
# usage: ynh_replace --match=match --replace=replace --file=file
|
||||
# | arg: --match= - String to be searched and replaced in the file
|
||||
# | arg: --replace= - String that will replace matches
|
||||
# | arg: --file= - File in which the string will be replaced.
|
||||
#
|
||||
# As this helper is based on sed command, regular expressions and references to
|
||||
# sub-expressions can be used (see sed manual page for more information)
|
||||
ynh_replace() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([m]=match= [r]=replace= [f]=file=)
|
||||
local match
|
||||
local replace
|
||||
local file
|
||||
ynh_handle_getopts_args "$@"
|
||||
# ===========================================
|
||||
set +o xtrace # set +x
|
||||
|
||||
local delimit=$'\001'
|
||||
# Escape the delimiter if it's in the string.
|
||||
match=${match//${delimit}/"\\${delimit}"}
|
||||
replace=${replace//${delimit}/"\\${delimit}"}
|
||||
|
||||
set -o xtrace # set -x
|
||||
sed --in-place "s${delimit}${match}${delimit}${replace}${delimit}g" "$file"
|
||||
}
|
||||
|
||||
# Substitute/replace a regex in a file
|
||||
#
|
||||
# usage: ynh_replace_regex --match=match --replace=replace --file=file
|
||||
# | arg: --match= - String to be searched and replaced in the file
|
||||
# | arg: --replace= - String that will replace matches
|
||||
# | arg: --file= - File in which the string will be replaced.
|
||||
#
|
||||
# This helper will use ynh_replace, but as you can use special
|
||||
# characters, you can't use some regular expressions and sub-expressions.
|
||||
ynh_replace_regex() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([m]=match= [r]=replace= [f]=file=)
|
||||
local match
|
||||
local replace
|
||||
local file
|
||||
ynh_handle_getopts_args "$@"
|
||||
# ===========================================
|
||||
|
||||
# Escape any backslash to preserve them as simple backslash.
|
||||
match=${match//\\/"\\\\"}
|
||||
replace=${replace//\\/"\\\\"}
|
||||
|
||||
# Escape the & character, who has a special function in sed.
|
||||
match=${match//&/"\&"}
|
||||
replace=${replace//&/"\&"}
|
||||
|
||||
ynh_replace --match="$match" --replace="$replace" --file="$file"
|
||||
}
|
||||
|
||||
# Sanitize a string intended to be the name of a database
|
||||
#
|
||||
# [packagingv1]
|
||||
#
|
||||
# usage: ynh_sanitize_dbid --db_name=name
|
||||
# | arg: --db_name= - name to correct/sanitize
|
||||
# | ret: the corrected name
|
||||
#
|
||||
# example: dbname=$(ynh_sanitize_dbid $app)
|
||||
#
|
||||
# Underscorify the string (replace - and . by _)
|
||||
ynh_sanitize_dbid() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([n]=db_name=)
|
||||
local db_name
|
||||
ynh_handle_getopts_args "$@"
|
||||
# ===========================================
|
||||
|
||||
# We should avoid having - and . in the name of databases. They are replaced by _
|
||||
echo ${db_name//[-.]/_}
|
||||
}
|
||||
|
||||
# Normalize the url path syntax
|
||||
#
|
||||
# Handle the slash at the beginning of path and its absence at ending
|
||||
# Return a normalized url path
|
||||
#
|
||||
# examples:
|
||||
# url_path=$(ynh_normalize_url_path $url_path)
|
||||
# ynh_normalize_url_path example # -> /example
|
||||
# ynh_normalize_url_path /example # -> /example
|
||||
# ynh_normalize_url_path /example/ # -> /example
|
||||
# ynh_normalize_url_path / # -> /
|
||||
#
|
||||
# usage: ynh_normalize_url_path path_to_normalize
|
||||
ynh_normalize_url_path() {
|
||||
local path_url=$1
|
||||
|
||||
test -n "$path_url" || ynh_die "ynh_normalize_url_path expect a URL path as first argument and received nothing."
|
||||
if [ "${path_url:0:1}" != "/" ]; then # If the first character is not a /
|
||||
path_url="/$path_url" # Add / at begin of path variable
|
||||
fi
|
||||
if [ "${path_url:${#path_url}-1}" == "/" ] && [ ${#path_url} -gt 1 ]; then # If the last character is a / and that not the only character.
|
||||
path_url="${path_url:0:${#path_url}-1}" # Delete the last character
|
||||
fi
|
||||
echo $path_url
|
||||
}
|
178
helpers/helpers.v2.1.d/systemd
Normal file
178
helpers/helpers.v2.1.d/systemd
Normal file
|
@ -0,0 +1,178 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Create a dedicated systemd config
|
||||
#
|
||||
# usage: ynh_config_add_systemd [--service=service] [--template=template]
|
||||
# | arg: --service= - Service name (optionnal, `$app` by default)
|
||||
# | arg: --template= - Name of template file (optionnal, this is 'systemd' by default, meaning `../conf/systemd.service` will be used as template)
|
||||
#
|
||||
# This will use the template `../conf/<templatename>.service`.
|
||||
#
|
||||
# See the documentation of `ynh_config_add` for a description of the template
|
||||
# format and how placeholders are replaced with actual variables.
|
||||
ynh_config_add_systemd() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([s]=service= [t]=template=)
|
||||
local service
|
||||
local template
|
||||
ynh_handle_getopts_args "$@"
|
||||
service="${service:-$app}"
|
||||
template="${template:-systemd.service}"
|
||||
# ===========================================
|
||||
|
||||
ynh_config_add --template="$template" --destination="/etc/systemd/system/$service.service"
|
||||
|
||||
systemctl enable $service --quiet
|
||||
systemctl daemon-reload
|
||||
}
|
||||
|
||||
# Remove the dedicated systemd config
|
||||
#
|
||||
# usage: ynh_config_remove_systemd service
|
||||
# | arg: service - Service name (optionnal, $app by default)
|
||||
ynh_config_remove_systemd() {
|
||||
local service="${1:-$app}"
|
||||
if [ -e "/etc/systemd/system/$service.service" ]; then
|
||||
ynh_systemctl --service=$service --action=stop
|
||||
systemctl disable $service --quiet
|
||||
ynh_safe_rm "/etc/systemd/system/$service.service"
|
||||
systemctl daemon-reload
|
||||
fi
|
||||
}
|
||||
|
||||
# Start (or other actions) a service, print a log in case of failure and optionnaly wait until the service is completely started
|
||||
#
|
||||
# usage: ynh_systemctl [--service=service] [--action=action] [ [--wait_until="line to match"] [--log_path=log_path] [--timeout=300] [--length=20] ]
|
||||
# | arg: --service= - Name of the service to start. Default : `$app`
|
||||
# | arg: --action= - Action to perform with systemctl. Default: start
|
||||
# | arg: --wait_until= - The pattern to find in the log to attest the service is effectively fully started.
|
||||
# | arg: --log_path= - Log file - Path to the log file. Default : `/var/log/$app/$app.log`
|
||||
# | arg: --timeout= - Timeout - The maximum time to wait before ending the watching. Default : 60 seconds.
|
||||
# | arg: --length= - Length of the error log displayed for debugging : Default : 20
|
||||
ynh_systemctl() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([n]=service= [a]=action= [w]=wait_until= [p]=log_path= [t]=timeout= [e]=length=)
|
||||
local service
|
||||
local action
|
||||
local wait_until
|
||||
local length
|
||||
local log_path
|
||||
local timeout
|
||||
ynh_handle_getopts_args "$@"
|
||||
service="${service:-$app}"
|
||||
action=${action:-start}
|
||||
wait_until=${wait_until:-}
|
||||
length=${length:-20}
|
||||
log_path="${log_path:-/var/log/$service/$service.log}"
|
||||
timeout=${timeout:-60}
|
||||
# ===========================================
|
||||
|
||||
# On CI, use length=100 because it's sometime hell to debug otherwise for super-long output
|
||||
if ynh_in_ci_tests && [ $length -le 20 ]; then
|
||||
length=100
|
||||
fi
|
||||
|
||||
# Manage case of service already stopped
|
||||
if [ "$action" == "stop" ] && ! systemctl is-active --quiet $service; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Start to read the log
|
||||
if [[ -n "$wait_until" ]]; then
|
||||
local templog="$(mktemp)"
|
||||
# Following the starting of the app in its log
|
||||
if [ "$log_path" == "systemd" ]; then
|
||||
# Read the systemd journal
|
||||
journalctl --unit=$service --follow --since=-0 --quiet > "$templog" &
|
||||
# Get the PID of the journalctl command
|
||||
local pid_tail=$!
|
||||
else
|
||||
# Read the specified log file
|
||||
tail --follow=name --retry --lines=0 "$log_path" > "$templog" 2>&1 &
|
||||
# Get the PID of the tail command
|
||||
local pid_tail=$!
|
||||
fi
|
||||
fi
|
||||
|
||||
# Use reload-or-restart instead of reload. So it wouldn't fail if the service isn't running.
|
||||
if [ "$action" == "reload" ]; then
|
||||
action="reload-or-restart"
|
||||
fi
|
||||
|
||||
local time_start="$(date --utc --rfc-3339=seconds | cut -d+ -f1) UTC"
|
||||
|
||||
# If the service fails to perform the action
|
||||
if ! systemctl $action $service; then
|
||||
# Show syslog for this service
|
||||
journalctl --quiet --no-hostname --no-pager --lines=$length --unit=$service >&2
|
||||
# If a log is specified for this service, show also the content of this log
|
||||
if [ -e "$log_path" ]; then
|
||||
tail --lines=$length "$log_path" >&2
|
||||
fi
|
||||
_ynh_clean_check_starting
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Start the timeout and try to find wait_until
|
||||
if [[ -n "${wait_until:-}" ]]; then
|
||||
set +o xtrace # set +x
|
||||
local i=0
|
||||
local starttime=$(date +%s)
|
||||
for i in $(seq 1 $timeout); do
|
||||
# Read the log until the sentence is found, that means the app finished to start. Or run until the timeout
|
||||
if [ "$log_path" == "systemd" ]; then
|
||||
# For systemd services, we in fact dont rely on the templog, which for some reason is not reliable, but instead re-read journalctl every iteration, starting at the timestamp where we triggered the action
|
||||
if journalctl --unit=$service --since="$time_start" --quiet --no-pager --no-hostname | grep --extended-regexp --quiet "$wait_until"; then
|
||||
ynh_print_info "The service $service has correctly executed the action ${action}."
|
||||
break
|
||||
fi
|
||||
else
|
||||
if grep --extended-regexp --quiet "$wait_until" "$templog"; then
|
||||
ynh_print_info "The service $service has correctly executed the action ${action}."
|
||||
break
|
||||
fi
|
||||
fi
|
||||
if [ $i -eq 30 ]; then
|
||||
echo "(this may take some time)" >&2
|
||||
fi
|
||||
# Also check the timeout using actual timestamp, because sometimes for some reason,
|
||||
# journalctl may take a huge time to run, and we end up waiting literally an entire hour
|
||||
# instead of 5 min ...
|
||||
if [[ "$(($(date +%s) - $starttime))" -gt "$timeout" ]]; then
|
||||
i=$timeout
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
set -o xtrace # set -x
|
||||
if [ $i -ge 3 ]; then
|
||||
echo "" >&2
|
||||
fi
|
||||
if [ $i -eq $timeout ]; then
|
||||
ynh_print_warn "The service $service didn't fully executed the action ${action} before the timeout."
|
||||
ynh_print_warn "Please find here an extract of the end of the log of the service $service:"
|
||||
journalctl --quiet --no-hostname --no-pager --lines=$length --unit=$service >&2
|
||||
if [ -e "$log_path" ]; then
|
||||
ynh_print_warn "==="
|
||||
tail --lines=$length "$log_path" >&2
|
||||
fi
|
||||
|
||||
# If we tried to reload/start/restart the service but systemctl consider it to be still inactive/broken, then handle it as a failure
|
||||
if ([ "$action" == "reload" ] || [ "$action" == "start" ] || [ "$action" == "restart" ]) && ! systemctl --quiet is-active $service; then
|
||||
_ynh_clean_check_starting
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
_ynh_clean_check_starting
|
||||
fi
|
||||
}
|
||||
|
||||
_ynh_clean_check_starting() {
|
||||
if [ -n "${pid_tail:-}" ]; then
|
||||
# Stop the execution of tail.
|
||||
kill -SIGTERM $pid_tail 2>&1
|
||||
fi
|
||||
if [ -n "${templog:-}" ]; then
|
||||
ynh_safe_rm "$templog" 2>&1
|
||||
fi
|
||||
}
|
105
helpers/helpers.v2.1.d/systemuser
Normal file
105
helpers/helpers.v2.1.d/systemuser
Normal file
|
@ -0,0 +1,105 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Check if a user exists on the system
|
||||
#
|
||||
# usage: ynh_system_user_exists --username=username
|
||||
# | arg: --username= - the username to check
|
||||
# | ret: 0 if the user exists, 1 otherwise.
|
||||
ynh_system_user_exists() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([u]=username=)
|
||||
local username
|
||||
ynh_handle_getopts_args "$@"
|
||||
# ===========================================
|
||||
|
||||
getent passwd "$username" &> /dev/null
|
||||
}
|
||||
|
||||
# Check if a group exists on the system
|
||||
#
|
||||
# usage: ynh_system_group_exists --group=group
|
||||
# | arg: --group= - the group to check
|
||||
# | ret: 0 if the group exists, 1 otherwise.
|
||||
ynh_system_group_exists() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([g]=group=)
|
||||
local group
|
||||
ynh_handle_getopts_args "$@"
|
||||
# ===========================================
|
||||
|
||||
getent group "$group" &> /dev/null
|
||||
}
|
||||
|
||||
# Create a system user
|
||||
#
|
||||
# usage: ynh_system_user_create --username=user_name [--home_dir=home_dir] [--use_shell] [--groups="group1 group2"]
|
||||
# | arg: --username= - Name of the system user that will be create
|
||||
# | arg: --home_dir= - Path of the home dir for the user. Usually the final path of the app. If this argument is omitted, the user will be created without home
|
||||
# | arg: --use_shell - Create a user using the default login shell if present. If this argument is omitted, the user will be created with /usr/sbin/nologin shell
|
||||
# | arg: --groups - Add the user to system groups. Typically meant to add the user to the ssh.app / sftp.app group (e.g. for borgserver, my_webapp)
|
||||
#
|
||||
# Create a nextcloud user with no home directory and /usr/sbin/nologin login shell (hence no login capability) :
|
||||
# ```
|
||||
# ynh_system_user_create --username=nextcloud
|
||||
# ```
|
||||
# Create a discourse user using /var/www/discourse as home directory and the default login shell :
|
||||
# ```
|
||||
# ynh_system_user_create --username=discourse --home_dir=/var/www/discourse --use_shell
|
||||
# ```
|
||||
ynh_system_user_create() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([u]=username= [h]=home_dir= [s]=use_shell [g]=groups=)
|
||||
local username
|
||||
local home_dir
|
||||
local use_shell
|
||||
local groups
|
||||
ynh_handle_getopts_args "$@"
|
||||
use_shell="${use_shell:-0}"
|
||||
home_dir="${home_dir:-}"
|
||||
groups="${groups:-}"
|
||||
# ===========================================
|
||||
|
||||
if ! ynh_system_user_exists --username="$username"; then # Check if the user exists on the system
|
||||
# If the user doesn't exist
|
||||
if [ -n "$home_dir" ]; then # If a home dir is mentioned
|
||||
local user_home_dir="--home-dir $home_dir"
|
||||
else
|
||||
local user_home_dir="--no-create-home"
|
||||
fi
|
||||
if [ $use_shell -eq 1 ]; then # If we want a shell for the user
|
||||
local shell="" # Use default shell
|
||||
else
|
||||
local shell="--shell /usr/sbin/nologin"
|
||||
fi
|
||||
useradd $user_home_dir --system --user-group $username $shell || ynh_die "Unable to create $username system account"
|
||||
fi
|
||||
|
||||
local group
|
||||
for group in $groups; do
|
||||
usermod -a -G "$group" "$username"
|
||||
done
|
||||
}
|
||||
|
||||
# Delete a system user
|
||||
#
|
||||
# usage: ynh_system_user_delete --username=user_name
|
||||
# | arg: --username= - Name of the system user that will be create
|
||||
ynh_system_user_delete() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([u]=username=)
|
||||
local username
|
||||
ynh_handle_getopts_args "$@"
|
||||
# ===========================================
|
||||
|
||||
# Check if the user exists on the system
|
||||
if ynh_system_user_exists --username="$username"; then
|
||||
deluser $username
|
||||
else
|
||||
ynh_print_warn "The user $username was not found"
|
||||
fi
|
||||
|
||||
# Check if the group exists on the system
|
||||
if ynh_system_group_exists --group="$username"; then
|
||||
delgroup $username
|
||||
fi
|
||||
}
|
332
helpers/helpers.v2.1.d/templating
Normal file
332
helpers/helpers.v2.1.d/templating
Normal file
|
@ -0,0 +1,332 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Create a dedicated config file from a template
|
||||
#
|
||||
# usage: ynh_config_add --template="template" --destination="destination"
|
||||
# | arg: --template= - Template config file to use
|
||||
# | arg: --destination= - Destination of the config file
|
||||
# | arg: --jinja - Use jinja template instead of the simple `__MY_VAR__` templating format
|
||||
#
|
||||
# examples:
|
||||
# ynh_add_config --template=".env" --destination="$install_dir/.env" # (use the template file "conf/.env" from the app's package)
|
||||
# ynh_add_config --jinja --template="config.j2" --destination="$install_dir/config" # (use the template file "conf/config.j2" from the app's package)
|
||||
#
|
||||
# The template can be 1) the name of a file in the `conf` directory of
|
||||
# the app, 2) a relative path or 3) an absolute path.
|
||||
#
|
||||
# This applies a simple templating format which covers a good 95% of cases,
|
||||
# where patterns like `__FOO__` are replaced by the bash variable `$foo`, for example:
|
||||
# `__DOMAIN__` by `$domain`
|
||||
# `__PATH__` by `$path`
|
||||
# `__APP__` by `$app`
|
||||
# `__VAR_1__` by `$var_1`
|
||||
# `__VAR_2__` by `$var_2`
|
||||
#
|
||||
# Special case for `__PATH__/` which is replaced by `/` instead of `//` if `$path` is `/`
|
||||
#
|
||||
# ##### When --jinja is enabled
|
||||
#
|
||||
# This option is meant for advanced use-cases where the "simple" templating
|
||||
# mode ain't enough because you need conditional blocks or loops.
|
||||
#
|
||||
# For a full documentation of jinja's syntax you can refer to:
|
||||
# https://jinja.palletsprojects.com/en/3.1.x/templates/
|
||||
#
|
||||
# Note that in YunoHost context, all variables are from shell variables and therefore are strings
|
||||
#
|
||||
# ##### Keeping track of manual changes by the admin
|
||||
#
|
||||
# The helper will verify the checksum and backup the destination file
|
||||
# if it's different before applying the new template.
|
||||
#
|
||||
# And it will calculate and store the destination file checksum
|
||||
# into the app settings when configuration is done.
|
||||
ynh_config_add() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([t]=template= [d]=destination= [j]=jinja)
|
||||
local template
|
||||
local destination
|
||||
local jinja
|
||||
ynh_handle_getopts_args "$@"
|
||||
jinja="${jinja:-0}"
|
||||
# ===========================================
|
||||
|
||||
local template_path
|
||||
if [ -f "$YNH_APP_BASEDIR/conf/$template" ]; then
|
||||
template_path="$YNH_APP_BASEDIR/conf/$template"
|
||||
elif [ -f "$template" ]; then
|
||||
template_path=$template
|
||||
else
|
||||
ynh_die "The provided template $template doesn't exist"
|
||||
fi
|
||||
|
||||
ynh_backup_if_checksum_is_different "$destination"
|
||||
|
||||
# Make sure to set the permissions before we copy the file
|
||||
# This is to cover a case where an attacker could have
|
||||
# created a file beforehand to have control over it
|
||||
# (cp won't overwrite ownership / modes by default...)
|
||||
touch $destination
|
||||
chmod 640 $destination
|
||||
_ynh_apply_default_permissions $destination
|
||||
|
||||
if [[ "$jinja" == 1 ]]; then
|
||||
# This is ran in a subshell such that the "export" does not "contaminate" the main process
|
||||
(
|
||||
export $(compgen -v)
|
||||
j2 "$template_path" -f env -o $destination
|
||||
)
|
||||
else
|
||||
cp -f "$template_path" "$destination"
|
||||
_ynh_replace_vars "$destination"
|
||||
fi
|
||||
|
||||
ynh_store_file_checksum "$destination"
|
||||
}
|
||||
|
||||
# Replace `__FOO__` patterns in file with bash variable `$foo`
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# usage: ynh_replace_vars "/path/to/file"
|
||||
# | arg: /path/to/file - File where to replace variables
|
||||
#
|
||||
# This applies a simple templating format which covers a good 95% of cases,
|
||||
# where patterns like `__FOO__` are replaced by the bash variable `$foo`, for example:
|
||||
# `__DOMAIN__` by `$domain`
|
||||
# `__PATH__` by `$path`
|
||||
# `__APP__` by `$app`
|
||||
# `__VAR_1__` by `$var_1`
|
||||
# `__VAR_2__` by `$var_2`
|
||||
#
|
||||
# Special case for `__PATH__/` which is replaced by `/` instead of `//` if `$path` is `/`
|
||||
_ynh_replace_vars() {
|
||||
local file=$1
|
||||
|
||||
# List unique (__ __) variables in $file
|
||||
local uniques_vars=($(grep -oP '__[A-Z0-9]+?[A-Z0-9_]*?[A-Z0-9]*?__' $file | sort --unique | sed "s@__\([^.]*\)__@\L\1@g"))
|
||||
|
||||
set +o xtrace # set +x
|
||||
|
||||
# Specific trick to make sure that __PATH__/ doesn't end up in "//" if $path=/
|
||||
if [[ "${path:-}" == "/" ]] && grep -q '__PATH__/' $file; then
|
||||
sed --in-place "s@__PATH__/@/@g" "$file"
|
||||
fi
|
||||
|
||||
# Do the replacement
|
||||
local delimit=@
|
||||
for one_var in "${uniques_vars[@]}"; do
|
||||
# Validate that one_var is indeed defined
|
||||
# -v checks if the variable is defined, for example:
|
||||
# -v FOO tests if $FOO is defined
|
||||
# -v $FOO tests if ${!FOO} is defined
|
||||
# More info: https://stackoverflow.com/questions/3601515/how-to-check-if-a-variable-is-set-in-bash/17538964#comment96392525_17538964
|
||||
[[ -v "${one_var:-}" ]] || ynh_die "Variable \$$one_var wasn't initialized when trying to replace __${one_var^^}__ in $file"
|
||||
|
||||
# Escape delimiter in match/replace string
|
||||
match_string="__${one_var^^}__"
|
||||
match_string=${match_string//${delimit}/"\\${delimit}"}
|
||||
replace_string="${!one_var}"
|
||||
replace_string=${replace_string//\\/\\\\}
|
||||
replace_string=${replace_string//${delimit}/"\\${delimit}"}
|
||||
|
||||
# Actually replace (sed is used instead of ynh_replace_string to avoid triggering an epic amount of debug logs)
|
||||
sed --in-place "s${delimit}${match_string}${delimit}${replace_string}${delimit}g" "$file"
|
||||
done
|
||||
set -o xtrace # set -x
|
||||
}
|
||||
|
||||
# Get a value from heterogeneous file (yaml, json, php, python...)
|
||||
#
|
||||
# usage: ynh_read_var_in_file --file=PATH --key=KEY
|
||||
# | arg: --file= - the path to the file
|
||||
# | arg: --key= - the key to get
|
||||
# | arg: --after= - the line just before the key (in case of multiple lines with the name of the key in the file)
|
||||
#
|
||||
# This helpers match several var affectation use case in several languages
|
||||
# We don't use jq or equivalent to keep comments and blank space in files
|
||||
# This helpers work line by line, it is not able to work correctly
|
||||
# if you have several identical keys in your files
|
||||
#
|
||||
# Example of line this helpers can managed correctly
|
||||
# .yml
|
||||
# title: YunoHost documentation
|
||||
# email: 'yunohost@yunohost.org'
|
||||
# .json
|
||||
# "theme": "colib'ris",
|
||||
# "port": 8102
|
||||
# "some_boolean": false,
|
||||
# "user": null
|
||||
# .ini
|
||||
# some_boolean = On
|
||||
# action = "Clear"
|
||||
# port = 20
|
||||
# .php
|
||||
# $user=
|
||||
# user => 20
|
||||
# .py
|
||||
# USER = 8102
|
||||
# user = 'https://donate.local'
|
||||
# CUSTOM['user'] = 'YunoHost'
|
||||
ynh_read_var_in_file() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([f]=file= [k]=key= [a]=after=)
|
||||
local file
|
||||
local key
|
||||
local after
|
||||
ynh_handle_getopts_args "$@"
|
||||
after="${after:-}"
|
||||
# ===========================================
|
||||
|
||||
[[ -f $file ]] || ynh_die "File $file does not exists"
|
||||
|
||||
set +o xtrace # set +x
|
||||
|
||||
# Get the line number after which we search for the variable
|
||||
local line_number=1
|
||||
if [[ -n "$after" ]]; then
|
||||
line_number=$(grep -m1 -n $after $file | cut -d: -f1)
|
||||
if [[ -z "$line_number" ]]; then
|
||||
set -o xtrace # set -x
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
local filename="$(basename -- "$file")"
|
||||
local ext="${filename##*.}"
|
||||
local endline=',;'
|
||||
local assign="=>|:|="
|
||||
local comments="#"
|
||||
local string="\"'"
|
||||
if [[ "$ext" =~ ^ini|env|toml|yml|yaml$ ]]; then
|
||||
endline='#'
|
||||
fi
|
||||
if [[ "$ext" =~ ^ini|env$ ]]; then
|
||||
comments="[;#]"
|
||||
fi
|
||||
if [[ "php" == "$ext" ]] || [[ "$ext" == "js" ]]; then
|
||||
comments="//"
|
||||
fi
|
||||
local list='\[\s*['$string']?\w+['$string']?\]'
|
||||
local var_part='^\s*((const|var|let)\s+)?\$?(\w+('$list')*(->|\.|\[))*\s*'
|
||||
var_part+="[$string]?${key}[$string]?"
|
||||
var_part+='\s*\]?\s*'
|
||||
var_part+="($assign)"
|
||||
var_part+='\s*'
|
||||
|
||||
# Extract the part after assignation sign
|
||||
local expression_with_comment="$( (tail +$line_number ${file} | grep -i -o -P $var_part'\K.*$' || echo YNH_NULL) | head -n1)"
|
||||
if [[ "$expression_with_comment" == "YNH_NULL" ]]; then
|
||||
set -o xtrace # set -x
|
||||
echo YNH_NULL
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Remove comments if needed
|
||||
local expression="$(echo "$expression_with_comment" | sed "s@${comments}[^$string]*\$@@g" | sed "s@\s*[$endline]*\s*]*\$@@")"
|
||||
|
||||
local first_char="${expression:0:1}"
|
||||
if [[ "$first_char" == '"' ]]; then
|
||||
echo "$expression" | grep -m1 -o -P '"\K([^"](\\")?)*[^\\](?=")' | head -n1 | sed 's/\\"/"/g'
|
||||
elif [[ "$first_char" == "'" ]]; then
|
||||
echo "$expression" | grep -m1 -o -P "'\K([^'](\\\\')?)*[^\\\\](?=')" | head -n1 | sed "s/\\\\'/'/g"
|
||||
else
|
||||
echo "$expression"
|
||||
fi
|
||||
set -o xtrace # set -x
|
||||
}
|
||||
|
||||
# Set a value into heterogeneous file (yaml, json, php, python...)
|
||||
#
|
||||
# usage: ynh_write_var_in_file --file=PATH --key=KEY --value=VALUE
|
||||
# | arg: --file= - the path to the file
|
||||
# | arg: --key= - the key to set
|
||||
# | arg: --value= - the value to set
|
||||
# | arg: --after= - the line just before the key (in case of multiple lines with the name of the key in the file)
|
||||
ynh_write_var_in_file() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([f]=file= [k]=key= [v]=value= [a]=after=)
|
||||
local file
|
||||
local key
|
||||
local value
|
||||
local after
|
||||
ynh_handle_getopts_args "$@"
|
||||
after="${after:-}"
|
||||
# ===========================================
|
||||
|
||||
[[ -f $file ]] || ynh_die "File $file does not exists"
|
||||
|
||||
set +o xtrace # set +x
|
||||
|
||||
# Get the line number after which we search for the variable
|
||||
local after_line_number=1
|
||||
if [[ -n "$after" ]]; then
|
||||
after_line_number=$(grep -m1 -n $after $file | cut -d: -f1)
|
||||
if [[ -z "$after_line_number" ]]; then
|
||||
set -o xtrace # set -x
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
local filename="$(basename -- "$file")"
|
||||
local ext="${filename##*.}"
|
||||
local endline=',;'
|
||||
local assign="=>|:|="
|
||||
local comments="#"
|
||||
local string="\"'"
|
||||
if [[ "$ext" =~ ^ini|env|toml|yml|yaml$ ]]; then
|
||||
endline='#'
|
||||
fi
|
||||
if [[ "$ext" =~ ^ini|env$ ]]; then
|
||||
comments="[;#]"
|
||||
fi
|
||||
if [[ "php" == "$ext" ]] || [[ "$ext" == "js" ]]; then
|
||||
comments="//"
|
||||
fi
|
||||
local list='\[\s*['$string']?\w+['$string']?\]'
|
||||
local var_part='^\s*((const|var|let)\s+)?\$?(\w+('$list')*(->|\.|\[))*\s*'
|
||||
var_part+="[$string]?${key}[$string]?"
|
||||
var_part+='\s*\]?\s*'
|
||||
var_part+="($assign)"
|
||||
var_part+='\s*'
|
||||
|
||||
# Extract the part after assignation sign
|
||||
local expression_with_comment="$( (tail +$after_line_number ${file} | grep -i -o -P $var_part'\K.*$' || echo YNH_NULL) | head -n1)"
|
||||
if [[ "$expression_with_comment" == "YNH_NULL" ]]; then
|
||||
set -o xtrace # set -x
|
||||
return 1
|
||||
fi
|
||||
local value_line_number="$(tail +$after_line_number ${file} | grep -m1 -n -i -P $var_part'\K.*$' | cut -d: -f1)"
|
||||
value_line_number=$((after_line_number + value_line_number))
|
||||
local range="${after_line_number},${value_line_number} "
|
||||
|
||||
# Remove comments if needed
|
||||
local expression="$(echo "$expression_with_comment" | sed "s@${comments}[^$string]*\$@@g" | sed "s@\s*[$endline]*\s*]*\$@@")"
|
||||
endline=${expression_with_comment#"$expression"}
|
||||
endline="$(echo "$endline" | sed 's/\\/\\\\/g')"
|
||||
value="$(echo "$value" | sed 's/\\/\\\\/g')"
|
||||
value=${value//&/"\&"}
|
||||
local first_char="${expression:0:1}"
|
||||
delimiter=$'\001'
|
||||
if [[ "$first_char" == '"' ]]; then
|
||||
# \ and sed is quite complex you need 2 \\ to get one in a sed
|
||||
# So we need \\\\ to go through 2 sed
|
||||
value="$(echo "$value" | sed 's/"/\\\\"/g')"
|
||||
sed -ri "${range}s$delimiter"'(^'"${var_part}"'")([^"]|\\")*("[\s;,]*)(\s*'$comments'.*)?$'$delimiter'\1'"${value}"'"'"${endline}${delimiter}i" ${file}
|
||||
elif [[ "$first_char" == "'" ]]; then
|
||||
# \ and sed is quite complex you need 2 \\ to get one in a sed
|
||||
# However double quotes implies to double \\ to
|
||||
# So we need \\\\\\\\ to go through 2 sed and 1 double quotes str
|
||||
value="$(echo "$value" | sed "s/'/\\\\\\\\'/g")"
|
||||
sed -ri "${range}s$delimiter(^${var_part}')([^']|\\')*('"'[\s,;]*)(\s*'$comments'.*)?$'$delimiter'\1'"${value}'${endline}${delimiter}i" ${file}
|
||||
else
|
||||
if [[ "$value" == *"'"* ]] || [[ "$value" == *'"'* ]] || [[ "$ext" =~ ^php|py|json|js$ ]]; then
|
||||
value='\"'"$(echo "$value" | sed 's/"/\\\\"/g')"'\"'
|
||||
fi
|
||||
if [[ "$ext" =~ ^yaml|yml$ ]]; then
|
||||
value=" $value"
|
||||
fi
|
||||
sed -ri "${range}s$delimiter(^${var_part}).*\$$delimiter\1${value}${endline}${delimiter}i" ${file}
|
||||
fi
|
||||
set -o xtrace # set -x
|
||||
}
|
583
helpers/helpers.v2.1.d/utils
Normal file
583
helpers/helpers.v2.1.d/utils
Normal file
|
@ -0,0 +1,583 @@
|
|||
#!/bin/bash
|
||||
|
||||
YNH_APP_BASEDIR=${YNH_APP_BASEDIR:-$(realpath ..)}
|
||||
|
||||
# Handle script crashes / failures
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
ynh_exit_properly() {
|
||||
local exit_code=$?
|
||||
|
||||
if [[ "${YNH_APP_ACTION:-}" =~ ^install$|^upgrade$|^restore$ ]]; then
|
||||
rm -rf "/var/cache/yunohost/download/"
|
||||
fi
|
||||
|
||||
if [ "$exit_code" -eq 0 ]; then
|
||||
exit 0 # Exit without error if the script ended correctly
|
||||
fi
|
||||
|
||||
trap '' EXIT # Ignore new exit signals
|
||||
# Do not exit anymore if a command fail or if a variable is empty
|
||||
set +o errexit # set +e
|
||||
set +o nounset # set +u
|
||||
|
||||
# Small tempo to avoid the next message being mixed up with other DEBUG messages
|
||||
sleep 0.5
|
||||
|
||||
# Exit with error status
|
||||
# We don't call ynh_die basically to avoid unecessary 10-ish
|
||||
# debug lines about parsing args and stuff just to exit 1..
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Exits if an error occurs during the execution of the script.
|
||||
#
|
||||
# [packagingv1]
|
||||
#
|
||||
# usage: ynh_abort_if_errors
|
||||
#
|
||||
# This configure the rest of the script execution such that, if an error occurs
|
||||
# or if an empty variable is used, the execution of the script stops immediately
|
||||
ynh_abort_if_errors() {
|
||||
set -o errexit # set -e; Exit if a command fail
|
||||
set -o nounset # set -u; And if a variable is used unset
|
||||
trap ynh_exit_properly EXIT # Capturing exit signals on shell script
|
||||
}
|
||||
|
||||
# When running an app script, auto-enable ynh_abort_if_errors except for remove script
|
||||
if [[ "${YNH_CONTEXT:-}" != "regenconf" ]] && [[ "${YNH_APP_ACTION}" != "remove" ]]; then
|
||||
ynh_abort_if_errors
|
||||
fi
|
||||
|
||||
# Execute a command after sudoing as $app
|
||||
#
|
||||
# Note that the $PATH variable is preserved (using --preserve-env=PATH)
|
||||
#
|
||||
# usage: ynh_exec_as_app COMMAND [ARG ...]
|
||||
ynh_exec_as_app() {
|
||||
sudo --preserve-env=PATH -u "$app" "$@"
|
||||
}
|
||||
|
||||
# Curl abstraction to help with POST requests to local pages (such as installation forms)
|
||||
#
|
||||
# usage: ynh_local_curl "page_uri" "key1=value1" "key2=value2" ...
|
||||
# | arg: page_uri - Path (relative to `$path`) of the page where POST data will be sent
|
||||
# | arg: key1=value1 - (Optionnal) POST key and corresponding value
|
||||
# | arg: key2=value2 - (Optionnal) Another POST key and corresponding value
|
||||
# | arg: ... - (Optionnal) More POST keys and values
|
||||
#
|
||||
# example: ynh_local_curl "/install.php?installButton" "foo=$var1" "bar=$var2"
|
||||
#
|
||||
# For multiple calls, cookies are persisted between each call for the same app
|
||||
#
|
||||
# `$domain` and `$path` should be defined externally (and correspond to the domain.tld and the /path (of the app?))
|
||||
ynh_local_curl() {
|
||||
# Define url of page to curl
|
||||
local local_page=$(ynh_normalize_url_path $1)
|
||||
local full_path=$path$local_page
|
||||
|
||||
if [ "${path}" == "/" ]; then
|
||||
full_path=$local_page
|
||||
fi
|
||||
|
||||
local full_page_url=https://localhost$full_path
|
||||
|
||||
# Concatenate all other arguments with '&' to prepare POST data
|
||||
local POST_data=""
|
||||
local arg=""
|
||||
for arg in "${@:2}"; do
|
||||
POST_data="${POST_data}${arg}&"
|
||||
done
|
||||
if [ -n "$POST_data" ]; then
|
||||
# Add --data arg and remove the last character, which is an unecessary '&'
|
||||
POST_data="--data ${POST_data::-1}"
|
||||
fi
|
||||
|
||||
# Wait untils nginx has fully reloaded (avoid curl fail with http2)
|
||||
sleep 2
|
||||
|
||||
local cookiefile=/tmp/ynh-$app-cookie.txt
|
||||
touch $cookiefile
|
||||
chown root $cookiefile
|
||||
chmod 700 $cookiefile
|
||||
|
||||
# Temporarily enable visitors if needed...
|
||||
local visitors_enabled=$(ynh_permission_has_user --permission="main" --user="visitors" && echo yes || echo no)
|
||||
if [[ $visitors_enabled == "no" ]]; then
|
||||
ynh_permission_update --permission="main" --add="visitors"
|
||||
fi
|
||||
|
||||
# Curl the URL
|
||||
curl --silent --show-error --insecure --location --header "Host: $domain" --resolve $domain:443:127.0.0.1 $POST_data "$full_page_url" --cookie-jar $cookiefile --cookie $cookiefile
|
||||
|
||||
if [[ $visitors_enabled == "no" ]]; then
|
||||
ynh_permission_update --permission="main" --remove="visitors"
|
||||
fi
|
||||
}
|
||||
|
||||
_acceptable_path_to_delete() {
|
||||
local file=$1
|
||||
|
||||
local forbidden_paths=$(ls -d / /* /{var,home,usr}/* /etc/{default,sudoers.d,yunohost,cron*} /etc/yunohost/{apps,domains,hooks.d} /opt/yunohost 2> /dev/null)
|
||||
|
||||
# Legacy : A couple apps still have data in /home/$app ...
|
||||
if [[ -n "${app:-}" ]]; then
|
||||
forbidden_paths=$(echo "$forbidden_paths" | grep -v "/home/$app")
|
||||
fi
|
||||
|
||||
# Use realpath to normalize the path ..
|
||||
# i.e convert ///foo//bar//..///baz//// to /foo/baz
|
||||
file=$(realpath --no-symlinks "$file")
|
||||
if [ -z "$file" ] || grep -q -x -F "$file" <<< "$forbidden_paths"; then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# Remove a file or a directory, checking beforehand that it's not a disastrous location to rm such as entire /var or /home
|
||||
#
|
||||
# usage: ynh_safe_rm path_to_remove
|
||||
ynh_safe_rm() {
|
||||
local target="$1"
|
||||
set +o xtrace # set +x
|
||||
|
||||
if [ $# -ge 2 ]; then
|
||||
ynh_print_warn "/!\ Packager ! You provided more than one argument to ynh_safe_rm but it will be ignored... Use this helper with one argument at time."
|
||||
fi
|
||||
|
||||
if [[ -z "$target" ]]; then
|
||||
ynh_print_warn "ynh_safe_rm called with empty argument, ignoring."
|
||||
elif [[ ! -e "$target" ]] && [[ ! -L "$target" ]]; then
|
||||
ynh_print_info "'$target' wasn't deleted because it doesn't exist."
|
||||
elif ! _acceptable_path_to_delete "$target"; then
|
||||
ynh_print_warn "Not deleting '$target' because it is not an acceptable path to delete."
|
||||
else
|
||||
rm --recursive "$target"
|
||||
fi
|
||||
|
||||
set -o xtrace # set -x
|
||||
}
|
||||
|
||||
# Read the value of a key in the app's manifest
|
||||
#
|
||||
# usage: ynh_read_manifest "key"
|
||||
# | arg: key - Name of the key to find
|
||||
# | ret: the value associate to that key
|
||||
ynh_read_manifest() {
|
||||
cat $YNH_APP_BASEDIR/manifest.toml | toml_to_json | jq ".$1" --raw-output
|
||||
}
|
||||
|
||||
# Return the app upstream version, deduced from `$YNH_APP_MANIFEST_VERSION` and strippig the `~ynhX` part
|
||||
#
|
||||
# usage: ynh_app_upstream_version
|
||||
# | ret: the version number of the upstream app
|
||||
#
|
||||
# For example, if the manifest contains `4.3-2~ynh3` the function will return `4.3-2`
|
||||
ynh_app_upstream_version() {
|
||||
echo "${YNH_APP_MANIFEST_VERSION/~ynh*/}"
|
||||
}
|
||||
|
||||
# Return 0 if the "upstream" part of the version changed, or 1 otherwise (ie only the ~ynh suffix changed)
|
||||
#
|
||||
# usage: if ynh_app_upstream_version_changed; then ...
|
||||
ynh_app_upstream_version_changed() {
|
||||
# "UPGRADE_PACKAGE" means only the ~ynh prefix changed
|
||||
[[ "$YNH_APP_UPGRADE_TYPE" == "UPGRADE_PACKAGE" ]] && return 1 || return 0
|
||||
}
|
||||
|
||||
# Compare the current package version is strictly lower than another version given as an argument
|
||||
#
|
||||
# example: if ynh_app_upgrading_from_version_before 2.3.2~ynh1; then ...
|
||||
ynh_app_upgrading_from_version_before() {
|
||||
local version=$1
|
||||
[[ $version =~ '~ynh' ]] || ynh_die "Invalid argument for version, should include the ~ynhX prefix"
|
||||
|
||||
dpkg --compare-versions $YNH_APP_CURRENT_VERSION lt $version
|
||||
}
|
||||
|
||||
# Compare the current package version is lower or equal to another version given as an argument
|
||||
#
|
||||
# example: if ynh_app_upgrading_from_version_before_or_equal_to 2.3.2~ynh1; then ...
|
||||
ynh_app_upgrading_from_version_before_or_equal_to() {
|
||||
local version=$1
|
||||
[[ $version =~ '~ynh' ]] || ynh_die "Invalid argument for version, should include the ~ynhX prefix"
|
||||
|
||||
dpkg --compare-versions $YNH_APP_CURRENT_VERSION le $version
|
||||
}
|
||||
|
||||
# Apply sane permissions for files installed by ynh_setup_source and ynh_config_add.
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# * Anything below $install_dir is chown $app:$app and chmod o-rwx,g-w
|
||||
# * The rest is considered as system configuration and chown root, chmod 400
|
||||
#
|
||||
_ynh_apply_default_permissions() {
|
||||
local target=$1
|
||||
|
||||
is_in_dir() {
|
||||
# Returns false if parent is empty
|
||||
[ -n "$2" ] || return 1
|
||||
local child=$(realpath "$1" 2> /dev/null)
|
||||
local parent=$(realpath "$2" 2> /dev/null)
|
||||
[[ "${child}" =~ ^$parent ]]
|
||||
}
|
||||
|
||||
# App files can have files of their own
|
||||
if ynh_system_user_exists --username="$app"; then
|
||||
# If this is a file in $install_dir or $data_dir : it should be owned and read+writable by $app only
|
||||
if [ -f "$target" ] && (is_in_dir "$target" "${install_dir:-}" || is_in_dir "$target" "${data_dir:-}" || is_in_dir "$target" "/etc/$app"); then
|
||||
chmod 600 "$target"
|
||||
chown "$app:$app" "$target"
|
||||
return
|
||||
fi
|
||||
# If this is the install dir (so far this is the only way this helper is called with a directory)
|
||||
if [ "$target" == "${install_dir:-}" ]; then
|
||||
# Read the group from the install_dir manifest resource
|
||||
local group="$(ynh_read_manifest 'resources.install_dir.group' | sed 's/null//g' | sed "s/__APP__/$app/g" | cut -f1 -d:)"
|
||||
if [[ -z "$group" ]]; then
|
||||
# We set the group to www-data for webapps that do serve static assets, which therefore need to be readable by nginx ...
|
||||
# The fact that the app needs this is infered by the existence of an nginx.conf and the presence of "alias" or "root" directive
|
||||
if grep -q '^\s*alias\s\|^\s*root\s' "$YNH_APP_BASEDIR/conf/nginx.conf" 2> /dev/null; then
|
||||
group="www-data"
|
||||
# Or default to "$app"
|
||||
else
|
||||
group="$app"
|
||||
fi
|
||||
fi
|
||||
# Files inside should be owned by $app with rw-r----- (+x for folders or files that already have +x)
|
||||
# The group needs read/dirtraversal (in particular if it's www-data)
|
||||
chmod -R u=rwX,g=rX,o=--- "$target"
|
||||
chown -R "$app:$group" "$target"
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
# Other files are considered system
|
||||
chmod 400 "$target"
|
||||
chown root:root "$target"
|
||||
}
|
||||
|
||||
int_to_bool() {
|
||||
sed -e 's/^1$/True/g' -e 's/^0$/False/g' -e 's/^true$/True/g' -e 's/^false$/False/g'
|
||||
}
|
||||
|
||||
toml_to_json() {
|
||||
python3 -c 'import toml, json, sys; print(json.dumps(toml.load(sys.stdin)))'
|
||||
}
|
||||
|
||||
# Validate an IP address
|
||||
#
|
||||
# usage: ynh_validate_ip --family=family --ip_address=ip_address
|
||||
# | ret: 0 for valid ip addresses, 1 otherwise
|
||||
#
|
||||
# example: ynh_validate_ip 4 111.222.333.444
|
||||
ynh_validate_ip() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([f]=family= [i]=ip_address=)
|
||||
local family
|
||||
local ip_address
|
||||
ynh_handle_getopts_args "$@"
|
||||
# ===========================================
|
||||
|
||||
[ "$family" == "4" ] || [ "$family" == "6" ] || return 1
|
||||
|
||||
# http://stackoverflow.com/questions/319279/how-to-validate-ip-address-in-python#319298
|
||||
python3 /dev/stdin << EOF
|
||||
import socket
|
||||
import sys
|
||||
family = { "4" : socket.AF_INET, "6" : socket.AF_INET6 }
|
||||
try:
|
||||
socket.inet_pton(family["$family"], "$ip_address")
|
||||
except socket.error:
|
||||
sys.exit(1)
|
||||
sys.exit(0)
|
||||
EOF
|
||||
}
|
||||
|
||||
# Get the total or free amount of RAM+swap on the system
|
||||
#
|
||||
# [packagingv1]
|
||||
#
|
||||
# usage: ynh_get_ram [--free|--total]
|
||||
# | arg: --free - Count free RAM+swap
|
||||
# | arg: --total - Count total RAM+swap
|
||||
# | ret: the amount of free ram, in MB (MegaBytes)
|
||||
ynh_get_ram() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([f]=free [t]=total)
|
||||
local free
|
||||
local total
|
||||
ynh_handle_getopts_args "$@"
|
||||
free=${free:-0}
|
||||
total=${total:-0}
|
||||
# ===========================================
|
||||
|
||||
if [ $free -eq $total ]; then
|
||||
ynh_print_warn "You have to choose --free or --total when using ynh_get_ram"
|
||||
ram=0
|
||||
elif [ $free -eq 1 ]; then
|
||||
local free_ram=$(LC_ALL=C vmstat --stats --unit M | grep "free memory" | awk '{print $1}')
|
||||
local free_swap=$(LC_ALL=C vmstat --stats --unit M | grep "free swap" | awk '{print $1}')
|
||||
local free_ram_swap=$((free_ram + free_swap))
|
||||
local ram=$free_ram_swap
|
||||
elif [ $total -eq 1 ]; then
|
||||
local total_ram=$(LC_ALL=C vmstat --stats --unit M | grep "total memory" | awk '{print $1}')
|
||||
local total_swap=$(LC_ALL=C vmstat --stats --unit M | grep "total swap" | awk '{print $1}')
|
||||
local total_ram_swap=$((total_ram + total_swap))
|
||||
local ram=$total_ram_swap
|
||||
fi
|
||||
|
||||
echo $ram
|
||||
}
|
||||
|
||||
# Check if the scripts are being run by the package_check in CI
|
||||
#
|
||||
# usage: ynh_in_ci_tests
|
||||
#
|
||||
# Return 0 if in CI, 1 otherwise
|
||||
ynh_in_ci_tests() {
|
||||
[ "${PACKAGE_CHECK_EXEC:-0}" -eq 1 ]
|
||||
}
|
||||
|
||||
# Retrieve a YunoHost user information
|
||||
#
|
||||
# usage: ynh_user_get_info --username=username --key=key
|
||||
# | arg: --username= - the username to retrieve info from
|
||||
# | arg: --key= - the key to retrieve
|
||||
# | ret: the value associate to that key
|
||||
#
|
||||
# example: mail=$(ynh_user_get_info --username="toto" --key=mail)
|
||||
ynh_user_get_info() {
|
||||
# ============ Argument parsing =============
|
||||
local -A args_array=([u]=username= [k]=key=)
|
||||
local username
|
||||
local key
|
||||
ynh_handle_getopts_args "$@"
|
||||
# ===========================================
|
||||
|
||||
yunohost user info "$username" --output-as json --quiet | jq -r ".$key"
|
||||
}
|
||||
|
||||
# Get the list of YunoHost users
|
||||
#
|
||||
# usage: ynh_user_list
|
||||
# | ret: one username per line as strings
|
||||
#
|
||||
# example: for u in $(ynh_user_list); do ... ; done
|
||||
ynh_user_list() {
|
||||
yunohost user list --output-as json --quiet | jq -r ".users | keys[]"
|
||||
}
|
||||
|
||||
# Spawn a Bash shell with the app environment loaded
|
||||
#
|
||||
# usage: ynh_spawn_app_shell "appname"
|
||||
#
|
||||
# examples:
|
||||
# ynh_spawn_app_shell "foobar" <<< 'echo "$USER"'
|
||||
# ynh_spawn_app_shell "foobar" < /tmp/some_script.bash
|
||||
#
|
||||
# The spawned shell will have environment variables loaded and environment files sourced
|
||||
# from the app's service configuration file (defaults to $app.service, overridable by the packager with `service` setting).
|
||||
# If the app relies on a specific PHP version, then `php` will be aliased that version. The PHP command will also be appended with the `phpflags` settings.
|
||||
ynh_spawn_app_shell() {
|
||||
local app=$1
|
||||
|
||||
# Force Bash to be used to run this helper
|
||||
[[ $0 =~ \/?bash$ ]] || ynh_die "Please use Bash as shell"
|
||||
|
||||
# Make sure the app is installed
|
||||
test -d /etc/yunohost/apps/$app || ynh_die "$app is not an installed app ?!"
|
||||
|
||||
# Make sure the app has its own user
|
||||
id -u "$app" &> /dev/null || ynh_die "There is no \"$app\" system user"
|
||||
|
||||
# Make sure the app has an install_dir setting
|
||||
local install_dir=$(ynh_app_setting_get --app=$app --key=install_dir)
|
||||
[ -n "$install_dir" ] || ynh_die "$app has no install_dir setting (does it use packaging format >=2?)"
|
||||
|
||||
# Load the app's service name, or default to $app
|
||||
local service=$(ynh_app_setting_get --app=$app --key=service)
|
||||
[ -z "$service" ] && service=$app
|
||||
|
||||
# Export HOME variable
|
||||
export HOME=$install_dir
|
||||
|
||||
# Load the Environment variables from the app's service
|
||||
local env_var=$(systemctl show $service.service -p "Environment" --value)
|
||||
[ -n "$env_var" ] && export $env_var
|
||||
|
||||
# Force `php` to its intended version
|
||||
# We use `eval`+`export` since `alias` is not propagated to subshells, even with `export`
|
||||
local phpversion=$(ynh_app_setting_get --app=$app --key=phpversion)
|
||||
local phpflags=$(ynh_app_setting_get --app=$app --key=phpflags)
|
||||
if [ -n "$phpversion" ]; then
|
||||
eval "php() { php${phpversion} ${phpflags} \"\$@\"; }"
|
||||
export -f php
|
||||
fi
|
||||
|
||||
# Source the EnvironmentFiles from the app's service
|
||||
local env_files=($(systemctl show $service.service -p "EnvironmentFiles" --value))
|
||||
if [ ${#env_files[*]} -gt 0 ]; then
|
||||
# set -/+a enables and disables new variables being automatically exported. Needed when using `source`.
|
||||
set -a
|
||||
for file in ${env_files[*]}; do
|
||||
[[ $file = /* ]] && source $file
|
||||
done
|
||||
set +a
|
||||
fi
|
||||
|
||||
# Activate the Python environment, if it exists
|
||||
if [ -f $install_dir/venv/bin/activate ]; then
|
||||
# set -/+a enables and disables new variables being automatically exported. Needed when using `source`.
|
||||
set -a
|
||||
source $install_dir/venv/bin/activate
|
||||
set +a
|
||||
fi
|
||||
|
||||
# cd into the WorkingDirectory set in the service, or default to the install_dir
|
||||
local env_dir=$(systemctl show $service.service -p "WorkingDirectory" --value)
|
||||
[ -z $env_dir ] && env_dir=$install_dir
|
||||
cd $env_dir
|
||||
|
||||
# Spawn the app shell
|
||||
su -s /bin/bash $app
|
||||
}
|
||||
|
||||
# Add swap
|
||||
#
|
||||
# usage: ynh_add_swap --size=SWAP in Mb
|
||||
# | arg: -s, --size= - Amount of SWAP to add in Mb.
|
||||
ynh_add_swap() {
|
||||
if systemd-detect-virt --container --quiet; then
|
||||
ynh_print_warn --message="You are inside a container/VM. swap will not be added, but that can cause troubles for the app $app. Please make sure you have enough RAM available."
|
||||
return
|
||||
fi
|
||||
|
||||
# Declare an array to define the options of this helper.
|
||||
declare -Ar args_array=([s]=size=)
|
||||
local size
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
local swap_max_size=$(($size * 1024))
|
||||
|
||||
local free_space=$(df --output=avail / | sed 1d)
|
||||
# Because we don't want to fill the disk with a swap file, divide by 2 the available space.
|
||||
local usable_space=$(($free_space / 2))
|
||||
|
||||
SD_CARD_CAN_SWAP=${SD_CARD_CAN_SWAP:-0}
|
||||
|
||||
# Swap on SD card only if it's is specified
|
||||
if ynh_is_main_device_a_sd_card && [ "$SD_CARD_CAN_SWAP" == "0" ]; then
|
||||
ynh_print_warn --message="The main mountpoint of your system '/' is on an SD card, swap will not be added to prevent some damage of this one, but that can cause troubles for the app $app. If you still want activate the swap, you can relaunch the command preceded by 'SD_CARD_CAN_SWAP=1'"
|
||||
return
|
||||
fi
|
||||
|
||||
# Compare the available space with the size of the swap.
|
||||
# And set a acceptable size from the request
|
||||
if [ $usable_space -ge $swap_max_size ]; then
|
||||
local swap_size=$swap_max_size
|
||||
elif [ $usable_space -ge $(($swap_max_size / 2)) ]; then
|
||||
local swap_size=$(($swap_max_size / 2))
|
||||
elif [ $usable_space -ge $(($swap_max_size / 3)) ]; then
|
||||
local swap_size=$(($swap_max_size / 3))
|
||||
elif [ $usable_space -ge $(($swap_max_size / 4)) ]; then
|
||||
local swap_size=$(($swap_max_size / 4))
|
||||
else
|
||||
echo "Not enough space left for a swap file" >&2
|
||||
local swap_size=0
|
||||
fi
|
||||
|
||||
# If there's enough space for a swap, and no existing swap here
|
||||
if [ $swap_size -ne 0 ] && [ ! -e /swap_$app ]; then
|
||||
# Create file
|
||||
truncate -s 0 /swap_$app
|
||||
|
||||
# set the No_COW attribute on the swapfile with chattr
|
||||
chattr +C /swap_$app
|
||||
|
||||
# Preallocate space for the swap file, fallocate may sometime not be used, use dd instead in this case
|
||||
if ! fallocate -l ${swap_size}K /swap_$app; then
|
||||
dd if=/dev/zero of=/swap_$app bs=1024 count=${swap_size}
|
||||
fi
|
||||
chmod 0600 /swap_$app
|
||||
# Create the swap
|
||||
mkswap /swap_$app
|
||||
# And activate it
|
||||
swapon /swap_$app
|
||||
# Then add an entry in fstab to load this swap at each boot.
|
||||
echo -e "/swap_$app swap swap defaults 0 0 #Swap added by $app" >> /etc/fstab
|
||||
fi
|
||||
}
|
||||
|
||||
ynh_del_swap() {
|
||||
# If there a swap at this place
|
||||
if [ -e /swap_$app ]; then
|
||||
# Clean the fstab
|
||||
sed -i "/#Swap added by $app/d" /etc/fstab
|
||||
# Desactive the swap file
|
||||
swapoff /swap_$app
|
||||
# And remove it
|
||||
rm /swap_$app
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if the device of the main mountpoint "/" is an SD card
|
||||
#
|
||||
# [internal]
|
||||
#
|
||||
# return 0 if it's an SD card, else 1
|
||||
ynh_is_main_device_a_sd_card() {
|
||||
if [ "$(systemd-detect-virt)" != "none" ]; then
|
||||
# Assume virtualization does not take place on SD card
|
||||
return 1
|
||||
fi
|
||||
|
||||
local main_device=$(lsblk --output PKNAME --noheadings $(findmnt / --nofsroot --uniq --output source --noheadings --first-only))
|
||||
|
||||
if echo $main_device | grep --quiet "mmc" && [ $(tail -n1 /sys/block/$main_device/queue/rotational) == "0" ]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check available space before creating a temp directory.
|
||||
#
|
||||
# usage: ynh_smart_mktemp --min_size="Min size"
|
||||
#
|
||||
# | arg: -s, --min_size= - Minimal size needed for the temporary directory, in Mb
|
||||
ynh_smart_mktemp() {
|
||||
# Declare an array to define the options of this helper.
|
||||
declare -Ar args_array=([s]=min_size=)
|
||||
local min_size
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
min_size="${min_size:-300}"
|
||||
# Transform the minimum size from megabytes to kilobytes
|
||||
min_size=$(($min_size * 1024))
|
||||
|
||||
# Check if there's enough free space in a directory
|
||||
is_there_enough_space() {
|
||||
local free_space=$(df --output=avail "$1" | sed 1d)
|
||||
test $free_space -ge $min_size
|
||||
}
|
||||
|
||||
if is_there_enough_space /tmp; then
|
||||
local tmpdir=/tmp
|
||||
elif is_there_enough_space /var; then
|
||||
local tmpdir=/var
|
||||
elif is_there_enough_space /; then
|
||||
local tmpdir=/
|
||||
elif is_there_enough_space /home; then
|
||||
local tmpdir=/home
|
||||
else
|
||||
ynh_die "Insufficient free space to continue..."
|
||||
fi
|
||||
|
||||
echo "$(mktemp --directory --tmpdir="$tmpdir")"
|
||||
}
|
1
helpers/helpers.v2.1.d/vendor
Symbolic link
1
helpers/helpers.v2.1.d/vendor
Symbolic link
|
@ -0,0 +1 @@
|
|||
../vendor
|
|
@ -6,7 +6,7 @@ YNH_CWD="${YNH_BACKUP_DIR%/}/conf/manually_modified_files"
|
|||
mkdir -p "$YNH_CWD"
|
||||
cd "$YNH_CWD"
|
||||
|
||||
yunohost tools shell -c "from yunohost.regenconf import manually_modified_files; print('\n'.join(manually_modified_files()))" >./manually_modified_files_list
|
||||
yunohost tools shell -c "from yunohost.regenconf import manually_modified_files; print('\n'.join(manually_modified_files()))" > ./manually_modified_files_list
|
||||
|
||||
ynh_backup --src_path="./manually_modified_files_list"
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ do_init_regen() {
|
|||
|
||||
# set default current_host
|
||||
[[ -f /etc/yunohost/current_host ]] \
|
||||
|| echo "yunohost.org" >/etc/yunohost/current_host
|
||||
|| echo "yunohost.org" > /etc/yunohost/current_host
|
||||
|
||||
# copy default services and firewall
|
||||
[[ -f /etc/yunohost/firewall.yml ]] \
|
||||
|
@ -45,7 +45,7 @@ do_init_regen() {
|
|||
chown root:root /home/yunohost.backup/archives # This is later changed to root:admins once the admins group exists
|
||||
|
||||
# Empty ssowat json persistent conf
|
||||
echo "{}" >'/etc/ssowat/conf.json.persistent'
|
||||
echo "{}" > '/etc/ssowat/conf.json.persistent'
|
||||
chmod 644 /etc/ssowat/conf.json.persistent
|
||||
chown root:root /etc/ssowat/conf.json.persistent
|
||||
|
||||
|
@ -64,14 +64,17 @@ do_init_regen() {
|
|||
|
||||
systemctl enable yunohost-api.service --quiet
|
||||
systemctl start yunohost-api.service
|
||||
|
||||
# Enable yunoprompt (in particular for installs from ISO where we want this to show on first boot instead of asking for a login/password)
|
||||
systemctl enable yunoprompt --quiet
|
||||
|
||||
# Yunohost-firewall is enabled only during postinstall, not init, not 100% sure why
|
||||
|
||||
cp dpkg-origins /etc/dpkg/origins/yunohost
|
||||
|
||||
# Change dpkg vendor
|
||||
# see https://wiki.debian.org/Derivatives/Guidelines#Vendor
|
||||
if readlink -f /etc/dpkg/origins/default | grep -q debian;
|
||||
then
|
||||
if readlink -f /etc/dpkg/origins/default | grep -q debian; then
|
||||
rm -f /etc/dpkg/origins/default
|
||||
ln -s /etc/dpkg/origins/yunohost /etc/dpkg/origins/default
|
||||
fi
|
||||
|
@ -89,19 +92,19 @@ do_pre_regen() {
|
|||
# add cron job for diagnosis to be ran at 7h and 19h + a random delay between
|
||||
# 0 and 20min, meant to avoid every instances running their diagnosis at
|
||||
# exactly the same time, which may overload the diagnosis server.
|
||||
cat >$pending_dir/etc/cron.d/yunohost-diagnosis <<EOF
|
||||
cat > $pending_dir/etc/cron.d/yunohost-diagnosis << EOF
|
||||
SHELL=/bin/bash
|
||||
0 7,19 * * * root : YunoHost Automatic Diagnosis; sleep \$((RANDOM\\%1200)); yunohost diagnosis run --email > /dev/null 2>/dev/null || echo "Running the automatic diagnosis failed miserably"
|
||||
EOF
|
||||
|
||||
# Cron job that upgrade the app list everyday
|
||||
cat >$pending_dir/etc/cron.daily/yunohost-fetch-apps-catalog <<EOF
|
||||
cat > $pending_dir/etc/cron.daily/yunohost-fetch-apps-catalog << EOF
|
||||
#!/bin/bash
|
||||
sleep \$((RANDOM%3600)); yunohost tools update apps > /dev/null
|
||||
EOF
|
||||
|
||||
# Cron job that renew lets encrypt certificates if there's any that needs renewal
|
||||
cat >$pending_dir/etc/cron.daily/yunohost-certificate-renew <<EOF
|
||||
cat > $pending_dir/etc/cron.daily/yunohost-certificate-renew << EOF
|
||||
#!/bin/bash
|
||||
yunohost domain cert renew --email
|
||||
EOF
|
||||
|
@ -109,8 +112,8 @@ EOF
|
|||
# If we subscribed to a dyndns domain, add the corresponding cron
|
||||
# - delay between 0 and 60 secs to spread the check over a 1 min window
|
||||
# - do not run the command if some process already has the lock, to avoid queuing hundreds of commands...
|
||||
if ls -l /etc/yunohost/dyndns/K*.key 2>/dev/null; then
|
||||
cat >$pending_dir/etc/cron.d/yunohost-dyndns <<EOF
|
||||
if ls -l /etc/yunohost/dyndns/K*.key 2> /dev/null; then
|
||||
cat > $pending_dir/etc/cron.d/yunohost-dyndns << EOF
|
||||
SHELL=/bin/bash
|
||||
# Every 10 minutes,
|
||||
# - (sleep random 60 is here to spread requests over a 1-min window)
|
||||
|
@ -125,10 +128,9 @@ EOF
|
|||
fi
|
||||
|
||||
# Skip ntp if inside a container (inspired from the conf of systemd-timesyncd)
|
||||
if systemctl | grep -q 'ntp.service'
|
||||
then
|
||||
if systemctl | grep -q 'ntp.service'; then
|
||||
mkdir -p ${pending_dir}/etc/systemd/system/ntp.service.d/
|
||||
cat >${pending_dir}/etc/systemd/system/ntp.service.d/ynh-override.conf <<EOF
|
||||
cat > ${pending_dir}/etc/systemd/system/ntp.service.d/ynh-override.conf << EOF
|
||||
[Unit]
|
||||
ConditionCapability=CAP_SYS_TIME
|
||||
ConditionVirtualization=!container
|
||||
|
@ -137,7 +139,7 @@ EOF
|
|||
|
||||
# Make nftable conflict with yunohost-firewall
|
||||
mkdir -p ${pending_dir}/etc/systemd/system/nftables.service.d/
|
||||
cat >${pending_dir}/etc/systemd/system/nftables.service.d/ynh-override.conf <<EOF
|
||||
cat > ${pending_dir}/etc/systemd/system/nftables.service.d/ynh-override.conf << EOF
|
||||
[Unit]
|
||||
# yunohost-firewall and nftables conflict with each other
|
||||
Conflicts=yunohost-firewall.service
|
||||
|
@ -147,7 +149,7 @@ EOF
|
|||
|
||||
# Don't suspend computer on LidSwitch
|
||||
mkdir -p ${pending_dir}/etc/systemd/logind.conf.d/
|
||||
cat >${pending_dir}/etc/systemd/logind.conf.d/ynh-override.conf <<EOF
|
||||
cat > ${pending_dir}/etc/systemd/logind.conf.d/ynh-override.conf << EOF
|
||||
[Login]
|
||||
HandleLidSwitch=ignore
|
||||
HandleLidSwitchDocked=ignore
|
||||
|
@ -162,6 +164,8 @@ EOF
|
|||
mkdir -p ${pending_dir}/etc/dpkg/origins/
|
||||
cp dpkg-origins ${pending_dir}/etc/dpkg/origins/yunohost
|
||||
|
||||
# Remove legacy hackish/clumsy nodejs autoupdate which ends up filling up space with ambiguous upgrades >_>
|
||||
touch "/etc/cron.daily/node_update"
|
||||
}
|
||||
|
||||
do_post_regen() {
|
||||
|
@ -186,8 +190,7 @@ do_post_regen() {
|
|||
find /etc/systemd/system/*.service -type f | xargs -r chown root:root
|
||||
find /etc/systemd/system/*.service -type f | xargs -r chmod 0644
|
||||
|
||||
if ls -l /etc/php/*/fpm/pool.d/*.conf
|
||||
then
|
||||
if ls -l /etc/php/*/fpm/pool.d/*.conf; then
|
||||
chown root:root /etc/php/*/fpm/pool.d/*.conf
|
||||
chmod 644 /etc/php/*/fpm/pool.d/*.conf
|
||||
fi
|
||||
|
@ -216,8 +219,8 @@ do_post_regen() {
|
|||
mkdir -p /etc/yunohost/domains
|
||||
|
||||
# Misc configuration / state files
|
||||
chown root:root $(ls /etc/yunohost/{*.yml,*.yaml,*.json,mysql,psql} 2>/dev/null | grep -vw mdns.yml)
|
||||
chmod 600 $(ls /etc/yunohost/{*.yml,*.yaml,*.json,mysql,psql} 2>/dev/null)
|
||||
chown root:root $(ls /etc/yunohost/{*.yml,*.yaml,*.json,mysql,psql} 2> /dev/null | grep -vw mdns.yml)
|
||||
chmod 600 $(ls /etc/yunohost/{*.yml,*.yaml,*.json,mysql,psql} 2> /dev/null)
|
||||
|
||||
# Apps folder, custom hooks folder
|
||||
[[ ! -e /etc/yunohost/hooks.d ]] || (chown root /etc/yunohost/hooks.d && chmod 700 /etc/yunohost/hooks.d)
|
||||
|
@ -229,15 +232,14 @@ do_post_regen() {
|
|||
grep -q '^sftp.app:' /etc/group || groupadd sftp.app
|
||||
|
||||
# Propagates changes in systemd service config overrides
|
||||
if systemctl | grep -q 'ntp.service'
|
||||
then
|
||||
if systemctl | grep -q 'ntp.service'; then
|
||||
[[ ! "$regen_conf_files" =~ "ntp.service.d/ynh-override.conf" ]] || {
|
||||
systemctl daemon-reload
|
||||
systemctl restart ntp
|
||||
}
|
||||
fi
|
||||
[[ ! "$regen_conf_files" =~ "nftables.service.d/ynh-override.conf" ]] || systemctl daemon-reload
|
||||
[[ ! "$regen_conf_files" =~ "login.conf.d/ynh-override.conf" ]] || {
|
||||
[[ ! "$regen_conf_files" =~ "login.conf.d/ynh-override.conf" ]] || {
|
||||
systemctl daemon-reload
|
||||
systemctl restart systemd-logind
|
||||
}
|
||||
|
@ -257,14 +259,12 @@ do_post_regen() {
|
|||
|
||||
# Change dpkg vendor
|
||||
# see https://wiki.debian.org/Derivatives/Guidelines#Vendor
|
||||
if readlink -f /etc/dpkg/origins/default | grep -q debian;
|
||||
then
|
||||
if readlink -f /etc/dpkg/origins/default | grep -q debian; then
|
||||
rm -f /etc/dpkg/origins/default
|
||||
ln -s /etc/dpkg/origins/yunohost /etc/dpkg/origins/default
|
||||
fi
|
||||
|
||||
if test -e /etc/yunohost/installed && test -e /etc/profile.d/check_yunohost_is_installed.sh
|
||||
then
|
||||
if test -e /etc/yunohost/installed && test -e /etc/profile.d/check_yunohost_is_installed.sh; then
|
||||
rm /etc/profile.d/check_yunohost_is_installed.sh
|
||||
fi
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
set -e
|
||||
|
||||
ssl_dir="/usr/share/yunohost/ssl"
|
||||
template_dir="/usr/share/yunohost/conf/ssl/"
|
||||
template_dir="/usr/share/yunohost/conf/ssl"
|
||||
ynh_ca="/etc/yunohost/certs/yunohost.org/ca.pem"
|
||||
ynh_crt="/etc/yunohost/certs/yunohost.org/crt.pem"
|
||||
ynh_key="/etc/yunohost/certs/yunohost.org/key.pem"
|
||||
|
@ -23,7 +23,7 @@ regen_local_ca() {
|
|||
# (Update the serial so that it's specific to this very instance)
|
||||
# N.B. : the weird RANDFILE thing comes from:
|
||||
# https://stackoverflow.com/questions/94445/using-openssl-what-does-unable-to-write-random-state-mean
|
||||
RANDFILE=.rnd openssl rand -hex 19 >serial
|
||||
RANDFILE=.rnd openssl rand -hex 19 > serial
|
||||
rm -f index.txt
|
||||
touch index.txt
|
||||
cp ${template_dir}/openssl.cnf openssl.ca.cnf
|
||||
|
@ -51,7 +51,7 @@ regen_local_ca() {
|
|||
do_init_regen() {
|
||||
|
||||
LOGFILE=/tmp/yunohost-ssl-init
|
||||
echo "" >$LOGFILE
|
||||
echo "" > $LOGFILE
|
||||
chown root:root $LOGFILE
|
||||
chmod 640 $LOGFILE
|
||||
|
||||
|
@ -61,24 +61,24 @@ do_init_regen() {
|
|||
|
||||
# create default certificates
|
||||
if [[ ! -f "$ynh_ca" ]]; then
|
||||
regen_local_ca yunohost.org >>$LOGFILE
|
||||
regen_local_ca yunohost.org >> $LOGFILE
|
||||
fi
|
||||
|
||||
if [[ ! -f "$ynh_crt" ]]; then
|
||||
echo -e "\n# Creating initial key and certificate \n" >>$LOGFILE
|
||||
echo -e "\n# Creating initial key and certificate \n" >> $LOGFILE
|
||||
|
||||
openssl req -new \
|
||||
-config "${ssl_dir}/openssl.cnf" \
|
||||
-out "${ssl_dir}/certs/yunohost_csr.pem" \
|
||||
-keyout "${ssl_dir}/certs/yunohost_key.pem" \
|
||||
-nodes -batch &>>$LOGFILE
|
||||
-nodes -batch &>> $LOGFILE
|
||||
|
||||
openssl ca \
|
||||
-config "${ssl_dir}/openssl.cnf" \
|
||||
-days 730 \
|
||||
-in "${ssl_dir}/certs/yunohost_csr.pem" \
|
||||
-out "${ssl_dir}/certs/yunohost_crt.pem" \
|
||||
-batch &>>$LOGFILE
|
||||
-batch &>> $LOGFILE
|
||||
|
||||
chmod 640 "${ssl_dir}/certs/yunohost_key.pem"
|
||||
chmod 640 "${ssl_dir}/certs/yunohost_crt.pem"
|
||||
|
@ -104,10 +104,9 @@ do_post_regen() {
|
|||
|
||||
current_local_ca_domain=$(openssl x509 -in $ynh_ca -text | tr ',' '\n' | grep Issuer | awk '{print $4}')
|
||||
main_domain=$(cat /etc/yunohost/current_host)
|
||||
|
||||
|
||||
# Automigrate legacy folder
|
||||
if [ -e /usr/share/yunohost/yunohost-config/ssl/yunoCA ]
|
||||
then
|
||||
if [ -e /usr/share/yunohost/yunohost-config/ssl/yunoCA ]; then
|
||||
mv /usr/share/yunohost/yunohost-config/ssl/yunoCA/* ${ssl_dir}
|
||||
rm -rf /usr/share/yunohost/yunohost-config
|
||||
# Overwrite openssl.cnf because it may still contain references to the old yunoCA dir
|
||||
|
@ -120,7 +119,7 @@ do_post_regen() {
|
|||
chown root:root ${ssl_dir}
|
||||
chmod 750 ${ssl_dir}
|
||||
chmod -R o-rwx ${ssl_dir}
|
||||
chmod o+x ${ssl_dir}/certs
|
||||
chmod o+x ${ssl_dir}/certs
|
||||
chmod o+r ${ssl_dir}/certs/yunohost_crt.pem
|
||||
|
||||
if [[ "$current_local_ca_domain" != "$main_domain" ]]; then
|
||||
|
|
|
@ -12,7 +12,7 @@ do_pre_regen() {
|
|||
# do not listen to IPv6 if unavailable
|
||||
[[ -f /proc/net/if_inet6 ]] && ipv6_enabled=true || ipv6_enabled=false
|
||||
|
||||
ssh_keys=$(ls /etc/ssh/ssh_host_{ed25519,rsa,ecdsa}_key 2>/dev/null || true)
|
||||
ssh_keys=$(ls /etc/ssh/ssh_host_{ed25519,rsa,ecdsa}_key 2> /dev/null || true)
|
||||
|
||||
# Support different strategy for security configurations
|
||||
export compatibility="$(yunohost settings get 'security.ssh.ssh_compatibility')"
|
||||
|
|
|
@ -20,7 +20,7 @@ do_init_regen() {
|
|||
rm -rf /var/backups/*.ldapdb
|
||||
rm -rf /var/backups/slapd-*
|
||||
|
||||
debconf-set-selections <<EOF
|
||||
debconf-set-selections << EOF
|
||||
slapd slapd/password1 password yunohost
|
||||
slapd slapd/password2 password yunohost
|
||||
slapd slapd/domain string yunohost.org
|
||||
|
@ -87,13 +87,13 @@ do_pre_regen() {
|
|||
rm -f "$tmp_backup_dir_file"
|
||||
|
||||
# Define if we need to migrate from hdb to mdb
|
||||
curr_backend=$(grep '^database' /etc/ldap/slapd.conf 2>/dev/null | awk '{print $2}')
|
||||
curr_backend=$(grep '^database' /etc/ldap/slapd.conf 2> /dev/null | awk '{print $2}')
|
||||
if [ -e /etc/ldap/slapd.conf ] && [ -n "$curr_backend" ] \
|
||||
&& [ $curr_backend != 'mdb' ]; then
|
||||
backup_dir="/var/backups/dc=yunohost,dc=org-${curr_backend}-$(date +%s)"
|
||||
mkdir -p "$backup_dir"
|
||||
slapcat -b dc=yunohost,dc=org -l "${backup_dir}/dc=yunohost-dc=org.ldif"
|
||||
echo "$backup_dir" >"$tmp_backup_dir_file"
|
||||
echo "$backup_dir" > "$tmp_backup_dir_file"
|
||||
fi
|
||||
|
||||
# create needed directories
|
||||
|
@ -155,7 +155,7 @@ objectClass: top"
|
|||
_regenerate_slapd_conf
|
||||
|
||||
# If there's a backup, re-import its data
|
||||
backup_dir=$(cat "$tmp_backup_dir_file" 2>/dev/null || true)
|
||||
backup_dir=$(cat "$tmp_backup_dir_file" 2> /dev/null || true)
|
||||
if [[ -n "$backup_dir" && -f "${backup_dir}/dc=yunohost-dc=org.ldif" ]]; then
|
||||
# regenerate LDAP config directory and import database as root
|
||||
echo "Import the database using slapadd"
|
||||
|
|
|
@ -17,14 +17,14 @@ do_pre_regen() {
|
|||
echo "
|
||||
Package: php-common
|
||||
Pin: origin \"packages.sury.org\"
|
||||
Pin-Priority: 500" >>"${pending_dir}/etc/apt/preferences.d/extra_php_version"
|
||||
Pin-Priority: 500" >> "${pending_dir}/etc/apt/preferences.d/extra_php_version"
|
||||
|
||||
packages_to_refuse_from_sury="php php-* openssl libssl1.1 libssl-dev"
|
||||
for package in $packages_to_refuse_from_sury; do
|
||||
echo "
|
||||
Package: $package
|
||||
Pin: origin \"packages.sury.org\"
|
||||
Pin-Priority: -1" >>"${pending_dir}/etc/apt/preferences.d/extra_php_version"
|
||||
Pin-Priority: -1" >> "${pending_dir}/etc/apt/preferences.d/extra_php_version"
|
||||
done
|
||||
|
||||
echo "
|
||||
|
@ -54,8 +54,7 @@ Pin-Priority: -1
|
|||
Package: bind9
|
||||
Pin: release *
|
||||
Pin-Priority: -1
|
||||
" >>"${pending_dir}/etc/apt/preferences.d/ban_packages"
|
||||
|
||||
" >> "${pending_dir}/etc/apt/preferences.d/ban_packages"
|
||||
|
||||
}
|
||||
|
||||
|
@ -63,19 +62,17 @@ do_post_regen() {
|
|||
regen_conf_files=$1
|
||||
|
||||
# Purge expired keys (such as sury 95BD4743)
|
||||
EXPIRED_KEYS="$(LC_ALL='en_US.UTF-8' apt-key list 2>/dev/null | grep -A1 'expired:' | grep -v 'expired\|^-' | sed 's/\s//g')"
|
||||
for KEY in $EXPIRED_KEYS; do apt-key del $KEY 2>/dev/null; done
|
||||
EXPIRED_KEYS="$(LC_ALL='en_US.UTF-8' apt-key list 2> /dev/null | grep -A1 'expired:' | grep -v 'expired\|^-' | sed 's/\s//g')"
|
||||
for KEY in $EXPIRED_KEYS; do apt-key del $KEY 2> /dev/null; done
|
||||
|
||||
# Add sury key
|
||||
# We do this only at the post regen and if the key doesn't already exists, because we don't want the regenconf to fuck everything up if the regenconf runs while the network is down
|
||||
if [[ ! -s /etc/apt/trusted.gpg.d/extra_php_version.gpg ]]
|
||||
then
|
||||
wget --timeout 900 --quiet "https://packages.sury.org/php/apt.gpg" --output-document=- | gpg --dearmor >"/etc/apt/trusted.gpg.d/extra_php_version.gpg"
|
||||
if [[ ! -s /etc/apt/trusted.gpg.d/extra_php_version.gpg ]]; then
|
||||
wget --timeout 900 --quiet "https://packages.sury.org/php/apt.gpg" --output-document=- | gpg --dearmor > "/etc/apt/trusted.gpg.d/extra_php_version.gpg"
|
||||
fi
|
||||
|
||||
# Make sure php7.4 is the default version when using php in cli
|
||||
if test -e /usr/bin/php$YNH_DEFAULT_PHP_VERSION
|
||||
then
|
||||
if test -e /usr/bin/php$YNH_DEFAULT_PHP_VERSION; then
|
||||
update-alternatives --set php /usr/bin/php$YNH_DEFAULT_PHP_VERSION
|
||||
fi
|
||||
}
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
set -e
|
||||
|
||||
if ! dpkg --list | grep -q 'ii *metronome '
|
||||
then
|
||||
if ! dpkg --list | grep -q 'ii *metronome '; then
|
||||
echo 'metronome is not installed, skipping'
|
||||
exit 0
|
||||
fi
|
||||
|
@ -24,7 +23,7 @@ do_pre_regen() {
|
|||
# install main conf file
|
||||
cat metronome.cfg.lua \
|
||||
| sed "s/{{ main_domain }}/${main_domain}/g" \
|
||||
>"${metronome_dir}/metronome.cfg.lua"
|
||||
> "${metronome_dir}/metronome.cfg.lua"
|
||||
|
||||
# Trick such that old conf files are flagged as to remove
|
||||
for domain in $YNH_DOMAINS; do
|
||||
|
@ -36,7 +35,7 @@ do_pre_regen() {
|
|||
for domain in $domain_list; do
|
||||
cat domain.tpl.cfg.lua \
|
||||
| sed "s/{{ domain }}/${domain}/g" \
|
||||
>"${metronome_conf_dir}/${domain}.cfg.lua"
|
||||
> "${metronome_conf_dir}/${domain}.cfg.lua"
|
||||
done
|
||||
|
||||
# remove old domain conf files
|
||||
|
@ -74,16 +73,13 @@ do_post_regen() {
|
|||
chown -R metronome: /var/lib/metronome/
|
||||
chown -R metronome: /etc/metronome/conf.d/
|
||||
|
||||
if [[ -z "$(ls /etc/metronome/conf.d/*.cfg.lua 2>/dev/null)" ]]
|
||||
then
|
||||
if systemctl is-enabled metronome &>/dev/null
|
||||
then
|
||||
systemctl disable metronome --now 2>/dev/null
|
||||
if [[ -z "$(ls /etc/metronome/conf.d/*.cfg.lua 2> /dev/null)" ]]; then
|
||||
if systemctl is-enabled metronome &> /dev/null; then
|
||||
systemctl disable metronome --now 2> /dev/null
|
||||
fi
|
||||
else
|
||||
if ! systemctl is-enabled metronome &>/dev/null
|
||||
then
|
||||
systemctl enable metronome --now 2>/dev/null
|
||||
if ! systemctl is-enabled metronome &> /dev/null; then
|
||||
systemctl enable metronome --now 2> /dev/null
|
||||
sleep 3
|
||||
fi
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ do_init_regen() {
|
|||
cp "redirect_to_admin.conf" $nginx_conf_dir/default.d/
|
||||
|
||||
# Restart nginx if conf looks good, otherwise display error and exit unhappy
|
||||
nginx -t 2>/dev/null || {
|
||||
nginx -t 2> /dev/null || {
|
||||
nginx -t
|
||||
exit 1
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ do_pre_regen() {
|
|||
# remove the panel overlay if this is specified in settings
|
||||
panel_overlay=$(yunohost settings get 'misc.portal.ssowat_panel_overlay_enabled' | int_to_bool)
|
||||
if [ "$panel_overlay" == "False" ]; then
|
||||
echo "#" >"${nginx_conf_dir}/yunohost_panel.conf.inc"
|
||||
echo "#" > "${nginx_conf_dir}/yunohost_panel.conf.inc"
|
||||
fi
|
||||
|
||||
# retrieve variables
|
||||
|
@ -86,22 +86,19 @@ do_pre_regen() {
|
|||
export domain_cert_ca=$(echo $cert_status \
|
||||
| jq ".certificates.\"$domain\".CA_type" \
|
||||
| tr -d '"')
|
||||
if echo "$xmpp_domain_list" | grep -q "^$domain$"
|
||||
then
|
||||
if echo "$xmpp_domain_list" | grep -q "^$domain$"; then
|
||||
export xmpp_enabled="True"
|
||||
else
|
||||
export xmpp_enabled="False"
|
||||
fi
|
||||
if echo "$mail_domain_list" | grep -q "^$domain$"
|
||||
then
|
||||
if echo "$mail_domain_list" | grep -q "^$domain$"; then
|
||||
export mail_enabled="True"
|
||||
else
|
||||
export mail_enabled="False"
|
||||
fi
|
||||
|
||||
ynh_render_template "server.tpl.conf" "${nginx_conf_dir}/${domain}.conf"
|
||||
if [ $mail_enabled == "True" ]
|
||||
then
|
||||
if [ $mail_enabled == "True" ]; then
|
||||
ynh_render_template "autoconfig.tpl.xml" "${mail_autoconfig_dir}/config-v1.1.xml"
|
||||
fi
|
||||
|
||||
|
@ -129,7 +126,7 @@ do_pre_regen() {
|
|||
done
|
||||
|
||||
# remove old mail-autoconfig files
|
||||
autoconfig_files=$(ls -1 /var/www/.well-known/*/autoconfig/mail/config-v1.1.xml 2>/dev/null || true)
|
||||
autoconfig_files=$(ls -1 /var/www/.well-known/*/autoconfig/mail/config-v1.1.xml 2> /dev/null || true)
|
||||
for file in $autoconfig_files; do
|
||||
domain=$(basename $(readlink -f $(dirname $file)/../..))
|
||||
[[ $YNH_DOMAINS =~ $domain ]] \
|
||||
|
@ -144,8 +141,7 @@ do_pre_regen() {
|
|||
do_post_regen() {
|
||||
regen_conf_files=$1
|
||||
|
||||
if ls -l /etc/nginx/conf.d/*.d/*.conf
|
||||
then
|
||||
if ls -l /etc/nginx/conf.d/*.d/*.conf; then
|
||||
chown root:root /etc/nginx/conf.d/*.d/*.conf
|
||||
chmod 644 /etc/nginx/conf.d/*.d/*.conf
|
||||
fi
|
||||
|
@ -158,7 +154,7 @@ do_post_regen() {
|
|||
done
|
||||
|
||||
# Reload nginx if conf looks good, otherwise display error and exit unhappy
|
||||
nginx -t 2>/dev/null || {
|
||||
nginx -t 2> /dev/null || {
|
||||
nginx -t
|
||||
exit 1
|
||||
}
|
||||
|
|
|
@ -43,8 +43,21 @@ do_pre_regen() {
|
|||
chown postfix ${pending_dir}/etc/postfix
|
||||
chown postfix ${pending_dir}/etc/postfix/sasl_passwd
|
||||
|
||||
cat <<<"[${relay_host}]:${relay_port} ${relay_user}:${relay_password}" >${postfix_dir}/sasl_passwd
|
||||
cat <<< "[${relay_host}]:${relay_port} ${relay_user}:${relay_password}" > ${postfix_dir}/sasl_passwd
|
||||
fi
|
||||
|
||||
# Use this postfix server as a backup MX
|
||||
export backup_mx_domains="$(yunohost settings get 'email.smtp.smtp_backup_mx_domains' | sed "s/,/ /g")"
|
||||
export backup_mx_emails="$(yunohost settings get 'email.smtp.smtp_backup_mx_emails_whitelisted' | sed "s/,/ /g")"
|
||||
rm -f ${postfix_dir}/relay_recipients
|
||||
touch ${postfix_dir}/relay_recipients
|
||||
if [ -n "${backup_mx_domains}" ] && [ -n "${backup_mx_emails}" ]; then
|
||||
for mail in ${backup_mx_emails}; do
|
||||
echo "$mail OK" >> ${postfix_dir}/relay_recipients
|
||||
done
|
||||
postmap ${postfix_dir}/relay_recipients
|
||||
fi
|
||||
|
||||
export main_domain
|
||||
export domain_list="$(yunohost domain list --features mail_in mail_out --output-as json | jq -r ".domains[]" | tr '\n' ' ')"
|
||||
ynh_render_template "main.cf" "${postfix_dir}/main.cf"
|
||||
|
@ -53,7 +66,7 @@ do_pre_regen() {
|
|||
cat postsrsd \
|
||||
| sed "s/{{ main_domain }}/${main_domain}/g" \
|
||||
| sed "s/{{ domain_list }}/${domain_list}/g" \
|
||||
>"${default_dir}/postsrsd"
|
||||
> "${default_dir}/postsrsd"
|
||||
|
||||
# adapt it for IPv4-only hosts
|
||||
ipv6="$(yunohost settings get 'email.smtp.smtp_allow_ipv6' | int_to_bool)"
|
||||
|
@ -78,6 +91,11 @@ do_post_regen() {
|
|||
postmap /etc/postfix/sasl_passwd
|
||||
fi
|
||||
|
||||
if [ -e /etc/postfix/relay_recipients ]; then
|
||||
chmod 750 /etc/postfix/relay_recipients*
|
||||
chown postfix:root /etc/postfix/relay_recipients*
|
||||
fi
|
||||
|
||||
postmap -F hash:/etc/postfix/sni
|
||||
|
||||
python3 -c 'from yunohost.app import regen_mail_app_user_config_for_dovecot_and_postfix as r; r(only="postfix")'
|
||||
|
|
|
@ -41,7 +41,7 @@ do_post_regen() {
|
|||
mkdir -p "/etc/dovecot/yunohost.d/post-ext.d"
|
||||
|
||||
# create vmail user
|
||||
id vmail >/dev/null 2>&1 \
|
||||
id vmail > /dev/null 2>&1 \
|
||||
|| adduser --system --ingroup mail --uid 500 vmail --home /var/vmail --no-create-home
|
||||
|
||||
# Delete legacy home for vmail that existed in the past but was empty, poluting /home/
|
||||
|
|
|
@ -13,8 +13,8 @@ do_pre_regen() {
|
|||
"${pending_dir}/etc/rspamd/local.d/dkim_signing.conf"
|
||||
install -D -m 644 rspamd.sieve \
|
||||
"${pending_dir}/etc/dovecot/global_script/rspamd.sieve"
|
||||
install -D -m 644 redis.conf \
|
||||
"${pending_dir}/etc/rspamd/local.d/redis.conf"
|
||||
install -D -m 644 redis.conf \
|
||||
"${pending_dir}/etc/rspamd/local.d/redis.conf"
|
||||
}
|
||||
|
||||
do_post_regen() {
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
set -e
|
||||
. /usr/share/yunohost/helpers
|
||||
|
||||
if ! dpkg --list | grep -q 'ii *mariadb-server '
|
||||
then
|
||||
if ! dpkg --list | grep -q 'ii *mariadb-server '; then
|
||||
echo 'mysql/mariadb is not installed, skipping'
|
||||
exit 0
|
||||
fi
|
||||
|
|
|
@ -3,42 +3,42 @@
|
|||
set -e
|
||||
. /usr/share/yunohost/helpers
|
||||
|
||||
if ! dpkg --list | grep -q "ii *postgresql-$PSQL_VERSION "
|
||||
then
|
||||
if ! dpkg --list | grep -q "ii *postgresql-$PSQL_VERSION "; then
|
||||
echo 'postgresql is not installed, skipping'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ ! -e "/etc/postgresql/$PSQL_VERSION" ]
|
||||
then
|
||||
if [ ! -e "/etc/postgresql/$PSQL_VERSION" ]; then
|
||||
ynh_die --message="It looks like postgresql was not properly configured ? /etc/postgresql/$PSQL_VERSION is missing ... Could be due to a locale issue, c.f.https://serverfault.com/questions/426989/postgresql-etc-postgresql-doesnt-exist"
|
||||
fi
|
||||
|
||||
|
||||
do_pre_regen() {
|
||||
return 0
|
||||
}
|
||||
|
||||
do_post_regen() {
|
||||
#regen_conf_files=$1
|
||||
|
||||
|
||||
# Make sure postgresql is started and enabled
|
||||
# (N.B. : to check the active state, we check the cluster state because
|
||||
# postgresql could be flagged as active even though the cluster is in
|
||||
# failed state because of how the service is configured..)
|
||||
systemctl is-active postgresql@$PSQL_VERSION-main -q || ynh_systemd_action --service_name=postgresql --action=restart
|
||||
systemctl is-enabled postgresql -q || systemctl enable postgresql --quiet
|
||||
|
||||
|
||||
# If this is the very first time, we define the root password
|
||||
# and configure a few things
|
||||
if [ ! -f "$PSQL_ROOT_PWD_FILE" ] || [ -z "$(cat $PSQL_ROOT_PWD_FILE)" ]; then
|
||||
ynh_string_random >$PSQL_ROOT_PWD_FILE
|
||||
ynh_string_random > $PSQL_ROOT_PWD_FILE
|
||||
fi
|
||||
|
||||
[ ! -e $PSQL_ROOT_PWD_FILE ] || { chown root:postgres $PSQL_ROOT_PWD_FILE; chmod 440 $PSQL_ROOT_PWD_FILE; }
|
||||
|
||||
[ ! -e $PSQL_ROOT_PWD_FILE ] || {
|
||||
chown root:postgres $PSQL_ROOT_PWD_FILE
|
||||
chmod 440 $PSQL_ROOT_PWD_FILE
|
||||
}
|
||||
|
||||
sudo --login --user=postgres psql -c"ALTER user postgres WITH PASSWORD '$(cat $PSQL_ROOT_PWD_FILE)'" postgres
|
||||
|
||||
|
||||
# force all user to connect to local databases using hashed passwords
|
||||
# https://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html#EXAMPLE-PG-HBA.CONF
|
||||
# Note: we can't use peer since YunoHost create users with nologin
|
||||
|
|
|
@ -5,8 +5,7 @@ set -e
|
|||
_generate_config() {
|
||||
echo "domains:"
|
||||
# Add yunohost.local (only if yunohost.local ain't already in ynh_domains)
|
||||
if ! echo "$YNH_DOMAINS" | tr ' ' '\n' | grep -q --line-regexp 'yunohost.local'
|
||||
then
|
||||
if ! echo "$YNH_DOMAINS" | tr ' ' '\n' | grep -q --line-regexp 'yunohost.local'; then
|
||||
echo " - yunohost.local"
|
||||
fi
|
||||
for domain in $YNH_DOMAINS; do
|
||||
|
@ -15,10 +14,8 @@ _generate_config() {
|
|||
[[ "$domain" =~ ^[^.]+\.local$ ]] || continue
|
||||
echo " - $domain"
|
||||
done
|
||||
if [[ -e /etc/yunohost/mdns.aliases ]]
|
||||
then
|
||||
for localalias in $(cat /etc/yunohost/mdns.aliases | grep -v "^ *$")
|
||||
do
|
||||
if [[ -e /etc/yunohost/mdns.aliases ]]; then
|
||||
for localalias in $(cat /etc/yunohost/mdns.aliases | grep -v "^ *$"); do
|
||||
echo " - $localalias.local"
|
||||
done
|
||||
fi
|
||||
|
@ -37,10 +34,10 @@ do_pre_regen() {
|
|||
mkdir -p ${pending_dir}/etc/systemd/system/
|
||||
cp yunomdns.service ${pending_dir}/etc/systemd/system/
|
||||
|
||||
getent passwd mdns &>/dev/null || useradd --no-create-home --shell /usr/sbin/nologin --system --user-group mdns
|
||||
getent passwd mdns &> /dev/null || useradd --no-create-home --shell /usr/sbin/nologin --system --user-group mdns
|
||||
|
||||
mkdir -p ${pending_dir}/etc/yunohost
|
||||
_generate_config >${pending_dir}/etc/yunohost/mdns.yml
|
||||
_generate_config > ${pending_dir}/etc/yunohost/mdns.yml
|
||||
}
|
||||
|
||||
do_post_regen() {
|
||||
|
|
|
@ -18,12 +18,12 @@ do_pre_regen() {
|
|||
cp plain/etcdefault ${pending_dir}/etc/default/dnsmasq
|
||||
|
||||
# add resolver file
|
||||
cat plain/resolv.dnsmasq.conf | grep "^nameserver" | shuf >${pending_dir}/etc/resolv.dnsmasq.conf
|
||||
cat plain/resolv.dnsmasq.conf | grep "^nameserver" | shuf > ${pending_dir}/etc/resolv.dnsmasq.conf
|
||||
|
||||
# retrieve variables
|
||||
ipv4=$(curl --max-time 10 -s -4 https://ip.yunohost.org 2>/dev/null || true)
|
||||
ipv4=$(curl --max-time 10 -s -4 https://ip.yunohost.org 2> /dev/null || true)
|
||||
ynh_validate_ip4 "$ipv4" || ipv4='127.0.0.1'
|
||||
ipv6=$(curl --max-time 10 -s -6 https://ip6.yunohost.org 2>/dev/null || true)
|
||||
ipv6=$(curl --max-time 10 -s -6 https://ip6.yunohost.org 2> /dev/null || true)
|
||||
ynh_validate_ip6 "$ipv6" || ipv6=''
|
||||
interfaces="$(ip -j addr show | jq -r '[.[].ifname]|join(" ")')"
|
||||
wireless_interfaces="lo"
|
||||
|
@ -51,8 +51,7 @@ do_pre_regen() {
|
|||
conf_files=$(ls -1 /etc/dnsmasq.d \
|
||||
| awk '/^[^\.]+\.[^\.]+.*$/ { print $1 }')
|
||||
for domain in $conf_files; do
|
||||
if [[ ! $YNH_DOMAINS =~ $domain ]] && [[ ! $domain =~ \.local$ ]]
|
||||
then
|
||||
if [[ ! $YNH_DOMAINS =~ $domain ]] && [[ ! $domain =~ \.local$ ]]; then
|
||||
touch "${dnsmasq_dir}/${domain}"
|
||||
fi
|
||||
done
|
||||
|
@ -68,27 +67,27 @@ do_post_regen() {
|
|||
# Fuck it, those domain/search entries from dhclient are usually annoying
|
||||
# lying shit from the ISP trying to MiTM
|
||||
if grep -q -E "^ *(domain|search)" /run/resolvconf/resolv.conf; then
|
||||
if grep -q -E "^ *(domain|search)" /run/resolvconf/interface/*.dhclient 2>/dev/null; then
|
||||
if grep -q -E "^ *(domain|search)" /run/resolvconf/interface/*.dhclient 2> /dev/null; then
|
||||
sed -E "s/^(domain|search)/#\1/g" -i /run/resolvconf/interface/*.dhclient
|
||||
fi
|
||||
|
||||
grep -q '^supersede domain-name "";' /etc/dhcp/dhclient.conf 2>/dev/null || echo 'supersede domain-name "";' >>/etc/dhcp/dhclient.conf
|
||||
grep -q '^supersede domain-search "";' /etc/dhcp/dhclient.conf 2>/dev/null || echo 'supersede domain-search "";' >>/etc/dhcp/dhclient.conf
|
||||
grep -q '^supersede search "";' /etc/dhcp/dhclient.conf 2>/dev/null || echo 'supersede search "";' >>/etc/dhcp/dhclient.conf
|
||||
grep -q '^supersede domain-name "";' /etc/dhcp/dhclient.conf 2> /dev/null || echo 'supersede domain-name "";' >> /etc/dhcp/dhclient.conf
|
||||
grep -q '^supersede domain-search "";' /etc/dhcp/dhclient.conf 2> /dev/null || echo 'supersede domain-search "";' >> /etc/dhcp/dhclient.conf
|
||||
grep -q '^supersede search "";' /etc/dhcp/dhclient.conf 2> /dev/null || echo 'supersede search "";' >> /etc/dhcp/dhclient.conf
|
||||
systemctl restart resolvconf
|
||||
fi
|
||||
|
||||
# Some stupid things like rabbitmq-server used by onlyoffice won't work if
|
||||
# the *short* hostname doesn't exists in /etc/hosts -_-
|
||||
short_hostname=$(hostname -s)
|
||||
grep -q "127.0.0.1.*$short_hostname" /etc/hosts || echo -e "\n127.0.0.1\t$short_hostname" >>/etc/hosts
|
||||
grep -q "127.0.0.1.*$short_hostname" /etc/hosts || echo -e "\n127.0.0.1\t$short_hostname" >> /etc/hosts
|
||||
|
||||
[[ -n "$regen_conf_files" ]] || return 0
|
||||
|
||||
# Remove / disable services likely to conflict with dnsmasq
|
||||
for SERVICE in systemd-resolved bind9; do
|
||||
systemctl is-enabled $SERVICE &>/dev/null && systemctl disable $SERVICE 2>/dev/null
|
||||
systemctl is-active $SERVICE &>/dev/null && systemctl stop $SERVICE
|
||||
systemctl is-enabled $SERVICE &> /dev/null && systemctl disable $SERVICE 2> /dev/null
|
||||
systemctl is-active $SERVICE &> /dev/null && systemctl stop $SERVICE
|
||||
done
|
||||
|
||||
systemctl restart dnsmasq
|
||||
|
|
|
@ -24,8 +24,7 @@ do_pre_regen() {
|
|||
do_post_regen() {
|
||||
regen_conf_files=$1
|
||||
|
||||
if ls -l /etc/fail2ban/jail.d/*.conf
|
||||
then
|
||||
if ls -l /etc/fail2ban/jail.d/*.conf; then
|
||||
chown root:root /etc/fail2ban/jail.d/*.conf
|
||||
chmod 644 /etc/fail2ban/jail.d/*.conf
|
||||
fi
|
||||
|
|
|
@ -782,4 +782,4 @@
|
|||
"user_import_partial_failed": "L'operació d'importació dels usuaris ha fallat parcialment",
|
||||
"domain_dns_push_record_failed": "No s'ha pogut {action} el registre {type}/{name}: {error}",
|
||||
"registrar_infos": "Informació del registrador"
|
||||
}
|
||||
}
|
|
@ -63,7 +63,7 @@
|
|||
"mail_forward_remove_failed": "Die Weiterleitungs-E-Mail '{mail}' konnte nicht gelöscht werden",
|
||||
"main_domain_change_failed": "Die Hauptdomain konnte nicht geändert werden",
|
||||
"main_domain_changed": "Die Hauptdomain wurde geändert",
|
||||
"pattern_backup_archive_name": "Muss ein gültiger Dateiname mit maximal 30 Zeichen sein, ausschliesslich alphanumerische Zeichen und -_.",
|
||||
"pattern_backup_archive_name": "Muss ein gültiger Dateiname mit maximal 30 Zeichen sein, ausschließlich alphanumerische Zeichen und -_.",
|
||||
"pattern_domain": "Muss ein gültiger Domainname sein (z.B. meine-domain.org)",
|
||||
"pattern_email": "Es muss sich um eine gültige E-Mail-Adresse handeln, ohne '+'-Symbol (z. B. name@domäne.de)",
|
||||
"pattern_firstname": "Muss ein gültiger Vorname sein (mindestens 3 Zeichen)",
|
||||
|
@ -782,4 +782,4 @@
|
|||
"dyndns_set_recovery_password_failed": "Konnte Wiederherstellungspasswort nicht einstellen: {error}",
|
||||
"dyndns_set_recovery_password_success": "Wiederherstellungspasswort eingestellt!",
|
||||
"global_settings_setting_ssh_port_help": "Ein Port unter 1024 wird bevorzugt, um Kaperversuche durch Nicht-Administratordienste auf dem Remote-Computer zu verhindern. Sie sollten auch vermeiden, einen bereits verwendeten Port zu verwenden, z. B. 80 oder 443."
|
||||
}
|
||||
}
|
|
@ -1,4 +1,12 @@
|
|||
{
|
||||
"password_too_simple_1": "Ο κωδικός πρόσβασης πρέπει να έχει τουλάχιστον 8 χαρακτήρες",
|
||||
"aborting": "Ματαίωση."
|
||||
}
|
||||
"aborting": "Ματαίωση.",
|
||||
"action_invalid": "Μη έγκυρη ενέργεια '{action}'",
|
||||
"app_action_broke_system": "Αυτή η ενέργεια φαίνεται να έχει προκαλέσει προβλήματα σε αυτές τις σημαντικές υπηρεσίες: {services}",
|
||||
"app_already_installed": "Η φαρμογή {app} είναι ήδη εγκατεστημένη",
|
||||
"admin_password": "Κωδικός διαχείρισης",
|
||||
"all_users": "Όλοι οι χρήστες YunoHost",
|
||||
"admins": "Διαχειριστές",
|
||||
"app_action_failed": "Αποτυχία εκτέλεσης ενέργειας {action} για την εφαρμογή {app}",
|
||||
"already_up_to_date": "Δεν υπάρχει τίποτα να γίνει. Όλα είναι επικαιροποιημένα."
|
||||
}
|
||||
|
|
|
@ -248,6 +248,13 @@
|
|||
"diagnosis_http_special_use_tld": "Domain {domain} is based on a special-use top-level domain (TLD) such as .local or .test and is therefore not expected to be exposed outside the local network.",
|
||||
"diagnosis_http_timeout": "Timed-out while trying to contact your server from the outside. It appears to be unreachable.<br>1. The most common cause for this issue is that port 80 (and 443) <a href='https://yunohost.org/isp_box_config'>are not correctly forwarded to your server</a>.<br>2. You should also make sure that the service nginx is running<br>3. On more complex setups: make sure that no firewall or reverse-proxy is interfering.",
|
||||
"diagnosis_http_unreachable": "Domain {domain} appears unreachable through HTTP from outside the local network.",
|
||||
"diagnosis_ignore_already_filtered": "(There is already a diagnosis {category} filter with these criterias)",
|
||||
"diagnosis_ignore_criteria_error": "Criterias should be of the form key=value (e.g. domain=yolo.test)",
|
||||
"diagnosis_ignore_filter_added": "Added a {category} diagnosis filter",
|
||||
"diagnosis_ignore_filter_removed": "Removed a {category} diagnosis filter",
|
||||
"diagnosis_ignore_missing_criteria": "You should provide at least one criteria being the diagnosis category to ignore",
|
||||
"diagnosis_ignore_no_filter_found": "(There is no such diagnosis {category} filter with these criterias to remove)",
|
||||
"diagnosis_ignore_no_issue_found": "No issues was found matching the given criteria.",
|
||||
"diagnosis_ignored_issues": "(+ {nb_ignored} ignored issue(s))",
|
||||
"diagnosis_ip_broken_dnsresolution": "Domain name resolution seems to be broken for some reason… Is a firewall blocking DNS requests?",
|
||||
"diagnosis_ip_broken_resolvconf": "Domain name resolution seems to be broken on your server, which seems related to <code>/etc/resolv.conf</code> not pointing to <code>127.0.0.1</code>.",
|
||||
|
@ -309,6 +316,8 @@
|
|||
"diagnosis_regenconf_allgood": "All configuration files are in line with the recommended configuration!",
|
||||
"diagnosis_regenconf_manually_modified": "Configuration file <code>{file}</code> appears to have been manually modified.",
|
||||
"diagnosis_regenconf_manually_modified_details": "This is probably OK if you know what you're doing! YunoHost will stop updating this file automatically… But beware that YunoHost upgrades could contain important recommended changes. If you want to, you can inspect the differences with <cmd>yunohost tools regen-conf {category} --dry-run --with-diff</cmd> and force the reset to the recommended configuration with <cmd>yunohost tools regen-conf {category} --force</cmd>",
|
||||
"diagnosis_rfkill_wifi": "The Wi-Fi card is disabled and a system warning might prevent app installations",
|
||||
"diagnosis_rfkill_wifi_details": "This warning sneaks in many command outputs, breaking some apps. It is usually required to specify your country code with the command <code>sudo raspi-config</code>. Here is the error:<br>{rfkill_wifi_error}",
|
||||
"diagnosis_rootfstotalspace_critical": "The root filesystem only has a total of {space} which is quite worrisome! You will likely run out of disk space very quickly! It's recommended to have at least 16 GB for the root filesystem.",
|
||||
"diagnosis_rootfstotalspace_warning": "The root filesystem only has a total of {space}. This may be okay, but be careful because ultimately you may run out of disk space quickly… It's recommended to have at least 16 GB for the root filesystem.",
|
||||
"diagnosis_security_vulnerable_to_meltdown": "You appear vulnerable to the Meltdown critical security vulnerability",
|
||||
|
@ -449,6 +458,10 @@
|
|||
"global_settings_setting_security_experimental_enabled_help": "Enable experimental security features (don't enable this if you don't know what you're doing!)",
|
||||
"global_settings_setting_smtp_allow_ipv6": "Allow IPv6",
|
||||
"global_settings_setting_smtp_allow_ipv6_help": "Allow the use of IPv6 to receive and send mail",
|
||||
"global_settings_setting_smtp_backup_mx_domains": "Domains to act as secondary MX for",
|
||||
"global_settings_setting_smtp_backup_mx_domains_help": "Allow this server to act as a backup *secondary* MX domain for the listed domain. This means that if the main MX for the domain is not reachable (for example because of an outage), mails will still be sent to this server, which will keep them during a maximum of 20 days and try to relay them to the real destination once it goes back up. Several domains can be provided, separated by commas.",
|
||||
"global_settings_setting_smtp_backup_mx_emails_whitelisted": "SMTP backup MX emails whitelist",
|
||||
"global_settings_setting_smtp_backup_mx_emails_whitelisted_help": "When acting as a secondary MX, the exhaustive list of allowed recipient's email addresses must be provided (otherwise mails will be refused and discarded). Several entries can be provided, separated by commas.",
|
||||
"global_settings_setting_smtp_relay_enabled": "Enable SMTP relay",
|
||||
"global_settings_setting_smtp_relay_enabled_help": "Enable the SMTP relay to use in order to send mail instead of this yunohost instance. Useful if you are in one of this situation: your 25 port is blocked by your ISP or VPS provider, you have a residential IP listed on DUHL, you are not able to configure reverse DNS or this server is not directly exposed on the internet and you want use an other one to send mails.",
|
||||
"global_settings_setting_smtp_relay_host": "SMTP relay host",
|
||||
|
@ -573,7 +586,7 @@
|
|||
"migration_0021_general_warning": "Please note that this migration is a delicate operation. The YunoHost team did its best to review and test it, but the migration might still break parts of the system or its apps.\n\nTherefore, it is recommended to:\n - Perform a backup of any critical data or app. More info on https://yunohost.org/backup;\n - Be patient after launching the migration: Depending on your Internet connection and hardware, it might take up to a few hours for everything to upgrade.",
|
||||
"migration_0021_main_upgrade": "Starting main upgrade…",
|
||||
"migration_0021_modified_files": "Please note that the following files were found to be manually modified and might be overwritten following the upgrade: {manually_modified_files}",
|
||||
"migration_0021_not_buster2": "The current Debian distribution is not Buster! If you already ran the Buster->Bullseye migration, then this error is symptomatic of the fact that the migration procedure was not 100% succesful (otherwise YunoHost would have flagged it as completed). It is recommended to investigate what happened with the support team, who will need the **full** log of the `migration, which can be found in Tools > Logs in the webadmin.",
|
||||
"migration_0021_not_buster2": "The current Debian distribution is not Buster! If you already ran the Buster -> Bullseye migration, then this error is symptomatic of the fact that the migration procedure was not 100% succesful (otherwise YunoHost would have flagged it as completed). It is recommended to investigate what happened with the support team, who will need the **full** log of the migration, which can be found in Tools > Logs in the webadmin.",
|
||||
"migration_0021_not_enough_free_space": "Free space is pretty low in /var/! You should have at least 1GB free to run this migration.",
|
||||
"migration_0021_patch_yunohost_conflicts": "Applying patch to workaround conflict issue…",
|
||||
"migration_0021_patching_sources_list": "Patching the sources.lists…",
|
||||
|
@ -591,12 +604,27 @@
|
|||
"migration_0024_rebuild_python_venv_disclaimer_rebuild": "Rebuilding the virtualenv will be attempted for the following apps (NB: the operation may take some time!): {rebuild_apps}",
|
||||
"migration_0024_rebuild_python_venv_failed": "Failed to rebuild the Python virtualenv for {app}. The app may not work as long as this is not resolved. You should fix the situation by forcing the upgrade of this app using `yunohost app upgrade --force {app}`.",
|
||||
"migration_0024_rebuild_python_venv_in_progress": "Now attempting to rebuild the Python virtualenv for `{app}`",
|
||||
"migration_0027_cleaning_up": "Cleaning up cache and packages not useful anymore…",
|
||||
"migration_0027_delayed_api_restart": "The YunoHost API will automatically be restarted in 15 seconds. It may be unavailable for a few seconds, and then you will have to login again.",
|
||||
"migration_0027_general_warning": "Please note that this migration is a delicate operation. The YunoHost team did its best to review and test it, but the migration might still break parts of the system or its apps.\n\nTherefore, it is recommended to:\n - Perform a backup of any critical data or app. More info on https://yunohost.org/backup;\n - Be patient after launching the migration: Depending on your Internet connection and hardware, it might take up to a few hours for everything to upgrade properly.",
|
||||
"migration_0027_main_upgrade": "Starting main upgrade…",
|
||||
"migration_0027_modified_files": "Please note that the following files were found to be manually modified and might be overwritten following the upgrade: {manually_modified_files}",
|
||||
"migration_0027_not_bullseye": "The current Debian distribution is not Bullseye! If you already ran the Bullseye -> Bookworm migration, then this error is symptomatic of the fact that the migration procedure was not 100% succesful (otherwise YunoHost would have flagged it as completed). It is recommended to investigate what happened with the support team, who will need the **full** log of the migration, which can be found in Tools > Logs in the webadmin.",
|
||||
"migration_0027_not_enough_free_space": "Free space is pretty low in /var/! You should have at least 1GB free to run this migration.",
|
||||
"migration_0027_patch_yunohost_conflicts": "Applying patch to workaround conflict issue…",
|
||||
"migration_0027_patching_sources_list": "Patching the sources.lists file…",
|
||||
"migration_0027_problematic_apps_warning": "Please note that the following possibly problematic installed apps were detected. It looks like those were not installed from the YunoHost app catalog, or are not flagged as 'working'. Consequently, it cannot be guaranteed that they will still work after the upgrade: {problematic_apps}",
|
||||
"migration_0027_start": "Starting migration to Bookworm…",
|
||||
"migration_0027_still_on_bullseye_after_main_upgrade": "Something went wrong during the main upgrade, the system appears to still be on Debian Bullseye.",
|
||||
"migration_0027_system_not_fully_up_to_date": "Your system is not fully up-to-date. Please perform a regular upgrade before running the migration to Bookworm.",
|
||||
"migration_0027_yunohost_upgrade": "Starting YunoHost core upgrade…",
|
||||
"migration_description_0021_migrate_to_bullseye": "Upgrade the system to Debian Bullseye and YunoHost 11.x",
|
||||
"migration_description_0022_php73_to_php74_pools": "Migrate php7.3-fpm 'pool' conf files to php7.4",
|
||||
"migration_description_0023_postgresql_11_to_13": "Migrate databases from PostgreSQL 11 to 13",
|
||||
"migration_description_0024_rebuild_python_venv": "Repair Python app after bullseye migration",
|
||||
"migration_description_0025_global_settings_to_configpanel": "Migrate legacy global settings nomenclature to the new, modern nomenclature",
|
||||
"migration_description_0026_new_admins_group": "Migrate to the new 'multiple admins' system",
|
||||
"migration_description_0027_migrate_to_bookworm": "Upgrade the system to Debian Bookworm and YunoHost 12",
|
||||
"migration_ldap_backup_before_migration": "Creating a backup of LDAP database and apps settings prior to the actual migration.",
|
||||
"migration_ldap_can_not_backup_before_migration": "The backup of the system could not be completed before the migration failed. Error: {error}",
|
||||
"migration_ldap_migration_failed_trying_to_rollback": "Could not migrate… trying to roll back the system.",
|
||||
|
|
|
@ -507,4 +507,4 @@
|
|||
"global_settings_setting_postfix_compatibility_help": "Kongruo vs sekureca kompromiso por la Postfix-servilo. Afektas la ĉifradojn (kaj aliajn aspektojn pri sekureco)",
|
||||
"global_settings_setting_ssh_compatibility_help": "Kongruo vs sekureca kompromiso por la SSH-servilo. Afektas la ĉifradojn (kaj aliajn aspektojn pri sekureco)",
|
||||
"global_settings_setting_smtp_allow_ipv6_help": "Permesu la uzon de IPv6 por ricevi kaj sendi poŝton"
|
||||
}
|
||||
}
|
|
@ -782,4 +782,4 @@
|
|||
"dyndns_set_recovery_password_success": "¡Password de recuperación establecida!",
|
||||
"global_settings_setting_dns_exposure_help": "NB: Esto afecta únicamente a la configuración recomentada de DNS y en las pruebas de diagnóstico. No afecta a la configuración del sistema.",
|
||||
"global_settings_setting_ssh_port_help": "Un puerto menor a 1024 es preferible para evitar intentos de usurpación por servicios no administrativos en la máquina remota. También debe de evitar usar un puerto ya en uso, como el 80 o 443."
|
||||
}
|
||||
}
|
102
locales/eu.json
102
locales/eu.json
|
@ -36,7 +36,7 @@
|
|||
"diagnosis_http_bad_status_code": "Zerbitzari hau ez den beste gailu batek erantzun omen dio eskaerari (agian routerrak).<br>1. Honen arrazoi ohikoena 80 (eta 443) ataka <a href='https://yunohost.org/isp_box_config'>zerbitzarira ondo birbidaltzen ez dela</a> da.<br>2. Konfigurazio konplexua badarabilzu, egiaztatu suebakiak edo reverse-proxyk oztopatzen ez dutela.",
|
||||
"diagnosis_http_timeout": "Denbora agortu da sare lokaletik kanpo zure zerbitzarira konektatzeko ahaleginean. Eskuragarri ez dagoela dirudi.<br>1. 80 (eta 443) ataka <a href='https://yunohost.org/isp_box_config'>zerbitzarira modu egokian birzuzentzen ez direla da</a> ohiko zergatia.<br>2. Badaezpada egiaztatu nginx martxan dagoela.<br>3. Konfigurazio konplexuetan, egiaztatu suebakiak edo reverse-proxyk konexioa oztopatzen ez dutela.",
|
||||
"app_sources_fetch_failed": "Ezinezkoa izan da fitxategiak eskuratzea, zuzena al da URLa?",
|
||||
"app_make_default_location_already_used": "Ezinezkoa izan da '{app}' '{domain}' domeinuan lehenestea, '{other_app}'(e)k lehendik ere erabiltzen duelako",
|
||||
"app_make_default_location_already_used": "Ezin da '{app}' '{domain}' domeinuan lehenetsi, '{other_app}'(e)k lehendik ere erabiltzen duelako",
|
||||
"app_already_installed_cant_change_url": "Aplikazio hau instalatuta dago dagoeneko. URLa ezin da aldatu aukera honekin. Markatu 'app changeurl' markatzeko moduan badago.",
|
||||
"diagnosis_ip_not_connected_at_all": "Badirudi zerbitzaria ez dagoela internetera konektatuta!?",
|
||||
"app_already_up_to_date": "{app} egunean da dagoeneko",
|
||||
|
@ -51,7 +51,7 @@
|
|||
"config_validate_url": "Benetazko URL bat izan behar da",
|
||||
"app_restore_script_failed": "Errorea gertatu da aplikazioa lehengoratzeko aginduan",
|
||||
"app_upgrade_some_app_failed": "Ezinezkoa izan da aplikazio batzuk eguneratzea",
|
||||
"app_install_failed": "Ezinezkoa izan da {app} instalatzea: {error}",
|
||||
"app_install_failed": "Ezin da {app} instalatu: {error}",
|
||||
"diagnosis_basesystem_kernel": "Zerbitzariak Linuxen {kernel_version} kernela darabil",
|
||||
"app_argument_invalid": "Aukeratu balio egoki bat '{name}' argumenturako: {error}",
|
||||
"app_already_installed": "{app} instalatuta dago dagoeneko",
|
||||
|
@ -132,7 +132,7 @@
|
|||
"diagnosis_http_could_not_diagnose": "Ezinezkoa izan da domeinuak IPv{ipversion} kanpotik eskuragarri dauden egiaztatzea.",
|
||||
"diagnosis_http_ok": "{domain} domeinua HTTP bidez bisitatu daiteke sare lokaletik kanpo.",
|
||||
"diagnosis_http_unreachable": "Badirudi {domain} domeinua ez dagoela eskuragarri HTTP bidez sare lokaletik kanpo.",
|
||||
"apps_catalog_failed_to_download": "Ezinezkoa izan da {apps_catalog} aplikazioen zerrenda eskuratzea: {error}",
|
||||
"apps_catalog_failed_to_download": "Ezin da {apps_catalog} aplikazioen zerrenda eskuratu: {error}",
|
||||
"apps_catalog_init_success": "Abiarazi da aplikazioen katalogo sistema!",
|
||||
"apps_catalog_obsolete_cache": "Aplikazioen katalogoaren katxea hutsik edo zaharkituta dago.",
|
||||
"diagnosis_description_mail": "Posta elektronikoa",
|
||||
|
@ -148,18 +148,18 @@
|
|||
"diagnosis_http_hairpinning_issue": "Dirudienez zure sareak ez du hairpinninga gaituta.",
|
||||
"diagnosis_http_partially_unreachable": "Badirudi {domain} domeinua ezin dela bisitatu HTTP bidez IPv{failed} sare lokaletik kanpo, bai ordea IPv{passed} erabiliz.",
|
||||
"backup_archive_cant_retrieve_info_json": "Ezinezkoa izan da '{archive}' fitxategiko informazioa eskuratzea… info.json fitxategia ezin izan da eskuratu (edo ez da baliozko json-a).",
|
||||
"diagnosis_domain_expiration_not_found": "Ezinezkoa izan da domeinu batzuen iraungitze data egiaztatzea",
|
||||
"diagnosis_domain_expiration_not_found": "Ezin da domeinu batzuen iraungitze data egiaztatu",
|
||||
"diagnosis_domain_expiration_not_found_details": "Badirudi {domain} domeinuari buruzko WHOIS informazioak ez duela zehazten noiz iraungiko den?",
|
||||
"certmanager_domain_not_diagnosed_yet": "Oraindik ez dago {domain} domeinurako diagnostikorik. Berrabiarazi diagnostikoak 'DNS balioak' eta 'Web' ataletarako diagnostikoen gunean Let's Encrypt ziurtagirirako prest ote dagoen egiaztatzeko. (Edo zertan ari zaren baldin badakizu, erabili '--no-checks' egiaztatzea desgaitzeko.)",
|
||||
"diagnosis_domain_expiration_warning": "Domeinu batzuk iraungitzear daude!",
|
||||
"app_packaging_format_not_supported": "Aplikazio hau ezin da instalatu YunoHostek ez duelako paketea ezagutzen. Sistema eguneratzea hausnartu beharko zenuke ziur asko.",
|
||||
"diagnosis_dns_try_dyndns_update_force": "Domeinu honen DNS konfigurazioa YunoHostek kudeatu beharko luke automatikoki. Gertatuko ez balitz, eguneratzera behartu zenezake <cmd>yunohost dyndns update --force</cmd> erabiliz.",
|
||||
"app_manifest_install_ask_path": "Aukeratu aplikazio hau instalatzeko URLaren bidea (domeinuaren atzeko aldean)",
|
||||
"app_manifest_install_ask_admin": "Aukeratu administrari bat aplikazio honetarako",
|
||||
"app_manifest_install_ask_admin": "Aukeratu administratzaile bat aplikazio honetarako",
|
||||
"app_manifest_install_ask_password": "Aukeratu administrazio-pasahitz bat aplikazio honetarako",
|
||||
"ask_user_domain": "Erabiltzailearen posta elektroniko eta XMPP konturako erabiliko den domeinua",
|
||||
"app_action_cannot_be_ran_because_required_services_down": "{services} zerbitzuak martxan egon beharko lirateke eragiketa hau exekutatu ahal izateko. Saia zaitez zerbitzuok berrabiarazten (eta ikertu zergatik ez diren abiarazi).",
|
||||
"apps_already_up_to_date": "Egunean daude dagoeneko aplikazio guztiak",
|
||||
"apps_already_up_to_date": "Aplikazio guztiak egunean daude dagoeneko",
|
||||
"app_full_domain_unavailable": "Aplikazio honek bere domeinu propioa behar du, baina beste aplikazio batzuk daude dagoeneko instalatuta '{domain}' domeinuan. Azpidomeinu bat erabil zenezake instalatu nahi duzun aplikaziorako.",
|
||||
"app_install_script_failed": "Errore bat gertatu da aplikazioaren instalatzailearen aginduetan",
|
||||
"diagnosis_basesystem_host": "Zerbitzariak Debian {debian_version} darabil",
|
||||
|
@ -263,14 +263,14 @@
|
|||
"log_user_import": "Inportatu erabiltzaileak",
|
||||
"diagnosis_mail_fcrdns_ok": "Alderantzizko DNSa zuzen konfiguratuta dago!",
|
||||
"diagnosis_mail_queue_unavailable_details": "Errorea: {error}",
|
||||
"dyndns_provider_unreachable": "Ezinezkoa izan da DynDNS {provider} enpresarekin konektatzea: agian zure YunoHost zerbitzaria ez dago internetera konektatuta edo dynette zerbitzaria ez dago martxan.",
|
||||
"dyndns_provider_unreachable": "Ezin da DynDNS {provider} enpresarekin konektatu: agian zure YunoHost zerbitzaria ez dago internetera konektatuta edo dynette zerbitzaria ez dago martxan.",
|
||||
"extracting": "Ateratzen…",
|
||||
"diagnosis_ports_unreachable": "{port}. ataka ez dago eskuragarri kanpotik.",
|
||||
"diagnosis_regenconf_manually_modified_details": "Ez dago arazorik zertan ari zaren baldin badakizu! YunoHostek fitxategi hau automatikoki eguneratzeari utziko dio… Baina kontuan izan YunoHosten eguneraketek aldaketa garrantzitsuak izan ditzaketela. Nahi izatekotan, desberdintasunak aztertu ditzakezu <cmd>yunohost tools regen-conf {category} --dry-run --with-diff</cmd> komandoa exekutatuz, eta gomendatutako konfiguraziora bueltatu <cmd>yunohost tools regen-conf {category} --force</cmd> erabiliz",
|
||||
"dyndns_domain_not_provided": "{provider} DynDNS enpresak ezin du {domain} domeinua eskaini.",
|
||||
"firewall_reload_failed": "Ezinezkoa izan da suebakia birkargatzea",
|
||||
"hook_name_unknown": "'{name}' 'hook' izen ezezaguna",
|
||||
"domain_deletion_failed": "Ezinezkoa izan da {domain} ezabatzea: {error}",
|
||||
"domain_deletion_failed": "Ezin da {domain} ezabatu: {error}",
|
||||
"log_regen_conf": "Berregin '{}' sistemaren konfigurazioa",
|
||||
"dpkg_lock_not_available": "Ezin da komando hau une honetan exekutatu beste aplikazio batek dpkg (sistemaren paketeen kudeatzailea) blokeatuta duelako, erabiltzen ari baita",
|
||||
"group_created": "'{group}' taldea sortu da",
|
||||
|
@ -351,7 +351,7 @@
|
|||
"diagnosis_mail_queue_unavailable": "Ezinezkoa da ilaran zenbat posta elektroniko dauden kontsultatzea",
|
||||
"log_user_create": "Gehitu '{}' erabiltzailea",
|
||||
"group_cannot_edit_visitors": "'bisitariak' taldea ezin da eskuz moldatu. Saiorik hasi gabeko bisitariak barne hartzen dituen talde berezia da",
|
||||
"diagnosis_ram_verylow": "Sistemak RAM memoriaren {available} baino ez ditu erabilgarri; memoria guztiaren ({total}) %{available_percent}a bakarrik!",
|
||||
"diagnosis_ram_verylow": "Sistemak RAM memoriaren {available} baino ez ditu erabilgarri; memoria guztiaren ({total}) %{available_percent}a.",
|
||||
"diagnosis_ram_low": "Sistemak RAM memoriaren {available} ditu erabilgarri; memoria guztiaren ({total}) %{available_percent}a. Adi ibili.",
|
||||
"diagnosis_ram_ok": "Sistemak RAM memoriaren {available} ditu oraindik erabilgarri; memoria guztiaren ({total}) %{available_percent}a.",
|
||||
"diagnosis_swap_none": "Sistemak ez du swap-ik. Gutxienez {recommended} izaten saiatu beharko zinateke, sistema memoriarik gabe gera ez dadin.",
|
||||
|
@ -387,7 +387,7 @@
|
|||
"diagnosis_mail_outgoing_port_25_ok": "SMTP posta zerbitzaria posta elektronikoa bidaltzeko gai da (25. atakaren irteera ez dago blokeatuta).",
|
||||
"diagnosis_ports_partially_unreachable": "{port}. ataka ez dago eskuragarri kanpotik IPv{failed} erabiliz.",
|
||||
"diagnosis_ports_forwarding_tip": "Arazoa konpontzeko, litekeena da operadorearen routerrean ataken birbideraketa konfiguratu behar izatea, <a href='https://yunohost.org/isp_box_config'>https://yunohost.org/isp_box_config</a>-n agertzen den bezala",
|
||||
"domain_creation_failed": "Ezinezkoa izan da {domain} domeinua sortzea: {error}",
|
||||
"domain_creation_failed": "Ezin da {domain} domeinua sortu: {error}",
|
||||
"domains_available": "Erabilgarri dauden domeinuak:",
|
||||
"group_already_exist_on_system": "{group} taldea existitzen da dagoeneko sistemaren taldeetan",
|
||||
"diagnosis_processes_killed_by_oom_reaper": "Memoria agortu eta sistemak prozesu batzuk amaituarazi behar izan ditu. Honek esan nahi du sistemak ez duela memoria nahikoa edo prozesuren batek memoria gehiegi behar duela. Amaituarazi d(ir)en prozesua(k):\n{kills_summary}",
|
||||
|
@ -400,7 +400,7 @@
|
|||
"domain_cannot_remove_main": "Ezin duzu '{domain}' ezabatu domeinu nagusia delako. Beste domeinu bat ezarri beharko duzu nagusi bezala 'yunohost domain main-domain -n <another-domain>' erabiliz; honako hauek dituzu aukeran: {other_domains}",
|
||||
"domain_created": "Sortu da domeinua",
|
||||
"domain_dyndns_already_subscribed": "Dagoeneko izena eman duzu DynDNS domeinu batean",
|
||||
"domain_hostname_failed": "Ezinezkoa izan da hostname berria ezartzea. Honek arazoak ekar litzake etorkizunean (litekeena da ondo egotea).",
|
||||
"domain_hostname_failed": "Ezin da hostname berria ezarri. Honek arazoak ekar litzake etorkizunean (litekeena da ondo egotea).",
|
||||
"domain_uninstall_app_first": "Honako aplikazio hauek domeinuan instalatuta daude:\n{apps}\n\nDesinstalatu 'yunohost app remove the_app_id' exekutatuz edo alda itzazu beste domeinu batera 'yunohost app change-url the_app_id' erabiliz domeinua ezabatu baino lehen",
|
||||
"file_does_not_exist": "{path} fitxategia ez da existitzen.",
|
||||
"firewall_rules_cmd_failed": "Suebakiko arau batzuen exekuzioak huts egin du. Informazio gehiago erregistroetan.",
|
||||
|
@ -423,7 +423,7 @@
|
|||
"domain_cert_gen_failed": "Ezinezkoa izan da ziurtagiria sortzea",
|
||||
"field_invalid": "'{}' ez da baliogarria",
|
||||
"diagnosis_mail_outgoing_port_25_blocked_relay_vpn": "Operadore batzuei bost axola zaie internetaren neutraltasuna (Net Neutrality) eta ez dute 25. ataka desblokeatzen uzten.<br>- Operadore batzuek <a href='https://yunohost.org/email_configure_relay'>relay posta zerbitzari bat</a> eskaini dezakete, baina kasu horretan zure posta elektronikoa zelatatu dezakete.<br>- Pribatutasuna bermatzeko *IP publikoa* duen VPN bat erabiltzea izan daiteke irtenbidea. Ikus <a href='https://yunohost.org/vpn_advantage'>https://yunohost.org/vpn_advantage</a><br>- Edo <a href='https://yunohost.org/isp'>operadore desberdin batera aldatu</a>",
|
||||
"ldap_server_down": "Ezin izan da LDAP zerbitzarira konektatu",
|
||||
"ldap_server_down": "Ezin da LDAP zerbitzarira konektatu",
|
||||
"ldap_server_is_down_restart_it": "LDAP zerbitzaria ez dago martxan, saia zaitez berrabiarazten…",
|
||||
"log_app_upgrade": "'{}' aplikazioa eguneratu",
|
||||
"log_tools_shutdown": "Itzali zerbitzaria",
|
||||
|
@ -461,7 +461,7 @@
|
|||
"user_import_success": "Erabiltzaileak arazorik gabe inportatu dira",
|
||||
"yunohost_already_installed": "YunoHost instalatuta dago dagoeneko",
|
||||
"migrations_success_forward": "{id} migrazioak amaitu du",
|
||||
"migrations_to_be_ran_manually": "{id} migrazioa eskuz abiarazi behar da. Joan Tresnak → Migrazioak atalera administrazio-atarian edo bestela exekutatu 'yunohost tools migrations run'.",
|
||||
"migrations_to_be_ran_manually": "{id} migrazioa eskuz abiarazi behar da. Joan Tresnak → Migrazioak atalera administrazio-gunean edo bestela exekutatu 'yunohost tools migrations run'.",
|
||||
"permission_currently_allowed_for_all_users": "Baimen hau erabiltzaile guztiei esleitzen zaie eta baita beste talde batzuei ere. Litekeena da 'all users' baimena edo esleituta duten taldeei baimena kendu nahi izatea.",
|
||||
"permission_require_account": "'{permission}' baimena zerbitzarian kontua duten erabiltzaileentzat da eta, beraz, ezin da gaitu bisitarientzat.",
|
||||
"postinstall_low_rootfsspace": "'root' fitxategi-sistemak 10 GB edo espazio gutxiago dauka, kezkatzekoa dena! Litekeena da espaziorik gabe geratzea aurki! Gomendagarria da 'root' fitxategi-sistemak gutxienez 16 GB libre izatea. Jakinarazpen honen ondoren YunoHost instalatzen jarraitu nahi baduzu, berrabiarazi agindua '--force-diskspace' gehituz",
|
||||
|
@ -515,7 +515,7 @@
|
|||
"service_disable_failed": "Ezin izan da '{service}' zerbitzua geldiarazi zerbitzaria abiaraztean.\n\nZerbitzuen erregistro berrienak: {logs}",
|
||||
"migrations_skip_migration": "{id} migrazioa saihesten…",
|
||||
"upnp_disabled": "UPnP itzalita dago",
|
||||
"main_domain_change_failed": "Ezinezkoa izan da domeinu nagusia aldatzea",
|
||||
"main_domain_change_failed": "Ezin da domeinu nagusia aldatu",
|
||||
"regenconf_failed": "Ezinezkoa izan da ondorengo atal(ar)en konfigurazioa berregitea: {categories}",
|
||||
"pattern_email_forward": "Helbide elektroniko baliagarri bat izan behar da, '+' karakterea onartzen da (adibidez: izena+urtea@domeinua.eus)",
|
||||
"regenconf_file_manually_removed": "'{conf}' konfigurazio fitxategia eskuz ezabatu da eta ez da berriro sortuko",
|
||||
|
@ -579,7 +579,7 @@
|
|||
"port_already_opened": "{port}. ataka dagoeneko irekita dago {ip_version} konexioetarako",
|
||||
"user_home_creation_failed": "Ezin izan da erabiltzailearentzat '{home}' direktorioa sortu",
|
||||
"user_unknown": "Erabiltzaile ezezaguna: {user}",
|
||||
"yunohost_postinstall_end_tip": "Instalazio ondorengo prozesua amaitu da! Sistemaren konfigurazioa bukatzeko:\n- erabili 'Diagnostikoak' gunea ohiko arazoei aurre hartzeko. Administrazio-atarian abiarazi edo 'yunohost diagnosis run' exekutatu;\n- irakurri 'Finalizing your setup' eta 'Getting to know YunoHost' atalak. Dokumentazioan aurki ditzakezu: https://yunohost.org/admindoc.",
|
||||
"yunohost_postinstall_end_tip": "Instalazio ondorengo prozesua amaitu da! Sistemaren konfigurazioa bukatzeko:\n- erabili 'Diagnostikoak' gunea ohiko arazoei aurre hartzeko. Abiarazi administrazio-gunean edo exekutatu 'yunohost diagnosis run';\n- irakurri 'Finalizing your setup' eta 'Getting to know YunoHost' atalak. Dokumentazioan aurki ditzakezu: https://yunohost.org/admindoc.",
|
||||
"yunohost_not_installed": "YunoHost ez da zuzen instalatu. Exekutatu 'yunohost tools postinstall'",
|
||||
"unlimit": "Mugarik ez",
|
||||
"restore_already_installed_apps": "Ondorengo aplikazioak ezin dira lehengoratu dagoeneko instalatuta daudelako: {apps}",
|
||||
|
@ -590,9 +590,9 @@
|
|||
"migration_ldap_rollback_success": "Sistema lehengoratu da.",
|
||||
"regenconf_need_to_explicitly_specify_ssh": "SSH ezarpenak eskuz aldatu dira, baina aldaketak erabiltzeko '--force' zehaztu behar duzu 'ssh' atalean.",
|
||||
"regex_incompatible_with_tile": "/!\\ Pakete-arduradunak! {permission}' baimenak show_tile aukera 'true' bezala dauka eta horregatik ezin duzue regex URLa URL nagusi bezala ezarri",
|
||||
"root_password_desynchronized": "Administrariaren pasahitza aldatu da baina YunoHostek ezin izan du aldaketa root pasahitzera hedatu!",
|
||||
"root_password_desynchronized": "Administratzailearen pasahitza aldatu da baina YunoHostek ezin izan du aldaketa root pasahitzera hedatu!",
|
||||
"server_shutdown": "Zerbitzaria itzaliko da",
|
||||
"service_stop_failed": "Ezin izan da '{service}' zerbitzua geldiarazi\n\nZerbitzuen azken erregistroak: {logs}",
|
||||
"service_stop_failed": "Ezin da '{service}' zerbitzua geldiarazi\n\nZerbitzuaren azken erregistroak: {logs}",
|
||||
"service_unknown": "'{service}' zerbitzu ezezaguna",
|
||||
"show_tile_cant_be_enabled_for_url_not_defined": "Ezin duzu 'show_tile' gaitu une honetan, '{permission}' baimenerako URL bat zehaztu behar duzulako",
|
||||
"upnp_enabled": "UPnP piztuta dago",
|
||||
|
@ -601,8 +601,8 @@
|
|||
"restore_hook_unavailable": "'{part}'-(e)rako lehengoratze agindua ez dago erabilgarri ez sisteman ezta fitxategian ere",
|
||||
"restore_cleaning_failed": "Ezin izan dira lehengoratzeko behin-behineko fitxategiak ezabatu",
|
||||
"restore_confirm_yunohost_installed": "Ziur al zaude dagoeneko instalatuta dagoen sistema lehengoratu nahi duzula? [{answers}]",
|
||||
"restore_may_be_not_enough_disk_space": "Badirudi zure sistemak ez duela nahikoa espazio (erabilgarri: {free_space} B, beharrezkoa {needed_space} B, segurtasuneko tartea: {margin} B)",
|
||||
"restore_not_enough_disk_space": "Ez dago nahikoa espazio (erabilgarri: {free_space} B, beharrezkoa {needed_space} B, segurtasuneko tartea: {margin} B)",
|
||||
"restore_may_be_not_enough_disk_space": "Badirudi zure sistemak ez duela nahikoa espazio (erabilgarri: {free_space} B, beharrezkoa {needed_space} B, segurtasun-tartea: {margin} B)",
|
||||
"restore_not_enough_disk_space": "Ez dago nahikoa espazio (erabilgarri: {free_space} B, beharrezkoa {needed_space} B, segurtasun-tartea: {margin} B)",
|
||||
"restore_running_hooks": "Lehengoratzeko 'hook'ak exekutatzen…",
|
||||
"restore_system_part_failed": "Ezinezkoa izan da sistemaren '{part}' atala lehengoratzea",
|
||||
"server_reboot": "Zerbitzaria berrabiaraziko da",
|
||||
|
@ -620,24 +620,24 @@
|
|||
"service_description_redis-server": "Datuak bizkor atzitzeko, zereginak lerratzeko eta programen arteko komunikaziorako datubase berezi bat da",
|
||||
"service_description_rspamd": "Spama bahetu eta posta elektronikoarekin zerikusia duten bestelako futzioen ardura dauka",
|
||||
"service_description_slapd": "Erabiltzaileak, domeinuak eta hauei lotutako informazioa gordetzen du",
|
||||
"service_description_yunohost-api": "YunoHosten web-atariaren eta sistemaren arteko hartuemana kudeatzen du",
|
||||
"service_description_yunohost-api": "YunoHosten web-interfazearen eta sistemaren arteko hartuemana kudeatzen du",
|
||||
"domain_config_default_app": "Lehenetsitako aplikazioa",
|
||||
"tools_upgrade": "Sistemaren paketeak eguneratzen",
|
||||
"tools_upgrade_failed": "Ezin izan dira paketeak eguneratu: {packages_list}",
|
||||
"service_description_postgresql": "Aplikazioen datuak gordetzen ditu (SQL datubasea)",
|
||||
"migration_0021_start": "Bullseye (e)rako migrazioa abiarazten",
|
||||
"migration_0021_start": "Bullseye-rako migrazioa abiarazten",
|
||||
"migration_0021_patching_sources_list": "sources.lists petatxatzen…",
|
||||
"migration_0021_main_upgrade": "Eguneraketa nagusia abiarazten…",
|
||||
"migration_0021_still_on_buster_after_main_upgrade": "Zerbaitek huts egin du eguneraketa nagusian, badirudi sistemak oraindik darabilela Debian Buster",
|
||||
"migration_0021_yunohost_upgrade": "YunoHosten muineko eguneraketa abiarazten…",
|
||||
"migration_0021_not_enough_free_space": "/var/-enerabilgarri dagoen espazioa oso txikia da! Guxtienez GB 1 izan beharko zenuke erabilgarri migrazioari ekiteko.",
|
||||
"migration_0021_system_not_fully_up_to_date": "Sistema ez dago erabat egunean. Egizu eguneraketa arrunt bat Bullseye-(e)rako migrazioa abiarazi baino lehen.",
|
||||
"migration_0021_yunohost_upgrade": "YunoHosten muineko bertsio-berriztea abiarazten…",
|
||||
"migration_0021_not_enough_free_space": "/var/-en erabilgarri dagoen espazioa oso txikia da! Gutxienez GB 1 izan beharko zenuke erabilgarri migrazioari ekiteko.",
|
||||
"migration_0021_system_not_fully_up_to_date": "Sistema ez dago erabat egunean. Egizu eguneraketa arrunt bat Bullseye-rako migrazioa abiarazi baino lehen.",
|
||||
"migration_0021_general_warning": "Kontuan hartu migrazio hau konplexua dela. YunoHost taldeak ahalegin handia egin du probatzeko, baina hala ere migrazioak sistemaren zatiren bat edo aplikazioak apurt litzake.\n\nHorregatik, gomendagarria da:\n\t- Datu edo aplikazio garrantzitsuen babeskopia egitea. Informazio gehiago: https://yunohost.org/backup;\n\t- Ez izan presarik migrazioa abiaraztean: zure internet eta hardwarearen arabera ordu batzuk ere iraun lezake eguneraketa prozesuak.",
|
||||
"migration_0021_modified_files": "Kontuan hartu ondorengo fitxategiak eskuz moldatu omen direla eta eguneraketak berridatziko dituela: {manually_modified_files}",
|
||||
"migration_0021_cleaning_up": "Katxea eta erabilgarriak ez diren paketeak garbitzen…",
|
||||
"migration_0021_patch_yunohost_conflicts": "Arazo gatazkatsu bati adabakia jartzen…",
|
||||
"migration_description_0021_migrate_to_bullseye": "Eguneratu sistema Debian Bullseye eta Yunohost 11.x-ra",
|
||||
"migration_0021_problematic_apps_warning": "Kontuan izan ziur asko gatazkatsuak izango diren odorengo aplikazioak aurkitu direla. Badirudi ez zirela YunoHost aplikazioen katalogotik instalatu, edo ez daude 'badabiltza' bezala etiketatuak. Ondorioz, ezin da bermatu eguneratu ondoren funtzionatzen jarraituko dutenik: {problematic_apps}",
|
||||
"migration_description_0021_migrate_to_bullseye": "Bertsio-berritu sistema Debian Bullseye eta YunoHost 11.x-ra",
|
||||
"migration_0021_problematic_apps_warning": "Kontuan izan ziur asko gatazkatsuak izango diren ondorengo aplikazioak aurkitu direla. Badirudi ez zirela YunoHost aplikazioen katalogotik instalatu, edo ez daude 'badabiltza' bezala etiketatuak. Ondorioz, ezin da bermatu eguneratu ondoren funtzionatzen jarraituko dutenik: {problematic_apps}",
|
||||
"migration_0023_not_enough_space": "{path}-en ez dago toki nahikorik migrazioa abiarazteko.",
|
||||
"migration_0023_postgresql_11_not_installed": "PostgreSQL ez zegoen zure isteman instalatuta. Ez dago egitekorik.",
|
||||
"migration_0023_postgresql_13_not_installed": "PostgreSQL 11 dago instalatuta baina PostgreSQL 13 ez!? Zerbait arraroa gertatu omen zaio zure sistemari :(…",
|
||||
|
@ -654,8 +654,8 @@
|
|||
"global_settings_setting_ssh_password_authentication_help": "Baimendu pasahitz bidezko autentikazioa SSHrako",
|
||||
"global_settings_setting_ssh_port": "SSH ataka",
|
||||
"global_settings_setting_webadmin_allowlist_help": "Administrazio-atarira sar daitezken IP helbideak. CIDR notazioa ahalbidetzen da.",
|
||||
"global_settings_setting_webadmin_allowlist_enabled_help": "Baimendu IP zehatz batzuk bakarrik administrazio-atarian.",
|
||||
"global_settings_setting_smtp_allow_ipv6_help": "Baimendu IPv6 posta elektronikoa jaso eta bidaltzeko",
|
||||
"global_settings_setting_webadmin_allowlist_enabled_help": "Baimendu IP zehatz batzuk bakarrik administrazio-gunerako.",
|
||||
"global_settings_setting_smtp_allow_ipv6_help": "Gaitu IPv6 posta elektronikoa jaso eta bidaltzeko",
|
||||
"global_settings_setting_smtp_relay_enabled_help": "YunoHosten ordez posta elektronikoa bidaltzeko SMTP relay helbidea. Erabilgarri izan daiteke egoera hauetan: operadore edo VPS enpresak 25. ataka blokeatzen badu, DUHLen zure etxeko IPa ageri bada, ezin baduzu alderantzizko DNSa ezarri edo zerbitzari hau ez badago zuzenean internetera konektatuta baina posta elektronikoa bidali nahi baduzu.",
|
||||
"migration_0024_rebuild_python_venv_broken_app": "{app} aplikazioari ez ikusiarena egin zaio ezin delako ingurune birtuala modu errazean birsortu. Horren ordez, aplikazioaren eguneraketa behartzen saia zaitezke `yunohost app upgrade --force {app}` arazoa konpontzeko.",
|
||||
"migration_0024_rebuild_python_venv_disclaimer_rebuild": "Ondorengo aplikazioen virtualenv-a birsortzeko saiakera egingo da (eragiketak luze jo dezake!): {rebuild_apps}",
|
||||
|
@ -664,12 +664,12 @@
|
|||
"migration_0024_rebuild_python_venv_failed": "{app} aplikazioaren Python virtualenv-aren birsorkuntza saiakerak huts egin du. Litekeena da aplikazioak ez funtzionatzea arazoa konpondu arte. Aplikazioaren eguneraketa behartu beharko zenuke ondorengo komandoarekin: `yunohost app upgrade --force {app}`.",
|
||||
"migration_description_0024_rebuild_python_venv": "Konpondu Python aplikazioa Bullseye eguneraketa eta gero",
|
||||
"migration_0024_rebuild_python_venv_disclaimer_base": "Debian Bullseye eguneraketa dela-eta, Python aplikazio batzuk birsortu behar dira Debianekin datorren Pythonen bertsiora egokitzeko (teknikoki 'virtualenv' deritzaiona birsortu behar da). Egin artean, litekeena da Python aplikazio horiek ez funtzionatzea. YunoHost saia daiteke beherago ageri diren aplikazioen virtualenv edo ingurune birtualak birsortzen. Beste aplikazio batzuen kasuan, edo birsortze saiakerak kale egingo balu, aplikazio horien eguneraketa behartu beharko duzu.",
|
||||
"migration_0021_not_buster2": "Zerbitzariak darabilen Debian bertsioa ez da Buster! Dagoeneko Buster -> Bullseye migrazioa exekutatu baduzu, errore honek migrazioa erabat arrakastatsua izan ez zela esan nahi du (bestela YunoHostek amaitutzat markatuko luke). Komenigarria izango litzateke, laguntza taldearekin batera, zer gertatu zen aztertzea. Horretarako `migrazioaren erregistro **osoa** beharko duzue, Tresnak > Erregistroak atalean eskuragarri dagoena.",
|
||||
"migration_0021_not_buster2": "Zerbitzariak darabilen Debian bertsioa ez da Buster! Dagoeneko Buster -> Bullseye migrazioa exekutatu baduzu, errore honek migrazioa erabat arrakastatsua izan ez zela esan nahi du (bestela YunoHostek amaitutzat markatuko luke). Komenigarria izango litzateke, laguntza taldearekin batera, zer gertatu zen aztertzea. Horretarako migrazioaren erregistro **osoa** beharko duzue, Tresnak > Erregistroak atalean eskuragarri dagoena.",
|
||||
"admins": "Administratzaileek",
|
||||
"app_action_failed": "{app} aplikaziorako {action} eragiketak huts egin du",
|
||||
"config_action_disabled": "Ezin izan da '{action}' eragiketa exekutatu ezgaituta dagoelako, egiaztatu bere mugak betetzen dituzula. Laguntza: {help}",
|
||||
"all_users": "YunoHosten erabiltzaile guztiek",
|
||||
"app_manifest_install_ask_init_admin_permission": "Nork izan beharko luke aplikazio honetako administrazio aukeretara sarbidea? (Aldatzea dago)",
|
||||
"app_manifest_install_ask_init_admin_permission": "Nork izan beharko luke aplikazio honetako administrazio-aukeretara sarbidea? (Aldatzea dago)",
|
||||
"app_manifest_install_ask_init_main_permission": "Nork izan beharko luke aplikazio honetara sarbidea? (Aldatzea dago)",
|
||||
"ask_admin_fullname": "Administratzailearen izen osoa",
|
||||
"ask_admin_username": "Administratzailearen erabiltzaile-izena",
|
||||
|
@ -681,7 +681,7 @@
|
|||
"domain_config_cert_summary_expired": "LARRIA: Uneko ziurtagiria ez da baliozkoa! HTTPS ezin da erabili!",
|
||||
"domain_config_cert_summary_selfsigned": "ADI: Uneko zirutagiria norberak sinatutakoa da. Web-nabigatzaileek bisitariak izutuko dituen mezu bat erakutsiko dute!",
|
||||
"global_settings_setting_postfix_compatibility": "Postfixekin bateragarritasuna",
|
||||
"global_settings_setting_root_access_explain": "Linux sistemetan 'root' administratzaile gorena da. YunoHosten testuinguruan, zuzeneko 'root' SSH saioa ezgaituta dago defektuz, zerbitzariaren sare lokaletik ez bada. 'administrariak' taldeko kideek sudo komandoa erabili dezakete root bailitzan jarduteko terminalaren bidez. Hala ere lagungarri izan liteke root pasahitz (sendo) bat izatea sistema arazteko egoeraren batean administratzaile arruntek saiorik hasi ezin balute.",
|
||||
"global_settings_setting_root_access_explain": "Linux sistemetan 'root' administratzaile gorena da. YunoHosten testuinguruan, zuzeneko 'root' SSH saioa ezgaituta dago defektuz, zerbitzariaren sare lokaletik ez bada. 'administratzaileak' taldeko kideek sudo komandoa erabili dezakete root bailitzan jarduteko terminalaren bidez. Hala ere lagungarri izan liteke root pasahitz (sendo) bat izatea sistema arazteko egoeraren batean administratzaile arruntek saiorik hasi ezin balute.",
|
||||
"log_settings_reset": "Berrezarri ezarpenak",
|
||||
"log_settings_reset_all": "Berrezarri ezarpen guztiak",
|
||||
"root_password_changed": "root pasahitza aldatu da",
|
||||
|
@ -695,7 +695,7 @@
|
|||
"diagnosis_using_stable_codename": "<cmd>apt</cmd> (sistemaren pakete kudeatzailea) 'stable' (egonkorra) izen kodea duten paketeak instalatzeko ezarrita dago une honetan, eta ez uneko Debianen bertsioaren (bullseye) izen kodea.",
|
||||
"diagnosis_using_yunohost_testing": "<cmd>apt</cmd> (sistemaren pakete kudeatzailea) YunoHosten muinerako 'testing' (proba) izen kodea duten paketeak instalatzeko ezarrita dago une honetan.",
|
||||
"diagnosis_using_yunohost_testing_details": "Ez dago arazorik zertan ari zaren baldin badakizu, baina arretaz irakurri oharrak YunoHosten eguneraketak instalatu baino lehen! 'testing' (proba) bertsioak ezgaitu nahi badituzu, kendu <cmd>testing</cmd> gakoa <cmd>/etc/apt/sources.list.d/yunohost.list</cmd> fitxategitik.",
|
||||
"global_settings_setting_smtp_allow_ipv6": "Baimendu IPv6",
|
||||
"global_settings_setting_smtp_allow_ipv6": "Gaitu IPv6",
|
||||
"global_settings_setting_smtp_relay_host": "SMTP errele-ostatatzailea",
|
||||
"domain_config_acme_eligible": "ACME hautagarritasuna",
|
||||
"domain_config_acme_eligible_explain": "Ez dirudi domeinu hau Let's Encrypt ziurtagirirako prest dagoenik. Egiaztatu DNS ezarpenak eta zerbitzariaren HTTP irisgarritasuna. <a href='#/diagnosis'>Diagnostikoen guneko</a> 'DNS erregistroak' eta 'Web' atalek zer dagoen gaizki ulertzen lagun zaitzakete.",
|
||||
|
@ -720,12 +720,12 @@
|
|||
"global_settings_setting_ssh_password_authentication": "Pasahitz bidezko autentifikazioa",
|
||||
"global_settings_setting_user_strength_help": "Betekizun hauek lehenbizikoz sortzerakoan edo pasahitza aldatzerakoan bete behar dira soilik",
|
||||
"global_settings_setting_webadmin_allowlist": "Administrazio-atarira sartzeko baimendutako IPak",
|
||||
"global_settings_setting_webadmin_allowlist_enabled": "Gaitu administrazio-ataria sartzeko baimendutako IPak",
|
||||
"global_settings_setting_webadmin_allowlist_enabled": "Gaitu administrazio-gunera sartzeko baimendutako IPak",
|
||||
"invalid_credentials": "Pasahitz edo erabiltzaile-izen baliogabea",
|
||||
"log_resource_snippet": "Baliabide bat eguneratzen / eskuratzen / eskuragarritasuna uzten",
|
||||
"log_settings_set": "Aplikatu ezarpenak",
|
||||
"migration_description_0025_global_settings_to_configpanel": "Migratu ezarpen globalen nomenklatura zaharra izendegi berri eta modernora",
|
||||
"migration_description_0026_new_admins_group": "Migratu 'administrari bat baino gehiago' sistema berrira",
|
||||
"migration_description_0026_new_admins_group": "Migratu 'administratzaile bat baino gehiago' sistema berrira",
|
||||
"password_confirmation_not_the_same": "Pasahitzak ez datoz bat",
|
||||
"password_too_long": "Aukeratu 127 karaktere baino laburragoa den pasahitz bat",
|
||||
"diagnosis_using_stable_codename_details": "Ostatatzaileak zerbait oker ezarri duenean gertatu ohi da hau. Arriskutsua da, Debianen datorren bertsioa 'estable' (egonkorra) bilakatzen denean, <cmd>apt</cmd>-k sistemaren pakete guztiak bertsio-berritzen saiatuko da, beharrezko migrazio-prozedurarik burutu gabe. Debianen gordailuan apt iturria editatzen konpontzea da gomendioa, <cmd>stable</cmd> gakoa <cmd>bullseye</cmd> gakoarekin ordezkatuz. Ezarpen-fitxategia <cmd>/etc/apt/sources.list</cmd> izan beharko litzateke, edo <cmd>/etc/apt/sources.list.d/</cmd> direktorioko fitxategiren bat.",
|
||||
|
@ -739,7 +739,7 @@
|
|||
"app_resource_failed": "{app} aplikaziorako baliabideen eguneraketak / prestaketak / askapenak huts egin du: {error}",
|
||||
"app_not_enough_disk": "Aplikazio honek {required} espazio libre behar ditu.",
|
||||
"app_yunohost_version_not_supported": "Aplikazio honek YunoHost >= {required} behar du baina unean instalatutako bertsioa {current} da",
|
||||
"global_settings_setting_passwordless_sudo": "Baimendu administrariek 'sudo' erabiltzea pasahitzak berriro idatzi beharrik gabe",
|
||||
"global_settings_setting_passwordless_sudo": "Baimendu administratzaileek 'sudo' erabiltzea pasahitzak berriro idatzi beharrik gabe",
|
||||
"global_settings_setting_portal_theme": "Atariko gaia",
|
||||
"global_settings_setting_portal_theme_help": "Atariko gai propioak sortzeari buruzko informazio gehiago: https://yunohost.org/theming",
|
||||
"invalid_shell": "Shell baliogabea: {shell}",
|
||||
|
@ -765,7 +765,7 @@
|
|||
"group_user_add": "'{user}' erabiltzailea '{group}' taldera gehituko da",
|
||||
"ask_dyndns_recovery_password_explain": "Aukeratu DynDNS domeinurako berreskuratze-pasahitza, etorkizunean berrezarri beharko bazenu.",
|
||||
"ask_dyndns_recovery_password_explain_during_unsubscribe": "Sartu DynDNS domeinuaren berreskuratze-pasahitza.",
|
||||
"dyndns_no_recovery_password": "Ez da berreskuratze-pasahitzik zehaztu! Domeinuaren gaineko kontrola galduz gero, YunoHost taldeko administrariarekin jarri beharko zara harremanetan!",
|
||||
"dyndns_no_recovery_password": "Ez da berreskuratze-pasahitzik zehaztu! Domeinuaren gaineko kontrola galduz gero, YunoHost taldeko administratzailearekin jarri beharko zara harremanetan!",
|
||||
"ask_dyndns_recovery_password": "DynDNS berreskuratze-pasahitza",
|
||||
"dyndns_subscribed": "DynDNS domeinua harpidetu da",
|
||||
"dyndns_subscribe_failed": "Ezin izan da DynDNS domeinua harpidetu: {error}",
|
||||
|
@ -781,5 +781,33 @@
|
|||
"dyndns_set_recovery_password_invalid_password": "Berreskuratze-pasahitza ezartzeak huts egin du: pasahitza ez da nahikoa sendoa",
|
||||
"dyndns_set_recovery_password_failed": "Berreskuratze-pasahitza ezartzeak huts egin du: {error}",
|
||||
"dyndns_set_recovery_password_success": "Berreskuratze-pasahitza ezarri da!",
|
||||
"global_settings_setting_ssh_port_help": "1024 baino ataka txikiago bat izan beharko litzateke, zerbitzu ez-administratzaileek urruneko makinan usurpazio-saiorik egin ez dezaten. Lehendik ere erabiltzen ari diren atakak ere ekidin beharko zenituzke, 80 edo 443 kasu."
|
||||
"global_settings_setting_ssh_port_help": "1024 baino ataka txikiago bat izan beharko litzateke, zerbitzu ez-administratzaileek urruneko makinan usurpazio-saiorik egin ez dezaten. Lehendik ere erabiltzen ari diren atakak ere ekidin beharko zenituzke, 80 edo 443 kasu.",
|
||||
"migration_0027_start": "Bookworm-erako migrazioa abiarazten…",
|
||||
"migration_0027_still_on_bullseye_after_main_upgrade": "Zerbaitek kale egin du bertsio-berritze nagusian; sistemak oraindik Debian Bullseye darabilela dirudi.",
|
||||
"migration_0027_general_warning": "Migrazioa tentuz ibiltzeko prozedura da. YunoHosten taldeak ahal izan duen guztia egin du berrikusi eta probatzeko, baina hala ere sistemaren atalak edo aplikazioak honda litzake.\n\nBeraz, gomendagarria da:\n - Datu edo aplikazio garrantzitsuen babeskopia egitea. Informazio gehiagorako: https://yunohost.org/backup;\n - Ez izan presarik migrazioa abiaraztean: internet konexioaren eta hardwarearen arabera, litekeena da ordu apur batzuk ere behar izatea guztia dagokion bezala bertsio-berritzeko.",
|
||||
"migration_description_0027_migrate_to_bookworm": "Bertsio-berritu sistema Debian Bookworm eta YunoHost 12-ra",
|
||||
"migration_0027_system_not_fully_up_to_date": "Sistema ez dago erabat egunean. Egizu eguneraketa arrunt bat Bookworm-erako migrazioa abiarazi baino lehen.",
|
||||
"diagnosis_ignore_filter_added": "{category} atalaren diagnostikorako iragazkia gehitu da",
|
||||
"migration_0027_problematic_apps_warning": "Kontuan izan ziur asko gatazkatsuak izango diren ondorengo aplikazioak aurkitu direla. Badirudi ez zirela YunoHost aplikazioen katalogotik instalatu, edo ez daude 'badabiltza' bezala etiketatuak. Ondorioz, ezin da bermatu eguneratu ondoren funtzionatzen jarraituko dutenik: {problematic_apps}",
|
||||
"diagnosis_ignore_missing_criteria": "Gutxienez irizpide bat gehitu behar duzu atalaren diagnostikoak kontuan har ez dezan",
|
||||
"migration_0027_not_bullseye": "Zerbitzariak darabilen Debian bertsioa ez da Bullseye! Dagoeneko Bullseye -> Bookworm migrazioa exekutatu baduzu, errore honek migrazioa erabat arrakastatsua izan ez zela esan nahi du (bestela YunoHostek amaitutzat markatuko luke). Komenigarria izango litzateke, laguntza taldearekin batera, zer gertatu zen aztertzea. Horretarako migrazioaren erregistro **osoa** beharko duzue, Tresnak > Erregistroak atalean eskuragarri dagoena.",
|
||||
"diagnosis_ignore_criteria_error": "Irizpideek forma hau izan behar dute: gakoa=balorea (adib. domain=yolo.test)",
|
||||
"diagnosis_ignore_already_filtered": "(Badago lehendik ere irizpide horiek dituen {category} atalaren diagnostikorako iragazkia)",
|
||||
"diagnosis_ignore_filter_removed": "{category} atalaren diagnostikorako iragazkia kendu da",
|
||||
"diagnosis_ignore_no_filter_found": "(Ez dago irizpide horiek dituen {category} atalaren diagnostikorako iragazkirik)",
|
||||
"diagnosis_ignore_no_issue_found": "Ez da arazorik aurkitu emandako irizpideekin.",
|
||||
"migration_0027_delayed_api_restart": "YunoHosten APIa 15 segundu barru berrabiaraziko da automatikoki. Litekeena da tarte batez erabilgarri egoteari uztea eta ondoren berriro hasi beharko duzu saioa.",
|
||||
"migration_0027_main_upgrade": "Bertsio-berritze nagusia abiarazten…",
|
||||
"migration_0027_cleaning_up": "Erabilgarri izateari utzi dioten katxe eta paketeak garbitzen…",
|
||||
"migration_0027_yunohost_upgrade": "YunoHosten muineko bertsio-berriztea abiarazten…",
|
||||
"migration_0027_patch_yunohost_conflicts": "Arazo gatazkatsu bati adabakia jartzen…",
|
||||
"migration_0027_modified_files": "Ondorengo fitxategiak eskuz moldatu direla antzeman da eta litekeena da bertsio-berritzeak gainean idaztea: {manually_modified_files}",
|
||||
"migration_0027_not_enough_free_space": "/var/-en erabilgarri dagoen espazioa oso txikia da! Gutxienez GB 1 izan beharko zenuke erabilgarri migrazioari ekiteko.",
|
||||
"migration_0027_patching_sources_list": "sources.lists fitxategia petatxatzen…",
|
||||
"global_settings_setting_smtp_backup_mx_emails_whitelisted": "Baimendutako posta elektronikoen MXren SMTP babeskopia",
|
||||
"global_settings_setting_smtp_backup_mx_domains": "Bigarren mailako MX gisa jarduteko domeinuak",
|
||||
"global_settings_setting_smtp_backup_mx_domains_help": "Zerbitzari honek zerrendan agertzen den domeinurako *bigarren mailako* MX domeinu gisa jardun dezake. Domeinurako lehenetsitako MX lortu ezin denean (adibidez, itzalaldi baten ondorioz), mezuak bigarren zerbitzari horretara bidaliko dira —gehienez 20 egunez mantenduko dituena— eta berriro eskuragarri dagoenean benetako helburura helarazten saiatuko da. Hainbat domeinu zehaztu daitezke, komaz bereizita.",
|
||||
"global_settings_setting_smtp_backup_mx_emails_whitelisted_help": "Bigarren mailako MX gisa jarduten duenean, baimendutako hartzaileen posta elektronikoko helbideen zerrenda zehatza eman beharko da (bestela, mezuak ukatu eta baztertuko dira). Hainbat sarrera eman daitezke, komaz bereizita.",
|
||||
"diagnosis_rfkill_wifi_details": "Ohartarazpena komando askotan ageri da, aplikazio batzuk hautsiz. Herrialdearen kodea zehaztuz konpon daiteke <code>sudo raspi-config</code> komandoaren bidez. Hau da errorea:<br>{rfkill_wifi_error}",
|
||||
"diagnosis_rfkill_wifi": "Wi-Fi txartela ezgaituta dago eta sistemaren ohartarazpen batek aplikazioen instalazioak eragotzi ditzake"
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue