diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..fb31cd2 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ + +*.pyc +*.pyo +.git/ +__pycache__ +Dockerfile +Tiltfile +tilt* +kubernetes.yaml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a3ce754 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,10 @@ +FROM python:3.8-alpine + +ADD requirements.txt . +RUN pip install -r requirements.txt +WORKDIR /app +ENV PYTHONUNBUFFERED 1 +ADD . . +RUN chmod +x /app/dockerentry.sh +ENTRYPOINT ["/app/dockerentry.sh"] +EXPOSE 8000 diff --git a/Tiltfile b/Tiltfile new file mode 100644 index 0000000..549b5e5 --- /dev/null +++ b/Tiltfile @@ -0,0 +1,10 @@ +# -*- mode: Python -* +cfg = read_json('tilt_config.json') +k8s_yaml('kubernetes.yaml') +k8s_resource('tilt-deploy', port_forwards=8000) + +# Replace the cluster context where you have to deploy +allow_k8s_contexts(cfg['K8S_CONTEXT']) + +#Container registry to sync images from ... +docker_build(cfg['CONTAINER_REGISTRY'], '.', build_args={}) diff --git a/dockerentry.sh b/dockerentry.sh new file mode 100644 index 0000000..9b095a6 --- /dev/null +++ b/dockerentry.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +echo "Start Django app" + +python manage.py runserver 0.0.0.0:8000 diff --git a/kubernetes.yaml b/kubernetes.yaml new file mode 100644 index 0000000..f14bdff --- /dev/null +++ b/kubernetes.yaml @@ -0,0 +1,22 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tilt-deploy + labels: + app: tilt-deploy +spec: + selector: + matchLabels: + app: tilt-deploy + template: + metadata: + labels: + app: tilt-deploy + spec: + containers: + - name: tilt-deploy + image: tilt-demo # Change the image + ports: + - containerPort: 8000 + imagePullSecrets: + - name: dockercreds diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..6048b68 --- /dev/null +++ b/manage.py @@ -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', 'myserver.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() diff --git a/myapp/__init__.py b/myapp/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/myapp/admin.py b/myapp/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/myapp/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/myapp/apps.py b/myapp/apps.py new file mode 100644 index 0000000..c34fb20 --- /dev/null +++ b/myapp/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class MyappConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'myapp' diff --git a/myapp/migrations/__init__.py b/myapp/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/myapp/models.py b/myapp/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/myapp/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/myapp/tests.py b/myapp/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/myapp/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/myapp/urls.py b/myapp/urls.py new file mode 100644 index 0000000..88a9cac --- /dev/null +++ b/myapp/urls.py @@ -0,0 +1,7 @@ +from django.urls import path + +from . import views + +urlpatterns = [ + path('', views.index, name='index'), +] diff --git a/myapp/views.py b/myapp/views.py new file mode 100644 index 0000000..eb790ad --- /dev/null +++ b/myapp/views.py @@ -0,0 +1,14 @@ +from django.shortcuts import render + +# Create your views here. + +from django.http import HttpResponse +from django.shortcuts import render + + +#def index(request): +# return HttpResponse("Simple Django App to demonstrate Tilt workflow") + +def index (request): + return render(request, 'index.html') + diff --git a/myserver/__init__.py b/myserver/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/myserver/asgi.py b/myserver/asgi.py new file mode 100644 index 0000000..8fde1e6 --- /dev/null +++ b/myserver/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for myserver 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/3.2/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myserver.settings') + +application = get_asgi_application() diff --git a/myserver/settings.py b/myserver/settings.py new file mode 100644 index 0000000..9f2599b --- /dev/null +++ b/myserver/settings.py @@ -0,0 +1,131 @@ +""" +Django settings for myserver project. + +Generated by 'django-admin startproject' using Django 3.2.2. + +For more information on this file, see +https://docs.djangoproject.com/en/3.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/3.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/3.2/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-o=npbzcu3@pdzd0z^hs^-7rj&kliqw+u7!1g-9***triu+88@$' + +# 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 = 'myserver.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [os.path.join(BASE_DIR, 'templates')], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'myserver.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/3.2/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} + + +# Password validation +# https://docs.djangoproject.com/en/3.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/3.2/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/3.2/howto/static-files/ + +STATIC_URL = '/static/' +PROJECT_DIR = os.path.dirname(os.path.abspath(__file__)) +STATIC_ROOT = os.path.join(PROJECT_DIR, 'static') +STATICFILES_DIRS = [ + os.path.join(BASE_DIR, "static"), +] + +# Default primary key field type +# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' diff --git a/myserver/urls.py b/myserver/urls.py new file mode 100644 index 0000000..dc8b43b --- /dev/null +++ b/myserver/urls.py @@ -0,0 +1,22 @@ +"""myserver URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/3.2/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('tilt/', include('myapp.urls')), +] diff --git a/myserver/wsgi.py b/myserver/wsgi.py new file mode 100644 index 0000000..c2122bc --- /dev/null +++ b/myserver/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for myserver 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/3.2/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myserver.settings') + +application = get_wsgi_application() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..ab947b9 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +Django==3.2.2 diff --git a/static/style.css b/static/style.css new file mode 100644 index 0000000..882440a --- /dev/null +++ b/static/style.css @@ -0,0 +1,209 @@ +body { + font-family: "Open Sans", sans-serif; + color: #444444; +} + +a { + color: #009cea; + text-decoration: none; +} + +a:hover { + color: #1eb4ff; + text-decoration: none; +} + +h1, h2, h3, h4, h5, h6 { + font-family: "Raleway", sans-serif; +} + +/*-------------------------------------------------------------- +# Back to top button +--------------------------------------------------------------*/ +.back-to-top { + position: fixed; + visibility: hidden; + opacity: 0; + right: 15px; + bottom: 15px; + z-index: 996; + background: #009cea; + width: 40px; + height: 40px; + border-radius: 4px; + transition: all 0.4s; +} + +.back-to-top i { + font-size: 28px; + color: #fff; + line-height: 0; +} + +.back-to-top:hover { + background: #14b1ff; + color: #fff; +} + +.back-to-top.active { + visibility: visible; + opacity: 1; +} + +/*-------------------------------------------------------------- +# Header +--------------------------------------------------------------*/ +#header { + height: 72px; + transition: all 0.5s; + z-index: 997; + transition: all 0.5s; + background: #fff; +} + +#header.header-scrolled { + box-shadow: 0px 2px 15px rgba(0, 0, 0, 0.1); +} + +#header .logo h1 { + font-size: 28px; + margin: 0; + line-height: 0; + font-weight: 600; + letter-spacing: 1px; + font-family: "Open Sans", sans-serif; +} + +#header .logo h1 a, #header .logo h1 a:hover { + color: #576971; + text-decoration: none; + +} + +#header .logo img { + padding: 0; + margin: 0; + max-height: 40px; +} + +/*-------------------------------------------------------------- +# Header Social Links +--------------------------------------------------------------*/ +.header-social-links { + margin: 0 0 0 30px; +} + +@media (max-width: 768px) { + .header-social-links { + margin: 0 15px 0 0; + } +} + +.header-social-links a { + color: #7b909a; + display: inline-block; + line-height: 0px; + transition: 0.3s; + padding-left: 10px; +} + +.header-social-links a:hover { + color: #009cea; +} + +/*-------------------------------------------------------------- +# Navigation Menu +--------------------------------------------------------------*/ +/** +* Desktop Navigation +*/ +.navbar { + padding: 0; +} + +.navbar ul { + margin: 0; + padding: 0; + display: flex; + list-style: none; + align-items: center; +} + +.navbar li { + position: relative; +} + +.navbar a { + display: flex; + align-items: center; + justify-content: space-between; + padding: 10px 0 10px 30px; + font-size: 15px; + font-family: "Poppins", sans-serif; + color: #7b909a; + white-space: nowrap; + transition: 0.3s; +} + +.navbar a i { + font-size: 12px; + line-height: 0; + margin-left: 5px; +} + +.navbar a:hover, .navbar .active, .navbar li:hover > a { + color: #009cea; +} + +/*-------------------------------------------------------------- +# Hero Section +--------------------------------------------------------------*/ +#hero { + width: 100%; + margin-top: 80px; + padding: 60px 0; +} + +#hero h1 { + margin: 0 0 20px 0; + font-size: 48px; + font-weight: 700; + line-height: 56px; + color: #364146; +} + +#hero h2 { + color: #576971; + margin-bottom: 30px; + font-size: 24px; +} + +#hero .btn-get-started { + font-family: "Raleway", sans-serif; + font-weight: 600; + font-size: 13px; + text-transform: uppercase; + letter-spacing: 1px; + display: inline-block; + padding: 12px 28px; + border-radius: 3px; + transition: 0.5s; + color: #fff; + background: #009cea; +} + +#hero .hero-img img { + display: block; + margin-left: auto; + margin-right: auto; + width: 70%; +} + +#hero .hero-content { + display: block; + margin-left: auto; + margin-right: auto; + text-align: center; + padding: 4rem; +} + diff --git a/static/tilt.jpeg b/static/tilt.jpeg new file mode 100644 index 0000000..08d7624 Binary files /dev/null and b/static/tilt.jpeg differ diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..7bd80a5 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,72 @@ +{% load static %} + + + + +
+ + + +