cloudcoil 0.2.2__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cloudcoil-0.3.0/.github/workflows/pypi_publish.yml +47 -0
- cloudcoil-0.3.0/.github/workflows/update_repos.yml +30 -0
- cloudcoil-0.3.0/.gitignore +178 -0
- cloudcoil-0.3.0/Makefile +74 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/PKG-INFO +243 -3
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/README.md +242 -2
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/apimachinery.py +14 -14
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/codegen/generator.py +160 -119
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/codegen/templates/pydantic_v2/BaseModel.jinja2 +6 -6
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/codegen/templates/pydantic_v2/RootModel.jinja2 +4 -4
- cloudcoil-0.3.0/cookiecutter/LICENSE +190 -0
- cloudcoil-0.3.0/cookiecutter/README.md +2 -0
- cloudcoil-0.3.0/cookiecutter/cookiecutter.json +11 -0
- cloudcoil-0.3.0/cookiecutter/hooks/post_gen_project.sh +10 -0
- cloudcoil-0.3.0/cookiecutter/models-{{ cookiecutter.model_name }}/.gitattributes +1 -0
- cloudcoil-0.3.0/cookiecutter/models-{{ cookiecutter.model_name }}/.github/workflows/ci.yml +52 -0
- cloudcoil-0.2.2/.github/workflows/pypi_publish.yml → cloudcoil-0.3.0/cookiecutter/models-{{ cookiecutter.model_name }}/.github/workflows/pypi_publish.yml +4 -2
- cloudcoil-0.3.0/cookiecutter/models-{{ cookiecutter.model_name }}/.github/workflows/test_pypi_publish.yml +45 -0
- cloudcoil-0.3.0/cookiecutter/models-{{ cookiecutter.model_name }}/.github/workflows/update_releases.yml +126 -0
- cloudcoil-0.3.0/cookiecutter/models-{{ cookiecutter.model_name }}/LICENSE +201 -0
- cloudcoil-0.3.0/cookiecutter/models-{{ cookiecutter.model_name }}/Makefile +39 -0
- cloudcoil-0.3.0/cookiecutter/models-{{ cookiecutter.model_name }}/README.md +3 -0
- cloudcoil-0.3.0/cookiecutter/models-{{ cookiecutter.model_name }}/mkdocs.yml +38 -0
- cloudcoil-0.3.0/cookiecutter/models-{{ cookiecutter.model_name }}/pyproject.toml +87 -0
- cloudcoil-0.3.0/cookiecutter/models-{{ cookiecutter.model_name }}/tests/test_import.py +8 -0
- cloudcoil-0.3.0/docs/api.md +3 -0
- cloudcoil-0.3.0/models/cert-manager/README.md +204 -0
- cloudcoil-0.3.0/models/cert-manager/cookiecutter.yaml +8 -0
- cloudcoil-0.3.0/models/cert-manager/pyproject.toml +3 -0
- cloudcoil-0.3.0/models/fluxcd/README.md +207 -0
- cloudcoil-0.3.0/models/fluxcd/cookiecutter.yaml +8 -0
- cloudcoil-0.3.0/models/fluxcd/pyproject.toml +4 -0
- cloudcoil-0.3.0/models/kubernetes/README.md +262 -0
- cloudcoil-0.3.0/models/kubernetes/cookiecutter.yaml +8 -0
- cloudcoil-0.3.0/models/kubernetes/pyproject.toml +8 -0
- cloudcoil-0.3.0/models/kyverno/README.md +206 -0
- cloudcoil-0.3.0/models/kyverno/cookiecutter.yaml +8 -0
- cloudcoil-0.3.0/models/kyverno/pyproject.toml +4 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/pyproject.toml +3 -2
- cloudcoil-0.3.0/tests/test_cli.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/tests/test_codegen.py +249 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/uv.lock +11 -6
- cloudcoil-0.2.2/Makefile +0 -39
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/.gitattributes +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/.github/ISSUE_TEMPLATE//360/237/220/233-bug-report.md" +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/.github/ISSUE_TEMPLATE//360/237/224/214-model-request.md" +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/.github/ISSUE_TEMPLATE//360/237/232/200-feature-request.md" +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/.github/workflows/ci.yml +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/.github/workflows/docs.yml +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/.github/workflows/test_pypi_publish.yml +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/CODE_OF_CONDUCT.md +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/LICENSE +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/MEMBERS.md +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/SECURITY.md +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/_context.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/_pydantic.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/_testing/__init__.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/_testing/clusters.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/_testing/plugin.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/client/__init__.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/client/_api_client.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/client/_config.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/codegen/__init__.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/codegen/_tomllib/__init__.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/codegen/_tomllib/_parser.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/codegen/_tomllib/_re.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/codegen/_tomllib/_types.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/codegen/import_rewriter.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/codegen/ruff.toml +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/errors.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/models/py.typed +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/mypy.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/py.typed +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/pydantic.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/resources.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/cloudcoil/version.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0/cookiecutter/models-{{ cookiecutter.model_name }}}/.gitignore +0 -0
- /cloudcoil-0.2.2/tests/test_cli.py → /cloudcoil-0.3.0/cookiecutter/models-{{ cookiecutter.model_name }}/cloudcoil/models/{{ cookiecutter.module_name }}/__init__.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0/cookiecutter/models-{{ cookiecutter.model_name }}}/docs/api.md +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/docs/index.md +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/mkdocs.yml +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/tests/data/k8s-swagger.json +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/tests/test_config.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/tests/test_context.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/tests/test_e2e.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/tests/test_fluent.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/tests/test_import_rewriter.py +0 -0
- {cloudcoil-0.2.2 → cloudcoil-0.3.0}/tests/test_resources.py +0 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: PyPI publish
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
release:
|
|
6
|
+
types: [released]
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
# IMPORTANT: this permission is mandatory for Trusted Publishing
|
|
13
|
+
id-token: write
|
|
14
|
+
steps:
|
|
15
|
+
- name: Checkout code
|
|
16
|
+
uses: actions/checkout@v3
|
|
17
|
+
|
|
18
|
+
- name: Setup Python
|
|
19
|
+
uses: actions/setup-python@v4
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.10"
|
|
22
|
+
|
|
23
|
+
- name: Install uv
|
|
24
|
+
uses: astral-sh/setup-uv@v4
|
|
25
|
+
with:
|
|
26
|
+
python-version: "3.10"
|
|
27
|
+
enable-cache: true
|
|
28
|
+
cache-dependency-glob: "**/uv.lock"
|
|
29
|
+
|
|
30
|
+
- name: Install dependencies
|
|
31
|
+
run: uv sync --extra all --dev
|
|
32
|
+
|
|
33
|
+
- name: Bump version number
|
|
34
|
+
run: |
|
|
35
|
+
sed -i "s/version = \".*\"/version = \"${{ github.event.release.tag_name }}\"/" pyproject.toml
|
|
36
|
+
|
|
37
|
+
- name: Build package
|
|
38
|
+
run: uv build
|
|
39
|
+
|
|
40
|
+
- name: Publish package distributions to PyPI
|
|
41
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
42
|
+
|
|
43
|
+
# Trigger a workflow dispatch in the same repository
|
|
44
|
+
- name: Trigger update-repos workflow
|
|
45
|
+
uses: peter-evans/repository-dispatch@v1
|
|
46
|
+
with:
|
|
47
|
+
event-type: update-repos
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
|
|
2
|
+
name: Update Versions
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
push:
|
|
6
|
+
branches:
|
|
7
|
+
- main
|
|
8
|
+
repository_dispatch:
|
|
9
|
+
types: [update-repos]
|
|
10
|
+
jobs:
|
|
11
|
+
update-repos:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
with:
|
|
16
|
+
token: ${{ secrets.CI_GITHUB_TOKEN }}
|
|
17
|
+
|
|
18
|
+
- name: Install uv and set python
|
|
19
|
+
uses: astral-sh/setup-uv@v4
|
|
20
|
+
with:
|
|
21
|
+
python-version: '3.10'
|
|
22
|
+
enable-cache: true
|
|
23
|
+
cache-dependency-glob: "**/uv.lock"
|
|
24
|
+
|
|
25
|
+
- name: Update all repos
|
|
26
|
+
env:
|
|
27
|
+
GITHUB_TOKEN: ${{ secrets.CI_GITHUB_TOKEN }}
|
|
28
|
+
run: |
|
|
29
|
+
gh auth setup-git
|
|
30
|
+
make -j8 publish-all-repos
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py,cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
#Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# UV
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
#uv.lock
|
|
102
|
+
|
|
103
|
+
# poetry
|
|
104
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
105
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
106
|
+
# commonly ignored for libraries.
|
|
107
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
108
|
+
#poetry.lock
|
|
109
|
+
|
|
110
|
+
# pdm
|
|
111
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
112
|
+
#pdm.lock
|
|
113
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
114
|
+
# in version control.
|
|
115
|
+
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
|
116
|
+
.pdm.toml
|
|
117
|
+
.pdm-python
|
|
118
|
+
.pdm-build/
|
|
119
|
+
|
|
120
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
121
|
+
__pypackages__/
|
|
122
|
+
|
|
123
|
+
# Celery stuff
|
|
124
|
+
celerybeat-schedule
|
|
125
|
+
celerybeat.pid
|
|
126
|
+
|
|
127
|
+
# SageMath parsed files
|
|
128
|
+
*.sage.py
|
|
129
|
+
|
|
130
|
+
# Environments
|
|
131
|
+
.env
|
|
132
|
+
.venv
|
|
133
|
+
env/
|
|
134
|
+
venv/
|
|
135
|
+
ENV/
|
|
136
|
+
env.bak/
|
|
137
|
+
venv.bak/
|
|
138
|
+
|
|
139
|
+
# Spyder project settings
|
|
140
|
+
.spyderproject
|
|
141
|
+
.spyproject
|
|
142
|
+
|
|
143
|
+
# Rope project settings
|
|
144
|
+
.ropeproject
|
|
145
|
+
|
|
146
|
+
# mkdocs documentation
|
|
147
|
+
/site
|
|
148
|
+
|
|
149
|
+
# mypy
|
|
150
|
+
.mypy_cache/
|
|
151
|
+
.dmypy.json
|
|
152
|
+
dmypy.json
|
|
153
|
+
.*cache
|
|
154
|
+
# Pyre type checker
|
|
155
|
+
.pyre/
|
|
156
|
+
|
|
157
|
+
# pytype static type analyzer
|
|
158
|
+
.pytype/
|
|
159
|
+
|
|
160
|
+
# Cython debug symbols
|
|
161
|
+
cython_debug/
|
|
162
|
+
|
|
163
|
+
# PyCharm
|
|
164
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
165
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
166
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
167
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
168
|
+
#.idea/
|
|
169
|
+
|
|
170
|
+
# PyPI configuration file
|
|
171
|
+
.pypirc
|
|
172
|
+
processed_swagger.json
|
|
173
|
+
extra_data.json
|
|
174
|
+
.DS_Store
|
|
175
|
+
.vscode
|
|
176
|
+
junit.xml
|
|
177
|
+
/output
|
|
178
|
+
/tmp
|
cloudcoil-0.3.0/Makefile
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
.PHONY: test
|
|
2
|
+
test:
|
|
3
|
+
uv run --frozen pytest
|
|
4
|
+
|
|
5
|
+
.PHONY: lint
|
|
6
|
+
lint:
|
|
7
|
+
uv run --frozen ruff check cloudcoil tests
|
|
8
|
+
uv run --frozen ruff format --check cloudcoil tests
|
|
9
|
+
uv run --frozen mypy -p cloudcoil
|
|
10
|
+
|
|
11
|
+
.PHONY: fix-lint
|
|
12
|
+
fix-lint:
|
|
13
|
+
uv run --frozen ruff format cloudcoil tests
|
|
14
|
+
uv run --frozen ruff check --fix --unsafe-fixes cloudcoil tests
|
|
15
|
+
|
|
16
|
+
.PHONY: docs-deploy
|
|
17
|
+
docs-deploy:
|
|
18
|
+
rm -rf docs/index.md
|
|
19
|
+
cp README.md docs/index.md
|
|
20
|
+
uv run --frozen mkdocs gh-deploy --force
|
|
21
|
+
|
|
22
|
+
.PHONY: docs-serve
|
|
23
|
+
docs-serve:
|
|
24
|
+
rm -rf docs/index.md
|
|
25
|
+
cp README.md docs/index.md
|
|
26
|
+
uv run --frozen mkdocs serve
|
|
27
|
+
|
|
28
|
+
.PHONY: prepare-for-pr
|
|
29
|
+
prepare-for-pr: fix-lint lint test
|
|
30
|
+
@echo "========"
|
|
31
|
+
@echo "It looks good! :)"
|
|
32
|
+
@echo "Make sure to commit all changes!"
|
|
33
|
+
@echo "========"
|
|
34
|
+
|
|
35
|
+
.PHONY: gen-models
|
|
36
|
+
gen-models:
|
|
37
|
+
rm -rf cloudcoil/apimachinery.py
|
|
38
|
+
uv run --frozen cloudcoil-model-codegen
|
|
39
|
+
$(MAKE) fix-lint
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
REPOS := $(shell ls models | sed 's/\/$$//')
|
|
43
|
+
|
|
44
|
+
gen-all-repos: $(addprefix gen-repo-,$(REPOS))
|
|
45
|
+
|
|
46
|
+
publish-all-repos: $(addprefix publish-repo-,$(REPOS))
|
|
47
|
+
|
|
48
|
+
gen-repo-%:
|
|
49
|
+
rm -rf output/models-$*
|
|
50
|
+
uvx cookiecutter --no-input --output-dir=output --config-file=models/$*/cookiecutter.yaml cookiecutter _config_dir=$$PWD/models/$*
|
|
51
|
+
|
|
52
|
+
# publish-repo-% creates a repo in cloudcoil/models-$* if it doesn't exist, and pushes the generated code to it
|
|
53
|
+
# It should not force push to the repo and instead change all the existing files in the repo to match the generated code
|
|
54
|
+
# Check if the repo exists using gh
|
|
55
|
+
# If it doesn't exist, create it
|
|
56
|
+
# If it does exist, change all the existing files in the repo to match the generated code
|
|
57
|
+
# Push the generated code to the repo
|
|
58
|
+
publish-repo-%: gen-repo-%
|
|
59
|
+
@echo "Publishing to cloudcoil/models-$*"
|
|
60
|
+
@if ! gh repo view cloudcoil/models-$* >/dev/null 2>&1; then \
|
|
61
|
+
gh repo create cloudcoil/models-$* --public --description "Generated model repository for $*"; \
|
|
62
|
+
fi
|
|
63
|
+
@rm -rf tmp/models-$*
|
|
64
|
+
@mkdir -p tmp/models-$*
|
|
65
|
+
@cd tmp/models-$* && \
|
|
66
|
+
git clone https://github.com/cloudcoil/models-$*.git . || git init && \
|
|
67
|
+
git remote add origin https://github.com/cloudcoil/models-$*.git || true && \
|
|
68
|
+
git rm -rf . && \
|
|
69
|
+
git config user.name "github-actions[bot]" && \
|
|
70
|
+
git config user.email "github-actions[bot]@users.noreply.github.com" && \
|
|
71
|
+
cp -a ../../output/models-$*/. . && \
|
|
72
|
+
git add -A && \
|
|
73
|
+
git diff --cached --quiet || git commit -m "Update generated code" && \
|
|
74
|
+
git push -u origin HEAD:main
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cloudcoil
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Cloud native made easy with Python
|
|
5
5
|
Project-URL: Homepage, https://github.com/cloudcoil/cloudcoil
|
|
6
6
|
Project-URL: Documentation, https://cloudcoil.github.io/cloudcoil
|
|
@@ -53,7 +53,7 @@ Description-Content-Type: text/markdown
|
|
|
53
53
|
|
|
54
54
|
## ✨ Features
|
|
55
55
|
|
|
56
|
-
- 🔥 **Elegant, Pythonic API** - Feels natural to Python developers
|
|
56
|
+
- 🔥 **Elegant, Pythonic API** - Feels natural to Python developers including fluent and context manager style resource builders
|
|
57
57
|
- ⚡ **Async First** - Native async/await support for high performance
|
|
58
58
|
- 🛡️ **Type Safe** - Full mypy support and runtime validation
|
|
59
59
|
- 🧪 **Testing Ready** - Built-in pytest fixtures for K8s integration tests
|
|
@@ -114,6 +114,246 @@ for pod in k8s.core.v1.Pod.list(namespace="default"):
|
|
|
114
114
|
async for pod in await k8s.core.v1.Pod.async_list():
|
|
115
115
|
print(f"Found pod: {pod.metadata.name}")
|
|
116
116
|
```
|
|
117
|
+
### Building resources
|
|
118
|
+
|
|
119
|
+
#### Using Models
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
from cloudcoil import apimachinery
|
|
123
|
+
import cloudcoil.models.kubernetes.core.v1 as k8score
|
|
124
|
+
import cloudcoil.models.kubernetes.apps.v1 as k8sapps
|
|
125
|
+
|
|
126
|
+
# Create a Deployment
|
|
127
|
+
deployment = k8sapps.Deployment(
|
|
128
|
+
metadata=apimachinery.ObjectMeta(name="nginx"),
|
|
129
|
+
spec=k8sapps.DeploymentSpec(
|
|
130
|
+
replicas=3,
|
|
131
|
+
selector=apimachinery.LabelSelector(
|
|
132
|
+
match_labels={"app": "nginx"}
|
|
133
|
+
),
|
|
134
|
+
template=k8score.PodTemplateSpec(
|
|
135
|
+
metadata=apimachinery.ObjectMeta(
|
|
136
|
+
labels={"app": "nginx"}
|
|
137
|
+
),
|
|
138
|
+
spec=k8score.PodSpec(
|
|
139
|
+
containers=[
|
|
140
|
+
k8score.Container(
|
|
141
|
+
name="nginx",
|
|
142
|
+
image="nginx:latest",
|
|
143
|
+
ports=[k8score.ContainerPort(container_port=80)]
|
|
144
|
+
)
|
|
145
|
+
]
|
|
146
|
+
)
|
|
147
|
+
)
|
|
148
|
+
)
|
|
149
|
+
).create()
|
|
150
|
+
|
|
151
|
+
# Create a Service
|
|
152
|
+
service = k8score.Service(
|
|
153
|
+
metadata=apimachinery.ObjectMeta(name="nginx"),
|
|
154
|
+
spec=k8score.ServiceSpec(
|
|
155
|
+
selector={"app": "nginx"},
|
|
156
|
+
ports=[k8score.ServicePort(port=80, target_port=80)]
|
|
157
|
+
)
|
|
158
|
+
).create()
|
|
159
|
+
|
|
160
|
+
# List Deployments
|
|
161
|
+
for deploy in k8sapps.Deployment.list():
|
|
162
|
+
print(f"Found deployment: {deploy.metadata.name}")
|
|
163
|
+
|
|
164
|
+
# Update a Deployment
|
|
165
|
+
deployment.spec.replicas = 5
|
|
166
|
+
deployment.save()
|
|
167
|
+
|
|
168
|
+
# Delete resources
|
|
169
|
+
k8score.Service.delete("nginx")
|
|
170
|
+
k8sapps.Deployment.delete("nginx")
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
#### Using the Fluent Builder API
|
|
174
|
+
|
|
175
|
+
Cloudcoil provides a powerful fluent builder API for Kubernetes resources with full IDE support and rich autocomplete capabilities:
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
from cloudcoil.models.kubernetes.apps.v1 import Deployment
|
|
179
|
+
from cloudcoil.models.kubernetes.core.v1 import Service
|
|
180
|
+
|
|
181
|
+
# Create a Deployment using the fluent builder
|
|
182
|
+
# The fluent style is great for one-liners and simple configurations
|
|
183
|
+
nginx_deployment = (
|
|
184
|
+
Deployment.builder()
|
|
185
|
+
# Metadata can be configured in a single chain for simple objects
|
|
186
|
+
.metadata(lambda metadata: metadata
|
|
187
|
+
.name("nginx")
|
|
188
|
+
.namespace("default")
|
|
189
|
+
)
|
|
190
|
+
# Complex nested structures can be built using nested lambda functions
|
|
191
|
+
.spec(lambda deployment_spec: deployment_spec
|
|
192
|
+
.replicas(3)
|
|
193
|
+
# Each level of nesting gets its own lambda for clarity
|
|
194
|
+
.selector(lambda label_selector: label_selector
|
|
195
|
+
.match_labels({"app": "nginx"})
|
|
196
|
+
)
|
|
197
|
+
.template(lambda pod_template: pod_template
|
|
198
|
+
.metadata(lambda pod_metadata: pod_metadata
|
|
199
|
+
.labels({"app": "nginx"})
|
|
200
|
+
)
|
|
201
|
+
.spec(lambda pod_spec: pod_spec
|
|
202
|
+
# Lists can be built using array literals with lambda items
|
|
203
|
+
.containers([
|
|
204
|
+
lambda container: container
|
|
205
|
+
.name("nginx")
|
|
206
|
+
.image("nginx:latest")
|
|
207
|
+
# Nested collections can use the add() helper
|
|
208
|
+
.ports(lambda port_list: port_list.add(
|
|
209
|
+
lambda port: port.container_port(80)
|
|
210
|
+
))
|
|
211
|
+
])
|
|
212
|
+
)
|
|
213
|
+
)
|
|
214
|
+
)
|
|
215
|
+
.build()
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
# Create a Service using the builder
|
|
219
|
+
service = (
|
|
220
|
+
Service.builder()
|
|
221
|
+
.metadata(lambda m: m
|
|
222
|
+
.name("nginx")
|
|
223
|
+
.namespace("default")
|
|
224
|
+
)
|
|
225
|
+
.spec(lambda s: s
|
|
226
|
+
.selector({"app": "nginx"})
|
|
227
|
+
.ports(lambda ports: ports.add(lambda p: p.container_port(80)))
|
|
228
|
+
)
|
|
229
|
+
.build()
|
|
230
|
+
)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
The fluent builder provides:
|
|
234
|
+
- ✨ Full IDE support with detailed type information
|
|
235
|
+
- 🔍 Rich autocomplete for all fields and nested objects
|
|
236
|
+
- ⚡ Compile-time validation of your configuration
|
|
237
|
+
- 🎯 Clear and chainable API that guides you through resource creation
|
|
238
|
+
|
|
239
|
+
#### Using the Context Manager Builder API
|
|
240
|
+
|
|
241
|
+
For complex nested resources, Cloudcoil also provides a context manager-based builder pattern that can make the structure more clear:
|
|
242
|
+
|
|
243
|
+
```python
|
|
244
|
+
from cloudcoil.models.kubernetes.apps.v1 import Deployment
|
|
245
|
+
from cloudcoil.models.kubernetes.core.v1 import Service
|
|
246
|
+
|
|
247
|
+
# Create a deployment using context managers
|
|
248
|
+
# Context managers are ideal for deeply nested structures
|
|
249
|
+
with Deployment.new() as nginx_deployment:
|
|
250
|
+
# Each context creates a clear visual scope
|
|
251
|
+
with nginx_deployment.metadata() as deployment_metadata:
|
|
252
|
+
deployment_metadata.name("nginx")
|
|
253
|
+
deployment_metadata.namespace("default")
|
|
254
|
+
|
|
255
|
+
with nginx_deployment.spec() as deployment_spec:
|
|
256
|
+
# Simple fields can be set directly
|
|
257
|
+
deployment_spec.replicas(3)
|
|
258
|
+
|
|
259
|
+
# Each nested object gets its own context
|
|
260
|
+
with deployment_spec.selector() as label_selector:
|
|
261
|
+
label_selector.match_labels({"app": "nginx"})
|
|
262
|
+
|
|
263
|
+
with deployment_spec.template() as pod_template:
|
|
264
|
+
with pod_template.metadata() as pod_metadata:
|
|
265
|
+
pod_metadata.labels({"app": "nginx"})
|
|
266
|
+
|
|
267
|
+
with pod_template.spec() as pod_spec:
|
|
268
|
+
# Collections use a parent context for the list
|
|
269
|
+
with pod_spec.containers() as container_list:
|
|
270
|
+
# And child contexts for each item
|
|
271
|
+
with container_list.add() as nginx_container:
|
|
272
|
+
nginx_container.name("nginx")
|
|
273
|
+
nginx_container.image("nginx:latest")
|
|
274
|
+
# Ports can be added one by one
|
|
275
|
+
with nginx_container.add_port() as container_port:
|
|
276
|
+
container_port.container_port(80)
|
|
277
|
+
|
|
278
|
+
final_deployment = nginx_deployment.build()
|
|
279
|
+
|
|
280
|
+
# Create a service using context managers
|
|
281
|
+
with Service.new() as nginx_service:
|
|
282
|
+
# Context managers make the structure very clear
|
|
283
|
+
with nginx_service.metadata() as service_metadata:
|
|
284
|
+
service_metadata.name("nginx")
|
|
285
|
+
service_metadata.namespace("default")
|
|
286
|
+
|
|
287
|
+
with nginx_service.spec() as service_spec:
|
|
288
|
+
# Simple fields can still be set directly
|
|
289
|
+
service_spec.selector({"app": "nginx"})
|
|
290
|
+
# Port configuration is more readable with contexts
|
|
291
|
+
with service_spec.add_port() as service_port:
|
|
292
|
+
service_port.port(80)
|
|
293
|
+
service_port.target_port(80)
|
|
294
|
+
|
|
295
|
+
final_service = nginx_service.build()
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
The context manager builder provides:
|
|
299
|
+
- 🎭 Clear visual nesting of resource structure
|
|
300
|
+
- 🔒 Automatic resource cleanup
|
|
301
|
+
- 🎯 Familiar Python context manager pattern
|
|
302
|
+
- ✨ Same great IDE support as the fluent builder
|
|
303
|
+
|
|
304
|
+
#### Mixing Builder Styles
|
|
305
|
+
|
|
306
|
+
CloudCoil's intelligent builder system automatically detects which style you're using and provides appropriate IDE support:
|
|
307
|
+
|
|
308
|
+
```python
|
|
309
|
+
from cloudcoil.models.kubernetes.apps.v1 import Deployment
|
|
310
|
+
from cloudcoil import apimachinery
|
|
311
|
+
|
|
312
|
+
# Mixing styles lets you choose the best approach for each part
|
|
313
|
+
# The IDE automatically adapts to your chosen style at each level
|
|
314
|
+
with Deployment.new() as nginx_deployment:
|
|
315
|
+
# Direct object initialization with full type checking
|
|
316
|
+
nginx_deployment.metadata(apimachinery.ObjectMeta(
|
|
317
|
+
name="nginx",
|
|
318
|
+
namespace="default",
|
|
319
|
+
labels={"app": "nginx"}
|
|
320
|
+
))
|
|
321
|
+
|
|
322
|
+
with nginx_deployment.spec() as deployment_spec:
|
|
323
|
+
# IDE shows all available fields with types
|
|
324
|
+
deployment_spec.replicas(3)
|
|
325
|
+
# Fluent style with rich autocomplete
|
|
326
|
+
deployment_spec.selector(lambda sel: sel.match_labels({"app": "nginx"}))
|
|
327
|
+
|
|
328
|
+
# Context manager style with full type hints
|
|
329
|
+
with deployment_spec.template() as pod_template:
|
|
330
|
+
# Mix and match freely - IDE adjusts automatically
|
|
331
|
+
pod_template.metadata(apimachinery.ObjectMeta(labels={"app": "nginx"}))
|
|
332
|
+
with pod_template.spec() as pod_spec:
|
|
333
|
+
with pod_spec.containers() as container_list:
|
|
334
|
+
with container_list.add() as nginx_container:
|
|
335
|
+
# Complete IDE support regardless of style
|
|
336
|
+
nginx_container.name("nginx")
|
|
337
|
+
nginx_container.image("nginx:latest")
|
|
338
|
+
# Switch styles any time
|
|
339
|
+
nginx_container.ports(lambda ports: ports
|
|
340
|
+
.add(lambda p: p.container_port(80))
|
|
341
|
+
.add(lambda p: p.container_port(443))
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
final_deployment = nginx_deployment.build()
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
This flexibility allows you to:
|
|
348
|
+
- 🔀 Choose the most appropriate style for each part of your configuration
|
|
349
|
+
- 📖 Maximize readability for both simple and complex structures
|
|
350
|
+
- 🎨 Format your code according to your team's preferences
|
|
351
|
+
- 🧠 Get full IDE support with automatic style detection
|
|
352
|
+
- ✨ Enjoy rich autocomplete in all styles
|
|
353
|
+
- ⚡ Benefit from type checking across mixed styles
|
|
354
|
+
- 🎯 Receive immediate feedback on type errors
|
|
355
|
+
- 🔍 See documentation for all fields regardless of style
|
|
356
|
+
|
|
117
357
|
|
|
118
358
|
### Creating Resources
|
|
119
359
|
|
|
@@ -388,7 +628,7 @@ Cloudcoil supports generating typed models from CustomResourceDefinitions (CRDs)
|
|
|
388
628
|
|
|
389
629
|
### Using the Cookiecutter Template
|
|
390
630
|
|
|
391
|
-
The fastest way to get started is using our cookiecutter template: [cloudcoil-models-cookiecutter](https://github.com/cloudcoil/cloudcoil
|
|
631
|
+
The fastest way to get started is using our cookiecutter template: [cloudcoil-models-cookiecutter](https://github.com/cloudcoil/cloudcoil/tree/main/cookiecutter)
|
|
392
632
|
|
|
393
633
|
### Codegen Config
|
|
394
634
|
|