Added backstage template for basic python django application
This commit is contained in:
parent
1a8c2846bc
commit
59ff83a8f8
14 changed files with 453 additions and 0 deletions
|
@ -10,6 +10,7 @@ spec:
|
||||||
- ./app-with-bucket/template.yaml
|
- ./app-with-bucket/template.yaml
|
||||||
- ./demo-go-hello-world/template.yaml
|
- ./demo-go-hello-world/template.yaml
|
||||||
- ./spring-petclinic/template.yaml
|
- ./spring-petclinic/template.yaml
|
||||||
|
- ./django_template/template.yaml
|
||||||
---
|
---
|
||||||
apiVersion: backstage.io/v1alpha1
|
apiVersion: backstage.io/v1alpha1
|
||||||
kind: Location
|
kind: Location
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
name: ci
|
||||||
|
|
||||||
|
on: push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Repository meta
|
||||||
|
id: repository
|
||||||
|
run: |
|
||||||
|
registry=${{ github.server_url }}
|
||||||
|
registry=${registry##http*://}
|
||||||
|
echo "registry=${registry}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "registry=${registry}"
|
||||||
|
repository="$(echo "${{ github.repository }}" | tr '[:upper:]' '[:lower:]')"
|
||||||
|
echo "repository=${repository}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "repository=${repository}"
|
||||||
|
-
|
||||||
|
name: Docker meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
id: docker
|
||||||
|
with:
|
||||||
|
images: ${{ steps.repository.outputs.registry }}/${{ steps.repository.outputs.repository }}
|
||||||
|
-
|
||||||
|
name: Login to registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: {% raw %} ${{ steps.repository.outputs.registry }}
|
||||||
|
username: ${{ secrets.PACKAGES_USER }}
|
||||||
|
password: ${{ secrets.PACKAGES_TOKEN }} {% endraw %}
|
||||||
|
-
|
||||||
|
name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
with:
|
||||||
|
buildkitd-flags: '--allow-insecure-entitlement network.host'
|
||||||
|
driver-opts: network=host
|
||||||
|
-
|
||||||
|
name: Build and push
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
push: true
|
||||||
|
allow: network.host
|
||||||
|
network: host
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
tags: ${{ steps.docker.outputs.tags }}
|
|
@ -0,0 +1,10 @@
|
||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
CMD ["python", "project/manage.py", "runserver", "0.0.0.0:8000"]
|
|
@ -0,0 +1,35 @@
|
||||||
|
---
|
||||||
|
apiVersion: backstage.io/v1alpha1
|
||||||
|
kind: Component
|
||||||
|
metadata:
|
||||||
|
name: ${{ values.name }}
|
||||||
|
description: A Django application generated via a custom Backstage template.
|
||||||
|
annotations:
|
||||||
|
backstage.io/techdocs-ref: dir:.
|
||||||
|
backstage.io/kubernetes-label-selector: 'app=django'
|
||||||
|
backstage.io/kubernetes-namespace: ${{ values.namespace }}
|
||||||
|
argocd/app-name: ${{values.name | dump}}
|
||||||
|
links:
|
||||||
|
- url: https://gitea-192-168-197-3.c-one-infra.de/giteaAdmin/${{ values.name }}
|
||||||
|
title: Source Code Repository
|
||||||
|
icon: git
|
||||||
|
spec:
|
||||||
|
owner: guests
|
||||||
|
lifecycle: experimental
|
||||||
|
type: service
|
||||||
|
system: ${{ values.name | dump }}
|
||||||
|
---
|
||||||
|
apiVersion: backstage.io/v1alpha1
|
||||||
|
kind: System
|
||||||
|
metadata:
|
||||||
|
name: ${{ values.name | dump }}
|
||||||
|
description: A system containing a Django application created via template.
|
||||||
|
annotations:
|
||||||
|
backstage.io/techdocs-ref: dir:.
|
||||||
|
links:
|
||||||
|
- url: https://gitea-192-168-197-3.c-one-infra.de/giteaAdmin/${{ values.name }}
|
||||||
|
title: Gitea Repository
|
||||||
|
icon: git
|
||||||
|
spec:
|
||||||
|
owner: guests
|
||||||
|
lifecycle: experimental
|
|
@ -0,0 +1,78 @@
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: ${{ values.namespace }}
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: django
|
||||||
|
namespace: ${{ values.namespace }}
|
||||||
|
labels:
|
||||||
|
app: django
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 8000
|
||||||
|
targetPort: http
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
app: django
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: ${{ values.namespace }}
|
||||||
|
namespace: ${{ values.namespace }}
|
||||||
|
annotations:
|
||||||
|
nginx.ingress.kubernetes.io/rewrite-target: /$2
|
||||||
|
spec:
|
||||||
|
ingressClassName: nginx
|
||||||
|
rules:
|
||||||
|
- host: 192-168-197-3.c-one-infra.de
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- backend:
|
||||||
|
service:
|
||||||
|
name: django
|
||||||
|
port:
|
||||||
|
number: 8000
|
||||||
|
path: /${{ values.name }}
|
||||||
|
pathType: Prefix
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: django
|
||||||
|
namespace: ${{ values.namespace }}
|
||||||
|
labels:
|
||||||
|
app: django
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: django
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: django
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: django
|
||||||
|
image: gitea-192-168-197-3.c-one-infra.de/giteaadmin/${{ values.name }}
|
||||||
|
command: ["python", "project/manage.py", "runserver", "0.0.0.0:8000"]
|
||||||
|
env:
|
||||||
|
- name: APP_NAME
|
||||||
|
value: ${{ values.name }}
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 8000
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /healthcheck
|
||||||
|
port: http
|
||||||
|
periodSeconds: 10
|
||||||
|
|
|
@ -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', 'project.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()
|
|
@ -0,0 +1,16 @@
|
||||||
|
"""
|
||||||
|
ASGI config for project project.
|
||||||
|
|
||||||
|
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/5.2/howto/deployment/asgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.asgi import get_asgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')
|
||||||
|
|
||||||
|
application = get_asgi_application()
|
|
@ -0,0 +1,123 @@
|
||||||
|
"""
|
||||||
|
Django settings for project project.
|
||||||
|
|
||||||
|
Generated by 'django-admin startproject' using Django 5.2.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/5.2/topics/settings/
|
||||||
|
|
||||||
|
For the full list of settings and their values, see
|
||||||
|
https://docs.djangoproject.com/en/5.2/ref/settings/
|
||||||
|
"""
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
|
||||||
|
# Quick-start development settings - unsuitable for production
|
||||||
|
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
|
||||||
|
|
||||||
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
|
SECRET_KEY = 'django-insecure-8uqicq3zw$=f=%wc=z*!o)0f-%1f_v^6+^3p4+8fcq!u$3fnq6'
|
||||||
|
|
||||||
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
|
DEBUG = True
|
||||||
|
|
||||||
|
ALLOWED_HOSTS = ["*", ]
|
||||||
|
|
||||||
|
|
||||||
|
# Application definition
|
||||||
|
|
||||||
|
INSTALLED_APPS = [
|
||||||
|
'django.contrib.admin',
|
||||||
|
'django.contrib.auth',
|
||||||
|
'django.contrib.contenttypes',
|
||||||
|
'django.contrib.sessions',
|
||||||
|
'django.contrib.messages',
|
||||||
|
'django.contrib.staticfiles',
|
||||||
|
]
|
||||||
|
|
||||||
|
MIDDLEWARE = [
|
||||||
|
'django.middleware.security.SecurityMiddleware',
|
||||||
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
|
'django.middleware.common.CommonMiddleware',
|
||||||
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
|
]
|
||||||
|
|
||||||
|
ROOT_URLCONF = 'project.urls'
|
||||||
|
|
||||||
|
TEMPLATES = [
|
||||||
|
{
|
||||||
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
'DIRS': [],
|
||||||
|
'APP_DIRS': True,
|
||||||
|
'OPTIONS': {
|
||||||
|
'context_processors': [
|
||||||
|
'django.template.context_processors.request',
|
||||||
|
'django.contrib.auth.context_processors.auth',
|
||||||
|
'django.contrib.messages.context_processors.messages',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
WSGI_APPLICATION = 'project.wsgi.application'
|
||||||
|
|
||||||
|
|
||||||
|
# Database
|
||||||
|
# https://docs.djangoproject.com/en/5.2/ref/settings/#databases
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
'NAME': BASE_DIR / 'db.sqlite3',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Password validation
|
||||||
|
# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators
|
||||||
|
|
||||||
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Internationalization
|
||||||
|
# https://docs.djangoproject.com/en/5.2/topics/i18n/
|
||||||
|
|
||||||
|
LANGUAGE_CODE = 'en-us'
|
||||||
|
|
||||||
|
TIME_ZONE = 'UTC'
|
||||||
|
|
||||||
|
USE_I18N = True
|
||||||
|
|
||||||
|
USE_TZ = True
|
||||||
|
|
||||||
|
|
||||||
|
# Static files (CSS, JavaScript, Images)
|
||||||
|
# https://docs.djangoproject.com/en/5.2/howto/static-files/
|
||||||
|
|
||||||
|
STATIC_URL = 'static/'
|
||||||
|
|
||||||
|
# Default primary key field type
|
||||||
|
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
|
||||||
|
|
||||||
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
|
@ -0,0 +1,17 @@
|
||||||
|
from django.http import HttpResponse
|
||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
def hello_world(request):
|
||||||
|
return HttpResponse("Hello EDP!")
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('', hello_world)
|
||||||
|
]
|
||||||
|
|
||||||
|
def healthcheck(request):
|
||||||
|
return HttpResponse("I'm healthy!")
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path("healthcheck/", healthcheck),
|
||||||
|
path("", hello_world),
|
||||||
|
]
|
|
@ -0,0 +1,16 @@
|
||||||
|
"""
|
||||||
|
WSGI config for project project.
|
||||||
|
|
||||||
|
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/5.2/howto/deployment/wsgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.wsgi import get_wsgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')
|
||||||
|
|
||||||
|
application = get_wsgi_application()
|
|
@ -0,0 +1,4 @@
|
||||||
|
Django>=4.2
|
||||||
|
requests
|
||||||
|
celery
|
||||||
|
django-celery-beat
|
|
@ -0,0 +1,80 @@
|
||||||
|
apiVersion: scaffolder.backstage.io/v1beta3
|
||||||
|
kind: Template
|
||||||
|
metadata:
|
||||||
|
name: django-app
|
||||||
|
title: Django App Template
|
||||||
|
description: Template for creating a simple Django application with ArgoCD deployment
|
||||||
|
spec:
|
||||||
|
owner: user:guest
|
||||||
|
type: service
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
- title: Django App Configuration
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
title: Project Name
|
||||||
|
type: string
|
||||||
|
description: Unique name of the Django app
|
||||||
|
ui:autofocus: true
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- id: fetch-template
|
||||||
|
name: Generate Project
|
||||||
|
action: fetch:template
|
||||||
|
input:
|
||||||
|
url: ./skeleton
|
||||||
|
values:
|
||||||
|
name: ${{ parameters.name }}
|
||||||
|
gitea_username: ${{ secrets.GITEA_USERNAME }}
|
||||||
|
gitea_password: ${{ secrets.GITEA_PASSWORD }}
|
||||||
|
targetPath: ./
|
||||||
|
|
||||||
|
- id: fetch-overrides # Apply specific overrides to add features and make modifications for compatibility
|
||||||
|
name: Fetch Overrides
|
||||||
|
action: fetch:template
|
||||||
|
input:
|
||||||
|
# url: ./skeleton/.github/workflows
|
||||||
|
# targetPath: ./.github/workflows
|
||||||
|
url: ./skeleton/
|
||||||
|
targetPath: ./
|
||||||
|
replace: true
|
||||||
|
values:
|
||||||
|
name: ${{ parameters.name }}
|
||||||
|
namespace: ${{ parameters.name }}
|
||||||
|
|
||||||
|
- id: publish
|
||||||
|
name: Publish to Gitea
|
||||||
|
action: publish:gitea
|
||||||
|
input:
|
||||||
|
repoUrl: gitea-192-168-197-3.c-one-infra.de:443/?repo=${{ parameters.name }}
|
||||||
|
description: Django app for ${{ parameters.name }}
|
||||||
|
sourcePath: ./
|
||||||
|
defaultBranch: main
|
||||||
|
|
||||||
|
- id: create-argocd-app
|
||||||
|
name: Create ArgoCD App
|
||||||
|
action: cnoe:create-argocd-app
|
||||||
|
input:
|
||||||
|
appName: ${{ parameters.name }}
|
||||||
|
appNamespace: ${{ parameters.name }}
|
||||||
|
argoInstance: in-cluster
|
||||||
|
projectName: default
|
||||||
|
repoUrl: https://gitea-192-168-197-3.c-one-infra.de:443/giteaAdmin/${{ parameters.name }}
|
||||||
|
path: "k8s"
|
||||||
|
|
||||||
|
- id: register
|
||||||
|
name: Register in Backstage Catalog
|
||||||
|
action: catalog:register
|
||||||
|
input:
|
||||||
|
repoContentsUrl: ${{ steps['publish'].output.repoContentsUrl }}
|
||||||
|
catalogInfoPath: catalog-info.yaml
|
||||||
|
|
||||||
|
output:
|
||||||
|
links:
|
||||||
|
- title: Open Repository
|
||||||
|
url: ${{ steps['publish'].output.remoteUrl }}
|
||||||
|
- title: View in Catalog
|
||||||
|
icon: catalog
|
||||||
|
entityRef: ${{ steps['register'].output.entityRef }}
|
Loading…
Reference in a new issue