Skip to main content

mz_orchestratord/
lib.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10use std::fmt::Display;
11
12pub mod controller;
13pub mod k8s;
14pub mod metrics;
15pub mod tls;
16
17#[derive(Debug, thiserror::Error)]
18pub enum Error {
19    Anyhow(#[from] anyhow::Error),
20    Kube(#[from] kube::Error),
21    Reqwest(#[from] reqwest::Error),
22}
23
24impl Display for Error {
25    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26        match self {
27            Self::Anyhow(e) => write!(f, "{e}"),
28            Self::Kube(e) => write!(f, "{e}"),
29            Self::Reqwest(e) => write!(f, "{e}"),
30        }
31    }
32}
33
34/// Extracts the tag from an OCI image reference, correctly ignoring
35/// registry-host ports (`gcr.io:443/...`) and `@sha256:` digests.
36pub fn parse_image_tag(image_ref: &str) -> Option<&str> {
37    let before_digest = image_ref.split('@').next().unwrap_or(image_ref);
38    let name_part = before_digest
39        .rsplit_once('/')
40        .map_or(before_digest, |(_, n)| n);
41    name_part.rsplit_once(':').map(|(_, tag)| tag)
42}
43
44pub fn matching_image_from_environmentd_image_ref(
45    environmentd_image_ref: &str,
46    image_name: &str,
47    image_tag: Option<&str>,
48) -> String {
49    let namespace = environmentd_image_ref
50        .rsplit_once('/')
51        .unwrap_or(("materialize", ""))
52        .0;
53    let tag = image_tag
54        .or_else(|| parse_image_tag(environmentd_image_ref))
55        .unwrap_or("latest");
56    format!("{namespace}/{image_name}:{tag}")
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62
63    #[mz_ore::test]
64    fn test_parse_image_tag() {
65        for (input, expected) in [
66            ("materialize/environmentd:v0.27.0", Some("v0.27.0")),
67            ("materialize/environmentd", None),
68            (
69                "gcr.io:443/materialize/environmentd:v0.27.0",
70                Some("v0.27.0"),
71            ),
72            ("gcr.io:443/materialize/environmentd", None),
73            ("pkg.dev/proj/repo/env@sha256:deadbeef", None),
74            ("pkg.dev/proj/repo/env:v1.0@sha256:deadbeef", Some("v1.0")),
75            ("environmentd:latest", Some("latest")),
76            ("environmentd", None),
77        ] {
78            assert_eq!(parse_image_tag(input), expected, "input: {input}");
79        }
80    }
81
82    #[mz_ore::test]
83    fn test_matching_image() {
84        let f = matching_image_from_environmentd_image_ref;
85        assert_eq!(
86            f("materialize/environmentd:v0.27.0", "console", None),
87            "materialize/console:v0.27.0"
88        );
89        assert_eq!(
90            f(
91                "materialize/environmentd:v0.27.0",
92                "console",
93                Some("custom")
94            ),
95            "materialize/console:custom"
96        );
97        assert_eq!(
98            f("gcr.io:443/materialize/environmentd", "clusterd", None),
99            "gcr.io:443/materialize/clusterd:latest"
100        );
101        assert_eq!(
102            f("pkg.dev/proj/repo/env@sha256:deadbeef", "console", None),
103            "pkg.dev/proj/repo/console:latest"
104        );
105        assert_eq!(
106            f("environmentd", "console", None),
107            "materialize/console:latest"
108        );
109    }
110}