def test_very_long_job_name(): config_path = 'config/nebuchadnezzar.yml' config_name = config_path.replace('config/', '') config_lookback = 0 # in minutes args = [config_name] runner = BuildConnectorRunner(args) config = runner.getConfiguration(config_path) connector = BLDConnector(config, runner.log) agicen = connector.agicen_conn # see if a BuildDefinition exists in AgileCentral whose Name contains '/job/Marduk-apla-iddina%20II/' # if so, delete it funky_job_name = '/job/Marduk-apla-iddina%20II/' response = agicen.agicen.get('BuildDefinition', query='Name contains "%s"' % funky_job_name) for build_def in response: agicen.agicen.delete('BuildDefinition', build_def.ObjectID) project = 'Dunder Donut' path = 'http://tiema03-u183073.ca.com:8080/job/Zoolander/job/Apatosaurus/job/Brachiosaurus/job/Compsognathus/job/TorturedCircularLogicThatIsOrbulentAndVeryRoundishlyCircular/job/Babylon/job/Nebuchadnezzar%20III/job/AndHisKids-Shmeb-Dolly-PollyanaBillyJoe-Zukobnitsche/job/Marduk-apla-iddina%20II/' scm = 'git' build_defn = agicen.ensureBuildDefinitionExists(path, project, scm) print(path[-40:]) print(build_defn.Name[-40:]) assert build_defn assert build_defn.Name.endswith(funky_job_name) assert len(build_defn.Name) == 256 print(build_defn.Name) build_defn2 = agicen.ensureBuildDefinitionExists(path, project, scm) assert build_defn2.oid == build_defn.oid response = agicen.agicen.get('BuildDefinition', query='Name contains "%s"' % funky_job_name) for build_def in response: agicen.agicen.delete('BuildDefinition', build_def.ObjectID)
def test_jenkins_for_invalid_items(): config_file = ('bad_jenk_items.yml') runner = BuildConnectorRunner([config_file]) runner.run() log = "log/{}.log".format(config_file.replace('.yml', '')) with open(log, 'r') as f: log_content = f.readlines() target_line = "Jenkins section of the config contained these invalid entries" match = [line for line in log_content if target_line in line][0] assert re.search(r'%s' % target_line, match)
def test_lock(): lock = 'LOCK.tmp' config_path = 'config/wombat.yml' config_name = config_path.replace('config/', '') args = [config_name] runner = BuildConnectorRunner(args) assert runner.acquireLock() assert os.path.isfile(lock) assert os.path.abspath(lock) == "%s/%s" % (os.getcwd(), lock) runner.releaseLock() assert not os.path.isfile(lock)
def test_jenkins_for_empty_folders(): config_file = ('bad_jenk_empty_folders.yml') runner = BuildConnectorRunner([config_file]) runner.run() log = "log/{}.log".format(config_file.replace('.yml', '')) with open(log, 'r') as f: log_content = f.readlines() target_line = "Folders section of the config is empty" match = [line for line in log_content if target_line in line][0] assert re.search(r'%s' % target_line, match)
def get_bld_connector(config_file): try: config_path = 'config/%s' % config_file config_name = config_path.replace('config/', '') args = [config_name] runner = BuildConnectorRunner(args) config = runner.getConfiguration(config_path) connector = BLDConnector(config, runner.log) return connector except Exception as msg: print('Oh noes! %s' % msg) raise
def test_identify_unrecorded_builds(): config_path = 'config/dupes.yml' config_name = config_path.replace('config/', '') config_lookback = 0 # in minutes last_run_zulu = create_time_file(config_name, minutes=1) t = int(time.mktime(time.strptime( last_run_zulu, '%Y-%m-%d %H:%M:%S Z'))) - config_lookback last_run_minus_lookback_zulu = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.localtime(t)) args = [config_name] runner = BuildConnectorRunner(args) config = runner.getConfiguration(config_path) job_name = 'black-swan-2' folder1 = 'Parkour' folder2 = 'abacab/job/bontamy' jenk_conf = config.topLevel('Jenkins') jenkins_url = jsh.construct_jenkins_url(jenk_conf) r1 = jsh.build(jenk_conf, jenkins_url, job_name) assert r1.status_code in [200, 201] r2 = jsh.build(jenk_conf, jenkins_url, job_name, folder=folder1) assert r2.status_code in [200, 201] r3 = jsh.build(jenk_conf, jenkins_url, job_name, folder=folder2) assert r3.status_code in [200, 201] time.sleep(45) connector = BLDConnector(config, runner.log) connector.validate() print("our ref time: %s" % last_run_minus_lookback_zulu) agicen_ref_time = bld_ref_time = time.localtime(t) recent_agicen_builds = connector.agicen_conn.getRecentBuilds( agicen_ref_time, connector.target_projects) recent_bld_builds = connector.bld_conn.getRecentBuilds(bld_ref_time) unrecorded_builds = connector._identifyUnrecordedBuilds( recent_agicen_builds, recent_bld_builds) runner.log.info("unrecorded Builds count: %d" % len(unrecorded_builds)) # sort the unrecorded_builds into build chrono order, oldest to most recent, then project and job unrecorded_builds.sort(key=lambda build_info: (build_info[ 1].timestamp, build_info[2], build_info[1])) paths = [] for job, build, project, view in unrecorded_builds: print("build %s" % build) paths.append(job.fully_qualified_path()) assert 'tiema03-u183073.ca.com:8080/job/abacab/job/bontamy/view/dark flock/job/black-swan-2' in paths assert 'tiema03-u183073.ca.com:8080/job/black-swan-2' in paths assert 'tiema03-u183073.ca.com:8080/job/Parkour/job/black-swan-2' in paths
def test_builds_same_repo(): #default_lookback = 3600 # 1 hour in seconds config_lookback = 7200 # this is in seconds, even though in the config file the units are minutes config_file = 'same_scmrepo.yml' z = "2017-01-24 17:17:10 Z" last_run_zulu = create_time_file(config_file, zulu_time=z, minutes=60) t = int(time.mktime(time.strptime(last_run_zulu, '%Y-%m-%d %H:%M:%S Z'))) last_run_minus_lookback_zulu = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.localtime(t)) args = [config_file] runner = BuildConnectorRunner(args) assert runner.first_config == config_file runner.run() target_projects = runner.connector.target_projects assert 'Jenkins // Salamandra' in target_projects assert 'Jenkins // Corral // Salamandra' in target_projects
def test_dont_duplicate_builds(): job_name = 'truculent elk medallions' assert util.delete_ac_builds(job_name) == [] config_file = 'truculent.yml' ymlfile = open("config/{}".format(config_file), 'r') conf = yaml.load(ymlfile) project = conf['JenkinsBuildConnector']['Jenkins']['Jobs'][0]['AgileCentral_Project'] create_time_file(config_file, minutes=2) args = [config_file] runner = BuildConnectorRunner(args) assert runner.first_config == config_file last_run_zulu = '2016-12-01 00:00:00 Z' time_file_name = "{}_time.file".format(config_file.replace('.yml', '')) with open("log/{}".format(time_file_name), 'w') as tf: tf.write(last_run_zulu) runner.run() jenk_conn = runner.connector.bld_conn all_naked_jobs = jenk_conn.inventory.jobs targeted = [job for job in all_naked_jobs if job.name == job_name] target_job = targeted[0] build_defs = util.get_build_definition(target_job.fully_qualified_path(), project=project) assert len(build_defs) == 1 assert build_defs[0].Project.Name == project builds = util.get_ac_builds(build_defs[0], project=project) #assert len(builds) == 10 assert [build for build in builds if build.Number in ['8', '9', '10']] assert [build for build in builds if build.Number == '8' and build.Status == 'SUCCESS'] assert [build for build in builds if build.Number == '9' and build.Status == 'FAILURE'] last_run_zulu = '2016-10-31 00:00:00 Z' time_file_name = "{}_time.file".format(config_file.replace('.yml', '')) with open("log/{}".format(time_file_name), 'w') as tf: tf.write(last_run_zulu) runner.run() build_defs = util.get_build_definition(target_job.fully_qualified_path(), project=project) assert len(build_defs) == 1 builds = util.get_ac_builds(build_defs[0], project=project) assert len(builds) == 10 assert len([build for build in builds if build.Number == '1']) == 1 assert len([build for build in builds if build.Number in ['8', '9', '10']]) == 3 assert [build for build in builds if build.Number == '5' and build.Status == 'SUCCESS'] assert [build for build in builds if build.Number == '1' and build.Status == 'FAILURE']
def test_identify_unrecorded_builds(): config_path = 'config/dupes.yml' config_name = config_path.replace('config/', '') config_lookback = 0 # in minutes last_run_zulu = create_time_file(config_name, minutes=1) t = int(time.mktime(time.strptime(last_run_zulu, '%Y-%m-%d %H:%M:%S Z'))) - config_lookback last_run_minus_lookback_zulu = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.localtime(t)) args = [config_name] runner = BuildConnectorRunner(args) config = runner.getConfiguration(config_path) job_name = 'black-swan-2' folder1 = 'Parkour' folder2 = 'abacab/job/bontamy' jenk_conf = config.topLevel('Jenkins') jenkins_url = jsh.construct_jenkins_url(jenk_conf) r1 = jsh.build(jenk_conf, jenkins_url, job_name) assert r1.status_code in [200, 201] r2 = jsh.build(jenk_conf, jenkins_url, job_name, folder=folder1) assert r2.status_code in [200, 201] r3 = jsh.build(jenk_conf, jenkins_url, job_name, folder=folder2) assert r3.status_code in [200, 201] time.sleep(45) connector = BLDConnector(config, runner.log) connector.validate() print("our ref time: %s" % last_run_minus_lookback_zulu) agicen_ref_time = bld_ref_time = time.localtime(t) recent_agicen_builds = connector.agicen_conn.getRecentBuilds(agicen_ref_time, connector.target_projects) recent_bld_builds = connector.bld_conn.getRecentBuilds(bld_ref_time) unrecorded_builds = connector._identifyUnrecordedBuilds(recent_agicen_builds, recent_bld_builds) runner.log.info("unrecorded Builds count: %d" % len(unrecorded_builds)) # sort the unrecorded_builds into build chrono order, oldest to most recent, then project and job unrecorded_builds.sort(key=lambda build_info: (build_info[1].timestamp, build_info[2], build_info[1])) paths = [] for job, build, project, view in unrecorded_builds: print ("build %s" % build) paths.append(job.fully_qualified_path()) assert 'tiema03-u183073.ca.com:8080/job/abacab/job/bontamy/view/dark flock/job/black-swan-2' in paths assert 'tiema03-u183073.ca.com:8080/job/black-swan-2' in paths assert 'tiema03-u183073.ca.com:8080/job/Parkour/job/black-swan-2' in paths
def test_log_for_config_vetting(): config_file = BAD_CONFIG1 args = [config_file] runner = BuildConnectorRunner(args) assert runner.first_config == config_file runner.run() log = "log/{}.log".format(config_file.replace('.yml', '')) assert runner.logfile_name == log with open(log, 'r') as f: log_content = f.readlines() #error = "these jobs: Parkour, pillage-and-plunder, torment were not present in the Jenkins inventory of Jobs" # the log contained the same error, but the order of job names is different: # "these jobs: 'pillage-and-plunder', 'torment', 'Parkour' were not present in the Jenkins inventory of Jobs" error = "were not present in the Jenkins inventory of Jobs" match = [line for line in log_content if "{}".format(error) in line][0] assert re.search(r'%s' % error, match)
def test_existing_job(): ref_time = datetime.utcnow() - timedelta(minutes=2) config_file = "koalas.yml" folder = "koalas" my_job = "lunch" other_job = "dinner" conf = read_config(config_file) jenk_conf = conf['JenkinsBuildConnector']['Jenkins'] jenk_url = construct_jenkins_url(jenk_conf) r1 = build(jenk_conf, jenk_url, my_job, folder=folder) assert r1.status_code in [200, 201] time.sleep(15) args = [config_file] runner = BuildConnectorRunner(args) assert runner.first_config == config_file config_path = "config/{}".format(config_file) config = runner.getConfiguration(config_path) assert config_file in runner.config_file_names connector = BLDConnector(config, runner.log) connector.validate() jenk_builds = connector.bld_conn.getRecentBuilds(ref_time.utctimetuple()) jobs_snarfed = [] jenk_builds_snarfed = [] for container_proj, build_info in jenk_builds.items(): print (container_proj) for job, builds in build_info.items(): jobs_snarfed.append(job) jenk_builds_snarfed.extend(builds) print (builds) job_names = [job.name for job in jobs_snarfed] assert my_job in job_names assert other_job in job_names jenk_build_names = [build.name for build in jenk_builds_snarfed] assert not other_job in jenk_build_names assert my_job in job_names
def test_existing_job(): ref_time = datetime.utcnow() - timedelta(minutes=2) config_file = "koalas.yml" folder = "koalas" my_job = "lunch" other_job = "dinner" conf = read_config(config_file) jenk_conf = conf['JenkinsBuildConnector']['Jenkins'] jenk_url = construct_jenkins_url(jenk_conf) r1 = build(jenk_conf, jenk_url, my_job, folder=folder) assert r1.status_code in [200, 201] time.sleep(15) args = [config_file] runner = BuildConnectorRunner(args) assert runner.first_config == config_file config_path = "config/{}".format(config_file) config = runner.getConfiguration(config_path) assert config_file in runner.config_file_names connector = BLDConnector(config, runner.log) connector.validate() jenk_builds = connector.bld_conn.getRecentBuilds(ref_time.utctimetuple()) jobs_snarfed = [] jenk_builds_snarfed = [] for container_proj, build_info in jenk_builds.items(): print(container_proj) for job, builds in build_info.items(): jobs_snarfed.append(job) jenk_builds_snarfed.extend(builds) print(builds) job_names = [job.name for job in jobs_snarfed] assert my_job in job_names assert other_job in job_names jenk_build_names = [build.name for build in jenk_builds_snarfed] assert not other_job in jenk_build_names assert my_job in job_names
def test_bld_connector_runner(): #default_lookback = 3600 # 1 hour in seconds config_lookback = 7200 # this is in seconds, even though in the config file the units are minutes config_file = 'wombat.yml' last_run_zulu = create_time_file(config_file, minutes=60) #t = int(time.mktime(time.strptime(last_run_zulu, '%Y-%m-%d %H:%M:%S Z'))) - default_lookback t = int(time.mktime(time.strptime( last_run_zulu, '%Y-%m-%d %H:%M:%S Z'))) - config_lookback last_run_minus_lookback_zulu = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.localtime(t)) args = [config_file] runner = BuildConnectorRunner(args) assert runner.first_config == config_file runner.run() assert config_file in runner.config_file_names assert 'AgileCentral' in runner.connector.config.topLevels() assert 'Static' in runner.connector.target_projects log = "log/{}.log".format(config_file.replace('.yml', '')) assert runner.logfile_name == log with open(log, 'r') as f: log_content = f.readlines() line1 = "Connected to Jenkins server" line2 = "Connected to Agile Central" line3 = "Got a BLDConnector instance" line4 = "recent Builds query: CreationDate >= {}".format( last_run_minus_lookback_zulu) match1 = [line for line in log_content if "{}".format(line1) in line][-1] match2 = [line for line in log_content if "{}".format(line2) in line][-1] match3 = [line for line in log_content if "{}".format(line3) in line][-1] match4 = [line for line in log_content if "{}".format(line4) in line][-1] assert last_run_minus_lookback_zulu in match4 assert re.search(r'%s' % line1, match1) assert re.search(r'%s' % line2, match2) assert re.search(r'%s' % line3, match3) assert re.search(r'%s' % line4, match4)
def main(args): try: connector_runner = BuildConnectorRunner(args) connector_runner.run() except ConfigurationError as msg: # raising a ConfigurationError will cause an ERROR to be logged sys.stderr.write('ERROR: %s detected a fatal configuration error. See log file.\n' % PROG) sys.exit(1) except Exception as msg: sys.stderr.write('ERROR: %s encountered an ERROR condition.\n' % PROG) # blurt out a formatted stack trace excp_type, excp_value, tb = sys.exc_info() traceback.print_tb(tb) mo = re.search(r"'(?P<ex_name>.+)'", str(excp_type)) if mo: excp_type = mo.group('ex_name').replace('exceptions.', '').replace('bldeif.utils.', '') sys.stderr.write('%s: %s\n' % (excp_type, str(excp_value))) sys.exit(2) sys.exit(0)
def test_two_runners(): lock = 'LOCK.tmp' config_path = 'config/wombat.yml' config_name = config_path.replace('config/', '') args = [config_name] runner1 = BuildConnectorRunner(args) assert runner1.acquireLock() assert os.path.isfile(lock) assert os.path.abspath(lock) == "%s/%s" % (os.getcwd(), lock) runner2 = BuildConnectorRunner(args) expectedErrPattern = "Simultaneous processes for this connector are prohibited" with pytest.raises(Exception) as excinfo: runner2.acquireLock() actualErrVerbiage = excinfo.value.args[0] assert re.search(expectedErrPattern, actualErrVerbiage) is not None runner1.releaseLock() assert not os.path.isfile(lock)
def test_reflect_builds(): config_file = 'wombat.yml' folder = "immovable wombats" my_job = "Top" ymlfile = open("config/{}".format(config_file), 'r') data = yaml.load(ymlfile) jenkins = data['JenkinsBuildConnector']['Jenkins'] username = jenkins['Username'] api_token = jenkins['API_Token'] protocol = jenkins['Protocol'] server = jenkins['Server'] port = jenkins['Port'] headers = {'Content-Type': 'application/json'} jenkins_base_url = "{}://{}:{}".format(protocol, server, port) url = "{}/job/{}/job/{}/build".format(jenkins_base_url, folder, my_job) r = requests.post(url, auth=(username, api_token), headers=headers) assert r.status_code in [200, 201] create_time_file(config_file, minutes=2) args = [config_file] runner = BuildConnectorRunner(args) assert runner.first_config == config_file runner.run() assert config_file in runner.config_file_names assert 'AgileCentral' in runner.connector.config.topLevels() assert 'Static' in runner.connector.target_projects log = "log/{}.log".format(config_file.replace('.yml', '')) assert runner.logfile_name == log with open(log, 'r') as f: log_content = f.readlines() job_build_signature = "Created Build: tiema03-u183073.ca.com:8080/job/immovable wombats/job/Top" #job_build_signature = "Created Build: {}/job/{}/job/{}".format(jenkins_base_url, folder, my_job) job_url_lines = [ line for line in log_content if job_build_signature in line ] assert job_url_lines
def test_bld_connector_runner(): #default_lookback = 3600 # 1 hour in seconds config_lookback = 7200 # this is in seconds, even though in the config file the units are minutes config_file = 'wombat.yml' last_run_zulu = create_time_file(config_file, minutes=60) #t = int(time.mktime(time.strptime(last_run_zulu, '%Y-%m-%d %H:%M:%S Z'))) - default_lookback t = int(time.mktime(time.strptime(last_run_zulu, '%Y-%m-%d %H:%M:%S Z'))) - config_lookback last_run_minus_lookback_zulu = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.localtime(t)) args = [config_file] runner = BuildConnectorRunner(args) assert runner.first_config == config_file runner.run() assert config_file in runner.config_file_names assert 'AgileCentral' in runner.connector.config.topLevels() assert 'Static' in runner.connector.target_projects log = "log/{}.log".format(config_file.replace('.yml', '')) assert runner.logfile_name == log with open(log, 'r') as f: log_content = f.readlines() line1 = "Connected to Jenkins server" line2 = "Connected to Agile Central" line3 = "Got a BLDConnector instance" line4 = "recent Builds query: CreationDate >= {}".format(last_run_minus_lookback_zulu) match1 = [line for line in log_content if "{}".format(line1) in line][-1] match2 = [line for line in log_content if "{}".format(line2) in line][-1] match3 = [line for line in log_content if "{}".format(line3) in line][-1] match4 = [line for line in log_content if "{}".format(line4) in line][-1] assert last_run_minus_lookback_zulu in match4 assert re.search(r'%s' % line1, match1) assert re.search(r'%s' % line2, match2) assert re.search(r'%s' % line3, match3) assert re.search(r'%s' % line4, match4)
def test_reflect_builds(): config_file = 'wombat.yml' folder = "immovable wombats" my_job = "Top" ymlfile = open("config/{}".format(config_file), 'r') data = yaml.load(ymlfile) jenkins = data['JenkinsBuildConnector']['Jenkins'] username = jenkins['Username'] api_token = jenkins['API_Token'] protocol = jenkins['Protocol'] server = jenkins['Server'] port = jenkins['Port'] headers = {'Content-Type': 'application/json'} jenkins_base_url = "{}://{}:{}".format(protocol, server, port) url = "{}/job/{}/job/{}/build".format(jenkins_base_url, folder, my_job) r = requests.post(url, auth=(username, api_token), headers=headers) assert r.status_code in [200, 201] create_time_file(config_file, minutes=2) args = [config_file] runner = BuildConnectorRunner(args) assert runner.first_config == config_file runner.run() assert config_file in runner.config_file_names assert 'AgileCentral' in runner.connector.config.topLevels() assert 'Static' in runner.connector.target_projects log = "log/{}.log".format(config_file.replace('.yml', '')) assert runner.logfile_name == log with open(log, 'r') as f: log_content = f.readlines() job_build_signature = "Created Build: tiema03-u183073.ca.com:8080/job/immovable wombats/job/Top" #job_build_signature = "Created Build: {}/job/{}/job/{}".format(jenkins_base_url, folder, my_job) job_url_lines = [line for line in log_content if job_build_signature in line] assert job_url_lines
def test_special_chars(): config_file = 'aouch.yml' z = "2017-01-24 17:17:10 Z" last_run_zulu = create_time_file(config_file, zulu_time=z, minutes=60) t = int(time.mktime(time.strptime(last_run_zulu, '%Y-%m-%d %H:%M:%S Z'))) args = [config_file] runner = BuildConnectorRunner(args) assert runner.first_config == config_file runner.run() log = "log/{}.log".format(config_file.replace('.yml', '')) assert runner.logfile_name == log with open(log, 'r', encoding='utf-8') as f: log_content = f.readlines() target_line = "showQualifiedJobs - áâèüSørençñ" match = [line for line in log_content if target_line in line][0] assert re.search(r'%s' % target_line, match) target_line = "東方青龍" match = [line for line in log_content if target_line in line][0] assert re.search(r'%s' % target_line, match)
def test_dont_duplicate_builds(): job_name = 'truculent elk medallions' assert util.delete_ac_builds(job_name) == [] config_file = 'truculent.yml' ymlfile = open("config/{}".format(config_file), 'r') conf = yaml.load(ymlfile) project = conf['JenkinsBuildConnector']['Jenkins']['Jobs'][0][ 'AgileCentral_Project'] create_time_file(config_file, minutes=2) args = [config_file] runner = BuildConnectorRunner(args) assert runner.first_config == config_file last_run_zulu = '2016-12-01 00:00:00 Z' time_file_name = "{}_time.file".format(config_file.replace('.yml', '')) with open("log/{}".format(time_file_name), 'w') as tf: tf.write(last_run_zulu) runner.run() jenk_conn = runner.connector.bld_conn all_naked_jobs = jenk_conn.inventory.jobs targeted = [job for job in all_naked_jobs if job.name == job_name] target_job = targeted[0] build_defs = util.get_build_definition(target_job.fully_qualified_path(), project=project) assert len(build_defs) == 1 assert build_defs[0].Project.Name == project builds = util.get_ac_builds(build_defs[0], project=project) #assert len(builds) == 10 assert [build for build in builds if build.Number in ['8', '9', '10']] assert [ build for build in builds if build.Number == '8' and build.Status == 'SUCCESS' ] assert [ build for build in builds if build.Number == '9' and build.Status == 'FAILURE' ] last_run_zulu = '2016-10-31 00:00:00 Z' time_file_name = "{}_time.file".format(config_file.replace('.yml', '')) with open("log/{}".format(time_file_name), 'w') as tf: tf.write(last_run_zulu) runner.run() build_defs = util.get_build_definition(target_job.fully_qualified_path(), project=project) assert len(build_defs) == 1 builds = util.get_ac_builds(build_defs[0], project=project) assert len(builds) == 10 assert len([build for build in builds if build.Number == '1']) == 1 assert len([build for build in builds if build.Number in ['8', '9', '10']]) == 3 assert [ build for build in builds if build.Number == '5' and build.Status == 'SUCCESS' ] assert [ build for build in builds if build.Number == '1' and build.Status == 'FAILURE' ]