Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatically apply fixes to hosts file #8173

Merged
merged 8 commits into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions packages/grid/devspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -325,16 +325,15 @@ profiles:
path: deployments.seaweedfs-config

commands:
start:
command: |-
tox -e dev.k8s.start
deploy:
command: |-
devspace use context k3d-syft-dev
devspace use namespace syft
devspace deploy --var CONTAINER_REGISTRY=k3d-registry.localhost:12345
devspace deploy --kube-context k3d-syft-dev --namespace syft --var CONTAINER_REGISTRY=k3d-registry.localhost:12345
dev:
command: |-
devspace use context k3d-syft-dev
devspace use namespace syft
devspace dev --var CONTAINER_REGISTRY=k3d-registry.localhost:12345
contexts:
devspace dev --kube-context k3d-syft-dev --namespace syft --var CONTAINER_REGISTRY=k3d-registry.localhost:12345
info:
command: |-
kubectl config get-contexts
tox -e dev.k8s.info
212 changes: 212 additions & 0 deletions scripts/patch_hosts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
# stdlib
import argparse
from functools import cached_property
import os
from pathlib import Path
import platform
import re
import sys


class Platform:
system = platform.system()
uname = platform.uname()

@staticmethod
def get() -> str:
return Platform.system

@staticmethod
def windows() -> bool:
return Platform.system == "Windows"

@staticmethod
def macos() -> bool:
return Platform.system == "Darwin"

@staticmethod
def linux() -> bool:
return Platform.system == "Linux"

@staticmethod
def wsl2() -> bool:
return "wsl2" in Platform.uname.release.lower()


class Hosts:
def __init__(self, path: str = None) -> None:
self.__path = path
self.content = self.read()

@cached_property
def path(self) -> Path:
if self.__path:
p = self.__path
elif Platform.linux():
p = "/etc/hosts"
elif Platform.macos():
new_hosts = "/etc/hosts"
old_hosts = "/private/etc/hosts"
p = new_hosts if os.path.exists(new_hosts) else old_hosts
elif Platform.windows():
p = "C:\Windows\System32\drivers\etc\hosts"
else:
raise Exception(f"Unsupported OS: {Platform.system}")

p = Path(p).absolute()
assert p.exists(), "Host file does not exist"
return p

def read(self) -> str:
return self.path.read_text()

def get(self, domain: str) -> list[str]:
return re.findall(f"(.+)\s+{domain}", self.content)

def add(self, ip: str, domain: str) -> None:
if self.get(domain):
return

self.content = self.content.rstrip() + f"\n{ip}\t{domain}"
self.__write()

def remove(self, domain: str) -> None:
if not self.get(domain):
return

self.content = re.sub(f"(.+)\s+{domain}\n", "", self.content)
self.__write()

def update(self, ip: str, domain: str) -> None:
if not self.get(domain):
self.add(ip, domain)

# inplace
self.content = re.sub(f"(.+)\s+{domain}\n", f"{ip}\t{domain}\n", self.content)
self.__write()

def __write(self) -> None:
cleaned = re.sub("\n{2}\n+", "\n", self.content)
self.path.write_text(cleaned.rstrip() + "\n")


def running_as_root() -> bool:
if not Platform.windows():
return os.geteuid() == 0
else:
# stdlib
import ctypes

return ctypes.windll.shell32.IsUserAnAdmin() == 1


def wsl2_disable_auto_hosts() -> None:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: Yash , could you remind me again, on why we remove this?

if not Platform.wsl2():
return

# stdlib
import configparser

conf_path = Path("/etc/wsl.conf")
conf = configparser.ConfigParser()
conf.optionxform = str
conf.read(conf_path)

if "network" not in conf:
conf["network"] = {}

if conf["network"]["generateHosts"] != "false":
conf["network"]["generateHosts"] = "false"
with conf_path.open("w") as fp:
conf.write(fp)


def main():
parser = argparse.ArgumentParser()
parser.add_argument(
"--add",
nargs=2,
action="append",
default=[],
metavar=("IP", "DOMAIN"),
help="Add entry to hosts file",
)
parser.add_argument(
"--add-k3d-registry",
action="store_true",
default=False,
help="Add entry for k3d-registry.localhost",
)
parser.add_argument(
"--fix-docker-hosts",
action="store_true",
default=False,
help="Windows - Fix *.docker.internal. Linux/macOS - remove them",
)
parser.add_argument(
"--disable-wsl2-auto-hosts",
action="store_true",
default=False,
dest="wsl2_disable_auto_hosts",
help="[Optional] Disable automatic /etc/hosts generation from Windows in WSL2",
)
parser.add_argument(
"--hosts",
type=Path,
default=None,
help="[Optional] Path to a hosts-like file",
)

if len(sys.argv) < 2:
parser.print_help()
sys.exit(1)

args = parser.parse_args()

if not args.hosts and not running_as_root():
print(
"ERROR: This script must be run as root since it will modify system hosts file"
)
sys.exit(1)

hosts = Hosts(args.hosts)

print(">> Args", args.__dict__)
print(">> OS:", Platform.system)
print(">> Release:", Platform.uname.release)
print(">> Version:", Platform.uname.version)
print(">> Hosts file:", hosts.path)

if len(args.add):
for ip, domain in args.add:
print(f">> Adding {ip} {domain}")
hosts.update(ip, domain)

if args.add_k3d_registry:
print(">> Adding k3d registry host entry")
hosts.update("127.0.0.1", "k3d-registry.localhost")

if args.fix_docker_hosts:
if Platform.windows() or Platform.wsl2():
print(">> Fixing docker host entries for Windows/WSL2")
hosts.update("0.0.0.0", "host.docker.internal")
hosts.update("0.0.0.0", "gateway.docker.internal")
hosts.update("127.0.0.1", "kubernetes.docker.internal")
else:
print(">> Removing docker host entries")
hosts.remove("host.docker.internal")
hosts.remove("gateway.docker.internal")
hosts.remove("kubernetes.docker.internal")

if args.wsl2_disable_auto_hosts and Platform.wsl2():
print(">> Disabling auto hosts generation")
wsl2_disable_auto_hosts()

print(">> Done")
print("-" * 50)
print(hosts.read())
print("-" * 50)


if __name__ == "__main__":
main()
79 changes: 56 additions & 23 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
[tox]
envlist =
dev.k8s.registry
dev.k8s.start
dev.k8s.deploy
dev.k8s.info
dev.k8s.destroy
dev.k8s.destroyall
hagrid.publish
lint
stack.test.integration
Expand Down Expand Up @@ -936,52 +942,79 @@ commands =
pytest

[testenv:dev.k8s.registry]
changedir = {toxinidir}/packages/grid
description = Start local Kubernetes registry with k3d
changedir = {toxinidir}
passenv=HOME,USER
allowlist_externals =
bash
sudo
commands =
bash -c 'k3d registry create registry.localhost --port 12345 -v $HOME/.k3d-registry:/var/lib/registry'
bash -c '\
CYAN="\033[1;36m"; \
CLEAR="\033[0m"; \
printf "\n${CYAN}---------------------------------------------------------\n" ;\
printf "Make sure to add the following to your /etc/hosts file:${CLEAR}\n";\
printf "127.0.0.1 k3d-registry.localhost\n";\
printf "${CYAN}---------------------------------------------------------${CLEAR}\n"'
bash -c 'k3d registry create registry.localhost --port 12345 -v $HOME/.k3d-registry:/var/lib/registry || true'
sudo {envpython} scripts/patch_hosts.py --add-k3d-registry --fix-docker-hosts
yashgorana marked this conversation as resolved.
Show resolved Hide resolved

[testenv:dev.k8s.start]
changedir = {toxinidir}/packages/grid
description = Start local Kubernetes registry & cluster with k3d
changedir = {toxinidir}
passenv=*
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: Why do we pass in all the environment variables?

allowlist_externals =
bash
k3d
sleep
tox
commands =
bash -c 'URL=http://k3d-registry.localhost:12345/v2/_catalog; \
curl -X GET $URL || (echo "ERROR: Add \"127.0.0.1 k3d-registry.localhost\" to /etc/hosts" && exit 1)'
tox -e dev.k8s.registry
sleep 3
bash -c 'URL=http://k3d-registry.localhost:12345/v2/_catalog; curl -X GET $URL'
bash -c 'k3d cluster create syft-dev -p "8080:80@loadbalancer" --registry-use k3d-registry.localhost:12345; \
k3d cluster list'
kubectl create namespace syft;'
tox -e dev.k8s.info

[testenv:dev.k8s.deploy]
description = Deploy to a local Kubernetes cluster with Devspace
changedir = {toxinidir}/packages/grid
passenv=HOME, USER
allowlist_externals =
bash
commands =
bash -c '\
devspace use context k3d-syft-dev; \
devspace use namespace syft; \
devspace deploy --var CONTAINER_REGISTRY=k3d-registry.localhost:12345 --config=devspace.yaml'
bash -c 'devspace deploy -b --kube-context k3d-syft-dev --namespace syft --var CONTAINER_REGISTRY=k3d-registry.localhost:12345'

[testenv:dev.k8s.info]
description = Gather info about the localKubernetes cluster
passenv=HOME, USER
ignore_errors = True
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: Why do we ignore errors at this place?

allowlist_externals =
k3d
kubectl
commands =
kubectl config view
k3d cluster list
kubectl cluster-info
kubectl config current-context
kubectl get namespaces

[testenv:dev.k8s.cleanup]
[testenv:dev.k8s.destroy]
description = Destroy local Kubernetes cluster
changedir = {toxinidir}/packages/grid
passenv=HOME, USER
allowlist_externals =
bash
commands =
bash -c '\
devspace use context k3d-syft-dev; \
devspace use namespace syft; \
devspace purge; \
devspace purge --kube-context k3d-syft-dev --namespace syft; \
rm -rf .devspace; echo ""; \
k3d cluster delete syft-dev; echo ""; \
k3d registry delete registry.localhost; echo "";\
kubectl config view'

[testenv:dev.k8s.destroyall]
description = Destroy both local Kubernetes cluster and registry
changedir = {toxinidir}
passenv=HOME, USER
ignore_errors=True
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: Why do we ignore error at this place?

allowlist_externals =
bash
tox
sudo
rm
commands =
tox -e dev.k8s.destroy
bash -c 'k3d registry delete registry.localhost || true'
sudo rm -rf ~/.k3d-registry
Loading