This commit is contained in:
22
docs/cfg/footer.json
Normal file
22
docs/cfg/footer.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"style": "dark",
|
||||
"links": [
|
||||
{
|
||||
"title": "Web",
|
||||
"items": [
|
||||
{
|
||||
"label": "ThreeFold.io",
|
||||
"href": "https://threefold.io"
|
||||
},
|
||||
{
|
||||
"href": "https://mycelium.threefold.io/",
|
||||
"label": "Mycelium Network"
|
||||
},
|
||||
{
|
||||
"href": "https://aibox.threefold.io/",
|
||||
"label": "AI Box"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
17
docs/cfg/main.json
Normal file
17
docs/cfg/main.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"title": "ThreeFold HeroScript",
|
||||
"tagline": "ThreeFold HeroScript",
|
||||
"favicon": "img/favicon.png",
|
||||
"url": "https://threefold.info",
|
||||
"url_home": "docs/intro",
|
||||
"baseUrl": "/heroscript/",
|
||||
"image": "img/tf_graph.png",
|
||||
"metadata": {
|
||||
"description": "Internet Infrastructur for Everyone by Everyone, Everywhere.",
|
||||
"image": "https://threefold.info/tfgrid4/img/tf_graph.png",
|
||||
"title": "ThreeFold"
|
||||
},
|
||||
"buildDest":["root@info.ourworld.tf:/root/hero/www/info/heroscript"],
|
||||
"buildDestDev":["root@info.ourworld.tf:/root/hero/www/infodev/heroscript"],
|
||||
"copyright": "ThreeFold"
|
||||
}
|
25
docs/cfg/navbar.json
Normal file
25
docs/cfg/navbar.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"title": "",
|
||||
"logo": {
|
||||
"alt": "ThreeFold Logo",
|
||||
"src": "img/logo.svg",
|
||||
"srcDark": "img/new_logo_tft.png"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"href": "https://threefold.io",
|
||||
"label": "ThreeFold.io",
|
||||
"position": "right"
|
||||
},
|
||||
{
|
||||
"href": "https://mycelium.threefold.io/",
|
||||
"label": "Mycelium Network",
|
||||
"position": "right"
|
||||
},
|
||||
{
|
||||
"href": "https://aibox.threefold.io/",
|
||||
"label": "AI Box",
|
||||
"position": "right"
|
||||
}
|
||||
]
|
||||
}
|
7
docs/docs/intro.md
Normal file
7
docs/docs/intro.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: "intro"
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# HeroScript
|
||||
|
8
docs/docs/sal/_category_.json
Normal file
8
docs/docs/sal/_category_.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"label": "SAL",
|
||||
"position": 6,
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"description": "Tools to work with operating system."
|
||||
}
|
||||
}
|
239
docs/docs/sal/buildah.md
Normal file
239
docs/docs/sal/buildah.md
Normal file
@@ -0,0 +1,239 @@
|
||||
---
|
||||
title: "build containers"
|
||||
sidebar_position: 20
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Container Builder
|
||||
|
||||
The Buildah module provides functions for working with containers and images using the Buildah tool. Buildah helps you create and manage container images.
|
||||
|
||||
## Builder Pattern
|
||||
|
||||
The Buildah module now supports a Builder pattern, which provides a more intuitive and flexible way to work with containers and images.
|
||||
|
||||
### Creating a Builder
|
||||
|
||||
```js
|
||||
// Create a builder with a name and base image
|
||||
let builder = bah_new("my-container", "alpine:latest");
|
||||
|
||||
// Access builder properties
|
||||
let container_id = builder.container_id;
|
||||
let name = builder.name;
|
||||
let image = builder.image;
|
||||
```
|
||||
|
||||
### Builder Methods
|
||||
The Builder object provides the following methods:
|
||||
|
||||
- `run(command)`: Run a command in the container
|
||||
- `run_with_isolation(command, isolation)`: Run a command with specified isolation
|
||||
- `copy(source, dest)`: Copy files into the container
|
||||
- `add(source, dest)`: Add files into the container
|
||||
- `commit(image_name)`: Commit the container to an image
|
||||
- `remove()`: Remove the container
|
||||
- `reset()`: Remove the container and clear the container_id
|
||||
- `config(options)`: Configure container metadata
|
||||
- `set_entrypoint(entrypoint)`: Set the entrypoint for the container
|
||||
- `set_cmd(cmd)`: Set the default command for the container
|
||||
- `debug_mode`: Get or set the debug flag (true/false)
|
||||
- `write_content(content, dest_path)`: Write content to a file in the container
|
||||
- `read_content(source_path)`: Read content from a file in the container
|
||||
- `images()`: List images in local storage
|
||||
- `image_remove(image)`: Remove an image
|
||||
- `image_pull(image, tls_verify)`: Pull an image from a registry
|
||||
- `image_push(image, destination, tls_verify)`: Push an image to a registry
|
||||
- `image_tag(image, new_name)`: Add a tag to an image
|
||||
- `build(tag, context_dir, file, isolation)`: Build an image from a Dockerfile
|
||||
- `build(tag, context_dir, file, isolation)`: Build an image from a Dockerfile
|
||||
|
||||
### Example
|
||||
|
||||
```js
|
||||
// Create a builder
|
||||
let builder = bah_new("my-container", "alpine:latest");
|
||||
|
||||
// Enable debug mode to see command output
|
||||
builder.debug_mode = true;
|
||||
|
||||
// Reset the builder to remove any existing container
|
||||
builder.reset();
|
||||
|
||||
// Create a new container
|
||||
builder = bah_new("my-container", "alpine:latest");
|
||||
|
||||
// Run a command
|
||||
let result = builder.run("echo 'Hello from container'");
|
||||
println(`Command output: ${result.stdout}`);
|
||||
|
||||
// Write content directly to a file in the container
|
||||
let script_content = `#!/bin/sh
|
||||
echo "Hello from startup script"
|
||||
`;
|
||||
builder.write_content(script_content, "/start.sh");
|
||||
builder.run("chmod +x /start.sh");
|
||||
|
||||
// Set the entrypoint for the container
|
||||
builder.set_entrypoint("/start.sh");
|
||||
|
||||
// Add a file
|
||||
file_write("test_file.txt", "Test content");
|
||||
builder.add("test_file.txt", "/");
|
||||
|
||||
// Commit to an image
|
||||
builder.commit("my-custom-image:latest");
|
||||
|
||||
// Clean up
|
||||
builder.remove();
|
||||
delete("test_file.txt");
|
||||
```
|
||||
|
||||
## Image Information
|
||||
|
||||
### Image Properties
|
||||
|
||||
When working with images, you can access the following information:
|
||||
|
||||
- `id`: The unique identifier for the image
|
||||
- `names`: A list of names/tags for the image
|
||||
- `name`: The primary name of the image, or `<none>` if the image has no names
|
||||
- `size`: The size of the image
|
||||
- `created`: When the image was created
|
||||
|
||||
## Builder Methods
|
||||
|
||||
### `bah_new(name, image)`
|
||||
|
||||
Creates a new Builder object for working with a container.
|
||||
|
||||
**Parameters:**
|
||||
- `name` (string): The name to give the container
|
||||
- `image` (string): The name or ID of the image to create the container from
|
||||
|
||||
**Returns:** A Builder object if successful.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Create a new Builder
|
||||
let builder = bah_new("my-container", "alpine:latest");
|
||||
```
|
||||
|
||||
**Notes:**
|
||||
- If a container with the given name already exists, it will be reused instead of creating a new one
|
||||
- The Builder object provides methods for working with the container
|
||||
|
||||
### `reset()`
|
||||
|
||||
Resets a Builder by removing the container and clearing the container_id. This allows you to start fresh with the same Builder object.
|
||||
|
||||
**Returns:** Nothing.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Create a Builder
|
||||
let builder = bah_new("my-container", "alpine:latest");
|
||||
|
||||
// Reset the Builder to remove the container
|
||||
builder.reset();
|
||||
|
||||
// Create a new container with the same name
|
||||
builder = bah_new("my-container", "alpine:latest");
|
||||
```
|
||||
|
||||
### `debug_mode`
|
||||
|
||||
Get or set the debug flag for the Builder. When debug mode is enabled, all buildah commands will output their stdout/stderr, making it easier to debug issues.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Create a Builder
|
||||
let builder = bah_new("my-container", "alpine:latest");
|
||||
|
||||
// Enable debug mode
|
||||
builder.debug_mode = true;
|
||||
|
||||
// Run a command with debug output
|
||||
builder.run("echo 'Hello with debug'");
|
||||
|
||||
// Disable debug mode
|
||||
builder.debug_mode = false;
|
||||
```
|
||||
|
||||
### `set_entrypoint(entrypoint)`
|
||||
|
||||
Sets the entrypoint for the container. The entrypoint is the command that will be executed when the container starts.
|
||||
|
||||
**Parameters:**
|
||||
- `entrypoint` (string): The entrypoint command
|
||||
|
||||
**Returns:** Command result if successful.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Create a Builder
|
||||
let builder = bah_new("my-container", "alpine:latest");
|
||||
|
||||
// Set the entrypoint
|
||||
builder.set_entrypoint("/start.sh");
|
||||
```
|
||||
|
||||
### `set_cmd(cmd)`
|
||||
|
||||
Sets the default command for the container. This is used as arguments to the entrypoint.
|
||||
|
||||
**Parameters:**
|
||||
- `cmd` (string): The default command
|
||||
|
||||
**Returns:** Command result if successful.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Create a Builder
|
||||
let builder = bah_new("my-container", "alpine:latest");
|
||||
|
||||
// Set the default command
|
||||
builder.set_cmd("--verbose");
|
||||
```
|
||||
|
||||
### `write_content(content, dest_path)`
|
||||
|
||||
Writes content to a file in the container.
|
||||
|
||||
**Parameters:**
|
||||
- `content` (string): The content to write
|
||||
- `dest_path` (string): The destination path in the container
|
||||
|
||||
**Returns:** Command result if successful.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Create a Builder
|
||||
let builder = bah_new("my-container", "alpine:latest");
|
||||
|
||||
// Write content to a file
|
||||
let content = "Hello, world!";
|
||||
builder.write_content(content, "/hello.txt");
|
||||
```
|
||||
|
||||
### `read_content(source_path)`
|
||||
|
||||
Reads content from a file in the container.
|
||||
|
||||
**Parameters:**
|
||||
- `source_path` (string): The source path in the container
|
||||
|
||||
**Returns:** The file content as a string if successful.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Create a Builder
|
||||
let builder = bah_new("my-container", "alpine:latest");
|
||||
|
||||
// Write content to a file
|
||||
builder.write_content("Hello, world!", "/hello.txt");
|
||||
|
||||
// Read content from the file
|
||||
let content = builder.read_content("/hello.txt");
|
||||
println(content); // Outputs: Hello, world!
|
||||
```
|
210
docs/docs/sal/git.md
Normal file
210
docs/docs/sal/git.md
Normal file
@@ -0,0 +1,210 @@
|
||||
---
|
||||
title: "git"
|
||||
sidebar_position: 5
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Git
|
||||
|
||||
This module provides HeroScript wrappers for the Git functionality in SAL.
|
||||
|
||||
> **Note:** The constructor for GitTree has been renamed from `new()` to `gittree_new()` to avoid confusion with other constructors. This makes the interface more explicit and less likely to cause naming conflicts.
|
||||
|
||||
## Object-Oriented Design
|
||||
|
||||
The Git module follows an object-oriented design with two main classes:
|
||||
|
||||
1. **GitTree** - Represents a collection of git repositories under a base path
|
||||
- Created with `gittree_new(base_path)`
|
||||
- Methods for listing, finding, and getting repositories
|
||||
|
||||
2. **GitRepo** - Represents a single git repository
|
||||
- Obtained from GitTree's `get()` method
|
||||
- Methods for common git operations: pull, reset, push, commit
|
||||
|
||||
This design allows for a more intuitive and flexible interface, with method chaining for complex operations.
|
||||
|
||||
## Creating a GitTree
|
||||
|
||||
The GitTree object is the main entry point for git operations. It represents a collection of git repositories under a base path.
|
||||
|
||||
```js
|
||||
// Create a new GitTree with a base path
|
||||
let git_tree = gittree_new("/root/code");
|
||||
print(`Created GitTree with base path: /home/user/code`);
|
||||
```
|
||||
|
||||
## Finding Repositories
|
||||
|
||||
### List All Repositories
|
||||
|
||||
```js
|
||||
// List all git repositories under the base path
|
||||
let repos = git_tree.list();
|
||||
print(`Found ${repos.len()} repositories`);
|
||||
|
||||
// Print the repositories
|
||||
for repo in repos {
|
||||
print(` - ${repo}`);
|
||||
}
|
||||
```
|
||||
|
||||
### Find Repositories Matching a Pattern
|
||||
|
||||
```js
|
||||
// Find repositories matching a pattern
|
||||
// Use a wildcard (*) suffix to find multiple matches
|
||||
let matching_repos = git_tree.find("my-project*");
|
||||
print("Matching repositories:");
|
||||
for repo in matching_repos {
|
||||
print(` - ${repo}`);
|
||||
}
|
||||
|
||||
// Find a specific repository (must match exactly one)
|
||||
let specific_repo = git_tree.find("unique-project")[0];
|
||||
print(`Found specific repository: ${specific_repo}`);
|
||||
```
|
||||
|
||||
## Working with Repositories
|
||||
|
||||
### Get Repository Objects
|
||||
|
||||
```js
|
||||
// Get GitRepo objects for repositories matching a pattern
|
||||
let repos = git_tree.get("my-project*");
|
||||
print(`Found ${repos.len()} repositories`);
|
||||
|
||||
// Get a specific repository
|
||||
let repo = git_tree.get("unique-project")[0];
|
||||
print(`Working with repository: ${repo.path()}`);
|
||||
```
|
||||
|
||||
### Clone a Repository
|
||||
|
||||
```js
|
||||
// Clone a repository by URL
|
||||
// This will clone the repository to the base path of the GitTree
|
||||
let repos = git_tree.get("https://github.com/username/repo.git");
|
||||
let repo = repos[0];
|
||||
print(`Repository cloned to: ${repo.path()}`);
|
||||
```
|
||||
|
||||
### Check for Changes
|
||||
|
||||
```js
|
||||
// Check if a repository has uncommitted changes
|
||||
let repo = git_tree.get("my-project")[0];
|
||||
if repo.has_changes() {
|
||||
print("Repository has uncommitted changes");
|
||||
} else {
|
||||
print("Repository is clean");
|
||||
}
|
||||
```
|
||||
|
||||
## Repository Operations
|
||||
|
||||
### Pull Changes
|
||||
|
||||
```js
|
||||
// Pull the latest changes from the remote
|
||||
// This will fail if there are uncommitted changes
|
||||
let repo = git_tree.get("my-project")[0];
|
||||
let result = repo.pull();
|
||||
print("Repository updated successfully");
|
||||
```
|
||||
|
||||
### Reset Local Changes
|
||||
|
||||
```js
|
||||
// Reset any local changes in the repository
|
||||
let repo = git_tree.get("my-project")[0];
|
||||
let result = repo.reset();
|
||||
print("Repository reset successfully");
|
||||
```
|
||||
|
||||
### Commit Changes
|
||||
|
||||
```js
|
||||
// Commit changes in the repository
|
||||
let repo = git_tree.get("my-project")[0];
|
||||
let result = repo.commit("Fix bug in login form");
|
||||
print("Changes committed successfully");
|
||||
```
|
||||
|
||||
### Push Changes
|
||||
|
||||
```js
|
||||
// Push changes to the remote
|
||||
let repo = git_tree.get("my-project")[0];
|
||||
let result = repo.push();
|
||||
print("Changes pushed successfully");
|
||||
```
|
||||
|
||||
## Method Chaining
|
||||
|
||||
The GitRepo methods can be chained together for more complex operations:
|
||||
|
||||
```js
|
||||
// Commit changes and push them to the remote
|
||||
let repo = git_tree.get("my-project")[0];
|
||||
let result = repo.commit("Add new feature").push();
|
||||
print("Changes committed and pushed successfully");
|
||||
|
||||
// Reset local changes, pull the latest changes, and commit new changes
|
||||
let repo = git_tree.get("my-project")[0];
|
||||
let result = repo.reset().pull().commit("Update dependencies");
|
||||
print("Repository updated successfully");
|
||||
```
|
||||
|
||||
## Complete Example
|
||||
|
||||
```js
|
||||
// Create a new GitTree
|
||||
let home_dir = env("HOME");
|
||||
let git_tree = gittree_new(`${home_dir}/code`);
|
||||
|
||||
// Clone a repository
|
||||
let repos = git_tree.get("https://github.com/username/example-repo.git");
|
||||
let repo = repos[0];
|
||||
print(`Cloned repository to: ${repo.path()}`);
|
||||
|
||||
// Make some changes (using OS module functions)
|
||||
let file_path = `${repo.path()}/README.md`;
|
||||
let content = "# Example Repository\n\nThis is an example repository.";
|
||||
write_file(file_path, content);
|
||||
|
||||
// Commit and push the changes
|
||||
let result = repo.commit("Update README.md").push();
|
||||
print("Changes committed and pushed successfully");
|
||||
|
||||
// List all repositories
|
||||
let all_repos = git_tree.list();
|
||||
print("All repositories:");
|
||||
for repo_path in all_repos {
|
||||
print(` - ${repo_path}`);
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
All methods in the Git module return a Result type, which means they can either succeed or fail with an error. If an error occurs, it will be propagated to the HeroScript script as a runtime error.
|
||||
|
||||
For example, if you try to clone a repository that doesn't exist:
|
||||
|
||||
```js
|
||||
// Try to clone a non-existent repository
|
||||
try {
|
||||
let git_tree = gittree_new("/root/code");
|
||||
let repos = git_tree.get("https://github.com/nonexistent/repo.git");
|
||||
print("This will not be executed if the repository doesn't exist");
|
||||
} catch(err) {
|
||||
print(`Error: ${err}`); // Will print the error message from git
|
||||
}
|
||||
```
|
||||
|
||||
Common errors include:
|
||||
- Invalid URL
|
||||
- Repository not found
|
||||
- Authentication failure
|
||||
- Network issues
|
||||
- Local changes exist when trying to pull
|
10
docs/docs/sal/intro.md
Normal file
10
docs/docs/sal/intro.md
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
title: "intro"
|
||||
sidebar_position: 1
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
## HeroScript Script Commands Documentation
|
||||
|
||||
|
||||
The SAL library provides integration with the HeroScript scripting language, allowing you to use powerful system functions within your HeroScript scripts. These functions are organized into modules that provide related functionality.
|
239
docs/docs/sal/nerdctl.md
Normal file
239
docs/docs/sal/nerdctl.md
Normal file
@@ -0,0 +1,239 @@
|
||||
---
|
||||
title: "run containers"
|
||||
sidebar_position: 21
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Container Manager
|
||||
|
||||
The Container Manager module provides a comprehensive API for working with containers using nerdctl. It offers a modern builder pattern approach for container management.
|
||||
|
||||
## Container Builder Pattern
|
||||
|
||||
The Container Builder Pattern allows for fluent, chainable configuration of containers. This pattern makes container creation more readable and maintainable by allowing you to build complex container configurations step by step.
|
||||
|
||||
### Creating a Container
|
||||
|
||||
Start by creating a new container instance:
|
||||
|
||||
```rhai
|
||||
// Create an empty container with just a name
|
||||
let container = nerdctl_container_new("my-container");
|
||||
|
||||
// Or create a container from an image
|
||||
let container = nerdctl_container_from_image("my-container", "nginx:latest");
|
||||
```
|
||||
|
||||
### Configuring the Container
|
||||
|
||||
Once you have a container instance, you can configure it using the various builder methods:
|
||||
|
||||
```rhai
|
||||
// Configure the container with various options
|
||||
let container = nerdctl_container_from_image("web-server", "nginx:latest")
|
||||
.with_port("8080:80") // Map port 8080 to container port 80
|
||||
.with_volume("/host/path:/container/path") // Mount a volume
|
||||
.with_env("NGINX_HOST", "localhost") // Set an environment variable
|
||||
.with_network("bridge") // Set the network
|
||||
.with_detach(true); // Run in detached mode
|
||||
```
|
||||
|
||||
### Resetting Container Configuration
|
||||
|
||||
If you need to reset the container configuration to its default state while keeping the name and image:
|
||||
|
||||
```rhai
|
||||
// Reset the container configuration
|
||||
let container = nerdctl_container_from_image("web-server", "nginx:latest")
|
||||
.reset() // Reset all configuration to defaults
|
||||
.with_port("8080:80") // Start configuring again
|
||||
.with_detach(true);
|
||||
```
|
||||
|
||||
### Building and Starting the Container
|
||||
|
||||
After configuring the container, you can build and start it:
|
||||
|
||||
```rhai
|
||||
// Build the container (creates it but doesn't start it)
|
||||
let built_container = container.build();
|
||||
|
||||
// Start the container
|
||||
let start_result = built_container.start();
|
||||
|
||||
// Check if the container started successfully
|
||||
if (start_result.success) {
|
||||
println("Container started successfully!");
|
||||
} else {
|
||||
println(`Failed to start container: ${start_result.stderr}`);
|
||||
}
|
||||
```
|
||||
|
||||
### Container Lifecycle Operations
|
||||
|
||||
Once your container is running, you can perform various operations:
|
||||
|
||||
```rhai
|
||||
// Execute a command in the container
|
||||
let exec_result = container.exec("ls -la");
|
||||
|
||||
// Get container logs
|
||||
let logs = container.logs();
|
||||
|
||||
// Stop the container
|
||||
let stop_result = container.stop();
|
||||
|
||||
// Remove the container
|
||||
let remove_result = container.remove();
|
||||
```
|
||||
|
||||
## Available Builder Methods
|
||||
|
||||
The Container Builder Pattern provides the following methods for configuring containers:
|
||||
|
||||
| Method | Description | Example |
|
||||
| -------------------------------------------------------------------------- | ---------------------------------- | --------------------------------------------------------------------------------- |
|
||||
| `reset()` | Reset configuration to defaults | `.reset()` |
|
||||
| `with_port(port)` | Add a port mapping | `.with_port("8080:80")` |
|
||||
| `with_ports(ports_array)` | Add multiple port mappings | `.with_ports(["8080:80", "443:443"])` |
|
||||
| `with_volume(volume)` | Add a volume mount | `.with_volume("/host/path:/container/path")` |
|
||||
| `with_volumes(volumes_array)` | Add multiple volume mounts | `.with_volumes(["/host/path1:/container/path1", "/host/path2:/container/path2"])` |
|
||||
| `with_env(key, value)` | Add an environment variable | `.with_env("NGINX_HOST", "localhost")` |
|
||||
| `with_envs(env_map)` | Add multiple environment variables | `.with_envs(#{"KEY1": "value1", "KEY2": "value2"})` |
|
||||
| `with_network(network)` | Set the network | `.with_network("bridge")` |
|
||||
| `with_network_alias(alias)` | Add a network alias | `.with_network_alias("web-server")` |
|
||||
| `with_network_aliases(aliases_array)` | Add multiple network aliases | `.with_network_aliases(["web-server", "http-service"])` |
|
||||
| `with_cpu_limit(cpus)` | Set CPU limit | `.with_cpu_limit("1.0")` |
|
||||
| `with_cpu_shares(shares)` | Set CPU shares | `.with_cpu_shares("1024")` |
|
||||
| `with_memory_limit(memory)` | Set memory limit | `.with_memory_limit("512m")` |
|
||||
| `with_memory_swap_limit(memory_swap)` | Set memory swap limit | `.with_memory_swap_limit("1g")` |
|
||||
| `with_restart_policy(policy)` | Set restart policy | `.with_restart_policy("unless-stopped")` |
|
||||
| `with_health_check(cmd)` | Set health check command | `.with_health_check("curl -f http://localhost/ | | exit 1")` |
|
||||
| `with_health_check_options(cmd, interval, timeout, retries, start_period)` | Set health check with options | `.with_health_check_options("curl -f http://localhost/ | | exit 1", "5s", "3s", 3, "10s")` |
|
||||
| `with_snapshotter(snapshotter)` | Set snapshotter | `.with_snapshotter("native")` |
|
||||
| `with_detach(detach)` | Set detach mode | `.with_detach(true)` |
|
||||
|
||||
## Complete Example: Web Server
|
||||
|
||||
Here's a complete example that demonstrates setting up an Nginx web server using the Container Builder Pattern:
|
||||
|
||||
```rhai
|
||||
// Create a temporary directory for our files
|
||||
let work_dir = "/tmp/nerdctl";
|
||||
mkdir(work_dir);
|
||||
chdir(work_dir);
|
||||
|
||||
// Create a custom index.html file
|
||||
let html_content = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Rhai Nerdctl Demo</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 40px;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
}
|
||||
h1 {
|
||||
color: #0066cc;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello from Rhai Nerdctl!</h1>
|
||||
<p>This page is served by an Nginx container created using the Rhai nerdctl wrapper.</p>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
// Write the HTML file
|
||||
let html_file = `${work_dir}/index.html`;
|
||||
file_write(html_file, html_content);
|
||||
|
||||
// Set up environment variables
|
||||
let env_map = #{};
|
||||
env_map["NGINX_HOST"] = "localhost";
|
||||
env_map["NGINX_PORT"] = "80";
|
||||
env_map["NGINX_WORKER_PROCESSES"] = "auto";
|
||||
|
||||
// Create and configure the container
|
||||
let container_name = "rhai-nginx-demo";
|
||||
|
||||
// First, try to remove any existing container with the same name
|
||||
nerdctl_remove(container_name);
|
||||
|
||||
// Create a container with a rich set of options using the builder pattern
|
||||
let container = nerdctl_container_from_image(container_name, "nginx:latest")
|
||||
.reset() // Reset to default configuration
|
||||
.with_detach(true)
|
||||
.with_ports(["8080:80"]) // Add multiple ports at once
|
||||
.with_volumes([`${work_dir}:/usr/share/nginx/html`]) // Mount our work dir
|
||||
.with_envs(env_map) // Add multiple environment variables at once
|
||||
.with_network("bridge")
|
||||
.with_network_aliases(["web-server", "nginx-demo"]) // Add multiple network aliases
|
||||
.with_cpu_limit("1.0")
|
||||
.with_memory_limit("512m");
|
||||
|
||||
// Build and start the container
|
||||
let built_container = container.build();
|
||||
let start_result = built_container.start();
|
||||
|
||||
println("The web server is running at http://localhost:8080");
|
||||
```
|
||||
|
||||
## Using Local Images Created with Buildah
|
||||
|
||||
When working with images created by Buildah, you may need to take additional steps to ensure nerdctl can find and use these images. This is because Buildah and nerdctl may use different storage backends by default.
|
||||
|
||||
### Tagging with localhost Prefix
|
||||
|
||||
One approach is to tag the Buildah-created image with a `localhost/` prefix:
|
||||
|
||||
```rhai
|
||||
// Create and commit a container with Buildah
|
||||
let builder = bah_new("my-container", "alpine:latest");
|
||||
builder.run("echo 'Hello' > /hello.txt");
|
||||
builder.commit("my-custom-image:latest");
|
||||
|
||||
// Tag the image with localhost prefix for nerdctl compatibility
|
||||
let local_image_name = "localhost/my-custom-image:latest";
|
||||
bah_image_tag("my-custom-image:latest", local_image_name);
|
||||
|
||||
// Now use the image with nerdctl
|
||||
let container = nerdctl_container_from_image("my-app", local_image_name)
|
||||
.with_detach(true)
|
||||
.build();
|
||||
```
|
||||
|
||||
### Using a Local Registry
|
||||
|
||||
For more reliable interoperability, you can push the image to a local registry:
|
||||
|
||||
```rhai
|
||||
// Push the Buildah-created image to a local registry
|
||||
bah_image_push("my-custom-image:latest", "localhost:5000/my-custom-image:latest", false);
|
||||
|
||||
// Pull the image with nerdctl
|
||||
nerdctl_image_pull("localhost:5000/my-custom-image:latest");
|
||||
|
||||
// Use the image
|
||||
let container = nerdctl_container_from_image("my-app", "localhost:5000/my-custom-image:latest")
|
||||
.with_detach(true)
|
||||
.build();
|
||||
```
|
||||
|
||||
## Image Management Functions
|
||||
|
||||
The module also provides functions for managing container images:
|
||||
|
||||
| Function | Description | Example |
|
||||
| --------------------------------------------- | --------------------------------------- | ------------------------------------------------------------------------------- |
|
||||
| `nerdctl_images()` | List images in local storage | `nerdctl_images()` |
|
||||
| `nerdctl_image_remove(image)` | Remove an image | `nerdctl_image_remove("nginx:latest")` |
|
||||
| `nerdctl_image_push(image, destination)` | Push an image to a registry | `nerdctl_image_push("my-image:latest", "registry.example.com/my-image:latest")` |
|
||||
| `nerdctl_image_tag(image, new_name)` | Add an additional name to a local image | `nerdctl_image_tag("nginx:latest", "my-nginx:latest")` |
|
||||
| `nerdctl_image_pull(image)` | Pull an image from a registry | `nerdctl_image_pull("nginx:latest")` |
|
||||
| `nerdctl_image_commit(container, image_name)` | Commit a container to an image | `nerdctl_image_commit("web-server", "my-nginx:latest")` |
|
||||
| `nerdctl_image_build(tag, context_path)` | Build an image using a Dockerfile | `nerdctl_image_build("my-image:latest", "./")` |
|
359
docs/docs/sal/os.md
Normal file
359
docs/docs/sal/os.md
Normal file
@@ -0,0 +1,359 @@
|
||||
---
|
||||
title: "os"
|
||||
sidebar_position: 2
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# OS Tools
|
||||
|
||||
The OS module provides functions for working with files, directories, and downloading files from the internet.
|
||||
|
||||
## File System Functions
|
||||
|
||||
### `copy(src, dest)`
|
||||
|
||||
Recursively copies a file or directory from source to destination.
|
||||
|
||||
**Parameters:**
|
||||
- `src` (string): The source file or directory path
|
||||
- `dest` (string): The destination path
|
||||
|
||||
**Returns:** A message confirming the copy was successful.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Copy a file
|
||||
copy("source.txt", "destination.txt");
|
||||
|
||||
// Copy a directory recursively
|
||||
copy("source_dir", "destination_dir");
|
||||
```
|
||||
|
||||
### `exist(path)`
|
||||
|
||||
Checks if a file or directory exists.
|
||||
|
||||
**Parameters:**
|
||||
- `path` (string): The path to check
|
||||
|
||||
**Returns:** A boolean value - `true` if the file or directory exists, `false` otherwise.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
if exist("config.json") {
|
||||
// File exists, do something
|
||||
} else {
|
||||
// File doesn't exist
|
||||
}
|
||||
```
|
||||
|
||||
### `find_file(dir, filename)`
|
||||
|
||||
Finds a file in a directory with support for wildcards.
|
||||
|
||||
**Parameters:**
|
||||
- `dir` (string): The directory to search in
|
||||
- `filename` (string): The filename pattern to search for (supports wildcards)
|
||||
|
||||
**Returns:** The path of the first matching file.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Find a specific file
|
||||
let config_file = find_file("./config", "settings.json");
|
||||
|
||||
// Find using wildcards
|
||||
let log_file = find_file("./logs", "*.log");
|
||||
```
|
||||
|
||||
### `find_files(dir, filename)`
|
||||
|
||||
Finds multiple files in a directory recursively with support for wildcards.
|
||||
|
||||
**Parameters:**
|
||||
- `dir` (string): The directory to search in
|
||||
- `filename` (string): The filename pattern to search for (supports wildcards)
|
||||
|
||||
**Returns:** A list of matching file paths.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Find all JSON files
|
||||
let json_files = find_files("./data", "*.json");
|
||||
|
||||
// Process each file
|
||||
for file in json_files {
|
||||
print(`Found file: ${file}`);
|
||||
}
|
||||
```
|
||||
|
||||
### `find_dir(dir, dirname)`
|
||||
|
||||
Finds a directory in a parent directory with support for wildcards.
|
||||
|
||||
**Parameters:**
|
||||
- `dir` (string): The parent directory to search in
|
||||
- `dirname` (string): The directory name pattern to search for (supports wildcards)
|
||||
|
||||
**Returns:** The path of the first matching directory.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Find a specific directory
|
||||
let config_dir = find_dir("./", "config");
|
||||
|
||||
// Find using wildcards
|
||||
let version_dir = find_dir("./releases", "v*");
|
||||
```
|
||||
|
||||
### `find_dirs(dir, dirname)`
|
||||
|
||||
Finds multiple directories in a parent directory recursively with support for wildcards.
|
||||
|
||||
**Parameters:**
|
||||
- `dir` (string): The parent directory to search in
|
||||
- `dirname` (string): The directory name pattern to search for (supports wildcards)
|
||||
|
||||
**Returns:** A list of matching directory paths.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Find all version directories
|
||||
let version_dirs = find_dirs("./releases", "v*");
|
||||
|
||||
// Process each directory
|
||||
for dir in version_dirs {
|
||||
print(`Found directory: ${dir}`);
|
||||
}
|
||||
```
|
||||
|
||||
### `delete(path)`
|
||||
|
||||
Deletes a file or directory. This function is defensive and doesn't error if the file doesn't exist.
|
||||
|
||||
**Parameters:**
|
||||
- `path` (string): The path of the file or directory to delete
|
||||
|
||||
**Returns:** A message confirming the deletion was successful.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Delete a file
|
||||
delete("temp.txt");
|
||||
|
||||
// Delete a directory
|
||||
delete("temp_dir");
|
||||
```
|
||||
|
||||
### `mv(src, dest)`
|
||||
|
||||
Moves a file or directory from source to destination.
|
||||
|
||||
**Parameters:**
|
||||
- `src` (string): The source path
|
||||
- `dest` (string): The destination path
|
||||
|
||||
**Returns:** A message confirming the move was successful.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Move a file
|
||||
mv("file.txt", "new_location/file.txt");
|
||||
|
||||
// Move a directory
|
||||
mv("source_dir", "destination_dir");
|
||||
|
||||
// Rename a file
|
||||
mv("old_name.txt", "new_name.txt");
|
||||
```
|
||||
|
||||
### `mkdir(path)`
|
||||
|
||||
Creates a directory and all parent directories. This function is defensive and doesn't error if the directory already exists.
|
||||
|
||||
**Parameters:**
|
||||
- `path` (string): The path of the directory to create
|
||||
|
||||
**Returns:** A message confirming the directory was created.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Create a directory
|
||||
mkdir("new_dir");
|
||||
|
||||
// Create nested directories
|
||||
mkdir("parent/child/grandchild");
|
||||
```
|
||||
|
||||
### `file_size(path)`
|
||||
|
||||
Gets the size of a file in bytes.
|
||||
|
||||
**Parameters:**
|
||||
- `path` (string): The path of the file
|
||||
|
||||
**Returns:** The size of the file in bytes.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Get file size
|
||||
let size = file_size("large_file.dat");
|
||||
print(`File size: ${size} bytes`);
|
||||
```
|
||||
|
||||
## File Content Functions
|
||||
|
||||
### `file_read(path)`
|
||||
|
||||
Reads the contents of a file.
|
||||
|
||||
**Parameters:**
|
||||
- `path` (string): The path of the file to read
|
||||
|
||||
**Returns:** The content of the file as a string.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Read a file
|
||||
let content = file_read("config.json");
|
||||
print(`File content: ${content}`);
|
||||
```
|
||||
|
||||
### `file_write(path, content)`
|
||||
|
||||
Writes content to a file. Creates the file if it doesn't exist, overwrites if it does.
|
||||
|
||||
**Parameters:**
|
||||
- `path` (string): The path of the file to write to
|
||||
- `content` (string): The content to write to the file
|
||||
|
||||
**Returns:** A message confirming the file was written.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Write to a file
|
||||
file_write("config.json", "{\n \"setting\": \"value\"\n}");
|
||||
```
|
||||
|
||||
### `file_write_append(path, content)`
|
||||
|
||||
Appends content to a file. Creates the file if it doesn't exist.
|
||||
|
||||
**Parameters:**
|
||||
- `path` (string): The path of the file to append to
|
||||
- `content` (string): The content to append to the file
|
||||
|
||||
**Returns:** A message confirming the content was appended.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Append to a log file
|
||||
file_write_append("log.txt", "New log entry\n");
|
||||
```
|
||||
|
||||
### `rsync(src, dest)`
|
||||
|
||||
Syncs directories using rsync (or platform equivalent).
|
||||
|
||||
**Parameters:**
|
||||
- `src` (string): The source directory
|
||||
- `dest` (string): The destination directory
|
||||
|
||||
**Returns:** A message confirming the directories were synced.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Sync directories
|
||||
rsync("source_dir", "backup_dir");
|
||||
```
|
||||
|
||||
### `chdir(path)`
|
||||
|
||||
Changes the current working directory.
|
||||
|
||||
**Parameters:**
|
||||
- `path` (string): The path to change to
|
||||
|
||||
**Returns:** A message confirming the directory was changed.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Change directory
|
||||
chdir("project/src");
|
||||
```
|
||||
|
||||
## Download Functions
|
||||
|
||||
### `download(url, dest, min_size_kb)`
|
||||
|
||||
Downloads a file from a URL to a destination directory using the curl command. If the URL ends with a supported archive format, the file will be automatically extracted to the destination directory.
|
||||
|
||||
**Supported archive formats for automatic extraction:**
|
||||
- `.tar.gz`
|
||||
- `.tgz`
|
||||
- `.tar`
|
||||
- `.zip`
|
||||
|
||||
**Parameters:**
|
||||
- `url` (string): The URL to download from
|
||||
- `dest` (string): The destination directory where the file will be saved or extracted
|
||||
- `min_size_kb` (integer): The minimum expected file size in kilobytes (for validation)
|
||||
|
||||
**Returns:** The path where the file was saved or extracted.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Download a file to a directory
|
||||
download("https://example.com/file.zip", "downloads/", 10);
|
||||
```
|
||||
|
||||
### `download_file(url, dest, min_size_kb)`
|
||||
|
||||
Downloads a file from a URL to a specific file destination using the curl command. This function is designed for downloading files to a specific path, not for extracting archives.
|
||||
|
||||
**Parameters:**
|
||||
- `url` (string): The URL to download from
|
||||
- `dest` (string): The destination file path where the file will be saved
|
||||
- `min_size_kb` (integer): The minimum expected file size in kilobytes (for validation)
|
||||
|
||||
**Returns:** The path where the file was saved.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Download a file to a specific path
|
||||
download_file("https://example.com/file.txt", "downloads/myfile.txt", 10);
|
||||
```
|
||||
|
||||
### `download_install(url, min_size_kb)`
|
||||
|
||||
Downloads a file and installs it if it's a supported package format.
|
||||
|
||||
**Supported package formats for automatic installation:**
|
||||
- `.deb` packages on Debian-based systems
|
||||
|
||||
**Parameters:**
|
||||
- `url` (string): The URL to download from
|
||||
- `min_size_kb` (integer): The minimum expected file size in kilobytes (for validation)
|
||||
|
||||
**Returns:** The path where the file was saved or installed.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Download and install a package
|
||||
download_install("https://example.com/package.deb", 1000);
|
||||
```
|
||||
|
||||
### `chmod_exec(path)`
|
||||
|
||||
Makes a file executable (equivalent to `chmod +x` in Unix).
|
||||
|
||||
**Parameters:**
|
||||
- `path` (string): The path to the file to make executable
|
||||
|
||||
**Returns:** A message confirming the file was made executable.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Make a file executable
|
||||
chmod_exec("downloads/script.sh");
|
||||
```
|
237
docs/docs/sal/process.md
Normal file
237
docs/docs/sal/process.md
Normal file
@@ -0,0 +1,237 @@
|
||||
---
|
||||
title: "process"
|
||||
sidebar_position: 3
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Process Module
|
||||
|
||||
The Process module provides functions for running commands and managing processes on your system.
|
||||
|
||||
## Command Results
|
||||
|
||||
### Command Output Information
|
||||
|
||||
When you run a command, you get back information about what happened:
|
||||
|
||||
- `stdout`: The normal output of the command
|
||||
- `stderr`: Any error messages from the command
|
||||
- `success`: Whether the command worked (true) or failed (false)
|
||||
- `code`: The exit code (0 usually means success)
|
||||
|
||||
### Process Information
|
||||
|
||||
When you get information about a running process, you can see:
|
||||
|
||||
- `pid`: The process ID number
|
||||
- `name`: The name of the process
|
||||
- `memory`: How much memory the process is using
|
||||
- `cpu`: How much CPU the process is using
|
||||
|
||||
## Run Functions
|
||||
### `run(command)`
|
||||
|
||||
Runs a command or multiline script with arguments.
|
||||
|
||||
**Parameters:**
|
||||
- `command` (string): The command to run (can be a single command or a multiline script)
|
||||
|
||||
**Returns:** The result of the command, including output and whether it succeeded.
|
||||
|
||||
**Example 1: Running a simple command**
|
||||
```js
|
||||
// Run a simple command
|
||||
let result = run("ls -la");
|
||||
|
||||
// Check if the command was successful
|
||||
if result.success {
|
||||
print(`Command output: ${result.stdout}`);
|
||||
} else {
|
||||
print(`Command failed with error: ${result.stderr}`);
|
||||
}
|
||||
```
|
||||
|
||||
**Example 2: Running a multiline script**
|
||||
```js
|
||||
// Create a multiline script using backtick string literals
|
||||
let setup_script = `
|
||||
# Create directories
|
||||
mkdir -p /tmp/test_project
|
||||
cd /tmp/test_project
|
||||
|
||||
# Initialize git repository
|
||||
git init
|
||||
echo 'Initial content' > README.md
|
||||
git add README.md
|
||||
git config --local user.email 'test@example.com'
|
||||
git config --local user.name 'Test User'
|
||||
git commit -m 'Initial commit'
|
||||
`;
|
||||
|
||||
// Execute the multiline script
|
||||
let result = run(setup_script);
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
### `run_silent(command)`
|
||||
|
||||
Runs a command or multiline script with arguments silently (without displaying output).
|
||||
|
||||
**Parameters:**
|
||||
- `command` (string): The command to run
|
||||
|
||||
**Returns:** The result of the command, without displaying the output.
|
||||
|
||||
**Example:**
|
||||
|
||||
```js
|
||||
// Run a command silently
|
||||
let result = run_silent("git pull");
|
||||
|
||||
// Check the exit code
|
||||
if result.code == 0 {
|
||||
print("Git pull successful");
|
||||
} else {
|
||||
print(`Git pull failed with code ${result.code}`);
|
||||
}
|
||||
```
|
||||
|
||||
### `new_run_options()`
|
||||
|
||||
Creates a new map with default run options.
|
||||
|
||||
**Returns:** A map with the following default options:
|
||||
- `die` (boolean): `true` - Whether to throw an error if the command fails
|
||||
- `silent` (boolean): `false` - Whether to suppress command output
|
||||
- `async_exec` (boolean): `false` - Whether to run the command asynchronously
|
||||
- `log` (boolean): `false` - Whether to log the command execution
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Create run options
|
||||
let options = new_run_options();
|
||||
```
|
||||
|
||||
### `run_with_options(command, options)`
|
||||
|
||||
Runs a command with options specified in a map.
|
||||
|
||||
**Parameters:**
|
||||
- `command` (string): The command to run
|
||||
- `options` (map): A map of options created with `new_run_options()`
|
||||
|
||||
**Returns:** The result of the command with your custom settings applied.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Create and customize run options
|
||||
let options = new_run_options();
|
||||
options.die = false; // Don't throw an error if the command fails
|
||||
options.silent = true; // Suppress command output
|
||||
options.async_exec = false; // Run synchronously
|
||||
options.log = true; // Log the command execution
|
||||
|
||||
// Run a command with options
|
||||
let result = run_with_options("npm install", options);
|
||||
```
|
||||
|
||||
## Working with Multiline Scripts
|
||||
|
||||
The Process module allows you to execute multiline scripts, which is particularly useful for complex operations that require multiple commands to be executed in sequence.
|
||||
|
||||
### Creating Multiline Scripts
|
||||
|
||||
Multiline scripts can be created using backtick (`) string literals in HeroScript:
|
||||
|
||||
```js
|
||||
let my_script = `
|
||||
# This is a multiline bash script
|
||||
echo "Hello, World!"
|
||||
mkdir -p /tmp/my_project
|
||||
cd /tmp/my_project
|
||||
touch example.txt
|
||||
`;
|
||||
```
|
||||
|
||||
## Process Management Functions
|
||||
|
||||
### `which(cmd)`
|
||||
|
||||
Checks if a command exists in the PATH.
|
||||
|
||||
**Parameters:**
|
||||
- `cmd` (string): The command to check
|
||||
|
||||
**Returns:** The full path to the command if found, or nothing if not found.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Check if a command exists
|
||||
let git_path = which("git");
|
||||
|
||||
if git_path != () {
|
||||
print(`Git is installed at: ${git_path}`);
|
||||
} else {
|
||||
print("Git is not installed");
|
||||
}
|
||||
```
|
||||
|
||||
### `kill(pattern)`
|
||||
|
||||
Kills processes matching a pattern.
|
||||
|
||||
**Parameters:**
|
||||
- `pattern` (string): The pattern to match process names against
|
||||
|
||||
**Returns:** A message confirming the processes were killed.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Kill all processes with "node" in their name
|
||||
kill("node");
|
||||
```
|
||||
|
||||
### `process_list(pattern)`
|
||||
|
||||
Lists processes matching a pattern (or all processes if the pattern is empty).
|
||||
|
||||
**Parameters:**
|
||||
- `pattern` (string): The pattern to match process names against (can be empty to list all processes)
|
||||
|
||||
**Returns:** A list of processes matching your search.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// List all processes
|
||||
let all_processes = process_list("");
|
||||
|
||||
// List processes containing "node" in their name
|
||||
let node_processes = process_list("node");
|
||||
|
||||
// Display process information
|
||||
for process in node_processes {
|
||||
print(`PID: ${process.pid}, Name: ${process.name}, Memory: ${process.memory}, CPU: ${process.cpu}`);
|
||||
}
|
||||
```
|
||||
|
||||
### `process_get(pattern)`
|
||||
|
||||
Gets a single process matching the pattern. Throws an error if zero or more than one process matches.
|
||||
|
||||
**Parameters:**
|
||||
- `pattern` (string): The pattern to match process names against
|
||||
|
||||
**Returns:** Information about the matching process. This will only work if exactly one process matches.
|
||||
|
||||
**Example:**
|
||||
```js
|
||||
// Try to get a specific process
|
||||
try {
|
||||
let process = process_get("my_app");
|
||||
print(`Found process: PID=${process.pid}, Name=${process.name}`);
|
||||
} catch(err) {
|
||||
print(`Error: ${err}`);
|
||||
}
|
||||
```
|
154
docs/docs/sal/rfs.md
Normal file
154
docs/docs/sal/rfs.md
Normal file
@@ -0,0 +1,154 @@
|
||||
# RFS (Remote File System)
|
||||
|
||||
The RFS module provides a Rust wrapper for the RFS tool, which allows mounting remote filesystems locally and managing filesystem layers.
|
||||
|
||||
## Overview
|
||||
|
||||
RFS (Remote File System) is a tool that enables mounting various types of remote filesystems locally, as well as creating and managing filesystem layers. The SAL library provides a Rust wrapper for RFS with a fluent builder API, making it easy to use in your applications.
|
||||
|
||||
## Features
|
||||
|
||||
- Mount remote filesystems locally (SSH, S3, WebDAV, etc.)
|
||||
- List mounted filesystems
|
||||
- Unmount filesystems
|
||||
- Pack directories into filesystem layers
|
||||
- Unpack filesystem layers
|
||||
- List contents of filesystem layers
|
||||
- Verify filesystem layers
|
||||
|
||||
## Usage in Rust
|
||||
|
||||
### Mounting a Filesystem
|
||||
|
||||
```rust
|
||||
use sal::virt::rfs::{RfsBuilder, MountType};
|
||||
|
||||
// Create a new RFS builder
|
||||
let mount = RfsBuilder::new("user@example.com:/remote/path", "/local/mount/point", MountType::SSH)
|
||||
.with_option("port", "2222")
|
||||
.with_option("identity_file", "/path/to/key")
|
||||
.with_debug(true)
|
||||
.mount()?;
|
||||
|
||||
println!("Mounted filesystem with ID: {}", mount.id);
|
||||
```
|
||||
|
||||
### Listing Mounts
|
||||
|
||||
```rust
|
||||
use sal::virt::rfs::list_mounts;
|
||||
|
||||
// List all mounts
|
||||
let mounts = list_mounts()?;
|
||||
for mount in mounts {
|
||||
println!("Mount ID: {}, Source: {}, Target: {}", mount.id, mount.source, mount.target);
|
||||
}
|
||||
```
|
||||
|
||||
### Unmounting a Filesystem
|
||||
|
||||
```rust
|
||||
use sal::virt::rfs::unmount;
|
||||
|
||||
// Unmount a filesystem
|
||||
unmount("/local/mount/point")?;
|
||||
```
|
||||
|
||||
### Packing a Directory
|
||||
|
||||
```rust
|
||||
use sal::virt::rfs::{PackBuilder, StoreSpec};
|
||||
|
||||
// Create store specifications
|
||||
let store_spec = StoreSpec::new("file")
|
||||
.with_option("path", "/path/to/store");
|
||||
|
||||
// Pack a directory with builder pattern
|
||||
let result = PackBuilder::new("/path/to/directory", "output.fl")
|
||||
.with_store_spec(store_spec)
|
||||
.with_debug(true)
|
||||
.pack()?;
|
||||
```
|
||||
|
||||
### Unpacking a Filesystem Layer
|
||||
|
||||
```rust
|
||||
use sal::virt::rfs::unpack;
|
||||
|
||||
// Unpack a filesystem layer
|
||||
unpack("input.fl", "/path/to/unpack")?;
|
||||
```
|
||||
|
||||
## Usage in Rhai Scripts
|
||||
|
||||
### Mounting a Filesystem
|
||||
|
||||
```rhai
|
||||
// Create a map for mount options
|
||||
let options = #{
|
||||
"port": "22",
|
||||
"identity_file": "/path/to/key",
|
||||
"readonly": "true"
|
||||
};
|
||||
|
||||
// Mount the directory
|
||||
let mount = rfs_mount("user@example.com:/remote/path", "/local/mount/point", "ssh", options);
|
||||
|
||||
print(`Mounted ${mount.source} to ${mount.target} with ID: ${mount.id}`);
|
||||
```
|
||||
|
||||
### Listing Mounts
|
||||
|
||||
```rhai
|
||||
// List all mounts
|
||||
let mounts = rfs_list_mounts();
|
||||
print(`Number of mounts: ${mounts.len()}`);
|
||||
|
||||
for mount in mounts {
|
||||
print(`Mount ID: ${mount.id}, Source: ${mount.source}, Target: ${mount.target}`);
|
||||
}
|
||||
```
|
||||
|
||||
### Unmounting a Filesystem
|
||||
|
||||
```rhai
|
||||
// Unmount the directory
|
||||
rfs_unmount("/local/mount/point");
|
||||
```
|
||||
|
||||
### Packing a Directory
|
||||
|
||||
```rhai
|
||||
// Pack the directory
|
||||
// Store specs format: "file:path=/path/to/store,s3:bucket=my-bucket"
|
||||
rfs_pack("/path/to/directory", "output.fl", "file:path=/path/to/store");
|
||||
```
|
||||
|
||||
### Unpacking a Filesystem Layer
|
||||
|
||||
```rhai
|
||||
// Unpack the filesystem layer
|
||||
rfs_unpack("output.fl", "/path/to/unpack");
|
||||
```
|
||||
|
||||
## Mount Types
|
||||
|
||||
The RFS module supports various mount types:
|
||||
|
||||
- **Local**: Mount a local directory
|
||||
- **SSH**: Mount a remote directory via SSH
|
||||
- **S3**: Mount an S3 bucket
|
||||
- **WebDAV**: Mount a WebDAV server
|
||||
|
||||
## Store Specifications
|
||||
|
||||
When packing a directory into a filesystem layer, you can specify one or more stores to use. Each store has a type and options:
|
||||
|
||||
- **File**: Store files on the local filesystem
|
||||
- Options: `path` (path to the store)
|
||||
- **S3**: Store files in an S3 bucket
|
||||
- Options: `bucket` (bucket name), `region` (AWS region), `access_key`, `secret_key`
|
||||
|
||||
## Examples
|
||||
|
||||
See the [RFS example script](../../rhaiexamples/rfs_example.rhai) for more examples of how to use the RFS module in Rhai scripts.
|
237
docs/docs/sal/text.md
Normal file
237
docs/docs/sal/text.md
Normal file
@@ -0,0 +1,237 @@
|
||||
# Text Manipulation Tools
|
||||
|
||||
The SAL text module provides powerful text manipulation capabilities that can be used from Rhai scripts. These include text replacement (with regex support), template rendering, string normalization, and text formatting utilities.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Text Replacement](#text-replacement)
|
||||
- [Template Rendering](#template-rendering)
|
||||
- [String Normalization](#string-normalization)
|
||||
- [Text Formatting](#text-formatting)
|
||||
|
||||
## Text Replacement
|
||||
|
||||
The text replacement tools allow you to perform simple or complex text replacements, with support for regular expressions, case-insensitive matching, and file operations.
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```rhai
|
||||
// Create a new text replacer
|
||||
let replacer = text_replacer_new()
|
||||
.pattern("foo") // Set the pattern to search for
|
||||
.replacement("bar") // Set the replacement text
|
||||
.build(); // Build the replacer
|
||||
|
||||
// Apply the replacer to a string
|
||||
let result = replacer.replace("foo bar foo");
|
||||
// Result: "bar bar bar"
|
||||
```
|
||||
|
||||
### Advanced Features
|
||||
|
||||
#### Regular Expressions
|
||||
|
||||
```rhai
|
||||
// Create a replacer with regex support
|
||||
let replacer = text_replacer_new()
|
||||
.pattern("\\bfoo\\b") // Use regex pattern (word boundary)
|
||||
.replacement("bar")
|
||||
.regex(true) // Enable regex mode
|
||||
.build();
|
||||
|
||||
// Apply the replacer to a string
|
||||
let result = replacer.replace("foo foobar");
|
||||
// Result: "bar foobar" (only replaces whole "foo" words)
|
||||
```
|
||||
|
||||
#### Case-Insensitive Matching
|
||||
|
||||
```rhai
|
||||
// Create a replacer with case-insensitive matching
|
||||
let replacer = text_replacer_new()
|
||||
.pattern("foo")
|
||||
.replacement("bar")
|
||||
.regex(true)
|
||||
.case_insensitive(true) // Enable case-insensitive matching
|
||||
.build();
|
||||
|
||||
// Apply the replacer to a string
|
||||
let result = replacer.replace("FOO foo Foo");
|
||||
// Result: "bar bar bar"
|
||||
```
|
||||
|
||||
#### Multiple Replacements
|
||||
|
||||
```rhai
|
||||
// Chain multiple replacements
|
||||
let replacer = text_replacer_new()
|
||||
.pattern("foo")
|
||||
.replacement("bar")
|
||||
.and() // Add another replacement operation
|
||||
.pattern("baz")
|
||||
.replacement("qux")
|
||||
.build();
|
||||
|
||||
// Apply the replacer to a string
|
||||
let result = replacer.replace("foo baz");
|
||||
// Result: "bar qux"
|
||||
```
|
||||
|
||||
#### File Operations
|
||||
|
||||
```rhai
|
||||
// Create a replacer
|
||||
let replacer = text_replacer_new()
|
||||
.pattern("foo")
|
||||
.replacement("bar")
|
||||
.build();
|
||||
|
||||
// Replace in a file and get the result as a string
|
||||
let result = replacer.replace_file("input.txt");
|
||||
|
||||
// Replace in a file and write back to the same file
|
||||
replacer.replace_file_in_place("input.txt");
|
||||
|
||||
// Replace in a file and write to a new file
|
||||
replacer.replace_file_to("input.txt", "output.txt");
|
||||
```
|
||||
|
||||
## Template Rendering
|
||||
|
||||
The template rendering tools allow you to create and render templates with variables, using the powerful Tera template engine.
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```rhai
|
||||
// Create a template builder with a template file
|
||||
let template = template_builder_open("template.txt")
|
||||
.add_var("name", "John") // Add a string variable
|
||||
.add_var("age", 30) // Add a numeric variable
|
||||
.add_var("items", ["a", "b", "c"]); // Add an array variable
|
||||
|
||||
// Render the template
|
||||
let result = template.render();
|
||||
|
||||
// Render to a file
|
||||
template.render_to_file("output.txt");
|
||||
```
|
||||
|
||||
### Template Variables
|
||||
|
||||
You can add variables of various types:
|
||||
|
||||
```rhai
|
||||
let template = template_builder_open("template.txt")
|
||||
.add_var("name", "John") // String
|
||||
.add_var("age", 30) // Integer
|
||||
.add_var("height", 1.85) // Float
|
||||
.add_var("is_active", true) // Boolean
|
||||
.add_var("items", ["a", "b", "c"]); // Array
|
||||
```
|
||||
|
||||
### Using Map for Variables
|
||||
|
||||
```rhai
|
||||
// Create a map of variables
|
||||
let vars = #{
|
||||
name: "Alice",
|
||||
place: "Wonderland"
|
||||
};
|
||||
|
||||
// Add all variables from the map
|
||||
let template = template_builder_open("template.txt")
|
||||
.add_vars(vars);
|
||||
```
|
||||
|
||||
### Template Syntax
|
||||
|
||||
The template engine uses Tera, which supports:
|
||||
|
||||
- Variable interpolation: `{{ variable }}`
|
||||
- Conditionals: `{% if condition %}...{% endif %}`
|
||||
- Loops: `{% for item in items %}...{% endfor %}`
|
||||
- Filters: `{{ variable | filter }}`
|
||||
|
||||
Example template:
|
||||
|
||||
```
|
||||
Hello, {{ name }}!
|
||||
|
||||
{% if show_greeting %}
|
||||
Welcome to {{ place }}.
|
||||
{% endif %}
|
||||
|
||||
Your items:
|
||||
{% for item in items %}
|
||||
- {{ item }}{% if not loop.last %}{% endif %}
|
||||
{% endfor %}
|
||||
```
|
||||
|
||||
## String Normalization
|
||||
|
||||
The string normalization tools help convert strings to consistent formats for use as file names or paths.
|
||||
|
||||
### name_fix
|
||||
|
||||
Converts a string to a safe, normalized name by:
|
||||
- Converting to lowercase
|
||||
- Replacing spaces and special characters with underscores
|
||||
- Removing non-alphanumeric characters
|
||||
|
||||
```rhai
|
||||
let fixed_name = name_fix("Hello World!");
|
||||
// Result: "hello_world"
|
||||
|
||||
let fixed_name = name_fix("File-Name.txt");
|
||||
// Result: "file_name.txt"
|
||||
```
|
||||
|
||||
### path_fix
|
||||
|
||||
Similar to name_fix, but preserves path separators:
|
||||
|
||||
```rhai
|
||||
let fixed_path = path_fix("/path/to/Hello World!");
|
||||
// Result: "/path/to/hello_world"
|
||||
|
||||
let fixed_path = path_fix("./relative/path/to/DOCUMENT-123.pdf");
|
||||
// Result: "./relative/path/to/document_123.pdf"
|
||||
```
|
||||
|
||||
## Text Formatting
|
||||
|
||||
Tools to help with text formatting and indentation.
|
||||
|
||||
### dedent
|
||||
|
||||
Removes common leading whitespace from multi-line strings:
|
||||
|
||||
```rhai
|
||||
let indented_text = " line 1
|
||||
line 2
|
||||
line 3";
|
||||
|
||||
let dedented = dedent(indented_text);
|
||||
// Result: "line 1
|
||||
// line 2
|
||||
// line 3"
|
||||
```
|
||||
|
||||
### prefix
|
||||
|
||||
Adds a prefix to every line in a multi-line string:
|
||||
|
||||
```rhai
|
||||
let text = "line 1
|
||||
line 2
|
||||
line 3";
|
||||
|
||||
let prefixed = prefix(text, " ");
|
||||
// Result: " line 1
|
||||
// line 2
|
||||
// line 3"
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
See the [text_tools.rhai](https://github.com/ourworld-tf/herocode/blob/main/sal/src/rhaiexamples/text_tools.rhai) example script for more detailed examples of using these text manipulation tools.
|
Reference in New Issue
Block a user