Browse Source

Añado versión de reymota para funcionar con longhorn

politica
Celestino Rey 9 months ago
parent
commit
674c1f93ba
2443 changed files with 437482 additions and 9 deletions
  1. +0
    -2
      Libros/K8S/Makefile
  2. +2
    -0
      Libros/K8S/libros-prod-persistentvolumeclaim.yaml
  3. +1
    -0
      Libros/K8S/static-volume-persistentvolumeclaim.yaml
  4. +2
    -6
      LyricsPy/K8S/Makefile
  5. +1
    -1
      LyricsPy/K8S/entra.sh
  6. +31
    -0
      LyricsPy/K8S/lyrics-ingress.yaml
  7. +1
    -0
      LyricsPy/K8S/lyrics-prod-persistentvolumeclaim.yaml
  8. +8
    -0
      LyricsPy/K8S/reg-secret.yaml
  9. +3
    -0
      ReyMotaAppsRancher/.dockerignore
  10. +73
    -0
      ReyMotaAppsRancher/Dockerfile
  11. +1
    -0
      ReyMotaAppsRancher/K8S/.gitignore
  12. +20
    -0
      ReyMotaAppsRancher/K8S/ConfigMaps/env-prod-configmap-local.yaml
  13. +20
    -0
      ReyMotaAppsRancher/K8S/ConfigMaps/env-prod-configmap.yaml
  14. +11
    -0
      ReyMotaAppsRancher/K8S/ConfigMaps/env-prod-db-configmap.yaml
  15. +53
    -0
      ReyMotaAppsRancher/K8S/Deployments/db-deployment.yaml
  16. +46
    -0
      ReyMotaAppsRancher/K8S/Deployments/nginx-deployment.yaml
  17. +126
    -0
      ReyMotaAppsRancher/K8S/Deployments/reymota-deployment.yaml
  18. +60
    -0
      ReyMotaAppsRancher/K8S/Makefile
  19. +13
    -0
      ReyMotaAppsRancher/K8S/PVC/postgres-data-persistentvolumeclaim.yaml
  20. +63
    -0
      ReyMotaAppsRancher/K8S/PVC/reymota-prod-persistentvolumeclaim.yaml
  21. +13
    -0
      ReyMotaAppsRancher/K8S/PVC/static-volume-persistentvolumeclaim.yaml
  22. +17
    -0
      ReyMotaAppsRancher/K8S/Services/db-service.yaml
  23. +20
    -0
      ReyMotaAppsRancher/K8S/Services/nginx-service.yaml
  24. +31
    -0
      ReyMotaAppsRancher/K8S/Services/reymota-ingress.yaml
  25. +12
    -0
      ReyMotaAppsRancher/K8S/Services/reymota-service.yaml
  26. +2
    -0
      ReyMotaAppsRancher/K8S/Shells/borraNS.sh
  27. +1
    -0
      ReyMotaAppsRancher/K8S/Shells/entra.sh
  28. +1
    -0
      ReyMotaAppsRancher/K8S/Shells/entraPsql.sh
  29. +7
    -0
      ReyMotaAppsRancher/K8S/namespace.yaml
  30. +8
    -0
      ReyMotaAppsRancher/K8S/reg-secret.yaml
  31. +8
    -0
      ReyMotaAppsRancher/Makefile
  32. +49
    -0
      ReyMotaAppsRancher/README.md
  33. +20
    -0
      ReyMotaAppsRancher/entrypoint.sh
  34. +4
    -0
      ReyMotaAppsRancher/nginx/Dockerfile
  35. +8
    -0
      ReyMotaAppsRancher/nginx/Makefile
  36. +25
    -0
      ReyMotaAppsRancher/nginx/nginx.conf
  37. +20
    -0
      ReyMotaAppsRancher/requirements.txt
  38. +1
    -0
      ReyMotaAppsRancher/reymota/accounts/.gitignore
  39. +0
    -0
      ReyMotaAppsRancher/reymota/accounts/__init__.py
  40. +3
    -0
      ReyMotaAppsRancher/reymota/accounts/admin.py
  41. +6
    -0
      ReyMotaAppsRancher/reymota/accounts/apps.py
  42. +3
    -0
      ReyMotaAppsRancher/reymota/accounts/models.py
  43. +3
    -0
      ReyMotaAppsRancher/reymota/accounts/tests.py
  44. +8
    -0
      ReyMotaAppsRancher/reymota/accounts/urls.py
  45. +1
    -0
      ReyMotaAppsRancher/reymota/accounts/views.py
  46. +6
    -0
      ReyMotaAppsRancher/reymota/entornoPruebas.sh
  47. +0
    -0
      ReyMotaAppsRancher/reymota/lyrics/__init__.py
  48. +9
    -0
      ReyMotaAppsRancher/reymota/lyrics/admin.py
  49. +6
    -0
      ReyMotaAppsRancher/reymota/lyrics/apps.py
  50. +41
    -0
      ReyMotaAppsRancher/reymota/lyrics/forms.py
  51. +0
    -0
      ReyMotaAppsRancher/reymota/lyrics/management/__init__.py
  52. +0
    -0
      ReyMotaAppsRancher/reymota/lyrics/management/commands/__init__.py
  53. +48
    -0
      ReyMotaAppsRancher/reymota/lyrics/management/commands/importar_albumes.py
  54. +42
    -0
      ReyMotaAppsRancher/reymota/lyrics/management/commands/importar_artistas.py
  55. +51
    -0
      ReyMotaAppsRancher/reymota/lyrics/management/commands/importar_canciones.py
  56. +52
    -0
      ReyMotaAppsRancher/reymota/lyrics/migrations/0001_initial.py
  57. +0
    -0
      ReyMotaAppsRancher/reymota/lyrics/migrations/__init__.py
  58. +42
    -0
      ReyMotaAppsRancher/reymota/lyrics/models.py
  59. +39
    -0
      ReyMotaAppsRancher/reymota/lyrics/serializers.py
  60. +3
    -0
      ReyMotaAppsRancher/reymota/lyrics/tests.py
  61. +39
    -0
      ReyMotaAppsRancher/reymota/lyrics/urls.py
  62. +251
    -0
      ReyMotaAppsRancher/reymota/lyrics/views.py
  63. +22
    -0
      ReyMotaAppsRancher/reymota/manage.py
  64. BIN
      ReyMotaAppsRancher/reymota/mediafiles/profile_images/default.jpg
  65. BIN
      ReyMotaAppsRancher/reymota/mediafiles/profile_images/gravatar-tino.jpeg
  66. BIN
      ReyMotaAppsRancher/reymota/mediafiles/profile_images/gravatar-tino_jqB0Vq4.jpeg
  67. BIN
      ReyMotaAppsRancher/reymota/mediafiles/vehiculos/bmw.jpg
  68. BIN
      ReyMotaAppsRancher/reymota/mediafiles/vehiculos/bmw.png
  69. BIN
      ReyMotaAppsRancher/reymota/mediafiles/vehiculos/bmw_PMjCK7Q.png
  70. BIN
      ReyMotaAppsRancher/reymota/mediafiles/vehiculos/bmw_cSbhRuf.png
  71. BIN
      ReyMotaAppsRancher/reymota/mediafiles/vehiculos/bmw_x00n9W7.png
  72. BIN
      ReyMotaAppsRancher/reymota/mediafiles/vehiculos/bmw_yVyuq4g.jpg
  73. +1
    -0
      ReyMotaAppsRancher/reymota/repostajes/.gitignore
  74. +0
    -0
      ReyMotaAppsRancher/reymota/repostajes/__init__.py
  75. +9
    -0
      ReyMotaAppsRancher/reymota/repostajes/admin.py
  76. +6
    -0
      ReyMotaAppsRancher/reymota/repostajes/apps.py
  77. +41
    -0
      ReyMotaAppsRancher/reymota/repostajes/forms.py
  78. +0
    -0
      ReyMotaAppsRancher/reymota/repostajes/management/__init__.py
  79. +0
    -0
      ReyMotaAppsRancher/reymota/repostajes/management/commands/__init__.py
  80. +53
    -0
      ReyMotaAppsRancher/reymota/repostajes/management/commands/importar_repostajes.py
  81. +42
    -0
      ReyMotaAppsRancher/reymota/repostajes/management/commands/importar_vehiculos.py
  82. +27
    -0
      ReyMotaAppsRancher/reymota/repostajes/models.py
  83. +24
    -0
      ReyMotaAppsRancher/reymota/repostajes/serializers.py
  84. +12
    -0
      ReyMotaAppsRancher/reymota/repostajes/static/css/portal.css
  85. +21
    -0
      ReyMotaAppsRancher/reymota/repostajes/static/images/app-logo.svg
  86. BIN
      ReyMotaAppsRancher/reymota/repostajes/static/images/background/background-1.jpg
  87. BIN
      ReyMotaAppsRancher/reymota/repostajes/static/images/background/background-2.jpg
  88. BIN
      ReyMotaAppsRancher/reymota/repostajes/static/images/background/background-3.jpg
  89. BIN
      ReyMotaAppsRancher/reymota/repostajes/static/images/background/background-palmeras.jpg
  90. BIN
      ReyMotaAppsRancher/reymota/repostajes/static/images/doc-thumb-1.jpg
  91. BIN
      ReyMotaAppsRancher/reymota/repostajes/static/images/doc-thumb-2.jpg
  92. BIN
      ReyMotaAppsRancher/reymota/repostajes/static/images/favicon.ico
  93. BIN
      ReyMotaAppsRancher/reymota/repostajes/static/images/favicon.png
  94. +21
    -0
      ReyMotaAppsRancher/reymota/repostajes/static/images/portal-logo.svg
  95. BIN
      ReyMotaAppsRancher/reymota/repostajes/static/images/profiles/profile-1.png
  96. BIN
      ReyMotaAppsRancher/reymota/repostajes/static/images/profiles/profile-2.png
  97. BIN
      ReyMotaAppsRancher/reymota/repostajes/static/images/profiles/profile-3.png
  98. BIN
      ReyMotaAppsRancher/reymota/repostajes/static/images/profiles/profile-4.png
  99. BIN
      ReyMotaAppsRancher/reymota/repostajes/static/images/profiles/profile-5.png
  100. BIN
      ReyMotaAppsRancher/reymota/repostajes/static/images/profiles/profile-6.png

+ 0
- 2
Libros/K8S/Makefile View File

@ -14,7 +14,6 @@ install:
-kubectl create -f env-prod-configmap.yaml -kubectl create -f env-prod-configmap.yaml
-kubectl create -f env-prod-db-configmap.yaml -kubectl create -f env-prod-db-configmap.yaml
-kubectl create -f pv-local-libros.yaml
-kubectl create -f libros-prod-persistentvolumeclaim.yaml -kubectl create -f libros-prod-persistentvolumeclaim.yaml
-kubectl create -f static-volume-persistentvolumeclaim.yaml -kubectl create -f static-volume-persistentvolumeclaim.yaml
-kubectl create -f postgres-data-persistentvolumeclaim.yaml -kubectl create -f postgres-data-persistentvolumeclaim.yaml
@ -40,7 +39,6 @@ clean:
-kubectl delete -f postgres-data-persistentvolumeclaim.yaml -kubectl delete -f postgres-data-persistentvolumeclaim.yaml
-kubectl delete -f static-volume-persistentvolumeclaim.yaml -kubectl delete -f static-volume-persistentvolumeclaim.yaml
-kubectl delete -f libros-prod-persistentvolumeclaim.yaml -kubectl delete -f libros-prod-persistentvolumeclaim.yaml
-kubectl delete -f pv-local-libros.yaml
-kubectl delete -f reg-secret.yaml -kubectl delete -f reg-secret.yaml
-kubectl delete -f namespace.yaml -kubectl delete -f namespace.yaml


+ 2
- 0
Libros/K8S/libros-prod-persistentvolumeclaim.yaml View File

@ -7,6 +7,7 @@ metadata:
name: libros-media name: libros-media
namespace: libros namespace: libros
spec: spec:
storageClassName: longhorn
accessModes: accessModes:
- ReadWriteOnce - ReadWriteOnce
resources: resources:
@ -23,6 +24,7 @@ metadata:
name: libros-migrations name: libros-migrations
namespace: libros namespace: libros
spec: spec:
storageClassName: longhorn
accessModes: accessModes:
- ReadWriteOnce - ReadWriteOnce
resources: resources:


+ 1
- 0
Libros/K8S/static-volume-persistentvolumeclaim.yaml View File

@ -11,3 +11,4 @@ spec:
resources: resources:
requests: requests:
storage: 70Mi storage: 70Mi
storageClassName: longhorn

+ 2
- 6
LyricsPy/K8S/Makefile View File

@ -6,13 +6,9 @@ imagen:
cd ../servicios; make cd ../servicios; make
install: install:
-kubectl create -f namespace.yaml
-kubectl create -f pv-local-lyrics.yaml
-kubectl create -f lyrics-prod-persistentvolumeclaim.yaml
-kubectl create -f reg-secret.yaml
-envsubst < lyrics-deployment.yaml |kubectl create -f - -envsubst < lyrics-deployment.yaml |kubectl create -f -
clean: clean:
-envsubst < lyrics-deployment.yaml |kubectl delete -f - -envsubst < lyrics-deployment.yaml |kubectl delete -f -
-kubectl delete -f lyrics-prod-persistentvolumeclaim.yaml
-kubectl delete -f pv-local-lyrics.yaml
-kubectl delete -f namespace.yaml
-kubectl delete -f reg-secret.yaml

+ 1
- 1
LyricsPy/K8S/entra.sh View File

@ -1 +1 @@
kubectl exec -ti deployment.apps/lyrics -- /bin/bash
kubectl -n lyrics exec -ti deployment.apps/lyrics -- /bin/bash

+ 31
- 0
LyricsPy/K8S/lyrics-ingress.yaml View File

@ -0,0 +1,31 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
generation: 1
managedFields:
- apiVersion: networking.k8s.io/v1
fieldsType: FieldsV1
fieldsV1:
f:spec:
f:defaultBackend:
.: {}
f:service:
.: {}
f:name: {}
f:port: {}
f:rules: {}
manager: rancher
operation: Update
name: lyrics
namespace: lyrics
spec:
defaultBackend:
service:
name: lyrics
port:
number: 5000
ingressClassName: lyrics
rules:
- host: lyrics.rancher.reymota.lab
status:
loadBalancer: {}

+ 1
- 0
LyricsPy/K8S/lyrics-prod-persistentvolumeclaim.yaml View File

@ -7,6 +7,7 @@ metadata:
name: lyrics-prod name: lyrics-prod
namespace: lyrics namespace: lyrics
spec: spec:
storageClassName: longhorn
accessModes: accessModes:
- ReadWriteOnce - ReadWriteOnce
resources: resources:


+ 8
- 0
LyricsPy/K8S/reg-secret.yaml View File

@ -0,0 +1,8 @@
apiVersion: v1
kind: Secret
metadata:
name: myregistrykey
namespace: lyrics
data:
.dockerconfigjson: ewoJImF1dGhzIjogewoJCSJyZWdpc3RyeS5yZXltb3RhLmVzIjogewoJCQkiYXV0aCI6ICJZM0psZVd4dmNHVjZPbEpsZVMweE1UYzIiCgkJfQoJfQp9
type: kubernetes.io/dockerconfigjson

+ 3
- 0
ReyMotaAppsRancher/.dockerignore View File

@ -0,0 +1,3 @@
Dockerfile
Makefile
venv/

+ 73
- 0
ReyMotaAppsRancher/Dockerfile View File

@ -0,0 +1,73 @@
# syntax=docker/dockerfile:1
##################
# BUILDER #
##################
FROM python:3.11.4-slim-buster AS builder
# set work directory
WORKDIR /app
# set environment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
# install system dependencies
RUN apt-get update && \
apt-get install -y --no-install-recommends gcc
# lint
RUN pip install --upgrade pip
RUN pip install flake8==6.0.0
COPY . /app/
RUN flake8 --ignore=E501,F401,E126 .
COPY ./requirements.txt .
RUN pip wheel --no-cache-dir --no-deps --wheel-dir /app/wheels -r requirements.txt
##################
# FINAL #
##################
FROM python:3.11.4-slim-buster
# create directory for the app user
RUN mkdir -p /app
# create the app user
#RUN addgroup --system app && adduser --system --group app
# create the appropriate directories
ENV APP_HOME=/app
RUN mkdir -p $APP_HOME
#RUN mkdir -p $APP_HOME/staticfiles
#RUN mkdir -p $APP_HOME/mediafiles
WORKDIR $APP_HOME
# install system dependencies
RUN apt-get update && apt-get install -y sqlite3 netcat vim procps curl jq
COPY --from=builder /app/wheels /wheels
COPY --from=builder /app/requirements.txt .
RUN pip install --upgrade pip
RUN pip install --no-cache /wheels/*
# copy entrypoint.sh
COPY ./entrypoint.sh .
# copy project
COPY . $APP_HOME
# chown all the files to the app user
#RUN chown -R app:app $APP_HOME
# change to the app user
#USER app
WORKDIR $APP_HOME/reymota
# run entrypoint.sh
ENTRYPOINT ["/app/entrypoint.sh"]

+ 1
- 0
ReyMotaAppsRancher/K8S/.gitignore View File

@ -0,0 +1 @@
temp.json

+ 20
- 0
ReyMotaAppsRancher/K8S/ConfigMaps/env-prod-configmap-local.yaml View File

@ -0,0 +1,20 @@
apiVersion: v1
data:
DEBUG: "True"
ENTORNO: "Pruebas"
DJANGO_ALLOWED_HOSTS: "ranchermota.es vmcluster k8s-server localhost 127.0.0.1 [::1]"
CSRF_TRUSTED_ORIGINS: "https://ranchermota.es http://vmcluster"
SECRET_KEY: change_me
SQL_DATABASE: reymota
SQL_ENGINE: django.db.backends.postgresql
SQL_HOST: db
SQL_PASSWORD: Dsa-0213
SQL_PORT: "5432"
SQL_USER: creylopez
DATABASE: postgres
kind: ConfigMap
metadata:
labels:
io.kompose.service: web-env-prod
name: env-prod
namespace: ranchermota

+ 20
- 0
ReyMotaAppsRancher/K8S/ConfigMaps/env-prod-configmap.yaml View File

@ -0,0 +1,20 @@
apiVersion: v1
data:
DEBUG: "True"
ENTORNO: "Producción"
DJANGO_ALLOWED_HOSTS: "ranchermota.rancher.reymota.lab reymota.es vmcluster k8s-server localhost 127.0.0.1 [::1]"
CSRF_TRUSTED_ORIGINS: "https://reymota.es http://vmcluster http://ranchermota.rancher.reymota.lab/ http://localhost http://127.0.0.1"
SECRET_KEY: change_me
SQL_DATABASE: reymota
SQL_ENGINE: django.db.backends.postgresql
SQL_HOST: db
SQL_PASSWORD: Dsa-0213
SQL_PORT: "5432"
SQL_USER: creylopez
DATABASE: postgres
kind: ConfigMap
metadata:
labels:
io.kompose.service: web-env-prod
name: env-prod
namespace: ranchermota

+ 11
- 0
ReyMotaAppsRancher/K8S/ConfigMaps/env-prod-db-configmap.yaml View File

@ -0,0 +1,11 @@
apiVersion: v1
data:
POSTGRES_DB: reymota
POSTGRES_PASSWORD: Dsa-0213
POSTGRES_USER: creylopez
kind: ConfigMap
metadata:
labels:
io.kompose.service: db-env-prod-db
name: env-prod-db
namespace: ranchermota

+ 53
- 0
ReyMotaAppsRancher/K8S/Deployments/db-deployment.yaml View File

@ -0,0 +1,53 @@
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.34.0 (cbf2835db)
labels:
io.kompose.service: db
name: db
namespace: ranchermota
spec:
replicas: 1
selector:
matchLabels:
io.kompose.service: db
strategy:
type: Recreate
template:
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.34.0 (cbf2835db)
labels:
io.kompose.service: db
spec:
containers:
- env:
- name: POSTGRES_DB
valueFrom:
configMapKeyRef:
key: POSTGRES_DB
name: env-prod-db
- name: POSTGRES_PASSWORD
valueFrom:
configMapKeyRef:
key: POSTGRES_PASSWORD
name: env-prod-db
- name: POSTGRES_USER
valueFrom:
configMapKeyRef:
key: POSTGRES_USER
name: env-prod-db
image: postgres:15
name: db
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: postgres-data
subPath: pgdata
restartPolicy: Always
volumes:
- name: postgres-data
persistentVolumeClaim:
claimName: postgres-data

+ 46
- 0
ReyMotaAppsRancher/K8S/Deployments/nginx-deployment.yaml View File

@ -0,0 +1,46 @@
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.34.0 (cbf2835db)
labels:
io.kompose.service: nginx
name: nginx
namespace: ranchermota
spec:
replicas: 1
selector:
matchLabels:
io.kompose.service: nginx
strategy:
type: Recreate
template:
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.34.0 (cbf2835db)
labels:
io.kompose.service: nginx
spec:
containers:
- image: $REGISTRY/nginx-reymota-$ARQUITECTURA:$IMG_NGINX_VERSION
name: nginx
ports:
- containerPort: 80
protocol: TCP
volumeMounts:
- mountPath: /app/reymota/staticfiles
name: static-volume
- mountPath: /app/reymota/mediafiles
name: reymota-media
imagePullSecrets:
- name: myregistrykey
restartPolicy: Always
volumes:
- name: static-volume
persistentVolumeClaim:
claimName: static-volume
- name: reymota-media
persistentVolumeClaim:
claimName: reymota-media

+ 126
- 0
ReyMotaAppsRancher/K8S/Deployments/reymota-deployment.yaml View File

@ -0,0 +1,126 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: reymota
namespace: ranchermota
labels:
app: reymota
spec:
replicas: 1
selector:
matchLabels:
app: reymota
strategy:
type: Recreate
template:
metadata:
labels:
app: reymota
spec:
containers:
- args:
- gunicorn
- reymota.wsgi:application
- --bind
- 0.0.0.0:8000
name: reymota
image: $REGISTRY/reymota-$ARQUITECTURA:$IMG_VERSION
env:
- name: VERSION
value: "$IMG_VERSION"
- name: ENVIRONMENT
valueFrom:
configMapKeyRef:
key: ENTORNO
name: env-prod
- name: DEBUG
valueFrom:
configMapKeyRef:
key: DEBUG
name: env-prod
- name: DJANGO_ALLOWED_HOSTS
valueFrom:
configMapKeyRef:
key: DJANGO_ALLOWED_HOSTS
name: env-prod
- name: CSRF_TRUSTED_ORIGINS
valueFrom:
configMapKeyRef:
key: CSRF_TRUSTED_ORIGINS
name: env-prod
- name: SECRET_KEY
valueFrom:
configMapKeyRef:
key: SECRET_KEY
name: env-prod
- name: DATABASE
valueFrom:
configMapKeyRef:
key: DATABASE
name: env-prod
- name: SQL_HOST
valueFrom:
configMapKeyRef:
key: SQL_HOST
name: env-prod
- name: SQL_PORT
valueFrom:
configMapKeyRef:
key: SQL_PORT
name: env-prod
- name: SQL_ENGINE
valueFrom:
configMapKeyRef:
key: SQL_ENGINE
name: env-prod
- name: SQL_DATABASE
valueFrom:
configMapKeyRef:
key: SQL_DATABASE
name: env-prod
- name: SQL_USER
valueFrom:
configMapKeyRef:
key: SQL_USER
name: env-prod
- name: SQL_PASSWORD
valueFrom:
configMapKeyRef:
key: SQL_PASSWORD
name: env-prod
ports:
- containerPort: 8000
protocol: TCP
volumeMounts:
- mountPath: /app/reymota/mediafiles
name: reymota-media
- mountPath: /app/reymota/lyrics/migrations
name: reymota-lyrics-migrations
- mountPath: /app/reymota/repostajes/migrations
name: reymota-repostajes-migrations
- mountPath: /app/reymota/reymotausers/migrations
name: reymota-reymotausers-migrations
- mountPath: /app/reymota/staticfiles
name: static-volume
imagePullSecrets:
- name: myregistrykey
restartPolicy: Always
volumes:
- name: reymota-media
persistentVolumeClaim:
claimName: reymota-media
- name: reymota-lyrics-migrations
persistentVolumeClaim:
claimName: reymota-lyrics-migrations
- name: reymota-repostajes-migrations
persistentVolumeClaim:
claimName: reymota-repostajes-migrations
- name: reymota-reymotausers-migrations
persistentVolumeClaim:
claimName: reymota-reymotausers-migrations
- name: static-volume
persistentVolumeClaim:
claimName: static-volume
status: {}

+ 60
- 0
ReyMotaAppsRancher/K8S/Makefile View File

@ -0,0 +1,60 @@
export ARQUITECTURA := $(shell lscpu |grep itectur | tr -d ' '| cut -f2 -d':')
#export REGISTRY=registry.cube.local
export REGISTRY=registry.reymota.es
export IMG_VERSION = 0.56
export IMG_NGINX_VERSION = 1.0
# limpia todo
all: imagen clean install
imagen:
cd ../; make
install:
# Secreto y configmaps
-kubectl create -f reg-secret.yaml
-kubectl create -f ./ConfigMaps/env-prod-configmap.yaml
-kubectl create -f ./ConfigMaps/env-prod-db-configmap.yaml
# Deployments
-kubectl create -f ./Deployments/db-deployment.yaml
-envsubst < ./Deployments/reymota-deployment.yaml |kubectl create -f -
-envsubst < ./Deployments/nginx-deployment.yaml |kubectl create -f -
# Servicios
-kubectl create -f ./Services/db-service.yaml
-kubectl create -f ./Services/reymota-service.yaml
-kubectl create -f ./Services/nginx-service.yaml
-kubectl create -f ./Services/reymota-ingress.yaml
clean:
# Deployments
-envsubst < ./Deployments/nginx-deployment.yaml |kubectl delete -f -
-envsubst < ./Deployments/reymota-deployment.yaml |kubectl delete -f -
-kubectl delete -f ./Deployments/db-deployment.yaml
# Servicios
-kubectl delete -f ./Services/reymota-ingress.yaml
-kubectl delete -f ./Services/reymota-service.yaml
-kubectl delete -f ./Services/nginx-service.yaml
-kubectl delete -f ./Services/db-service.yaml
# Secreto y configmaps
-kubectl delete -f ./ConfigMaps/env-prod-configmap.yaml
-kubectl delete -f ./ConfigMaps/env-prod-db-configmap.yaml
nginx:
cd ../nginx; make
backup:
kubectl --kubeconfig /home/creylopez/.kube/config -n reymota exec -ti deployment.apps/db -- /usr/lib/postgresql/15/bin/pg_dump --username=creylopez --dbname=reymota > reymota-$(IMG_VERSION).sql
muestra:
-envsubst < reymota-deployment.yaml > /tmp/deployment.yaml

+ 13
- 0
ReyMotaAppsRancher/K8S/PVC/postgres-data-persistentvolumeclaim.yaml View File

@ -0,0 +1,13 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
labels:
io.kompose.service: postgres-data
name: postgres-data
namespace: ranchermota
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Mi

+ 63
- 0
ReyMotaAppsRancher/K8S/PVC/reymota-prod-persistentvolumeclaim.yaml View File

@ -0,0 +1,63 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
creationTimestamp: null
labels:
io.kompose.service: reymota-media
name: reymota-media
namespace: ranchermota
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Mi
status: {}
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
creationTimestamp: null
labels:
io.kompose.service: reymota-lyrics-migrations
name: reymota-lyrics-migrations
namespace: ranchermota
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 50Mi
status: {}
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
creationTimestamp: null
labels:
io.kompose.service: reymota-repostajes-migrations
name: reymota-repostajes-migrations
namespace: ranchermota
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 52Mi
status: {}
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
creationTimestamp: null
labels:
io.kompose.service: reymota-reymotausers-migrations
name: reymota-reymotausers-migrations
namespace: ranchermota
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 53Mi
status: {}

+ 13
- 0
ReyMotaAppsRancher/K8S/PVC/static-volume-persistentvolumeclaim.yaml View File

@ -0,0 +1,13 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
labels:
io.kompose.service: static-volume
name: static-volume
namespace: ranchermota
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 70Mi

+ 17
- 0
ReyMotaAppsRancher/K8S/Services/db-service.yaml View File

@ -0,0 +1,17 @@
apiVersion: v1
kind: Service
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.34.0 (cbf2835db)
labels:
io.kompose.service: db
name: db
namespace: ranchermota
spec:
ports:
- name: "5432"
port: 5432
targetPort: 5432
selector:
io.kompose.service: db

+ 20
- 0
ReyMotaAppsRancher/K8S/Services/nginx-service.yaml View File

@ -0,0 +1,20 @@
apiVersion: v1
kind: Service
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.34.0 (cbf2835db)
labels:
io.kompose.service: nginx
name: nginx
namespace: ranchermota
spec:
type: NodePort
ports:
- name: "1337"
port: 1337
nodePort: 30343
targetPort: 80
selector:
io.kompose.service: nginx

+ 31
- 0
ReyMotaAppsRancher/K8S/Services/reymota-ingress.yaml View File

@ -0,0 +1,31 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
generation: 1
managedFields:
- apiVersion: networking.k8s.io/v1
fieldsType: FieldsV1
fieldsV1:
f:spec:
f:defaultBackend:
.: {}
f:service:
.: {}
f:name: {}
f:port: {}
f:rules: {}
manager: rancher
operation: Update
name: reymota
namespace: ranchermota
spec:
defaultBackend:
service:
name: nginx
port:
number: 1337
ingressClassName: nginx
rules:
- host: ranchermota.rancher.reymota.lab
status:
loadBalancer: {}

+ 12
- 0
ReyMotaAppsRancher/K8S/Services/reymota-service.yaml View File

@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: reymota
namespace: ranchermota
spec:
ports:
- name: "8000"
port: 8000
targetPort: 8000
selector:
app: reymota

+ 2
- 0
ReyMotaAppsRancher/K8S/Shells/borraNS.sh View File

@ -0,0 +1,2 @@
( NAMESPACE=ranchermota; kubectl proxy & kubectl get namespace $NAMESPACE -o json |jq '.spec = {"finalizers":[]}' >temp.json; curl -k -H "Content-Type: application/json" -X PUT --data-binary @temp.json 127.0.0.1:8001/api/v1/namespaces/$NAMESPACE/finalize; )

+ 1
- 0
ReyMotaAppsRancher/K8S/Shells/entra.sh View File

@ -0,0 +1 @@
kubectl -n ranchermota exec -ti deployment.apps/reymota -- /bin/bash

+ 1
- 0
ReyMotaAppsRancher/K8S/Shells/entraPsql.sh View File

@ -0,0 +1 @@
kubectl -n ranchermota exec -ti deployment.apps/db -- psql --username=creylopez --dbname=reymota

+ 7
- 0
ReyMotaAppsRancher/K8S/namespace.yaml View File

@ -0,0 +1,7 @@
###################################################
# Namespace reymota
###################################################
apiVersion: v1
kind: Namespace
metadata:
name: ranchermota

+ 8
- 0
ReyMotaAppsRancher/K8S/reg-secret.yaml View File

@ -0,0 +1,8 @@
apiVersion: v1
kind: Secret
metadata:
name: myregistrykey
namespace: ranchermota
data:
.dockerconfigjson: ewoJImF1dGhzIjogewoJCSJyZWdpc3RyeS5yZXltb3RhLmVzIjogewoJCQkiYXV0aCI6ICJZM0psZVd4dmNHVjZPbEpsZVMweE1UYzIiCgkJfQoJfQp9
type: kubernetes.io/dockerconfigjson

+ 8
- 0
ReyMotaAppsRancher/Makefile View File

@ -0,0 +1,8 @@
install:
echo "Creando imagen con version '${IMG_VERSION}' para la arquitectura '${ARQUITECTURA}' en el registry '${REGISTRY}'"
docker build --no-cache -t ${REGISTRY}/reymota-${ARQUITECTURA}:${IMG_VERSION} .
docker push ${REGISTRY}/reymota-${ARQUITECTURA}:${IMG_VERSION}

+ 49
- 0
ReyMotaAppsRancher/README.md View File

@ -0,0 +1,49 @@
# Instalación
Desde el directorio K8S ejecutar make (esto hace todo: la imagen, para los pods y los lanza otra vez)
La primera vez, hay que entrar en el pod de vehículos con 'entra.sh' y
python manage.py createsuperuser
python manage.py makemigrations
python manage.py migrate
## Comprobar la base de datos
Con la shell entraPsql.sh:
\l para listar las BD
\c reymota para usar nuestra db
\dt para ver las tablas
# De dónde cogí ideas
https://learndjango.com/tutorials/django-login-and-logout-tutorial
Username: {{ user.username }}
User Full name: {{ user.get_full_name }}
User Group: {{ user.groups.all.0 }}
Email: {{ user.email }}
Session Started at: {{ user.last_login }}
## Para funcionar con gunicorn y nginx
https://testdriven.io/blog/dockerizing-django-with-postgres-gunicorn-and-nginx/
## Cambiar la secuencia de lo sid
ALTER SEQUENCE tablename_id_seq RESTART WITH nn;
esto se hace cuando restauro un volcado de la bd sobre una instalación nueva. Si hay índices ya creados, hay que reinciar a partir del último.

+ 20
- 0
ReyMotaAppsRancher/entrypoint.sh View File

@ -0,0 +1,20 @@
#!/bin/bash
if [ "$DATABASE" = "postgres" ]
then
echo "Waiting for postgres..."
while ! nc -z $SQL_HOST $SQL_PORT; do
sleep 0.1
done
echo "PostgreSQL started"
else
echo "la base de datos no es postgres: '$DATABASE'"
fi
python manage.py collectstatic --noinput
#python manage.py flush --no-input
#python manage.py migrate
exec "$@"

+ 4
- 0
ReyMotaAppsRancher/nginx/Dockerfile View File

@ -0,0 +1,4 @@
FROM nginx:1.25
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d

+ 8
- 0
ReyMotaAppsRancher/nginx/Makefile View File

@ -0,0 +1,8 @@
install:
echo "Creando imagen con version '${IMG_NGINX_VERSION}' para la arquitectura '${ARQUITECTURA}' en el registry '${REGISTRY}'"
docker build --no-cache -t ${REGISTRY}/nginx-reymota-${ARQUITECTURA}:${IMG_NGINX_VERSION} .
docker push ${REGISTRY}/nginx-reymota-${ARQUITECTURA}:${IMG_NGINX_VERSION}

+ 25
- 0
ReyMotaAppsRancher/nginx/nginx.conf View File

@ -0,0 +1,25 @@
upstream reymota {
server reymota:8000;
}
server {
listen 80;
location / {
proxy_pass http://reymota;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
client_max_body_size 100M;
}
location /static/ {
alias /app/reymota/staticfiles/;
}
location /media/ {
alias /app/reymota/mediafiles/;
}
}

+ 20
- 0
ReyMotaAppsRancher/requirements.txt View File

@ -0,0 +1,20 @@
asgiref==3.8.1
Django==4.2
django-calculation==1.0.0
djangorestframework==3.15.2
flake8==7.1.1
gunicorn==22.0.0
mccabe==0.7.0
numpy==2.2.2
packaging==24.1
pandas==2.2.3
pillow==10.4.0
psycopg2-binary==2.9.6
pycodestyle==2.12.1
pyflakes==3.2.0
python-dateutil==2.9.0.post0
pytz==2025.1
six==1.17.0
sqlparse==0.5.1
typing_extensions==4.12.2
tzdata==2025.1

+ 1
- 0
ReyMotaAppsRancher/reymota/accounts/.gitignore View File

@ -0,0 +1 @@
migrations/

+ 0
- 0
ReyMotaAppsRancher/reymota/accounts/__init__.py View File


+ 3
- 0
ReyMotaAppsRancher/reymota/accounts/admin.py View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

+ 6
- 0
ReyMotaAppsRancher/reymota/accounts/apps.py View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class AccountsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'accounts'

+ 3
- 0
ReyMotaAppsRancher/reymota/accounts/models.py View File

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

+ 3
- 0
ReyMotaAppsRancher/reymota/accounts/tests.py View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

+ 8
- 0
ReyMotaAppsRancher/reymota/accounts/urls.py View File

@ -0,0 +1,8 @@
# accounts/urls.py
from django.urls import path
from django.contrib.auth import views as auth_views
urlpatterns = [
path('login/', auth_views.LoginView.as_view(), name='login'),
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
]

+ 1
- 0
ReyMotaAppsRancher/reymota/accounts/views.py View File

@ -0,0 +1 @@
from django.shortcuts import render

+ 6
- 0
ReyMotaAppsRancher/reymota/entornoPruebas.sh View File

@ -0,0 +1,6 @@
export CSRF_TRUSTED_ORIGINS="http://localhost"
export DEBUG="True"
export SECRET_KEY="hola"
export DJANGO_ALLOWED_HOSTS="localhost"

+ 0
- 0
ReyMotaAppsRancher/reymota/lyrics/__init__.py View File


+ 9
- 0
ReyMotaAppsRancher/reymota/lyrics/admin.py View File

@ -0,0 +1,9 @@
from django.contrib import admin
# Register your models here.
from .models import Artista, Album, Song
admin.site.register(Artista)
admin.site.register(Album)
admin.site.register(Song)

+ 6
- 0
ReyMotaAppsRancher/reymota/lyrics/apps.py View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class LyricsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'lyrics'

+ 41
- 0
ReyMotaAppsRancher/reymota/lyrics/forms.py View File

@ -0,0 +1,41 @@
from django import forms
from .models import Artista, Album, Song
class ArtistaForm(forms.ModelForm):
class Meta:
model = Artista
fields = ['nombre', 'biografia', 'foto']
nombre = forms.CharField(
widget=forms.TextInput(attrs={'class': 'form-control'}))
biografia = forms.CharField(
widget=forms.TextInput(attrs={'class': 'form-control'}))
class AlbumForm(forms.ModelForm):
class Meta:
model = Album
fields = ['name', 'artist', 'year', 'cover_image']
# year = forms.DateField(
# widget=forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}))
artist = forms.ModelChoiceField(
queryset=Artista.objects.all(),
widget=forms.Select(attrs={'class': 'form-control'}))
class SongForm(forms.ModelForm):
class Meta:
model = Song
fields = ['title', 'artist', 'album', 'year', 'lyrics']
artist = forms.ModelChoiceField(
queryset=Artista.objects.all(),
widget=forms.Select(attrs={'class': 'form-control'}))
album = forms.ModelChoiceField(
queryset=Album.objects.all(), # habría que seleccionar los álbumes del artista
widget=forms.Select(attrs={'class': 'form-control'}))

+ 0
- 0
ReyMotaAppsRancher/reymota/lyrics/management/__init__.py View File


+ 0
- 0
ReyMotaAppsRancher/reymota/lyrics/management/commands/__init__.py View File


+ 48
- 0
ReyMotaAppsRancher/reymota/lyrics/management/commands/importar_albumes.py View File

@ -0,0 +1,48 @@
import json
from django.core.management.base import BaseCommand
from lyrics.models import Album, Artista
class Command(BaseCommand):
help = "Importa albumes desde un archivo JSON"
def add_arguments(self, parser):
parser.add_argument('archivo_json', type=str, help="Ruta del archivo JSON")
def handle(self, *args, **kwargs):
archivo_json = kwargs['archivo_json']
try:
with open(archivo_json, 'r', encoding='utf-8') as file:
datos = json.load(file)
self.stdout.write(self.style.WARNING(f"\nSe encontraron {len(datos)} albumes en el archivo '{archivo_json}'."))
confirmar = input("¿Deseas continuar con la importación? (s/n): ").strip().lower()
if confirmar != 's':
self.stdout.write(self.style.ERROR("Importación cancelada."))
return
albumes_creados = 0
for album_data in datos:
try:
artista = Artista.objects.get(nombre=album_data["artista_nombre"])
creado = Album.objects.create(
artist=artista,
name=album_data['name'],
year=album_data['year'],
cover_image=album_data['cover_image'],
)
if creado:
albumes_creados += 1
except Artista.DoesNotExist:
self.stderr.write(self.style.ERROR(f"Artista '{album_data['artista_nombre']}' no encontrado."))
self.stdout.write(self.style.SUCCESS(f'Se importaron {albumes_creados} albumes correctamente.'))
except FileNotFoundError:
self.stderr.write(self.style.ERROR(f"El archivo {archivo_json} no se encontró."))
except json.JSONDecodeError:
self.stderr.write(self.style.ERROR("Error al leer el archivo JSON. Asegúrate de que el formato sea correcto."))

+ 42
- 0
ReyMotaAppsRancher/reymota/lyrics/management/commands/importar_artistas.py View File

@ -0,0 +1,42 @@
import json
from django.core.management.base import BaseCommand
from lyrics.models import Artista
class Command(BaseCommand):
help = "Importa artistas desde un archivo JSON"
def add_arguments(self, parser):
parser.add_argument('archivo_json', type=str, help="Ruta del archivo JSON")
def handle(self, *args, **kwargs):
archivo_json = kwargs['archivo_json']
try:
with open(archivo_json, 'r', encoding='utf-8') as file:
datos = json.load(file)
self.stdout.write(self.style.WARNING(f"\nSe encontraron {len(datos)} artistas en el archivo '{archivo_json}'."))
confirmar = input("¿Deseas continuar con la importación? (s/n): ").strip().lower()
if confirmar != 's':
self.stdout.write(self.style.ERROR("Importación cancelada."))
return
artistas_creados = 0
for artista_data in datos:
creado = Artista.objects.create(
id=artista_data['id'],
nombre=artista_data['nombre'],
biografia=artista_data['biografia'],
foto=artista_data['foto']
)
if creado:
artistas_creados += 1
self.stdout.write(self.style.SUCCESS(f'Se importaron {artistas_creados} artistas correctamente.'))
except FileNotFoundError:
self.stderr.write(self.style.ERROR(f"El archivo {archivo_json} no se encontró."))
except json.JSONDecodeError:
self.stderr.write(self.style.ERROR("Error al leer el archivo JSON. Asegúrate de que el formato sea correcto."))

+ 51
- 0
ReyMotaAppsRancher/reymota/lyrics/management/commands/importar_canciones.py View File

@ -0,0 +1,51 @@
import json
from django.core.management.base import BaseCommand
from lyrics.models import Song, Album, Artista
class Command(BaseCommand):
help = "Importa canciones desde un archivo JSON"
def add_arguments(self, parser):
parser.add_argument('archivo_json', type=str, help="Ruta del archivo JSON")
def handle(self, *args, **kwargs):
archivo_json = kwargs['archivo_json']
try:
with open(archivo_json, 'r', encoding='utf-8') as file:
datos = json.load(file)
self.stdout.write(self.style.WARNING(f"\nSe encontraron {len(datos)} canciones en el archivo '{archivo_json}'."))
confirmar = input("¿Deseas continuar con la importación? (s/n): ").strip().lower()
if confirmar != 's':
self.stdout.write(self.style.ERROR("Importación cancelada."))
return
canciones_creados = 0
for cancion_data in datos:
try:
album = Album.objects.get(name=cancion_data["album_nombre"])
artista = Artista.objects.get(nombre=cancion_data["artista_nombre"])
creado = Song.objects.create(
album=album,
artist=artista,
title=cancion_data['title'],
year=cancion_data['year'],
lyrics=cancion_data['lyrics'],
pista=cancion_data['pista'],
)
if creado:
canciones_creados += 1
except Album.DoesNotExist:
self.stderr.write(self.style.ERROR(f"Album '{cancion_data['album']}' no encontrado."))
self.stdout.write(self.style.SUCCESS(f'Se importaron {canciones_creados} canciones correctamente.'))
except FileNotFoundError:
self.stderr.write(self.style.ERROR(f"El archivo {archivo_json} no se encontró."))
except json.JSONDecodeError:
self.stderr.write(self.style.ERROR("Error al leer el archivo JSON. Asegúrate de que el formato sea correcto."))

+ 52
- 0
ReyMotaAppsRancher/reymota/lyrics/migrations/0001_initial.py View File

@ -0,0 +1,52 @@
# Generated by Django 4.2 on 2024-09-10 13:23
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
import lyrics.models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Album',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=200)),
('year', models.PositiveBigIntegerField(default=2024, validators=[django.core.validators.MinValueValidator(1984), lyrics.models.max_value_current_year])),
('cover_image', models.ImageField(blank=True, null=True, upload_to='cover_image/')),
],
),
migrations.CreateModel(
name='Artista',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('nombre', models.CharField(max_length=200)),
('biografia', models.TextField(blank=True, null=True)),
('foto', models.ImageField(blank=True, null=True, upload_to='artistas/')),
],
),
migrations.CreateModel(
name='Song',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=200)),
('year', models.PositiveBigIntegerField(default=2024, validators=[django.core.validators.MinValueValidator(1984), lyrics.models.max_value_current_year])),
('lyrics', models.CharField(max_length=1000)),
('pista', models.DecimalField(blank=True, decimal_places=0, max_digits=5, null=True)),
('album', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lyrics.album')),
('artist', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lyrics.artista')),
],
),
migrations.AddField(
model_name='album',
name='artist',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lyrics.artista'),
),
]

+ 0
- 0
ReyMotaAppsRancher/reymota/lyrics/migrations/__init__.py View File


+ 42
- 0
ReyMotaAppsRancher/reymota/lyrics/models.py View File

@ -0,0 +1,42 @@
from django.db import models
import datetime
from django.core.validators import MaxValueValidator, MinValueValidator
def current_year():
return datetime.date.today().year
def max_value_current_year(value):
return MaxValueValidator(current_year())(value)
class Artista(models.Model):
nombre = models.CharField(max_length=200)
biografia = models.TextField(blank=True, null=True)
foto = models.ImageField(upload_to='artistas/', blank=True, null=True) # Nuevo campo
def __str__(self):
return self.nombre
class Album(models.Model):
name = models.CharField(max_length=200)
artist = models.ForeignKey(Artista, on_delete=models.CASCADE)
year = models.PositiveBigIntegerField(default=current_year(), validators=[MinValueValidator(1945), max_value_current_year])
cover_image = models.ImageField(upload_to='cover_image/', blank=True, null=True) # Nuevo campo
def __str__(self):
return self.name
class Song(models.Model):
title = models.CharField(max_length=200)
artist = models.ForeignKey(Artista, on_delete=models.CASCADE)
album = models.ForeignKey(Album, on_delete=models.CASCADE, related_name='song')
year = models.DecimalField(max_digits=4, decimal_places=0, blank=False, null=False)
lyrics = models.TextField()
pista = models.DecimalField(max_digits=5, decimal_places=0, blank=True, null=True)
def __str__(self):
return self.title

+ 39
- 0
ReyMotaAppsRancher/reymota/lyrics/serializers.py View File

@ -0,0 +1,39 @@
import os
from rest_framework import serializers
from .models import Artista, Album, Song
class ArtistaSerializer(serializers.ModelSerializer):
class Meta:
model = Artista
fields = '__all__' # Incluir todos los campos del modelo
def to_representation(self, instance):
ret = super().to_representation(instance)
ret['foto'] = "artistas/" + os.path.basename(ret['foto'])
return ret
class AlbumSerializer(serializers.ModelSerializer):
artista_nombre = serializers.CharField(source='artist.nombre', read_only=True)
class Meta:
model = Album
fields = ['name', 'year', 'cover_image', 'artista_nombre']
def to_representation(self, instance):
ret = super().to_representation(instance)
ret['cover_image'] = "cover_image/" + os.path.basename(ret['cover_image'])
return ret
class CancionSerializer(serializers.ModelSerializer):
artista_nombre = serializers.CharField(source='artist.nombre', read_only=True)
album_nombre = serializers.CharField(source='album.name', read_only=True)
class Meta:
model = Song
fields = ['title', 'year', 'lyrics', 'pista', 'artista_nombre', 'album_nombre']

+ 3
- 0
ReyMotaAppsRancher/reymota/lyrics/tests.py View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

+ 39
- 0
ReyMotaAppsRancher/reymota/lyrics/urls.py View File

@ -0,0 +1,39 @@
from django.urls import path
from . import views
from .views import api_lista_artistas, api_detalle_artista
from .views import api_lista_albumes, api_detalle_album
from .views import api_lista_canciones, api_detalle_cancion
app_name = 'lyrics'
urlpatterns = [
path('', views.principal, name='principal'),
path('artistas/', views.lista_artistas, name='lista_artistas'),
path('artistas/nuevo/', views.nuevo_artista, name='nuevo_artista'),
path('artistas/<int:artista_id>/', views.detalle_artista, name='detalle_artista'),
path('artistas/<int:artista_id>/editar/', views.editar_artista, name='editar_artista'),
path('artistas/<int:artista_id>/eliminar/', views.eliminar_artista, name='eliminar_artista'),
path('album/', views.lista_albumes, name='lista_albumes'),
path('album/nuevo/', views.nuevo_album, name='nuevo_album'),
path('album/<int:album_id>/', views.detalle_album, name='detalle_album'),
path('album/<int:album_id>/editar/', views.editar_album, name='editar_album'),
path('album/<int:album_id>/eliminar/', views.eliminar_album, name='eliminar_album'),
path('song/', views.lista_songs, name='lista_songs'),
path('song/nuevo/', views.nuevo_song, name='nuevo_song'),
path('song/<int:song_id>/', views.detalle_song, name='detalle_song'),
path('song/<int:song_id>/editar/', views.editar_song, name='editar_song'),
path('song/<int:song_id>/eliminar/', views.eliminar_song, name='eliminar_song'),
path('api/artistas/', api_lista_artistas, name='api_lista_artistas'),
path('api/artistas/<int:artista_id>/', api_detalle_artista, name='api_detalle_artista'),
path('api/albumes/', api_lista_albumes, name='api_lista_albumes'),
path('api/albumes/<int:album_id>/', api_detalle_album, name='api_detalle_album'),
path('api/canciones/', api_lista_canciones, name='api_lista_canciones'),
path('api/canciones/<int:cancion_id>/', api_detalle_cancion, name='api_detalle_cancion'),
]

+ 251
- 0
ReyMotaAppsRancher/reymota/lyrics/views.py View File

@ -0,0 +1,251 @@
# Create your views here.
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from rest_framework.response import Response
from rest_framework.decorators import api_view
from .models import Artista, Album, Song
from .forms import ArtistaForm, AlbumForm, SongForm
from .serializers import ArtistaSerializer, AlbumSerializer, CancionSerializer
import logging
logger = logging.getLogger(__name__)
@login_required
def principal(request):
artistas = Artista.objects.all()
albumes = Album.objects.all()
return render(request, 'lyrics/index.html', {'artistas': artistas, 'albumes': albumes})
#########################
# Vistas para los artistas
@login_required
def lista_artistas(request):
artistas = Artista.objects.all()
return render(request, 'lyrics/lista_artistas.html', {'artistas': artistas})
@login_required
def detalle_artista(request, artista_id):
artista = get_object_or_404(Artista, pk=artista_id)
albumes = Album.objects.filter(artist=artista_id)
return render(request, 'lyrics/detalle_artista.html', {'artista': artista, 'albumes': albumes})
@login_required
def nuevo_artista(request):
if request.method == 'POST':
form = ArtistaForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('lyrics:lista_artistas')
else:
form = ArtistaForm()
return render(request, 'lyrics/form_artista.html', {'form': form})
@login_required
def editar_artista(request, artista_id):
artista = get_object_or_404(Artista, pk=artista_id)
if request.method == 'POST':
form = ArtistaForm(request.POST, request.FILES, instance=artista)
if form.is_valid():
form.save()
return redirect('lyrics:lista_artistas')
else:
form = ArtistaForm(instance=artista)
return render(request, 'lyrics/form_artista.html', {'form': form})
@login_required
def eliminar_artista(request, artista_id):
artista = get_object_or_404(Artista, pk=artista_id)
artista.delete()
return redirect('lyrics:lista_artistas')
#########################
# Vistas para los albumes
@login_required
def lista_albumes(request):
albumes = Album.objects.all()
return render(request, 'lyrics/lista_albumes.html', {'albumes': albumes})
@login_required
def detalle_album(request, album_id):
album = get_object_or_404(Album, pk=album_id)
songs = Song.objects.filter(album_id=album_id)
return render(request, 'lyrics/detalle_album.html', {'album': album, 'songs': songs})
@login_required
def nuevo_album(request):
artistas = Artista.objects.all() # vamos a ver si hay vehículos dados de alta
if artistas:
if request.method == 'POST':
form = AlbumForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('lyrics:lista_albumes')
else:
form = AlbumForm()
return render(request, 'lyrics/form_album.html', {'form': form})
else:
return render(request, 'lyrics/index.html')
@login_required
def editar_album(request, album_id):
album = get_object_or_404(Album, pk=album_id)
if request.method == 'POST':
form = AlbumForm(request.POST, request.FILES, instance=album)
if form.is_valid():
form.save()
return redirect('lyrics:lista_albumes')
else:
form = AlbumForm(instance=album)
return render(request, 'lyrics/form_album.html', {'form': form})
@login_required
def eliminar_album(request, album_id):
album = Album.objects.get(pk=album_id)
album.delete()
return redirect('lyrics:lista_albumes')
#########################
# Vistas para los songs
@login_required
def lista_songs(request):
songs = Song.objects.all()
return render(request, 'lyrics/lista_songs.html', {'songs': songs})
@login_required
def detalle_song(request, song_id):
song = get_object_or_404(Song, pk=song_id)
albumes = Album.objects.filter(song=song_id)
return render(request, 'lyrics/detalle_song.html', {'song': song, 'albumes': albumes})
@login_required
def nuevo_song(request):
album_id = request.GET.get('album_id') # Obtener el album_id de los parámetros de la URL
if request.method == 'POST':
form = SongForm(request.POST, request.FILES)
if form.is_valid():
album = form.cleaned_data['album']
song_count = album.song.count()
nueva_cancion = form.save(commit=False)
nueva_cancion.pista = song_count + 1
nueva_cancion.save()
logger.info("Canción creada %s", nueva_cancion.title)
return redirect('lyrics:lista_songs')
else:
if album_id:
# Si tenemos un album_id, preseleccionamos ese álbum en el formulario
album = get_object_or_404(Album, id=album_id)
form = SongForm(initial={'album': album, 'artist': album.artist, 'year': album.year})
else:
form = SongForm()
return render(request, 'lyrics/form_song.html', {'form': form})
@login_required
def editar_song(request, song_id):
song = get_object_or_404(Song, pk=song_id)
if request.method == 'POST':
form = SongForm(request.POST, request.FILES, instance=song)
if form.is_valid():
form.save()
return redirect('lyrics:lista_songs')
else:
form = SongForm(instance=song)
return render(request, 'lyrics/form_song.html', {'form': form})
@login_required
def eliminar_song(request, song_id):
song = get_object_or_404(Song, pk=song_id)
song.delete()
return redirect('lyrics:lista_songs')
@api_view(['GET'])
def api_lista_artistas(request):
"""Devuelve la lista de todos los artistas."""
artistas = Artista.objects.all()
serializer = ArtistaSerializer(artistas, many=True)
return Response(serializer.data)
@api_view(['GET'])
def api_detalle_artista(request, artista_id):
"""Devuelve los detalles de un artista específico."""
try:
artista = Artista.objects.get(id=artista_id)
serializer = ArtistaSerializer(artista)
return Response(serializer.data)
except Artista.DoesNotExist:
return Response({'error': 'Artista no encontrado'}, status=404)
@api_view(['GET'])
def api_lista_albumes(request):
"""Devuelve la lista de todos los albumes."""
albumes = Album.objects.all()
serializer = AlbumSerializer(albumes, many=True)
return Response(serializer.data)
@api_view(['GET'])
def api_detalle_album(request, album_id):
"""Devuelve los detalles de un album específico."""
try:
album = Album.objects.get(id=album_id)
serializer = AlbumSerializer(album)
return Response(serializer.data)
except Album.DoesNotExist:
return Response({'error': 'Album no encontrado'}, status=404)
@api_view(['GET'])
def api_lista_canciones(request):
"""Devuelve la lista de todos los canciones."""
canciones = Song.objects.all()
serializer = CancionSerializer(canciones, many=True)
return Response(serializer.data)
@api_view(['GET'])
def api_detalle_cancion(request, cancion_id):
"""Devuelve los detalles de un cancion específica."""
try:
cancion = Song.objects.get(id=cancion_id)
serializer = CancionSerializer(cancion)
return Response(serializer.data)
except Song.DoesNotExist:
return Response({'error': 'Canción no encontrada'}, status=404)

+ 22
- 0
ReyMotaAppsRancher/reymota/manage.py View File

@ -0,0 +1,22 @@
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'reymota.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()

BIN
ReyMotaAppsRancher/reymota/mediafiles/profile_images/default.jpg View File

Before After
Width: 826  |  Height: 826  |  Size: 20 KiB

BIN
ReyMotaAppsRancher/reymota/mediafiles/profile_images/gravatar-tino.jpeg View File

Before After
Width: 256  |  Height: 256  |  Size: 29 KiB

BIN
ReyMotaAppsRancher/reymota/mediafiles/profile_images/gravatar-tino_jqB0Vq4.jpeg View File

Before After
Width: 256  |  Height: 256  |  Size: 29 KiB

BIN
ReyMotaAppsRancher/reymota/mediafiles/vehiculos/bmw.jpg View File

Before After
Width: 500  |  Height: 500  |  Size: 18 KiB

BIN
ReyMotaAppsRancher/reymota/mediafiles/vehiculos/bmw.png View File

Before After
Width: 360  |  Height: 225  |  Size: 9.5 KiB

BIN
ReyMotaAppsRancher/reymota/mediafiles/vehiculos/bmw_PMjCK7Q.png View File

Before After
Width: 360  |  Height: 225  |  Size: 9.5 KiB

BIN
ReyMotaAppsRancher/reymota/mediafiles/vehiculos/bmw_cSbhRuf.png View File

Before After
Width: 360  |  Height: 225  |  Size: 9.5 KiB

BIN
ReyMotaAppsRancher/reymota/mediafiles/vehiculos/bmw_x00n9W7.png View File

Before After
Width: 360  |  Height: 225  |  Size: 9.5 KiB

BIN
ReyMotaAppsRancher/reymota/mediafiles/vehiculos/bmw_yVyuq4g.jpg View File

Before After
Width: 500  |  Height: 500  |  Size: 18 KiB

+ 1
- 0
ReyMotaAppsRancher/reymota/repostajes/.gitignore View File

@ -0,0 +1 @@
migrations/

+ 0
- 0
ReyMotaAppsRancher/reymota/repostajes/__init__.py View File


+ 9
- 0
ReyMotaAppsRancher/reymota/repostajes/admin.py View File

@ -0,0 +1,9 @@
from django.contrib import admin
# Register your models here.
from .models import Vehiculo, Repostaje
admin.site.register(Vehiculo)
admin.site.register(Repostaje)

+ 6
- 0
ReyMotaAppsRancher/reymota/repostajes/apps.py View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class RepostajesConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'repostajes'

+ 41
- 0
ReyMotaAppsRancher/reymota/repostajes/forms.py View File

@ -0,0 +1,41 @@
from django import forms
from .models import Vehiculo, Repostaje
class VehiculoForm(forms.ModelForm):
class Meta:
model = Vehiculo
fields = ['marca', 'modelo', 'matricula', 'foto']
marca = forms.CharField(
widget=forms.TextInput(attrs={'class': 'form-control'}))
modelo = forms.CharField(
widget=forms.TextInput(attrs={'class': 'form-control'}))
matricula = forms.CharField(
widget=forms.TextInput(attrs={'class': 'form-control'}))
class RepostajeForm(forms.ModelForm):
class Meta:
model = Repostaje
fields = ['fecha', 'vehiculo', 'kms', 'litros', 'importe']
exclude = ['descuento', 'precioxlitro']
fecha = forms.DateField(
widget=forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}))
vehiculo = forms.ModelChoiceField(
queryset=Vehiculo.objects.all(),
widget=forms.Select(attrs={'class': 'form-control'}))
kms = forms.DecimalField(
widget=forms.TextInput(attrs={'class': 'form-control'}))
litros = forms.DecimalField(
widget=forms.NumberInput(attrs={'class': 'form-control'}))
importe = forms.DecimalField(
widget=forms.NumberInput(attrs={'class': 'form-control'}))
aplica_descuento = forms.BooleanField(initial=False, required=False)

+ 0
- 0
ReyMotaAppsRancher/reymota/repostajes/management/__init__.py View File


+ 0
- 0
ReyMotaAppsRancher/reymota/repostajes/management/commands/__init__.py View File


+ 53
- 0
ReyMotaAppsRancher/reymota/repostajes/management/commands/importar_repostajes.py View File

@ -0,0 +1,53 @@
import json
from django.core.management.base import BaseCommand
from repostajes.models import Repostaje, Vehiculo
class Command(BaseCommand):
help = "Importa repostajes desde un archivo JSON"
def add_arguments(self, parser):
parser.add_argument('archivo_json', type=str, help="Ruta del archivo JSON")
def handle(self, *args, **kwargs):
archivo_json = kwargs['archivo_json']
try:
with open(archivo_json, 'r', encoding='utf-8') as file:
datos = json.load(file)
self.stdout.write(self.style.WARNING(f"\nSe encontraron {len(datos)} repostajes en el archivo '{archivo_json}'."))
confirmar = input("¿Deseas continuar con la importación? (s/n): ").strip().lower()
if confirmar != 's':
self.stdout.write(self.style.ERROR("Importación cancelada."))
return
repostajes_creados = 0
for repostaje_data in datos:
try:
vehiculo = Vehiculo.objects.get(matricula=repostaje_data["vehiculo_matricula"])
creado = Repostaje.objects.create(
vehiculo=vehiculo,
fecha=repostaje_data['fecha'],
kms=repostaje_data['kms'],
litros=repostaje_data['litros'],
descuento=repostaje_data['descuento'],
importe=repostaje_data['importe'],
precioxlitro=repostaje_data['precioxlitro'],
kmsrecorridos=repostaje_data['kmsrecorridos'],
consumo=repostaje_data['consumo']
)
if creado:
repostajes_creados += 1
except Vehiculo.DoesNotExist:
self.stderr.write(self.style.ERROR(f"Vehiculo con matrícula '{repostaje_data['vehiculo_matricula']}' no encontrado."))
self.stdout.write(self.style.SUCCESS(f'Se importaron {repostajes_creados} repostajes correctamente.'))
except FileNotFoundError:
self.stderr.write(self.style.ERROR(f"El archivo {archivo_json} no se encontró."))
except json.JSONDecodeError:
self.stderr.write(self.style.ERROR("Error al leer el archivo JSON. Asegúrate de que el formato sea correcto."))

+ 42
- 0
ReyMotaAppsRancher/reymota/repostajes/management/commands/importar_vehiculos.py View File

@ -0,0 +1,42 @@
import json
from django.core.management.base import BaseCommand
from repostajes.models import Vehiculo
class Command(BaseCommand):
help = "Importa vehiculos desde un archivo JSON"
def add_arguments(self, parser):
parser.add_argument('archivo_json', type=str, help="Ruta del archivo JSON")
def handle(self, *args, **kwargs):
archivo_json = kwargs['archivo_json']
try:
with open(archivo_json, 'r', encoding='utf-8') as file:
datos = json.load(file)
self.stdout.write(self.style.WARNING(f"\nSe encontraron {len(datos)} vehiculos en el archivo '{archivo_json}'."))
confirmar = input("¿Deseas continuar con la importación? (s/n): ").strip().lower()
if confirmar != 's':
self.stdout.write(self.style.ERROR("Importación cancelada."))
return
vehiculos_creados = 0
for vehiculo_data in datos:
creado = Vehiculo.objects.create(
marca=vehiculo_data['marca'],
modelo=vehiculo_data['modelo'],
matricula=vehiculo_data['matricula'],
foto=vehiculo_data['foto']
)
if creado:
vehiculos_creados += 1
self.stdout.write(self.style.SUCCESS(f'Se importaron {vehiculos_creados} vehiculos correctamente.'))
except FileNotFoundError:
self.stderr.write(self.style.ERROR(f"El archivo {archivo_json} no se encontró."))
except json.JSONDecodeError:
self.stderr.write(self.style.ERROR("Error al leer el archivo JSON. Asegúrate de que el formato sea correcto."))

+ 27
- 0
ReyMotaAppsRancher/reymota/repostajes/models.py View File

@ -0,0 +1,27 @@
from django.db import models
from django.core.validators import MaxValueValidator
class Vehiculo(models.Model):
marca = models.CharField(max_length=200)
modelo = models.CharField(max_length=200)
matricula = models.CharField(max_length=200)
foto = models.ImageField(upload_to='vehiculos/', blank=True, null=True) # Nuevo campo
def __str__(self):
return self.marca
class Repostaje(models.Model):
vehiculo = models.ForeignKey(Vehiculo, on_delete=models.CASCADE)
fecha = models.DateField()
kms = models.DecimalField(max_digits=10, decimal_places=0, blank=True, null=True)
litros = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
descuento = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
importe = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
precioxlitro = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
kmsrecorridos = models.DecimalField(max_digits=10, decimal_places=0, blank=True, null=True)
consumo = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
def __str__(self):
return str(self.fecha)

+ 24
- 0
ReyMotaAppsRancher/reymota/repostajes/serializers.py View File

@ -0,0 +1,24 @@
import os
from rest_framework import serializers
from .models import Vehiculo, Repostaje
class VehiculoSerializer(serializers.ModelSerializer):
class Meta:
model = Vehiculo
fields = '__all__' # Incluir todos los campos del modelo
def to_representation(self, instance):
ret = super().to_representation(instance)
ret['foto'] = "vehiculos/" + os.path.basename(ret['foto'])
return ret
class RepostajeSerializer(serializers.ModelSerializer):
vehiculo_matricula = serializers.CharField(source='vehiculo.matricula', read_only=True)
class Meta:
model = Repostaje
fields = ['id', 'fecha', 'kms', 'litros', 'descuento', 'importe', 'precioxlitro', 'kmsrecorridos', 'consumo', 'vehiculo', 'vehiculo_matricula']

+ 12
- 0
ReyMotaAppsRancher/reymota/repostajes/static/css/portal.css
File diff suppressed because it is too large
View File


+ 21
- 0
ReyMotaAppsRancher/reymota/repostajes/static/images/app-logo.svg View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="215px" height="215px" viewBox="0 0 215 215" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 52.6 (67491) - http://www.bohemiancoding.com/sketch -->
<title>portal-logo</title>
<desc>Created with Sketch.</desc>
<defs>
<path d="M51.165,8.742 C54.505,12.619 56.876,17.365 57.892,22.588 C60.148,17.225 65.452,13.46 71.636,13.46 C79.867,13.46 86.541,20.134 86.541,28.365 C86.541,36.597 79.867,43.269 71.636,43.269 C63.404,43.269 56.728,36.597 56.728,28.365 C56.728,12.7 44.03,0 28.365,0 C12.7,0 0,12.7 0,28.365 C0,44.031 12.7,56.731 28.365,56.731 C36.419,56.731 43.695,53.393 48.858,48.003 C45.501,44.117 43.128,39.383 42.108,34.14 C39.852,39.504 34.548,43.269 28.365,43.269 C20.133,43.269 13.46,36.597 13.46,28.365 C13.46,20.134 20.133,13.46 28.365,13.46 C36.966,13.46 43.27,20.577 43.27,28.365 C43.27,44.031 55.97,56.731 71.636,56.731 C87.3,56.731 100,44.031 100,28.365 C100,12.7 87.3,0 71.636,0 C63.589,0 56.327,3.358 51.165,8.742 Z" id="path-1"></path>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="portal-logo">
<circle id="Oval" fill="#51B37F" fill-rule="nonzero" cx="107.5" cy="107.5" r="107.5"></circle>
<g id="logo" transform="translate(58.000000, 79.000000)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<g id="Clip-2"></g>
<polygon id="Fill-1" fill="#FFFFFE" mask="url(#mask-2)" points="-5 61.73 105 61.73 105 -5 -5 -5"></polygon>
</g>
</g>
</g>
</svg>

BIN
ReyMotaAppsRancher/reymota/repostajes/static/images/background/background-1.jpg View File

Before After
Width: 1000  |  Height: 1139  |  Size: 150 KiB

BIN
ReyMotaAppsRancher/reymota/repostajes/static/images/background/background-2.jpg View File

Before After
Width: 1200  |  Height: 781  |  Size: 232 KiB

BIN
ReyMotaAppsRancher/reymota/repostajes/static/images/background/background-3.jpg View File

Before After
Width: 1200  |  Height: 789  |  Size: 256 KiB

BIN
ReyMotaAppsRancher/reymota/repostajes/static/images/background/background-palmeras.jpg View File

Before After
Width: 1000  |  Height: 1139  |  Size: 360 KiB

BIN
ReyMotaAppsRancher/reymota/repostajes/static/images/doc-thumb-1.jpg View File

Before After
Width: 600  |  Height: 432  |  Size: 75 KiB

BIN
ReyMotaAppsRancher/reymota/repostajes/static/images/doc-thumb-2.jpg View File

Before After
Width: 600  |  Height: 472  |  Size: 75 KiB

BIN
ReyMotaAppsRancher/reymota/repostajes/static/images/favicon.ico View File

Before After

BIN
ReyMotaAppsRancher/reymota/repostajes/static/images/favicon.png View File

Before After
Width: 32  |  Height: 32  |  Size: 1.7 KiB

+ 21
- 0
ReyMotaAppsRancher/reymota/repostajes/static/images/portal-logo.svg View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="215px" height="215px" viewBox="0 0 215 215" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 52.6 (67491) - http://www.bohemiancoding.com/sketch -->
<title>portal-logo</title>
<desc>Created with Sketch.</desc>
<defs>
<path d="M51.165,8.742 C54.505,12.619 56.876,17.365 57.892,22.588 C60.148,17.225 65.452,13.46 71.636,13.46 C79.867,13.46 86.541,20.134 86.541,28.365 C86.541,36.597 79.867,43.269 71.636,43.269 C63.404,43.269 56.728,36.597 56.728,28.365 C56.728,12.7 44.03,0 28.365,0 C12.7,0 0,12.7 0,28.365 C0,44.031 12.7,56.731 28.365,56.731 C36.419,56.731 43.695,53.393 48.858,48.003 C45.501,44.117 43.128,39.383 42.108,34.14 C39.852,39.504 34.548,43.269 28.365,43.269 C20.133,43.269 13.46,36.597 13.46,28.365 C13.46,20.134 20.133,13.46 28.365,13.46 C36.966,13.46 43.27,20.577 43.27,28.365 C43.27,44.031 55.97,56.731 71.636,56.731 C87.3,56.731 100,44.031 100,28.365 C100,12.7 87.3,0 71.636,0 C63.589,0 56.327,3.358 51.165,8.742 Z" id="path-1"></path>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="portal-logo">
<circle id="Oval" fill="#09B6CA" fill-rule="nonzero" cx="107.5" cy="107.5" r="107.5"></circle>
<g id="logo" transform="translate(58.000000, 79.000000)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<g id="Clip-2"></g>
<polygon id="Fill-1" fill="#FFFFFE" mask="url(#mask-2)" points="-5 61.73 105 61.73 105 -5 -5 -5"></polygon>
</g>
</g>
</g>
</svg>

BIN
ReyMotaAppsRancher/reymota/repostajes/static/images/profiles/profile-1.png View File

Before After
Width: 120  |  Height: 120  |  Size: 34 KiB

BIN
ReyMotaAppsRancher/reymota/repostajes/static/images/profiles/profile-2.png View File

Before After
Width: 120  |  Height: 120  |  Size: 35 KiB

BIN
ReyMotaAppsRancher/reymota/repostajes/static/images/profiles/profile-3.png View File

Before After
Width: 120  |  Height: 120  |  Size: 37 KiB

BIN
ReyMotaAppsRancher/reymota/repostajes/static/images/profiles/profile-4.png View File

Before After
Width: 120  |  Height: 120  |  Size: 22 KiB

BIN
ReyMotaAppsRancher/reymota/repostajes/static/images/profiles/profile-5.png View File

Before After
Width: 120  |  Height: 120  |  Size: 36 KiB

BIN
ReyMotaAppsRancher/reymota/repostajes/static/images/profiles/profile-6.png View File

Before After
Width: 120  |  Height: 120  |  Size: 29 KiB

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save