From 0a209fdb7b2a8293fd416bb564717d7419ec1484 Mon Sep 17 00:00:00 2001 From: Alex Batisse Date: Fri, 15 Mar 2024 12:12:47 +0100 Subject: [PATCH 01/24] feat (interface): Add a zookeeper_client interface --- interfaces/zookeeper_client/v0/README.md | 56 +++++++++++ interfaces/zookeeper_client/v0/charms.yaml | 8 ++ .../v0/interface_tests/README.md | 33 +++++++ .../v0/interface_tests/test_provider.py | 1 + .../v0/interface_tests/test_requirer.py | 1 + interfaces/zookeeper_client/v0/schema.py | 92 +++++++++++++++++++ 6 files changed, 191 insertions(+) create mode 100644 interfaces/zookeeper_client/v0/README.md create mode 100644 interfaces/zookeeper_client/v0/charms.yaml create mode 100644 interfaces/zookeeper_client/v0/interface_tests/README.md create mode 100644 interfaces/zookeeper_client/v0/interface_tests/test_provider.py create mode 100644 interfaces/zookeeper_client/v0/interface_tests/test_requirer.py create mode 100644 interfaces/zookeeper_client/v0/schema.py diff --git a/interfaces/zookeeper_client/v0/README.md b/interfaces/zookeeper_client/v0/README.md new file mode 100644 index 00000000..68b2d469 --- /dev/null +++ b/interfaces/zookeeper_client/v0/README.md @@ -0,0 +1,56 @@ +# `zookeeper_client` + +## Usage + +This relation interface describes the expected behavior of any charm claiming to be able to interface with a Zookeeper cluster as a client. + +## Direction + +```mermaid +flowchart TD + Requirer -- database, \nrequested-secrets --> Provider + Provider -- database, \nendpoints, \nsecret-user --> Requirer +``` + +## Behavior + +Both the Requirer and the Provider need to adhere to criteria to be considered compatible with the interface. + +### Provider + +- Is expected to create an application user inside the database cluster when the requirer provides the `database` field. +- Is expected to provide credentials (`username` and `password`) in a Juju Secret whenever the Requirer supplies the `database` field. +- Is expected to expose the Juju Secrets URI to the credentials through the `secret-user` field of the data bag. +- Is expected to provide the `endpoints` field with a comma-separated list of server uris and zNode. +- Is expected to provide the `database` field with the zNode that was actually created. +- Is expected to provide the `version` field whenever database charm wants to communicate its database version. +- Is expected to provide the CA chain in the `tls-ca` field of a Juju Secret, whenever the provider has TLS enabled (such as using the [TLS Certificates Operator](https://github.com/canonical/tls-certificates-operator)). +- Is expected to share the TLS Juju Secret URI through the `secret-tls` field of the databag. +- If the Requirer asks for additional secrets (via `requested-secrets`, see below) other than those stored in the `user` and `tls` secrets, Provider is expected to define a `secret-extra` field holding the URI of the Juju Secret containing all additional secret fields. + +### Requirer + +- Is expected to provide `requested-secrets`, which is a list of field names that are not to be exposed on the relation databag, but handled within Juju Secrets. It should be JSON parsable array of strings, and correspond to valid Juju Secret keys (i.e. alphanumerical characters with a potential '-' (dash) character). Secret fields must contain `username` and `password` (and `tls-ca` in case TLS is enabled). +- Is expected to provide a zNode in the `database` field. +- Is expected to have unique credentials for each relation. Therefore, different instances of the same Charm (juju applications) will have different relations with different credentials. +- Is expected to have different relations names on Requirer with the same interface name if Requirer needs access to multiple database charms. +- Is expected to allow multiple different Juju applications to access the same zNode. +- Is expected to tolerate that the Provider may ignore the `database` field in some cases and instead use the zNode received. + +## Relation Data + +[\[Pydantic Schema\]](./schema.py) + + +```yaml +provider: + app: + database: /myappB + endpoints: 10.141.78.133:2181,10.141.78.50:2181,10.141.78.45:2181/myappB + secret-user: secret://59060ecc-0495-4a80-8006-5f1fc13fd783/cjqub6vubg2s77p3nio0 + secret-tls: secret://59060ecc-0495-4a80-8006-5f1fc13fd783/cjqub7fubg2s77p3niog +requirer: + app: + database: myappA + requested-secrets: ["username", "password", "tls-ca", "uris"] +``` diff --git a/interfaces/zookeeper_client/v0/charms.yaml b/interfaces/zookeeper_client/v0/charms.yaml new file mode 100644 index 00000000..4a75b58f --- /dev/null +++ b/interfaces/zookeeper_client/v0/charms.yaml @@ -0,0 +1,8 @@ +providers: + # list of charms using this interface as providers + - name: charm-using-the-provider-side + url: https://github.com/foo/charm-using-the-provider-side-k8s-operator # repo to clone; required + +# list of charms using this interface as requirers. +# same structure as providers +requirers: [] diff --git a/interfaces/zookeeper_client/v0/interface_tests/README.md b/interfaces/zookeeper_client/v0/interface_tests/README.md new file mode 100644 index 00000000..00ed852c --- /dev/null +++ b/interfaces/zookeeper_client/v0/interface_tests/README.md @@ -0,0 +1,33 @@ +This directory is meant to contain the tests for your interface, so that it is possible to programmatically verify its implementations. + +Find some relevant documentation at: +- [Interface Tests](https://discourse.charmhub.io/t/interface-tests/12691) +- [How to write interface tests](https://discourse.charmhub.io/t/how-to-write-interface-tests/12690) + +## Quickstart + +Copy this test to `test_provider.py` and fill in the blanks however appropriate for your interfaces + +```python +from scenario import Relation, State +from interface_tester import Tester + +def test_data_published_on_changed_remote_valid(): + # GIVEN a relation over containing all the right data + # in the right format for the : + relation = Relation( + endpoint='ingress', + interface='ingress', remote_app_name='remote', + remote_app_data={'foo': '"bar"', 'baz': '42', 'qux': '"www.lol.com:4242"', }, + remote_units_data={0: {'fizz': 'buzz', }}) + t = Tester( + State(relations=[relation]) + ) + + # WHEN the receives a event: + t.run(relation.changed_event) + + # THEN the also publishes valid data to its side of the relation + # (if applicable) + t.assert_schema_valid() +``` diff --git a/interfaces/zookeeper_client/v0/interface_tests/test_provider.py b/interfaces/zookeeper_client/v0/interface_tests/test_provider.py new file mode 100644 index 00000000..e06c107c --- /dev/null +++ b/interfaces/zookeeper_client/v0/interface_tests/test_provider.py @@ -0,0 +1 @@ +# TODO: add here interface tests for the provider side diff --git a/interfaces/zookeeper_client/v0/interface_tests/test_requirer.py b/interfaces/zookeeper_client/v0/interface_tests/test_requirer.py new file mode 100644 index 00000000..d0fc2366 --- /dev/null +++ b/interfaces/zookeeper_client/v0/interface_tests/test_requirer.py @@ -0,0 +1 @@ +# TODO: add here interface tests for the requirer side diff --git a/interfaces/zookeeper_client/v0/schema.py b/interfaces/zookeeper_client/v0/schema.py new file mode 100644 index 00000000..e86348ee --- /dev/null +++ b/interfaces/zookeeper_client/v0/schema.py @@ -0,0 +1,92 @@ +"""This file defines the schemas for the provider and requirer sides of the zookeeper_client interface. + +It must expose two interfaces.schema_base.DataBagSchema subclasses called: +- ProviderSchema +- RequirerSchema +""" + +from typing import Annotated + +from interface_tester.schema_base import DataBagSchema +from pydantic import ( + AfterValidator, + BaseModel, + Field, + IPvAnyAddress, + conint, +) + + +class URI(BaseModel): + ip: IPvAnyAddress + port: conint(ge=0, le=65535) | None + + def __init__(self, value: str) -> None: + ip, _, port = value.partition(":") + if not port: + port = None + super().__init__(ip=ip, port=port) + + +def parse_endpoints(value: str): + uris, _, znode = value.partition("/") + [URI(val) for val in uris.split(",")] + + +Endpoints = Annotated[str, AfterValidator(parse_endpoints)] + + +class ZookeeperProviderAppData(BaseModel): + database: str = Field( + description="The zNode granted to the requirer", + examples=["/myAppb"], + title="zNode", + ) + + endpoints: Endpoints = Field( + description="A comma-seperated list of ZooKeeper server uris, and zNode", + examples=["10.141.78.133:2181,10.141.78.50:2181,10.141.78.45:2181/myappB"], + title="ZooKeeper URIs", + ) + + secret_user: str = Field( + alias="secret-user", + description="", + examples=["secret://59060ecc-0495-4a80-8006-5f1fc13fd783/cjqub6vubg2s77p3nio0"], + title="Credentials Secret Name", + ) + + secret_tls: str | None = Field( + None, + alias="secret-tls", + description="The name of the TLS secret to use. Leaving this empty will configure a client with TLS disabled.", + examples=["secret://59060ecc-0495-4a80-8006-5f1fc13fd783/cjqub7fubg2s77p3niog"], + title="Tls Secret Name", + ) + + +class ZookeeperRequirerAppData(BaseModel): + database: str = Field( + description="The zNode requested by the requirer", + examples=["/myappA"], + title="zNode", + ) + + requested_secrets: list[str] = Field( + alias="requested-secrets", + description="Any provider field which should be transfered as Juju Secret", + examples=[["username", "password", "tls-ca", "uris"]], + title="Requested secrets", + ) + + +class ProviderSchema(DataBagSchema): + """The schema for the provider side of this interface.""" + + app: ZookeeperProviderAppData + + +class RequirerSchema(DataBagSchema): + """The schema for the requirer side of this interface.""" + + app: ZookeeperRequirerAppData From cca873cc41560151c95463c8b1fd373615207abb Mon Sep 17 00:00:00 2001 From: Alex Batisse Date: Fri, 15 Mar 2024 14:31:41 +0100 Subject: [PATCH 02/24] feat (schema): Add json schemas --- .../zookeeper_client/v0/provider.json | 82 +++++++++++++++++++ .../zookeeper_client/v0/requirer.json | 65 +++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 docs/json_schemas/zookeeper_client/v0/provider.json create mode 100644 docs/json_schemas/zookeeper_client/v0/requirer.json diff --git a/docs/json_schemas/zookeeper_client/v0/provider.json b/docs/json_schemas/zookeeper_client/v0/provider.json new file mode 100644 index 00000000..ac4e365e --- /dev/null +++ b/docs/json_schemas/zookeeper_client/v0/provider.json @@ -0,0 +1,82 @@ +{ + "$defs": { + "BaseModel": { + "properties": {}, + "title": "BaseModel", + "type": "object" + }, + "ZookeeperProviderAppData": { + "properties": { + "database": { + "description": "The zNode granted to the requirer", + "examples": [ + "/myAppb" + ], + "title": "zNode", + "type": "string" + }, + "endpoints": { + "description": "A comma-seperated list of ZooKeeper server uris, and zNode", + "examples": [ + "10.141.78.133:2181,10.141.78.50:2181,10.141.78.45:2181/myappB" + ], + "title": "ZooKeeper URIs", + "type": "string" + }, + "secret-user": { + "description": "", + "examples": [ + "secret://59060ecc-0495-4a80-8006-5f1fc13fd783/cjqub6vubg2s77p3nio0" + ], + "title": "Credentials Secret Name", + "type": "string" + }, + "secret-tls": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The name of the TLS secret to use. Leaving this empty will configure a client with TLS disabled.", + "examples": [ + "secret://59060ecc-0495-4a80-8006-5f1fc13fd783/cjqub7fubg2s77p3niog" + ], + "title": "Tls Secret Name" + } + }, + "required": [ + "database", + "endpoints", + "secret-user" + ], + "title": "ZookeeperProviderAppData", + "type": "object" + } + }, + "description": "The schema for the provider side of this interface.", + "properties": { + "unit": { + "anyOf": [ + { + "$ref": "#/$defs/BaseModel" + }, + { + "type": "null" + } + ], + "default": null + }, + "app": { + "$ref": "#/$defs/ZookeeperProviderAppData" + } + }, + "required": [ + "app" + ], + "title": "ProviderSchema", + "type": "object" +} \ No newline at end of file diff --git a/docs/json_schemas/zookeeper_client/v0/requirer.json b/docs/json_schemas/zookeeper_client/v0/requirer.json new file mode 100644 index 00000000..64ed12e3 --- /dev/null +++ b/docs/json_schemas/zookeeper_client/v0/requirer.json @@ -0,0 +1,65 @@ +{ + "$defs": { + "BaseModel": { + "properties": {}, + "title": "BaseModel", + "type": "object" + }, + "ZookeeperRequirerAppData": { + "properties": { + "database": { + "description": "The zNode requested by the requirer", + "examples": [ + "/myappA" + ], + "title": "zNode", + "type": "string" + }, + "requested-secrets": { + "description": "Any provider field which should be transfered as Juju Secret", + "examples": [ + [ + "username", + "password", + "tls-ca", + "uris" + ] + ], + "items": { + "type": "string" + }, + "title": "Requested secrets", + "type": "array" + } + }, + "required": [ + "database", + "requested-secrets" + ], + "title": "ZookeeperRequirerAppData", + "type": "object" + } + }, + "description": "The schema for the requirer side of this interface.", + "properties": { + "unit": { + "anyOf": [ + { + "$ref": "#/$defs/BaseModel" + }, + { + "type": "null" + } + ], + "default": null + }, + "app": { + "$ref": "#/$defs/ZookeeperRequirerAppData" + } + }, + "required": [ + "app" + ], + "title": "RequirerSchema", + "type": "object" +} \ No newline at end of file From 059770b706e534f149d734df9608803127584f2e Mon Sep 17 00:00:00 2001 From: Alex Batisse Date: Tue, 19 Mar 2024 17:27:25 +0100 Subject: [PATCH 03/24] docs (schema): Improve wording in title and description --- docs/json_schemas/zookeeper_client/v0/provider.json | 6 +++--- docs/json_schemas/zookeeper_client/v0/requirer.json | 2 +- interfaces/zookeeper_client/v0/schema.py | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/json_schemas/zookeeper_client/v0/provider.json b/docs/json_schemas/zookeeper_client/v0/provider.json index ac4e365e..d60b74ec 100644 --- a/docs/json_schemas/zookeeper_client/v0/provider.json +++ b/docs/json_schemas/zookeeper_client/v0/provider.json @@ -8,7 +8,7 @@ "ZookeeperProviderAppData": { "properties": { "database": { - "description": "The zNode granted to the requirer", + "description": "The parent chroot zNode granted to the requirer", "examples": [ "/myAppb" ], @@ -16,7 +16,7 @@ "type": "string" }, "endpoints": { - "description": "A comma-seperated list of ZooKeeper server uris, and zNode", + "description": "A comma-seperated list of ZooKeeper server uris, and parent chroot zNode", "examples": [ "10.141.78.133:2181,10.141.78.50:2181,10.141.78.45:2181/myappB" ], @@ -45,7 +45,7 @@ "examples": [ "secret://59060ecc-0495-4a80-8006-5f1fc13fd783/cjqub7fubg2s77p3niog" ], - "title": "Tls Secret Name" + "title": "TLS Secret Name" } }, "required": [ diff --git a/docs/json_schemas/zookeeper_client/v0/requirer.json b/docs/json_schemas/zookeeper_client/v0/requirer.json index 64ed12e3..8d252214 100644 --- a/docs/json_schemas/zookeeper_client/v0/requirer.json +++ b/docs/json_schemas/zookeeper_client/v0/requirer.json @@ -8,7 +8,7 @@ "ZookeeperRequirerAppData": { "properties": { "database": { - "description": "The zNode requested by the requirer", + "description": "The parent chroot zNode requested by the requirer", "examples": [ "/myappA" ], diff --git a/interfaces/zookeeper_client/v0/schema.py b/interfaces/zookeeper_client/v0/schema.py index e86348ee..d6d01622 100644 --- a/interfaces/zookeeper_client/v0/schema.py +++ b/interfaces/zookeeper_client/v0/schema.py @@ -38,13 +38,13 @@ def parse_endpoints(value: str): class ZookeeperProviderAppData(BaseModel): database: str = Field( - description="The zNode granted to the requirer", + description="The parent chroot zNode granted to the requirer", examples=["/myAppb"], title="zNode", ) endpoints: Endpoints = Field( - description="A comma-seperated list of ZooKeeper server uris, and zNode", + description="A comma-seperated list of ZooKeeper server uris, and parent chroot zNode", examples=["10.141.78.133:2181,10.141.78.50:2181,10.141.78.45:2181/myappB"], title="ZooKeeper URIs", ) @@ -61,13 +61,13 @@ class ZookeeperProviderAppData(BaseModel): alias="secret-tls", description="The name of the TLS secret to use. Leaving this empty will configure a client with TLS disabled.", examples=["secret://59060ecc-0495-4a80-8006-5f1fc13fd783/cjqub7fubg2s77p3niog"], - title="Tls Secret Name", + title="TLS Secret Name", ) class ZookeeperRequirerAppData(BaseModel): database: str = Field( - description="The zNode requested by the requirer", + description="The parent chroot zNode requested by the requirer", examples=["/myappA"], title="zNode", ) From 289314784c31cf17d9ad6aee929f7f92e0fb0206 Mon Sep 17 00:00:00 2001 From: Alex Batisse Date: Tue, 19 Mar 2024 17:44:22 +0100 Subject: [PATCH 04/24] docs (interface): Add kafka and zookeeper in charms.yaml --- interfaces/zookeeper_client/v0/charms.yaml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/interfaces/zookeeper_client/v0/charms.yaml b/interfaces/zookeeper_client/v0/charms.yaml index 4a75b58f..8697d9da 100644 --- a/interfaces/zookeeper_client/v0/charms.yaml +++ b/interfaces/zookeeper_client/v0/charms.yaml @@ -1,8 +1,14 @@ providers: # list of charms using this interface as providers - - name: charm-using-the-provider-side - url: https://github.com/foo/charm-using-the-provider-side-k8s-operator # repo to clone; required + - name: zookeeper + url: https://github.com/canonical/zookeeper-operator + - name: zookeeper-k8s + url: https://github.com/canonical/zookeeper-k8s-operator # list of charms using this interface as requirers. # same structure as providers -requirers: [] +requirers: + - name: kafka + url: https://github.com/canonical/kafka-operator + - name: kafka-k8s + url: https://github.com/canonical/kafka-k8s-operator From ba07bb21c16ff0732c456d43dfd1a8bb1bd17576 Mon Sep 17 00:00:00 2001 From: Alex Batisse Date: Fri, 22 Mar 2024 08:31:26 +0100 Subject: [PATCH 05/24] fix: Wording for consistency --- interfaces/zookeeper_client/v0/README.md | 2 +- interfaces/zookeeper_client/v0/schema.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interfaces/zookeeper_client/v0/README.md b/interfaces/zookeeper_client/v0/README.md index 68b2d469..bce1bb43 100644 --- a/interfaces/zookeeper_client/v0/README.md +++ b/interfaces/zookeeper_client/v0/README.md @@ -2,7 +2,7 @@ ## Usage -This relation interface describes the expected behavior of any charm claiming to be able to interface with a Zookeeper cluster as a client. +This relation interface describes the expected behavior of any charm claiming to be able to interface with a Zookeeper cluster. ## Direction diff --git a/interfaces/zookeeper_client/v0/schema.py b/interfaces/zookeeper_client/v0/schema.py index d6d01622..6365823f 100644 --- a/interfaces/zookeeper_client/v0/schema.py +++ b/interfaces/zookeeper_client/v0/schema.py @@ -39,7 +39,7 @@ def parse_endpoints(value: str): class ZookeeperProviderAppData(BaseModel): database: str = Field( description="The parent chroot zNode granted to the requirer", - examples=["/myAppb"], + examples=["/myappB"], title="zNode", ) From 07d3db37998571327d0bf1bbb19f5bc5d1eea488 Mon Sep 17 00:00:00 2001 From: Alex Batisse Date: Fri, 22 Mar 2024 08:38:00 +0100 Subject: [PATCH 06/24] fix: Rebuild zk json schema --- docs/json_schemas/zookeeper_client/v0/provider.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/json_schemas/zookeeper_client/v0/provider.json b/docs/json_schemas/zookeeper_client/v0/provider.json index d60b74ec..23c82459 100644 --- a/docs/json_schemas/zookeeper_client/v0/provider.json +++ b/docs/json_schemas/zookeeper_client/v0/provider.json @@ -10,7 +10,7 @@ "database": { "description": "The parent chroot zNode granted to the requirer", "examples": [ - "/myAppb" + "/myappB" ], "title": "zNode", "type": "string" From 07e0d40f1cdbef48ebd929d0508dfaf5fcd821d2 Mon Sep 17 00:00:00 2001 From: Alex Batisse Date: Thu, 25 Apr 2024 15:38:33 +0200 Subject: [PATCH 07/24] WIP: Add minimal provider test --- .../zookeeper_client/v0/interface_tests/test_provider.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/interfaces/zookeeper_client/v0/interface_tests/test_provider.py b/interfaces/zookeeper_client/v0/interface_tests/test_provider.py index e06c107c..9522f3cc 100644 --- a/interfaces/zookeeper_client/v0/interface_tests/test_provider.py +++ b/interfaces/zookeeper_client/v0/interface_tests/test_provider.py @@ -1 +1,8 @@ -# TODO: add here interface tests for the provider side +from scenario import State +from interface_tester import Tester + +def test_data_published_on_joined(): + t = Tester(State()) + t.run("database-relation-joined") + t.assert_relation_data_empty() + From 912b1b9fc86e908747f22d841efdd0705d9117db Mon Sep 17 00:00:00 2001 From: Alex Batisse Date: Fri, 26 Apr 2024 16:40:23 +0200 Subject: [PATCH 08/24] tests: Add simple zk interface tests --- .../v0/interface_tests/test_provider.py | 40 +++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/interfaces/zookeeper_client/v0/interface_tests/test_provider.py b/interfaces/zookeeper_client/v0/interface_tests/test_provider.py index 9522f3cc..c77a1f3d 100644 --- a/interfaces/zookeeper_client/v0/interface_tests/test_provider.py +++ b/interfaces/zookeeper_client/v0/interface_tests/test_provider.py @@ -1,8 +1,42 @@ -from scenario import State +from scenario import State, Relation from interface_tester import Tester -def test_data_published_on_joined(): - t = Tester(State()) + +def test_no_data_on_created(): + t = Tester( + State( + leader=True, + relations=[Relation(endpoint="database", interface="zookeeper_client")], + ) + ) + t.run("database-relation-created") + t.assert_relation_data_empty() + + +def test_no_data_on_joined(): + t = Tester( + State( + leader=True, + relations=[ + Relation( + endpoint="database", + interface="zookeeper_client", + ) + ], + ) + ) t.run("database-relation-joined") t.assert_relation_data_empty() + +def test_data_published_on_changed_remote_valid(): + zk = Relation( + endpoint="database", + interface="zookeeper_client", + remote_app_data={ + "database": "/myapp", + }, + ) + t = Tester(State(leader=True, relations=[zk])) + t.run(zk.changed_event) + t.assert_schema_valid() From a2fffddeab656e5ce1d6be8bcddb52f33e162111 Mon Sep 17 00:00:00 2001 From: Alex Batisse Date: Fri, 26 Apr 2024 17:31:31 +0200 Subject: [PATCH 09/24] WIP: Try removing pydantic v2 in zk client interface --- interfaces/zookeeper_client/v0/schema.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/interfaces/zookeeper_client/v0/schema.py b/interfaces/zookeeper_client/v0/schema.py index 6365823f..75bafe23 100644 --- a/interfaces/zookeeper_client/v0/schema.py +++ b/interfaces/zookeeper_client/v0/schema.py @@ -5,11 +5,11 @@ - RequirerSchema """ -from typing import Annotated +from typing import Annotated, TypeAlias from interface_tester.schema_base import DataBagSchema from pydantic import ( - AfterValidator, + # AfterValidator, BaseModel, Field, IPvAnyAddress, @@ -33,7 +33,8 @@ def parse_endpoints(value: str): [URI(val) for val in uris.split(",")] -Endpoints = Annotated[str, AfterValidator(parse_endpoints)] +# Endpoints = Annotated[str, AfterValidator(parse_endpoints)] +Endpoints: TypeAlias = str class ZookeeperProviderAppData(BaseModel): From 529e16c8e9573e0b9571cc604d7ef01d2697b4dc Mon Sep 17 00:00:00 2001 From: Alex Batisse Date: Mon, 29 Apr 2024 12:55:15 +0200 Subject: [PATCH 10/24] fix (tests): Add requested_secrets to remote app data --- interfaces/zookeeper_client/v0/interface_tests/test_provider.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interfaces/zookeeper_client/v0/interface_tests/test_provider.py b/interfaces/zookeeper_client/v0/interface_tests/test_provider.py index c77a1f3d..cec944ea 100644 --- a/interfaces/zookeeper_client/v0/interface_tests/test_provider.py +++ b/interfaces/zookeeper_client/v0/interface_tests/test_provider.py @@ -35,8 +35,10 @@ def test_data_published_on_changed_remote_valid(): interface="zookeeper_client", remote_app_data={ "database": "/myapp", + "requested-secrets": """["username","password","tls","tls-ca","uris"]""", }, ) t = Tester(State(leader=True, relations=[zk])) t.run(zk.changed_event) + t.run("config-changed") t.assert_schema_valid() From f2cdcdbe881dfd99a828a33bc6874f50faf6b76d Mon Sep 17 00:00:00 2001 From: Alex Batisse Date: Mon, 29 Apr 2024 15:59:59 +0200 Subject: [PATCH 11/24] feat: Rename interface to former name --- docs/json_schemas/zookeeper/v0/provider.json | 82 +++++++++++++++++++ docs/json_schemas/zookeeper/v0/requirer.json | 65 +++++++++++++++ .../v0/README.md | 3 +- interfaces/zookeeper/v0/charms.yaml | 15 ++++ .../v0/interface_tests/README.md | 0 .../v0/interface_tests/test_provider.py | 6 +- .../v0/interface_tests/test_requirer.py | 0 .../v0/schema.py | 0 interfaces/zookeeper_client/v0/charms.yaml | 14 ---- 9 files changed, 167 insertions(+), 18 deletions(-) create mode 100644 docs/json_schemas/zookeeper/v0/provider.json create mode 100644 docs/json_schemas/zookeeper/v0/requirer.json rename interfaces/{zookeeper_client => zookeeper}/v0/README.md (96%) create mode 100644 interfaces/zookeeper/v0/charms.yaml rename interfaces/{zookeeper_client => zookeeper}/v0/interface_tests/README.md (100%) rename interfaces/{zookeeper_client => zookeeper}/v0/interface_tests/test_provider.py (90%) rename interfaces/{zookeeper_client => zookeeper}/v0/interface_tests/test_requirer.py (100%) rename interfaces/{zookeeper_client => zookeeper}/v0/schema.py (100%) delete mode 100644 interfaces/zookeeper_client/v0/charms.yaml diff --git a/docs/json_schemas/zookeeper/v0/provider.json b/docs/json_schemas/zookeeper/v0/provider.json new file mode 100644 index 00000000..23c82459 --- /dev/null +++ b/docs/json_schemas/zookeeper/v0/provider.json @@ -0,0 +1,82 @@ +{ + "$defs": { + "BaseModel": { + "properties": {}, + "title": "BaseModel", + "type": "object" + }, + "ZookeeperProviderAppData": { + "properties": { + "database": { + "description": "The parent chroot zNode granted to the requirer", + "examples": [ + "/myappB" + ], + "title": "zNode", + "type": "string" + }, + "endpoints": { + "description": "A comma-seperated list of ZooKeeper server uris, and parent chroot zNode", + "examples": [ + "10.141.78.133:2181,10.141.78.50:2181,10.141.78.45:2181/myappB" + ], + "title": "ZooKeeper URIs", + "type": "string" + }, + "secret-user": { + "description": "", + "examples": [ + "secret://59060ecc-0495-4a80-8006-5f1fc13fd783/cjqub6vubg2s77p3nio0" + ], + "title": "Credentials Secret Name", + "type": "string" + }, + "secret-tls": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The name of the TLS secret to use. Leaving this empty will configure a client with TLS disabled.", + "examples": [ + "secret://59060ecc-0495-4a80-8006-5f1fc13fd783/cjqub7fubg2s77p3niog" + ], + "title": "TLS Secret Name" + } + }, + "required": [ + "database", + "endpoints", + "secret-user" + ], + "title": "ZookeeperProviderAppData", + "type": "object" + } + }, + "description": "The schema for the provider side of this interface.", + "properties": { + "unit": { + "anyOf": [ + { + "$ref": "#/$defs/BaseModel" + }, + { + "type": "null" + } + ], + "default": null + }, + "app": { + "$ref": "#/$defs/ZookeeperProviderAppData" + } + }, + "required": [ + "app" + ], + "title": "ProviderSchema", + "type": "object" +} \ No newline at end of file diff --git a/docs/json_schemas/zookeeper/v0/requirer.json b/docs/json_schemas/zookeeper/v0/requirer.json new file mode 100644 index 00000000..8d252214 --- /dev/null +++ b/docs/json_schemas/zookeeper/v0/requirer.json @@ -0,0 +1,65 @@ +{ + "$defs": { + "BaseModel": { + "properties": {}, + "title": "BaseModel", + "type": "object" + }, + "ZookeeperRequirerAppData": { + "properties": { + "database": { + "description": "The parent chroot zNode requested by the requirer", + "examples": [ + "/myappA" + ], + "title": "zNode", + "type": "string" + }, + "requested-secrets": { + "description": "Any provider field which should be transfered as Juju Secret", + "examples": [ + [ + "username", + "password", + "tls-ca", + "uris" + ] + ], + "items": { + "type": "string" + }, + "title": "Requested secrets", + "type": "array" + } + }, + "required": [ + "database", + "requested-secrets" + ], + "title": "ZookeeperRequirerAppData", + "type": "object" + } + }, + "description": "The schema for the requirer side of this interface.", + "properties": { + "unit": { + "anyOf": [ + { + "$ref": "#/$defs/BaseModel" + }, + { + "type": "null" + } + ], + "default": null + }, + "app": { + "$ref": "#/$defs/ZookeeperRequirerAppData" + } + }, + "required": [ + "app" + ], + "title": "RequirerSchema", + "type": "object" +} \ No newline at end of file diff --git a/interfaces/zookeeper_client/v0/README.md b/interfaces/zookeeper/v0/README.md similarity index 96% rename from interfaces/zookeeper_client/v0/README.md rename to interfaces/zookeeper/v0/README.md index bce1bb43..db106af8 100644 --- a/interfaces/zookeeper_client/v0/README.md +++ b/interfaces/zookeeper/v0/README.md @@ -1,4 +1,4 @@ -# `zookeeper_client` +# `zookeeper` ## Usage @@ -36,6 +36,7 @@ Both the Requirer and the Provider need to adhere to criteria to be considered c - Is expected to have different relations names on Requirer with the same interface name if Requirer needs access to multiple database charms. - Is expected to allow multiple different Juju applications to access the same zNode. - Is expected to tolerate that the Provider may ignore the `database` field in some cases and instead use the zNode received. +- Can optionally provide the `extra-user-roles` field specifying a ACL string for the client application. ## Relation Data diff --git a/interfaces/zookeeper/v0/charms.yaml b/interfaces/zookeeper/v0/charms.yaml new file mode 100644 index 00000000..de2d3204 --- /dev/null +++ b/interfaces/zookeeper/v0/charms.yaml @@ -0,0 +1,15 @@ +providers: + # list of charms using this interface as providers + - name: zookeeper + url: https://github.com/canonical/zookeeper-operator + branch: feat/DPE-3737-client-interface + # - name: zookeeper-k8s + # url: https://github.com/canonical/zookeeper-k8s-operator + +# list of charms using this interface as requirers. +# same structure as providers +requirers: [] + # - name: kafka + # url: https://github.com/canonical/kafka-operator + # - name: kafka-k8s + # url: https://github.com/canonical/kafka-k8s-operator diff --git a/interfaces/zookeeper_client/v0/interface_tests/README.md b/interfaces/zookeeper/v0/interface_tests/README.md similarity index 100% rename from interfaces/zookeeper_client/v0/interface_tests/README.md rename to interfaces/zookeeper/v0/interface_tests/README.md diff --git a/interfaces/zookeeper_client/v0/interface_tests/test_provider.py b/interfaces/zookeeper/v0/interface_tests/test_provider.py similarity index 90% rename from interfaces/zookeeper_client/v0/interface_tests/test_provider.py rename to interfaces/zookeeper/v0/interface_tests/test_provider.py index cec944ea..9a63bf36 100644 --- a/interfaces/zookeeper_client/v0/interface_tests/test_provider.py +++ b/interfaces/zookeeper/v0/interface_tests/test_provider.py @@ -6,7 +6,7 @@ def test_no_data_on_created(): t = Tester( State( leader=True, - relations=[Relation(endpoint="database", interface="zookeeper_client")], + relations=[Relation(endpoint="database", interface="zookeeper")], ) ) t.run("database-relation-created") @@ -20,7 +20,7 @@ def test_no_data_on_joined(): relations=[ Relation( endpoint="database", - interface="zookeeper_client", + interface="zookeeper", ) ], ) @@ -32,7 +32,7 @@ def test_no_data_on_joined(): def test_data_published_on_changed_remote_valid(): zk = Relation( endpoint="database", - interface="zookeeper_client", + interface="zookeeper", remote_app_data={ "database": "/myapp", "requested-secrets": """["username","password","tls","tls-ca","uris"]""", diff --git a/interfaces/zookeeper_client/v0/interface_tests/test_requirer.py b/interfaces/zookeeper/v0/interface_tests/test_requirer.py similarity index 100% rename from interfaces/zookeeper_client/v0/interface_tests/test_requirer.py rename to interfaces/zookeeper/v0/interface_tests/test_requirer.py diff --git a/interfaces/zookeeper_client/v0/schema.py b/interfaces/zookeeper/v0/schema.py similarity index 100% rename from interfaces/zookeeper_client/v0/schema.py rename to interfaces/zookeeper/v0/schema.py diff --git a/interfaces/zookeeper_client/v0/charms.yaml b/interfaces/zookeeper_client/v0/charms.yaml deleted file mode 100644 index 8697d9da..00000000 --- a/interfaces/zookeeper_client/v0/charms.yaml +++ /dev/null @@ -1,14 +0,0 @@ -providers: - # list of charms using this interface as providers - - name: zookeeper - url: https://github.com/canonical/zookeeper-operator - - name: zookeeper-k8s - url: https://github.com/canonical/zookeeper-k8s-operator - -# list of charms using this interface as requirers. -# same structure as providers -requirers: - - name: kafka - url: https://github.com/canonical/kafka-operator - - name: kafka-k8s - url: https://github.com/canonical/kafka-k8s-operator From 1664cef2d9d80c3fe12508718c30bd17ea18fdac Mon Sep 17 00:00:00 2001 From: Alex Batisse Date: Mon, 29 Apr 2024 16:20:36 +0200 Subject: [PATCH 12/24] feat: Add extra-user-roles to requirer schema --- docs/json_schemas/zookeeper/v0/provider.json | 4 ++-- docs/json_schemas/zookeeper/v0/requirer.json | 16 ++++++++++++++++ interfaces/zookeeper/v0/README.md | 2 +- .../v0/interface_tests/test_provider.py | 2 +- interfaces/zookeeper/v0/schema.py | 12 ++++++++++-- 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/docs/json_schemas/zookeeper/v0/provider.json b/docs/json_schemas/zookeeper/v0/provider.json index 23c82459..ebe39296 100644 --- a/docs/json_schemas/zookeeper/v0/provider.json +++ b/docs/json_schemas/zookeeper/v0/provider.json @@ -16,9 +16,9 @@ "type": "string" }, "endpoints": { - "description": "A comma-seperated list of ZooKeeper server uris, and parent chroot zNode", + "description": "A comma-seperated list of ZooKeeper server and ports", "examples": [ - "10.141.78.133:2181,10.141.78.50:2181,10.141.78.45:2181/myappB" + "10.141.78.133:2181,10.141.78.50:2181,10.141.78.45:2181" ], "title": "ZooKeeper URIs", "type": "string" diff --git a/docs/json_schemas/zookeeper/v0/requirer.json b/docs/json_schemas/zookeeper/v0/requirer.json index 8d252214..8df8b711 100644 --- a/docs/json_schemas/zookeeper/v0/requirer.json +++ b/docs/json_schemas/zookeeper/v0/requirer.json @@ -15,6 +15,22 @@ "title": "zNode", "type": "string" }, + "extra-user-roles": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "ACL string representation for the parent chroot", + "examples": [ + "cdrwa" + ], + "title": "User roles" + }, "requested-secrets": { "description": "Any provider field which should be transfered as Juju Secret", "examples": [ diff --git a/interfaces/zookeeper/v0/README.md b/interfaces/zookeeper/v0/README.md index db106af8..b67c3e19 100644 --- a/interfaces/zookeeper/v0/README.md +++ b/interfaces/zookeeper/v0/README.md @@ -47,7 +47,7 @@ Both the Requirer and the Provider need to adhere to criteria to be considered c provider: app: database: /myappB - endpoints: 10.141.78.133:2181,10.141.78.50:2181,10.141.78.45:2181/myappB + endpoints: 10.141.78.133:2181,10.141.78.50:2181,10.141.78.45:2181 secret-user: secret://59060ecc-0495-4a80-8006-5f1fc13fd783/cjqub6vubg2s77p3nio0 secret-tls: secret://59060ecc-0495-4a80-8006-5f1fc13fd783/cjqub7fubg2s77p3niog requirer: diff --git a/interfaces/zookeeper/v0/interface_tests/test_provider.py b/interfaces/zookeeper/v0/interface_tests/test_provider.py index 9a63bf36..bad00241 100644 --- a/interfaces/zookeeper/v0/interface_tests/test_provider.py +++ b/interfaces/zookeeper/v0/interface_tests/test_provider.py @@ -40,5 +40,5 @@ def test_data_published_on_changed_remote_valid(): ) t = Tester(State(leader=True, relations=[zk])) t.run(zk.changed_event) - t.run("config-changed") + # t.run("config-changed") t.assert_schema_valid() diff --git a/interfaces/zookeeper/v0/schema.py b/interfaces/zookeeper/v0/schema.py index 75bafe23..418cf16d 100644 --- a/interfaces/zookeeper/v0/schema.py +++ b/interfaces/zookeeper/v0/schema.py @@ -45,8 +45,8 @@ class ZookeeperProviderAppData(BaseModel): ) endpoints: Endpoints = Field( - description="A comma-seperated list of ZooKeeper server uris, and parent chroot zNode", - examples=["10.141.78.133:2181,10.141.78.50:2181,10.141.78.45:2181/myappB"], + description="A comma-seperated list of ZooKeeper server and ports", + examples=["10.141.78.133:2181,10.141.78.50:2181,10.141.78.45:2181"], title="ZooKeeper URIs", ) @@ -73,6 +73,14 @@ class ZookeeperRequirerAppData(BaseModel): title="zNode", ) + extra_user_roles: str | None = Field( + None, + alias="extra-user-roles", + description="ACL string representation for the parent chroot", + examples=["cdrwa"], + title="User roles" + ) + requested_secrets: list[str] = Field( alias="requested-secrets", description="Any provider field which should be transfered as Juju Secret", From 94a8e2d3f43e61fec625957df5f3c3ca11994e77 Mon Sep 17 00:00:00 2001 From: Alex Batisse Date: Thu, 2 May 2024 13:39:00 +0200 Subject: [PATCH 13/24] Revert "WIP: Try removing pydantic v2 in zk client interface" This reverts commit a2fffddeab656e5ce1d6be8bcddb52f33e162111. --- interfaces/zookeeper/v0/schema.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/interfaces/zookeeper/v0/schema.py b/interfaces/zookeeper/v0/schema.py index 418cf16d..e57a79a3 100644 --- a/interfaces/zookeeper/v0/schema.py +++ b/interfaces/zookeeper/v0/schema.py @@ -5,11 +5,11 @@ - RequirerSchema """ -from typing import Annotated, TypeAlias +from typing import Annotated from interface_tester.schema_base import DataBagSchema from pydantic import ( - # AfterValidator, + AfterValidator, BaseModel, Field, IPvAnyAddress, @@ -33,8 +33,7 @@ def parse_endpoints(value: str): [URI(val) for val in uris.split(",")] -# Endpoints = Annotated[str, AfterValidator(parse_endpoints)] -Endpoints: TypeAlias = str +Endpoints = Annotated[str, AfterValidator(parse_endpoints)] class ZookeeperProviderAppData(BaseModel): From 8c4e01c078710b56056da7cadafaa1e1fe37ad08 Mon Sep 17 00:00:00 2001 From: Alex Batisse Date: Thu, 2 May 2024 13:44:04 +0200 Subject: [PATCH 14/24] feat: Remove chroot from endpoints value --- docs/json_schemas/zookeeper/v0/provider.json | 2 +- .../v0/interface_tests/test_provider.py | 16 +--------------- interfaces/zookeeper/v0/schema.py | 7 +++---- 3 files changed, 5 insertions(+), 20 deletions(-) diff --git a/docs/json_schemas/zookeeper/v0/provider.json b/docs/json_schemas/zookeeper/v0/provider.json index ebe39296..73ce1c98 100644 --- a/docs/json_schemas/zookeeper/v0/provider.json +++ b/docs/json_schemas/zookeeper/v0/provider.json @@ -20,7 +20,7 @@ "examples": [ "10.141.78.133:2181,10.141.78.50:2181,10.141.78.45:2181" ], - "title": "ZooKeeper URIs", + "title": "ZooKeeper endpoints", "type": "string" }, "secret-user": { diff --git a/interfaces/zookeeper/v0/interface_tests/test_provider.py b/interfaces/zookeeper/v0/interface_tests/test_provider.py index bad00241..7782a56d 100644 --- a/interfaces/zookeeper/v0/interface_tests/test_provider.py +++ b/interfaces/zookeeper/v0/interface_tests/test_provider.py @@ -1,4 +1,4 @@ -from scenario import State, Relation +from scenario import State, Relation, PeerRelation from interface_tester import Tester @@ -28,17 +28,3 @@ def test_no_data_on_joined(): t.run("database-relation-joined") t.assert_relation_data_empty() - -def test_data_published_on_changed_remote_valid(): - zk = Relation( - endpoint="database", - interface="zookeeper", - remote_app_data={ - "database": "/myapp", - "requested-secrets": """["username","password","tls","tls-ca","uris"]""", - }, - ) - t = Tester(State(leader=True, relations=[zk])) - t.run(zk.changed_event) - # t.run("config-changed") - t.assert_schema_valid() diff --git a/interfaces/zookeeper/v0/schema.py b/interfaces/zookeeper/v0/schema.py index e57a79a3..2f72d918 100644 --- a/interfaces/zookeeper/v0/schema.py +++ b/interfaces/zookeeper/v0/schema.py @@ -17,7 +17,7 @@ ) -class URI(BaseModel): +class Endpoint(BaseModel): ip: IPvAnyAddress port: conint(ge=0, le=65535) | None @@ -29,8 +29,7 @@ def __init__(self, value: str) -> None: def parse_endpoints(value: str): - uris, _, znode = value.partition("/") - [URI(val) for val in uris.split(",")] + [Endpoint(val) for val in value.split(",")] Endpoints = Annotated[str, AfterValidator(parse_endpoints)] @@ -46,7 +45,7 @@ class ZookeeperProviderAppData(BaseModel): endpoints: Endpoints = Field( description="A comma-seperated list of ZooKeeper server and ports", examples=["10.141.78.133:2181,10.141.78.50:2181,10.141.78.45:2181"], - title="ZooKeeper URIs", + title="ZooKeeper endpoints", ) secret_user: str = Field( From 1876a7152fe8f3fc8818931aa38391199083e9d2 Mon Sep 17 00:00:00 2001 From: Alex Batisse Date: Thu, 2 May 2024 14:41:33 +0200 Subject: [PATCH 15/24] chore: Remove old schema dir --- .../zookeeper_client/v0/provider.json | 82 ------------------- .../zookeeper_client/v0/requirer.json | 65 --------------- 2 files changed, 147 deletions(-) delete mode 100644 docs/json_schemas/zookeeper_client/v0/provider.json delete mode 100644 docs/json_schemas/zookeeper_client/v0/requirer.json diff --git a/docs/json_schemas/zookeeper_client/v0/provider.json b/docs/json_schemas/zookeeper_client/v0/provider.json deleted file mode 100644 index 23c82459..00000000 --- a/docs/json_schemas/zookeeper_client/v0/provider.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "$defs": { - "BaseModel": { - "properties": {}, - "title": "BaseModel", - "type": "object" - }, - "ZookeeperProviderAppData": { - "properties": { - "database": { - "description": "The parent chroot zNode granted to the requirer", - "examples": [ - "/myappB" - ], - "title": "zNode", - "type": "string" - }, - "endpoints": { - "description": "A comma-seperated list of ZooKeeper server uris, and parent chroot zNode", - "examples": [ - "10.141.78.133:2181,10.141.78.50:2181,10.141.78.45:2181/myappB" - ], - "title": "ZooKeeper URIs", - "type": "string" - }, - "secret-user": { - "description": "", - "examples": [ - "secret://59060ecc-0495-4a80-8006-5f1fc13fd783/cjqub6vubg2s77p3nio0" - ], - "title": "Credentials Secret Name", - "type": "string" - }, - "secret-tls": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "The name of the TLS secret to use. Leaving this empty will configure a client with TLS disabled.", - "examples": [ - "secret://59060ecc-0495-4a80-8006-5f1fc13fd783/cjqub7fubg2s77p3niog" - ], - "title": "TLS Secret Name" - } - }, - "required": [ - "database", - "endpoints", - "secret-user" - ], - "title": "ZookeeperProviderAppData", - "type": "object" - } - }, - "description": "The schema for the provider side of this interface.", - "properties": { - "unit": { - "anyOf": [ - { - "$ref": "#/$defs/BaseModel" - }, - { - "type": "null" - } - ], - "default": null - }, - "app": { - "$ref": "#/$defs/ZookeeperProviderAppData" - } - }, - "required": [ - "app" - ], - "title": "ProviderSchema", - "type": "object" -} \ No newline at end of file diff --git a/docs/json_schemas/zookeeper_client/v0/requirer.json b/docs/json_schemas/zookeeper_client/v0/requirer.json deleted file mode 100644 index 8d252214..00000000 --- a/docs/json_schemas/zookeeper_client/v0/requirer.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "$defs": { - "BaseModel": { - "properties": {}, - "title": "BaseModel", - "type": "object" - }, - "ZookeeperRequirerAppData": { - "properties": { - "database": { - "description": "The parent chroot zNode requested by the requirer", - "examples": [ - "/myappA" - ], - "title": "zNode", - "type": "string" - }, - "requested-secrets": { - "description": "Any provider field which should be transfered as Juju Secret", - "examples": [ - [ - "username", - "password", - "tls-ca", - "uris" - ] - ], - "items": { - "type": "string" - }, - "title": "Requested secrets", - "type": "array" - } - }, - "required": [ - "database", - "requested-secrets" - ], - "title": "ZookeeperRequirerAppData", - "type": "object" - } - }, - "description": "The schema for the requirer side of this interface.", - "properties": { - "unit": { - "anyOf": [ - { - "$ref": "#/$defs/BaseModel" - }, - { - "type": "null" - } - ], - "default": null - }, - "app": { - "$ref": "#/$defs/ZookeeperRequirerAppData" - } - }, - "required": [ - "app" - ], - "title": "RequirerSchema", - "type": "object" -} \ No newline at end of file From ca2f1f3612ca1f8d57dabe769161ea4fdfea2db4 Mon Sep 17 00:00:00 2001 From: Alex Batisse Date: Thu, 2 May 2024 14:47:56 +0200 Subject: [PATCH 16/24] Update zookeeper charms list --- interfaces/zookeeper/v0/charms.yaml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/interfaces/zookeeper/v0/charms.yaml b/interfaces/zookeeper/v0/charms.yaml index de2d3204..8697d9da 100644 --- a/interfaces/zookeeper/v0/charms.yaml +++ b/interfaces/zookeeper/v0/charms.yaml @@ -2,14 +2,13 @@ providers: # list of charms using this interface as providers - name: zookeeper url: https://github.com/canonical/zookeeper-operator - branch: feat/DPE-3737-client-interface - # - name: zookeeper-k8s - # url: https://github.com/canonical/zookeeper-k8s-operator + - name: zookeeper-k8s + url: https://github.com/canonical/zookeeper-k8s-operator # list of charms using this interface as requirers. # same structure as providers -requirers: [] - # - name: kafka - # url: https://github.com/canonical/kafka-operator - # - name: kafka-k8s - # url: https://github.com/canonical/kafka-k8s-operator +requirers: + - name: kafka + url: https://github.com/canonical/kafka-operator + - name: kafka-k8s + url: https://github.com/canonical/kafka-k8s-operator From 9b7d5e2d38fbdc7a122f693570a05a1cf3c626f7 Mon Sep 17 00:00:00 2001 From: Alex Batisse Date: Wed, 4 Sep 2024 17:15:57 +0200 Subject: [PATCH 17/24] fix: Rename charms.yaml to interface.yaml --- docs/json_schemas/zookeeper/v0/requirer.json | 18 +++++++++++++++++- interfaces/zookeeper/v0/README.md | 2 ++ interfaces/zookeeper/v0/charms.yaml | 14 -------------- interfaces/zookeeper/v0/interface.yaml | 12 ++++++++++++ .../v0/interface_tests/test_requirer.py | 4 ++++ interfaces/zookeeper/v0/schema.py | 9 ++++++++- 6 files changed, 43 insertions(+), 16 deletions(-) delete mode 100644 interfaces/zookeeper/v0/charms.yaml create mode 100644 interfaces/zookeeper/v0/interface.yaml diff --git a/docs/json_schemas/zookeeper/v0/requirer.json b/docs/json_schemas/zookeeper/v0/requirer.json index 8df8b711..21a60d3b 100644 --- a/docs/json_schemas/zookeeper/v0/requirer.json +++ b/docs/json_schemas/zookeeper/v0/requirer.json @@ -46,11 +46,27 @@ }, "title": "Requested secrets", "type": "array" + }, + "secret-mtls": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The name of the mTLS secret to use. Leaving this empty will configure the provider to not use mTLS.", + "examples": [ + "secret://59060ecc-0495-4a80-8006-5f1fc13fd783/cjqub7fubg2s77p3niog" + ], + "title": "mTLS Secret Name" } }, "required": [ "database", - "requested-secrets" + "requested-secrets", + "secret-mtls" ], "title": "ZookeeperRequirerAppData", "type": "object" diff --git a/interfaces/zookeeper/v0/README.md b/interfaces/zookeeper/v0/README.md index b67c3e19..2a42622e 100644 --- a/interfaces/zookeeper/v0/README.md +++ b/interfaces/zookeeper/v0/README.md @@ -27,6 +27,7 @@ Both the Requirer and the Provider need to adhere to criteria to be considered c - Is expected to provide the CA chain in the `tls-ca` field of a Juju Secret, whenever the provider has TLS enabled (such as using the [TLS Certificates Operator](https://github.com/canonical/tls-certificates-operator)). - Is expected to share the TLS Juju Secret URI through the `secret-tls` field of the databag. - If the Requirer asks for additional secrets (via `requested-secrets`, see below) other than those stored in the `user` and `tls` secrets, Provider is expected to define a `secret-extra` field holding the URI of the Juju Secret containing all additional secret fields. +- If the Requirer both requested the `tls-ca` and provided `secret-mtls`, the Provider should use enable mTLS. ### Requirer @@ -37,6 +38,7 @@ Both the Requirer and the Provider need to adhere to criteria to be considered c - Is expected to allow multiple different Juju applications to access the same zNode. - Is expected to tolerate that the Provider may ignore the `database` field in some cases and instead use the zNode received. - Can optionally provide the `extra-user-roles` field specifying a ACL string for the client application. +- Can optionally provide the mTLS Juju Secret Uri through the `secret-mtls` field of the databag ## Relation Data diff --git a/interfaces/zookeeper/v0/charms.yaml b/interfaces/zookeeper/v0/charms.yaml deleted file mode 100644 index 8697d9da..00000000 --- a/interfaces/zookeeper/v0/charms.yaml +++ /dev/null @@ -1,14 +0,0 @@ -providers: - # list of charms using this interface as providers - - name: zookeeper - url: https://github.com/canonical/zookeeper-operator - - name: zookeeper-k8s - url: https://github.com/canonical/zookeeper-k8s-operator - -# list of charms using this interface as requirers. -# same structure as providers -requirers: - - name: kafka - url: https://github.com/canonical/kafka-operator - - name: kafka-k8s - url: https://github.com/canonical/kafka-k8s-operator diff --git a/interfaces/zookeeper/v0/interface.yaml b/interfaces/zookeeper/v0/interface.yaml new file mode 100644 index 00000000..f47eb1da --- /dev/null +++ b/interfaces/zookeeper/v0/interface.yaml @@ -0,0 +1,12 @@ +providers: + # - name: zookeeper + # url: https://github.com/canonical/zookeeper-operator + - name: zookeeper-k8s + url: https://github.com/canonical/zookeeper-k8s-operator + branch: feat/interface-tester + +requirers: [] + # - name: kafka + # url: https://github.com/canonical/kafka-operator + # - name: kafka-k8s + # url: https://github.com/canonical/kafka-k8s-operator diff --git a/interfaces/zookeeper/v0/interface_tests/test_requirer.py b/interfaces/zookeeper/v0/interface_tests/test_requirer.py index d0fc2366..2f642424 100644 --- a/interfaces/zookeeper/v0/interface_tests/test_requirer.py +++ b/interfaces/zookeeper/v0/interface_tests/test_requirer.py @@ -1 +1,5 @@ # TODO: add here interface tests for the requirer side + + +def test_pass(): + pass diff --git a/interfaces/zookeeper/v0/schema.py b/interfaces/zookeeper/v0/schema.py index 2f72d918..ee0309b6 100644 --- a/interfaces/zookeeper/v0/schema.py +++ b/interfaces/zookeeper/v0/schema.py @@ -76,7 +76,7 @@ class ZookeeperRequirerAppData(BaseModel): alias="extra-user-roles", description="ACL string representation for the parent chroot", examples=["cdrwa"], - title="User roles" + title="User roles", ) requested_secrets: list[str] = Field( @@ -86,6 +86,13 @@ class ZookeeperRequirerAppData(BaseModel): title="Requested secrets", ) + secret_mtls: str | None = Field( + alias="secret-mtls", + description="The name of the mTLS secret to use. Leaving this empty will configure the provider to not use mTLS.", + examples=["secret://59060ecc-0495-4a80-8006-5f1fc13fd783/cjqub7fubg2s77p3niog"], + title="mTLS Secret Name" + ) + class ProviderSchema(DataBagSchema): """The schema for the provider side of this interface.""" From 7d9571300a43568067fe7eac666057c9885146e7 Mon Sep 17 00:00:00 2001 From: Alex Batisse Date: Wed, 4 Sep 2024 17:27:11 +0200 Subject: [PATCH 18/24] fix: Add missing fields in zk interfaces.yaml Still need to remove 'branch' upon upstream merge --- interfaces/zookeeper/v0/interface.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/interfaces/zookeeper/v0/interface.yaml b/interfaces/zookeeper/v0/interface.yaml index f47eb1da..74159649 100644 --- a/interfaces/zookeeper/v0/interface.yaml +++ b/interfaces/zookeeper/v0/interface.yaml @@ -1,3 +1,7 @@ +name: zookeeper +version: 0 +status: draft + providers: # - name: zookeeper # url: https://github.com/canonical/zookeeper-operator From 0563817406230604a170cda1eed26fb8f4cfaa01 Mon Sep 17 00:00:00 2001 From: Alex Batisse Date: Thu, 5 Sep 2024 18:01:56 +0200 Subject: [PATCH 19/24] tests: Add zookeeper provider tests --- docs/json_schemas/zookeeper/v0/provider.json | 6 +- docs/json_schemas/zookeeper/v0/requirer.json | 6 +- interfaces/__init__.py | 0 .../v0/interface_tests/test_provider.py | 90 +++++++++++++++---- interfaces/zookeeper/v0/schema.py | 19 ++-- 5 files changed, 87 insertions(+), 34 deletions(-) create mode 100644 interfaces/__init__.py diff --git a/docs/json_schemas/zookeeper/v0/provider.json b/docs/json_schemas/zookeeper/v0/provider.json index 73ce1c98..fb330a0b 100644 --- a/docs/json_schemas/zookeeper/v0/provider.json +++ b/docs/json_schemas/zookeeper/v0/provider.json @@ -5,7 +5,7 @@ "title": "BaseModel", "type": "object" }, - "ZookeeperProviderAppData": { + "ZooKeeperProviderAppData": { "properties": { "database": { "description": "The parent chroot zNode granted to the requirer", @@ -53,7 +53,7 @@ "endpoints", "secret-user" ], - "title": "ZookeeperProviderAppData", + "title": "ZooKeeperProviderAppData", "type": "object" } }, @@ -71,7 +71,7 @@ "default": null }, "app": { - "$ref": "#/$defs/ZookeeperProviderAppData" + "$ref": "#/$defs/ZooKeeperProviderAppData" } }, "required": [ diff --git a/docs/json_schemas/zookeeper/v0/requirer.json b/docs/json_schemas/zookeeper/v0/requirer.json index 21a60d3b..9e8b6fa9 100644 --- a/docs/json_schemas/zookeeper/v0/requirer.json +++ b/docs/json_schemas/zookeeper/v0/requirer.json @@ -5,7 +5,7 @@ "title": "BaseModel", "type": "object" }, - "ZookeeperRequirerAppData": { + "ZooKeeperRequirerAppData": { "properties": { "database": { "description": "The parent chroot zNode requested by the requirer", @@ -68,7 +68,7 @@ "requested-secrets", "secret-mtls" ], - "title": "ZookeeperRequirerAppData", + "title": "ZooKeeperRequirerAppData", "type": "object" } }, @@ -86,7 +86,7 @@ "default": null }, "app": { - "$ref": "#/$defs/ZookeeperRequirerAppData" + "$ref": "#/$defs/ZooKeeperRequirerAppData" } }, "required": [ diff --git a/interfaces/__init__.py b/interfaces/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/interfaces/zookeeper/v0/interface_tests/test_provider.py b/interfaces/zookeeper/v0/interface_tests/test_provider.py index 7782a56d..e535cd39 100644 --- a/interfaces/zookeeper/v0/interface_tests/test_provider.py +++ b/interfaces/zookeeper/v0/interface_tests/test_provider.py @@ -1,30 +1,88 @@ -from scenario import State, Relation, PeerRelation +from scenario import Secret, State, Relation, PeerRelation from interface_tester import Tester -def test_no_data_on_created(): - t = Tester( - State( - leader=True, - relations=[Relation(endpoint="database", interface="zookeeper")], - ) - ) - t.run("database-relation-created") - t.assert_relation_data_empty() +# def test_no_data_on_created(): +# t = Tester( +# State( +# leader=True, +# relations=[Relation(endpoint="zookeeper", interface="zookeeper")], +# ) +# ) +# t.run("database-relation-created") +# t.assert_relation_data_empty() + + +# def test_no_data_on_joined(): +# t = Tester( +# State( +# leader=True, +# relations=[ +# Relation( +# endpoint="zookeeper", +# interface="zookeeper", +# ) +# ], +# ) +# ) +# t.run("database-relation-joined") +# t.assert_relation_data_empty() -def test_no_data_on_joined(): +# def test_database_requested(): +# t = Tester( +# State( +# leader=True, +# relations=[ +# Relation( +# endpoint="zookeeper", +# interface="zookeeper", +# remote_app_data={ +# "database": "lotr", +# "requested-secrets": '["username","password","tls","tls-ca","uris"]', +# }, +# ) +# ], +# ) +# ) +# state = t.run("zookeeper-relation-changed") +# t.assert_relation_data_empty() + + +def test_database_creds_in_secrets(): + secrets = [ + Secret( + id="secret:20171337734412181011", + contents={0: {"relation-1": "speakfriend"}}, + owner="app", + revision=0, + remote_grants={}, + label="cluster.zookeeper-k8s.app", + description=None, + expire=None, + rotate=None, + ) + ] + + cluster_peer = PeerRelation( + "cluster", "cluster", local_app_data={str(i): "added" for i in range(4)} + ) t = Tester( State( leader=True, relations=[ + cluster_peer, Relation( - endpoint="database", + endpoint="zookeeper", interface="zookeeper", - ) + remote_app_data={ + "database": "lotr", + "requested-secrets": '["username","password","tls","tls-ca","uris"]', + }, + ), ], + secrets=secrets, ) ) - t.run("database-relation-joined") - t.assert_relation_data_empty() - + state = t.run("cluster-relation-changed") + t.assert_schema_valid() diff --git a/interfaces/zookeeper/v0/schema.py b/interfaces/zookeeper/v0/schema.py index ee0309b6..4a9982c0 100644 --- a/interfaces/zookeeper/v0/schema.py +++ b/interfaces/zookeeper/v0/schema.py @@ -5,11 +5,10 @@ - RequirerSchema """ -from typing import Annotated +from typing import Annotated, TypeAlias from interface_tester.schema_base import DataBagSchema from pydantic import ( - AfterValidator, BaseModel, Field, IPvAnyAddress, @@ -28,14 +27,10 @@ def __init__(self, value: str) -> None: super().__init__(ip=ip, port=port) -def parse_endpoints(value: str): - [Endpoint(val) for val in value.split(",")] +Endpoints: TypeAlias = str -Endpoints = Annotated[str, AfterValidator(parse_endpoints)] - - -class ZookeeperProviderAppData(BaseModel): +class ZooKeeperProviderAppData(BaseModel): database: str = Field( description="The parent chroot zNode granted to the requirer", examples=["/myappB"], @@ -64,7 +59,7 @@ class ZookeeperProviderAppData(BaseModel): ) -class ZookeeperRequirerAppData(BaseModel): +class ZooKeeperRequirerAppData(BaseModel): database: str = Field( description="The parent chroot zNode requested by the requirer", examples=["/myappA"], @@ -90,17 +85,17 @@ class ZookeeperRequirerAppData(BaseModel): alias="secret-mtls", description="The name of the mTLS secret to use. Leaving this empty will configure the provider to not use mTLS.", examples=["secret://59060ecc-0495-4a80-8006-5f1fc13fd783/cjqub7fubg2s77p3niog"], - title="mTLS Secret Name" + title="mTLS Secret Name", ) class ProviderSchema(DataBagSchema): """The schema for the provider side of this interface.""" - app: ZookeeperProviderAppData + app: ZooKeeperProviderAppData class RequirerSchema(DataBagSchema): """The schema for the requirer side of this interface.""" - app: ZookeeperRequirerAppData + app: ZooKeeperRequirerAppData From cd17bfdb619f292240182ea94998ee1d2f043c56 Mon Sep 17 00:00:00 2001 From: Alex Batisse Date: Fri, 6 Sep 2024 11:48:38 +0200 Subject: [PATCH 20/24] fix: Remove tests & add kyuubi to zookeeper requirers --- interfaces/zookeeper/v0/interface.yaml | 17 ++-- .../zookeeper/v0/interface_tests/README.md | 33 ------- .../v0/interface_tests/test_provider.py | 88 ------------------- .../v0/interface_tests/test_requirer.py | 5 -- 4 files changed, 9 insertions(+), 134 deletions(-) delete mode 100644 interfaces/zookeeper/v0/interface_tests/README.md delete mode 100644 interfaces/zookeeper/v0/interface_tests/test_provider.py delete mode 100644 interfaces/zookeeper/v0/interface_tests/test_requirer.py diff --git a/interfaces/zookeeper/v0/interface.yaml b/interfaces/zookeeper/v0/interface.yaml index 74159649..6d43f4a4 100644 --- a/interfaces/zookeeper/v0/interface.yaml +++ b/interfaces/zookeeper/v0/interface.yaml @@ -3,14 +3,15 @@ version: 0 status: draft providers: - # - name: zookeeper - # url: https://github.com/canonical/zookeeper-operator + - name: zookeeper + url: https://github.com/canonical/zookeeper-operator - name: zookeeper-k8s url: https://github.com/canonical/zookeeper-k8s-operator - branch: feat/interface-tester -requirers: [] - # - name: kafka - # url: https://github.com/canonical/kafka-operator - # - name: kafka-k8s - # url: https://github.com/canonical/kafka-k8s-operator +requirers: + - name: kafka + url: https://github.com/canonical/kafka-operator + - name: kafka-k8s + url: https://github.com/canonical/kafka-k8s-operator + - name: kyuubi-k8s-operator + url: https://github.com/canonical/kyuubi-k8s-operator diff --git a/interfaces/zookeeper/v0/interface_tests/README.md b/interfaces/zookeeper/v0/interface_tests/README.md deleted file mode 100644 index 00ed852c..00000000 --- a/interfaces/zookeeper/v0/interface_tests/README.md +++ /dev/null @@ -1,33 +0,0 @@ -This directory is meant to contain the tests for your interface, so that it is possible to programmatically verify its implementations. - -Find some relevant documentation at: -- [Interface Tests](https://discourse.charmhub.io/t/interface-tests/12691) -- [How to write interface tests](https://discourse.charmhub.io/t/how-to-write-interface-tests/12690) - -## Quickstart - -Copy this test to `test_provider.py` and fill in the blanks however appropriate for your interfaces - -```python -from scenario import Relation, State -from interface_tester import Tester - -def test_data_published_on_changed_remote_valid(): - # GIVEN a relation over containing all the right data - # in the right format for the : - relation = Relation( - endpoint='ingress', - interface='ingress', remote_app_name='remote', - remote_app_data={'foo': '"bar"', 'baz': '42', 'qux': '"www.lol.com:4242"', }, - remote_units_data={0: {'fizz': 'buzz', }}) - t = Tester( - State(relations=[relation]) - ) - - # WHEN the receives a event: - t.run(relation.changed_event) - - # THEN the also publishes valid data to its side of the relation - # (if applicable) - t.assert_schema_valid() -``` diff --git a/interfaces/zookeeper/v0/interface_tests/test_provider.py b/interfaces/zookeeper/v0/interface_tests/test_provider.py deleted file mode 100644 index e535cd39..00000000 --- a/interfaces/zookeeper/v0/interface_tests/test_provider.py +++ /dev/null @@ -1,88 +0,0 @@ -from scenario import Secret, State, Relation, PeerRelation -from interface_tester import Tester - - -# def test_no_data_on_created(): -# t = Tester( -# State( -# leader=True, -# relations=[Relation(endpoint="zookeeper", interface="zookeeper")], -# ) -# ) -# t.run("database-relation-created") -# t.assert_relation_data_empty() - - -# def test_no_data_on_joined(): -# t = Tester( -# State( -# leader=True, -# relations=[ -# Relation( -# endpoint="zookeeper", -# interface="zookeeper", -# ) -# ], -# ) -# ) -# t.run("database-relation-joined") -# t.assert_relation_data_empty() - - -# def test_database_requested(): -# t = Tester( -# State( -# leader=True, -# relations=[ -# Relation( -# endpoint="zookeeper", -# interface="zookeeper", -# remote_app_data={ -# "database": "lotr", -# "requested-secrets": '["username","password","tls","tls-ca","uris"]', -# }, -# ) -# ], -# ) -# ) -# state = t.run("zookeeper-relation-changed") -# t.assert_relation_data_empty() - - -def test_database_creds_in_secrets(): - secrets = [ - Secret( - id="secret:20171337734412181011", - contents={0: {"relation-1": "speakfriend"}}, - owner="app", - revision=0, - remote_grants={}, - label="cluster.zookeeper-k8s.app", - description=None, - expire=None, - rotate=None, - ) - ] - - cluster_peer = PeerRelation( - "cluster", "cluster", local_app_data={str(i): "added" for i in range(4)} - ) - t = Tester( - State( - leader=True, - relations=[ - cluster_peer, - Relation( - endpoint="zookeeper", - interface="zookeeper", - remote_app_data={ - "database": "lotr", - "requested-secrets": '["username","password","tls","tls-ca","uris"]', - }, - ), - ], - secrets=secrets, - ) - ) - state = t.run("cluster-relation-changed") - t.assert_schema_valid() diff --git a/interfaces/zookeeper/v0/interface_tests/test_requirer.py b/interfaces/zookeeper/v0/interface_tests/test_requirer.py deleted file mode 100644 index 2f642424..00000000 --- a/interfaces/zookeeper/v0/interface_tests/test_requirer.py +++ /dev/null @@ -1,5 +0,0 @@ -# TODO: add here interface tests for the requirer side - - -def test_pass(): - pass From 41240216a0e3527e61c3c2d815c0e285279a09fc Mon Sep 17 00:00:00 2001 From: Alex Batisse Date: Fri, 6 Sep 2024 11:54:37 +0200 Subject: [PATCH 21/24] chore: Remove __init__.py from interfaces root folder A leftover from some testing --- interfaces/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 interfaces/__init__.py diff --git a/interfaces/__init__.py b/interfaces/__init__.py deleted file mode 100644 index e69de29b..00000000 From 31afb083cafc1fa63b7ec3894a5cbaa099edb5fd Mon Sep 17 00:00:00 2001 From: Alex Batisse Date: Fri, 6 Sep 2024 17:49:05 +0200 Subject: [PATCH 22/24] fix: Add secret_user description field --- docs/json_schemas/zookeeper/v0/provider.json | 4 ++-- interfaces/zookeeper/v0/schema.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/json_schemas/zookeeper/v0/provider.json b/docs/json_schemas/zookeeper/v0/provider.json index fb330a0b..a635c042 100644 --- a/docs/json_schemas/zookeeper/v0/provider.json +++ b/docs/json_schemas/zookeeper/v0/provider.json @@ -24,7 +24,7 @@ "type": "string" }, "secret-user": { - "description": "", + "description": "The credentials to connect to ZooKeeper. The secret contains [user,password,uris].", "examples": [ "secret://59060ecc-0495-4a80-8006-5f1fc13fd783/cjqub6vubg2s77p3nio0" ], @@ -41,7 +41,7 @@ } ], "default": null, - "description": "The name of the TLS secret to use. Leaving this empty will configure a client with TLS disabled.", + "description": "The name of the TLS secret to use. Leaving this empty will configure a client with TLS disabled. The secret contains [tls].", "examples": [ "secret://59060ecc-0495-4a80-8006-5f1fc13fd783/cjqub7fubg2s77p3niog" ], diff --git a/interfaces/zookeeper/v0/schema.py b/interfaces/zookeeper/v0/schema.py index 4a9982c0..0889cba1 100644 --- a/interfaces/zookeeper/v0/schema.py +++ b/interfaces/zookeeper/v0/schema.py @@ -45,7 +45,7 @@ class ZooKeeperProviderAppData(BaseModel): secret_user: str = Field( alias="secret-user", - description="", + description="The credentials to connect to ZooKeeper. The secret contains [user,password,uris].", examples=["secret://59060ecc-0495-4a80-8006-5f1fc13fd783/cjqub6vubg2s77p3nio0"], title="Credentials Secret Name", ) @@ -53,7 +53,7 @@ class ZooKeeperProviderAppData(BaseModel): secret_tls: str | None = Field( None, alias="secret-tls", - description="The name of the TLS secret to use. Leaving this empty will configure a client with TLS disabled.", + description="The name of the TLS secret to use. Leaving this empty will configure a client with TLS disabled. The secret contains [tls].", examples=["secret://59060ecc-0495-4a80-8006-5f1fc13fd783/cjqub7fubg2s77p3niog"], title="TLS Secret Name", ) From c8704aa45cb76badaa5be58459f0c301ea8b5b47 Mon Sep 17 00:00:00 2001 From: Alex Batisse Date: Mon, 9 Sep 2024 09:48:21 +0200 Subject: [PATCH 23/24] fix: Remove mtls secret field from zookeeper requirer --- docs/json_schemas/zookeeper/v0/requirer.json | 18 +----------------- interfaces/zookeeper/v0/README.md | 2 -- interfaces/zookeeper/v0/schema.py | 9 +-------- 3 files changed, 2 insertions(+), 27 deletions(-) diff --git a/docs/json_schemas/zookeeper/v0/requirer.json b/docs/json_schemas/zookeeper/v0/requirer.json index 9e8b6fa9..0f22c0d9 100644 --- a/docs/json_schemas/zookeeper/v0/requirer.json +++ b/docs/json_schemas/zookeeper/v0/requirer.json @@ -46,27 +46,11 @@ }, "title": "Requested secrets", "type": "array" - }, - "secret-mtls": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The name of the mTLS secret to use. Leaving this empty will configure the provider to not use mTLS.", - "examples": [ - "secret://59060ecc-0495-4a80-8006-5f1fc13fd783/cjqub7fubg2s77p3niog" - ], - "title": "mTLS Secret Name" } }, "required": [ "database", - "requested-secrets", - "secret-mtls" + "requested-secrets" ], "title": "ZooKeeperRequirerAppData", "type": "object" diff --git a/interfaces/zookeeper/v0/README.md b/interfaces/zookeeper/v0/README.md index 2a42622e..b67c3e19 100644 --- a/interfaces/zookeeper/v0/README.md +++ b/interfaces/zookeeper/v0/README.md @@ -27,7 +27,6 @@ Both the Requirer and the Provider need to adhere to criteria to be considered c - Is expected to provide the CA chain in the `tls-ca` field of a Juju Secret, whenever the provider has TLS enabled (such as using the [TLS Certificates Operator](https://github.com/canonical/tls-certificates-operator)). - Is expected to share the TLS Juju Secret URI through the `secret-tls` field of the databag. - If the Requirer asks for additional secrets (via `requested-secrets`, see below) other than those stored in the `user` and `tls` secrets, Provider is expected to define a `secret-extra` field holding the URI of the Juju Secret containing all additional secret fields. -- If the Requirer both requested the `tls-ca` and provided `secret-mtls`, the Provider should use enable mTLS. ### Requirer @@ -38,7 +37,6 @@ Both the Requirer and the Provider need to adhere to criteria to be considered c - Is expected to allow multiple different Juju applications to access the same zNode. - Is expected to tolerate that the Provider may ignore the `database` field in some cases and instead use the zNode received. - Can optionally provide the `extra-user-roles` field specifying a ACL string for the client application. -- Can optionally provide the mTLS Juju Secret Uri through the `secret-mtls` field of the databag ## Relation Data diff --git a/interfaces/zookeeper/v0/schema.py b/interfaces/zookeeper/v0/schema.py index 0889cba1..9af3e3db 100644 --- a/interfaces/zookeeper/v0/schema.py +++ b/interfaces/zookeeper/v0/schema.py @@ -5,7 +5,7 @@ - RequirerSchema """ -from typing import Annotated, TypeAlias +from typing import TypeAlias from interface_tester.schema_base import DataBagSchema from pydantic import ( @@ -81,13 +81,6 @@ class ZooKeeperRequirerAppData(BaseModel): title="Requested secrets", ) - secret_mtls: str | None = Field( - alias="secret-mtls", - description="The name of the mTLS secret to use. Leaving this empty will configure the provider to not use mTLS.", - examples=["secret://59060ecc-0495-4a80-8006-5f1fc13fd783/cjqub7fubg2s77p3niog"], - title="mTLS Secret Name", - ) - class ProviderSchema(DataBagSchema): """The schema for the provider side of this interface.""" From 8687e858332bbbbab6041c4cfbfd48136fd11b9f Mon Sep 17 00:00:00 2001 From: Alex Batisse Date: Mon, 20 Jan 2025 12:18:12 +0100 Subject: [PATCH 24/24] refactor: Remove unused Endpoint model --- interfaces/zookeeper/v0/schema.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/interfaces/zookeeper/v0/schema.py b/interfaces/zookeeper/v0/schema.py index 9af3e3db..9ed75d9b 100644 --- a/interfaces/zookeeper/v0/schema.py +++ b/interfaces/zookeeper/v0/schema.py @@ -11,22 +11,9 @@ from pydantic import ( BaseModel, Field, - IPvAnyAddress, - conint, ) -class Endpoint(BaseModel): - ip: IPvAnyAddress - port: conint(ge=0, le=65535) | None - - def __init__(self, value: str) -> None: - ip, _, port = value.partition(":") - if not port: - port = None - super().__init__(ip=ip, port=port) - - Endpoints: TypeAlias = str