def _run_step(self): """Runs the step implemented by this StepImplementer. Returns ------- StepResult Object containing the dictionary results of this step. """ step_result = StepResult.from_step_implementer(self) app_version = None pre_release = None build = None release_branch = self.get_value('release-branch') app_version = self.get_value('app-version') pre_release = self.get_value('pre-release') build = self.get_value('build') if pre_release == release_branch: version = f'{app_version}+{build}' image_tag = f'{app_version}' else: version = f'{app_version}-{pre_release}+{build}' image_tag = f'{app_version}-{pre_release}' step_result.add_artifact(name='version', value=version) step_result.add_artifact(name='container-image-version', value=image_tag) return step_result
def _run_step(self): """Runs the step implemented by this StepImplementer. Returns ------- StepResult Object containing the dictionary results of this step. """ step_result = StepResult.from_step_implementer(self) package_file = self.get_value('package-file') with open(package_file) as package_file_object: package_file_data = json.load(package_file_object) if not "version" in package_file_data: step_result.success = False step_result.message = f'Given npm package file ({package_file})' + \ ' does not contain a \"version\" key.' return step_result step_result.add_artifact(name='app-version', value=package_file_data["version"]) return step_result
def _run_step(self): """Runs the step implemented by this StepImplementer. Returns ------- StepResult Object containing the dictionary results of this step. """ step_result = StepResult.from_step_implementer(self) # extract configs signature_server_url = self.get_value( 'container-image-signature-server-url') signature_server_username = self.get_value( 'container-image-signature-server-username') signature_server_password = self.get_value( 'container-image-signature-server-password') # extract step results container_image_signature_file_path = self.get_value( 'container-image-signature-file-path') container_image_signature_name = self.get_value( 'container-image-signature-name') with_fips = self.get_value('with-fips') try: container_image_signature_url, signature_file_md5, signature_file_sha1 = \ CurlPush.__curl_file( container_image_signature_file_path=container_image_signature_file_path, container_image_signature_name=container_image_signature_name, signature_server_url=signature_server_url, signature_server_username=signature_server_username, signature_server_password=signature_server_password, with_fips=with_fips ) step_result.add_artifact( name='container-image-signature-url', value=container_image_signature_url, ) if not with_fips: step_result.add_artifact( name='container-image-signature-file-md5', value=signature_file_md5, ) step_result.add_artifact( name='container-image-signature-file-sha1', value=signature_file_sha1) except StepRunnerException as error: step_result.success = False step_result.message = str(error) return step_result
def _run_step(self): """Runs the step implemented by this StepImplementer. Returns ------- StepResult Object containing the dictionary results of this step. """ step_result = StepResult.from_step_implementer(self) username = None password = None if self.has_config_value(AUTHENTICATION_CONFIG): username = self.get_value('git-username') password = self.get_value('git-password') else: print('No username/password found, assuming ssh') tag = self.__get_tag() try: self.__git_tag(tag) git_url = self.__git_url() if git_url.startswith('http://'): if username and password: self.__git_push('http://' + username + ':' + password + '@' + git_url[7:]) else: step_result.success = False step_result.message = 'For a http:// git url, you need to also provide ' \ 'username/password pair' return step_result elif git_url.startswith('https://'): if username and password: self.__git_push('https://' + username + ':' + password + '@' + git_url[8:]) else: step_result.success = False step_result.message = 'For a https:// git url, you need to also provide ' \ 'username/password pair' return step_result else: self.__git_push(None) except StepRunnerException as error: step_result.success = False step_result.message = str(error) step_result.add_artifact(name='tag', value=tag) return step_result
def _run_step(self): """Runs the step implemented by this StepImplementer. Returns ------- StepResult Object containing the dictionary results of this step. """ step_result = StepResult.from_step_implementer(self) # get the pgp private key to sign the image with image_signer_pgp_private_key = self.get_value( 'container-image-signer-pgp-private-key') # get the uri to the image to sign container_image_tag = self.get_value('container-image-tag') image_signatures_directory = self.create_working_dir_sub_dir( sub_dir_relative_path='image-signature') # import the PGP key and get the finger print try: image_signer_pgp_private_key_fingerprint = PodmanSign.__import_pgp_key( pgp_private_key=image_signer_pgp_private_key) step_result.add_artifact( name='container-image-signature-private-key-fingerprint', value=image_signer_pgp_private_key_fingerprint) # sign the image signature_file_path = PodmanSign.__sign_image( pgp_private_key_fingerprint= image_signer_pgp_private_key_fingerprint, image_signatures_directory=image_signatures_directory, container_image_tag=container_image_tag) step_result.add_artifact( name='container-image-signature-file-path', value=signature_file_path, ) signature_name = os.path.relpath(signature_file_path, image_signatures_directory) step_result.add_artifact(name='container-image-signature-name', value=signature_name) except StepRunnerException as error: step_result.success = False step_result.message = str(error) return step_result
def _run_step(self): """Runs the step implemented by this StepImplementer. Returns ------- StepResult Object containing the dictionary results of this step. """ step_result = StepResult.from_step_implementer(self) argocd_result_set = self.get_value('argocd-deployed-manifest') if not os.path.exists(argocd_result_set): step_result.success = False step_result.message = 'File specified in ' \ f'argocd-deployed-manifest {argocd_result_set} not found' return step_result step_result.add_artifact(name='configlint-yml-path', value=argocd_result_set) return step_result
def _run_step(self): # pylint: disable=too-many-locals """Runs the step implemented by this StepImplementer. Returns ------- StepResult Object containing the dictionary results of this step. """ step_result = StepResult.from_step_implementer(self) # get input deployment_config_repo = self.get_value('deployment-config-repo') deployment_config_repo_branch = ArgoCD.__get_repo_branch() deployment_config_helm_chart_path = self.get_value( 'deployment-config-helm-chart-path') deployment_config_destination_cluster_uri = self.get_value( 'kube-api-uri') deployment_config_destination_cluster_token = self.get_value( 'kube-api-token') deployment_config_helm_chart_environment_values_file = \ self.__get_deployment_config_helm_chart_environment_values_file() deployment_config_helm_chart_values_file_image_tag_yq_path = \ self.get_value('deployment-config-helm-chart-values-file-image-tag-yq-path') deployment_config_helm_chart_additional_value_files = \ self.get_value('deployment-config-helm-chart-additional-values-files') container_image_tag = self.get_value('container-image-tag') try: argocd_app_name = self.__get_app_name() step_result.add_artifact(name='argocd-app-name', value=argocd_app_name) # clone the configuration repository print("Clone the configuration repository") clone_repo_dir_name = 'deployment-config-repo' deployment_config_repo_dir = ArgoCD.__clone_repo( repo_dir=self.create_working_dir_sub_dir(clone_repo_dir_name), repo_url=deployment_config_repo, repo_branch=deployment_config_repo_branch, user_email=self.get_value('git-email'), user_name=self.get_value('git-name')) # update values file, commit it, push it, and tag it print("Update the environment values file") deployment_config_helm_chart_environment_values_file_path = os.path.join( deployment_config_repo_dir, deployment_config_helm_chart_path, deployment_config_helm_chart_environment_values_file) self.__update_yaml_file_value( file=deployment_config_helm_chart_environment_values_file_path, yq_path= deployment_config_helm_chart_values_file_image_tag_yq_path, value=container_image_tag) print("Commit the updated environment values file") ArgoCD.__git_commit_file( git_commit_message= f'Updating values for deployment to {self.environment}', file_path=os.path.join( deployment_config_helm_chart_path, deployment_config_helm_chart_environment_values_file), repo_dir=deployment_config_repo_dir) print("Tag and push the updated environment values file") deployment_config_repo_tag = self.__get_deployment_config_repo_tag( ) self.__git_tag_and_push_deployment_config_repo( deployment_config_repo=deployment_config_repo, deployment_config_repo_dir=deployment_config_repo_dir, deployment_config_repo_tag=deployment_config_repo_tag) step_result.add_artifact(name='config-repo-git-tag', value=deployment_config_repo_tag) # create/update argocd app and sync it print("Sign into ArgoCD") ArgoCD.__argocd_sign_in(argocd_api=self.get_value('argocd-api'), username=self.get_value('argocd-username'), password=self.get_value('argocd-password'), insecure=self.get_value('argocd-skip-tls')) print("Add target cluster to ArgoCD") self.__argocd_add_target_cluster( kube_api=deployment_config_destination_cluster_uri, kube_api_token=deployment_config_destination_cluster_token, kube_api_skip_tls=self.get_value('kube-api-skip-tls')) print(f"Create or update ArgoCD Application ({argocd_app_name})") argocd_values_files = [] argocd_values_files += deployment_config_helm_chart_additional_value_files argocd_values_files += [ deployment_config_helm_chart_environment_values_file ] ArgoCD.__argocd_app_create_or_update( argocd_app_name=argocd_app_name, repo=deployment_config_repo, revision=deployment_config_repo_branch, path=deployment_config_helm_chart_path, dest_server=deployment_config_destination_cluster_uri, auto_sync=self.get_value('argocd-auto-sync'), values_files=argocd_values_files) # sync and wait for the sync of the ArgoCD app print( f"Sync (and wait for) ArgoCD Application ({argocd_app_name})") ArgoCD.__argocd_app_sync( argocd_app_name=argocd_app_name, argocd_sync_timeout_seconds=self.get_value( 'argocd-sync-timeout-seconds')) # get the ArgoCD app manifest that was synced print( f"Get ArgoCD Application ({argocd_app_name}) synced manifest") arogcd_app_manifest_file = self.__argocd_get_app_manifest( argocd_app_name=argocd_app_name) step_result.add_artifact(name='argocd-deployed-manifest', value=arogcd_app_manifest_file) # determine the deployed host URLs print("Determine the deployed host URLs for the synced" f" ArgoCD Application (({argocd_app_name})") deployed_host_urls = ArgoCD.__get_deployed_host_urls( manifest_path=arogcd_app_manifest_file) step_result.add_artifact(name='deployed-host-urls', value=deployed_host_urls) except StepRunnerException as error: step_result.success = False step_result.message = f"Error deploying to environment ({self.environment}):" \ f" {str(error)}" return step_result
def _run_step(self): # pylint: disable=too-many-locals,too-many-statements """Runs the step implemented by this StepImplementer. Returns ------- StepResult Object containing the dictionary results of this step. """ step_result = StepResult.from_step_implementer(self) settings_file = self._generate_maven_settings() pom_file = self.get_value('pom-file') fail_on_no_tests = self.get_value('fail-on-no-tests') selenium_hub_url = self.get_value('selenium-hub-url') deployed_host_urls = ConfigValue.convert_leaves_to_values( self.get_value('deployed-host-urls') ) uat_maven_profile = self.get_value('uat-maven-profile') tls_verify = self.get_value('tls-verify') # NOTE: # at some point may need to do smarter logic if a deployable has more then one deployed # host URL to do UAT against all of them, but for now, use first one as target of UAT if isinstance(deployed_host_urls, list): target_base_url = deployed_host_urls[0] if len(deployed_host_urls) > 1: step_result.message = \ f"Given more then one deployed host URL ({deployed_host_urls})," \ f" targeting first one ({target_base_url}) for user acceptance test (UAT)." print(step_result.message) elif deployed_host_urls: target_base_url = deployed_host_urls else: target_base_url = self.get_value('target-host-url') # ensure surefire plugin enabled maven_surefire_plugin = self._get_effective_pom_element( element_path=MavenGeneric.SUREFIRE_PLUGIN_XML_ELEMENT_PATH ) if maven_surefire_plugin is None: step_result.success = False step_result.message = 'Unit test dependency "maven-surefire-plugin" ' \ f'missing from effective pom ({self._get_effective_pom()}).' return step_result # get surefire test results dir reports_dir = self._get_effective_pom_element( element_path=MavenGeneric.SUREFIRE_PLUGIN_REPORTS_DIR_XML_ELEMENT_PATH ) if reports_dir is not None: test_results_dir = reports_dir.text else: test_results_dir = os.path.join( os.path.dirname(os.path.abspath(pom_file)), MavenGeneric.DEFAULT_SUREFIRE_PLUGIN_REPORTS_DIR ) mvn_additional_options = [] if not tls_verify: mvn_additional_options += [ '-Dmaven.wagon.http.ssl.insecure=true', '-Dmaven.wagon.http.ssl.allowall=true', '-Dmaven.wagon.http.ssl.ignore.validity.dates=true', ] cucumber_html_report_path = os.path.join(self.work_dir_path, 'cucumber.html') cucumber_json_report_path = os.path.join(self.work_dir_path, 'cucumber.json') mvn_output_file_path = self.write_working_file('mvn_test_output.txt') try: with open(mvn_output_file_path, 'w') as mvn_output_file: out_callback = create_sh_redirect_to_multiple_streams_fn_callback([ sys.stdout, mvn_output_file ]) err_callback = create_sh_redirect_to_multiple_streams_fn_callback([ sys.stderr, mvn_output_file ]) sh.mvn( # pylint: disable=no-member 'clean', 'test', f'-P{uat_maven_profile}', f'-Dselenium.hub.url={selenium_hub_url}', f'-Dtarget.base.url={target_base_url}', f'-Dcucumber.plugin=' \ f'html:{cucumber_html_report_path},' \ f'json:{cucumber_json_report_path}', '-f', pom_file, '-s', settings_file, *mvn_additional_options, _out=out_callback, _err=err_callback ) if not os.path.isdir(test_results_dir) or len(os.listdir(test_results_dir)) == 0: if fail_on_no_tests: step_result.message = "No user acceptance tests defined" \ f" using maven profile ({uat_maven_profile})." step_result.success = False else: step_result.message = "No user acceptance tests defined" \ f" using maven profile ({uat_maven_profile})," \ " but 'fail-on-no-tests' is False." except sh.ErrorReturnCode: step_result.message = "User acceptance test failures. See 'maven-output'" \ ", 'surefire-reports', 'cucumber-report-html', and 'cucumber-report-json'" \ " report artifacts for details." step_result.success = False step_result.add_artifact( description=f"Standard out and standard error by 'mvn -P{uat_maven_profile} test'.", name='maven-output', value=mvn_output_file_path ) step_result.add_artifact( description=f"Surefire reports generated by 'mvn -P{uat_maven_profile} test'.", name='surefire-reports', value=test_results_dir ) step_result.add_artifact( description=f"Cucumber (HTML) report generated by 'mvn -P{uat_maven_profile} test'.", name='cucumber-report-html', value=cucumber_html_report_path ) step_result.add_artifact( description=f"Cucumber (JSON) report generated by 'mvn -P{uat_maven_profile} test'.", name='cucumber-report-json', value=cucumber_json_report_path ) return step_result
def _run_step(self): """Runs the step implemented by this StepImplementer. Returns ------- StepResult Object containing the dictionary results of this step. """ step_result = StepResult.from_step_implementer(self) # configlint-yml-path is required configlint_yml_path = self.get_value('configlint-yml-path') if not os.path.exists(configlint_yml_path): step_result.success = False step_result.message = 'File specified in ' \ f'configlint-yml-path not found: {configlint_yml_path}' return step_result # Required: rules and exists rules_file = self.get_value('rules') if not os.path.exists(rules_file): step_result.success = False step_result.message = f'File specified in rules not found: {rules_file}' return step_result configlint_results_file_path = self.write_working_file('configlint_results_file.txt') try: # run config-lint writing stdout and stderr to the standard streams # as well as to a results file. with open(configlint_results_file_path, 'w') as configlint_results_file: out_callback = create_sh_redirect_to_multiple_streams_fn_callback([ sys.stdout, configlint_results_file ]) err_callback = create_sh_redirect_to_multiple_streams_fn_callback([ sys.stderr, configlint_results_file ]) sh.config_lint( # pylint: disable=no-member "-verbose", "-debug", "-rules", rules_file, configlint_yml_path, _encoding='UTF-8', _out=out_callback, _err=err_callback, _tee='err' ) except sh.ErrorReturnCode_255: # pylint: disable=no-member # NOTE: expected failure condition, # aka, the config lint run, but found an issue # stderr/stdout is captured in configlint_results_file_path step_result.success = False step_result.message = 'Failed config-lint scan.' except sh.ErrorReturnCode: # NOTE: un-expected failure condition # aka, the config lint failed to run for some reason # stderr/stdout is captured in configlint_results_file_path step_result.success = False step_result.message = 'Unexpected Error invoking config-lint.' step_result.add_artifact( name='configlint-result-set', value=configlint_results_file_path ) step_result.add_artifact( name='configlint-yml-path', value=configlint_yml_path ) return step_result
def _run_step(self): step_result = StepResult.from_step_implementer(self) return step_result
def _run_step(self): """Runs the step implemented by this StepImplementer. Returns ------- StepResult Object containing the dictionary results of this step. """ step_result = StepResult.from_step_implementer(self) # Optional: username and password username = None password = None if self.has_config_value(AUTHENTICATION_CONFIG): if (self.get_value('username') and self.get_value('password')): username = self.get_value('username') password = self.get_value('password') application_name = self.get_value('application-name') service_name = self.get_value('service-name') project_key = f'{application_name}:{service_name}' url = self.get_value('url') version = self.get_value('version') properties_file = self.get_value('properties') java_truststore = self.get_value('java-truststore') if not os.path.exists(properties_file): step_result.success = False step_result.message = f'Properties file not found: {properties_file}' return step_result try: # Hint: Call sonar-scanner with sh.sonar_scanner # https://amoffat.github.io/sh/sections/faq.html working_directory = self.work_dir_path if username: sh.sonar_scanner( # pylint: disable=no-member f'-Dproject.settings={properties_file}', f'-Dsonar.host.url={url}', f'-Dsonar.projectVersion={version}', f'-Dsonar.projectKey={project_key}', f'-Dsonar.login={username}', f'-Dsonar.password={password}', f'-Dsonar.working.directory={working_directory}', _env={"SONAR_SCANNER_OPTS": f'-Djavax.net.ssl.trustStore={java_truststore}'}, _out=sys.stdout, _err=sys.stderr ) else: sh.sonar_scanner( # pylint: disable=no-member f'-Dproject.settings={properties_file}', f'-Dsonar.host.url={url}', f'-Dsonar.projectVersion={version}', f'-Dsonar.projectKey={project_key}', f'-Dsonar.working.directory={working_directory}', _env={"SONAR_SCANNER_OPTS": f'-Djavax.net.ssl.trustStore={java_truststore}'}, _out=sys.stdout, _err=sys.stderr ) except sh.ErrorReturnCode_1 as error: # pylint: disable=no-member # Error Code 1: INTERNAL_ERROR # See error codes: https://github.com/SonarSource/sonar-scanner-cli/blob/master/src/main/java/org/sonarsource/scanner/cli/Exit.java # pylint: disable=line-too-long step_result.success = False step_result.message = "Error running static code analysis" \ f" using sonar-scanner: {error}" except sh.ErrorReturnCode_2 as error: # pylint: disable=no-member # Error Code 2: USER_ERROR # See error codes: https://github.com/SonarSource/sonar-scanner-cli/blob/master/src/main/java/org/sonarsource/scanner/cli/Exit.java # pylint: disable=line-too-long step_result.success = False step_result.message = "Static code analysis failed." \ " See 'sonarqube-result-set' result artifact for details." except sh.ErrorReturnCode as error: # pylint: disable=no-member # Error Code Other: unexpected # See error codes: https://github.com/SonarSource/sonar-scanner-cli/blob/master/src/main/java/org/sonarsource/scanner/cli/Exit.java # pylint: disable=line-too-long step_result.success = False step_result.message = "Unexpected error running static code analysis" \ f" using sonar-scanner: {error}" step_result.add_artifact(name='sonarqube-result-set', value=f'{working_directory}/report-task.txt') return step_result
def run_step(self): """Wrapper for running the implemented step. Returns ------- StepResult Results of running this step. """ StepImplementer.__print_section_title(f"Step Start - {self.step_name}") # print information about the configuration StepImplementer.__print_section_title( f"Configuration - {self.step_name}", div_char="-", indent=1 ) StepImplementer.__print_data( "Step Implementer Configuration Defaults", ConfigValue.convert_leaves_to_values(self.step_implementer_config_defaults()) ) StepImplementer.__print_data( "Global Configuration Defaults", ConfigValue.convert_leaves_to_values(self.global_config_defaults) ) StepImplementer.__print_data( "Global Environment Configuration Defaults", ConfigValue.convert_leaves_to_values(self.global_environment_config_defaults) ) StepImplementer.__print_data( "Step Configuration", ConfigValue.convert_leaves_to_values(self.step_config) ) StepImplementer.__print_data( "Step Environment Configuration", ConfigValue.convert_leaves_to_values(self.step_environment_config) ) StepImplementer.__print_data( "Step Configuration Runtime Overrides", ConfigValue.convert_leaves_to_values(self.step_config_overrides) ) # create the munged runtime step configuration and print copy_of_runtime_step_config = self.get_copy_of_runtime_step_config() StepImplementer.__print_data( "Runtime Step Configuration", ConfigValue.convert_leaves_to_values(copy_of_runtime_step_config) ) step_result = None try: # validate the runtime step configuration self._validate_required_config_or_previous_step_result_artifact_keys() # run the step StepImplementer.__print_section_title( f"Standard Out - {self.step_name}", div_char="-", indent=1 ) indented_stdout = TextIOIndenter( parent_stream=sys.stdout, indent_level=2 ) indented_stderr = TextIOIndenter( parent_stream=sys.stderr, indent_level=2 ) with redirect_stdout(indented_stdout), redirect_stderr(indented_stderr): step_result = self._run_step() except AssertionError as invalid_error: step_result = StepResult.from_step_implementer(self) step_result.success = False step_result.message = str(invalid_error) # print the step run results StepImplementer.__print_section_title( f"Results - {self.step_name}", div_char="-", indent=1 ) StepImplementer.__print_data('Environment', step_result.environment) StepImplementer.__print_data('Step', step_result.step_name) StepImplementer.__print_data('Sub Step', step_result.sub_step_name) StepImplementer.__print_data('Sub Step Implementer', step_result.sub_step_implementer_name) StepImplementer.__print_data('Success', step_result.success) StepImplementer.__print_data('Message', step_result.message) StepImplementer.__print_data('Artifacts', step_result.artifacts) StepImplementer.__print_section_title(f'Step End - {self.step_name}') return step_result
def run_step(self): """Wrapper for running the implemented step. Returns ------- bool True on step run success. False on step run failure. """ StepImplementer.__print_section_title(f"Step Start - {self.step_name}") # print information about the configuration StepImplementer.__print_section_title( f"Configuration - {self.step_name}", div_char="-", indent=1 ) StepImplementer.__print_data( "Step Implementer Configuration Defaults", ConfigValue.convert_leaves_to_values(self.step_implementer_config_defaults()) ) StepImplementer.__print_data( "Global Configuration Defaults", ConfigValue.convert_leaves_to_values(self.global_config_defaults) ) StepImplementer.__print_data( "Global Environment Configuration Defaults", ConfigValue.convert_leaves_to_values(self.global_environment_config_defaults) ) StepImplementer.__print_data( "Step Configuration", ConfigValue.convert_leaves_to_values(self.step_config) ) StepImplementer.__print_data( "Step Environment Configuration", ConfigValue.convert_leaves_to_values(self.step_environment_config) ) StepImplementer.__print_data( "Step Configuration Runtime Overrides", ConfigValue.convert_leaves_to_values(self.step_config_overrides) ) # create the munged runtime step configuration and print copy_of_runtime_step_config = self.get_copy_of_runtime_step_config() StepImplementer.__print_data( "Runtime Step Configuration", ConfigValue.convert_leaves_to_values(copy_of_runtime_step_config) ) step_result = None try: # validate the runtime step configuration self._validate_required_config_or_previous_step_result_artifact_keys() # run the step StepImplementer.__print_section_title( f"Standard Out - {self.step_name}", div_char="-", indent=1 ) indented_stdout = TextIOIndenter( parent_stream=sys.stdout, indent_level=2 ) indented_stderr = TextIOIndenter( parent_stream=sys.stderr, indent_level=2 ) with redirect_stdout(indented_stdout), redirect_stderr(indented_stderr): step_result = self._run_step() except AssertionError as invalid_error: step_result = StepResult.from_step_implementer(self) step_result.success = False step_result.message = str(invalid_error) # save the step results self.workflow_result.add_step_result( step_result=step_result ) self.workflow_result.write_to_pickle_file( pickle_filename=self.__workflow_result_pickle_file_path ) self.workflow_result.write_results_to_yml_file( yml_filename=self.results_file_path ) # print the step run results StepImplementer.__print_section_title( f"Results - {self.step_name}", div_char="-", indent=1 ) StepImplementer.__print_data('Results File Path', self.results_file_path) StepImplementer.__print_data('Results', step_result.get_step_result_dict()) StepImplementer.__print_section_title(f'Step End - {self.step_name}') return step_result.success