297 lines
6.6 KiB
Markdown
297 lines
6.6 KiB
Markdown
# Skybridge FaaS Client
|
|
|
|
A lightweight Go client library for interacting with the Skybridge Function-as-a-Service (FaaS) platform.
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
go get github.com/RyanCopley/skybridge/faas-client
|
|
```
|
|
|
|
## Usage
|
|
|
|
### Basic Client Setup
|
|
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
|
|
faasclient "github.com/RyanCopley/skybridge/faas-client"
|
|
)
|
|
|
|
func main() {
|
|
// Create a new client
|
|
client := faasclient.NewClient(
|
|
"http://localhost:8080", // FaaS API base URL
|
|
faasclient.WithUserEmail("admin@example.com"), // Authentication
|
|
)
|
|
|
|
// Use the client...
|
|
}
|
|
```
|
|
|
|
### Authentication Options
|
|
|
|
```go
|
|
// Using user email header (for development)
|
|
client := faasclient.NewClient(baseURL,
|
|
faasclient.WithUserEmail("user@example.com"))
|
|
|
|
// Using custom auth headers
|
|
client := faasclient.NewClient(baseURL,
|
|
faasclient.WithAuth(map[string]string{
|
|
"Authorization": "Bearer " + token,
|
|
"X-User-Email": "user@example.com",
|
|
}))
|
|
|
|
// Using custom HTTP client
|
|
httpClient := &http.Client{Timeout: 30 * time.Second}
|
|
client := faasclient.NewClient(baseURL,
|
|
faasclient.WithHTTPClient(httpClient))
|
|
```
|
|
|
|
### Function Management
|
|
|
|
#### Creating a Function
|
|
|
|
```go
|
|
req := &faasclient.CreateFunctionRequest{
|
|
Name: "my-function",
|
|
AppID: "my-app",
|
|
Runtime: faasclient.RuntimeNodeJS18,
|
|
Image: "node:18-alpine", // Optional, auto-selected if not provided
|
|
Handler: "index.handler",
|
|
Code: "exports.handler = async (event) => { return 'Hello World'; }",
|
|
Environment: map[string]string{
|
|
"NODE_ENV": "production",
|
|
},
|
|
Timeout: faasclient.Duration(30 * time.Second),
|
|
Memory: 512,
|
|
Owner: faasclient.Owner{
|
|
Type: faasclient.OwnerTypeIndividual,
|
|
Name: "John Doe",
|
|
Owner: "john@example.com",
|
|
},
|
|
}
|
|
|
|
function, err := client.CreateFunction(context.Background(), req)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
log.Printf("Created function: %s (ID: %s)", function.Name, function.ID)
|
|
```
|
|
|
|
#### Getting a Function
|
|
|
|
```go
|
|
function, err := client.GetFunction(context.Background(), functionID)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
log.Printf("Function: %s, Runtime: %s", function.Name, function.Runtime)
|
|
```
|
|
|
|
#### Updating a Function
|
|
|
|
```go
|
|
newTimeout := faasclient.Duration(60 * time.Second)
|
|
req := &faasclient.UpdateFunctionRequest{
|
|
Timeout: &newTimeout,
|
|
Environment: map[string]string{
|
|
"NODE_ENV": "development",
|
|
},
|
|
}
|
|
|
|
function, err := client.UpdateFunction(context.Background(), functionID, req)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
```
|
|
|
|
#### Listing Functions
|
|
|
|
```go
|
|
response, err := client.ListFunctions(context.Background(), "my-app", 50, 0)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
for _, fn := range response.Functions {
|
|
log.Printf("Function: %s (ID: %s)", fn.Name, fn.ID)
|
|
}
|
|
```
|
|
|
|
#### Deleting a Function
|
|
|
|
```go
|
|
err := client.DeleteFunction(context.Background(), functionID)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
```
|
|
|
|
### Function Deployment
|
|
|
|
```go
|
|
// Deploy with default options
|
|
resp, err := client.DeployFunction(context.Background(), functionID, nil)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// Force deployment
|
|
req := &faasclient.DeployFunctionRequest{
|
|
Force: true,
|
|
}
|
|
resp, err = client.DeployFunction(context.Background(), functionID, req)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
log.Printf("Deployment status: %s", resp.Status)
|
|
```
|
|
|
|
### Function Execution
|
|
|
|
#### Synchronous Execution
|
|
|
|
```go
|
|
input := json.RawMessage(`{"name": "World"}`)
|
|
req := &faasclient.ExecuteFunctionRequest{
|
|
FunctionID: functionID,
|
|
Input: input,
|
|
Async: false,
|
|
}
|
|
|
|
response, err := client.ExecuteFunction(context.Background(), req)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
log.Printf("Result: %s", string(response.Output))
|
|
log.Printf("Duration: %v", response.Duration)
|
|
```
|
|
|
|
#### Asynchronous Execution
|
|
|
|
```go
|
|
input := json.RawMessage(`{"name": "World"}`)
|
|
response, err := client.InvokeFunction(context.Background(), functionID, input)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
log.Printf("Execution ID: %s", response.ExecutionID)
|
|
log.Printf("Status: %s", response.Status)
|
|
```
|
|
|
|
### Execution Management
|
|
|
|
#### Getting Execution Details
|
|
|
|
```go
|
|
execution, err := client.GetExecution(context.Background(), executionID)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
log.Printf("Status: %s", execution.Status)
|
|
log.Printf("Duration: %v", execution.Duration)
|
|
if execution.Error != "" {
|
|
log.Printf("Error: %s", execution.Error)
|
|
}
|
|
```
|
|
|
|
#### Listing Executions
|
|
|
|
```go
|
|
// List all executions
|
|
response, err := client.ListExecutions(context.Background(), nil, 50, 0)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// List executions for a specific function
|
|
response, err = client.ListExecutions(context.Background(), &functionID, 50, 0)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
for _, exec := range response.Executions {
|
|
log.Printf("Execution: %s, Status: %s", exec.ID, exec.Status)
|
|
}
|
|
```
|
|
|
|
#### Canceling an Execution
|
|
|
|
```go
|
|
err := client.CancelExecution(context.Background(), executionID)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
```
|
|
|
|
#### Getting Execution Logs
|
|
|
|
```go
|
|
logs, err := client.GetExecutionLogs(context.Background(), executionID)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
for _, logLine := range logs.Logs {
|
|
log.Printf("Log: %s", logLine)
|
|
}
|
|
```
|
|
|
|
#### Getting Running Executions
|
|
|
|
```go
|
|
response, err := client.GetRunningExecutions(context.Background())
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
log.Printf("Running executions: %d", response.Count)
|
|
for _, exec := range response.Executions {
|
|
log.Printf("Running: %s (Function: %s)", exec.ID, exec.FunctionID)
|
|
}
|
|
```
|
|
|
|
## Types
|
|
|
|
The client provides comprehensive type definitions that match the FaaS API:
|
|
|
|
- `FunctionDefinition` - Complete function metadata
|
|
- `FunctionExecution` - Execution details and results
|
|
- `RuntimeType` - Supported runtimes (NodeJS18, Python39, Go120, Custom)
|
|
- `ExecutionStatus` - Execution states (Pending, Running, Completed, Failed, etc.)
|
|
- `Owner` - Ownership information
|
|
- Request/Response types for all operations
|
|
|
|
## Error Handling
|
|
|
|
The client provides detailed error messages that include HTTP status codes and response bodies:
|
|
|
|
```go
|
|
function, err := client.GetFunction(ctx, nonExistentID)
|
|
if err != nil {
|
|
// Error will include status code and details
|
|
log.Printf("Error: %v", err) // "get function failed with status 404: Function not found"
|
|
}
|
|
```
|
|
|
|
## Architecture Benefits
|
|
|
|
This client package is designed as a lightweight, standalone library that:
|
|
|
|
- **No heavy dependencies**: Only requires `google/uuid`
|
|
- **Zero coupling**: Doesn't import the entire FaaS service
|
|
- **Modular**: Can be used by any service in your monolith
|
|
- **Type-safe**: Comprehensive Go types for all API operations
|
|
- **Flexible auth**: Supports multiple authentication methods |