Skip to content

Commit

Permalink
Add more refactoring and update docs. Fixes #574
Browse files Browse the repository at this point in the history
  • Loading branch information
OlafSzmidt committed May 14, 2018
1 parent 324602d commit 8342026
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 23 deletions.
80 changes: 63 additions & 17 deletions aimmo_runner/minikube.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,35 @@

MINIKUBE_EXECUTABLE = "minikube"


def get_ip():
# http://stackoverflow.com/a/28950776/671626
"""
Get a single primary IP address. This will not return all IPs in the
interface. See http://stackoverflow.com/a/28950776/671626
:return: Integer with the IP of the user.
"""
os_name = platform.system()
if os_name == "Darwin":
return socket.gethostbyname(socket.gethostname())

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# noinspection PyBroadException
try:
# doesn't even have to be reachable
s.connect(('10.255.255.255', 0))
IP = s.getsockname()[0]
client_socket.connect(('10.255.255.255', 0))
IP = client_socket.getsockname()[0]
except:
IP = '127.0.0.1'
finally:
s.close()
client_socket.close()
return IP


def restart_ingress_addon(minikube):
"""
Ingress needs to be restarted for old paths to be removed at startup.
:param minikube: Executable minikube installed beforehand.
"""
try:
run_command([minikube, 'addons', 'disable', 'ingress'])
except:
Expand All @@ -40,20 +49,30 @@ def restart_ingress_addon(minikube):


def create_ingress_yaml():
"""
Loads a ingress yaml file into a python object.
"""
path = os.path.join(BASE_DIR, 'ingress.yaml')
with open(path) as yaml_file:
content = yaml.safe_load(yaml_file.read())
return content


def create_creator_yaml():
"""
Loads a replication controller yaml file into a python object.
"""
orig_path = os.path.join(BASE_DIR, 'aimmo-game-creator', 'rc-aimmo-game-creator.yaml')
with open(orig_path) as orig_file:
content = yaml.safe_load(orig_file.read().replace('latest', 'test').replace('REPLACE_ME', 'http://%s:8000/players/api/games/' % get_ip()))
return content


def start_cluster(minikube):
"""
Starts the cluster unless it has been already started by the user.
:param minikube: Executable minikube installed beforehand.
"""
status = run_command([minikube, 'status'], True)
if 'minikube: Running' in status:
print('Cluster already running')
Expand All @@ -62,19 +81,36 @@ def start_cluster(minikube):


def build_docker_images(minikube):
"""
Finds environment settings and builds docker images for each directory.
:param minikube: Executable command to run in terminal.
"""
def _vm_none_enabled():
"""
Check if the VM driver is enabled or not. This is important to see where
the environment variables live.
:return: Boolean value indicating if enabled or not.
"""
return False if 'driver does not support' in raw_env_settings else True

print('Building docker images')
raw_env_settings = run_command([minikube, 'docker-env', '--shell="bash"'], True)
print("raw_env_settings: " + raw_env_settings)
matches = re.finditer(r'^export (.+)="(.+)"$', raw_env_settings, re.MULTILINE)
env = dict([(m.group(1), m.group(2)) for m in matches])
if _vm_none_enabled():
matches = re.finditer(r'^export (.+)="(.+)"$', raw_env_settings, re.MULTILINE)
env_variables = dict([(m.group(1), m.group(2)) for m in matches])

client = docker.from_env(
environment=env,
version='auto',
)
client = docker.from_env(
environment=env_variables,
version='auto',
)
else:
# VM driver is set
client = docker.from_env(
version='auto'
)

dirs = ('aimmo-game', 'aimmo-game-creator', 'aimmo-game-worker')
for dir in dirs:
directories = ('aimmo-game', 'aimmo-game-creator', 'aimmo-game-worker')
for dir in directories:
path = os.path.join(BASE_DIR, dir)
tag = 'ocadotechnology/%s:test' % dir
print("Building %s..." % tag)
Expand All @@ -85,7 +121,13 @@ def build_docker_images(minikube):
)


def restart_pods(game_creator, ingress_yaml):
def restart_pods(game_creator_yaml, ingress_yaml):
"""
Disables all the components running in the cluster and starts them again
with fresh updated state.
:param game_creator_yaml: Replication controller yaml settings file.
:param ingress_yaml: Ingress yaml settings file.
"""
print('Restarting pods')
kubernetes.config.load_kube_config(context='minikube')
api_instance = kubernetes.client.CoreV1Api()
Expand All @@ -112,12 +154,16 @@ def restart_pods(game_creator, ingress_yaml):

extensions_api_instance.create_namespaced_ingress("default", ingress_yaml)
api_instance.create_namespaced_replication_controller(
body=game_creator,
body=game_creator_yaml,
namespace='default',
)


def start():
"""
The entry point to the minikube class. Sends calls appropriately to set
up minikube.
"""
if platform.machine().lower() not in ('amd64', 'x86_64'):
raise ValueError('Requires 64-bit')
create_test_bin()
Expand Down
3 changes: 2 additions & 1 deletion aimmo_runner/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,14 @@ def run(use_minikube, server_wait=True, capture_output=False):

server_args = []
if use_minikube:
# Import minikube here, so we can install the deps first
parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(os.path.join(parent_dir, 'aimmo_runner'))

os.chdir(ROOT_DIR_LOCATION)
run_command(['pip', 'install', '-r', os.path.join(ROOT_DIR_LOCATION, 'minikube_requirements.txt')],
capture_output=capture_output)

# Import minikube here, so we can install the deps first
from aimmo_runner import minikube
minikube.start()

Expand Down
14 changes: 9 additions & 5 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,24 @@


## Running with Kubernetes with containers
**64bit environment is required for this mode!**
* Follow the instructions at [game frontend documentation](https://github.com/ocadotechnology/aimmo/blob/master/game_frontend/README.md) in order to install all the frontend requirements.
* By default, the local environment runs each worker in a Python thread. However, for some testing, it is useful to run as a Kubernetes cluster. Note that this is not for most testing, the default is more convenient as the Kubernetes cluster is slow and runs into resource limits with ~10 avatars.
* Linux, Windows (minikube is experimental though), and OSX (untested) are supported.
* By default, the local environment runs each worker in a Python thread. This is the closest mode that reflects the environment in production. However, this will require much more resources.
* Linux, Windows, and OSX.
* Prerequisites:
* All platforms: VT-x/AMD-v virtualization.
* Linux: [Virtualbox](https://www.virtualbox.org/wiki/Downloads).
* OSX: either [Virtualbox](https://www.virtualbox.org/wiki/Downloads) or [VMWare Fusion](http://www.vmware.com/products/fusion.html).
* Download Docker, Minikube, and Kubectl before running the script.
* On Mac ([download homebrew](https://brew.sh/)) and run `brew update && brew install kubectl && brew cask install docker minikube virtualbox`.
* To download Docker, Minikube, and Kubectl before running the script.
* On Mac ([download homebrew](https://brew.sh/)) and run `brew update && brew cask install docker virtualbox`.
* Install a fixed minikube version (at the time of this article this is 0.25.2 but you can confirm that [here](https://github.com/ocadotechnology/aimmo/blob/b0fd1bf852b1b2630a8546d173798ec9a670c480/.travis.yml#L23)). To do this write
`curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.25.2/minikube-darwin-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/
` and replace the version with the desired one.
* On Ubuntu ([download snap](https://snapcraft.io/)) and run `sudo snap install kubectl --classic` then follow the ([docker installation instructions](https://docs.docker.com/install/linux/docker-ce/ubuntu/)).
* On Windows ([download chocolatey](https://chocolatey.org/)) and run `choco install kubernetes-cli` followed by the ([docker installation instructions for Windows](https://docs.docker.com/docker-for-windows/)).
* Alter your `/etc/hosts` file by adding the following to the end of the file: `192.168.99.100 local.aimmo.codeforlife.education`. You may be required to run this with `sudo` as the file is protected.
* Usage: `python run.py -k`. This will:
* Run `minikube start` (if the cluster is not already running).
* Run `minikube start --memory=2048 -cpus=2`. Feel free to change these values appropriately to your specifiation.
* Images are built and a aimmo-game-creator is created in your cluster. You can preview this in your kubernetes dashboard. Run `minikube dashboard` to open this.
* Perform the same setup that run.py normally performs.
* Start the Django project (which is not kubernetes controlled) on localhost:8000.
Expand Down

0 comments on commit 8342026

Please sign in to comment.