Merge "Replace VNC server docker image"
diff --git a/ansible/library/rancher1_api.py b/ansible/library/rancher1_api.py
new file mode 100644
index 0000000..5d74da1
--- /dev/null
+++ b/ansible/library/rancher1_api.py
@@ -0,0 +1,598 @@
+#!/usr/bin/python
+
+from ansible.module_utils.basic import AnsibleModule
+
+import requests
+import json
+import functools
+import time
+
+DOCUMENTATION = """
+---
+module: rancher1_api
+short_description: Client library for rancher API
+description:
+  - This module modifies a rancher 1.6 using it's API (v1).
+  - It supports some rancher features by the virtue of a 'mode'.
+  - 'modes' hide from you some necessary cruft and expose you to the only
+    important and interestig variables wich must be set. The mode mechanism
+    makes this module more easy to use and you don't have to create an
+    unnecessary boilerplate for the API.
+  - Only a few modes are/will be implemented so far - as they are/will be
+    needed. In the future the 'raw' mode can be added to enable you to craft
+    your own API requests, but that would be on the same level of a user
+    experience as running curl commands, and because the rancher 1.6 is already
+    obsoleted by the project, it would be a wasted effort.
+options:
+  rancher:
+    description:
+      - The domain name or the IP address and the port of the rancher
+        where API is exposed.
+      - For example: http://10.0.0.1:8080
+    required: true
+    aliases:
+      - server
+      - rancher_server
+      - rancher_api
+      - api
+  account_key:
+    description:
+      - The public and secret part of the API key-pair separated by colon.
+      - You can find all your keys in web UI.
+      - For example:
+        B1716C4133D3825051CB:3P2eb3QhokFKYUiXRNZLxvGNSRYgh6LHjuMicCHQ
+    required: false
+  mode:
+    description:
+      - A recognized mode how to deal with some concrete configuration task
+        in rancher API to ease the usage.
+      - The implemented modes so far are:
+        'settings':
+            Many options under <api_server>/v1/settings API url and some can
+            be seen also under advanced options in the web UI.
+        'access_control':
+            It setups user and password for the account (defaults to 'admin')
+            and it enables the local authentication - so the web UI and API
+            will require username/password (UI) or apikey (API).
+    required: true
+    aliases:
+      - rancher_mode
+      - api_mode
+    choices:
+      - settings
+      - access_control
+  data:
+    description:
+      - Dictionary with key/value pairs. The actual names and meaning of pairs
+        depends on the used mode.
+      - settings mode:
+        option - Option/path in JSON API (url).
+        value - A new value to replace the current one.
+      - access_control mode:
+        account_id - The unique ID of the account - the default rancher admin
+        has '1a1'. Better way would be to just create arbitrary username and
+        set credentials for that, but due to time constraints, the route with
+        an ID is simpler. The designated '1a1' could be hardcoded and hidden
+        but if the user will want to use some other account (there are many),
+        then it can be just changed to some other ID.
+        password - A new password in a plaintext.
+    required: true
+  timeout:
+    description:
+      - How long in seconds to wait for a response before raising error
+    required: false
+    default: 10.0
+"""
+
+default_timeout = 10.0
+
+
+class ModeError(Exception):
+    pass
+
+
+def _decorate_rancher_api_request(request_method):
+
+    @functools.wraps(request_method)
+    def wrap_request(*args, **kwargs):
+
+        response = request_method(*args, **kwargs)
+        authorized = True
+
+        if response.status_code == 401:
+            authorized = False
+        elif response.status_code != requests.codes.ok:
+            response.raise_for_status()
+
+        try:
+            json_data = response.json()
+        except Exception:
+            json_data = None
+
+        return json_data, authorized
+
+    return wrap_request
+
+
+@_decorate_rancher_api_request
+def get_rancher_api_value(url, headers=None, timeout=default_timeout,
+                          username=None, password=None):
+
+    if username and password:
+        return requests.get(url, headers=headers,
+                            timeout=timeout,
+                            allow_redirects=False,
+                            auth=(username, password))
+    else:
+        return requests.get(url, headers=headers,
+                            timeout=timeout,
+                            allow_redirects=False)
+
+
+@_decorate_rancher_api_request
+def set_rancher_api_value(url, payload, headers=None, timeout=default_timeout,
+                          username=None, password=None, method='PUT'):
+
+    if method == 'PUT':
+        request_set_method = requests.put
+    elif method == 'POST':
+        request_set_method = requests.post
+    else:
+        raise ModeError('ERROR: Wrong request method: %s' % str(method))
+
+    if username and password:
+        return request_set_method(url, headers=headers,
+                                  timeout=timeout,
+                                  allow_redirects=False,
+                                  data=json.dumps(payload),
+                                  auth=(username, password))
+    else:
+        return request_set_method(url, headers=headers,
+                                  timeout=timeout,
+                                  allow_redirects=False,
+                                  data=json.dumps(payload))
+
+
+def create_rancher_api_url(server, mode, option):
+    request_url = server.strip('/') + '/v1/'
+
+    if mode == 'raw':
+        request_url += option.strip('/')
+    elif mode == 'settings':
+        request_url += 'settings/' + option.strip('/')
+    elif mode == 'access_control':
+        request_url += option.strip('/')
+
+    return request_url
+
+
+def get_keypair(keypair):
+    if keypair:
+        keypair = keypair.split(':')
+        if len(keypair) == 2:
+            return keypair[0], keypair[1]
+
+    return None, None
+
+
+def mode_access_control(api_url, data=None, headers=None,
+                        timeout=default_timeout, access_key=None,
+                        secret_key=None, dry_run=False):
+
+    # returns true if local auth was enabled or false if passwd changed
+    def is_admin_enabled(json_data, password):
+        try:
+            if json_data['type'] == "localAuthConfig" and \
+                    json_data['accessMode'] == "unrestricted" and \
+                    json_data['username'] == "admin" and \
+                    json_data['password'] == password and \
+                    json_data['enabled']:
+                return True
+        except Exception:
+            pass
+
+        try:
+            if json_data['type'] == "error" and \
+                    json_data['code'] == "IncorrectPassword":
+                return False
+        except Exception:
+            pass
+
+        # this should never happen
+        raise ModeError('ERROR: Unknown status of the local authentication')
+
+    def create_localauth_payload(password):
+        payload = {
+            "enabled": True,
+            "accessMode": "unrestricted",
+            "username": "admin",
+            "password": password
+        }
+
+        return payload
+
+    def get_admin_password_id():
+        # assemble request URL
+        request_url = api_url + 'accounts/' + data['account_id'].strip('/') \
+            + '/credentials'
+
+        # API get current value
+        try:
+            json_response, authorized = \
+                get_rancher_api_value(request_url,
+                                      username=access_key,
+                                      password=secret_key,
+                                      headers=headers,
+                                      timeout=timeout)
+        except requests.HTTPError as e:
+            raise ModeError(str(e))
+        except requests.Timeout as e:
+            raise ModeError(str(e))
+
+        if not authorized or not json_response:
+            raise ModeError('ERROR: BAD RESPONSE (GET) - no json value in '
+                            + 'the response')
+
+        try:
+            for item in json_response['data']:
+                if item['type'] == 'password' and \
+                        item['accountId'] == data['account_id']:
+                    return item['id']
+        except Exception:
+            pass
+
+        return None
+
+    def remove_password(password_id, action):
+        if action == 'deactivate':
+            action_status = 'deactivating'
+        elif action == 'remove':
+            action_status = 'removing'
+
+        request_url = api_url + 'passwords/' + password_id + \
+            '/?action=' + action
+
+        try:
+            json_response, authorized = \
+                set_rancher_api_value(request_url,
+                                      {},
+                                      username=access_key,
+                                      password=secret_key,
+                                      headers=headers,
+                                      method='POST',
+                                      timeout=timeout)
+        except requests.HTTPError as e:
+            raise ModeError(str(e))
+        except requests.Timeout as e:
+            raise ModeError(str(e))
+
+        if not authorized or not json_response:
+            raise ModeError('ERROR: BAD RESPONSE (POST) - no json value in '
+                            + 'the response')
+
+        if json_response['state'] != action_status:
+            raise ModeError("ERROR: Failed to '%s' the password: %s" %
+                            (action, password_id))
+
+    # check if data contains all required fields
+    try:
+        if not isinstance(data['account_id'], str) or data['account_id'] == '':
+            raise ModeError("ERROR: 'account_id' must contain an id of the "
+                            + "affected account")
+    except KeyError:
+        raise ModeError("ERROR: Mode 'access_control' requires the field: "
+                        + "'account_id': %s" % str(data))
+    try:
+        if not isinstance(data['password'], str) or data['password'] == '':
+            raise ModeError("ERROR: 'password' must contain some password")
+    except KeyError:
+        raise ModeError("ERROR: Mode 'access_control' requires the field: "
+                        + "'password': %s" % str(data))
+
+    # assemble request URL
+    request_url = api_url + 'localauthconfigs'
+
+    # API get current value
+    try:
+        json_response, authorized = \
+            get_rancher_api_value(request_url,
+                                  username=access_key,
+                                  password=secret_key,
+                                  headers=headers,
+                                  timeout=timeout)
+    except requests.HTTPError as e:
+        raise ModeError(str(e))
+    except requests.Timeout as e:
+        raise ModeError(str(e))
+
+    if not authorized or not json_response:
+        raise ModeError('ERROR: BAD RESPONSE (GET) - no json value in the '
+                        + 'response')
+
+    # we will check if local auth is enabled or not
+    enabled = False
+    try:
+        for item in json_response['data']:
+            if item['type'] == 'localAuthConfig' and \
+                    item['accessMode'] == 'unrestricted' and \
+                    item['enabled']:
+                enabled = True
+                break
+    except Exception:
+        enabled = False
+
+    if dry_run:
+        # we will not set anything and only signal potential change
+        if enabled:
+            changed = False
+        else:
+            changed = True
+    else:
+        # we will try to enable again with the same password
+        localauth_payload = create_localauth_payload(data['password'])
+        try:
+            json_response, authorized = \
+                set_rancher_api_value(request_url,
+                                      localauth_payload,
+                                      username=access_key,
+                                      password=secret_key,
+                                      headers=headers,
+                                      method='POST',
+                                      timeout=timeout)
+        except requests.HTTPError as e:
+            raise ModeError(str(e))
+        except requests.Timeout as e:
+            raise ModeError(str(e))
+
+        # here we ignore authorized status - we will try to reset password
+        if not json_response:
+            raise ModeError('ERROR: BAD RESPONSE (POST) - no json value in '
+                            + 'the response')
+
+        # we check if the admin was already set or not...
+        if enabled and is_admin_enabled(json_response, data['password']):
+            # it was enabled before and password is the same - no change
+            changed = False
+        elif is_admin_enabled(json_response, data['password']):
+            # we enabled it for the first time
+            changed = True
+        # ...and reset password if needed (unauthorized access)
+        else:
+            # local auth is enabled but the password differs
+            # we must reset the admin's password
+            password_id = get_admin_password_id()
+
+            if password_id is None:
+                raise ModeError("ERROR: admin's password is set, but we "
+                                + "cannot identify it")
+
+            # One of the way to reset the password is to remove it first
+            # TODO - refactor this
+            remove_password(password_id, 'deactivate')
+            time.sleep(2)
+            remove_password(password_id, 'remove')
+            time.sleep(1)
+
+            try:
+                json_response, authorized = \
+                    set_rancher_api_value(request_url,
+                                          localauth_payload,
+                                          username=access_key,
+                                          password=secret_key,
+                                          headers=headers,
+                                          method='POST',
+                                          timeout=timeout)
+            except requests.HTTPError as e:
+                raise ModeError(str(e))
+            except requests.Timeout as e:
+                raise ModeError(str(e))
+
+            # finally we signal the change
+            changed = True
+
+    if changed:
+        msg = "Local authentication is enabled, admin has assigned password"
+    else:
+        msg = "Local authentication was already enabled, admin's password " \
+            + "is unchanged"
+
+    return changed, msg
+
+
+def mode_settings(api_url, data=None, headers=None, timeout=default_timeout,
+                  access_key=None, secret_key=None, dry_run=False):
+
+    def is_valid_rancher_api_option(json_data):
+
+        try:
+            api_activeValue = json_data['activeValue']
+            api_source = json_data['source']
+        except Exception:
+            return False
+
+        if api_activeValue is None and api_source is None:
+            return False
+
+        return True
+
+    def create_rancher_api_payload(json_data, new_value):
+
+        payload = {}
+        differs = False
+
+        try:
+            api_id = json_data['id']
+            api_activeValue = json_data['activeValue']
+            api_name = json_data['name']
+            api_source = json_data['source']
+        except Exception:
+            raise ValueError
+
+        payload.update({"activeValue": api_activeValue,
+                        "id": api_id,
+                        "name": api_name,
+                        "source": api_source,
+                        "value": new_value})
+
+        if api_activeValue != new_value:
+            differs = True
+
+        return differs, payload
+
+    # check if data contains all required fields
+    try:
+        if not isinstance(data['option'], str) or data['option'] == '':
+            raise ModeError("ERROR: 'option' must contain a name of the "
+                            + "option")
+    except KeyError:
+        raise ModeError("ERROR: Mode 'settings' requires the field: 'option': "
+                        + "%s" % str(data))
+    try:
+        if not isinstance(data['value'], str) or data['value'] == '':
+            raise ModeError("ERROR: 'value' must contain a value")
+    except KeyError:
+        raise ModeError("ERROR: Mode 'settings' requires the field: 'value': "
+                        + "%s" % str(data))
+
+    # assemble request URL
+    request_url = api_url + 'settings/' + data['option'].strip('/')
+
+    # API get current value
+    try:
+        json_response, authorized = \
+            get_rancher_api_value(request_url,
+                                  username=access_key,
+                                  password=secret_key,
+                                  headers=headers,
+                                  timeout=timeout)
+    except requests.HTTPError as e:
+        raise ModeError(str(e))
+    except requests.Timeout as e:
+        raise ModeError(str(e))
+
+    if not authorized or not json_response:
+        raise ModeError('ERROR: BAD RESPONSE (GET) - no json value in the '
+                        + 'response')
+
+    if is_valid_rancher_api_option(json_response):
+        valid = True
+        try:
+            differs, payload = create_rancher_api_payload(json_response,
+                                                          data['value'])
+        except ValueError:
+            raise ModeError('ERROR: INVALID JSON - missing json values in '
+                            + 'the response')
+    else:
+        valid = False
+
+    if valid and differs and dry_run:
+        # ansible dry-run mode
+        changed = True
+    elif valid and differs:
+        # API set new value
+        try:
+            json_response, authorized = \
+                set_rancher_api_value(request_url,
+                                      payload,
+                                      username=access_key,
+                                      password=secret_key,
+                                      headers=headers,
+                                      timeout=timeout)
+        except requests.HTTPError as e:
+            raise ModeError(str(e))
+        except requests.Timeout as e:
+            raise ModeError(str(e))
+
+        if not authorized or not json_response:
+            raise ModeError('ERROR: BAD RESPONSE (PUT) - no json value in '
+                            + 'the response')
+        else:
+            changed = True
+    else:
+        changed = False
+
+    if changed:
+        msg = "Option '%s' is now set to the new value: %s" \
+            % (data['option'], data['value'])
+    else:
+        msg = "Option '%s' is unchanged." % (data['option'])
+
+    return changed, msg
+
+
+def mode_handler(server, rancher_mode, data=None, timeout=default_timeout,
+                 account_key=None, dry_run=False):
+
+    changed = False
+    msg = 'UNKNOWN: UNAPPLICABLE MODE'
+
+    # check API key-pair
+    if account_key:
+        access_key, secret_key = get_keypair(account_key)
+        if not (access_key and secret_key):
+            raise ModeError('ERROR: INVALID API KEY-PAIR')
+
+    # all requests share these headers
+    http_headers = {'Content-Type': 'application/json',
+                    'Accept': 'application/json'}
+
+    # assemble API url
+    api_url = server.strip('/') + '/v1/'
+
+    if rancher_mode == 'settings':
+        changed, msg = mode_settings(api_url, data=data,
+                                     headers=http_headers,
+                                     timeout=timeout,
+                                     access_key=access_key,
+                                     secret_key=secret_key,
+                                     dry_run=dry_run)
+    elif rancher_mode == 'access_control':
+        changed, msg = mode_access_control(api_url, data=data,
+                                           headers=http_headers,
+                                           timeout=timeout,
+                                           access_key=access_key,
+                                           secret_key=secret_key,
+                                           dry_run=dry_run)
+
+    return changed, msg
+
+
+def main():
+    module = AnsibleModule(
+        argument_spec=dict(
+            rancher=dict(type='str', required=True,
+                         aliases=['server',
+                                  'rancher_api',
+                                  'rancher_server',
+                                  'api']),
+            account_key=dict(type='str', required=False),
+            mode=dict(required=True,
+                      choices=['settings', 'access_control'],
+                      aliases=['api_mode']),
+            data=dict(type='dict', required=True),
+            timeout=dict(type='float', default=default_timeout),
+        ),
+        supports_check_mode=True
+    )
+
+    rancher_server = module.params['rancher']
+    rancher_account_key = module.params['account_key']
+    rancher_mode = module.params['mode']
+    rancher_data = module.params['data']
+    rancher_timeout = module.params['timeout']
+
+    try:
+        changed, msg = mode_handler(rancher_server,
+                                    rancher_mode,
+                                    data=rancher_data,
+                                    account_key=rancher_account_key,
+                                    timeout=rancher_timeout,
+                                    dry_run=module.check_mode)
+    except ModeError as e:
+        module.fail_json(msg=str(e))
+
+    module.exit_json(changed=changed, msg=msg)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/ansible/roles/rancher/defaults/main.yml b/ansible/roles/rancher/defaults/main.yml
index 6ab52e6..6d354e6 100644
--- a/ansible/roles/rancher/defaults/main.yml
+++ b/ansible/roles/rancher/defaults/main.yml
@@ -4,3 +4,30 @@
 rancher_redeploy_k8s_env: true
 rancher_cluster_health_state: healthy
 rancher_cluster_health_check_retries: 30
+rancher:
+  # The following variables can be set via the UI under advanced/settings.
+  # All of these affect tables in the cattle db and are uninteresting
+  # to the user (they serve the internal logic of the cattle), but
+  # they can eat a lot of space when a deployment is busy or faulty.
+  #
+  # Audit-Log is the only user-facing option here and it is represented
+  # in the UI.
+  #
+  # Auto-purge deleted entries from most tables after this long (seconds)
+  main_tables_purge_after_seconds: 28800  # 8 hours
+  # Auto-purge Event entries after this long (seconds)
+  events_purge_after_seconds: 28800       # 8 hours
+  # Auto-purge Service Log entries after this long (seconds)
+  service_log_purge_after_seconds: 86400  # 1 day
+  # Auto-purge Audit Log entries after this long (seconds)
+  audit_log_purge_after_seconds: 2592000  # 30 days
+
+  # By default we don't enable local authentication (mainly due to
+  # to the fact that rancher_k8s_environment.py would have to be
+  # rewritten completely)
+  # But if you don't need to run rancher_kubernetes playbook more
+  # than once (you should not have to under the terms of a regular
+  # installation), then you can safely enable it.
+  auth_enabled: false
+  # Set this password for the rancher admin account:
+  admin_password: "admin"
diff --git a/ansible/roles/rancher/tasks/rancher_server.yml b/ansible/roles/rancher/tasks/rancher_server.yml
index e1eb5a5..4cda372 100644
--- a/ansible/roles/rancher/tasks/rancher_server.yml
+++ b/ansible/roles/rancher/tasks/rancher_server.yml
@@ -32,6 +32,14 @@
   delay: 5
   until: env.data is defined
 
+# There is a lack of idempotency in the previous task and so there are new api
+# key-pairs created with each run.
+#
+# ToDo: fix idempotency of rancher role
+#
+# Anyway as rke will be default k8s orchestrator in Dublin, it's supposed to be
+# low prio topic. The following tasks dealing with the API are ignoring this problem
+# and they simply use the new created API key-pair, which is set as a fact here:
 - name: Set apikey values
   set_fact:
     k8s_env_id: "{{ env.data.environment.id }}"
@@ -39,3 +47,49 @@
     key_private: "{{ env.data.apikey.private }}"
     rancher_agent_image: "{{ env.data.registration_tokens.image }}"
     rancher_agent_reg_url: "{{ env.data.registration_tokens.reg_url }}"
+
+# By default disabled - when enabled this playbook cannot be run more than once.
+- name: Setup rancher admin password and enable authentication
+  rancher1_api:
+    server: "{{ rancher_server_url }}"
+    account_key: "{{ key_public }}:{{ key_private }}"
+    mode: access_control
+    data:
+      account_id: 1a1 # default rancher admin account
+      password: "{{ rancher.admin_password }}"
+  when: "rancher.auth_enabled is defined and rancher.auth_enabled"
+
+- name: Configure the size of the rancher cattle db and logs
+  block:
+    - name: Main tables
+      rancher1_api:
+        server: "{{ rancher_server_url }}"
+        account_key: "{{ key_public }}:{{ key_private }}"
+        mode: settings
+        data:
+          option: main_tables.purge.after.seconds
+          value: "{{ rancher.main_tables_purge_after_seconds }}"
+    - name: Events
+      rancher1_api:
+        server: "{{ rancher_server_url }}"
+        account_key: "{{ key_public }}:{{ key_private }}"
+        mode: settings
+        data:
+          option: events.purge.after.seconds
+          value: "{{ rancher.events_purge_after_seconds }}"
+    - name: Service log
+      rancher1_api:
+        server: "{{ rancher_server_url }}"
+        account_key: "{{ key_public }}:{{ key_private }}"
+        mode: settings
+        data:
+          option: service_log.purge.after.seconds
+          value: "{{ rancher.service_log_purge_after_seconds }}"
+    - name: Audit log
+      rancher1_api:
+        server: "{{ rancher_server_url }}"
+        account_key: "{{ key_public }}:{{ key_private }}"
+        mode: settings
+        data:
+          option: audit_log.purge.after.seconds
+          value: "{{ rancher.audit_log_purge_after_seconds }}"
diff --git a/build/data_lists/onap_3.0.2-docker_images.list b/build/data_lists/onap_3.0.2-docker_images.list
new file mode 100644
index 0000000..e652a12
--- /dev/null
+++ b/build/data_lists/onap_3.0.2-docker_images.list
@@ -0,0 +1,220 @@
+alpine:3.6
+cassandra:2.1
+crunchydata/crunchy-pgpool:centos7-10.4-2.0.0
+crunchydata/crunchy-postgres:centos7-10.3-1.8.2
+crunchydata/crunchy-postgres:centos7-10.4-2.0.0
+docker.elastic.co/beats/filebeat:5.5.0
+docker.elastic.co/elasticsearch/elasticsearch:5.5.0
+docker.elastic.co/elasticsearch/elasticsearch:6.1.2
+docker.elastic.co/elasticsearch/elasticsearch:6.3.1
+docker.elastic.co/elasticsearch/elasticsearch-oss:6.1.3
+docker.elastic.co/kibana/kibana:5.5.0
+docker.elastic.co/kibana/kibana:6.3.1
+docker.elastic.co/logstash/logstash:5.4.3
+docker.io/aaionap/haproxy:1.2.4
+docker.io/busybox
+docker.io/cdposs/zookeeper:3.4.9
+docker.io/consul:1.0.6
+docker.io/library/busybox:latest
+docker.io/nginx:1.13-alpine
+docker.io/ninech/netbox:v2.3.5
+docker.io/oomk8s/consul:1.0.0
+docker.io/postgres:10.2-alpine
+docker.io/taskrabbit/elasticsearch-dump
+gcr.io/google_samples/k8szk:v3
+gcr.io/google-samples/xtrabackup:1.0
+library/mariadb:10
+nexus3.onap.org:10001/adfinissygroup/k8s-mariadb-galera-centos:v002
+nexus3.onap.org:10001/busybox
+nexus3.onap.org:10001/library/consul:1.0.6
+nexus3.onap.org:10001/library/tomcat:8.5
+nexus3.onap.org:10001/library/vault:0.10.0
+nexus3.onap.org:10001/mariadb:10.1.11
+nexus3.onap.org:10001/mariadb:10.2.14
+nexus3.onap.org:10001/onap/aaf/aaf_cass:2.1.8
+nexus3.onap.org:10001/onap/aaf/aaf_cm:2.1.8
+nexus3.onap.org:10001/onap/aaf/aaf_config:2.1.8
+nexus3.onap.org:10001/onap/aaf/aaf_fs:2.1.8
+nexus3.onap.org:10001/onap/aaf/aaf_gui:2.1.8
+nexus3.onap.org:10001/onap/aaf/aaf_hello:2.1.8
+nexus3.onap.org:10001/onap/aaf/aaf_locate:2.1.8
+nexus3.onap.org:10001/onap/aaf/aaf_oauth:2.1.8
+nexus3.onap.org:10001/onap/aaf/aaf_service:2.1.8
+nexus3.onap.org:10001/onap/aaf/distcenter:3.0.0
+nexus3.onap.org:10001/onap/aaf/sms:3.0.1
+nexus3.onap.org:10001/onap/aaf/smsquorumclient:3.0.1
+nexus3.onap.org:10001/onap/aaf/testcaservice:3.0.0
+nexus3.onap.org:10001/onap/aai/esr-gui:1.2.1
+nexus3.onap.org:10001/onap/aai/esr-server:1.2.1
+nexus3.onap.org:10001/onap/aai-graphadmin:1.0.4
+nexus3.onap.org:10001/onap/aai-resources:1.3.5
+nexus3.onap.org:10001/onap/aai-traversal:1.3.4
+nexus3.onap.org:10001/onap/admportal-sdnc-image:1.4.4
+nexus3.onap.org:10001/onap/appc-cdt-image:1.4.4
+nexus3.onap.org:10001/onap/appc-image:1.4.4
+nexus3.onap.org:10001/onap/babel:1.3.3
+nexus3.onap.org:10001/onap/ccsdk-ansible-server-image:0.3.3
+nexus3.onap.org:10001/onap/ccsdk-apps-ms-neng:0.3.3
+nexus3.onap.org:10001/onap/ccsdk-controllerblueprints:0.3.3
+nexus3.onap.org:10001/onap/ccsdk-dgbuilder-image:0.3.3
+nexus3.onap.org:10001/onap/champ:1.3.1
+nexus3.onap.org:10001/onap/clamp:3.0.4
+nexus3.onap.org:10001/onap/clamp-dashboard-kibana:3.0.4
+nexus3.onap.org:10001/onap/clamp-dashboard-logstash:3.0.4
+nexus3.onap.org:10001/onap/cli:2.0.4
+nexus3.onap.org:10001/onap/data-router:1.3.3
+nexus3.onap.org:10001/onap/dcae-be:1.3.0
+nexus3.onap.org:10001/onap/dcae-dt:1.2.0
+nexus3.onap.org:10001/onap/dcae-fe:1.3.0
+nexus3.onap.org:10001/onap/dcae-tools:1.3.0
+nexus3.onap.org:10001/onap/dcae-tosca-app:1.3.0
+nexus3.onap.org:10001/onap/dmaap/buscontroller:1.0.23
+nexus3.onap.org:10001/onap/dmaap/datarouter-node:1.0.9
+nexus3.onap.org:10001/onap/dmaap/datarouter-prov:1.0.9
+nexus3.onap.org:10001/onap/dmaap/dmaap-mr:1.1.8
+nexus3.onap.org:10001/onap/dmaap/kafka01101:0.0.1
+nexus3.onap.org:10001/onap/externalapi/nbi:3.0.2
+nexus3.onap.org:10001/onap/gizmo:1.3.2
+nexus3.onap.org:10001/onap/holmes/engine-management:1.2.2
+nexus3.onap.org:10001/onap/holmes/rule-management:1.2.3
+nexus3.onap.org:10001/onap/model-loader:1.3.2
+nexus3.onap.org:10001/onap/msb/msb_apigateway:1.2.1
+nexus3.onap.org:10001/onap/msb/msb_discovery:1.2.1
+nexus3.onap.org:10001/onap/multicloud/azure:1.2.1
+nexus3.onap.org:10001/onap/multicloud/framework:1.2.1
+nexus3.onap.org:10001/onap/multicloud/openstack-ocata:1.2.3
+nexus3.onap.org:10001/onap/multicloud/openstack-pike:1.2.3
+nexus3.onap.org:10001/onap/multicloud/openstack-windriver:1.2.3
+nexus3.onap.org:10001/onap/multicloud/vio:1.2.1
+nexus3.onap.org:10001/onap/music/cassandra_3_11:3.0.24
+nexus3.onap.org:10001/onap/music/cassandra_job:3.0.24
+nexus3.onap.org:10001/onap/music/cassandra_music:3.0.0
+nexus3.onap.org:10001/onap/music/music:3.0.24
+nexus3.onap.org:10001/onap/network-discovery:1.4.2
+nexus3.onap.org:10001/onap/oom/kube2msb:1.1.0
+nexus3.onap.org:10001/onap/optf-cmso-dbinit:1.0.1
+nexus3.onap.org:10001/onap/optf-cmso-service:1.0.1
+nexus3.onap.org:10001/onap/optf-has:1.2.5
+nexus3.onap.org:10001/onap/optf-osdf:1.2.4
+nexus3.onap.org:10001/onap/org.onap.dcaegen2.collectors.datafile.datafile-app-server:1.0.5
+nexus3.onap.org:10001/onap/org.onap.dcaegen2.collectors.hv-ves.hv-collector-main:1.0.2
+nexus3.onap.org:10001/onap/org.onap.dcaegen2.collectors.snmptrap:1.4.0
+nexus3.onap.org:10001/onap/org.onap.dcaegen2.collectors.ves.vescollector:1.3.2
+nexus3.onap.org:10001/onap/org.onap.dcaegen2.deployments.cm-container:1.4.2
+nexus3.onap.org:10001/onap/org.onap.dcaegen2.deployments.healthcheck-container:1.1.2
+nexus3.onap.org:10001/onap/org.onap.dcaegen2.deployments.k8s-bootstrap-container:1.4.5
+nexus3.onap.org:10001/onap/org.onap.dcaegen2.deployments.redis-cluster-container:1.0.0
+nexus3.onap.org:10001/onap/org.onap.dcaegen2.deployments.tca-cdap-container:1.1.0
+nexus3.onap.org:10001/onap/org.onap.dcaegen2.platform.configbinding.app-app:2.2.3
+nexus3.onap.org:10001/onap/org.onap.dcaegen2.platform.deployment-handler:3.0.3
+nexus3.onap.org:10001/onap/org.onap.dcaegen2.platform.inventory-api:3.0.4
+nexus3.onap.org:10001/onap/org.onap.dcaegen2.platform.policy-handler:4.4.0
+nexus3.onap.org:10001/onap/org.onap.dcaegen2.platform.servicechange-handler:1.1.5
+nexus3.onap.org:10001/onap/org.onap.dcaegen2.services.prh.prh-app-server:1.1.1
+nexus3.onap.org:10001/onap/policy-apex-pdp:2.0.4
+nexus3.onap.org:10001/onap/policy-distribution:2.0.5
+nexus3.onap.org:10001/onap/policy-drools:1.3.6
+nexus3.onap.org:10001/onap/policy-pe:1.3.6
+nexus3.onap.org:10001/onap/pomba-aai-context-builder:1.3.2
+nexus3.onap.org:10001/onap/pomba-context-aggregator:1.3.4
+nexus3.onap.org:10001/onap/pomba-network-discovery-context-builder:1.3.1
+nexus3.onap.org:10001/onap/pomba-sdc-context-builder:1.3.2
+nexus3.onap.org:10001/onap/portal-app:2.3.1
+nexus3.onap.org:10001/onap/portal-db:2.3.1
+nexus3.onap.org:10001/onap/portal-sdk:2.3.1
+nexus3.onap.org:10001/onap/portal-wms:2.3.1
+nexus3.onap.org:10001/onap/sdc-backend:1.3.6
+nexus3.onap.org:10001/onap/sdc-backend-init:1.3.6
+nexus3.onap.org:10001/onap/sdc-cassandra:1.3.6
+nexus3.onap.org:10001/onap/sdc-cassandra-init:1.3.6
+nexus3.onap.org:10001/onap/sdc-elasticsearch:1.3.6
+nexus3.onap.org:10001/onap/sdc-frontend:1.3.6
+nexus3.onap.org:10001/onap/sdc-init-elasticsearch:1.3.6
+nexus3.onap.org:10001/onap/sdc-kibana:1.3.6
+nexus3.onap.org:10001/onap/sdc-onboard-backend:1.3.6
+nexus3.onap.org:10001/onap/sdc-onboard-cassandra-init:1.3.6
+nexus3.onap.org:10001/onap/sdnc-ansible-server-image:1.4.4
+nexus3.onap.org:10001/onap/sdnc-dmaap-listener-image:1.4.4
+nexus3.onap.org:10001/onap/sdnc-image:1.4.4
+nexus3.onap.org:10001/onap/sdnc-ueb-listener-image:1.4.4
+nexus3.onap.org:10001/onap/search-data-service:1.3.2
+nexus3.onap.org:10001/onap/service-decomposition:1.4.2
+nexus3.onap.org:10001/onap/sniroemulator:1.0.0
+nexus3.onap.org:10001/onap/so/api-handler-infra:1.3.6
+nexus3.onap.org:10001/onap/so/bpmn-infra:1.3.6
+nexus3.onap.org:10001/onap/so/catalog-db-adapter:1.3.6
+nexus3.onap.org:10001/onap/so/openstack-adapter:1.3.6
+nexus3.onap.org:10001/onap/so/request-db-adapter:1.3.6
+nexus3.onap.org:10001/onap/so/sdc-controller:1.3.6
+nexus3.onap.org:10001/onap/so/sdnc-adapter:1.3.6
+nexus3.onap.org:10001/onap/so/so-monitoring:1.3.6
+nexus3.onap.org:10001/onap/so/vfc-adapter:1.3.6
+nexus3.onap.org:10001/onap/sparky-be:1.3.2
+nexus3.onap.org:10001/onap/spike:1.3.1
+nexus3.onap.org:10001/onap/testsuite:1.3.3
+nexus3.onap.org:10001/onap/usecase-ui:1.2.2
+nexus3.onap.org:10001/onap/usecase-ui-server:1.2.1
+nexus3.onap.org:10001/onap/validation:1.3.1
+nexus3.onap.org:10001/onap/vfc/catalog:1.2.1
+nexus3.onap.org:10001/onap/vfc/db:1.2.1
+nexus3.onap.org:10001/onap/vfc/emsdriver:1.2.1
+nexus3.onap.org:10001/onap/vfc/gvnfmdriver:1.2.1
+nexus3.onap.org:10001/onap/vfc/jujudriver:1.2.1
+nexus3.onap.org:10001/onap/vfc/multivimproxy:1.2.1
+nexus3.onap.org:10001/onap/vfc/nfvo/svnfm/huawei:1.2.1
+nexus3.onap.org:10001/onap/vfc/nfvo/svnfm/nokia:1.1.0
+nexus3.onap.org:10001/onap/vfc/nfvo/svnfm/nokiav2:1.3.0
+nexus3.onap.org:10001/onap/vfc/nslcm:1.2.1
+nexus3.onap.org:10001/onap/vfc/resmanagement:1.2.1
+nexus3.onap.org:10001/onap/vfc/vnflcm:1.2.1
+nexus3.onap.org:10001/onap/vfc/vnfmgr:1.2.1
+nexus3.onap.org:10001/onap/vfc/vnfres:1.2.1
+nexus3.onap.org:10001/onap/vfc/wfengine-activiti:1.2.0
+nexus3.onap.org:10001/onap/vfc/wfengine-mgrservice:1.2.0
+nexus3.onap.org:10001/onap/vfc/ztesdncdriver:1.2.0
+nexus3.onap.org:10001/onap/vfc/ztevnfmdriver:1.2.1
+nexus3.onap.org:10001/onap/vid:3.2.3
+nexus3.onap.org:10001/onap/vnfsdk/refrepo:1.2.0
+nexus3.onap.org:10001/onap/workflow-backend:1.3.2
+nexus3.onap.org:10001/onap/workflow-frontend:1.3.2
+nexus3.onap.org:10001/onap/workflow-init:1.3.2
+nexus3.onap.org:10001/sonatype/nexus:2.14.8-01
+nexus3.onap.org:10001/zookeeper:3.4
+oomk8s/mariadb-client-init:3.0.0
+oomk8s/readiness-check:2.0.0
+oomk8s/readiness-check:2.0.0
+oomk8s/readiness-check:2.0.1
+oomk8s/ubuntu-init:1.0.0
+registry.hub.docker.com/library/busybox:latest
+registry.hub.docker.com/library/consul:0.9.3
+registry.hub.docker.com/library/mongo:3
+registry.hub.docker.com/library/mysql:5.7
+registry.hub.docker.com/oomk8s/ubuntu-init:2.0.0
+gcr.io/kubernetes-helm/tiller:v2.9.1
+nexus3.onap.org:10001/onap/org.onap.dcaegen2.deployments.tls-init-container:1.0.0
+library/postgres:9.5.2
+rancher/agent:v1.2.11
+rancher/dns:v0.17.4
+rancher/etc-host-updater:v0.0.3
+rancher/etcd:v2.3.7-17
+rancher/healthcheck:v0.3.8
+rancher/heapster-amd64:v1.5.2
+rancher/heapster-grafana-amd64:v4.4.3
+rancher/heapster-influxdb-amd64:v1.3.3
+rancher/k8s-dns-dnsmasq-nanny-amd64:1.14.10
+rancher/k8s-dns-kube-dns-amd64:1.14.10
+rancher/k8s-dns-sidecar-amd64:1.14.10
+rancher/k8s:v1.11.5-rancher1-1
+rancher/kubectld:v0.8.8
+rancher/kubernetes-agent:v0.6.9
+rancher/kubernetes-auth:v0.0.8
+rancher/kubernetes-dashboard-amd64:v1.8.3
+rancher/lb-service-haproxy:v0.9.6
+rancher/lb-service-rancher:v0.9.6
+rancher/metadata:v0.10.4
+rancher/net:holder
+rancher/net:v0.13.17
+rancher/network-manager:v0.7.22
+rancher/pause-amd64:3.0
+rancher/server:v1.6.22
+rancher/tiller:v2.9.1
\ No newline at end of file