diff --git a/.gitignore b/.gitignore
index 0943770..8993cdd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@ Applications/
 *.swp
 generated_input.yaml
 archives/
+dash-charts.json
 
 # Byte-compiled / optimized / DLL files
 __pycache__/
diff --git a/get-image-info.py b/get-image-info.py
index 8b23e74..5d9982b 100644
--- a/get-image-info.py
+++ b/get-image-info.py
@@ -7,7 +7,7 @@ from datetime import datetime
 from utils.setup_utils import *
 
 
-def main(args):
+def main(args, start_time):
 	#storage variables
 	creds_file_loc = str(os.getcwd() + "/" + args.user.name)
 	
@@ -31,12 +31,14 @@ def main(args):
 		#cleanup from last run
 		shutil.rmtree(str(os.getcwd() + "/Applications"), ignore_errors=True)
 
+	dash_dict = get_dashboard_json()
+
 	num_tracker = 0
 
 	#for each app, get a lot of info on them
 	for app in app_list:
 		num_tracker += 1
-		progress_bar(num_tracker, len(app_list), 50)
+		progress_bar(num_tracker, len(app_list), start_time, 50)
 
 		dest_dir = "{}/Applications/{}/".format(os.getcwd(), app.name)
 		mkdir_p(dest_dir)	#Create the Applications/app/ dir
@@ -65,20 +67,24 @@ def main(args):
 
 	diff_last_files()
 
-	#TODO - output names of bad apps at end of log
-	print("\n========\n")
+	print("\n==== CONFLICT WITH DASHBOARD ====\n")
+	for app in app_list:
+		if not app.matches_dashboard(dash_dict):
+			print(app.name)
+
+	print("\n==== BAD APPS ====\n")
 	i = 0
 	for app in app_list:
-		if app.is_bad == True:
+		if app.is_bad:
 			i += 1
 			print(app.name)
-	print(i)
+	print("Total: {}".format(i))
 
 if __name__ == "__main__":
 	start_time = datetime.now()
 
 	args = setup_logging()
-	main(args)
+	main(args, start_time)
 
 	end_time = datetime.now()
 	print("Time to run program: {}".format(end_time - start_time))
diff --git a/objects/image.py b/objects/image.py
index dc92b15..571503f 100644
--- a/objects/image.py
+++ b/objects/image.py
@@ -30,10 +30,13 @@ class App:
 		self.Charts_exists = False
 		self.is_bad = False # something did't parse correctly so its causing problems
 		self.product_name = '' #taken from README file of app
+		self.archs = []
 
 
 	def add_keyword(self, keyword):
 		self.keywords.append(keyword)
+		if (keyword in ['amd64', 'ppc64le', 's390x']):
+			self.archs.append(keyword)
 
 	def verify(self):
 		"""iterate thru an App's sub images to make sure we have all the info we need.
@@ -200,7 +203,7 @@ class App:
 			if (len(nested_lookup('keywords', document=chart_yaml_doc)) > 0):
 				keywords = nested_lookup('keywords', document=chart_yaml_doc)
 				for key in keywords[0]:
-					self.add_keyword(key)
+					self.add_keyword(key)		
 
 	def clean_image_repo(self):
 		"""from list of repo strings, get image names and repos.
@@ -314,6 +317,15 @@ class App:
 			# From here, all the vars are set for the output.
 			self.sub_images.append(image_obj)
 
+	def matches_dashboard(self, dashboard_file):
+		if (dashboard_file is not None):
+			archs_from_dash = dashboard_file[self.name]["architectures"]
+			archs_from_dash.sort()
+			self.archs.sort()
+			return self.archs == archs_from_dash
+		else:
+			return True
+
 	def output_app_keywords(self, f):
 		""" use keywords from App. no for loop so outputs only once"""
 		if 'amd64' in self.keywords and 'ppc64le' in self.keywords and 's390x' in self.keywords:
diff --git a/utils/setup_utils.py b/utils/setup_utils.py
index 07e7a91..6730fdf 100644
--- a/utils/setup_utils.py
+++ b/utils/setup_utils.py
@@ -7,6 +7,7 @@ import sys
 import os
 import errno
 import difflib
+from json import load
 
 from objects.hub import Hub
 from objects.image import App
@@ -31,14 +32,16 @@ def mkdir_p(path):
 #prints a progress bar as a process runs with
 #how many items are complete, how many need to complete,
 #and the length of the bar on the screen
-def progress_bar(num, total, length=50):
+def progress_bar(num, total, start_time, length=50):
 	#get decimal and integer percent done
 	proportion = num / total
 	percent = int(proportion * 100)
 	#get number of octothorpes to display
 	size = int(proportion * length)
+	# Get runtime to display
+	runtime = str(datetime.now() - start_time)
 	#display [###   ] NN% done
-	display = '[' + ('#' * size) + (' ' * (length - size)) + '] ' + str(percent) + '% done'
+	display = '[' + ('#' * size) + (' ' * (length - size)) + '] ' + str(percent) + '% done ' + runtime
 	#write with stdout to allow for in-place printing
 	sys.stdout.write(display)
 	sys.stdout.flush()
@@ -73,7 +76,7 @@ def setup_logging():
 
 	# let argparse do the work for us
 	logging.basicConfig(level=args.loglevel,filename='container-output.log',
-						format='%(levelname)s:%(message)s')
+						format='%(asctime)s ~ %(levelname)s:\n%(message)s\n')
 
 	return args
 
@@ -162,7 +165,7 @@ def diff_last_files():
 	try:
 		yesterday_f_commas = open(yesterday_file_loc, "r").readlines()
 	except:
-		print("Yesterday's file not found, could not diff files")
+		print("\nYesterday's file not found, could not diff files")
 		return "Yesterday not found"
 	today_lines = [l.replace(",", "") for l in today_f_commas]
 	yesterday_lines = [l.replace(",", "") for l in yesterday_f_commas]
@@ -173,3 +176,17 @@ def diff_last_files():
 			print(line)
 	return "Finished properly"
 
+def get_dashboard_json():
+	""" Tries to return a dict from dash-charts.json, if it exists.
+		If it doesn't exist, None is returned and caught later
+	"""
+
+	try:
+		dash_json_f = open("dash-charts.json", "r")
+		dash_dict = load(dash_json_f)
+		return dash_dict
+	except:
+		print("No dash-charts.json found in directory")
+		print("Disregard 'CONFLICTS' section at end of printout")
+		return None
+

Obtain info from GSA dashboard and cross-validate against our results
There exists a dashboard with architecture information. This task is focused on:

* Downloading arch info from GSA dashboard
* Extracting arch info
* Validating GSA dashboard info with our info from dockerhub

This issue is a different type of cross-validation than #39 in that this task is about verifying our results against a different data set (GSA dashboard) and not verifying our own past results.
diff --git a/tests/test_objects.py b/tests/test_objects.py
index 7286be1..309789b 100644
--- a/tests/test_objects.py
+++ b/tests/test_objects.py
@@ -19,6 +19,11 @@ def test_make_app():
 	new_app.verify()
 	assert(new_app.is_bad == True)
 
+	fake_data = {"im": { "architectures" : []}}
+	assert(new_app.matches_dashboard(fake_data))
+
+	assert(new_app.matches_dashboard(None))
+
 
 #test __init__ from objects.image.Image
 def test_make_image():
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 29d3b79..8d63238 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -29,16 +29,20 @@ def test_get_repo_pages_1000():
 
 #test progress_bar function from setup_utils
 def test_progress_bar_1_100():
-	assert(progress_bar(1, 100) == 1)
+	start_time = datetime.now()
+	assert(progress_bar(1, 100, start_time) == 1)
 
 def test_progress_bar_1_50():
-	assert(progress_bar(1, 50) == 2)
+	start_time = datetime.now()
+	assert(progress_bar(1, 50, start_time) == 2)
 
 def test_progress_bar_466_693():
-	assert(progress_bar(466, 693) == 67)
+	start_time = datetime.now()
+	assert(progress_bar(466, 693, start_time) == 67)
 
 def test_progress_bar_385_745():
-	assert(progress_bar(385, 745) == 51)
+	start_time = datetime.now()
+	assert(progress_bar(385, 745, start_time) == 51)
 
 
 #test parse_creds function from setup_utils

pip install -e .
parse_log_pytest
requirements.txt
pytest
3.7
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
certifi==2019.6.16
chardet==3.0.4
-e git+https://github.com/mtarsel/ContainerAnalysis.git@d65303170ac64aa6ad35d93ae3edb761562a2192#egg=ContainerAnalysis
exceptiongroup==1.2.2
idna==2.8
importlib-metadata==6.7.0
iniconfig==2.0.0
nested-lookup==0.2.17
numpy==1.16.4
packaging==24.0
pluggy==1.2.0
pytest==7.4.4
PyYAML==5.1.1
requests==2.22.0
six==1.12.0
tomli==2.0.1
typing_extensions==4.7.1
urllib3==1.25.3
zipp==3.15.0

name: ContainerAnalysis
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=22.3.1=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - certifi==2019.6.16
      - chardet==3.0.4
      - exceptiongroup==1.2.2
      - idna==2.8
      - importlib-metadata==6.7.0
      - iniconfig==2.0.0
      - nested-lookup==0.2.17
      - numpy==1.16.4
      - packaging==24.0
      - pluggy==1.2.0
      - pytest==7.4.4
      - pyyaml==5.1.1
      - requests==2.22.0
      - six==1.12.0
      - tomli==2.0.1
      - typing-extensions==4.7.1
      - urllib3==1.25.3
      - zipp==3.15.0
prefix: /opt/conda/envs/ContainerAnalysis

tests/test_objects.py::test_make_app tests/test_utils.py::test_progress_bar_1_100 tests/test_utils.py::test_progress_bar_1_50 tests/test_utils.py::test_progress_bar_466_693 tests/test_utils.py::test_progress_bar_385_745
tests/test_utils.py::test_diff_last_files_no_yesterday tests/test_utils.py::test_diff_last_files_blank_yesterday
tests/test_objects.py::test_make_hub tests/test_objects.py::test_make_image tests/test_utils.py::test_travis_1 tests/test_utils.py::test_get_repo_pages_10 tests/test_utils.py::test_get_repo_pages_100 tests/test_utils.py::test_get_repo_pages_101 tests/test_utils.py::test_get_repo_pages_999 tests/test_utils.py::test_get_repo_pages_1000 tests/test_utils.py::test_parse_creds tests/test_utils.py::test_parse_index_yaml
.gitignore get-image-info.py objects/image.py utils/setup_utils.py
.gitignore get-image-info.py objects/image.py utils/setup_utils.py