feat: Add openwebui installation example #277

Open
johnride wants to merge 1 commits from feat/openwebui into master
4 changed files with 166 additions and 34 deletions

13
Cargo.lock generated
View File

@@ -2944,6 +2944,19 @@ dependencies = [
"url",
]
[[package]]
name = "example-openwebui"
version = "0.1.0"
dependencies = [
"clap",
"harmony",
"harmony_cli",
"harmony_macros",
"harmony_types",
"tokio",
"url",
]
[[package]]
name = "example-operatorhub-catalogsource"
version = "0.1.0"

View File

@@ -0,0 +1,16 @@
[package]
name = "example-openwebui"
edition = "2024"
version.workspace = true
readme.workspace = true
license.workspace = true
publish = false
[dependencies]
harmony = { path = "../../harmony" }
harmony_cli = { path = "../../harmony_cli" }
harmony_macros = { path = "../../harmony_macros" }
harmony_types = { path = "../../harmony_types" }
tokio = { workspace = true }
url = { workspace = true }
clap = { workspace = true }

View File

@@ -0,0 +1,101 @@
use std::str::FromStr;
use harmony::{
inventory::Inventory,
modules::helm::chart::{HelmChartScore, HelmRepository, NonBlankString},
topology::{K8sAnywhereTopology, TlsRouter, Topology},
};
use harmony_macros::hurl;
#[tokio::main]
async fn main() {
harmony_cli::cli_logger::init();
let ollama_url = "http://your-ollama-server:11434";
deploy(ollama_url).await
}
async fn deploy(ollama_url: &str) {
let topology = K8sAnywhereTopology::from_env();
topology.ensure_ready().await.unwrap();
let domain = topology
.get_internal_domain()
.await
.unwrap()
.expect("cluster ingress domain not found — ensure this is an OKD cluster");
let ingress_host = format!("openwebui.{}", domain);
let webui_secret_key = "CHANGE-ME-TO-A-STRONG-RANDOM-SECRET";
let values_yaml = format!(
r#"ollama:
enabled: false
ollamaUrls:
- "{ollama_url}"
pipelines:
enabled: false
tika:
enabled: false
websocket:
enabled: false
replicaCount: 1
persistence:
enabled: true
size: 5Gi
accessModes:
- ReadWriteOnce
storageClass: ""
extraEnvVars:
- name: WEBUI_SECRET_KEY
value: "{webui_secret_key}"
podSecurityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
ingress:
enabled: true
annotations:
route.openshift.io/termination: edge
host: "{ingress_host}"
tls: true
service:
type: ClusterIP
port: 80
containerPort: 8080"#,
ollama_url = ollama_url,
ingress_host = ingress_host,
webui_secret_key = webui_secret_key,
);
let openwebui = HelmChartScore {
namespace: Some(NonBlankString::from_str("openwebui").unwrap()),
release_name: NonBlankString::from_str("openwebui").unwrap(),
chart_name: NonBlankString::from_str("open-webui/open-webui").unwrap(),
chart_version: None,
values_overrides: None,
values_yaml: Some(values_yaml),
create_namespace: true,
install_only: false,
repository: Some(HelmRepository::new(
"open-webui".to_string(),
hurl!("https://open-webui.github.io/helm-charts/"),
true,
)),
};
harmony_cli::run(
Inventory::autoload(),
topology,
vec![Box::new(openwebui)],
None,
)
.await
.unwrap();
}

View File

@@ -205,43 +205,45 @@ impl<T: Topology + HelmCommand> Interpret<T> for HelmChartInterpret {
.unwrap_or_else(|| todo!("Get namespace from active kubernetes cluster"));
let ns_str = ns.to_string();
if let Some(installed_chart) = self.find_installed_release(topology, &ns_str)? {
return match self.expected_chart_field() {
Some(expected)
if Self::normalize_chart_field(&expected)
== Self::normalize_chart_field(&installed_chart) =>
{
warn!(
"Helm release '{}' already installed at desired version ('{}'); skipping.",
self.score.release_name, installed_chart
);
Ok(Outcome::success(format!(
"Helm Chart {} already at desired version",
self.score.release_name
)))
}
Some(expected) => Err(InterpretError::new(format!(
"Helm release '{}' already installed as '{}', but score requests '{}'. \
Refusing to upgrade/downgrade; resolve manually.",
self.score.release_name, installed_chart, expected
))),
None => {
warn!(
"Helm release '{}' already installed as '{}'; score has no pinned \
chart_version so skipping re-install.",
self.score.release_name, installed_chart
);
Ok(Outcome::success(format!(
"Helm Chart {} already installed (version not pinned)",
self.score.release_name
)))
}
};
}
self.add_repo(topology)?;
let mut args = if self.score.install_only {
// In install only mode we don't want to fail all the time, only when requesting
// something that looks like an upgrade
if let Some(installed_chart) = self.find_installed_release(topology, &ns_str)? {
return match self.expected_chart_field() {
Some(expected)
if Self::normalize_chart_field(&expected)
== Self::normalize_chart_field(&installed_chart) =>
{
warn!(
"Helm release '{}' already installed at desired version ('{}'); skipping.",
self.score.release_name, installed_chart
);
Ok(Outcome::success(format!(
"Helm Chart {} already at desired version",
self.score.release_name
)))
}
Some(expected) => Err(InterpretError::new(format!(
"Helm release '{}' already installed as '{}', but score requests '{}'. \
Refusing to upgrade/downgrade; resolve manually.",
self.score.release_name, installed_chart, expected
))),
None => {
warn!(
"Helm release '{}' already installed as '{}'; score has no pinned \
chart_version so skipping re-install.",
self.score.release_name, installed_chart
);
Ok(Outcome::success(format!(
"Helm Chart {} already installed (version not pinned)",
self.score.release_name
)))
}
};
}
vec!["install"]
} else {
vec!["upgrade", "--install"]