Formulas testing revision 2019/10

Related: PROD-32744
Related: PROD-33634
Related: PROD-33698
Related: PROD-33984

Partial cherry-pick of: https://gerrit.mcp.mirantis.com/#/c/32829/

Change-Id: I7a7da0322bc3e692688bb49c314f101d00fe5590
diff --git a/.kitchen.yml b/.kitchen.yml
new file mode 100644
index 0000000..df16a5a
--- /dev/null
+++ b/.kitchen.yml
@@ -0,0 +1,58 @@
+---
+driver:
+  name: docker
+  hostname: gerrit.ci.local
+  use_sudo: false
+
+provisioner:
+  name: salt_solo
+  salt_install: bootstrap
+  salt_bootstrap_url: https://bootstrap.saltstack.com
+  salt_version: latest
+  require_chef: false
+  log_level: info
+  formula: gerrit
+  grains:
+    noservices: True
+  dependencies:
+    - name: linux
+      repo: git
+      source: https://gerrit.mcp.mirantis.com/salt-formulas/linux.git
+      branch: <%=ENV['GERRIT_BRANCH'] || 'release/2019.2.0' %>
+  state_top:
+    base:
+      "*":
+        - linux.system.repo
+        - gerrit
+  pillars:
+    top.sls:
+      base:
+        "*":
+          - mcp_extra_repo
+          - gerrit
+  pillars-from-files:
+    mcp_extra_repo.sls: tests/pillar/mcp_extra_repo.sls
+
+verifier:
+  name: inspec
+  sudo: true
+
+docker_images:
+  - &xenial-20177 <%=ENV['IMAGE_XENIAL_20177'] || 'docker-dev-local.docker.mirantis.net/mirantis/drivetrain/salt-formulas-ci/salt-formulas-ci-xenial-2017.7:latest'%>
+
+platforms:
+  - name: xenial-2017.7
+    driver_config:
+      image: *xenial-20177
+      platform: ubuntu
+
+suites:
+  - name: server
+    provisioner:
+      pillars-from-files:
+        gerrit.sls: tests/pillar/server.sls
+
+  - name: client
+    provisioner:
+      pillars-from-files:
+        gerrit.sls: tests/pillar/client.sls
diff --git a/gerrit/client/project.sls b/gerrit/client/project.sls
index b7c6506..432e3f1 100644
--- a/gerrit/client/project.sls
+++ b/gerrit/client/project.sls
@@ -5,15 +5,19 @@
   file.managed:
   - source: salt://gerrit/files/projects.ini
   - template: jinja
+  {%- if grains.get('virtual_subtype', None) not in ['Docker', 'LXC'] %}
   - require_in:
     - cmd: gerrit_client_enforce_projects
+  {%- endif %}
 {%- if client.dir.project_config == "/srv/jeepyb" %}
 /srv/jeepyb/projects.yaml:
   file.managed:
   - source: salt://gerrit/files/projects.yaml
   - template: jinja
+  {%- if grains.get('virtual_subtype', None) not in ['Docker', 'LXC'] %}
   - require_in:
     - cmd: gerrit_client_enforce_projects
+  {%- endif %}
 
 {%- for project_name, project in client.project.iteritems() %}
 
@@ -24,8 +28,10 @@
   - makedirs: true
   - defaults:
       project_name: {{ project.get('name', project_name) }}
+  {%- if grains.get('virtual_subtype', None) not in ['Docker', 'LXC'] %}
   - require_in:
     - cmd: gerrit_client_enforce_projects
+  {%- endif %}
 
 {#
 gerrit_client_project_{{ project_name }}:
@@ -42,6 +48,8 @@
   {%- set manage_projects_bin = "manage-projects" %}
 {%- endif %}
 
+{%- if grains.get('virtual_subtype', None) not in ['Docker', 'LXC'] %}
+
 gerrit_client_enforce_projects:
   cmd.run:
   - shell: /bin/bash
@@ -62,5 +70,6 @@
     - NO_PROXY: "{{ client.proxy.no_proxy }}"
     {%- endif %}
 
+{%- endif %}
 
 {%- endif %}
diff --git a/gerrit/client/service.sls b/gerrit/client/service.sls
index 45d1855..f1395f6 100644
--- a/gerrit/client/service.sls
+++ b/gerrit/client/service.sls
@@ -61,5 +61,6 @@
   file.managed:
   - mode: 400
   - contents_pillar: gerrit:client:server:key
+  - makedirs: true
 
 {%- endif %}
diff --git a/gerrit/files/secure.config b/gerrit/files/secure.config
index afff595..0447d8e 100644
--- a/gerrit/files/secure.config
+++ b/gerrit/files/secure.config
@@ -8,12 +8,12 @@
 [auth]
     registerEmailPrivateKey = {{ server.email_private_key }}
     restTokenPrivateKey = {{ server.token_private_key }}
-    {%- if server.mail.privatekey is defined %}
+    {%- if server.get('mail', {}).privatekey is defined %}
     registerEmailPrivateKey = {{ server.mail.privatekey }}
     {%- endif %}
 
 [sendemail]
-    {%- if server.mail.password is defined %}
+    {%- if server.get('mail', {}).password is defined %}
     smtpPass = {{ server.mail.password }}
     {%- endif %}
 
diff --git a/gerrit/server/service.sls b/gerrit/server/service.sls
index 1d614a3..2d4f8ef 100644
--- a/gerrit/server/service.sls
+++ b/gerrit/server/service.sls
@@ -189,11 +189,15 @@
   - group: gerrit2
   - require:
     - file: gerrit_home
+  {%- if grains.get('virtual_subtype', None) not in ['Docker', 'LXC'] %}
   - require_in:
     - cmd: gerrit_server_initial_init
+  {%- endif %}
 
 {%- endif %}
 
+{%- if grains.get('virtual_subtype', None) not in ['Docker', 'LXC'] %}
+
 gerrit_server_initial_init:
   cmd.run:
   - name: /usr/bin/java -jar {{ server.dir.home }}/gerrit.war init -d {{ server.dir.site }} --batch --no-auto-start{% for plugin_name, plugin in server.get('plugin', {}).iteritems() %}{% if plugin.engine == "gerrit" %} --install-plugin {{ plugin_name }}{% endif %}{% endfor %}
@@ -211,6 +215,8 @@
   - require:
     - cmd: gerrit_server_initial_init
 
+{%- endif %}
+
 /etc/default/gerritcodereview:
   file.managed:
   - source: salt://gerrit/files/gerritcodereview
@@ -234,6 +240,8 @@
   - name: /etc/init.d/{{ server.service }}
   - target: {{ server.dir.site }}/bin/gerrit.sh
 
+{%- if grains.get('virtual_subtype', None) not in ['Docker', 'LXC'] %}
+
 gerrit_server_service:
   service.running:
   - name: {{ server.service }}
@@ -271,13 +279,18 @@
 
 {%- endfor %}
 {%- endif %}
+{%- endif %}
 
 gerrit_server_configured:
   file.touch:
   - name: {{ server.dir.home }}/.gerrit-configured
   - unless: /usr/bin/test -f {{ server.dir.home }}/.gerrit-configured
+  {%- if grains.get('virtual_subtype', None) not in ['Docker', 'LXC'] %}
   - require:
     - service: gerrit_server_service
+  {%- endif %}
+
+{%- if grains.get('virtual_subtype', None) not in ['Docker', 'LXC'] %}
 
 gerrit_server_service_available:
   cmd.run:
@@ -297,3 +310,4 @@
       - cmd: gerrit_server_service_available
 
 {%- endif %}
+{%- endif %}
diff --git a/tests/pillar/client.sls b/tests/pillar/client.sls
index e132408..c149363 100644
--- a/tests/pillar/client.sls
+++ b/tests/pillar/client.sls
@@ -66,4 +66,5 @@
       host: 0.0.0.0
       protocol: "http"
       http_port: 80
-      ssh_port: 22
\ No newline at end of file
+      ssh_port: 22
+      key: "key"
\ No newline at end of file
diff --git a/tests/pillar/mcp_extra_repo.sls b/tests/pillar/mcp_extra_repo.sls
new file mode 100644
index 0000000..68094b3
--- /dev/null
+++ b/tests/pillar/mcp_extra_repo.sls
@@ -0,0 +1,58 @@
+linux:
+  system:
+    enabled: true
+    repo:
+      mcp_extra_repo:
+        source: "deb http://mirror.mirantis.com/update/2019.2.0/extra/{{ grains.get('oscodename') }} {{ grains.get('oscodename') }} main"
+        architectures: amd64
+        clean_file: true
+        key: |
+          -----BEGIN PGP PUBLIC KEY BLOCK-----
+          Version: GnuPG v1
+
+          mQENBFWt8ogBCACtT/j4WMGuhEI486Vv9zVV0GWGefHE5hBlgJSjSgrExLFqQ2Fo
+          ScaABCfvzUeuXHNoh/c2eLjx3YE6oFrdiw5tam0NFlZMM+PSufciTxQz8vrXHGx7
+          VB5rg2TXKoqOv9cW690FsRAeOtKTtBxZvYVTLEPn2GJW09Xy9CBa+n23XBHTBvKs
+          j3hxkn25Oy70Wgxk/BJqpynXGno+NzuAnIbb+f+X7i6fiXwrvtp5zOYOJeUwS+fU
+          IM/mXbetOd/sHtJqc9NUYpTip4nElEqAYRCsXDTbuMNdzSr8VlSMM8b61mBGelLH
+          XJe+EPP+Logc5KXO8adoGgWhqlbD6n7w+ynHABEBAAG0LmZ1ZWwtaW5mcmEgKEV4
+          YW1wbGUga2V5KSA8ZGV2b3BzQG1pcmFudGlzLmNvbT6JATgEEwECACIFAlWt8ogC
+          GwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJELzlzEYfoisIkuQIAJl0cFJ5
+          BSKMXHhRYf0BeDzhdh3pmcOXs/jSznTIxB4OE5OdwrMgKyoIkSIP8AEttvB+BuOv
+          BHmhTL7kvRhP5xiKdbCwmDtoERoaqxhRRbZJcJ+pHvl7mkEu8Gj2KZe2lfE4Z6ZF
+          6q00Gx9HYfse1+VgUR5ymh41nZCvRTNEnYBp1RQcPogiLy2rYvZbxYnUtg4jaD7D
+          vuuEQwrfEHdKFUlWBCIVbl+e3K6ZSniOcqqyHK72/HI0SYuZpGfCzzw5deODcjWm
+          Gz4nZr41cB3eHXkfmG3ngdhmb2MpVr83u+JebOovjzusf71oIdZBTFNYsZNSVKrn
+          l0rrRuDIMHbQMuS5AQ0EVa3yiAEIALZqdLGXSGZAgUXl7zhPH5wnIQtdo6iMIovZ
+          zQNW95RDT2nm/3YddiRy6FuOTbaHXw07D4ZUl4dGVHzEwBllhULxcHV3OOdQ3gVp
+          4mBAZ8kv0EelzqPfDQWR2Cq0hi7IJ4Q4ePpZhQFiasz8qbV7D7CYbZdDAmQKxqAk
+          0XYOjbB3jzB2r6MHflAKmJzTp3+NAE9bDLAwXa0ot2THDbpPdB4R6pxpD6Y3jweW
+          uLUCnIfvyIBwhHobaU28pw/BA+0dkC9jnLnoO+TrzB9YD5839Lc3ctrdPBLiFPMG
+          wdfAVRCyfgLjOyULqjTudx1Mo+Dgz9+xrcTFoehI7UYoZnraEKkAEQEAAYkBHwQY
+          AQIACQUCVa3yiAIbDAAKCRC85cxGH6IrCPH5B/0Uc+OhMSCkRos1Yv5tA4bsEcjt
+          8+sJ2S6pUqCbZxmXpzKspKpnjp3DJjmQKDB2q4UPDVElVDMMdBlstTx1RRZDf8yk
+          nDvRBSzawk7Xhfloro8N2Lxv6gWhhMvHUYItyO6KMbAZuZ2M1I1/OFHG/f//7oPM
+          0QpNbihf+GqE/dWRz9ZDz+xlSFli6AR/3ldq7N6gkCsEFdi3j6ZDf0qLsZpazPUI
+          wiCC/aAYLkRDtTJV1G6EsWijmOTNNlCEFS/XDLQ3N2Ev/1sgAO0AlBMdXqSnqUI1
+          1h/eSKCiGmkwFWlCf/4HnJVP7QpSeRPLyw785Fvt3p9vT+64isZ0ZK6cpcj8
+          =0aQD
+          -----END PGP PUBLIC KEY BLOCK-----
+          -----BEGIN PGP PUBLIC KEY BLOCK-----
+          Version: GnuPG v1
+
+          mQENBFtYVY8BCAC3oli93husG0ZVtv/L8I4/bcW60LFCyB0DuwEznGlSaj1fjOQu
+          C7QX9wvGRq8mRZ8mfZ6sbxGmgs0LnV5QIBle1l5I3B+AMGksf6UGEWgoN/vq86g+
+          0Jg6kJP/D0sjGXvdlfy+bgAqjsx2bWOLjQGtHSIxhe4cE9HPBfMiYsFwGQua3XN3
+          tiGKcifszvDA6uqdjS6DuTEPCzyKiSyUevnWtBh0oUtUt//X4lG2Mx0lU91uUQGj
+          KeZ+fYXOLqgZm/FxLVT5w3g/UGK9Cbz5h4kGCJOfk0EwIZp0IRRs1phOC6gVMwoV
+          yWKCtdHmg7Ob8I4AZ8OW5HJn1UPHTprxcHBnABEBAAG0LEF1dG9idWlsZGVyIDxp
+          bmZyYSthdXRpYnVpbGRlckBtaXJhbnRpcy5jb20+iQE4BBMBAgAiBQJbWFWPAhsD
+          BgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRCRZVp5TFKJ70cJB/9ArWrSFyEx
+          qs7Tyo9M5WCPjqw7y2F7jd4Et3hqwc5jx6KlxGpg17SHt4oWcmtML3VBx+ziBAi0
+          5Ry4Z4w0QqFW6gAqQepeW76Yq/OP5SoqEI9sUwzLfUY7raK/P1buvXB1eZh4mMw4
+          TFf4Hgo8yUQ3geYNnUBBfaSfkmiyBJGsMXBfW2zhlpVIyB6Cye5R823FxGNJe+li
+          hggNCQnKYqrGtr55RO6xYI1v89cgGrO2EVwPkFLA/MUnQEb433Ck+sjp1NZDUfuJ
+          U3gg8S0hT+Cf5XiknT/xqIhhTY/KzlNmynZt/51DzZzsbM+RO6JZFYJL2LuC69gB
+          +R5jrmaGu9fG
+          =sqIn
+          -----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/pillar/server.sls b/tests/pillar/server.sls
index 0103f1b..e0acbb6 100644
--- a/tests/pillar/server.sls
+++ b/tests/pillar/server.sls
@@ -2,8 +2,10 @@
   server:
     enabled: true
     canonical_web_url: http://10.10.10.148:8082/
-    email_private_key: ""
-    token_private_key: ""
+    bind:
+      address: 127.0.0.1
+    email_private_key: "email_private_key"
+    token_private_key: "token_private_key"
     initial_user:
       full_name: John Doe
       email: 'mail@jdoe.com'
@@ -45,7 +47,7 @@
       port: 5432
       name: gerrit
       user: gerrit
-      password: ${_param:postgresql_gerrit_password}
+      password: passw0rd
       pool_limit: 250
       pool_max_idle: 16
     download:
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 4a7ce6e..4665d34 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -1,9 +1,15 @@
 #!/usr/bin/env bash
 
 ###
+# Script source: https://gerrit.mcp.mirantis.com/#/admin/projects/salt-formulas/cookiecutter-salt-formula
 # Script requirments:
 #apt-get install -y python-yaml virtualenv git
 
+__ScriptVersion="2019.01.07"
+__ScriptName="run_tests.sh"
+__ScriptFullName="$0"
+__ScriptArgs="$*"
+
 set -e
 [ -n "$DEBUG" ] && set -x
 
@@ -28,6 +34,8 @@
 
 SALT_OPTS="${SALT_OPTS} --retcode-passthrough --local -c ${SALT_CONFIG_DIR} --log-file=/dev/null"
 
+IGNORE_MODELVALIDATE_MASK=${IGNORE_MODELVALIDATE_MASK:-"novalidate"}
+
 if [ "x${SALT_VERSION}" != "x" ]; then
     PIP_SALT_VERSION="==${SALT_VERSION}"
 fi
@@ -47,9 +55,8 @@
     virtualenv $VENV_DIR
     source ${VENV_DIR}/bin/activate
     python -m pip install salt${PIP_SALT_VERSION}
-    python -m pip install jsonschema
-    if [[ -f ${CURDIR}/pip_requirements.txt ]]; then
-       python -m pip install -r ${CURDIR}/pip_requirements.txt
+    if [[ -f ${CURDIR}/test-requirements.txt ]]; then
+       python -m pip install -r ${CURDIR}/test-requirements.txt
     fi
 }
 
@@ -70,6 +77,12 @@
         state_name=$(basename ${pillar%.sls})
         echo -e "  ${state_name}:\n    - ${state_name}" >> ${SALT_PILLAR_DIR}/top.sls
     done
+    for pillar in $(find $PILLARDIR  -mindepth 2 -type f -iname *.sls); do
+        state_name=$(basename "${pillar%*.sls}")
+        os_release=$(echo $pillar | rev | cut -d'/' -f2 | rev)
+        grep ${FORMULA_NAME}: ${pillar} &>/dev/null || continue
+        echo -e "  ${os_release}_${state_name}:\n    - ${os_release}.${state_name}" >> ${SALT_PILLAR_DIR}/top.sls
+    done
 }
 
 setup_salt() {
@@ -84,6 +97,12 @@
         state_name=$(basename ${pillar%.sls})
         echo -e "  ${state_name}:\n    - ${FORMULA_NAME}" >> ${SALT_FILE_DIR}/top.sls
     done
+    for pillar in $(find $PILLARDIR  -mindepth 2 -type f -iname *.sls); do
+        state_name=$(basename "${pillar%*.sls}")
+        os_release=$(echo $pillar | rev | cut -d'/' -f2 | rev)
+        grep ${FORMULA_NAME}: ${pillar} &>/dev/null || continue
+        echo -e "  ${os_release}_${state_name}:\n    - ${FORMULA_NAME}" >> ${SALT_FILE_DIR}/top.sls
+    done
 
     cat << EOF > ${SALT_CONFIG_DIR}/minion
 file_client: local
@@ -155,7 +174,11 @@
 }
 
 prepare() {
-    [ -d ${BUILDDIR} ] && mkdir -p ${BUILDDIR}
+    if [[ -f ${BUILDDIR}/.prepare_done ]]; then
+      log_info "${BUILDDIR}/.prepare_done exist, not rebuilding BUILDDIR"
+      return
+    fi
+    [[ -d ${BUILDDIR} ]] && mkdir -p ${BUILDDIR}
 
     [[ ! -f "${VENV_DIR}/bin/activate" ]] && setup_virtualenv
     setup_mock_bin
@@ -163,12 +186,12 @@
     setup_salt
     install_dependencies
     link_modules
+    touch ${BUILDDIR}/.prepare_done
 }
 
 lint_releasenotes() {
     [[ ! -f "${VENV_DIR}/bin/activate" ]] && setup_virtualenv
     source ${VENV_DIR}/bin/activate
-    python -m pip install reno
     reno lint ${CURDIR}/../
 }
 
@@ -205,21 +228,37 @@
 }
 
 run_model_validate(){
-    if [ -d ${SCHEMARDIR} ]; then
-      # model validator require py modules
-      fetch_dependency "salt:https://github.com/salt-formulas/salt-formula-salt"
-      link_modules
-      # Rendered Example:
-      # python $(which salt-call) --local -c /test1/maas/tests/build/salt --id=maas_cluster modelschema.model_validate maas cluster
-      for role in ${SCHEMARDIR}/*.yaml; do
-          state_name=$(basename "${role%*.yaml}")
-          minion_id="${state_name}"
-          salt_run saltutil.clear_cache; salt_run saltutil.refresh_pillar; salt_run saltutil.sync_all;
-          salt_run -m ${DEPSDIR}/salt-formula-salt --id=${minion_id} modelschema.model_validate ${FORMULA_NAME} ${state_name} || { log_err "Execution of ${FORMULA_NAME}.${state_name} failed"; exit 1 ; }
+  # Run modelschema.model_validate validation.
+  # TEST iterateble, run for `each formula ROLE against each ROLE_PILLARNAME`
+  # Pillars should be named in conviend ROLE_XXX.sls or ROLE.sls
+  # Example:
+  # client.sls  client_auth.sls  server.sls  server_auth.sls
+  if [ -d ${SCHEMARDIR} ]; then
+    # model validator require py modules
+    fetch_dependency "salt:https://github.com/salt-formulas/salt-formula-salt"
+    link_modules
+    salt_run saltutil.clear_cache; salt_run saltutil.refresh_pillar; salt_run saltutil.sync_all;
+    for role in $(find $SCHEMARDIR/* -maxdepth 0 -type f -iname *.yaml); do
+      role_name=$(basename "${role%*.yaml}")
+      for pillar in $(ls pillar/${role_name}*.sls | grep -v ${IGNORE_MODELVALIDATE_MASK} ); do
+        pillar_name=$(basename "${pillar%*.sls}")
+        local _message="FORMULA:${FORMULA_NAME} ROLE:${role_name} against PILLAR:${pillar_name}"
+        log_info "model_validate ${_message}"
+        # Rendered Example:
+        # python $(which salt-call) --local -c /test1/maas/tests/build/salt --id=maas_cluster modelschema.model_validate maas cluster
+        salt_run -m ${DEPSDIR}/salt-formula-salt --id=${pillar_name} modelschema.model_validate ${FORMULA_NAME} ${role_name} || { log_err "Execution of model_validate ${_message} failed"; exit 1 ; }
       done
-    else
-      log_info "${SCHEMARDIR} not found!";
-    fi
+    done
+    for schema in $(find $SCHEMARDIR -mindepth 2 -type f -iname *.yaml); do
+        role_name=$(basename "${schema%*.yaml}")
+        os_release=$(echo $schema | rev | cut -d'/' -f2 | rev)
+        local _message="FORMULA:${FORMULA_NAME} ROLE:${role_name} against PILLAR:${role_name}"
+        log_info "model_validate ${_message}"
+        salt_run -m ${DEPSDIR}/salt-formula-salt --id=${os_release}_${role_name} modelschema.model_validate ${FORMULA_NAME} ${role_name} ${os_release} || { log_err "Execution of model_validate ${_message} failed"; exit 1 ; }
+    done
+  else
+    log_info "${SCHEMARDIR} not found!";
+  fi
 }
 
 dependency_check() {
@@ -243,6 +282,10 @@
 }
 
 ## Main
+
+log_info "Running version: ${__ScriptVersion}"
+log_info "Command line: '${__ScriptFullName} ${__ScriptArgs}'"
+
 trap _atexit INT TERM EXIT
 
 case $1 in
@@ -271,4 +314,4 @@
         run
         run_model_validate
         ;;
-esac
\ No newline at end of file
+esac
diff --git a/tests/test-requirements.txt b/tests/test-requirements.txt
new file mode 100644
index 0000000..a0f561a
--- /dev/null
+++ b/tests/test-requirements.txt
@@ -0,0 +1,2 @@
+jsonschema
+reno