aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Elliott <mike.elliott@amdocs.com>2018-03-26 10:12:41 -0400
committerMike Elliott <mike.elliott@amdocs.com>2018-03-26 10:16:23 -0400
commit0eccf6a7e0b9c1d5d93d364d611329f4fc4dabcf (patch)
treeb0bb4270113eff8495f8d589abadcc14c14ff52e
parent114736eb5119b023bc5f166a3b42aaf933b0b223 (diff)
Remove deprecated oneclick scripts
As of Beijing, all ONAP deploys will use Helm directly. Please refer to README (OOM-827) for instructions on how to deploy ONAP using Helm. Change-Id: I5b9322c127f324d815d8dea23057bc60e04ed9c9 Issue-ID: OOM-828 Signed-off-by: Mike Elliott <mike.elliott@amdocs.com>
-rwxr-xr-xkubernetes/oneclick/createAll.bash189
-rwxr-xr-xkubernetes/oneclick/deleteAll.bash150
-rw-r--r--kubernetes/oneclick/setenv.bash15
-rw-r--r--kubernetes/oneclick/tools/autoCleanConfig.bash54
-rw-r--r--kubernetes/oneclick/tools/autoCreateConfig.bash65
-rw-r--r--kubernetes/oneclick/tools/collectInfo.bash171
6 files changed, 0 insertions, 644 deletions
diff --git a/kubernetes/oneclick/createAll.bash b/kubernetes/oneclick/createAll.bash
deleted file mode 100755
index ded7c392ed..0000000000
--- a/kubernetes/oneclick/createAll.bash
+++ /dev/null
@@ -1,189 +0,0 @@
-#!/bin/bash
-
-. $(dirname "$0")/setenv.bash
-
-
-usage() {
- cat <<EOF
-Usage: $0 [PARAMs]
--u : Display usage
--n [NAMESPACE] : Kubernetes namespace (required)
--v [VALUES] : HELM values filepath (usefull when deploying one component at a time)
--l [LOCATION] : Location of oom project
--i [INSTANCE] : ONAP deployment instance # (default: 1)
--a [APP] : Specify a specific ONAP component (default: all)
- from the following choices:
- sdc, aai ,mso, message-router, robot, vid, aaf, uui
- sdnc, portal, policy, appc, multicloud, clamp, consul, vnfsdk
-EOF
-}
-
-check_return_code(){
- ret=$?
- if [ $ret -ne 0 ]; then
- printf "The command $1 returned with error code $ret \n" 1>&2
- exit $ret
- fi
-}
-
-create_service_account() {
- cmd=`echo kubectl create clusterrolebinding $1-admin-binding --clusterrole=cluster-admin --serviceaccount=$1:default`
- eval ${cmd}
- check_return_code $cmd
-}
-
-create_namespace() {
- cmd=`echo kubectl create namespace $1`
- eval ${cmd}
-}
-
-create_registry_key() {
-cmd=`echo kubectl --namespace $1 create secret docker-registry $2 --docker-server=$3 --docker-username=$4 --docker-password=$5 --docker-email=$6`
- eval ${cmd}
- check_return_code $cmd
-}
-
-configure_dcaegen2() {
- if [ ! -s "$OPENSTACK_PRIVATE_KEY_PATH" ]
- then
- echo "ERROR: $OPENSTACK_PRIVATE_KEY_PATH does not exist or is empty. Cannot launch dcae gen2."
- return 1
- fi
-
- cmd=`echo kubectl --namespace $1-$2 create secret generic $2-openstack-ssh-private-key --from-file=key=${OPENSTACK_PRIVATE_KEY_PATH}`
- eval ${cmd}
- check_return_code $cmd
-
- if [ ! -s "$DCAEGEN2_CONFIG_INPUT_FILE_PATH" ]
- then
- echo "ERROR: $DCAEGEN2_CONFIG_INPUT_FILE_PATH does not exist or is empty. Cannot launch dcae gen2."
- return 1
- fi
-
- cmd=`echo kubectl --namespace $1-$2 create configmap $2-config-inputs --from-file=inputs.yaml=${DCAEGEN2_CONFIG_INPUT_FILE_PATH}`
- eval ${cmd}
- check_return_code $cmd
-}
-
-create_onap_helm() {
- HELM_VALUES_ADDITION=""
- if [[ ! -z $HELM_VALUES_FILEPATH ]]; then
- HELM_VALUES_ADDITION="--values=$HELM_VALUES_FILEPATH"
- fi
- # Have to put a check for dcaegen2 because it requires external files to helm
- # which should not be part of the Chart.
- if [ "$2" = "dcaegen2" ];
- then
- configure_dcaegen2 $1 $2
- local result=$?
- if [ $result -ne 0 ]
- then
- echo "ERROR: dcaegen2 failed to configure: Pre-requisites not met. Skipping deploying it and continue"
- return
- fi
- fi
-
- cmd=`echo helm install $LOCATION/$2/ --name $1-$2 --namespace $1 --set nsPrefix=$1,nodePortPrefix=$3 ${HELM_VALUES_ADDITION}`
- eval ${cmd}
- check_return_code $cmd
-}
-
-#MAINs
-NS=
-HELM_VALUES_FILEPATH=""
-LOCATION="../"
-INCL_SVC=true
-APP=
-INSTANCE=1
-MAX_INSTANCE=5
-DU=$ONAP_DOCKER_USER
-DP=$ONAP_DOCKER_PASS
-
-SINGLE_COMPONENT=false
-
-while getopts ":n:u:s:i:a:du:dp:l:v:" PARAM; do
- case $PARAM in
- u)
- usage
- exit 1
- ;;
- n)
- NS=${OPTARG}
- ;;
- v)
- HELM_VALUES_FILEPATH=${OPTARG}
- ;;
- i)
- INSTANCE=${OPTARG}
- ;;
- l)
- LOCATION=${OPTARG}
- ;;
- a)
- SINGLE_COMPONENT=true
- APP=${OPTARG}
- if [[ -z $APP ]]; then
- usage
- exit 1
- fi
- ;;
- du)
- DU=${OPTARG}
- ;;
- dp)
- DP=${OPTARG}
- ;;
- ?)
- usage
- exit
- ;;
- esac
-done
-
-if [[ -z $NS ]]; then
- usage
- exit 1
-fi
-
-if [[ ! -z "$APP" ]]; then
- HELM_APPS=($APP)
-fi
-
-
-if [ "$INSTANCE" -gt "$MAX_INSTANCE" ];then
- printf "\n********** You choose to create ${INSTANCE}th instance of ONAP \n"
- printf "\n********** Due to port allocation only ${MAX_INSTANCE} instances of ONAP is allowed per kubernetes deployment\n"
- exit 1
-fi
-
-start=$((300+2*INSTANCE))
-end=$((start+1))
-
-printf "\n********** Creating instance ${INSTANCE} of ONAP with port range ${start}00 and ${end}99\n"
-
-
-printf "\n********** Creating ONAP: ${ONAP_APPS[*]}\n"
-
-if [ "$SINGLE_COMPONENT" == "false" ]
-then
- printf "\nCreating namespace **********\n"
- create_namespace $NS
-
- printf "\nCreating registry secret **********\n"
- create_registry_key $NS ${NS}-docker-registry-key $ONAP_DOCKER_REGISTRY $DU $DP $ONAP_DOCKER_MAIL
-
- printf "\nCreating service account **********\n"
- create_service_account $NS
-fi
-
-printf "\n\n********** Creating deployments for ${HELM_APPS[*]} ********** \n"
-
-for i in ${HELM_APPS[@]}; do
-
- printf "\nCreating deployments and services **********\n"
- create_onap_helm $NS $i $start
-
- printf "\n"
-done
-
-printf "\n**** Done ****\n"
diff --git a/kubernetes/oneclick/deleteAll.bash b/kubernetes/oneclick/deleteAll.bash
deleted file mode 100755
index 9833af7909..0000000000
--- a/kubernetes/oneclick/deleteAll.bash
+++ /dev/null
@@ -1,150 +0,0 @@
-#!/bin/bash
-
-. $(dirname "$0")/setenv.bash
-
-delete_namespace() {
- kubectl delete namespace $1
-}
-
-delete_service_account() {
- kubectl delete clusterrolebinding $1-admin-binding
-}
-
-delete_registry_key() {
- kubectl --namespace $1 delete secret ${1}-docker-registry-key
-}
-
-delete_app_helm() {
- helm delete $1-$2 --purge
-}
-
-wait_terminate() {
- printf "Waiting for namespaces termination...\n"
- while true; do
- declare -i _STATUS=0
- for i in ${HELM_APPS[@]}; do
- kubectl get pods --namespace $1 | grep -w " $i" > /dev/null 2>&1
- if [ "$?" -ne "0" ]; then
- _STATUS=1
- break
- fi
- done
-
- if [ "$SINGLE_COMPONENT" == "false" ]; then
- kubectl get namespaces $1 > /dev/null 2>&1
- _STATUS=$?
- fi
- if [ "$_STATUS" -ne "0" ]; then
- break
- fi
- sleep 2
- done
-}
-
-usage() {
- cat <<EOF
-Usage: $0 [PARAMs]
--u : Display usage
--n [NAMESPACE] : Kubernetes namespace (required)
--c : kubectl context (default: current context)
--y : Skip interactive confirmation (default: no)
--a [APP] : Specify a specific ONAP component (default: all)
- from the following choices:
- sdc, aai ,mso, message-router, robot, vid, aaf, uui
- sdnc, portal, policy, appc, multicloud, clamp, consul, vnfsdk
--N : Do not wait for deletion of namespace and its objects
-EOF
-}
-
-#MAINs
-NS=
-INCL_SVC=false
-APP=
-WAIT_TERMINATE=true
-SKIP_INTERACTIVE_CONFIRMATION=no
-KUBECTL_CONTEXT=
-SINGLE_COMPONENT=false
-while getopts ":c:n:u:s:a:yN" PARAM; do
- case $PARAM in
- u)
- usage
- exit 1
- ;;
- n)
- NS=${OPTARG}
- ;;
- a)
- APP=${OPTARG}
- if [[ -z $APP ]]; then
- usage
- exit 1
- fi
- SINGLE_COMPONENT=true
- ;;
- N)
- WAIT_TERMINATE=false
- ;;
- y)
- SKIP_INTERACTIVE_CONFIRMATION=yes
- ;;
- c)
- KUBECTL_CONTEXT=${OPTARG}
- ;;
- ?)
- usage
- exit
- ;;
- esac
-done
-
-if [[ -z $NS ]]; then
- usage
- exit 1
-fi
-
-if [[ "$SKIP_INTERACTIVE_CONFIRMATION" != yes ]]; then
- current_kubectl_context=$(kubectl config get-contexts |grep "*" |awk '{print $2}')
- if test "$KUBECTL_CONTEXT" != "$current_kubectl_context"; then
- printf "Current kubectl context does not match context specified:\x1b[31m $current_kubectl_context\x1b[0m\n"
- if [ ! -z "$KUBECTL_CONTEXT" -a "$KUBECTL_CONTEXT" != " " ]; then
- read -p "Do you wish to switch context to $KUBECTL_CONTEXT and continue?" yn
- case $yn in
- [Yy]* ) kubectl config use-context $KUBECTL_CONTEXT;;
- * ) printf "Skipping delete...\n"; exit;;
- esac
- else
- printf "You are about to delete deployment from:\x1b[31m $current_kubectl_context\x1b[0m\n"
- read -p "To continue enter context name: " response
-
- if test "$response" != "$current_kubectl_context"
- then
- printf "Your response does not match current context! Skipping delete ...\n"
- exit 1
- fi
- fi
- fi
-fi
-
-if [[ ! -z "$APP" ]]; then
- HELM_APPS=($APP)
-fi
-
-printf "\n********** Cleaning up ONAP: ${ONAP_APPS[*]}\n"
-
-for i in ${HELM_APPS[@]}; do
- delete_app_helm $NS $i
-done
-
-if [ "$SINGLE_COMPONENT" == "false" ]
-then
- delete_app_helm $NS "config"
- delete_namespace $NS
- delete_registry_key $NS
- delete_service_account $NS
-fi
-
-if $WAIT_TERMINATE; then
- wait_terminate $NS
-fi
-
-printf "\n********** Gone **********\n"
diff --git a/kubernetes/oneclick/setenv.bash b/kubernetes/oneclick/setenv.bash
deleted file mode 100644
index 716b76c410..0000000000
--- a/kubernetes/oneclick/setenv.bash
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-
-# Deploying MSB first so the started ONAP services can be registered to MSB
-HELM_APPS=('consul' 'msb' 'mso' 'message-router' 'sdnc' 'vid' 'robot' 'portal' 'policy' 'aai' 'sdc' 'dcaegen2' 'log' 'cli' 'multicloud' 'clamp' 'vnfsdk' 'uui' 'aaf' 'vfc' 'esr')
-ONAP_DOCKER_REGISTRY=${ONAP_DOCKER_REGISTRY:-nexus3.onap.org:10001}
-ONAP_DOCKER_USER=${ONAP_DOCKER_USER:-docker}
-ONAP_DOCKER_PASS=${ONAP_DOCKER_PASS:-docker}
-ONAP_DOCKER_MAIL=${ONAP_DOCKER_MAIL:-$USERNAME@$USERDOMAIN}
-# Openstack key pair private key file location required to enable dcaegen2 installer CRUD operations in your Openstack
-# Ensure you set the name of your keypair in the dcae-parameters.yaml entry "keypair: "dcae-g2"
-# example: export OPENSTACK_PRIVATE_KEY_PATH=/home/user/Downloads/dcae-g2.pem
-OPENSTACK_PRIVATE_KEY_PATH=${OPENSTACK_PRIVATE_KEY_PATH:-~/.ssh/onap_rsa}
-# dcaegen2 bootstrap configuration input yaml file. Start from the sample, and set your environments real values:
-# example: export DCAEGEN2_CONFIG_INPUT_FILE_PATH=/tmp/dcae-parameters.yaml
-DCAEGEN2_CONFIG_INPUT_FILE_PATH=${DCAEGEN2_CONFIG_INPUT_FILE_PATH:-../dcaegen2/dcae-parameters-sample.yaml}
diff --git a/kubernetes/oneclick/tools/autoCleanConfig.bash b/kubernetes/oneclick/tools/autoCleanConfig.bash
deleted file mode 100644
index e274e0d0c5..0000000000
--- a/kubernetes/oneclick/tools/autoCleanConfig.bash
+++ /dev/null
@@ -1,54 +0,0 @@
-########################################################################################
-# This script wraps {$OOM}/kubernetes/oneclick/deleteAll.sh script along with #
-# the following steps to clean up ONAP configure for specified namespace: #
-# - remove namespace #
-# - remove release #
-# - remove shared directory #
-# #
-# To run it, just enter the following command: #
-# ./autoCleanConfig.bash <namespace, default is "onap"> #
-########################################################################################
-#!/bin/bash
-
-
-NS=$1
-if [[ -z $NS ]]
-then
- echo "Namespace is not specified, use onap namespace."
- NS="onap"
-fi
-
-echo "Clean up $NS configuration"
-cd ..
-./deleteAll.bash -n $NS -y
-cd -
-
-echo "----------------------------------------------
-Force remove namespace..."
-kubectl delete namespace $NS
-echo "...done : kubectl get namespace
------------------------------------------------
->>>>>>>>>>>>>> k8s namespace"
-kubectl get namespace
-while [[ ! -z `kubectl get namespace|grep $NS` ]]
-do
- echo "Wait for namespace $NS to be deleted
------------------------------------------------
->>>>>>>>>>>>>> k8s namespace"
- kubectl get namespace
- sleep 2
-done
-
-echo "Force delete helm process ..."
-helm delete $NS-config --purge --debug
-echo "...done : helm ls --all
- -----------------------------------------------
->>>>>>>>>>>>>> helm"
-helm ls --all
-
-echo "Remove $NS dockerdata..."
-sudo rm -rf /dockerdata-nfs/onap
-echo "...done : ls -altr /dockerdata-nfs
- -----------------------------------------------
->>>>>>>>>>>>>> /dockerdata-nfs directory"
-ls -altr /dockerdata-nfs
diff --git a/kubernetes/oneclick/tools/autoCreateConfig.bash b/kubernetes/oneclick/tools/autoCreateConfig.bash
deleted file mode 100644
index 99ea03e1bb..0000000000
--- a/kubernetes/oneclick/tools/autoCreateConfig.bash
+++ /dev/null
@@ -1,65 +0,0 @@
-########################################################################################
-# This script wraps {$OOM}/kubernetes/config/createConfig.sh script #
-# and will only terminated when the configuration is Completed or failed #
-# #
-# To run it, just enter the following command: #
-# ./autoCreateConfig.bash <namespace, default is "onap"> #
-########################################################################################
-#!/bin/bash
-
-
-NS=$1
-if [[ -z $NS ]]
-then
- echo "Namespace is not specified, use onap namespace."
- NS="onap"
-fi
-
-echo "Create $NS config under config directory..."
-cd ../../config
-./createConfig.sh -n $NS
-cd -
-
-
-echo "...done : kubectl get namespace
------------------------------------------------
->>>>>>>>>>>>>> k8s namespace"
-kubectl get namespace
-
-
-echo "
------------------------------------------------
->>>>>>>>>>>>>> helm : helm ls --all"
-helm ls --all
-
-
-echo "
------------------------------------------------
->>>>>>>>>>>>>> pod : kubectl get pods -n $NS -a"
-kubectl get pods -n $NS -a
-
-
-while true
-do
- echo "wait for $NS config pod reach to Completed STATUS"
- sleep 5
- echo "-----------------------------------------------"
- kubectl get pods -n $NS -a
-
- status=`kubectl get pods -n $NS -a |grep config |xargs echo | cut -d' ' -f3`
-
- if [ "$status" = "Completed" ]
- then
- echo "$NS config is Completed!!!"
- break
- fi
-
- if [ "$status" = "Error" ]
- then
- echo "
-$NS config is failed with Error!!!
-Logs are:"
- kubectl logs config -n $NS -f
- break
- fi
-done
diff --git a/kubernetes/oneclick/tools/collectInfo.bash b/kubernetes/oneclick/tools/collectInfo.bash
deleted file mode 100644
index 734c5a6c62..0000000000
--- a/kubernetes/oneclick/tools/collectInfo.bash
+++ /dev/null
@@ -1,171 +0,0 @@
-#!/bin/bash
-
-NS=
-OUT_NAME=onap_info_$(date +%y.%m.%d_%H.%M.%S.%N)
-OUT_FILE=
-OUT_DIR=$(dirname "$0")
-TMP_DIR=$(dirname $(mktemp -u))
-CONTAINER_LOGS_PATH=/var/log/onap
-CP_CONTAINER_LOGS=false
-
-if [ ! -z "$DEBUG" ]; then
- set -x
-fi
-
-usage() {
- cat <<EOF
-Utility script collecting various information about ONAP deployment on kubernetes.
-
-Usage: $0 [PARAMs]
--u : Display usage
--n [NAMESPACE] : Kubernetes namespace (required)
--a [APP] : Specify a specific ONAP component (default: all)
--d [OUT_DIR] : Specify output folder for the collected info pack file
- (default: current dir)
--f [OUT_FILE] : Specify output file for the collected info
- (default: file name with timestamp)
--c : Collect log files from containers, from path ${CONTAINER_LOGS_PATH}
-EOF
-}
-
-call_with_log() {
- local _cmd=$1
- local _log=$2
- # Make sure otput dir exists
- mkdir -p "$(dirname "$_log")"
- printf "Command: ${_cmd}\n" >> ${_log}
- printf "================================================================================\n" >> ${_log}
- eval "${_cmd}" >> ${_log} 2>&1
- printf "================================================================================\n" >> ${_log}
-}
-
-collect_pod_info() {
- local _ns=$1
- local _id=$2
- local _log_dir=$3
- local _cp_logs=$4
- declare -i _i=0
- kubectl -n $_ns get pods $_id -o=jsonpath='{range .spec.containers[*]}{.name}{"\n"}{end}' | while read c; do
- call_with_log "kubectl -n $_ns logs $_id -c $c" "$_log_dir/$_id-$c.log"
- if [ "$_i" -eq "0" ] && [ "$_cp_logs" == "true" ]; then
- # copy logs from 1st container only as logs dir is shared between the containers
- local _cmd="kubectl cp $_ns/$_id:${CONTAINER_LOGS_PATH} $_log_dir/$_id-$c -c $c"
- if [ -z "$DEBUG" ]; then
- _cmd+=" > /dev/null 2>&1"
- fi
- eval "${_cmd}"
- fi
- ((_i++))
- done
-}
-
-collect_ns_info() {
- local _ns=$1
- local _log_dir=$2/$_ns
- call_with_log "kubectl -n $NS-$i get services -o=wide" "$_log_dir/list_services.log"
- kubectl -n "$_ns" get services | while read i; do
- local _id=`echo -n $i | tr -s ' ' | cut -d' ' -n -f1`
- if [ "$_id" == "NAME" ]; then
- continue
- fi
- call_with_log "kubectl -n $_ns describe services $_id" "$_log_dir/describe_services/$_id.log"
- done
- call_with_log "kubectl -n $NS-$i get pods -o=wide" "$_log_dir/list_pods.log"
- kubectl -n "$_ns" get pods | while read i; do
- local _id=`echo -n $i | tr -s ' ' | cut -d' ' -n -f1`
- if [ "$_id" == "NAME" ]; then
- continue
- fi
- call_with_log "kubectl -n $_ns describe pods $_id" "$_log_dir/describe_pods/$_id.log"
- collect_pod_info "$_ns" "$_id" "$_log_dir/logs" "${CP_CONTAINER_LOGS}"
- done
-}
-
-while getopts ":un:a:d:f:c" PARAM; do
- case $PARAM in
- u)
- usage
- exit 1
- ;;
- n)
- NS=${OPTARG}
- ;;
- a)
- APP=${OPTARG}
- if [[ -z $APP ]]; then
- usage
- exit 1
- fi
- ;;
- d)
- OUT_DIR=${OPTARG}
- if [[ -z $OUT_DIR ]]; then
- usage
- exit 1
- fi
- ;;
- f)
- OUT_FILE=${OPTARG}
- if [[ -z $OUT_FILE ]]; then
- usage
- exit 1
- fi
- ;;
- c)
- CP_CONTAINER_LOGS=true
- ;;
- ?)
- usage
- exit
- ;;
- esac
-done
-
-if [ -z "$NS" ]; then
- usage
- exit 1
-fi
-
-if [[ -z $OUT_FILE ]]; then
- OUT_FILE=$OUT_NAME.tgz
-fi
-
-if [ ! -z "$APP" ]; then
- _APPS=($APP)
-else
- _APPS=(`kubectl get namespaces | grep "^$NS-" | tr -s ' ' | cut -d' ' -n -f1 | sed -e "s/^$NS-//"`)
-fi
-
-printf "Collecting information about ONAP deployment...\n"
-printf "Components: %s\n" "${_APPS[*]}"
-
-# Collect common info
-mkdir -p ${TMP_DIR}/${OUT_NAME}/
-echo "${_APPS[*]}" > ${TMP_DIR}/${OUT_NAME}/component-list.log
-printf "Collecting Helm info\n"
-call_with_log "helm version" "${TMP_DIR}/${OUT_NAME}/helm-version.log"
-call_with_log "helm list" "${TMP_DIR}/${OUT_NAME}/helm-list.log"
-
-printf "Collecting Kubernetes info\n"
-call_with_log "kubectl version" "${TMP_DIR}/${OUT_NAME}/k8s-version.log"
-call_with_log "kubectl get nodes -o=wide" "${TMP_DIR}/${OUT_NAME}/k8s-nodes.log"
-call_with_log "kubectl cluster-info" "${TMP_DIR}/${OUT_NAME}/k8s-cluster-info.log"
-call_with_log "kubectl cluster-info dump" "${TMP_DIR}/${OUT_NAME}/k8s-cluster-info-dump.log"
-call_with_log "kubectl top node" "${TMP_DIR}/${OUT_NAME}/k8s-top-node.log"
-
-# Collect per-component info
-for i in ${_APPS[@]}; do
- printf "Writing Kubernetes info of component $i\n"
- collect_ns_info "$NS-$i" "${TMP_DIR}/${OUT_NAME}"
-done
-
-# Pack and cleanup
-mkdir -p ${OUT_DIR}
-_OUT_DIR=`readlink -e ${OUT_DIR}`
-printf "Packing output to ${_OUT_DIR}/${OUT_FILE}...\n"
-cd ${TMP_DIR}
-tar cfz ${_OUT_DIR}/${OUT_FILE} ${OUT_NAME}
-cd -
-printf "Cleaning up...\n"
-rm -rf ${TMP_DIR}/${OUT_NAME}
-printf "Done\n"