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