Skip to content

Commit

Permalink
Adding chrono minimum rhai binding
Browse files Browse the repository at this point in the history
  • Loading branch information
sebt3 committed Dec 10, 2024
1 parent 3cdfac4 commit 5906da6
Show file tree
Hide file tree
Showing 19 changed files with 149 additions and 39 deletions.
2 changes: 1 addition & 1 deletion agent/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
ARG RUST_VERSION=1.81
ARG DEBIAN_VERSION=bookworm
ARG DEBIAN_NEXT=trixie
FROM docker.io/rust:${RUST_VERSION}-slim-${DEBIAN_VERSION} AS builder
FROM --platform=${BUILDPLATFORM:-linux/amd64} docker.io/rust:${RUST_VERSION}-slim-${DEBIAN_VERSION} AS builder
ARG BUILD_DEPS="binutils libssl-dev pkg-config git build-essential g++"
WORKDIR /usr/src/agent
COPY Cargo.lock .
Expand Down
10 changes: 9 additions & 1 deletion agent/scripts/lib/wait.rhai
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,15 @@ fn vital(lst, duration) {
let api = k8s_resource(v.kind, v.namespace);
let obj = api.get_obj(v.name);
obj.wait_condition("ClusterAvailable", duration);
} else if ["Redis", "MongoDBCommunity"].contains(v.kind) {
} else if ["RedisSentinel"].contains(v.kind) {
log_info(`Waiting for ${v.kind} ${v.namespace}/${v.name} to be available`);
let sts = get_statefulset(v.namespace, `${v.name}--sentinel`);
sts.wait_available(duration);
} else if ["RedisCluster"].contains(v.kind) {
log_info(`Waiting for ${v.kind} ${v.namespace}/${v.name} to be available`);
let sts = get_statefulset(v.namespace, `${v.name}-leader`);
sts.wait_available(duration);
} else if ["Redis", "RedisReplication", "MongoDBCommunity"].contains(v.kind) {
log_info(`Waiting for ${v.kind} ${v.namespace}/${v.name} to be available`);
let sts = get_statefulset(v.namespace, v.name);
sts.wait_available(duration);
Expand Down
2 changes: 1 addition & 1 deletion agent/scripts/packages/build.rhai
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn build(args) {
}
}
} else if base in ["scripts"] && is_dir(item) {
copy::dir_exts(item, args.temp+"/"+base, [".rhai"], true);
copy::dir_exts(item, args.temp+"/"+base, [".rhai", ".sh"], true);
} else if base == "tofu" && is_dir(item) {
copy::dir_exts(item, args.temp+"/"+base, [".tf", ".tpl", ".tftpl"], true);
} else if base == "files" && is_dir(item) {
Expand Down
6 changes: 3 additions & 3 deletions agent/scripts/system/install_systems.rhai
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ fn run(instance, context) {
import_run("install_systems_pre", instance, context);
try {
let applied_objs = dir::install(instance, context, `${context.package_dir}/systems`, true, false);
if instance.status != () && instance.status.systems != () {
dir::remove(applied_objs, instance.status.systems, instance.metadata.namespace);
}
let added = import_run("install_systems_add", instance, context);
switch type_of(added) {
"map" => {
Expand All @@ -18,6 +15,9 @@ fn run(instance, context) {
applied_objs += added.filter(|i|dir::validate_add_item(i));
}
}
if instance.status != () && instance.status.systems != () {
dir::remove(applied_objs, instance.status.systems, instance.metadata.namespace);
}
let tmp = instance.set_status_systems(applied_objs);
wait::all(applied_objs);
} catch (e) {
Expand Down
6 changes: 3 additions & 3 deletions agent/scripts/tenant/install_others.rhai
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ fn run(instance, context) {
import_run("install_others_pre", instance, context);
try {
let applied_objs = dir::install_allowed(instance, context, `${context.package_dir}/others`, context.tenant.namespaces);
if instance.status != () && instance.status.others != () {
dir::remove(applied_objs, instance.status.others, instance.metadata.namespace);
}
let added = import_run("install_others_add", instance, context);
switch type_of(added) {
"map" => {
Expand All @@ -18,6 +15,9 @@ fn run(instance, context) {
applied_objs += added.filter(|i|dir::validate_add_item(i));
}
}
if instance.status != () && instance.status.others != () {
dir::remove(applied_objs, instance.status.others, instance.metadata.namespace);
}
let tmp = instance.set_status_others(applied_objs);
wait::all(applied_objs);
} catch (e) {
Expand Down
6 changes: 3 additions & 3 deletions agent/scripts/tenant/install_scalables.rhai
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ fn run(instance, context) {
import_run("install_scalables_pre", instance, context);
try {
let applied_objs = dir::install_allowed(instance, context, `${context.package_dir}/scalables`, context.tenant.namespaces);
if instance.status != () && instance.status.scalables != () {
dir::remove(applied_objs, instance.status.scalables, instance.metadata.namespace);
}
// TODO: scale a target
let added = import_run("install_scalables_add", instance, context);
switch type_of(added) {
Expand All @@ -19,6 +16,9 @@ fn run(instance, context) {
applied_objs += added.filter(|i|dir::validate_add_item(i));
}
}
if instance.status != () && instance.status.scalables != () {
dir::remove(applied_objs, instance.status.scalables, instance.metadata.namespace);
}
let tmp = instance.set_status_scalables(applied_objs);
wait::all(applied_objs);
} catch (e) {
Expand Down
2 changes: 1 addition & 1 deletion common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ base64.workspace = true
thiserror = "2.0.3"
handlebars = { version = "6.2.0", features = ["script_helper", "string_helpers"] }
handlebars_misc_helpers = { version = "0.17.0", features = ["string", "json", "jsonnet", "regex", "uuid"] }
rhai = { version = "1.20.0", features = ["sync", "serde"] }
rhai = { version = "1.20.0", features = ["sync", "serde", "internals"] }
reqwest = { version = "0.12.4", features = ["rustls-tls"] }
rand = "0.8.5"
lazy_static = "1.5.0"
Expand Down
21 changes: 21 additions & 0 deletions common/src/chronohandler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use chrono::{DateTime, Local};
use rhai::ImmutableString;

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct DateTimeHandler {
pub date: DateTime<Local>,
}
impl DateTimeHandler {
#[must_use]
pub fn now() -> Self {
Self {
date: Local::now()
}
}
pub fn format(&self, fmt: &str) -> String {
format!("{}", self.date.format(fmt))
}
pub fn rhai_format(&mut self, fmt: String) -> ImmutableString {
self.format(&fmt).into()
}
}
10 changes: 9 additions & 1 deletion common/src/handlebarshandler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ handlebars_helper!(gen_password_alphanum: |len:u32| Passwords::new().generate(l
handlebars_helper!(selector: |ctx: Value, {comp:str=""}| {
let mut sel = ctx.as_object().unwrap()["instance"].as_object().unwrap()["selector"].as_object().unwrap().clone();
if !comp.is_empty() {
sel.insert("app.kubernetes.io/componant".into(), Value::from(comp));
sel.insert("app.kubernetes.io/component".into(), Value::from(comp));
}
sel
});
Expand All @@ -53,6 +53,13 @@ handlebars_helper!(labels: |ctx: Value| {
handlebars_helper!(have_crd: |ctx: Value, name: String| {
ctx.as_object().unwrap()["cluster"].as_object().unwrap()["crds"].as_array().unwrap().iter().any(|crd| *crd==name)
});
handlebars_helper!(concat: |a: Value, b: Value| format!("{}{}", a.as_str().unwrap_or_else(|| {
warn!("handlebars::concat received a non-string parameter: {:?}", a);
""
}),b.as_str().unwrap_or_else(|| {
warn!("handlebars::concat received a non-string parameter: {:?}", b);
""
})));

#[derive(Clone, Debug)]
pub struct HandleBars<'a> {
Expand All @@ -62,6 +69,7 @@ impl HandleBars<'_> {
#[must_use]
pub fn new() -> HandleBars<'static> {
let mut engine = new_hbs();
engine.register_helper("concat", Box::new(concat));
engine.register_helper("labels_from_ctx", Box::new(labels));
engine.register_helper("ctx_have_crd", Box::new(have_crd));
engine.register_helper("selector_from_ctx", Box::new(selector));
Expand Down
22 changes: 22 additions & 0 deletions common/src/instancesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,28 @@ impl SystemInstance {
api.list(&lp).await.map_err(Error::KubeError)
}

pub fn have_child(&self) -> bool {
if let Some(status) = self.status.clone() {
if status.rhaistate.is_some() {
return true;
}
if status.tfstate.is_some() {
return true;
}
if let Some(child) = status.systems.clone() {
if child.len() > 0 {
return true;
}
}
if let Some(child) = status.crds.clone() {
if child.len() > 0 {
return true;
}
}
}
false
}

pub fn get_options_digest(&mut self) -> String {
if let Some(ref opt) = self.spec.options {
sha256::digest(serde_json::to_string(opt).unwrap())
Expand Down
41 changes: 38 additions & 3 deletions common/src/instancetenant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,33 @@ impl TenantInstance {
api.list(&lp).await.map_err(Error::KubeError)
}

pub fn have_child(&self) -> bool {
if let Some(status) = self.status.clone() {
if status.rhaistate.is_some() {
return true;
}
if status.tfstate.is_some() {
return true;
}
if let Some(child) = status.vitals.clone() {
if child.len() > 0 {
return true;
}
}
if let Some(child) = status.others.clone() {
if child.len() > 0 {
return true;
}
}
if let Some(child) = status.scalables.clone() {
if child.len() > 0 {
return true;
}
}
}
false
}

pub fn get_options_digest(&mut self) -> String {
if let Some(ref opt) = self.spec.options {
sha256::digest(serde_json::to_string(opt).unwrap())
Expand Down Expand Up @@ -1059,8 +1086,16 @@ impl TenantInstance {
.map_err(rhai_err)
}

pub fn rhai_get_tenant_namespaces(&mut self) -> RhaiRes<Vec<String>> {
block_in_place(|| Handle::current().block_on(async move { self.get_tenant_namespaces().await }))
.map_err(rhai_err)
pub fn rhai_get_tenant_namespaces(&mut self) -> RhaiRes<Dynamic> {
block_in_place(|| Handle::current().block_on(async move {
let arr = self.get_tenant_namespaces().await;
if arr.is_ok() {
let arr = arr.unwrap();
let v = serde_json::to_string(&arr).map_err( Error::SerializationError)?;
serde_json::from_str::<Dynamic>(&v).map_err(Error::SerializationError)
} else {
arr.map(|_| Dynamic::from(""))
}
})).map_err(rhai_err)
}
}
1 change: 1 addition & 0 deletions common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ pub mod passwordhandler;
pub mod rhaihandler;
mod semverhandler;
pub mod shellhandler;
pub mod chronohandler;
mod tools;
pub mod vynilpackage;
pub use context::get_client_name;
Expand Down
8 changes: 7 additions & 1 deletion common/src/rhaihandler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::{
k8sworkload::{K8sDaemonSet, K8sDeploy, K8sJob, K8sStatefulSet},
ocihandler::Registry,
passwordhandler::Passwords,
chronohandler::DateTimeHandler,
rhai_err, shellhandler,
vynilpackage::{rhai_read_package_yaml, VynilPackageSource},
Error::{self, *},
Expand All @@ -23,8 +24,8 @@ pub use rhai::{
module_resolvers::{FileModuleResolver, ModuleResolversCollection},
serde::to_dynamic,
Array, Dynamic, Engine, ImmutableString, Map, Module, Scope,
// FnPtr, NativeCallContext,
};
use rhai::{FnPtr, NativeCallContext};
use serde::Deserialize;


Expand Down Expand Up @@ -286,6 +287,11 @@ impl Script {
.register_fn("<=", |a: Semver, b: Semver| a <= b)
.register_fn(">=", |a: Semver, b: Semver| a >= b)
.register_fn("to_string", Semver::to_string);
script
.engine
.register_type_with_name::<DateTimeHandler>("DateTimeHandler")
.register_fn("date_now", DateTimeHandler::now)
.register_fn("format", DateTimeHandler::rhai_format);
script
.engine
.register_type_with_name::<Registry>("Registry")
Expand Down
2 changes: 1 addition & 1 deletion common/src/semverhandler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub struct Semver {
pub version: Version,
pub use_v: bool,
}
// support des rc (release candidate)
// TODO: support des rc (release candidate)
impl Semver {
pub fn parse(str: &str) -> Result<Self> {
let use_v = str.starts_with("v");
Expand Down
2 changes: 1 addition & 1 deletion operator/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
ARG RUST_VERSION=1.81
ARG DEBIAN_VERSION=bookworm
ARG DEBIAN_NEXT=trixie
FROM rust:${RUST_VERSION}-slim-${DEBIAN_VERSION} AS builder
FROM --platform=${BUILDPLATFORM:-linux/amd64} rust:${RUST_VERSION}-slim-${DEBIAN_VERSION} AS builder
ARG BUILD_DEPS="binutils libssl-dev pkg-config git build-essential g++"
WORKDIR /usr/src/operator
COPY Cargo.lock .
Expand Down
20 changes: 12 additions & 8 deletions operator/src/instancesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,9 @@ impl Reconciler for SystemInstance {
if pck.value_script.is_some() {
let mut rhai = Script::new(vec![]);
rhai.ctx.set_value("instance", self.clone());
let val = rhai.eval_map_string(
serde_json::from_str(&pck.value_script.unwrap()).map_err(Error::JsonError)?,
)?;
tracing::info!("Using {:?} as ctrl_values", val);
let value_script = pck.value_script.unwrap();
let script = serde_json::from_str::<String>(&value_script).map_err(Error::JsonError)?;
let val = rhai.eval_map_string(&script)?;
context
.as_object_mut()
.unwrap()
Expand All @@ -157,6 +156,7 @@ impl Reconciler for SystemInstance {
}
// Evrything is good to go
// Create the job
tracing::info!("Creating with: {:?}", &context);
let job_def_str = hbs.render("{{> package.yaml }}", &context)?;
let job_def: Value = serde_yaml::from_str(&job_def_str).map_err(Error::YamlError)?;
let job_api: Api<Job> = Api::namespaced(client.clone(), my_ns);
Expand Down Expand Up @@ -248,7 +248,10 @@ impl Reconciler for SystemInstance {
&& p.metadata.usage == VynilPackageType::System
})
{
// Package doesnt exist, cannot have been installed
// Package doesnt exist
if self.have_child() {
return Err(Error::Other(String::from("This install have child but the package cannot be found")));
}
return Ok(Action::await_change());
}
if let Some(pull_secret) = packages[&self.spec.jukebox].pull_secret.clone() {
Expand Down Expand Up @@ -292,9 +295,9 @@ impl Reconciler for SystemInstance {
if pck.value_script.is_some() {
let mut rhai = Script::new(vec![]);
rhai.ctx.set_value("instance", self.clone());
let val = rhai.eval_map_string(
serde_json::from_str(&pck.value_script.unwrap()).map_err(Error::JsonError)?,
)?;
let value_script = pck.value_script.unwrap();
let script = serde_json::from_str::<String>(&value_script).map_err(Error::JsonError)?;
let val = rhai.eval_map_string(&script)?;
context
.as_object_mut()
.unwrap()
Expand Down Expand Up @@ -324,6 +327,7 @@ impl Reconciler for SystemInstance {
};
}
// Create the delete Job
tracing::info!("Deleting with: {:?}", &context);
let job_def_str = hbs.render("{{> package.yaml }}", &context)?;
let job_def: Value = serde_yaml::from_str(&job_def_str).map_err(Error::YamlError)?;
job_api
Expand Down
Loading

0 comments on commit 5906da6

Please sign in to comment.