def test_retrieve_binaries_data(self): features.register(DockerFeature()) load_registered_features() action = actions.get( 'docker:display-info') # type:DockerDisplayInfoAction assert [] == action._retrieve_binaries_data(Dotty({})) assert [] == action._retrieve_binaries_data(Dotty({'toto': 'toto'})) assert [] == action._retrieve_binaries_data( Dotty({'labels': { 'toto': '123' }})) assert ['npm-simple'] == action._retrieve_binaries_data( Dotty({ 'labels': { 'ddb.emit.docker:binary[npm-simple](name)': 'npm-simple', 'ddb.emit.docker:binary[npm-simple](workdir)': '/app' } })) assert ['npm', 'npm-simple'] == sorted( action._retrieve_binaries_data( Dotty({ 'labels': { 'ddb.emit.docker:binary[npm](name)': 'npm', 'ddb.emit.docker:binary[npm-simple](name)': 'npm-simple', 'ddb.emit.docker:binary[npm-simple](workdir)': '/app' } })))
def test_execute_extra_services(self, capsys: CaptureFixture, project_loader): project_loader("extra-services") features.register(DockerFeature()) features.register(TraefikFeature()) load_registered_features() config.args.type = None action = actions.get( 'docker:display-info') # type:DockerDisplayInfoAction action.execute() capture = capsys.readouterr() assert capture.out assert not capture.err assert ('\n'.join([ '+-------------------------+', '| web |', '+-------------------------+', '| https://web.domain.tld/ |', '+-------------------------+', '', '+-----------------------------------------------+', '| foo (extra) |', '+-----------------------------------------------+', '| https://sub.test --> http://192.168.99.1:8080 |', '+-----------------------------------------------+', '\n' ])) == capture.out
def test_extra_services(self, project_loader): project_loader("extra-services") features.register(CoreFeature()) features.register(TraefikFeature()) features.register(DockerFeature()) features.register(JsonnetFeature()) load_registered_features() install_action = TraefikExtraServicesAction() install_action.initialize() install_action.execute() files = { "api": { "generated": "sub.project.test.extra-service.api.toml", "expected": "sub.project.test.extra-service.api.expected.toml" }, "rule": { "generated": "rule.project.test.extra-service.web.toml", "expected": "rule.project.test.extra-service.web.expected.toml", "replaces": { "{{ip}}": config.data.get('docker.debug.host') } }, "secured": { "generated": "secured.project.test.extra-service.redirect.toml", "expected": "secured.project.test.extra-service.redirect.expected.toml" }, "secured_path_prefix": { "generated": "secured.project.test.extra-service.path_prefix.toml", "expected": "secured.project.test.extra-service.path_prefix.expected.toml" }, "secured_path_prefix_with_redirect": { "generated": "secured.project.test.extra-service.path_prefix_with_redirect.toml", "expected": "secured.project.test.extra-service.path_prefix_with_redirect.expected.toml" } } for file in files: generated = os.path.join( config.data['traefik']['config_directory'], files.get(file).get('generated')) assert os.path.exists(generated) expected = Path( os.path.join(config.data['traefik']['config_directory'], files.get(file).get('expected'))).read_text() if files.get(file).get('replaces'): for replace in files.get(file).get('replaces'): expected = expected.replace( replace, files.get(file).get('replaces').get(replace)) assert expected == Path(generated).read_text()
def test_empty_project_without_core(self, project_loader): project_loader("empty") features.register(DockerFeature()) load_registered_features() action = actions.get('docker:emit-docker-compose-config' ) # type:EmitDockerComposeConfigAction action.execute()
def test_binary_options(self, project_loader): project_loader("binary-options") features.register(DockerFeature()) load_registered_features() register_actions_in_event_bus(True) action = actions.get('docker:emit-docker-compose-config' ) # type:EmitDockerComposeConfigAction action.execute() assert len(list(binaries.all())) == 3 assert binaries.has("npm-simple") assert binaries.has("npm-conditions") assert binaries.has("mysql") npm_simple_set = binaries.get("npm-simple") assert len(npm_simple_set) == 1 npm_simple = list(npm_simple_set)[0] assert npm_simple.command() == ( ''.join(effective_command("docker-compose")) + " run --rm --workdir=/app/. --label traefik.enable=false node" ).split() assert npm_simple.command("serve") == ( ''.join(effective_command("docker-compose")) + ' run --rm --workdir=/app/. --label traefik.enable=false node' ).split() assert npm_simple.command("run serve") == ( ''.join(effective_command("docker-compose")) + ' run --rm --workdir=/app/. --label traefik.enable=false node' ).split() npm_conditions_set = binaries.get("npm-conditions") assert len(npm_conditions_set) == 1 npm_conditions = list(npm_conditions_set)[0] assert npm_conditions.command() == ( ''.join(effective_command("docker-compose")) + " run --rm --workdir=/app/. --label traefik.enable=false node" ).split() assert npm_conditions.command("serve") == ( ''.join(effective_command("docker-compose")) + ' run --rm --workdir=/app/. --label traefik.enable=false node' ).split() assert npm_conditions.command("run serve") == ( ''.join(effective_command("docker-compose")) + ' run --rm --workdir=/app/. node').split() mysql_set = binaries.get("mysql") assert len(mysql_set) == 1 mysql = list(mysql_set)[0] assert mysql.command() == ( ''.join(effective_command("docker-compose")) + ' run --rm --workdir=/app/. db mysql -hdb -uproject-management-tool -pproject-management-tool' ).split()
def test_binary_workdir(self, project_loader): project_loader("binary-workdir") features.register(DockerFeature()) load_registered_features() register_actions_in_event_bus(True) action = actions.get('docker:emit-docker-compose-config' ) # type:EmitDockerComposeConfigAction action.execute() assert len(list(binaries.all())) == 2 assert binaries.has("npm") assert binaries.has("node")
def test_retrieve_environment_data(self): features.register(DockerFeature()) load_registered_features() action = actions.get( 'docker:display-info') # type:DockerDisplayInfoAction assert {} == action._retrieve_environment_data(Dotty({})) assert {} == action._retrieve_environment_data(Dotty({'toto': 'toto'})) assert { 'AZERTY': '123' } == action._retrieve_environment_data( Dotty({'environment': { 'AZERTY': '123' }}))
def test_local_volume_related(self, project_loader): project_loader("local-volume-related") features.register(DockerFeature()) load_registered_features() register_actions_in_event_bus(True) action = actions.get('docker:emit-docker-compose-config' ) # type:EmitDockerComposeConfigAction action.execute() assert not os.path.exists('node-path') assert os.path.isdir('new_directory') assert os.path.isdir('child') assert os.path.isdir(os.path.join('new_directory', 'some', 'child'))
def test_extra_services_redirect(self, project_loader): project_loader("extra-services-redirect") features.register(CoreFeature()) features.register(TraefikFeature()) features.register(DockerFeature()) features.register(JsonnetFeature()) load_registered_features() install_action = TraefikExtraServicesAction() install_action.initialize() install_action.execute() api_toml = os.path.join(config.data['traefik']['config_directory'], "sub.project.test.extra-service.api.toml") assert os.path.exists(api_toml) api_toml_expected = Path( os.path.join(config.data['traefik']['config_directory'], "sub.project.test.extra-service.api.expected.toml")) assert api_toml_expected.read_text() == Path(api_toml).read_text() web_toml = os.path.join(config.data['traefik']['config_directory'], "rule.project.test.extra-service.web.toml") assert os.path.exists(web_toml) web_toml_expected = Path( os.path.join(config.data['traefik']['config_directory'], "rule.project.test.extra-service.web.expected.toml")) assert web_toml_expected.read_text().replace( '{{ip}}', config.data.get('docker.debug.host')) == Path( web_toml).read_text() secured_toml = os.path.join( config.data['traefik']['config_directory'], "secured.project.test.extra-service.no-redirect.toml") assert os.path.exists(secured_toml) secured_toml_expected = Path( os.path.join( config.data['traefik']['config_directory'], "secured.project.test.extra-service.no-redirect.expected.toml") ) assert secured_toml_expected.read_text() == Path( secured_toml).read_text()
def test_docker_compose_variants(self, project_loader, variant): project_loader("docker_compose" + variant) features.register(CoreFeature()) features.register(FileFeature()) features.register(DockerFeature()) features.register(JsonnetFeature()) load_registered_features() register_actions_in_event_bus(True) action = FileWalkAction() action.initialize() action.execute() assert os.path.exists('docker-compose.yml') with open('docker-compose.yml', 'r') as f: rendered = yaml.load(f.read(), yaml.SafeLoader) with open('docker-compose.expected.yml', 'r') as f: expected_data = f.read() if os.name == 'nt': mapped_cwd = re.sub(r"^([a-zA-Z]):", r"/\1", os.getcwd()) mapped_cwd = pathlib.Path(mapped_cwd).as_posix() expected_data = expected_data.replace("%ddb.path.project%", mapped_cwd) else: expected_data = expected_data.replace("%ddb.path.project%", os.getcwd()) expected_data = expected_data.replace( "%uid%", str(config.data.get('docker.user.uid'))) expected_data = expected_data.replace( "%gid%", str(config.data.get('docker.user.gid'))) expected_data = expected_data.replace( "%docker.debug.host%", str(config.data.get('docker.debug.host'))) expected = yaml.load(expected_data, yaml.SafeLoader) assert rendered == expected if variant == '_mount_single_volume': assert os.path.isdir('volumes/shared-volume') if variant == '_mount_single_volume_with_default': assert os.path.isdir('shared-volume')
def test_docker_compose_traefik_defaults(self, project_loader, variant): def before_load_config(): os.rename("ddb.%s.yml" % variant, "ddb.yml") os.rename("docker-compose.expected.%s.yml" % variant, "docker-compose.expected.yml") project_loader("docker_compose_traefik_defaults", before_load_config) features.register(CoreFeature()) features.register(FileFeature()) features.register(DockerFeature()) features.register(JsonnetFeature()) load_registered_features() register_actions_in_event_bus(True) action = FileWalkAction() action.initialize() action.execute() assert os.path.exists('docker-compose.yml') with open('docker-compose.yml', 'r') as f: rendered = yaml.load(f.read(), yaml.SafeLoader) with open('docker-compose.expected.yml', 'r') as f: expected_data = f.read() if os.name == 'nt': mapped_cwd = re.sub(r"^([a-zA-Z]):", r"/\1", os.getcwd()) mapped_cwd = pathlib.Path(mapped_cwd).as_posix() expected_data = expected_data.replace("%ddb.path.project%", mapped_cwd) else: expected_data = expected_data.replace("%ddb.path.project%", os.getcwd()) expected_data = expected_data.replace( "%uid%", str(config.data.get('docker.user.uid'))) expected_data = expected_data.replace( "%gid%", str(config.data.get('docker.user.gid'))) expected_data = expected_data.replace( "%docker.debug.host%", str(config.data.get('docker.debug.host'))) expected = yaml.load(expected_data, yaml.SafeLoader) assert rendered == expected
def test_retrieve_vhosts_data(self): features.register(DockerFeature()) load_registered_features() action = actions.get( 'docker:display-info') # type:DockerDisplayInfoAction assert [] == action._retrieve_vhosts_data(Dotty({})) assert [] == action._retrieve_vhosts_data(Dotty({'toto': 'toto'})) assert [] == action._retrieve_vhosts_data( Dotty({'labels': { 'toto': '123' }})) assert ['http://web.domain.tld/'] == action._retrieve_vhosts_data( Dotty({ 'labels': { 'traefik.http.routers.defaults-project.rule': 'Host(`web.domain.tld`)', 'ddb.emit.docker:binary[npm-simple](workdir)': '/app' } })) assert ['http://test.tld/', 'http://web.domain.tld/'] == sorted( action._retrieve_vhosts_data( Dotty({ 'labels': { 'traefik.http.routers.defaults-project.rule': 'Host(`web.domain.tld`)', 'traefik.http.routers.test-project.rule': 'Host(`test.tld`)', 'ddb.emit.docker:binary[npm-simple](workdir)': '/app' } }))) assert ['http://test.tld/', 'https://web.domain.tld/'] == sorted( action._retrieve_vhosts_data( Dotty({ 'labels': { 'traefik.http.routers.defaults-project.rule': 'Host(`web.domain.tld`)', 'traefik.http.routers.defaults-project-tls.rule': 'Host(`web.domain.tld`)', 'traefik.http.routers.test-project.rule': 'Host(`test.tld`)', 'ddb.emit.docker:binary[npm-simple](workdir)': '/app' } })))
def test_execute_traefik_cert(self, capsys: CaptureFixture, project_loader): project_loader("traefik-cert") features.register(DockerFeature()) load_registered_features() config.args.type = None action = actions.get( 'docker:display-info') # type:DockerDisplayInfoAction action.execute() capture = capsys.readouterr() assert capture.out assert not capture.err assert ('\n'.join([ '+-------------------------+', '| web |', '+-------------------------+', '| https://web.domain.tld/ |', '+-------------------------+', '\n' ])) == capture.out
def test_emit_one_arg(self, project_loader): project_loader("emit-one-arg") features.register(DockerFeature()) load_registered_features() custom_event_listeners = [] def listener(data): custom_event_listeners.append(data) bus.on("some:test", listener) action = actions.get('docker:emit-docker-compose-config' ) # type:EmitDockerComposeConfigAction action.execute() assert len(custom_event_listeners) == 1 assert custom_event_listeners[0] == "emit-one-arg"
def test_local_volume_simple(self, project_loader): project_loader("local-volume-simple") features.register(DockerFeature()) load_registered_features() register_actions_in_event_bus(True) action = actions.get('docker:emit-docker-compose-config' ) # type:EmitDockerComposeConfigAction action.execute() assert not os.path.exists('node-path') assert os.path.isdir('existing-directory') assert os.path.isdir('new_directory') assert os.path.isfile('existing-file.txt') assert os.path.isfile('new_file') assert os.path.isfile('another_new_file.txt') with open('existing-file.txt', 'r') as f: assert f.read() == 'existing-file.txt'
def test_retrieve_ports_data(self): features.register(DockerFeature()) load_registered_features() action = actions.get( 'docker:display-info') # type:DockerDisplayInfoAction assert [] == action._retrieve_service_ports(Dotty({})) assert [] == action._retrieve_service_ports(Dotty({'toto': 'toto'})) assert [ServicePort(45, 123, None, None, None) ] == action._retrieve_service_ports( Dotty({'ports': [{ 'published': '123', 'target': '45' }]})) assert [ServicePort(45, 123, None, None, None)] == action._retrieve_service_ports( Dotty({'ports': ['123:45']})) assert [ServicePort(45, 123, 'tcp', None, None)] == action._retrieve_service_ports( Dotty({'ports': ['123:45/tcp']}))
def test_autofix_variables_only(self, project_loader): project_loader("autofix_variables_only") config.args.autofix = True history = ( PropertyMigration("old_property", "new_property", since="v1.1.0"), PropertyMigration("some.deep.old.property", "some.another.new.property", since="v1.1.0"), ) migrations.set_history(history) features.register(CoreFeature()) features.register(FileFeature()) features.register(DockerFeature()) features.register(JsonnetFeature()) load_registered_features() register_actions_in_event_bus(True) action = FileWalkAction() action.initialize() action.execute() assert os.path.exists('variables.json') with open('variables.json', 'r') as f: rendered = f.read() with open('variables.expected.json', 'r') as f: expected = f.read() assert expected == rendered with open('variables.json.jsonnet', 'r') as f: source = f.read() with open('variables.json.autofix', 'r') as f: fixed = f.read() assert source == fixed
def test_emit_complex(self, project_loader): project_loader("emit-complex") features.register(DockerFeature()) load_registered_features() some_events = [] another_events = [] def someListener(*args, **kwargs): some_events.append({"args": args, "kwargs": kwargs}) def anotherListener(*args, **kwargs): another_events.append({"args": args, "kwargs": kwargs}) bus.on("some:test", someListener) bus.on("another:test", anotherListener) action = actions.get('docker:emit-docker-compose-config' ) # type:EmitDockerComposeConfigAction action.execute() assert len(some_events) == 3 assert {"args": ("emit-one-arg", ), "kwargs": {}} in some_events assert {"args": ("emit-one-arg-2", ), "kwargs": {}} in some_events # docker-compose >= 1.27.0 returns major version only. see https://github.com/docker/compose/issues/7730 assert {"args": ("emit-some-arg",), "kwargs": {'image': 'ubuntu', 'kw1': 'emit-one-kwarg', 'kw2': 7, 'version': '3.7'}} in some_events or \ {"args": ("emit-some-arg",), "kwargs": {'image': 'ubuntu', 'kw1': 'emit-one-kwarg', 'kw2': 7, 'version': '3'}} in some_events assert len(another_events) == 2 assert {"args": ("emit-another-arg", ), "kwargs": {}} in another_events assert { "args": (), "kwargs": { "kw1": "emit-another-kwarg" } } in another_events
def test_docker_compose_xdebug(self, project_loader, variant): def before_load_config(): os.rename("ddb.%s.yml" % variant, "ddb.yml") os.rename("docker-compose.expected.%s.yml" % variant, "docker-compose.expected.yml") project_loader("docker_compose_xdebug", before_load_config) print(os.getcwd()) features.register(CoreFeature()) features.register(FileFeature()) features.register(DockerFeature()) features.register(JsonnetFeature()) load_registered_features() register_actions_in_event_bus(True) action = FileWalkAction() action.initialize() action.execute() assert os.path.exists('docker-compose.yml') with open('docker-compose.yml', 'r') as f: rendered = yaml.load(f.read(), yaml.SafeLoader) with open('docker-compose.expected.yml', 'r') as f: expected_data = f.read() expected_data = expected_data.replace( "%uid%", str(config.data.get('docker.user.uid'))) expected_data = expected_data.replace( "%gid%", str(config.data.get('docker.user.gid'))) expected_data = expected_data.replace( "%docker.debug.host%", str(config.data.get('docker.debug.host'))) expected = yaml.load(expected_data, yaml.SafeLoader) assert rendered == expected
def test_docker_compose_included_services(self, project_loader): project_loader("docker_compose_included_services") features.register(CoreFeature()) features.register(FileFeature()) features.register(DockerFeature()) features.register(JsonnetFeature()) load_registered_features() register_actions_in_event_bus(True) action = FileWalkAction() action.initialize() action.execute() assert os.path.exists('docker-compose.yml') with open('docker-compose.yml', 'r') as f: rendered = yaml.load(f.read(), yaml.SafeLoader) with open('docker-compose.expected.yml', 'r') as f: expected_data = f.read() expected = yaml.load(expected_data, yaml.SafeLoader) assert rendered == expected
def test_ubuntu(self, project_loader): project_loader("ubuntu") features.register(DockerFeature()) load_registered_features() custom_event_listeners = [] def listener(docker_compose_config): custom_event_listeners.append(docker_compose_config) bus.on("docker:docker-compose-config", listener) action = actions.get('docker:emit-docker-compose-config' ) # type:EmitDockerComposeConfigAction action.execute() assert len(custom_event_listeners) == 1 assert custom_event_listeners[0] in [ # docker-compose >= 1.27.0 returns major version only. see https://github.com/docker/compose/issues/7730 { "version": "3", "services": { "docker": { "image": "ubuntu" } } }, { "version": "3.7", "services": { "docker": { "image": "ubuntu" } } } ]
def test_output_data(self, project_loader): features.register(DockerFeature()) load_registered_features() action = actions.get( 'docker:display-info') # type:DockerDisplayInfoAction config.args.type = None assert '' == action._output_data('test', dict(), [], [], []) test_vhosts = action._retrieve_vhosts_data( Dotty({ 'labels': { 'traefik.http.routers.defaults-project.rule': 'Host(`web.domain.tld`)', 'traefik.http.routers.defaults-project-tls.rule': 'Host(`web.domain.tld`)', 'traefik.http.routers.test-project.rule': 'Host(`test.tld`)', 'ddb.emit.docker:binary[npm-simple](workdir)': '/app' } })) assert ('\n'.join([ '+-------------------------+', '| test |', '+-------------------------+', '| http://test.tld/ |', '| https://web.domain.tld/ |', '+-------------------------+' ])) == action._output_data('test', dict(), [], [], test_vhosts) test_binaries = action._retrieve_binaries_data( Dotty({ 'labels': { 'ddb.emit.docker:binary[npm](name)': 'npm', 'ddb.emit.docker:binary[npm-simple](name)': 'npm-simple', 'ddb.emit.docker:binary[npm-simple](workdir)': '/app' } })) assert ('\n'.join([ '+-------------------------+', '| test |', '+-------------------------+', '| npm |', '| npm-simple |', '+-------------------------+', '| http://test.tld/ |', '| https://web.domain.tld/ |', '+-------------------------+' ])) == action._output_data('test', dict(), [], test_binaries, test_vhosts) test_envs = action._retrieve_environment_data( Dotty({'environment': { 'AZERTY': '123' }})) assert ('\n'.join([ '+-------------------------+', '| test |', '+-------------------------+', '| AZERTY: 123 |', '+-------------------------+', '| npm |', '| npm-simple |', '+-------------------------+', '| http://test.tld/ |', '| https://web.domain.tld/ |', '+-------------------------+' ])) == action._output_data('test', test_envs, [], test_binaries, test_vhosts) test_ports = action._retrieve_service_ports( Dotty({'ports': [{ 'published': '12123', 'target': '123' }]})) assert ('\n'.join([ '+-------------------------+', '| test |', '+-------------------------+', '| AZERTY: 123 |', '+-------------------------+', '| 12123:123/tcp |', '+-------------------------+', '| npm |', '| npm-simple |', '+-------------------------+', '| http://test.tld/ |', '| https://web.domain.tld/ |', '+-------------------------+' ])) == action._output_data('test', test_envs, test_ports, test_binaries, test_vhosts) config.args.type = 'nothing' assert '' == action._output_data('test', dict(), [], [], test_vhosts) config.args.type = 'vhost' assert ('\n'.join([ '+-------------------------+', '| test |', '+-------------------------+', '| http://test.tld/ |', '| https://web.domain.tld/ |', '+-------------------------+' ])) == action._output_data('test', dict(), [], [], test_vhosts)
def test_traefik_cert(self, project_loader, module_scoped_container_getter): project_loader("traefik-cert") features.register(CertsFeature()) features.register(TraefikFeature()) features.register(DockerFeature()) load_registered_features() register_actions_in_event_bus(True) setup_cfssl(module_scoped_container_getter) shutil.copyfile("docker-compose.yml", "docker-compose.original.yml") action = actions.get('docker:emit-docker-compose-config' ) # type:EmitDockerComposeConfigAction action.execute() assert os.path.exists( os.path.join(config.paths.project_home, ".certs", "web.domain.tld.key")) assert os.path.exists( os.path.join(config.paths.project_home, ".certs", "web.domain.tld.crt")) assert os.path.exists( os.path.join(config.paths.home, "certs", "web.domain.tld.key")) assert os.path.exists( os.path.join(config.paths.home, "certs", "web.domain.tld.crt")) assert os.path.exists( os.path.join(config.paths.home, "traefik", "config", "web.domain.tld.ssl.toml")) shutil.copyfile("docker-compose.removed.yml", "docker-compose.yml") action.execute() assert not os.path.exists( os.path.join(config.paths.project_home, ".certs", "web.domain.tld.key")) assert not os.path.exists( os.path.join(config.paths.project_home, ".certs", "web.domain.tld.crt")) assert not os.path.exists( os.path.join(config.paths.home, "certs", "web.domain.tld.key")) assert not os.path.exists( os.path.join(config.paths.home, "certs", "web.domain.tld.crt")) assert not os.path.exists( os.path.join(config.paths.home, "traefik", "config", "web.domain.tld.ssl.toml")) shutil.copyfile("docker-compose.original.yml", "docker-compose.yml") action.execute() assert os.path.exists( os.path.join(config.paths.project_home, ".certs", "web.domain.tld.key")) assert os.path.exists( os.path.join(config.paths.project_home, ".certs", "web.domain.tld.crt")) assert os.path.exists( os.path.join(config.paths.home, "certs", "web.domain.tld.key")) assert os.path.exists( os.path.join(config.paths.home, "certs", "web.domain.tld.crt")) assert os.path.exists( os.path.join(config.paths.home, "traefik", "config", "web.domain.tld.ssl.toml")) shutil.copyfile("docker-compose.changed.yml", "docker-compose.yml") action.execute() assert not os.path.exists( os.path.join(config.paths.project_home, ".certs", "web.domain.tld.key")) assert not os.path.exists( os.path.join(config.paths.project_home, ".certs", "web.domain.tld.crt")) assert not os.path.exists( os.path.join(config.paths.home, "certs", "web.domain.tld.key")) assert not os.path.exists( os.path.join(config.paths.home, "certs", "web.domain.tld.crt")) assert not os.path.exists( os.path.join(config.paths.home, "traefik", "config", "web.domain.tld.ssl.toml")) assert os.path.exists( os.path.join(config.paths.project_home, ".certs", "web-changed.domain.tld.key")) assert os.path.exists( os.path.join(config.paths.project_home, ".certs", "web-changed.domain.tld.crt")) assert os.path.exists( os.path.join(config.paths.home, "certs", "web-changed.domain.tld.key")) assert os.path.exists( os.path.join(config.paths.home, "certs", "web-changed.domain.tld.crt")) assert os.path.exists( os.path.join(config.paths.home, "traefik", "config", "web-changed.domain.tld.ssl.toml"))