From 1ef5339cb522abb8ef9a5b1f38895a60576638be Mon Sep 17 00:00:00 2001 From: Felix Dumbeck <53702818+f-eliks@users.noreply.github.com> Date: Mon, 31 Jul 2023 15:28:19 +0200 Subject: [PATCH] Doc (#111) --- .github/workflows/mdbook.yml | 60 ++++++++++++++++++++++++ doc/.gitignore | 1 + doc/book.toml | 6 +++ doc/src/SUMMARY.md | 18 +++++++ doc/src/generator/README.md | 1 + doc/src/generator/environment.md | 1 + doc/src/generator/specs.md | 25 ++++++++++ doc/src/generator/templates.md | 73 +++++++++++++++++++++++++++++ doc/src/microservice/environment.md | 29 ++++++++++++ doc/src/microservice/opa.md | 8 ++++ doc/templates.org | 60 ------------------------ 11 files changed, 222 insertions(+), 60 deletions(-) create mode 100644 .github/workflows/mdbook.yml create mode 100644 doc/.gitignore create mode 100644 doc/book.toml create mode 100644 doc/src/SUMMARY.md create mode 100644 doc/src/generator/README.md create mode 100644 doc/src/generator/environment.md create mode 100644 doc/src/generator/specs.md create mode 100644 doc/src/generator/templates.md create mode 100644 doc/src/microservice/environment.md create mode 100644 doc/src/microservice/opa.md delete mode 100644 doc/templates.org diff --git a/.github/workflows/mdbook.yml b/.github/workflows/mdbook.yml new file mode 100644 index 0000000..0a4c10f --- /dev/null +++ b/.github/workflows/mdbook.yml @@ -0,0 +1,60 @@ +# Sample workflow for building and deploying a mdBook site to GitHub Pages +# +# To get started with mdBook see: https://rust-lang.github.io/mdBook/index.html +# +name: Deploy mdBook site to Pages + +on: + # Runs on pushes targeting the default branch + push: + branches: ["main"] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + # Build job + build: + runs-on: ubuntu-latest + env: + MDBOOK_VERSION: 0.4.21 + steps: + - uses: actions/checkout@v3 + - name: Install mdBook + run: | + curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf -y | sh + rustup update + cargo install --version ${MDBOOK_VERSION} mdbook + - name: Setup Pages + id: pages + uses: actions/configure-pages@v3 + - name: Build with mdBook + run: mdbook build ./doc + - name: Upload artifact + uses: actions/upload-pages-artifact@v2 + with: + path: ./doc/book + + # Deployment job + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v2 diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 0000000..7585238 --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1 @@ +book diff --git a/doc/book.toml b/doc/book.toml new file mode 100644 index 0000000..c0e3fe6 --- /dev/null +++ b/doc/book.toml @@ -0,0 +1,6 @@ +[book] +authors = ["crustagen"] +language = "en" +multilingual = false +src = "./src" +title = "crustagen" diff --git a/doc/src/SUMMARY.md b/doc/src/SUMMARY.md new file mode 100644 index 0000000..c9418ac --- /dev/null +++ b/doc/src/SUMMARY.md @@ -0,0 +1,18 @@ +# Summary +- [Overview]() +- [Introduction]() + - [Motivation]() + - [Prerequisites]() + - [Features]() +- [Generator]() + - [How it works]() + - [Usage]() + - [How to write spec files](generator/specs.md) + - [How to write your own templates](generator/templates.md) +- [Microservice]() + - [How it works]() + - [Usage]() + - [Environment Variables](microservice/environment.md) + - [Working with Open Policy Agent](microservice/opa.md) + - [Tracing]() + - [Metadata server]() diff --git a/doc/src/generator/README.md b/doc/src/generator/README.md new file mode 100644 index 0000000..7a6c19c --- /dev/null +++ b/doc/src/generator/README.md @@ -0,0 +1 @@ +# Microservice diff --git a/doc/src/generator/environment.md b/doc/src/generator/environment.md new file mode 100644 index 0000000..1d535f2 --- /dev/null +++ b/doc/src/generator/environment.md @@ -0,0 +1 @@ +# Environment Variables diff --git a/doc/src/generator/specs.md b/doc/src/generator/specs.md new file mode 100644 index 0000000..b0412e6 --- /dev/null +++ b/doc/src/generator/specs.md @@ -0,0 +1,25 @@ +# How to write spec files + +The generator is mostly* compliant with the [AsyncAPI specification](https://github.com/asyncapi/spec) + +## *Limitations + + - Only json payloads are currently supported for automatic deserialization + - Only one server is currently supported and only nats protocol is supported + - Generated microservice doesn't support authentication with NATS-broker out of the box + - Only one message is currently supported per channel, payloads can be choosen freely including anyOf/oneOf/allOf + - The generated rust types are required by default, if you want to use optional types, please modify the generated types after generation or use oneOf/anyOf/allOf to represent optional types + - references in the specification are only suppported inside the same file, external references are not supported + + +## Crustagen specific features + + - A channel supposed to be a stream can be declared in the specification file with the `x-streamname` field. + ```yaml + channels: + {channel-name}: + {channel-operation}: + bindings: + nats: + x-streamname: testStream + ``` diff --git a/doc/src/generator/templates.md b/doc/src/generator/templates.md new file mode 100644 index 0000000..c30aa55 --- /dev/null +++ b/doc/src/generator/templates.md @@ -0,0 +1,73 @@ +# Writing your own templates + +- Any templates that in the templates folder at compilation time will be embedded in the compiled binary. +- If you only have the binary you can put templates in the folder `user-templates`. + If a file from the `user-templates` folder has the same path as an embedded template, only the template from `user-template` will be rendered. + - set the command line argument `--user-templates` or `-u` to set a custom folder +- the last file extension will be removed e.g: `file.rs.go` will be rendered to `file.rs`. +- For examples refer to the allready included [templates](https://github.com/Programmierpraktikum-MVA/AsyncAPI/tree/d05d047c5ea9dfb221f31ecbf5af03387103e342/templates) + + + +## What fields are available inside templates? + +Any of these fields will be accessible: +```rust,noplayground + pub struct TemplateContext<'a> { + pub title: &'a String, + pub description: &'a Option, + pub server: &'a Server, + pub subscribe_channels: Vec<(&'a String, SimplifiedOperation)>, + pub publish_channels: Vec<(&'a String, SimplifiedOperation)>, + pub model: Model, + } + + pub struct Model { + pub message_models: Vec, + // pub enums: Vec, + } + + pub struct SimplifiedOperation { + pub unique_id: String, + pub original_operation: Operation, + // array, da es eine oder mehrere messages geben kann + pub messages: Vec, + // pub multiple_messages_enum: Option, + } + + pub struct MultiStructEnum { + pub unique_id: String, + pub messages: Vec, + pub struct_definition: String, + } + + pub struct SimplifiedMessage { + pub unique_id: String, + pub original_message: Message, + pub payload: Option, + } +``` +- for more information about the fields available from these structs please refer to: [all rust structs](https://github.com/Programmierpraktikum-MVA/AsyncAPI/tree/main/src/asyncapi_model) + + + +## Render to separate files + +It is possible to generate files for each specific object in your AsyncAPI documentation. For example, you can specify a filename like `$$handler$$.rs.go` to generate a file for each `publish_channel` defined in your AsyncAPI spec. + +This works with file templates that include the following in their name: +- `$$handler$$` +- `$$producer$$` +- `$$model$$` +- `$$schemas$$` + + + +## Functions available inside the templates + +- `to_lower(input: String) -> String` converts String to lowercase +- `key_exists(input: String) -> String` checks if key exists +- `camel_to_snake_case(input :String) -> String` converts a String in camelCase to snake_case +- `replace(input: String, from: String, to: String) -> String` replaces `from` with `to` for `input` + - Side Note: these functions are defined in `src/generator/template_functions.rs` feel free to extend then, if you have access to the source code. + diff --git a/doc/src/microservice/environment.md b/doc/src/microservice/environment.md new file mode 100644 index 0000000..fc488c8 --- /dev/null +++ b/doc/src/microservice/environment.md @@ -0,0 +1,29 @@ +# Environment Variables + +An `.env`-file is automatically generated from the [.env template](https://github.com/Programmierpraktikum-MVA/AsyncAPI/blob/d05d047c5ea9dfb221f31ecbf5af03387103e342/templates/.env.go) +If you want to extend the .env file feel free to do so in the generated code +- or if you want to customize the generated .enf file before it is generated take a look at [writing your own templates](../generator/templates.md) +The generated microservice uses the following environment variables (with their respective default values): +```json +SERVICE_PORT = "8080" +SERVER_URL = "{{ .server.url }}" +LOG_LEVEL = "DEBUG" # available levels are ERROR, WARN, INFO, DEBUG and TRACE +OPA_RULES= "path/to/admin/policy" +TRACING_ENABLED = false +SCHEMA_VALIDATION_ENABLED = true +``` + +Also per channel the subject will be set via an environment variable: +```json +{channel_name}_SUBJECT = "{subject}" # for normal pub_sub channels +{channel_name}_QUEUE = "{subject}" # for nats queue channels +{channel_name}_STREAM = "{subject}" # for nats jetstream channels +``` + +And for OPA +```json +OPA_ENABLED = false # choose if OPA should be enabled +#OPA_REMOTE_URL = "localhost:4042" # pick the url for an opa server +#OPA_LOCAL_WASM_PATH = "some/path" # pick the path of a to wasm compiled rego file +``` +- for more information see [Working with Open Policy Agent](./opa.md) diff --git a/doc/src/microservice/opa.md b/doc/src/microservice/opa.md new file mode 100644 index 0000000..822f496 --- /dev/null +++ b/doc/src/microservice/opa.md @@ -0,0 +1,8 @@ +# Working with Open Policy Agent +The microservice can utilize the function: +```rust,noplayground +pub async fn opa_eval(input: Serialize) -> Result +``` +from `src/policy/policy.rs` +which sends the `input` to an opa_server or uses it as input to evaluate a to `.wasm` compiled `.rego` file dependant on the set [enviornment variables](./environment.md). + diff --git a/doc/templates.org b/doc/templates.org deleted file mode 100644 index fca9d56..0000000 --- a/doc/templates.org +++ /dev/null @@ -1,60 +0,0 @@ -#+title: Templates -#+date: [2023-07-06 Thu 21:25] - -* Writing your own templates -- Any templates that in the templates folder at compilation time will be embedded in the compiled binary. -- If you only have the binary you can put templates in the folder ~user-templates~. - If a file from the ~user-templates~ folder has the same path as an embedded template, only the template from ~user-template~ will be rendered. - - set the command line argument ~--user-templates~ or ~-u~ to set a custom folder -- the last file extension will be removed e.g: ~file.rs.go~ will be rendered to ~file.rs~. -** What fields are available inside templates? -- Any of these fields will be accessible: -#+begin_src rust -pub struct TemplateContext<'a> { - pub title: &'a String, - pub description: &'a Option, - pub server: &'a Server, - pub subscribe_channels: Vec<(&'a String, SimplifiedOperation)>, - pub publish_channels: Vec<(&'a String, SimplifiedOperation)>, - pub model: Model, -} - -pub struct Model { - pub message_models: Vec, - // pub enums: Vec, -} - -pub struct SimplifiedOperation { - pub unique_id: String, - pub original_operation: Operation, - // array, da es eine oder mehrere messages geben kann - pub messages: Vec, - // pub multiple_messages_enum: Option, -} - -pub struct MultiStructEnum { - pub unique_id: String, - pub messages: Vec, - pub struct_definition: String, -} - -pub struct SimplifiedMessage { - pub unique_id: String, - pub original_message: Message, - pub payload: Option, -} -#+end_src - - for more information about the fields available from these structs please refer to: [[https://github.com/Programmierpraktikum-MVA/AsyncAPI/tree/main/src/asyncapi_model]] -** Render to separate files -- It is possible to generate files for each specific object in your AsyncAPI documentation. For example, you can specify a filename like ~$$handler$$.rs.go~ to generate a file for each ~publish_channel~ defined in your AsyncAPI spec. - This works with file templates that include the following in their name: - - ~$$handler$$~ - - ~$$producer$$~ - - ~$$model$$~ - - ~$$schemas$$~ -** Functions available inside the templates -- ~to_lower(input: String) -> String~ converts String to lowercase -- ~key_exists(input: String) -> String~ checks if key exists -- ~camel_to_snake_case(input :String) -> String~ converts a String in camelCase to snake_case -- ~replace(input: String, from: String, to: String) -> String~ replaces =from= with =to= for =input= - - Side Note: these functions are defined in ~src/generator/template_functions.rs~ feel free to extend then, if you have access to the source code.