コード例 #1
0
def test_git(capfd: Capture, faker: Faker) -> None:

    create_project(
        capfd=capfd,
        name=random_project_name(faker),
    )
    init_project(capfd)

    assert git.get_repo("does/not/exist") is None
    do_repo = git.get_repo("submodules/do")
    assert do_repo is not None
    assert git.get_active_branch(None) is None
    assert git.get_active_branch(do_repo) == __version__
    assert not git.switch_branch(None, branch_name="0.7.3")
    # Same branch => no change => return True
    assert git.switch_branch(do_repo, branch_name=__version__)
    assert not git.switch_branch(do_repo, branch_name="XYZ")

    assert git.switch_branch(do_repo, branch_name="0.7.3")
    assert git.get_active_branch(do_repo) == "0.7.3"
    assert git.switch_branch(do_repo, branch_name=__version__)
    assert git.get_active_branch(do_repo) == __version__

    assert git.get_origin(None) is None

    r = git.get_repo(".")
    assert git.get_origin(r) == "https://your_remote_git/your_project.git"

    # Create an invalid repo (i.e. without any remote)
    r = git.init("../justatest")
    assert git.get_origin(r) is None
コード例 #2
0
def install_controller_from_folder(version: str) -> None:

    do_path = SUBMODULES_DIR.joinpath("do")
    try:
        Application.git_submodules()
    except SystemExit:

        log.info(
            """You asked to install rapydo {ver} in editable mode, but {p} is missing.

You can force the installation by disabling the editable mode:

rapydo install {ver} --no-editable

""",
            ver=version,
            p=do_path,
        )

        raise

    log.info(
        "You asked to install rapydo {}. It will be installed in editable mode",
        version,
    )

    do_repo = Application.gits.get("do")

    b = git.get_active_branch(do_repo)

    if b is None:
        log.error(
            "Unable to read local controller repository")  # pragma: no cover
    elif b == version:
        log.info("Controller repository already at {}", version)
    elif git.switch_branch(do_repo, version):
        log.info("Controller repository switched to {}", version)
    else:
        print_and_exit("Invalid version")

    Packages.install(do_path, editable=True)
    log.info("Controller version {} installed from local folder", version)
コード例 #3
0
def test_base(capfd: Capture) -> None:

    execute_outside(capfd, "check")

    create_project(
        capfd=capfd,
        name="third",
        auth="postgres",
        frontend="angular",
    )
    init_project(capfd)

    repo = git.get_repo("submodules/http-api")
    git.switch_branch(repo, "0.7.6")
    exec_command(
        capfd,
        "check -i main",
        f"http-api: wrong branch 0.7.6, expected {__version__}",
        f"You can fix it with {colors.RED}rapydo init{colors.RESET}",
    )
    init_project(capfd)

    with TemporaryRemovePath(DATA_DIR):
        exec_command(
            capfd,
            "check -i main --no-git --no-builds",
            "Folder not found: data",
            "Please note that this command only works from inside a rapydo-like repo",
            "Verify that you are in the right folder, now you are in: ",
        )

    with TemporaryRemovePath(Path("projects/third/builds")):
        exec_command(
            capfd,
            "check -i main --no-git --no-builds",
            "Project third is invalid: required folder not found projects/third/builds",
        )

    with TemporaryRemovePath(Path(".gitignore")):
        exec_command(
            capfd,
            "check -i main --no-git --no-builds",
            "Project third is invalid: required file not found .gitignore",
        )

    # Add a custom image to extend base backend image:
    with open("projects/third/confs/commons.yml", "a") as f:
        f.write(
            """
services:
  backend:
    build: ${PROJECT_DIR}/builds/backend
    image: third/backend:${RAPYDO_VERSION}

    """
        )

    os.makedirs("projects/third/builds/backend")
    with open("projects/third/builds/backend/Dockerfile", "w+") as f:
        f.write(
            f"""
FROM rapydo/backend:{__version__}
RUN mkdir xyz
"""
        )

    # Skipping main because we are on a fake git repository
    exec_command(
        capfd,
        "check -i main",
        f" image, execute {colors.RED}rapydo pull",
        f" image, execute {colors.RED}rapydo build",
        f"Compose is installed with version {COMPOSE_VERSION}",
        f"Buildx is installed with version {BUILDX_VERSION}",
        "Checks completed",
    )

    exec_command(
        capfd,
        "--stack invalid check -i main",
        "Failed to read projects/third/confs/invalid.yml: File does not exist",
    )

    os.mkdir("submodules/rapydo-confs")
    exec_command(
        capfd,
        "check -i main --no-git --no-builds",
        "Project third contains an obsolete file or folder: submodules/rapydo-confs",
    )

    shutil.rmtree("submodules/rapydo-confs")

    # Test selection with two projects
    create_project(
        capfd=capfd,
        name="justanother",
        auth="postgres",
        frontend="no",
    )

    os.remove(".projectrc")

    exec_command(
        capfd,
        "check -i main --no-git --no-builds",
        "Multiple projects found, please use --project to specify one of the following",
    )

    # Test with zero projects
    with TemporaryRemovePath(Path("projects")):
        os.mkdir("projects")
        # in this case SystemExit is raised in the command init...
        with pytest.raises(SystemExit):
            exec_command(
                capfd,
                "check -i main --no-git --no-builds",
                "No project found (is projects folder empty?)",
            )
        shutil.rmtree("projects")

    exec_command(
        capfd,
        "-p third check -i main --no-git --no-builds",
        "Checks completed",
    )

    # Numbers are not allowed as first characters
    pname = "2invalidcharacter"
    os.makedirs(f"projects/{pname}")
    exec_command(
        capfd,
        f"-p {pname} check -i main --no-git --no-builds",
        "Wrong project name, found invalid characters: 2",
    )
    shutil.rmtree(f"projects/{pname}")

    invalid_characters = {
        "_": "_",
        "-": "-",
        "C": "C",
        # Invalid characters in output are ordered
        # Numbers are allowed if not leading
        "_C-2": "-C_",
    }
    # Check invalid and reserved project names
    for invalid_key, invalid_value in invalid_characters.items():
        pname = f"invalid{invalid_key}character"
        os.makedirs(f"projects/{pname}")
        exec_command(
            capfd,
            f"-p {pname} check -i main --no-git --no-builds",
            f"Wrong project name, found invalid characters: {invalid_value}",
        )
        shutil.rmtree(f"projects/{pname}")

    os.makedirs("projects/celery")
    exec_command(
        capfd,
        "-p celery check -i main --no-git --no-builds",
        "You selected a reserved name, invalid project name: celery",
    )
    shutil.rmtree("projects/celery")

    exec_command(
        capfd,
        "-p fourth check -i main --no-git --no-builds",
        "Wrong project fourth",
        "Select one of the following: ",
    )

    # Test init of data folders
    shutil.rmtree(LOGS_FOLDER)
    assert not LOGS_FOLDER.is_dir()
    # Let's restore .projectrc and data/logs
    init_project(capfd, "--project third")

    assert LOGS_FOLDER.is_dir()
    exec_command(
        capfd,
        "check -i main --no-git --no-builds",
        "Checks completed",
    )

    # Test dirty repo
    fin = open("submodules/do/new_file", "wt+")
    fin.write("xyz")
    fin.close()

    exec_command(
        capfd,
        "check -i main",
        "You have unstaged files on do",
        "Untracked files:",
        "submodules/do/new_file",
    )

    with open(".gitattributes", "a") as a_file:
        a_file.write("\n")
        a_file.write("# new line")

    exec_command(
        capfd,
        "check -i main",
        ".gitattributes changed, "
        f"please execute {colors.RED}rapydo upgrade --path .gitattributes",
    )

    exec_command(
        capfd,
        "--prod check -i main --no-git --no-builds",
        "The following variables are missing in your configuration",
        "You can fix this error by updating your .projectrc file",
    )

    # Default ALCHEMY_PASSWORD has as score of 2
    exec_command(
        capfd,
        "-e MIN_PASSWORD_SCORE=3 check -i main --no-git --no-builds",
        "The password used in ALCHEMY_PASSWORD is weak",
    )
    exec_command(
        capfd,
        "-e MIN_PASSWORD_SCORE=4 check -i main --no-git --no-builds",
        "The password used in ALCHEMY_PASSWORD is very weak",
    )
    exec_command(
        capfd,
        "-e MIN_PASSWORD_SCORE=4 -e AUTH_DEFAULT_PASSWORD=x check -i main --no-git --no-builds",
        "The password used in AUTH_DEFAULT_PASSWORD is extremely weak",
    )

    exec_command(
        capfd,
        "--prod init -f",
        "Created default .projectrc file",
        "Project initialized",
    )

    exec_command(
        capfd,
        "--prod check -i main --no-git --no-builds",
        "Checks completed",
    )

    if Configuration.swarm_mode:
        # Skipping main because we are on a fake git repository
        exec_command(
            capfd,
            "check -i main",
            "Swarm is correctly initialized",
            "Checks completed",
        )

        docker = Docker()
        docker.client.swarm.leave(force=True)

        exec_command(
            capfd,
            "check -i main",
            f"Swarm is not initialized, please execute {colors.RED}rapydo init",
        )
        exec_command(
            capfd,
            "init",
            "Swarm is now initialized",
            "Project initialized",
        )
        exec_command(
            capfd,
            "check -i main",
            "Swarm is correctly initialized",
            "Checks completed",
        )

        check = "check -i main --no-git --no-builds"

        exec_command(
            capfd,
            f"-e ASSIGNED_MEMORY_BACKEND=50G {check}",
            "Your deployment requires 50GB of RAM but your nodes only have",
            # The error does not halt the checks execution
            "Checks completed",
        )

        exec_command(
            capfd,
            f"-e ASSIGNED_CPU_BACKEND=50.0 {check}",
            "Your deployment requires ",
            " cpus but your nodes only have ",
            # The error does not halt the checks execution
            "Checks completed",
        )

        exec_command(
            capfd,
            f"-e DEFAULT_SCALE_BACKEND=55 -e ASSIGNED_MEMORY_BACKEND=1G {check}",
            "Your deployment requires 55GB of RAM but your nodes only have",
            # The error does not halt the checks execution
            "Checks completed",
        )

        exec_command(
            capfd,
            f"-e DEFAULT_SCALE_BACKEND=50 -e ASSIGNED_CPU_BACKEND=1.0 {check}",
            "Your deployment requires ",
            " cpus but your nodes only have ",
            # The error does not halt the checks execution
            "Checks completed",
        )
コード例 #4
0
def test_init(capfd: Capture, faker: Faker) -> None:

    execute_outside(capfd, "init")
    create_project(
        capfd=capfd,
        name=random_project_name(faker),
        auth="postgres",
        frontend="no",
    )

    exec_command(
        capfd,
        "check -i main",
        "Repo https://github.com/rapydo/http-api.git missing as submodules/http-api.",
        "You should init your project",
    )

    if Configuration.swarm_mode:
        exec_command(
            capfd,
            "-e HEALTHCHECK_INTERVAL=1s -e SWARM_MANAGER_ADDRESS=127.0.0.1 init",
            "docker compose is installed",
            "Initializing Swarm with manager IP 127.0.0.1",
            "Swarm is now initialized",
            "Project initialized",
        )

        docker = Docker()
        docker.client.swarm.leave(force=True)
        local_ip = system.get_local_ip(production=False)
        exec_command(
            capfd,
            "-e HEALTHCHECK_INTERVAL=1s -e SWARM_MANAGER_ADDRESS= init",
            "docker compose is installed",
            "Swarm is now initialized",
            f"Initializing Swarm with manager IP {local_ip}",
            "Project initialized",
        )

        exec_command(
            capfd,
            "init",
            "Swarm is already initialized",
            "Project initialized",
        )

    else:
        init_project(capfd)

    repo = git.get_repo("submodules/http-api")
    git.switch_branch(repo, "0.7.6")

    exec_command(
        capfd,
        "init",
        f"Switched http-api branch from 0.7.6 to {__version__}",
        f"build-templates already set on branch {__version__}",
        f"do already set on branch {__version__}",
    )

    os.rename("submodules", "submodules.bak")
    os.mkdir("submodules")

    # This is to re-fill the submodules folder,
    # these folder will be removed by the next init
    exec_command(capfd, "init", "Project initialized")

    modules_path = Path("submodules.bak").resolve()

    with TemporaryRemovePath(Path("submodules.bak/do")):
        exec_command(
            capfd,
            f"init --submodules-path {modules_path}",
            "Submodule do not found in ",
        )
    exec_command(
        capfd,
        f"init --submodules-path {modules_path}",
        "Path submodules/http-api already exists, removing",
        "Project initialized",
    )

    assert os.path.islink("submodules/do")
    assert not os.path.islink("submodules.bak/do")

    # Init again, this time in submodules there are links...
    # and will be removed as well as the folders
    exec_command(
        capfd,
        f"init --submodules-path {modules_path}",
        "Path submodules/http-api already exists, removing",
        "Project initialized",
    )

    exec_command(
        capfd,
        "init --submodules-path invalid/path",
        "Local path not found: invalid/path",
    )

    exec_command(
        capfd,
        "--prod init -f",
        "Created default .projectrc file",
        "Project initialized",
    )

    exec_command(
        capfd,
        "--prod -e MYVAR=MYVAL init -f",
        "Created default .projectrc file",
        "Project initialized",
    )

    with open(".projectrc") as projectrc:
        lines = [line.strip() for line in projectrc.readlines()]
        assert "MYVAR: MYVAL" in lines
コード例 #5
0
def test_install(capfd: Capture, faker: Faker) -> None:

    execute_outside(capfd, "install")

    project = random_project_name(faker)
    create_project(
        capfd=capfd,
        name=project,
        auth="postgres",
        frontend="no",
    )
    init_project(capfd)

    # Initially the controller is installed from pip
    exec_command(
        capfd,
        "update -i main",
        "Controller not updated because it is installed outside this project",
        "Installation path is ",
        ", the current folder is ",
        "All updated",
    )

    with TemporaryRemovePath(SUBMODULES_DIR.joinpath("do")):
        exec_command(
            capfd,
            "install",
            "missing as submodules/do. You should init your project",
        )

    exec_command(capfd, "install 100.0", "Invalid version")

    exec_command(capfd, "install docker", "Docker current version:",
                 "Docker installed version:")
    exec_command(capfd, "install compose", "Docker compose is installed")
    exec_command(
        capfd,
        "install buildx",
        "Docker buildx current version:",
        "Docker buildx installed version:",
    )

    exec_command(capfd, "install auto")

    r = git.get_repo("submodules/do")
    git.switch_branch(r, "0.7.6")

    exec_command(
        capfd,
        "install",
        f"Controller repository switched to {__version__}",
    )

    # Here the controller is installed in editable mode from the correct submodules
    # folder (this is exactly the default normal condition)
    exec_command(
        capfd,
        "update -i main",
        # Controller installed from {} and updated
        "Controller installed from ",
        " and updated",
        "All updated",
    )

    # Install the controller from a linked folder to verify that the post-update checks
    # are able to correctly resolve symlinks
    # ###########################################################
    # Copied from test_init_check_update.py from here...
    SUBMODULES_DIR.rename("submodules.bak")
    SUBMODULES_DIR.mkdir()

    # This is to re-fill the submodules folder,
    # these folder will be removed by the next init
    exec_command(capfd, "init", "Project initialized")

    modules_path = Path("submodules.bak").resolve()

    exec_command(
        capfd,
        f"init --submodules-path {modules_path}",
        "Path submodules/http-api already exists, removing",
        "Project initialized",
    )
    # ... to here
    # ###########################################################
    exec_command(
        capfd,
        "update -i main",
        # Controller installed from {} and updated
        "Controller installed from ",
        " and updated",
        "All updated",
    )

    # This test will change the required version
    pconf = f"projects/{project}/project_configuration.yaml"

    # Read and change the content
    fin = open(pconf)
    data = fin.read()
    data = data.replace(f'rapydo: "{__version__}"', 'rapydo: "0.7.6"')
    fin.close()
    # Write the new content
    fin = open(pconf, "wt")
    fin.write(data)
    fin.close()

    exec_command(
        capfd,
        "version",
        f"This project is not compatible with rapydo version {__version__}",
        "Please downgrade rapydo to version 0.7.6 or modify this project",
    )

    # Read and change the content
    fin = open(pconf)
    data = fin.read()
    data = data.replace('rapydo: "0.7.6"', 'rapydo: "99.99.99"')
    fin.close()
    # Write the new content
    fin = open(pconf, "wt")
    fin.write(data)
    fin.close()

    exec_command(
        capfd,
        "version",
        f"This project is not compatible with rapydo version {__version__}",
        "Please upgrade rapydo to version 99.99.99 or modify this project",
    )

    exec_command(capfd, "install --no-editable 0.8")

    exec_command(capfd, "install --no-editable")

    exec_command(capfd, "install")