def main(artifact_dir: str, apps: list, bdd_http_proto: str, bdd_url: str, bdd_api_endpoint: str, bdd_version: int,
         cicd_http_proto: str, cicd_url: str, cicd_api_endpoint: str, cicd_version: int):
    # use the script variables
    global bdd_test, bdd_modules, test_names, test_list, test_urls

    probe_endpoint = build_probe_endpoint(
        cicd_http_proto, cicd_url, cicd_api_endpoint, cicd_version)
    bdd_endpoint = build_bdd_endpoint(
        bdd_http_proto, bdd_url, bdd_api_endpoint, bdd_version)

    # Query the CICD probe
    for app in apps:
        # Removes whitespaces in the beginning and end of the string
        app = app.strip()
        response = scan_bdd_test_endpoint(artifact_dir, probe_endpoint, app)
        if len(response) == 0:
            continue  # It has no test suites, continue the loop
        for test_endpoint in response:
            # Get the BDD test endpoints information
            bdd_test += [{"EspaceName": test_endpoint["BDDTestEndpointsInfo"]["EspaceName"],
                          "WebFlows": test_endpoint["BDDTestEndpointsInfo"]["WebFlows"]}]
            bdd_modules += len(test_endpoint["BDDTestEndpointsInfo"]
                               ["WebFlows"])
    print("{} BDD module(s) found.".format(bdd_modules), flush=True)

    # Get the tests to run (just for presentation)
    for bdd in bdd_test:  # For each BDD test
        if "WebFlows" in bdd:  # Sanity check to see if there are actual webflows in tests
            for webflow in bdd["WebFlows"]:  # For each webflow
                if "WebScreens" in webflow:  # Sanity check to see if there are actual webscreens in tests
                    test_list += webflow["WebScreens"]
    print("{} BDD endpoint(s) scanned successfully.".format(len(test_list)), flush=True)

    # Get the names of the tests to run (just for presentation)
    for test in test_list:
        test_names.append(test["Name"])
    print("Tests to run:{}".format(test_names), flush=True)

    # For each test, generate the URL to query the BDD framework, to be used in the test class
    for bdd in bdd_test:  # For each BDD test
        if "WebFlows" in bdd:  # Sanity check to see if there are actual webflows in tests
            for webflow in bdd["WebFlows"]:  # For each webflow
                if "WebScreens" in webflow:  # Sanity check to see if there are actual webscreens in tests
                    for webscreen in webflow["WebScreens"]:  # for each webscreen
                        test_endpoint = build_bdd_test_endpoint(
                            bdd_endpoint, bdd["EspaceName"], webscreen["Name"])
                        test_urls.append(
                            {"TestSuite": bdd["EspaceName"], "Name": webscreen["Name"], "URL": test_endpoint})

    # Save the test results in a file for later processing
    filename = os.path.join(BDD_FRAMEWORK_FOLDER,
                            BDD_FRAMEWORK_TEST_ENDPOINTS_FILE)
    store_data(artifact_dir, filename, test_urls)
def get_environments(artifact_dir: str, endpoint: str, auth_token: str):
    # Sends the request
    response = send_get_request(endpoint, auth_token, ENVIRONMENTS_ENDPOINT,
                                None)
    status_code = int(response["http_status"])
    if status_code == ENVIRONMENTS_SUCCESS_CODE:
        # Stores the result
        store_data(artifact_dir, ENVIRONMENTS_FILE, response["response"])
        return response["response"]
    elif status_code == ENVIRONMENTS_NOT_FOUND_CODE:
        raise EnvironmentNotFoundError(
            "No environments found. Details {}".format(response["response"]))
    elif status_code == ENVIRONMENTS_FAILED_CODE:
        raise ServerError(
            "Failed to list the environments. Details: {}".format(
                response["response"]))
    else:
        raise NotImplementedError(
            "There was an error. Response from server: {}".format(response))
def get_environment_app_version(artifact_dir: str, endpoint: str,
                                auth_token: str, extra_data: bool, **kwargs):
    # Tuple with (AppName, AppKey): app_tuple[0] = AppName; app_tuple[1] = AppKey
    app_tuple = _get_application_info(artifact_dir, endpoint, auth_token,
                                      **kwargs)
    # Tuple with (EnvName, EnvKey): env_tuple[0] = EnvName; env_tuple[1] = EnvKey
    env_tuple = _get_environment_info(artifact_dir, endpoint, auth_token,
                                      **kwargs)
    # Builds the query and arguments for the call to the API
    query = "{}/{}/{}/{}".format(ENVIRONMENTS_ENDPOINT, env_tuple[1],
                                 ENVIRONMENT_APPLICATIONS_ENDPOINT,
                                 app_tuple[1])
    arguments = {"IncludeEnvStatus": extra_data, "IncludeModules": extra_data}
    # Sends the request
    response = send_get_request(endpoint, auth_token, query, arguments)
    status_code = int(response["http_status"])
    if status_code == ENVIRONMENT_APP_SUCCESS_CODE:
        # Stores the result
        filename = "{}.{}{}".format(env_tuple[0], app_tuple[0],
                                    ENVIRONMENT_APPLICATION_FILE)
        filename = os.path.join(ENVIRONMENT_FOLDER, filename)
        store_data(artifact_dir, filename, response["response"])
        return response["response"]
    elif status_code == ENVIRONMENT_APP_NOT_STATUS_CODE:
        raise InvalidParametersError(
            "Error in the request parameters. Params: {}. Details {}".format(
                arguments, response["response"]))
    elif status_code == ENVIRONMENT_APP_NO_PERMISSION_CODE:
        raise NotEnoughPermissionsError(
            "You don't have enough permissions to see the application in that environment. Details: {}"
            .format(response["response"]))
    elif status_code == ENVIRONMENT_APP_NOT_FOUND:
        raise AppDoesNotExistError(
            "The application does not exist in the environment. Details: {}".
            format(response["response"]))
    elif status_code == ENVIRONMENT_APP_FAILED_CODE:
        raise ServerError(
            "Failed to access the running version of an application. Details: {}"
            .format(response["response"]))
    else:
        raise NotImplementedError(
            "There was an error. Response from server: {}".format(response))
Ejemplo n.º 4
0
def generate_regular_deployment(artifact_dir: str, lt_endpoint: str,
                                lt_token: str, src_env_key: str,
                                app_list: list):
    app_data_list = [
    ]  # will contain the applications to deploy details from LT
    deployment_manifest = [
    ]  # will store the deployment plan, that may be used in later stages of the pipeline

    # Creates a list with the details for the apps you want to deploy
    for app_name in app_list:
        # Removes whitespaces in the beginning and end of the string
        app_name = app_name.strip()

        # Get the app running version on the source environment. It will only retrieve tagged applications
        deployed = get_running_app_version(artifact_dir,
                                           lt_endpoint,
                                           lt_token,
                                           src_env_key,
                                           app_name=app_name)

        # Add it to the app data list
        app_data_list.append({
            'Name': app_name,
            'Key': deployed["ApplicationKey"],
            'Version': deployed["Version"],
            'VersionKey': deployed["VersionKey"]
        })

        # Add app to manifest, since this is a regular deployment
        deployment_manifest.append(deployed)

    # Store the manifest to be used in other stages of the pipeline
    filename = "{}/{}".format(DEPLOYMENT_FOLDER, DEPLOYMENT_MANIFEST_FILE)
    store_data(ARTIFACT_FOLDER, filename, deployment_manifest)

    return app_data_list
Ejemplo n.º 5
0
def main(artifact_dir: str, lt_http_proto: str, lt_url: str,
         lt_api_endpoint: str, lt_api_version: int, lt_token: str,
         source_env: str, dest_env: str, apps: list, dep_manifest: list,
         dep_note: str):

    app_data_list = [
    ]  # will contain the applications to deploy details from LT
    to_deploy_app_keys = []  # will contain the app keys for the apps tagged

    # Builds the LifeTime endpoint
    lt_endpoint = build_lt_endpoint(lt_http_proto, lt_url, lt_api_endpoint,
                                    lt_api_version)

    # Gets the environment key for the source environment
    src_env_key = get_environment_key(artifact_dir, lt_endpoint, lt_token,
                                      source_env)
    # Gets the environment key for the destination environment
    dest_env_key = get_environment_key(artifact_dir, lt_endpoint, lt_token,
                                       dest_env)

    # If the manifest file is being used, the app versions MUST come from that file
    # Or else you might not be deploying the same app versions that were deployed in
    # previous pipeline steps
    if dep_manifest:
        app_data_list = generate_deployment_based_on_manifest(
            artifact_dir, lt_endpoint, lt_token, src_env_key, source_env, apps,
            dep_manifest)
    else:
        app_data_list = generate_regular_deployment(artifact_dir, lt_endpoint,
                                                    lt_token, src_env_key,
                                                    apps)

    to_deploy_app_keys = check_if_can_deploy(artifact_dir, lt_endpoint,
                                             lt_api_version, lt_token,
                                             dest_env_key, dest_env,
                                             app_data_list)

    # Check if there are apps to be deployed
    if len(to_deploy_app_keys) == 0:
        print(
            "Deployment skipped because {} environment already has the target application deployed with the same tags."
            .format(dest_env),
            flush=True)
        sys.exit(0)

    # Write the names and keys of the application versions to be deployed
    to_deploy_app_names = []
    to_deploy_app_info = []
    for app in app_data_list:
        for deploying_apps in to_deploy_app_keys:
            if lt_api_version == 1:  # LT for OS version < 11
                if deploying_apps == app["VersionKey"]:
                    to_deploy_app_names.append(app["Name"])
                    to_deploy_app_info.append(app)
            elif lt_api_version == 2:  # LT for OS v11
                if deploying_apps["ApplicationVersionKey"] == app[
                        "VersionKey"]:
                    to_deploy_app_names.append(app["Name"])
                    to_deploy_app_info.append(app)
            else:
                raise NotImplementedError(
                    "Please make sure the API version is compatible with the module."
                )
    print(
        "Creating deployment plan from {} to {} including applications: {} ({})."
        .format(source_env, dest_env, to_deploy_app_names, to_deploy_app_info),
        flush=True)

    wait_counter = 0
    deployments = get_running_deployment(artifact_dir, lt_endpoint, lt_token,
                                         dest_env_key)
    while len(deployments) > 0:
        if wait_counter >= QUEUE_TIMEOUT_IN_SECS:
            print(
                "Timeout occurred while waiting for LifeTime to be free, to create the new deployment plan.",
                flush=True)
            sys.exit(1)
        sleep(SLEEP_PERIOD_IN_SECS)
        wait_counter += SLEEP_PERIOD_IN_SECS
        print("Waiting for LifeTime to be free. Elapsed time: {} seconds...".
              format(wait_counter),
              flush=True)
        deployments = get_running_deployment(artifact_dir, lt_endpoint,
                                             lt_token, dest_env_key)

    # LT is free to deploy
    # Send the deployment plan and grab the key
    dep_plan_key = send_deployment(artifact_dir, lt_endpoint, lt_token,
                                   lt_api_version, to_deploy_app_keys,
                                   dep_note, source_env, dest_env)
    print("Deployment plan {} created successfully.".format(dep_plan_key),
          flush=True)

    # Check if created deployment plan has conflicts
    dep_details = get_deployment_info(artifact_dir, lt_endpoint, lt_token,
                                      dep_plan_key)
    if len(dep_details["ApplicationConflicts"]) > 0:
        store_data(artifact_dir, CONFLICTS_FILE,
                   dep_details["ApplicationConflicts"])
        print(
            "Deployment plan {} has conflicts and will be aborted. Check {} artifact for more details."
            .format(dep_plan_key, CONFLICTS_FILE),
            flush=True)
        # Abort previously created deployment plan to target environment
        delete_deployment(lt_endpoint, lt_token, dep_plan_key)
        print("Deployment plan {} was deleted successfully.".format(
            dep_plan_key),
              flush=True)
        sys.exit(1)

    # Check if outdated consumer applications (outside of deployment plan) should be redeployed and start the deployment plan execution
    if lt_api_version == 1:  # LT for OS version < 11
        start_deployment(lt_endpoint, lt_token, dep_plan_key)
    elif lt_api_version == 2:  # LT for OS v11
        start_deployment(lt_endpoint,
                         lt_token,
                         dep_plan_key,
                         redeploy_outdated=REDEPLOY_OUTDATED_APPS)
    else:
        raise NotImplementedError(
            "Please make sure the API version is compatible with the module.")
    print("Deployment plan {} started being executed.".format(dep_plan_key),
          flush=True)

    # Sleep thread until deployment has finished
    wait_counter = 0
    while wait_counter < DEPLOYMENT_TIMEOUT_IN_SECS:
        # Check Deployment Plan status.
        dep_status = get_deployment_status(artifact_dir, lt_endpoint, lt_token,
                                           dep_plan_key)
        if dep_status["DeploymentStatus"] != DEPLOYMENT_RUNNING_STATUS:
            # Check deployment status is pending approval. Force it to continue (if 2-Step deployment is enabled)
            if dep_status["DeploymentStatus"] == DEPLOYMENT_WAITING_STATUS:
                continue_deployment(lt_endpoint, lt_token, dep_plan_key)
                print("Deployment plan {} resumed execution.".format(
                    dep_plan_key),
                      flush=True)
            elif dep_status[
                    "DeploymentStatus"] in DEPLOYMENT_ERROR_STATUS_LIST:
                print("Deployment plan finished with status {}.".format(
                    dep_status["DeploymentStatus"]),
                      flush=True)
                store_data(artifact_dir, DEPLOY_ERROR_FILE, dep_status)
                sys.exit(1)
            else:
                # If it reaches here, it means the deployment was successful
                print("Deployment plan finished with status {}.".format(
                    dep_status["DeploymentStatus"]),
                      flush=True)
                # Exit the script to continue with the pipeline
                sys.exit(0)
        # Deployment status is still running. Go back to sleep.
        sleep(SLEEP_PERIOD_IN_SECS)
        wait_counter += SLEEP_PERIOD_IN_SECS
        print("{} secs have passed since the deployment started...".format(
            wait_counter),
              flush=True)

    # Deployment timeout reached. Exit script with error
    print(
        "Timeout occurred while deployment plan is still in {} status.".format(
            DEPLOYMENT_RUNNING_STATUS),
        flush=True)
    sys.exit(1)