diff --git a/scripts/_common.sh b/scripts/_common.sh index 124b61d..44aed53 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -7,6 +7,8 @@ # dependencies used by the app pkg_dependencies="libpq5" +pkg_image="vaultwarden/server" + #================================================= # PERSONAL HELPERS #================================================= diff --git a/scripts/install b/scripts/install index 44c183a..1e26415 100644 --- a/scripts/install +++ b/scripts/install @@ -93,7 +93,7 @@ ynh_script_progression --message="Setting up source files..." ynh_app_setting_set --app=$app --key=final_path --value=$final_path # Download, check integrity, uncompress and patch the source from app.src -ynh_docker_image_extract --dest_dir="$final_path/build/" --image_spec="vaultwarden/server:$(ynh_app_upstream_version)" +ynh_docker_image_extract --dest_dir="$final_path/build/" --image_spec="$pkg_image:$(ynh_app_upstream_version)" mkdir -p "$final_path/live/" chmod 750 "$final_path" diff --git a/scripts/upgrade b/scripts/upgrade index 1a5526e..e719e01 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -143,7 +143,7 @@ then ynh_script_progression --message="Upgrading source files..." # Download, check integrity, uncompress the source of vaultwarden from app.src to his build directory - ynh_docker_image_extract --dest_dir="$final_path/build/" --image_spec="vaultwarden/server:$(ynh_app_upstream_version)" + ynh_docker_image_extract --dest_dir="$final_path/build/" --image_spec="$pkg_image:$(ynh_app_upstream_version)" mkdir -p "$final_path/live/" fi diff --git a/scripts/ynh_docker_image_extract b/scripts/ynh_docker_image_extract index 4dc6061..4c19d13 100644 --- a/scripts/ynh_docker_image_extract +++ b/scripts/ynh_docker_image_extract @@ -3,11 +3,10 @@ # # This script pulls and extracts all files from an image in Docker Hub. # -# usage: ynh_docker_image_extract --dest_dir=dest_dir --image_spec=image_spec [--os_arch_variant=os_arch_variant] [--keep="file1 file2"] +# usage: ynh_docker_image_extract --dest_dir=dest_dir --image_spec=image_spec [--os_arch_variant=os_arch_variant] # | arg: -d, --dest_dir= - Directory where to setup sources # | arg: -i, --image_spec= - Image specification -# | arg: -o, --os_arch_variant= - OS, architecture and variant seen as OS/ARCH. on Docker Hub -# | 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/' +# | arg: -o, --os_arch_variant= - OS, architecture and variant seen as OS/ARCH on Docker Hub default:linux/$YNH_ARCH. # # Pull and extract all files from the 'hello-world' image tagged 'latest'. # example: ynh_docker_image_extract --dest_dir="dest_dir" --image_spec="hello-world:latest" @@ -31,129 +30,14 @@ # Requires YunoHost version *.*.* or higher. ynh_docker_image_extract() { # Declare an array to define the options of this helper. - local legacy_args=diok - local -A args_array=([d]=dest_dir= [i]=image_spec= [o]=os_arch_variant= [k]=keep=) + local legacy_args=dio + local -A args_array=([d]=dest_dir= [i]=image_spec= [o]=os_arch_variant=) local dest_dir local image_spec local os_arch_variant - local keep # Manage arguments with getopts ynh_handle_getopts_args "$@" - os_arch_variant="${os_arch_variant:-}" - keep="${keep:-}" - - have_curl() { - command -v curl >/dev/null - } - - have_wget() { - command -v wget >/dev/null - } - - if ! have_curl && ! have_wget; then - ynh_die --message="This script requires either curl or wget." - fi - - # Given a JSON input on stdin, extract the string value associated with the - # specified key. This avoids an extra dependency on a tool like `jq`. - extract() { - local key="$1" - # Extract "":"" (assumes key/val won't contain double quotes). - # The colon may have whitespace on either side. - grep -o "\"${key}\"[[:space:]]*:[[:space:]]*\"[^\"]\+\"" | - # Extract just by deleting the last '"', and then greedily deleting - # everything up to '"'. - sed -e 's/"$//' -e 's/.*"//' - } - - # Fetch a URL to stdout. Up to two header arguments may be specified: - # - # fetch [name1: value1] [name2: value2] - # - fetch() { - if have_curl; then - if [ $# -eq 2 ]; then - set -- -H "$2" "$1" - elif [ $# -eq 3 ]; then - set -- -H "$2" -H "$3" "$1" - fi - curl -sSL "$@" - else - if [ $# -eq 2 ]; then - set -- --header "$2" "$1" - elif [ $# -eq 3 ]; then - set -- --header "$2" --header "$3" "$1" - fi - wget -qO- "$@" - fi - } - - IFS='/' read -ra newarr <<< "$os_arch_variant" - os=${newarr[0]:-'linux'} - arch=${newarr[1]:-$YNH_ARCH} - variant=${newarr[2]:-} - - image="${image_spec%%:*}" - if [ "${image#*/}" = "${image}" ]; then - # Docker official images are in the 'library' namespace. - image="library/${image}" - fi - - tag="${image_spec#*:}" - if [ "${tag}" = "${image_spec}" ]; then - tag=latest - fi - - digest="${image_spec#*:}" - if [[ "${digest}" != sha* ]]; then - if [ -z "$variant" ] - then - digest=$(fetch https://hub.docker.com/v2/repositories/$image/tags/$tag/ | jq -r '.images[] | select(.os=="'$os'" and .architecture=="'$arch'").digest') - else - digest=$(fetch https://hub.docker.com/v2/repositories/$image/tags/$tag/ | jq -r '.images[] | select(.os=="'$os'" and .architecture=="'$arch'" and .variant=="'$variant'").digest') - fi - else - tag=unknow - fi - - # https://docs.docker.com/registry/spec/auth/token/#how-to-authenticate - api_token_url="https://auth.docker.io/token?service=registry.docker.io&scope=repository:$image:pull" - - # https://github.com/docker/distribution/blob/master/docs/spec/api.md#pulling-an-image-manifest - manifest_url="https://registry-1.docker.io/v2/${image}/manifests/$digest" - - # https://github.com/docker/distribution/blob/master/docs/spec/api.md#pulling-a-layer - blobs_base_url="https://registry-1.docker.io/v2/${image}/blobs" - - # Getting API token - token=$(fetch "${api_token_url}" | extract 'token') - auth_header="Authorization: Bearer $token" - v2_header="Accept: application/vnd.docker.distribution.manifest.v2+json" - - # Getting image manifest for $image:$tag $digest - layers=$(fetch "${manifest_url}" "${auth_header}" "${v2_header}" | - # Extract `digest` values only after the `layers` section appears. - sed -n '/"layers":/,$ p' | - extract 'digest') - - if [ -z "${layers}" ]; then - ynh_die --message="No layers returned. Verify that the image and tag are valid." - 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 + os_arch_variant="${os_arch_variant:-"linux/$YNH_ARCH"}" # Extract source into the app dir mkdir --parents "$dest_dir" @@ -162,23 +46,14 @@ ynh_docker_image_extract() { _ynh_apply_default_permissions $dest_dir fi - for layer in $layers; do - hash="${layer#sha256:}" - # Fetching and extracting layer ${hash} - fetch "${blobs_base_url}/${layer}" "${auth_header}" | gzip -d | tar -C "${dest_dir}" -xf - - # Ref: https://github.com/moby/moby/blob/master/image/spec/v1.2.md#creating-an-image-filesystem-changeset - # https://github.com/moby/moby/blob/master/pkg/archive/whiteouts.go - # Search for "whiteout" files to indicate files deleted in this layer. - OLD_IFS="${IFS}" - find "${dest_dir}" -name '.wh.*' | while IFS= read -r f; do - dir="${f%/*}" - wh_file="${f##*/}" - file="${wh_file#.wh.}" - # Delete both the whiteout file and the whited-out file. - rm -rf "${dir}/${wh_file}" "${dir}/${file}" - done - IFS="${OLD_IFS}" - done + tempdir="$(mktemp -d)" + pushd $tempdir + git init -q + git remote add -f -t main origin https://github.com/jjlin/docker-image-extract.git > /dev/null 2>&1 + git checkout -q -b main origin/main + ./docker-image-extract -p $os_arch_variant -o $dest_dir $image_spec 2>&1 + popd + rm -rf $tempdir # Apply patches if [ -d "$YNH_APP_BASEDIR/sources/patches/" ]; then @@ -198,40 +73,4 @@ ynh_docker_image_extract() { if test -e "$YNH_APP_BASEDIR/sources/extra_files/${image_spec}"; then cp --archive $YNH_APP_BASEDIR/sources/extra_files/$image_spec/. "$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")" - cp --archive "$keep_dir/$stuff_to_keep" "$dest_dir/$stuff_to_keep" - fi - done - fi - rm -rf /var/cache/yunohost/files_to_keep_during_setup_source/ } - -# -# Copyright (c) 2020-2021, Jeremy Lin -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. -#