diff --git a/src/aws_authentication.py b/src/aws_authentication.py index 3a43592..dd9f08d 100644 --- a/src/aws_authentication.py +++ b/src/aws_authentication.py @@ -1,11 +1,12 @@ import boto3 import os + def get_boto_client(): - print("AUTH_METHOD: " + str(os.getenv('AUTH_METHOD'))) - if os.getenv('AUTH_METHOD') == 'SSO': - boto3.setup_default_session(profile_name=os.getenv('SSO_PROFILE')) - print("SSO Authentication") - else: - print("AWS KEYS authentication") - return boto3 \ No newline at end of file + print("AUTH_METHOD: ") + if os.getenv('AUTH_METHOD') == 'SSO': + boto3.setup_default_session(profile_name=os.getenv('SSO_PROFILE')) + print("\t -> SSO Authentication\n") + else: + print("\t -> AWS KEYS authentication\n") + return boto3 diff --git a/src/clone_blue_environment.py b/src/clone_blue_environment.py index 8f84d0f..4be65f3 100644 --- a/src/clone_blue_environment.py +++ b/src/clone_blue_environment.py @@ -45,6 +45,10 @@ def main(BLUE_ENV_NAME, GREEN_ENV_NAME, BEANSTALK_APP_NAME, S3_ARTIFACTS_BUCKET, print("Created a new CNAME file at S3") + current_release_bucket, current_release_key = get_current_release_package( + beanstalkclient, BEANSTALK_APP_NAME) + return current_release_bucket, current_release_key + def create_config_template(beanstalkclient, AppName, blue_env_id, TempName): '''Creates a ElasticBeanstalk deployment template and return the Template Name''' @@ -101,7 +105,7 @@ def wait_green_be_ready(beanstalkclient, GREEN_ENV_NAME): green_env_info = get_env_info(beanstalkclient, GREEN_ENV_NAME) while green_env_info["Environments"][0]["Status"] != "Ready": print("Waiting the blue environment be Ready!") - time.sleep(10) + time.sleep(60) green_env_info = get_env_info(beanstalkclient, GREEN_ENV_NAME) @@ -118,3 +122,11 @@ def rollback_created_env(boto_authenticated_client, environment_name): EnvironmentId=green_env_info["Environments"][0]["EnvironmentId"] ) return "Environment terminaated successfully!!" + +def get_current_release_package(client, application_name): + response = client.describe_application_versions( + ApplicationName=application_name, + MaxRecords=1 + ) + + return response['ApplicationVersions'][0]['SourceBundle']['S3Bucket'], response['ApplicationVersions'][0]['SourceBundle']['S3Key'] diff --git a/src/deploy_release.py b/src/deploy_release.py index 031162e..cbb08af 100644 --- a/src/deploy_release.py +++ b/src/deploy_release.py @@ -65,7 +65,8 @@ def deploy_new_version(beanstalkclient, BEANSTALK_APP_NAME, BLUE_ENV_NAME, VERSI return False print("The new version was deployed successfully!") - print(f"New version environment URL: http://{response['EnvironmentName']}.elasticbeanstalk.com") + print( + f"New version environment URL: http://{response['EnvironmentName']}.elasticbeanstalk.com") return True diff --git a/src/main.py b/src/main.py index 471ce0d..28c845b 100644 --- a/src/main.py +++ b/src/main.py @@ -7,21 +7,29 @@ import release_health_check import terminate_green_env import aws_authentication +import time def main(): + print("------------Initiating blue green deployment process------------\n\n\n") + starting_time = time.time() + BLUE_ENV_NAME = os.getenv("BLUE_ENV_NAME") GREEN_ENV_NAME = os.getenv("GREEN_ENV_NAME") BEANSTALK_APP_NAME = os.getenv("BEANSTALK_APP_NAME") S3_ARTIFACTS_BUCKET = os.getenv("S3_ARTIFACTS_BUCKET") S3_ARTIFACTS_OBJECT = os.getenv("S3_ARTIFACTS_OBJECT") + print("Environment variables: \n") print(f"BLUE_ENV_NAME = {BLUE_ENV_NAME}\n") print(f"GREEN_ENV_NAME = {GREEN_ENV_NAME}\n") print(f"BEANSTALK_APP_NAME = {BEANSTALK_APP_NAME}\n") print(f"S3_ARTIFACTS_BUCKET = {S3_ARTIFACTS_BUCKET}\n") print(f"S3_ARTIFACTS_OBJECT {S3_ARTIFACTS_OBJECT}\n") + current_release_bucket="" + current_release_key="" + available_execution_types = ["deploy", "cutover", "full", "rollback"] execution_type = str(sys.argv[1]) @@ -36,16 +44,22 @@ def main(): sys.exit(1) boto_authenticated_client = aws_authentication.get_boto_client() - print("Execution Type: " + execution_type) + print(f"\n Execution Type: {execution_type}\n") print("Initiating blue green deployment process") - print("\n\n\n ------------------ Initiating Step 1 --------------------- \n\n\n") - print("\n\n\n ------------------ Creating Green Env --------------------- \n\n\n") + + + if execution_type == "deploy" or execution_type == "full": + print("\n\n\n ------------------ Stating Deployment Step 1 --------------------- \n") + print("------------------ Creating Green Env --------------------- \n\n\n") # Step 1: Cloning the blue env into green env. try: - print("Clonning the blue environment") - clone_blue_environment.main( + print("Clonning the blue environment...") + start_1 = time.time() + previous_release_bucket, previous_release_key = clone_blue_environment.main( BLUE_ENV_NAME, GREEN_ENV_NAME, BEANSTALK_APP_NAME, S3_ARTIFACTS_BUCKET, boto_authenticated_client) + print(f"Clonning the blue environment has finished successfully!\n\ + \tIt took: {time.time() - start_1} seconds\n") except Exception as err: clone_blue_environment.rollback_created_env( boto_authenticated_client, GREEN_ENV_NAME @@ -56,13 +70,18 @@ def main(): print(str(e)) traceback.print_exc() sys.exit(1) + boto_authenticated_client = aws_authentication.get_boto_client() + print("\n\n\n ------------------ Stating Step 2 ---------------------\n") + print("------------------ Swapping Domains --------------------- \n\n\n") # Step 2: Swapping blue and green envs URL's. try: - print("Swapping environment URL's") + print("Swapping environment Domains...") + start_2 = time.time() swap_environment.main(BLUE_ENV_NAME, GREEN_ENV_NAME, S3_ARTIFACTS_BUCKET, BEANSTALK_APP_NAME, boto_authenticated_client) - print("URL's swap task finished succesfully") + print(f"Swapping environment Domains has finished successfully!\n\ + \tIt took: {time.time() - start_2} seconds\n") except Exception as err: print("Swap environment has failed.") print(("Error: " + str(err))) @@ -75,13 +94,18 @@ def main(): print(e) traceback.print_exc() sys.exit(1) + boto_authenticated_client = aws_authentication.get_boto_client() + print("\n\n\n ------------------ Stating Step 3 --------------------- \n") + print("----------------- New release Deployment --------------------- \n\n\n") # ## Step 3: Deploying the new release into the blue env. try: print("New release deployment initiated.") + start_3 = time.time() deploy_release.main(S3_ARTIFACTS_OBJECT, S3_ARTIFACTS_BUCKET, BLUE_ENV_NAME, BEANSTALK_APP_NAME, boto_authenticated_client) - print("New release was deployed successfully.") + print(f"New release deployment has finished successfully!\n\ + \tIt took: {time.time() - start_3} seconds\n") except Exception as err: print("New release deployment has failed.") print(("Error: " + str(err))) @@ -90,7 +114,6 @@ def main(): traceback.print_exc() sys.exit(1) - boto_authenticated_client = aws_authentication.get_boto_client() # Start cutover phase if execution_type == "cutover" or execution_type == "full": # Step 4: Health checking new release deployment. @@ -107,26 +130,16 @@ def main(): sys.exit(1) # Step 5: Re-swapping the URL's and terminating the green environment. + print("\n\n\n ------------------ Stating Cutover --------------------- \n") + print("------------------ Re-swapping the Domains && Killing the green environment --------------------- \n\n\n") boto_authenticated_client = aws_authentication.get_boto_client() try: print("Re-swapping the URL's and terminating the green environment.") + time_4 = time.time() terminate_green_env.main( BLUE_ENV_NAME, GREEN_ENV_NAME, BEANSTALK_APP_NAME, boto_authenticated_client) - print("The green environment has terminated successfully.") - print("The URL's has reswapped successfully.") - except Exception as err: - print( - "Re-swapping the URL's and terminating the green environment has failed!") - print(("Error: " + str(err))) - e = sys.exc_info()[0] - print(e) - traceback.print_exc() - sys.exit(1) - if execution_type == "rollback": - try: - print("Re-swapping the URL's and terminating the green environment.") - swap_environment.re_swap_dns( - boto_authenticated_client, S3_ARTIFACTS_BUCKET, GREEN_ENV_NAME, BLUE_ENV_NAME) + print(f"Re-swapping the URL's and terminating the green environment has finished successfully!\n\ + \tIt took: {time.time() - time_4} seconds\n") except Exception as err: print( "Re-swapping the URL's and terminating the green environment has failed!") @@ -135,19 +148,45 @@ def main(): print(e) traceback.print_exc() sys.exit(1) - try: - print("Rolling back the blue environment.") - clone_blue_environment.rollback_created_env( - boto_authenticated_client, GREEN_ENV_NAME - ) - print("The blue environment has rolled back successfully.") - except Exception as err: - print("Rolling back the blue environment has failed!") - print(("Error: " + str(err))) - e = sys.exc_info()[0] - print(e) - traceback.print_exc() - sys.exit(1) + # if execution_type == "rollback": + # try: + # print("Rolling back the blue environment to the previous version.") + # deploy_release.main(previous_release_key, previous_release_bucket, + # BLUE_ENV_NAME, BEANSTALK_APP_NAME, boto_authenticated_client) + # + # except Exception as err: + # print("Rolling back the blue environment has failed!") + # print(("Error: " + str(err))) + # e = sys.exc_info()[0] + # print(e) + # traceback.print_exc() + # sys.exit(1) + # try: + # print("Re-swapping the URL's and terminating the green environment.") + # swap_environment.re_swap_dns( + # boto_authenticated_client, S3_ARTIFACTS_BUCKET, GREEN_ENV_NAME, BLUE_ENV_NAME) + # except Exception as err: + # print( + # "Re-swapping the URL's and terminating the green environment has failed!") + # print(("Error: " + str(err))) + # e = sys.exc_info()[0] + # print(e) + # traceback.print_exc() + # sys.exit(1) + # try: + # print("Rolling back the blue environment.") + # clone_blue_environment.rollback_created_env( + # boto_authenticated_client, GREEN_ENV_NAME + # ) + # except Exception as err: + # print("Rolling back the blue environment has failed!") + # print(("Error: " + str(err))) + # e = sys.exc_info()[0] + # print(e) + # traceback.print_exc() + # sys.exit(1) + + if __name__ == "__main__": diff --git a/src/release_health_check.py b/src/release_health_check.py index ec0756b..867f003 100644 --- a/src/release_health_check.py +++ b/src/release_health_check.py @@ -4,37 +4,40 @@ import requests import time + def main(BLUE_ENV_NAME, boto_authenticated_client): - beanstalkclient = boto_authenticated_client.client('elasticbeanstalk') + beanstalkclient = boto_authenticated_client.client('elasticbeanstalk') + + wait_until_env_be_ready(beanstalkclient, BLUE_ENV_NAME) - wait_until_env_be_ready(beanstalkclient, BLUE_ENV_NAME) + if os.getenv("RELEASE_HEALTH_CHECKING_PATH"): + blue_env_cname = os.getenv("RELEASE_HEALTH_CHECKING_PATH") + else: + blue_env_info = get_env_info(beanstalkclient, BLUE_ENV_NAME) + blue_env_cname = "http://" + blue_env_info["Environments"][0]["CNAME"] - if os.getenv("RELEASE_HEALTH_CHECKING_PATH"): - blue_env_cname = os.getenv("RELEASE_HEALTH_CHECKING_PATH") - else: - blue_env_info = get_env_info(beanstalkclient, BLUE_ENV_NAME) - blue_env_cname = "http://" + blue_env_info["Environments"][0]["CNAME"] - - print("blue_env_cname: " + blue_env_cname) - env_http_response = requests.get(blue_env_cname, verify=False) - env_reponse_status = env_http_response.status_code + print("blue_env_cname: " + blue_env_cname) + env_http_response = requests.get(blue_env_cname, verify=False) + env_reponse_status = env_http_response.status_code + + if env_reponse_status == 200 or env_reponse_status == 301: + return "Ok" + else: + raise Exception("The environment isn't health") - if env_reponse_status == 200 or env_reponse_status == 301: - return "Ok" - else: - raise Exception("The environment isn't health") def get_env_info(beanstalkclient, env_name): - response = beanstalkclient.describe_environments( - EnvironmentNames=[ - env_name - ]) - return response + response = beanstalkclient.describe_environments( + EnvironmentNames=[ + env_name + ]) + return response + def wait_until_env_be_ready(beanstalkclient, ENV_NAME): - env_info = get_env_info(beanstalkclient, ENV_NAME) - while env_info["Environments"][0]["Status"] != "Ready": - print("Waiting the blue environment be Ready!") - time.sleep(10) env_info = get_env_info(beanstalkclient, ENV_NAME) - return "Env is ready" \ No newline at end of file + while env_info["Environments"][0]["Status"] != "Ready": + print("Waiting the blue environment be Ready!") + time.sleep(10) + env_info = get_env_info(beanstalkclient, ENV_NAME) + return "Env is ready" diff --git a/src/swap_environment.py b/src/swap_environment.py index 12ca945..7453bc1 100644 --- a/src/swap_environment.py +++ b/src/swap_environment.py @@ -63,7 +63,6 @@ def get_env_address(BLUE_CNAME_CONFIG_FILE, S3_ARTIFACTS_BUCKET, s3client): def get_environment_information(beanstalkclient, EnvName): ''' Get informations about a beanstalk environment''' env_count = 0 - env_count_for_credentials = 0 while True: response = beanstalkclient.describe_environments( @@ -72,21 +71,13 @@ def get_environment_information(beanstalkclient, EnvName): ]) if response["Environments"][0]["Status"] == "Ready": break - time.sleep(5) + time.sleep(60) if env_count == 3: print("Waiting the env be ready.") env_count = 0 else: env_count += 1 - if env_count_for_credentials == 12: - print("Renewing security token...") - boto_client = aws_authentication.get_boto_client() - beanstalkclient = boto_client.client( - "elasticbeanstalk", region_name="us-east-1") - env_count_for_credentials = 0 - else: - env_count_for_credentials += 1 return response, beanstalkclient diff --git a/src/terminate_green_env.py b/src/terminate_green_env.py index a1930b1..45e91b6 100644 --- a/src/terminate_green_env.py +++ b/src/terminate_green_env.py @@ -56,6 +56,5 @@ def delete_green_environment(beanstalkclient, EnvName): time.sleep(10) if (GreenEnvStatus == 'Ready'): response = beanstalkclient.terminate_environment(EnvironmentName=EnvName) - print(response) print("Successfully Terminated Green Environment") return \ No newline at end of file