Skip to content

Commit

Permalink
Adding an "init" script that run before client setup, to be used as a…
Browse files Browse the repository at this point in the history
… way to prepare a token for API that require a 2 step login
  • Loading branch information
sebt3 committed Dec 26, 2024
1 parent 85b0439 commit 7ebe821
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 33 deletions.
44 changes: 22 additions & 22 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "kuberest"
version = "1.1.5"
version = "1.2.0"
authors = ["Sébastien Huss <[email protected]>"]
edition = "2021"
default-run = "controller"
Expand Down
4 changes: 2 additions & 2 deletions charts/kuberest/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ apiVersion: v2
name: kuberest
description: Allow to Control remote REST api endpoints from the confort of your cluster
type: application
version: "1.1.5"
appVersion: "1.1.5"
version: "1.2.0"
appVersion: "1.2.0"
5 changes: 5 additions & 0 deletions deploy/crd/crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ spec:
required:
- baseurl
type: object
init:
description: A rhai pre-script to setup some complex variables before client setup
nullable: true
type: string
inputs:
description: List input source for Handlebars renders
items:
Expand Down Expand Up @@ -413,6 +417,7 @@ spec:
- InputMissing
- InputFailed
- TemplateFailed
- InitScriptFailed
- PreScriptFailed
- PostScriptFailed
- TeardownScriptFailed
Expand Down
8 changes: 4 additions & 4 deletions deploy/operator/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ metadata:
labels:
app: kuberest
app.kubernetes.io/name: kuberest
app.kubernetes.io/version: "1.1.5"
app.kubernetes.io/version: "1.2.0"
namespace: default
automountServiceAccountToken: true
---
Expand Down Expand Up @@ -102,7 +102,7 @@ metadata:
labels:
app: kuberest
app.kubernetes.io/name: kuberest
app.kubernetes.io/version: "1.1.5"
app.kubernetes.io/version: "1.2.0"
spec:
type: ClusterIP
ports:
Expand All @@ -122,7 +122,7 @@ metadata:
labels:
app: kuberest
app.kubernetes.io/name: kuberest
app.kubernetes.io/version: "1.1.5"
app.kubernetes.io/version: "1.2.0"
spec:
replicas: 1
selector:
Expand All @@ -140,7 +140,7 @@ spec:
{}
containers:
- name: kuberest
image: sebt3/kuberest:1.1.5
image: sebt3/kuberest:1.2.0
imagePullPolicy: IfNotPresent
securityContext:
{}
Expand Down
3 changes: 0 additions & 3 deletions src/httphandler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -676,12 +676,9 @@ impl RestClient {
path: &str,
key: &str,
input: &Value,
use_slash: bool,
) -> Result<Value, Error> {
let full_path = if key.is_empty() {
path.to_string()
} else if use_slash {
format!("{path}/{key}/")
} else {
format!("{path}/{key}")
};
Expand Down
86 changes: 85 additions & 1 deletion src/restendpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ pub enum ConditionsType {
InputMissing,
InputFailed,
TemplateFailed,
InitScriptFailed,
PreScriptFailed,
PostScriptFailed,
TeardownScriptFailed,
Expand Down Expand Up @@ -309,6 +310,10 @@ impl ApplicationCondition {
)
}

pub fn init_script_failed(message: &str) -> ApplicationCondition {
ApplicationCondition::new(message, ConditionsStatus::True, ConditionsType::InitScriptFailed)
}

pub fn pre_script_failed(message: &str) -> ApplicationCondition {
ApplicationCondition::new(message, ConditionsStatus::True, ConditionsType::PreScriptFailed)
}
Expand Down Expand Up @@ -455,6 +460,8 @@ pub struct RestEndPointSpec {
pub templates: Option<Vec<TemplateItem>>,
/// List input source for Handlebars renders
pub inputs: Option<Vec<InputItem>>,
/// A rhai pre-script to setup some complex variables before client setup
pub init: Option<String>,
/// Define the how the client should connect to the API endpoint(s)
pub client: WebClient,
/// A rhai pre-script to setup some complex variables
Expand Down Expand Up @@ -824,6 +831,45 @@ impl RestEndPoint {
rhai.set_dynamic("input", &values["input"]);
rhai.set_dynamic("values", &values);

// Run the init script
if let Some(script) = self.spec.init.clone() {
let cnd = conditions.clone();
values["init"] = rhai.eval(&script).unwrap_or_else(|e| {
conditions.push(ApplicationCondition::init_script_failed(&format!("{e:?}")));
json!({})
});
// Validate that init-script went Ok
if cnd
.iter()
.any(|c| c.condition_type != ConditionsType::InputMissing)
{
let msg = "Init-script failed";
Self::publish_warning(
&recorder,
String::from(msg),
format!("Found {} error(s) running the init-script", conditions.len()),
String::from("fail"),
)
.await?;
conditions.push(ApplicationCondition::not_ready(msg));
let new_status = Patch::Apply(json!({
"apiVersion": "kuberest.solidite.fr/v1",
"kind": "RestEndPoint",
"status": RestEndPointStatus { conditions, generation: self.metadata.generation.unwrap_or(1), owned: self.owned(), owned_target: self.owned_target() }
}));
let ps = PatchParams::apply(RESTPATH_FINALIZER).force();
let _o = restendpoints
.patch_status(&name, &ps, &new_status)
.await
.map_err(Error::KubeError)?;
return Ok(Action::requeue(Duration::from_secs(
self.spec.check_frequency.unwrap_or(15 * 60),
)));
}
}
rhai.set_dynamic("init", &values["init"]);
rhai.set_dynamic("values", &values);

// Setup the httpClient
let mut rest = RestClient::new(&template!(
self.spec.client.baseurl.clone().as_str(),
Expand Down Expand Up @@ -1056,7 +1102,6 @@ impl RestEndPoint {
path.as_str(),
&myself.key,
&vals,
group.key_use_slash.unwrap_or(false),
)
.unwrap_or_else(|e| {
giveup = if let Error::MethodFailed(_, code, _) = e {
Expand Down Expand Up @@ -1739,6 +1784,45 @@ impl RestEndPoint {
}
rhai.set_dynamic("input", &values["input"]);
rhai.set_dynamic("values", &values);

// Run the init script
if let Some(script) = self.spec.init.clone() {
let cnd = conditions.clone();
values["init"] = rhai.eval(&script).unwrap_or_else(|e| {
conditions.push(ApplicationCondition::init_script_failed(&format!("{e:?}")));
json!({})
});
// Validate that init-script went Ok
if cnd
.iter()
.any(|c| c.condition_type != ConditionsType::InputMissing)
{
let msg = "Init-script failed";
Self::publish_warning(
&recorder,
String::from(msg),
format!("Found {} error(s) running the init-script", conditions.len()),
String::from("fail"),
)
.await?;
conditions.push(ApplicationCondition::not_ready(msg));
let new_status = Patch::Apply(json!({
"apiVersion": "kuberest.solidite.fr/v1",
"kind": "RestEndPoint",
"status": RestEndPointStatus { conditions, generation: self.metadata.generation.unwrap_or(1), owned: self.owned(), owned_target: self.owned_target() }
}));
let ps = PatchParams::apply(RESTPATH_FINALIZER).force();
let _o = restendpoints
.patch_status(&name, &ps, &new_status)
.await
.map_err(Error::KubeError)?;
return Ok(Action::requeue(Duration::from_secs(
self.spec.check_frequency.unwrap_or(15 * 60),
)));
}
}
rhai.set_dynamic("init", &values["init"]);
rhai.set_dynamic("values", &values);
}

// Setup the httpClient
Expand Down

0 comments on commit 7ebe821

Please sign in to comment.