Skip to content

fix!: Make fields on S3 structs mandatory, add S3 helpers #863

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

Merged
merged 30 commits into from
Sep 19, 2024

Conversation

sbernauer
Copy link
Member

@sbernauer sbernauer commented Sep 11, 2024

Description

Reviving #679 (replacing it)

Example usage is in https://github.com/stackabletech/trino-operator/tree/chore/new-s3-structs

Definition of Done Checklist

  • Not all of these items are applicable to all PRs, the author should update this template to only leave the boxes in that are relevant
  • Please make sure all these things are done and tick the boxes
# Author
- [ ] Changes are OpenShift compatible
- [ ] CRD changes approved
- [ ] Integration tests passed (for non trivial changes)
# Reviewer
- [ ] Code contains useful comments
- [ ] (Integration-)Test cases added
- [ ] Documentation added or updated
- [ ] Changelog updated
- [ ] Cargo.toml only contains references to git tags (not specific commits or branches)
# Acceptance
- [ ] Feature Tracker has been updated
- [ ] Proper release label has been added

Copy link
Member

@NickLarsenNZ NickLarsenNZ left a comment

Choose a reason for hiding this comment

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

Partial review (as I see changes are still coming in)

@Techassi Techassi self-requested a review September 12, 2024 09:24
Copy link
Member

@NickLarsenNZ NickLarsenNZ left a comment

Choose a reason for hiding this comment

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

Partial review again :)

sbernauer and others added 3 commits September 12, 2024 12:08
Co-authored-by: Nick <10092581+NickLarsenNZ@users.noreply.github.com>
Copy link
Member

@Techassi Techassi left a comment

Choose a reason for hiding this comment

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

I didn't look at the S3 stuff super closely (I can if you want @sbernauer). The TLS code looks fine (as it is copy+pasted from the previous location).

All other comments are minor notes / suggestions.

@sbernauer sbernauer requested review from Techassi and NickLarsenNZ and removed request for NickLarsenNZ September 16, 2024 13:46
Copy link
Member

@Techassi Techassi left a comment

Choose a reason for hiding this comment

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

LGTM, only minor changes.

sbernauer and others added 3 commits September 18, 2024 12:41
Co-authored-by: Techassi <git@techassi.dev>
Co-authored-by: Techassi <git@techassi.dev>
Co-authored-by: Techassi <git@techassi.dev>
@sbernauer sbernauer requested a review from Techassi September 18, 2024 10:42
@sbernauer sbernauer marked this pull request as ready for review September 19, 2024 08:07
@Techassi Techassi changed the title fix!: Make fields on S3 structs mandatory. Also offer helper functions fix!: Make fields on S3 structs mandatory, add S3 helpers Sep 19, 2024
Copy link
Member

@Techassi Techassi left a comment

Choose a reason for hiding this comment

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

LGTM overall, just three small comments.

@sbernauer sbernauer requested a review from Techassi September 19, 2024 08:57
@sbernauer sbernauer added this pull request to the merge queue Sep 19, 2024
Merged via the queue into main with commit a7e70f1 Sep 19, 2024
10 checks passed
@sbernauer sbernauer deleted the refactor/add-host-struct branch September 19, 2024 09:31
Comment on lines +74 to +76
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
String::json_schema(gen)
}
Copy link
Member

Choose a reason for hiding this comment

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

This is effectively dropping the validation regex from the composite type.

Copy link
Member Author

Choose a reason for hiding this comment

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

You're right. So far we don't have any regex on HostName, but instead let IpAddr::parse do it's thing and try to parse it as domain name in case it#s not an IP.
We should be able to come up with an regex that accepts a DomainName, IPv4 or IPv6 address. But do you think it's worth the effort?

Copy link
Member

Choose a reason for hiding this comment

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

That's fair.

Comment on lines +64 to +67
pub enum HostName {
IpAddress(IpAddr),
DomainName(DomainName),
}
Copy link
Member

Choose a reason for hiding this comment

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

Do we actually care about distinguishing these cases?

Copy link
Member Author

Choose a reason for hiding this comment

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

I personally modeled it as String, but @Techassi suggested using an enum instead, which sounded fine to me. No preference from me.

Copy link
Member

Choose a reason for hiding this comment

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

The RFC calls for these two distinct variants of a hostname.

Why should we remove all the value we get from using proper types by just using a plain string? We could simplify the DomainName variant to use String, but I would definitely keep the enum.

Copy link
Member

Choose a reason for hiding this comment

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

Ultimately the question here is the purpose of the type. Detailed types makes sense for inspecting and manipulating the hostname. The original intent for Hostname was the much smaller scope of "make sure this opaque looks close enough to a hostname that it won't fuck up the syntax of the config file it's string-templated into".

Copy link
Member

Choose a reason for hiding this comment

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

looks close enough

If we want to achieve this, sure. But then why reference RFC 1123 and only vaguely conform to it. If we want to conform to various RFCs, we should do so as closely as possible.

Another region where we try to conform to an RFC (1035), we also completely miss the mark when validating domain labels. So I'm just trying to avoid the same thing happening here (even tho the domain name is not 100% valid).

Comment on lines +91 to +94
InvalidHostnameSnafu {
hostname: value.to_owned(),
}
.fail()
Copy link
Member

Choose a reason for hiding this comment

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

This is dropping the context for why validation failed.

Copy link
Member Author

Choose a reason for hiding this comment

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

At this code point we have access to an IpAdd::parse error and and regex validation error.

        if let Ok(ip) = value.parse::<IpAddr>() {
            return Ok(HostName::IpAddress(ip));
        }

        if let Ok(domain_name) = value.parse() {
            return Ok(HostName::DomainName(domain_name));
        };

        InvalidHostnameSnafu {
            hostname: value.to_owned(),
        }
        .fail()

Should we capture both errors and put them both in? E.g. "needs to be an ip, which it does'nt because of {error1}, and also is no domain name because of [error2}"?

Copy link
Member

Choose a reason for hiding this comment

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

That's one way, but it loses the error chain. Another alternative would be to guess based on a cursory inspection.. something like:

if value.starts_with(char::is_ascii_digit) || value.contains(':') {
    Ok(HostName::IpAddress(value.parse().context(InvalidIpAddressSnafu { hostname: value })?))
} else {
    Ok(HostName::DomainName(value.parse().context(InvalidDomainNameSnafu { hostname: value })?))
}

Copy link
Member

Choose a reason for hiding this comment

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

We could also do something like:

match value.parse::<IpAddr>() {
    Ok(ip_addr) => return Ok(Hostname::IpAddr(ip_addr)),
    Err(ip_err) => match value.parse::<DomainName>() {
        Ok(dn) => return Ok(Hostname::DomainName(dn)),
        Err(dn_err) => // return both errors
    }
}

Copy link
Member

Choose a reason for hiding this comment

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

Yes that's effectively what @sbernauer suggested. There problem is that there's no way for an Error to have multiple source()s, so we'd have to pick one primary and render the other one as unawkwardly as we can.

Copy link
Member

Choose a reason for hiding this comment

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

there's no way for an Error to have multiple source()s, so we'd have to pick one primary and render the other one as unawkwardly as we can.

That is indeed very true (and unfortunate). The cursed inspection is also kinda meh tho. I don't know if it helps (I assume not), RFC 1123 states that the host name should first tried to be parsed as an IP address. So at least we do the correct thing RFC-wise.

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.

4 participants