From f04178fd12731a58c899c309ad43f55d339909c5 Mon Sep 17 00:00:00 2001
From: Doug Hellmann <doug.hellmann@dreamhost.com>
Date: Thu, 5 Jul 2012 17:10:03 -0400
Subject: [PATCH] add functions to manipulate ENABLED_SERVICES

Editing ENABLED_SERVICES directly can get tricky when
the user wants to disable something. This patch includes
two new functions for adding or removing services
safely, and a third (for completeness) to clear the
settings entirely before adding a minimal set of
services.

It also moves the logic for dealing with "negated"
services into a function so it can be tested and
applied by the new functions for manipulating
ENABLED_SERVICES.

Change-Id: I88f205f3666b86e6f0b6a94e0ec32a26c4bc6873
Signed-off-by: Doug Hellmann <doug.hellmann@dreamhost.com>
---
 AUTHORS            |  1 +
 README.md          |  5 ++-
 functions          | 71 ++++++++++++++++++++++++++++++++++
 openrc             |  3 ++
 stack.sh           | 13 ++-----
 tests/functions.sh | 96 ++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 178 insertions(+), 11 deletions(-)

diff --git a/AUTHORS b/AUTHORS
index b5f972fd99..67120f6cae 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -8,6 +8,7 @@ Chmouel Boudjnah <chmouel@chmouel.com>
 Dan Prince <dprince@redhat.com>
 Dean Troyer <dtroyer@gmail.com>
 Devin Carlen <devin.carlen@gmail.com>
+Doug hellmann <doug.hellmann@dreamhost.com>
 Eddie Hebert <edhebert@gmail.com>
 Eoghan Glynn <eglynn@redhat.com>
 Gabriel Hurley <gabriel@strikeawe.com>
diff --git a/README.md b/README.md
index cfcfe7c3f7..ed9d9d12ae 100644
--- a/README.md
+++ b/README.md
@@ -61,11 +61,12 @@ You can override environment variables used in `stack.sh` by creating file name
 
 Swift is not installed by default, you can enable easily by adding this to your `localrc`:
 
-    ENABLED_SERVICE="$ENABLED_SERVICES,swift"
+    enable_service swift
 
 If you want a minimal Swift install with only Swift and Keystone you can have this instead in your `localrc`:
 
-    ENABLED_SERVICES="key,mysql,swift"
+    disable_all_services
+    enable_service key mysql swift
 
 If you use Swift with Keystone, Swift will authenticate against it. You will need to make sure to use the Keystone URL to auth against.
 
diff --git a/functions b/functions
index 8cf7c74b6b..a22d8b767a 100644
--- a/functions
+++ b/functions
@@ -1,3 +1,4 @@
+# -*- mode: Shell-script -*-
 # functions - Common functions used by DevStack components
 #
 # ENABLED_SERVICES is used by is_service_enabled()
@@ -349,6 +350,76 @@ function is_service_enabled() {
     return 1
 }
 
+# remove extra commas from the input string (ENABLED_SERVICES)
+function _cleanup_service_list () {
+	echo "$1" | sed -e '
+        s/,,/,/g;
+        s/^,//;
+        s/,$//
+    '
+}
+
+# enable_service() adds the services passed as argument to the
+# **ENABLED_SERVICES** list, if they are not already present.
+#
+# For example:
+#
+#   enable_service n-vol
+#
+# This function does not know about the special cases
+# for nova, glance, and quantum built into is_service_enabled().
+function enable_service() {
+    local tmpsvcs="${ENABLED_SERVICES}"
+    for service in $@; do
+        if ! is_service_enabled $service; then
+            tmpsvcs+=",$service"
+        fi
+    done
+    ENABLED_SERVICES=$(_cleanup_service_list "$tmpsvcs")
+    disable_negated_services
+}
+
+# disable_service() removes the services passed as argument to the
+# **ENABLED_SERVICES** list, if they are present.
+#
+# For example:
+#
+#   disable_service n-vol
+#
+# This function does not know about the special cases
+# for nova, glance, and quantum built into is_service_enabled().
+function disable_service() {
+    local tmpsvcs=",${ENABLED_SERVICES},"
+    local service
+    for service in $@; do
+        if is_service_enabled $service; then
+            tmpsvcs=${tmpsvcs//,$service,/,}
+        fi
+    done
+    ENABLED_SERVICES=$(_cleanup_service_list "$tmpsvcs")
+}
+
+# disable_all_services() removes all current services
+# from **ENABLED_SERVICES** to reset the configuration
+# before a minimal installation
+function disable_all_services() {
+    ENABLED_SERVICES=""
+}
+
+# We are looking for services with a - at the beginning to force
+# excluding those services. For example if you want to install all the default
+# services but not nova-volume (n-vol) you can have this set in your localrc :
+# ENABLED_SERVICES+=",-n-vol"
+function disable_negated_services() {
+    local tmpsvcs="${ENABLED_SERVICES}"
+    local service
+    for service in ${tmpsvcs//,/ }; do
+        if [[ ${service} == -* ]]; then
+            tmpsvcs=$(echo ${tmpsvcs}|sed -r "s/(,)?(-)?${service#-}(,)?/,/g")
+        fi
+    done
+    ENABLED_SERVICES=$(_cleanup_service_list "$tmpsvcs")
+}
 
 # Distro-agnostic package installer
 # install_package package [package ...]
diff --git a/openrc b/openrc
index be7850b5fa..4430e82975 100644
--- a/openrc
+++ b/openrc
@@ -20,6 +20,9 @@ fi
 # Find the other rc files
 RC_DIR=$(cd $(dirname "$BASH_SOURCE") && pwd)
 
+# Import common functions
+source $RC_DIR/functions
+
 # Load local configuration
 source $RC_DIR/stackrc
 
diff --git a/stack.sh b/stack.sh
index 513f8be4a1..1ee70a6d85 100755
--- a/stack.sh
+++ b/stack.sh
@@ -89,15 +89,10 @@ DEST=${DEST:-/opt/stack}
 # Sanity Check
 # ============
 
-# We are looking for services with a - at the beginning to force
-# excluding those services. For example if you want to install all the default
-# services but not nova-volume (n-vol) you can have this set in your localrc :
-# ENABLED_SERVICES+=",-n-vol"
-for service in ${ENABLED_SERVICES//,/ }; do
-    if [[ ${service} == -* ]]; then
-        ENABLED_SERVICES=$(echo ${ENABLED_SERVICES}|sed -r "s/(,)?(-)?${service#-}(,)?/,/g")
-    fi
-done
+# Remove services which were negated in ENABLED_SERVICES
+# using the "-" prefix (e.g., "-n-vol") instead of
+# calling disable_service().
+disable_negated_services
 
 # Warn users who aren't on an explicitly supported distro, but allow them to
 # override check and attempt installation with ``FORCE=yes ./stack``
diff --git a/tests/functions.sh b/tests/functions.sh
index e436ed97cd..f111a48dbb 100755
--- a/tests/functions.sh
+++ b/tests/functions.sh
@@ -143,3 +143,99 @@ else
 fi
 
 rm test.ini
+
+# Enabling/disabling services
+
+echo "Testing enable_service()"
+
+function test_enable_service() {
+    local start="$1"
+    local add="$2"
+    local finish="$3"
+
+    ENABLED_SERVICES="$start"
+    enable_service $add
+    if [ "$ENABLED_SERVICES" = "$finish" ]
+    then
+        echo "OK: $start + $add -> $ENABLED_SERVICES"
+    else
+        echo "changing $start to $finish with $add failed: $ENABLED_SERVICES"
+    fi
+}
+
+test_enable_service '' a 'a'
+test_enable_service 'a' b 'a,b'
+test_enable_service 'a,b' c 'a,b,c'
+test_enable_service 'a,b' c 'a,b,c'
+test_enable_service 'a,b,' c 'a,b,c'
+test_enable_service 'a,b' c,d 'a,b,c,d'
+test_enable_service 'a,b' "c d" 'a,b,c,d'
+test_enable_service 'a,b,c' c 'a,b,c'
+
+test_enable_service 'a,b,-c' c 'a,b'
+test_enable_service 'a,b,c' -c 'a,b'
+
+function test_disable_service() {
+    local start="$1"
+    local del="$2"
+    local finish="$3"
+
+    ENABLED_SERVICES="$start"
+    disable_service "$del"
+    if [ "$ENABLED_SERVICES" = "$finish" ]
+    then
+        echo "OK: $start - $del -> $ENABLED_SERVICES"
+    else
+        echo "changing $start to $finish with $del failed: $ENABLED_SERVICES"
+    fi
+}
+
+echo "Testing disable_service()"
+test_disable_service 'a,b,c' a 'b,c'
+test_disable_service 'a,b,c' b 'a,c'
+test_disable_service 'a,b,c' c 'a,b'
+
+test_disable_service 'a,b,c' a 'b,c'
+test_disable_service 'b,c' b 'c'
+test_disable_service 'c' c ''
+test_disable_service '' d ''
+
+test_disable_service 'a,b,c,' c 'a,b'
+test_disable_service 'a,b' c 'a,b'
+
+
+echo "Testing disable_all_services()"
+ENABLED_SERVICES=a,b,c
+disable_all_services
+
+if [[ -z "$ENABLED_SERVICES" ]]
+then
+    echo "OK"
+else
+    echo "disabling all services FAILED: $ENABLED_SERVICES"
+fi
+
+echo "Testing disable_negated_services()"
+
+
+function test_disable_negated_services() {
+    local start="$1"
+    local finish="$2"
+
+    ENABLED_SERVICES="$start"
+    disable_negated_services
+    if [ "$ENABLED_SERVICES" = "$finish" ]
+    then
+        echo "OK: $start + $add -> $ENABLED_SERVICES"
+    else
+        echo "changing $start to $finish failed: $ENABLED_SERVICES"
+    fi
+}
+
+test_disable_negated_services '-a' ''
+test_disable_negated_services '-a,a' ''
+test_disable_negated_services '-a,-a' ''
+test_disable_negated_services 'a,-a' ''
+test_disable_negated_services 'b,a,-a' 'b'
+test_disable_negated_services 'a,b,-a' 'b'
+test_disable_negated_services 'a,-a,b' 'b'