Skip to content

Commit 7f8bfc8

Browse files
committed
🎉 First commit, from couchbase generator, basic changes
not tested / updated yet
0 parents  commit 7f8bfc8

File tree

198 files changed

+21022
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

198 files changed

+21022
-0
lines changed

Diff for: .gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.vscode
2+
testing-project
3+
docker-stack.yml
4+
.mypy_cache

Diff for: .travis.yml

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
sudo: required
2+
3+
language: python
4+
5+
install:
6+
- pip install cookiecutter
7+
8+
services:
9+
- docker
10+
11+
script:
12+
- bash ./test.sh

Diff for: LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2019 Sebastián Ramírez
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

Diff for: README.md

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# Full Stack Flask and PostgreSQL - Base Project Generator
2+
3+
[![Build Status](https://travis-ci.org/tiangolo/full-stack.svg?branch=master)](https://travis-ci.org/tiangolo/full-stack)
4+
5+
Generate a backend and frontend stack using Python, including interactive API documentation.
6+
7+
[![Screenshot](screenshot.png)](https://github.com/tiangolo/full-stack)
8+
9+
## Features
10+
11+
* Full **Docker** integration (Docker based)
12+
* Docker Swarm Mode deployment
13+
* **Docker Compose** integration and optimization for local development
14+
* **Production ready** Python web server using Nginx and uWSGI
15+
* Python **Flask** backend with:
16+
* **Flask-apispec**: Swagger live documentation generation
17+
* **Marshmallow**: model and data serialization (convert model objects to JSON)
18+
* **Webargs**: parse, validate and document inputs to the endpoint / route
19+
* **Secure password** hashing by default
20+
* **JWT token** authentication
21+
* **SQLAlchemy** models (independent of Flask extensions, so they can be used with Celery workers directly)
22+
* Basic starting models for users and groups (modify and remove as you need)
23+
* **Alembic** migrations
24+
* **CORS** (Cross Origin Resource Sharing)
25+
* **Celery** worker that can import and use models and code from the rest of the backend selectively (you don't have to install the complete app in each worker)
26+
* REST backend tests based on **Pytest**, integrated with Docker, so you can test the full API interaction, independent on the database. As it runs in Docker, it can build a new data store from scratch each time (so you can use ElasticSearch, MongoDB, CouchDB, or whatever you want, and just test that the API works)
27+
* Easy Python integration with **Jupyter Kernels** for remote or in-Docker development with extensions like Atom Hydrogen or Visual Studio Code Jupyter
28+
* Vue frontend:
29+
* Generated with **Vue CLI**
30+
* JWT Authentication handling
31+
* Login view
32+
* After login, main dashboard view
33+
* **Vuex**
34+
* **Vue-router**
35+
* **Vuetify** for beautiful material design components
36+
* **TypeScript**
37+
* Docker server based on **Nginx** (configured to play nicely with Vue-router)
38+
* Docker multi-stage building, so you don't need to save or commit compiled code
39+
* Frontend tests ran at build time (can be disabled too)
40+
* Made as modular as possible, so it works out of the box, but you can re-generate with Vue CLI or create it as you need, and re-use what you want
41+
* **PGAdmin** for PostgreSQL database, you can modify it to use PHPMyAdmin and MySQL easily
42+
* **Swagger-UI** for live interactive documentation
43+
* **Flower** for Celery jobs monitoring
44+
* Load balancing between frontend and backend with **Traefik**, so you can have both under the same domain, separated by path, but served by different containers
45+
* Traefik integration, including Let's Encrypt **HTTPS** certificates automatic generation
46+
* **GitLab CI** (continuous integration), including frontend and backend testing
47+
48+
## How to use it
49+
50+
Go to the directoy where you want to create your project and run:
51+
52+
```bash
53+
pip install cookiecutter
54+
cookiecutter https://github.com/tiangolo/full-stack
55+
```
56+
57+
### Generate passwords
58+
59+
You will be asked to provide passwords and secret keys for several components. Open another terminal and run:
60+
61+
```bash
62+
openssl rand -hex 32
63+
# Outputs something like: 99d3b1f01aa639e4a76f4fc281fc834747a543720ba4c8a8648ba755aef9be7f
64+
```
65+
66+
Copy the contents and use that as password / secret key. And run that again to generate another secure key.
67+
68+
69+
### Input variables
70+
71+
The generator (cookiecutter) will ask you for some data, you might want to have at hand before generating the project.
72+
73+
The input variables, with their default values (some auto generated) are:
74+
75+
* `project_name`: The name of the project
76+
* `project_slug`: The development friendly name of the project. By default, based on the project name
77+
* `domain_main`: The domain in where to deploy the project for production (from the branch `production`), used by the load balancer, backend, etc. By default, based on the project slug.
78+
* `domain_staging`: The domain in where to deploy while staging (before production) (from the branch `master`). By default, based on the main domain.
79+
80+
* `docker_swarm_stack_name_main`: The name of the stack while deploying to Docker in Swarm mode for production. By default, based on the domain.
81+
* `docker_swarm_stack_name_staging`: The name of the stack while deploying to Docker in Swarm mode for staging. By default, based on the domain.
82+
83+
* `secret_key`: Backend server secret key. Use the method above to generate it.
84+
* `first_superuser`: The first superuser generated, with it you will be able to create more users, etc. By default, based on the domain.
85+
* `first_superuser_password`: First superuser password. Use the method above to generate it.
86+
* `backend_cors_origins`: Origins (domains, more or less) that are enabled for CORS (Cross Origin Resource Sharing). This allows a frontend in one domain (e.g. `https://dashboard.example.com`) to communicate with this backend, that could be living in another domain (e.g. `https://api.example.com`). It can also be used to allow your local frontend (with a custom `hosts` domain mapping, as described in the project's `README.md`) that could be living in `http://dev.example.com:8080` to cummunicate with the backend at `https://stag.example.com`. Notice the `http` vs `https` and the `dev.` prefix for local development vs the "staging" `stag.` prefix. By default, it includes origins for production, staging and development, with ports commonly used during local development by several popular frontend frameworks (Vue with `:8080`, React, Angular).
87+
88+
* `postgres_password`: Postgres database password. Use the method above to generate it. (You could easily modify it to use MySQL, MariaDB, etc).
89+
* `pgadmin_default_user`: PGAdmin default user, to log-in to the PGAdmin interface.
90+
* `pgadmin_default_user_password`: PGAdmin default user password. Generate it with the method above.
91+
92+
* `traefik_constraint_tag`: The tag to be used by the internal Traefik load balancer (for example, to divide requests between backend and frontend) for production. Used to separate this stack from any other stack you might have. This should identify each stack in each environment (production, staging, etc).
93+
* `traefik_constraint_tag_staging`: The Traefik tag to be used while on staging.
94+
* `traefik_public_network`: This assumes you have another separate publicly facing Traefik at the server / cluster level. This is the network that main Traefik lives in.
95+
* `traefik_public_constraint_tag`: The tag that should be used by stack services that should communicate with the public.
96+
97+
* `flower_auth`: Basic HTTP authentication for flower, in the form`user:password`. By default: "`root:changethis`".
98+
99+
* `sentry_dsn`: Key URL (DSN) of Sentry, for live error reporting. If you are not using it yet, you should, is open source. E.g.: `https://1234abcd:5678ef@sentry.example.com/30`.
100+
101+
* `docker_image_prefix`: Prefix to use for Docker image names. If you are using GitLab Docker registry it would be based on your code repository. E.g.: `git.example.com/development-team/my-awesome-project/`.
102+
* `docker_image_backend`: Docker image name for the backend. By default, it will be based on your Docker image prefix, e.g.: `git.example.com/development-team/my-awesome-project/backend`. And depending on your environment, a different tag will be appended ( `prod`, `stag`, `branch` ). So, the final image names used will be like: `git.example.com/development-team/my-awesome-project/backend:prod`.
103+
* `docker_image_celeryworker`: Docker image for the celery worker. By default, based on your Docker image prefix.
104+
* `docker_image_frontend`: Docker image for the frontend. By default, based on your Docker image prefix.
105+
106+
## How to deploy
107+
108+
This stack can be adjusted and used with several deployment options that are compatible with Docker Compose, but it is designed to be used in a cluster controlled with pure Docker in Swarm Mode with a Traefik main load balancer proxy handling automatic HTTPS certificates, using the ideas from <a href="https://dockerswarm.rocks" target="_blank">DockerSwarm.rocks</a>.
109+
110+
Please refer to <a href="https://dockerswarm.rocks" target="_blank">DockerSwarm.rocks</a> to see how to deploy such a cluster in 20 minutes.
111+
112+
## More details
113+
114+
After using this generator, your new project (the directory created) will contain an extensive `README.md` with instructions for development, deployment, etc. You can pre-read [the project `README.md` template here too](./{{cookiecutter.project_slug}}/README.md).
115+
116+
## History
117+
118+
**Note about Angular**: a previous version of this project generated a basic default Angular frontend application, but without any view or interaction with the rest of the stack (the backend API). I recently switched to Vue for frontend and used it to created the basic frontend views for this project (that didn't exist before). If you are interested in keeping the Angular version, let me know in an issue, I can create an Angular version of the project (without the current default views), then you can integrate your Angular app with the basic `Dockerfile` and additional files.
119+
120+
This project was based on [senseta-os/senseta-base-project](https://github.com/senseta-os/senseta-base-project).
121+
122+
As [I was the only maintainer](https://github.com/tiangolo), I'm continuing the development in this fork (https://github.com/tiangolo/full-stack).
123+
124+
## License
125+
126+
This project is licensed under the terms of the MIT license.

Diff for: cookiecutter.json

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"project_name": "Base Project",
3+
"project_slug": "{{ cookiecutter.project_name|lower|replace(' ', '-') }}",
4+
"domain_main": "{{cookiecutter.project_slug}}.com",
5+
"domain_staging": "stag.{{cookiecutter.domain_main}}",
6+
7+
"docker_swarm_stack_name_main": "{{cookiecutter.domain_main|replace('.', '-')}}",
8+
"docker_swarm_stack_name_staging": "{{cookiecutter.domain_staging|replace('.', '-')}}",
9+
10+
"secret_key": "changethis",
11+
"first_superuser": "admin@{{cookiecutter.domain_main}}",
12+
"first_superuser_password": "changethis",
13+
"backend_cors_origins": "http://localhost, http://localhost:4200, http://localhost:3000, http://localhost:8080, https://localhost, https://localhost:4200, https://localhost:3000, https://localhost:8080, http://dev.{{cookiecutter.domain_main}}, https://{{cookiecutter.domain_staging}}, https://{{cookiecutter.domain_main}}, http://local.dockertoolbox.tiangolo.com, http://localhost.tiangolo.com",
14+
"smtp_port": "587",
15+
"smtp_host": "",
16+
"smtp_user": "",
17+
"smtp_password": "",
18+
"smtp_emails_from_email": "info@{{cookiecutter.domain_main}}",
19+
20+
"postgres_password": "changethis",
21+
"pgadmin_default_user": "{{cookiecutter.first_superuser}}",
22+
"pgadmin_default_user_password": "changethis",
23+
24+
"traefik_constraint_tag": "{{cookiecutter.domain_main}}",
25+
"traefik_constraint_tag_staging": "{{cookiecutter.domain_staging}}",
26+
"traefik_public_network": "traefik-public",
27+
"traefik_public_constraint_tag": "traefik-public",
28+
29+
"flower_auth": "admin:{{cookiecutter.first_superuser_password}}",
30+
31+
"sentry_dsn": "",
32+
33+
"docker_image_prefix": "",
34+
35+
"docker_image_backend": "{{cookiecutter.docker_image_prefix}}backend",
36+
"docker_image_celeryworker": "{{cookiecutter.docker_image_prefix}}celeryworker",
37+
"docker_image_frontend": "{{cookiecutter.docker_image_prefix}}frontend",
38+
39+
"_copy_without_render": [
40+
"frontend/src/**/*.html",
41+
"frontend/src/**/*.vue",
42+
"frontend/node_modules/*",
43+
"backend/app/app/email-templates/**"
44+
]
45+
}

Diff for: screenshot.png

84.8 KB
Loading

Diff for: scripts/discard-dev-files.sh

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
rm -rf \{\{cookiecutter.project_slug\}\}/.git
2+
rm -rf \{\{cookiecutter.project_slug\}\}/frontend/node_modules
3+
rm -rf \{\{cookiecutter.project_slug\}\}/frontend/dist
4+
git checkout \{\{cookiecutter.project_slug\}\}/README.md
5+
git checkout \{\{cookiecutter.project_slug\}\}/.gitlab-ci.yml
6+
git checkout \{\{cookiecutter.project_slug\}\}/cookiecutter-config-file.yml
7+
git checkout \{\{cookiecutter.project_slug\}\}/docker-compose.deploy.networks.yml
8+
git checkout \{\{cookiecutter.project_slug\}\}/env-backend.env
9+
git checkout \{\{cookiecutter.project_slug\}\}/env-couchbase.env
10+
git checkout \{\{cookiecutter.project_slug\}\}/env-flower.env
11+
git checkout \{\{cookiecutter.project_slug\}\}/.env
12+
git checkout \{\{cookiecutter.project_slug\}\}/frontend/.env
13+
git checkout \{\{cookiecutter.project_slug\}\}/env-sync-gateway.env

Diff for: scripts/generate_cookiecutter_config.py

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import json
2+
from collections import OrderedDict
3+
import oyaml as yaml
4+
from pathlib import Path
5+
cookie_path = Path('./cookiecutter.json')
6+
out_path = Path('./{{cookiecutter.project_slug}}/cookiecutter-config-file.yml')
7+
8+
with open(cookie_path) as f:
9+
cookie_config = json.load(f)
10+
config_out = OrderedDict()
11+
12+
for key, value in cookie_config.items():
13+
if key.startswith('_'):
14+
config_out[key] = value
15+
else:
16+
config_out[key] = '{{ cookiecutter.' + key + ' }}'
17+
config_out['_template'] = './'
18+
19+
with open(out_path, 'w') as out_f:
20+
out_f.write(yaml.dump({'default_context': config_out}, line_break=None, width=200))

Diff for: test.sh

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#! /usr/bin/env bash
2+
3+
# Exit in case of error
4+
set -e
5+
6+
rm -rf ./testing-project
7+
8+
cookiecutter --config-file ./testing-config.yml --no-input -f ./
9+
10+
cd ./testing-project
11+
12+
bash ./scripts/test.sh
13+
14+
cd ../

Diff for: testing-config.yml

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
default_context:
2+
"project_name": "Testing Project"

Diff for: {{cookiecutter.project_slug}}/.env

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
COMPOSE_PATH_SEPARATOR=:
2+
COMPOSE_FILE=docker-compose.test.yml:docker-compose.shared.admin.yml:docker-compose.shared.base-images.yml:docker-compose.shared.depends.yml:docker-compose.shared.env.yml:docker-compose.dev.build.yml:docker-compose.dev.command.yml:docker-compose.dev.env.yml:docker-compose.dev.labels.yml:docker-compose.dev.networks.yml:docker-compose.dev.ports.yml:docker-compose.dev.volumes.yml
3+
4+
DOMAIN=localhost
5+
# DOMAIN=local.dockertoolbox.tiangolo.com
6+
# DOMAIN=localhost.tiangolo.com
7+
# DOMAIN=dev.{{cookiecutter.domain_main}}
8+
9+
TRAEFIK_TAG={{cookiecutter.traefik_constraint_tag}}
10+
TRAEFIK_PUBLIC_NETWORK={{cookiecutter.traefik_public_network}}
11+
TRAEFIK_PUBLIC_TAG={{cookiecutter.traefik_public_constraint_tag}}
12+
13+
DOCKER_IMAGE_BACKEND={{cookiecutter.docker_image_backend}}
14+
DOCKER_IMAGE_CELERYWORKER={{cookiecutter.docker_image_celeryworker}}
15+
DOCKER_IMAGE_FRONTEND={{cookiecutter.docker_image_frontend}}
16+
DOCKER_IMAGE_SYNC_GATEWAY={{cookiecutter.docker_image_sync_gateway}}

Diff for: {{cookiecutter.project_slug}}/.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.vscode
2+
.mypy_cache

Diff for: {{cookiecutter.project_slug}}/.gitlab-ci.yml

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
image: tiangolo/docker-with-compose
2+
3+
before_script:
4+
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
5+
- pip install docker-auto-labels
6+
7+
stages:
8+
- test
9+
- build
10+
- deploy
11+
12+
tests:
13+
stage: test
14+
script:
15+
- sh ./scripts/test.sh
16+
tags:
17+
- build
18+
- test
19+
20+
build-stag:
21+
stage: build
22+
script:
23+
- TAG=stag FRONTEND_ENV=staging sh ./scripts/build-push.sh
24+
only:
25+
- master
26+
tags:
27+
- build
28+
- test
29+
30+
build-prod:
31+
stage: build
32+
script:
33+
- TAG=prod FRONTEND_ENV=production sh ./scripts/build-push.sh
34+
only:
35+
- production
36+
tags:
37+
- build
38+
- test
39+
40+
deploy-stag:
41+
stage: deploy
42+
script:
43+
- >
44+
DOMAIN={{cookiecutter.domain_staging}}
45+
TRAEFIK_TAG={{cookiecutter.traefik_constraint_tag_staging}}
46+
STACK_NAME={{cookiecutter.docker_swarm_stack_name_staging}}
47+
TAG=stag
48+
sh ./scripts/deploy.sh
49+
environment:
50+
name: staging
51+
url: https://{{cookiecutter.domain_staging}}
52+
only:
53+
- master
54+
tags:
55+
- swarm
56+
- stag
57+
58+
deploy-prod:
59+
stage: deploy
60+
script:
61+
- >
62+
DOMAIN={{cookiecutter.domain_main}}
63+
TRAEFIK_TAG={{cookiecutter.traefik_constraint_tag}}
64+
STACK_NAME={{cookiecutter.docker_swarm_stack_name_main}}
65+
TAG=prod
66+
sh ./scripts/deploy.sh
67+
environment:
68+
name: production
69+
url: https://{{cookiecutter.domain_main}}
70+
only:
71+
- production
72+
tags:
73+
- swarm
74+
- prod

0 commit comments

Comments
 (0)