def test_run_step_fail_missing_path_file_from_deploy(self): with TempDirectory() as temp_dir: parent_work_dir_path = os.path.join(temp_dir.path, 'working') test_file_name = 'yamlnotused' test_file_path = os.path.join(temp_dir.path, test_file_name) temp_dir.write(test_file_path, b'ignored') step_config = {} artifact_config = { 'argocd-deployed-manifest': { 'value': f'{test_file_path}.bad' } } workflow_result = self.setup_previous_result( parent_work_dir_path, artifact_config) step_implementer = self.create_step_implementer( step_config=step_config, step_name='validate-environment-configuration', implementer='ConfiglintArgocd', workflow_result=workflow_result, parent_work_dir_path=parent_work_dir_path) result = step_implementer._run_step() expected_step_result = StepResult( step_name='validate-environment-configuration', sub_step_name='ConfiglintArgocd', sub_step_implementer_name='ConfiglintArgocd') expected_step_result.success = False expected_step_result.message = f'File specified in argocd-deployed-manifest {test_file_path}.bad not found' self.assertEqual(expected_step_result, result)
def test_run_step_fail_missing_version_in_package_file(self): with TempDirectory() as temp_dir: parent_work_dir_path = os.path.join(temp_dir.path, 'working') temp_dir.write( 'package.json', b'''{ "name": "my-awesome-package" }''') package_file_path = os.path.join(temp_dir.path, 'package.json') step_config = {'package-file': package_file_path} step_implementer = self.create_step_implementer( step_config=step_config, step_name='generate-metadata', implementer='Npm', parent_work_dir_path=parent_work_dir_path, ) result = step_implementer._run_step() expected_step_result = StepResult( step_name='generate-metadata', sub_step_name='Npm', sub_step_implementer_name='Npm', ) expected_step_result.success = False expected_step_result.message = f"Given npm package file ({package_file_path})" + \ ' does not contain a \"version\" key.' self.assertEqual(result, expected_step_result)
def test_fail_git_repo_bare( self, mock_repo, mock_git_url, mock_git_commit_utc_timestamp ): with TempDirectory() as temp_dir: # setup step_config = { 'repo-root': temp_dir.path } step_implementer = self.create_step_implementer( step_config=step_config, step_name='generate-metadata', implementer='Git' ) # setup mocks mock_repo().bare = True # run test actual_step_result = step_implementer._run_step() # verify results expected_step_result = StepResult( step_name='generate-metadata', sub_step_name='Git', sub_step_implementer_name='Git' ) expected_step_result.success = False expected_step_result.message = f'Given git-repo-root is not a Git repository' self.assertEqual(actual_step_result, expected_step_result)
def test_fail_getting_git_repo( self, mock_repo, mock_git_url, mock_git_commit_utc_timestamp ): with TempDirectory() as temp_dir: # setup step_config = { 'repo-root': temp_dir.path } step_implementer = self.create_step_implementer( step_config=step_config, step_name='generate-metadata', implementer='Git' ) # setup mocks mock_repo.side_effect = StepRunnerException('mock error') # run test actual_step_result = step_implementer._run_step() # verify results expected_step_result = StepResult( step_name='generate-metadata', sub_step_name='Git', sub_step_implementer_name='Git' ) expected_step_result.success = False expected_step_result.message = f'mock error' self.assertEqual(actual_step_result, expected_step_result)
def test_fail_is_detached( self, mock_repo, mock_git_url, mock_git_commit_utc_timestamp ): with TempDirectory() as temp_dir: # setup step_config = { 'git-repo-root': temp_dir.path } step_implementer = self.create_step_implementer( step_config=step_config, step_name='generate-metadata', implementer='Git' ) # setup mocks mock_repo().bare = False mock_repo().head.is_detached = True # run test actual_step_result = step_implementer._run_step() # verify results expected_step_result = StepResult( step_name='generate-metadata', sub_step_name='Git', sub_step_implementer_name='Git' ) expected_step_result.success = False expected_step_result.message = f'Expected a Git branch in given git repo root' \ f' but has a detached head' self.assertEqual(actual_step_result, expected_step_result)
def test_run_step_fail_bad_rule_path(self, config_lint_mock): with TempDirectory() as temp_dir: parent_work_dir_path = os.path.join(temp_dir.path, 'working') test_file_name = 'rules' test_file_path = os.path.join(temp_dir.path, test_file_name) temp_dir.write(test_file_path, b'ignored') step_config = { 'configlint-yml-path': test_file_path, 'rules': 'invalid_file' } step_implementer = self.create_step_implementer( step_config=step_config, step_name='validate-environment-configuration', implementer='Configlint', parent_work_dir_path=parent_work_dir_path, ) result = step_implementer._run_step() expected_step_result = StepResult( step_name='validate-environment-configuration', sub_step_name='Configlint', sub_step_implementer_name='Configlint' ) expected_step_result.success = False expected_step_result.message = 'File specified in rules not found: invalid_file' self.assertEqual(expected_step_result, result)
def test_fail(self, mock_write_working_file, mock_run_maven_step): with TempDirectory() as test_dir: parent_work_dir_path = os.path.join(test_dir.path, 'working') step_config = {} step_implementer = self.create_step_implementer( step_config=step_config, parent_work_dir_path=parent_work_dir_path, ) # run step with mock failure mock_run_maven_step.side_effect = StepRunnerException( 'Mock error running maven') actual_step_result = step_implementer._run_step() # create expected step result expected_step_result = StepResult( step_name='foo', sub_step_name='MavenGeneric', sub_step_implementer_name='MavenGeneric') expected_step_result.add_artifact( description="Standard out and standard error from maven.", name='maven-output', value='/mock/mvn_output.txt') expected_step_result.message = "Error running maven. " \ "More details maybe found in 'maven-output' report artifact: "\ "Mock error running maven" expected_step_result.success = False # verify step result self.assertEqual(actual_step_result, expected_step_result) mock_write_working_file.assert_called_once() mock_run_maven_step.assert_called_with( mvn_output_file_path='/mock/mvn_output.txt')
def test_fail_no_properties_and_project_key(self, mock_sonar, mock_is_release_branch): with TempDirectory() as temp_dir: parent_work_dir_path = os.path.join(temp_dir.path, 'working') artifact_config = { 'version': {'description': '', 'value': '1.0-123abc'}, } workflow_result = self.setup_previous_result(parent_work_dir_path, artifact_config) step_config = { 'url': 'https://sonarqube-sonarqube.apps.ploigos_step_runner.rht-set.com', 'application-name': 'app-name', 'service-name': 'service-name', 'project-key': 'project-key' } step_implementer = self.create_step_implementer( step_config=step_config, step_name='static-code-analysis', implementer='SonarQube', workflow_result=workflow_result, parent_work_dir_path=parent_work_dir_path ) result = step_implementer._run_step() expected_step_result = StepResult( step_name='static-code-analysis', sub_step_name='SonarQube', sub_step_implementer_name='SonarQube' ) expected_step_result.success = False expected_step_result.message = 'Properties file not found: ./sonar-project.properties' self.assertEqual(result, expected_step_result)
def test_run_step_multiple_sub_steps_first_sub_step_fail_contine_sub_steps_on_failure_str( self, foo_step_implementer_run_step_mock, foo_step_implementer2_run_step_mock ): config = { 'step-runner-config': { 'foo': [ { 'name': 'Mock Sub Step 1', 'continue-sub-steps-on-failure': 'true', 'implementer': 'tests.helpers.sample_step_implementers.FooStepImplementer' }, { 'name': 'Mock Sub Step 2', 'implementer': 'tests.helpers.sample_step_implementers.FooStepImplementer2' } ] } } # mock return value mock_sub_step_1_result = StepResult( step_name='foo', sub_step_name='Mock Sub Step 1', sub_step_implementer_name='tests.helpers.sample_step_implementers.FooStepImplementer' ) mock_sub_step_1_result.success = False mock_sub_step_2_result = StepResult( step_name='foo', sub_step_name='Mock Sub Step 2', sub_step_implementer_name='tests.helpers.sample_step_implementers.FooStepImplementer' ) mock_sub_step_2_result.success = True foo_step_implementer_run_step_mock.return_value = mock_sub_step_1_result foo_step_implementer2_run_step_mock.return_value = mock_sub_step_2_result # run test step_runner = StepRunner(config) actual_success = step_runner.run_step('foo') # validate self.assertFalse(actual_success) foo_step_implementer_run_step_mock.assert_called_once() foo_step_implementer2_run_step_mock.assert_called_once()
def test_fail_set_version(self, mock_settings_file, mock_write_working_file, mock_run_maven_step, mock_run_maven): with TempDirectory() as test_dir: parent_work_dir_path = os.path.join(test_dir.path, 'working') pom_file = os.path.join(test_dir.path, 'mock-pom.xml') maven_push_artifact_repo_id = 'mock-repo-id' maven_push_artifact_repo_url = 'https://mock-repo.ploigos.com' version = '0.42.0-mock' step_config = { 'pom-file': pom_file, 'maven-push-artifact-repo-id': maven_push_artifact_repo_id, 'maven-push-artifact-repo-url': maven_push_artifact_repo_url, 'version': version } step_implementer = self.create_step_implementer( step_config=step_config, parent_work_dir_path=parent_work_dir_path, ) # run step with mvn version:set failure mock_run_maven.side_effect = StepRunnerException( 'mock error setting new pom version') actual_step_result = step_implementer._run_step() # create expected step result expected_step_result = StepResult( step_name='deploy', sub_step_name='MavenDeploy', sub_step_implementer_name='MavenDeploy') expected_step_result.success = False expected_step_result.message = "Error running 'maven deploy' to push artifacts. " \ "More details maybe found in 'maven-output' report artifact: " \ "mock error setting new pom version" expected_step_result.add_artifact( description= "Standard out and standard error from running maven to update version.", name='maven-update-version-output', value='/mock/mvn_versions_set_output.txt') expected_step_result.add_artifact( description="Standard out and standard error from running maven to " \ "push artifacts to repository.", name='maven-push-artifacts-output', value='/mock/mvn_deploy_output.txt' ) # verify step result self.assertEqual(actual_step_result, expected_step_result) mock_write_working_file.assert_called() mock_run_maven.assert_called_with( mvn_output_file_path='/mock/mvn_versions_set_output.txt', settings_file='/fake/settings.xml', pom_file=pom_file, phases_and_goals=['versions:set'], additional_arguments=[f'-DnewVersion={version}']) mock_run_maven_step.assert_not_called()
def test_run_step_pass_with_existing_tags(self, MockRepo, mock_sh): previous_dir = os.getcwd() try: with TempDirectory() as temp_dir: parent_work_dir_path = os.path.join(temp_dir.path, 'working') repo = Repo.init(str(temp_dir.path)) temp_dir.write( '.cz.json', b'''{ "commitizen": { "bump_message": "build: bump $current_version \\u2192 $new_version [skip-ci]", "name": "cz_conventional_commits", "tag_format": "$version", "update_changelog_on_bump": true } }''') cz_json_path = os.path.join(temp_dir.path, '.cz.json') step_config = { 'cz-json': cz_json_path, 'repo-root': temp_dir.path } step_implementer = self.create_step_implementer( step_config=step_config, step_name='generate-metadata', implementer='Commitizen', parent_work_dir_path=parent_work_dir_path, ) mock_sh.cz.bump.side_effect = functools.partial( self._mock_cz_bump, path=os.path.join(temp_dir.path, '.cz.json'), increment_type='minor') tag = collections.namedtuple('Tag', 'name') MockRepo().tags = [ tag(name='v_0.1.0__'), tag(name='0.3.0'), tag(name='version_4.34.0'), tag(name='5.2.7-prerelease'), tag(name='v3.142.0-test_abcxyz') ] result = step_implementer._run_step() expected_step_result = StepResult( step_name='generate-metadata', sub_step_name='Commitizen', sub_step_implementer_name='Commitizen') expected_step_result.success = True expected_step_result.add_artifact(name='app-version', value='5.3.0') self.assertEqual(result, expected_step_result) finally: os.chdir(previous_dir)
def __run__fail_sonar_scanner_error_test( self, sonar_scanner_error, expected_result_message_regex, mock_sonar ): with TempDirectory() as temp_dir: parent_work_dir_path = os.path.join(temp_dir.path, 'working') temp_dir.write('sonar-project.properties',b'''testing''') properties_path = os.path.join(temp_dir.path, 'sonar-project.properties') artifact_config = { 'version': {'description': '', 'value': '1.0-123abc'}, } workflow_result = self.setup_previous_result(parent_work_dir_path, artifact_config) step_config = { 'properties': properties_path, 'url': 'https://sonarqube-sonarqube.apps.ploigos_step_runner.rht-set.com', 'application-name': 'app-name', 'service-name': 'service-name', 'username': '******', 'password': '******' } step_implementer = self.create_step_implementer( step_config=step_config, step_name='static-code-analysis', implementer='SonarQube', workflow_result=workflow_result, parent_work_dir_path=parent_work_dir_path, ) mock_sonar.side_effect = sonar_scanner_error result = step_implementer._run_step() expected_step_result = StepResult( step_name='static-code-analysis', sub_step_name='SonarQube', sub_step_implementer_name='SonarQube' ) expected_step_result.success = False expected_step_result.add_artifact( name='sonarqube-result-set', value=f'{temp_dir.path}/working/static-code-analysis/report-task.txt' ) expected_step_result.add_evidence( name='sonarqube-quality-gate-pass', value=False ) self.assertEqual(result.success, expected_step_result.success) self.assertEqual(result.artifacts, expected_step_result.artifacts) self.assertRegex(result.message, expected_result_message_regex)
def test__run_step_pass_upload_to_remote_with_auth_failure( self, create_archive_mock, upload_file_mock): with TempDirectory() as temp_dir: parent_work_dir_path = os.path.join(temp_dir.path, 'working') step_config = { 'organization': 'test-ORG', 'application-name': 'test-APP', 'service-name': 'test-SERVICE', 'version': '42.0-test', 'results-archive-destination-url': 'https://ploigos.com/mock/results-archives', 'results-archive-destination-username': '******', 'results-archive-destination-password': '******' } step_implementer = self.create_step_implementer( step_config=step_config, parent_work_dir_path=parent_work_dir_path, ) # mock the upload results upload_file_mock.side_effect = RuntimeError('mock upload error') # run the step step_result = step_implementer._run_step() # verify results expected_step_result = StepResult( step_name='report', sub_step_name='ResultArtifactsArchive', sub_step_implementer_name='ResultArtifactsArchive') expected_step_result.add_artifact( name='result-artifacts-archive', value='/fake/archive/path/foo.zip', description= 'Archive of all of the step result artifacts marked for archiving.' ) expected_step_result.add_artifact( name='results-archive-uri', description='URI of the uploaded results archive.', value= 'https://ploigos.com/mock/results-archives/test-ORG/test-APP/test-SERVICE/foo.zip' ) expected_step_result.success = False expected_step_result.message = 'mock upload error' # verify mocks called create_archive_mock.assert_called_once() upload_file_mock.assert_called_once_with( file_path=mock.ANY, destination_uri= 'https://ploigos.com/mock/results-archives/test-ORG/test-APP/test-SERVICE/foo.zip', username='******', password='******')
def test_fail_sign_image(self, mock_sign_image, mock_import_pgp_key, mock_upload_file, mock_container_registries_login, mock_get_deploy_time_container_image_address): with TempDirectory() as temp_dir: # setup parent_work_dir_path = os.path.join(temp_dir.path, 'working') pgp_private_key_fingerprint = 'abc123' step_config = TestStepImplementerSignContainerImagePodmanBase.generate_config( ) # setup mocks def import_pgp_key_side_effect(pgp_private_key): return pgp_private_key_fingerprint mock_import_pgp_key.side_effect = import_pgp_key_side_effect mock_sign_image.side_effect = StepRunnerException( 'mock error signing image') # run test step_implementer = self.create_step_implementer( step_config=step_config, step_name='sign-container-image', implementer='PodmanSign', parent_work_dir_path=parent_work_dir_path) result = step_implementer._run_step() # validate mock_import_pgp_key.assert_called_once_with( pgp_private_key=step_config['signer-pgp-private-key']) mock_sign_image.assert_called_once_with( pgp_private_key_fingerprint=pgp_private_key_fingerprint, image_signatures_directory=os.path.join( parent_work_dir_path, 'sign-container-image/image-signature'), container_image_address= 'mock-deploy-time-container-image-address') mock_container_registries_login.assert_called_once_with( registries=None, containers_config_tls_verify=True, container_command_short_name='podman') mock_get_deploy_time_container_image_address.assert_called_once() expected_step_result = StepResult( step_name='sign-container-image', sub_step_name='PodmanSign', sub_step_implementer_name='PodmanSign') expected_step_result.add_artifact( name='container-image-signature-signer-private-key-fingerprint', value=pgp_private_key_fingerprint) expected_step_result.success = False expected_step_result.message = 'mock error signing image' self.assertEqual(expected_step_result, result)
def test_run_step_error_git_push(self, git_repo_mock, git_url_mock, get_tag_value_mock): # Test data setup tag = '1.0+69442c8' url = '[email protected]:ploigos/ploigos-step-runner.git' error = 'oh no. ohhhhh no.' branch_name = 'feature/no-feature' # Mock setup get_tag_value_mock.return_value = tag git_url_mock.return_value = url git_repo_mock.active_branch.name = branch_name with TempDirectory() as temp_dir: parent_work_dir_path = os.path.join(temp_dir.path, 'working') artifact_config = { 'version': {'description': '', 'value': tag}, 'container-image-version': {'description': '', 'value': tag} } workflow_result = self.setup_previous_result(parent_work_dir_path, artifact_config) step_config = { 'url': url, 'git-username': '******', 'git-password': '******' } step_implementer = self.create_step_implementer( step_config=step_config, workflow_result=workflow_result, parent_work_dir_path=parent_work_dir_path ) # this is the test here git_repo_mock.git.push.side_effect = Exception(error) result = step_implementer._run_step() # verify the test results expected_step_result = StepResult( step_name='tag-source', sub_step_name='Git', sub_step_implementer_name='Git' ) expected_step_result.add_artifact(name='tag', value=tag) expected_step_result.success = False expected_step_result.message = f"Error tagging and pushing tags: Error pushing tags to remote ({url})" \ f" on current branch ({branch_name}): {error}" # verifying all mocks were called git_repo_mock.create_tag.assert_called_once_with(tag, force=True) git_url_mock.assert_called_once_with() git_repo_mock.git.push.assert_called_once_with(url, '--tag') self.assertEqual(result, expected_step_result)
def test_fail_with_report_dir(self, mock_gather_evidence, mock_get_test_report_dir, mock_write_working_file, mock_run_maven_step): with TempDirectory() as test_dir: # setup test parent_work_dir_path = os.path.join(test_dir.path, 'working') pom_file = os.path.join(test_dir.path, 'mock-pom.xml') step_config = { 'pom-file': pom_file, 'target-host-url-maven-argument-name': 'mock.target-host-url-param', 'deployed-host-urls': ['https://mock.ploigos.org/mock-app-1'] } step_implementer = self.create_step_implementer( step_config=step_config, parent_work_dir_path=parent_work_dir_path, ) # setup mocks mock_run_maven_step.side_effect = StepRunnerException('mock error') # run test actual_step_result = step_implementer._run_step() # verify results expected_step_result = StepResult( step_name='unit-test', sub_step_name='MavenIntegrationTest', sub_step_implementer_name='MavenIntegrationTest') expected_step_result.success = False expected_step_result.message = "Error running maven. " \ "More details maybe found in report artifacts: " \ "mock error" expected_step_result.add_artifact( description="Standard out and standard error from maven.", name='maven-output', value='/mock/mvn_output.txt') expected_step_result.add_artifact( description="Test report generated when running unit tests.", name='test-report', value='/mock/test-results-dir') self.assertEqual(actual_step_result, expected_step_result) mock_run_maven_step.assert_called_once_with( mvn_output_file_path='/mock/mvn_output.txt', step_implementer_additional_arguments=[ '-Dmock.target-host-url-param=https://mock.ploigos.org/mock-app-1' ]) mock_gather_evidence.assert_called_once_with( step_result=Any(StepResult), test_report_dirs='/mock/test-results-dir')
def test_run_step_fail_commit_changes_and_push( self, mock_repo, mock_git_url, mock_git_commit_utc_timestamp ): # Data setup git_branch = 'main' error = 'Holy guacamole..!' with TempDirectory() as temp_dir: # setup step_config = { 'repo-root': temp_dir.path, 'git-commit-and-push-changes': True } step_implementer = self.create_step_implementer( step_config=step_config, step_name='generate-metadata', implementer='Git' ) # setup mocks mock_repo().bare = False mock_repo().head.is_detached = False mock_repo().active_branch.name = git_branch mock_repo().git.commit.side_effect = Exception(error) # run test actual_step_result = step_implementer._run_step() # verify results expected_step_result = StepResult( step_name='generate-metadata', sub_step_name='Git', sub_step_implementer_name='Git' ) expected_step_result.add_artifact( name='branch', value=git_branch ) expected_step_result.add_artifact( name='is-pre-release', value=False ) expected_step_result.success = False expected_step_result.message = f'Error committing and pushing changes: Error committing changes ' \ f'to current branch ({git_branch}): {error}' self.assertEqual(actual_step_result, expected_step_result)
def test_run_step_fail_scan(self, configlint_mock): with TempDirectory() as temp_dir: parent_work_dir_path = os.path.join(temp_dir.path, 'working') file_to_validate_contents = 'notused' temp_dir.write('config-file-to-validate.yml', file_to_validate_contents.encode()) file_to_validate_file_path = str(os.path.join(temp_dir.path, 'config-file-to-validate.yml')) # write config-lint rules file configlint_rules_content = 'not used' config_lint_rules_file_name = 'config-lint-test-rules.yml' temp_dir.write(config_lint_rules_file_name, configlint_rules_content.encode()) config_lint_rules_file_path = os.path.join(temp_dir.path, config_lint_rules_file_name) step_config = { 'configlint-yml-path': file_to_validate_file_path, 'rules': config_lint_rules_file_path } configlint_mock.side_effect = \ TestStepImplementerConfiglint.create_config_lint_side_effect( config_lint_fail=True ) step_implementer = self.create_step_implementer( step_config=step_config, step_name='validate-environment-configuration', implementer='Configlint', parent_work_dir_path=parent_work_dir_path, ) result = step_implementer._run_step() expected_step_result = StepResult( step_name='validate-environment-configuration', sub_step_name='Configlint', sub_step_implementer_name='Configlint' ) expected_step_result.success = False expected_step_result.message = 'Failed config-lint scan.' expected_step_result.add_artifact( name='configlint-result-set', value=f'{step_implementer.work_dir_path}/configlint_results_file.txt' ) expected_step_result.add_artifact( name='configlint-yml-path', value=file_to_validate_file_path ) self.assertEqual(expected_step_result, result)
def test_fail_no_commit_history( self, mock_repo, mock_git_url, mock_git_commit_utc_timestamp ): # Data setup git_branch = 'main' with TempDirectory() as temp_dir: # setup step_config = { 'repo-root': temp_dir.path } step_implementer = self.create_step_implementer( step_config=step_config, step_name='generate-metadata', implementer='Git' ) # setup mocks mock_repo().bare = False mock_repo().head.is_detached = False mock_repo().active_branch.name = git_branch type(mock_repo().head.reference).commit = PropertyMock(side_effect=ValueError) # run test actual_step_result = step_implementer._run_step() # verify results expected_step_result = StepResult( step_name='generate-metadata', sub_step_name='Git', sub_step_implementer_name='Git' ) expected_step_result.add_artifact( name='branch', value=git_branch ) expected_step_result.add_artifact( name='is-pre-release', value=False ) expected_step_result.success = False expected_step_result.message = f'Given Git repository root is a' \ f' git branch ({git_branch}) with no commit history.' self.assertEqual(actual_step_result, expected_step_result)
def test_run_step_error_git_url(self, git_repo_mock, git_url_mock, get_tag_value_mock): with TempDirectory() as temp_dir: tag = '1.0+69442c8' url = '[email protected]:ploigos/ploigos-step-runner.git' parent_work_dir_path = os.path.join(temp_dir.path, 'working') error = 'uh oh spaghetti-os' artifact_config = { 'version': {'description': '', 'value': tag}, 'container-image-version': {'description': '', 'value': tag} } workflow_result = self.setup_previous_result(parent_work_dir_path, artifact_config) step_config = { 'url': url, 'git-username': '******', 'git-password': '******' } step_implementer = self.create_step_implementer( step_config=step_config, workflow_result=workflow_result, parent_work_dir_path=parent_work_dir_path ) get_tag_value_mock.return_value = tag # this is the test here git_url_mock.side_effect = StepRunnerException(error) result = step_implementer._run_step() # verify test results expected_step_result = StepResult( step_name='tag-source', sub_step_name='Git', sub_step_implementer_name='Git' ) expected_step_result.add_artifact(name='tag', value=tag) expected_step_result.success = False expected_step_result.message = f"Error tagging and pushing tags: {error}" # verifying correct mocks were called git_repo_mock.create_tag.assert_called_once_with(tag, force=True) git_url_mock.assert_called_once() self.assertEqual(result, expected_step_result)
def test__run_step_pass_upload_to_remote_with_auth_failure(self, gather_evidence_mock, upload_file_mock): with TempDirectory() as temp_dir: parent_work_dir_path = os.path.join(temp_dir.path, 'working') step_config = { 'organization': 'test-ORG', 'application-name': 'test-APP', 'service-name': 'test-SERVICE', 'version': '42.0-test', 'evidence-destination-url': self.DEST_URL, 'evidence-destination-username': '******', 'evidence-destination-password': '******' } step_implementer = self.create_step_implementer( step_config=step_config, parent_work_dir_path=parent_work_dir_path ) # mock the upload results upload_file_mock.side_effect = RuntimeError('mock upload error') upload_file_mock.return_value = "mock upload results" # run the step step_result = step_implementer._run_step() # verify results expected_step_result = StepResult( step_name='generate_evidence', sub_step_name='GenerateEvidence', sub_step_implementer_name='GenerateEvidence' ) expected_step_result.success = False expected_step_result.message = 'mock upload error' self.assertEqual(step_result, expected_step_result) # verify mocks called gather_evidence_mock.assert_called_once() upload_file_mock.assert_called_once_with( file_path=mock.ANY, destination_uri=self.DEST_URI, username='******', password='******' )
def test_fail_import_pgp_key(self, mock_sign_image, mock_import_pgp_key, mock_upload_file, mock_container_registries_login, mock_get_deploy_time_container_image_address): with TempDirectory() as temp_dir: # setup parent_work_dir_path = os.path.join(temp_dir.path, 'working') step_config = TestStepImplementerSignContainerImagePodmanBase.generate_config( ) signature_name = 'does/not/matter/signature-0' # setup mocks mock_import_pgp_key.side_effect = RuntimeError( 'mock error importing pgp key') def sign_image_side_effect(pgp_private_key_fingerprint, image_signatures_directory, container_image_address): return os.path.join(image_signatures_directory, signature_name) mock_sign_image.side_effect = sign_image_side_effect # run test step_implementer = self.create_step_implementer( step_config=step_config, step_name='sign-container-image', implementer='PodmanSign', parent_work_dir_path=parent_work_dir_path) result = step_implementer._run_step() # validate mock_import_pgp_key.assert_called_once_with( pgp_private_key=step_config['signer-pgp-private-key']) mock_upload_file.assert_not_called() mock_container_registries_login.assert_not_called() mock_get_deploy_time_container_image_address.assert_called_once() expected_step_result = StepResult( step_name='sign-container-image', sub_step_name='PodmanSign', sub_step_implementer_name='PodmanSign') expected_step_result.success = False expected_step_result.message = 'mock error importing pgp key' self.assertEqual(expected_step_result, result)
def test_push_error(self, mock_pelorus_prometheus_job, mock_pelorus_prometheus_pushgateway_url, mock_commit_utc_timestamp, mock_container_image_digest, mock_commit_hash, mock_pelorus_app_name, mock_push_to_gateway): # setup mocks mock_pelorus_prometheus_job.return_value = 'mock-job' mock_pelorus_prometheus_pushgateway_url.return_value = 'mock-push-url' mock_commit_utc_timestamp.return_value = '1642079293.0' mock_container_image_digest.return_value = 'mock-digest' mock_commit_hash.return_value = 'mock-commit-hash' mock_pelorus_app_name.return_value = 'mock-app-name' mock_push_to_gateway.side_effect = Exception('mock push error') # setup step_implementer = self.create_step_implementer() # run step actual_result = step_implementer._run_step() # verify expected_step_result = StepResult( step_name='push-container-image', sub_step_name='PelorusCommitTimestampMetric', sub_step_implementer_name='PelorusCommitTimestampMetric') expected_step_result.success = False expected_step_result.message = "Error pushing Pelorus Commit Timestamp metric to" \ " Prometheus Pushgateway (mock-push-url): mock push error" self.assertEqual(actual_result, expected_step_result) mock_push_to_gateway.assert_called_once_with(gateway='mock-push-url', job='mock-job', grouping_key={ 'job': 'mock-job', 'app': 'mock-app-name', 'commit': 'mock-commit-hash' }, registry=ANY)
def test_run_step_fail_missing_version_in_pom_file( self, mock_run_maven ): mock_run_maven.side_effect = StepRunnerException("no version found") with TempDirectory() as temp_dir: parent_work_dir_path = os.path.join(temp_dir.path, 'working') temp_dir.write('pom.xml', b'''<project> <modelVersion>4.0.0</modelVersion> <groupId>com.mycompany.app</groupId> <artifactId>my-app</artifactId> </project>''') pom_file_path = os.path.join(temp_dir.path, 'pom.xml') step_config = { 'pom-file': pom_file_path } step_implementer = self.create_step_implementer( step_config=step_config, step_name='generate-metadata', implementer='Maven', parent_work_dir_path=parent_work_dir_path, ) result = step_implementer._run_step() expected_step_result = StepResult( step_name='generate-metadata', sub_step_name='Maven', sub_step_implementer_name='Maven' ) expected_step_result.success = False expected_step_result.message = f'Error running maven to get the project version: ' \ f'no version found' \ f'Could not get project version from given pom file' \ f' ({pom_file_path})' self.assertEqual(result, expected_step_result)
def test__run_step_fail_audit_fail_missing_workflow_attestation(self): with TempDirectory() as temp_dir: workflow_attestation_uri = 'https://foo.bar/evidence.json' workflow_policy_uri = 'https://foo.bar/policy.json' parent_work_dir_path = os.path.join(temp_dir.path, 'working') step_config = { 'workflow-policy-uri': workflow_policy_uri } step_result = StepResult( step_name='test-step', sub_step_name='test-sub-step', sub_step_implementer_name='test-sub-step-implementer' ) step_result.add_artifact('evidence-uri-wrong-key', workflow_attestation_uri, 'URI of the uploaded results archive.') workflow_result = WorkflowResult() workflow_result.add_step_result(step_result) step_implementer = self.create_step_implementer( step_config=step_config, parent_work_dir_path=parent_work_dir_path, workflow_result=workflow_result ) step_result = step_implementer._run_step() expected_step_result = StepResult( step_name='audit_attestation', sub_step_name='OpenPolicyAgent', sub_step_implementer_name='OpenPolicyAgent' ) expected_step_result.success = False expected_step_result.message = "No value found for evidence-uri" self.assertEqual(step_result, expected_step_result)
def test_fail_no_report_dir(self, mock_gather_evidence, mock_get_test_report_dir, mock_write_working_file, mock_run_maven_step): with TempDirectory() as test_dir: # setup test parent_work_dir_path = os.path.join(test_dir.path, 'working') pom_file = os.path.join(test_dir.path, 'mock-pom.xml') step_config = {'pom-file': pom_file} step_implementer = self.create_step_implementer( step_config=step_config, parent_work_dir_path=parent_work_dir_path, ) # setup mocks mock_run_maven_step.side_effect = StepRunnerException('mock error') mock_get_test_report_dir.return_value = None # run test actual_step_result = step_implementer._run_step() # verify results expected_step_result = StepResult( step_name='unit-test', sub_step_name='MavenTest', sub_step_implementer_name='MavenTest') expected_step_result.success = False expected_step_result.message = "Error running maven. " \ "More details maybe found in report artifacts: " \ "mock error" expected_step_result.add_artifact( description="Standard out and standard error from maven.", name='maven-output', value='/mock/mvn_output.txt') self.assertEqual(actual_step_result, expected_step_result) mock_run_maven_step.assert_called_once_with( mvn_output_file_path='/mock/mvn_output.txt') mock_gather_evidence.assert_not_called()
def test_fail_no_find_artifacts(self, mock_write_working_file, mock_run_maven_step): with TempDirectory() as test_dir: parent_work_dir_path = os.path.join(test_dir.path, 'working') pom_file = os.path.join(test_dir.path, 'mock-pom.xml') step_config = { 'pom-file': pom_file, 'artifact-parent-dir': 'mock/does-not-exist' } step_implementer = self.create_step_implementer( step_config=step_config, parent_work_dir_path=parent_work_dir_path, ) # run step actual_step_result = step_implementer._run_step() # create expected step result expected_step_result = StepResult( step_name='package', sub_step_name='MavenPackage', sub_step_implementer_name='MavenPackage') expected_step_result.success = False expected_step_result.message = \ "Error finding artifacts after running maven package:" \ f" [Errno 2] No such file or directory: '{test_dir.path}/mock/does-not-exist'" expected_step_result.add_artifact( description="Standard out and standard error from maven.", name='maven-output', value='/mock/mvn_output.txt') # verify step result self.assertEqual(actual_step_result, expected_step_result) mock_write_working_file.assert_called_once() mock_run_maven_step.assert_called_with( mvn_output_file_path='/mock/mvn_output.txt')
def test_run_step_pass(self, config_lint_mock): with TempDirectory() as temp_dir: parent_work_dir_path = os.path.join(temp_dir.path, 'working') test_file_name = 'file.txt' test_file_path = os.path.join(temp_dir.path, test_file_name) temp_dir.write(test_file_path, b'ignored') step_config = { 'rules': test_file_path, 'configlint-yml-path': test_file_path } step_implementer = self.create_step_implementer( step_config=step_config, step_name='validate-environment-configuration', implementer='Configlint', parent_work_dir_path=parent_work_dir_path, ) config_lint_mock.side_effect = sh.ErrorReturnCode('config_lint', b'mock out', b'mock error') result = step_implementer._run_step() expected_step_result = StepResult( step_name='validate-environment-configuration', sub_step_name='Configlint', sub_step_implementer_name='Configlint' ) expected_step_result.success = False expected_step_result.message = 'Unexpected Error invoking config-lint.' expected_step_result.add_artifact( name='configlint-result-set', value=f'{step_implementer.work_dir_path}/configlint_results_file.txt' ) expected_step_result.add_artifact( name='configlint-yml-path', value=test_file_path ) self.assertEqual(expected_step_result, result)
def test_run_step_success( self, mock_argocd, argocd_sign_in_mock, get_app_name_mock ): with TempDirectory() as temp_dir: # Test setup: Test inputs / mocks parent_work_dir_path = os.path.join(temp_dir.path, 'working') argocd_cascade = True argocd_propagation_policy = 'background' step_config = { 'argocd-username': '******', 'argocd-password': '******', 'argocd-api': 'https://argo.ploigos.xyz', 'argocd-skip-tls': False, 'argocd-cascade': argocd_cascade, 'argocd-propagation-policy': argocd_propagation_policy } # Test setup: Expected outputs expected_step_result = StepResult( step_name='delete', sub_step_name='ArgoCDDelete', sub_step_implementer_name='ArgoCDDelete', environment='PROD' ) expected_step_result.success = True expected_step_result.add_artifact( name='argocd-app-name', value='test-app-name' ) # Test execution step_implementer = self.create_step_implementer( step_config=step_config, parent_work_dir_path=parent_work_dir_path, environment='PROD' ) actual_step_results = step_implementer._run_step() # Test verification: Step results self.assertEqual(actual_step_results, expected_step_result) # Test verification: Mock method calls get_app_name_mock.assert_called_once_with() argocd_sign_in_mock.assert_called_once_with( argocd_api=step_config['argocd-api'], username=step_config['argocd-username'], password=step_config['argocd-password'], insecure=step_config['argocd-skip-tls'] ) mock_argocd.app.delete.assert_called_once_with( 'test-app-name', f'--cascade={argocd_cascade}', f'--propagation-policy={argocd_propagation_policy}', '--yes', _out=ANY, _err=ANY )
def test_run_step_failure( self, mock_argocd, argocd_sign_in_mock, get_app_name_mock ): with TempDirectory() as temp_dir: # Test setup: Test inputs / mocks parent_work_dir_path = os.path.join(temp_dir.path, 'working') argocd_cascade = True argocd_propagation_policy = 'background' environment = 'PROD' step_config = { 'argocd-username': '******', 'argocd-password': '******', 'argocd-api': 'https://argo.ploigos.xyz', 'argocd-skip-tls': False, 'argocd-cascade': argocd_cascade, 'argocd-propagation-policy': argocd_propagation_policy } # Test setup: Expected outputs delete_error_return = sh.ErrorReturnCode('argocd', b'mock out', b'mock argocd sign-in failure') delete_failure_error_msg = f"Error deleting ArgoCD app (test-app-name): {delete_error_return}" delete_exception = StepRunnerException(delete_failure_error_msg) expected_step_result = StepResult( step_name='delete', sub_step_name='ArgoCDDelete', sub_step_implementer_name='ArgoCDDelete', environment=environment ) expected_step_result.success = False expected_step_result.message = f"Error deleting environment ({environment}):" \ f" {str(delete_exception)}" expected_step_result.add_artifact( name='argocd-app-name', value='test-app-name' ) # Test setup: Mock behaviors mock_argocd.app.delete.side_effect = create_sh_side_effect( exception=delete_error_return ) # Test execution step_implementer = self.create_step_implementer( step_config=step_config, parent_work_dir_path=parent_work_dir_path, environment='PROD' ) actual_step_results = step_implementer._run_step() # Test verification: Step results self.assertEqual(actual_step_results, expected_step_result) # Test verification: Mock method calls get_app_name_mock.assert_called_once_with() argocd_sign_in_mock.assert_called_once_with( argocd_api=step_config['argocd-api'], username=step_config['argocd-username'], password=step_config['argocd-password'], insecure=step_config['argocd-skip-tls'] )