From ed2b803ce5c8000b7570f80be84dd67e9c57b2b2 Mon Sep 17 00:00:00 2001 From: Biedermann Steve Date: Fri, 10 May 2024 10:23:49 +0200 Subject: [PATCH] update --- .gitignore | 1 + Cargo.lock | 16 ++++ Cargo.toml | 1 + generate.sh | 12 +++ orig.md | 126 -------------------------- out.md | 120 ------------------------- out.pdf | Bin 90601 -> 0 bytes req.yml | 234 +++++++++---------------------------------------- src/lib.rs | 133 +--------------------------- src/main.rs | 201 +++++++++++++++++++++++++----------------- test_result.md | 36 -------- 11 files changed, 193 insertions(+), 687 deletions(-) create mode 100755 generate.sh delete mode 100644 orig.md delete mode 100644 out.md delete mode 100644 out.pdf delete mode 100644 test_result.md diff --git a/.gitignore b/.gitignore index ea8c4bf..0a25f36 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +/out diff --git a/Cargo.lock b/Cargo.lock index 0118703..7528216 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -332,6 +332,15 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "markdown" +version = "1.0.0-alpha.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21e27d6220ce21f80ce5c4201f23a37c6f1ad037c72c9d1ff215c2919605a5d6" +dependencies = [ + "unicode-id", +] + [[package]] name = "memchr" version = "2.7.2" @@ -469,6 +478,7 @@ dependencies = [ "clap", "crossterm 0.27.0", "indexmap", + "markdown", "ratatui", "regex", "rsn", @@ -745,6 +755,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "unicode-id" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1b6def86329695390197b82c1e244a54a131ceb66c996f2088a3876e2ae083f" + [[package]] name = "unicode-ident" version = "1.0.12" diff --git a/Cargo.toml b/Cargo.toml index e511f19..30b6617 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ anyhow = "1.0.83" clap = { version = "4.5.4", features = ["derive"] } crossterm = "0.27.0" indexmap = { version = "2.2.6", features = ["serde"] } +markdown = "1.0.0-alpha.17" ratatui = "0.26.2" regex = "1.10.4" rsn = "0.1.0" diff --git a/generate.sh b/generate.sh new file mode 100755 index 0000000..3614140 --- /dev/null +++ b/generate.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +source_dir="$(dirname "${BASH_SOURCE[0]}")" +pushd "$source_dir" + +mkdir -p out +cargo build +cargo run -q -- schema > out/schema.json +cargo run -q -- demo > out/demo.yml +cargo run -q -- md req.yml > out/requirements.md +cargo run -q -- html req.yml > out/requirements.html +cargo run -q -- check req.yml test_result.txt > out/text_result.md diff --git a/orig.md b/orig.md deleted file mode 100644 index 005d273..0000000 --- a/orig.md +++ /dev/null @@ -1,126 +0,0 @@ -# Requirements for journal-uploader - -[[_TOC_]] - -The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", -"MAY", and "OPTIONAL" in this document are to be interpreted as described in -[RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119). - -## Purpose -The journal-uploader has two main functionalities. -- Take a stream of log messages and filter them depending on their severity -- Upload journal logs for a specified time when activated through cloud call - -## Requirements -### 1. Traced Logging -#### 1.1 File Monitoring -- **1.1.1 Continuous Monitoring:** The tool **_MUST_** continuously monitor a designated directory. - -#### 1.2 File Detection -- **1.2.1 Detection of New Files:** The tool **_MUST_** detect the addition of new files in the monitored directory. -- **1.2.2 Avoid Re-processing:** The tool **_MUST NOT_** process files that have already been processed. - -#### 1.3 File Processing -- **1.3.1 Reading Log Messages:** When a new file is processed, each log message **_SHOULD_** be put into a buffer. -- **1.3.2 Filtering Log Messages:** The tool will search for messages of a defined priority (Trigger Priority). - Each message of this priority, as well as all messages before and after, which are inside a defined timespan, **_MUST_** - get written into a file. Every other message **_SHOULD_** gets dropped. -- **1.3.3 No Duplicate Log Messages:** The tool **_SHALL_** make sure that no log entry will be written to the file twice. - -#### 1.4 Traced Log Rotation -- **1.4.1 Rotating Files:** When the size of the current traced log file exceeds a certain threshold, - it **_MUST_** be closed and a new file **_MUST_** be opened for writing. -- **1.4.2 Compression of Rotated Files:** Each traced log file **_MUST_** get compressed after it got rotated. -- **1.4.3 Rotating Directory:** When the directory size exceeds a certain threshold, the tool **_MUST_** delete the oldest - files in the directory, until the size is below the threshold again. - -### 2. Remote Journal Logging -#### 2.1 Service Activation -- **2.1.1 Cloud Activation:** The remote journal logging **_SHALL_** be startable through a function call from the cloud. - The api call has the duration and max interval as arguments. -- **2.1.2 Duration:** The remote journal logging **_SHOULD_** stay active, until it reaches the specified duration. -- **2.1.3 Max Interval:** If no upload was done after the amount of time specified in max interval, - a log rotation **_SHALL_** be triggered, which will in turn get picked up by the file monitoring. -- **2.1.4 Analytics Not Accepted:** If the user has not accepted the usage of their data, the cloud call **_MUST_** - result in an error. - -#### 2.2 File Monitoring -- **2.2.1 Continuous Monitoring:** The tool **_SHOULD_** continuously monitor a designated directory. - -#### 2.3 File Detection -- **2.3.1 Detection of New Files:** The tool **_MUST_** detect the addition of new files in the monitored directory. -- **2.3.2 Avoid Re-processing:** The tool **_MUST NOT_** process files that have already been processed. - -#### 2.4 File Processing -- **2.4.1 File Upload:** When a file gets detected, it **_SHOULD_** get uploaded to the cloud. -- **2.4.2 No Duplicate Files:** Already processed files **_MUST NOT_** get uploaded again. -- **2.4.3 Revoking Analytics:** If the user revokes the usage of their data, the service **_MAY_** continue running - but **_MUST NOT_** upload any data until the user allows the usage of their data again. -- **2.4.4 Duration Expired:** After the specified duration is expired, the service **_SHOULD_** stop uploading files. - -### 3. Configuration -- **3.1 Configurable Journal Directory:** Users **_SHOULD_** be able to specify the directory to be monitored for - journal files. -- **3.2 Configurable Output Directory:** Users **_SHOULD_** be able to specify the directory into which the final files - will be written. -- **3.3 Configurable Trigger Priority:** Users **_SHOULD_** be able to specify which priority triggers the filtering. -- **3.4 Configurable Journal Context:** Users **_SHOULD_** be able to specify how many seconds of context will be added - to traced logs when encountering a trigger priority. -- **3.5 Configurable Max File Size:** Users **_SHOULD_** be able to specify the max file size, at which a file gets rotated. -- **3.6 Configurable Max Directory Size:** Users **_SHOULD_** be able to specify the max directory size, at which a - directory gets rotated. -- **3.7 Configurable File Monitoring Interval:** Users **_SHOULD_** be able to specify an interval, which **_SHOULD_** change - how long the tool waits before checking if new files are available. - -### 4. Performance Requirements -- **4.1 Efficiency:** The tool **_SHOULD_** efficiently monitor and process files without excessive resource consumption. -- **4.2 Interval Delay:** The tool **_SHOULD_** do its work with no more than 10 seconds delay after its interval. - -### 5. Data Protection -- **5.1 No Insecure Connection:** The tool **_MUST_** send data only through a secure connection. -- **5.2 GDPR compliance:** The tool **_MUST NOT_** upload data if the user has not agreed to share this information. - -### 6. Testing -- **6.1 Unit Tests:** Comprehensive unit tests **_SHOULD_** be written to cover major functionalities. -- **6.2 Integration Tests:** Integration tests **_SHOULD_** be conducted to ensure all parts of the tool work together - seamlessly. - -## Definitions -- Default Journal Directory: /run/log/journal/ - - Machine ID can be found at /etc/machine-id -- Default Output Directory: /run/log/filtered-journal - -## Config Defaults -- **Journal Directory** - - type: Path - - **Required**: This value **_MUST_** be provided as a start parameter. - -- **Output Directory** - - type: Path - - **Required**: This value **_MUST_** be provided as a start parameter. - -- **Trigger Priority** - - type: Enum - - Valid Values: _Emergency, Alert, Critical, Error, Warning, Notice, Info, Debug_ - - Default Value: _Warning_ - -- **Journal Context** - - type: Integer - - unit: Seconds - - Default Value: _15_ - -- **Max File Size** - - type: Integer - - unit: Bytes - - Default Value: _8388608_ (8 MB) - -- **Max Directory Size** - - type: Integer - - unit: Bytes - - Default Value: _75497472_ (72 MB) - -- **File Monitoring Interval** - - type: Integer - - unit: Seconds - - Default Value: _10_ - diff --git a/out.md b/out.md deleted file mode 100644 index feee318..0000000 --- a/out.md +++ /dev/null @@ -1,120 +0,0 @@ -# Requirements for journal-uploader - -[[_TOC_]] - -The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", -"MAY", and "OPTIONAL" in this document are to be interpreted as described in -[RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119). - - -## Description -The journal-uploader has two main functionalities. -- Take a stream of log messages and filter them depending on their severity -- Upload journal logs for a specified time when activated through cloud call - -## Requirements -### _TOPIC-1_ - Journal Watcher -#### _SUB-1.1_ - File Monitoring -- **_REQ-1.1.1_ - Continuous Monitoring:** The tool **_MUST_** continuously monitor a designated directory. - -#### _SUB-1.2_ - File Detection -- **_REQ-1.2.1_ - Detection of New Files:** The tool **_MUST_** detect the addition of new files in the monitored directory. -- **_REQ-1.2.2_ - Avoid Re-processing:** The tool **_MUST NOT_** process files that have already been processed. - - -### _TOPIC-2_ - Traced Logging -#### _SUB-2.1_ - File Processing -- **_REQ-2.1.1_ - Reading Log Messages:** When a new file is processed, each log message **_SHOULD_** be put into a buffer. -- **_REQ-2.1.2_ - Filtering Log Messages:** The tool will search for messages of a defined priority (Trigger Priority). -Each message of this priority, as well as all messages before and after, which are inside a defined timespan, **_MUST_** -get written into a file. Every other message **_SHOULD_** gets dropped. -- **_REQ-2.1.3_ - No Duplicate Log Messages:** The tool **_SHALL_** make sure that no log entry will be written to the file twice. - -#### _SUB-2.2_ - Traced Log Rotation -- **_REQ-2.2.1_ - Rotating Files:** When the size of the current traced log file exceeds a certain threshold, -it **_MUST_** be closed and a new file **_MUST_** be opened for writing. -- **_REQ-2.2.2_ - Compression of Rotated Files:** Each traced log file **_MUST_** get compressed after it got rotated. -- **_REQ-2.2.3_ - Rotating Directory:** When the directory size exceeds a certain threshold, the tool **_MUST_** delete the oldest -files in the directory, until the size is below the threshold again. - - -### _TOPIC-3_ - Remote Journal Logging -#### _SUB-3.1_ - Service Activation -- **_REQ-3.1.1_ - Cloud Activation:** The remote journal logging **_SHALL_** be startable through a function call from the cloud. -The api call has the duration and max interval as arguments. -- **_REQ-3.1.2_ - Duration:** The remote journal logging **_SHOULD_** stay active, until it reaches the specified duration. -- **_REQ-3.1.3_ - Max Interval:** If no upload was done after the amount of time specified in max interval, -a log rotation **_SHALL_** be triggered, which will in turn get picked up by the file monitoring. -- **_REQ-3.1.4_ - Analytics Not Accepted:** If the user has not accepted the usage of their data, the cloud call **_MUST_** -result in an error. - -#### _SUB-3.2_ - File Processing -- **_REQ-3.2.1_ - File Upload:** When a file gets detected, it **_SHOULD_** get uploaded to the cloud. -- **_REQ-3.2.2_ - No Duplicate Files:** Already processed files **_MUST NOT_** get uploaded again. -- **_REQ-3.2.3_ - Revoking Analytics:** If the user revokes the usage of their data, the service **_MAY_** continue running -but **_MUST NOT_** upload any data until the user allows the usage of their data again. -- **_REQ-3.2.4_ - Duration Expired:** After the specified duration is expired, the service **_SHOULD_** stop uploading files. - - -### _TOPIC-4_ - Configuration -- **_CONF-4.1_ - Journal Directory:** Users **_SHOULD_** be able to specify the directory to be monitored for journal files. -- **_CONF-4.2_ - Output Directory:** Users **_SHOULD_** be able to specify the directory into which the final files will be written. -- **_CONF-4.3_ - Trigger Priority:** Users **_SHOULD_** be able to specify which priority triggers the filtering. -- **_CONF-4.4_ - Journal Context:** Users **_SHOULD_** be able to specify how many seconds of context will be added to traced logs when encountering a trigger priority. -- **_CONF-4.5_ - Max File Size:** Users **_SHOULD_** be able to specify the max file size, at which a file gets rotated. -- **_CONF-4.6_ - Max Directory Size:** Users **_SHOULD_** be able to specify the max directory size, at which a directory gets rotated. -- **_CONF-4.7_ - File Monitoring Interval:** Users **_SHOULD_** be able to specify an interval, which **_SHOULD_** change -how long the tool waits before checking if new files are available. - -### _TOPIC-5_ - Performance Requirements -- **_PERF-5.1_ - Efficiency:** The tool **_SHOULD_** efficiently monitor and process files without excessive resource consumption. -- **_PERF-5.2_ - Interval Delay:** The tool **_SHOULD_** do its work with no more than 10 seconds delay after its interval. - -### _TOPIC-6_ - Security & Data Protection -- **_SEC-6.1_ - No Insecure Connection:** The tool **_MUST_** send data only through a secure connection. -- **_SEC-6.2_ - GDPR compliance:** The tool **_MUST NOT_** upload data if the user has not agreed to share this information. - -### _TOPIC-7_ - Testing -- **_TST-7.1_ - Unit Tests:** Comprehensive unit tests **_SHOULD_** be written to cover major functionalities. -- **_TST-7.2_ - Integration Tests:** Integration tests **_SHOULD_** be conducted to ensure all parts of the tool work together seamlessly. - - -## Definitions -- Default Journal Directory: /run/log/journal/ - - Machine ID can be found at /etc/machine-id -- Default Output Directory: /run/log/filtered-journal - -## Config Defaults -- **Journal Directory** - - Type: Path - - **Required**: This value **_MUST_** be provided as a start parameter. - -- **Output Directory** - - Type: Path - - **Required**: This value **_MUST_** be provided as a start parameter. - -- **Trigger Priority** - - Type: Enum - - Valid Values: _Emergency, Alert, Critical, Error, Warning, Notice, Info, Debug_ - - Default Value: _Warning_ - -- **Journal Context** - - Type: Integer - - Unit: Seconds - - Default Value: _15_ - -- **Max File Size** - - Type: Integer - - Unit: Bytes - - Default Value: _8388608_ (8 MB) - -- **Max Directory Size** - - Type: Integer - - Unit: Bytes - - Default Value: _75497472_ (72 MB) - -- **File Monitoring Interval** - - Type: Integer - - Unit: Seconds - - Default Value: _10_ - diff --git a/out.pdf b/out.pdf deleted file mode 100644 index 91ddd2e8884fb45239bd01aef544945a15fb8c05..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 90601 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 z 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 Z;XWTdJZ;@QxrYlp6M%y>7Q4ex_b+EVvrhm3 diff --git a/req.yml b/req.yml index 533d12e..4bbe33b 100644 --- a/req.yml +++ b/req.yml @@ -1,203 +1,47 @@ -name: journal-uploader +name: Req version: 1.0.0 description: |- - The journal-uploader has two main functionalities. - - Take a stream of log messages and filter them depending on their severity - - Upload journal logs for a specified time when activated through cloud call + The project has the following functionalities: + - Output the schema that is used to specify requirements + - Convert requirements from one of the allowed text formats to Markdown + - Convert requirements from one of the allowed text formats to HTML + - Check test output for requirements and output a summary of requirement test status topics: TOPIC-1: - name: Journal Watcher - subtopics: - SUB-1.1: - name: File Monitoring - requirements: - REQ-1.1.1: - name: Continuous Monitoring - description: The tool must continuously monitor a designated directory. - SUB-1.2: - name: File Detection - requirements: - REQ-1.2.1: - name: Detection of New Files - description: The tool must detect the addition of new files in the monitored directory. - REQ-1.2.2: - name: Avoid Re-processing - description: The tool must not process files that have already been processed. - + name: Output Data + requirements: + REQ-1.1: + name: Output Json Schema + description: The tool must be able to print a valid JSON schema of the input format + REQ-1.2: + name: Demo Data + description: The tool should be able to output a valid YAML string to be used as a starting point TOPIC-2: - name: Traced Logging - subtopics: - SUB-2.1: - name: File Processing - requirements: - REQ-2.1.1: - name: Reading Log Messages - description: When a new file is processed, each log message should be put into a buffer. - REQ-2.1.2: - name: Filtering Log Messages - description: |- - The tool will search for messages of a defined priority (Trigger Priority). - Each message of this priority, as well as all messages before and after, which are inside a defined timespan, must - get written into a file. Every other message should gets dropped. - REQ-2.1.3: - name: No Duplicate Log Messages - description: The tool shall make sure that no log entry will be written to the file twice. - SUB-2.2: - name: Traced Log Rotation - requirements: - REQ-2.2.1: - name: Rotating Files - description: |- - When the size of the current traced log file exceeds a certain threshold, - it must be closed and a new file must be opened for writing. - REQ-2.2.2: - name: Compression of Rotated Files - description: Each traced log file must get compressed after it got rotated. - REQ-2.2.3: - name: Rotating Directory - description: |- - When the directory size exceeds a certain threshold, the tool must delete the oldest - files in the directory, until the size is below the threshold again. + name: Reading Requirement Files + requirements: + REQ-2.1: + name: Parsing From Multiple Data Formats + description: 'The tool must be able to read requirements in the following formats:' + additional_info: + - YAML + - JSON + - RSN + - TOML TOPIC-3: - name: Remote Journal Logging - subtopics: - SUB-3.1: - name: Service Activation - requirements: - REQ-3.1.1: - name: Cloud Activation - description: |- - The remote journal logging shall be startable through a function call from the cloud. - The api call has the duration and max interval as arguments. - REQ-3.1.2: - name: Duration - description: The remote journal logging should stay active, until it reaches the specified duration. - REQ-3.1.3: - name: Max Interval - description: |- - If no upload was done after the amount of time specified in max interval, - a log rotation shall be triggered, which will in turn get picked up by the file monitoring. - REQ-3.1.4: - name: Analytics Not Accepted - description: |- - If the user has not accepted the usage of their data, the cloud call must - result in an error. - SUB-3.2: - name: File Processing - requirements: - REQ-3.2.1: - name: File Upload - description: When a file gets detected, it should get uploaded to the cloud. - REQ-3.2.2: - name: No Duplicate Files - description: Already processed files must not get uploaded again. - REQ-3.2.3: - name: Revoking Analytics - description: |- - If the user revokes the usage of their data, the service may continue running - but must not upload any data until the user allows the usage of their data again. - REQ-3.2.4: - name: Duration Expired - description: After the specified duration is expired, the service should stop uploading files. - - TOPIC-4: - name: Configuration + name: File Processing requirements: - CONF-4.1: - name: Journal Directory - description: Users should be able to specify the directory to be monitored for journal files. - CONF-4.2: - name: Output Directory - description: Users should be able to specify the directory into which the final files will be written. - CONF-4.3: - name: Trigger Priority - description: Users should be able to specify which priority triggers the filtering. - CONF-4.4: - name: Journal Context - description: Users should be able to specify how many seconds of context will be added - to traced logs when encountering a trigger priority. - CONF-4.5: - name: Max File Size - description: Users should be able to specify the max file size, at which a file gets rotated. - CONF-4.6: - name: Max Directory Size - description: Users should be able to specify the max directory size, at which a directory gets rotated. - CONF-4.7: - name: File Monitoring Interval - description: |- - Users should be able to specify an interval, which should change - how long the tool waits before checking if new files are available. - - TOPIC-5: - name: Performance Requirements - requirements: - PERF-5.1: - name: Efficiency - description: The tool should efficiently monitor and process files without excessive resource consumption. - PERF-5.2: - name: Interval Delay - description: The tool should do its work with no more than 10 seconds delay after its interval. - - TOPIC-6: - name: Security & Data Protection - requirements: - SEC-6.1: - name: No Insecure Connection - description: The tool must send data only through a secure connection. - SEC-6.2: - name: GDPR compliance - description: The tool must not upload data if the user has not agreed to share this information. - - TOPIC-7: - name: Testing - requirements: - TST-7.1: - name: Unit Tests - description: Comprehensive unit tests should be written to cover major functionalities. - TST-7.2: - name: Integration Tests - description: Integration tests should be conducted to ensure all parts of the tool work together seamlessly. - -definitions: -- name: Default Journal Directory - value: /run/log/journal/ - additional_info: - - Machine ID can be found at /etc/machine-id -- name: Default Output Directory - value: /run/log/filtered-journal -config_defaults: -- name: Journal Directory - type: Path -- name: Output Directory - type: Path -- name: Trigger Priority - type: Enum - valid_values: - - Emergency - - Alert - - Critical - - Error - - Warning - - Notice - - Info - - Debug - default_value: Warning -- name: Journal Context - type: Integer - unit: Seconds - default_value: '15' -- name: Max File Size - type: Integer - unit: Bytes - default_value: '8388608' - hint: (8 MB) -- name: Max Directory Size - type: Integer - unit: Bytes - default_value: '75497472' - hint: (72 MB) -- name: File Monitoring Interval - type: Integer - unit: Seconds - default_value: '10' + REQ-3.1: + name: Pretty Print To Markdown + description: The tool must be able to produce Markdown, containing all the relevant data from the input data + REQ-3.2: + name: Pretty Print to HTML + description: The tool must be able to produce HTML, containing all the relevant data from the input data + REQ-3.3: + name: Analyze Test Output + description: | + The tool must be able to scan text files for requirement IDs and create a summary of the test status of the defined requirements. + The IDs must be in one of the following formats, where is a placeholder for the real id: + additional_info: + - ": success" + - ": failed" diff --git a/src/lib.rs b/src/lib.rs index c193dda..2790380 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,9 @@ use std::fmt; -use indexmap::{indexmap, IndexMap}; +use indexmap::IndexMap; use schemars::JsonSchema; use serde::de::{self, Unexpected, Visitor}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use stringlit::s; pub fn my_trim(v: &str, s: S) -> Result where @@ -19,7 +18,7 @@ pub struct Requirement { #[serde(serialize_with = "my_trim")] pub description: String, #[serde(default, skip_serializing_if = "Vec::is_empty")] - pub requires: Vec, + pub additional_info: Vec, } #[derive(JsonSchema, Debug, Deserialize, Serialize)] @@ -137,131 +136,7 @@ pub struct Project { pub config_defaults: Vec, } +#[must_use] pub fn demo_project() -> Project { - Project { - name: s!("journal-uploader"), - version: Version { - major: 1, - minor: 0, - patch: 0, - }, - description: s!(r" -The journal-uploader has two main functionalities. -- Take a stream of log messages and filter them depending on their severity -- Upload journal logs for a specified time when activated through cloud call"), - topics: indexmap! { - s!("FEAT-1") => Topic { - name: s!("Traced Logging"), - subtopics: indexmap! { - s!("SUB-1") => Topic { - name: s!("File Monitoring"), - requirements: indexmap! { - s!("REQ-1") => Requirement { - name: s!("Continuous Monitoring"), - description: s!(r"The tool must continuously monitor a designated directory."), - requires: vec! [], - } - }, - subtopics: indexmap! {} - }, - s!("SUB-2") => Topic { - name: s!("File Detection"), - requirements: indexmap! { - s!("REQ-1") => Requirement { - name: s!("Detection of New Files"), - description: s!(r"The tool must detect the addition of new files in the monitored directory."), - requires: vec! [], - }, - s!("REQ-2") => Requirement { - name: s!("Avoid Re-processing"), - description: s!(r"The tool must not process files that have already been processed."), - requires: vec! [], - } - }, - subtopics: indexmap! {} - }, - }, - requirements: indexmap! {}, - } - }, - definitions: vec![ - Definition { - name: s!("Default Journal Directory"), - value: s!("/run/log/journal/"), - additional_info: vec![s!("Machine ID can be found at /etc/machine-id")], - }, - Definition { - name: s!("Default Output Directory"), - value: s!("/run/log/filtered-journal"), - additional_info: vec![], - }, - ], - config_defaults: vec![ - ConfigDefault { - name: s!("Journal Directory"), - typ: s!("Path"), - unit: None, - valid_values: None, - default_value: None, - hint: None, - }, - ConfigDefault { - name: s!("Output Directory"), - typ: s!("Path"), - unit: None, - valid_values: None, - default_value: None, - hint: None, - }, - ConfigDefault { - name: s!("Trigger Priority"), - typ: s!("Enum"), - unit: None, - valid_values: Some(vec![ - s!("Emergency"), - s!("Alert"), - s!("Critical"), - s!("Error"), - s!("Warning"), - s!("Notice"), - s!("Info"), - s!("Debug"), - ]), - default_value: Some(s!("Warning")), - hint: None, - }, - ConfigDefault { - name: s!("Journal Context"), - typ: s!("Integer"), - unit: Some(s!("Seconds")), - valid_values: None, - default_value: Some(s!("15")), - hint: None, - }, - ConfigDefault { - name: s!("Max File Size"), - typ: s!("Integer"), - unit: Some(s!("Bytes")), - valid_values: None, - default_value: Some(s!("8388608")), - hint: Some(s!("(8 MB)")), - }, - ConfigDefault { - name: s!("Max Directory Size"), - typ: s!("Integer"), - unit: Some(s!("Bytes")), - valid_values: None, - default_value: Some(s!("75497472")), - hint: Some(s!("(72 MB)")), - }, - ConfigDefault { - name: s!("File Monitoring Interval"), - typ: s!("Integer"), - unit: Some(s!("Seconds")), - valid_values: None, - default_value: Some(s!("10")), - hint: None, - }, - ], - } + serde_yaml::from_str(include_str!("../req.yml")).expect("Should never happen!") } diff --git a/src/main.rs b/src/main.rs index b357212..20e0e8c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -41,14 +41,18 @@ fn check_requirements( ) { for (id, requirement) in requirements { if allowed_requirements.is_match(id) { - let status = if test_results.contains(&format!("{id} succeeded")) { + let status = if test_results.contains(&format!("{} succeeded", id.trim())) { ":white_check_mark:" - } else if test_results.contains(&format!("{id} failed")) { + } else if test_results.contains(&format!("{} failed", id.trim())) { ":x:" } else { ":warning:" }; - output.push(format!("- _{id}_ - {}: {status}", requirement.name)); + output.push(format!( + "- _{}_ - {}: {status}", + id.trim(), + requirement.name + )); } } } @@ -83,7 +87,12 @@ fn check_topics( { continue; } - output.push(format!("{} _{id}_ - {}", "#".repeat(level), topic.name)); + output.push(format!( + "{} _{}_ - {}", + "#".repeat(level), + id.trim(), + topic.name + )); if !topic.requirements.is_empty() { check_requirements( test_results, @@ -109,18 +118,23 @@ fn check_topics( fn add_requirements(output: &mut Vec, requirements: &IndexMap) { for (id, requirement) in requirements { output.push(format!( - "- **_{id}_ - {}:** {}", + "- **_{}_ - {}:** {}", + id.trim(), requirement.name.trim(), requirement.description.trim() )); + for info in &requirement.additional_info { + output.push(format!(" - {}", info.trim(),)); + } } } fn add_topics(output: &mut Vec, topics: &IndexMap, level: usize) { for (id, topic) in topics { output.push(format!( - "{} _{id}_ - {}", + "{} _{}_ - {}", "#".repeat(level), + id.trim(), topic.name.trim() )); if !topic.requirements.is_empty() { @@ -141,6 +155,9 @@ enum Command { Markdown { requirements: PathBuf, }, + Html { + requirements: PathBuf, + }, Check { #[arg(short, long, default_value = "REQ-.*")] allowed_requirements: String, @@ -155,91 +172,113 @@ struct Args { command: Command, } +fn parse(value: &str) -> anyhow::Result { + Ok(serde_yaml::from_str(value) + .or_else(|_| serde_json::from_str(value)) + .or_else(|_| rsn::from_str(value)) + .or_else(|_| toml::from_str(value))?) +} + +fn to_markdown(requirements: PathBuf) -> anyhow::Result { + let project: Project = parse(&std::fs::read_to_string(requirements)?)?; + + let mut output = vec![ + format!("# Requirements for {}", project.name.trim()), + nl(), + s!("[[_TOC_]]"), + nl(), + WORD_DESCRIPTION.trim().to_string(), + nl(), + format!("**VERSION: {}**", project.version), + nl(), + s!("## Description"), + project.description.trim().to_string(), + nl(), + ]; + + if !project.topics.is_empty() { + output.push(s!("## Requirements")); + add_topics(&mut output, &project.topics, 3); + } + + if !project.definitions.is_empty() { + output.push(s!("## Definitions")); + for definition in project.definitions { + output.push(format!( + "- {}: {}", + definition.name.trim(), + definition.value.trim() + )); + for info in definition.additional_info { + output.push(format!(" - {}", info.trim())) + } + } + output.push(nl()); + } + + if !project.config_defaults.is_empty() { + output.push(s!("## Config Defaults")); + for default in project.config_defaults { + output.push(format!("- **{}**", default.name.trim())); + output.push(format!(" - Type: {}", default.typ.trim())); + if let Some(unit) = default.unit { + output.push(format!(" - Unit: {}", unit.trim())); + } + if let Some(valid_values) = default.valid_values { + output.push(format!( + " - Valid Values: _{}_", + valid_values.join(", ").trim() + )); + } + if let Some(default_value) = default.default_value { + output.push(format!( + " - Default Value: _{}_{}", + default_value.trim(), + default + .hint + .map(|h| format!(" {}", h.trim())) + .unwrap_or_default() + )); + } else { + output.push(format!( + " - **Required**: This value **_MUST_** be provided as a start parameter.{}", + default + .hint + .map(|h| format!(" {}", h.trim())) + .unwrap_or_default() + )); + } + output.push(nl()); + } + } + + let mut output = output.join("\n"); + for word in HIGHLIGHTED_WORDS { + output = output.replace(word, &format!("**_{}_**", word.to_uppercase())); + } + Ok(output) +} + fn main() -> anyhow::Result<()> { let Args { command } = Args::parse(); match command { Command::Demo => { println!("{}", serde_yaml::to_string(&demo_project())?); } + Command::Html { requirements } => { + let output = to_markdown(requirements)?; + println!( + "{}", + markdown::to_html_with_options(&output, &markdown::Options::gfm()) + .map_err(|e| anyhow::anyhow!("{e}"))? + ); + } Command::Schema => { let schema = schema_for!(Project); println!("{}", serde_json::to_string_pretty(&schema).unwrap()); } Command::Markdown { requirements } => { - let project: Project = serde_yaml::from_str(&std::fs::read_to_string(requirements)?)?; - - let mut output = vec![ - format!("# Requirements for {}", project.name.trim()), - nl(), - s!("[[_TOC_]]"), - nl(), - WORD_DESCRIPTION.trim().to_string(), - nl(), - format!("**VERSION: {}**", project.version), - nl(), - s!("## Description"), - project.description.trim().to_string(), - nl(), - ]; - - if !project.topics.is_empty() { - output.push(s!("## Requirements")); - add_topics(&mut output, &project.topics, 3); - } - - if !project.definitions.is_empty() { - output.push(s!("## Definitions")); - for definition in project.definitions { - output.push(format!( - "- {}: {}", - definition.name.trim(), - definition.value.trim() - )); - for info in definition.additional_info { - output.push(format!(" - {}", info.trim())) - } - } - output.push(nl()); - } - - if !project.config_defaults.is_empty() { - output.push(s!("## Config Defaults")); - for default in project.config_defaults { - output.push(format!("- **{}**", default.name.trim())); - output.push(format!(" - Type: {}", default.typ.trim())); - if let Some(unit) = default.unit { - output.push(format!(" - Unit: {}", unit.trim())); - } - if let Some(valid_values) = default.valid_values { - output.push(format!( - " - Valid Values: _{}_", - valid_values.join(", ").trim() - )); - } - if let Some(default_value) = default.default_value { - output.push(format!( - " - Default Value: _{}_{}", - default_value.trim(), - default - .hint - .map(|h| format!(" {}", h.trim())) - .unwrap_or_default() - )); - } else { - output.push(format!( - " - **Required**: This value **_MUST_** be provided as a start parameter.{}", - default.hint.map(|h| format!(" {}", h.trim())).unwrap_or_default() - )); - } - output.push(nl()); - } - } - - let mut output = output.join("\n"); - for word in HIGHLIGHTED_WORDS { - output = output.replace(word, &format!("**_{}_**", word.to_uppercase())); - } - + let output = to_markdown(requirements)?; println!("{output}"); } Command::Check { @@ -249,7 +288,7 @@ fn main() -> anyhow::Result<()> { } => { let re = Regex::new(&allowed_requirements).unwrap(); let test_results = std::fs::read_to_string(test_results)?; - let project: Project = serde_yaml::from_str(&std::fs::read_to_string(requirements)?)?; + let project: Project = parse(&std::fs::read_to_string(requirements)?)?; let mut output = vec![format!("# Test Results - {}", project.name)]; check_topics(&test_results, &mut output, &project.topics, &re, 2); diff --git a/test_result.md b/test_result.md deleted file mode 100644 index 05eb278..0000000 --- a/test_result.md +++ /dev/null @@ -1,36 +0,0 @@ -# Test Results - journal-uploader -## _TOPIC-1_ - Journal Watcher -### _SUB-1.1_ - File Monitoring -- _REQ-1.1.1_ - Continuous Monitoring: :white_check_mark: - -### _SUB-1.2_ - File Detection -- _REQ-1.2.1_ - Detection of New Files: :white_check_mark: -- _REQ-1.2.2_ - Avoid Re-processing: :x: - - -## _TOPIC-2_ - Traced Logging -### _SUB-2.1_ - File Processing -- _REQ-2.1.1_ - Reading Log Messages: :white_check_mark: -- _REQ-2.1.2_ - Filtering Log Messages: :white_check_mark: -- _REQ-2.1.3_ - No Duplicate Log Messages: :x: - -### _SUB-2.2_ - Traced Log Rotation -- _REQ-2.2.1_ - Rotating Files: :white_check_mark: -- _REQ-2.2.2_ - Compression of Rotated Files: :white_check_mark: -- _REQ-2.2.3_ - Rotating Directory: :x: - - -## _TOPIC-3_ - Remote Journal Logging -### _SUB-3.1_ - Service Activation -- _REQ-3.1.1_ - Cloud Activation: :white_check_mark: -- _REQ-3.1.2_ - Duration: :white_check_mark: -- _REQ-3.1.3_ - Max Interval: :x: -- _REQ-3.1.4_ - Analytics Not Accepted: :white_check_mark: - -### _SUB-3.2_ - File Processing -- _REQ-3.2.1_ - File Upload: :white_check_mark: -- _REQ-3.2.2_ - No Duplicate Files: :x: -- _REQ-3.2.3_ - Revoking Analytics: :white_check_mark: -- _REQ-3.2.4_ - Duration Expired: :warning: - -