diff --git a/Dockerfile b/Dockerfile index 4fca59f..fb1a7e1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,15 +1,14 @@ -FROM python:3.6-slim +FROM python:3.7-slim WORKDIR /usr/src/app RUN pip install pipenv COPY Pipfile Pipfile.lock ./ -RUN pipenv install - -COPY dist/abot-0.0.1a0.tar.gz ./mosbot.tar.gz -RUN tar xf mosbot.tar.gz --strip-components=1 +RUN pipenv sync +COPY setup.cfg setup.py README.rst alembic.ini ./ +COPY alembic ./alembic +COPY mosbot ./mosbot RUN pipenv run python setup.py develop -CMD ["pipenv", "run", "bot", "run"] - +CMD ["/bin/sh", "-c", "pipenv run alembic upgrade head && pipenv run bot run"] diff --git a/README.rst b/README.rst index 5f49022..788b5bd 100644 --- a/README.rst +++ b/README.rst @@ -1,55 +1,56 @@ + How to get started ------------------ 1. Install *Pipenv* at a system level - + If you are not using it for your projects, you should. *Pipenv* is a mix between *pip* and *virtualenv* (it uses both of them below) and basically manages everything. You can probably find *Pipenv* packaged, check their webpage for installation steps. 2. Install dependencies - + In a command line, navigate to the current project directory and install the dependencies by running one of the commands below. - * To use the bot: `pipenv install` + * To use the bot: ``pipenv install`` - * To develop: `pipenv install -d` + * To develop: ``pipenv install -d`` If these steps don't work, please report it so that I can update these instructions with relevant steps. 3. Install *mostbot* as a package - - Run the command `python setup.py develop`. You can also do `python setup.py install`, but it's better to keep the - installation linked to this directory instead of having `setuptools` package and install the bot separately. If you + + Run the command ``python setup.py develop``. You can also do ``python setup.py install``, but it's better to keep the + installation linked to this directory instead of having ``setuptools`` package and install the bot separately. If you have doubts on what I just said, https://stackoverflow.com/questions/19048732/python-setup-py-develop-vs-install 4. Install a database - + Apart from the bot code, you also need a database to link the bot to. You can link it to whatever *PostgreSQL* database you want, but I would recommend you to run a local instance. - + Using *Docker* and *Docker Compose* is a really good way to run packaged software. There are complete guides on the internet about how to run them, but for the basics: 1. Install *Docker* either using your package manager or as suggested in *Docker*'s official webpage. By the way, the official website method is just a Python script, so you can also install it with *pip* (I would discourage this option). - + 2. Install *Docker Compose*. Same thing as *Docker*: user either package manager or the official webpage script. - + 3. Open another terminal in this folder. This new terminal will be used all the time to maintain up the database while your bot is running. There are other ways to run the database in the background, but I recommend this one. - - 4. In the new terminal, run `docker-compose up` to download and run the packaged software (the *PostgreSQL* + + 4. In the new terminal, run ``docker-compose up`` to download and run the packaged software (the *PostgreSQL* database in this case). - - 5. Run `alembic upgrade head` to create the database structure by setting up all the database tables, etc. + + 5. Run ``alembic upgrade head`` to create the database structure by setting up all the database tables, etc. 5. Launch *mosbot* - - Go back to the first terminal, and run `bot` to launch. The output of the command should be self explanatory. + + Go back to the first terminal, and run ``bot`` to launch. The output of the command should be self explanatory. @@ -59,20 +60,20 @@ Project structure This is a brief outline to cover the basics of the project structure: * The more inner layer and the thing that most defines the bot is the Data Model. This are the Entities that we - manage, and they are in `mosbot/db.py`. + manage, and they are in ``mosbot/db.py``. * From there, because we have no ORM at the moment (asyncio doesn't have an async ORM yet), we have all the functions - and queries that operate on the data in `mosbot/query.py`. + and queries that operate on the data in ``mosbot/query.py``. * Now you should be able to gather/write data and make some operations. There are some operations that are not as "simple" as the queries, and these are the "usecases" where you have a whole flow of queries and data transformation. - The place where these are stored is in `mosbot/usecase.py` + The place where these are stored is in ``mosbot/usecase.py`` * Finally, in the most outer layer, you have the two main "interfaces", this is where we receive the data from the - `abot` library and we have the handlers and commands. The files are, `mosbot/handler.py` for event handlers and - `mosbot/command.py` for the commands. + ``abot`` library and we have the handlers and commands. The files are, ``mosbot/handler.py`` for event handlers and + ``mosbot/command.py`` for the commands. -* There are two other files, that are "transversal" that are the `mosbot/utils.py` and `mosbot/config.py`. +* There are two other files, that are "transversal" that are the ``mosbot/utils.py`` and ``mosbot/config.py``. You should think of this architecture (file structure/function dependencies) as an onion. The idea is that the most @@ -91,6 +92,22 @@ Further recommendations rest of alternatives. Of course, you are free to choose whichever editor you want. +Using the Helm chart +-------------------- + +1. Fetch/update chart dependencies: + + .. code-block:: bash + + helm dependency update ./helm + + +2. Install mosbot chart: + + .. code-block:: bash + + helm install ./helm + Contributions ------------- diff --git a/docker-compose.yml b/docker-compose.yml index f5f767b..0bcbe57 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,16 +1,12 @@ version: '2' services: - rabbitmq: - image: rabbitmq:management - ports: - - "15672:15672" - - "5672:5672" - - "4369:4369" - redis: - image: redis - ports: - - "6379:6379" postgres: image: mdillon/postgis ports: - "5432:5432" + # mosbot: + # image: dtgoitia/mosbot:latest + # environment: + # DATABASE_URL: postgresql://postgres@postgres/postgres + # depends_on: + # - postgres diff --git a/helm/Chart.yaml b/helm/Chart.yaml new file mode 100644 index 0000000..554c777 --- /dev/null +++ b/helm/Chart.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +name: mosbot +description: Master of Soundtrack bot +version: 0.0.1 +appVersion: 0.0.1 +home: https://github.com/txomon/mosbot +sources: + - https://github.com/txomon/mosbot +keywords: + - bot + - mosbot + - master of soundtrack +maintainers: + - name: txomon + email: javierdo1@gmail.com diff --git a/helm/charts/common-0.0.5.tgz b/helm/charts/common-0.0.5.tgz new file mode 100644 index 0000000..ca0a64a Binary files /dev/null and b/helm/charts/common-0.0.5.tgz differ diff --git a/helm/charts/postgresql-3.13.1.tgz b/helm/charts/postgresql-3.13.1.tgz new file mode 100644 index 0000000..b9feaf6 Binary files /dev/null and b/helm/charts/postgresql-3.13.1.tgz differ diff --git a/helm/requirements.lock b/helm/requirements.lock new file mode 100644 index 0000000..060f6c9 --- /dev/null +++ b/helm/requirements.lock @@ -0,0 +1,9 @@ +dependencies: +- name: common + repository: http://storage.googleapis.com/kubernetes-charts-incubator + version: 0.0.5 +- name: postgresql + repository: https://kubernetes-charts.storage.googleapis.com + version: 3.13.1 +digest: sha256:e1563a17669e7c46c9db98c4322374903cd88974b24634e0334047f98c2eacc3 +generated: "2019-05-19T08:39:48.617716388+01:00" diff --git a/helm/requirements.yaml b/helm/requirements.yaml new file mode 100644 index 0000000..3bf437d --- /dev/null +++ b/helm/requirements.yaml @@ -0,0 +1,7 @@ +dependencies: + - name: common + repository: http://storage.googleapis.com/kubernetes-charts-incubator + version: 0.0.5 + - name: postgresql + repository: https://kubernetes-charts.storage.googleapis.com + version: 3.13.1 diff --git a/helm/templates/NOTES.txt b/helm/templates/NOTES.txt new file mode 100644 index 0000000..6a10e4a --- /dev/null +++ b/helm/templates/NOTES.txt @@ -0,0 +1,21 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ . }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "mosbot-chart.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "mosbot-chart.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "mosbot-chart.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "mosbot-chart.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl port-forward $POD_NAME 8080:80 +{{- end }} diff --git a/helm/templates/_helpers.tpl b/helm/templates/_helpers.tpl new file mode 100644 index 0000000..d662b2b --- /dev/null +++ b/helm/templates/_helpers.tpl @@ -0,0 +1,27 @@ +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "mosbot-chart.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* Generate PostgreSQL database URL */}} +{{- define "mosbot-chart.databaseurl" -}} + postgresql:// + {{- .Values.postgresql.postgresqlUsername -}}: + {{- .Values.postgresql.postgresqlPassword -}}@ + {{- .Release.Name }}-postgresql. + {{- .Release.Namespace -}}/ + {{- .Values.postgresql.postgresqlDatabase -}} +{{- end -}} diff --git a/helm/templates/deployment.yaml b/helm/templates/deployment.yaml new file mode 100644 index 0000000..80bfe17 --- /dev/null +++ b/helm/templates/deployment.yaml @@ -0,0 +1,20 @@ +{{- template "common.deployment" (list . "mosbot.deployment") -}} +{{- define "mosbot.deployment" -}} +spec: + replicas: {{ .Values.replicaCount }} + template: + spec: + containers: + - {{ template "common.container" (list . "mosbot.deployment.container") }} +{{- end -}} +{{- define "mosbot.deployment.container" -}} +env: + - name: DATABASE_URL + value: {{ template "mosbot-chart.databaseurl" . }} + {{ if and .Values.dubtrackUsername .Values.dubtrackPassword -}} + - name: DUBTRACK_USERNAME + value: {{ .Values.dubtrackUsername | quote }} + - name: DUBTRACK_PASSWORD + value: {{ .Values.dubtrackPassword | quote }} + {{ end -}} +{{- end -}} diff --git a/helm/values.yaml b/helm/values.yaml new file mode 100644 index 0000000..b442191 --- /dev/null +++ b/helm/values.yaml @@ -0,0 +1,29 @@ +image: + repository: dtgoitia/mosbot + tag: latest + pullPolicy: IfNotPresent + +replicaCount: 1 + +# TODO: setup ingress +service: + type: NodePort + port: 80 + +# Dubtrack credentials +# dubtrackUsername: rococo +# dubtrackPassword: 1234 + +ingress: + enabled: false + tls: false + hosts: + - host: mosbot-chart.local + paths: [] + +postgresql: + postgresqlUsername: dbUser + postgresqlPassword: pass1234 + postgresqlDatabase: myPostgresDatabaseName + service: + port: 5432 diff --git a/setup.py b/setup.py index 2db43af..341cc24 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,7 @@ ] }, install_requires=[ - 'abot==0.0.1a1.post0.dev23', + 'abot==0.0.1a1.post0.dev30', 'aiopg', 'alembic', 'asyncio-extras',