support installing clients at released versions

expand the devstack support for libraries from released versions to
support python-* clients and tempest_lib.

Depends-On: I81b0d228e7769758c61e5b0323ecfce8c8886d39

Change-Id: I26fac0ccf8fd4818e24618d56bf04b32306f88f6
diff --git a/extras.d/70-trove.sh b/extras.d/70-trove.sh
index a4dc7fb..f284354 100644
--- a/extras.d/70-trove.sh
+++ b/extras.d/70-trove.sh
@@ -11,7 +11,6 @@
         cleanup_trove
     elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then
         echo_summary "Configuring Trove"
-        configure_troveclient
         configure_trove
 
         if is_service_enabled key; then
diff --git a/functions-common b/functions-common
index 48edba8..4e6ad14 100644
--- a/functions-common
+++ b/functions-common
@@ -1621,6 +1621,7 @@
     return $enabled
 }
 
+
 # setup a library by name. If we are trying to use the library from
 # git, we'll do a git based install, otherwise we'll punt and the
 # library should be installed by a requirements pull from another
diff --git a/lib/ceilometer b/lib/ceilometer
index 9046b9d..b1ff8b4 100644
--- a/lib/ceilometer
+++ b/lib/ceilometer
@@ -35,8 +35,9 @@
 # --------
 
 # Set up default directories
+GITDIR["ceilometerclient"]=$DEST/python-ceilometerclient
+
 CEILOMETER_DIR=$DEST/ceilometer
-CEILOMETERCLIENT_DIR=$DEST/python-ceilometerclient
 CEILOMETER_CONF_DIR=/etc/ceilometer
 CEILOMETER_CONF=$CEILOMETER_CONF_DIR/ceilometer.conf
 CEILOMETER_API_LOG_DIR=/var/log/ceilometer-api
@@ -254,9 +255,11 @@
 
 # install_ceilometerclient() - Collect source and prepare
 function install_ceilometerclient {
-    git_clone $CEILOMETERCLIENT_REPO $CEILOMETERCLIENT_DIR $CEILOMETERCLIENT_BRANCH
-    setup_develop $CEILOMETERCLIENT_DIR
-    sudo install -D -m 0644 -o $STACK_USER {$CEILOMETERCLIENT_DIR/tools/,/etc/bash_completion.d/}ceilometer.bash_completion
+    if use_library_from_git "ceilometerclient"; then
+        git_clone_by_name "ceilometerclient"
+        setup_develop "ceilometerclient"
+        sudo install -D -m 0644 -o $STACK_USER {$CEILOMETERCLIENT_DIR/tools/,/etc/bash_completion.d/}ceilometer.bash_completion
+    fi
 }
 
 # start_ceilometer() - Start running processes, including screen
diff --git a/lib/cinder b/lib/cinder
index 29cda42..5687864 100644
--- a/lib/cinder
+++ b/lib/cinder
@@ -36,8 +36,9 @@
 fi
 
 # set up default directories
+GITDIR["cinderclient"]=$DEST/python-cinderclient
+
 CINDER_DIR=$DEST/cinder
-CINDERCLIENT_DIR=$DEST/python-cinderclient
 CINDER_STATE_PATH=${CINDER_STATE_PATH:=$DATA_DIR/cinder}
 CINDER_AUTH_CACHE_DIR=${CINDER_AUTH_CACHE_DIR:-/var/cache/cinder}
 
@@ -402,9 +403,11 @@
 
 # install_cinderclient() - Collect source and prepare
 function install_cinderclient {
-    git_clone $CINDERCLIENT_REPO $CINDERCLIENT_DIR $CINDERCLIENT_BRANCH
-    setup_develop $CINDERCLIENT_DIR
-    sudo install -D -m 0644 -o $STACK_USER {$CINDERCLIENT_DIR/tools/,/etc/bash_completion.d/}cinder.bash_completion
+    if use_library_from_git "cinderclient"; then
+        git_clone_by_name "cinderclient"
+        setup_develop "cinderclient"
+        sudo install -D -m 0644 -o $STACK_USER {$CINDERCLIENT_DIR/tools/,/etc/bash_completion.d/}cinder.bash_completion
+    fi
 }
 
 # apply config.d approach for cinder volumes directory
diff --git a/lib/glance b/lib/glance
index 4194842..8cd48b1 100644
--- a/lib/glance
+++ b/lib/glance
@@ -27,9 +27,10 @@
 # --------
 
 # Set up default directories
+GITDIR["glanceclient"]=$DEST/python-glanceclient
+
 GLANCE_DIR=$DEST/glance
 GLANCE_STORE_DIR=$DEST/glance_store
-GLANCECLIENT_DIR=$DEST/python-glanceclient
 GLANCE_CACHE_DIR=${GLANCE_CACHE_DIR:=$DATA_DIR/glance/cache}
 GLANCE_IMAGE_DIR=${GLANCE_IMAGE_DIR:=$DATA_DIR/glance/images}
 GLANCE_AUTH_CACHE_DIR=${GLANCE_AUTH_CACHE_DIR:-/var/cache/glance}
@@ -286,8 +287,10 @@
 
 # install_glanceclient() - Collect source and prepare
 function install_glanceclient {
-    git_clone $GLANCECLIENT_REPO $GLANCECLIENT_DIR $GLANCECLIENT_BRANCH
-    setup_develop $GLANCECLIENT_DIR
+    if use_library_from_git "glanceclient"; then
+        git_clone_by_name "glanceclient"
+        setup_develop "glanceclient"
+    fi
 }
 
 # install_glance() - Collect source and prepare
diff --git a/lib/heat b/lib/heat
index 53eca25..ed5181b 100644
--- a/lib/heat
+++ b/lib/heat
@@ -29,8 +29,9 @@
 # --------
 
 # set up default directories
+GITDIR["heatclient"]=$DEST/python-heatclient
+
 HEAT_DIR=$DEST/heat
-HEATCLIENT_DIR=$DEST/python-heatclient
 HEAT_CFNTOOLS_DIR=$DEST/heat-cfntools
 HEAT_TEMPLATES_REPO_DIR=$DEST/heat-templates
 HEAT_AUTH_CACHE_DIR=${HEAT_AUTH_CACHE_DIR:-/var/cache/heat}
@@ -183,9 +184,11 @@
 
 # install_heatclient() - Collect source and prepare
 function install_heatclient {
-    git_clone $HEATCLIENT_REPO $HEATCLIENT_DIR $HEATCLIENT_BRANCH
-    setup_develop $HEATCLIENT_DIR
-    sudo install -D -m 0644 -o $STACK_USER {$HEATCLIENT_DIR/tools/,/etc/bash_completion.d/}heat.bash_completion
+    if use_library_from_git "heatclient"; then
+        git_clone_by_name "heatclient"
+        setup_develop "heatclient"
+        sudo install -D -m 0644 -o $STACK_USER {$HEATCLIENT_DIR/tools/,/etc/bash_completion.d/}heat.bash_completion
+    fi
 }
 
 # install_heat() - Collect source and prepare
diff --git a/lib/ironic b/lib/ironic
index 0a84e47..0fadb8d 100644
--- a/lib/ironic
+++ b/lib/ironic
@@ -28,11 +28,12 @@
 # --------
 
 # Set up default directories
+GITDIR["ironicclient"]=$DEST/python-ironicclient
+
 IRONIC_DIR=$DEST/ironic
 IRONIC_PYTHON_AGENT_DIR=$DEST/ironic-python-agent
 IRONIC_DATA_DIR=$DATA_DIR/ironic
 IRONIC_STATE_PATH=/var/lib/ironic
-IRONICCLIENT_DIR=$DEST/python-ironicclient
 IRONIC_AUTH_CACHE_DIR=${IRONIC_AUTH_CACHE_DIR:-/var/cache/ironic}
 IRONIC_CONF_DIR=${IRONIC_CONF_DIR:-/etc/ironic}
 IRONIC_CONF_FILE=$IRONIC_CONF_DIR/ironic.conf
@@ -150,9 +151,14 @@
 
 # install_ironicclient() - Collect sources and prepare
 function install_ironicclient {
-    git_clone $IRONICCLIENT_REPO $IRONICCLIENT_DIR $IRONICCLIENT_BRANCH
-    setup_develop $IRONICCLIENT_DIR
-    sudo install -D -m 0644 -o $STACK_USER {$IRONICCLIENT_DIR/tools/,/etc/bash_completion.d/}ironic.bash_completion
+    if use_library_from_git "ironicclient"; then
+        git_clone_by_name "ironicclient"
+        setup_develop "ironicclient"
+        sudo install -D -m 0644 -o $STACK_USER {$IRONICCLIENT_DIR/tools/,/etc/bash_completion.d/}ironic.bash_completion
+    else
+        # nothing actually "requires" ironicclient, so force instally from pypi
+        pip_install python-ironicclient
+    fi
 }
 
 # _cleanup_ironic_apache_wsgi() - Remove wsgi files, disable and remove apache vhost file
diff --git a/lib/keystone b/lib/keystone
index 276e971..6341ce2 100644
--- a/lib/keystone
+++ b/lib/keystone
@@ -33,6 +33,8 @@
 # --------
 
 # Set up default directories
+GITDIR["keystoneclient"]=$DEST/python-keystoneclient
+
 KEYSTONE_DIR=$DEST/keystone
 KEYSTONE_CONF_DIR=${KEYSTONE_CONF_DIR:-/etc/keystone}
 KEYSTONE_CONF=$KEYSTONE_CONF_DIR/keystone.conf
@@ -45,7 +47,6 @@
 fi
 
 KEYSTONEMIDDLEWARE_DIR=$DEST/keystonemiddleware
-KEYSTONECLIENT_DIR=$DEST/python-keystoneclient
 
 # Set up additional extensions, such as oauth1, federation
 # Example of KEYSTONE_EXTENSIONS=oauth1,federation
@@ -479,9 +480,11 @@
 
 # install_keystoneclient() - Collect source and prepare
 function install_keystoneclient {
-    git_clone $KEYSTONECLIENT_REPO $KEYSTONECLIENT_DIR $KEYSTONECLIENT_BRANCH
-    setup_develop $KEYSTONECLIENT_DIR
-    sudo install -D -m 0644 -o $STACK_USER {$KEYSTONECLIENT_DIR/tools/,/etc/bash_completion.d/}keystone.bash_completion
+    if use_library_from_git "keystoneclient"; then
+        git_clone_by_name "keystoneclient"
+        setup_develop "keystoneclient"
+        sudo install -D -m 0644 -o $STACK_USER {$KEYSTONECLIENT_DIR/tools/,/etc/bash_completion.d/}keystone.bash_completion
+    fi
 }
 
 # install_keystonemiddleware() - Collect source and prepare
diff --git a/lib/neutron b/lib/neutron
index d05dcc8..faca3e0 100644
--- a/lib/neutron
+++ b/lib/neutron
@@ -77,8 +77,10 @@
 
 
 # Set up default directories
+GITDIR["neutronclient"]=$DEST/python-neutronclient
+
+
 NEUTRON_DIR=$DEST/neutron
-NEUTRONCLIENT_DIR=$DEST/python-neutronclient
 NEUTRON_AUTH_CACHE_DIR=${NEUTRON_AUTH_CACHE_DIR:-/var/cache/neutron}
 
 # Support entry points installation of console scripts
@@ -601,9 +603,11 @@
 
 # install_neutronclient() - Collect source and prepare
 function install_neutronclient {
-    git_clone $NEUTRONCLIENT_REPO $NEUTRONCLIENT_DIR $NEUTRONCLIENT_BRANCH
-    setup_develop $NEUTRONCLIENT_DIR
-    sudo install -D -m 0644 -o $STACK_USER {$NEUTRONCLIENT_DIR/tools/,/etc/bash_completion.d/}neutron.bash_completion
+    if use_library_from_git "neutronclient"; then
+        git_clone_by_name "neutronclient"
+        setup_develop "neutronclient"
+        sudo install -D -m 0644 -o $STACK_USER {$NEUTRONCLIENT_DIR/tools/,/etc/bash_completion.d/}neutron.bash_completion
+    fi
 }
 
 # install_neutron_agent_packages() - Collect source and prepare
diff --git a/lib/nova b/lib/nova
index 0f83807..d5f1192 100644
--- a/lib/nova
+++ b/lib/nova
@@ -29,8 +29,10 @@
 # --------
 
 # Set up default directories
+GITDIR["novaclient"]=$DEST/python-novaclient
+
+
 NOVA_DIR=$DEST/nova
-NOVACLIENT_DIR=$DEST/python-novaclient
 NOVA_STATE_PATH=${NOVA_STATE_PATH:=$DATA_DIR/nova}
 # INSTANCES_PATH is the previous name for this
 NOVA_INSTANCES_PATH=${NOVA_INSTANCES_PATH:=${INSTANCES_PATH:=$NOVA_STATE_PATH/instances}}
@@ -637,9 +639,11 @@
 
 # install_novaclient() - Collect source and prepare
 function install_novaclient {
-    git_clone $NOVACLIENT_REPO $NOVACLIENT_DIR $NOVACLIENT_BRANCH
-    setup_develop $NOVACLIENT_DIR
-    sudo install -D -m 0644 -o $STACK_USER {$NOVACLIENT_DIR/tools/,/etc/bash_completion.d/}nova.bash_completion
+    if use_library_from_git "novaclient"; then
+        git_clone_by_name "novaclient"
+        setup_develop "novaclient"
+        sudo install -D -m 0644 -o $STACK_USER {$NOVACLIENT_DIR/tools/,/etc/bash_completion.d/}nova.bash_completion
+    fi
 }
 
 # install_nova() - Collect source and prepare
diff --git a/lib/swift b/lib/swift
index 7ef4496..8016282 100644
--- a/lib/swift
+++ b/lib/swift
@@ -34,8 +34,10 @@
 fi
 
 # Set up default directories
+GITDIR["swiftclient"]=$DEST/python-swiftclient
+
+
 SWIFT_DIR=$DEST/swift
-SWIFTCLIENT_DIR=$DEST/python-swiftclient
 SWIFT_AUTH_CACHE_DIR=${SWIFT_AUTH_CACHE_DIR:-/var/cache/swift}
 SWIFT_APACHE_WSGI_DIR=${SWIFT_APACHE_WSGI_DIR:-/var/www/swift}
 SWIFT3_DIR=$DEST/swift3
@@ -675,8 +677,10 @@
 }
 
 function install_swiftclient {
-    git_clone $SWIFTCLIENT_REPO $SWIFTCLIENT_DIR $SWIFTCLIENT_BRANCH
-    setup_develop $SWIFTCLIENT_DIR
+    if use_library_from_git "swiftclient"; then
+        git_clone_by_name "swiftclient"
+        setup_develop "swiftclient"
+    fi
 }
 
 # start_swift() - Start running processes, including screen
diff --git a/lib/tempest b/lib/tempest
index 66f1a78..25dc171 100644
--- a/lib/tempest
+++ b/lib/tempest
@@ -45,11 +45,12 @@
 # --------
 
 # Set up default directories
+GITDIR["tempest_lib"]=$DEST/tempest-lib
+
 TEMPEST_DIR=$DEST/tempest
 TEMPEST_CONFIG_DIR=${TEMPEST_CONFIG_DIR:-$TEMPEST_DIR/etc}
 TEMPEST_CONFIG=$TEMPEST_CONFIG_DIR/tempest.conf
 TEMPEST_STATE_PATH=${TEMPEST_STATE_PATH:=$DATA_DIR/tempest}
-TEMPEST_LIB_DIR=$DEST/tempest-lib
 
 NOVA_SOURCE_DIR=$DEST/nova
 
@@ -441,8 +442,10 @@
 
 # install_tempest_lib() - Collect source, prepare, and install tempest-lib
 function install_tempest_lib {
-    git_clone $TEMPEST_LIB_REPO $TEMPEST_LIB_DIR $TEMPEST_LIB_BRANCH
-    setup_develop $TEMPEST_LIB_DIR
+    if use_library_from_git "tempest_lib"; then
+        git_clone_by_name "tempest_lib"
+        setup_develop "tempest_lib"
+    fi
 }
 
 # install_tempest() - Collect source and prepare
diff --git a/lib/trove b/lib/trove
index 1d1b5f4..2f8b696 100644
--- a/lib/trove
+++ b/lib/trove
@@ -28,8 +28,9 @@
 fi
 
 # Set up default configuration
+GITDIR["troveclient"]=$DEST/python-troveclient
+
 TROVE_DIR=$DEST/trove
-TROVECLIENT_DIR=$DEST/python-troveclient
 TROVE_CONF_DIR=/etc/trove
 TROVE_LOCAL_CONF_DIR=$TROVE_DIR/etc/trove
 TROVE_AUTH_CACHE_DIR=${TROVE_AUTH_CACHE_DIR:-/var/cache/trove}
@@ -109,10 +110,6 @@
     rm -fr $TROVE_CONF_DIR/*
 }
 
-# configure_troveclient() - Set config files, create data dirs, etc
-function configure_troveclient {
-    setup_develop $TROVECLIENT_DIR
-}
 
 # configure_trove() - Set config files, create data dirs, etc
 function configure_trove {
@@ -184,7 +181,10 @@
 
 # install_troveclient() - Collect source and prepare
 function install_troveclient {
-    git_clone $TROVECLIENT_REPO $TROVECLIENT_DIR $TROVECLIENT_BRANCH
+    if use_library_from_git "troveclient"; then
+        git_clone_by_name "troveclient"
+        setup_develop "troveclient"
+    fi
 }
 
 # install_trove() - Collect source and prepare
diff --git a/stack.sh b/stack.sh
index ec13338..5f87a90 100755
--- a/stack.sh
+++ b/stack.sh
@@ -585,7 +585,7 @@
 fi
 
 # Set the destination directories for other OpenStack projects
-OPENSTACKCLIENT_DIR=$DEST/python-openstackclient
+GITDIR["openstackclient"]=$DEST/python-openstackclient
 
 # Interactive Configuration
 # -------------------------
@@ -788,8 +788,14 @@
 # Install middleware
 install_keystonemiddleware
 
-git_clone $OPENSTACKCLIENT_REPO $OPENSTACKCLIENT_DIR $OPENSTACKCLIENT_BRANCH
-setup_develop $OPENSTACKCLIENT_DIR
+# install the OpenStack client, needed for most setup commands
+if use_library_from_git "openstackclient"; then
+    git_clone_by_name "openstackclient"
+    setup_develop "openstackclient"
+else
+    pip_install python-openstackclient
+fi
+
 
 if is_service_enabled key; then
     if [ "$KEYSTONE_AUTH_HOST" == "$SERVICE_HOST" ]; then
diff --git a/stackrc b/stackrc
index 15b0951..2f08c73 100644
--- a/stackrc
+++ b/stackrc
@@ -199,8 +199,8 @@
 TEMPEST_BRANCH=${TEMPEST_BRANCH:-master}
 
 # TODO(sdague): this should end up as a library component like below
-TEMPEST_LIB_REPO=${TEMPEST_LIB_REPO:-${GIT_BASE}/openstack/tempest-lib.git}
-TEMPEST_LIB_BRANCH=${TEMPEST_LIB_BRANCH:-master}
+GITREPO["tempest_lib"]=${TEMPEST_LIB_REPO:-${GIT_BASE}/openstack/tempest-lib.git}
+GITBRANCH["tempest_lib"]=${TEMPEST_LIB_BRANCH:-master}
 
 
 ##############
@@ -210,48 +210,48 @@
 ##############
 
 # ceilometer client library
-CEILOMETERCLIENT_REPO=${CEILOMETERCLIENT_REPO:-${GIT_BASE}/openstack/python-ceilometerclient.git}
-CEILOMETERCLIENT_BRANCH=${CEILOMETERCLIENT_BRANCH:-master}
+GITREPO["ceilometerclient"]=${CEILOMETERCLIENT_REPO:-${GIT_BASE}/openstack/python-ceilometerclient.git}
+GITBRANCH["ceilometerclient"]=${CEILOMETERCLIENT_BRANCH:-master}
 
 # volume client
-CINDERCLIENT_REPO=${CINDERCLIENT_REPO:-${GIT_BASE}/openstack/python-cinderclient.git}
-CINDERCLIENT_BRANCH=${CINDERCLIENT_BRANCH:-master}
+GITREPO["cinderclient"]=${CINDERCLIENT_REPO:-${GIT_BASE}/openstack/python-cinderclient.git}
+GITBRACH["cinderclient"]=${CINDERCLIENT_BRANCH:-master}
 
 # python glance client library
-GLANCECLIENT_REPO=${GLANCECLIENT_REPO:-${GIT_BASE}/openstack/python-glanceclient.git}
-GLANCECLIENT_BRANCH=${GLANCECLIENT_BRANCH:-master}
+GITREPO["glanceclient"]=${GLANCECLIENT_REPO:-${GIT_BASE}/openstack/python-glanceclient.git}
+GITBRANCH["glanceclient"]=${GLANCECLIENT_BRANCH:-master}
 
 # python heat client library
-HEATCLIENT_REPO=${HEATCLIENT_REPO:-${GIT_BASE}/openstack/python-heatclient.git}
-HEATCLIENT_BRANCH=${HEATCLIENT_BRANCH:-master}
+GITREPO["heatclient"]=${HEATCLIENT_REPO:-${GIT_BASE}/openstack/python-heatclient.git}
+GITBRANCH["heatclient"]=${HEATCLIENT_BRANCH:-master}
 
 # ironic client
-IRONICCLIENT_REPO=${IRONICCLIENT_REPO:-${GIT_BASE}/openstack/python-ironicclient.git}
-IRONICCLIENT_BRANCH=${IRONICCLIENT_BRANCH:-master}
+GITREPO["ironicclient"]=${IRONICCLIENT_REPO:-${GIT_BASE}/openstack/python-ironicclient.git}
+GITBRANCH["ironicclient"]=${IRONICCLIENT_BRANCH:-master}
 
 # python keystone client library to nova that horizon uses
-KEYSTONECLIENT_REPO=${KEYSTONECLIENT_REPO:-${GIT_BASE}/openstack/python-keystoneclient.git}
-KEYSTONECLIENT_BRANCH=${KEYSTONECLIENT_BRANCH:-master}
+GITREPO["keystoneclient"]=${KEYSTONECLIENT_REPO:-${GIT_BASE}/openstack/python-keystoneclient.git}
+GITBRANCH["keystoneclient"]=${KEYSTONECLIENT_BRANCH:-master}
 
 # neutron client
-NEUTRONCLIENT_REPO=${NEUTRONCLIENT_REPO:-${GIT_BASE}/openstack/python-neutronclient.git}
-NEUTRONCLIENT_BRANCH=${NEUTRONCLIENT_BRANCH:-master}
+GITREPO["neutronclient"]=${NEUTRONCLIENT_REPO:-${GIT_BASE}/openstack/python-neutronclient.git}
+GITBRANCH["neutronclient"]=${NEUTRONCLIENT_BRANCH:-master}
 
 # python client library to nova that horizon (and others) use
-NOVACLIENT_REPO=${NOVACLIENT_REPO:-${GIT_BASE}/openstack/python-novaclient.git}
-NOVACLIENT_BRANCH=${NOVACLIENT_BRANCH:-master}
+GITREPO["novaclient"]=${NOVACLIENT_REPO:-${GIT_BASE}/openstack/python-novaclient.git}
+GITBRANCH["novaclient"]=${NOVACLIENT_BRANCH:-master}
 
 # python swift client library
-SWIFTCLIENT_REPO=${SWIFTCLIENT_REPO:-${GIT_BASE}/openstack/python-swiftclient.git}
-SWIFTCLIENT_BRANCH=${SWIFTCLIENT_BRANCH:-master}
+GITREPO["swiftclient"]=${SWIFTCLIENT_REPO:-${GIT_BASE}/openstack/python-swiftclient.git}
+GITBRANCH["swiftclient"]=${SWIFTCLIENT_BRANCH:-master}
 
 # trove client library test
-TROVECLIENT_REPO=${TROVECLIENT_REPO:-${GIT_BASE}/openstack/python-troveclient.git}
-TROVECLIENT_BRANCH=${TROVECLIENT_BRANCH:-master}
+GITREPO["troveclient"]=${TROVECLIENT_REPO:-${GIT_BASE}/openstack/python-troveclient.git}
+GITBRANCH["troveclient"]=${TROVECLIENT_BRANCH:-master}
 
 # consolidated openstack python client
-OPENSTACKCLIENT_REPO=${OPENSTACKCLIENT_REPO:-${GIT_BASE}/openstack/python-openstackclient.git}
-OPENSTACKCLIENT_BRANCH=${OPENSTACKCLIENT_BRANCH:-master}
+GITREPO["openstackclient"]=${OPENSTACKCLIENT_REPO:-${GIT_BASE}/openstack/python-openstackclient.git}
+GITBRANCH["openstackclient"]=${OPENSTACKCLIENT_BRANCH:-master}
 
 ###################
 #