Skip to content

Commit

Permalink
Merge pull request #140 from rtCamp/various-fixes
Browse files Browse the repository at this point in the history
`--work-dir` flag in `code`, Optimize containers permissions and force recreate in `start` command.
  • Loading branch information
Xieyt committed Mar 21, 2024
2 parents b6de697 + 0409202 commit ab23a78
Show file tree
Hide file tree
Showing 10 changed files with 47 additions and 52 deletions.
10 changes: 4 additions & 6 deletions Docker/frappe/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,19 @@ mkdir -p /opt/user/conf.d
chown -R "$USERID":"$USERGROUP" /opt

if [[ ! -d "/workspace/.oh-my-zsh" ]]; then
cp -r /opt/user/.oh-my-zsh /workspace/.oh-my-zsh
cp -pr /opt/user/.oh-my-zsh /workspace/
fi

if [[ ! -f "/workspace/.zshrc" ]]; then
cat /opt/user/.zshrc > /workspace/.zshrc
cp -p /opt/user/.zshrc /workspace/
fi

if [[ ! -f "/workspace/.profile" ]]; then
cat /opt/user/.profile > /workspace/.profile
cp -p /opt/user/.profile /workspace/
fi

chown "$USERID":"$USERGROUP" /workspace /workspace/frappe-bench

ls -p /workspace | grep -v 'frappe-bench/' | xargs -I{} chown -R "$USERID":"$USERGROUP" /workspace{}

ls -pA /workspace | xargs -I{} chown -R "$USERID":"$USERGROUP" /workspace/{} &

if [ "$#" -gt 0 ]; then
gosu "$USERID":"$USERGROUP" "/scripts/$@"
Expand Down
2 changes: 1 addition & 1 deletion Docker/images-tag.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"frappe": "v0.11.1",
"frappe": "v0.12.0",
"nginx": "v0.10.0",
"mailhog": "v0.8.3"
}
3 changes: 2 additions & 1 deletion frappe_manager/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,12 +308,13 @@ def code(
] = DEFAULT_EXTENSIONS,
force_start: Annotated[bool, typer.Option("--force-start", "-f", help="Force start the site before attaching to container.")] = False,
debugger: Annotated[bool, typer.Option("--debugger", "-d", help="Sync vscode debugger configuration.")] = False,
workdir: Annotated[str, typer.Option("--work-dir", "-w", help="Set working directory in vscode.")] = '/workspace/frappe-bench',
):
"""Open site in vscode."""
sites.init(sitename)
if force_start:
sites.start_site()
sites.attach_to_site(user, extensions, debugger)
sites.attach_to_site(user, extensions, workdir,debugger)


@app.command()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
from frappe_manager import CLI_DIR


class MigrationV0110(MigrationBase):
version = Version("0.11.1")
class MigrationV0120(MigrationBase):
version = Version("0.12.0")

def __init__(self):
super().init()
Expand Down
6 changes: 3 additions & 3 deletions frappe_manager/site_manager/SiteManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ def stop_site(self):
self.site.stop()
richprint.print(f"Stopped site")

def start_site(self,force: bool = False):
def start_site(self, force: bool = False):
"""
Starts the site.
"""
Expand All @@ -239,7 +239,7 @@ def start_site(self,force: bool = False):
self.site.frappe_logs_till_start(status_msg="Starting Site")
self.site.sync_workers_compose()

def attach_to_site(self, user: str, extensions: List[str], debugger: bool = False):
def attach_to_site(self, user: str, extensions: List[str], workdir: str, debugger: bool = False):
"""
Attaches to a running site's container using Visual Studio Code Remote Containers extension.
Expand All @@ -262,7 +262,7 @@ def attach_to_site(self, user: str, extensions: List[str], debugger: bool = Fals
vscode_cmd = shlex.join(
[
vscode_path,
f"--folder-uri=vscode-remote://attached-container+{container_hex}+/workspace/frappe-bench",
f"--folder-uri=vscode-remote://attached-container+{container_hex}+{workdir}",
]
)
extensions.sort()
Expand Down
16 changes: 8 additions & 8 deletions frappe_manager/site_manager/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def validate_sitename(self) -> bool:
match = is_fqdn(sitename)

if not match:
richprint.error(f"The {sitename} must follow Fully Qualified Domain Name (FQDN) format.",exception=SiteException(self, f"Valid FQDN site name not provided."))
richprint.error(f"The {sitename} must follow Fully Qualified Domain Name (FQDN) format.", exception=SiteException(self, f"Valid FQDN site name not provided."))

return True

Expand Down Expand Up @@ -199,7 +199,7 @@ def create_compose_dirs(self) -> bool:

return True

def start(self,force: bool = False) -> bool:
def start(self, force: bool = False) -> bool:
"""
Starts the Docker containers for the site.
Expand All @@ -210,16 +210,16 @@ def start(self,force: bool = False) -> bool:
richprint.change_head(status_text)

try:
output = self.docker.compose.up(detach=True, pull="never",force_recreate=force, stream=self.quiet)
output = self.docker.compose.up(detach=True, pull="never", force_recreate=force, stream=self.quiet)
if self.quiet:
richprint.live_lines(output, padding=(0, 0, 0, 2))
richprint.print(f"{status_text}: Done")
except DockerException as e:
richprint.error(f"{status_text}: Failed",exception=e)
richprint.error(f"{status_text}: Failed", exception=e)

# start workers if exists
if self.workers.exists():
self.workers.start()
self.workers.start(force=force)

return True

Expand Down Expand Up @@ -314,7 +314,7 @@ def stop(self) -> bool:
richprint.live_lines(output, padding=(0, 0, 0, 2))
richprint.print(f"{status_text}: Done")
except DockerException as e:
richprint.error(f"{status_text}: Failed",exception=e)
richprint.error(f"{status_text}: Failed", exception=e)

# stopping worker containers
if self.workers.exists():
Expand Down Expand Up @@ -346,7 +346,7 @@ def down(self, remove_ophans=True, volumes=True, timeout=5) -> bool:
exit_code = richprint.live_lines(output, padding=(0, 0, 0, 2))
richprint.print(f"{status_text}: Done")
except DockerException as e:
richprint.error(f"{status_text}: Failed",exception=e)
richprint.error(f"{status_text}: Failed", exception=e)

def remove(self) -> bool:
"""
Expand All @@ -371,7 +371,7 @@ def remove(self) -> bool:
exit_code = richprint.live_lines(output, padding=(0, 0, 0, 2))
richprint.print(f"Removing Containers: Done")
except DockerException as e:
richprint.error(f"{status_text}: Failed",exception=e)
richprint.error(f"{status_text}: Failed", exception=e)

richprint.change_head(f"Removing Dirs")

Expand Down
48 changes: 22 additions & 26 deletions frappe_manager/site_manager/workers_manager/SiteWorker.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,40 +9,40 @@
from frappe_manager.docker_wrapper.DockerClient import DockerClient
from frappe_manager.docker_wrapper.DockerException import DockerException


class SiteWorkers:
def __init__(self,site_path, site_name, quiet: bool = True):
def __init__(self, site_path, site_name, quiet: bool = True):
self.compose_path = site_path / "docker-compose.workers.yml"
self.config_dir = site_path / 'workspace' / 'frappe-bench' / 'config'
self.supervisor_config_path = self.config_dir / 'supervisor.conf'
self.config_dir = site_path / "workspace" / "frappe-bench" / "config"
self.supervisor_config_path = self.config_dir / "supervisor.conf"
self.site_name = site_name
self.quiet = quiet
self.init()

def init(self):
self.composefile = ComposeFile( self.compose_path, template_name='docker-compose.workers.tmpl')
self.composefile = ComposeFile(self.compose_path, template_name="docker-compose.workers.tmpl")
self.docker = DockerClient(compose_file_path=self.composefile.compose_path)

def exists(self):
return self.compose_path.exists()

def get_expected_workers(self)-> list[str]:

def get_expected_workers(self) -> list[str]:
richprint.change_head("Getting Workers info")

workers_supervisor_conf_paths = []

for file_path in self.config_dir.iterdir():
file_path_abs = str(file_path.absolute())
if file_path.is_file():
if file_path_abs.endswith('.workers.fm.supervisor.conf'):
if file_path_abs.endswith(".workers.fm.supervisor.conf"):
workers_supervisor_conf_paths.append(file_path)

workers_expected_service_names = []

for worker_name in workers_supervisor_conf_paths:
worker_name = worker_name.name
worker_name = worker_name.replace("frappe-bench-frappe-","")
worker_name = worker_name.replace(".workers.fm.supervisor.conf","")
worker_name = worker_name.replace("frappe-bench-frappe-", "")
worker_name = worker_name.replace(".workers.fm.supervisor.conf", "")
workers_expected_service_names.append(worker_name)

workers_expected_service_names.sort()
Expand All @@ -52,7 +52,6 @@ def get_expected_workers(self)-> list[str]:
return workers_expected_service_names

def is_expected_worker_same_as_template(self) -> bool:

if not self.composefile.is_template_loaded:
prev_workers = self.composefile.get_services_list()
prev_workers.sort()
Expand All @@ -72,46 +71,47 @@ def generate_compose(self):
# create compose file for workers
self.composefile.yml = self.composefile.load_template()

template_worker_config = self.composefile.yml['services']['worker-name']
template_worker_config = self.composefile.yml["services"]["worker-name"]

del self.composefile.yml['services']['worker-name']
del self.composefile.yml["services"]["worker-name"]

workers_expected_service_names = self.get_expected_workers()

if len(workers_expected_service_names) > 0:
import os

for worker in workers_expected_service_names:
worker_config = deepcopy(template_worker_config)

# setting environments
worker_config['environment']['WAIT_FOR'] = str(worker_config['environment']['WAIT_FOR']).replace("{worker-name}",worker)
worker_config['environment']['COMMAND'] = str(worker_config['environment']['COMMAND']).replace("{worker-name}",worker)
worker_config['environment']['USERID'] = os.getuid()
worker_config['environment']['USERGROUP'] = os.getgid()
worker_config["environment"]["WAIT_FOR"] = str(worker_config["environment"]["WAIT_FOR"]).replace("{worker-name}", worker)
worker_config["environment"]["COMMAND"] = str(worker_config["environment"]["COMMAND"]).replace("{worker-name}", worker)
worker_config["environment"]["USERID"] = os.getuid()
worker_config["environment"]["USERGROUP"] = os.getgid()

self.composefile.yml['services'][worker] = worker_config
self.composefile.yml["services"][worker] = worker_config

self.composefile.set_container_names(get_container_name_prefix(self.site_name))

fm_version = importlib.metadata.version("frappe-manager")
self.composefile.set_version(fm_version)

# set network name
self.composefile.yml["networks"]["site-network"]["name"] = (self.site_name.replace(".", "") + f"-network")
self.composefile.yml["networks"]["site-network"]["name"] = self.site_name.replace(".", "") + f"-network"
self.composefile.write_to_file()
else:
richprint.error("Workers configuration not found.")

def start(self):
def start(self, force=False):
status_text = "Starting Workers Containers"
richprint.change_head(status_text)
try:
output = self.docker.compose.up(detach=True, pull="never", stream=self.quiet)
output = self.docker.compose.up(detach=True, pull="never", force_recreate=force, stream=self.quiet)
if self.quiet:
richprint.live_lines(output, padding=(0, 0, 0, 2))
richprint.print(f"{status_text}: Done")
except DockerException as e:
richprint.error (f"{status_text}: Failed Error: {e}")
richprint.error(f"{status_text}: Failed Error: {e}")
raise e

def stop(self) -> bool:
Expand All @@ -130,15 +130,12 @@ def stop(self) -> bool:
richprint.warning(f"{status_text}: Failed")

def get_services_running_status(self) -> dict:

services = self.composefile.get_services_list()
containers = self.composefile.get_container_names().values()

services_status = {}
try:
output = self.docker.compose.ps(
service=services, format="json", all=True, stream=True
)
output = self.docker.compose.ps(service=services, format="json", all=True, stream=True)
status: list = []
for source, line in output:
if source == "stdout":
Expand All @@ -156,7 +153,6 @@ def get_services_running_status(self) -> dict:
except DockerException as e:
return {}


def running(self) -> bool:
"""
The `running` function checks if all the services defined in a Docker Compose file are running.
Expand Down
6 changes: 3 additions & 3 deletions frappe_manager/templates/docker-compose.tmpl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
version: "3.9"
services:
frappe:
image: ghcr.io/rtcamp/frappe-manager-frappe:v0.11.1
image: ghcr.io/rtcamp/frappe-manager-frappe:v0.12.0
container_name: REPLACE_ME_WITH_CONTAINER_NAME
environment:
ADMIN_PASS: REPLACE_me_with_frappe_web_admin_pass
Expand Down Expand Up @@ -72,7 +72,7 @@ services:
global-backend-network:

socketio:
image: ghcr.io/rtcamp/frappe-manager-frappe:v0.11.1
image: ghcr.io/rtcamp/frappe-manager-frappe:v0.12.0
container_name: REPLACE_ME_WITH_CONTAINER_NAME
environment:
TIMEOUT: 60000
Expand All @@ -90,7 +90,7 @@ services:
site-network:

schedule:
image: ghcr.io/rtcamp/frappe-manager-frappe:v0.11.1
image: ghcr.io/rtcamp/frappe-manager-frappe:v0.12.0
container_name: REPLACE_ME_WITH_CONTAINER_NAME
environment:
TIMEOUT: 60000
Expand Down
2 changes: 1 addition & 1 deletion frappe_manager/templates/docker-compose.workers.tmpl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
services:
worker-name:
image: ghcr.io/rtcamp/frappe-manager-frappe:v0.11.1
image: ghcr.io/rtcamp/frappe-manager-frappe:v0.12.0
environment:
TIMEOUT: 6000
CHANGE_DIR: /workspace/frappe-bench
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "frappe-manager"
version = "0.11.1"
version = "0.12.0"
license = "MIT"
repository = "https://github.com/rtcamp/frappe-manager"
description = "A CLI tool based on Docker Compose to easily manage Frappe based projects. As of now, only suitable for development in local machines running on Mac and Linux based OS."
Expand Down

0 comments on commit ab23a78

Please sign in to comment.