aglsetup: generate setup manifest file 21/16721/13
authorStephane Desneux <stephane.desneux@iot.bzh>
Fri, 21 Sep 2018 11:12:22 +0000 (11:12 +0000)
committerStéphane Desneux <stephane.desneux@iot.bzh>
Tue, 9 Oct 2018 13:58:34 +0000 (13:58 +0000)
This patch modifies aglsetup to output the execution context in a
"setup manifest" located in $builddir/aglsetup.manifest

This file can then be processed by another script (distro-manifest-generator.sh)
to generate a complete distro manifest at build time.

Bug-AGL: SPEC-720, SPEC-1741

Change-Id: I1f9bc8a6d8bc4c659e59ed0025f71ad9e1c86355
Signed-off-by: Stephane Desneux <stephane.desneux@iot.bzh>
scripts/.aglsetup_genconfig.bash
scripts/distro-manifest-generator.sh [new file with mode: 0755]

index b0d24e5..1e6eb1e 100755 (executable)
@@ -455,6 +455,8 @@ EOF
        $BUILDDIR/conf/setup.* \
        $BUILDDIR/conf/*.log
 
+####### step 1: generate configuration file #######
+
 if [[ -f $BUILDDIR/conf/local.conf || -f $BUILDDIR/conf/bblayers.conf ]]; then
        info "Configuration files already exist:"
        for x in $BUILDDIR/conf/local.conf $BUILDDIR/conf/bblayers.conf; do
@@ -466,6 +468,45 @@ else
        genconfig
 fi
 
+####### step 2: generate aglsetup.manifest #######
+
+SETUP_MANIFEST=aglsetup.manifest
+
+infon "Generating setup manifest: $BUILDDIR/$SETUP_MANIFEST ... "
+for x in /etc/os-release /usr/lib/os-release; do
+       [[ -f $x ]] && . $x
+done
+FEATURES_md5=$(echo $FEATURES|md5sum -|awk '{print $1;}')
+cat <<EOF >$BUILDDIR/$SETUP_MANIFEST
+# ----------------------------------------------
+# This fragment has been generated by $SCRIPT at setup time
+
+# distro name
+DIST_DISTRO_NAME="AGL"
+
+# target machine as passed to $SCRIPT
+DIST_MACHINE="$MACHINE"
+
+# features as resolved by $SCRIPT
+DIST_FEATURES="$FEATURES"
+DIST_FEATURES_MD5="${FEATURES_md5}"
+
+# build host information deduced from os-release
+DIST_BUILD_HOST="$(id -un)@$(hostname -f || hostname || hostname -s)"
+DIST_BUILD_OS="${PRETTY_NAME:-${NAME} ${VERSION} [COMPUTED]}"
+
+# meta directory
+DIST_METADIR="$METADIR"
+
+# timestamp
+DIST_SETUP_TS="$(date -u +%Y%m%d_%H%M%S_%Z)"
+
+# ------------ end of $SCRIPT fragment --------
+EOF
+info "OK"
+
+####### step 3: generate agl-init-build-env #######
+
 # always generate setup script in builddir: it can be sourced later manually without re-running the setup
 infon "Generating setup file: $BUILDDIR/agl-init-build-env ... "
 
@@ -477,11 +518,19 @@ fi
 if [ -n "\$SSTATE_DIR" ]; then
        BB_ENV_EXTRAWHITE="\$BB_ENV_EXTRAWHITE SSTATE_DIR"
 fi
+
+# build manifest generator used in distro-build-manifest.bb
+BB_ENV_EXTRAWHITE="\$BB_ENV_EXTRAWHITE DISTRO_SETUP_MANIFEST DISTRO_MANIFEST_GENERATOR"
+export DISTRO_SETUP_MANIFEST=$(realpath -Ls $BUILDDIR)/$SETUP_MANIFEST
+export DISTRO_MANIFEST_GENERATOR=$(dirname $(realpath $BASH_SOURCE))/distro-manifest-generator.sh
+
 export BB_ENV_EXTRAWHITE
 unset TEMPLATECONF
 EOF
 info "OK"
 
+####### step 4: generate output script #######
+
 # finally, generate output script if requested by caller
 if [[ -n "$SETUPSCRIPT" ]]; then
        debug "generating setupscript in $SETUPSCRIPT"
diff --git a/scripts/distro-manifest-generator.sh b/scripts/distro-manifest-generator.sh
new file mode 100755 (executable)
index 0000000..9a910e5
--- /dev/null
@@ -0,0 +1,146 @@
+#!/usr/bin/env bash
+
+################################################################################
+#
+# The MIT License (MIT)
+#
+# Copyright (c) 2018 Stéphane Desneux <sdx@iot.bzh>
+#
+# 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.
+#
+################################################################################
+
+function _getgitmanifest() {
+       # this function takes the setup.manifest generated by setup script and uses DIST_METADIR
+       # to analyze git repos
+
+       local manifest=$1 mode=$2
+       [[ -f $manifest ]] && source $manifest || { echo "$BASH_SOURCE: Invalid setup manifest '$manifest'" >&2; return 1; }
+       [[ ! -d "$DIST_METADIR" ]] && {
+               echo "$BASH_SOURCE: Invalid meta directory. Check variable DIST_METADIR in manifest file '$manifest'." >&2
+               echo "$BASH_SOURCE: Also, check directory '$DIST_METADIR'." >&2
+               return 2
+       }
+       local GIT=$(which git) REALPATH=$(which realpath)
+       [[ ! -x $GIT ]] && { echo "$BASH_SOURCE: Unable to find git command in $PATH." >&2; return 3; }
+       [[ ! -x $REALPATH ]] && { echo "$BASH_SOURCE: Unable to find realpath command in $PATH." >&2; return 4; }
+
+       local gitrepo gitrev metagitdir sep=""
+       DIST_LAYERS=""
+       for metagitdir in $(ls -d $DIST_METADIR/*/.git); do
+               gitrepo=$($REALPATH -Ls $metagitdir/.. --relative-to=$DIST_METADIR)
+               pushd $DIST_METADIR/$gitrepo &>/dev/null && {
+                       gitrev=$( { $GIT describe --long --dirty --always 2>/dev/null || echo "unknown_revision"; } | tr ' \t' '__' )
+                       popd &>/dev/null
+               } || {
+                       gitrev=unknown
+               }
+               DIST_LAYERS="${DIST_LAYERS}${sep}${gitrepo}:${gitrev}"
+               sep=" "
+       done
+
+       # layers checksum
+       DIST_LAYERS_MD5=$(echo $DIST_LAYERS|md5sum -|awk '{print $1;}')
+
+       # compute build hash
+       DIST_BUILD_HASH="F${DIST_FEATURES_MD5:0:8}-L${DIST_LAYERS_MD5:0:8}"
+       DIST_BUILD_ID="${DIST_DISTRO_NAME}-${DIST_MACHINE}-F${DIST_FEATURES_MD5:0:8}-L${DIST_LAYERS_MD5:0:8}"
+
+       # compute setup manifest path and build TS
+       DIST_SETUP_MANIFEST="$($REALPATH $manifest)"
+
+       # Manifest build timestamp
+       DIST_BUILD_TS="$(date -u +%Y%m%d_%H%M%S_%Z)"
+
+       # what to retain from setup manifest?
+       # to generate the full list: cat setup.manifest  | grep = | cut -f1 -d"=" | awk '{printf("%s ",$1);}'
+       declare -A SETUP_VARS
+       SETUP_VARS[deploy]="DIST_MACHINE DIST_FEATURES DIST_FEATURES_MD5 DIST_BUILD_HOST DIST_BUILD_OS DIST_SETUP_TS"
+       SETUP_VARS[target]="DIST_MACHINE DIST_FEATURES"
+       SETUP_VARS[sdk]="DIST_MACHINE DIST_FEATURES"
+
+       # extra vars not coming from setup.manifest but generated here
+       declare -A EXTRA_VARS
+       EXTRA_VARS[deploy]="DIST_SETUP_MANIFEST DIST_BUILD_TS DIST_LAYERS DIST_LAYERS_MD5 DIST_BUILD_HASH DIST_BUILD_ID"
+       EXTRA_VARS[target]="DIST_LAYERS DIST_BUILD_HASH DIST_BUILD_ID"
+       EXTRA_VARS[sdk]="DIST_LAYERS DIST_BUILD_HASH DIST_BUILD_ID"
+
+       echo "# setup variables in $mode mode"
+       for x in ${SETUP_VARS[$mode]}; do
+               echo "$x=\"${!x}\""
+       done
+       echo
+
+       echo "# set by $BASH_SOURCE"
+       for x in ${EXTRA_VARS[$mode]}; do
+               echo "$x=\"${!x}\""
+       done
+}
+
+function getmanifest() {
+       local rc=0
+       echo "# DISTRO BUILD MANIFEST"
+       echo
+
+       # add layers manifest
+       echo "# ----- this fragment has been generated by $BASH_SOURCE"
+       _getgitmanifest $1 $2 || rc=$?
+       echo "# ------------ end of $BASH_SOURCE fragment --------"
+
+       return $rc
+}
+
+set -e
+
+verbose=0
+if [[ "$1" =~ ^(-v|--verbose)$ ]]; then
+       shift
+       verbose=1
+fi
+
+if [[ -f "$1" ]]; then
+       manifest=$1
+       shift
+
+       # default mode
+       mode=${1:-deploy}
+       case $mode in
+               deploy|target|sdk) mode=$mode;;
+               *) echo "Invalid mode specified. Allow modes are: deploy target sdk"; exit 42;;
+       esac
+
+       getmanifest $manifest $mode | { [[ $verbose == 1 ]] && cat || sed -e 's/#.*$//g;/^\s*$/d'; }
+       exit ${PIPESTATUS[0]}
+else
+       cat <<EOF >&2
+Usage: $0 [-v|--verbose] <setup_manifest_file> [mode]
+   Options:
+      -v|--verbose: generate comments in the output file
+
+   <setup_manifest_file> is generated from setup script in the specified build dir
+
+   [mode] specifies the destination for the generated manifest
+   Accepted values:
+      'deploy' : for the tmp/deploy/images/* directories
+      'target' : for the manifest to be installed inside a target image
+      'sdk'    : for the manifest to be installed inside the SDK
+EOF
+       exit 56
+fi
+