Beispiel #1
0
def test_environment_definition_equality():
    env_def_1 = EnvironmentDefinition('{"packages": {"foo": "1.2.3"}}')
    env_def_2 = EnvironmentDefinition('{"packages": {"foo": "1.2.4"}}')
    env_def_3 = EnvironmentDefinition('{"packages": {"foo": "1.2.3"}}')

    assert env_def_1 == env_def_3
    assert env_def_2 != env_def_3
    assert env_def_2 == env_def_2
Beispiel #2
0
def test_env_service_multiple_env_defs(env_service: EnvironmentService):
    for n in [4, 5, 6]:
        _ = EnvironmentDefinition('{"packages": {"foo": "1.2.%s"}}' % n)
        env_service.save_env_def(_)

    env_id = EnvironmentDefinition('{"packages": {"foo": "1.2.5"}}').id

    env_def = env_service.get_env_def(env_id)

    assert env_def.id == env_id
    assert env_def.packages == {"foo": "1.2.5"}
Beispiel #3
0
def test_create_invalid_environment_definition_blank_packages():
    with pytest.raises(
            ValueError,
            match="Your packages cannot be blank/empty in your "
            "environment definition.",
    ):
        EnvironmentDefinition('{"packages": {}}')
Beispiel #4
0
def test_create_invalid_environment_definition_missing_packages():
    with pytest.raises(
            ValueError,
            match='You must specify "packages" in your '
            "environment definition.",
    ):
        EnvironmentDefinition("{}")
Beispiel #5
0
def test_create_simple_environment_definition():
    env_def = EnvironmentDefinition(TEST_INPUT)
    assert env_def.id == "92f9752"
    assert (env_def.long_id ==
            "92f97528f268a88eb83866586f9281634d4b93b2c98503326ba99363f55c0e0c")
    assert env_def.packages == {"foo": "1.2.3"}
    assert env_def.channels == []
Beispiel #6
0
def test_get_env_def_for_app_env(mock_responses, client):
    mock_responses.add(
        responses.GET,
        "http://baseurl/appenvs?app=myapp&env=myenv",
        json={
            "app": "myapp",
            "env": "myenv",
            "env_def": {
                "env_id": "abcd1234",
                "packages": {
                    "pkg-a": "1.0",
                    "pkg-b": ">2.0,<3",
                },
                "channels": [],
            },
        },
        status=200,
    )

    app_env = client.get_env_def_for_app_env("myapp", "myenv")

    expected_app_env = ApplicationEnvironment(
        app=Application("myapp"),
        env="myenv",
        env_def=EnvironmentDefinition.from_dict(
            {"packages": {
                "pkg-a": "1.0",
                "pkg-b": ">2.0,<3"
            }}),
    )
    assert expected_app_env == app_env
Beispiel #7
0
 def _env_def_from_orm_to_business_model(
         cls, env_def_orm_obj: EnvDef) -> EnvironmentDefinition:
     env_def = EnvironmentDefinition.from_dict(env_def_orm_obj.env_def)
     if env_def.id != env_def_orm_obj.id:  # sanity check
         raise EnvironmentPersistenceError(
             f"IDs do not match: {env_def.id = } != {env_def_orm_obj.id = }"
         )
     return env_def
Beispiel #8
0
def test_associate_application_environment(env_service: EnvironmentService):
    env_def = EnvironmentDefinition('{"packages": {"foo": "9.8.7"}}')
    env_service.save_env_def(env_def)

    app = Application(name="my-app")

    app_env = ApplicationEnvironment(app=app, env="prod", env_def=env_def)

    env_service.save_app_env(app_env)
Beispiel #9
0
def test_env_service_roundtrip_persistence_for_env_def(
        env_service: EnvironmentService):
    raw = '{"packages": {"foo": "1.2.3"}}'
    env_def = EnvironmentDefinition(raw)

    env_service.save_env_def(env_def)

    env_def_returned = env_service.get_env_def(env_def.id)
    assert env_def_returned == env_def
Beispiel #10
0
def test_deploy_env_with_command_first_time():
    deployer = MockDeployer()
    deployer.env_exists = Mock(return_value=False)
    deployer.create_env = Mock()
    deployer.execute = Mock()
    env_def = EnvironmentDefinition(TEST_INPUT)
    deployer.deploy(env_def, 'command.exe')
    deployer.env_exists.assert_called_once_with(env_def.long_id)
    deployer.create_env.assert_called_once_with(env_def)
    deployer.execute.assert_called_once_with(env_def.long_id, 'command.exe')
Beispiel #11
0
def test_create_env_second_time():
    deployer = MockDeployer()
    deployer.env_exists = Mock(return_value=True)
    deployer.create_env = Mock()
    deployer.execute = Mock()
    env_def = EnvironmentDefinition(TEST_INPUT)
    deployer.deploy(env_def)
    deployer.env_exists.assert_called_once_with(env_def.long_id)
    deployer.create_env.assert_not_called()
    deployer.execute.assert_not_called()
Beispiel #12
0
async def create_env_def(env_def: EnvDef):
    # TODO: do we need here 2 models, one pure Python and one Pydantic? I don't think
    #  so... ?
    env_def_dict = {"packages": env_def.packages}
    if env_def.channels:
        env_def_dict["channels"] = env_def.channels

    env_def = EnvironmentDefinition.from_dict(env_def_dict)
    store.save_env_def(env_def)
    return {"env_id": env_def.id}
Beispiel #13
0
def test_create_env_first_time_id():
    deployer = MockDeployer(use_long_id=False)
    deployer.env_exists = Mock(return_value=False)
    deployer.create_env = Mock()
    deployer.execute = Mock()
    env_def = EnvironmentDefinition(TEST_INPUT)
    deployer.deploy(env_def)
    deployer.env_exists.assert_called_once_with(env_def.id)
    deployer.create_env.assert_called_once_with(env_def)
    deployer.execute.assert_not_called()
Beispiel #14
0
def test_application_environment_roundtrip(env_service: EnvironmentService):
    env_def = EnvironmentDefinition('{"packages": {"foo": "9.8.7"}}')
    env_service.save_env_def(env_def)

    app = Application(name="my-app")

    app_env = ApplicationEnvironment(app=app, env="prod", env_def=env_def)

    env_service.save_app_env(app_env)

    app_env_returned = env_service.get_app_env("my-app", "prod")

    assert app_env_returned.env_def.packages == {"foo": "9.8.7"}
Beispiel #15
0
def test_deployer_can_run_something():
    deployer = InMemoryDeploymentBackend()

    assert [] == deployer.envs
    assert [] == deployer.executed_commands

    env_def = EnvironmentDefinition('{"packages": {"foo": "1.2.3"}}')
    cmd_args = ["command-main", "arg1", "--option=foo"]
    deployer.run(env_def, cmd_args)

    assert [("92f9752", env_def)] == deployer.envs
    assert [("92f9752", cmd_args)] == deployer.executed_commands

    # If you run something on the environment for the second time
    # it doesn't create a new environment
    cmd_args_2 = ["other-command"]
    deployer.run(env_def, cmd_args_2)

    assert [("92f9752", env_def)] == deployer.envs
    assert [
        ("92f9752", cmd_args),
        ("92f9752", cmd_args_2),
    ] == deployer.executed_commands

    # Now we want to use a brand new environment
    env_def_2 = EnvironmentDefinition('{"packages": {"bar": "4.5.6"}}')
    cmd_args_3 = ["foobar", "123"]
    deployer.run(env_def_2, cmd_args_3)

    # We will check that environment was created - new deployment!
    assert [("92f9752", env_def), ("95e885b", env_def_2)] == deployer.envs
    expected_runs = [
        ("92f9752", cmd_args),
        ("92f9752", cmd_args_2),
        ("95e885b", cmd_args_3),
    ]
    assert expected_runs == deployer.executed_commands
Beispiel #16
0
def test_run(env_service: EnvironmentService):
    # First we create an environment definition
    env_def = EnvironmentDefinition('{"packages": {"foo": "9.8.7"}}')
    env_service.save_env_def(env_def)

    # Then we associate it to an (application, environment)
    app = Application(name="some_app")
    app_env = ApplicationEnvironment(app=app, env="uat", env_def=env_def)
    env_service.save_app_env(app_env)

    # Finally we ask the service to run something on that (app, env)
    env_service.run("some_app", "uat", ["hello", "world"])

    # We can then run the asserts against the deployment backend inside our service
    assert [("b262deb", env_def)] == env_service.deployment_backend.envs
    assert [("b262deb", ["hello", "world"])
            ] == env_service.deployment_backend.executed_commands
def test_conda_deployment_backend_run_command(mocker, in_memory_store):
    backend = CondaDeploymentBackend()

    service = EnvironmentService(store=in_memory_store,
                                 deployment_backend=backend)

    env_def = EnvironmentDefinition(
        '{"packages": {"foo": "1.2.3", "bar": ">=4.5.1,<5.0"}}')
    service.save_env_def(env_def)

    app = Application(name="my-app")
    app_env = ApplicationEnvironment(app=app, env="prod", env_def=env_def)
    service.save_app_env(app_env)

    mock_subprocess_run = mocker.patch(
        "ee.backends.conda_deployment_backend.subprocess.run", autospec=True)
    mock_subprocess_Popen = mocker.patch(
        "ee.backends.conda_deployment_backend.subprocess.Popen", autospec=True)

    service.run("my-app", "prod", ["foo", "bar"])

    # This should trigger 3 calls to subprocess.run
    # 1) for checking if the environment already exists
    # 2) for creating the environment the first time
    # 3) for running the command
    assert mock_subprocess_run.call_args_list == [
        mocker.call(["conda", "list", "-n", "412b992"],
                    shell=SHELL,
                    capture_output=True),
        mocker.call(
            'conda create -n 412b992 -y "foo=1.2.3" "bar>=4.5.1,<5.0"'.split(),
            shell=SHELL,
            capture_output=True,
        ),
    ]

    mock_subprocess_Popen.assert_has_calls([
        mocker.call(
            "conda run --no-capture-output -n base "
            "conda run --no-capture-output -n 412b992 foo bar".split(),
            shell=SHELL,
        ),
    ])
Beispiel #18
0
    def get_env_def_for_app_env(self, app: str,
                                env: str) -> ApplicationEnvironment:
        """Send a request to fetch the env def for the pair (app, env)."""
        # TODO: should return only the EnvironmentDefinition instead?
        url = f"{self.base_url}/appenvs?app={app}&env={env}"
        resp = self.client.get(url, timeout=EE_REQUEST_TIMEOUT)
        resp.raise_for_status()

        data = resp.json()

        env_def_dict = {"packages": data["env_def"]["packages"]}
        if data["env_def"].get("channels"):
            env_def_dict["channels"] = data["env_def"]["channels"]

        app_env = ApplicationEnvironment(
            app=Application(data["app"]),
            env=data["env"],
            env_def=EnvironmentDefinition.from_dict(env_def_dict),
        )
        return app_env
Beispiel #19
0
def new(filename: Path):
    """Add a new Env Spec based on the given filename.

    It must be a JSON file defining "packages".
    Optionally it may define "channels".

    E.g.:

    # my_env.json
    {
        "packages": {
            "pandas": ">=1.2.1,<1.3",
            "python": "3.8"
        }
    }

    $ ee new my_env.json
    """
    temp = EnvironmentDefinition(filename.open().read())
    env_def = EnvDef(packages=temp.packages, channels=temp.channels)
    typer.echo(f"Read EnvironmentDefinition from file: {filename}")
    env_id = client.new_env_def(env_def)
    typer.secho(f"New Environment defined. ID: {env_id}", fg="yellow")
Beispiel #20
0
def test_create_environment_with_channels_specified():
    env_def = EnvironmentDefinition(INPUT_WITH_CHANNELS)
    assert env_def.channels == ["chan1", "chan2"]
    assert env_def.id == "22594ba"
Beispiel #21
0
def simple_env_def():
    env_def_dict = {"packages": {"pandas": ">=1.1,<1.2"}}
    raw = json.dumps(env_def_dict)
    env_def = EnvironmentDefinition(raw)
    return env_def