initial commit

This commit is contained in:
Chris Cowley 2024-09-30 16:50:20 +02:00
commit 02c4f8ac53
10 changed files with 503 additions and 0 deletions

162
.dockerignore Normal file
View file

@ -0,0 +1,162 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$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
.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
# 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
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.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/

2
.envrc Normal file
View file

@ -0,0 +1,2 @@
export FLASK_APP=api.py
export FLASK_DEBUG=1

162
.gitignore vendored Normal file
View file

@ -0,0 +1,162 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$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
.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
# 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
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.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/

12
Dockerfile Normal file
View file

@ -0,0 +1,12 @@
FROM python:alpine
WORKDIR /app
COPY ./requirements.txt /app/requirements.txt
RUN pip install -r requirements.txt
COPY . /app/
EXPOSE 5000
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "wsgi:app"]

10
Makefile Normal file
View file

@ -0,0 +1,10 @@
dev:
docker run -p 5000:5000 -v ~/.kube/config:/root/.kube/config -e FLASK_ENV=development -e FLASK_DEBUG=1 -v ./:/app db-deployer flask run --host 0.0.0.0
run:
docker run -p 5000:5000 -v ~/.kube/config:/root/.kube/config db-deployer
clean:
for resource in $$(kubectl -n test get mariadbs.k8s.mariadb.com,pvc -o name); do kubectl -n test delete $$resource; done
build:
docker build -t db-deployer .

1
README.md Normal file
View file

@ -0,0 +1 @@
https://faizanbashir.github.io/creating-kubernetes-custom-resource-definition-using-python#listing-resources-using-the-dynamic-client

111
api.py Normal file
View file

@ -0,0 +1,111 @@
import os
import random
from flask import (
Flask,
request,
jsonify,
)
from flask_restful import reqparse, abort, Resource, Api
from kubernetes import client as k8s_client
from kubernetes.client import api_client
from kubernetes import config, watch, dynamic
from kubernetes.dynamic.exceptions import ResourceNotFoundError
app = Flask(__name__)
api = Api(app)
if "KUBERNETES_SERVICE_HOST" in os.environ:
config.load_incluster_config()
else:
config.load_kube_config()
v1 = k8s_client.CoreV1Api()
client = dynamic.DynamicClient(
api_client.ApiClient(configuration=config.load_kube_config())
)
custom_object_api = k8s_client.CustomObjectsApi()
first_names = ['Ada', 'Bela', 'Cade', 'Dax', 'Eva', 'Fynn', 'Gia', 'Hugo', 'Ivy', 'Jax']
last_names = ['Smith', 'Johnson', 'Williams', 'Jones', 'Brown', 'Davis', 'Miller', 'Wilson', 'Moore', 'Taylor']
def create_name():
first_name = random.choice(first_names)
last_name = random.choice(last_names)
return f"{first_name}{last_name}"
class DBCluster(Resource):
def get(self):
namespace = "test"
clusters = []
mariadb_resource = client.resources.get(api_version='k8s.mariadb.com/v1alpha1', kind='MariaDB')
mariadbs = mariadb_resource.get(namespace=namespace)
for mariadb in mariadbs.items:
name = mariadb.metadata.name
clusters.append({'name': name})
return clusters
def post(self):
namespace = "test"
name = random.choice(first_names).lower()
print(name )
mariadb = {
'apiVersion': 'k8s.mariadb.com/v1alpha1',
'kind': 'MariaDB',
'metadata': {
'name': name,
'namespace': namespace,
},
'spec': {
'rootPasswordSecretKeyRef': {
'name': 'mariadb-root',
'key': 'password',
'generate': True
},
'username': 'mariadb',
'passwordSecretKeyRef': {
'name': 'mariadb-password',
'key': 'password',
'generate': True
},
'port': 3306,
'storage': {
'size': '1Gi',
}
}
}
mariadb_instance = custom_object_api.create_namespaced_custom_object(
group='k8s.mariadb.com',
version='v1alpha1',
namespace=namespace,
plural='mariadbs',
body=mariadb
)
return mariadb_instance
class DBClusterDetails(Resource):
def get(self, name):
namespace = "test"
cluster = {}
mariadb_resource = client.resources.get(api_version='k8s.mariadb.com/v1alpha1', kind='MariaDB')
mariadbs = mariadb_resource.get(namespace=namespace)
for mariadb in mariadbs.items:
if mariadb.metadata.name == name:
for k,v in mariadb.metadata:
print(k,v)
data = {
"name": mariadb.metadata.name,
"storage": mariadb.spec.storage.size,
}
return data
api.add_resource(DBCluster, '/clusters')
api.add_resource(DBClusterDetails, '/clusters/<string:name>')
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)

8
manage.py Normal file
View file

@ -0,0 +1,8 @@
from flask.cli import FlaskGroup
from api import api
cli = FlaskGroup(api)
if __name__ == "__main__":
cli()

30
requirements.txt Normal file
View file

@ -0,0 +1,30 @@
aniso8601==9.0.1
blinker==1.8.2
cachetools==5.5.0
certifi==2024.8.30
charset-normalizer==3.3.2
click==8.1.7
durationpy==0.7
Flask==3.0.3
Flask-RESTful==0.3.10
google-auth==2.35.0
gunicorn==23.0.0
idna==3.10
itsdangerous==2.2.0
Jinja2==3.1.4
kubernetes==31.0.0
MarkupSafe==2.1.5
oauthlib==3.2.2
packaging==24.1
pyasn1==0.6.1
pyasn1_modules==0.4.1
python-dateutil==2.9.0.post0
pytz==2024.2
PyYAML==6.0.2
requests==2.32.3
requests-oauthlib==2.0.0
rsa==4.9
six==1.16.0
urllib3==2.2.3
websocket-client==1.8.0
Werkzeug==3.0.4

5
wsgi.py Normal file
View file

@ -0,0 +1,5 @@
from api import app
if __name__ == '__main__':
app.run()