Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more information about what happend when executing a check #7

Merged
merged 4 commits into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 13 additions & 98 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -1,111 +1,26 @@
name: Rust
name: Build with rust and docker

on:
push:
workflow_dispatch:
pull_request:
schedule:
# Fetch new base image updates every night at 1am
- cron: '0 1 * * *'

env:
CARGO_TERM_COLOR: always
PROFILE: release

jobs:
pre-check:
name: Security, License Check
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- uses: EmbarkStudios/cargo-deny-action@v1

build-rust:
name: Build (Rust)
runs-on: ubuntu-20.04

strategy:
matrix:
arch:
- amd64
- arm64

steps:
- name: Set arch ${{ matrix.arch }}
env:
ARCH: ${{ matrix.arch }}
run: |
if [ "${ARCH}" == "arm64" ]; then
echo "rustarch=aarch64-unknown-linux-gnu" >> $GITHUB_ENV
elif [ "${ARCH}" == "amd64" ]; then
echo "rustarch=x86_64-unknown-linux-gnu" >> $GITHUB_ENV
else
exit 1
fi
if [ "$(dpkg --print-architecture)" != "${ARCH}" ]; then
echo "Cross-compiling to ${ARCH}."
echo "is_cross=true" >> $GITHUB_ENV
else
echo "Natively compiling to ${ARCH}."
echo "is_cross=false" >> $GITHUB_ENV
fi
- name: Set profile ${{ env.PROFILE }}
env:
PROFILE: ${{ env.PROFILE }}
run: |
if [ "${PROFILE}" == "release" ]; then
echo "profilestr=--release" >> $GITHUB_ENV
elif [ "${PROFILE}" == "debug" ]; then
echo "profilestr=" >> $GITHUB_ENV
else
echo "profilestr=--profile $PROFILE" >> $GITHUB_ENV
fi
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
target: ${{ env.rustarch }}
- uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.arch }}-${{ env.PROFILE }}
- name: Build (${{ matrix.arch }})
uses: actions-rs/cargo@v1
with:
use-cross: ${{ env.is_cross }}
command: build
args: --target ${{ env.rustarch }} ${{ env.profilestr }}
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: binaries-${{ matrix.arch }}
path: |
target/${{ env.rustarch }}/${{ env.PROFILE }}/bridgehead-monitoring


docker:
needs: [ build-rust, pre-check ]
if: github.ref_protected == true

# This workflow defines how a maven package is built, tested and published.
# Visit: https://github.com/samply/github-workflows/blob/develop/.github/workflows/docker-ci.yml, for more information
uses: samply/github-workflows/.github/workflows/docker-ci.yml@main
build-with-samply:
uses: samply/github-workflows/.github/workflows/rust.yml@main
with:
# The Docker Hub Repository you want eventually push to, e.g samply/share-client
image-name: "samply/bridgehead-monitoring"
# Define special prefixes for docker tags. They will prefix each images tag.
# image-tag-prefix: "foo"
# Define the build context of your image, typically default '.' will be enough
# build-context: '.'
# Define the Dockerfile of your image, typically default './Dockerfile' will be enough
build-file: './Dockerfile'
# NOTE: This doesn't work currently
# A list of build arguments, passed to the docker build
# Define the target platforms of the docker build (default "linux/amd64,linux/arm64/v8")
# build-platforms: "linux/amd64,linux/arm64"
# If your actions generate an artifact in a previous build step, you can tell this workflow to download it
artifact-name: '*'
# This passes the secrets from calling workflow to the called workflow
# For information on these variables, please refer to https://github.com/samply/github-workflows/tree/main/.github/workflows/rust.yml
# Docker Hub name will be {image-prefix}{component}
image-prefix: "samply/"
components: '[ "bridgehead-monitoring" ]'
#architectures: '[ "amd64" ]'
#profile: debug
#test-via-script: true
#features: '[ "", "sockets" ]'
push-to: ${{ (github.ref_protected == true || github.event_name == 'workflow_dispatch') && 'dockerhub' || 'ghcr' }}
secrets:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

[workspace]
resolver = "2"
members = [
"bin",
"lib",
Expand Down
37 changes: 15 additions & 22 deletions bin/src/checks.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,36 @@
use async_trait::async_trait;
use bridgehead_monitoring_lib::Check;
use bridgehead_monitoring_lib::{Check, CheckResult};
use reqwest::StatusCode;
use serde_json::Value;

use crate::{CLIENT, CONFIG};

#[async_trait]
pub trait CheckExecutor {
async fn execute(&self) -> String;
async fn execute(&self) -> Result<CheckResult, CheckResult>;
}

#[async_trait]
impl CheckExecutor for Check {
async fn execute(&self) -> String {
async fn execute(&self) -> Result<CheckResult, CheckResult> {
match self {
Check::BlazeHealth => {
match CLIENT.get(format!("{}health", CONFIG.blaze_url)).send().await {
Ok(res) => {
res.status().to_string()
},
Err(e) => e.to_string()
let res = CLIENT.get(format!("{}health", CONFIG.blaze_url)).send().await?;
if res.status() == StatusCode::OK {
Ok(CheckResult::Ok(res.status().to_string()))
} else {
Err(CheckResult::Err(format!("Unhealthy: {}", res.status())))
}
},
Check::BlazeResources => {
match CLIENT.get(format!("{}fhir", CONFIG.blaze_url)).send().await {
Ok(res) => {
let json = &res.json::<Value>().await.unwrap_or(Value::Null)["total"];
serde_json::to_string(json).unwrap_or_else(|e| e.to_string())
},
Err(e) => e.to_string()
}
let res = CLIENT.get(format!("{}fhir", CONFIG.blaze_url)).send().await?;
let json = &res.json::<Value>().await?["total"];
Ok(CheckResult::Ok(serde_json::to_string(json)?))
},
Check::BlazeVersion => {
match CLIENT.get(format!("{}fhir/metadata", CONFIG.blaze_url)).send().await {
Ok(res) => {
let json = &res.json::<Value>().await.unwrap_or(Value::Null)["software"]["version"];
serde_json::to_string(json).unwrap_or_else(|e| e.to_string())
},
Err(e) => e.to_string()
}
let res = CLIENT.get(format!("{}fhir/metadata", CONFIG.blaze_url)).send().await?;
let json = &res.json::<Value>().await?["software"]["version"];
Ok(CheckResult::Ok(serde_json::to_string(json)?))
}
}
}
Expand Down
12 changes: 8 additions & 4 deletions bin/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use beam_lib::{MsgId, TaskRequest, TaskResult, WorkStatus, AppId};
use checks::CheckExecutor;
use clap::Parser;
use config::Config;
use bridgehead_monitoring_lib::Check;
use futures::future::join_all;
use bridgehead_monitoring_lib::{Check, CheckResult};
use futures::{future::join_all, FutureExt};
use once_cell::sync::Lazy;
use reqwest::{Client, StatusCode, header::{HeaderMap, AUTHORIZATION, HeaderValue, ACCEPT}};
use serde_json::Value;
Expand Down Expand Up @@ -33,7 +33,11 @@ async fn main() {
let Some((checks, task_id, sender)) = poll_checks().await else {
break;
};
let results = join_all(checks.iter().map(CheckExecutor::execute)).await;
let results = join_all(checks
.iter()
.map(CheckExecutor::execute)
.map(|f| f.map(|res| res.unwrap_or_else(|e| e))))
.await;
send_results(results, task_id, sender).await;
}
}
Expand Down Expand Up @@ -81,7 +85,7 @@ async fn poll_checks() -> Option<(Vec<Check>, MsgId, AppId)> {
None
}

async fn send_results(results: Vec<String>, task_id: MsgId, sender: AppId) {
async fn send_results(results: Vec<CheckResult>, task_id: MsgId, sender: AppId) {
let url = CONFIG.beam_proxy_url.join(&format!("/v1/tasks/{task_id}/results/{}", CONFIG.beam_id)).unwrap();

let resp = CLIENT.put(url).json(&TaskResult {
Expand Down
15 changes: 14 additions & 1 deletion lib/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::fmt;
use std::{fmt, error::Error};

use serde::{Serialize, Deserialize};

Expand All @@ -20,3 +20,16 @@ impl fmt::Display for Check {
f.write_str(name)
}
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub enum CheckResult {
Ok(String),
Err(String),
Unexpected(String)
}

impl<E: Error> From<E> for CheckResult {
fn from(value: E) -> Self {
Self::Err(value.to_string())
}
}