From 277ecbd472894f188d89c84ec84b3d9844fe9bf6 Mon Sep 17 00:00:00 2001 From: Javier de la Puente Date: Thu, 8 Aug 2024 14:47:52 +0200 Subject: [PATCH 01/11] go-framework init and extension --- charmcraft/application/commands/init.py | 1 + charmcraft/extensions/__init__.py | 3 +- .../{gunicorn.py => twelvefactor.py} | 105 +++++++++++++----- .../templates/init-go-framework/.gitignore.j2 | 9 ++ .../init-go-framework/charmcraft.yaml.j2 | 53 +++++++++ .../init-go-framework/requirements.txt.j2 | 1 + .../init-go-framework/src/charm.py.j2 | 30 +++++ ...{test_gunicorn.py => test_twelvefactor.py} | 71 +++++++++++- 8 files changed, 242 insertions(+), 31 deletions(-) rename charmcraft/extensions/{gunicorn.py => twelvefactor.py} (80%) create mode 100644 charmcraft/templates/init-go-framework/.gitignore.j2 create mode 100644 charmcraft/templates/init-go-framework/charmcraft.yaml.j2 create mode 100644 charmcraft/templates/init-go-framework/requirements.txt.j2 create mode 100755 charmcraft/templates/init-go-framework/src/charm.py.j2 rename tests/extensions/{test_gunicorn.py => test_twelvefactor.py} (79%) diff --git a/charmcraft/application/commands/init.py b/charmcraft/application/commands/init.py index 101938309..35345041d 100644 --- a/charmcraft/application/commands/init.py +++ b/charmcraft/application/commands/init.py @@ -38,6 +38,7 @@ "machine": "init-machine", "flask-framework": "init-flask-framework", "django-framework": "init-django-framework", + "go-framework": "init-go-framework", } DEFAULT_PROFILE = "simple" diff --git a/charmcraft/extensions/__init__.py b/charmcraft/extensions/__init__.py index a9f252346..ad1cf1fd9 100644 --- a/charmcraft/extensions/__init__.py +++ b/charmcraft/extensions/__init__.py @@ -18,7 +18,7 @@ from charmcraft.extensions._utils import apply_extensions from charmcraft.extensions.extension import Extension -from charmcraft.extensions.gunicorn import DjangoFramework, FlaskFramework +from charmcraft.extensions.twelvefactor import DjangoFramework, FlaskFramework, GoFramework from charmcraft.extensions.registry import ( get_extension_class, get_extension_names, @@ -41,3 +41,4 @@ register("flask-framework", FlaskFramework) register("django-framework", DjangoFramework) +register("go-framework", GoFramework) diff --git a/charmcraft/extensions/gunicorn.py b/charmcraft/extensions/twelvefactor.py similarity index 80% rename from charmcraft/extensions/gunicorn.py rename to charmcraft/extensions/twelvefactor.py index a2a76f773..6be828c34 100644 --- a/charmcraft/extensions/gunicorn.py +++ b/charmcraft/extensions/twelvefactor.py @@ -24,27 +24,8 @@ from .extension import Extension -class _GunicornBase(Extension): - """A base class for 12-factor WSGI applications.""" - - _WEBSERVER_OPTIONS = { - "webserver-keepalive": { - "type": "int", - "description": "Time in seconds for webserver to wait for requests on a Keep-Alive connection.", - }, - "webserver-threads": { - "type": "int", - "description": "Run each webserver worker with the specified number of threads.", - }, - "webserver-timeout": { - "type": "int", - "description": "Time in seconds to kill and restart silent webserver workers.", - }, - "webserver-workers": { - "type": "int", - "description": "The number of webserver worker processes for handling requests.", - }, - } +class _TwelveFactorBase(Extension): + """A base class for 12-factor applications.""" _CHARM_LIBS = [ {"lib": "traefik_k8s.ingress", "version": "2"}, @@ -138,10 +119,10 @@ def _get_root_snippet(self) -> dict[str, Any]: return { "assumes": ["k8s-api"], "containers": { - f"{self.framework}-app": {"resource": f"{self.framework}-app-image"}, + self.get_container_name(): {"resource": self.get_image_name()}, }, "resources": { - f"{self.framework}-app-image": { + self.get_image_name(): { "type": "oci-image", "description": f"{self.framework} application image.", }, @@ -157,7 +138,7 @@ def _get_root_snippet(self) -> dict[str, Any]: "metrics-endpoint": {"interface": "prometheus_scrape"}, "grafana-dashboard": {"interface": "grafana_dashboard"}, }, - "config": {"options": {**self._WEBSERVER_OPTIONS, **self.options}}, + "config": {"options": self.options}, "parts": { "charm": { "plugin": "charm", @@ -184,8 +165,36 @@ def get_parts_snippet(self) -> dict[str, Any]: """Return the parts to add to parts.""" return {} + def get_container_name(self) -> str: + """Return name of the container for the app image.""" + return f"{self.framework}-app" + + def get_image_name(self) -> str: + """Return name of the app image.""" + return f"{self.framework}-app-image" + + +GUNICORN_WEBSERVER_OPTIONS = { + "webserver-keepalive": { + "type": "int", + "description": "Time in seconds for webserver to wait for requests on a Keep-Alive connection.", + }, + "webserver-threads": { + "type": "int", + "description": "Run each webserver worker with the specified number of threads.", + }, + "webserver-timeout": { + "type": "int", + "description": "Time in seconds to kill and restart silent webserver workers.", + }, + "webserver-workers": { + "type": "int", + "description": "The number of webserver worker processes for handling requests.", + }, +} + -class FlaskFramework(_GunicornBase): +class FlaskFramework(_TwelveFactorBase): """Extension for 12-factor Flask applications.""" framework = "flask" @@ -195,6 +204,7 @@ class FlaskFramework(_GunicornBase): } } options = { + **GUNICORN_WEBSERVER_OPTIONS, "flask-application-root": { "type": "string", "description": "Path in which the application / web server is mounted. This configuration will set the FLASK_APPLICATION_ROOT environment variable. Run `app.config.from_prefixed_env()` in your Flask application in order to receive this configuration.", @@ -233,7 +243,7 @@ def is_experimental(base: tuple[str, ...] | None) -> bool: # noqa: ARG004 return False -class DjangoFramework(_GunicornBase): +class DjangoFramework(_TwelveFactorBase): """Extension for 12-factor Django applications.""" framework = "django" @@ -248,6 +258,7 @@ class DjangoFramework(_GunicornBase): }, } options = { + **GUNICORN_WEBSERVER_OPTIONS, "django-debug": { "type": "boolean", "default": False, @@ -262,3 +273,45 @@ class DjangoFramework(_GunicornBase): "description": "A comma-separated list of host/domain names that this Django site can serve. This configuration will set the DJANGO_ALLOWED_HOSTS environment variable with its content being a JSON encoded list.", }, } + + +class GoFramework(_TwelveFactorBase): + """Extension for 12-factor Go applications.""" + + framework = "go" + actions = { + "rotate-secret-key": { + "description": "Rotate the go secret key. Users will be forced to log in again. This might be useful if a security breach occurs." + } + } + options = { + "port": { + "type": "int", + "default": 8080, + "description": "Default port where the application will listen on.", + }, + "metrics-port": { + "type": "int", + "default": 8080, + "description": "Port where the prometheus metrics will be scraped.", + }, + "metrics-path": { + "type": "string", + "default": "/metrics", + "description": "Path where the prometheus metrics will be scraped.", + }, + "secret-key": { + "type": "string", + "description": "Long secret you can use for sessions, csrf or any other thing where you need a random secret shared by all units", + }, + } + + @override + def get_image_name(self) -> str: + """Return name of the app image.""" + return "app-image" + + @override + def get_container_name(self) -> str: + """Return name of the container for the app image.""" + return "app" diff --git a/charmcraft/templates/init-go-framework/.gitignore.j2 b/charmcraft/templates/init-go-framework/.gitignore.j2 new file mode 100644 index 000000000..a26d707f9 --- /dev/null +++ b/charmcraft/templates/init-go-framework/.gitignore.j2 @@ -0,0 +1,9 @@ +venv/ +build/ +*.charm +.tox/ +.coverage +__pycache__/ +*.py[cod] +.idea +.vscode/ diff --git a/charmcraft/templates/init-go-framework/charmcraft.yaml.j2 b/charmcraft/templates/init-go-framework/charmcraft.yaml.j2 new file mode 100644 index 000000000..8e9373bdb --- /dev/null +++ b/charmcraft/templates/init-go-framework/charmcraft.yaml.j2 @@ -0,0 +1,53 @@ +# This file configures Charmcraft. +# See https://juju.is/docs/sdk/charmcraft-config for guidance. + +name: {{ name }} + +type: charm + +bases: + - build-on: + - name: ubuntu + channel: "22.04" + run-on: + - name: ubuntu + channel: "22.04" + +# (Required) +summary: A very short one-line summary of the Go application. + +# (Required) +description: | + A comprehensive overview of your Go application. + +extensions: + - go-framework + +# Uncomment the integrations used by your application +# Integrations set to "optional: false" will block the charm +# until the applications are integrated. +# requires: +# mysql: +# interface: mysql_client +# optional: false +# limit: 1 +# postgresql: +# interface: postgresql_client +# optional: false +# limit: 1 +# mongodb: +# interface: mongodb_client +# optional: false +# limit: 1 +# redis: +# interface: redis +# optional: false +# limit: 1 +# s3: +# interface: s3 +# optional: false +# limit: 1 +# saml: +# interface: saml +# optional: false +# limit: 1 diff --git a/charmcraft/templates/init-go-framework/requirements.txt.j2 b/charmcraft/templates/init-go-framework/requirements.txt.j2 new file mode 100644 index 000000000..acab50eb1 --- /dev/null +++ b/charmcraft/templates/init-go-framework/requirements.txt.j2 @@ -0,0 +1 @@ +paas-app-charmer==1.* diff --git a/charmcraft/templates/init-go-framework/src/charm.py.j2 b/charmcraft/templates/init-go-framework/src/charm.py.j2 new file mode 100755 index 000000000..825c204c7 --- /dev/null +++ b/charmcraft/templates/init-go-framework/src/charm.py.j2 @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 +# Copyright {{ year }} {{ author }} +# See LICENSE file for licensing details. + +"""Go Charm entrypoint.""" + +import logging +import typing + +import ops + +import paas_app_charmer.go + +logger = logging.getLogger(__name__) + + +class GoCharm(paas_app_charmer.go.Charm): + """Go Charm service.""" + + def __init__(self, *args: typing.Any) -> None: + """Initialize the instance. + + Args: + args: passthrough to CharmBase. + """ + super().__init__(*args) + + +if __name__ == "__main__": + ops.main.main(GoCharm) diff --git a/tests/extensions/test_gunicorn.py b/tests/extensions/test_twelvefactor.py similarity index 79% rename from tests/extensions/test_gunicorn.py rename to tests/extensions/test_twelvefactor.py index 54fcf638a..b85eb7644 100644 --- a/tests/extensions/test_gunicorn.py +++ b/tests/extensions/test_twelvefactor.py @@ -17,7 +17,11 @@ from charmcraft.errors import ExtensionError from charmcraft.extensions import apply_extensions -from charmcraft.extensions.gunicorn import DjangoFramework, FlaskFramework +from charmcraft.extensions.twelvefactor import ( + DjangoFramework, + FlaskFramework, + GoFramework, +) def make_flask_input_yaml(): @@ -63,7 +67,7 @@ def flask_input_yaml_fixture(): {"lib": "saml_integrator.saml", "version": "0"}, ], "config": { - "options": {**FlaskFramework.options, **FlaskFramework._WEBSERVER_OPTIONS} + "options": {**FlaskFramework.options}, }, "parts": { "charm": { @@ -123,7 +127,7 @@ def flask_input_yaml_fixture(): {"lib": "saml_integrator.saml", "version": "0"}, ], "config": { - "options": {**DjangoFramework.options, **DjangoFramework._WEBSERVER_OPTIONS} + "options": {**DjangoFramework.options}, }, "parts": { "charm": { @@ -152,6 +156,66 @@ def flask_input_yaml_fixture(): "type": "charm", }, ), + ( + { + "type": "charm", + "name": "test-go", + "summary": "test summary", + "description": "test description", + "bases": [{"name": "ubuntu", "channel": "22.04"}], + "extensions": ["go-framework"], + }, + True, + { + "actions": GoFramework.actions, + "assumes": ["k8s-api"], + "bases": [{"channel": "22.04", "name": "ubuntu"}], + "containers": { + "app": {"resource": "app-image"}, + }, + "description": "test description", + "name": "test-go", + "charm-libs": [ + {"lib": "traefik_k8s.ingress", "version": "2"}, + {"lib": "observability_libs.juju_topology", "version": "0"}, + {"lib": "grafana_k8s.grafana_dashboard", "version": "0"}, + {"lib": "loki_k8s.loki_push_api", "version": "0"}, + {"lib": "data_platform_libs.data_interfaces", "version": "0"}, + {"lib": "prometheus_k8s.prometheus_scrape", "version": "0"}, + {"lib": "redis_k8s.redis", "version": "0"}, + {"lib": "data_platform_libs.s3", "version": "0"}, + {"lib": "saml_integrator.saml", "version": "0"}, + ], + "config": { + "options": {**GoFramework.options}, + }, + "parts": { + "charm": { + "plugin": "charm", + "source": ".", + "build-snaps": ["rustup"], + "override-build": "rustup default stable\ncraftctl default", + } + }, + "peers": {"secret-storage": {"interface": "secret-storage"}}, + "provides": { + "metrics-endpoint": {"interface": "prometheus_scrape"}, + "grafana-dashboard": {"interface": "grafana_dashboard"}, + }, + "requires": { + "logging": {"interface": "loki_push_api"}, + "ingress": {"interface": "ingress", "limit": 1}, + }, + "resources": { + "app-image": { + "description": "go application image.", + "type": "oci-image", + }, + }, + "summary": "test summary", + "type": "charm", + }, + ), ], ) def test_apply_extensions_correct(monkeypatch, experimental, tmp_path, input_yaml, expected): @@ -184,7 +248,6 @@ def test_flask_merge_options(flask_input_yaml, tmp_path): assert applied["config"] == { "options": { **FlaskFramework.options, - **FlaskFramework._WEBSERVER_OPTIONS, **added_options, } } From b8d3b5e001e5b8248e1679a9bc6802d50ba28502 Mon Sep 17 00:00:00 2001 From: Javier de la Puente Date: Tue, 13 Aug 2024 14:24:32 +0200 Subject: [PATCH 02/11] refactor twelvefactor extension to have rotate action in the base class --- charmcraft/extensions/twelvefactor.py | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/charmcraft/extensions/twelvefactor.py b/charmcraft/extensions/twelvefactor.py index 6be828c34..24b9447ab 100644 --- a/charmcraft/extensions/twelvefactor.py +++ b/charmcraft/extensions/twelvefactor.py @@ -52,7 +52,12 @@ def is_experimental(base: tuple[str, ...] | None) -> bool: # noqa: ARG004 return True framework: str - actions: dict + actions: dict = { + "rotate-secret-key": { + "description": "Rotate the secret key. Users will be forced to log in again. This might be useful if a security breach occurs." + } + } + options: dict def _get_nested(self, obj: dict, path: str) -> dict: @@ -198,11 +203,6 @@ class FlaskFramework(_TwelveFactorBase): """Extension for 12-factor Flask applications.""" framework = "flask" - actions = { - "rotate-secret-key": { - "description": "Rotate the flask secret key. Users will be forced to log in again. This might be useful if a security breach occurs." - } - } options = { **GUNICORN_WEBSERVER_OPTIONS, "flask-application-root": { @@ -248,9 +248,7 @@ class DjangoFramework(_TwelveFactorBase): framework = "django" actions = { - "rotate-secret-key": { - "description": "Rotate the django secret key. Users will be forced to log in again. This might be useful if a security breach occurs." - }, + **_TwelveFactorBase.actions, "create-superuser": { "description": "Create a new Django superuser account.", "params": {"username": {"type": "string"}, "email": {"type": "string"}}, @@ -279,11 +277,6 @@ class GoFramework(_TwelveFactorBase): """Extension for 12-factor Go applications.""" framework = "go" - actions = { - "rotate-secret-key": { - "description": "Rotate the go secret key. Users will be forced to log in again. This might be useful if a security breach occurs." - } - } options = { "port": { "type": "int", From d6122b8672ad23dbc7836313785d7a5cea38da2e Mon Sep 17 00:00:00 2001 From: Javier de la Puente Date: Wed, 14 Aug 2024 12:09:26 +0200 Subject: [PATCH 03/11] Upgrade go extension to 24.04 --- .../init-go-framework/charmcraft.yaml.j2 | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/charmcraft/templates/init-go-framework/charmcraft.yaml.j2 b/charmcraft/templates/init-go-framework/charmcraft.yaml.j2 index 8e9373bdb..b37d6631d 100644 --- a/charmcraft/templates/init-go-framework/charmcraft.yaml.j2 +++ b/charmcraft/templates/init-go-framework/charmcraft.yaml.j2 @@ -5,13 +5,15 @@ name: {{ name }} type: charm -bases: - - build-on: - - name: ubuntu - channel: "22.04" - run-on: - - name: ubuntu - channel: "22.04" +base: ubuntu@24.04 + +platforms: + amd64: + arm64: + armhf: + ppc64el: + riscv64: + s390x: # (Required) summary: A very short one-line summary of the Go application. From 5cf05dece1127d5fdf77c362c4d915c8e6f10a57 Mon Sep 17 00:00:00 2001 From: Javier de la Puente Date: Wed, 14 Aug 2024 12:20:37 +0200 Subject: [PATCH 04/11] Add test go base 24.04 --- tests/extensions/test_twelvefactor.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/tests/extensions/test_twelvefactor.py b/tests/extensions/test_twelvefactor.py index b85eb7644..e2976b93d 100644 --- a/tests/extensions/test_twelvefactor.py +++ b/tests/extensions/test_twelvefactor.py @@ -102,14 +102,30 @@ def flask_input_yaml_fixture(): "name": "test-django", "summary": "test summary", "description": "test description", - "bases": [{"name": "ubuntu", "channel": "22.04"}], + "base": "ubuntu@22.04", + "platforms": { + "amd64": None, + "arm64": None, + "armhf": None, + "ppc64el": None, + "riscv64": None, + "s390x": None, + }, "extensions": ["django-framework"], }, True, { "actions": DjangoFramework.actions, "assumes": ["k8s-api"], - "bases": [{"channel": "22.04", "name": "ubuntu"}], + "base": "ubuntu@22.04", + "platforms": { + "amd64": None, + "arm64": None, + "armhf": None, + "ppc64el": None, + "riscv64": None, + "s390x": None, + }, "containers": { "django-app": {"resource": "django-app-image"}, }, From 58ca56598c470f27ea7395363da8cb6b4a594ff6 Mon Sep 17 00:00:00 2001 From: Javier de la Puente Date: Mon, 19 Aug 2024 11:06:27 +0200 Subject: [PATCH 05/11] Remove armhf and riscv64 platforms from go init profile --- charmcraft/templates/init-go-framework/charmcraft.yaml.j2 | 2 -- 1 file changed, 2 deletions(-) diff --git a/charmcraft/templates/init-go-framework/charmcraft.yaml.j2 b/charmcraft/templates/init-go-framework/charmcraft.yaml.j2 index b37d6631d..f45e8104d 100644 --- a/charmcraft/templates/init-go-framework/charmcraft.yaml.j2 +++ b/charmcraft/templates/init-go-framework/charmcraft.yaml.j2 @@ -10,9 +10,7 @@ base: ubuntu@24.04 platforms: amd64: arm64: - armhf: ppc64el: - riscv64: s390x: # (Required) From 1dbb68f1a3d9ab35cf87c292b1d1b945b9b760b7 Mon Sep 17 00:00:00 2001 From: Javier de la Puente Date: Mon, 19 Aug 2024 11:36:24 +0200 Subject: [PATCH 06/11] update twelfactor init profiles to use {{ class_name }} --- charmcraft/templates/init-django-framework/src/charm.py.j2 | 4 ++-- charmcraft/templates/init-flask-framework/src/charm.py.j2 | 4 ++-- charmcraft/templates/init-go-framework/src/charm.py.j2 | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/charmcraft/templates/init-django-framework/src/charm.py.j2 b/charmcraft/templates/init-django-framework/src/charm.py.j2 index 96582e0f2..d31095a16 100755 --- a/charmcraft/templates/init-django-framework/src/charm.py.j2 +++ b/charmcraft/templates/init-django-framework/src/charm.py.j2 @@ -14,7 +14,7 @@ import paas_app_charmer.django logger = logging.getLogger(__name__) -class DjangoCharm(paas_app_charmer.django.Charm): +class {{ class_name }}(paas_app_charmer.django.Charm): """Django Charm service.""" def __init__(self, *args: typing.Any) -> None: @@ -27,4 +27,4 @@ class DjangoCharm(paas_app_charmer.django.Charm): if __name__ == "__main__": - ops.main.main(DjangoCharm) + ops.main.main({{ class_name }}) diff --git a/charmcraft/templates/init-flask-framework/src/charm.py.j2 b/charmcraft/templates/init-flask-framework/src/charm.py.j2 index 81fedfff2..b75c440a3 100755 --- a/charmcraft/templates/init-flask-framework/src/charm.py.j2 +++ b/charmcraft/templates/init-flask-framework/src/charm.py.j2 @@ -14,7 +14,7 @@ import paas_app_charmer.flask logger = logging.getLogger(__name__) -class FlaskCharm(paas_app_charmer.flask.Charm): +class {{ class_name }}(paas_app_charmer.flask.Charm): """Flask Charm service.""" def __init__(self, *args: typing.Any) -> None: @@ -27,4 +27,4 @@ class FlaskCharm(paas_app_charmer.flask.Charm): if __name__ == "__main__": - ops.main.main(FlaskCharm) + ops.main.main({{ class_name }}) diff --git a/charmcraft/templates/init-go-framework/src/charm.py.j2 b/charmcraft/templates/init-go-framework/src/charm.py.j2 index 825c204c7..de6162513 100755 --- a/charmcraft/templates/init-go-framework/src/charm.py.j2 +++ b/charmcraft/templates/init-go-framework/src/charm.py.j2 @@ -14,7 +14,7 @@ import paas_app_charmer.go logger = logging.getLogger(__name__) -class GoCharm(paas_app_charmer.go.Charm): +class {{ class_name }}(paas_app_charmer.go.Charm): """Go Charm service.""" def __init__(self, *args: typing.Any) -> None: @@ -27,4 +27,4 @@ class GoCharm(paas_app_charmer.go.Charm): if __name__ == "__main__": - ops.main.main(GoCharm) + ops.main.main({{ class_name }}) From 4e263b7afa813b176e8db7181cb229f950503173 Mon Sep 17 00:00:00 2001 From: Javier de la Puente Date: Tue, 20 Aug 2024 11:59:52 +0200 Subject: [PATCH 07/11] twelfactor -> app --- charmcraft/extensions/__init__.py | 2 +- charmcraft/extensions/{twelvefactor.py => app.py} | 14 +++++++------- .../{test_twelvefactor.py => test_app.py} | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) rename charmcraft/extensions/{twelvefactor.py => app.py} (98%) rename tests/extensions/{test_twelvefactor.py => test_app.py} (99%) diff --git a/charmcraft/extensions/__init__.py b/charmcraft/extensions/__init__.py index ad1cf1fd9..05467123c 100644 --- a/charmcraft/extensions/__init__.py +++ b/charmcraft/extensions/__init__.py @@ -17,8 +17,8 @@ """Extension processor and related utilities.""" from charmcraft.extensions._utils import apply_extensions +from charmcraft.extensions.app import DjangoFramework, FlaskFramework, GoFramework from charmcraft.extensions.extension import Extension -from charmcraft.extensions.twelvefactor import DjangoFramework, FlaskFramework, GoFramework from charmcraft.extensions.registry import ( get_extension_class, get_extension_names, diff --git a/charmcraft/extensions/twelvefactor.py b/charmcraft/extensions/app.py similarity index 98% rename from charmcraft/extensions/twelvefactor.py rename to charmcraft/extensions/app.py index 24b9447ab..0628804fe 100644 --- a/charmcraft/extensions/twelvefactor.py +++ b/charmcraft/extensions/app.py @@ -24,7 +24,7 @@ from .extension import Extension -class _TwelveFactorBase(Extension): +class _AppBase(Extension): """A base class for 12-factor applications.""" _CHARM_LIBS = [ @@ -199,7 +199,7 @@ def get_image_name(self) -> str: } -class FlaskFramework(_TwelveFactorBase): +class FlaskFramework(_AppBase): """Extension for 12-factor Flask applications.""" framework = "flask" @@ -243,12 +243,12 @@ def is_experimental(base: tuple[str, ...] | None) -> bool: # noqa: ARG004 return False -class DjangoFramework(_TwelveFactorBase): +class DjangoFramework(_AppBase): """Extension for 12-factor Django applications.""" framework = "django" actions = { - **_TwelveFactorBase.actions, + **_AppBase.actions, "create-superuser": { "description": "Create a new Django superuser account.", "params": {"username": {"type": "string"}, "email": {"type": "string"}}, @@ -273,12 +273,12 @@ class DjangoFramework(_TwelveFactorBase): } -class GoFramework(_TwelveFactorBase): +class GoFramework(_AppBase): """Extension for 12-factor Go applications.""" framework = "go" options = { - "port": { + "app-port": { "type": "int", "default": 8080, "description": "Default port where the application will listen on.", @@ -293,7 +293,7 @@ class GoFramework(_TwelveFactorBase): "default": "/metrics", "description": "Path where the prometheus metrics will be scraped.", }, - "secret-key": { + "app-secret-key": { "type": "string", "description": "Long secret you can use for sessions, csrf or any other thing where you need a random secret shared by all units", }, diff --git a/tests/extensions/test_twelvefactor.py b/tests/extensions/test_app.py similarity index 99% rename from tests/extensions/test_twelvefactor.py rename to tests/extensions/test_app.py index e2976b93d..5d66c658d 100644 --- a/tests/extensions/test_twelvefactor.py +++ b/tests/extensions/test_app.py @@ -17,7 +17,7 @@ from charmcraft.errors import ExtensionError from charmcraft.extensions import apply_extensions -from charmcraft.extensions.twelvefactor import ( +from charmcraft.extensions.app import ( DjangoFramework, FlaskFramework, GoFramework, From b7752a1dff8c82b0fedfd0ccb4104343c9195692 Mon Sep 17 00:00:00 2001 From: Javier de la Puente Date: Tue, 27 Aug 2024 14:09:16 +0200 Subject: [PATCH 08/11] default and supported base is 24.04 in charmcraft --- charmcraft/extensions/app.py | 4 ++++ tests/extensions/test_app.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/charmcraft/extensions/app.py b/charmcraft/extensions/app.py index 0628804fe..39a6ca6c3 100644 --- a/charmcraft/extensions/app.py +++ b/charmcraft/extensions/app.py @@ -299,6 +299,10 @@ class GoFramework(_AppBase): }, } + def get_supported_bases() -> list[tuple[str, str]]: + """Return supported bases.""" + return [("ubuntu", "24.04")] + @override def get_image_name(self) -> str: """Return name of the app image.""" diff --git a/tests/extensions/test_app.py b/tests/extensions/test_app.py index 5d66c658d..a783a7194 100644 --- a/tests/extensions/test_app.py +++ b/tests/extensions/test_app.py @@ -185,7 +185,7 @@ def flask_input_yaml_fixture(): { "actions": GoFramework.actions, "assumes": ["k8s-api"], - "bases": [{"channel": "22.04", "name": "ubuntu"}], + "bases": [{"channel": "24.04", "name": "ubuntu"}], "containers": { "app": {"resource": "app-image"}, }, From 5f8110b461ddb7285e21e6833883cba5313a0893 Mon Sep 17 00:00:00 2001 From: Javier de la Puente Date: Tue, 27 Aug 2024 14:14:32 +0200 Subject: [PATCH 09/11] Fix linting --- charmcraft/extensions/app.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/charmcraft/extensions/app.py b/charmcraft/extensions/app.py index 39a6ca6c3..b7c4bd3a6 100644 --- a/charmcraft/extensions/app.py +++ b/charmcraft/extensions/app.py @@ -299,6 +299,8 @@ class GoFramework(_AppBase): }, } + @staticmethod + @override def get_supported_bases() -> list[tuple[str, str]]: """Return supported bases.""" return [("ubuntu", "24.04")] From c96be58b1dc2be5198fca94afde63e860d818371 Mon Sep 17 00:00:00 2001 From: Javier de la Puente Date: Tue, 27 Aug 2024 14:23:56 +0200 Subject: [PATCH 10/11] comment non amd64 platforms for init go framework --- charmcraft/templates/init-go-framework/charmcraft.yaml.j2 | 6 +++--- tests/extensions/test_app.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/charmcraft/templates/init-go-framework/charmcraft.yaml.j2 b/charmcraft/templates/init-go-framework/charmcraft.yaml.j2 index f45e8104d..14fa5b2f6 100644 --- a/charmcraft/templates/init-go-framework/charmcraft.yaml.j2 +++ b/charmcraft/templates/init-go-framework/charmcraft.yaml.j2 @@ -9,9 +9,9 @@ base: ubuntu@24.04 platforms: amd64: - arm64: - ppc64el: - s390x: + # arm64: + # ppc64el: + # s390x: # (Required) summary: A very short one-line summary of the Go application. diff --git a/tests/extensions/test_app.py b/tests/extensions/test_app.py index a783a7194..d88a66c7a 100644 --- a/tests/extensions/test_app.py +++ b/tests/extensions/test_app.py @@ -178,7 +178,7 @@ def flask_input_yaml_fixture(): "name": "test-go", "summary": "test summary", "description": "test description", - "bases": [{"name": "ubuntu", "channel": "22.04"}], + "bases": [{"name": "ubuntu", "channel": "24.04"}], "extensions": ["go-framework"], }, True, From 284a8da5d0c94aa5cde391229a7010c0932b4b9a Mon Sep 17 00:00:00 2001 From: Javier de la Puente Date: Tue, 27 Aug 2024 15:11:26 +0200 Subject: [PATCH 11/11] Add comment for platforms --- charmcraft/templates/init-go-framework/charmcraft.yaml.j2 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/charmcraft/templates/init-go-framework/charmcraft.yaml.j2 b/charmcraft/templates/init-go-framework/charmcraft.yaml.j2 index 14fa5b2f6..20e93214d 100644 --- a/charmcraft/templates/init-go-framework/charmcraft.yaml.j2 +++ b/charmcraft/templates/init-go-framework/charmcraft.yaml.j2 @@ -7,6 +7,8 @@ type: charm base: ubuntu@24.04 +# the platforms this charm should be built on and run on. +# you can check your architecture with `dpkg --print-architecture` platforms: amd64: # arm64: