Merge pull request #5 from plurigrid/cosmonic

Cosmonic wasmCloud via nix shell, improving dev experience: tested on aarch64
This commit is contained in:
barton ⊛ 2023-05-24 04:11:22 +00:00 committed by GitHub
commit 74ac17d3ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 633 additions and 12 deletions

48
README.md Normal file
View file

@ -0,0 +1,48 @@
Here is the complete set of instructions:
1. Clone the Nexus repository
```bash
git clone https://github.com/nexus
```
2. Enter the Nexus flox environment
```bash
cd nexus
flox activate
```
This will activate the flox environment defined in the nexus/flox.nix file. This environment has all the necessary dependencies installed to build and run your project.
3. Build and run with cosmo
Now you can use cosmo to build and launch your project:
```bash
cosmo build
cosmo launch
```
**If this is your first run of cosmo**, it will automatically start the tutorial.
**If not your first run**, you can start the tutorial with:
```bash
cosmo tutorial hello
```
4. Explaining the components
- flox is a tool for managing declarative Nix-based environments. The nexus/flox.nix file defines an environment with all the dependencies for your project.
- cosmo is a tool for building and deploying WebAssembly actors. You use it to build and launch your actor from within the flox environment.
- Nix is a purely functional package manager that is used by flox to define environments.
5. Installation (if not already completed)
Follow the instructions to install flox and configure your system to use it. This will install the necessary tools to get started with the Nexus project.
- Install Nix (if not already installed)
- Install flox
You now have all the necessary components installed and configured to build and run the Nexus project! Let me know if you have any other questions.

37
cosmo-overlay.nix Normal file
View file

@ -0,0 +1,37 @@
self: super:
{
cosmo = super.stdenv.mkDerivation rec {
pname = "cosmo";
version = "1.0.0";
src = super.fetchurl {
url = "https://cosmonic.sh/install.sh";
sha256 = "1961f948b184b31a820a68c01388d7c8e2e21c47285b63407de07a774b60b7f8";
};
buildInputs = [ super.curl super.cacert super.which ];
phases = [ "installPhase" ];
installPhase = ''
mkdir -p $out/bin
cp $src $out/bin/cosmo
chmod +x $out/bin/cosmo
# Replace 'curl' with the absolute path to the curl binary from the Nix store
sed -i 's|curl|${super.curl}/bin/curl|g' $out/bin/cosmo
# Replace 'which' with the absolute path to the which binary from the Nix store
sed -i 's|which|${super.which}/bin/which|g' $out/bin/cosmo
# Set the installation directory to $out/bin
export COSMO_INSTALL_DIR=$out/bin
# Replace the original installation directory with $out/bin
sed -i 's|~/.cosmo/bin|$out/bin|g' $out/bin/cosmo
# Run the modified installation script
bash $out/bin/cosmo
'';
};
}

3
myapp/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
application.zip
src/main/application/security/
.idea/

13
myapp/README.md Normal file
View file

@ -0,0 +1,13 @@
<!-- Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
![Vespa logo](https://vespa.ai/assets/vespa-logo-color.png)
# Vespa sample applications - Album Recommendations
A simple Vespa application which can be deployed on one node,
and does search and recommendation in music data.
Follow
[vespa quick start guide](https://docs.vespa.ai/en/vespa-quick-start.html)
to deploy this.

View file

@ -0,0 +1,15 @@
{
"put": "id:mynamespace:music::a-head-full-of-dreams",
"fields": {
"album": "A Head Full of Dreams",
"artist": "Coldplay",
"year": 2015,
"category_scores": {
"cells": [
{ "address" : { "cat" : "pop" }, "value": 1 },
{ "address" : { "cat" : "rock" }, "value": 0.2 },
{ "address" : { "cat" : "jazz" }, "value": 0 }
]
}
}
}

View file

@ -0,0 +1,16 @@
{
"put": "id:mynamespace:music::hardwired-to-self-destruct",
"fields": {
"album": "Hardwired...To Self-Destruct",
"artist": "Metallica",
"year": 2016,
"category_scores": {
"cells": [
{ "address" : { "cat" : "pop" }, "value": 0 },
{ "address" : { "cat" : "rock" }, "value": 1 },
{ "address" : { "cat" : "jazz" }, "value": 0 }
]
}
}
}

View file

@ -0,0 +1,15 @@
{
"put": "id:mynamespace:music::liebe-ist-für-alle-da",
"fields": {
"album": "Liebe ist für alle da",
"artist": "Rammstein",
"year": 2009,
"category_scores": {
"cells": [
{ "address" : { "cat" : "pop" }, "value": 0.1 },
{ "address" : { "cat" : "rock" }, "value": 1.0 },
{ "address" : { "cat" : "jazz" }, "value": 0 }
]
}
}
}

View file

@ -0,0 +1,16 @@
{
"put": "id:mynamespace:music::love-is-here-to-stay",
"fields": {
"album": "Love Is Here To Stay",
"artist": "Diana Krall",
"year": 2018,
"category_scores": {
"cells": [
{ "address" : { "cat" : "pop" }, "value": 0.4 },
{ "address" : { "cat" : "rock" }, "value": 0 },
{ "address" : { "cat" : "jazz" }, "value": 0.8 }
]
}
}
}

View file

@ -0,0 +1,15 @@
{
"put": "id:mynamespace:music::when-we-all-fall-asleep-where-do-we-go",
"fields": {
"album": "When We All Fall Asleep, Where Do We Go?",
"artist": "Billie Eilish",
"year": 2019,
"category_scores": {
"cells": [
{ "address" : { "cat" : "pop" }, "value": 1.0 },
{ "address" : { "cat" : "rock" }, "value": 0 },
{ "address" : { "cat" : "jazz" }, "value": 0.1 }
]
}
}
}

View file

@ -0,0 +1,5 @@
{ "put": "id:mynamespace:music::a-head-full-of-dreams", "fields": { "album": "A Head Full of Dreams", "artist": "Coldplay", "year": 2015, "category_scores": { "cells": [ { "address" : { "cat" : "pop" }, "value": 1 }, { "address" : { "cat" : "rock" }, "value": 0.2 }, { "address" : { "cat" : "jazz" }, "value": 0 } ] } }}
{ "put": "id:mynamespace:music::hardwired-to-self-destruct", "fields": { "album": "Hardwired...To Self-Destruct", "artist": "Metallica", "year": 2016, "category_scores": { "cells": [ { "address" : { "cat" : "pop" }, "value": 0 }, { "address" : { "cat" : "rock" }, "value": 1 }, { "address" : { "cat" : "jazz" }, "value": 0 } ] } }}
{ "put": "id:mynamespace:music::liebe-ist-für-alle-da", "fields": { "album": "Liebe ist für alle da", "artist": "Rammstein", "year": 2009, "category_scores": { "cells": [ { "address" : { "cat" : "pop" }, "value": 0.1 }, { "address" : { "cat" : "rock" }, "value": 1.0 }, { "address" : { "cat" : "jazz" }, "value": 0 } ] } }}
{ "put": "id:mynamespace:music::love-is-here-to-stay", "fields": { "album": "Love Is Here To Stay", "artist": "Diana Krall", "year": 2018, "category_scores": { "cells": [ { "address" : { "cat" : "pop" }, "value": 0.4 }, { "address" : { "cat" : "rock" }, "value": 0 }, { "address" : { "cat" : "jazz" }, "value": 0.8 } ] } }}
{ "put": "id:mynamespace:music::when-we-all-fall-asleep-where-do-we-go", "fields": { "album": "When We All Fall Asleep, Where Do We Go?", "artist": "Billie Eilish", "year": 2019, "category_scores": { "cells": [ { "address" : { "cat" : "pop" }, "value": 1.0 }, { "address" : { "cat" : "rock" }, "value": 0 }, { "address" : { "cat" : "jazz" }, "value": 0.1 } ] } }}

3
myapp/myapp/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
application.zip
src/main/application/security/
.idea/

13
myapp/myapp/README.md Normal file
View file

@ -0,0 +1,13 @@
<!-- Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
![Vespa logo](https://vespa.ai/assets/vespa-logo-color.png)
# Vespa sample applications - Album Recommendations
A simple Vespa application which can be deployed on one node,
and does search and recommendation in music data.
Follow
[vespa quick start guide](https://docs.vespa.ai/en/vespa-quick-start.html)
to deploy this.

View file

@ -0,0 +1,15 @@
{
"put": "id:mynamespace:music::a-head-full-of-dreams",
"fields": {
"album": "A Head Full of Dreams",
"artist": "Coldplay",
"year": 2015,
"category_scores": {
"cells": [
{ "address" : { "cat" : "pop" }, "value": 1 },
{ "address" : { "cat" : "rock" }, "value": 0.2 },
{ "address" : { "cat" : "jazz" }, "value": 0 }
]
}
}
}

View file

@ -0,0 +1,16 @@
{
"put": "id:mynamespace:music::hardwired-to-self-destruct",
"fields": {
"album": "Hardwired...To Self-Destruct",
"artist": "Metallica",
"year": 2016,
"category_scores": {
"cells": [
{ "address" : { "cat" : "pop" }, "value": 0 },
{ "address" : { "cat" : "rock" }, "value": 1 },
{ "address" : { "cat" : "jazz" }, "value": 0 }
]
}
}
}

View file

@ -0,0 +1,15 @@
{
"put": "id:mynamespace:music::liebe-ist-für-alle-da",
"fields": {
"album": "Liebe ist für alle da",
"artist": "Rammstein",
"year": 2009,
"category_scores": {
"cells": [
{ "address" : { "cat" : "pop" }, "value": 0.1 },
{ "address" : { "cat" : "rock" }, "value": 1.0 },
{ "address" : { "cat" : "jazz" }, "value": 0 }
]
}
}
}

View file

@ -0,0 +1,16 @@
{
"put": "id:mynamespace:music::love-is-here-to-stay",
"fields": {
"album": "Love Is Here To Stay",
"artist": "Diana Krall",
"year": 2018,
"category_scores": {
"cells": [
{ "address" : { "cat" : "pop" }, "value": 0.4 },
{ "address" : { "cat" : "rock" }, "value": 0 },
{ "address" : { "cat" : "jazz" }, "value": 0.8 }
]
}
}
}

View file

@ -0,0 +1,15 @@
{
"put": "id:mynamespace:music::when-we-all-fall-asleep-where-do-we-go",
"fields": {
"album": "When We All Fall Asleep, Where Do We Go?",
"artist": "Billie Eilish",
"year": 2019,
"category_scores": {
"cells": [
{ "address" : { "cat" : "pop" }, "value": 1.0 },
{ "address" : { "cat" : "rock" }, "value": 0 },
{ "address" : { "cat" : "jazz" }, "value": 0.1 }
]
}
}
}

View file

@ -0,0 +1,5 @@
{ "put": "id:mynamespace:music::a-head-full-of-dreams", "fields": { "album": "A Head Full of Dreams", "artist": "Coldplay", "year": 2015, "category_scores": { "cells": [ { "address" : { "cat" : "pop" }, "value": 1 }, { "address" : { "cat" : "rock" }, "value": 0.2 }, { "address" : { "cat" : "jazz" }, "value": 0 } ] } }}
{ "put": "id:mynamespace:music::hardwired-to-self-destruct", "fields": { "album": "Hardwired...To Self-Destruct", "artist": "Metallica", "year": 2016, "category_scores": { "cells": [ { "address" : { "cat" : "pop" }, "value": 0 }, { "address" : { "cat" : "rock" }, "value": 1 }, { "address" : { "cat" : "jazz" }, "value": 0 } ] } }}
{ "put": "id:mynamespace:music::liebe-ist-für-alle-da", "fields": { "album": "Liebe ist für alle da", "artist": "Rammstein", "year": 2009, "category_scores": { "cells": [ { "address" : { "cat" : "pop" }, "value": 0.1 }, { "address" : { "cat" : "rock" }, "value": 1.0 }, { "address" : { "cat" : "jazz" }, "value": 0 } ] } }}
{ "put": "id:mynamespace:music::love-is-here-to-stay", "fields": { "album": "Love Is Here To Stay", "artist": "Diana Krall", "year": 2018, "category_scores": { "cells": [ { "address" : { "cat" : "pop" }, "value": 0.4 }, { "address" : { "cat" : "rock" }, "value": 0 }, { "address" : { "cat" : "jazz" }, "value": 0.8 } ] } }}
{ "put": "id:mynamespace:music::when-we-all-fall-asleep-where-do-we-go", "fields": { "album": "When We All Fall Asleep, Where Do We Go?", "artist": "Billie Eilish", "year": 2019, "category_scores": { "cells": [ { "address" : { "cat" : "pop" }, "value": 1.0 }, { "address" : { "cat" : "rock" }, "value": 0 }, { "address" : { "cat" : "jazz" }, "value": 0.1 } ] } }}

View file

@ -0,0 +1,49 @@
# Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
# A description of a type of data, how to store and index it, and what to compute over the data elements
#
# See:
# - https://docs.vespa.ai/en/schemas.html
schema music {
document music {
field artist type string {
indexing: summary | index
}
field album type string {
indexing: summary | index
index: enable-bm25
}
field year type int {
indexing: summary | attribute
}
field category_scores type tensor<float>(cat{}) {
indexing: summary | attribute
}
}
fieldset default {
fields: artist, album
}
# Rank profiles defines what to compute over the data, and how to use the computation result to order them
# They can be selected at query time (ranking.profile=[name]), and can be everything from simple handwritten
# expressions as below to references to large machine-learned models.
#
# See
# - https://docs.vespa.ai/en/ranking.html
rank-profile rank_albums inherits default {
inputs {
query(user_profile) tensor<float>(cat{})
}
first-phase {
expression: bm25(album) + 0.25 * sum(query(user_profile) * attribute(category_scores))
}
}
}

64
myapp/myapp/services.xml Normal file
View file

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
<services version="1.0" xmlns:deploy="vespa" xmlns:preprocess="properties">
<!--
A container cluster handles incoming requests to the application and processes those requests,
and their results. The processing to do and the API's to expose can be provides by Vespa
or by the application through Java components supplied as part of the application.
See:
- Reference: https://docs.vespa.ai/en/reference/services-container.html
-->
<container id="default" version="1.0">
<!--
<document-api> tells the container that it should accept documents for indexing. Through the
Document REST API you can PUT new documents, UPDATE existing documents, and DELETE documents
already in the cluster.
Documents sent to the Document REST API will be passed through document processors on the way
to the content cluster.
See:
- Reference: https://docs.vespa.ai/en/reference/services-container.html#document-api
- Operations: https://docs.vespa.ai/en/document-v1-api-guide.html
-->
<document-api/>
<!--
<search> tells the container to answers queries and serve results for those queries.
Inside the <search /> cluster you can configure chains of "searchers" -
Java components processing the query and/or result.
See:
- Reference: https://docs.vespa.ai/en/query-api.html
- Searchers: https://docs.vespa.ai/en/searcher-development.html
-->
<search/>
<!--
<nodes> specifies the nodes that should run this cluster.
-->
<nodes>
<node hostalias="node1" />
</nodes>
</container>
<!--
<content/> content clusters store application data, maintain indexes and executes the
distributed parts of a query.
See:
- Reference: https://docs.vespa.ai/en/reference/services-content.html
-->
<content id="music" version="1.0">
<redundancy>2</redundancy>
<documents>
<document type="music" mode="index" />
</documents>
<nodes>
<node hostalias="node1" distribution-key="0" />
</nodes>
</content>
</services>

49
myapp/schemas/music.sd Normal file
View file

@ -0,0 +1,49 @@
# Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
# A description of a type of data, how to store and index it, and what to compute over the data elements
#
# See:
# - https://docs.vespa.ai/en/schemas.html
schema music {
document music {
field artist type string {
indexing: summary | index
}
field album type string {
indexing: summary | index
index: enable-bm25
}
field year type int {
indexing: summary | attribute
}
field category_scores type tensor<float>(cat{}) {
indexing: summary | attribute
}
}
fieldset default {
fields: artist, album
}
# Rank profiles defines what to compute over the data, and how to use the computation result to order them
# They can be selected at query time (ranking.profile=[name]), and can be everything from simple handwritten
# expressions as below to references to large machine-learned models.
#
# See
# - https://docs.vespa.ai/en/ranking.html
rank-profile rank_albums inherits default {
inputs {
query(user_profile) tensor<float>(cat{})
}
first-phase {
expression: bm25(album) + 0.25 * sum(query(user_profile) * attribute(category_scores))
}
}
}

64
myapp/services.xml Normal file
View file

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
<services version="1.0" xmlns:deploy="vespa" xmlns:preprocess="properties">
<!--
A container cluster handles incoming requests to the application and processes those requests,
and their results. The processing to do and the API's to expose can be provides by Vespa
or by the application through Java components supplied as part of the application.
See:
- Reference: https://docs.vespa.ai/en/reference/services-container.html
-->
<container id="default" version="1.0">
<!--
<document-api> tells the container that it should accept documents for indexing. Through the
Document REST API you can PUT new documents, UPDATE existing documents, and DELETE documents
already in the cluster.
Documents sent to the Document REST API will be passed through document processors on the way
to the content cluster.
See:
- Reference: https://docs.vespa.ai/en/reference/services-container.html#document-api
- Operations: https://docs.vespa.ai/en/document-v1-api-guide.html
-->
<document-api/>
<!--
<search> tells the container to answers queries and serve results for those queries.
Inside the <search /> cluster you can configure chains of "searchers" -
Java components processing the query and/or result.
See:
- Reference: https://docs.vespa.ai/en/query-api.html
- Searchers: https://docs.vespa.ai/en/searcher-development.html
-->
<search/>
<!--
<nodes> specifies the nodes that should run this cluster.
-->
<nodes>
<node hostalias="node1" />
</nodes>
</container>
<!--
<content/> content clusters store application data, maintain indexes and executes the
distributed parts of a query.
See:
- Reference: https://docs.vespa.ai/en/reference/services-content.html
-->
<content id="music" version="1.0">
<redundancy>2</redundancy>
<documents>
<document type="music" mode="index" />
</documents>
<nodes>
<node hostalias="node1" distribution-key="0" />
</nodes>
</content>
</services>

View file

@ -1,4 +1,4 @@
{ pkgs ? import <nixpkgs> {} }: { pkgs ? import <nixpkgs> { overlays = [ (import ./vespa-cli-overlay.nix) ]; } }:
pkgs.mkShell { pkgs.mkShell {
buildInputs = with pkgs; [ buildInputs = with pkgs; [
@ -6,8 +6,93 @@ pkgs.mkShell {
cargo cargo
tree tree
poetry poetry
openssl_1_1
vespa-cli
]; ];
shellHook = '' shellHook = ''
# Check if Rust is installed, if not install it
if ! command -v rustc &> /dev/null; then
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
fi
# Check if wasm32-unknown-unknown target is installed, if not install it
if ! rustup target list --installed | grep -q "wasm32-unknown-unknown"; then
rustup target add wasm32-unknown-unknown
fi
# Check if OpenSSL 1.1 is installed
if ! (command -v openssl &> /dev/null && openssl version | grep -q "OpenSSL 1.1"); then
# Check the architecture and install OpenSSL 1.1 if needed
if [[ $(uname -m) == "arm64" ]]; then
if [[ "$OSTYPE" == "darwin"* ]]; then
# MacOS M1 installation
if ! command -v brew &> /dev/null; then
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
fi
export PATH="/opt/homebrew/bin:$PATH"
brew install openssl@1.1
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
# Check for Debian-based system
if grep -qi 'debian' /etc/os-release; then
# Ubuntu ARM installation
apt update && apt install curl -y
curl -s https://packagecloud.io/install/repositories/wasmcloud/core/script.deb.sh | bash
apt install wash
curl -fLO http://ftp.us.debian.org/debian/pool/main/o/openssl/libssl1.1_1.1.1n-0+deb11u4_arm64.deb
dpkg -i libssl1.1_1.1.1n-0+deb11u4_arm64.deb
else
echo "This script is designed for Debian-based systems only."
exit 1
fi
else
echo "Unsupported system type."
exit 1
fi
else
echo "This script is designed for arm64 systems only."
exit 1
fi
fi
# Check if cosmo is installed, if not install it
if ! command -v cosmo &> /dev/null; then
bash -c "$(curl -fsSL https://cosmonic.sh/install.sh)"
# Get the current shell name
current_shell="$(basename ${builtins.getEnv "SHELL"})"
# Update the corresponding configuration file based on the current shell
if [[ "$current_shell" == "bash" ]]; then
cat >> "${builtins.getEnv "HOME"}/.bashrc" <<EOF
export PATH="/Users/test/.cosmo/bin:\${builtins.getEnv "PATH"}"
EOF
source "${builtins.getEnv "HOME"}/.bashrc"
elif [[ "$current_shell" == "zsh" ]]; then
cat >> "${builtins.getEnv "HOME"}/.zshrc" <<EOF
export PATH="/Users/test/.cosmo/bin:\${builtins.getEnv "PATH"}"
EOF
source "${builtins.getEnv "HOME"}/.zshrc"
else
echo "Unsupported shell: $current_shell"
exit 1
fi
fi
cat <<'EOF' cat <<'EOF'
.-. .-.
`-' `-'

29
vespa-cli-overlay.nix Normal file
View file

@ -0,0 +1,29 @@
self: super:
{
vespa-cli = super.stdenv.mkDerivation rec {
pname = "vespa-cli";
version = "8.162.29";
src = super.fetchurl {
url = "https://github.com/vespa-engine/vespa/releases/download/v${version}/vespa-cli_${version}_darwin_arm64.tar.gz";
sha256 = "05cdabe044ac34a74eca66ade3db49b7a1db29c691e7f8bbd1e71ab991548688";
};
buildInputs = [];
nativeBuildInputs = [ super.makeWrapper ];
dontBuild = true;
unpackPhase = ''
tar -xzf $src
'';
installPhase = ''
mkdir -p $out/bin
cp vespa-cli_${version}_darwin_arm64/bin/vespa $out/bin
chmod +x $out/bin/vespa
'';
};
}