Merge "Improve dockerfile for Centos7"
[oom/offline-installer.git] / build / package.sh
1 #! /usr/bin/env bash
2
3 #   COPYRIGHT NOTICE STARTS HERE
4 #
5 #   Copyright 2018-2019 © Samsung Electronics Co., Ltd.
6 #
7 #   Licensed under the Apache License, Version 2.0 (the "License");
8 #   you may not use this file except in compliance with the License.
9 #   You may obtain a copy of the License at
10 #
11 #       http://www.apache.org/licenses/LICENSE-2.0
12 #
13 #   Unless required by applicable law or agreed to in writing, software
14 #   distributed under the License is distributed on an "AS IS" BASIS,
15 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 #   See the License for the specific language governing permissions and
17 #   limitations under the License.
18 #
19 #   COPYRIGHT NOTICE ENDS HERE
20
21
22 # Scope of this packaging script is to generate tarfiles for offline installation
23 # Build of any additional artifacts is out of scope for this script
24 set -e
25
26 crash () {
27     local exit_code="$1"
28     local cause="$2"
29     echo "Packaging script finished prematurely"
30     echo "Cause: $2"
31     exit "${exit_code}"
32 }
33
34 crash_arguments () {
35     echo "Missing some mandatory arguments!"
36     usage
37     exit 1
38 }
39
40 usage () {
41     echo "Usage:"
42     echo "   ./$(basename $0) <project_name> <version> <packaging_target_dir> [--conf <file>] [--force]"
43     echo ""
44     echo "Options:"
45     echo "   --force Remove packaging_target_dir if exists prior to script execution"
46     echo "   --conf  Custom configuration file path for script"
47     echo ""
48     echo "Example:"
49     echo "   ./$(basename $0) myproject 1.0.1 /tmp/package --conf ~/myproject.conf"
50     echo ""
51     echo "packaging_target_dir will be created if does not exist. All tars will be produced into it."
52 }
53
54 function create_tar {
55     local tar_dir="$1"
56     local tar_name="$2"
57
58     cd ${tar_dir}
59     touch ${tar_name} # Trick to avoid sporadic "tar: .: file changed as we read it" warning message
60     tar --exclude=${tar_name} -cf ../${tar_name} .
61     cd - &> /dev/null # Trick to avoid printing new dir on stdout
62
63     # Remove packaged folders
64     find ${tar_dir}/* -maxdepth 0 -type d -exec rm -rf '{}' \;
65     # Remove packaged files
66     find ${tar_dir}/* ! -name ${tar_name} -exec rm '{}' \;
67     echo "Tar file created to $(dirname ${tar_dir})/${tar_name}"
68 }
69
70 function create_pkg {
71     local pkg_type="$1"
72     echo "[Creating ${pkg_type} package]"
73     create_tar "${PKG_ROOT}" offline-${PROJECT_NAME}-${PROJECT_VERSION}-${pkg_type}.tar
74     rm -rf "${PKG_ROOT}"
75 }
76
77 function add_metadata {
78     local metafile="$1"
79     echo "Project name: ${PROJECT_NAME}" >> "${metafile}"
80     echo "Project version: ${PROJECT_VERSION}" >> "${metafile}"
81     echo "Package date: ${TIMESTAMP}" >> "${metafile}"
82 }
83
84 function add_additions {
85     local source="$1"
86     local target="$2"
87     if [ -d "${source}" ]; then
88         mkdir -p "${target}/$(basename $source)"
89         cp -r "${source}" "${target}"
90         echo "Adding directory  ... $(basename $source)"
91     else
92         if [ -f "${source}" ]; then
93              cp "${source}" "${target}"
94              echo "Adding file       ... $(basename $source)"
95         else
96              crash 4 "Invalid source specified for packaging: $1"
97         fi
98     fi
99 }
100
101 function build_sw_artifacts {
102     cd ${LOCAL_PATH}/../ansible/docker
103     ./build_ansible_image.sh
104     if [ $? -ne 0 ]; then
105         crash 5 "Building of ansible runner image failed."
106     fi
107     cd -
108 }
109
110 function create_sw_package {
111     PKG_ROOT="${PACKAGING_TARGET_DIR}/sw"
112
113     # Create directory structure of the sw package
114     mkdir -p "${PKG_ROOT}"
115     cp -r ${LOCAL_PATH}/../ansible "${PKG_ROOT}"
116
117     # Add application additional files/dirs into package based on package.conf
118     for item in "${APP_CONFIGURATION[@]}";do
119         # all SW package addons are expected within ./ansible/application folder
120         add_additions "${item}" "${PKG_ROOT}/${APPLICATION_FILES_IN_PACKAGE}"
121     done
122
123     # Application Helm charts
124     # To be consistent with resources and aux dir, create charts dir even if no charts provided.
125     mkdir -p ${PKG_ROOT}/${HELM_CHARTS_DIR_IN_PACKAGE}
126     if [ ! -z "${HELM_CHARTS_DIR}" ];
127     then
128         echo "Add application Helm charts"
129         # Copy charts available for ansible playbook to use/move them to target server/dir
130         cp -r "${HELM_CHARTS_DIR}"/* ${PKG_ROOT}/${HELM_CHARTS_DIR_IN_PACKAGE}
131     else
132         echo "No Helm charts defined, no application will be automatically installed by this package!"
133     fi
134
135     # Add metadata to the package
136     add_metadata "${PKG_ROOT}"/package.info
137
138     # Create sw tar package
139     create_pkg sw
140 }
141
142 function create_resource_package {
143     PKG_ROOT="${PACKAGING_TARGET_DIR}/resources"
144
145     # Create directory structure of the resource package
146     mkdir -p "${PKG_ROOT}"
147
148     # Add artifacts into resource package based on package.conf config
149     if [ ! -z ${APP_BINARY_RESOURCES_DIR} ]; then
150         cp -r ${APP_BINARY_RESOURCES_DIR}/* ${PKG_ROOT}
151     fi
152
153     # tar file with nexus_data is expected, we should find and untar it
154     # before resource.tar is created
155     for i in `ls -1 ${PKG_ROOT} | grep tar`; do
156         tar tvf "${PKG_ROOT}/${i}" | grep nexus_data &> /dev/null
157         if [ $? -eq 0 ]; then
158             echo "Debug: tar file with nexus blobs detected ${PKG_ROOT}/${i}. Start unarchive ..."
159             tar xf "${PKG_ROOT}/${i}" -C "${PKG_ROOT}" &> /dev/null
160             echo "Debug: unarchive finished. Removing original file"
161             rm -f "${PKG_ROOT}/${i}"
162         fi
163     done
164
165     create_pkg resources
166 }
167
168 function create_aux_package {
169     PKG_ROOT="${PACKAGING_TARGET_DIR}/aux"
170
171     # Create directory structure of the aux resource package
172     mkdir -p "${PKG_ROOT}"
173
174     # Add artifacts into resource packagee based on package.conf config
175     for item in "${APP_AUX_BINARIES[@]}";do
176         add_additions "${item}" "${PKG_ROOT}"
177     done
178
179     create_pkg aux-resources
180 }
181
182 #
183 # =================== Main ===================
184 #
185
186 PROJECT_NAME="$1"
187 PROJECT_VERSION="$2"
188 PACKAGING_TARGET_DIR="$3"
189
190 TIMESTAMP=$(date -u +%Y%m%dT%H%M%S)
191 SCRIPT_DIR=$(dirname "${0}")
192 LOCAL_PATH=$(readlink -f "$SCRIPT_DIR")
193
194 # Relative location inside the package for application related files.
195 # Application means Kubernetes application installed by Helm charts on ready cluster (e.g. onap).
196 APPLICATION_FILES_IN_PACKAGE="ansible/application"
197
198 # Relative location inside the package to place Helm charts to be available for
199 # Ansible process to transfer them into machine (infra node) running Helm repository.
200 # NOTE: This is quite hardcoded place to put them and agreement with Ansible code
201 # is done in ansible/group_vars/all.yml with variable "app_helm_charts_install_directory"
202 # whihc value must match to value of this variable (with exception of slash '/'
203 # prepended so that ansible docker/chroot process can see the dir).
204 # This variable can be of course changed in package.conf if really needed if
205 # corresponding ansible variable "app_helm_charts_install_directory" value
206 # adjusted accordingly.
207 HELM_CHARTS_DIR_IN_PACKAGE="${APPLICATION_FILES_IN_PACKAGE}/helm_charts"
208
209 if [ $# -eq 0 ]; then
210     crash_arguments
211 fi
212
213 CONF_FILE=""
214 FORCE_REMOVE=0
215 arg_ind=0
216 for arg in "$@"; do
217   shift
218   ((arg_ind+=1))
219   if [[ ${arg} =~ ^[-]{1,2}[a-zA-Z-]+$ && ${arg_ind} -lt 4 ]]; then
220       echo "Non-positional parameters should follow mandatory arguments!"
221       usage
222       exit 1
223   fi
224   case "$arg" in
225     -c|--conf)
226         CONF_FILE="$1" ;;
227     --force)
228         FORCE_REMOVE=1 ;;
229     *)
230         set -- "$@" "$arg"
231         if [ "$#" -lt 3 ]; then
232             crash_arguments
233         fi ;;
234   esac
235 done
236
237 if [ -z ${CONF_FILE} ]; then
238     CONF_FILE=${LOCAL_PATH}/package.conf # Fall to default conf file
239 fi
240
241 if [ ! -f ${CONF_FILE} ]; then
242     crash 2 "Mandatory config file missing! Provide it with --conf option or ${LOCAL_PATH}/package.conf"
243 fi
244
245 source ${CONF_FILE}
246 pushd ${LOCAL_PATH}
247
248 # checking bash capability of parsing arrays
249 whotest[0]='test' || (crash 3 "Arrays not supported in this version of bash.")
250
251 # Prepare output directory for our packaging
252 # Check target dir exists and is not empty
253 if [ -d ${PACKAGING_TARGET_DIR} ] && [ "$(ls -A ${PACKAGING_TARGET_DIR})" ]; then
254     if [ ${FORCE_REMOVE} -eq 0 ]; then
255         crash 1 "Target directory not empty. Use --force to overwrite it."
256     else
257         rm -rf ${PACKAGING_TARGET_DIR}
258     fi
259 fi
260
261 # Create all tars
262 build_sw_artifacts
263 create_sw_package
264 create_resource_package
265 create_aux_package
266
267 popd