Skip to content

Commit

Permalink
Version 15
Browse files Browse the repository at this point in the history
  • Loading branch information
peter-formlogic committed Feb 24, 2022
1 parent dd2e8b0 commit af01c2e
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 14 deletions.
8 changes: 4 additions & 4 deletions Cargo.lock

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

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "lorikeet"
version = "0.14.0"
version = "0.15.0"
authors = ["cetra3 <cetra3@hotmail.com>"]
license = "MIT/Apache-2.0"
description = "a parallel test runner for devops"
Expand All @@ -27,7 +27,7 @@ chashmap = "2.2.2"
hostname = "0.3.1"
sys-info = "0.8.0"
openssl-probe = "0.1.2"
jmespatch = "0.3.0"
jmespath = "0.3.0"
anyhow = "1.0.38"
serde_json = "1.0"
quick-xml = "0.21.0"
Expand Down
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@

A Parallel test runner for DevOps.


## Download

Download the latest binary for linux or osx from here: [https://github.com/cetra3/lorikeet/releases](https://github.com/cetra3/lorikeet/releases)

## Overview

Lorikeet is a command line tool and a rust library to run tests for smoke testing and integration testing. Lorikeet currently supports bash commands and simple http requests along with system information (ram, cpu).
Expand Down Expand Up @@ -57,6 +62,20 @@ The name comes from the [Rainbow Lorikeet](https://en.wikipedia.org/wiki/Rainbow

They are also very noisy birds.

## Changes in `0.15.0`

* Add in a new option to run a step on failure:

```yaml
on_fail_example:
value: true
matches: false
on_fail:
bash: notify-send "Lorikeet Failed!"
```

* We now have [releases](https://github.com/cetra3/lorikeet/releases) being generated via github actions

## Changes in `0.14.0`

* Breaking Change: Add in a default timeout (`timeout_ms`) for http requests to `30000` milliseconds (30 seconds), This default can be changed as per http options below.
Expand Down Expand Up @@ -174,6 +193,8 @@ Or clone and build this repo:
cargo build --release
```

Alternatively, you can download prebuilt from the [releases](https://github.com/cetra3/lorikeet/releases) page

## Usage

Command line usage is given by `lorikeet -h`:
Expand Down Expand Up @@ -545,6 +566,23 @@ there_are_four_lights:
less_than: 5
```

### On Fail

You can run another step when a step fails. This `on_fail` can be any of the step types: bash, http, system, step and value

```yaml
on_fail_example:
value: true
matches: false
on_fail:
bash: notify-send "Lorikeet Failed!"
```

The output or error of this on fail step will be included in the standard output.

If you are using retry counts, then the `on_fail` step will execute each time the step fail.


### Dependencies

By default tests are run in parallel and submitted to a thread pool for execution. If a step has a dependency it won't be run until the dependent step has been finished. If there are no dependencies to a step then it will run as soon as a thread is free. If you don't specify any dependencies there is no guaranteed ordering to execution.
Expand Down
3 changes: 3 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,16 @@ fn step_from_error(err: Error, quiet: bool, colours: bool) -> StepResult {
output: None,
error: Some(err.to_string()),
duration: Duration::default(),
on_fail_output: None,
on_fail_error: None,
};

let result: StepResult = Step {
name: "lorikeet".into(),
run: RunType::Value(String::new()),
do_output: true,
expect: ExpectType::Anything,
on_fail: None,
description: Some(
"This step is shown if there was an error when reading, parsing or running steps"
.into(),
Expand Down
6 changes: 5 additions & 1 deletion src/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub struct StepRunner {
pub name: String,
pub index: usize,
pub run: RunType,
pub on_fail: Option<RunType>,
pub expect: ExpectType,
pub retry: RetryPolicy,
pub filters: Vec<FilterType>,
Expand All @@ -35,7 +36,7 @@ impl StepRunner {
tokio::spawn(async move {
let outcome = self
.run
.execute(self.expect, self.filters, self.retry)
.execute(self.expect, self.filters, self.retry, self.on_fail)
.await;

if let Some(ref output) = outcome.output {
Expand Down Expand Up @@ -92,6 +93,7 @@ pub fn run_steps(steps: Vec<Step>) -> Result<StepStream, Error> {
for (i, step) in step_map.iter() {
let future = StepRunner {
run: step.run.clone(),
on_fail: step.on_fail.clone(),
expect: step.expect.clone(),
retry: step.retry,
filters: step.filters.clone(),
Expand Down Expand Up @@ -160,6 +162,8 @@ pub fn run_steps(steps: Vec<Step>) -> Result<StepStream, Error> {
output: Some("".into()),
error: Some("Dependency Not Met".into()),
duration: Duration::from_secs(0),
on_fail_output: None,
on_fail_error: None,
});

if tx_steps.send(step).is_err() {
Expand Down
27 changes: 24 additions & 3 deletions src/step/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use tera::{Context, Tera};

use std::{borrow::Cow, collections::HashMap};

use jmespatch::{self, Variable};
use jmespath::{self, Variable};

use lazy_static::lazy_static;
use log::debug;
Expand All @@ -29,6 +29,8 @@ use chashmap::CHashMap;
pub struct Outcome {
pub output: Option<String>,
pub error: Option<String>,
pub on_fail_output: Option<String>,
pub on_fail_error: Option<String>,
pub duration: Duration,
}

Expand All @@ -44,6 +46,7 @@ pub struct Step {
pub name: String,
pub description: Option<String>,
pub run: RunType,
pub on_fail: Option<RunType>,
pub filters: Vec<FilterType>,
pub expect: ExpectType,
pub do_output: bool,
Expand Down Expand Up @@ -91,6 +94,7 @@ impl RunType {
expect: ExpectType,
filters: Vec<FilterType>,
retry: RetryPolicy,
on_fail: Option<RunType>,
) -> Outcome {
let start = Instant::now();

Expand All @@ -104,6 +108,8 @@ impl RunType {

let mut output = String::new();
let mut error = String::new();
let mut on_fail_output = None;
let mut on_fail_error = None;
let mut successful = false;

'retry: for count in 0..try_count {
Expand All @@ -120,6 +126,8 @@ impl RunType {

output = String::new();
error = String::new();
on_fail_output = None;
on_fail_error = None;

//Run the runner first
match self.run().await {
Expand Down Expand Up @@ -158,6 +166,17 @@ impl RunType {
break 'retry;
}
}

if !successful {
if let Some(ref on_fail_runner) = on_fail {
match on_fail_runner.run().await {
Ok(val) => {
on_fail_output = Some(val);
}
Err(val) => on_fail_error = Some(val),
}
}
}
}

let output_opt = match output.as_ref() {
Expand All @@ -175,6 +194,8 @@ impl RunType {
output: output_opt,
error: error_opt,
duration: start.elapsed(),
on_fail_output,
on_fail_error,
}
}

Expand Down Expand Up @@ -241,10 +262,10 @@ impl FilterType {
match *self {
FilterType::NoOutput => Ok(String::from("")),
FilterType::JmesPath(ref jmes) => {
let expr = jmespatch::compile(jmes)
let expr = jmespath::compile(jmes)
.map_err(|err| format!("Could not compile jmespath:{}", err))?;

let data = jmespatch::Variable::from_json(val)
let data = Variable::from_json(val)
.map_err(|err| format!("Could not format as json:{}", err))?;

let result = expr
Expand Down
33 changes: 29 additions & 4 deletions src/submitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ pub struct StepResult {
pub pass: bool,
pub output: String,
pub error: Option<String>,
pub on_fail_output: Option<String>,
pub on_fail_error: Option<String>,
pub duration: f32,
}

Expand Down Expand Up @@ -175,11 +177,20 @@ impl StepResult {
message.push_str(&format!(" output: {}\n", self.output));
}
}

if let Some(ref error) = self.error {
message.push_str(&format!(" error: {}\n", error));
}

if let Some(ref output) = self.on_fail_output {
if !output.trim().is_empty() {
message.push_str(&format!(" on_fail_output: {}\n", output));
}
}

if let Some(ref error) = self.on_fail_error {
message.push_str(&format!(" on_fail_error: {}\n", error));
}

message.push_str(&format!(" duration: {}ms\n", self.duration));

if *colours {
Expand All @@ -203,16 +214,28 @@ impl From<Step> for StepResult {
let name = step.name;
let description = step.description;

let (pass, output, error) = match step.outcome {
let (pass, output, error, on_fail_output, on_fail_error) = match step.outcome {
Some(outcome) => {
let output = match step.do_output {
true => outcome.output.unwrap_or_default(),
false => String::new(),
};

(outcome.error.is_none(), output, outcome.error)
(
outcome.error.is_none(),
output,
outcome.error,
outcome.on_fail_output,
outcome.on_fail_error,
)
}
None => (false, String::new(), Some(String::from("Not finished"))),
None => (
false,
String::new(),
Some(String::from("Not finished")),
None,
None,
),
};

StepResult {
Expand All @@ -221,6 +244,8 @@ impl From<Step> for StepResult {
description,
pass,
output,
on_fail_output,
on_fail_error,
error,
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/yaml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ struct StepYaml {
retry_count: Option<usize>,
retry_delay_ms: Option<usize>,
delay_ms: Option<usize>,
on_fail: Option<RunType>,
require: Option<Requirement>,
required_by: Option<Requirement>,
}
Expand Down Expand Up @@ -138,6 +139,7 @@ pub fn get_steps_raw<T: Serialize>(yaml_contents: &str, context: &T) -> Result<V
steps.push(Step {
name,
run,
on_fail: step.on_fail,
do_output: step.do_output.unwrap_or(true),
expect,
description: step.description,
Expand Down

0 comments on commit af01c2e

Please sign in to comment.