Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DPE-3737] Add a zookeeper_client interface #144

Open
wants to merge 19 commits into
base: main
Choose a base branch
from

Conversation

Batalex
Copy link

@Batalex Batalex commented Mar 15, 2024

This PR adds a zookeeper interface.

Notes:

Copy link
Contributor

@marcoppenheimer marcoppenheimer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some nitpicks and a couple suggestions! I haven't had a chance to go through with a fine-comb yet, but will do when the PR is open.

Overall it looks good! I haven't seen the Pydantic use for client-relation-interfaces yet, and I'm less familiar with what actually is expected for secret-relations, so I'll defer my opinions to those more in the know.

Oh, and I suggest you just open a branch in the repo, rather than using forks. Makes it easier whenever other people from the team want to make changes to a PR branch!

docs/json_schemas/zookeeper_client/v0/provider.json Outdated Show resolved Hide resolved
interfaces/zookeeper_client/v0/charms.yaml Outdated Show resolved Hide resolved
Comment on lines 6 to 8
# list of charms using this interface as requirers.
# same structure as providers
requirers: []
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

todo: Likewise, adding kafka and kafka-k8s here.
@deusebio - Are there any charms 'close' to using ZK that would be relevant here?

Copy link
Contributor

@deusebio deusebio Mar 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kyuubi most likely once we will attack HA, but right now we are just charming a first draft (with no HA). Should we be exhaustive when listing things here? Meaning, should we keep this list updates as new charm implement the relation from the requirer side? @gruyaume

interfaces/zookeeper_client/v0/schema.py Outdated Show resolved Hide resolved
interfaces/zookeeper_client/v0/schema.py Outdated Show resolved Hide resolved
interfaces/zookeeper_client/v0/schema.py Outdated Show resolved Hide resolved

### 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).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Right now, we pass a fluffy extra field tls=""|"enabled". Am I correct in assuming that once we implement this, we should be doing something like this?

if not tls-ca:
    do_non_tls_stuff()

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are not compelled to do so because the extra field can still be a part of the secret. We could do it, though

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would keep UX consistent with other charms. If the TLS is enabled condition can be checked with the existence of tls-ca on the secrets, I wsuppose we are good

Comment on lines 20 to 36
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)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Perhaps here it might be OK to loosen the typing from URI to just be string.

Then, we can add a validator in the class itself, something like:

from pydantic import validator
from ipaddress

class ZookeeperProviderAppData(BaseModel):
    endpoints: string = 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",
    )

	@validator("endpoints")
    @classmethod
    def is_comma_list_of_ips(cls, value: str) -> str | None:
        try:
            ips = [address.split(":") for address in value.split(",")]
            valid_ips = [ipaddress.ip_address(ip) for ip in ips]
        except Exception as e:
            raise ValueError(
                f"Value not a valid IP address: {e}"
            )
	
    @validator("endpoints")
    @classmethod
    def ports_are_the_same(cls, value: str) -> str | None:
        try:
            non_chroot = value.split("/")[0]
            ports = {int(address.split(":")[1]) for address in non_chroot.split(",")}
            if not len(ports) == 1:
                raise ValueError(
                    "Value does not contain the same port for every address"
                )
        except Exception as e:
            raise ValueError(
                f"Value does not contain valid ports: {e}"
            )

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using Annotated, this is equivalent, but I might have missed your point

interfaces/zookeeper_client/v0/schema.py Outdated Show resolved Hide resolved
@Batalex
Copy link
Author

Batalex commented Mar 19, 2024

Thanks for the review!

Oh, and I suggest you just open a branch in the repo, rather than using forks. Makes it easier whenever other people from the team want to make changes to a PR branch!

Unfortunately I don't have permission :(

@Batalex Batalex changed the title WIP: [DPE-3737] Add a zookeeper_client interface [DPE-3737] Add a zookeeper_client interface Mar 20, 2024
interfaces/zookeeper_client/v0/README.md Outdated Show resolved Hide resolved
interfaces/zookeeper_client/v0/README.md Outdated Show resolved Hide resolved
interfaces/zookeeper_client/v0/schema.py Outdated Show resolved Hide resolved
# GIVEN a relation over <interface> containing all the right data
# in the right format for the <requirer side>:
relation = Relation(
endpoint='ingress',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ingress? Is this a mistake?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comes from the template for new interfaces, tests are not implemented yet

@Batalex Batalex marked this pull request as ready for review May 2, 2024 12:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants