From e8f9b253123d42a7e4e603762831a5faaaa88973 Mon Sep 17 00:00:00 2001
From: Merlin Mathesius <mmathesi@redhat.com>
Date: Jul 05 2017 21:42:31 +0000
Subject: [PATCH 1/2] - Implement configuration of SSH key-based authentication to docker image

- Revised docker and rhts role usage conventions to be compatible and interchangeable with cloud and beakerlib roles

---

diff --git a/roles/standard-test-docker/files/docker-inventory b/roles/standard-test-docker/files/docker-inventory
index 3a5fcf6..b23a7d0 100644
--- a/roles/standard-test-docker/files/docker-inventory
+++ b/roles/standard-test-docker/files/docker-inventory
@@ -1 +1,2 @@
 localhost ansible_ssh_port=2222 ansible_ssh_host=127.0.0.3 ansible_ssh_user=root ansible_ssh_pass=foobar ansible_ssh_common_args='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
+executor ansible_ssh_host=127.0.0.1 ansible_connection=local
diff --git a/roles/standard-test-docker/files/docker-run-ssh b/roles/standard-test-docker/files/docker-run-ssh
index 16faf06..75d530a 100644
--- a/roles/standard-test-docker/files/docker-run-ssh
+++ b/roles/standard-test-docker/files/docker-run-ssh
@@ -1,15 +1,30 @@
 #!/bin/sh
+authorized_key=
 python_version=2
+rootpass=foobar
 while [ $# -gt 0 ]; do
     case "$1" in
-    --py3) python_version=3 ;;
+    --py3)
+        python_version=3
+        ;;
+    --authorized-key)
+        authorized_key="$2"
+        shift
+        ;;
     esac
     shift
 done
-dnf install -y openssh-server python${python_version}-dnf
+# install minimum requirements to run ansible
+dnf install -y openssh-server python${python_version}-dnf rsync findutils
+# configure SSH
 ssh-keygen -q -t rsa -N '' -f /etc/ssh/ssh_host_rsa_key
-echo 'root:foobar' | chpasswd
-# start sshd in background
+echo "root:$rootpass" | chpasswd
+if [ -n "$authorized_key" ]; then
+    mkdir -p /root/.ssh
+    echo "$authorized_key" >> /root/.ssh/authorized_keys
+    chmod 644 /root/.ssh/authorized_keys
+fi
+# start SSHD in background
 /usr/sbin/sshd
 echo SSHD READY
 # wait forever
diff --git a/roles/standard-test-docker/tasks/main.yml b/roles/standard-test-docker/tasks/main.yml
index e6372aa..2f6013c 100644
--- a/roles/standard-test-docker/tasks/main.yml
+++ b/roles/standard-test-docker/tasks/main.yml
@@ -29,11 +29,28 @@
     my_playbook_extra_args: "{{my_playbook_extra_args}} -e \"rpms='{{rpms}}'\""
   when: rpms|default("") != ""
 
+- name: Create temporary directory
+  tempfile:
+    state: directory
+    suffix: docker
+  register: my_docker_tempdir
+
+- name: Create key pair for SSH authentication in container
+  shell: "/usr/bin/ssh-keygen -t rsa -N '' -f {{ my_docker_tempdir.path + '/key' }}"
+
+- name: Read contents of generated SSH public key file
+  set_fact:
+    my_public_key: "{{ lookup('file', my_docker_tempdir.path + '/key.pub') }}"
+
+- name: Configure arguments for SSH key based authentication
+  set_fact:
+    my_playbook_extra_args: "{{my_playbook_extra_args}} --private-key '{{ my_docker_tempdir.path + \'/key\' }}'"
+    my_run_cmd_extra_args: "{{my_run_cmd_extra_args}} --authorized-key '{{ my_public_key }}'"
+
 - name: Start ansible-ready docker container running SSHD
   shell: >
     docker run -d
     -p '{{docker_ssh_port}}:22'
-    -v '{{artifacts}}:/artifacts:z,rw'
     -v '{{role_path}}/files/docker-run-ssh:/run.sh:z'
     {{docker_extra_args}}
     '{{subjects}}'
@@ -47,19 +64,12 @@
   - name: Wait for container to initialize
     wait_for: port="{{docker_ssh_port}}" search_regex=OpenSSH
 
-# ********************************
-# HELP!
-# There must be a better way to run the actual test playbook without running
-# another instance of ansible-playbook in an external shell command.
-# The external run means we can't track the return status of the invidual
-# tasks in the test playbook--which is the whole point.
-# ********************************
   - name: Run the playbook in the container
     shell: >
       ANSIBLE_LOG_PATH='{{artifacts}}/container-playbook.log'
       ansible-playbook '{{playbooks}}'
       -i '{{role_path}}/files/docker-inventory'
-      -e artifacts='/artifacts'
+      -e artifacts='{{artifacts}}'
       {{my_playbook_extra_args}}
     register: playbook_output
 
@@ -75,6 +85,12 @@
        Continue when ready
     when: lookup('env','FEDORA_TEST_DIAGNOSE')|bool
 
+  - name: Remove temporary directory
+    file:
+      path: "{{ my_docker_tempdir.path }}/"
+      state: absent
+    when: my_docker_tempdir is defined
+
   - name: Save the container log as an artifact
     shell: docker logs "{{ container_id }}" >"{{artifacts}}/docker.log" 2>&1
 
diff --git a/roles/standard-test-rhts/README.md b/roles/standard-test-rhts/README.md
index 50efb62..338ce10 100644
--- a/roles/standard-test-rhts/README.md
+++ b/roles/standard-test-rhts/README.md
@@ -4,6 +4,9 @@ Put this role in your test_local.yml playbook. You'll need
 to have the following variables defined:
 
  * tests: A list of RHTS test directories
- * artifacts: An artifacts directory
+ * artifacts: An artifacts directory on localhost to store logs
+ * remote_artifacts: The directory on the system under test
+     where the logs are stored.  Note: if this variable is left
+     undefined, it will default to /tmp/artifacts
  * required_packages: A list of prerequisite packages required by RHTS tests
  * rpms: Space separated list of RPMs to install (optional, may include SRPMs)
diff --git a/roles/standard-test-rhts/tasks/main.yml b/roles/standard-test-rhts/tasks/main.yml
index 89cc28c..d3cb844 100644
--- a/roles/standard-test-rhts/tasks/main.yml
+++ b/roles/standard-test-rhts/tasks/main.yml
@@ -1,8 +1,9 @@
 ---
-- name: Install the RHTS pre-requirements
+- name: Install the Ansible and RHTS pre-requirements
   package: name={{item}} state=latest
   with_items:
-  - dnf-plugins-core            # COPR plugin needed
+  - rsync                       # need rsync for Ansible synchronize module
+  - dnf-plugins-core            # need COPR plugin
   - beakerlib
   - make
   - createrepo
@@ -22,6 +23,11 @@
   with_items:
     - "{{ required_packages }}"
 
+- name: Define remote_artifacts if it is not already defined
+  set_fact:
+    remote_artifacts: /tmp/artifacts
+  when: remote_artifacts is not defined
+
 - name: Create legacy beakerlib directories
   file:
     dest: "{{ item }}"
@@ -134,49 +140,51 @@
     chmod 644 /root/.ssh/authorized_keys
 
 - name: Make artifacts directory
-  file: path={{ artifacts }} state=directory owner=root mode=755 recurse=yes
+  file: path={{ remote_artifacts }} state=directory owner=root mode=755 recurse=yes
 
 - name: Start restraintd
   # instead of using service module, daemon is started directly since we want the
   # output as an artifact (and this could be running in a container)
-  shell: nohup /usr/bin/restraintd >"{{ artifacts }}/restraintd.log" 2>&1 &
+  shell: nohup /usr/bin/restraintd >"{{ remote_artifacts }}/restraintd.log" 2>&1 &
 
 - name: Start local web server for restraint
-  shell: nohup /usr/bin/python -m SimpleHTTPServer "{{ local_www_port }}" >"{{ artifacts }}/httpd.log" 2>&1 &
+  shell: nohup /usr/bin/python -m SimpleHTTPServer "{{ local_www_port }}" >"{{ remote_artifacts }}/httpd.log" 2>&1 &
   args:
     chdir: "{{ local_www_dir }}/"
 
 - block:
   - name: Execute RHTS tests using restraint
-    shell: /usr/bin/restraint --host localhost --job "{{ job_xml_file }}" >"{{ artifacts }}/restraint.log" 2>&1
+    shell: /usr/bin/restraint --host localhost --job "{{ job_xml_file }}" >"{{ remote_artifacts }}/restraint.log" 2>&1
     args:
-      chdir: "{{ artifacts }}/"
+      chdir: "{{ remote_artifacts }}/"
     ignore_errors: True
 
+- always:
   - name: Extract job output directory from restraint logfile
-    shell: sed -n 's/^Using \([^ ]*\).*$/\1/p' "{{ artifacts }}/restraint.log"
+    shell: sed -n 's/^Using \([^ ]*\).*$/\1/p' "{{ remote_artifacts }}/restraint.log"
     register: restraint_job_dir
 
   - name: Make job ouput directory tree readable by all
     file:
-      path: "{{ artifacts }}/{{restraint_job_dir.stdout}}"
+      path: "{{ remote_artifacts }}/{{restraint_job_dir.stdout}}"
       mode: u=rwX,g=rX,o=rX
       recurse: yes
 
   - name: Set name of restraint XML job results file
-    set_fact: results_xml="{{ artifacts }}/{{restraint_job_dir.stdout}}/job.xml"
+    set_fact: results_xml="{{ remote_artifacts }}/{{restraint_job_dir.stdout}}/job.xml"
 
   - name: Convert restraint XML job results to text as main output artifact
-    shell: xsltproc /usr/local/share/job2text.xsl "{{ results_xml }}" >"{{ artifacts }}/test.log"
+    shell: xsltproc /usr/local/share/job2text.xsl "{{ results_xml }}" >"{{ remote_artifacts }}/test.log"
+
+  - name: Pull out the logs
+    synchronize:
+      dest: "{{ artifacts }}/"
+      src: "{{ remote_artifacts }}/"
+      mode: pull
+      ssh_args: "-o UserKnownHostsFile=/dev/null"
+    when: artifacts|default("") != ""
 
   - name: Check the results for failures
-    shell: grep '^FAIL ' "{{ artifacts }}/test.log"
+    shell: grep '^FAIL ' "{{ remote_artifacts }}/test.log"
     register: test_fails
     failed_when: test_fails.stdout or test_fails.stderr
-
-- always:
-  - name: Pull out the logs
-    fetch:
-      dest: "{{artifacts}}/"
-      src: "{{artifacts}}/"
-      flat: yes
diff --git a/roles/standard-test-rhts/vars/main.yml b/roles/standard-test-rhts/vars/main.yml
index 9dbdcfa..902f0cb 100644
--- a/roles/standard-test-rhts/vars/main.yml
+++ b/roles/standard-test-rhts/vars/main.yml
@@ -1,5 +1,6 @@
 ---
 artifacts: ./artifacts
+remote_artifacts: /tmp/artifacts
 tests: []
 required_packages: []
 local_www_dir: "/var/www-test"

From b5e1ba3538ecfb3cd51f12221ff2cb9fb4d738b8 Mon Sep 17 00:00:00 2001
From: Merlin Mathesius <mmathesi@redhat.com>
Date: Jul 06 2017 12:56:45 +0000
Subject: [PATCH 2/2] Remove forced install of rsync and findutils


---

diff --git a/roles/standard-test-docker/files/docker-run-ssh b/roles/standard-test-docker/files/docker-run-ssh
index 75d530a..e5ec652 100644
--- a/roles/standard-test-docker/files/docker-run-ssh
+++ b/roles/standard-test-docker/files/docker-run-ssh
@@ -15,7 +15,7 @@ while [ $# -gt 0 ]; do
     shift
 done
 # install minimum requirements to run ansible
-dnf install -y openssh-server python${python_version}-dnf rsync findutils
+dnf install -y openssh-server python${python_version}-dnf
 # configure SSH
 ssh-keygen -q -t rsa -N '' -f /etc/ssh/ssh_host_rsa_key
 echo "root:$rootpass" | chpasswd

