Repository: thangchung/webassembly-tour Branch: main Commit: 1d198945e4b4 Files: 39 Total size: 34.8 MB Directory structure: gitextract_hv3_bjyn/ ├── .editorconfig ├── .gitattributes ├── .gitignore ├── .vscode/ │ ├── C4.code-snippets │ └── settings.json ├── LICENSE ├── README.md ├── assets/ │ ├── wasm_tour.puml │ └── wasm_tour.xmind ├── docker-compose.yml ├── krustlet/ │ ├── README.md │ ├── bootstrap.sh │ └── greet-wasmcloud.yaml ├── restclient.http ├── wagi/ │ ├── functions/ │ │ ├── .cargo/ │ │ │ └── config.toml │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── get-todos/ │ │ │ ├── Cargo.toml │ │ │ └── src/ │ │ │ └── main.rs │ │ ├── modules.toml │ │ └── wagi │ └── server/ │ ├── .gitignore │ ├── .vscode/ │ │ ├── launch.json │ │ └── tasks.json │ ├── Program.cs │ ├── Properties/ │ │ └── launchSettings.json │ ├── Startup.cs │ ├── appsettings.json │ ├── modules/ │ │ ├── fibonacci.wasm │ │ └── get-todos.wasm │ └── server.csproj └── wasmcloud/ ├── README.md ├── docker-compose.yml ├── mini-store/ │ ├── Cargo.toml │ ├── justfile │ ├── manifest.yaml │ └── src/ │ └── lib.rs └── tools/ ├── pf.sh └── wasm-to-oci ================================================ FILE CONTENTS ================================================ ================================================ FILE: .editorconfig ================================================ root = true [*.rs] end_of_line = lf charset = utf-8 trim_trailing_whitespace = true indent_style = space indent_size = 4 ================================================ FILE: .gitattributes ================================================ * text=auto *.sh linguist-language=rust ================================================ FILE: .gitignore ================================================ # Generated by Cargo # will have compiled files and executables /target/ **/*/target/ # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html Cargo.lock # These are backup files generated by rustfmt **/*.rs.bk **/*/krustlet-config ================================================ FILE: .vscode/C4.code-snippets ================================================ { "C4_Include_Context": { "scope": "plantuml", "prefix": "Include C4 Context Diagram", "body": [ "!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Context.puml" ], "description": "Include C4 Context Diagram" }, "C4_Include_Container": { "scope": "plantuml", "prefix": "Include C4 Container Diagram", "body": [ "!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml" ], "description": "Include C4 Container Diagram" }, "C4_Include_Component": { "scope": "plantuml", "prefix": "Include C4 Component Diagram", "body": [ "!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml" ], "description": "Include C4 Component Diagram" }, "C4_Include_Deployment": { "scope": "plantuml", "prefix": "Include C4 Deployment Diagram", "body": [ "!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Deployment.puml" ], "description": "Include C4 Deployment Diagram" }, "C4_Include_Dynamic": { "scope": "plantuml", "prefix": "Include C4 Dynamic Diagram", "body": [ "!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Dynamic.puml" ], "description": "Include C4 Dynamic Diagram" }, "C4_Person": { "scope": "plantuml", "prefix": "Person", "body": [ "Person(${1:alias}, \"${2:label}\")" ], "description": "Add Person to C4 diagram" }, "C4_Person_Descr": { "scope": "plantuml", "prefix": "Person with Description", "body": [ "Person(${1:alias}, \"${2:label}\", \"${3:description}\")" ], "description": "Add Person with Description to C4 diagram" }, "C4_Person_Ext": { "scope": "plantuml", "prefix": [ "External Person", "Person (External)" ], "body": [ "Person_Ext(${1:alias}, \"${2:label}\")" ], "description": "Add External Person to C4 diagram" }, "C4_Person_Ext_Descr": { "scope": "plantuml", "prefix": [ "External Person with Description", "Person (External) with Description" ], "body": [ "Person_Ext(${1:alias}, \"${2:label}\", \"${3:description}\")" ], "description": "Add External Person with Description to C4 diagram" }, "C4_Container": { "scope": "plantuml", "prefix": "Container", "body": [ "Container(${1:alias}, \"${2:label}\", \"${3:technology}\")" ], "description": "Add Container to C4 diagram" }, "C4_Container_Descr": { "scope": "plantuml", "prefix": "Container with Description", "body": [ "Container(${1:alias}, \"${2:label}\", \"${3:technology}\", \"${4:description}\")" ], "description": "Add Container with Description to C4 diagram" }, "C4_Container_Ext": { "scope": "plantuml", "prefix": [ "External Container", "Container (External)" ], "body": [ "Container_Ext(${1:alias}, \"${2:label}\", \"${3:technology}\")" ], "description": "Add External Container to C4 diagram" }, "C4_Container_Ext_Descr": { "scope": "plantuml", "prefix": [ "External Container with Description", "Container (External) with Description" ], "body": [ "Container_Ext(${1:alias}, \"${2:label}\", \"${3:technology}\", \"${4:description}\")" ], "description": "Add External Container with Description to C4 diagram" }, "C4_ContainerDb": { "scope": "plantuml", "prefix": "Database Container", "body": [ "ContainerDb(${1:alias}, \"${2:label}\", \"${3:technology}\")" ], "description": "Add Database Container to C4 diagram" }, "C4_ContainerDb_Descr": { "scope": "plantuml", "prefix": "Database Container with Description", "body": [ "ContainerDb(${1:alias}, \"${2:label}\", \"${3:technology}\", \"${4:description}\")" ], "description": "Add Database Container with Description to C4 diagram" }, "C4_ContainerDb_Ext": { "scope": "plantuml", "prefix": [ "External Database Container", "Database Container (External)" ], "body": [ "ContainerDb_Ext(${1:alias}, \"${2:label}\", \"${3:technology}\")" ], "description": "Add External Database Container to C4 diagram" }, "C4_ContainerDb_Ext_Descr": { "scope": "plantuml", "prefix": [ "External Database Container with Description", "Database Container (External) with Description" ], "body": [ "ContainerDb_Ext(${1:alias}, \"${2:label}\", \"${3:technology}\", \"${4:description}\")" ], "description": "Add External Database Container with Description to C4 diagram" }, "C4_ContainerQueue": { "scope": "plantuml", "prefix": "Queue Container", "body": [ "ContainerQueue(${1:alias}, \"${2:label}\", \"${3:technology}\")" ], "description": "Add Queue Container to C4 diagram" }, "C4_ContainerQueue_Descr": { "scope": "plantuml", "prefix": "Queue Container with Description", "body": [ "ContainerQueue(${1:alias}, \"${2:label}\", \"${3:technology}\", \"${4:description}\")" ], "description": "Add Queue Container with Description to C4 diagram" }, "C4_ContainerQueue_Ext": { "scope": "plantuml", "prefix": [ "External Queue Container", "Queue Container (External)" ], "body": [ "ContainerQueue_Ext(${1:alias}, \"${2:label}\", \"${3:technology}\")" ], "description": "Add External Queue Container to C4 diagram" }, "C4_ContainerQueue_Ext_Descr": { "scope": "plantuml", "prefix": [ "External Queue Container with Description", "Queue Container (External) with Description" ], "body": [ "ContainerQueue_Ext(${1:alias}, \"${2:label}\", \"${3:technology}\", \"${4:description}\")" ], "description": "Add ExternalQueue Container with Description to C4 diagram" }, "C4_Container_Boundary": { "scope": "plantuml", "prefix": [ "Container Boundary", "Boundary for Container" ], "body": [ "Container_Boundary(${1:alias}, \"${2:label}\"){", "\t$0", "}" ], "description": "Add a Container Boundary to C4 diagram" }, "C4_Component": { "scope": "plantuml", "prefix": "Component", "body": [ "Component(${1:alias}, \"${2:label}\", \"${3:technology}\")" ], "description": "Add Component to C4 diagram" }, "C4_Component_Descr": { "scope": "plantuml", "prefix": "Component with Description", "body": [ "Component(${1:alias}, \"${2:label}\", \"${3:technology}\", \"${4:description}\")" ], "description": "Add Component with Description to C4 diagram" }, "C4_Component_Ext": { "scope": "plantuml", "prefix": [ "External Component", "Component (External)" ], "body": [ "Component_Ext(${1:alias}, \"${2:label}\", \"${3:technology}\")" ], "description": "Add External Component to C4 diagram" }, "C4_Component_Ext_Descr": { "scope": "plantuml", "prefix": [ "External Component with Description", "Component (External) with Description" ], "body": [ "Component_Ext(${1:alias}, \"${2:label}\", \"${3:technology}\", \"${4:description}\")" ], "description": "Add External Component with Description to C4 diagram" }, "C4_ComponentDb": { "scope": "plantuml", "prefix": "Database Component", "body": [ "ComponentDb(${1:alias}, \"${2:label}\", \"${3:technology}\")" ], "description": "Add Database Component to C4 diagram" }, "C4_ComponentDb_Descr": { "scope": "plantuml", "prefix": "Database Component with Description", "body": [ "ComponentDb(${1:alias}, \"${2:label}\", \"${3:technology}\", \"${4:description}\")" ], "description": "Add Database Component with Description to C4 diagram" }, "C4_ComponentDb_Ext": { "scope": "plantuml", "prefix": [ "External Database Component", "Database Component (External)" ], "body": [ "ComponentDb_Ext(${1:alias}, \"${2:label}\", \"${3:technology}\")" ], "description": "Add External Database Component to C4 diagram" }, "C4_ComponentDb_Ext_Descr": { "scope": "plantuml", "prefix": [ "External Database Component with Description", "Database Component (External) with Description" ], "body": [ "ComponentDb_Ext(${1:alias}, \"${2:label}\", \"${3:technology}\", \"${4:description}\")" ], "description": "Add External Database Component with Description to C4 diagram" }, "C4_ComponentQueue": { "scope": "plantuml", "prefix": "Queue Component", "body": [ "ComponentQueue(${1:alias}, \"${2:label}\", \"${3:technology}\")" ], "description": "Add Queue Component to C4 diagram" }, "C4_ComponentQueue_Descr": { "scope": "plantuml", "prefix": "Queue Component with Description", "body": [ "ComponentQueue(${1:alias}, \"${2:label}\", \"${3:technology}\", \"${4:description}\")" ], "description": "Add Queue Component with Description to C4 diagram" }, "C4_ComponentQueue_Ext": { "scope": "plantuml", "prefix": [ "External Queue Component", "Queue Component (External)" ], "body": [ "ComponentQueue_Ext(${1:alias}, \"${2:label}\", \"${3:technology}\")" ], "description": "Add External Queue Component to C4 diagram" }, "C4_ComponentQueue_Ext_Descr": { "scope": "plantuml", "prefix": [ "External Queue Component with Description", "Queue Component (External) with Description" ], "body": [ "ComponentQueue_Ext(${1:alias}, \"${2:label}\", \"${3:technology}\", \"${4:description}\")" ], "description": "Add External Queue Component with Description to C4 diagram" }, "C4_System": { "scope": "plantuml", "prefix": "System", "body": [ "System(${1:alias}, \"${2:label}\")" ], "description": "Add System to C4 diagram" }, "C4_System_Descr": { "scope": "plantuml", "prefix": "System with Description", "body": [ "System(${1:alias}, \"${2:label}\", \"${3:description}\")" ], "description": "Add System with Description to C4 diagram" }, "C4_System_Ext": { "scope": "plantuml", "prefix": [ "External System", "System (External)" ], "body": [ "System_Ext(${1:alias}, \"${2:label}\")" ], "description": "Add External System to C4 diagram" }, "C4_System_Ext_Descr": { "scope": "plantuml", "prefix": [ "External System with Description", "System (External) with Description" ], "body": [ "System_Ext(${1:alias}, \"${2:label}\", \"${3:description}\")" ], "description": "Add External System with Description to C4 diagram" }, "C4_SystemDb": { "scope": "plantuml", "prefix": "Database System", "body": [ "SystemDb(${1:alias}, \"${2:label}\")" ], "description": "Add Database System to C4 diagram" }, "C4_SystemDb_Descr": { "scope": "plantuml", "prefix": "Database System with Description", "body": [ "SystemDb(${1:alias}, \"${2:label}\", \"${3:description}\")" ], "description": "Add Database System with Description to C4 diagram" }, "C4_SystemDb_Ext": { "scope": "plantuml", "prefix": [ "External Database System", "Database System (External)" ], "body": [ "SystemDb_Ext(${1:alias}, \"${2:label}\")" ], "description": "Add External Database System to C4 diagram" }, "C4_SystemDb_Ext_Descr": { "scope": "plantuml", "prefix": [ "External Database System with Description", "Database System (External) with Description" ], "body": [ "SystemDb_Ext(${1:alias}, \"${2:label}\", \"${3:description}\")" ], "description": "Add External Database System with Description to C4 diagram" }, "C4_SystemQueue": { "scope": "plantuml", "prefix": "Queue System", "body": [ "SystemQueue(${1:alias}, \"${2:label}\")" ], "description": "Add Queue System to C4 diagram" }, "C4_SystemQueue_Descr": { "scope": "plantuml", "prefix": "Queue System with Description", "body": [ "SystemQueue(${1:alias}, \"${2:label}\", \"${3:description}\")" ], "description": "Add Queue System with Description to C4 diagram" }, "C4_SystemQueue_Ext": { "scope": "plantuml", "prefix": [ "External Queue System", "Queue System (External)" ], "body": [ "SystemQueue_Ext(${1:alias}, \"${2:label}\")" ], "description": "Add External Queue System to C4 diagram" }, "C4_SystemQueue_Ext_Descr": { "scope": "plantuml", "prefix": [ "External Queue System with Description", "Queue System (External) with Description" ], "body": [ "SystemQueue_Ext(${1:alias}, \"${2:label}\", \"${3:description}\")" ], "description": "Add External Queue System with Description to C4 diagram" }, "C4_System_Boundary": { "scope": "plantuml", "prefix": [ "System Boundary", "Boundary for System" ], "body": [ "System_Boundary(${1:alias}, \"${2:label}\"){", "\t$0", "}" ], "description": "Add a System Boundary to C4 diagram" }, "C4_Enterprise_Boundary": { "scope": "plantuml", "prefix": [ "Enterprise Boundary", "Boundary for Enterprise" ], "body": [ "Enterprise_Boundary(${1:alias}, \"${2:label}\"){", "\t$0", "}" ], "description": "Add an Enterprise Boundary to C4 diagram" }, "C4_Relationship": { "scope": "plantuml", "prefix": "Relationship", "body": [ "Rel(${1:from_alias}, ${2:to_alias}, \"${3:label}\")" ], "description": "Add unidirectional Relationship to C4 diagram" }, "C4_Relationship_Techn": { "scope": "plantuml", "prefix": "Relationship with Technology", "body": [ "Rel(${1:from_alias}, ${2:to_alias}, \"${3:label}\", \"${4:technology}\")" ], "description": "Add unidirectional Relationship with Technology to C4 diagram" }, "C4_Relationship_Bi": { "scope": "plantuml", "prefix": "Bidirectional Relationship", "body": [ "BiRel(${1:from_alias}, ${2:to_alias}, \"${3:label}\")" ], "description": "Add bidirectional Relationship to C4 diagram" }, "C4_Relationship_Bi_Techn": { "scope": "plantuml", "prefix": "Bidirectional Relationship with Technology", "body": [ "BiRel(${1:from_alias}, ${2:to_alias}, \"${3:label}\", \"${4:technology}\")" ], "description": "Add bidirectional Relationship with Technology to C4 diagram" }, "C4_Relationship_Index": { "scope": "plantuml", "prefix": "Relationship with Index", "body": [ "RelIndex(${1:index}, ${2:from_alias}, ${3:to_alias}, \"${4:label}\")" ], "description": "Add unidirectional Relationship to C4 Dynamic Diagram" }, "C4_Relationship_Index_Techn": { "scope": "plantuml", "prefix": "Relationship with Technology and Index", "body": [ "RelIndex(${1:index}, ${2:from_alias}, ${3:to_alias}, \"${4:label}\", \"${5:technology}\")" ], "description": "Add unidirectional Relationship with Technology to C4 Dynamic Diagram" }, "C4_Layout_Right": { "scope": "plantuml", "prefix": "Layout to Right side", "body": [ "Lay_R(${1:from_alias}, ${2:to_alias})" ], "description": "Add hidden layout line to put {to} to the right of {from}" }, "C4_Layout_Left": { "scope": "plantuml", "prefix": "Layout to Left side", "body": [ "Lay_L(${1:from_alias}, ${2:to_alias})" ], "description": "Add hidden layout line to put {to} to the left of {from}" }, "C4_Boundary": { "scope": "plantuml", "prefix": "Boundary", "body": [ "Boundary(${1:alias}, \"${2:label}\"){", "\t$0", "}" ], "description": "Add a generic boundary to C4 diagram." }, "C4_Boundary_Type": { "scope": "plantuml", "prefix": [ "Boundary with type" ], "body": [ "Boundary(${1:alias}, \"${2:label}\", \"${3:type}\"){", "\t$0", "}" ], "description": "Add a generic boundary to C4 diagram." }, "C4_Deployment_Node": { "scope": "plantuml", "prefix": "Deployment Node", "body": [ "Deployment_Node(${1:alias}, \"${2:label}\"){", "\t$0", "}" ], "description": "Add a deployment node to C4 diagram." }, "C4_Deployment_Node_Type": { "scope": "plantuml", "prefix": [ "Deployment Node with type" ], "body": [ "Deployment_Node(${1:alias}, \"${2:label}\", \"${3:type}\"){", "\t$0", "}" ], "description": "Add a deployment node to C4 diagram." }, "C4_Dynamic_Increment": { "scope": "plantuml", "prefix": [ "Increment index" ], "body": [ "increment(${1:count})" ], "description": "Increment index of C4 Dynamic Diagram." }, "C4_Dynamic_Set_Index": { "scope": "plantuml", "prefix": [ "Set index" ], "body": [ "setIndex(${1:value})" ], "description": "Set index of C4 Dynamic Diagram" }, "C4_Hide_Stereotype": { "scope": "plantuml", "prefix": [ "Hide stereotype", "No stereotype" ], "body": [ "HIDE_STEREOTYPE()" ], "description": "Hide stereotypes from C4 diagram.." }, "C4_Layout_With_Legend": { "scope": "plantuml", "prefix": [ "Layout with legend", "Legend layout" ], "body": [ "LAYOUT_WITH_LEGEND()" ], "description": "Add legend to C4 diagram." }, "C4_Layout_Left_Right": { "scope": "plantuml", "prefix": [ "Layout left to right", "Left to right layout" ], "body": [ "LAYOUT_LEFT_RIGHT()" ], "description": "Left to right layout for C4 diagram." }, "C4_Layout_Top_Down": { "scope": "plantuml", "prefix": [ "Layout top down", "Top down layout" ], "body": [ "LAYOUT_TOP_DOWN()" ], "description": "Top down layout for C4 diagram." }, "C4_Layout_As_Sketch": { "scope": "plantuml", "prefix": [ "Layout as sketch", "Sketch layout" ], "body": [ "LAYOUT_AS_SKETCH()" ], "description": "Sketch layout for C4 diagram." } } ================================================ FILE: .vscode/settings.json ================================================ { "plantuml.render": "PlantUMLServer", "plantuml.server": "http://localhost:8080/" } ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2021 Thang Chung Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # WebAssembly Tour WebAssembly on Rust is a bright future in making application runs at the Edge or on the Serverless technologies. We spend a lot of time researching and doing a deep dive into it. We have documented it as the [`mindmap`](https://plantuml.com/mindmap-diagram) diagram so that it might help people like me to save time to search around the internet to find useful documents and tools to get started with WebAssembly on Rust. ## Give a Star! ⭐ If you like or are using this project to learn, please give a star. Thank you very much 👍 ## The picture of webassembly serverless ![](assets/wasm_serverless.jpg) Picture courtesy of [wasmCloud](https://wasmCloud.com) from Kubecon 2021 WasmDay [WebAssembly: The Future of Distributed Computing](https://www.youtube.com/watch?v=6UM64MbsHic) by Liam Randall. ## The full picture of WebAssembly ecosystem ![](assets/wasm-tour.png) ## Export large PNG file with PlantUML Make sure you install https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml and you have `docker` and `docker-compose` running on your local machine. ```bash $ docker-compose up ``` Then set settings as following ``` "plantuml.server": "http://192.168.1.100:8080", "plantuml.render": "PlantUMLServer", ``` Then right-click on the `assets/wasm-tour.puml`, then choose expose this current diagram. # Diagrams - https://plantuml.com/mindmap-diagram - https://github.com/plantuml-stdlib/C4-PlantUML/blob/master/samples/C4CoreDiagrams.md ================================================ FILE: assets/wasm_tour.puml ================================================ @startmindmap wasm-tour title WebAssembly Tour caption Copyright by @thangchung \nhttps://github.com/thangchung/webassembly-tour skinparam shadowing false 'skinparam handwritten true skinparam BackgroundColor white + WASM \n(WebAssembly) ++ WebAssembly: it's neither web, not assembly - Ancient wasm dev proverb ++ Concepts +++ Basic ++++ callstack is inaccessible ++++ pointers: compiled the offsets into linear memory (checked to ensure stating inbound), virtual address hides from application <> ++++ all control transfers: direct and indirect branches and calls (check to make sure not outbound) <> ++++ all interaction with outside world by imports and exports (no raw access) <> ++++ no undefined behavior +++ Filesystem access ++++ WASI APIs for file system access +++++ only access what we allow +++++ share nothing linking and nano-processes (future) +++ Terminal output ++++ ANSI-style escape sequences +++ Spectre ++++ not implement yet, but it is a subject of on-going research +++ https://docs.wasmtime.dev/security-sandboxing.html ++ ecosystem +++ Cloudflare - worker (node Isolation) ++++ Build serverless code +++++ https://github.com/cloudflare/wrangler ++++ https://blog.cloudflare.com/cloud-computing-without-containers +++ WASI ++++ WebAssembly System Interface (has 2 benefits: portability and security) ++++ Not have a networking layer ++++ current WASM are single-thread and not support concurrency ++++ CGI: attach scripts to website, and provide the dynamic server-side logic. And now WASM + WASI are the same +++++ https://datatracker.ietf.org/doc/html/rfc3875 ++++ wasm32-wasi target +++++ wasmtime ++++++ https://github.com/bytecodealliance/cargo-wasi ++++ wabt (convert wasm to wat, and vice versa) +++++ https://github.com/WebAssembly/wabt ++++ https://hacks.mozilla.org/2019/03/standardizing-wasi-a-webassembly-system-interface/ +++ wasmCloud ++++ High level concepts +++++ Middle Level Runtime ++++++ waPC (WebAssembly Procedure Calls) ++++++ wascap (Sign, Embed, Query JWTs in WebAssembly Modules) +++++ High Level Runtime ++++++ waSCC (WebAssembly Secure Capabilities Connector) +++++++ services and functions as Actors <> +++++++ Utilize embedded, signed JWTs (verify provenance, restrict access, integrate with OPA) <> +++++++ Dynamically bind Actors to Capabilities such as Message Broker, HTTP client and server, Key-value Store, and Custom Capabilities <> +++++++ Rust Host SDK +++++++ Rust Actor SDK ++++ wasmcloud shell +++++ wash CLI ++++++ start wash with `wash up` ++++++ sub-commands +++++++ claims ++++++++ Generate JWTs for actors, capability providers, accounts and operators. Sign actor modules with claims including capability IDs, expiration, and keys to verify identity <> ++++++++ for examples +++++++++ call `wash claims inspect wasmcloud.azurecr.io/echo:0.2.1` to inspect the echo actor <> +++++++++ or sign claims for actor like `claims sign ./table_tennis.wasm --http_server --name "demo" --ver 0.1.0 --rev 0` <> +++++++ ctl ++++++++ Interact directly with a wasmcloud control-interface, allowing you to imperatively schedule actors, providers and modify configurations of a wasmcloud host <> ++++++++ for examples +++++++++ `ctl get hosts` +++++++++ then based on the host id to call `ctl get inventory ` <> +++++++++ or we can start actor like `ctl start actor table_tennis_s.wasm`(_s mean the wasm file we have already signed it with `claims` sub-command) <> +++++++++ or we can start the provider too, like `ctl start provider wasmcloud.azurecr.io/httpserver:0.12.1` <> +++++++++ or we can link actor with provider like `ctl link wasmcloud:httpserver PORT=8080`, then we can `curl localhost:8080 -d "ping"` <> +++++++ drain ++++++++ Manage contents of the local wasmcloud cache <> +++++++ keys ++++++++ Generate ed25519 keys for securely signing and identifying wasmcloud entities (actors, providers, hosts) <> +++++++ par ++++++++ Create, modify and inspect provider archives, a TAR format that contains a signed JWT and OS/Architecture specific binaries for native capability providers <> +++++++ reg ++++++++ Push and Pull actors and capability providers to/from OCI compliant registries (registry with ORAS standard) <> ++++ Develop app +++++ manifest.yaml ++++++ declare: name, labels, actors to run, capabilities (image_ref and link_name), links between actor and host also with port (actor, provider_id, contract_id, link_name, values) <> +++++ More steps to run please see `wasmcloud/ministore/README.md`in this repository <> +++ WAGI (DeisLabs - Azure) ++++ WebAssembly Gateway Interface<> ++++ Http Server: dynamically load and execute WASM modules using the same CGI technic <> ++++ Headers in env variables, Query params sends in command line options, Incoming HTTP payloads via STDIN, and Response via STDOUT <> ++++ Security in mind: explicit access grants, cannot make outbound network connections, cannot execute others executes on the system, and cannot access arbitrary env variables <> ++++ It works on wasm32-wasi target only. If you want to install it, \nPlease follow command: rustup target add wasm32-wasi <> ++++ There is a version that is written in Rust at the https://github.com/deislabs/wagi <> ++++ DeisLabs is working to bring up .NET Core WAGI at https://github.com/deislabs/wagi-dotnet <> ++++ See more examples at this reposioty in https://github.com/thangchung/webassembly-tour/tree/main/wagi <> ++++ Networking API in WASI is not stable, and WASI socket is still in proposal stage +++++ wasi-experimental-http is to temporary to solve this problem (will not need when WASI networking API and socket is released and stabled) <> +++++ The DeisLabs build some of samples using wasi-experimental-http and Azure Rust SDKs (customized to work with WASI) at https://github.com/deislabs/wagi-azure-samples <> +++ krustlet ++++ [TODO] ++++ https://github.com/deislabs/krustlet +++ wasmer ++++ WebAssembly Runtime supporting WASI and Emscripten ++++ [TODO] ++++ https://github.com/wasmerio/wasmer +++ secondstate ++++ [TODO] ++++ https://www.secondstate.io/ +++ suborbital ++++ [TODO] ++++ https://github.com/suborbital/atmo +++ lucet ++++ Sandboxing WebAssembly Compiler ++++ [TODO] ++++ https://github.com/bytecodealliance/lucet +++ wapm ++++ [TODO] +++ wasi-nn ++++ [TODO] +++ webassembly-dwarf ++++ [TODO] ++++ https://yurydelendik.github.io/webassembly-dwarf/ +++ AssemblyLift ++++ A framework for building serverless applications powered by WebAssembly (AWS) <> ++++ [TODO] ++++ https://github.com/akkoro/assemblylift +++ WebContainer (StackBlitz) ++++ [TODO] ++++ https://github.com/stackblitz/webcontainer-core +++ Other tools ++++ https://github.com/engineerd/wasm-to-oci ++++ https://github.com/appcypher/awesome-wasm-runtimes ++++ https://github.com/grain-lang/grain ++ programming languages \n(LLVM family) +++ Rust +++ C/C++ +++ AssemblyScript (subset of Typescript) +++ TinyGo +++ swiftwasm +++ pyodide (python) @endmindmap ================================================ FILE: docker-compose.yml ================================================ version: "3.3" services: plantuml-server: image: "plantuml/plantuml-server:jetty" container_name: plantuml-server environment: PLANTUML_LIMIT_SIZE: 24384 ports: - 8080:8080 ================================================ FILE: krustlet/README.md ================================================ # Step by step to get starting `krustlet` with microk8s - `cd` into the krustlet folder (the folder contains this README.md file) ```bash $ vi /var/snap/microk8s/current/args/kube-apiserver # add --enable-bootstrap-token-auth into this file $ systemctl restart snap.microk8s.daemon-apiserver ``` - Remove everything if there are existing them ```bash $ rm -rf ~/.krustlet/ $ rm -rf ${PWD}/krustlet-config # make sure we don't have krustlet-config file in this current folder $ k delete csr rust-tour-tls # rust-tour is a machine name $ k delete csr krustlet ``` - Start to run krustlet ```bash # Download bootstrap.sh from krustlet repo, and change kubectl to microk8s.kubectl in the content of this file $ sudo chmod +x bootstrap.sh $ ./bootstrap.sh $ export KUBECONFIG=${PWD}/krustlet-config $ KUBECONFIG=${PWD}/krustlet-config krustlet-wasi --node-ip=127.0.0.1 --node-name=krustlet --bootstrap-file=${HOME}/.krustlet/config/bootstrap.conf # make sure don't Ctrl + C in this command # open another terminal $ k certificate approve rust-tour-tls # rust-tour is machine name ``` - Run application ```bash $ k apply --filename=https://raw.githubusercontent.com/deislabs/krustlet/master/demos/wasi/hello-world-rust/k8s.yaml $ k logs pod/hello-world-wasi-rust # you shoud see the logs there ``` More information, you could have a reference at https://github.com/deislabs/krustlet/blob/main/docs/howto/krustlet-on-microk8s.md ================================================ FILE: krustlet/bootstrap.sh ================================================ #!/usr/bin/env bash set -euo pipefail export LC_ALL=C token_id="$(/dev/null || date -v+1H -u "+%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -u "+%Y-%m-%dT%H:%M:%SZ" -D "%s" -d "$(( `date +%s`+3600 ))") cat <"${KUBECONFIG_FILE}.full.tmp" # Switch working context to correct context microk8s.kubectl --kubeconfig "${KUBECONFIG_FILE}.full.tmp" config use-context "${CONTEXT}" # Minify microk8s.kubectl --kubeconfig "${KUBECONFIG_FILE}.full.tmp" \ config view --flatten --minify >"${KUBECONFIG_FILE}.tmp" # Rename context microk8s.kubectl config --kubeconfig "${KUBECONFIG_FILE}.tmp" \ rename-context "${CONTEXT}" "${NEW_CONTEXT}" # Create token user microk8s.kubectl config --kubeconfig "${KUBECONFIG_FILE}.tmp" \ set-credentials "${TOKEN_USER}" --token "${TOKEN}" # Set context to use token user microk8s.kubectl config --kubeconfig "${KUBECONFIG_FILE}.tmp" \ set-context "${NEW_CONTEXT}" --user "${TOKEN_USER}" # Set context to correct namespace microk8s.kubectl config --kubeconfig "${KUBECONFIG_FILE}.tmp" \ set-context "${NEW_CONTEXT}" --namespace "${NAMESPACE}" # Flatten/minify kubeconfig microk8s.kubectl config --kubeconfig "${KUBECONFIG_FILE}.tmp" \ view --flatten --minify >"${KUBECONFIG_FILE}" ================================================ FILE: krustlet/greet-wasmcloud.yaml ================================================ apiVersion: v1 kind: Pod metadata: name: greet labels: app: greet spec: containers: - image: ghcr.io/thangchung/ministore:0.1.0 imagePullPolicy: Always name: greet ports: - containerPort: 8080 hostPort: 8080 nodeSelector: kubernetes.io/arch: wasm32-wasi tolerations: - key: "node.kubernetes.io/network-unavailable" operator: "Exists" effect: "NoSchedule" - key: "kubernetes.io/arch" operator: "Equal" value: "wasm32-wasi" effect: "NoExecute" - key: "kubernetes.io/arch" operator: "Equal" value: "wasm32-wasi" effect: "NoSchedule" ================================================ FILE: restclient.http ================================================ @host = http://localhost:8080 ### @a = 5 @b = 5 GET {{host}}/add?{{a}},{{b}} HTTP/1.1 content-type: application/json ================================================ FILE: wagi/functions/.cargo/config.toml ================================================ [alias] build-wasm = "build --target wasm32-wasi" build-native = "build" ================================================ FILE: wagi/functions/Cargo.toml ================================================ [workspace] members = [ "get-todos" ] ================================================ FILE: wagi/functions/README.md ================================================ # Get starting with wagi - Build ```bash $ rustup target add wasm32-wasi $ cargo build-wasm ``` - Run ``` $ ./wagi --config modules.toml ``` - Test ``` # test it $ curl -v http://localhost:3000/get-todos ``` Environment: - Ubuntu 20.04.2 LTS - rustc 1.52.1 (9bc8c42bb 2021-05-09) - cargo 1.52.0 (69767412a 2021-04-21) Happy hacking! ================================================ FILE: wagi/functions/get-todos/Cargo.toml ================================================ [package] name = "get-todos" version = "0.1.0" authors = ["thangchung "] edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] serde = { version = "1.0.126", features = ["derive"] } serde_json = "1.0.64" ================================================ FILE: wagi/functions/get-todos/src/main.rs ================================================ use serde::Serialize; #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] struct Todo { id: i32, name: String, is_completed: bool, } fn main() { println!("Content-Type: text/plain\n"); let todos = vec![ Todo { id: 1, name: String::from("todo 1"), is_completed: false, }, Todo { id: 2, name: String::from("todo 2"), is_completed: true, }, ]; println!("{}", serde_json::to_string_pretty(&todos).unwrap()); } ================================================ FILE: wagi/functions/modules.toml ================================================ default_host = "localhost:3000" [[module]] route = "/get-todos" module = "target/wasm32-wasi/debug/get-todos.wasm" ================================================ FILE: wagi/functions/wagi ================================================ [File too large to display: 24.1 MB] ================================================ FILE: wagi/server/.gitignore ================================================ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. ## ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore # User-specific files *.rsuser *.suo *.user *.userosscache *.sln.docstates # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs # Mono auto generated files mono_crash.* # Build results [Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ [Rr]eleases/ x64/ x86/ [Aa][Rr][Mm]/ [Aa][Rr][Mm]64/ bld/ [Bb]in/ [Oo]bj/ [Ll]og/ [Ll]ogs/ # Visual Studio 2015/2017 cache/options directory .vs/ # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ # Visual Studio 2017 auto generated files Generated\ Files/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* # NUnit *.VisualState.xml TestResult.xml nunit-*.xml # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ dlldata.c # Benchmark Results BenchmarkDotNet.Artifacts/ # .NET Core project.lock.json project.fragment.lock.json artifacts/ # Tye .tye/ # StyleCop StyleCopReport.xml # Files built by Visual Studio *_i.c *_p.c *_h.h *.ilk *.meta *.obj *.iobj *.pch *.pdb *.ipdb *.pgc *.pgd *.rsp *.sbr *.tlb *.tli *.tlh *.tmp *.tmp_proj *_wpftmp.csproj *.log *.vspscc *.vssscc .builds *.pidb *.svclog *.scc # Chutzpah Test files _Chutzpah* # Visual C++ cache files ipch/ *.aps *.ncb *.opendb *.opensdf *.sdf *.cachefile *.VC.db *.VC.VC.opendb # Visual Studio profiler *.psess *.vsp *.vspx *.sap # Visual Studio Trace Files *.e2e # TFS 2012 Local Workspace $tf/ # Guidance Automation Toolkit *.gpState # ReSharper is a .NET coding add-in _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user # TeamCity is a build add-in _TeamCity* # DotCover is a Code Coverage Tool *.dotCover # AxoCover is a Code Coverage Tool .axoCover/* !.axoCover/settings.json # Coverlet is a free, cross platform Code Coverage Tool coverage*[.json, .xml, .info] # Visual Studio code coverage results *.coverage *.coveragexml # NCrunch _NCrunch_* .*crunch*.local.xml nCrunchTemp_* # MightyMoose *.mm.* AutoTest.Net/ # Web workbench (sass) .sass-cache/ # Installshield output folder [Ee]xpress/ # DocProject is a documentation generator add-in DocProject/buildhelp/ DocProject/Help/*.HxT DocProject/Help/*.HxC DocProject/Help/*.hhc DocProject/Help/*.hhk DocProject/Help/*.hhp DocProject/Help/Html2 DocProject/Help/html # Click-Once directory publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml # Note: Comment the next line if you want to checkin your web deploy settings, # but database connection strings (with potential passwords) will be unencrypted *.pubxml *.publishproj # Microsoft Azure Web App publish settings. Comment the next line if you want to # checkin your Azure Web App publish settings, but sensitive information contained # in these scripts will be unencrypted PublishScripts/ # NuGet Packages *.nupkg # NuGet Symbol Packages *.snupkg # The packages folder can be ignored because of Package Restore **/[Pp]ackages/* # except build/, which is used as an MSBuild target. !**/[Pp]ackages/build/ # Uncomment if necessary however generally it will be regenerated when needed #!**/[Pp]ackages/repositories.config # NuGet v3's project.json files produces more ignorable files *.nuget.props *.nuget.targets # Microsoft Azure Build Output csx/ *.build.csdef # Microsoft Azure Emulator ecf/ rcf/ # Windows Store app package directories and files AppPackages/ BundleArtifacts/ Package.StoreAssociation.xml _pkginfo.txt *.appx *.appxbundle *.appxupload # Visual Studio cache files # files ending in .cache can be ignored *.[Cc]ache # but keep track of directories ending in .cache !?*.[Cc]ache/ # Others ClientBin/ ~$* *~ *.dbmdl *.dbproj.schemaview *.jfm *.pfx *.publishsettings orleans.codegen.cs # Including strong name files can present a security risk # (https://github.com/github/gitignore/pull/2483#issue-259490424) #*.snk # Since there are multiple workflows, uncomment next line to ignore bower_components # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) #bower_components/ # RIA/Silverlight projects Generated_Code/ # Backup & report files from converting an old project file # to a newer Visual Studio version. Backup files are not needed, # because we have git ;-) _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm ServiceFabricBackup/ *.rptproj.bak # SQL Server files *.mdf *.ldf *.ndf # Business Intelligence projects *.rdl.data *.bim.layout *.bim_*.settings *.rptproj.rsuser *- [Bb]ackup.rdl *- [Bb]ackup ([0-9]).rdl *- [Bb]ackup ([0-9][0-9]).rdl # Microsoft Fakes FakesAssemblies/ # GhostDoc plugin setting file *.GhostDoc.xml # Node.js Tools for Visual Studio .ntvs_analysis.dat node_modules/ # Visual Studio 6 build log *.plg # Visual Studio 6 workspace options file *.opt # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) *.vbw # Visual Studio LightSwitch build output **/*.HTMLClient/GeneratedArtifacts **/*.DesktopClient/GeneratedArtifacts **/*.DesktopClient/ModelManifest.xml **/*.Server/GeneratedArtifacts **/*.Server/ModelManifest.xml _Pvt_Extensions # Paket dependency manager .paket/paket.exe paket-files/ # FAKE - F# Make .fake/ # Ionide - VsCode extension for F# Support .ionide/ # CodeRush personal settings .cr/personal # Python Tools for Visual Studio (PTVS) __pycache__/ *.pyc # Cake - Uncomment if you are using it # tools/** # !tools/packages.config # Tabs Studio *.tss # Telerik's JustMock configuration file *.jmconfig # BizTalk build output *.btp.cs *.btm.cs *.odx.cs *.xsd.cs # OpenCover UI analysis results OpenCover/ # Azure Stream Analytics local run output ASALocalRun/ # MSBuild Binary and Structured Log *.binlog # NVidia Nsight GPU debugger configuration file *.nvuser # MFractors (Xamarin productivity tool) working folder .mfractor/ # Local History for Visual Studio .localhistory/ # BeatPulse healthcheck temp database healthchecksdb # Backup folder for Package Reference Convert tool in Visual Studio 2017 MigrationBackup/ # Ionide (cross platform F# VS Code tools) working folder .ionide/ ## ## Visual studio for Mac ## # globs Makefile.in *.userprefs *.usertasks config.make config.status aclocal.m4 install-sh autom4te.cache/ *.tar.gz tarballs/ test-results/ # Mac bundle stuff *.dmg *.app # content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore # General .DS_Store .AppleDouble .LSOverride # Icon must end with two \r Icon # Thumbnails ._* # Files that might appear in the root of a volume .DocumentRevisions-V100 .fseventsd .Spotlight-V100 .TemporaryItems .Trashes .VolumeIcon.icns .com.apple.timemachine.donotpresent # Directories potentially created on remote AFP share .AppleDB .AppleDesktop Network Trash Folder Temporary Items .apdisk # content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore # Windows thumbnail cache files Thumbs.db ehthumbs.db ehthumbs_vista.db # Dump file *.stackdump # Folder config file [Dd]esktop.ini # Recycle Bin used on file shares $RECYCLE.BIN/ # Windows Installer files *.cab *.msi *.msix *.msm *.msp # Windows shortcuts *.lnk # JetBrains Rider .idea/ *.sln.iml ## ## Visual Studio Code ## .vscode/* !.vscode/settings.json !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json copy_wasm.* ================================================ FILE: wagi/server/.vscode/launch.json ================================================ { // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "name": ".NET Core Launch (web)", "type": "coreclr", "request": "launch", "preLaunchTask": "build", "program": "${workspaceFolder}/bin/Debug/net5.0/server.dll", "args": [ ], "cwd": "${workspaceFolder}", "console": "internalConsole", "env":{ "WASMTIME_BACKTRACE_DETAILS":"1", "ASPNETCORE_ENVIRONMENT": "Development" }, "stopAtEntry": false }, { "name": ".NET Core Attach", "type": "coreclr", "request": "attach", "processId": "${command:pickProcess}" }, { "name": ".NET Core Launch (listen)", "type": "coreclr", "request": "launch", "preLaunchTask": "build", "env":{ "WASMTIME_BACKTRACE_DETAILS":"1", "ASPNETCORE_ENVIRONMENT": "Development" }, "program": "${workspaceFolder}/bin/Debug/net5.0/server.dll", "args": [], "cwd": "${workspaceFolder}", "console": "internalConsole", "stopAtEntry": false } ] } ================================================ FILE: wagi/server/.vscode/tasks.json ================================================ { "version": "2.0.0", "tasks": [ { "label": "build", "command": "dotnet", "type": "process", "args": [ "build", "${workspaceFolder}/server.csproj", "/property:GenerateFullPaths=true", "/consoleloggerparameters:NoSummary" ], "problemMatcher": "$msCompile" }, { "label": "publish", "command": "dotnet", "type": "process", "args": [ "publish", "${workspaceFolder}/server.csproj", "/property:GenerateFullPaths=true", "/consoleloggerparameters:NoSummary" ], "problemMatcher": "$msCompile" }, { "label": "watch", "command": "dotnet", "type": "process", "args": [ "watch", "run", "${workspaceFolder}/server.csproj", "/property:GenerateFullPaths=true", "/consoleloggerparameters:NoSummary" ], "problemMatcher": "$msCompile" } ] } ================================================ FILE: wagi/server/Program.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace server { public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }); } } ================================================ FILE: wagi/server/Properties/launchSettings.json ================================================ { "profiles": { "server": { "commandName": "Project", "dotnetRunMessages": "true", "launchBrowser": true, "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development", "WASMTIME_BACKTRACE_DETAILS":1 } } } } ================================================ FILE: wagi/server/Startup.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Deislabs.WAGI.Extensions; namespace server { public class Startup { // This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); app.UseEndpoints(endpoints => { // This adds any wagi endpoints in configuration as RouteEndpoints to the IEndpointRouteBuilder // by default it looks for its configuration in a section named WASM endpoints.MapWASMModules(); }); } } } ================================================ FILE: wagi/server/appsettings.json ================================================ { "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information", "Deislabs.WAGI": "Trace" } }, "AllowedHosts": "*", "WASM": { "ModulePath": "modules", "Modules": { "/fibonacci": { "FileName": "fibonacci.wasm", "Entrypoint": "_start", "Environment" :{ }, "Volumes" : { }, "HttpMethod": "GET" }, "/todos": { "FileName": "get-todos.wasm", "Entrypoint": "_start", "Environment" :{ }, "Volumes" : { }, "HttpMethod": "GET" } } } } ================================================ FILE: wagi/server/server.csproj ================================================ net5.0 PreserveNewest PreserveNewest ================================================ FILE: wasmcloud/README.md ================================================ # Installation Install on Windows Sub-system ```bash $ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh $ curl -s https://packagecloud.io/install/repositories/wasmcloud/core/script.deb.sh | sudo bash $ sudo apt install wasmcloud wash $ curl https://wasmtime.dev/install.sh -sSf | bash ``` # Build ## Step by step to run mini_store ```bash $ rustup target add wasm32-unknown-unknown $ cargo build --target wasm32-unknown-unknown --release $ wash claims sign target/wasm32-unknown-unknown/release/mini_store.wasm --http_server --name "ministore" --ver 0.1.0 --rev 0 $ wash claims inspect target/wasm32-unknown-unknown/release/mini_store_s.wasm ``` Make sure you run `docker-compose up` to start the `registry`, `redis`, and `nats` before execute the following command ```bash $ wash reg push localhost:5000/ministore:0.1.0 target/wasm32-unknown-unknown/release/mini_store_s.wasm --insecure ``` Create [`manifest.yaml`](mini-store/manifest.yaml) with content as below ```yaml labels: actor: "ministore" actors: - "localhost:5000/ministore:0.1.0" capabilities: - image_ref: wasmcloud.azurecr.io/httpserver:0.12.1 link_name: default links: - actor: ${CLIENT_ACTOR:} provider_id: "VAG3QITQQ2ODAOWB5TTQSDJ53XK3SHBEIFNK4AYJ5RKAX2UNSCAPHA5M" contract_id: "wasmcloud:httpserver" link_name: default values: PORT: 8080 ``` Then ```bash $ wasmcloud --allowed-insecure localhost:8080 -m manifest.yaml ``` Finally, you can run ```bash $ curl localhost:8080/add?5,5 --output - ``` > On the Ubuntu VM, you need to forward port of the docker-machine guest machine into the host machine as below ```bash # pf.sh in the tools folder, and its repo is at https://github.com/johanhaleby/docker-machine-port-forwarder $ ./pf.sh 5000 && ./pf.sh 6379 && ./pf.sh 4222 & ./pf.sh 6222 &7 ./pf.sh 8222 ``` > Push WebAssembly file with signed to Github package ```bash # before do this, we need to login into Github package so plz follow the link https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-docker-registry # wasm-to-oci is at https://github.com/engineerd/wasm-to-oci $ wasm-to-oci push ../mini-store/target/wasm32-unknown-unknown/release/mini_store_s.wasm ghcr.io/thangchung/ministore:0.1.0 ``` ## Run with wasmtime > it might not run well ```bash $ rustup target add wasm32-wasi $ cargo build --target wasm32-wasi --release $ wasmtime target/wasm32-wasi/release/mini_store.wasm ``` ================================================ FILE: wasmcloud/docker-compose.yml ================================================ version: "3" services: registry: image: registry:2 ports: - "5000:5000" nats: image: nats:2.1.9 ports: - "6222:6222" - "4222:4222" - "8222:8222" redis: image: redis:6.0.9 ports: - "6379:6379" ================================================ FILE: wasmcloud/mini-store/Cargo.toml ================================================ [package] name = "mini-store" version = "0.1.0" authors = ["thangchung@ymail.com"] edition = "2018" [lib] crate-type = ["cdylib"] [dependencies] wapc-guest = "0.4.0" wasmcloud-actor-core = { version = "0.2.2", features = ["guest"] } wasmcloud-actor-http-server = {version = "0.1.0", features = ["guest"]} [profile.release] # Optimize for small code size opt-level = "s" lto = true ================================================ FILE: wasmcloud/mini-store/justfile ================================================ build: cargo build run: cargo run --bin mini-store ================================================ FILE: wasmcloud/mini-store/manifest.yaml ================================================ labels: actor: "ministore" actors: - "localhost:5000/ministore:0.1.0" capabilities: - image_ref: wasmcloud.azurecr.io/httpserver:0.12.1 link_name: default links: - actor: ${CLIENT_ACTOR:MDIN3A5WRXNBIKIVMTTRV6CH6I4UQXRW4H6YIINZ4TMYOETYF5TTMJ7Z} provider_id: "VAG3QITQQ2ODAOWB5TTQSDJ53XK3SHBEIFNK4AYJ5RKAX2UNSCAPHA5M" contract_id: "wasmcloud:httpserver" link_name: default values: PORT: 8080 ================================================ FILE: wasmcloud/mini-store/src/lib.rs ================================================ extern crate wapc_guest as guest; extern crate wasmcloud_actor_http_server as httpserver; use guest::prelude::*; #[wasmcloud_actor_core::init] fn init() { httpserver::Handlers::register_handle_request(test_body); } fn test_body(msg: httpserver::Request) -> HandlerResult { let nums: Vec<&str> = msg.query_string.split(",").collect(); let mut ret: String = String::from("Welcome to wasmcloud calculator"); loop { match msg.path.as_str() { "/add" => { let sum = nums[0].parse::().unwrap() + nums[1].parse::().unwrap(); ret = format!("add: {} + {} = {}", nums[0], nums[1], sum); break; } "/sub" => { let sub = nums[0].parse::().unwrap() - nums[1].parse::().unwrap(); ret = format!("subtract: {} - {} = {}", nums[0], nums[1], sub); break; } // TODO: add multiplication "/div" => { if nums[1] == "0" { ret = String::from("Can not divide by zero!"); break; } let div = nums[0].parse::().unwrap() / nums[1].parse::().unwrap(); ret = format!("divide: {} / {} = {}", nums[0], nums[1], div); break; } _ => { break; } } } return Ok(httpserver::Response { status_code: 200, status: "OK".to_string(), header: msg.header, body: ret.as_bytes().to_vec(), }); } ================================================ FILE: wasmcloud/tools/pf.sh ================================================ #!/bin/bash readonly PROGNAME=$(basename $0) port="${1}" foreground="false" stop="false" environment="default" quiet="false" hostport="$1" usage="${PROGNAME} [-h] [-s] [-f] [-e] [-hp] -- Forwards a docker-machine port so that you can access it locally where: -h, --help Show this help text -s, --stop Stop the port forwarding process -f, --foreground Run the docker-machine ssh client in foreground instead of background -e, --environment The name of the docker-machine environment (default is default) -q, --quiet Don't print anything to the console, not even errors examples: # Port forward port 8047 in docker-machine environment default \$ ${PROGNAME} 8047 # Port forward docker port 8047 to host port 8087 in docker-machine environment default \$ ${PROGNAME} 8087:8047 # Port forward port 8047 in docker-machine dev \$ ${PROGNAME} 8047 -e dev # Runs in foreground (port forwarding is automatically stopped when process is terminated) \$ ${PROGNAME} 8047 -f # Stop the port forwarding for this port \$ ${PROGNAME} 8047 -s" if [ $# -eq 0 ]; then echo "$usage" exit 1 fi if [ -z "$1" ]; then echo "You need to specify the port to forward" >&2 echo "$usage" exit 1 fi if [ "$#" -ne 0 ]; then while [ "$#" -gt 0 ] do case "$1" in -h|--help) echo "$usage" exit 0 ;; -f|--foreground) foreground="true" ;; -s|--stop) stop="true" ;; -e|--environment) environment="$2" ;; -q|--quiet) quiet="true" ;; --) break ;; -*) echo "Invalid option '$1'. Use --help to see the valid options" >&2 exit 1 ;; # an option argument, continue *) ;; esac shift done fi pidport() { lsof -n -i4TCP:$1 | grep --exclude-dir={.bzr,CVS,.git,.hg,.svn} LISTEN } # Check if port contains ":", if so we should split if [[ $port == *":"* ]]; then # Split by : ports=(${port//:/ }) if [[ ${#ports[@]} != 2 ]]; then if [[ $quiet == "false" ]]; then echo "Port forwarding should be defined as hostport:targetport, for example: 8090:8080" fi exit 1 fi hostport=${ports[0]} port=${ports[1]} fi if [[ ${stop} == "true" ]]; then result=`pidport $hostport` if [ -z "${result}" ]; then if [[ $quiet == "false" ]]; then echo "Port $hostport is not forwarded, cannot stop" fi exit 1 fi process=`echo "${result}" | awk '{ print $1 }'` if [[ $process != "ssh" ]]; then if [[ $quiet == "false" ]]; then echo "Port $hostport is bound by process ${process} and not by docker-machine, won't stop" fi exit 1 fi pid=`echo "${result}" | awk '{ print $2 }'` && kill $pid && echo "Stopped port forwarding for $hostport" else docker-machine ssh $environment `if [[ ${foreground} == "false" ]]; then echo "-f -N"; fi` -L $hostport:localhost:$port && if [[ $quiet == "false" ]] && [[ $foreground == "false" ]]; then printf "Forwarding port $port" if [[ $hostport -ne $port ]]; then printf " to host port $hostport" fi echo " in docker-machine environment $environment." fi fi ================================================ FILE: wasmcloud/tools/wasm-to-oci ================================================ [File too large to display: 10.6 MB]