├── .github
└── workflows
│ ├── build.yml
│ └── main.yml
├── .gitignore
├── .gitmodules
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Cargo.lock
├── Cargo.toml
├── LICENSE.md
├── README.md
├── builtin
└── functions
│ └── verify-macaroon
│ ├── .cargo
│ └── config.toml
│ ├── Cargo.toml
│ └── src
│ └── main.rs
├── crates
├── cli
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ │ ├── archive.rs
│ │ ├── commands
│ │ ├── bind.rs
│ │ ├── burn.rs
│ │ ├── cast
│ │ │ ├── mod.rs
│ │ │ ├── ruby.rs
│ │ │ ├── rust.rs
│ │ │ └── wasm
│ │ │ │ ├── wasi_snapshot_preview1.command.wasm
│ │ │ │ └── wasi_snapshot_preview1.reactor.wasm
│ │ ├── host.rs
│ │ ├── init.rs
│ │ ├── make.rs
│ │ ├── mod.rs
│ │ ├── move.rs
│ │ ├── nuke.rs
│ │ ├── pack.rs
│ │ ├── push.rs
│ │ └── user.rs
│ │ ├── main.rs
│ │ └── templates
│ │ ├── mod.rs
│ │ └── project.rs
├── core
│ ├── Cargo.toml
│ ├── README.md
│ ├── guest
│ │ ├── Cargo.toml
│ │ ├── README.md
│ │ ├── macros
│ │ │ ├── Cargo.toml
│ │ │ ├── README.md
│ │ │ └── src
│ │ │ │ └── lib.rs
│ │ └── src
│ │ │ ├── assemblylift.rs
│ │ │ ├── command.rs
│ │ │ ├── jwt.rs
│ │ │ ├── lib.rs
│ │ │ ├── opa.rs
│ │ │ └── secrets.rs
│ ├── io
│ │ ├── README.md
│ │ ├── common
│ │ │ ├── Cargo.toml
│ │ │ ├── README.md
│ │ │ └── src
│ │ │ │ ├── constants.rs
│ │ │ │ └── lib.rs
│ │ └── guest
│ │ │ ├── Cargo.toml
│ │ │ ├── README.md
│ │ │ └── src
│ │ │ └── lib.rs
│ ├── iomod
│ │ ├── Cargo.toml
│ │ ├── README.md
│ │ ├── build.rs
│ │ ├── guest
│ │ │ ├── Cargo.toml
│ │ │ ├── README.md
│ │ │ └── src
│ │ │ │ └── lib.rs
│ │ ├── iomod.capnp
│ │ └── src
│ │ │ ├── lib.rs
│ │ │ ├── macros.rs
│ │ │ ├── package.rs
│ │ │ └── registry.rs
│ ├── src
│ │ ├── buffers.rs
│ │ ├── jwt
│ │ │ ├── README.md
│ │ │ ├── error.rs
│ │ │ ├── jwt.rs
│ │ │ ├── keyset.rs
│ │ │ └── mod.rs
│ │ ├── lib.rs
│ │ ├── policy_manager.rs
│ │ ├── threader.rs
│ │ └── wasm
│ │ │ ├── cache.rs
│ │ │ └── mod.rs
│ └── wit
│ │ ├── assemblylift
│ │ └── assemblylift.wit
│ │ ├── jwt
│ │ └── jwt.wit
│ │ ├── opa
│ │ └── opa.wit
│ │ └── secrets
│ │ └── secrets.wit
├── generator
│ ├── Cargo.toml
│ └── src
│ │ ├── context.rs
│ │ ├── lib.rs
│ │ ├── projectfs.rs
│ │ ├── providers
│ │ ├── api_gateway
│ │ │ ├── mod.rs
│ │ │ └── templates
│ │ │ │ ├── api_impl.tf.handlebars
│ │ │ │ └── api_inst.tf.handlebars
│ │ ├── aws_lambda
│ │ │ ├── mod.rs
│ │ │ └── templates
│ │ │ │ ├── function_impl.tf.handlebars
│ │ │ │ ├── service_impl.tf.handlebars
│ │ │ │ └── service_inst.tf.handlebars
│ │ ├── ecr
│ │ │ ├── mod.rs
│ │ │ └── templates
│ │ │ │ ├── ecr_impl.tf.handlebars
│ │ │ │ ├── ecr_inst.tf.handlebars
│ │ │ │ └── ecr_inst_root.tf.handlebars
│ │ ├── gloo
│ │ │ ├── mod.rs
│ │ │ └── templates
│ │ │ │ ├── api_impl.tf.handlebars
│ │ │ │ └── api_inst.tf.handlebars
│ │ ├── kubernetes
│ │ │ ├── mod.rs
│ │ │ └── templates
│ │ │ │ ├── function.dockerfile.handlebars
│ │ │ │ ├── function_impl.tf.handlebars
│ │ │ │ ├── service_impl.tf.handlebars
│ │ │ │ └── service_inst.tf.handlebars
│ │ ├── mod.rs
│ │ └── route53
│ │ │ ├── mod.rs
│ │ │ └── templates
│ │ │ ├── dns_impl.tf.handlebars
│ │ │ ├── dns_impl_apigw.tf.handlebars
│ │ │ ├── dns_impl_gloo.tf.handlebars
│ │ │ ├── dns_impl_root.tf.handlebars
│ │ │ ├── dns_inst.tf.handlebars
│ │ │ └── dns_inst_root.tf.handlebars
│ │ ├── templates
│ │ └── context.tf.handlebars
│ │ └── toml
│ │ ├── asml.rs
│ │ ├── mod.rs
│ │ └── service.rs
├── runtimes
│ ├── aws-lambda
│ │ ├── guest
│ │ │ ├── Cargo.toml
│ │ │ ├── README.md
│ │ │ └── src
│ │ │ │ └── lib.rs
│ │ └── host
│ │ │ ├── Cargo.toml
│ │ │ ├── README.md
│ │ │ └── src
│ │ │ ├── abi.rs
│ │ │ └── main.rs
│ ├── components
│ │ └── wasi-secrets
│ │ │ └── in-memory
│ │ │ ├── Cargo.toml
│ │ │ └── src
│ │ │ └── lib.rs
│ └── hyper
│ │ ├── Cargo.toml
│ │ └── src
│ │ ├── abi.rs
│ │ ├── launcher.rs
│ │ ├── lib.rs
│ │ ├── main.rs
│ │ └── runner.rs
└── tools
│ ├── Cargo.toml
│ └── src
│ ├── cmctl.rs
│ ├── glooctl.rs
│ ├── kubectl.rs
│ ├── lib.rs
│ └── terraform.rs
├── docker
├── asml-hyper-debian
├── asml-lambda-alpine
├── asml-lambda-default
└── asml-openfaas-alpine
├── docs
├── AssemblyLift_logo.png
├── README.md
├── cli-transpiler.md
├── core-abi.md
├── core-buffers.md
├── core-threader.md
├── lang-ruby.md
├── lang-rust.md
├── provider-apigw-amz.md
├── provider-apigw-gloo.md
├── provider-dns-route53.md
├── provider-service-aws.md
├── provider-service-k8s.md
├── rt-hyper.md
└── rt-lambda.md
└── examples
├── .gitignore
├── README.md
├── custom-domain
├── .gitignore
├── assemblylift.toml
└── services
│ └── example
│ ├── echo
│ ├── Cargo.lock
│ ├── Cargo.toml
│ └── src
│ │ └── main.rs
│ └── service.toml
└── hello-world
├── .gitignore
├── assemblylift.toml
└── services
└── hello
├── ruby
└── handler.rb
├── rust
├── Cargo.lock
├── Cargo.toml
└── src
│ └── main.rs
└── service.toml
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Verify Build
2 |
3 | on:
4 | pull_request:
5 | branches: [ mainline, v0.4.0-beta ]
6 |
7 | jobs:
8 |
9 | build-lambda-default:
10 | name: 'AWS Lambda Runtime'
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: 'Checkout'
14 | uses: actions/checkout@v2
15 | with:
16 | submodules: recursive
17 | - name: 'Build'
18 | run: docker build -t assemblylift/asml-lambda-default . --file docker/asml-lambda-default
19 |
20 | build-hyper:
21 | name: 'Hyper Runtime'
22 | runs-on: ubuntu-latest
23 | steps:
24 | - name: 'Checkout'
25 | uses: actions/checkout@v2
26 | with:
27 | submodules: recursive
28 | - name: 'Build'
29 | run: docker build -t assemblylift/hyper-debian . --file docker/asml-hyper-debian
30 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | **/target/**
3 | .DS_Store
4 | bootstrap
5 | bootstrap.zip
6 | *_capnp.rs
7 | .idea/
8 | ayo-test
9 |
10 | # for future use, ignore folders that match pattern: dev-test.*
11 | dev-test.*
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akkoro/assemblylift/a4f9094b0ed07eb813c9d2f5893a5a23dbca9a08/.gitmodules
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at conduct@akkoro.io. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Learning the codebase
2 | Take a look at the [design docs](docs/README.md).
3 |
4 | # Proposing a change
5 | If there's a feature you'd like to implement, please start a [discussion](https://github.com/akkoro/assemblylift/discussions) describing
6 | your proposal before moving forward with a PR. This helps ensure that changes stay in scope and work isn't duplicated. 🙂
7 |
8 | Changes don't have to be limited to new features! Feel free to propose something if there is code you think could be
9 | refactored to be clearer, documentation you'd like to contribute, CI/CD enhancements, etc.
10 |
11 | # Getting your change merged
12 | Please use [forking workflow](https://www.atlassian.com/git/tutorials/comparing-workflows/forking-workflow) to open a new Pull Request.
13 |
14 | # Reporting a bug
15 | Please [open an issue](https://github.com/akkoro/assemblylift/issues/new?labels=bug).
16 |
17 | # Guidelines
18 | Remember to abide by the [Contributor Covenant](CODE_OF_CONDUCT.md).
19 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | resolver = "2"
3 | members = [
4 | "crates/runtimes/aws-lambda/host",
5 | "crates/runtimes/aws-lambda/guest",
6 | "crates/runtimes/hyper",
7 | "crates/runtimes/components/wasi-secrets/in-memory",
8 | # "builtin/functions/verify-macaroon",
9 | "crates/generator",
10 | "crates/tools",
11 | "crates/core",
12 | "crates/core/guest",
13 | "crates/core/guest/macros",
14 | "crates/core/iomod",
15 | "crates/core/iomod/guest",
16 | "crates/core/io/guest",
17 | "crates/core/io/common",
18 | "crates/cli"
19 | ]
20 | exclude = ["examples"]
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | The AssemblyLift project is being rebooted... stay tuned!
6 |
7 |
--------------------------------------------------------------------------------
/builtin/functions/verify-macaroon/.cargo/config.toml:
--------------------------------------------------------------------------------
1 | [build]
2 | target = "wasm32-wasi"
3 |
--------------------------------------------------------------------------------
/builtin/functions/verify-macaroon/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "assemblylift-builtins-verify-macaroon"
3 | version = "0.0.0"
4 | edition = "2021"
5 |
6 | [dependencies]
7 | base64 = "0.20"
8 | direct-executor = "0.3.0"
9 | serde = "1"
10 | serde_json = "1"
11 | asml_core = { version = "0.4.0-alpha", package = "assemblylift-core-guest" }
12 | assemblylift_core_io_guest = { version = "0.4.0-alpha", package = "assemblylift-core-io-guest" }
13 | macaroon = { version = "0.1", package = "macaroon-asml-fork" }
14 | secretsmanager = { version = "0.1", package = "assemblylift-iomod-secretsmanager-guest" }
15 |
--------------------------------------------------------------------------------
/builtin/functions/verify-macaroon/src/main.rs:
--------------------------------------------------------------------------------
1 | use macaroon::{Macaroon, MacaroonKey, Verifier};
2 |
3 | use asml_core::*;
4 |
5 | use secretsmanager;
6 | use secretsmanager::structs::*;
7 |
8 | #[handler]
9 | async fn main() {
10 | let event: serde_json::Value =
11 | serde_json::from_str(&ctx.input).expect("could not parse function input as JSON");
12 |
13 | let identity = event["identitySource"].as_array().unwrap()[0]
14 | .as_str()
15 | .unwrap()
16 | .to_string();
17 | let macaroon = match Macaroon::deserialize(&identity) {
18 | Ok(m) => m,
19 | Err(err) => {
20 | FunctionContext::log(err.to_string());
21 | return FunctionContext::success("{\"isAuthorized\":false}".to_string());
22 | }
23 | };
24 | let verifier = Verifier::default();
25 | let user_key = get_user_key(
26 | std::str::from_utf8(macaroon.identifier().0.as_slice())
27 | .unwrap()
28 | .to_string(),
29 | )
30 | .await
31 | .unwrap();
32 |
33 | match verifier.verify(
34 | &macaroon,
35 | &MacaroonKey::generate(user_key.as_str().as_bytes()),
36 | vec![],
37 | ) {
38 | Ok(_) => FunctionContext::success("{\"isAuthorized\":true}".to_string()),
39 | Err(_) => FunctionContext::success("{\"isAuthorized\":false}".to_string()),
40 | }
41 | }
42 |
43 | async fn get_user_key(user_id: String) -> Result {
44 | let mut get_secret_req = GetSecretValueRequest::default();
45 | get_secret_req.secret_id = format!("echopod/user/{}", &user_id);
46 | match secretsmanager::get_secret_value(get_secret_req).await {
47 | Ok(res) => Ok(res.secret_string.unwrap()),
48 | Err(err) => Err(err.to_string()),
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/crates/cli/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "assemblylift-cli"
3 | version = "0.4.0-beta.0"
4 | description = "The AssemblyLift Command Line Interface"
5 | authors = ["Akkoro and the AssemblyLift contributors "]
6 | edition = "2018"
7 | license-file = "../LICENSE.md"
8 | repository = "https://github.com/akkoro/assemblylift"
9 | readme = "README.md"
10 | exclude = ["resources/**"]
11 |
12 | [[bin]]
13 | name = "asml"
14 | path = "src/main.rs"
15 |
16 | [dependencies]
17 | anyhow = "1"
18 | base64 = "0.13"
19 | bytes = "1.1"
20 | clap = "2.33"
21 | dialoguer = "0.10"
22 | flate2 = "1"
23 | handlebars = "3.5"
24 | itertools = "0.10"
25 | jsonpath_lib = "0.3.0"
26 | once_cell = "1.7"
27 | path_abs = "0.5"
28 | serde = { version = "1", features = ["derive", "rc"] }
29 | serde_json = "1"
30 | sha2 = "0.10"
31 | tar = "0.4"
32 | toml = "0.5"
33 | tracing = "0.1"
34 | tracing-subscriber = "0.3"
35 | walkdir = "2.3"
36 | z85 = "3"
37 | zip = "0.6"
38 |
39 | wasmtime = "18.0"
40 |
41 | assemblylift-core = { version = "0.4.0-beta.0", path = "../core" }
42 | assemblylift-core-iomod = { version = "0.4.0-beta.0", path = "../core/iomod" }
43 | assemblylift-generator = { path = "../generator" }
44 | assemblylift-hyper-runtime = { version = "0.4.0-beta.0", path = "../runtimes/hyper" }
45 | assemblylift-tools = { path = "../tools" }
46 |
47 | registry_common = { version = "0.1", package = "asml-iomod-registry-common" }
48 |
49 | [dependencies.reqwest]
50 | version = "0.11"
51 | features = ["blocking", "json"]
52 |
--------------------------------------------------------------------------------
/crates/cli/README.md:
--------------------------------------------------------------------------------
1 | assemblylift-cli
2 | ----------------
3 |
4 | The AssemblyLift `asml` CLI.
5 |
6 | Visit https://assemblylift.akkoro.io for more info about AssemblyLift.
7 |
--------------------------------------------------------------------------------
/crates/cli/src/archive.rs:
--------------------------------------------------------------------------------
1 | use std::fmt;
2 | use std::fs;
3 | use std::io::prelude::*;
4 | use std::path::{Path, PathBuf};
5 |
6 | use zip;
7 | use zip::write::FileOptions;
8 |
9 | #[derive(Debug)]
10 | pub struct ArchiveError {
11 | why: String,
12 | }
13 |
14 | impl std::error::Error for ArchiveError {}
15 |
16 | impl fmt::Display for ArchiveError {
17 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18 | write!(f, "{}", self.why)
19 | }
20 | }
21 |
22 | pub fn zip_dirs(
23 | dirs_in: Vec,
24 | file_out: impl AsRef,
25 | exclude_files_named: Vec<&str>,
26 | ) -> Result<(), ()> {
27 | use walkdir::WalkDir;
28 |
29 | let file = match fs::File::create(&file_out) {
30 | Ok(file) => file,
31 | Err(why) => panic!("could not create zip archive: {}", why.to_string()),
32 | };
33 |
34 | let mut zip = zip::ZipWriter::new(file);
35 | let options = FileOptions::default().compression_method(zip::CompressionMethod::Stored);
36 |
37 | for dir in dirs_in {
38 | for entry in WalkDir::new(dir.clone()).into_iter().filter_map(|e| e.ok()) {
39 | if exclude_files_named
40 | .iter()
41 | .find(|&f| f == &entry.file_name().to_str().unwrap())
42 | .is_none()
43 | {
44 | let mut root_dir_up = dir.clone();
45 | root_dir_up.pop();
46 | let zip_path = entry
47 | .path()
48 | .to_str()
49 | .unwrap()
50 | .replace(root_dir_up.to_str().unwrap(), "");
51 |
52 | let mut file_bytes = match fs::read(&entry.path()) {
53 | Ok(bytes) => bytes,
54 | Err(_) => continue,
55 | };
56 |
57 | zip.start_file(&format!("{}", zip_path), options)
58 | .expect("could not create zip archive");
59 | zip.write_all(file_bytes.as_mut_slice())
60 | .expect("could not create zip archive");
61 | }
62 | }
63 | }
64 |
65 | println!("🗜 > Wrote zip artifact {}", file_out.as_ref().display());
66 |
67 | Ok(())
68 | }
69 |
70 | pub fn unzip(bytes_in: &[u8], out_dir: &str) -> Result<(), ArchiveError> {
71 | println!("🗜 > Unzipping archive in {}...", out_dir);
72 | let reader = std::io::Cursor::new(bytes_in);
73 | let mut archive = zip::ZipArchive::new(reader).unwrap();
74 | archive.extract(out_dir).unwrap();
75 | Ok(())
76 | }
77 |
--------------------------------------------------------------------------------
/crates/cli/src/commands/bind.rs:
--------------------------------------------------------------------------------
1 | use assemblylift_tools::terraform::Terraform;
2 | use clap::ArgMatches;
3 |
4 | pub fn command(matches: Option<&ArgMatches>) {
5 | let _matches = match matches {
6 | Some(matches) => matches,
7 | _ => panic!("could not get matches for bind command"),
8 | };
9 |
10 | let tf = Terraform::default();
11 | tf.init();
12 | tf.apply();
13 | }
14 |
--------------------------------------------------------------------------------
/crates/cli/src/commands/burn.rs:
--------------------------------------------------------------------------------
1 | use assemblylift_generator::{
2 | projectfs::{self, Project},
3 | toml::{asml, service},
4 | };
5 | use clap::ArgMatches;
6 | use dialoguer::Confirm;
7 |
8 | pub fn command(matches: Option<&ArgMatches>) {
9 | let matches = match matches {
10 | Some(matches) => matches,
11 | _ => panic!("could not get matches for make command"),
12 | };
13 |
14 | let manifest = match projectfs::locate_asml_manifest() {
15 | Some(manifest) => manifest,
16 | None => panic!("could not find assemblylift.toml in tree"),
17 | };
18 | let mut manifest_dir = manifest.1.clone();
19 | manifest_dir.pop();
20 |
21 | let project = Project::new(manifest.0.project.name.clone(), Some(manifest_dir.clone()));
22 |
23 | let mut resource_type: Option<&str> = None;
24 | let mut resource_name: Option<&str> = None;
25 | for el in matches
26 | .values_of("resource")
27 | .expect("must specify either 'service', 'function' as an argument to burn")
28 | {
29 | if resource_type.is_none() {
30 | resource_type = Some(el);
31 | continue;
32 | }
33 | if resource_name.is_none() {
34 | resource_name = Some(el);
35 | continue;
36 | }
37 | }
38 |
39 | match resource_type {
40 | Some("service") => {
41 | let service_name = resource_name.unwrap();
42 | if Confirm::new()
43 | .with_prompt(format!(
44 | "Are you sure you want to destroy service \"{}\"?\nThis is PERMANENT!",
45 | service_name
46 | ))
47 | .interact()
48 | .unwrap()
49 | {
50 | let mut manifest: asml::Manifest = manifest.0.clone();
51 | manifest.remove_service(service_name);
52 | manifest
53 | .write(manifest_dir.clone())
54 | .expect("could not write assemblylift.toml");
55 |
56 | let mut service_dir = manifest_dir.clone();
57 | service_dir.push("services");
58 | service_dir.push(service_name);
59 | std::fs::remove_dir_all(service_dir).expect("could not remove service directory");
60 | }
61 | }
62 |
63 | Some("function") => {
64 | let resource_name = resource_name.unwrap().to_string();
65 | let function_name: Vec<&str> = resource_name.split(".").collect();
66 | if function_name.len() != 2 {
67 | panic!("syntax is `burn function .`")
68 | }
69 |
70 | if Confirm::new()
71 | .with_prompt(format!(
72 | "Are you sure you want to destroy function \"{}\"\nThis is PERMANENT!",
73 | resource_name
74 | ))
75 | .interact()
76 | .unwrap()
77 | {
78 | let service_dir = project.service_dir(function_name[0].into()).dir().clone();
79 | let mut manifest_file = service_dir.clone();
80 | manifest_file.push("service.toml");
81 | let mut service_manifest = service::Manifest::read(&manifest_file).unwrap();
82 | service_manifest.remove_function(function_name[1]);
83 | service_manifest.write(service_dir.clone()).unwrap();
84 | std::fs::remove_dir_all(
85 | &*project
86 | .service_dir(function_name[0].into())
87 | .function_dir(function_name[1].into()),
88 | )
89 | .expect("could not remove service directory");
90 | }
91 | }
92 |
93 | Some(_) => {
94 | panic!("must specify either 'service', or 'function', as an argument to burn")
95 | }
96 | None => panic!("must specify either 'service', or 'function' as an argument to burn"),
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/crates/cli/src/commands/cast/wasm/wasi_snapshot_preview1.command.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akkoro/assemblylift/a4f9094b0ed07eb813c9d2f5893a5a23dbca9a08/crates/cli/src/commands/cast/wasm/wasi_snapshot_preview1.command.wasm
--------------------------------------------------------------------------------
/crates/cli/src/commands/cast/wasm/wasi_snapshot_preview1.reactor.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akkoro/assemblylift/a4f9094b0ed07eb813c9d2f5893a5a23dbca9a08/crates/cli/src/commands/cast/wasm/wasi_snapshot_preview1.reactor.wasm
--------------------------------------------------------------------------------
/crates/cli/src/commands/host.rs:
--------------------------------------------------------------------------------
1 | use clap::ArgMatches;
2 | use tracing::Level;
3 | use tracing_subscriber::FmtSubscriber;
4 |
5 | use assemblylift_core_iomod::registry::{registry_channel, spawn_registry};
6 | use assemblylift_hyper_runtime::spawn_runtime;
7 |
8 | pub fn command(_matches: Option<&ArgMatches>) {
9 | let subscriber = FmtSubscriber::builder()
10 | .with_max_level(Level::DEBUG)
11 | .finish();
12 |
13 | tracing::subscriber::set_global_default(subscriber).expect("setting default subscriber failed");
14 |
15 | let (registry_tx, registry_rx) = registry_channel(8);
16 | spawn_registry(registry_rx).expect("unable to spawn IOmod registry");
17 | spawn_runtime(registry_tx);
18 | }
19 |
--------------------------------------------------------------------------------
/crates/cli/src/commands/init.rs:
--------------------------------------------------------------------------------
1 | use std::process;
2 |
3 | use assemblylift_generator::projectfs::Project;
4 | use clap::ArgMatches;
5 | use handlebars::to_json;
6 | use serde_json::value::{Map, Value as Json};
7 |
8 | use crate::templates::project::{ROOT_DOCUMENTS, SERVICE_DOCUMENTS};
9 | use crate::templates::write_documents;
10 |
11 | pub fn command(matches: Option<&ArgMatches>) {
12 | let matches = match matches {
13 | Some(matches) => matches,
14 | _ => panic!("could not get matches for init command"),
15 | };
16 |
17 | let default_service_name = "my-service";
18 | let default_function_name = "my-function";
19 | let project_name = matches.value_of("project_name").unwrap();
20 | // let function_language = matches.value_of("language").unwrap();
21 |
22 | let project = Project::new(project_name.parse().unwrap(), None);
23 |
24 | {
25 | let data = &mut Map::::new();
26 | data.insert(
27 | "project_name".to_string(),
28 | to_json(project_name.to_string()),
29 | );
30 | data.insert(
31 | "default_service_name".to_string(),
32 | to_json(default_service_name.to_string()),
33 | );
34 | write_documents(&project.dir(), (*ROOT_DOCUMENTS).clone().as_ref(), data);
35 | }
36 |
37 | {
38 | let data = &mut Map::::new();
39 | data.insert(
40 | "service_name".to_string(),
41 | to_json(default_service_name.to_string()),
42 | );
43 | // data.insert(
44 | // "function_language".to_string(),
45 | // to_json(function_language.to_string()),
46 | // );
47 | write_documents(
48 | &project
49 | .service_dir(String::from(default_service_name))
50 | .dir(),
51 | (*SERVICE_DOCUMENTS).clone().as_ref(),
52 | data,
53 | );
54 | }
55 |
56 | // match function_language {
57 | // "rust" => {
58 | // assert_prereqs();
59 | //
60 | // std::fs::create_dir_all(format!(
61 | // "{}/src",
62 | // project
63 | // .service_dir(String::from(default_service_name))
64 | // .function_dir(String::from(default_function_name))
65 | // .to_str()
66 | // .unwrap()
67 | // ))
68 | // .unwrap();
69 | //
70 | // let data = &mut Map::::new();
71 | // data.insert(
72 | // "function_name".to_string(),
73 | // to_json(default_function_name.to_string()),
74 | // );
75 | // write_documents(
76 | // &project
77 | // .service_dir(String::from(default_service_name))
78 | // .function_dir(String::from(default_function_name)),
79 | // (*RUST_FUNCTION_DOCUMENTS).clone().as_ref(),
80 | // data,
81 | // );
82 | // }
83 | // "ruby" => {
84 | // write_documents(
85 | // &project
86 | // .service_dir(String::from(default_service_name))
87 | // .function_dir(String::from(default_function_name)),
88 | // (*RUBY_FUNCTION_DOCUMENTS).clone().as_ref(),
89 | // &mut Map::::new(),
90 | // );
91 | // }
92 | // unknown => panic!("unsupported language: {}", unknown),
93 | // }
94 |
95 | println!("\r\n✅ Done! Your project root is: {:?}", project.dir());
96 | }
97 |
98 | fn check_rust_prereqs() -> bool {
99 | let cargo_version = process::Command::new("cargo").arg("--version").output();
100 |
101 | match cargo_version {
102 | Ok(_version) => true,
103 | Err(_) => {
104 | println!("ERROR: missing Cargo!");
105 | false
106 | }
107 | }
108 | }
109 |
110 | fn assert_prereqs() {
111 | if !check_rust_prereqs() {
112 | panic!("missing system dependencies")
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/crates/cli/src/commands/make.rs:
--------------------------------------------------------------------------------
1 | use assemblylift_generator::projectfs::{self, Project};
2 | use assemblylift_generator::toml::{asml, service};
3 | use clap::ArgMatches;
4 | use handlebars::to_json;
5 | use serde_json::value::{Map, Value as Json};
6 |
7 | use crate::templates::project::{
8 | RUBY_FUNCTION_DOCUMENTS, RUST_FUNCTION_DOCUMENTS, SERVICE_DOCUMENTS,
9 | };
10 | use crate::templates::write_documents;
11 |
12 | pub fn command(matches: Option<&ArgMatches>) {
13 | let matches = match matches {
14 | Some(matches) => matches,
15 | _ => panic!("could not get matches for make command"),
16 | };
17 |
18 | let manifest = match projectfs::locate_asml_manifest() {
19 | Some(manifest) => manifest,
20 | None => panic!("could not find assemblylift.toml in tree"),
21 | };
22 | let mut manifest_dir = manifest.1.clone();
23 | manifest_dir.pop();
24 |
25 | let project = Project::new(manifest.0.project.name.clone(), Some(manifest_dir.clone()));
26 |
27 | let mut resource_type: Option<&str> = None;
28 | let mut resource_name: Option<&str> = None;
29 | for el in matches.values_of("resource").unwrap() {
30 | if resource_type.is_none() {
31 | resource_type = Some(el);
32 | continue;
33 | }
34 | if resource_name.is_none() {
35 | resource_name = Some(el);
36 | continue;
37 | }
38 | }
39 |
40 | match resource_type {
41 | Some("service") => {
42 | let data = &mut Map::::new();
43 | data.insert(
44 | "service_name".to_string(),
45 | to_json(resource_name.unwrap().to_string()),
46 | );
47 | let path = project
48 | .service_dir(String::from(resource_name.unwrap()))
49 | .dir();
50 | write_documents(&path, (*SERVICE_DOCUMENTS).clone().as_ref(), data);
51 |
52 | let mut manifest: asml::Manifest = manifest.0.clone();
53 | manifest.add_service(resource_name.unwrap());
54 | manifest
55 | .write(manifest_dir.clone())
56 | .expect("could not write assemblylift.toml");
57 | }
58 |
59 | Some("function") => {
60 | let language = matches.value_of("language").unwrap_or("rust");
61 | let resource_name = resource_name.unwrap().to_string();
62 | let function_name: Vec<&str> = resource_name.split(".").collect();
63 | if function_name.len() != 2 {
64 | panic!("syntax is `make function .`")
65 | }
66 |
67 | let service_dir = project.service_dir(function_name[0].into()).dir().clone();
68 | let mut manifest_file = service_dir.clone();
69 | manifest_file.push("service.toml");
70 | let mut service_manifest = service::Manifest::read(&manifest_file).unwrap();
71 | service_manifest.add_function(function_name[1], language);
72 | service_manifest.write(service_dir.clone()).unwrap();
73 |
74 | match language {
75 | "rust" => {
76 | let data = &mut Map::::new();
77 | data.insert("function_name".to_string(), to_json(function_name[1]));
78 | let path = project
79 | .service_dir(String::from(function_name[0]))
80 | .function_dir(String::from(function_name[1]));
81 | write_documents(&path, (*RUST_FUNCTION_DOCUMENTS).clone().as_ref(), data);
82 | }
83 | "ruby" => {
84 | let path = project
85 | .service_dir(String::from(function_name[0]))
86 | .function_dir(String::from(function_name[1]));
87 | write_documents(
88 | &path,
89 | (*RUBY_FUNCTION_DOCUMENTS).clone().as_ref(),
90 | &mut Map::::new(),
91 | );
92 | }
93 | lang => panic!("function language `{}` is not supported", lang),
94 | }
95 | }
96 |
97 | Some(_) => panic!("must specify either 'service' or 'function' as an argument to make"),
98 | None => panic!("must specify either 'service' or 'function' as an argument to make"),
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/crates/cli/src/commands/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod bind;
2 | pub mod burn;
3 | pub mod cast;
4 | pub mod host;
5 | pub mod init;
6 | pub mod make;
7 | pub mod r#move;
8 | pub mod nuke;
9 | pub mod pack;
10 | pub mod push;
11 | pub mod user;
12 |
--------------------------------------------------------------------------------
/crates/cli/src/commands/nuke.rs:
--------------------------------------------------------------------------------
1 | use assemblylift_tools::terraform;
2 | use clap::ArgMatches;
3 | use dialoguer::Confirm;
4 |
5 | pub fn command(_matches: Option<&ArgMatches>) {
6 | if Confirm::new()
7 | .with_prompt(
8 | "Are you sure you want to destroy ALL provisioned infrastructure?\nThis is PERMANENT!",
9 | )
10 | .interact()
11 | .unwrap()
12 | {
13 | let tf = terraform::Terraform::default();
14 | tf.destroy();
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/crates/cli/src/commands/pack.rs:
--------------------------------------------------------------------------------
1 | use clap::ArgMatches;
2 |
3 | use assemblylift_core_iomod::package::IomodManifest;
4 |
5 | use crate::archive;
6 |
7 | pub fn command(matches: Option<&ArgMatches>) {
8 | let matches = match matches {
9 | Some(matches) => matches,
10 | _ => panic!("could not get matches for cast command"),
11 | };
12 |
13 | match matches.subcommand() {
14 | ("iomod", matches) => command_iomod(matches),
15 | _ => println!(
16 | "{}",
17 | "missing subcommand. try `asml pack help` for options."
18 | ),
19 | }
20 | }
21 |
22 | fn command_iomod(matches: Option<&ArgMatches>) {
23 | let matches = match matches {
24 | Some(matches) => matches,
25 | _ => panic!("could not get matches for cast command"),
26 | };
27 |
28 | let cwd = std::env::current_dir().expect("unable to determine the current working directory");
29 | let mut manifest_path = cwd.clone();
30 | manifest_path.push("iomod.toml");
31 |
32 | let manifest = IomodManifest::read(&manifest_path).expect(&format!(
33 | "could not read iomod manifest from {:?}",
34 | manifest_path
35 | ));
36 |
37 | let entrypoint = manifest.process.entrypoint;
38 | let mut binary_path = cwd.clone();
39 | binary_path.push(entrypoint);
40 |
41 | // verify that the entrypoint exists before we pack it
42 | std::fs::metadata(binary_path.clone())
43 | .expect(&format!("could not stat {:?}", binary_path.clone()));
44 |
45 | let out_path = matches.value_of("out").unwrap(); // unwrap: this arg is required
46 |
47 | archive::zip_dirs(vec![cwd], out_path, vec![]).expect("zip_dir failed during pack");
48 | }
49 |
--------------------------------------------------------------------------------
/crates/cli/src/commands/user.rs:
--------------------------------------------------------------------------------
1 | use clap::ArgMatches;
2 |
3 | pub fn command(matches: Option<&ArgMatches>) {
4 | let matches = match matches {
5 | Some(matches) => matches,
6 | _ => panic!("could not get matches for cast command"),
7 | };
8 |
9 | match matches.subcommand() {
10 | ("login", matches) => command_login(matches),
11 | _ => println!(
12 | "{}",
13 | "missing subcommand. try `asml pack help` for options."
14 | ),
15 | }
16 | }
17 |
18 | fn command_login(_matches: Option<&ArgMatches>) {}
19 |
--------------------------------------------------------------------------------
/crates/cli/src/templates/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod project;
2 |
3 | use std::io::Write;
4 | use std::path::PathBuf;
5 | use std::{fs, io, path};
6 |
7 | use handlebars::Handlebars;
8 | use serde_json::value::{Map as SerdeMap, Value as Json};
9 |
10 | pub struct Document {
11 | pub file_name: &'static str,
12 | pub document: String,
13 | }
14 |
15 | pub fn write_documents(path: &PathBuf, docs: &Vec, data: &mut SerdeMap) {
16 | let mut reg = Handlebars::new();
17 | for doc in docs {
18 | reg.register_template_string(doc.file_name, doc.document.clone())
19 | .unwrap();
20 |
21 | let render = reg.render(doc.file_name, &data).unwrap();
22 | let mut path = PathBuf::from(path);
23 | path.push(doc.file_name);
24 | write_to_file(&*path, render).unwrap();
25 | }
26 | }
27 |
28 | fn write_to_file(path: &path::Path, contents: String) -> Result<(), io::Error> {
29 | fs::create_dir_all(path.parent().unwrap())?;
30 |
31 | let mut file = match fs::File::create(path) {
32 | Err(why) => panic!(
33 | "couldn't create file {}: {}",
34 | path.display(),
35 | why.to_string()
36 | ),
37 | Ok(file) => file,
38 | };
39 |
40 | println!("📄 > Wrote {}", path.display());
41 | file.write_all(contents.as_bytes())
42 | }
43 |
--------------------------------------------------------------------------------
/crates/cli/src/templates/project.rs:
--------------------------------------------------------------------------------
1 | use std::sync::Arc;
2 |
3 | use once_cell::sync::Lazy;
4 |
5 | use crate::templates::Document;
6 |
7 | static ROOT_GITIGNORE: &str = r#".asml/
8 | .terraform/
9 | .DS_Store
10 | net/
11 | **/target/
12 | **/build/
13 | "#;
14 |
15 | static ASSEMBLYLIFT_TOML: &str = r#"[project]
16 | name = "{{project_name}}"
17 |
18 | # Platforms define an environment in which to deploy providers.
19 | # [[platforms]]
20 | # id = "my-id" # A unique identifier for this platform
21 | # name = "platform-name" # Name of the platform, one of "aws" or "kubernetes"
22 | # options = {} # Map of options to pass to the platform
23 |
24 | [[services]]
25 | name = "{{default_service_name}}" # Must correspond to a service in the services/ directory
26 | provider = { name = "my-provider", platform_id = "my-id" } # `platform_id` is the `id` of one of the platforms defined above
27 | # registry_id = "my-registry-id" # Optional; needed for Service providers which deploy using containers
28 | # domain_name = "my.example-domain.com" # Optional; needed if deploying service with a Domain name
29 |
30 | # [[registries]]
31 | # id = "my-registry-id"
32 | # provider = { name = "my-provider", platform_id = "my-id" }
33 |
34 | # [[domains]]
35 | # dns_name = "my.example-domain.com" # An existing hosted zone with the DNS Provider specified
36 | # [domains.provider]
37 | # name = "my-provider"
38 | # platform_id = "my-id"
39 | # options = {} # Map of options to pass to the provider
40 |
41 | "#;
42 |
43 | pub static ROOT_DOCUMENTS: Lazy>> = Lazy::new(|| {
44 | Arc::new(Vec::from([
45 | Document {
46 | file_name: "assemblylift.toml",
47 | document: String::from(ASSEMBLYLIFT_TOML),
48 | },
49 | Document {
50 | file_name: ".gitignore",
51 | document: String::from(ROOT_GITIGNORE),
52 | },
53 | ]))
54 | });
55 |
56 | static SERVICE_TOML: &str = r#"[gateway]
57 | provider = { name = "{{service_name}}" }
58 |
59 | #[[functions]]
60 | #name = "rusty-fn" # Must correspond to a function in the service's functions/ directory
61 | #language = "rust" # Kind of source code for function; one of "rust" or "ruby"
62 | #http = { verb = "GET", path = "/rustyfn" } # HTTP route to the function from the Service's Gateway
63 | #environment = { var1 = "val1" } # Map of environment variables to pass to the function
64 | "#;
65 |
66 | pub static SERVICE_DOCUMENTS: Lazy>> = Lazy::new(|| {
67 | Arc::new(Vec::from([Document {
68 | file_name: "service.toml",
69 | document: String::from(SERVICE_TOML),
70 | }]))
71 | });
72 |
73 | static FUNCTION_CARGO_TOML: &str = r#"[package]
74 | name = "{{function_name}}"
75 | version = "0.0.0"
76 | edition = "2021"
77 |
78 | [dependencies]
79 | serde = "1"
80 | serde_json = "1"
81 | assemblylift-core-guest = { version = "0.4.0-beta" }
82 | # You can omit core-io-guest if you will not be using IOmods in your function
83 | assemblylift-core-io-guest = { version = "0.4.0-beta" }
84 | "#;
85 |
86 | static FUNCTION_MAIN_RS: &str = r#"use assemblylift_core_guest::*;
87 |
88 | #[handler]
89 | async fn main() {
90 | // `ctx` is a value injected by the `handler` attribute macro
91 | let event: serde_json::Value = match serde_json::from_slice(&ctx.input) {
92 | Ok(val) => val,
93 | Err(err) => return FunctionContext::failure(format!("could not parse function input as JSON: {}", err.to_string()));
94 | };
95 |
96 | FunctionContext::success("\"Function returned OK!\"".to_string());
97 | }
98 | "#;
99 |
100 | static FUNCTION_HANDLER_RB: &str = r#"require 'asml'
101 | require 'base64'
102 | require 'json'
103 |
104 | def main(input)
105 | # TODO implement your function code here!
106 | Asml.success(JSON.generate(input.to_s))
107 | end
108 |
109 | main(JSON.parse(Asml.get_function_input()))
110 | "#;
111 |
112 | pub static RUST_FUNCTION_DOCUMENTS: Lazy>> = Lazy::new(|| {
113 | Arc::new(Vec::from([
114 | Document {
115 | file_name: "Cargo.toml",
116 | document: String::from(FUNCTION_CARGO_TOML),
117 | },
118 | Document {
119 | file_name: "src/main.rs",
120 | document: String::from(FUNCTION_MAIN_RS),
121 | },
122 | ]))
123 | });
124 |
125 | pub static RUBY_FUNCTION_DOCUMENTS: Lazy>> = Lazy::new(|| {
126 | Arc::new(Vec::from([Document {
127 | file_name: "handler.rb",
128 | document: String::from(FUNCTION_HANDLER_RB),
129 | }]))
130 | });
131 |
--------------------------------------------------------------------------------
/crates/core/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "assemblylift-core"
3 | version = "0.4.0-beta.0"
4 | description = "AssemblyLift core library"
5 | authors = ["Akkoro and the AssemblyLift contributors "]
6 | edition = "2018"
7 | license-file = "../LICENSE.md"
8 | repository = "https://github.com/akkoro/assemblylift"
9 | readme = "README.md"
10 |
11 | [dependencies]
12 | anyhow = "1.0"
13 | base64 = "0.21"
14 | bincode = "1.3"
15 | crossbeam-channel = "0.5"
16 | itertools = "0.10"
17 | once_cell = "1.4"
18 | opa = { version = "0.10.0-dev", git = "https://github.com/dotxlem/opa-rs.git", rev = "19f4836" }
19 | regex = "1.7"
20 | reqwest = { version = "0.11", features = ["blocking", "json"] }
21 | ring = "0.16"
22 | serde = "1"
23 | serde_json = "1"
24 | tokio = { version = "1.4", features = ["full"] }
25 | tracing = "0.1"
26 | uuid = { version = "1.3", features = ["v4", "fast-rng"] }
27 |
28 | wasmtime = { version = "18.0", features = ["default", "component-model"] }
29 | wasmtime-wasi = { version = "18.0", features = ["preview2"] }
30 |
31 | wat = "1.0.85"
32 | wast = "70.0.2"
33 | wasm-encoder = "0.41"
34 | wit-component = "0.20.1"
35 | wit-parser = "0.13.1"
36 |
37 | assemblylift-core-iomod = { path = "./iomod" }
38 |
39 | [dev-dependencies]
40 | tokio = {version = "1", features = ["macros", "rt-multi-thread"]}
41 | tokio-test = "0.4"
42 |
--------------------------------------------------------------------------------
/crates/core/README.md:
--------------------------------------------------------------------------------
1 | assemblylift-core
2 | -----------------
3 |
4 | AssemblyLift core library
5 |
--------------------------------------------------------------------------------
/crates/core/guest/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "assemblylift-core-guest"
3 | version = "0.4.0-beta.0"
4 | description = "AssemblyLift core WASM guest library"
5 | authors = ["Akkoro and the AssemblyLift contributors "]
6 | edition = "2018"
7 | license-file = "../../LICENSE.md"
8 | repository = "https://github.com/akkoro/assemblylift"
9 | readme = "README.md"
10 |
11 | [dependencies]
12 | clap = { version = "4", features = ["cargo"] }
13 | direct-executor = "0.3"
14 | serde = { version = "1", features = ["derive"] }
15 | serde_json = "1"
16 | wit-bindgen = "0.15"
17 |
18 | assemblylift-core-guest-macros = { version = "0.4.0-beta.0", path = "./macros" }
19 |
--------------------------------------------------------------------------------
/crates/core/guest/README.md:
--------------------------------------------------------------------------------
1 | assemblylift-core-guest
2 | ------------------------
3 |
4 | AssemblyLift core WASM guest library
5 |
--------------------------------------------------------------------------------
/crates/core/guest/macros/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "assemblylift-core-guest-macros"
3 | version = "0.4.0-beta.0"
4 | description = "Procedural macros for assemblylift-core-guest"
5 | authors = ["Akkoro and the AssemblyLift contributors "]
6 | edition = "2018"
7 | license-file = "../../../LICENSE.md"
8 | repository = "https://github.com/akkoro/assemblylift"
9 | readme = "README.md"
10 |
11 | [lib]
12 | proc-macro = true
13 |
14 | [dependencies]
15 | proc-macro2 = "1.0"
16 | quote = "1.0"
17 | syn = { version = "1.0", features = ["full"] }
18 |
--------------------------------------------------------------------------------
/crates/core/guest/macros/README.md:
--------------------------------------------------------------------------------
1 | assemblylift-core-guest-macros
2 | ------------------------------
3 |
--------------------------------------------------------------------------------
/crates/core/guest/macros/src/lib.rs:
--------------------------------------------------------------------------------
1 | use quote::{quote, quote_spanned};
2 | use syn::{parse2, ItemFn};
3 |
4 | #[proc_macro_attribute]
5 | pub fn handler(
6 | _args: proc_macro::TokenStream,
7 | stream: proc_macro::TokenStream,
8 | ) -> proc_macro::TokenStream {
9 | let input: ItemFn = parse2(stream.into()).expect("could not parse token stream");
10 | let block_statements = &input.block.stmts;
11 | let name = &input.sig.ident;
12 | let _ret = &input.sig.output;
13 |
14 | if name != "main" {
15 | return proc_macro::TokenStream::from(quote_spanned! { name.span() =>
16 | compile_error!("only the main function can be tagged with #[handler]"),
17 | });
18 | }
19 |
20 | proc_macro::TokenStream::from(quote! {
21 | use assemblylift_core_guest::asml_rt;
22 | use assemblylift_core_guest::direct_executor;
23 | // use assemblylift_core_guest::export_command;
24 | use assemblylift_core_guest::FunctionContext;
25 | // use assemblylift_core_guest::command::Command;
26 | use assemblylift_core_guest::wit_bindgen;
27 | // struct Cmd;
28 | // impl Command for Cmd {
29 | // fn run() -> Result<(), ()> {
30 | // Ok(__handler(FunctionContext { input: asml_rt::get_input() }))
31 | // }
32 | // }
33 | // export_command!(Cmd);
34 | fn __handler(ctx: FunctionContext) {
35 | direct_executor::run_spinning(async {
36 | #(#block_statements)*
37 | });
38 | }
39 | fn main() {
40 | __handler(FunctionContext { input: asml_rt::get_input() })
41 | }
42 | })
43 | }
44 |
--------------------------------------------------------------------------------
/crates/core/guest/src/lib.rs:
--------------------------------------------------------------------------------
1 | extern crate assemblylift_core_guest_macros;
2 |
3 | use std::collections::HashMap;
4 | use std::fmt;
5 |
6 | pub use direct_executor;
7 | use serde::{Deserialize, Serialize};
8 | pub use wit_bindgen;
9 |
10 | pub use assemblylift::akkoro::assemblylift::asml_io;
11 | pub use assemblylift::akkoro::assemblylift::asml_rt;
12 | pub use assemblylift_core_guest_macros::handler;
13 | // pub use command::wasi;
14 |
15 | pub mod assemblylift;
16 | // pub mod command;
17 | pub mod jwt;
18 | pub mod opa;
19 | pub mod secrets;
20 |
21 | pub struct FunctionContext {
22 | pub input: Vec,
23 | }
24 |
25 | // TODO success and failure should take bytes as args, not string
26 | impl FunctionContext {
27 | pub fn log(message: String) {
28 | asml_rt::log(asml_rt::LogLevel::Info, clap::crate_name!(), &message)
29 | }
30 |
31 | pub fn success(response: String) {
32 | asml_rt::success(&response.as_bytes().to_vec())
33 | }
34 |
35 | pub fn failure(response: String) {
36 | asml_rt::failure(&response.as_bytes().to_vec())
37 | }
38 | }
39 |
40 | pub type StatusCode = u16;
41 | #[derive(Serialize, Deserialize)]
42 | pub struct HttpResponse {
43 | #[serde(rename = "isBase64Encoded")]
44 | is_base64_encoded: bool,
45 | #[serde(rename = "statusCode")]
46 | status_code: StatusCode,
47 | headers: HashMap,
48 | body: String,
49 | }
50 |
51 | #[derive(Serialize, Deserialize)]
52 | pub struct HttpError {
53 | pub code: StatusCode,
54 | pub desc: String,
55 | pub message: String,
56 | }
57 |
58 | #[derive(Copy, Clone, Debug, Serialize, Deserialize)]
59 | pub enum HttpErrorCode {
60 | NotFound = 404,
61 | FunctionError = 520,
62 | }
63 |
64 | impl fmt::Display for HttpErrorCode {
65 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
66 | match self {
67 | HttpErrorCode::NotFound => write!(f, "Missing Resource"),
68 | HttpErrorCode::FunctionError => write!(f, "Function Error"),
69 | }
70 | }
71 | }
72 |
73 | impl HttpResponse {
74 | pub fn ok(
75 | body: String,
76 | content_type: Option,
77 | is_base64_encoded: bool,
78 | gzip: bool,
79 | ) -> Self {
80 | let mut headers = HashMap::default();
81 | headers.insert(
82 | "content-type".to_string(),
83 | content_type.unwrap_or_else(|| String::from("application/json")),
84 | );
85 | if gzip {
86 | headers.insert("content-encoding".to_string(), "gzip".to_string());
87 | }
88 |
89 | Self {
90 | status_code: 200,
91 | is_base64_encoded,
92 | headers,
93 | body,
94 | }
95 | }
96 |
97 | pub fn error(message: String, code: HttpErrorCode) -> Self {
98 | let mut headers = HashMap::default();
99 | headers.insert(
100 | String::from("content-type"),
101 | String::from("application/json"),
102 | );
103 |
104 | Self {
105 | status_code: code as StatusCode,
106 | is_base64_encoded: false,
107 | headers,
108 | body: serde_json::to_string(&HttpError {
109 | code: code as StatusCode,
110 | desc: code.to_string(),
111 | message,
112 | })
113 | .unwrap(),
114 | }
115 | }
116 | }
117 |
118 | #[macro_export]
119 | macro_rules! http_ok {
120 | ($response:expr) => {
121 | FunctionContext::success(
122 | serde_json::to_string(&HttpResponse::ok(
123 | serde_json::to_string(&$response).unwrap(),
124 | None,
125 | false,
126 | false,
127 | ))
128 | .unwrap(),
129 | );
130 | };
131 |
132 | ($response:expr, $type:expr, $isb64:expr, $isgzip:expr) => {
133 | FunctionContext::success(
134 | serde_json::to_string(&HttpResponse::ok($response, $type, $isb64, $isgzip)).unwrap(),
135 | );
136 | };
137 | }
138 |
139 | #[macro_export]
140 | macro_rules! http_error {
141 | ($message:expr) => {
142 | FunctionContext::success(
143 | serde_json::to_string(&HttpResponse::error($message, HttpErrorCode::FunctionError))
144 | .unwrap(),
145 | );
146 | };
147 | }
148 |
149 | #[macro_export]
150 | macro_rules! http_not_found {
151 | ($resource_name:expr) => {
152 | FunctionContext::success(
153 | serde_json::to_string(&HttpResponse::error(
154 | format!("missing resource {:?}", $resource_name),
155 | HttpErrorCode::NotFound,
156 | ))
157 | .unwrap(),
158 | );
159 | };
160 | }
161 |
--------------------------------------------------------------------------------
/crates/core/io/README.md:
--------------------------------------------------------------------------------
1 | assemblylift-core-event
2 | ----------------------
3 |
4 | AssemblyLift core event library
5 |
--------------------------------------------------------------------------------
/crates/core/io/common/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "assemblylift-core-io-common"
3 | version = "0.3.0"
4 | description = "AssemblyLift core event common library"
5 | authors = ["Akkoro and the AssemblyLift contributors "]
6 | edition = "2018"
7 | license-file = "../../../LICENSE.md"
8 | repository = "https://github.com/akkoro/assemblylift"
9 | readme = "README.md"
10 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
11 |
12 | [dependencies]
13 | serde = { version = "1.0", features = ["derive"] }
14 |
--------------------------------------------------------------------------------
/crates/core/io/common/README.md:
--------------------------------------------------------------------------------
1 | assemblylift-core-event-common
2 | ------------------------------
3 |
4 | AssemblyLift core event common library. Provides functionality common to both the
5 | host and guest event implementations.
6 |
--------------------------------------------------------------------------------
/crates/core/io/common/src/constants.rs:
--------------------------------------------------------------------------------
1 | pub const IO_BUFFER_SIZE_BYTES: usize = 32768;
2 | pub const FUNCTION_INPUT_BUFFER_SIZE: usize = 8192;
3 |
--------------------------------------------------------------------------------
/crates/core/io/common/src/lib.rs:
--------------------------------------------------------------------------------
1 | pub mod constants;
2 |
--------------------------------------------------------------------------------
/crates/core/io/guest/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "assemblylift-core-io-guest"
3 | version = "0.4.0-beta.0"
4 | description = "AssemblyLift core event WASM guest library"
5 | authors = ["Akkoro and the AssemblyLift contributors "]
6 | edition = "2018"
7 | license-file = "../../../LICENSE.md"
8 | repository = "https://github.com/akkoro/assemblylift"
9 | readme = "README.md"
10 |
11 | [dependencies]
12 | serde = "1"
13 | serde_json = "1"
14 | futures = "0.3"
15 | lazy_static = "1.4"
16 |
17 | assemblylift-core-guest = { version = "0.4.0-beta.0", path = "../../guest" }
18 |
--------------------------------------------------------------------------------
/crates/core/io/guest/README.md:
--------------------------------------------------------------------------------
1 | assemblylift-core-event-guest
2 | -----------------------------
3 |
4 | AssemblyLift core event WASM guest library
5 |
--------------------------------------------------------------------------------
/crates/core/io/guest/src/lib.rs:
--------------------------------------------------------------------------------
1 | use std::future::Future;
2 | use std::marker::PhantomData;
3 | use std::pin::Pin;
4 | use std::task::{Context, Poll, Waker};
5 |
6 | use serde::{de::DeserializeOwned, Deserialize};
7 |
8 | use assemblylift_core_guest::asml_rt::LogLevel;
9 | use assemblylift_core_guest::{asml_io, asml_rt};
10 |
11 | #[derive(Clone)]
12 | /// A handle implementing `std::future::Future` for an in-flight IOmod call
13 | pub struct Io<'a, R> {
14 | pub id: u32,
15 | waker: Box