Ejemplo n.º 1
0
def test_scaffold_environment():
    """Environment scaffold tests."""
    with using_temporary_directory() as tempdir:
        # Copy playground
        project_path = copy_sample("sample01", tempdir)

        # Scaffold new environment
        scaffold_environment(project_path, "toto")
        assert os.path.isfile(env_get_yaml_path(project_path, "toto"))
        content = Environment.load_from_project(project_path, "toto")
        assert len(content) == 0

        # Scaffold new environment with values
        scaffold_environment(project_path, "tata", {"POUET": 6})
        assert os.path.isfile(env_get_yaml_path(project_path, "tata"))
        content = Environment.load_from_project(project_path, "tata")
        assert len(content) == 1
        assert content["POUET"] == 6

        # Scaffold existing environment
        with mock_input("n"):
            scaffold_environment(project_path, "tata", {"POUET": 6})
        with mock_input("n"):
            scaffold_environment(project_path, "tata", {"POUET": 6})

        # Copy existing environment
        scaffold_environment_copy(project_path, "tata", "tutu")
        assert os.path.isfile(env_get_yaml_path(project_path, "tutu"))
        content = Environment.load_from_project(project_path, "tutu")
        assert len(content) == 1
        assert content["POUET"] == 6
Ejemplo n.º 2
0
def test_template():
    """Template test."""
    with using_temporary_directory() as tempdir:
        project_path = copy_sample("sample01", tempdir)
        project_config_root = os.path.join(project_path, ".docknv")
        session_file_path = os.path.join(project_config_root, ".docknv.yml")

        os.makedirs(project_config_root)
        with io_open(session_file_path, mode="w") as handle:
            handle.write(CONFIG_DATA)

        project = Project.load_from_path(project_path)
        config = project.database.get_configuration("config")

        # Missing template file
        with pytest.raises(MissingTemplate):
            renderer_render_template("toto.sh", config)

        # Creating file
        templates_path = os.path.join(project_path, "data", "files")
        with io_open(os.path.join(templates_path, "toto.sh"),
                     mode="w") as handle:
            handle.write("...")

        # Malformed template file
        with pytest.raises(MalformedTemplate):
            renderer_render_template("toto.sh", config)
Ejemplo n.º 3
0
def test_collection():
    """Collection test."""
    with using_temporary_directory() as tempdir:
        project_path = copy_sample("sample01", tempdir)

        # Load
        collection = EnvironmentCollection.load_from_project(project_path)
        assert len(collection) == 8

        # Show
        collection.show_environments()

        # Error get
        with pytest.raises(MissingEnvironment):
            collection.get_environment("toto")
        with pytest.raises(MissingEnvironment):
            collection.get_environment_path("toto")

        # Inheritance
        default_env = collection.get_environment("default")
        env = collection.create_inherited_environment("default", "default2")
        assert os.path.isfile(
            os.path.join(project_path, "envs", "default2.env.yml"))

        assert len(collection) == 9
        assert env.name == "default2"
        assert len(env) == len(default_env)

        # Inheritance errors
        with pytest.raises(MissingEnvironment):
            collection.create_inherited_environment("pouet", "pouet2")
        with pytest.raises(ExistingEnvironment):
            collection.create_inherited_environment("default", "default")
        with pytest.raises(ExistingEnvironment):
            collection.create_inherited_environment("inclusion", "default")
Ejemplo n.º 4
0
def test_scaffold_image():
    """Image scaffold tests."""
    with using_temporary_directory() as tempdir:
        # Copy playground
        project_path = copy_sample("sample01", tempdir)

        # Scaffold new image
        scaffold_image(project_path, "postgres", "postgres")
        assert image_check_dockerfile(project_path, "postgres")
        content = image_load_in_memory(project_path, "postgres")
        assert content == "FROM postgres:latest\n"

        # Overwrite
        with mock_input("y"):
            scaffold_image(project_path, "postgres", "postgres")
        with mock_input("n"):
            scaffold_image(project_path, "postgres", "postgres")

        # Scaffold image version
        scaffold_image(project_path, "pouet", "ici/pouet", "2.1.1")
        assert image_check_dockerfile(project_path, "pouet")
        content = image_load_in_memory(project_path, "pouet")
        assert content == "FROM ici/pouet:2.1.1\n"

        # Scaffold in empty folder
        empty_folder = os.path.join(tempdir, "toto")
        os.makedirs(empty_folder)
        scaffold_image(empty_folder, "pouet", "ici/pouet")
Ejemplo n.º 5
0
def test_commands():
    """Commands."""
    shell = Shell()

    with using_temporary_directory() as tempdir:
        project_path = copy_sample("sample02", tempdir)

        def run_shell(args=None):
            args = args or []
            shell.run(["--project", project_path, "--dry-run"] + args)

        with pytest.raises(SystemExit):
            run_shell(["custom"])

        with pytest.raises(SystemExit):
            run_shell(["custom", "notebook"])

        run_shell([
            "config",
            "create",
            "toto",
            "-e",
            "default",
            "-S",
            "ipython",
            "pouet",
            "-N",
            "net",
        ])

        run_shell(["custom", "notebook", "password"])
Ejemplo n.º 6
0
def test_lifecycle():
    """Lifecycle test."""
    with using_temporary_directory() as tempdir:
        project_path = copy_sample("sample01", tempdir)
        project_config_root = os.path.join(project_path, ".docknv")
        session_file_path = os.path.join(project_config_root, ".docknv.yml")

        os.makedirs(project_config_root)
        with io_open(session_file_path, mode="w") as handle:
            handle.write(CONFIG_DATA)

        project = Project.load_from_path(project_path)
        lifecycle = project.lifecycle

        # Should raise, no active configuration
        with pytest.raises(MissingActiveConfiguration):
            lifecycle.config.start(dry_run=True)

        # Active tests
        project.set_current_configuration("config")
        lifecycle.config.start(dry_run=True)
        lifecycle.config.stop(dry_run=True)
        lifecycle.config.restart(dry_run=True)
        lifecycle.config.restart(force=True, dry_run=True)

        # Manual tests
        lifecycle.config.start(["config", "config2"], dry_run=True)

        # Service tests
        lifecycle.service.start("portainer", dry_run=True)
        lifecycle.service.stop("portainer", dry_run=True)
        lifecycle.service.restart("portainer", dry_run=True)
        lifecycle.service.restart("portainer", force=True, dry_run=True)
        lifecycle.service.execute("portainer", ["toto"], dry_run=True)
        lifecycle.service.execute("portainer", ["toto", "tutu"], dry_run=True)
        lifecycle.service.shell("portainer", dry_run=True)
        lifecycle.service.shell("portainer", shell="/bin/sh", dry_run=True)
        lifecycle.service.logs("portainer", dry_run=True)
        lifecycle.service.attach("portainer", dry_run=True)
        lifecycle.service.build("portainer", dry_run=True)

        # Update config
        lifecycle.config.update(dry_run=True)
        lifecycle.config.update("config2", dry_run=True)
        lifecycle.config.update(restart=True, dry_run=True)
        lifecycle.config.build(dry_run=True)

        lifecycle.config.update(environment="default", dry_run=True)
        lifecycle.config.update(services=[], dry_run=True)
        lifecycle.config.update(volumes=[], dry_run=True)
        lifecycle.config.update(networks=[], dry_run=True)
        lifecycle.config.update(namespace="", dry_run=True)
        lifecycle.config.update(namespace="hello", dry_run=True)

        # Create config
        lifecycle.config.create(name="tutu", services=["portainer"])
        lifecycle.config.ps(dry_run=True)
Ejemplo n.º 7
0
def test_empty_database():
    """Empty db test."""
    with using_temporary_directory() as tempdir:
        project_path = copy_sample("sample01", tempdir)

        project = Project.load_from_path(project_path)
        database = project.database
        assert len(database) == 0

        database.show_configuration_list()
        database.save()
Ejemplo n.º 8
0
def test_create_path_tree():
    """Test create_path_tree function."""
    with using_temporary_directory() as tempdir:
        path_to_create_local = os.path.join(tempdir, "toto/tutu/titi")
        create_path_tree(path_to_create_local)

        assert os.path.isdir(os.path.join(tempdir, "toto"))

        assert os.path.isdir(os.path.join(tempdir, "toto", "tutu"))

        assert os.path.isdir(os.path.join(tempdir, "toto", "tutu", "titi"))
Ejemplo n.º 9
0
def test_scaffold_config():
    """Config scaffold tests."""
    with using_temporary_directory() as tempdir:
        # Copy playground
        project_path = copy_sample("sample01", tempdir)

        # Scaffold config
        scaffold_config(project_path)
        configfile = os.path.join(project_path, "config.yml")

        with io_open(configfile, mode="rt") as handle:
            content = handle.read()

        assert content == CONFIG_FILE_CONTENT
Ejemplo n.º 10
0
def test_project2():
    """Test project2."""
    with using_temporary_directory() as tempdir:
        project_path = copy_sample("sample02", tempdir)
        proj = Project.load_from_path(project_path)

        # Command config
        assert proj.get_command_parameters() == {
            "notebook": {
                "service": "ipython"
            }
        }
        assert proj.get_command_parameters("notebook") == {
            "service": "ipython"
        }
        assert proj.get_command_parameters("tutu") == {}
Ejemplo n.º 11
0
def test_environment():
    """Environment test."""
    with using_temporary_directory() as tempdir:
        project_path = copy_sample("sample01", tempdir)

        # Simple
        envdefault = Environment.load_from_project(project_path, "default")
        assert "PORTAINER_OUTPUT_PORT" in envdefault
        assert envdefault["PORTAINER_OUTPUT_PORT"] == 9000
        assert envdefault["TEST_VALUE"] == "default"
        assert len(envdefault) == 11

        # Error
        with pytest.raises(MissingEnvironment):
            Environment.load_from_project(project_path, "toto")

        # Import
        env = Environment.load_from_project(project_path, "inclusion")
        assert env["TEST_VALUE"] == "inclusion"
        assert env["TEST_ONE"] == 1
        assert env["TEST_ONE_2"] == "toto:1"

        # Neg values
        assert env["TEST_NEG_ONE"] == 0
        assert env["TEST_NEG_BOOL1"] is False
        assert env["TEST_NEG_BOOL2"] is True
        assert env["TEST_NEG_ONE_2"] == env["TEST_ONE_2"]

        # Inheritance
        env = Environment.load_from_project(project_path, "inclusion2")
        assert env["TEST_VALUE"] == "inclusion2"
        assert env["TEST_ONE"] == 2
        assert env["TEST_ONE_2"] == "toto:2"

        # Loop test
        env = Environment.load_from_project(project_path, "inclusion-loop")
        assert env["POUET"] == "loop"

        # Multiple loop test
        env = Environment.load_from_project(project_path, "inclusion-loop-mul")
        assert env["POUET"] == "pouet"

        # Show
        env.show()

        # Key-value export
        envdefault.export_as_key_values()
Ejemplo n.º 12
0
def test_old_database():
    """Test old database."""
    with using_temporary_directory() as tempdir:
        project_path = copy_sample("sample03", tempdir)

        # Values key should be present
        db_file = os.path.join(project_path, ".docknv", ".docknv.yml")
        with io_open(db_file) as handle:
            data = yaml_ordered_load(handle.read())
            assert "values" in data

        project = Project.load_from_path(project_path)
        assert len(project.database) == 2

        with io_open(db_file) as handle:
            data = yaml_ordered_load(handle.read())
            assert "values" not in data
Ejemplo n.º 13
0
def test_collection_error():
    """Collection test."""
    with using_temporary_directory() as tempdir:
        project_path = copy_sample("sample01", tempdir)

        # Remove envs
        shutil.rmtree(os.path.join(project_path, "envs"))

        # Load
        with pytest.raises(MalformedProject):
            EnvironmentCollection.load_from_project(project_path)

        # Create envs
        os.makedirs(os.path.join(project_path, "envs"))
        collection = EnvironmentCollection.load_from_project(project_path)

        # Show
        collection.show_environments()
Ejemplo n.º 14
0
def test_session_config():
    """Session config."""
    with using_temporary_directory() as tempdir:
        project_path = tempdir
        os.environ["DOCKNV_USER_PATH"] = project_path

        session = UserSession.load_from_path(user_get_username(), project_path)

        # No configuration set
        assert session.get_current_configuration() is None

        # Setting one configuration
        session.set_current_configuration("pouet")
        assert session.get_current_configuration() == "pouet"

        # Unset
        session.unset_current_configuration()
        assert session.get_current_configuration() is None
Ejemplo n.º 15
0
def test_session_paths():
    """Session paths."""
    with using_temporary_directory() as tempdir:
        project_path = tempdir
        os.environ["DOCKNV_USER_PATH"] = project_path

        session = UserSession.load_from_path(user_get_username(), project_path)
        paths = session.get_paths()

        assert paths.get_project_root() == os.path.join(
            project_path, ".docknv")
        assert paths.get_user_root() == os.path.join(project_path, ".docknv",
                                                     "test")
        assert paths.get_user_configuration_root("toto") == os.path.join(
            project_path, ".docknv", "test", "toto")
        assert paths.get_file_path("tutu") == os.path.join(
            project_path, ".docknv", "test", "tutu")
        assert paths.get_file_path("tutu", "toto") == os.path.join(
            project_path, ".docknv", "test", "toto", "tutu")
Ejemplo n.º 16
0
def test_project():
    """Test project."""
    with using_temporary_directory() as tempdir:
        project_path = copy_sample("sample01", tempdir)

        # Path validation
        assert Project.validate_path(project_path)
        assert not Project.validate_path(os.path.join(project_path, "toto"))

        # Project load
        proj = Project.load_from_path(project_path)
        repr(proj)
        assert len(proj.schemas) == 2

        # Ensure current config
        with pytest.raises(MissingActiveConfiguration):
            proj.ensure_current_configuration()

        # Project load error
        with pytest.raises(MissingProject):
            Project.load_from_path(os.path.join(project_path, "toto"))

        # Get current config
        assert proj.get_current_configuration() is None

        # Create config
        proj.lifecycle.config.create("toto")

        # Set current config
        proj.set_current_configuration("toto")
        assert proj.get_current_configuration() == "toto"

        # Unset
        proj.unset_current_configuration()
        assert proj.get_current_configuration() is None

        # Temporary set
        with proj.using_temporary_configuration("toto"):
            assert proj.get_current_configuration() == "toto"
        assert proj.get_current_configuration() is None

        # Command config
        assert proj.get_command_parameters() == {}
Ejemplo n.º 17
0
def test_scaffold_ignore():
    """Ignorefile scaffold tests."""
    with using_temporary_directory() as tempdir:
        # Copy playground
        project_path = copy_sample("sample01", tempdir)

        # Scaffold ignore
        scaffold_ignore(project_path)
        ignorefile = os.path.join(project_path, ".gitignore")
        with io_open(ignorefile, mode="rt") as handle:
            content = handle.read()
        assert content == IGNORE_FILE_CONTENT

        with mock_input("y"):
            scaffold_ignore(project_path)
        with mock_input("n"):
            scaffold_ignore(project_path)

        with pytest.raises(MissingProject):
            scaffold_ignore("/a/b/c/d")
Ejemplo n.º 18
0
def test_scaffold_project():
    """Project scaffold tests."""
    with using_temporary_directory() as tempdir:
        # New playground
        project_path = os.path.join(tempdir, "playground")

        with mock_input("y"):
            scaffold_project(project_path)
        with mock_input("n"):
            scaffold_project(project_path)

        assert os.path.isfile(os.path.join(project_path, ".gitignore"))
        assert os.path.isfile(os.path.join(project_path, "config.yml"))
        assert os.path.isdir(os.path.join(project_path, "envs"))
        assert os.path.isdir(os.path.join(project_path, "composefiles"))
        assert os.path.isdir(os.path.join(project_path, "images"))
        assert os.path.isdir(os.path.join(project_path, "data"))
        assert os.path.isdir(os.path.join(project_path, "data", "files"))

        assert os.path.isfile(env_get_yaml_path(project_path, "default"))
Ejemplo n.º 19
0
def test_compose():
    """Compose test."""
    with using_temporary_directory() as tempdir:
        project_path = copy_sample("sample01", tempdir)
        project_config_root = os.path.join(project_path, ".docknv")
        session_file_path = os.path.join(project_config_root, ".docknv.yml")

        os.makedirs(project_config_root)
        with io_open(session_file_path, mode="w") as handle:
            handle.write(CONFIG_DATA)

        project = Project.load_from_path(project_path)
        database = project.database

        compose = ComposeDefinition.load_from_project(project_path)
        assert len(compose.get_networks()) == 1
        assert len(compose.get_volumes()) == 1
        assert len(compose.get_services()) == 3

        test_path = os.path.join(project_path, "test.yml")
        compose.save_to_path(test_path)
        composeclone = ComposeDefinition.load_from_path(test_path)

        with pytest.raises(MissingComposefile):
            ComposeDefinition.load_from_path(
                os.path.join(project_path, "test2.yml"))

        assert compose.content == composeclone.content

        # Filter configuration
        conf = database.get_configuration("config")
        compose.apply_configuration(conf)
        assert len(compose.get_services()) == 2

        # Namespace
        conf2 = database.get_configuration("config2")
        compose = ComposeDefinition.load_from_project(project_path)
        compose.apply_configuration(conf2)
        assert len(compose.get_services()) == 2
Ejemplo n.º 20
0
def test_session_existing():
    """Session tests."""
    with using_temporary_directory() as tempdir:
        project_path = tempdir
        os.environ["DOCKNV_USER_PATH"] = project_path

        session_file = os.path.join(project_path, ".docknv", "test",
                                    "docknv.yml")
        os.makedirs(os.path.dirname(session_file))

        with open(session_file, mode="w") as handle:
            handle.write("current:")

        session = UserSession.load_from_path(user_get_username(), project_path)
        assert "current" in session.session_data
        assert session.session_data["current"] is None

        # Save
        session.save()

        # Remove
        session.remove_path(force=True)
        session.remove_path(force=True)
        session.remove_path("toto", force=True)
Ejemplo n.º 21
0
def test_database():
    """Database test."""
    database_file = """\
first:
    services:
        - ser1
        - ser2
    networks:
        - net1
    volumes:
        - vol1
    environment: default
    user: test
    namespace:
second:
    services:
        - ser3
    networks: []
    volumes: []
    environment: default
    user: tost
    namespace: hello\
    """

    with using_temporary_directory() as tempdir:
        project_path = copy_sample("sample01", tempdir)

        # Create directory
        os.makedirs(os.path.join(project_path, ".docknv"))
        with open(os.path.join(project_path, ".docknv", ".docknv.yml"),
                  mode="w") as handle:
            handle.write(database_file)

        project = Project.load_from_path(project_path)
        database = project.database
        assert len(database) == 2

        first = database.get_configuration("first")
        os.makedirs(first.get_path())
        assert os.path.exists(first.get_path())

        config = Configuration(
            database,
            "toto",
            user="******",
            environment="default",
            services=["toto"],
            volumes=[],
            networks=[],
            namespace=None,
        )
        database.create_configuration(config)

        assert len(database) == 3

        assert database["first"].has_permission()
        assert not database["second"].has_permission()
        assert database["toto"].has_permission()

        assert database.includes_configuration("first")
        assert not database.includes_configuration("pouet")

        first = database.get_configuration("first")
        first.environment = "inclusion"
        database.update_configuration(first)

        # Unknown name should fail
        first.name = "test1"
        with pytest.raises(MissingConfiguration):
            database.update_configuration(first)
        first.name = "first"

        # Second edit should fail
        second = database.get_configuration("second")
        second.environment = "inclusion"
        with pytest.raises(PermissionDenied):
            database.update_configuration(second)

        # Pouet does not exist
        with pytest.raises(MissingConfiguration):
            database.get_configuration("pouet")

        # Serialization test
        database.serialize()
        # Show test
        database.show_configuration_list()
        # Save test
        database.save()

        assert os.path.exists(first.get_composefile_path())
        assert os.path.exists(first.get_environment_path())

        # Paths test
        assert first.get_path() == os.path.join(project_path, ".docknv",
                                                "test", "first")
        assert second.get_path() == os.path.join(project_path, ".docknv",
                                                 "tost", "second")
        assert first.get_environment_path() == os.path.join(
            project_path, ".docknv", "test", "first", "environment.env")
        assert second.get_environment_path() == os.path.join(
            project_path, ".docknv", "tost", "second", "environment.env")
        assert first.get_composefile_path() == os.path.join(
            project_path, ".docknv", "test", "first", "docker-compose.yml")
        assert second.get_composefile_path() == os.path.join(
            project_path, ".docknv", "tost", "second", "docker-compose.yml")

        # Removal test
        project.session.set_current_configuration("first")
        database.remove_configuration("first", force=True)
        assert project.session.get_current_configuration() is None
        assert len(database) == 2

        with pytest.raises(MissingConfiguration):
            database.remove_configuration("pouet", force=True)
        with pytest.raises(PermissionDenied):
            database.remove_configuration("second", force=True)

        assert len(database) == 2
Ejemplo n.º 22
0
def test_session_lock():
    """Session lock."""
    with using_temporary_directory() as tempdir:
        project_path = tempdir
        os.environ["DOCKNV_USER_PATH"] = project_path

        session = UserSession.load_from_path(user_get_username(), project_path)
        lock = session.get_lock()

        assert lock.get_file() == f"{project_path}/.test.lock"

        # Lock should be disabled
        assert not lock.is_enabled
        # Unlocking should work
        assert lock.unlock()
        # Locking should work
        assert lock.lock()
        # Lock should be enabled
        assert lock.is_enabled

        # Lockfile should contain a $
        with open(lock.get_file(), mode="r") as handle:
            assert handle.read() == "$"

        # Relocking should return False
        assert not lock.lock()
        # But unlocking should work
        assert lock.unlock()
        # And is should be disabled
        assert not lock.is_enabled

        # And the file should not exist
        with pytest.raises(IOError):
            with open(lock.get_file(), mode="r") as handle:
                pass

        # Try-lock test
        with lock.try_lock():
            # Lock should be enabled
            assert lock.is_enabled

        # Now, lock should be disabled
        assert not lock.is_enabled

        # Second try-lock test
        assert lock.lock()
        with pytest.raises(ProjectLocked):
            with lock.try_lock():
                pass
        assert lock.is_enabled

        # Third try-lock test
        assert lock.unlock()
        with pytest.raises(RuntimeError):
            with lock.try_lock():
                assert lock.is_enabled
                # Raise exception
                raise RuntimeError("oops")

        # Should be unlocked
        assert not lock.is_enabled

        # Try-lock w/ timeout test
        lock.lock()
        with pytest.raises(ProjectLocked):
            with lock.try_lock(timeout=2):
                pass

        # Try-lock w/ timeout, waiting for unlock
        def unlock_thread():
            time.sleep(2)
            lock.unlock()

        thr1 = threading.Thread(target=unlock_thread)
        thr1.start()
        assert lock.is_enabled
        with lock.try_lock(timeout=2):
            pass
        thr1.join()
        assert not lock.is_enabled

        # Try-lock /w infinite timeout, waiting for unlock
        def unlock_thread2():
            time.sleep(3)
            lock.unlock()

        lock.lock()
        thr1 = threading.Thread(target=unlock_thread2)
        thr1.start()
        with lock.try_lock(timeout=-1):
            pass
        thr1.join()
        assert not lock.is_enabled
Ejemplo n.º 23
0
def test_shell():
    """Shell test."""
    shell = Shell()

    with using_temporary_directory() as tempdir:
        project_path = copy_sample("sample01", tempdir)

        def run_shell(args=None):
            args = args or []
            shell.run(["--project", project_path, "--dry-run"] + args)

        with pytest.raises(SystemExit):
            run_shell([])

        # Config create
        run_shell([
            "config",
            "create",
            "toto",
            "-e",
            "default",
            "-S",
            "portainer",
            "pouet",
            "-V",
            "portainer",
            "-N",
            "net",
        ])

        # Start config
        run_shell(["config", "start"])
        # Stop config
        run_shell(["config", "stop"])
        # Restart config
        run_shell(["config", "restart"])
        run_shell(["config", "restart", "-f"])

        # Set config
        run_shell(["config", "set", "toto"])
        # Unset config
        run_shell(["config", "unset"])

        with mock_input("y"):
            # Remove config
            run_shell(["config", "rm", "toto"])

        # Status
        run_shell(["config", "status"])

        # Toto
        run_shell([
            "config",
            "create",
            "toto",
            "-e",
            "default",
            "-S",
            "portainer",
            "pouet",
            "-V",
            "portainer",
            "-N",
            "net",
        ])

        run_shell(["config", "status"])
        run_shell(["config", "update"])
        run_shell(["config", "ls"])
        run_shell(["config", "build"])
        run_shell(["config", "ps"])

        ########
        # Service

        run_shell(["service", "build", "portainer"])
        run_shell(["service", "start", "portainer"])
        run_shell(["service", "stop", "portainer"])
        run_shell(["service", "restart", "portainer"])
        run_shell(["service", "restart", "portainer", "-f"])
        run_shell(["service", "run", "portainer", "bash"])
        run_shell(["service", "run", "portainer", "-d", "bash"])
        run_shell(["service", "exec", "portainer", "bash"])
        run_shell(["service", "shell", "portainer"])
        run_shell(["service", "logs", "portainer"])
        run_shell(["service", "push", "portainer", "./a", "/b"])
        run_shell(["service", "pull", "portainer", "/a", "./b"])

        #######
        # Env

        run_shell(["env", "ls"])
        run_shell(["env", "show", "default"])

        try:
            run_shell(["env", "edit", "default"])
            run_shell(["env", "edit", "default", "-e", "vim"])
        except NoEditorFound:
            pass

        #########
        # Schemas

        run_shell(["schema", "ls"])

        ########
        # Scaffold

        run_shell(["scaffold", "project", f"{project_path}/toto"])
        run_shell(["scaffold", "image", "apzt", "otapti"])
        run_shell(["scaffold", "env", "tototo"])
        run_shell(["scaffold", "env", "totototo", "-i", "tototo"])

        ######
        # User

        try:
            run_shell(["user", "edit"])
            run_shell(["user", "edit", "-e", "vim"])
            run_shell(["user", "edit", "toto"])
        except NoEditorFound:
            pass

        run_shell(["user", "rm-lock"])

        with mock_input("y"):
            run_shell(["user", "clean", "toto"])
            run_shell(["user", "clean"])

        ########
        # Custom

        with pytest.raises(SystemExit):
            run_shell(["custom"])

        ########
        # Machine

        with pytest.raises(SystemExit):
            run_shell(["machine"])
        with pytest.raises(SystemExit):
            run_shell(["machine", "restart", "portainer"])