Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added examples/test_program.zip
Binary file not shown.
301 changes: 153 additions & 148 deletions src/aleph_client/asynchronous.py

Large diffs are not rendered by default.

Empty file.
105 changes: 50 additions & 55 deletions src/aleph_client/commands/message.py
Original file line number Diff line number Diff line change
@@ -1,56 +1,51 @@
import asyncio
import json
import os.path
import subprocess
from typing import Optional, Dict, List
from pathlib import Path
import tempfile
import asyncio
from pathlib import Path
from typing import Optional, Dict, List

import typer

from aleph_message.models import (
PostMessage,
ForgetMessage,
AlephMessage,
)


from aleph_client import synchronous
from aleph_client.commands import help_strings
from aleph_client.types import AccountFromPrivateKey
from aleph_client.account import _load_account
from aleph_client.conf import settings

from aleph_client.asynchronous import (
get_fallback_session,
StorageEnum,
)

from aleph_client.commands import help_strings
from aleph_client.commands.utils import (
setup_logging,
input_multiline,
)

from aleph_client.conf import settings
from aleph_client.types import AccountFromPrivateKey

app = typer.Typer()


@app.command()
def post(
path: Optional[Path] = typer.Option(
None,
help="Path to the content you want to post. If omitted, you can input your content directly",
),
type: str = typer.Option("test", help="Text representing the message object type"),
ref: Optional[str] = typer.Option(None, help=help_strings.REF),
channel: str = typer.Option(settings.DEFAULT_CHANNEL, help=help_strings.CHANNEL),
private_key: Optional[str] = typer.Option(
settings.PRIVATE_KEY_STRING, help=help_strings.PRIVATE_KEY
),
private_key_file: Optional[Path] = typer.Option(
settings.PRIVATE_KEY_FILE, help=help_strings.PRIVATE_KEY_FILE
),
debug: bool = False,
path: Optional[Path] = typer.Option(
None,
help="Path to the content you want to post. If omitted, you can input your content directly",
),
type: str = typer.Option("test", help="Text representing the message object type"),
ref: Optional[str] = typer.Option(None, help=help_strings.REF),
channel: str = typer.Option(settings.DEFAULT_CHANNEL, help=help_strings.CHANNEL),
private_key: Optional[str] = typer.Option(
settings.PRIVATE_KEY_STRING, help=help_strings.PRIVATE_KEY
),
private_key_file: Optional[Path] = typer.Option(
settings.PRIVATE_KEY_FILE, help=help_strings.PRIVATE_KEY_FILE
),
debug: bool = False,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same goes for formatting here

):
"""Post a message on Aleph.im."""

Expand Down Expand Up @@ -104,14 +99,14 @@ def post(

@app.command()
def amend(
hash: str = typer.Argument(..., help="Hash reference of the message to amend"),
private_key: Optional[str] = typer.Option(
settings.PRIVATE_KEY_STRING, help=help_strings.PRIVATE_KEY
),
private_key_file: Optional[Path] = typer.Option(
settings.PRIVATE_KEY_FILE, help=help_strings.PRIVATE_KEY_FILE
),
debug: bool = False,
hash: str = typer.Argument(..., help="Hash reference of the message to amend"),
private_key: Optional[str] = typer.Option(
settings.PRIVATE_KEY_STRING, help=help_strings.PRIVATE_KEY
),
private_key_file: Optional[Path] = typer.Option(
settings.PRIVATE_KEY_FILE, help=help_strings.PRIVATE_KEY_FILE
),
debug: bool = False,
):
"""Amend an existing Aleph message."""

Expand Down Expand Up @@ -149,10 +144,10 @@ def amend(


def forget_messages(
account: AccountFromPrivateKey,
hashes: List[str],
reason: Optional[str],
channel: str,
account: AccountFromPrivateKey,
hashes: List[str],
reason: Optional[str],
channel: str,
):
try:
result: ForgetMessage = synchronous.forget(
Expand All @@ -169,20 +164,20 @@ def forget_messages(

@app.command()
def forget(
hashes: str = typer.Argument(
..., help="Comma separated list of hash references of messages to forget"
),
reason: Optional[str] = typer.Option(
None, help="A description of why the messages are being forgotten."
),
channel: str = typer.Option(settings.DEFAULT_CHANNEL, help=help_strings.CHANNEL),
private_key: Optional[str] = typer.Option(
settings.PRIVATE_KEY_STRING, help=help_strings.PRIVATE_KEY
),
private_key_file: Optional[Path] = typer.Option(
settings.PRIVATE_KEY_FILE, help=help_strings.PRIVATE_KEY_FILE
),
debug: bool = False,
hashes: str = typer.Argument(
..., help="Comma separated list of hash references of messages to forget"
),
reason: Optional[str] = typer.Option(
None, help="A description of why the messages are being forgotten."
),
channel: str = typer.Option(settings.DEFAULT_CHANNEL, help=help_strings.CHANNEL),
private_key: Optional[str] = typer.Option(
settings.PRIVATE_KEY_STRING, help=help_strings.PRIVATE_KEY
),
private_key_file: Optional[Path] = typer.Option(
settings.PRIVATE_KEY_FILE, help=help_strings.PRIVATE_KEY_FILE
),
debug: bool = False,
):
"""Forget an existing Aleph message."""

Expand All @@ -196,9 +191,9 @@ def forget(

@app.command()
def watch(
ref: str = typer.Argument(..., help="Hash reference of the message to watch"),
indent: Optional[int] = typer.Option(None, help="Number of indents to use"),
debug: bool = False,
ref: str = typer.Argument(..., help="Hash reference of the message to watch"),
indent: Optional[int] = typer.Option(None, help="Number of indents to use"),
debug: bool = False,
):
"""Watch a hash for amends and print amend hashes"""

Expand All @@ -207,6 +202,6 @@ def watch(
original: AlephMessage = synchronous.get_message(item_hash=ref)

for message in synchronous.watch_messages(
refs=[ref], addresses=[original.content.address]
refs=[ref], addresses=[original.content.address]
):
typer.echo(f"{message.json(indent=indent)}")
165 changes: 102 additions & 63 deletions src/aleph_client/commands/program.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,3 @@
import typer
from typing import Optional, Dict, List
from aleph_client.types import AccountFromPrivateKey
from aleph_client.account import _load_account
from aleph_client.conf import settings
from pathlib import Path
import asyncio
from aleph_client import synchronous
import json
from zipfile import BadZipFile
from aleph_client.commands import help_strings

import asyncio
import json
import logging
Expand All @@ -19,19 +7,18 @@
from zipfile import BadZipFile

import typer
from aleph_message.models import (
ProgramMessage,
StoreMessage,
)

from aleph_client.types import AccountFromPrivateKey
from aleph_client import synchronous
from aleph_client.account import _load_account
from aleph_client.commands import help_strings
from aleph_client.commands.utils import volume_to_dict
from aleph_client.conf import settings
from aleph_client.types import AccountFromPrivateKey
from aleph_client.utils import create_archive

logger = logging.getLogger(__name__)
app = typer.Typer()


from aleph_client.asynchronous import (
get_fallback_session,
StorageEnum,
Expand All @@ -56,35 +43,67 @@

@app.command()
def upload(
path: Path = typer.Argument(..., help="Path to your source code"),
entrypoint: str = typer.Argument(..., help="Your program entrypoint"),
channel: str = typer.Option(settings.DEFAULT_CHANNEL, help=help_strings.CHANNEL),
memory: int = typer.Option(
settings.DEFAULT_VM_MEMORY, help="Maximum memory allocation on vm in MiB"
),
vcpus: int = typer.Option(
settings.DEFAULT_VM_VCPUS, help="Number of virtual cpus to allocate."
),
timeout_seconds: float = typer.Option(
settings.DEFAULT_VM_TIMEOUT,
help="If vm is not called after [timeout_seconds] it will shutdown",
),
private_key: Optional[str] = typer.Option(
settings.PRIVATE_KEY_STRING, help=help_strings.PRIVATE_KEY
),
private_key_file: Optional[Path] = typer.Option(
settings.PRIVATE_KEY_FILE, help=help_strings.PRIVATE_KEY_FILE
),
print_messages: bool = typer.Option(False),
print_code_message: bool = typer.Option(False),
print_program_message: bool = typer.Option(False),
runtime: str = typer.Option(
None,
help="Hash of the runtime to use for your program. Defaults to aleph debian with Python3.8 and node. You can also create your own runtime and pin it",
),
beta: bool = typer.Option(False),
debug: bool = False,
persistent: bool = False,
path: Path = typer.Argument(..., help="Path to your source code"),
entrypoint: str = typer.Argument(..., help="Your program entrypoint"),
channel: str = typer.Option(settings.DEFAULT_CHANNEL, help=help_strings.CHANNEL),
memory: int = typer.Option(
settings.DEFAULT_VM_MEMORY, help="Maximum memory allocation on vm in MiB"
),
allow_amend: bool = typer.Option(False, help='Deployed VM image may be changed and deployed on the same URL'),
use_latest: bool = typer.Option(True, help='Use latest version of the base docker image'),
reproducible: bool = typer.Option(False, help=' (Not Implemented)--> Check output is same for other nodes'),
internet: bool = typer.Option(True, help='VM should have internet connectivity'),
aleph_api: bool = typer.Option(True, help='VM needs access to Aleph messages AP'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
aleph_api: bool = typer.Option(True, help='VM needs access to Aleph messages AP'),
aleph_api: bool = typer.Option(True, help='VM needs access to Aleph messages'),

vcpus: int = typer.Option(
settings.DEFAULT_VM_VCPUS, help="Number of virtual CPUS to allocate."
),
timeout_seconds: float = typer.Option(
settings.DEFAULT_VM_TIMEOUT,
help="If vm is not called after [timeout_seconds] it will shutdown",
),
private_key: Optional[str] = typer.Option(
settings.PRIVATE_KEY_STRING, help=help_strings.PRIVATE_KEY
),
private_key_file: Optional[Path] = typer.Option(
settings.PRIVATE_KEY_FILE, help=help_strings.PRIVATE_KEY_FILE
),
print_messages: bool = typer.Option(False),
print_code_message: bool = typer.Option(False),
print_program_message: bool = typer.Option(False),
runtime: str = typer.Option(
None,
help="Hash of the runtime to use for your program. Defaults to aleph debian with Python3.8 and node. You can also create your own runtime and pin it",
),
beta: bool = typer.Option(False),

debug: bool = False,
persistent: bool = False,
persistent_volume: Optional[List[str]] = typer.Option(
None,
help='''Takes 3 parameters
A persistent volume is allocated on the host machine at any time
eg: Use , to seperate the parameters and no spaces
--persistent_volume persistence=host,name=my-volume,size=100 ./my-program main:app
'''),

ephemeral_volume: Optional[List[str]] = typer.Option(
None,
help=
'''Takes 1 parameter Only
Ephemeral volumes can move and be removed by the host,Garbage collected basically, when the VM isn't running
eg: Use , to seperate the parameters and no spaces
--ephemeral-volume size_mib=100 ./my-program main:app '''),

immutable_volume: Optional[List[str]] = typer.Option(
None,
help=
'''Takes 3 parameters
Immutable volume is one whose contents do not change
eg: Use , to seperate the parameters and no spaces
--immutable-volume ref=25a393222692c2f73489dc6710ae87605a96742ceef7b91de4d7ec34bb688d94,use_latest=true,mount=/mnt/volume ./my-program main:app
'''
)

):
"""Register a program to run on Aleph.im virtual machines from a zip archive."""

Expand All @@ -104,15 +123,30 @@ def upload(
account: AccountFromPrivateKey = _load_account(private_key, private_key_file)

runtime = (
runtime
or input(f"Ref of runtime ? [{settings.DEFAULT_RUNTIME_ID}] ")
or settings.DEFAULT_RUNTIME_ID
runtime
or input(f"Ref of runtime ? [{settings.DEFAULT_RUNTIME_ID}] ")
or settings.DEFAULT_RUNTIME_ID
)

volumes = []
for volume in prompt_for_volumes():
volumes.append(volume)
typer.echo("\n")

# Check if the volumes are empty
if persistent_volume is None or ephemeral_volume is None or immutable_volume is None:
for volume in prompt_for_volumes():
volumes.append(volume)
typer.echo("\n")

# else Parse all the volumes that have passed as the cli parameters and put it into volume list
else:
if len(persistent_volume) > 0:
persistent_volume_dict = volume_to_dict(volume=persistent_volume)
volumes.append(persistent_volume_dict)
if len(ephemeral_volume) > 0:
ephemeral_volume_dict = volume_to_dict(volume=ephemeral_volume)
volumes.append(ephemeral_volume_dict)
if len(immutable_volume) > 0:
immutable_volume_dict = volume_to_dict(volume=immutable_volume)
volumes.append(immutable_volume_dict)

subscriptions: Optional[List[Dict]]
if beta and yes_no_input("Subscribe to messages ?", default=False):
Expand Down Expand Up @@ -156,6 +190,11 @@ def upload(
program_ref=program_ref,
entrypoint=entrypoint,
runtime=runtime,
allow_amend=allow_amend,
use_latest=use_latest,
reproducible=reproducible,
internet=internet,
aleph_api=aleph_api,
storage_engine=StorageEnum.storage,
channel=channel,
memory=memory,
Expand Down Expand Up @@ -189,12 +228,12 @@ def upload(

@app.command()
def update(
hash: str,
path: Path,
private_key: Optional[str] = settings.PRIVATE_KEY_STRING,
private_key_file: Optional[Path] = settings.PRIVATE_KEY_FILE,
print_message: bool = True,
debug: bool = False,
hash: str,
path: Path,
private_key: Optional[str] = settings.PRIVATE_KEY_STRING,
private_key_file: Optional[Path] = settings.PRIVATE_KEY_FILE,
print_message: bool = True,
debug: bool = False,
):
"""Update the code of an existing program"""

Expand Down Expand Up @@ -252,10 +291,10 @@ def update(

@app.command()
def unpersist(
hash: str,
private_key: Optional[str] = settings.PRIVATE_KEY_STRING,
private_key_file: Optional[Path] = settings.PRIVATE_KEY_FILE,
debug: bool = False,
hash: str,
private_key: Optional[str] = settings.PRIVATE_KEY_STRING,
private_key_file: Optional[Path] = settings.PRIVATE_KEY_FILE,
debug: bool = False,
):
"""Stop a persistent virtual machine by making it non-persistent"""

Expand Down
Loading