CORD-616 some cleanup and clarification about registry tags

Change-Id: Ia8562b8b17c949fe135b8092fa370733629e039c
diff --git a/build.gradle b/build.gradle
index aa33b39..da1440f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -39,16 +39,29 @@
     // Upstream registry to simplify filling out the comps table below
     upstreamReg = project.hasProperty('upstreamReg') ? project.getProperty('upstreamReg') : 'docker.io'
 
-    // Target registry to be used to publish docker images needed for deployment
-    targetReg = project.hasProperty('targetReg') ? project.getProperty('targetReg') : 'localhost:5000'
-
-    // The tag used to tag the docker images push to the target registry
-    targetTag = project.hasProperty('targetTag') ? project.getProperty('targetTag') : 'candidate'
-
     // Deployment target config file (yaml format); this can be overwritten from the command line
     // using the -PdeployConfig=<file-path> syntax.
     deployConfig = project.hasProperty('deployConfig') ? project.getProperty('deployConfig') : './config/default.yml'
 
+    println "Using deployment config: $deployConfig"
+    File configFile = new File(deployConfig)
+    def yaml = new Yaml()
+    config = yaml.load(configFile.newReader())
+
+    // Target registry to be used to publish docker images needed for deployment
+    targetReg = project.hasProperty('targetReg')
+        ? project.getProperty('targetReg')
+        : config.docker && config.docker.registry
+            ? config.docker.registry
+            : 'localhost:5000'
+
+    // The tag used to tag the docker images push to the target registry
+    targetTag = project.hasProperty('targetTag')
+        ? project.getProperty('targetTag')
+        : config.docker && config.docker.imageVersion
+            ? config.docker.imageVersion
+            : 'candidate'
+
     comps = [
             'consul': [
                     'type':     'image',
@@ -282,11 +295,6 @@
 }
 
 task prime (type: Exec)  {
-    println "Using deployment config: $deployConfig"
-    File configFile = new File(deployConfig)
-    def yaml = new Yaml()
-    def config = yaml.load(configFile.newReader())
-
     executable = "ansible-playbook"
     args = ["-i", config.seedServer.ip + ',']
 
@@ -328,10 +336,8 @@
         .p(config.otherServers.role, "prov_role")
     }
 
-    if (config.docker) {
-        extraVars = extraVars.p(config.docker.registry, "docker_registry")
-            .p(config.docker.imageVersion, "docker_image_version")
-    }
+    extraVars = extraVars.p("$targetReg", "deploy_docker_registry")
+        .p("$targetTag", "deploy_docker_tag")
 
     def skipTags = [].p(config.seedServer.skipTags)
 
@@ -339,11 +345,6 @@
 }
 
 task deployBase(type: Exec)  {
-    println "Using deployment config: $deployConfig"
-    File configFile = new File(deployConfig)
-    def yaml = new Yaml()
-    def config = yaml.load(configFile.newReader())
-
     executable = "ansible-playbook"
     args = ["-i", config.seedServer.ip + ',']
 
@@ -384,10 +385,8 @@
         .p(config.otherServers.role, "prov_role")
     }
 
-    if (config.docker) {
-        extraVars = extraVars.p(config.docker.registry, "docker_registry")
-            .p(config.docker.imageVersion, "docker_image_version")
-    }
+    extraVars = extraVars.p("$targetReg", "deploy_docker_registry")
+        .p("$targetTag", "deploy_docker_tag")
 
     def skipTags = [].p(config.seedServer.skipTags)
 
diff --git a/roles/head-node/files/commands/cord-registry b/roles/head-node/files/commands/cord-registry
new file mode 100755
index 0000000..c4faacb
--- /dev/null
+++ b/roles/head-node/files/commands/cord-registry
@@ -0,0 +1,94 @@
+#!/bin/bash
+#D Displays information about Docker images in the CORD POD registry
+
+PROG=$(echo $(basename $0) | sed -e 's/^cord-/cord /g')
+
+usage() {
+    echo "usage: $PROG [-r|--registry <registry] <sub-command> [options]"
+    echo "    list    display the Docker images in the registry"
+    echo "    help    this message"
+}
+
+usage_list() {
+    echo "usage $PROG list [--json|-j]"
+    echo "    json    display output as JSON object"
+    echo "    help    this message"
+}
+
+REG=docker-registry:5000
+while [ $# -gt 0 ]; do
+    case $1 in
+      -r|--registry)
+          shift
+          REG=$1
+          ;;
+      -*)
+          echo "Unknown option '$1'"
+          usage
+          exit 1
+          ;;
+      *)
+          break
+          ;;
+    esac
+    shift
+done
+
+COMMAND=$1; shift
+
+case $COMMAND in
+    list)
+        DO_JSON=0
+        while [ $# -gt 0 ]; do
+            case $1 in
+                json|--json|-j)
+                    DO_JSON=1
+                    ;;
+                help|--help|-h)
+                    usage_list
+                    exit 0
+                    ;;
+                *)
+                    >&2 echo "Unknown option '$1'"
+                    usage_list
+                    exit 1
+                    ;;
+            esac
+            shift
+        done
+
+        if [ $DO_JSON -eq 1 ]; then
+            /bin/echo -n '{"registries":['
+            COMMA=
+            for i in $(curl -sSL http://$REG/v2/_catalog | jq '.repositories | .[]' | sed -e 's/"//g'); do
+                /bin/echo -n "$COMMA{\"registry\":\"${REG}/$i\",\"tags\":["
+                C2=
+                for t in $(curl -sSL http://$REG/v2/redis/tags/list | jq '.tags | .[]' | sed -e 's/"//g'); do
+                    echo -n "${C2}\"$t\""
+                    C2=","
+                done
+                /bin/echo -n "]}"
+                COMMA=","
+            done
+            echo -n "]}"
+        else
+            OUT=$(mktemp)
+            echo "REPOSITORY,TAG" > $OUT
+            for i in $(curl -sSL http://$REG/v2/_catalog | jq '.repositories | .[]' | sed -e 's/"//g'); do
+                for t in $(curl -sSL http://$REG/v2/redis/tags/list | jq '.tags | .[]' | sed -e 's/"//g'); do
+                    /bin/echo -e "${REG}/$i,$t" >> $OUT
+                done
+            done
+            cat $OUT | column -s , -t
+            rm -f $OUT
+        fi
+        ;;
+    help)
+        usage
+        exit 0
+        ;;
+    *)
+        usage
+        exit 1
+        ;;
+esac
diff --git a/roles/head-node/tasks/main.yml b/roles/head-node/tasks/main.yml
index 1d85d03..62b7766 100644
--- a/roles/head-node/tasks/main.yml
+++ b/roles/head-node/tasks/main.yml
@@ -121,3 +121,4 @@
     - cord-prov
     - cord-switch
     - cord-generate
+    - cord-registry
diff --git a/roles/maas/tasks/main.yml b/roles/maas/tasks/main.yml
index 83c43b1..7961f61 100644
--- a/roles/maas/tasks/main.yml
+++ b/roles/maas/tasks/main.yml
@@ -43,13 +43,13 @@
     image: "{{ item.image }}"
     state: absent
   with_items:
-    - { name: "storage", image: "docker-registry:5000/consul:{{ docker.image_version }}" }
-    - { name: "allocator", image: "docker-registry:5000/cord-ip-allocator:{{ docker.image_version }}" }
-    - { name: "provisioner", image: "docker-registry:5000/cord-provisioner:{{ docker.image_version }}" }
-    - { name: "switchq", image: "docker-registry:5000/cord-maas-switchq:{{ docker.image_version }}" }
-    - { name: "automation", image: "docker-registry:5000/cord-maas-automation:{{ docker.image_version }}" }
-    - { name: "generator", image: "docker-registry:5000/config-generator:{{ docker.image_version }}" }
-    - { name: "harvester", image: "docker-registry:5000/cord-dhcp-harvester:{{ docker.image_version }}" }
+    - { name: "storage", image: "docker-registry:5000/consul:{{ docker.tag }}" }
+    - { name: "allocator", image: "docker-registry:5000/cord-ip-allocator:{{ docker.tag }}" }
+    - { name: "provisioner", image: "docker-registry:5000/cord-provisioner:{{ docker.tag }}" }
+    - { name: "switchq", image: "docker-registry:5000/cord-maas-switchq:{{ docker.tag }}" }
+    - { name: "automation", image: "docker-registry:5000/cord-maas-automation:{{ docker.tag }}" }
+    - { name: "generator", image: "docker-registry:5000/config-generator:{{ docker.tag }}" }
+    - { name: "harvester", image: "docker-registry:5000/cord-dhcp-harvester:{{ docker.tag }}" }
 
 - name: MAAS Repository
   become: yes
@@ -184,7 +184,7 @@
 
 - name: Configure MAAS
   become: yes
-  command: docker run docker-registry:5000/cord-maas-bootstrap:{{ docker.image_version }} --apikey='{{apikey.stdout}}' --sshkey='{{maas.user_sshkey}}' --url='http://{{mgmt_ip_address.stdout}}/MAAS/api/1.0' --network='{{networks.management}}' --interface='{{interfaces.management}}' --zone='administrative' --cluster='Cluster master' --domain='{{maas.domain}}'
+  command: docker run docker-registry:5000/cord-maas-bootstrap:{{ docker.tag }} --apikey='{{apikey.stdout}}' --sshkey='{{maas.user_sshkey}}' --url='http://{{mgmt_ip_address.stdout}}/MAAS/api/1.0' --network='{{networks.management}}' --interface='{{interfaces.management}}' --zone='administrative' --cluster='Cluster master' --domain='{{maas.domain}}'
   register: maas_config_result
   changed_when: maas_config_result.stdout.find("CHANGED") != -1
   failed_when: "maas_config_result.rc != 0 or 'ERROR' in maas_config_result.stdout"
diff --git a/roles/maas/templates/automation-compose.yml.j2 b/roles/maas/templates/automation-compose.yml.j2
index f8c468e..51034bf 100644
--- a/roles/maas/templates/automation-compose.yml.j2
+++ b/roles/maas/templates/automation-compose.yml.j2
@@ -2,7 +2,7 @@
 
 services:
   storage:
-    image: "docker-registry:5000/consul:{{ docker.image_version }}"
+    image: "docker-registry:5000/consul:{{ docker.tag }}"
     container_name: storage
     labels:
       - "lab.solution=CORD"
@@ -15,7 +15,7 @@
     restart: unless-stopped
 
   allocator:
-    image: "docker-registry:5000/cord-ip-allocator:{{ docker.image_version }}"
+    image: "docker-registry:5000/cord-ip-allocator:{{ docker.tag }}"
     container_name: allocator
     ports:
       - "4242:4242"
@@ -35,7 +35,7 @@
     restart: unless-stopped
 
   provisioner:
-    image: "docker-registry:5000/cord-provisioner:{{ docker.image_version }}"
+    image: "docker-registry:5000/cord-provisioner:{{ docker.tag }}"
     container_name: provisioner
     dns: {{ mgmt_ip_address.stdout }}
     ports:
@@ -63,7 +63,7 @@
     restart: unless-stopped
 
   switchq:
-    image: "docker-registry:5000/cord-maas-switchq:{{ docker.image_version }}"
+    image: "docker-registry:5000/cord-maas-switchq:{{ docker.tag }}"
     container_name: switchq
     ports:
       - "4244:4244"
@@ -88,7 +88,7 @@
     restart: unless-stopped
 
   automation:
-    image: "docker-registry:5000/cord-maas-automation:{{ docker.image_version }}"
+    image: "docker-registry:5000/cord-maas-automation:{{ docker.tag }}"
     container_name: automation
     labels:
       - "lab.solution=CORD"
@@ -122,7 +122,7 @@
     restart: unless-stopped
 
   harvester:
-      image: "docker-registry:5000/cord-dhcp-harvester:{{ docker.image_version }}"
+      image: "docker-registry:5000/cord-dhcp-harvester:{{ docker.tag }}"
       container_name: harvester
       restart: always
       labels:
@@ -151,7 +151,7 @@
       restart: unless-stopped
 
   generator:
-    image: "docker-registry:5000/config-generator:{{ docker.image_version }}"
+    image: "docker-registry:5000/config-generator:{{ docker.tag }}"
     container_name: generator
     ports:
       - "4245:4245"
diff --git a/roles/maas/vars/main.yml b/roles/maas/vars/main.yml
index a20e6c2..40f6f38 100644
--- a/roles/maas/vars/main.yml
+++ b/roles/maas/vars/main.yml
@@ -56,5 +56,4 @@
         high: "{{ fabric_range_high | default(fabric_ip | default('10.6.1.0/24')) | ipaddr(-3) | ipaddr('address') }}"
 
 docker:
-    registry: "{{ docker_registry | default('opencord') }}"
-    image_version: "{{ docker_image_version | default('latest') }}"
+    tag: "{{ deploy_docker_tag | default('candidate') }}"