From 7cf5cc141d04a14096f26132998f28ece077eaa6 Mon Sep 17 00:00:00 2001
From: Russell Teague <rteague@redhat.com>
Date: Tue, 21 Feb 2017 10:47:23 -0500
Subject: openshift_hosted: Update tasks to use oc_ modules

---
 roles/openshift_hosted/handlers/main.yml           |   0
 roles/openshift_hosted/meta/main.yml               |   1 +
 roles/openshift_hosted/tasks/main.yml              |  19 ---
 roles/openshift_hosted/tasks/registry/registry.yml | 126 +++++++++------
 roles/openshift_hosted/tasks/registry/secure.yml   | 147 ++++++-----------
 .../tasks/registry/storage/object_storage.yml      | 123 +++++----------
 .../tasks/registry/storage/persistent_volume.yml   |  26 ----
 .../openshift_hosted/tasks/registry/storage/s3.yml |  73 ++++-----
 roles/openshift_hosted/tasks/router/router.yml     | 173 ++++++++++-----------
 9 files changed, 274 insertions(+), 414 deletions(-)
 delete mode 100644 roles/openshift_hosted/handlers/main.yml
 delete mode 100644 roles/openshift_hosted/tasks/registry/storage/persistent_volume.yml

diff --git a/roles/openshift_hosted/handlers/main.yml b/roles/openshift_hosted/handlers/main.yml
deleted file mode 100644
index e69de29bb..000000000
diff --git a/roles/openshift_hosted/meta/main.yml b/roles/openshift_hosted/meta/main.yml
index afea0ac59..e9b590550 100644
--- a/roles/openshift_hosted/meta/main.yml
+++ b/roles/openshift_hosted/meta/main.yml
@@ -20,6 +20,7 @@ dependencies:
 - role: openshift_serviceaccounts
   openshift_serviceaccounts_names:
   - router
+  - registry
   openshift_serviceaccounts_namespace: default
   openshift_serviceaccounts_sccs:
   - hostnetwork
diff --git a/roles/openshift_hosted/tasks/main.yml b/roles/openshift_hosted/tasks/main.yml
index 67c6bbfd7..fe254f72d 100644
--- a/roles/openshift_hosted/tasks/main.yml
+++ b/roles/openshift_hosted/tasks/main.yml
@@ -1,25 +1,6 @@
 ---
-- name: Create temp directory for kubeconfig
-  command: mktemp -d /tmp/openshift-ansible-XXXXXX
-  register: mktemp
-  changed_when: False
-
-- set_fact:
-    openshift_hosted_kubeconfig: "{{ mktemp.stdout }}/admin.kubeconfig"
-
-- name: Copy the admin client config(s)
-  command: >
-    cp {{ openshift_master_config_dir }}/admin.kubeconfig {{ openshift_hosted_kubeconfig }}
-  changed_when: False
-
 - include: router/router.yml
   when: openshift_hosted_manage_router | default(true) | bool
 
 - include: registry/registry.yml
   when: openshift_hosted_manage_registry | default(true) | bool
-
-- name: Delete temp directory
-  file:
-    name: "{{ mktemp.stdout }}"
-    state: absent
-  changed_when: False
diff --git a/roles/openshift_hosted/tasks/registry/registry.yml b/roles/openshift_hosted/tasks/registry/registry.yml
index 93b701ebc..cad5c666c 100644
--- a/roles/openshift_hosted/tasks/registry/registry.yml
+++ b/roles/openshift_hosted/tasks/registry/registry.yml
@@ -1,64 +1,88 @@
 ---
-- name: Retrieve list of openshift nodes matching registry selector
-  command: >
-    {{ openshift.common.client_binary }} --api-version='v1' -o json
-    get nodes -n default --config={{ openshift_hosted_kubeconfig }}
-    --selector={{ openshift.hosted.registry.selector | default('') }}
-  register: registry_nodes_json
-  changed_when: false
-  when: openshift.hosted.registry.replicas | default(none) is none
+- block:
 
-- set_fact:
-    l_node_count: "{{ (registry_nodes_json.stdout | default('{\"items\":[]}') | from_json)['items'] | length }}"
+  - name: Retrieve list of openshift nodes matching registry selector
+    oc_obj:
+      state: list
+      kind: node
+      selector: "{{ openshift.hosted.registry.selector | default(omit) }}"
+    register: registry_nodes
 
-# Determine the default number of registry/router replicas to use if no count
-# has been specified.
-# If no registry nodes defined, the default should be 0.
-- set_fact:
-    l_default_replicas: 0
-  when: l_node_count | int == 0
+  - name: set_fact l_node_count to number of nodes matching registry selector
+    set_fact:
+      l_node_count: "{{ registry_nodes.results.results[0]['items'] | length }}"
 
-# If registry nodes are defined and the registry storage kind is
-# defined, default should be the number of registry nodes, otherwise
-# just 1:
-- set_fact:
-    l_default_replicas: "{{ l_node_count if openshift.hosted.registry.storage.kind | default(none) is not none else 1 }}"
-  when: l_node_count | int > 0
+  # Determine the default number of registry/router replicas to use if no count
+  # has been specified.
+  # If no registry nodes defined, the default should be 0.
+  - name: set_fact l_default_replicas when l_node_count == 0
+    set_fact:
+      l_default_replicas: 0
+    when: l_node_count | int == 0
 
-- set_fact:
-    replicas: "{{ openshift.hosted.registry.replicas | default(l_default_replicas) }}"
+  # If registry nodes are defined and the registry storage kind is
+  # defined, default should be the number of registry nodes, otherwise
+  # just 1:
+  - name: set_fact l_default_replicas when l_node_count > 0
+    set_fact:
+      l_default_replicas: "{{ l_node_count if openshift.hosted.registry.storage.kind | default(none) is not none else 1 }}"
+    when: l_node_count | int > 0
 
-- name: Create OpenShift registry
-  command: >
-    {{ openshift.common.client_binary }} adm registry --create
-    --config={{ openshift_hosted_kubeconfig }}
-    {% if replicas > 1 -%}
-    --replicas={{ replicas }}
-    {% endif -%}
-    --namespace={{ openshift.hosted.registry.namespace | default('default') }}
-    --service-account=registry
-    {% if openshift.hosted.registry.selector | default(none) is not none -%}
-    --selector='{{ openshift.hosted.registry.selector }}'
-    {% endif -%}
-    {% if not openshift.common.version_gte_3_2_or_1_2 | bool -%}
-    --credentials={{ openshift_master_config_dir }}/openshift-registry.kubeconfig
-    {% endif -%}
-    {% if openshift.hosted.registry.registryurl | default(none) is not none -%}
-    --images='{{ openshift.hosted.registry.registryurl }}'
-    {% endif -%}
-  register: openshift_hosted_registry_results
-  changed_when: "'service exists' not in openshift_hosted_registry_results.stdout"
-  failed_when: "openshift_hosted_registry_results.rc != 0 and 'service exists' not in openshift_hosted_registry_results.stdout and 'deployment_config' not in openshift_hosted_registry_results.stderr and 'service' not in openshift_hosted_registry_results.stderr"
-  when: replicas | int > 0
+  when: openshift.hosted.registry.replicas | default(none) is none
+
+- name: set openshift_hosted facts
+  set_fact:
+    openshift_hosted_registry_replicas: "{{ openshift.hosted.registry.replicas | default(l_default_replicas) }}"
+    openshift_hosted_registry_name: docker-registry
+    openshift_hosted_registry_serviceaccount: registry
+    openshift_hosted_registry_namespace: "{{ openshift.hosted.registry.namespace | default('default') }}"
+    openshift_hosted_registry_selector: "{{ openshift.hosted.registry.selector }}"
+    openshift_hosted_registry_images: "{{ openshift.hosted.registry.registryurl | default('openshift3/ose-${component}:${version}')}}"
+    openshift_hosted_registry_volumes: []
+    openshift_hosted_registry_env_vars: {}
+    openshift_hosted_registry_edits:
+    # These edits are being specified only to prevent 'changed' on rerun
+    - key: spec.strategy.rollingParams
+      value:
+        intervalSeconds: 1
+        maxSurge: "25%"
+        maxUnavailable: "25%"
+        timeoutSeconds: 600
+        updatePeriodSeconds: 1
+      action: put
+    openshift_hosted_registry_force:
+    - False
 
 - include: secure.yml
   static: no
-  when: replicas | int > 0 and not (openshift.docker.hosted_registry_insecure | default(false) | bool)
+  run_once: true
+  when:
+  - not (openshift.docker.hosted_registry_insecure | default(false) | bool)
 
 - include: storage/object_storage.yml
   static: no
-  when: replicas | int > 0 and openshift.hosted.registry.storage.kind | default(none) == 'object'
+  when:
+  - openshift.hosted.registry.storage.kind | default(none) == 'object'
 
-- include: storage/persistent_volume.yml
-  static: no
-  when: replicas | int > 0 and openshift.hosted.registry.storage.kind | default(none) in ['nfs', 'openstack']
+- name: Set facts for persistent volume
+  set_fact:
+    pvc_volume_mounts:
+    - name: registry-storage
+      type: persistentVolumeClaim
+      claim_name: "{{ openshift.hosted.registry.storage.volume.name }}-claim"
+    openshift_hosted_registry_volumes: "{{ openshift_hosted_registry_volumes | union(pvc_volume_mounts) }}"
+  when:
+  - openshift.hosted.registry.storage.kind | default(none) in ['nfs', 'openstack']
+
+- name: Create OpenShift registry
+  oc_adm_registry:
+    name: "{{ openshift_hosted_registry_name }}"
+    namespace: "{{ openshift_hosted_registry_namespace }}"
+    selector: "{{ openshift_hosted_registry_selector }}"
+    replicas: "{{ openshift_hosted_registry_replicas }}"
+    service_account: "{{ openshift_hosted_registry_serviceaccount }}"
+    images: "{{ openshift_hosted_registry_images }}"
+    env_vars: "{{ openshift_hosted_registry_env_vars }}"
+    volume_mounts: "{{ openshift_hosted_registry_volumes }}"
+    edits: "{{ openshift_hosted_registry_edits }}"
+    force: "{{ True|bool in openshift_hosted_registry_force }}"
diff --git a/roles/openshift_hosted/tasks/registry/secure.yml b/roles/openshift_hosted/tasks/registry/secure.yml
index 8b44b94c6..e70d377c6 100644
--- a/roles/openshift_hosted/tasks/registry/secure.yml
+++ b/roles/openshift_hosted/tasks/registry/secure.yml
@@ -1,132 +1,77 @@
 ---
+- name: Set fact docker_registry_route_hostname
+  set_fact:
+    docker_registry_route_hostname: "{{ 'docker-registry-default.' ~ (openshift_master_default_subdomain | default('router.default.svc.cluster.local', true)) }}"
+
 - name: Create passthrough route for docker-registry
   oc_route:
-    kubeconfig: "{{ openshift_hosted_kubeconfig }}"
     name: docker-registry
-    namespace: default
+    namespace: "{{ openshift_hosted_registry_namespace }}"
     service_name: docker-registry
-    state: present
     tls_termination: passthrough
-  run_once: true
-
-- name: Determine if registry certificate must be created
-  stat:
-    path: "{{ openshift_master_config_dir }}/{{ item }}"
-  with_items:
-  - registry.crt
-  - registry.key
-  register: docker_registry_certificates_stat_result
-  changed_when: false
-  failed_when: false
+    host: "{{ docker_registry_route_hostname }}"
 
 - name: Retrieve registry service IP
   oc_service:
-    namespace: default
+    namespace: "{{ openshift_hosted_registry_namespace }}"
     name: docker-registry
     state: list
   register: docker_registry_service_ip
-  changed_when: false
-
-- set_fact:
-    docker_registry_route_hostname: "{{ 'docker-registry-default.' ~ (openshift_master_default_subdomain | default('router.default.svc.cluster.local', true)) }}"
 
-- name: Create registry certificates if they do not exist
-  command: >
-    {{ openshift.common.client_binary }} adm ca create-server-cert
-    --signer-cert={{ openshift_master_config_dir }}/ca.crt
-    --signer-key={{ openshift_master_config_dir }}/ca.key
-    --signer-serial={{ openshift_master_config_dir }}/ca.serial.txt
-    --hostnames="{{ docker_registry_service_ip.results.clusterip }},docker-registry.default.svc.cluster.local,{{ docker_registry_route_hostname }}"
-    --cert={{ openshift_master_config_dir }}/registry.crt
-    --key={{ openshift_master_config_dir }}/registry.key
-  when: False in (docker_registry_certificates_stat_result.results | default([]) | oo_collect(attribute='stat.exists') | list)
+- name: Create registry certificates
+  oc_adm_ca_server_cert:
+    signer_cert: "{{ openshift_master_config_dir }}/ca.crt"
+    signer_key: "{{ openshift_master_config_dir }}/ca.key"
+    signer_serial: "{{ openshift_master_config_dir }}/ca.serial.txt"
+    hostnames:
+    - "{{ docker_registry_service_ip.results.clusterip }}"
+    - docker-registry.default.svc.cluster.local
+    - "{{ docker_registry_route_hostname }}"
+    cert: "{{ openshift_master_config_dir }}/registry.crt"
+    key: "{{ openshift_master_config_dir }}/registry.key"
+  register: server_cert_out
 
 - name: Create the secret for the registry certificates
   oc_secret:
-    kubeconfig: "{{ openshift_hosted_kubeconfig }}"
     name: registry-certificates
-    namespace: default
-    state: present
+    namespace: "{{ openshift_hosted_registry_namespace }}"
     files:
     - name: registry.crt
       path: "{{ openshift_master_config_dir }}/registry.crt"
     - name: registry.key
       path: "{{ openshift_master_config_dir }}/registry.key"
-  register: create_registry_certificates_secret
-  run_once: true
+  register: create_registry_certificates_secret_out
 
-- name: "Add the secret to the registry's pod service accounts"
+- name: Add the secret to the registry's pod service accounts
   oc_serviceaccount_secret:
     service_account: "{{ item }}"
     secret: registry-certificates
-    namespace: default
-    kubeconfig: "{{ openshift_hosted_kubeconfig  }}"
-    state: present
+    namespace: "{{ openshift_hosted_registry_namespace }}"
   with_items:
   - registry
   - default
 
-- name: Determine if registry-certificates secret volume attached
-  command: >
-    {{ openshift.common.client_binary }} get dc/docker-registry
-    -o jsonpath='{.spec.template.spec.volumes[?(@.secret)].secret.secretName}'
-    --config={{ openshift_hosted_kubeconfig }}
-    -n default
-  register: docker_registry_volumes
-  changed_when: false
-  failed_when: "docker_registry_volumes.stdout != '' and 'secretName is not found' not in docker_registry_volumes.stdout and docker_registry_volumes.rc != 0"
-
-- name: Attach registry-certificates secret volume
-  command: >
-   {{ openshift.common.client_binary }} volume dc/docker-registry --add --type=secret
-   --secret-name=registry-certificates
-   -m /etc/secrets
-   --config={{ openshift_hosted_kubeconfig }}
-   -n default
-  when: "'registry-certificates' not in docker_registry_volumes.stdout"
-
-- name: Determine if registry environment variables must be set
-  command: >
-    {{ openshift.common.client_binary }} env dc/docker-registry
-    --list
-    --config={{ openshift_hosted_kubeconfig }}
-    -n default
-  register: docker_registry_env
-  changed_when: false
-
-- name: Configure certificates in registry deplomentConfig
-  command: >
-    {{ openshift.common.client_binary }} env dc/docker-registry
-    REGISTRY_HTTP_TLS_CERTIFICATE=/etc/secrets/registry.crt
-    REGISTRY_HTTP_TLS_KEY=/etc/secrets/registry.key
-    --config={{ openshift_hosted_kubeconfig }}
-    -n default
-  when: "'REGISTRY_HTTP_TLS_CERTIFICATE=/etc/secrets/registry.crt' not in docker_registry_env.stdout or 'REGISTRY_HTTP_TLS_KEY=/etc/secrets/registry.key' not in docker_registry_env.stdout"
-
-- name: Determine if registry liveness probe scheme is HTTPS
-  command: >
-    {{ openshift.common.client_binary }} get dc/docker-registry
-    -o jsonpath='{.spec.template.spec.containers[*].livenessProbe.httpGet.scheme}'
-    --config={{ openshift_hosted_kubeconfig }}
-    -n default
-  register: docker_registry_liveness_probe
-  changed_when: false
-
-# This command is on a single line to preserve patch json.
-- name: Update registry liveness probe from HTTP to HTTPS
-  command: "{{ openshift.common.client_binary }} patch dc/docker-registry --api-version=v1 -p '{\"spec\":{\"template\":{\"spec\":{\"containers\":[{\"name\":\"registry\",\"livenessProbe\":{\"httpGet\":{\"scheme\":\"HTTPS\"}}}]}}}}' --config={{ openshift_hosted_kubeconfig }} -n default"
-  when: "'HTTPS' not in docker_registry_liveness_probe.stdout"
-
-- name: Determine if registry readiness probe scheme is HTTPS
-  command: >
-    {{ openshift.common.client_binary }} get dc/docker-registry
-    -o jsonpath='{.spec.template.spec.containers[*].readinessProbe.httpGet.scheme}'
-    --config={{ openshift_hosted_kubeconfig }}
-    -n default
-  register: docker_registry_readiness_probe
-  changed_when: false
+- name: Set facts for secure registry
+  set_fact:
+    registry_secure_volume_mounts:
+    - name: registry-certificates
+      path: /etc/secrets
+      type: secret
+      secret_name: registry-certificates
+    registry_secure_env_vars:
+      REGISTRY_HTTP_TLS_CERTIFICATE: /etc/secrets/registry.crt
+      REGISTRY_HTTP_TLS_KEY: /etc/secrets/registry.key
+    registry_secure_edits:
+    - key: spec.template.spec.containers[0].livenessProbe.httpGet.scheme
+      value: HTTPS
+      action: put
+    - key: spec.template.spec.containers[0].readinessProbe.httpGet.scheme
+      value: HTTPS
+      action: put
 
-# This command is on a single line to preserve patch json.
-- name: Update registry readiness probe from HTTP to HTTPS
-  command: "{{ openshift.common.client_binary }} patch dc/docker-registry --api-version=v1 -p '{\"spec\":{\"template\":{\"spec\":{\"containers\":[{\"name\":\"registry\",\"readinessProbe\":{\"httpGet\":{\"scheme\":\"HTTPS\"}}}]}}}}' --config={{ openshift_hosted_kubeconfig }} -n default"
-  when: "'HTTPS' not in docker_registry_readiness_probe.stdout"
+- name: Update openshift_hosted facts with secure registry variables
+  set_fact:
+    openshift_hosted_registry_volumes: "{{ openshift_hosted_registry_volumes | union(registry_secure_volume_mounts) }}"
+    openshift_hosted_registry_env_vars: "{{ openshift_hosted_registry_env_vars | combine(registry_secure_env_vars) }}"
+    openshift_hosted_registry_edits: "{{ openshift_hosted_registry_edits | union(registry_secure_edits) }}"
+    openshift_hosted_registry_force: "{{ openshift_hosted_registry_force | union([server_cert_out.changed]) | union([create_registry_certificates_secret_out.changed]) }}"
diff --git a/roles/openshift_hosted/tasks/registry/storage/object_storage.yml b/roles/openshift_hosted/tasks/registry/storage/object_storage.yml
index 15128784e..3dde83bee 100644
--- a/roles/openshift_hosted/tasks/registry/storage/object_storage.yml
+++ b/roles/openshift_hosted/tasks/registry/storage/object_storage.yml
@@ -1,105 +1,52 @@
 ---
-- fail:
+- name: Assert supported openshift.hosted.registry.storage.provider
+  assert:
+    that:
+    - openshift.hosted.registry.storage.provider in ['azure_blob', 's3', 'swift']
     msg: >
-      Object Storage Provider: {{ openshift.hosted.registry.storage.provider }}
+      Object Storage Provider: "{{ openshift.hosted.registry.storage.provider }}"
       is not currently supported
-  when: openshift.hosted.registry.storage.provider not in ['azure_blob', 's3', 'swift']
 
-- fail:
+- name: Assert implemented openshift.hosted.registry.storage.provider
+  assert:
+    that:
+    - openshift.hosted.registry.storage.provider not in ['azure_blob', 'swift']
     msg: >
       Support for provider: "{{ openshift.hosted.registry.storage.provider }}"
       not implemented yet
-  when: openshift.hosted.registry.storage.provider in ['azure_blob', 'swift']
 
 - include: s3.yml
   when: openshift.hosted.registry.storage.provider == 's3'
 
-- name: Test if docker registry config secret exists
-  command: >
-    {{ openshift.common.client_binary }}
-    --config={{ openshift_hosted_kubeconfig }}
-    --namespace={{ openshift.hosted.registry.namespace | default('default') }}
-    get secrets {{ registry_config_secret_name }} -o json
-  register: secrets
-  changed_when: false
-  failed_when: false
-
-- set_fact:
-    registry_config: "{{ lookup('template', 'registry_config.j2') | b64encode }}"
-
-- set_fact:
-    registry_config_secret: "{{ lookup('template', 'registry_config_secret.j2') | from_yaml }}"
-
-- set_fact:
-    same_storage_provider: "{{ (secrets.stdout|from_json)['metadata']['annotations']['provider'] | default(none) == openshift.hosted.registry.storage.provider }}"
-  when: secrets.rc == 0
-
-- name: Update registry config secret
-  command: >
-    {{ openshift.common.client_binary }}
-    --config={{ openshift_hosted_kubeconfig }}
-    --namespace={{ openshift.hosted.registry.namespace | default('default') }}
-    patch secret/{{ registry_config_secret_name }}
-    -p '{"data": {"config.yml": "{{ registry_config }}"}}'
-  register: update_config_secret
-  when: secrets.rc == 0 and (secrets.stdout|from_json)['data']['config.yml'] != registry_config and same_storage_provider | bool
-
-- name: Create registry config secret
-  shell: >
-    echo '{{ registry_config_secret |to_json }}' |
-    {{ openshift.common.client_binary }}
-    --config={{ openshift_hosted_kubeconfig }}
-    --namespace={{ openshift.hosted.registry.namespace | default('default') }}
-    create -f -
-  when: secrets.rc == 1
+- name: Ensure the resgistry secret exists
+  oc_secret:
+    name: "{{ registry_config_secret_name }}"
+    state: present
+    contents:
+    - path: /tmp/config.yml
+      data: "{{ lookup('template', 'registry_config.j2') }}"
+  register: registry_config_out
 
 - name: Add secrets to registry service account
   oc_serviceaccount_secret:
     service_account: registry
     secret: "{{ registry_config_secret_name }}"
-    namespace: "{{ openshift.hosted.registry.namespace | default('default') }}"
-    kubeconfig: "{{ openshift_hosted_kubeconfig }}"
+    namespace: "{{ openshift_hosted_registry_namespace }}"
     state: present
-
-- name: Determine if deployment config contains secrets
-  command: >
-    {{ openshift.common.client_binary }}
-    --config={{ openshift_hosted_kubeconfig }}
-    --namespace={{ openshift.hosted.registry.namespace | default('default') }}
-    set volumes dc/docker-registry --list
-  register: volume
-  changed_when: false
-
-- name: Add secrets to registry deployment config
-  command: >
-    {{ openshift.common.client_binary }}
-    --config={{ openshift_hosted_kubeconfig }}
-    --namespace={{ openshift.hosted.registry.namespace | default('default') }}
-    set volumes dc/docker-registry --add --name=docker-config -m /etc/registry
-    --type=secret --secret-name={{ registry_config_secret_name }}
-  when: registry_config_secret_name not in volume.stdout
-
-- name: Determine if registry environment variable needs to be created
-  command: >
-    {{ openshift.common.client_binary }}
-    --config={{ openshift_hosted_kubeconfig }}
-    --namespace={{ openshift.hosted.registry.namespace | default('default') }}
-    set env --list dc/docker-registry
-  register: oc_env
-  changed_when: false
-
-- name: Add registry environment variable
-  command: >
-    {{ openshift.common.client_binary }}
-    --config={{ openshift_hosted_kubeconfig }}
-    --namespace={{ openshift.hosted.registry.namespace | default('default') }}
-    set env dc/docker-registry REGISTRY_CONFIGURATION_PATH=/etc/registry/config.yml
-  when: "'REGISTRY_CONFIGURATION_PATH' not in oc_env.stdout"
-
-- name: Redeploy registry
-  command: >
-    {{ openshift.common.client_binary }}
-    --config={{ openshift_hosted_kubeconfig }}
-    --namespace={{ openshift.hosted.registry.namespace | default('default') }}
-    deploy dc/docker-registry --latest
-  when: secrets.rc == 0 and not update_config_secret | skipped and update_config_secret.rc == 0 and same_storage_provider | bool
+  register: svcac
+
+- name: Set facts for registry object storage
+  set_fact:
+    registry_obj_storage_volume_mounts:
+    - name: docker-config
+      path: /etc/registry
+      type: secret
+      secret_name: "{{ registry_config_secret_name }}"
+    registry_obj_storage_env_vars:
+      REGISTRY_CONFIGURATION_PATH: /etc/registry/config.yml
+
+- name: Update openshift_hosted registry facts for storage
+  set_fact:
+    openshift_hosted_registry_volumes: "{{ openshift_hosted_registry_volumes | union(registry_obj_storage_volume_mounts) }}"
+    openshift_hosted_registry_env_vars: "{{ openshift_hosted_registry_env_vars | combine(registry_obj_storage_env_vars) }}"
+    openshift_hosted_registry_force: "{{ openshift_hosted_registry_force | union([registry_config_out.changed]) | union([svcac.changed]) }}"
diff --git a/roles/openshift_hosted/tasks/registry/storage/persistent_volume.yml b/roles/openshift_hosted/tasks/registry/storage/persistent_volume.yml
deleted file mode 100644
index 0172f5ca0..000000000
--- a/roles/openshift_hosted/tasks/registry/storage/persistent_volume.yml
+++ /dev/null
@@ -1,26 +0,0 @@
----
-- set_fact:
-    registry_volume_claim: "{{ openshift.hosted.registry.storage.volume.name }}-claim"
-
-- name: Determine if volume is already attached to dc/docker-registry
-  command: >
-      {{ openshift.common.client_binary }}
-      --config={{ openshift_hosted_kubeconfig }}
-      --namespace={{ openshift.hosted.registry.namespace | default('default') }}
-      get -o template dc/docker-registry --template=\\{\\{.spec.template.spec.volumes\\}\\} --output-version=v1
-  changed_when: false
-  failed_when: false
-  register: registry_volumes_output
-
-- set_fact:
-    volume_attached: "{{ registry_volume_claim in (registry_volumes_output).stdout | default(['']) }}"
-
-- name: Add volume to dc/docker-registry
-  command: >
-    {{ openshift.common.client_binary }}
-    --config={{ openshift_hosted_kubeconfig }}
-    --namespace={{ openshift.hosted.registry.namespace | default('default') }}
-    volume dc/docker-registry
-    --add --overwrite -t persistentVolumeClaim --claim-name={{ registry_volume_claim }}
-    --name=registry-storage
-  when: not volume_attached | bool
diff --git a/roles/openshift_hosted/tasks/registry/storage/s3.yml b/roles/openshift_hosted/tasks/registry/storage/s3.yml
index 16709dfef..69b91be0b 100644
--- a/roles/openshift_hosted/tasks/registry/storage/s3.yml
+++ b/roles/openshift_hosted/tasks/registry/storage/s3.yml
@@ -1,47 +1,48 @@
 ---
-- fail:
-    msg: >
-      openshift_hosted_registry_storage_s3_accesskey and
-      openshift_hosted_registry_storage_s3_secretkey are required
-  when: openshift.hosted.registry.storage.s3.accesskey | default(none) is none or openshift.hosted.registry.storage.s3.secretkey | default(none) is none
-
-- fail:
-    msg: >
-      openshift_hosted_registry_storage_s3_bucket and
-      openshift_hosted_registry_storage_s3_region are required
-  when: openshift.hosted.registry.storage.s3.bucket | default(none) is none or openshift.hosted.registry.storage.s3.region | default(none) is none
+- name: Assert that S3 variables are provided for registry_config template
+  assert:
+    that:
+    - openshift.hosted.registry.storage.s3.accesskey | default(none) is not none
+    - openshift.hosted.registry.storage.s3.secretkey | default(none) is not none
+    - openshift.hosted.registry.storage.s3.bucket | default(none) is not none
+    - openshift.hosted.registry.storage.s3.region | default(none) is not none
+    msg: |
+      When using S3 storage, the following variables are required:
+        openshift_hosted_registry_storage_s3_accesskey
+        openshift_hosted_registry_storage_s3_secretkey
+        openshift_hosted_registry_storage_s3_bucket
+        openshift_hosted_registry_storage_s3_region
 
-# If cloudfront is being used, fail if we don't have all the required variables
-- assert:
+- name: If cloudfront is being used, assert that we have all the required variables
+  assert:
     that:
-      - "openshift_hosted_registry_storage_s3_cloudfront_baseurl is not defined or openshift_hosted_registry_storage_s3_cloudfront_privatekeyfile | default(none) is not none"
-      - "openshift_hosted_registry_storage_s3_cloudfront_baseurl is not defined or openshift_hosted_registry_storage_s3_cloudfront_keypairid | default(none) is not none"
-    msg: >
+    - "openshift_hosted_registry_storage_s3_cloudfront_privatekeyfile | default(none) is not none"
+    - "openshift_hosted_registry_storage_s3_cloudfront_keypairid | default(none) is not none"
+    msg: |
       When openshift_hosted_registry_storage_s3_cloudfront_baseurl is provided
-      openshift_hosted_registry_storage_s3_cloudfront_keypairid and
-      openshift_hosted_registry_storage_s3_cloudfront_privatekeyfile are required
-
+        openshift_hosted_registry_storage_s3_cloudfront_keypairid and
+        openshift_hosted_registry_storage_s3_cloudfront_privatekeyfile are required
+  when: openshift_hosted_registry_storage_s3_cloudfront_baseurl is defined
 
 # Inject the cloudfront private key as a secret when required
 - block:
 
-    - name: Create registry secret for cloudfront
-      oc_secret:
-        state: present
-        namespace: "{{ openshift.hosted.registry.namespace | default('default') }}"
-        name: docker-registry-s3-cloudfront
-        contents:
-          - path: cloudfront.pem
-            data: "{{ lookup('file', openshift_hosted_registry_storage_s3_cloudfront_privatekeyfile) }}"
+  - name: Create registry secret for cloudfront
+    oc_secret:
+      state: present
+      namespace: "{{ openshift_hosted_registry_namespace }}"
+      name: docker-registry-s3-cloudfront
+      contents:
+      - path: cloudfront.pem
+        data: "{{ lookup('file', openshift_hosted_registry_storage_s3_cloudfront_privatekeyfile) }}"
 
-    - name: Add cloudfront secret to the registry deployment config
-      command: >
-        oc volume dc/docker-registry --add --name=cloudfront-vol
-        --namespace="{{ openshift.hosted.registry.namespace | default('default') }}"
-        -m /etc/origin --type=secret --secret-name=docker-registry-s3-cloudfront
-      register: cloudfront_vol_attach
-      failed_when:
-        - "'already exists' not in cloudfront_vol_attach.stderr"
-        - "cloudfront_vol_attach.rc != 0"
+  - name: Add cloudfront secret to the registry volumes
+    set_fact:
+      s3_volume_mount:
+      - name: cloudfront-vol
+        path: /etc/origin
+        type: secret
+        secret_name: docker-registry-s3-cloudfront
+      openshift_hosted_registry_volumes: "{{ openshift_hosted_registry_volumes | union(s3_volume_mount) }}"
 
   when: openshift_hosted_registry_storage_s3_cloudfront_baseurl | default(none) is not none
diff --git a/roles/openshift_hosted/tasks/router/router.yml b/roles/openshift_hosted/tasks/router/router.yml
index 3d5713d6b..3535d5f5e 100644
--- a/roles/openshift_hosted/tasks/router/router.yml
+++ b/roles/openshift_hosted/tasks/router/router.yml
@@ -1,104 +1,91 @@
 ---
-- fail:
-    msg: "'certfile', 'keyfile' and 'cafile' keys must be specified when supplying the openshift_hosted_router_certificate variable."
-  when: openshift_hosted_router_certificate is defined and ('certfile' not in openshift_hosted_router_certificate or 'keyfile' not in openshift_hosted_router_certificate or 'cafile' not in openshift_hosted_router_certificate)
+- name: Retrieve list of openshift nodes matching router selector
+  oc_obj:
+    state: list
+    kind: node
+    namespace: "{{ openshift.hosted.router.namespace | default('default') }}"
+    selector: "{{ openshift.hosted.router.selector | default(omit) }}"
+  register: router_nodes
+  when: openshift.hosted.router.replicas | default(none) is none
 
-- name: Read router certificate and key
-  become: no
-  local_action:
-    module: slurp
-    src: "{{ item }}"
-  register: openshift_router_certificate_output
-  # Defaulting dictionary keys to none to avoid deprecation warnings
-  # (future fatal errors) during template evaluation. Dictionary keys
-  # won't be accessed unless openshift_hosted_router_certificate is
-  # defined and has all keys (certfile, keyfile, cafile) which we
-  # check above.
-  with_items:
-  - "{{ (openshift_hosted_router_certificate | default({'certfile':none})).certfile }}"
-  - "{{ (openshift_hosted_router_certificate | default({'keyfile':none})).keyfile }}"
-  - "{{ (openshift_hosted_router_certificate | default({'cafile':none})).cafile }}"
-  when: openshift_hosted_router_certificate is defined
+- name: set_fact replicas
+  set_fact:
+    replicas: "{{ openshift.hosted.router.replicas | default(router_nodes.results.results[0]['items'] | length) }}"
 
-- name: Persist certificate contents
-  openshift_facts:
-    role: hosted
-    openshift_env:
-      openshift_hosted_router_certificate_contents: "{% for certificate in openshift_router_certificate_output.results -%}{{ certificate.content | b64decode }}{% endfor -%}"
-  when: openshift_hosted_router_certificate is defined
+- block:
 
-- name: Create PEM certificate
-  copy:
-    content: "{{ openshift.hosted.router.certificate.contents }}"
-    dest: "{{ openshift_master_config_dir }}/openshift-router.pem"
-    mode: 0600
-  when: "'certificate' in openshift.hosted.router and 'contents' in openshift.hosted.router.certificate"
+  - name: Assert that 'certfile', 'keyfile' and 'cafile' keys provided in openshift_hosted_router_certificate
+    assert:
+      that:
+      - "'certfile' in openshift_hosted_router_certificate"
+      - "'keyfile' in openshift_hosted_router_certificate"
+      - "'cafile' in openshift_hosted_router_certificate"
+      msg: "'certfile', 'keyfile' and 'cafile' keys must be specified when supplying the openshift_hosted_router_certificate variable."
 
-- name: Retrieve list of openshift nodes matching router selector
-  command: >
-    {{ openshift.common.client_binary }} --api-version='v1' -o json
-    get nodes -n default --config={{ openshift_hosted_kubeconfig }}
-    --selector={{ openshift.hosted.router.selector | default('') }}
-  register: router_nodes_json
-  changed_when: false
-  when: openshift.hosted.router.replicas | default(none) is none
+  - name: Read router certificate and key
+    become: no
+    local_action:
+      module: slurp
+      src: "{{ item }}"
+    register: openshift_router_certificate_output
+    # Defaulting dictionary keys to none to avoid deprecation warnings
+    # (future fatal errors) during template evaluation. Dictionary keys
+    # won't be accessed unless openshift_hosted_router_certificate is
+    # defined and has all keys (certfile, keyfile, cafile) which we
+    # check above.
+    with_items:
+    - "{{ (openshift_hosted_router_certificate | default({'certfile':none})).certfile }}"
+    - "{{ (openshift_hosted_router_certificate | default({'keyfile':none})).keyfile }}"
+    - "{{ (openshift_hosted_router_certificate | default({'cafile':none})).cafile }}"
 
-- set_fact:
-    replicas: "{{ openshift.hosted.router.replicas | default((router_nodes_json.stdout | default('{\"items\":[]}') | from_json)['items'] | length) }}"
+  - name: Persist certificate contents
+    openshift_facts:
+      role: hosted
+      openshift_env:
+        openshift_hosted_router_certificate_contents: "{% for certificate in openshift_router_certificate_output.results -%}{{ certificate.content | b64decode }}{% endfor -%}"
 
-- name: Create OpenShift router
-  command: >
-    {{ openshift.common.client_binary }} adm router --create
-    --config={{ openshift_hosted_kubeconfig }}
-    {% if replicas > 1 -%}
-    --replicas={{ replicas }}
-    {% endif -%}
-    {% if 'certificate' in openshift.hosted.router and 'contents' in openshift.hosted.router.certificate -%}
-    --default-cert={{ openshift_master_config_dir }}/openshift-router.pem
-    {% endif -%}
-    --namespace={{ openshift.hosted.router.namespace | default('default') }}
-    {% if openshift.hosted.router.force_subdomain | default(none) is not none %}
-    --force-subdomain={{ openshift.hosted.router.force_subdomain }}
-    {% endif %}
-    --service-account=router
-    {% if openshift.hosted.router.selector | default(none) is not none -%}
-    --selector='{{ openshift.hosted.router.selector }}'
-    {% endif -%}
-    {% if not openshift.common.version_gte_3_2_or_1_2 | bool -%}
-    --credentials={{ openshift_master_config_dir }}/openshift-router.kubeconfig
-    {% endif -%}
-    {% if openshift.hosted.router.registryurl | default(none) is not none -%}
-    --images='{{ openshift.hosted.router.registryurl }}'
-    {% endif -%}
-    {% if openshift.hosted.router.name | default(none) is not none -%}
-    {{ openshift.hosted.router.name }}
-    {% endif -%}
+  - name: Create PEM certificate
+    copy:
+      content: "{{ openshift.hosted.router.certificate.contents }}"
+      dest: "{{ openshift_master_config_dir }}/openshift-router.pem"
+      mode: 0600
 
-  register: openshift_hosted_router_results
-  changed_when: "'service exists' not in openshift_hosted_router_results.stdout"
-  failed_when: "openshift_hosted_router_results.rc != 0 and 'service exists' not in openshift_hosted_router_results.stdout and 'deployment_config' not in openshift_hosted_router_results.stderr and 'service' not in openshift_hosted_router_results.stderr"
-  when: replicas | int > 0
+  when: openshift_hosted_router_certificate is defined
 
-- command: >
-    {{ openshift.common.client_binary }}
-    {% if openshift.hosted.router.name | default(none) is not none -%}
-    get dc/{{ openshift.hosted.router.name }}
-    {% else %}
-    get dc/router
-    {% endif%}
-    --template=\\{\\{.spec.replicas\\}\\}
-    --namespace={{ openshift.hosted.router.namespace | default('default') }}
-  register: current_replicas
-  when: replicas | int > 0
+- name: Create OpenShift router
+  oc_adm_router:
+    name: "{{ openshift.hosted.router.name | default('router') }}"
+    replicas: "{{ replicas }}"
+    namespace: "{{ openshift.hosted.router.namespace | default('default') }}"
+    # This option is not yet implemented
+    # force_subdomain: "{{ openshift.hosted.router.force_subdomain | default(none) }}"
+    service_account: router
+    selector: "{{ openshift.hosted.router.selector | default(none) }}"
+    images: "{{ openshift.hosted.router.registryurl | default(none) }}"
+    default_cert: "{{ openshift_hosted_router_certificate is defined | default(false) | ternary(openshift_master_config_dir + '/openshift-router.pem', omit) }}"
+    # These edits are being specified only to prevent 'changed' on rerun
+    edits:
+    - key: spec.strategy.rollingParams.intervalSeconds
+      value: 1
+      action: put
+    - key: spec.strategy.rollingParams.updatePeriodSeconds
+      value: 1
+      action: put
+    - key: spec.strategy.activeDeadlineSeconds
+      value: 21600
+      action: put
+  register: routerout
+
+# This should probably move to module
+- name: wait for deploy
+  pause:
+    seconds: 30
+  when: routerout.changed
 
 - name: Ensure router replica count matches desired
-  command: >
-    {{ openshift.common.client_binary }}
-    scale --replicas={{ replicas }}
-    {% if openshift.hosted.router.name | default(none) is not none -%}
-    dc/{{ openshift.hosted.router.name }}
-    {% else %}
-    dc/router
-    {% endif%}
-    --namespace={{ openshift.hosted.router.namespace | default('default') }}
-  when: replicas | int > 0 and replicas | int != current_replicas.stdout | int
+  oc_scale:
+    kind: dc
+    name: "{{ openshift.hosted.router.name | default('router') }}"
+    namespace: "{{ openshift.hosted.router.namespace | default('default') }}"
+    replicas: "{{ replicas }}"
+  when: replicas | int > 0
-- 
cgit v1.2.3