Compare commits
212
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2454d77ce8 | ||
|
|
5432647293 | ||
|
|
14d2e869bb | ||
|
|
ce9072124d | ||
|
|
f78ffcc595 | ||
|
|
57d2559ad3 | ||
|
|
024736c887 | ||
|
|
73f57871b4 | ||
|
|
cf0c355416 | ||
|
|
54c53d4510 | ||
|
|
5e247e831c | ||
|
|
ecaa988b5f | ||
|
|
73c89d8d93 | ||
|
|
1a41a01dfa | ||
|
|
5d26a4dd05 | ||
|
|
956e7fc1d0 | ||
|
|
73101d8cb9 | ||
|
|
e93f00321e | ||
|
|
914e1c691f | ||
|
|
e153be4b58 | ||
|
|
6cacd1a2cf | ||
|
|
eecdb55ba0 | ||
|
|
4de2cbf1bc | ||
|
|
aff4debd79 | ||
|
|
022ad01ace | ||
|
|
cda89ea243 | ||
|
|
aa0939be6d | ||
|
|
e74b659b45 | ||
|
|
f522b69a68 | ||
|
|
ef7b47b0c5 | ||
|
|
3d8fc1d848 | ||
|
|
5820be065c | ||
|
|
5ee60c8324 | ||
|
|
4918d968b7 | ||
|
|
75e172c7c0 | ||
|
|
9ad042b371 | ||
|
|
ed240d3cd0 | ||
|
|
2da9e9390d | ||
|
|
47bf1d40f9 | ||
|
|
256cc8cd71 | ||
|
|
51769fb08a | ||
|
|
cf26fa90d3 | ||
|
|
0cce30b7d2 | ||
|
|
200fea731c | ||
|
|
0eca15a19b | ||
|
|
fbe38faf59 | ||
|
|
0015e105f9 | ||
|
|
3dc8cce37a | ||
|
|
090eeccf8c | ||
|
|
17a7e173fe | ||
|
|
8d52c43e68 | ||
|
|
8c09ab3c6e | ||
|
|
7d4a1897f7 | ||
|
|
72ab577431 | ||
|
|
535617594f | ||
|
|
1230cac914 | ||
|
|
a3d5c16484 | ||
|
|
29ea329ed5 | ||
|
|
d719af498c | ||
|
|
b118391dc6 | ||
|
|
17d2f3544c | ||
|
|
25ba693bbd | ||
|
|
e5406b6549 | ||
|
|
5fa8ad286f | ||
|
|
d3061eddaf | ||
|
|
883e028cae | ||
|
|
2f4b93d11c | ||
|
|
57d7e8feee | ||
|
|
dd3b0b7731 | ||
|
|
c86301c9b2 | ||
|
|
3079df9072 | ||
|
|
1c04605dc7 | ||
|
|
2b8a4ed46f | ||
|
|
622f2c8758 | ||
|
|
4e6637aba9 | ||
|
|
c6784759cd | ||
|
|
55f27433f9 | ||
|
|
2dd02f0632 | ||
|
|
5d4bc9e93b | ||
|
|
ccb69a43d2 | ||
|
|
36755ccfb0 | ||
|
|
27dff192f2 | ||
|
|
e9dad6bfe5 | ||
|
|
69d161c19b | ||
|
|
103dcc919e | ||
|
|
3eea2ea4a2 | ||
|
|
d0a948e93f | ||
|
|
2a3c71f939 | ||
|
|
8caa778ee0 | ||
|
|
5521b70e46 | ||
|
|
c8d784ae2b | ||
|
|
910170b594 | ||
|
|
4dee3442b0 | ||
|
|
b38f2a8b2f | ||
|
|
1e8afcbc44 | ||
|
|
9e2b51de60 | ||
|
|
eb0f467aad | ||
|
|
da4b86f4d3 | ||
|
|
b5ef38bc0d | ||
|
|
c5b7e9dcde | ||
|
|
b611d41e8a | ||
|
|
c3ba43b0fa | ||
|
|
dc0e006e0f | ||
|
|
0b66858969 | ||
|
|
16c8fba623 | ||
|
|
852fccd95c | ||
|
|
316d07db61 | ||
|
|
bf99f618f6 | ||
|
|
534f0cb7cb | ||
|
|
974f6820d4 | ||
|
|
6ccf910e29 | ||
|
|
aaf1ced21c | ||
|
|
d05a3e2dc6 | ||
|
|
8be8b44584 | ||
|
|
4a028c04c9 | ||
|
|
1f1d7ab75d | ||
|
|
e0e5d9e290 | ||
|
|
181eb67501 | ||
|
|
8af976c528 | ||
|
|
beba1f16b4 | ||
|
|
76d0cbdb8d | ||
|
|
6ff0bb31d3 | ||
|
|
e78825b99f | ||
|
|
33a9d6fec7 | ||
|
|
b01145e6bd | ||
|
|
06024c82c1 | ||
|
|
ce4a4838f1 | ||
|
|
f80cfbeba7 | ||
|
|
61e5966083 | ||
|
|
f49a606693 | ||
|
|
2b866b32bb | ||
|
|
97896b5170 | ||
|
|
3647ff15e1 | ||
|
|
267f753452 | ||
|
|
c33e463e09 | ||
|
|
40cfc3c9f5 | ||
|
|
632ba5257e | ||
|
|
7127effdaf | ||
|
|
ca3f7e964e | ||
|
|
904e779b59 | ||
|
|
63054b4a3a | ||
|
|
871f3c5ba8 | ||
|
|
9c706bb9b1 | ||
|
|
06c57ca837 | ||
|
|
39a3ec055b | ||
|
|
401cf8e1a7 | ||
|
|
f50d624d22 | ||
|
|
4aeee1acb5 | ||
|
|
b6a9cfed19 | ||
|
|
a67dcf763b | ||
|
|
0f58c2dcae | ||
|
|
9cb1418b0d | ||
|
|
f62e6ca651 | ||
|
|
0c6ddd4904 | ||
|
|
14d4dbfe97 | ||
|
|
50d0c2cd4d | ||
|
|
4fe45169c3 | ||
|
|
78d93a16eb | ||
|
|
b94bf528be | ||
|
|
11ad57bce4 | ||
|
|
495a55f8c1 | ||
|
|
c611360c04 | ||
|
|
ada418374b | ||
|
|
3bf7f2a195 | ||
|
|
2d22cab6e7 | ||
|
|
96dcbe1798 | ||
|
|
ac6dc5b426 | ||
|
|
b4f22ffeea | ||
|
|
ca3ed630ed | ||
|
|
e2d3868a9e | ||
|
|
47314620be | ||
|
|
f26f3f2665 | ||
|
|
938b37e920 | ||
|
|
2c5a989306 | ||
|
|
88a6dd9316 | ||
|
|
77742c1d6f | ||
|
|
ba16c6475a | ||
|
|
1735098b3a | ||
|
|
2fdaaa47ab | ||
|
|
bd4e4aed27 | ||
|
|
94a8240ad4 | ||
|
|
be03af61ea | ||
|
|
4da34c98f3 | ||
|
|
12253f0621 | ||
|
|
369954f5d2 | ||
|
|
4eee702dce | ||
|
|
e90daa2e61 | ||
|
|
cc8570d02f | ||
|
|
98e5ea965c | ||
|
|
7a98ab1c6d | ||
|
|
70973a63fb | ||
|
|
ad82f73c1d | ||
|
|
e08016c103 | ||
|
|
a65e99b199 | ||
|
|
4853150f07 | ||
|
|
a341e66c13 | ||
|
|
874779d230 | ||
|
|
779e8a8b0f | ||
|
|
8f35e88ce4 | ||
|
|
71e874cfb4 | ||
|
|
622b8942b5 | ||
|
|
7aeb7d094c | ||
|
|
4ee80f8b7e | ||
|
|
4859fa6877 | ||
|
|
a1d831cdf2 | ||
|
|
a3ee639d77 | ||
|
|
cd274aea81 | ||
|
|
aaa548eb21 | ||
|
|
99f05a055d | ||
|
|
e614d50f9c | ||
|
|
20526c829c | ||
|
|
c9ed33f108 |
@@ -1,16 +0,0 @@
|
|||||||
FROM gitea.tryton.geeraert.eu/pi-ux-ce/python:3
|
|
||||||
|
|
||||||
ENV PYTHONUNBUFFERED 1
|
|
||||||
|
|
||||||
WORKDIR /code/
|
|
||||||
|
|
||||||
# Copy only the requirements file first (Changes infrequently)
|
|
||||||
COPY requirements.txt ./
|
|
||||||
|
|
||||||
|
|
||||||
RUN --mount=type=cache,target=/root/.cache/pip pip install --upgrade pip
|
|
||||||
RUN --mount=type=cache,target=/root/.cache/pip pip list --outdated
|
|
||||||
RUN --mount=type=cache,target=/root/.cache/pip pip install --upgrade wheel
|
|
||||||
RUN --mount=type=cache,target=/root/.cache/pip pip install --upgrade setuptools
|
|
||||||
RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt
|
|
||||||
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
django
|
|
||||||
psycopg2
|
|
||||||
requests
|
|
||||||
proxmoxer
|
|
||||||
docker
|
|
||||||
kubernetes
|
|
||||||
ruamel.yaml
|
|
||||||
pyyaml
|
|
||||||
django-bootstrap-v5
|
|
||||||
jinja2
|
|
||||||
watchdog
|
|
||||||
celery
|
|
||||||
redis
|
|
||||||
lxml
|
|
||||||
requests
|
|
||||||
@@ -2,96 +2,45 @@ name: Gitea Actions Demo
|
|||||||
run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀
|
run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
#paths-ignore:
|
branches:
|
||||||
# - 'requirements.txt'
|
- main
|
||||||
|
paths-ignore:
|
||||||
|
- 'django_testing/dockerfile'
|
||||||
issue_comment:
|
issue_comment:
|
||||||
types: [created]
|
types: [created]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# Job to check for file changes and set an output
|
|
||||||
changes:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
requirements_changed: ${{ steps.filter.outputs.requirements }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: dorny/paths-filter@v3
|
|
||||||
id: filter
|
|
||||||
with:
|
|
||||||
filters: |
|
|
||||||
requirements:
|
|
||||||
- 'requirements.txt'
|
|
||||||
|
|
||||||
Build-dockerfile:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: changes
|
|
||||||
if: ${{ needs.changes.outputs.requirements_changed == 'true' }}
|
|
||||||
steps:
|
|
||||||
- run: echo "🔎 The name of your branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
|
|
||||||
- name: Check out repository code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- run: echo "💡 The ${{ gitea.repository }} repository has been cloned to the runner."
|
|
||||||
- name: List files in the repository
|
|
||||||
run: |
|
|
||||||
ls ${{ gitea.workspace }}
|
|
||||||
|
|
||||||
- name: Compute next version
|
|
||||||
id: versioning
|
|
||||||
run: |
|
|
||||||
latest="${{ vars.PYTHON_VERSION }}"
|
|
||||||
next_version=$(echo "$latest" | awk -F. -v OFS=. '{$NF += 1 ; print}')
|
|
||||||
echo "next_version=$next_version" >> $GITHUB_ENV
|
|
||||||
echo "Variables used :"
|
|
||||||
echo "------------------------------------------------"
|
|
||||||
echo "Next version: $next_version"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: /root/.cache/pip
|
|
||||||
key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pip-
|
|
||||||
|
|
||||||
|
|
||||||
- name: inject cache into docker
|
|
||||||
uses: reproducible-containers/buildkit-cache-dance@v3.1.0
|
|
||||||
with:
|
|
||||||
cache-source: /root/.cache/pip
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Login to gitea
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: gitea.tryton.geeraert.eu
|
|
||||||
username: ${{ secrets.USERNAME_GITEA }}
|
|
||||||
password: ${{ secrets.PASSWORD_GITEA }}
|
|
||||||
|
|
||||||
- name: Build and push
|
|
||||||
uses: docker/build-push-action@v6
|
|
||||||
with:
|
|
||||||
context: "{{defaultContext}}:.gitea/python_build"
|
|
||||||
push: true
|
|
||||||
tags: |
|
|
||||||
gitea.tryton.geeraert.eu/pi-ux-ce/modified-python:latest
|
|
||||||
gitea.tryton.geeraert.eu/pi-ux-ce/modified-python:${{ env.next_version }}
|
|
||||||
cache-from: type=registry,ref=gitea.tryton.geeraert.eu/pi-ux-ce/modified-python:buildcache
|
|
||||||
cache-to: type=registry,ref=gitea.tryton.geeraert.eu/pi-ux-ce/modified-python:buildcache,mode=max
|
|
||||||
|
|
||||||
- name: update version in the variable
|
|
||||||
run: |
|
|
||||||
curl -X PUT -H "Content-Type: application/json" \
|
|
||||||
--user ${{ secrets.USERNAME_GITEA }}:${{ secrets.PASSWORD_GITEA }} \
|
|
||||||
https://gitea.tryton.geeraert.eu/api/v1/repos/pi-ux-ce/${{ github.event.repository.name }}/actions/variables/PYTHON_VERSION \
|
|
||||||
-d "{\"Value\":\"$next_version\"}"
|
|
||||||
Explore-Gitea-Actions:
|
Explore-Gitea-Actions:
|
||||||
runs-on: ubuntu-latest
|
env:
|
||||||
|
RUNNER_TOOL_CACHE: /toolcache
|
||||||
|
DEBUG: True
|
||||||
|
ALLOWED_HOSTS: "django.tryton.geeraert.eu"
|
||||||
|
container:
|
||||||
|
image: gitea.tryton.geeraert.eu/pi-ux-ce/custom-runner-debian-slim:1.0.6
|
||||||
|
volumes:
|
||||||
|
- act-toolcache:/opt/hostedtoolcache # this is where Runner store their cache default
|
||||||
|
runs-on: host-runner
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- run: echo "🔎 The name of your branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
|
- run: echo "🔎 The name of your branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
|
||||||
|
|
||||||
|
- name: restore git folder if exist
|
||||||
|
run: if [ -d "/opt/hostedtoolcache/${{ github.event.repository.name }}/" ]; then cp -r /opt/hostedtoolcache/${{ github.event.repository.name }}/ ${{ gitea.workspace }}; fi
|
||||||
|
|
||||||
|
- name: Check Docker Version
|
||||||
|
run: whereis docker
|
||||||
|
|
||||||
- name: Check out repository code
|
- name: Check out repository code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
clean: false
|
||||||
|
fetch-depth: 1
|
||||||
|
ref: 'main'
|
||||||
|
|
||||||
|
# - name: Manually check out repository code
|
||||||
|
# run: cd ${{ gitea.workspace }} ; git pull origin main
|
||||||
|
|
||||||
- run: echo "💡 The ${{ gitea.repository }} repository has been cloned to the runner."
|
- run: echo "💡 The ${{ gitea.repository }} repository has been cloned to the runner."
|
||||||
|
|
||||||
- name: List files in the repository
|
- name: List files in the repository
|
||||||
run: |
|
run: |
|
||||||
ls ${{ gitea.workspace }}
|
ls ${{ gitea.workspace }}
|
||||||
@@ -106,18 +55,19 @@ jobs:
|
|||||||
echo "------------------------------------------------"
|
echo "------------------------------------------------"
|
||||||
echo "Next version: $next_version"
|
echo "Next version: $next_version"
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
- name: Cache Docker layers
|
||||||
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: /root/.cache/pip
|
path: /opt/hostedtoolcache/.buildx-cache
|
||||||
key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
|
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-pip-
|
${{ runner.os }}-buildx-
|
||||||
|
|
||||||
|
|
||||||
- name: inject cache into docker
|
- name: inject cache into docker
|
||||||
uses: reproducible-containers/buildkit-cache-dance@v3.1.0
|
uses: reproducible-containers/buildkit-cache-dance@v3.1.0
|
||||||
with:
|
with:
|
||||||
cache-source: /root/.cache/pip
|
cache-source: /opt/hostedtoolcache/pip
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
@@ -133,11 +83,19 @@ jobs:
|
|||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
push: true
|
push: true
|
||||||
|
build-args: |
|
||||||
|
ALLOWED_HOSTS='django.tryton.geeraert.eu'
|
||||||
|
DEBUG='True'
|
||||||
tags: |
|
tags: |
|
||||||
gitea.tryton.geeraert.eu/pi-ux-ce/django-python:latest
|
gitea.tryton.geeraert.eu/pi-ux-ce/django-python:latest
|
||||||
gitea.tryton.geeraert.eu/pi-ux-ce/django-python:${{ env.next_version }}
|
gitea.tryton.geeraert.eu/pi-ux-ce/django-python:${{ env.next_version }}
|
||||||
cache-from: type=registry,ref=gitea.tryton.geeraert.eu/pi-ux-ce/django-python:buildcache
|
cache-from: type=local,src=/opt/hostedtoolcache/.buildx-cache
|
||||||
cache-to: type=registry,ref=gitea.tryton.geeraert.eu/pi-ux-ce/django-python:buildcache,mode=max
|
cache-to: type=local,dest=/opt/hostedtoolcache/.buildx-cache-new,mode=max
|
||||||
|
|
||||||
|
- name: Move cache
|
||||||
|
run: |
|
||||||
|
rm -rf /opt/hostedtoolcache/.buildx-cache
|
||||||
|
mv /opt/hostedtoolcache/.buildx-cache-new /opt/hostedtoolcache/.buildx-cache
|
||||||
|
|
||||||
- name: Rollout Django to force pulling the new image
|
- name: Rollout Django to force pulling the new image
|
||||||
uses: actions-hub/kubectl@master
|
uses: actions-hub/kubectl@master
|
||||||
@@ -160,3 +118,6 @@ jobs:
|
|||||||
--user ${{ secrets.USERNAME_GITEA }}:${{ secrets.PASSWORD_GITEA }} \
|
--user ${{ secrets.USERNAME_GITEA }}:${{ secrets.PASSWORD_GITEA }} \
|
||||||
https://gitea.tryton.geeraert.eu/api/v1/repos/pi-ux-ce/${{ github.event.repository.name }}/actions/variables/VERSION \
|
https://gitea.tryton.geeraert.eu/api/v1/repos/pi-ux-ce/${{ github.event.repository.name }}/actions/variables/VERSION \
|
||||||
-d "{\"Value\":\"$next_version\"}"
|
-d "{\"Value\":\"$next_version\"}"
|
||||||
|
|
||||||
|
- name: backup git for future use
|
||||||
|
run: cp -r ${{ gitea.workspace }} /opt/hostedtoolcache/${{ github.event.repository.name }}/
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
name: Gitea Actions Demo
|
||||||
|
run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- "testing"
|
||||||
|
paths:
|
||||||
|
- 'django_testing/dockerfile'
|
||||||
|
tags-ignore:
|
||||||
|
- '*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
Explore-Gitea-Actions:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- run: echo "🔎 The name of your branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
|
||||||
|
- name: Check out repository code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- run: echo "💡 The ${{ gitea.repository }} repository has been cloned to the runner."
|
||||||
|
- name: List files in the repository
|
||||||
|
run: |
|
||||||
|
ls ${{ gitea.workspace }}
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Compute next version
|
||||||
|
id: versioning
|
||||||
|
run: |
|
||||||
|
latest="${{ vars.VERSION_TESTING }}"
|
||||||
|
next_version=$(echo "$latest" | awk -F. -v OFS=. '{$NF += 1 ; print}')
|
||||||
|
echo "next_version=$next_version" >> $GITHUB_ENV
|
||||||
|
echo "Variables used :"
|
||||||
|
echo "------------------------------------------------"
|
||||||
|
echo "Next version: $next_version"
|
||||||
|
|
||||||
|
|
||||||
|
- name: Login to gitea
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: gitea.tryton.geeraert.eu
|
||||||
|
username: ${{ secrets.USERNAME_GITEA }}
|
||||||
|
password: ${{ secrets.PASSWORD_GITEA }}
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: django_testing/
|
||||||
|
push: true
|
||||||
|
build-args: |
|
||||||
|
ALLOWED_HOSTS='django-testing.tryton.geeraert.eu'
|
||||||
|
DEBUG='True'
|
||||||
|
tags: |
|
||||||
|
gitea.tryton.geeraert.eu/pi-ux-ce/django-testing:latest
|
||||||
|
gitea.tryton.geeraert.eu/pi-ux-ce/django-testing:${{ env.next_version }}
|
||||||
|
cache-from: type=registry,ref=gitea.tryton.geeraert.eu/pi-ux-ce/django-testing:buildcache
|
||||||
|
cache-to: type=registry,ref=gitea.tryton.geeraert.eu/pi-ux-ce/django-testing:buildcache,mode=max
|
||||||
|
|
||||||
|
- name: update version in the variable
|
||||||
|
run: |
|
||||||
|
curl -X PUT -H "Content-Type: application/json" \
|
||||||
|
--user ${{ secrets.USERNAME_GITEA }}:${{ secrets.PASSWORD_GITEA }} \
|
||||||
|
https://gitea.tryton.geeraert.eu/api/v1/repos/pi-ux-ce/${{ github.event.repository.name }}/actions/variables/VERSION_TESTING \
|
||||||
|
-d "{\"Value\":\"$next_version\"}"
|
||||||
|
|
||||||
|
- name: Rollout Django to force pulling the new image
|
||||||
|
uses: actions-hub/kubectl@master
|
||||||
|
env:
|
||||||
|
KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}
|
||||||
|
with:
|
||||||
|
args: rollout restart deployment django-testing -n django-testing
|
||||||
|
|
||||||
|
- run: echo "🍏 This job's status is ${{ job.status }}."
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
name: Gitea Actions Demo
|
||||||
|
run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- "testing"
|
||||||
|
tags-ignore:
|
||||||
|
- '*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
Explore-Gitea-Actions:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- run: echo "🔎 The name of your branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
|
||||||
|
|
||||||
|
- name: Rollout Django to force pulling the new image
|
||||||
|
uses: actions-hub/kubectl@master
|
||||||
|
env:
|
||||||
|
KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}
|
||||||
|
with:
|
||||||
|
args: rollout restart deployment django-testing -n django-testing
|
||||||
|
|
||||||
|
- run: echo "🍏 This job's status is ${{ job.status }}."
|
||||||
+226
-3
@@ -1,6 +1,229 @@
|
|||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[codz]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py.cover
|
||||||
|
*.lcov
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# .python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
# Pipfile.lock
|
||||||
|
|
||||||
|
# UV
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
# uv.lock
|
||||||
|
|
||||||
|
# poetry
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||||
|
# poetry.lock
|
||||||
|
# poetry.toml
|
||||||
|
|
||||||
|
# pdm
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||||
|
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
||||||
|
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
||||||
|
# pdm.lock
|
||||||
|
# pdm.toml
|
||||||
|
.pdm-python
|
||||||
|
.pdm-build/
|
||||||
|
|
||||||
|
# pixi
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
||||||
|
# pixi.lock
|
||||||
|
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
||||||
|
# in the .venv directory. It is recommended not to include this directory in version control.
|
||||||
|
.pixi/*
|
||||||
|
!.pixi/config.toml
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule*
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# Redis
|
||||||
|
*.rdb
|
||||||
|
*.aof
|
||||||
|
*.pid
|
||||||
|
|
||||||
|
# RabbitMQ
|
||||||
|
mnesia/
|
||||||
|
rabbitmq/
|
||||||
|
rabbitmq-data/
|
||||||
|
|
||||||
|
# ActiveMQ
|
||||||
|
activemq-data/
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.envrc
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||||
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
|
# .idea/
|
||||||
|
|
||||||
|
# Abstra
|
||||||
|
# Abstra is an AI-powered process automation framework.
|
||||||
|
# Ignore directories containing user credentials, local state, and settings.
|
||||||
|
# Learn more at https://abstra.io/docs
|
||||||
|
.abstra/
|
||||||
|
|
||||||
|
# Visual Studio Code
|
||||||
|
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
||||||
|
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
||||||
|
# you could uncomment the following to ignore the entire vscode folder
|
||||||
|
# .vscode/
|
||||||
|
# Temporary file for partial code execution
|
||||||
|
tempCodeRunnerFile.py
|
||||||
|
|
||||||
|
# Ruff stuff:
|
||||||
|
.ruff_cache/
|
||||||
|
|
||||||
|
# PyPI configuration file
|
||||||
|
.pypirc
|
||||||
|
|
||||||
|
# Marimo
|
||||||
|
marimo/_static/
|
||||||
|
marimo/_lsp/
|
||||||
|
__marimo__/
|
||||||
|
|
||||||
|
# Streamlit
|
||||||
|
.streamlit/secrets.toml
|
||||||
|
|
||||||
*/__pycache__/*
|
*/__pycache__/*
|
||||||
*/.idea
|
*/.idea/*
|
||||||
venv/*
|
*/venv/*
|
||||||
*__pycache__*
|
*/.env/*
|
||||||
Webcal-python/*
|
Webcal-python/*
|
||||||
.idea/*
|
.idea/*
|
||||||
|
django_code/db.sqlite3
|
||||||
|
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
name: django-python
|
|
||||||
---
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: django-webserver
|
|
||||||
namespace: django-python
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: django-python
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: django-python
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: django-python
|
|
||||||
image: gitea.tryton.geeraert.eu/pi-ux-ce/django-python:latest
|
|
||||||
imagePullPolicy: Always
|
|
||||||
ports:
|
|
||||||
- containerPort: 8000
|
|
||||||
name: webserver-port
|
|
||||||
volumeMounts:
|
|
||||||
## - name: django-python-code
|
|
||||||
# mountPath: /code
|
|
||||||
- name: servarr-data
|
|
||||||
mountPath: /data
|
|
||||||
readOnly: true
|
|
||||||
- name: secret-kubeconfig
|
|
||||||
mountPath: /kubeconfig
|
|
||||||
|
|
||||||
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpu: 100m
|
|
||||||
memory: 200Mi
|
|
||||||
volumes:
|
|
||||||
- name: django-python-code
|
|
||||||
persistentVolumeClaim:
|
|
||||||
claimName: django-python-code
|
|
||||||
- name: servarr-data
|
|
||||||
hostPath:
|
|
||||||
path: /data
|
|
||||||
- name: secret-kubeconfig
|
|
||||||
secret:
|
|
||||||
defaultMode: 420
|
|
||||||
secretName: kubeconfig
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: webserver
|
|
||||||
namespace: django-python
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- name: http
|
|
||||||
port: 8000
|
|
||||||
protocol: TCP
|
|
||||||
selector:
|
|
||||||
app: django-python
|
|
||||||
@@ -1,9 +1,21 @@
|
|||||||
=======
|
=======
|
||||||
# Django_kube
|
# Django_kube
|
||||||
test
|
|
||||||
|
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
### Database migration
|
||||||
|
|
||||||
|
```
|
||||||
|
python django_code/manage.py makemigrations
|
||||||
|
python django_code/manage.py makemigrations redirect
|
||||||
|
python django_code/manage.py makemigrations cloudmanager
|
||||||
|
python django_code/manage.py makemigrations simpsons
|
||||||
|
python django_code/manage.py makemigrations job
|
||||||
|
|
||||||
|
python django_code/manage.py migrate
|
||||||
|
python django_code/manage.py migrate --database=cloudmanager_db
|
||||||
|
python django_code/manage.py migrate --database=simpsons_db
|
||||||
|
python django_code/manage.py migrate --database=redirect_db
|
||||||
|
python django_code/manage.py migrate --database=job_db
|
||||||
|
```
|
||||||
|
|
||||||
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
|
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
import requests
|
||||||
|
import hashlib
|
||||||
|
from apps.bitwarden.utils import bitwardenUtils
|
||||||
|
|
||||||
|
class betaserieUtils():
|
||||||
|
url = "https://api.betaseries.com/members/auth"
|
||||||
|
|
||||||
|
username_UID="7bc7ebd2-9c95-487f-9ba2-b47301591ef0"
|
||||||
|
password_UID="262c3246-203b-44e0-854b-b47301599730"
|
||||||
|
token_UID="2cf4be0f-f26f-473f-b8f1-b473016139e4"
|
||||||
|
|
||||||
|
#Adding __ to make the variable private and can't be access outside the class,
|
||||||
|
# only by the class itself ot the subclass
|
||||||
|
|
||||||
|
__access_token = "0.7720f24b-4328-41ef-b70b-b419018270a3.nhBoRMSkfrlxqJVZ9W0W1g3lNFrmfI:35muVQz2mO3coR46bIZgcQ=="
|
||||||
|
__organization_id = "a6361589-badd-4bde-9cb4-af8901161c0d"
|
||||||
|
|
||||||
|
bw = bitwardenUtils(__access_token,__organization_id)
|
||||||
|
|
||||||
|
__betaserie_username = bw.read_value_secret(username_UID)
|
||||||
|
__betaserie_md5_password = bw.read_value_secret(password_UID)
|
||||||
|
__betaserie_apikey = bw.read_value_secret(token_UID)
|
||||||
|
|
||||||
|
payload = {
|
||||||
|
'login': __betaserie_username, # username or email
|
||||||
|
'password': __betaserie_md5_password # MD5 hashed password
|
||||||
|
}
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
'X-BetaSeries-Key': __betaserie_apikey,
|
||||||
|
}
|
||||||
|
response = requests.post(url, headers=headers, data=payload)
|
||||||
|
|
||||||
|
#now set with the correct value
|
||||||
|
__betaserie_token = response.json()['token']
|
||||||
|
|
||||||
|
#set the __betaserie_token to the doct headers now
|
||||||
|
headers.update({'X-BetaSeries-Token': __betaserie_token})
|
||||||
|
|
||||||
|
def status_code(self):
|
||||||
|
print("Status code:", self.response.status_code)
|
||||||
|
print("Response:", self.response.json())
|
||||||
|
|
||||||
|
|
||||||
|
def identify_serie(self,serie_name,verbose=False):
|
||||||
|
#
|
||||||
|
# Usage
|
||||||
|
# show_id = beta.identify_serie("The simpsons")
|
||||||
|
# show_id = beta.identify_serie("The simpsons",verbose=True)
|
||||||
|
#
|
||||||
|
url = "https://api.betaseries.com/shows/search?title="+serie_name
|
||||||
|
|
||||||
|
response = requests.request("GET", url, headers=self.headers, data=self.payload)
|
||||||
|
if verbose:
|
||||||
|
print("Url request: "+str(url))
|
||||||
|
print(response.text)
|
||||||
|
|
||||||
|
show_id = response.json()['shows'][0]['id']
|
||||||
|
|
||||||
|
return show_id
|
||||||
|
|
||||||
|
def identify_episode(self,show_id,episode_number,verbose=False):
|
||||||
|
#
|
||||||
|
# Usage
|
||||||
|
# episode_id = beta.identify_episode(show_id,"S01E01",True)
|
||||||
|
#
|
||||||
|
url = "https://api.betaseries.com/episodes/search?show_id="+str(show_id)+"&number="+str(episode_number)
|
||||||
|
|
||||||
|
response = requests.request("GET", url, headers=self.headers, data=self.payload)
|
||||||
|
|
||||||
|
episode_id = response.json()['episode']['id']
|
||||||
|
if verbose:
|
||||||
|
print("Url request: "+str(url))
|
||||||
|
print(response.text)
|
||||||
|
|
||||||
|
return episode_id
|
||||||
|
|
||||||
|
def mark_episodes_watched(self,episode_id,verbose=False):
|
||||||
|
#
|
||||||
|
# Usage
|
||||||
|
# response = beta.mark_episodes_watched(episode_id,True)
|
||||||
|
#
|
||||||
|
url = "https://api.betaseries.com/episodes/watched?id="+str(episode_id)
|
||||||
|
|
||||||
|
response = requests.request("POST", url, headers=self.headers, data=self.payload)
|
||||||
|
if verbose:
|
||||||
|
print("Url request: "+str(url))
|
||||||
|
print(response.text)
|
||||||
|
|
||||||
|
return response.status_code
|
||||||
|
|
||||||
|
def unmark_episodes_watched(self,episode_id,verbose=False):
|
||||||
|
#
|
||||||
|
# Usage
|
||||||
|
# response = beta.unmark_episodes_watched(episode_id,True)
|
||||||
|
#
|
||||||
|
url = "https://api.betaseries.com/episodes/watched?id="+str(episode_id)
|
||||||
|
|
||||||
|
response = requests.request("DELETE", url, headers=self.headers, data=self.payload)
|
||||||
|
|
||||||
|
if verbose:
|
||||||
|
print("Url request: "+str(url))
|
||||||
|
print(response.text)
|
||||||
|
|
||||||
|
return response.status_code
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
import logging
|
||||||
|
import os
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
|
from bitwarden_sdk import BitwardenClient, DeviceType, client_settings_from_dict
|
||||||
|
|
||||||
|
|
||||||
|
class bitwardenUtils():
|
||||||
|
#documentation
|
||||||
|
#https://github.com/external-secrets/bitwarden-sdk-server
|
||||||
|
state_path = "/tmp/state_file.txt"
|
||||||
|
client = BitwardenClient(
|
||||||
|
client_settings_from_dict(
|
||||||
|
{
|
||||||
|
"apiUrl": os.getenv("API_URL", "https://bitwarden.tryton.geeraert.eu/api"),
|
||||||
|
"deviceType": DeviceType.SDK,
|
||||||
|
"identityUrl": os.getenv("IDENTITY_URL", "https://bitwarden.tryton.geeraert.eu/identity"),
|
||||||
|
"userAgent": "Python",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def verbose(self):
|
||||||
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, __access_token, __organization_id):
|
||||||
|
self.__access_token = __access_token
|
||||||
|
self.__organization_id = __organization_id
|
||||||
|
self.client.auth().login_access_token(self.__access_token, self.state_path)
|
||||||
|
|
||||||
|
def create_project(self,project_name):
|
||||||
|
project = self.client.projects().create(self.__organization_id, project_name)
|
||||||
|
return project.data.id
|
||||||
|
|
||||||
|
def generate_strong_password(self):
|
||||||
|
# Note: using the generator does not require authentication with a server
|
||||||
|
return self.client.generators().generate() # using default params
|
||||||
|
|
||||||
|
def create_secret(self,project_id,secret_name,secret_value,description="description"):
|
||||||
|
secret = self.client.secrets().create(
|
||||||
|
self.__organization_id,
|
||||||
|
secret_name,
|
||||||
|
secret_value,
|
||||||
|
description,
|
||||||
|
[project_id],
|
||||||
|
)
|
||||||
|
return secret.data.id
|
||||||
|
|
||||||
|
|
||||||
|
def read_value_secret(self,secret_id):
|
||||||
|
return self.client.secrets().get_by_ids([secret_id]).data.data[0].value
|
||||||
|
|
||||||
|
def read_value_secrets(self,list_secret_id):
|
||||||
|
if not(isinstance(list_secret_id, list)):
|
||||||
|
print("this is not a list")
|
||||||
|
return 1
|
||||||
|
list_secret_value = []
|
||||||
|
for secret_value in self.client.secrets().get_by_ids(list_secret_id).data.data:
|
||||||
|
list_secret_value.append(secret_value.value)
|
||||||
|
return list_secret_value
|
||||||
|
|
||||||
|
def delete_secrets(self,list_secret_id):
|
||||||
|
if not(isinstance(list_secret_id, list)):
|
||||||
|
print("this is not a list")
|
||||||
|
return 1
|
||||||
|
try:
|
||||||
|
self.client.secrets().delete(list_secret_id)
|
||||||
|
status=0
|
||||||
|
except:
|
||||||
|
print("Cannot delete the secrets")
|
||||||
|
status=1
|
||||||
|
return status
|
||||||
|
|
||||||
|
def delete_projects(self,list_project_id):
|
||||||
|
if not(isinstance(list_project_id, list)):
|
||||||
|
print("this is not a list")
|
||||||
|
return 1
|
||||||
|
try:
|
||||||
|
self.client.projects().delete(list_project_id)
|
||||||
|
status=0
|
||||||
|
except:
|
||||||
|
print("Cannot delete the project")
|
||||||
|
status=1
|
||||||
|
return status
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
from django.contrib import admin,messages
|
||||||
|
from django.utils.translation import ngettext
|
||||||
|
from .models import Deployment_Data,Schedule_Day_Data,Schedule_Week_Data,Namespace_Data,namespace_cmm_data_object
|
||||||
|
from .utils import import_namespace
|
||||||
|
from apps.kubernetes_connection.utils import scale_up,scale_down
|
||||||
|
|
||||||
|
DB = 'cloudmanager_db'
|
||||||
|
|
||||||
|
|
||||||
|
@admin.action(description="scale up")
|
||||||
|
def scale_up_deploy(modeladmin, request, queryset):
|
||||||
|
for query in queryset.values():
|
||||||
|
scale_up(namespace_name=query['namespace'],deploy_name=query['name'],replicas=query['replicas'])
|
||||||
|
modeladmin.message_user(
|
||||||
|
request,
|
||||||
|
ngettext(
|
||||||
|
"%d server was successfully scaled up.",
|
||||||
|
"%d servers were successfully scaled up.",
|
||||||
|
queryset.values().count(),
|
||||||
|
)
|
||||||
|
% queryset.values().count(),
|
||||||
|
messages.SUCCESS,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@admin.action(description="scale down")
|
||||||
|
def scale_down_deploy(modeladmin, request, queryset):
|
||||||
|
for query in queryset.values():
|
||||||
|
scale_down(namespace_name=query['namespace'],deploy_name=query['name'])
|
||||||
|
modeladmin.message_user(
|
||||||
|
request,
|
||||||
|
ngettext(
|
||||||
|
"%d server was successfully scaled down.",
|
||||||
|
"%d servers were successfully scaled down.",
|
||||||
|
queryset.values().count(),
|
||||||
|
)
|
||||||
|
% queryset.values().count(),
|
||||||
|
messages.SUCCESS,
|
||||||
|
)
|
||||||
|
|
||||||
|
@admin.action(description="create_entry")
|
||||||
|
def create_entry(modeladmin, request, queryset):
|
||||||
|
print("simpsons_data_object.create(season=2, episode=3, url='google.com'', seen=True)")
|
||||||
|
#call function to trigger refresh of all deploy
|
||||||
|
|
||||||
|
@admin.action(description="import namespace")
|
||||||
|
def import_namespace_admin(modeladmin, request, queryset):
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# don't forgot to clear thge quyeryset before running this
|
||||||
|
#
|
||||||
|
import_namespace(namespace_cmm_data_object)
|
||||||
|
print("simpsons_data_object.create(season=2, episode=3, url='google.com'', seen=True)")
|
||||||
|
#call function to trigger refresh of all deploy
|
||||||
|
|
||||||
|
|
||||||
|
class ActiveAtHourFilter(admin.SimpleListFilter):
|
||||||
|
title = 'Active at hour'
|
||||||
|
parameter_name = 'active_at_hour'
|
||||||
|
|
||||||
|
def lookups(self, request, model_admin):
|
||||||
|
return [(str(h), f'{h:02d}:00') for h in range(24)]
|
||||||
|
|
||||||
|
def queryset(self, request, queryset):
|
||||||
|
if self.value() is not None:
|
||||||
|
hour = self.value()
|
||||||
|
return queryset.filter(**{f'schedule_day__state_at_{hour}': True})
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
|
class MultiDBModelAdmin(admin.ModelAdmin):
|
||||||
|
"""Base class that pins all admin operations to DB."""
|
||||||
|
db = DB
|
||||||
|
|
||||||
|
def get_queryset(self, request):
|
||||||
|
return super().get_queryset(request).using(self.db)
|
||||||
|
|
||||||
|
def save_model(self, request, obj, form, change):
|
||||||
|
obj.save(using=self.db)
|
||||||
|
|
||||||
|
def delete_model(self, request, obj):
|
||||||
|
obj.delete(using=self.db)
|
||||||
|
|
||||||
|
def delete_queryset(self, request, queryset):
|
||||||
|
queryset.using(self.db).delete()
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Deployment_Data)
|
||||||
|
class DeploymentDataAdmin(MultiDBModelAdmin):
|
||||||
|
list_display = ('name', 'namespace', 'schedule_week', 'schedule_day', 'replicas')
|
||||||
|
list_filter = (ActiveAtHourFilter,)
|
||||||
|
actions = [scale_up_deploy,scale_down_deploy]
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Schedule_Day_Data)
|
||||||
|
class ScheduleDayAdmin(MultiDBModelAdmin):
|
||||||
|
list_display = ['name_schedule'] + [f'state_at_{h}' for h in range(24)]
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Schedule_Week_Data)
|
||||||
|
class ScheduleWeekAdmin(MultiDBModelAdmin):
|
||||||
|
list_display = (
|
||||||
|
'name_schedule',
|
||||||
|
'state_Monday', 'state_Tuesday', 'state_Wednesday',
|
||||||
|
'state_Thursday', 'state_Friday', 'state_Saturday', 'state_Sunday',
|
||||||
|
)
|
||||||
|
|
||||||
|
@admin.register(Namespace_Data)
|
||||||
|
class NamespaceAdmin(MultiDBModelAdmin):
|
||||||
|
list_display = ('namespace',)
|
||||||
|
actions = [import_namespace_admin]
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
from django.http import HttpResponse
|
||||||
|
from django.http import HttpResponseRedirect
|
||||||
|
from django.shortcuts import render
|
||||||
|
import os
|
||||||
|
import psycopg2
|
||||||
|
from apps.cloudmanager.db_interaction import DB_generation,Check_server_supposed_XXX,Give_current_weekday,Give_current_hour
|
||||||
|
|
||||||
|
|
||||||
|
class CloudmanagerConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'apps.cloudmanager'
|
||||||
|
label = 'cloudmanager'
|
||||||
|
|
||||||
|
def coucou(request):
|
||||||
|
return HttpResponse('<h1>Hello cmm!</h1>')
|
||||||
|
|
||||||
|
def hello(request):
|
||||||
|
list_schedule = ['schedule1','schedule2']
|
||||||
|
list_servers_up = [['wiki', 'wikijs', 2], ['book', 'bookstack-db', 1]]
|
||||||
|
return render(request, 'cloudmanager/index.html', {'list_schedule':list_schedule,'list_servers_up':list_servers_up})
|
||||||
|
|
||||||
|
def redirect(request):
|
||||||
|
db_host = os.environ.get('DB_HOST')
|
||||||
|
db_port = os.environ.get('DB_PORT')
|
||||||
|
db_user = os.environ.get('DB_USERNAME')
|
||||||
|
db_password = os.environ.get('DB_PASSWORD')
|
||||||
|
db_name = os.environ.get('CUSTOM_DB_DATABASE',os.environ.get('DB_DATABASE'))
|
||||||
|
|
||||||
|
generated_db = DB_generation(db_host, db_port, db_user, db_password,db_name)
|
||||||
|
##operation:
|
||||||
|
## Server(s) supposed to be UP
|
||||||
|
|
||||||
|
list_servers_up = Check_server_supposed_XXX(generated_db, "up", Give_current_hour(),Give_current_weekday())
|
||||||
|
print(list_servers_up)
|
||||||
|
return render(request, 'cloudmanager/cmm_blank_page.html', {'list_servers_up':list_servers_up})
|
||||||
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
class sql:
|
||||||
|
url = 'localhost'
|
||||||
|
port = 5432
|
||||||
|
user = 'postgres'
|
||||||
|
password = 'example'
|
||||||
|
database = 'cloudmanager'
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
import psycopg2
|
||||||
|
from django.http import HttpResponse
|
||||||
|
from django.views.decorators.http import require_POST
|
||||||
|
from apps.kubernetes_connection import apps as kubernetes_connection
|
||||||
|
import datetime
|
||||||
|
from apps.cloudmanager import credentials
|
||||||
|
import os
|
||||||
|
|
||||||
|
def hello(request):
|
||||||
|
kubernetes_connection.echoHello();
|
||||||
|
return HttpResponse('<h1>Hello cmm !</h1>')
|
||||||
|
|
||||||
|
def DB_generation(host_in,port_in,user_in,password_in,db_in):
|
||||||
|
db = psycopg2.connect(host=host_in, port=port_in, user=user_in, password=password_in,database=db_in)
|
||||||
|
return db
|
||||||
|
|
||||||
|
@require_POST
|
||||||
|
def change_schedule(request):
|
||||||
|
# HTMX sends these via standard POST data
|
||||||
|
schedule_id = request.POST.get('schedule_id')
|
||||||
|
server_name = request.POST.get('server_name')
|
||||||
|
|
||||||
|
if not schedule_id or not server_name:
|
||||||
|
return HttpResponse("<span style='color: red;'>Missing parameters.</span>", status=400)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# --- Your Core Logic Here ---
|
||||||
|
# e.g., Server.objects.filter(name=server_name).update(schedule_id=schedule_id)
|
||||||
|
print(f"Updating {server_name} to schedule profile {schedule_id}")
|
||||||
|
|
||||||
|
# Return a success message that will instantly inject into the server's status div
|
||||||
|
return HttpResponse("<span style='color: green;'>✓ Updated successfully!</span>")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return HttpResponse(f"<span style='color: red;'>Error: {str(e)}</span>", status=500)
|
||||||
|
|
||||||
|
def Launch_sql_query(sql,db):
|
||||||
|
# prepare a cursor object using cursor() method
|
||||||
|
cursor = db.cursor()
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Execute the SQL command
|
||||||
|
cursor.execute(sql)
|
||||||
|
# Fetch all the rows in a list of lists.
|
||||||
|
results = cursor.fetchall()
|
||||||
|
result_machine = []
|
||||||
|
#result_machine_type = []
|
||||||
|
for row in results:
|
||||||
|
result_machine_type = []
|
||||||
|
namespace = row[0]
|
||||||
|
name = row[1]
|
||||||
|
replicas = row[2]
|
||||||
|
|
||||||
|
result_machine_type.append(namespace)
|
||||||
|
result_machine_type.append(name)
|
||||||
|
result_machine_type.append(replicas)
|
||||||
|
result_machine.append(result_machine_type)
|
||||||
|
return result_machine
|
||||||
|
|
||||||
|
except:
|
||||||
|
print ("Error: unable to fetch data")
|
||||||
|
|
||||||
|
|
||||||
|
#Return the day of the week as an integer, where Monday is 0 and Sunday is 6.
|
||||||
|
def Give_current_weekday():
|
||||||
|
days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday','Saturday', 'Sunday']
|
||||||
|
weekday = days[datetime.datetime.today().weekday()]
|
||||||
|
return weekday
|
||||||
|
|
||||||
|
def Give_current_hour():
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
return now.hour
|
||||||
|
|
||||||
|
|
||||||
|
def Check_server_supposed_XXX(generated_db_in,wanted_status,Wanted_hour,Wanted_day):
|
||||||
|
sql_in=""
|
||||||
|
if wanted_status == "up":
|
||||||
|
sql_in = "select machine.namespace, machine.name, machine.replicas from scenario_hour,machine ,scenario_day_of_week where state_at_" + str(Wanted_hour) + "='1' and state_" + str(Wanted_day) + "='1' and machine.hour_behaviour_id=scenario_hour.id_scenario and machine.day_behaviour_id=scenario_day_of_week.id_scenario;"
|
||||||
|
elif wanted_status == "down":
|
||||||
|
sql_in = "select machine.namespace, machine.name, machine.replicas from scenario_hour,machine ,scenario_day_of_week where not(state_at_" + str(Wanted_hour) + "='1' and state_" + str(Wanted_day) + "='1') and machine.hour_behaviour_id=scenario_hour.id_scenario and machine.day_behaviour_id=scenario_day_of_week.id_scenario;"
|
||||||
|
else:
|
||||||
|
print("error value")
|
||||||
|
print(sql_in)
|
||||||
|
return_value = Launch_sql_query(sql_in, generated_db_in)
|
||||||
|
return return_value
|
||||||
|
|
||||||
|
def Is_the_server_already_wanted_state(id_machine, wanted_state,instance_type):
|
||||||
|
#stopped/running
|
||||||
|
bool_result = ""
|
||||||
|
proxmox = function.proxmox_connection(credentials.proxmox.zeus.url_proxmox,credentials.proxmox.zeus.user,credentials.proxmox.zeus.password)
|
||||||
|
if str(function.check_state_mix(id_machine,wanted_state,proxmox,instance_type)) == str(wanted_state):
|
||||||
|
bool_result = True
|
||||||
|
else:
|
||||||
|
bool_result = False
|
||||||
|
return bool_result
|
||||||
|
|
||||||
|
def all_operations(request,wanted_state,list_machine):
|
||||||
|
for machine_target in list_machine:
|
||||||
|
print(machine_target[1])
|
||||||
|
|
||||||
|
info_to_display = ""
|
||||||
|
if wanted_state == "up":
|
||||||
|
kubernetes_connection.scale_up(request,namespace_name=machine_target[0],deploy_name=machine_target[1],replicas=machine_target[2]);
|
||||||
|
elif wanted_state == "down":
|
||||||
|
kubernetes_connection.scale_down(request,namespace_name=machine_target[0],deploy_name=machine_target[1]);
|
||||||
|
else:
|
||||||
|
print("Incorrect wanted state")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# if not(Is_the_server_already_wanted_state(machine_target[0], wanted_state,machine_target[1])):
|
||||||
|
# function.action(False,machine_target[0],operation_to_perform,machine_target[1])
|
||||||
|
# print(str(machine_target[0])+" is now "+str(wanted_state))
|
||||||
|
# elif Is_the_server_already_wanted_state(machine_target[0], wanted_state,machine_target[1]):
|
||||||
|
# info_to_display = "operation already performed for "+machine_target[2]
|
||||||
|
# print(info_to_display)
|
||||||
|
#return info_to_display
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def main(request):
|
||||||
|
|
||||||
|
#get credentials from the env
|
||||||
|
db_host = os.environ.get('DB_HOST')
|
||||||
|
db_port = os.environ.get('DB_PORT')
|
||||||
|
db_user = os.environ.get('DB_USERNAME')
|
||||||
|
db_password = os.environ.get('DB_PASSWORD')
|
||||||
|
db_name = os.environ.get('CUSTOM_DB_DATABASE',os.environ.get('DB_DATABASE'))
|
||||||
|
|
||||||
|
generated_db = DB_generation(db_host, db_port, db_user, db_password,db_name)
|
||||||
|
##operation:
|
||||||
|
## Server(s) supposed to be UP
|
||||||
|
|
||||||
|
list_servers_up = Check_server_supposed_XXX(generated_db, "up", Give_current_hour(),Give_current_weekday())
|
||||||
|
print("------------------------------------------")
|
||||||
|
print("-----------------UP-----------------------")
|
||||||
|
print("------------------------------------------")
|
||||||
|
print(list_servers_up)
|
||||||
|
print(all_operations(request,"up", list_servers_up))
|
||||||
|
|
||||||
|
|
||||||
|
## Server(s) supposed to be DOWN
|
||||||
|
list_servers_down = Check_server_supposed_XXX(generated_db, "down", Give_current_hour(),Give_current_weekday())
|
||||||
|
|
||||||
|
print("------------------------------------------")
|
||||||
|
print("----------------DOWN----------------------")
|
||||||
|
print("------------------------------------------")
|
||||||
|
print(list_servers_down)
|
||||||
|
print(all_operations(request,"down",list_servers_down))
|
||||||
|
|
||||||
|
|
||||||
|
# disconnect from server
|
||||||
|
generated_db.close()
|
||||||
|
|
||||||
|
#print(Is_the_server_already_wanted_state(112, "stopped"))
|
||||||
|
return HttpResponse('<h1>CMM executed!</h1>')
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
TO DO:
|
||||||
|
EXTRACT TYPE OF MACHINE
|
||||||
|
CREATE FUNCTION TO CHECK IF A MACHINE IS ALREADY DOWN OR NOT
|
||||||
|
ADD FIELD IN SQL WITH PROJECT AND PUT DESCRIPTION -> ATTACH MACHINE TO PROJECT
|
||||||
|
|
||||||
|
"""
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
# Generated by Django 4.2.29 on 2026-06-22 20:21
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Namespace_Data',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('namespace', models.CharField(max_length=100)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'db_table': 'namespace',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Schedule_Day_Data',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name_schedule', models.CharField(max_length=100, unique=True)),
|
||||||
|
('state_at_0', models.BooleanField()),
|
||||||
|
('state_at_1', models.BooleanField()),
|
||||||
|
('state_at_2', models.BooleanField()),
|
||||||
|
('state_at_3', models.BooleanField()),
|
||||||
|
('state_at_4', models.BooleanField()),
|
||||||
|
('state_at_5', models.BooleanField()),
|
||||||
|
('state_at_6', models.BooleanField()),
|
||||||
|
('state_at_7', models.BooleanField()),
|
||||||
|
('state_at_8', models.BooleanField()),
|
||||||
|
('state_at_9', models.BooleanField()),
|
||||||
|
('state_at_10', models.BooleanField()),
|
||||||
|
('state_at_11', models.BooleanField()),
|
||||||
|
('state_at_12', models.BooleanField()),
|
||||||
|
('state_at_13', models.BooleanField()),
|
||||||
|
('state_at_14', models.BooleanField()),
|
||||||
|
('state_at_15', models.BooleanField()),
|
||||||
|
('state_at_16', models.BooleanField()),
|
||||||
|
('state_at_17', models.BooleanField()),
|
||||||
|
('state_at_18', models.BooleanField()),
|
||||||
|
('state_at_19', models.BooleanField()),
|
||||||
|
('state_at_20', models.BooleanField()),
|
||||||
|
('state_at_21', models.BooleanField()),
|
||||||
|
('state_at_22', models.BooleanField()),
|
||||||
|
('state_at_23', models.BooleanField()),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'db_table': 'schedule_day',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Schedule_Week_Data',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name_schedule', models.CharField(max_length=100, unique=True)),
|
||||||
|
('state_Monday', models.BooleanField()),
|
||||||
|
('state_Tuesday', models.BooleanField()),
|
||||||
|
('state_Wednesday', models.BooleanField()),
|
||||||
|
('state_Thursday', models.BooleanField()),
|
||||||
|
('state_Friday', models.BooleanField()),
|
||||||
|
('state_Saturday', models.BooleanField()),
|
||||||
|
('state_Sunday', models.BooleanField()),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'db_table': 'schedule_week',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Deployment_Data',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=100)),
|
||||||
|
('namespace', models.CharField(max_length=100)),
|
||||||
|
('replicas', models.IntegerField()),
|
||||||
|
('schedule_day', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='cloudmanager.schedule_day_data')),
|
||||||
|
('schedule_week', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='cloudmanager.schedule_week_data')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'db_table': 'machine',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Schedule_Week_Data(models.Model):
|
||||||
|
name_schedule = models.CharField(max_length=100,unique=True)
|
||||||
|
state_Monday = models.BooleanField()
|
||||||
|
state_Tuesday = models.BooleanField()
|
||||||
|
state_Wednesday = models.BooleanField()
|
||||||
|
state_Thursday = models.BooleanField()
|
||||||
|
state_Friday = models.BooleanField()
|
||||||
|
state_Saturday = models.BooleanField()
|
||||||
|
state_Sunday = models.BooleanField()
|
||||||
|
class Meta:
|
||||||
|
db_table = 'schedule_week'
|
||||||
|
def __str__(self):
|
||||||
|
return self.name_schedule
|
||||||
|
|
||||||
|
class Schedule_Day_Data(models.Model):
|
||||||
|
name_schedule = models.CharField(max_length=100,unique=True)
|
||||||
|
state_at_0 = models.BooleanField()
|
||||||
|
state_at_1 = models.BooleanField()
|
||||||
|
state_at_2 = models.BooleanField()
|
||||||
|
state_at_3 = models.BooleanField()
|
||||||
|
state_at_4 = models.BooleanField()
|
||||||
|
state_at_5 = models.BooleanField()
|
||||||
|
state_at_6 = models.BooleanField()
|
||||||
|
state_at_7 = models.BooleanField()
|
||||||
|
state_at_8 = models.BooleanField()
|
||||||
|
state_at_9 = models.BooleanField()
|
||||||
|
state_at_10 = models.BooleanField()
|
||||||
|
state_at_11 = models.BooleanField()
|
||||||
|
state_at_12 = models.BooleanField()
|
||||||
|
state_at_13 = models.BooleanField()
|
||||||
|
state_at_14 = models.BooleanField()
|
||||||
|
state_at_15 = models.BooleanField()
|
||||||
|
state_at_16 = models.BooleanField()
|
||||||
|
state_at_17 = models.BooleanField()
|
||||||
|
state_at_18 = models.BooleanField()
|
||||||
|
state_at_19 = models.BooleanField()
|
||||||
|
state_at_20 = models.BooleanField()
|
||||||
|
state_at_21 = models.BooleanField()
|
||||||
|
state_at_22 = models.BooleanField()
|
||||||
|
state_at_23 = models.BooleanField()
|
||||||
|
class Meta:
|
||||||
|
db_table = 'schedule_day'
|
||||||
|
def __str__(self):
|
||||||
|
return self.name_schedule
|
||||||
|
|
||||||
|
class Deployment_Data(models.Model):
|
||||||
|
name = models.CharField(max_length=100)
|
||||||
|
namespace = models.CharField(max_length=100)
|
||||||
|
schedule_week = models.ForeignKey(Schedule_Week_Data,null=True, blank=True, on_delete=models.SET_NULL)
|
||||||
|
schedule_day = models.ForeignKey(Schedule_Day_Data,null=True, blank=True, on_delete=models.SET_NULL)
|
||||||
|
replicas = models.IntegerField()
|
||||||
|
class Meta:
|
||||||
|
db_table = 'machine'
|
||||||
|
|
||||||
|
class Namespace_Data(models.Model):
|
||||||
|
namespace = models.CharField(max_length=100)
|
||||||
|
#deployments = models.ForeignKey(Schedule_Week_Data,null=True, blank=True, on_delete=models.SET_NULL)
|
||||||
|
class Meta:
|
||||||
|
db_table = 'namespace'
|
||||||
|
|
||||||
|
namespace_cmm_data_object = Namespace_Data.objects.using('cloudmanager_db')
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
from apps.kubernetes_connection.utils import get_namespace
|
||||||
|
|
||||||
|
|
||||||
|
def import_namespace(queryset):
|
||||||
|
namespaces_list = get_namespace()
|
||||||
|
for namespace in namespaces_list:
|
||||||
|
queryset.create(namespace=namespace)
|
||||||
|
|
||||||
|
def import_deployment(queryset):
|
||||||
|
namespaces_list = get_namespace()
|
||||||
|
#for namespace in namespaces_list:
|
||||||
|
# queryset.create(namespace=namespace)
|
||||||
|
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
from django.http import HttpResponse
|
||||||
|
|
||||||
|
# IMPORT AT THE TOP HERE: This is completely safe!
|
||||||
|
from apps.cloudmanager.models import Deployment_Data,Schedule_Week_Data
|
||||||
|
|
||||||
|
def coucou(request):
|
||||||
|
# 1. Prepare the data inside the function
|
||||||
|
data = CmmData(
|
||||||
|
name="test",
|
||||||
|
namespace="testspace",
|
||||||
|
schedule_hour="1",
|
||||||
|
schedule_day="deux",
|
||||||
|
replicas=3
|
||||||
|
)
|
||||||
|
|
||||||
|
# 2. This line actually pushes the data into your cloudmanager_db!
|
||||||
|
data.save()
|
||||||
|
|
||||||
|
return HttpResponse('<h1>Hello cmm! Data saved successfully!</h1>')
|
||||||
|
|
||||||
|
def display(request):
|
||||||
|
data = CmmData.objects.all()
|
||||||
|
print(data[0].namespace)
|
||||||
|
return HttpResponse(data)
|
||||||
|
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
|
||||||
|
def home(request):
|
||||||
|
thislist = ["apple", "banana", "cherry"]
|
||||||
|
return render(request, 'dashboard/home.html',{'thislist': thislist})
|
||||||
|
|
||||||
|
def about(request):
|
||||||
|
thislist = ["apple", "banana", "cherry"]
|
||||||
|
return render(request, 'dashboard/about.html',{'thislist': thislist})
|
||||||
|
|
||||||
|
def success(request):
|
||||||
|
return render(request, 'dashboard/start.html',{'deployment': 'django','url':'https://google.com'})
|
||||||
|
|
||||||
|
def scale_up(request,namespace_name,deploy_name):
|
||||||
|
baseurl = "{0}://{1}{2}".format(request.scheme, request.get_host(), request.path)
|
||||||
|
return render(request, 'dashboard/start.html', {'namespace':namespace_name,'deployment': deploy_name, 'url': 'https://namespace.com','baseurl': baseurl})
|
||||||
|
|
||||||
|
def scale_down(request,namespace_name,deploy_name):
|
||||||
|
baseurl = "{0}://{1}{2}".format(request.scheme, request.get_host(), request.path)
|
||||||
|
return render(request, 'dashboard/shutdown.html', {'namespace':namespace_name,'deployment': deploy_name, 'url': 'https://namespace.com','baseurl': baseurl})
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
from import_export.admin import ImportExportModelAdmin
|
||||||
|
from import_export import resources
|
||||||
|
from import_export.fields import Field
|
||||||
|
from .models import JobData
|
||||||
|
from django.utils.text import Truncator
|
||||||
|
|
||||||
|
# Register your models here.
|
||||||
|
|
||||||
|
|
||||||
|
class JobResource(resources.ModelResource):
|
||||||
|
# Map 'csv_column_name' from the file to 'model_variable_name' in your DB
|
||||||
|
job_position = Field(attribute='job_position',column_name='Job Position')
|
||||||
|
company = Field(attribute='company',column_name='Company')
|
||||||
|
URL = Field(attribute='URL',column_name='URL')
|
||||||
|
status = Field(attribute='status',column_name='Status')
|
||||||
|
date_saved = Field(attribute='date_saved',column_name='Date Saved')
|
||||||
|
date_applied = Field(attribute='date_applied',column_name='Date Applied')
|
||||||
|
type = Field(attribute='type',column_name='Type')
|
||||||
|
resume = Field(attribute='resume',column_name='Resume')
|
||||||
|
#cover_letter = Field(attribute='cover_letter',column_name='Cover Letter')
|
||||||
|
location = Field(attribute='location',column_name='Location')
|
||||||
|
job_description = Field(attribute='job_description',column_name='Job Description')
|
||||||
|
salary = Field(attribute='salary',column_name='Salary')
|
||||||
|
contact = Field(attribute='contact',column_name='Contact')
|
||||||
|
source = Field(attribute='source',column_name='Source')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = JobData
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(JobData)
|
||||||
|
class JobAdmin(ImportExportModelAdmin):
|
||||||
|
list_display = ('job_position','company','URL','status','date_saved','date_applied','type','resume','location','short_description','salary','contact','source')
|
||||||
|
#fields = ['job_position','company','URL','status','date_saved','date_applied','type','resume','cover_letter','location','job_description','salary ','contact','source']
|
||||||
|
resource_classes = [JobResource]
|
||||||
|
def short_description(self, obj):
|
||||||
|
return Truncator(obj.job_description).words(10, truncate=' ...')
|
||||||
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
class JobDashboardConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'apps.job_dashboard'
|
||||||
|
label = 'job'
|
||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,36 @@
|
|||||||
|
# Generated by Django 4.2.29 on 2026-06-22 20:21
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='JobData',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('job_position', models.CharField(max_length=100, null=True)),
|
||||||
|
('company', models.CharField(max_length=100, null=True)),
|
||||||
|
('URL', models.URLField(max_length=1000, null=True)),
|
||||||
|
('status', models.CharField(choices=[('Rejected', 'Rejected'), ('Applied', 'Applied'), ('Negotiating', 'Negotiating'), ('Bookmarked', 'Bookmarked'), ('Accepted', 'Accepted')], max_length=100, null=True)),
|
||||||
|
('date_saved', models.CharField(max_length=100, null=True)),
|
||||||
|
('date_applied', models.CharField(max_length=100, null=True)),
|
||||||
|
('type', models.CharField(max_length=100, null=True)),
|
||||||
|
('resume', models.URLField(null=True)),
|
||||||
|
('location', models.CharField(max_length=100, null=True)),
|
||||||
|
('job_description', models.CharField(null=True)),
|
||||||
|
('salary', models.CharField(null=True)),
|
||||||
|
('contact', models.CharField(max_length=100, null=True)),
|
||||||
|
('source', models.CharField(max_length=100, null=True)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'db_table': 'job',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
status_CHOICES = (
|
||||||
|
('Rejected','Rejected'),
|
||||||
|
('Applied','Applied'),
|
||||||
|
('Negotiating','Negotiating'),
|
||||||
|
('Bookmarked','Bookmarked'),
|
||||||
|
('Accepted','Accepted')
|
||||||
|
)
|
||||||
|
|
||||||
|
class JobData(models.Model):
|
||||||
|
job_position = models.CharField(max_length=100, null=True)
|
||||||
|
company = models.CharField(max_length=100, null=True)
|
||||||
|
URL = models.URLField(max_length=1000,null=True)
|
||||||
|
status = models.CharField(max_length=100,choices=status_CHOICES, null=True)
|
||||||
|
date_saved = models.CharField(max_length=100, null=True)
|
||||||
|
date_applied = models.CharField(max_length=100, null=True)
|
||||||
|
type = models.CharField(max_length=100, null=True)
|
||||||
|
resume = models.URLField(max_length=200, null=True)
|
||||||
|
#cover_letter = models.URLField(max_length=200, null=True)
|
||||||
|
location = models.CharField(max_length=100, null=True)
|
||||||
|
job_description = models.CharField(null=True)
|
||||||
|
salary = models.CharField(null=True)
|
||||||
|
contact = models.CharField(max_length=100, null=True)
|
||||||
|
source = models.CharField(max_length=100, null=True)
|
||||||
|
class Meta:
|
||||||
|
db_table = 'job'
|
||||||
|
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
"""
|
||||||
|
URL configuration for django_code project.
|
||||||
|
|
||||||
|
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||||
|
https://docs.djangoproject.com/en/4.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
|
||||||
|
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('', admin.site.urls),
|
||||||
|
]
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
# Create your views here.
|
||||||
+9
-4
@@ -14,18 +14,23 @@ import ruamel.yaml
|
|||||||
import yaml
|
import yaml
|
||||||
import urllib.request
|
import urllib.request
|
||||||
|
|
||||||
|
|
||||||
def hello(request):
|
def hello(request):
|
||||||
return HttpResponse('<h1>Hello k8s!</h1>')
|
return HttpResponse('<h1>Hello k8s!</h1>')
|
||||||
|
|
||||||
def scale_up(request,namespace_name,deploy_name):
|
def echoHello():
|
||||||
|
print("hello from k8s")
|
||||||
|
return "returned from k8s"
|
||||||
|
|
||||||
|
def scale_up(request,namespace_name,deploy_name,replicas=1):
|
||||||
config.load_kube_config(config_file='/kubeconfig/config')
|
config.load_kube_config(config_file='/kubeconfig/config')
|
||||||
api = client.AppsV1Api()
|
api = client.AppsV1Api()
|
||||||
deployment = api.read_namespaced_deployment(name=deploy_name, namespace=namespace_name)
|
deployment = api.read_namespaced_deployment(name=deploy_name, namespace=namespace_name)
|
||||||
deployment.spec.replicas = 1
|
deployment.spec.replicas = replicas
|
||||||
resp = api.patch_namespaced_deployment(
|
resp = api.patch_namespaced_deployment(
|
||||||
name=deploy_name, namespace=namespace_name, body=deployment);
|
name=deploy_name, namespace=namespace_name, body=deployment);
|
||||||
#return HttpResponse('<h1>Scaled up !</h1>')
|
#return HttpResponse('<h1>Scaled up !</h1>')
|
||||||
return render(request, 'start.html', {'namespace':namespace_name,'deployment': deploy_name, 'url': 'https://namespace.com'})
|
return render(request, 'dashboard/start.html', {'namespace':namespace_name,'deployment': deploy_name, 'url': 'https://namespace.com'})
|
||||||
|
|
||||||
|
|
||||||
def scale_down(request,namespace_name,deploy_name):
|
def scale_down(request,namespace_name,deploy_name):
|
||||||
@@ -36,7 +41,7 @@ def scale_down(request,namespace_name,deploy_name):
|
|||||||
resp = api.patch_namespaced_deployment(
|
resp = api.patch_namespaced_deployment(
|
||||||
name=deploy_name, namespace=namespace_name, body=deployment);
|
name=deploy_name, namespace=namespace_name, body=deployment);
|
||||||
#return HttpResponse('<h1>Scaled down !</h1>')
|
#return HttpResponse('<h1>Scaled down !</h1>')
|
||||||
return render(request, 'shutdown.html',
|
return render(request, 'dashboard/shutdown.html',
|
||||||
{'namespace': namespace_name, 'deployment': deploy_name, 'url': 'https://namespace.com'})
|
{'namespace': namespace_name, 'deployment': deploy_name, 'url': 'https://namespace.com'})
|
||||||
|
|
||||||
def nodes(request):
|
def nodes(request):
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
from kubernetes import client, config
|
||||||
|
|
||||||
|
|
||||||
|
def scale_up(namespace_name,deploy_name,replicas=1):
|
||||||
|
config.load_kube_config(config_file='/kubeconfig/config')
|
||||||
|
|
||||||
|
api = client.AppsV1Api()
|
||||||
|
deployment = api.read_namespaced_deployment(name=deploy_name, namespace=namespace_name)
|
||||||
|
deployment.spec.replicas = replicas
|
||||||
|
resp = api.patch_namespaced_deployment(
|
||||||
|
name=deploy_name, namespace=namespace_name, body=deployment);
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def scale_down(namespace_name,deploy_name):
|
||||||
|
config.load_kube_config(config_file='/kubeconfig/config')
|
||||||
|
api = client.AppsV1Api()
|
||||||
|
deployment = api.read_namespaced_deployment(name=deploy_name, namespace=namespace_name)
|
||||||
|
deployment.spec.replicas = 0
|
||||||
|
resp = api.patch_namespaced_deployment(
|
||||||
|
name=deploy_name, namespace=namespace_name, body=deployment);
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def import_Deployments():
|
||||||
|
config.load_kube_config(config_file='/kubeconfig/config')
|
||||||
|
api = client.AppsV1Api()
|
||||||
|
deployment = api.list_deployment_for_all_namespaces()
|
||||||
|
for i in range(1,len(deployment.items)):
|
||||||
|
print(deployment.items[i].spec.template.spec.containers[0].name)
|
||||||
|
|
||||||
|
len(deployment.items) #list all deployment inside the namespace
|
||||||
|
test.items[0].spec.template.spec.containers[0].name # name the first deploy within the namespace
|
||||||
|
test.items[2].spec.template.spec.containers[0].name # name the third deploy within the namespace
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def get_namespace():
|
||||||
|
config.load_kube_config(config_file='/kubeconfig/config')
|
||||||
|
core = client.CoreV1Api()
|
||||||
|
namespace = core.list_namespace()
|
||||||
|
namespace_list = []
|
||||||
|
for i in range(0,len(namespace.items)):
|
||||||
|
print(namespace.items[i].metadata.name)
|
||||||
|
namespace_list.append(namespace.items[i].metadata.name)
|
||||||
|
return namespace_list
|
||||||
|
|
||||||
|
def get_deployments():
|
||||||
|
config.load_kube_config(config_file='/kubeconfig/config')
|
||||||
|
api = client.AppsV1Api()
|
||||||
|
namespaces_list = get_namespace()
|
||||||
|
deployments_list = []
|
||||||
|
for namespace in namespaces_list:
|
||||||
|
print(namespace)
|
||||||
|
deployments = api.list_namespaced_deployment(namespace)
|
||||||
|
for deployment_index in range(0,len(deployments.items)):
|
||||||
|
deployment = deployments.items[deployment_index].metadata.name
|
||||||
|
print(" "+str(deployment))
|
||||||
|
deployments_list.append([namespace,deployment])
|
||||||
|
return deployments_list
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
from django.contrib import admin,messages
|
||||||
|
from django.utils.translation import ngettext
|
||||||
|
from .models import SimpsonsData,simpsons_data_object
|
||||||
|
from import_export import resources
|
||||||
|
from import_export.admin import ImportExportModelAdmin
|
||||||
|
# Register your models here.
|
||||||
|
|
||||||
|
DB = 'simpsons_db'
|
||||||
|
|
||||||
|
@admin.action(description="Mark episode as seen")
|
||||||
|
def make_seen(modeladmin, request, queryset):
|
||||||
|
updated = queryset.update(seen="True")
|
||||||
|
modeladmin.message_user(
|
||||||
|
request,
|
||||||
|
ngettext(
|
||||||
|
"%d episode was successfully marked as seen.",
|
||||||
|
"%d episodes were successfully marked as seen.",
|
||||||
|
updated,
|
||||||
|
)
|
||||||
|
% updated,
|
||||||
|
messages.SUCCESS,
|
||||||
|
)
|
||||||
|
|
||||||
|
@admin.action(description="Mark episode as not seen")
|
||||||
|
def make_unseen(modeladmin, request, queryset):
|
||||||
|
updated = queryset.update(seen="False")
|
||||||
|
modeladmin.message_user(
|
||||||
|
request,
|
||||||
|
ngettext(
|
||||||
|
"%d episode was successfully marked as not seen.",
|
||||||
|
"%d episodes were successfully marked as not seen.",
|
||||||
|
updated,
|
||||||
|
)
|
||||||
|
% updated,
|
||||||
|
messages.SUCCESS,
|
||||||
|
)
|
||||||
|
|
||||||
|
@admin.action(description="create_entry")
|
||||||
|
def create_entry(modeladmin, request, queryset):
|
||||||
|
simpsons_data_object.create(season=2, episode=3, url="google.com", seen=True)
|
||||||
|
|
||||||
|
@admin.register(SimpsonsData)
|
||||||
|
class EpisodeAdmin(ImportExportModelAdmin):
|
||||||
|
list_display = [field.name for field in SimpsonsData._meta.fields if field.name != 'id']
|
||||||
|
list_filter = ['seen']
|
||||||
|
fields = ['season', 'episode', 'url', 'seen']
|
||||||
|
actions = [make_seen,make_unseen,create_entry]
|
||||||
|
|
||||||
|
def get_queryset(self, request):
|
||||||
|
return super().get_queryset(request).using(DB)
|
||||||
|
|
||||||
|
def save_model(self, request, obj, form, change):
|
||||||
|
obj.save(using=DB)
|
||||||
|
|
||||||
|
def delete_model(self, request, obj):
|
||||||
|
obj.delete(using=DB)
|
||||||
|
|
||||||
|
def delete_queryset(self, request, queryset):
|
||||||
|
queryset.using(DB).delete()
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
class RandomSimpsonsConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'apps.random_simpsons'
|
||||||
|
label = 'simpsons'
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# Generated by Django 4.2.29 on 2026-06-22 20:21
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='SimpsonsData',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('season', models.IntegerField()),
|
||||||
|
('episode', models.IntegerField()),
|
||||||
|
('url', models.CharField(max_length=1000)),
|
||||||
|
('seen', models.BooleanField()),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'db_table': 'episodes',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
class SimpsonsData(models.Model):
|
||||||
|
season = models.IntegerField()
|
||||||
|
episode = models.IntegerField()
|
||||||
|
url = models.CharField(max_length=1000)
|
||||||
|
seen = models.BooleanField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
db_table = 'episodes'
|
||||||
|
|
||||||
|
simpsons_data_object = SimpsonsData.objects.using('simpsons_db')
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
from django.http import HttpResponse
|
||||||
|
from django.db.models import Count
|
||||||
|
from django.shortcuts import redirect
|
||||||
|
from apps.random_simpsons.models import SimpsonsData,simpsons_data_object
|
||||||
|
import random
|
||||||
|
|
||||||
|
|
||||||
|
def hello(request):
|
||||||
|
return HttpResponse('<h1>Hello Simpsons view!</h1>')
|
||||||
|
|
||||||
|
def episode_generator(request):
|
||||||
|
#simpsons_data_object = SimpsonsData.objects.using('simpsons_db')
|
||||||
|
|
||||||
|
boolean_restart = True;
|
||||||
|
while (boolean_restart):
|
||||||
|
maximum_number_of_seasons = simpsons_data_object.aggregate(unique_season=Count('season', distinct=True))['unique_season']
|
||||||
|
|
||||||
|
random_seasons = random.randint(1, maximum_number_of_seasons)
|
||||||
|
print("random season: " + str(random_seasons))
|
||||||
|
|
||||||
|
maximum_number_of_episodes = simpsons_data_object.filter(season=random_seasons).count()
|
||||||
|
|
||||||
|
random_episode = random.randint(1, maximum_number_of_episodes)
|
||||||
|
print("random episode: " + str(random_episode))
|
||||||
|
|
||||||
|
episode_seen = simpsons_data_object.filter(season=random_seasons, episode=random_episode).values('seen')[0]['seen']
|
||||||
|
|
||||||
|
if not(episode_seen):
|
||||||
|
boolean_restart = False
|
||||||
|
else:
|
||||||
|
print("episode "+str(random_episode)+" from season "+str(random_seasons)+" already seen")
|
||||||
|
|
||||||
|
random_url = simpsons_data_object.filter(season=random_seasons, episode=random_episode).values('url')[0]['url']
|
||||||
|
|
||||||
|
#Set episode as seen
|
||||||
|
# It will still update an already seem episode but it works and I'm lazy
|
||||||
|
|
||||||
|
simpsons_data_object.filter(season=random_seasons, episode=random_episode).values('seen').update(seen=True)
|
||||||
|
|
||||||
|
return redirect(str(random_url))
|
||||||
|
|
||||||
|
def download_file(request):
|
||||||
|
# fill these variables with real values
|
||||||
|
fl_path = '/data/download/sonarr'
|
||||||
|
filename = 'The.Boys.2019.S04E05.2160p.HDR10Plus.WEBRip.6CH.x265.HEVC-PSA.mkv'
|
||||||
|
|
||||||
|
# fl = open(fl_path, 'r')
|
||||||
|
# mime_type, _ = mimetypes.guess_type(fl_path)
|
||||||
|
|
||||||
|
# response = HttpResponse(fl, content_type=mime_type)
|
||||||
|
# response['Content-Disposition'] = "attachment; filename=%s" % filename
|
||||||
|
some_file = open('/data/kubernetes/Backup/nextcloud/notes/2024-07-28/Course.md', "r")
|
||||||
|
django_file = File(some_file)
|
||||||
|
return HttpResponse("<h1>Hello download!</h1><h1><a href='{{ MEDIA_URL }}{{ django_file.relative_path }}'>{{ django_file.name }}</a></h1><h1>bye download!</h1>")
|
||||||
|
# return response
|
||||||
|
|
||||||
|
def download_mo(request,file):
|
||||||
|
path_to_file = os.path.realpath(file)
|
||||||
|
response = FileResponse(open(path_to_file, 'rb'))
|
||||||
|
file_name = file[5:]
|
||||||
|
response['Content-Disposition'] = 'inline; filename=' + file_name
|
||||||
|
return response
|
||||||
@@ -2,7 +2,6 @@ from django.apps import AppConfig
|
|||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
#from jinja2 import Environment, FileSystemLoader
|
|
||||||
from django.core.files import File
|
from django.core.files import File
|
||||||
from kubernetes import client, config
|
from kubernetes import client, config
|
||||||
from celery import shared_task
|
from celery import shared_task
|
||||||
@@ -10,6 +9,7 @@ from celery import shared_task
|
|||||||
from lxml import html
|
from lxml import html
|
||||||
import requests
|
import requests
|
||||||
import os
|
import os
|
||||||
|
import json
|
||||||
import time
|
import time
|
||||||
import random
|
import random
|
||||||
import mimetypes
|
import mimetypes
|
||||||
@@ -33,15 +33,16 @@ proxies = {
|
|||||||
"https" : proxy_url
|
"https" : proxy_url
|
||||||
}
|
}
|
||||||
|
|
||||||
destination_folder = "/tmp/stash/"
|
destination_folder = "/stash/"
|
||||||
|
|
||||||
def hello(request):
|
def hello(request):
|
||||||
return HttpResponse('<h1>Hello stash!</h1>')
|
return HttpResponse('<h1>Hello stash!</h1>')
|
||||||
def form(request):
|
def form(request):
|
||||||
return render(request, 'stash_form.html',{})
|
return render(request, 'stash/stash_form.html',{})
|
||||||
def album(request):
|
def album(request):
|
||||||
return render(request, 'album_form.html',{})
|
return render(request, 'stash/album_form.html',{})
|
||||||
|
def simple(request):
|
||||||
|
return render(request, 'stash/simple_form.html',{})
|
||||||
def check_and_create_destination_folder(name):
|
def check_and_create_destination_folder(name):
|
||||||
#check if the output directory exist and create if not
|
#check if the output directory exist and create if not
|
||||||
if not os.path.isdir(destination_folder):
|
if not os.path.isdir(destination_folder):
|
||||||
@@ -116,12 +117,69 @@ def images_downloader(name,images_url_list,destination_named_folder):
|
|||||||
opener = urlrequest.build_opener(proxy)
|
opener = urlrequest.build_opener(proxy)
|
||||||
|
|
||||||
urlrequest.install_opener(opener)
|
urlrequest.install_opener(opener)
|
||||||
|
try:
|
||||||
urlrequest.urlretrieve(image_url, filename )
|
urlrequest.urlretrieve(image_url, filename )
|
||||||
|
except:
|
||||||
|
print("Can't download "+filename+" -- "+image_url)
|
||||||
|
individual_image_downloader.delay(image_url=image_url, filename=filename)
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
@shared_task()
|
||||||
|
def individual_image_downloader(image_url, filename ):
|
||||||
|
print("Downloading again: "+filename+" -- "+image_url)
|
||||||
|
|
||||||
|
opener = urlrequest.build_opener(proxy)
|
||||||
|
|
||||||
|
urlrequest.install_opener(opener)
|
||||||
|
try:
|
||||||
|
urlrequest.urlretrieve(image_url, filename )
|
||||||
|
except:
|
||||||
|
print("Still Can't download "+filename+" -- "+image_url+" == Cancelling")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def simple_form(request):
|
||||||
|
name = request.GET.get('name')
|
||||||
|
reddit_downloader(username=name)
|
||||||
|
|
||||||
|
text_generated = "successfully sent to the reddit downloader"
|
||||||
|
return HttpResponse(text_generated, content_type="text/plain")
|
||||||
|
|
||||||
|
def reddit_downloader(username):
|
||||||
|
|
||||||
|
#create the prerequisites folder
|
||||||
|
destination_named_folder = check_and_create_destination_folder(name=username)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
url = "https://www.reddit.com/user/"+username+"/submitted/.json?limit=1000"
|
||||||
|
opener = urlrequest.build_opener(proxy)
|
||||||
|
urlrequest.install_opener(opener)
|
||||||
|
|
||||||
|
req = urlrequest.Request(url)
|
||||||
|
urlcurl = urlrequest.urlopen(req).read()
|
||||||
|
data = json.loads(urlcurl)
|
||||||
|
|
||||||
|
picture_list=[]
|
||||||
|
for children in data['data']['children']:
|
||||||
|
print("adding to the list : "+children['data']['url'])
|
||||||
|
picture_list.append(children['data']['url'])
|
||||||
|
|
||||||
|
images_downloader.delay(name=username,images_url_list=picture_list,destination_named_folder=destination_named_folder)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def redgif_donloader(username):
|
||||||
|
#on te front page of the user , https://www.redgifs.com/users/princesspizookie
|
||||||
|
# F12 and search network , find something that start as api.redgifs.com
|
||||||
|
# and the file is search?order=new&count=40&type=g
|
||||||
|
# copy as curl and you got the bearer
|
||||||
|
|
||||||
|
#curl curl 'https://api.redgifs.com/v2/users/princesspizookie/search?order=new&count=40&type=g'
|
||||||
|
#and you get the URLS , needs to be parsedw
|
||||||
|
return 0
|
||||||
def incremental(request):
|
def incremental(request):
|
||||||
return render(request, 'incremental_form.html',{})
|
return render(request, 'stash/incremental_form.html',{})
|
||||||
|
|
||||||
def incremental_form(request):
|
def incremental_form(request):
|
||||||
name = request.GET.get('name')
|
name = request.GET.get('name')
|
||||||
@@ -165,9 +223,10 @@ def increment_and_download(minimum_increment,maximum_increment,url,url_suffix,na
|
|||||||
increment_generated ='000' + str(increment)
|
increment_generated ='000' + str(increment)
|
||||||
|
|
||||||
url_generated = url+increment_generated+url_suffix
|
url_generated = url+increment_generated+url_suffix
|
||||||
|
print(url_generated)
|
||||||
destination_filename = increment_generated+url_suffix
|
destination_filename = increment_generated+url_suffix
|
||||||
destination_file = os.path.join(destination_named_folder,destination_filename)
|
destination_file = os.path.join(destination_named_folder,destination_filename)
|
||||||
|
print(destination_file)
|
||||||
opener = urlrequest.build_opener(proxy)
|
opener = urlrequest.build_opener(proxy)
|
||||||
urlrequest.install_opener(opener)
|
urlrequest.install_opener(opener)
|
||||||
urlrequest.urlretrieve(url_generated, destination_file )
|
urlrequest.urlretrieve(url_generated, destination_file )
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
||||||
@@ -9,4 +9,4 @@ def hello(request):
|
|||||||
|
|
||||||
|
|
||||||
def home(request):
|
def home(request):
|
||||||
return render(request, 'listing.html')
|
return render(request, 'stash/listing.html')
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
from .models import redirectData
|
||||||
|
from import_export.admin import ImportExportModelAdmin
|
||||||
|
|
||||||
|
# Register your models here.
|
||||||
|
@admin.register(redirectData)
|
||||||
|
class redirectAdmin(ImportExportModelAdmin):
|
||||||
|
list_display = [field.name for field in redirectData._meta.fields if field.name != 'id']
|
||||||
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import redis
|
||||||
|
from django.http import HttpResponse
|
||||||
|
from django.http import HttpResponseRedirect
|
||||||
|
from django.shortcuts import render
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class redirectConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'apps.website_redirection'
|
||||||
|
label = 'redirect'
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# Generated by Django 4.2.29 on 2026-06-22 20:21
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='redirectData',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('url', models.CharField(max_length=1000)),
|
||||||
|
('addedDate', models.DateField(blank=True, null=True, verbose_name='Published')),
|
||||||
|
('seenDate', models.DateField(blank=True, null=True, verbose_name='Published')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'db_table': 'redirect',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
class redirectData(models.Model):
|
||||||
|
url = models.CharField(max_length=1000)
|
||||||
|
addedDate = models.DateField('Published', blank=True, null=True)
|
||||||
|
seenDate = models.DateField('Published', blank=True, null=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
db_table = 'redirect'
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
"""
|
||||||
|
URL configuration for django_code project.
|
||||||
|
|
||||||
|
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||||
|
https://docs.djangoproject.com/en/4.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
|
||||||
|
from apps.website_redirection import views as website_redirectionapp
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
# path('admin/', admin.site.urls),
|
||||||
|
|
||||||
|
################### Redirect ###################
|
||||||
|
path('', website_redirectionapp.redirect),
|
||||||
|
path('hello/', website_redirectionapp.hello),
|
||||||
|
path('set/', website_redirectionapp.redirect),
|
||||||
|
path('get/<str:key>', website_redirectionapp.display_key),
|
||||||
|
path('go/<str:key>', website_redirectionapp.redirect_to_key),
|
||||||
|
path('redirect-form/', website_redirectionapp.redirect_process, name='submit_form'),
|
||||||
|
path('clearkey/', website_redirectionapp.clearkey_process, name='submit_form'),
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
]
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
# Create your views here.
|
||||||
|
from django.http import HttpResponse
|
||||||
|
from django.shortcuts import render
|
||||||
|
from .models import redirectData
|
||||||
|
import redis
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
def hello(request):
|
||||||
|
return HttpResponse('<h1>Hello Django!</h1>')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
r = redis.Redis(
|
||||||
|
host='django-redis-svc',
|
||||||
|
port=6379,
|
||||||
|
db=0 # The default Redis database index
|
||||||
|
)
|
||||||
|
|
||||||
|
def hello(request):
|
||||||
|
return HttpResponse('<h1>Hello redirect!</h1>')
|
||||||
|
|
||||||
|
|
||||||
|
def redirect(request):
|
||||||
|
return render(request, 'website_redirection/redirect_form.html',{})
|
||||||
|
|
||||||
|
def clearkey_process(request):
|
||||||
|
key = request.GET.get('key')
|
||||||
|
r.delete(key)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def redirect_process(request):
|
||||||
|
key = request.GET.get('key')
|
||||||
|
value = request.GET.get('value')
|
||||||
|
key = key.lower()
|
||||||
|
|
||||||
|
r.set(key, value)
|
||||||
|
redirectData.create(url=key,addedDate=datetime.datetime.now(),seenDate="")
|
||||||
|
text_generated = "successfully set "+value+" to "+key
|
||||||
|
return HttpResponse(text_generated, content_type="text/plain")
|
||||||
|
|
||||||
|
def display_key(request,key):
|
||||||
|
value = r.get(key)
|
||||||
|
value_extracted = str(value.decode())
|
||||||
|
text_generated = key+" is set to "+value_extracted
|
||||||
|
return HttpResponse(text_generated, content_type="text/plain")
|
||||||
|
|
||||||
|
|
||||||
|
def redirect_to_key(request,key):
|
||||||
|
value = r.get(key)
|
||||||
|
if value == None:
|
||||||
|
icon_url = r.get('icon')
|
||||||
|
if icon_url == None:
|
||||||
|
icon_url = "https://cdn-icons-png.flaticon.com/512/6402/6402576.png"
|
||||||
|
print(key+" is not setup, displaying default page")
|
||||||
|
return render(request, 'website_redirection/blank_page.html', {'title': key,'icon_url':icon_url})
|
||||||
|
else:
|
||||||
|
value_extracted = str(value.decode('utf-8'))
|
||||||
|
print(key+" is setup to : "+value_extracted)
|
||||||
|
print(value_extracted)
|
||||||
|
return HttpResponseRedirect(value_extracted)
|
||||||
@@ -11,6 +11,6 @@ import os
|
|||||||
|
|
||||||
from django.core.asgi import get_asgi_application
|
from django.core.asgi import get_asgi_application
|
||||||
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_code.settings')
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings')
|
||||||
|
|
||||||
application = get_asgi_application()
|
application = get_asgi_application()
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import os
|
import os
|
||||||
from celery import Celery
|
from celery import Celery
|
||||||
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_code.settings')
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings')
|
||||||
|
|
||||||
app = Celery("django_code")
|
app = Celery("core")
|
||||||
app.config_from_object("django.conf:settings", namespace="CELERY")
|
app.config_from_object("django.conf:settings", namespace="CELERY")
|
||||||
app.autodiscover_tasks()
|
app.autodiscover_tasks()
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
from django.conf import settings
|
||||||
|
from django_hosts import patterns, host
|
||||||
|
|
||||||
|
host_patterns = patterns('',
|
||||||
|
host(r"django-testing", settings.ROOT_URLCONF, name="django-testing"),
|
||||||
|
host(r"redirect", 'apps.website_redirection.urls', name="redirect"),
|
||||||
|
host(r"redirect-testing", 'apps.website_redirection.urls', name="redirect-testing"),
|
||||||
|
host(r"job", 'apps.job_dashboard.urls', name="job_dashboard"),
|
||||||
|
host(r"job-testing", 'apps.job_dashboard.urls', name="job_dashboard-testing"),
|
||||||
|
)
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
# routers.py
|
||||||
|
|
||||||
|
class ProjectDatabaseRouter:
|
||||||
|
"""
|
||||||
|
A router to control all database operations on models in the
|
||||||
|
simpsons and cloudmanager applications.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def db_for_read(self, model, **hints):
|
||||||
|
"""Attempts to read simpsons and cloudmanager models go to their specific dbs."""
|
||||||
|
if model._meta.app_label == 'simpsons':
|
||||||
|
return 'simpsons_db'
|
||||||
|
if model._meta.app_label == 'job':
|
||||||
|
return 'job_db'
|
||||||
|
if model._meta.app_label == 'redirect':
|
||||||
|
return 'redirect_db'
|
||||||
|
if model._meta.app_label == 'cloudmanager':
|
||||||
|
return 'cloudmanager_db'
|
||||||
|
return 'default'
|
||||||
|
|
||||||
|
def db_for_write(self, model, **hints):
|
||||||
|
"""Attempts to write simpsons and cloudmanager models go to their specific dbs."""
|
||||||
|
if model._meta.app_label == 'simpsons':
|
||||||
|
return 'simpsons_db'
|
||||||
|
if model._meta.app_label == 'job':
|
||||||
|
return 'job_db'
|
||||||
|
if model._meta.app_label == 'cloudmanager':
|
||||||
|
return 'cloudmanager_db'
|
||||||
|
if model._meta.app_label == 'redirect':
|
||||||
|
return 'redirect_db'
|
||||||
|
return 'default'
|
||||||
|
|
||||||
|
def allow_relation(self, obj1, obj2, **hints):
|
||||||
|
"""Allow relations if both models are in the same database."""
|
||||||
|
# Prevents accidental foreign key relationships across different physical DBs
|
||||||
|
if (
|
||||||
|
obj1._meta.app_label in ['simpsons', 'cloudmanager','redirect','job'] or
|
||||||
|
obj2._meta.app_label in ['simpsons', 'cloudmanager','redirect','job']
|
||||||
|
):
|
||||||
|
return obj1._meta.app_label == obj2._meta.app_label
|
||||||
|
return None
|
||||||
|
|
||||||
|
def allow_migrate(self, db, app_label, model_name=None, **hints):
|
||||||
|
"""Ensure the app's models only show up in the designated database."""
|
||||||
|
if app_label == 'simpsons':
|
||||||
|
return db == 'simpsons_db'
|
||||||
|
if app_label == 'job':
|
||||||
|
return db == 'job_db'
|
||||||
|
if app_label == 'cloudmanager':
|
||||||
|
return db == 'cloudmanager_db'
|
||||||
|
if app_label == 'redirect':
|
||||||
|
return 'redirect_db'
|
||||||
|
# Ensure default Django apps (auth, sessions, etc.) don't migrate into simpsons/cloudmanager
|
||||||
|
if db in ['simpsons_db', 'cloudmanager_db','redirect_db','job_db']:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return None
|
||||||
@@ -9,7 +9,7 @@ https://docs.djangoproject.com/en/4.2/topics/settings/
|
|||||||
For the full list of settings and their values, see
|
For the full list of settings and their values, see
|
||||||
https://docs.djangoproject.com/en/4.2/ref/settings/
|
https://docs.djangoproject.com/en/4.2/ref/settings/
|
||||||
"""
|
"""
|
||||||
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
@@ -23,10 +23,14 @@ BASE_DIR = Path(__file__).resolve().parent.parent
|
|||||||
SECRET_KEY = 'django-insecure-71%)_#e#o9-dl2o^6mfud-*rw+4+8vy-nd*bzeier&(34ap-p9'
|
SECRET_KEY = 'django-insecure-71%)_#e#o9-dl2o^6mfud-*rw+4+8vy-nd*bzeier&(34ap-p9'
|
||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
DEBUG = True
|
#DEBUG = os.getenv("DEBUG")
|
||||||
|
DEBUG = os.getenv("DEBUG", "False").lower() in ("true", "1", "t")
|
||||||
|
|
||||||
ALLOWED_HOSTS = ['reverse.tryton.geeraert.eu','192.168.4.100','django.tryton.geeraert.eu','localhost']
|
|
||||||
|
|
||||||
|
ALLOWED_HOSTS = os.getenv("ALLOWED_HOSTS").split(",")
|
||||||
|
CSRF_TRUSTED_ORIGINS=[]
|
||||||
|
for ALLOWED_HOST in os.getenv("ALLOWED_HOSTS").split(","):
|
||||||
|
CSRF_TRUSTED_ORIGINS.append("https://"+str(ALLOWED_HOST))
|
||||||
|
|
||||||
# Application definition
|
# Application definition
|
||||||
|
|
||||||
@@ -38,9 +42,16 @@ INSTALLED_APPS = [
|
|||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
'bootstrap5',
|
'bootstrap5',
|
||||||
|
'django_hosts',
|
||||||
|
'apps.cloudmanager.apps.CloudmanagerConfig',
|
||||||
|
'apps.random_simpsons.apps.RandomSimpsonsConfig',
|
||||||
|
'apps.website_redirection.apps.redirectConfig',
|
||||||
|
'apps.job_dashboard.apps.JobDashboardConfig',
|
||||||
|
'import_export',
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
'django_hosts.middleware.HostsRequestMiddleware',
|
||||||
'django.middleware.security.SecurityMiddleware',
|
'django.middleware.security.SecurityMiddleware',
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
@@ -48,15 +59,21 @@ MIDDLEWARE = [
|
|||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
|
'django_hosts.middleware.HostsResponseMiddleware',
|
||||||
]
|
]
|
||||||
|
|
||||||
ROOT_URLCONF = 'django_code.urls'
|
ROOT_URLCONF = 'core.urls'
|
||||||
|
ROOT_HOSTCONF = 'core.hosts'
|
||||||
|
DEFAULT_HOST = 'django-testing'
|
||||||
|
|
||||||
|
|
||||||
TEMPLATES = [
|
TEMPLATES = [
|
||||||
{
|
{
|
||||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
#'DIRS': ["/code/django_code/templates","/code/django_code/dashboard/templates/"],
|
#'DIRS': ["/code/core/templates","/code/core/dashboard/templates/"],
|
||||||
'DIRS': [BASE_DIR / "templates","django_code/dashboard/templates/","django_code/stash_management/templates"],
|
'DIRS': [
|
||||||
|
BASE_DIR / "templates"
|
||||||
|
],
|
||||||
'APP_DIRS': True,
|
'APP_DIRS': True,
|
||||||
'OPTIONS': {
|
'OPTIONS': {
|
||||||
'context_processors': [
|
'context_processors': [
|
||||||
@@ -69,7 +86,7 @@ TEMPLATES = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
WSGI_APPLICATION = 'django_code.wsgi.application'
|
WSGI_APPLICATION = 'core.wsgi.application'
|
||||||
|
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
@@ -77,11 +94,48 @@ WSGI_APPLICATION = 'django_code.wsgi.application'
|
|||||||
|
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
'ENGINE': 'django.db.backends.postgresql',
|
||||||
'NAME': BASE_DIR / 'db.sqlite3',
|
'NAME': 'django',
|
||||||
}
|
'USER': os.environ.get('DB_USERNAME'),
|
||||||
|
'PASSWORD': os.environ.get('DB_PASSWORD'),
|
||||||
|
'HOST': os.environ.get('DB_HOST'),
|
||||||
|
'PORT': os.environ.get('DB_PORT'),
|
||||||
|
},
|
||||||
|
'cloudmanager_db': {
|
||||||
|
'ENGINE': 'django.db.backends.postgresql',
|
||||||
|
'NAME': 'cloudmanager',
|
||||||
|
'USER': os.environ.get('DB_USERNAME'),
|
||||||
|
'PASSWORD': os.environ.get('DB_PASSWORD'),
|
||||||
|
'HOST': os.environ.get('DB_HOST'),
|
||||||
|
'PORT': os.environ.get('DB_PORT'),
|
||||||
|
},
|
||||||
|
'simpsons_db': {
|
||||||
|
'ENGINE': 'django.db.backends.postgresql',
|
||||||
|
'NAME': 'simpsons',
|
||||||
|
'USER': os.environ.get('DB_USERNAME'),
|
||||||
|
'PASSWORD': os.environ.get('DB_PASSWORD'),
|
||||||
|
'HOST': os.environ.get('DB_HOST'),
|
||||||
|
'PORT': os.environ.get('DB_PORT'),
|
||||||
|
},
|
||||||
|
'redirect_db': {
|
||||||
|
'ENGINE': 'django.db.backends.postgresql',
|
||||||
|
'NAME': 'redirect',
|
||||||
|
'USER': os.environ.get('DB_USERNAME'),
|
||||||
|
'PASSWORD': os.environ.get('DB_PASSWORD'),
|
||||||
|
'HOST': os.environ.get('DB_HOST'),
|
||||||
|
'PORT': os.environ.get('DB_PORT'),
|
||||||
|
},
|
||||||
|
'job_db': {
|
||||||
|
'ENGINE': 'django.db.backends.postgresql',
|
||||||
|
'NAME': 'job',
|
||||||
|
'USER': os.environ.get('DB_USERNAME'),
|
||||||
|
'PASSWORD': os.environ.get('DB_PASSWORD'),
|
||||||
|
'HOST': os.environ.get('DB_HOST'),
|
||||||
|
'PORT': os.environ.get('DB_PORT'),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
DATABASE_ROUTERS = ['core.routers.ProjectDatabaseRouter']
|
||||||
|
#DATABASE_ROUTERS = []
|
||||||
|
|
||||||
# Password validation
|
# Password validation
|
||||||
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
|
||||||
@@ -117,7 +171,16 @@ USE_TZ = True
|
|||||||
# Static files (CSS, JavaScript, Images)
|
# Static files (CSS, JavaScript, Images)
|
||||||
# https://docs.djangoproject.com/en/4.2/howto/static-files/
|
# https://docs.djangoproject.com/en/4.2/howto/static-files/
|
||||||
|
|
||||||
STATIC_URL = 'static/'
|
STATIC_URL = '/static/'
|
||||||
|
|
||||||
|
STATICFILES_DIRS = [
|
||||||
|
BASE_DIR / "templates/cloudmanager/css",
|
||||||
|
BASE_DIR / "templates/cloudmanager/fonts",
|
||||||
|
BASE_DIR / "templates/cloudmanager/images",
|
||||||
|
BASE_DIR / "templates/cloudmanager/js"
|
||||||
|
]
|
||||||
|
|
||||||
|
STATIC_ROOT = BASE_DIR / "templates/static"
|
||||||
|
|
||||||
# Default primary key field type
|
# Default primary key field type
|
||||||
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
|
||||||
@@ -129,6 +192,6 @@ CELERY_BROKER_URL = "redis://django-redis-svc:6379"
|
|||||||
CELERY_RESULT_BACKEND = "redis://django-redis-svc:6379"
|
CELERY_RESULT_BACKEND = "redis://django-redis-svc:6379"
|
||||||
|
|
||||||
CELERY_IMPORTS = [
|
CELERY_IMPORTS = [
|
||||||
'stash_management.apps', # This line imports the tasks.py file
|
'apps.stash_management.apps', # This line imports the tasks.py file
|
||||||
# Add other app tasks here if needed
|
# Add other app tasks here if needed
|
||||||
]
|
]
|
||||||
@@ -16,30 +16,33 @@ Including another URLconf
|
|||||||
"""
|
"""
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
#from docker_connection import views, apps
|
#from apps.cloudmanager import (credentials,db_interaction)
|
||||||
from random_simpsons import apps as random_simpsons
|
from apps.cloudmanager import apps as cloudmanager_apps
|
||||||
from paperless_django import apps as paperless_django
|
from apps.cloudmanager import views as cloudmanager_views
|
||||||
from onenote import apps as onenote
|
from apps.random_simpsons import views as random_simpsons
|
||||||
from dashboard import apps as dashboardapp
|
from apps.dashboard import apps as dashboardapp
|
||||||
from dashboard import views as dashboardview
|
from apps.dashboard import views as dashboardview
|
||||||
from kubernetes_connection import apps as kubernetes_connection
|
from apps.kubernetes_connection import apps as kubernetes_connection
|
||||||
from stash_management import apps as stashapp
|
from apps.stash_management import apps as stashapp
|
||||||
from stash_management import views as stashview
|
from apps.stash_management import views as stashview
|
||||||
|
from apps.website_redirection import views as website_redirectionapp
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
# path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
|
|
||||||
################### Simpsons ###################
|
################### Simpsons ###################
|
||||||
path('hello/', random_simpsons.hello),
|
path('hello/', random_simpsons.hello),
|
||||||
path('simpsons/', random_simpsons.simpsons),
|
path('simpsons/', random_simpsons.episode_generator),
|
||||||
path('download_file/', random_simpsons.download_file),
|
path('download_file/', random_simpsons.download_file),
|
||||||
|
|
||||||
################### paperless ###################
|
################### Redirect ###################
|
||||||
path('paperless/hello/', paperless_django.hello),
|
path('redirect/hello/', website_redirectionapp.hello),
|
||||||
# path('simpsons/', random_simpsons.simpsons),
|
path('redirect/set/', website_redirectionapp.redirect),
|
||||||
|
path('redirect/get/<str:key>', website_redirectionapp.display_key),
|
||||||
################### onenote ###################
|
path('redirect/go/<str:key>', website_redirectionapp.redirect_to_key),
|
||||||
path('onenote/hello/', onenote.hello),
|
path('redirect/redirect-form/', website_redirectionapp.redirect_process, name='submit_form'),
|
||||||
|
path('redirect/clearkey/', website_redirectionapp.clearkey_process, name='submit_form'),
|
||||||
|
|
||||||
################### onenote ###################
|
################### onenote ###################
|
||||||
path('dashboard/hello/', dashboardapp.hello),
|
path('dashboard/hello/', dashboardapp.hello),
|
||||||
@@ -59,22 +62,31 @@ urlpatterns = [
|
|||||||
path('kubernetes_connection/scale_up/<str:namespace_name>/<str:deploy_name>', kubernetes_connection.scale_up),
|
path('kubernetes_connection/scale_up/<str:namespace_name>/<str:deploy_name>', kubernetes_connection.scale_up),
|
||||||
path('kubernetes_connection/scale_down/<str:namespace_name>/<str:deploy_name>', kubernetes_connection.scale_down),
|
path('kubernetes_connection/scale_down/<str:namespace_name>/<str:deploy_name>', kubernetes_connection.scale_down),
|
||||||
|
|
||||||
################## kubernetes_connection#####
|
################## stash#####
|
||||||
path('stash/', stashview.home),
|
path('stash/', stashview.home),
|
||||||
path('stash/hello/', stashapp.hello),
|
path('stash/hello/', stashapp.hello),
|
||||||
path('stash/form/', stashapp.form),
|
path('stash/form/', stashapp.form),
|
||||||
path('stash/incremental/', stashapp.incremental),
|
path('stash/incremental/', stashapp.incremental),
|
||||||
path('stash/album/', stashapp.album),
|
path('stash/album/', stashapp.album),
|
||||||
path('stash/album-form/', stashapp.album_form, name='submit_form'),
|
path('stash/album-form/', stashapp.album_form, name='submit_form'),
|
||||||
|
path('stash/simple/', stashapp.simple),
|
||||||
|
path('stash/simple-form/', stashapp.simple_form, name='submit_form'),
|
||||||
path('stash/submit-form/', stashapp.handle_survey_form, name='submit_form'),
|
path('stash/submit-form/', stashapp.handle_survey_form, name='submit_form'),
|
||||||
path('stash/incremental-form/', stashapp.incremental_form, name='submit_form'),
|
path('stash/incremental-form/', stashapp.incremental_form, name='submit_form'),
|
||||||
|
|
||||||
|
|
||||||
# path('bookstack/', docker_connection.apps.hello),
|
# path('bookstack/', docker_connection.apps.hello),
|
||||||
# path('test/', docker_connection.apps.http_call_test),
|
# path('test/', docker_connection.apps.http_call_test),
|
||||||
# path('proxmox/', docker_connection.apps.proxmox),
|
# path('proxmox/', docker_connection.apps.proxmox),
|
||||||
# path('simpsons/', random_simpsons.hello),
|
# path('simpsons/', random_simpsons.hello),
|
||||||
# path('docker/<str:action>/<str:id_docker>', docker_connection.apps.docker_call),
|
# path('docker/<str:action>/<str:id_docker>', docker_connection.apps.docker_call),
|
||||||
|
|
||||||
|
################### cloudmanager ###################
|
||||||
|
path('cmm/', cloudmanager_apps.redirect),
|
||||||
|
path('cmm/hello', cloudmanager_apps.hello, name='hello'),
|
||||||
|
path('cmm/coucou', cloudmanager_views.coucou, name='coucou'),
|
||||||
|
path('cmm/display', cloudmanager_views.display, name='display'),
|
||||||
|
#path('cmm/run-action/', cloudmanager_views.trigger_my_action, name='run_my_action_url'),
|
||||||
|
#path('change-schedule/', cloudmanager_views.change_schedule, name='change_schedule'),
|
||||||
|
#path('cmm/main/', db_interaction.main),
|
||||||
|
|
||||||
]
|
]
|
||||||
@@ -11,7 +11,7 @@ import os
|
|||||||
|
|
||||||
from django.core.wsgi import get_wsgi_application
|
from django.core.wsgi import get_wsgi_application
|
||||||
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_code.settings')
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings')
|
||||||
|
|
||||||
application = get_wsgi_application()
|
application = get_wsgi_application()
|
||||||
https_proxy = "gluetun-svc.gluetun.svc:8888"
|
https_proxy = "gluetun-svc.gluetun.svc:8888"
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
from django.shortcuts import render
|
|
||||||
|
|
||||||
|
|
||||||
def home(request):
|
|
||||||
thislist = ["apple", "banana", "cherry"]
|
|
||||||
return render(request, 'home.html',{'thislist': thislist})
|
|
||||||
|
|
||||||
def about(request):
|
|
||||||
thislist = ["apple", "banana", "cherry"]
|
|
||||||
return render(request, 'about.html',{'thislist': thislist})
|
|
||||||
|
|
||||||
def success(request):
|
|
||||||
return render(request, 'start.html',{'deployment': 'django','url':'https://google.com'})
|
|
||||||
|
|
||||||
def scale_up(request,namespace_name,deploy_name):
|
|
||||||
baseurl = "{0}://{1}{2}".format(request.scheme, request.get_host(), request.path)
|
|
||||||
return render(request, 'start.html', {'namespace':namespace_name,'deployment': deploy_name, 'url': 'https://namespace.com','baseurl': baseurl})
|
|
||||||
|
|
||||||
def scale_down(request,namespace_name,deploy_name):
|
|
||||||
baseurl = "{0}://{1}{2}".format(request.scheme, request.get_host(), request.path)
|
|
||||||
return render(request, 'shutdown.html', {'namespace':namespace_name,'deployment': deploy_name, 'url': 'https://namespace.com','baseurl': baseurl})
|
|
||||||
@@ -6,7 +6,7 @@ import sys
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Run administrative tasks."""
|
"""Run administrative tasks."""
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_code.settings')
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings')
|
||||||
try:
|
try:
|
||||||
from django.core.management import execute_from_command_line
|
from django.core.management import execute_from_command_line
|
||||||
except ImportError as exc:
|
except ImportError as exc:
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
from django.apps import AppConfig
|
|
||||||
from django.http import HttpResponse
|
|
||||||
from django.shortcuts import render
|
|
||||||
from django.shortcuts import redirect
|
|
||||||
#from django.template.loader import render_to_string
|
|
||||||
from django.template import loader
|
|
||||||
#import time
|
|
||||||
#import random
|
|
||||||
|
|
||||||
def hello(request):
|
|
||||||
# htmlContent = '
|
|
||||||
#<!DOCTYPE html>
|
|
||||||
#<html lang="en">
|
|
||||||
#<body>
|
|
||||||
#<strong>Hello World from const</strong>
|
|
||||||
#</body>
|
|
||||||
#</html>
|
|
||||||
#'
|
|
||||||
# response = "coucou"
|
|
||||||
# context = {'response': HttpResponse(response)}
|
|
||||||
# return HttpResponse(htmlContent)
|
|
||||||
# return HttpResponse('<h1>Hello onenote! <h1>')
|
|
||||||
# return render(request, 'hello.html', context)
|
|
||||||
|
|
||||||
template = loader.get_template('onenote/hello.html')
|
|
||||||
# template = loader.get_template('onenote/Roser.mht')
|
|
||||||
return HttpResponse(template.render())
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<body>
|
|
||||||
<strong>Hello World</strong>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
from django.apps import AppConfig
|
|
||||||
from django.http import HttpResponse
|
|
||||||
from django.shortcuts import render
|
|
||||||
from django.shortcuts import redirect
|
|
||||||
import time
|
|
||||||
import random
|
|
||||||
|
|
||||||
def hello(request):
|
|
||||||
return HttpResponse('<h1>Hello paperless! <h1>')
|
|
||||||
|
|
||||||
def redirect_authenticated(request):
|
|
||||||
|
|
||||||
final_url = "https://paperless.tryton.geeraert.eu/"
|
|
||||||
print(final_url)
|
|
||||||
|
|
||||||
return redirect(str(final_url))
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
from django.apps import AppConfig
|
|
||||||
from django.http import HttpResponse
|
|
||||||
from django.shortcuts import render
|
|
||||||
from django.shortcuts import redirect
|
|
||||||
|
|
||||||
from django.core.files import File
|
|
||||||
|
|
||||||
#from django.template.loader import render_to_string
|
|
||||||
import time
|
|
||||||
import psycopg2
|
|
||||||
import random
|
|
||||||
import mimetypes
|
|
||||||
|
|
||||||
def DB_generation(host_in,port_in,user_in,password_in,db_in):
|
|
||||||
#db = pymysql.connect(host=host_in, port=port_in, user=user_in, passwd=password_in,db=db_in)
|
|
||||||
db = psycopg2.connect(host=host_in, port=port_in, user=user_in, password=password_in,database=db_in)
|
|
||||||
return db
|
|
||||||
|
|
||||||
def Launch_sql_query(sql,db):
|
|
||||||
#sql query with 1 object returned
|
|
||||||
cursor = db.cursor()
|
|
||||||
|
|
||||||
try:
|
|
||||||
# Execute the SQL command
|
|
||||||
cursor.execute(sql)
|
|
||||||
# Fetch all the rows in a list of lists.
|
|
||||||
results = cursor.fetchall()
|
|
||||||
for row in results:
|
|
||||||
return row[0]
|
|
||||||
|
|
||||||
except:
|
|
||||||
print ("Error: unable to fetch data from the query:")
|
|
||||||
print (sql)
|
|
||||||
print("---")
|
|
||||||
cursor.close()
|
|
||||||
|
|
||||||
|
|
||||||
def hello(request):
|
|
||||||
return HttpResponse('<h1>Hello Simpsons!</h1>')
|
|
||||||
#<h1>href="{{ STATIC_URL }}/files/somefile</h1>)
|
|
||||||
|
|
||||||
|
|
||||||
def download_file(request):
|
|
||||||
# fill these variables with real values
|
|
||||||
fl_path = '/data/download/sonarr'
|
|
||||||
filename = 'The.Boys.2019.S04E05.2160p.HDR10Plus.WEBRip.6CH.x265.HEVC-PSA.mkv'
|
|
||||||
|
|
||||||
# fl = open(fl_path, 'r')
|
|
||||||
# mime_type, _ = mimetypes.guess_type(fl_path)
|
|
||||||
|
|
||||||
# response = HttpResponse(fl, content_type=mime_type)
|
|
||||||
# response['Content-Disposition'] = "attachment; filename=%s" % filename
|
|
||||||
some_file = open('/data/kubernetes/Backup/nextcloud/notes/2024-07-28/Course.md', "r")
|
|
||||||
django_file = File(some_file)
|
|
||||||
return HttpResponse("<h1>Hello download!</h1><h1><a href='{{ MEDIA_URL }}{{ django_file.relative_path }}'>{{ django_file.name }}</a></h1><h1>bye download!</h1>")
|
|
||||||
# return response
|
|
||||||
|
|
||||||
def download_mo(request,file):
|
|
||||||
path_to_file = os.path.realpath(file)
|
|
||||||
response = FileResponse(open(path_to_file, 'rb'))
|
|
||||||
file_name = file[5:]
|
|
||||||
response['Content-Disposition'] = 'inline; filename=' + file_name
|
|
||||||
return response
|
|
||||||
|
|
||||||
#def template(request):
|
|
||||||
# rendered = render_to_string("my_template.html", {"foo": "bar"})
|
|
||||||
#return HttpResponse('<h1>Hello !</h1>')
|
|
||||||
|
|
||||||
def simpsons(request):
|
|
||||||
#dev settings
|
|
||||||
#generated_db = DB_generation("192.168.88.50",32345, "django_username", "Suffrage-Moneybags-Illusion7","django")
|
|
||||||
#production settings
|
|
||||||
generated_db = DB_generation("django-db-svc",5432, "django_username", "Suffrage-Moneybags-Illusion7","django")
|
|
||||||
|
|
||||||
cursor = generated_db.cursor()
|
|
||||||
|
|
||||||
#get max number of season
|
|
||||||
maximum_number_of_seasons = Launch_sql_query("SELECT COUNT(DISTINCT season) as result FROM episodes;",generated_db)
|
|
||||||
|
|
||||||
boolean_restart = True;
|
|
||||||
while (boolean_restart):
|
|
||||||
|
|
||||||
random_seasons = random.randint(1, maximum_number_of_seasons)
|
|
||||||
print("random season: " + str(random_seasons))
|
|
||||||
|
|
||||||
|
|
||||||
#get max number of epiosde for this season
|
|
||||||
maximum_number_of_episodes_query = "SELECT COUNT(url) as result FROM episodes WHERE season = " + str(random_seasons) + ";"
|
|
||||||
|
|
||||||
maximum_number_of_episodes = Launch_sql_query(maximum_number_of_episodes_query,generated_db)
|
|
||||||
|
|
||||||
random_episode = random.randint(1, maximum_number_of_episodes)
|
|
||||||
print("random episode: " + str(random_episode))
|
|
||||||
|
|
||||||
#check if the episode was already seen
|
|
||||||
check_if_already_seen_query = "select seen from episodes where season="+ str(random_seasons) +" and episode = "+ str(random_episode) +";"
|
|
||||||
if not Launch_sql_query(check_if_already_seen_query, generated_db):
|
|
||||||
boolean_restart = False
|
|
||||||
else:
|
|
||||||
print("episode "+str(random_episode)+" from season "+str(random_seasons)+" already seen")
|
|
||||||
|
|
||||||
url_from_episode_season_query = "select url from episodes where season="+ str(random_seasons) +" and episode = "+ str(random_episode) +";"
|
|
||||||
generated_url = Launch_sql_query(url_from_episode_season_query,generated_db)
|
|
||||||
|
|
||||||
#mark as seen
|
|
||||||
url_from_episode_season_query = "update episodes set seen = True where season=" + str(random_seasons) + " and episode = " + str(random_episode) + ";"
|
|
||||||
Launch_sql_query(url_from_episode_season_query, generated_db)
|
|
||||||
|
|
||||||
generated_db.commit()
|
|
||||||
generated_db.close()
|
|
||||||
#return HttpResponse(str(generated_url))
|
|
||||||
return redirect(str(generated_url))
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
from django.shortcuts import render
|
|
||||||
|
|
||||||
# Create your views here.
|
|
||||||
from django.http import HttpResponse
|
|
||||||
from django.shortcuts import render
|
|
||||||
|
|
||||||
def hello(request):
|
|
||||||
return HttpResponse('<h1>Hello Django!</h1>')
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
from django.contrib import admin
|
|
||||||
|
|
||||||
# Register your models here.
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
from django.db import models
|
|
||||||
|
|
||||||
# Create your models here.
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
<h1>Hello template!</h1>
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<link rel="icon" type="image/x-icon" href="https://cdn-icons-png.flaticon.com/512/6402/6402576.png">
|
||||||
|
<title> title </title>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>namespace</th>
|
||||||
|
<th>name</th>
|
||||||
|
<th>replicas</th>
|
||||||
|
</tr>
|
||||||
|
{% block content %}
|
||||||
|
{% for machine_target in list_servers_up %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ machine_target.0 }}</td>
|
||||||
|
<td>{{ machine_target.1 }}</td>
|
||||||
|
<td>{{ machine_target.2 }}</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
{% endblock %}
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,294 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<title>Redirect form</title>
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto|Varela+Round">
|
||||||
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@charset "UTF-8";
|
||||||
|
.m-b-xs {
|
||||||
|
margin-bottom: 2%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.m-b-md {
|
||||||
|
margin-bottom: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.m-t-xs {
|
||||||
|
margin-top: 2%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.m-t-sm {
|
||||||
|
margin-top: 5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
outline: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
padding: 2% 0;
|
||||||
|
background-color: #37404a;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-family: "Roboto", sans-serif;
|
||||||
|
font-size: 2.2em;
|
||||||
|
font-weight: 300;
|
||||||
|
color: #85ffc7;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-family: "Roboto", sans-serif;
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: 300;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#survey-form label,
|
||||||
|
#survey-form .labels {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 2%;
|
||||||
|
font-family: "Roboto", sans-serif;
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: 300;
|
||||||
|
color: #fff;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
#survey-form input::-webkit-input-placeholder {
|
||||||
|
color: transparent !important;
|
||||||
|
}
|
||||||
|
#survey-form input::-moz-placeholder {
|
||||||
|
color: transparent !important;
|
||||||
|
}
|
||||||
|
#survey-form input:-ms-input-placeholder {
|
||||||
|
color: transparent !important;
|
||||||
|
}
|
||||||
|
#survey-form input:-moz-placeholder {
|
||||||
|
color: transparent !important;
|
||||||
|
}
|
||||||
|
#survey-form input,
|
||||||
|
#survey-form select {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
outline: none;
|
||||||
|
border: 2px solid #333;
|
||||||
|
}
|
||||||
|
#survey-form input {
|
||||||
|
margin-top: 1.5%;
|
||||||
|
padding: 0 0 5px 0;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
border-bottom: 2px solid #fff;
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: 300;
|
||||||
|
color: #85ffc7;
|
||||||
|
}
|
||||||
|
#survey-form input:focus {
|
||||||
|
border-color: #85ffc7;
|
||||||
|
}
|
||||||
|
#survey-form [type=checkbox],
|
||||||
|
#survey-form [type=radio] {
|
||||||
|
display: inline-block;
|
||||||
|
width: auto;
|
||||||
|
margin: 0px 10px 0 0;
|
||||||
|
}
|
||||||
|
#survey-form [type=checkbox],
|
||||||
|
#survey-form [type=radio] {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0 10px 0 0 !important;
|
||||||
|
position: relative;
|
||||||
|
top: 5px;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
-o-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
height: 23px;
|
||||||
|
width: 23px;
|
||||||
|
transition: all 0.15s ease-out 0s;
|
||||||
|
background: #37404a;
|
||||||
|
color: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
outline: none;
|
||||||
|
z-index: 1000;
|
||||||
|
border: 1px solid #fff;
|
||||||
|
}
|
||||||
|
#survey-form [type=checkbox]:hover,
|
||||||
|
#survey-form [type=radio]:hover {
|
||||||
|
border-color: #85ffc7;
|
||||||
|
}
|
||||||
|
#survey-form [type=checkbox]:checked:before,
|
||||||
|
#survey-form [type=radio]:checked:before {
|
||||||
|
display: inline-block;
|
||||||
|
height: 21px;
|
||||||
|
width: 21px;
|
||||||
|
position: relative;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
content: "";
|
||||||
|
text-align: center;
|
||||||
|
font-family: "Glyphicons Halflings";
|
||||||
|
line-height: 20px;
|
||||||
|
font-size: 15px;
|
||||||
|
color: #85ffc7;
|
||||||
|
}
|
||||||
|
#survey-form [type=checkbox]:focus,
|
||||||
|
#survey-form [type=radio]:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: #fff;
|
||||||
|
}
|
||||||
|
#survey-form [type=radio] {
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
#survey-form [type=radio]:after {
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
#survey-form [type=number] {
|
||||||
|
width: 45px;
|
||||||
|
}
|
||||||
|
#survey-form [type=number]::-webkit-inner-spin-button, #survey-form [type=number]::-webkit-outer-spin-button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
#survey-form select {
|
||||||
|
height: 40px;
|
||||||
|
padding-left: 5px;
|
||||||
|
background-color: #37404a;
|
||||||
|
border: 2px solid #fff;
|
||||||
|
color: #85ffc7;
|
||||||
|
}
|
||||||
|
#survey-form select option {
|
||||||
|
padding: 5px 10px;
|
||||||
|
font-weight: 300;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
#survey-form select option:hover {
|
||||||
|
background-color: #85ffc7;
|
||||||
|
}
|
||||||
|
#survey-form textarea {
|
||||||
|
resize: none;
|
||||||
|
margin-top: 2%;
|
||||||
|
padding: 10px 10px 0px 20px;
|
||||||
|
width: 100%;
|
||||||
|
height: 90px;
|
||||||
|
color: #85ffc7;
|
||||||
|
background-color: #37404a;
|
||||||
|
border: 2px solid #fff;
|
||||||
|
}
|
||||||
|
#survey-form .btn {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
margin: 3% 0 0 0;
|
||||||
|
height: 45px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 3px solid #85ffc7;
|
||||||
|
border-radius: 0;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 1.2em;
|
||||||
|
color: #85ffc7;
|
||||||
|
text-align: center;
|
||||||
|
background: none;
|
||||||
|
transition: color 0.25s ease;
|
||||||
|
}
|
||||||
|
#survey-form .btn:after {
|
||||||
|
position: absolute;
|
||||||
|
content: "";
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 0;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #85ffc7;
|
||||||
|
transform-origin: left;
|
||||||
|
transition: width 0.5s ease;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
#survey-form .btn:hover {
|
||||||
|
color: #37404a;
|
||||||
|
}
|
||||||
|
#survey-form .btn:hover:after {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
#survey-form fieldset {
|
||||||
|
margin: 5% 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 10px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.copyright i {
|
||||||
|
color: #ef5350;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 600px) {
|
||||||
|
body {
|
||||||
|
padding: 8% 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<main id="main" class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-12 col-lg-offset-3 col-lg-6">
|
||||||
|
<div class="m-b-md text-center">
|
||||||
|
<h1 id="title">Redirect Form</h1>
|
||||||
|
<p id="description" class="description" class="text-center">Download form</p>
|
||||||
|
</div>
|
||||||
|
<form method="GET" action="/redirect-form/" id="survey-form" name="survey-form">
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<label for="key" id="key-label">
|
||||||
|
Key *
|
||||||
|
<input class="" type="text" id="key" name="key" placeholder="Enter your key (required)" required />
|
||||||
|
</label>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<label for="value" id="value-label">
|
||||||
|
Value *
|
||||||
|
<input class="" type="value" id="value" name="value" placeholder="Enter the value (required)" />
|
||||||
|
</label>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<button id="submit" type="submit" class="btn">Submit the form</button>
|
||||||
|
<button id="clearkey" type="submit" formaction="/clearkey/" class="btn">Clear the key</button>
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<button type="button" onclick="location.href='/go/streaming'" class="btn">Streaming</button>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<button type="button" onclick="location.href='/go/streaming-sam'" class="btn">Streaming Sam</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</html>
|
||||||
+2744
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,407 @@
|
|||||||
|
/* Blue Version CSS */
|
||||||
|
|
||||||
|
a:link, a:visited, a:hover, a:focus{text-decoration: none; color: #00cfef;}
|
||||||
|
|
||||||
|
|
||||||
|
/* Home Slider */
|
||||||
|
#home-slider .caption h1 strong{
|
||||||
|
color:#00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-control:hover,
|
||||||
|
.right-control:hover {
|
||||||
|
background-color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.learn-more {
|
||||||
|
border: 2px solid #00cfef;
|
||||||
|
}
|
||||||
|
.learn-more:hover {
|
||||||
|
background: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-control, .right-control {
|
||||||
|
border:1px solid #00cfef;
|
||||||
|
}
|
||||||
|
/* End Home Slider */
|
||||||
|
|
||||||
|
|
||||||
|
/* Navbar */
|
||||||
|
|
||||||
|
/* Link Color */
|
||||||
|
.navbar-inverse { border-color: #00cfef}
|
||||||
|
.navbar-inverse .navbar-nav>li>a:hover, .navbar-inverse .navbar-nav>li>a:focus { color: #00cfef}
|
||||||
|
.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a, .navbar-inverse .navbar-nav>.open>a:hover, .navbar-inverse .navbar-nav>.open>a:focus { color: #00cfef}
|
||||||
|
.navbar-inverse .navbar-nav>.active>a:hover, .navbar-inverse .navbar-nav>.active>a:focus { color: #00cfef}
|
||||||
|
.dropdown-menu>li>a { color: #00cfef}
|
||||||
|
.navbar-inverse .navbar-nav>.dropdown>a:hover .caret { border-top-color: #00cfef}
|
||||||
|
|
||||||
|
.navbar-toggle {
|
||||||
|
border: transparent;
|
||||||
|
background-color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-inverse .navbar-toggle:hover,
|
||||||
|
.navbar-inverse .navbar-toggle:focus {
|
||||||
|
background-color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* End Navbar */
|
||||||
|
|
||||||
|
/* Loader */
|
||||||
|
.spinner > div
|
||||||
|
{
|
||||||
|
background: #00cfef;
|
||||||
|
}
|
||||||
|
/* End Loader*/
|
||||||
|
|
||||||
|
/* Titles & Color */
|
||||||
|
.section-title h1 span{
|
||||||
|
background-color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
background-image: none;
|
||||||
|
background-color: #00cfef;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.btn {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn a {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-inverse:hover{
|
||||||
|
color: #fff;
|
||||||
|
background-color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-inverse:hover a{
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.btn-inverse:hover {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.btn:hover {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn:hover a{
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-inverse {
|
||||||
|
color: #00cfef;
|
||||||
|
border: 1px solid #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.btn-inverse{
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-inverse a{
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
a.btn:hover {
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn a:hover {
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-one{
|
||||||
|
background: none repeat scroll 0 0 #00cfef;
|
||||||
|
border: 1px solid #00cfef;
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-one:hover {
|
||||||
|
border: 1px solid #00cfef;
|
||||||
|
color: #00cfef;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.btn:hover {
|
||||||
|
border: 1px solid #00cfef;
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hovicon.effect-1 {
|
||||||
|
background: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hovicon.effect-1:after {
|
||||||
|
box-shadow: 0 0 0 4px #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-color {
|
||||||
|
background: none repeat scroll 0 0 #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dporcaps-negative {
|
||||||
|
background: none repeat scroll 0 0 #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dporcaps {
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blockqoute-style-2 {
|
||||||
|
border-left: 5px solid #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
cite {
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Effect 1a */
|
||||||
|
.hovicon.effect-1.sub-a:hover {
|
||||||
|
background: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-color
|
||||||
|
{
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.white-color
|
||||||
|
{
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* End Titles & Color */
|
||||||
|
|
||||||
|
|
||||||
|
/* Facts */
|
||||||
|
.number p:first-letter {
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
/* End Facts */
|
||||||
|
|
||||||
|
/* Team Member */
|
||||||
|
.team-member-holder:hover {
|
||||||
|
border-color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-overlay {
|
||||||
|
background: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view-profile {
|
||||||
|
color:#00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.team-member-social-list-item {
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.team-details h3{
|
||||||
|
color: #00cdef;
|
||||||
|
}
|
||||||
|
/* End Team Member */
|
||||||
|
|
||||||
|
/* Skills */
|
||||||
|
.skills h4:first-letter {
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
/* End Skills */
|
||||||
|
|
||||||
|
/* Works */
|
||||||
|
#filters li span.active,#filters li span:hover {
|
||||||
|
background: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
#filters li span {
|
||||||
|
border: 1px solid #00cfef;
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-details h3 {
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-description h3 {
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* End Works */
|
||||||
|
|
||||||
|
/* Partners */
|
||||||
|
.partners-img:hover img{
|
||||||
|
border-color: #00cfef;
|
||||||
|
}
|
||||||
|
/* End Partners */
|
||||||
|
|
||||||
|
/* Pricing */
|
||||||
|
.single-table h4:first-letter {
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-icon {
|
||||||
|
background-color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.price {
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.single-table .btn-price, .sign_form input[type="submit"] {
|
||||||
|
background: none repeat scroll 0 0 #00cfef;
|
||||||
|
border: 1px solid #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.single-table .btn-price:hover {
|
||||||
|
border: 1px solid #00cfef;
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.single-table.featured .price-icon, .single-table.featured .btn-price {
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.single-table.featured{
|
||||||
|
background-color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.single-table.featured .price {
|
||||||
|
background-color: #00cfef;
|
||||||
|
}
|
||||||
|
/* End Pricing */
|
||||||
|
|
||||||
|
/* Clients */
|
||||||
|
.clients h5 {
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-indicators .active {
|
||||||
|
background-color: #00cfef;
|
||||||
|
border-color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-indicators li {
|
||||||
|
border-color: #00cfef;
|
||||||
|
}
|
||||||
|
/* End Clients */
|
||||||
|
|
||||||
|
/* News */
|
||||||
|
.post-date {
|
||||||
|
background-color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entry-title a:hover {
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
/* End News */
|
||||||
|
|
||||||
|
/* Blog */
|
||||||
|
.widget.tags-cloud a {
|
||||||
|
border: 1px solid #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.widget.tags-cloud a:hover {
|
||||||
|
border: 1px solid #00cfef;
|
||||||
|
background-color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags a {
|
||||||
|
border: 1px solid #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags a:hover {
|
||||||
|
border: 1px solid #00cfef;
|
||||||
|
background-color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.pager li > a, .pager li > span {
|
||||||
|
border: 1px solid #00cfef;
|
||||||
|
}
|
||||||
|
.pager li > a:hover, .pager li > a:focus {
|
||||||
|
border: 1px solid #00cfef;
|
||||||
|
background-color: #00cfef;
|
||||||
|
}
|
||||||
|
/* End Blog */
|
||||||
|
|
||||||
|
|
||||||
|
/* Tweet */
|
||||||
|
#twitter-carousel .item a {
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.twitter-icon .fa-twitter:after {
|
||||||
|
border-color: #00cfef transparent transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.twitter-icon .fa-twitter, .twitter-left-control:hover, .twitter-right-control:hover {
|
||||||
|
background-color: #00cfef;
|
||||||
|
}
|
||||||
|
/* End Tweet */
|
||||||
|
|
||||||
|
/* Footer */
|
||||||
|
.bottom-footer {
|
||||||
|
border-top: 7px solid #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-footer-left p a {
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-social-icons li a i{
|
||||||
|
background-color: #00cfef;
|
||||||
|
border: 1px solid #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-social-icons li a i:hover{
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* End Footer */
|
||||||
|
|
||||||
|
/* Contacts */
|
||||||
|
.contact_form i{
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact_form input[type="submit"] {
|
||||||
|
background: #00cfef;
|
||||||
|
border: 1px solid #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact_form input[type="submit"]:hover {
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sign_form input[type="submit"]:hover {
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
/* End Contacts */
|
||||||
|
|
||||||
|
/* To Top */
|
||||||
|
a.scroll-up {
|
||||||
|
background: none repeat scroll 0 0 #00cfef;
|
||||||
|
}
|
||||||
|
a.scroll-up i {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.scroll-up:hover i {
|
||||||
|
color: #00cfef;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.scroll-up:hover {
|
||||||
|
color: #00cfef;
|
||||||
|
border-color: #00cfef;
|
||||||
|
}
|
||||||
|
/* End To Top */
|
||||||
@@ -0,0 +1,470 @@
|
|||||||
|
/*!
|
||||||
|
* Bootstrap v3.3.1 (http://getbootstrap.com)
|
||||||
|
* Copyright 2011-2014 Twitter, Inc.
|
||||||
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||||
|
*/
|
||||||
|
|
||||||
|
.btn-default,
|
||||||
|
.btn-primary,
|
||||||
|
.btn-success,
|
||||||
|
.btn-info,
|
||||||
|
.btn-warning,
|
||||||
|
.btn-danger {
|
||||||
|
text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);
|
||||||
|
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
|
||||||
|
}
|
||||||
|
.btn-default:active,
|
||||||
|
.btn-primary:active,
|
||||||
|
.btn-success:active,
|
||||||
|
.btn-info:active,
|
||||||
|
.btn-warning:active,
|
||||||
|
.btn-danger:active,
|
||||||
|
.btn-default.active,
|
||||||
|
.btn-primary.active,
|
||||||
|
.btn-success.active,
|
||||||
|
.btn-info.active,
|
||||||
|
.btn-warning.active,
|
||||||
|
.btn-danger.active {
|
||||||
|
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
|
||||||
|
box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
|
||||||
|
}
|
||||||
|
.btn-default .badge,
|
||||||
|
.btn-primary .badge,
|
||||||
|
.btn-success .badge,
|
||||||
|
.btn-info .badge,
|
||||||
|
.btn-warning .badge,
|
||||||
|
.btn-danger .badge {
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
.btn:active,
|
||||||
|
.btn.active {
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
.btn-default {
|
||||||
|
text-shadow: 0 1px 0 #fff;
|
||||||
|
background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
|
||||||
|
background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-color: #dbdbdb;
|
||||||
|
border-color: #ccc;
|
||||||
|
}
|
||||||
|
.btn-default:hover,
|
||||||
|
.btn-default:focus {
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
background-position: 0 -15px;
|
||||||
|
}
|
||||||
|
.btn-default:active,
|
||||||
|
.btn-default.active {
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
border-color: #dbdbdb;
|
||||||
|
}
|
||||||
|
.btn-default:disabled,
|
||||||
|
.btn-default[disabled] {
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
.btn-primary {
|
||||||
|
background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88));
|
||||||
|
background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-color: #245580;
|
||||||
|
}
|
||||||
|
.btn-primary:hover,
|
||||||
|
.btn-primary:focus {
|
||||||
|
background-color: #265a88;
|
||||||
|
background-position: 0 -15px;
|
||||||
|
}
|
||||||
|
.btn-primary:active,
|
||||||
|
.btn-primary.active {
|
||||||
|
background-color: #265a88;
|
||||||
|
border-color: #245580;
|
||||||
|
}
|
||||||
|
.btn-primary:disabled,
|
||||||
|
.btn-primary[disabled] {
|
||||||
|
background-color: #265a88;
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
.btn-success {
|
||||||
|
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
|
||||||
|
background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-color: #3e8f3e;
|
||||||
|
}
|
||||||
|
.btn-success:hover,
|
||||||
|
.btn-success:focus {
|
||||||
|
background-color: #419641;
|
||||||
|
background-position: 0 -15px;
|
||||||
|
}
|
||||||
|
.btn-success:active,
|
||||||
|
.btn-success.active {
|
||||||
|
background-color: #419641;
|
||||||
|
border-color: #3e8f3e;
|
||||||
|
}
|
||||||
|
.btn-success:disabled,
|
||||||
|
.btn-success[disabled] {
|
||||||
|
background-color: #419641;
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
.btn-info {
|
||||||
|
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
|
||||||
|
background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-color: #28a4c9;
|
||||||
|
}
|
||||||
|
.btn-info:hover,
|
||||||
|
.btn-info:focus {
|
||||||
|
background-color: #2aabd2;
|
||||||
|
background-position: 0 -15px;
|
||||||
|
}
|
||||||
|
.btn-info:active,
|
||||||
|
.btn-info.active {
|
||||||
|
background-color: #2aabd2;
|
||||||
|
border-color: #28a4c9;
|
||||||
|
}
|
||||||
|
.btn-info:disabled,
|
||||||
|
.btn-info[disabled] {
|
||||||
|
background-color: #2aabd2;
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
.btn-warning {
|
||||||
|
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
|
||||||
|
background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-color: #e38d13;
|
||||||
|
}
|
||||||
|
.btn-warning:hover,
|
||||||
|
.btn-warning:focus {
|
||||||
|
background-color: #eb9316;
|
||||||
|
background-position: 0 -15px;
|
||||||
|
}
|
||||||
|
.btn-warning:active,
|
||||||
|
.btn-warning.active {
|
||||||
|
background-color: #eb9316;
|
||||||
|
border-color: #e38d13;
|
||||||
|
}
|
||||||
|
.btn-warning:disabled,
|
||||||
|
.btn-warning[disabled] {
|
||||||
|
background-color: #eb9316;
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
.btn-danger {
|
||||||
|
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
|
||||||
|
background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-color: #b92c28;
|
||||||
|
}
|
||||||
|
.btn-danger:hover,
|
||||||
|
.btn-danger:focus {
|
||||||
|
background-color: #c12e2a;
|
||||||
|
background-position: 0 -15px;
|
||||||
|
}
|
||||||
|
.btn-danger:active,
|
||||||
|
.btn-danger.active {
|
||||||
|
background-color: #c12e2a;
|
||||||
|
border-color: #b92c28;
|
||||||
|
}
|
||||||
|
.btn-danger:disabled,
|
||||||
|
.btn-danger[disabled] {
|
||||||
|
background-color: #c12e2a;
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
.thumbnail,
|
||||||
|
.img-thumbnail {
|
||||||
|
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
|
||||||
|
box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
|
||||||
|
}
|
||||||
|
.dropdown-menu > li > a:hover,
|
||||||
|
.dropdown-menu > li > a:focus {
|
||||||
|
background-color: #e8e8e8;
|
||||||
|
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
|
||||||
|
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.dropdown-menu > .active > a,
|
||||||
|
.dropdown-menu > .active > a:hover,
|
||||||
|
.dropdown-menu > .active > a:focus {
|
||||||
|
background-color: #2e6da4;
|
||||||
|
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
|
||||||
|
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.navbar-default {
|
||||||
|
background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8));
|
||||||
|
background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-radius: 4px;
|
||||||
|
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
|
||||||
|
}
|
||||||
|
.navbar-default .navbar-nav > .open > a,
|
||||||
|
.navbar-default .navbar-nav > .active > a {
|
||||||
|
background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2));
|
||||||
|
background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
|
||||||
|
box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
|
||||||
|
}
|
||||||
|
.navbar-brand,
|
||||||
|
.navbar-nav > li > a {
|
||||||
|
text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
|
||||||
|
}
|
||||||
|
.navbar-inverse {
|
||||||
|
background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
|
||||||
|
background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.navbar-inverse .navbar-nav > .open > a,
|
||||||
|
.navbar-inverse .navbar-nav > .active > a {
|
||||||
|
background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f));
|
||||||
|
background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
|
||||||
|
box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
|
||||||
|
}
|
||||||
|
.navbar-inverse .navbar-brand,
|
||||||
|
.navbar-inverse .navbar-nav > li > a {
|
||||||
|
text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);
|
||||||
|
}
|
||||||
|
.navbar-static-top,
|
||||||
|
.navbar-fixed-top,
|
||||||
|
.navbar-fixed-bottom {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
.navbar .navbar-nav .open .dropdown-menu > .active > a,
|
||||||
|
.navbar .navbar-nav .open .dropdown-menu > .active > a:hover,
|
||||||
|
.navbar .navbar-nav .open .dropdown-menu > .active > a:focus {
|
||||||
|
color: #fff;
|
||||||
|
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
|
||||||
|
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.alert {
|
||||||
|
text-shadow: 0 1px 0 rgba(255, 255, 255, .2);
|
||||||
|
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
|
||||||
|
}
|
||||||
|
.alert-success {
|
||||||
|
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
|
||||||
|
background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-color: #b2dba1;
|
||||||
|
}
|
||||||
|
.alert-info {
|
||||||
|
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
|
||||||
|
background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-color: #9acfea;
|
||||||
|
}
|
||||||
|
.alert-warning {
|
||||||
|
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
|
||||||
|
background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-color: #f5e79e;
|
||||||
|
}
|
||||||
|
.alert-danger {
|
||||||
|
background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
|
||||||
|
background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-color: #dca7a7;
|
||||||
|
}
|
||||||
|
.progress {
|
||||||
|
background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
|
||||||
|
background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.progress-bar {
|
||||||
|
background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090));
|
||||||
|
background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.progress-bar-success {
|
||||||
|
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
|
||||||
|
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.progress-bar-info {
|
||||||
|
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
|
||||||
|
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.progress-bar-warning {
|
||||||
|
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
|
||||||
|
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.progress-bar-danger {
|
||||||
|
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
|
||||||
|
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.progress-bar-striped {
|
||||||
|
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
|
||||||
|
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
|
||||||
|
background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
|
||||||
|
}
|
||||||
|
.list-group {
|
||||||
|
border-radius: 4px;
|
||||||
|
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
|
||||||
|
box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
|
||||||
|
}
|
||||||
|
.list-group-item.active,
|
||||||
|
.list-group-item.active:hover,
|
||||||
|
.list-group-item.active:focus {
|
||||||
|
text-shadow: 0 -1px 0 #286090;
|
||||||
|
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a));
|
||||||
|
background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-color: #2b669a;
|
||||||
|
}
|
||||||
|
.list-group-item.active .badge,
|
||||||
|
.list-group-item.active:hover .badge,
|
||||||
|
.list-group-item.active:focus .badge {
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
.panel {
|
||||||
|
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
|
||||||
|
box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
|
||||||
|
}
|
||||||
|
.panel-default > .panel-heading {
|
||||||
|
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
|
||||||
|
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.panel-primary > .panel-heading {
|
||||||
|
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
|
||||||
|
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.panel-success > .panel-heading {
|
||||||
|
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
|
||||||
|
background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.panel-info > .panel-heading {
|
||||||
|
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
|
||||||
|
background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.panel-warning > .panel-heading {
|
||||||
|
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
|
||||||
|
background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.panel-danger > .panel-heading {
|
||||||
|
background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
|
||||||
|
background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.well {
|
||||||
|
background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
|
||||||
|
background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-color: #dcdcdc;
|
||||||
|
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
|
||||||
|
box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
|
||||||
|
}
|
||||||
|
/*# sourceMappingURL=bootstrap-theme.css.map */
|
||||||
File diff suppressed because one or more lines are too long
+6332
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
+2337
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user