Skip to content

Commit

Permalink
docs: improving documentation (#64)
Browse files Browse the repository at this point in the history
* added comments to stuff under crates/

Signed-off-by: Dan Chiarlone <[email protected]>

* first draft on CONTRIBUTING, CODE_OF_CONDUCT, and LICENSE docs

Signed-off-by: Dan Chiarlone <[email protected]>

* updated README, removed old design principles file (we have to remake it), and updated primer a bit

Signed-off-by: Dan Chiarlone <[email protected]>

* cargo fmt and cargo clippy

Signed-off-by: Dan Chiarlone <[email protected]>

fixing typo

Signed-off-by: Dan Chiarlone <[email protected]>

small changes

Signed-off-by: Dan Chiarlone <[email protected]>

small typo

Signed-off-by: Dan Chiarlone <[email protected]>
  • Loading branch information
danbugs committed Jul 4, 2022
1 parent 15bb4dc commit 8091917
Show file tree
Hide file tree
Showing 23 changed files with 191 additions and 167 deletions.
9 changes: 9 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Microsoft Open Source Code of Conduct

This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).

Resources:

- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
- Contact [[email protected]](mailto:[email protected]) with questions or concerns
74 changes: 74 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Contributing Guide

* [How to Help](#contributing-guide)
* [Find an Issue](#find-an-issue)
* [Ask for Help](#ask-for-help)
* [Pull Request Lifecycle](#pull-request-lifecycle)
* [Development Environment Setup](#development-environment-setup)
* [Sign Your Commits](#sign-your-commits)
* [Pull Request Checklist](#pull-request-checklist)

## How to Help

Welcome! We are glad that you want to contribute to our project! 💖

As you get started, you are in the best position to give us feedback on areas of our project that we need help with!

If anything doesn't make sense, or doesn't work when you run it, please open a bug report and let us know!

### Find an Issue

We have good first issues for new contributors and help wanted issues suitable for any contributor. [good first issue](https://github.com/deislabs/wasi-cloud/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) has extra information to help you make your first contribution. [help wanted](https://github.com/deislabs/wasi-cloud/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) are issues suitable for someone who isn't a core maintainer and is good to move onto after your first pull request.

We will always try to have at least some issues with these labels, but, if there are not, feel free to file an issue asking if there is any place that could use some collaboration — in the future, we plan to have a Zulip/Slack/Gitter/Discord channel to make this process smoother.

Once you see an issue that you'd like to work on, please post a comment saying that you want to work on it. Something like "I want to work on this" is fine.

### Ask for Help

The best way to reach us with a question when contributing is to ask on the original github issue.

### Pull Request Lifecycle

If you are working on something that does not have an issue associated with it, your first step before making a PR should be to make an issue and explain the problem and motivation for your proposed change. Once that's done, make a PR from your feature branch (usually named `<your-username>/<feature-name>`) onto `main`. After that, someone will be assigned to review your PR.

> Note: Prior to making a PR, it's good practice to always run `cargo fmt`, and `cargo clippy`.
### Development Environment Setup

⚠️ **Explain how to set up a development environment**

### Sign Your Commits

In this repository, we require commits to be signed. If you don't know what that means, we highly recommend checking out [this](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits) tutorial on how to sign your own commits.

If you've already made commits and they haven't been signed, you'll have to ammend those commits with something like:
```sh
git rebase --exec 'git commit --amend --no-edit -n -S' -i <commit-hash>
```

> Note: Please, make sure that the work up until `<commit-hash>` is your work to avoid re-signing someone else's work.
#### Developer Certificate of Origin (DCO)
Licensing is important to open source projects. It provides some assurances that
the software will continue to be available based under the terms that the
author(s) desired. We require that contributors sign off on commits submitted to
our project's repositories. The [Developer Certificate of Origin
(DCO)](https://probot.github.io/apps/dco/) is a way to certify that you wrote and
have the right to contribute the code you are submitting to the project.

You sign-off by adding the following to your commit messages. Your sign-off must
match the git user and email associated with the commit.

This is my commit message

Signed-off-by: Your Name <[email protected]>

Git has a `-s` command line option to do this automatically:

git commit -s -m 'This is my commit message'

If you forgot to do this and have not yet pushed your changes to the remote
repository, you can amend your commit with the sign-off by running

git commit --amend -s
21 changes: 21 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Copyright (c) Microsoft Corporation.

MIT License

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
44 changes: 14 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,26 @@
# wasi-cloud
wasi-cloud is a straight-forward attempt to see if ~80% of the cloud native APIs can be modeled in Wasm component interfaces compiled to the WebAssembly System Interface or WASI specification. If so, the developer experience could take a step _backward into tight productivity_, with quick development feedback loops while removing the domain specific cloud knowledge currently required. Enabling developers to build apps and ops teams to deploy them with radically separated fields of expertise.
<img align="right" src="docs/images/tmp-logo.png" width="150px" />

Fundamentally, this experiment tests out the the possibility that system interface-based webassemly components (using wit) could drive a useful separation between the app developer, deployment environment, and operator to enable critical optimizations and experiences that can then be built to optimize both, making distributed, cloud-native applications easier for both dev and ops as well as extending the reach of what we currently call "cloud native" into constrained, heterogeneous environments that are not called "hyperscale public cloud".
# WASI-Cloud
WASI-Cloud defines a set of WebAssembly Interface Types (i.e., WIT) files that abstract the cloud-provider specific knowledge required behind utilizing a Cloud serivce (e.g., key-value store, message queue, etc.).

The approach taken here does not involve any new technologies; it tries to lay down a test case to determine whether 80% of all cloud-native apps could be built more easily and operated more easily by more people. Note that this means that we are not assuming that we can reach the other 20% right away, if ever. Instead, it embraces the concept that Visual Basic enabled vastly easier application building because it made that first 80% so easy to do that the power of every developer was exponentially increased. Increasing the delivery velocity of the 80% was fundamental to the explosion of Windows in the first place, and if there's one thing that is true of the current environment it's that everyone agrees it's hard to know where to start.
In simple terms, WASI-Cloud allows you to go from doing this:
<img align="center" src="docs/images/readme0.png" width="50%" />

## Preamble to the experiment
To this:
<img align="center" src="docs/images/readme1.png" width="50%" />

Getting to the essence of Visual Basic:

```
Visual Basic 6 accomplished its goals by abstracting away the complexity of the underlying Windows OS. Simple things were very simple to accomplish. On the other hand, complex things, such as dealing with threads, were impossible. My rule of thumb for Visual Basic 6 was: if I couldn’t do it within 10 minutes, I couldn’t do it at all.
```

-- https://docs.microsoft.com/en-us/archive/msdn-magazine/2012/june/don-t-get-me-started-the-silent-majority-why-visual-basic-6-still-thrives

this we cant do in cloud native.

In cloud native, we've achieved the explosive growth of the public cloud (helped by the epidemic), but the acceleration curve (though still healthy) is already flattening. Evidence:
- the requirement of all three hyperscale cloud competitors to begin building private cloud attach in the form of Arc-like agents.
- the rise of [CDN clouds](https://stratechery.com/2021/cloudflares-disruption/) out of the original CDN function platforms like Fastly and CloudFlare, and the rise of the [attack on public cloud data egress charges](https://blog.cloudflare.com/aws-egregious-egress/).
- the focus by [prominent VCs](https://a16z.com/2021/05/27/cost-of-cloud-paradox-market-cap-cloud-lifecycle-scale-growth-repatriation-optimization/) and [startups](https://www.fermyon.com/blog/dont-repatriate-servers) on the dramatic reduction of costs by limiting or "repatriating" your compute off of hyperscale

By far most future compute will appear in lower-powered, smaller chips that will not be the stock in trade of hyperscale for some time, instead adding compute power to the "edge" -- where compute will be more heterogeneous and more constrained than the infinite, homogeneous scale out of hyperscale.

That last is the future explosive growth of cloud over the next five to ten years, and it includes places we know about but the outside world only vaguely. Space is the edge: constrained, heterogeneous, with satelite and orbital data centers coming within the decade. Industrial automation is the edge: assembly lines are constrained, heterogeneous, long using native code systems that constrain democratic labor supply and have not seen the explosion of productivity gained by cloud-native operational practices. Vehicles are moving, small data centers, as are ships, planes, buses, trains, cell towers, billboards, and so on.

Distributed application development methods must become simpler in order to scale out developer impact and scope; we know it's too hard for most people to choose not only stacks, but _combinations of composed stacks_ in order to build what they need, and of course select clouds that have proprietary but public APIs to consume. It's all so hard that bigger companies now build [custom developer experience platforms](https://redmonk.com/sogrady/2020/10/06/developer-experience-gap/) _on_ public clouds instead of using those clouds' platforms.

wasi-cloud is a strait-forward attempt to see if ~80% of the cloud native APIs can be modeled in Wasm component interfaces compiled to the WebAssembly System Interface or WASI specification. If so, the developer experience could take a step _backward into tight productivity_, with quick development feedback loops while removing the domain specific cloud knowledge currently required. Enabling developers to build apps and ops teams to deploy them with radically separated fields of expertise.

## Structure
## Repository Structure
- `/wit`: the wasi-cloud specification written in `*.wit` format (see [WIT](https://github.com/bytecodealliance/wit-bindgen/blob/main/WIT.md))
- `/src`: the wasi-cloud host cli
- `/crates`: host implementation
- `/crates`: service implementations
- `/examples`: guest examples
- `/tests`: guest tests

## Looking for Contributors
Do you want to contribute to WASI-Cloud's growth?

<p align="center">Start with our <a href="https://github.com/deislabs/wasi-cloud/blob/main/CONTRIBUTING.md">CONTRIBUTING.md</a></p>

## Build
- Run `make build`

Expand Down
6 changes: 3 additions & 3 deletions crates/kv-azure-blob/src/azure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use azure_storage_blobs::prelude::BlobClient;
use bytes::Bytes;
use std::sync::Arc;

/// get the value given blob_client
/// Get the value given a `blob_client`
pub async fn get(blob_client: Arc<BlobClient>) -> Result<Vec<u8>> {
let res = blob_client
.get()
Expand All @@ -13,7 +13,7 @@ pub async fn get(blob_client: Arc<BlobClient>) -> Result<Vec<u8>> {
Ok(Bytes::from(res.data.to_vec()).to_vec())
}

/// set the value given blob_client and value
/// Set the value given a `blob_client` and `value`
pub async fn set(blob_client: Arc<BlobClient>, value: Vec<u8>) -> Result<()> {
blob_client
.put_block_blob(value)
Expand All @@ -24,7 +24,7 @@ pub async fn set(blob_client: Arc<BlobClient>, value: Vec<u8>) -> Result<()> {
Ok(())
}

/// delete the value given blob_client
/// Delete the `value` given a `blob_client`
pub async fn delete(blob_client: Arc<BlobClient>) -> Result<()> {
blob_client
.delete()
Expand Down
18 changes: 7 additions & 11 deletions crates/kv-azure-blob/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,16 @@ wit_error_rs::impl_from!(anyhow::Error, Error::ErrorWithDescription);

const SCHEME_NAME: &str = "azblobkv";

/// A Azure Blob Storage binding for kv interface.
/// A Azure Blob Storage implementation for the kv interface
#[derive(Default, Clone, Resource, RuntimeResource)]
pub struct KvAzureBlob {
inner: Option<Arc<ContainerClient>>,
resource_map: Option<ResourceMap>,
}

impl KvAzureBlob {
/// Create a new KvAzureBlob.
pub fn new(
storage_account_name: &str,
storage_account_key: &str,
container_name: &str,
) -> Self {
/// Create a new `KvAzureBlob`
fn new(storage_account_name: &str, storage_account_key: &str, container_name: &str) -> Self {
let http_client = azure_core::new_http_client();
let inner = Some(
StorageAccountClient::new_access_key(
Expand All @@ -50,7 +46,7 @@ impl KvAzureBlob {
}

impl kv::Kv for KvAzureBlob {
/// Construct a new KvAzureBlob from container name. For example, A container name could be "my-container".
/// Construct a new `KvAzureBlob` from a container name. For example, a container name could be "my-container"
fn get_kv(&mut self, name: &str) -> Result<ResourceDescriptorResult, Error> {
let storage_account_name = std::env::var("AZURE_STORAGE_ACCOUNT")
.with_context(|| "failed to read AZURE_STORAGE_ACCOUNT environment variable")?;
Expand All @@ -67,7 +63,7 @@ impl kv::Kv for KvAzureBlob {
Ok(rd)
}

/// Output the value of a set key.
/// Output the value of a set key
fn get(&mut self, rd: ResourceDescriptorParam, key: &str) -> Result<PayloadResult, Error> {
Uuid::parse_str(rd).with_context(|| "failed to parse resource descriptor")?;

Expand All @@ -79,7 +75,7 @@ impl kv::Kv for KvAzureBlob {
Ok(res)
}

/// Create a key-value pair.
/// Create a key-value pair
fn set(
&mut self,
rd: ResourceDescriptorParam,
Expand All @@ -97,7 +93,7 @@ impl kv::Kv for KvAzureBlob {
Ok(())
}

/// Delete a key-value pair.
/// Delete a key-value pair
fn delete(&mut self, rd: ResourceDescriptorParam, key: &str) -> Result<(), Error> {
Uuid::parse_str(rd).with_context(|| "failed to parse resource descriptor")?;

Expand Down
11 changes: 6 additions & 5 deletions crates/kv-filesystem/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,16 @@ wit_error_rs::impl_from!(anyhow::Error, Error::ErrorWithDescription);

const SCHEME_NAME: &str = "filekv";

/// A Filesystem implementation for kv interface.
/// A Filesystem implementation for the kv interface
#[derive(Default, Clone, Resource, RuntimeResource)]
pub struct KvFilesystem {
/// The root directory of the filesystem.
/// The root directory of the filesystem
inner: Option<String>,
resource_map: Option<ResourceMap>,
}

impl kv::Kv for KvFilesystem {
/// Contruct a new `KvFilesystem` from a folder name. This folder will be created under `/tmp`
fn get_kv(&mut self, name: &str) -> Result<ResourceDescriptorResult, Error> {
let path = Path::new("/tmp").join(name);
let path = path
Expand All @@ -42,7 +43,7 @@ impl kv::Kv for KvFilesystem {
Ok(rd)
}

/// Output the value of a set key.
/// Output the value of a set key
fn get(&mut self, rd: ResourceDescriptorParam, key: &str) -> Result<PayloadResult, Error> {
Uuid::parse_str(rd).with_context(|| "failed to parse resource descriptor")?;

Expand All @@ -59,7 +60,7 @@ impl kv::Kv for KvFilesystem {
Ok(buf)
}

/// Create a key-value pair.
/// Create a key-value pair
fn set(
&mut self,
rd: ResourceDescriptorParam,
Expand All @@ -82,7 +83,7 @@ impl kv::Kv for KvFilesystem {
Ok(())
}

/// Delete a key-value pair.
/// Delete a key-value pair
fn delete(&mut self, rd: ResourceDescriptorParam, key: &str) -> Result<(), Error> {
Uuid::parse_str(rd).with_context(|| "failed to parse resource descriptor")?;

Expand Down
3 changes: 3 additions & 0 deletions crates/lockd-etcd/src/etcd.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
use anyhow::Result;
use etcd_client::{Client, LockOptions, LockResponse};

/// Create a lock
pub async fn lock(client: &mut Client, lock_name: &[u8]) -> Result<Vec<u8>> {
let resp = client.lock(lock_name, None).await?;
Ok(resp.key().to_vec())
}

/// Create a lease
pub async fn lease_grant(client: &mut Client, ttl: i64) -> Result<i64> {
let resp = client.lease_grant(ttl, None).await?;
Ok(resp.id())
}

/// Create a lock with a time to live (i.e., a lease)
pub async fn lock_with_lease(
client: &mut Client,
lock_name: &[u8],
Expand Down
10 changes: 8 additions & 2 deletions crates/lockd-etcd/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ mod etcd;

const SCHEME_NAME: &str = "etcdlockd";

/// An etcd implementation for the lockd (i.e., distributed locking) Interface
#[derive(Default, Clone, Resource, RuntimeResource)]
pub struct LockdEtcd {
inner: Option<Arc<Mutex<Client>>>,
resource_map: Option<ResourceMap>,
}

impl LockdEtcd {
/// Create a new `LockdEtcd`
fn new(endpoint: &str) -> Self {
let client = block_on(Client::connect([endpoint], None))
.with_context(|| "failed to connect to etcd server")
Expand All @@ -40,6 +42,7 @@ impl LockdEtcd {
}

impl lockd::Lockd for LockdEtcd {
/// Construct a new `LockdEtcd` instance
fn get_lockd(&mut self, name: &str) -> Result<ResourceDescriptorResult, Error> {
let etcd_lockd = Self::new(name);
self.inner = etcd_lockd.inner;
Expand All @@ -51,6 +54,7 @@ impl lockd::Lockd for LockdEtcd {
Ok(rd)
}

/// Create a lock without a time to live
fn lock(
&mut self,
rd: ResourceDescriptorParam,
Expand All @@ -66,6 +70,7 @@ impl lockd::Lockd for LockdEtcd {
Ok(pr)
}

/// Create a lock with a time to live. Once the time to live runs out, the lock is no longer locking
fn lock_with_time_to_live(
&mut self,
rd: ResourceDescriptorParam,
Expand All @@ -86,6 +91,7 @@ impl lockd::Lockd for LockdEtcd {
Ok(pr)
}

/// Unlock a lock
fn unlock(
&mut self,
rd: ResourceDescriptorParam,
Expand All @@ -96,8 +102,8 @@ impl lockd::Lockd for LockdEtcd {
let map = Map::lock(&mut self.resource_map)?;
let inner = map.get::<Arc<Mutex<Client>>>(rd)?;

let pr = block_on(etcd::unlock(&mut inner.lock().unwrap(), lock_key))
block_on(etcd::unlock(&mut inner.lock().unwrap(), lock_key))
.with_context(|| "failed to unlock")?;
Ok(pr)
Ok(())
}
}
2 changes: 2 additions & 0 deletions crates/mq-azure-servicebus/src/azure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ use anyhow::{bail, Result};
use azure_messaging_servicebus::prelude::*;
use chrono::Duration;

// Send a message
pub async fn send(client: &mut Client, msg: String) -> Result<()> {
client.send_message(&msg).await?;
Ok(())
}

// Receive a message
pub async fn receive(client: &mut Client) -> Result<Vec<u8>> {
let peek_lock = client
.peek_lock_message2(Some(Duration::seconds(60)))
Expand Down
Loading

0 comments on commit 8091917

Please sign in to comment.