# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['gefyra', 'gefyra.api', 'gefyra.cluster', 'gefyra.local']

package_data = \
{'': ['*'], 'gefyra.local': ['cargo/*']}

install_requires = \
['docker>=5.0.3,<6.0.0', 'kubernetes>=19.15.0,<20.0.0']

entry_points = \
{'console_scripts': ['gefyra = gefyra.__main__:main']}

setup_kwargs = {
    'name': 'gefyra',
    'version': '0.1.2',
    'description': "Gefyra runs all developer machine side components of Gefyra's Kubernetes-based development infrastructure",
    'long_description': '# Gefyra\nGefyra gives Kubernetes-("cloud-native")-developers a completely new way of writing and testing their applications. \nGone are the times of custom Docker-compose setups, Vagrants, custom scrips or other scenarios in order to develop (micro-)services\nfor Kubernetes.  \n\nGefyra offers you to:\n- run services locally on a developer machine\n- operate feature-branches in production-like Kubernetes environment with all adjacent services\n- write code in the IDE you already love, be fast, be confident\n- leverage all the neat development features, such as debugger, code-hot-reloading, override environment variables\n- run high-level integration tests against all dependant services\n- keep peace-of-mind when pushing new code to the integration environment \n\nGefyra was designed to be fast and robust on an average developer machine including most platforms.\n\n## Table of contents\n- [What is Gefyra?](#what-is-gefyra)\n- [Did I hear developer convenience?](#did-i-hear-developer-convenience)\n- [Installation](#installation)\n- [Try it yourself](#try-it-yourself)\n- [How does it work?](#how-does-it-work)\n  - [Docker](#docker)\n  - [Wireguard](#wireguard)\n  - [CoreDNS](#coredns)\n  - [Nginx](#nginx)\n- [Architecture of the entire development system](#architecture-of-the-entire-development-system)\n  - [Local development setup](#local-development-setup)\n  - [The _bridge_ operation in action](#the-_bridge_-operation-in-action)\n\n## What is Gefyra?\nGefyra is a toolkit written in Python to arrange a local development infrastructure in order to produce software for and with \nKubernetes while having fun. It is installed on any development computer and starts its work when it is asked. Gefyra runs\nas user-space application and controls the local Docker host and Kubernetes via _Kubernetes Python Client_. \n\n<p align="center">\n  <img src="https://github.com/Schille/gefyra/raw/main/docs/static/img/gefyra-intro.png" alt="Gefyra controls docker and kubeapi"/>\n</p>\n\n(_Kubectl_ is not really required but makes kinda sense to be in this picture)\n\nIn order for this to work, a few requirements have to be satisfied:\n- a Docker host must be available for the user on the development machine\n- there are a few container capabilities required on both sides, within the Kubernetes cluster and on the local computer\n- a node port must be opened on the development cluster for the duration of the development work \n\nGefyra makes sure your development container runs as part of the cluster while you still have full access to it. In addition\nGefyra is able to intercept the target application running within the cluster, i.e. a container in a Pod, and tunnels all traffic hitting said container to the one running \nlocally. Now, developers can add new code or fix bugs and run it right away in the Kubernetes cluster, or simply introspect the traffic. \nGefyra provides the entire infrastructure to do so and provides a high level of developer convenience. \n\n\n## Did I hear developer convenience?\nThe idea is to relieve developers from the hassle with containers to go back and forth to the integration system. Instead, take\nthe integration system closer to the developer and make the development cycles as short as possible. No more waiting for the CI to complete\njust to see the service failing on the first request. Cloud-native (or Kubernetes-native) technologies have completely changed the \ndeveloper experience: infrastructure is increasingly becoming part of developer\'s business with all the barriers and obstacles, but also chances\nto turn the software for a better.  \nGefyra is here to provide a development workflow with the highest convenience possible. It brings low setup times, rapid development, \nhigh release cadence and super-satisfied managers.\n\n## Installation\nTodo\n\n\n## Try it yourself\nYou can easily try Gefyra yourself following this small example:   \n1) Follow the installation  \n2) Create a a local Kubernetes cluster with `k3d` like so:    \n**< v5** `k3d cluster create mycluster --agents 1 -p 8080:80@agent[0] -p 31820:31820/UDP@agent[0]`  \n**>= v5** `k3d cluster create mycluster --agents 1 -p 8080:80@agent:0 -p 31820:31820/UDP@agent:0`  \nThis creates a Kubernetes cluster that binds port 8080 and 31820 to localhost. `Kubectl` context is immediately set to this cluster.\n3) Apply some workload, for example from the testing directory:  \n`kubectl apply -f testing/workloads/hello.yaml`\nCheck out this workload running under: http://hello.127.0.0.1.nip.io:8080/    \n4) Set up Gefyra with `python -m gefyra up`\n5) Run a local Docker image with Gefyra in order to  make it part of the cluster.  \n  a) Build your Docker image with a local tag, for example from the testing directory:  \n   `cd testing/images/ && docker build -f Dockerfile.local . -t mypyserver`  \n  b) Execute Gefyra\'s run command (**sudo password is required**):    \n   `python -m gefyra run -i pyserver -N mypyserver -n default`  \n  c) _Exec_ into the running container and look around. You will find the container to run within your Kubernetes cluster.  \n   `docker exec -it mypyserver bash`  \n   `wget -O- hello-nginx` will print out the website of the cluster service _hello-nginx_ from within the cluster.\n6) Create a bridge in order to intercept the traffic to the cluster application with the one running locally:    \n`python -m gefyra bridge -N mypyserver -n default --deployment hello-nginxdemo --port 8000 --container-name hello-nginx --container-port 80 -I mypybridge`    \nCheck out the locally running server comes up under: http://hello.127.0.0.1.nip.io:8080/  \n7) List all running _bridges_:  \n`python -m gefyra list --bridges`\n8) _Unbridge_ the local container and reset the cluster to its original state: \n`python -m gefyra unbridge -N mypybridge`\nCheck out the initial response from: http://hello.127.0.0.1.nip.io:8080/  \n9) Free the cluster up from Gefyra\'s componentens with `python -m gefyra down`\n10) Remove the locally running Kubernetes cluster with `k3d cluster delete mycluster`\n\n## How does it work?\nIn order to write software for and with Kubernetes, obviously a Kubernetes cluster is required. There are already a number of Kubernetes \ndistributions available to run everything locally. A cloud-based Kubernetes cluster can be connected as well in order to spare the development\ncomputer from blasting off.\nA working _KUBECONFIG_ connection is required with appropriate permissions which should always be the case for local clusters. Gefyra installs the required \ncluster-side components by itself once a development setup is about to be established.\n\n<p align="center">\n  <img src="https://github.com/Schille/gefyra/raw/main/docs/static/img/gefyra-overview.png" alt="Gefyra connects to a Kubernetes cluster"/>\n</p>\n\nWith these components, Gefyra is able to control a local development machine, and the development cluster, too. Both sides are now in the hand of \nGefyra.  \nOnce the developer\'s work is done, Gefyra well and truly removes all components from the cluster without leaving a trace.  \n\nA few things are required in order to achieve this:\n- a _tunnel_ between the local development machine and the Kubernetes cluster\n- a local end of that tunnel to steer the traffic, DNS, and encrypt everything passing over the line\n- a cluster end of the tunnel, forwarding traffic, taking care of the encryption\n- a local DNS resolver that behaves like the cluster DNS\n- sophisticated IP routing mechanisms\n- a traffic interceptor for containers already running withing the Kubernetes cluster\n\nGefyra builds on top of the following popular open-source technologies:\n\n### Docker\n[*Docker*](https://docker.io) is currently used in order to manage the local container-based development setup, including the\nhost, networking and container management procedures.\n\n### Wireguard\n[*Wireguard*](https://wireguard.com) is used to establish the connection tunnel between the two ends. It securely encrypts the UDP-based traffic\nand allows to create a _site-to-site_ network for Gefyra. That way, the development setup becomes part of the cluster and locally running containers \nare actually able to reach cluster-based resources, such as databases, other (micro)services and so on.\n\n### CoreDNS\n[*CoreDNS*](https://coredns.io) provides local DNS functionality. It allows resolving resources running within the Kubernetes cluster.\n\n### Nginx\n[*Nginx*](https://www.nginx.com/) is used for all kinds of proxying and reverse-proxying traffic, including the interceptions of already running containers\nin the cluster.\n\n### Rsync\n[*Rsync*](https://rsync.samba.org/) is used to synchronize directories from containers running in the cluster to local\ninstances. This is particularly important for Kubernetes service account tokens during a bridge operation.\n\n## Architecture of the entire development system\n\n### Local development setup\nThe local development happens with a running container instance of the application in question on the developer machine.\nGefyra takes care of the local Docker host setup, and hence needs access to it. It creates a dedicated Docker network \nwhich the container is deployed to. Next to the developed application, Gefyra places a _sidecar_ container. This container,\nas a component of Gefyra, is called _Cargo_.  \nCargo acts as a network gateway for the app container and, as such, takes care of the IP routing into and from the cluster.\nIn addition, Cargo provides a CoreDNS server which forwards all request to the cluster. That way, the app container will be\nable to resolve cluster resources and may not resolve domain names that are not supposed to be resolved (think of \nisolated application scenarios).\nCargo encrypts all the passing traffic with Wireguard using ad-hoc connection secrets. \n\n<p align="center">\n  <img src="https://github.com/Schille/gefyra/raw/main/docs/static/img/gefyra-development.png" alt="Gefyra local development"/>\n</p>\n\nThis local setup allows developers to use their existing tooling, including their favorite code editor and debuggers. The\napplication, when it is supported, can perform code-hot-reloading upon changes and pipe logging output to a local shell \n(or other systems).  \nOf course, developers are able to mount local storage volumes into the container, override environment variables and modify\neverything as they\'d like to.  \nReplacing a container in the cluster with a local instance is called _bridge_: from an architectural perspective the application is _bridged_ into the cluster.\nIf the container is already running within a Kubernetes Pod, it gets replaced and all traffic to the originally running \ncontainer is proxied to the one on the developer machine.  \nDuring the container startup of the application, Gefyra modifies the container\'s networking from the outside and sets the \n_default gateway_ to Cargo. That way, all container\'s traffic is passed to the cluster via Cargo\'s encrypted tunnel. The\nsame procedure can be applied for multiple app containers at the same time.  \n\nThe neat part is that with a debugger and two or more _bridged_ containers, developers can introspect requests from the source\nto the target and back around while being attached to both ends.\n\n### The _bridge_ operation in action \nThis chapter covers the important _bridge_ operation by following an example.\n\n#### Before the bridge operation\nThink of a provisioned Kubernetes cluster running some workload. There is an Ingress, Kubernetes Services and Pods running\ncontainers. Some of them use the _sidecar_ (https://medium.com/nerd-for-tech/microservice-design-pattern-sidecar-sidekick-pattern-dbcea9bed783) pattern.\n\n<p align="center">\n  <img src="https://github.com/Schille/gefyra/raw/main/docs/static/img/gefyra-process-step-1.png" alt="Gefyra development workflow_step1"/>\n</p>\n\n#### Preparing the bridge operation\nBefore the _brigde_ can happen, Gefyra installs all required components to the cluster. A valid and privileged connection\nmust be available on the developer machine to do so.  \nThe main component is the cluster agent called _Stowaway_. The Stowaway controls the cluster side of the tunnel connection.\nIt is operated by [Gefyra\'s Operator application](operator).\n\n<p align="center">\n  <img src="https://github.com/Schille/gefyra/raw/main/docs/static/img/gefyra-process-step-2.png" alt="Gefyra development workflow step 2"/>\n</p>\n\nStowaway boots up and dynamically creates Wireguard connection secrets (private/public key-pair) for itself and Cargo.\nGefyra copies these secrets to Cargo for it to establish a connection. This is a UDP connection. It requires a Kubernetes\nService of kind _nodeport_ to allow the traffic to pass through *for the time of an active development session*. Gefyra\'s \noperator installs these components with the requested parameters and removes it after the session terminates.  \nBy the way: Gefyra\'s operator removes all components and itself from the cluster in case the connection was disrupted \nfor some time, too.  \nOnce a connection could be establised from Cargo to Stowaway, Gefyra spins up the app container on the local side for the\ndeveloper to start working.  \nAnother job of Gefyra\'s operator is to rewrite the target Pods, i.e. exchange the running container through Gefyras proxy,\ncalled _Carrier_.  \nFor that, it creates a temporary Kubernetes Service that channels the Ingress traffic (or any other kind of cluster internal\ntraffic) to the container through Stowaway and Cargo to the locally running app container. \n\n\n#### During the bridge operation\nA bridge can robustly run as long as it is required to (given the connection does not drop in the meanwhile).\nLooking at the example, Carrier was installed in Pod &lt;C&gt; on port _XY_. That port was previously occupied by the container\nrunning originally here. In most cases, the local app container represents the development version of that originally\nprovisioned container. Traffic coming from the Ingress, passing on to the Service &lt;C&gt; hits Carrier (the proxy). Carrier\nbends the request to flow through Gefyras Service to the local app container via Stowaway\' and Cargo\'s tunnel. This works\nsince the app container\'s IP is routable from within the cluster.  \nThe local app container does not simply return a response, but fires up another subsequent request by itself to \nService &lt;A&gt;. The request roams from the local app container back into the cluster and hits Pod &lt;A&gt;\'s container via \nService &lt;A&gt;. The response is awaited.  \nOnce the local app container is done with constructing its initial answer the response gets back to Carrier and afterwards\nto the Ingress and back to the client.\n\n<p align="center">\n  <img src="https://github.com/Schille/gefyra/raw/main/docs/static/img/gefyra-process-step-3.png" alt="Gefyra development workflow step 3"/>\n</p>\n\nWith that, the local development container is reachable exactly the same way another container from within the cluster \nwould be. That fact is a major advantage, especially for frontend applications or domain-sensitive services.  \nDevelopers now can run local integration tests with new software while having access to all interdependent services.  \nOnce the development job is done, Gefyra properly removes everything, resets Pod &lt;C&gt; to its original configuration,\nand tears the local environment down (just like nothing ever happened).\n\nDoge is excited about that.\n\n<p align="center">\n  <img src="https://github.com/Schille/gefyra/raw/main/docs/static/img/doge.jpg" alt="Doge is excited"/>\n</p>\n\n\n## Credits\nTodo\n\n\n\n\n\n',
    'author': 'Michael Schilonka',
    'author_email': 'michael@blueshoe.de',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/Schille/gefyra',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'entry_points': entry_points,
    'python_requires': '>=3.8,<4.0',
}


setup(**setup_kwargs)
