-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Changes from all commits
3d80e55
151c06f
d61faf5
c03ae10
5dde914
6849b0a
523a11f
ff7c4ed
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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: | ||
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() |
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 | ||
|
@@ -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=* | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
There was a problem hiding this comment.
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?