Skip to content
This repository has been archived by the owner on Jun 29, 2022. It is now read-only.

Commit

Permalink
Merge branch 'master' into issues/154 and add a test case.
Browse files Browse the repository at this point in the history
  • Loading branch information
chambridge committed Aug 28, 2017
2 parents f9ec6bb + 3279ac5 commit 34a2c9d
Show file tree
Hide file tree
Showing 11 changed files with 70 additions and 20 deletions.
5 changes: 5 additions & 0 deletions doc/command_syntax_usage.rst
Expand Up @@ -182,8 +182,13 @@ scan does not have the appropriate permissions to execute the command used to
gather the targeted facts. The following set of facts require *admin/root*
permissions to collect the facts:

- ``cpu.socket_count``
- ``date.anaconda_log``
- ``date.yum_history``
- ``dmi.x``
- ``subman.x``
- ``virt.virt``
- ``virt.type``
- ``virt-what.x``

The scan user can successful collect these values if the user is **root** or
Expand Down
2 changes: 1 addition & 1 deletion rho/factdecryptcommand.py
Expand Up @@ -87,7 +87,7 @@ def read_and_decrypt(self, path, vault):
data = []
keys = None

with open(path, 'rb') as read_file:
with open(path, 'r') as read_file:
reader = csv.DictReader(read_file, delimiter=',')
for row in reader:
for fact in self.facts_to_decrypt:
Expand Down
2 changes: 1 addition & 1 deletion rho/factencryptcommand.py
Expand Up @@ -87,7 +87,7 @@ def read_and_encrypt(self, path, vault):
data = []
keys = None

with open(path, 'rb') as read_file:
with open(path, 'r') as read_file:
reader = csv.DictReader(read_file, delimiter=',')
for row in reader:
for fact in self.facts_to_encrypt:
Expand Down
4 changes: 2 additions & 2 deletions rho/factredactcommand.py
Expand Up @@ -81,7 +81,7 @@ def _do_command(self):
data = []
keys = None
normalized_path = os.path.normpath(self.options.report_path)
with open(normalized_path, 'rb') as read_file:
with open(normalized_path, 'r') as read_file:
reader = csv.DictReader(read_file, delimiter=',')
for row in reader:
for fact in self.facts_to_redact:
Expand All @@ -100,7 +100,7 @@ def _do_command(self):
print(_("Fact %s was not present in %s" %
(fact, self.options.report_path)))

with tempfile.NamedTemporaryFile(mode='wb', delete=False) as data_temp:
with tempfile.NamedTemporaryFile(mode='w', delete=False) as data_temp:
# Construct the CSV writer
writer = csv.DictWriter(
data_temp, fieldnames=sorted(keys), delimiter=',')
Expand Down
16 changes: 11 additions & 5 deletions rho/utilities.py
Expand Up @@ -16,11 +16,16 @@
import re
import csv
import tempfile
import thread
from shutil import move
import sh
from rho.translation import _

if sys.version_info > (3,):
import _thread
else:
import thread as _thread # pylint: disable=import-error


CREDENTIALS_PATH = 'data/credentials'
PROFILES_PATH = 'data/profiles'

Expand Down Expand Up @@ -120,12 +125,13 @@
+ CONNECTION_FACTS_TUPLE


def threaded_tailing(path, ansible_verbosity):
def threaded_tailing(path, ansible_verbosity=0):
"""Follow and provide output using a thread
:param path: path to file to follow
:param ansible_verbosity: the verbosity level
"""

thread.start_new_thread(tail_and_follow, (path, ansible_verbosity))
_thread.start_new_thread(tail_and_follow, (path, ansible_verbosity))


def tail_and_follow(path, ansible_verbosity):
Expand All @@ -142,7 +148,7 @@ def tail_and_follow(path, ansible_verbosity):
truncated = False

# pylint: disable=no-member
for line in sh.tail('-f', path, _iter=True):
for line in sh.tail('-f', '-n', '+0', path, _iter=True):
line = line.strip('\n')
if line.startswith('TASK') or line.startswith('PLAY'):
print(line)
Expand Down Expand Up @@ -288,7 +294,7 @@ def write_csv_data(keys, data, path):
:param data: The dictionary of data to convert to csv
:param path: The file path to write to
"""
with tempfile.NamedTemporaryFile(mode='wb', delete=False) as data_temp:
with tempfile.NamedTemporaryFile(mode='w', delete=False) as data_temp:
# Construct the CSV writer
writer = csv.DictWriter(
data_temp, fieldnames=sorted(keys), delimiter=',')
Expand Down
5 changes: 3 additions & 2 deletions rho/vault.py
Expand Up @@ -127,6 +127,7 @@ def dump_as_json(self, obj, stream=None):
""" Convert object to json and encrypt the data.
:param obj: Python object to convert to json
:param stream: If not None the location to write the encrypted data to.
If this is a file in Python 3, it must be open in binary mode.
:returns: If stream is None then the encrypted bytes otherwise None.
"""
data = json.dumps(obj, separators=(',', ': '))
Expand All @@ -137,7 +138,7 @@ def dump_as_json_to_file(self, obj, file_path):
:param obj: Python object to convert to json
:param file_path: The file to write data to via temp file
"""
with tempfile.NamedTemporaryFile(mode='wb', delete=False) as data_temp:
with tempfile.NamedTemporaryFile(delete=False) as data_temp:
self.dump_as_json(obj, data_temp)
data_temp.close()
move(data_temp.name, os.path.abspath(file_path))
Expand All @@ -156,7 +157,7 @@ def dump_as_yaml_to_file(self, obj, file_path):
:param obj: Python object to convert to yaml
:param file_path: The file to write data to via temp file
"""
with tempfile.NamedTemporaryFile(mode='wb', delete=False) as data_temp:
with tempfile.NamedTemporaryFile(mode='w', delete=False) as data_temp:
self.dump_as_yaml(obj, data_temp)
data_temp.close()
move(data_temp.name, os.path.abspath(file_path))
5 changes: 3 additions & 2 deletions roles/cpu/tasks/main.yml
Expand Up @@ -83,14 +83,15 @@
when: '"cpu.count" in facts_to_collect'

- name: gather cpu.socket_count fact
raw: sudo -n /usr/sbin/dmidecode -t 4 | grep 'Socket Designation'| wc -l
raw: /usr/sbin/dmidecode -t 4 | grep 'Socket Designation'| wc -l
register: cpu_socket_count
become: yes
ignore_errors: yes
when: '"cpu.socket_count" in facts_to_collect'

- name: add cpu.socket_count to dictionary
set_fact:
cpu: "{{ cpu|default({}) | combine({ item: cpu_socket_count['stdout_lines'][0] | default('error') }) }}"
cpu: "{{ cpu|default({}) | combine({ item: cpu_socket_count['stdout'] | trim | default('error') }) }}"
with_items:
- 'cpu.socket_count'
when: '"cpu.socket_count" in facts_to_collect'
6 changes: 4 additions & 2 deletions roles/date/tasks/main.yml
Expand Up @@ -20,12 +20,13 @@
- name: gather date.anaconda_log fact
raw: ls --full-time /root/anaconda-ks.cfg | grep -o '[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}'
register: date_anaconda_log
become: yes
ignore_errors: yes
when: '"date.anaconda_log" in facts_to_collect'

- name: add date.anaconda_log to dictionary
set_fact:
date: "{{ date|default({}) | combine({ item: date_anaconda_log['stdout_lines'][0] | default('error') }) }}"
date: "{{ date|default({}) | combine({ item: date_anaconda_log['stdout'] | trim | default('error') }) }}"
with_items:
- 'date.anaconda_log'
when: '"date.anaconda_log" in facts_to_collect'
Expand Down Expand Up @@ -59,12 +60,13 @@
- name: gather date.yum_history fact
raw: yum history | tail -n 4 | grep -o '[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}'
register: date_yum_history
become: yes
ignore_errors: yes
when: '"date.yum_history" in facts_to_collect'

- name: add date.yum_history to dictionary
set_fact:
date: "{{ date|default({}) | combine({ item: date_yum_history['stdout_lines'][0] | default('error') }) }}"
date: "{{ date|default({}) | combine({ item: date_yum_history['stdout_lines'] | select | first | default('error') }) }}"
with_items:
- 'date.yum_history'
when: '"date.yum_history" in facts_to_collect'
12 changes: 8 additions & 4 deletions roles/virt/tasks/main.yml
Expand Up @@ -29,26 +29,30 @@
when: '"virt.virt" in facts_to_collect or "virt.type" in facts_to_collect'

- name: check system manufacture for VMware
raw: manufacturer=$(sudo -n /usr/sbin/dmidecode | grep -A4 'System Information' | grep 'Manufacturer' | sed -n -e 's/^.*Manufacturer:\s//p'); if [[ $manufacturer == *"VMware"* ]]; then echo "Y"; else echo "N"; fi
raw: manufacturer=$(/usr/sbin/dmidecode | grep -A4 'System Information' | grep 'Manufacturer' | sed -n -e 's/^.*Manufacturer:\s//p'); if [[ $manufacturer == *"VMware"* ]]; then echo "Y"; else echo "N"; fi
register: sys_manu_vmware
become: yes
ignore_errors: yes
when: '"virt.virt" in facts_to_collect or "virt.type" in facts_to_collect'

- name: check system manufacture for innotek GmbH
raw: manufacturer=$(sudo -n /usr/sbin/dmidecode | grep -A4 'System Information' | grep 'Manufacturer' | sed -n -e 's/^.*Manufacturer:\s//p'); if [[ $manufacturer == *"innotek GmbH"* ]]; then echo "Y"; else echo "N"; fi
raw: manufacturer=$(/usr/sbin/dmidecode | grep -A4 'System Information' | grep 'Manufacturer' | sed -n -e 's/^.*Manufacturer:\s//p'); if [[ $manufacturer == *"innotek GmbH"* ]]; then echo "Y"; else echo "N"; fi
register: sys_manu_virtualbox
become: yes
ignore_errors: yes
when: '"virt.virt" in facts_to_collect or "virt.type" in facts_to_collect'

- name: check system manufacture for Microsoft
raw: manufacturer=$(sudo -n /usr/sbin/dmidecode | grep -A4 'System Information' | grep 'Manufacturer' | sed -n -e 's/^.*Manufacturer:\s//p'); if [[ $manufacturer == *"Microsoft"* ]]; then echo "Y"; else echo "N"; fi
raw: manufacturer=$(/usr/sbin/dmidecode | grep -A4 'System Information' | grep 'Manufacturer' | sed -n -e 's/^.*Manufacturer:\s//p'); if [[ $manufacturer == *"Microsoft"* ]]; then echo "Y"; else echo "N"; fi
register: sys_manu_virtualpc
become: yes
ignore_errors: yes
when: '"virt.virt" in facts_to_collect or "virt.type" in facts_to_collect'

- name: check system manufacture for QEMU
raw: manufacturer=$(sudo -n /usr/sbin/dmidecode | grep -A4 'System Information' | grep 'Manufacturer' | sed -n -e 's/^.*Manufacturer:\s//p'); if [[ $manufacturer == *"QEMU"* ]]; then echo "Y"; else echo "N"; fi
raw: manufacturer=$(/usr/sbin/dmidecode | grep -A4 'System Information' | grep 'Manufacturer' | sed -n -e 's/^.*Manufacturer:\s//p'); if [[ $manufacturer == *"QEMU"* ]]; then echo "Y"; else echo "N"; fi
register: sys_manu_kvm
become: yes
ignore_errors: yes
when: '"virt.virt" in facts_to_collect or "virt.type" in facts_to_collect'

Expand Down
2 changes: 1 addition & 1 deletion test/test_clicommand.py
Expand Up @@ -208,7 +208,7 @@ def setUp(self):
'date.machine_id': '2017-07-18',
'jboss.installed-versions': 'WildFly-10',
'uname.hardware_platform': 'x86_64'}]
with open(TMP_TEST_REPORT_SENSITIVE, 'wb') as data_temp:
with open(TMP_TEST_REPORT_SENSITIVE, 'w') as data_temp:
writer = csv.DictWriter(data_temp,
fieldnames=sorted(report_keys),
delimiter=',')
Expand Down
31 changes: 31 additions & 0 deletions test/test_utilities.py
Expand Up @@ -9,13 +9,37 @@

"""Unit tests for rho/utilities.py."""

import contextlib
import sys
import os
import time
import unittest
import six
from rho import utilities

# pylint: disable=missing-docstring
TMP_FOLLOW = "/tmp/follow.txt"


@contextlib.contextmanager
def redirect_stdout(stream):
"""Run a code block, capturing stdout to the given stream"""

old_stdout = sys.stdout
try:
sys.stdout = stream
yield
finally:
sys.stdout = old_stdout


class TestValidatePort(unittest.TestCase):
def setUp(self):
if os.path.isfile(TMP_FOLLOW):
os.remove(TMP_FOLLOW)
with open(TMP_FOLLOW, 'w') as follow_file:
follow_file.write('follow\n')

def test_wrong_type(self):
with self.assertRaises(ValueError):
utilities.validate_port([1, 2, 3])
Expand All @@ -37,3 +61,10 @@ def test_valid_string_port(self):

def test_valid_int_port(self):
self.assertEqual(utilities.validate_port(123), 123)

def test_threaded_tailing(self):
follow_list_out = six.StringIO()
with redirect_stdout(follow_list_out):
utilities.threaded_tailing(TMP_FOLLOW, 3)
time.sleep(2)
self.assertEqual(follow_list_out.getvalue(), 'follow\n')

0 comments on commit 34a2c9d

Please sign in to comment.