cli
import "runvoy/cmd/cli"
Package main implements the runvoy CLI tool. It provides commands for managing users and running remote commands.
Index
local
import "runvoy/cmd/local"
Package main implements the local development server for runvoy. It runs both the orchestrator and async event processor services locally for testing and development.
Index
api
import "runvoy/internal/api"
Package api defines the API types and structures used across runvoy.
Package api defines the API types and structures used across runvoy.
Package api defines the API types and structures used across runvoy.
Package api defines the API types and structures used across runvoy.
Package api defines the API types and structures used across runvoy. This file contains request and response structures for the secrets API.
Package api defines the API types and structures used across runvoy. It contains request and response structures for the orchestrator API.
Package api defines the API types and structures used across runvoy.
Package api defines the API types and structures used across runvoy.
Index
- type AuthorizerHealthStatus
- type ClaimAPIKeyResponse
- type ComputeHealthStatus
- type CreateSecretRequest
- type CreateSecretResponse
- type CreateUserRequest
- type CreateUserResponse
- type DeleteSecretRequest
- type DeleteSecretResponse
- type ErrorResponse
- type Execution
- type ExecutionRequest
- type ExecutionResponse
- type ExecutionStatusResponse
- type GetSecretRequest
- type GetSecretResponse
- type HealthIssue
- type HealthReconcileResponse
- type HealthReport
- type HealthResponse
- type IdentityHealthStatus
- type ImageInfo
- type KillExecutionResponse
- type ListImagesResponse
- type ListSecretsRequest
- type ListSecretsResponse
- type ListUsersResponse
- type LogEvent
- type LogsResponse
- type PendingAPIKey
- type Playbook
- type RegisterImageRequest
- type RegisterImageResponse
- type RelatedResources
- type RemoveImageRequest
- type RemoveImageResponse
- type RevokeUserRequest
- type RevokeUserResponse
- type Secret
- type SecretsHealthStatus
- type TraceResponse
- type UpdateSecretRequest
- type UpdateSecretResponse
- type User
- type WebSocketConnection
- type WebSocketDisconnectReason
- type WebSocketMessage
- type WebSocketMessageType
- type WebSocketToken
type AuthorizerHealthStatus
AuthorizerHealthStatus contains the health status for authorization data.
type AuthorizerHealthStatus struct {
UsersWithInvalidRoles []string `json:"users_with_invalid_roles"`
UsersWithMissingRoles []string `json:"users_with_missing_roles"`
ResourcesWithMissingOwners []string `json:"resources_with_missing_owners"`
OrphanedOwnerships []string `json:"orphaned_ownerships"`
MissingOwnerships []string `json:"missing_ownerships"`
TotalUsersChecked int `json:"total_users_checked"`
TotalResourcesChecked int `json:"total_resources_checked"`
}
type ClaimAPIKeyResponse
ClaimAPIKeyResponse represents the response when claiming an API key
type ClaimAPIKeyResponse struct {
APIKey string `json:"api_key"`
UserEmail string `json:"user_email"`
Message string `json:"message,omitempty"`
}
type ComputeHealthStatus
ComputeHealthStatus contains the health status for compute resources (e.g., containers, task definitions).
type ComputeHealthStatus struct {
TotalResources int `json:"total_resources"`
VerifiedCount int `json:"verified_count"`
RecreatedCount int `json:"recreated_count"`
TagUpdatedCount int `json:"tag_updated_count"`
OrphanedCount int `json:"orphaned_count"`
OrphanedResources []string `json:"orphaned_resources"`
}
type CreateSecretRequest
CreateSecretRequest represents the request to create a new secret
type CreateSecretRequest struct {
Name string `json:"name"` // Internal identifier for the secret
KeyName string `json:"key_name"` // Environment variable name (e.g., GITHUB_TOKEN)
Description string `json:"description,omitempty"`
Value string `json:"value"` // The secret value to store
}
type CreateSecretResponse
CreateSecretResponse represents the response after creating a secret To avoid exposing secret data, only a success message is returned.
type CreateSecretResponse struct {
Message string `json:"message"`
}
type CreateUserRequest
CreateUserRequest represents the request to create a new user
type CreateUserRequest struct {
Email string `json:"email"`
APIKey string `json:"api_key,omitempty"` // Optional: if not provided, one will be generated
Role string `json:"role"` // Required: admin, operator, developer, or viewer
}
type CreateUserResponse
CreateUserResponse represents the response after creating a user
type CreateUserResponse struct {
User *User `json:"user"`
ClaimToken string `json:"claim_token"`
}
type DeleteSecretRequest
DeleteSecretRequest represents the request to delete a secret The secret name is provided in the URL path parameter
type DeleteSecretRequest struct {
Name string `json:"name"` // Secret name from URL path
}
type DeleteSecretResponse
DeleteSecretResponse represents the response after deleting a secret
type DeleteSecretResponse struct {
Name string `json:"name"`
Message string `json:"message"`
}
type ErrorResponse
ErrorResponse represents an error response
type ErrorResponse struct {
Error string `json:"error"`
Code string `json:"code,omitempty"`
Details string `json:"details,omitempty"`
}
type Execution
Execution represents an execution record
type Execution struct {
ExecutionID string `json:"execution_id"`
CreatedBy string `json:"created_by"`
OwnedBy []string `json:"owned_by"`
Command string `json:"command"`
StartedAt time.Time `json:"started_at"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
Status string `json:"status"`
ExitCode int `json:"exit_code"`
DurationSeconds int `json:"duration_seconds,omitempty"`
LogStreamName string `json:"log_stream_name,omitempty"`
CreatedByRequestID string `json:"created_by_request_id"`
ModifiedByRequestID string `json:"modified_by_request_id"`
ComputePlatform string `json:"cloud,omitempty"`
}
type ExecutionRequest
ExecutionRequest represents a request to execute a command
type ExecutionRequest struct {
Command string `json:"command"`
Image string `json:"image,omitempty"`
Env map[string]string `json:"env,omitempty"`
Timeout int `json:"timeout,omitempty"`
Secrets []string `json:"secrets,omitempty"`
// Git repository configuration (optional sidecar pattern)
GitRepo string `json:"git_repo,omitempty"` // Git repository URL (e.g., "https://github.com/user/repo.git")
GitRef string `json:"git_ref,omitempty"` // Git branch, tag, or commit SHA (default: "main")
GitPath string `json:"git_path,omitempty"` // Working directory within the cloned repo (default: ".")
// SecretVarNames contains the environment variable names that should be treated as secrets.
// This is populated by the service layer after resolving secrets from the Secrets field.
// It includes both explicitly resolved secrets and pattern-detected sensitive variables.
SecretVarNames []string `json:"-"` // Not serialized in API responses
}
type ExecutionResponse
ExecutionResponse represents the response to an execution request
type ExecutionResponse struct {
ExecutionID string `json:"execution_id"`
LogURL string `json:"log_url"`
Status string `json:"status"`
ImageID string `json:"image_id"`
}
type ExecutionStatusResponse
ExecutionStatusResponse represents the current status of an execution
type ExecutionStatusResponse struct {
ExecutionID string `json:"execution_id"`
Status string `json:"status"`
StartedAt time.Time `json:"started_at"`
ExitCode *int `json:"exit_code"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
}
type GetSecretRequest
GetSecretRequest represents the request to retrieve a secret The secret name is provided in the URL path parameter
type GetSecretRequest struct {
Name string `json:"name"` // Secret name from URL path
}
type GetSecretResponse
GetSecretResponse represents the response when retrieving a secret
type GetSecretResponse struct {
Secret *Secret `json:"secret"`
}
type HealthIssue
HealthIssue represents a single health issue found during reconciliation.
type HealthIssue struct {
// ResourceType is provider-specific resource type (e.g., "ecs_task_definition", "cloud_run_service")
ResourceType string `json:"resource_type"`
ResourceID string `json:"resource_id"`
Severity string `json:"severity"` // "error", "warning"
Message string `json:"message"`
Action string `json:"action"` // "recreated", "requires_manual_intervention", "reported", "tag_updated"
}
type HealthReconcileResponse
HealthReconcileResponse is returned by POST /api/v1/health/reconcile.
type HealthReconcileResponse struct {
Status string `json:"status"`
Report *HealthReport `json:"report"`
}
type HealthReport
HealthReport contains the results of a health reconciliation run.
type HealthReport struct {
Timestamp time.Time `json:"timestamp"`
ComputeStatus ComputeHealthStatus `json:"compute_status"`
SecretsStatus SecretsHealthStatus `json:"secrets_status"`
IdentityStatus IdentityHealthStatus `json:"identity_status"`
AuthorizerStatus AuthorizerHealthStatus `json:"authorizer_status"`
Issues []HealthIssue `json:"issues"`
ReconciledCount int `json:"reconciled_count"`
ErrorCount int `json:"error_count"`
}
type HealthResponse
HealthResponse represents the response to a health check request
type HealthResponse struct {
Status string `json:"status"`
Version string `json:"version"`
}
type IdentityHealthStatus
IdentityHealthStatus contains the health status for identity and access management resources.
type IdentityHealthStatus struct {
DefaultRolesVerified bool `json:"default_roles_verified"`
CustomRolesVerified int `json:"custom_roles_verified"`
CustomRolesTotal int `json:"custom_roles_total"`
MissingRoles []string `json:"missing_roles"`
}
type ImageInfo
ImageInfo represents information about a registered image
type ImageInfo struct {
ImageID string `json:"image_id"`
Image string `json:"image"`
TaskDefinitionName string `json:"task_definition_name,omitempty"`
IsDefault *bool `json:"is_default,omitempty"`
TaskRoleName *string `json:"task_role_name,omitempty"`
TaskExecutionRoleName *string `json:"task_execution_role_name,omitempty"`
CPU int `json:"cpu,omitempty"`
Memory int `json:"memory,omitempty"`
RuntimePlatform string `json:"runtime_platform,omitempty"`
ImageRegistry string `json:"image_registry,omitempty"`
ImageName string `json:"image_name,omitempty"`
ImageTag string `json:"image_tag,omitempty"`
CreatedBy string `json:"created_by,omitempty"`
OwnedBy []string `json:"owned_by"`
CreatedAt time.Time `json:"created_at"`
CreatedByRequestID string `json:"created_by_request_id"`
ModifiedByRequestID string `json:"modified_by_request_id"`
}
type KillExecutionResponse
KillExecutionResponse represents the response after killing an execution
type KillExecutionResponse struct {
ExecutionID string `json:"execution_id"`
Message string `json:"message"`
}
type ListImagesResponse
ListImagesResponse represents the response containing all registered images
type ListImagesResponse struct {
Images []ImageInfo `json:"images"`
}
type ListSecretsRequest
ListSecretsRequest represents the request to list secrets Optionally filters by user email
type ListSecretsRequest struct {
CreatedBy string `json:"created_by,omitempty"` // Filter by user who created the secret
}
type ListSecretsResponse
ListSecretsResponse represents the response containing all secrets
type ListSecretsResponse struct {
Secrets []*Secret `json:"secrets"`
Total int `json:"total"`
}
type ListUsersResponse
ListUsersResponse represents the response containing all users
type ListUsersResponse struct {
Users []*User `json:"users"`
}
type LogEvent
LogEvent represents a single log event. Events are ordered by timestamp. Clients should sort by timestamp and compute line numbers as needed for display purposes.
type LogEvent struct {
Timestamp int64 `json:"timestamp"` // Unix timestamp in milliseconds
Message string `json:"message"` // The actual log message text
}
type LogsResponse
LogsResponse contains all log events for an execution
type LogsResponse struct {
ExecutionID string `json:"execution_id"`
Events []LogEvent `json:"events"`
// Current execution status (RUNNING, SUCCEEDED, FAILED, STOPPED)
Status string `json:"status"`
// WebSocket URL for streaming logs (only provided if execution is RUNNING)
WebSocketURL string `json:"websocket_url,omitempty"`
}
type PendingAPIKey
PendingAPIKey represents a pending API key awaiting claim
type PendingAPIKey struct {
SecretToken string `json:"secret_token"`
APIKey string `json:"api_key"`
UserEmail string `json:"user_email"`
CreatedBy string `json:"created_by"`
CreatedAt time.Time `json:"created_at"`
ExpiresAt int64 `json:"expires_at"` // Unix timestamp for TTL
Viewed bool `json:"viewed"`
ViewedAt *time.Time `json:"viewed_at,omitempty"`
ViewedFromIP string `json:"viewed_from_ip,omitempty"`
}
type Playbook
Playbook represents a reusable command execution configuration
type Playbook struct {
Description string `yaml:"description,omitempty"`
Image string `yaml:"image,omitempty"`
GitRepo string `yaml:"git_repo,omitempty"`
GitRef string `yaml:"git_ref,omitempty"`
GitPath string `yaml:"git_path,omitempty"`
Secrets []string `yaml:"secrets,omitempty"`
Env map[string]string `yaml:"env,omitempty"`
Commands []string `yaml:"commands"`
}
type RegisterImageRequest
RegisterImageRequest represents the request to register a new Docker image
type RegisterImageRequest struct {
Image string `json:"image"`
IsDefault *bool `json:"is_default,omitempty"`
TaskRoleName *string `json:"task_role_name,omitempty"`
TaskExecutionRoleName *string `json:"task_execution_role_name,omitempty"`
CPU *int `json:"cpu,omitempty"`
Memory *int `json:"memory,omitempty"`
RuntimePlatform *string `json:"runtime_platform,omitempty"`
}
type RegisterImageResponse
RegisterImageResponse represents the response after registering an image
type RegisterImageResponse struct {
Image string `json:"image"`
Message string `json:"message"`
}
type RelatedResources
RelatedResources contains all resources associated with a request ID
type RelatedResources struct {
Executions []*Execution `json:"executions,omitempty"`
Secrets []*Secret `json:"secrets,omitempty"`
Users []*User `json:"users,omitempty"`
Images []ImageInfo `json:"images,omitempty"`
}
type RemoveImageRequest
RemoveImageRequest represents the request to remove a Docker image
type RemoveImageRequest struct {
Image string `json:"image"`
}
type RemoveImageResponse
RemoveImageResponse represents the response after removing an image
type RemoveImageResponse struct {
Image string `json:"image"`
Message string `json:"message"`
}
type RevokeUserRequest
RevokeUserRequest represents the request to revoke a user's API key
type RevokeUserRequest struct {
Email string `json:"email"`
}
type RevokeUserResponse
RevokeUserResponse represents the response after revoking a user
type RevokeUserResponse struct {
Message string `json:"message"`
Email string `json:"email"`
}
type Secret
Secret represents a secret with its metadata and optionally its value
type Secret struct {
Name string `json:"name"` // Internal identifier for the secret
KeyName string `json:"key_name"` // Environment variable name (e.g., GITHUB_TOKEN)
Description string `json:"description,omitempty"`
Value string `json:"value,omitempty"`
CreatedBy string `json:"created_by"`
OwnedBy []string `json:"owned_by"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
UpdatedBy string `json:"updated_by"`
CreatedByRequestID string `json:"created_by_request_id"`
ModifiedByRequestID string `json:"modified_by_request_id"`
}
type SecretsHealthStatus
SecretsHealthStatus contains the health status for secrets/parameters.
type SecretsHealthStatus struct {
TotalSecrets int `json:"total_secrets"`
VerifiedCount int `json:"verified_count"`
TagUpdatedCount int `json:"tag_updated_count"`
MissingCount int `json:"missing_count"`
OrphanedCount int `json:"orphaned_count"`
OrphanedParameters []string `json:"orphaned_parameters"`
}
type TraceResponse
TraceResponse contains logs and related resources for a request ID
type TraceResponse struct {
// Logs retrieved from backend infrastructure
Logs []LogEvent `json:"logs"`
// Related resources associated with this request ID
RelatedResources RelatedResources `json:"related_resources"`
}
type UpdateSecretRequest
UpdateSecretRequest represents the request to update a secret (metadata and/or value) Users can update: description, key_name (environment variable name), and value. Description and KeyName are metadata fields. UpdatedAt is always refreshed. If Value is provided, the secret's value will be updated.
type UpdateSecretRequest struct {
Description string `json:"description,omitempty"` // Environment variable description
KeyName string `json:"key_name,omitempty"` // Environment variable name (e.g., GITHUB_TOKEN)
Value string `json:"value,omitempty"` // If provided, updates the secret value
}
type UpdateSecretResponse
UpdateSecretResponse represents the response after updating a secret To avoid exposing secret data, only a success message is returned.
type UpdateSecretResponse struct {
Message string `json:"message"`
}
type User
User represents a user in the system
type User struct {
Email string `json:"email"`
APIKey string `json:"api_key,omitempty"`
Role string `json:"role"`
CreatedAt time.Time `json:"created_at"`
Revoked bool `json:"revoked"`
LastUsed *time.Time `json:"last_used,omitempty"`
CreatedByRequestID string `json:"created_by_request_id"`
ModifiedByRequestID string `json:"modified_by_request_id"`
}
type WebSocketConnection
WebSocketConnection represents a WebSocket connection record
type WebSocketConnection struct {
ConnectionID string `json:"connection_id"`
ExecutionID string `json:"execution_id"`
Functionality string `json:"functionality"`
ExpiresAt int64 `json:"expires_at"`
ClientIP string `json:"client_ip,omitempty"`
Token string `json:"token,omitempty"`
UserEmail string `json:"user_email,omitempty"`
// Client IP captured when the websocket token was created (for tracing)
TokenRequestClientIP string `json:"token_request_client_ip,omitempty"`
}
type WebSocketDisconnectReason
WebSocketDisconnectReason represents the reason for a disconnect
type WebSocketDisconnectReason string
const (
// WebSocketDisconnectReasonExecutionCompleted indicates the execution has completed
WebSocketDisconnectReasonExecutionCompleted WebSocketDisconnectReason = "execution_completed"
)
type WebSocketMessage
WebSocketMessage represents a WebSocket message sent to clients
type WebSocketMessage struct {
Type WebSocketMessageType `json:"type"`
Reason *WebSocketDisconnectReason `json:"reason,omitempty"`
Message *string `json:"message,omitempty"`
Timestamp *int64 `json:"timestamp,omitempty"`
}
type WebSocketMessageType
WebSocketMessageType represents the type of WebSocket message
type WebSocketMessageType string
const (
// WebSocketMessageTypeLog represents a log event message
WebSocketMessageTypeLog WebSocketMessageType = "log"
// WebSocketMessageTypeDisconnect represents a disconnect notification message
WebSocketMessageTypeDisconnect WebSocketMessageType = "disconnect"
)
type WebSocketToken
WebSocketToken represents a WebSocket authentication token
type WebSocketToken struct {
Token string `json:"token"`
ExecutionID string `json:"execution_id"`
UserEmail string `json:"user_email,omitempty"`
// Client IP captured when the websocket token was created (for tracing)
ClientIP string `json:"client_ip,omitempty"`
ExpiresAt int64 `json:"expires_at"`
CreatedAt int64 `json:"created_at"`
}
auth
import "runvoy/internal/auth"
Package auth provides authentication utilities for runvoy.
Index
- func GenerateSecretToken() (string, error)
- func GenerateUUID() string
- func HashAPIKey(apiKey string) string
func GenerateSecretToken
func GenerateSecretToken() (string, error)
GenerateSecretToken creates a cryptographically secure random secret token. Used for claim URLs, WebSocket authentication, and other temporary access tokens. The token is base64-encoded and approximately 32 characters long.
func GenerateUUID
func GenerateUUID() string
GenerateUUID generates a UUID-like identifier using crypto/rand. Returns a hex-encoded string of 32 characters (16 random bytes). Used for generating unique identifiers such as task definition family names.
func HashAPIKey
func HashAPIKey(apiKey string) string
HashAPIKey creates a SHA-256 hash of the API key for secure storage. NOTICE: we never store plain API keys in the database.
client
import "runvoy/internal/client"
Package client provides HTTP client functionality for the runvoy API. It handles authentication, request/response serialization, and error handling.
Package client provides HTTP client functionality for the runvoy API.
Index
- type Client
- func New(cfg *config.Config, log *slog.Logger) *Client
- func (c *Client) ClaimAPIKey(ctx context.Context, token string) (*api.ClaimAPIKeyResponse, error)
- func (c *Client) CreateSecret(ctx context.Context, req api.CreateSecretRequest) (*api.CreateSecretResponse, error)
- func (c *Client) CreateUser(ctx context.Context, req api.CreateUserRequest) (*api.CreateUserResponse, error)
- func (c *Client) DeleteSecret(ctx context.Context, name string) (*api.DeleteSecretResponse, error)
- func (c *Client) Do(ctx context.Context, req Request) (*Response, error)
- func (c *Client) DoJSON(ctx context.Context, req Request, result any) error
- func (c *Client) FetchBackendLogs(ctx context.Context, requestID string) (*api.TraceResponse, error)
- func (c *Client) GetExecutionStatus(ctx context.Context, executionID string) (*api.ExecutionStatusResponse, error)
- func (c *Client) GetHealth(ctx context.Context) (*api.HealthResponse, error)
- func (c *Client) GetImage(ctx context.Context, image string) (*api.ImageInfo, error)
- func (c *Client) GetLogs(ctx context.Context, executionID string) (*api.LogsResponse, error)
- func (c *Client) GetSecret(ctx context.Context, name string) (*api.GetSecretResponse, error)
- func (c *Client) KillExecution(ctx context.Context, executionID string) (*api.KillExecutionResponse, error)
- func (c *Client) ListExecutions(ctx context.Context, limit int, statuses string) ([]api.Execution, error)
- func (c *Client) ListImages(ctx context.Context) (*api.ListImagesResponse, error)
- func (c *Client) ListSecrets(ctx context.Context) (*api.ListSecretsResponse, error)
- func (c *Client) ListUsers(ctx context.Context) (*api.ListUsersResponse, error)
- func (c *Client) ReconcileHealth(ctx context.Context) (*api.HealthReconcileResponse, error)
- func (c *Client) RegisterImage(ctx context.Context, image string, isDefault *bool, taskRoleName, taskExecutionRoleName *string, cpu, memory *int, runtimePlatform *string) (*api.RegisterImageResponse, error)
- func (c *Client) RevokeUser(ctx context.Context, req api.RevokeUserRequest) (*api.RevokeUserResponse, error)
- func (c *Client) RunCommand(ctx context.Context, req *api.ExecutionRequest) (*api.ExecutionResponse, error)
- func (c *Client) UnregisterImage(ctx context.Context, image string) (*api.RemoveImageResponse, error)
- func (c *Client) UpdateSecret(ctx context.Context, name string, req api.UpdateSecretRequest) (*api.UpdateSecretResponse, error)
- type Interface
- type Request
- type Response
type Client
Client provides a generic HTTP client for API operations
type Client struct {
// contains filtered or unexported fields
}
func New
func New(cfg *config.Config, log *slog.Logger) *Client
New creates a new API client
func (*Client) ClaimAPIKey
func (c *Client) ClaimAPIKey(ctx context.Context, token string) (*api.ClaimAPIKeyResponse, error)
ClaimAPIKey claims a user's API key
func (*Client) CreateSecret
func (c *Client) CreateSecret(ctx context.Context, req api.CreateSecretRequest) (*api.CreateSecretResponse, error)
CreateSecret creates a new secret
func (*Client) CreateUser
func (c *Client) CreateUser(ctx context.Context, req api.CreateUserRequest) (*api.CreateUserResponse, error)
CreateUser creates a new user using the API
func (*Client) DeleteSecret
func (c *Client) DeleteSecret(ctx context.Context, name string) (*api.DeleteSecretResponse, error)
DeleteSecret deletes a secret by name
func (*Client) Do
func (c *Client) Do(ctx context.Context, req Request) (*Response, error)
Do makes an HTTP request to the API
func (*Client) DoJSON
func (c *Client) DoJSON(ctx context.Context, req Request, result any) error
DoJSON makes a request and unmarshals the response into the provided interface
func (*Client) FetchBackendLogs
func (c *Client) FetchBackendLogs(ctx context.Context, requestID string) (*api.TraceResponse, error)
FetchBackendLogs fetches backend infrastructure logs and related resources for a request ID
func (*Client) GetExecutionStatus
func (c *Client) GetExecutionStatus(ctx context.Context, executionID string) (*api.ExecutionStatusResponse, error)
GetExecutionStatus gets the status of an execution
func (*Client) GetHealth
func (c *Client) GetHealth(ctx context.Context) (*api.HealthResponse, error)
GetHealth checks the API health status
func (*Client) GetImage
func (c *Client) GetImage(ctx context.Context, image string) (*api.ImageInfo, error)
GetImage retrieves a single container image by ID or name
func (*Client) GetLogs
func (c *Client) GetLogs(ctx context.Context, executionID string) (*api.LogsResponse, error)
GetLogs gets the logs for an execution The response includes a WebSocketURL field for streaming logs if WebSocket is configured
func (*Client) GetSecret
func (c *Client) GetSecret(ctx context.Context, name string) (*api.GetSecretResponse, error)
GetSecret retrieves a secret by name
func (*Client) KillExecution
func (c *Client) KillExecution(ctx context.Context, executionID string) (*api.KillExecutionResponse, error)
KillExecution stops a running execution by its ID Returns nil response if the execution was already terminated (204 No Content)
func (*Client) ListExecutions
func (c *Client) ListExecutions(ctx context.Context, limit int, statuses string) ([]api.Execution, error)
ListExecutions fetches executions with optional filtering and pagination. Parameters:
- limit: maximum number of executions to return (0 returns all)
- statuses: comma-separated list of execution statuses to filter by (e.g., "RUNNING,TERMINATING")
func (*Client) ListImages
func (c *Client) ListImages(ctx context.Context) (*api.ListImagesResponse, error)
ListImages retrieves all registered container images
func (*Client) ListSecrets
func (c *Client) ListSecrets(ctx context.Context) (*api.ListSecretsResponse, error)
ListSecrets lists all secrets
func (*Client) ListUsers
func (c *Client) ListUsers(ctx context.Context) (*api.ListUsersResponse, error)
ListUsers lists all users
func (*Client) ReconcileHealth
func (c *Client) ReconcileHealth(ctx context.Context) (*api.HealthReconcileResponse, error)
ReconcileHealth triggers a full health reconciliation on the server. Requires authentication and returns a reconciliation report.
func (*Client) RegisterImage
func (c *Client) RegisterImage(ctx context.Context, image string, isDefault *bool, taskRoleName, taskExecutionRoleName *string, cpu, memory *int, runtimePlatform *string) (*api.RegisterImageResponse, error)
RegisterImage registers a new container image for execution, optionally marking it as the default
func (*Client) RevokeUser
func (c *Client) RevokeUser(ctx context.Context, req api.RevokeUserRequest) (*api.RevokeUserResponse, error)
RevokeUser revokes a user's API key
func (*Client) RunCommand
func (c *Client) RunCommand(ctx context.Context, req *api.ExecutionRequest) (*api.ExecutionResponse, error)
RunCommand executes a command remotely via the runvoy API.
func (*Client) UnregisterImage
func (c *Client) UnregisterImage(ctx context.Context, image string) (*api.RemoveImageResponse, error)
UnregisterImage removes a container image from the registry
func (*Client) UpdateSecret
func (c *Client) UpdateSecret(ctx context.Context, name string, req api.UpdateSecretRequest) (*api.UpdateSecretResponse, error)
UpdateSecret updates a secret by name
type Interface
Interface defines the API client interface for dependency injection and testing
type Interface interface {
// Health
ReconcileHealth(ctx context.Context) (*api.HealthReconcileResponse, error)
GetLogs(ctx context.Context, executionID string) (*api.LogsResponse, error)
FetchBackendLogs(ctx context.Context, requestID string) (*api.TraceResponse, error)
GetExecutionStatus(ctx context.Context, executionID string) (*api.ExecutionStatusResponse, error)
RunCommand(ctx context.Context, req *api.ExecutionRequest) (*api.ExecutionResponse, error)
KillExecution(ctx context.Context, executionID string) (*api.KillExecutionResponse, error)
ListExecutions(ctx context.Context, limit int, statuses string) ([]api.Execution, error)
ClaimAPIKey(ctx context.Context, token string) (*api.ClaimAPIKeyResponse, error)
CreateUser(ctx context.Context, req api.CreateUserRequest) (*api.CreateUserResponse, error)
RevokeUser(ctx context.Context, req api.RevokeUserRequest) (*api.RevokeUserResponse, error)
ListUsers(ctx context.Context) (*api.ListUsersResponse, error)
RegisterImage(
ctx context.Context,
image string,
isDefault *bool,
taskRoleName, taskExecutionRoleName *string,
cpu, memory *int,
runtimePlatform *string,
) (*api.RegisterImageResponse, error)
ListImages(ctx context.Context) (*api.ListImagesResponse, error)
GetImage(ctx context.Context, image string) (*api.ImageInfo, error)
UnregisterImage(ctx context.Context, image string) (*api.RemoveImageResponse, error)
CreateSecret(ctx context.Context, req api.CreateSecretRequest) (*api.CreateSecretResponse, error)
GetSecret(ctx context.Context, name string) (*api.GetSecretResponse, error)
ListSecrets(ctx context.Context) (*api.ListSecretsResponse, error)
UpdateSecret(ctx context.Context, name string, req api.UpdateSecretRequest) (*api.UpdateSecretResponse, error)
DeleteSecret(ctx context.Context, name string) (*api.DeleteSecretResponse, error)
}
type Request
Request represents an API request
type Request struct {
Method string
Path string
Body any
}
type Response
Response represents an API response
type Response struct {
StatusCode int
Body []byte
}
config
import "runvoy/internal/config"
Package config manages configuration for the runvoy CLI and services. It uses Viper for unified configuration management from files and environment variables.
Index
- func GetConfigPath() (string, error)
- func Save(config *Config) error
- type Config
- func Load() (*Config, error)
- func LoadCLI() (*Config, error)
- func LoadEventProcessor() (*Config, error)
- func LoadOrchestrator() (*Config, error)
- func MustLoadEventProcessor() *Config
- func MustLoadOrchestrator() *Config
- func (c *Config) GetDefaultStackName() string
- func (c *Config) GetLogLevel() slog.Level
- func (c *Config) GetProviderIdentifier() string
func GetConfigPath
func GetConfigPath() (string, error)
GetConfigPath returns the path to the config file
func Save
func Save(config *Config) error
Save saves the configuration to the user's home directory. Overwrites the existing config file if it exists.
type Config
Config represents the unified configuration structure for both CLI and services. It supports loading from YAML files and environment variables. Provider-specific configurations are nested under their respective provider keys.
type Config struct {
// CLI Configuration
APIEndpoint string `mapstructure:"api_endpoint" yaml:"api_endpoint" validate:"omitempty,url"`
APIKey string `mapstructure:"api_key" yaml:"api_key"`
WebURL string `mapstructure:"web_url" yaml:"web_url" validate:"omitempty,url"`
// Backend Service Configuration
BackendProvider constants.BackendProvider `mapstructure:"backend_provider" yaml:"backend_provider"`
InitTimeout time.Duration `mapstructure:"init_timeout"`
LogLevel string `mapstructure:"log_level"`
Port int `mapstructure:"port" validate:"omitempty"`
RequestTimeout time.Duration `mapstructure:"request_timeout"`
CORSAllowedOrigins []string `mapstructure:"cors_allowed_origins" yaml:"cors_allowed_origins"`
// Provider-specific configurations
AWS *awsconfig.Config `mapstructure:"aws" yaml:"aws,omitempty"`
}
func Load
func Load() (*Config, error)
Load loads the configuration using Viper. For CLI: loads from \~/.runvoy/config.yaml For services: loads from environment variables with RUNVOY_ prefix Environment variables take precedence over config file values.
func LoadCLI
func LoadCLI() (*Config, error)
LoadCLI loads configuration specifically for CLI usage. Returns an error if the config file doesn't exist.
func LoadEventProcessor
func LoadEventProcessor() (*Config, error)
LoadEventProcessor loads configuration for the event processor service. Loads from environment variables and validates required fields.
func LoadOrchestrator
func LoadOrchestrator() (*Config, error)
LoadOrchestrator loads configuration for the orchestrator service. Loads from environment variables and validates required fields. This maintains parity with the Lambda orchestrator which requires all AWS resources.
func MustLoadEventProcessor
func MustLoadEventProcessor() *Config
MustLoadEventProcessor loads event processor configuration and exits on error. Suitable for application startup where configuration errors should be fatal.
func MustLoadOrchestrator
func MustLoadOrchestrator() *Config
MustLoadOrchestrator loads orchestrator configuration and exits on error. Suitable for application startup where configuration errors should be fatal.
func (*Config) GetDefaultStackName
func (c *Config) GetDefaultStackName() string
GetDefaultStackName returns the default infrastructure stack name. Returns the configured value or the default if not set.
func (*Config) GetLogLevel
func (c *Config) GetLogLevel() slog.Level
GetLogLevel returns the slog.Level from the string configuration. Defaults to INFO if the level string is invalid.
func (*Config) GetProviderIdentifier
func (c *Config) GetProviderIdentifier() string
GetProviderIdentifier returns the lowercase provider identifier string. For AWS, returns "aws".
constants
import "runvoy/internal/constants"
Package constants defines global constants used throughout runvoy.
Package constants defines global constants used throughout runvoy.
Package constants defines global constants used throughout runvoy.
Package constants defines global constants used throughout runvoy.
Package constants defines global constants used throughout runvoy.
Package constants defines global constants used throughout runvoy.
Package constants defines global constants used throughout runvoy.
Package constants defines global constants used throughout runvoy.
Package constants defines global constants used throughout runvoy.
Package constants defines global constants used throughout runvoy.
Package constants defines global constants used throughout runvoy.
Package constants defines global constants used throughout runvoy.
Package constants defines global constants used throughout runvoy.
Package constants defines global constants used throughout runvoy.
Index
- Constants
- Variables
- func CanTransition(from, to ExecutionStatus) bool
- func ConfigDirPath(homeDir string) string
- func ConfigFilePath(homeDir string) string
- func GetVersion() *string
- type BackendProvider
- type ConfigCtxKeyType
- type Environment
- type ExecutionStatus
- func TerminalExecutionStatuses() []ExecutionStatus
- type Service
- type StartTimeCtxKeyType
Constants
APIKeyByteSize is the number of random bytes used to generate API keys
const APIKeyByteSize = 24
APIKeyHeader is the HTTP header name for API key authentication
const APIKeyHeader = "X-API-Key"
BoxBorderPadding is the padding used in box borders
const BoxBorderPadding = 2
ClaimURLExpirationMinutes is the number of minutes after which a claim URL expires
const ClaimURLExpirationMinutes = 15
ConfigDirName is the name of the configuration directory in the user's home directory
const ConfigDirName = "." + ProjectName
ConfigDirPermissions is the file system permissions for config directory (0750)
const ConfigDirPermissions = 0750
ConfigFileName is the name of the global configuration file
const ConfigFileName = "config.yaml"
ConfigFilePermissions is the file system permissions for config file (0600)
const ConfigFilePermissions = 0600
ConnectionTTLHours is the time-to-live for connection records in the database (24 hours)
const ConnectionTTLHours = 24
ContentTypeHeader is the HTTP Content-Type header name.
const ContentTypeHeader = "Content-Type"
DefaultContextTimeout is the default timeout for context operations
const DefaultContextTimeout = 10 * time.Second
DefaultGitRef is the default Git reference to use if no reference is provided
const DefaultGitRef = "main"
DefaultWebURL is the default URL of the web application HTML file. This can be overridden via configuration (RUNVOY_WEB_URL env var or config file).
const DefaultWebURL = "https://runvoy.site/"
EnvVarSplitLimit is the limit for splitting environment variable strings (KEY=VALUE)
const EnvVarSplitLimit = 2
ExecutionsSliceInitialCapacity is the initial capacity for executions slices
const ExecutionsSliceInitialCapacity = 64
ExpectedArgsCreateConfigFile is the expected number of arguments for create-config-file script
const ExpectedArgsCreateConfigFile = 2
ExpectedArgsSeedAdminUser is the expected number of arguments for seed-admin-user script
const ExpectedArgsSeedAdminUser = 3
ExpectedArgsTruncateDynamoDBTable is the expected number of arguments for truncate-dynamodb-table script
const ExpectedArgsTruncateDynamoDBTable = 2
FunctionalityLogStreaming identifies connections used for streaming execution logs
const FunctionalityLogStreaming = "log_streaming"
HTTPStatusBadRequest is the HTTP status code for bad requests (400)
const HTTPStatusBadRequest = 400
HTTPStatusServerError is the HTTP status code for server errors (500)
const HTTPStatusServerError = 500
HeaderSeparatorLength is the length of the header separator line
const HeaderSeparatorLength = 50
LocalDevelopmentURL is the default URL of the local development server.
const LocalDevelopmentURL = "http://localhost:5173/"
LongScriptContextTimeout is the timeout for longer script context operations
const LongScriptContextTimeout = 30 * time.Second
MaxConcurrentSends is the maximum number of concurrent sends to WebSocket connections
const MaxConcurrentSends = 10
MillisecondsPerSecond is the number of milliseconds in a second
const MillisecondsPerSecond = 1000
MinimumArgsDeleteS3Buckets is the minimum number of arguments for delete-s3-buckets script (script name + at least 1 bucket)
const MinimumArgsDeleteS3Buckets = 2
MinimumArgsUpdateReadmeHelp is the minimum number of arguments for update-readme-help script
const MinimumArgsUpdateReadmeHelp = 2
MinutesPerHour is the number of minutes in an hour
const MinutesPerHour = 60
PercentageMultiplier is the multiplier to convert fraction to percentage
const PercentageMultiplier = 100
PlaybookDirName is the name of the playbook directory in the current working directory
const PlaybookDirName = ".runvoy"
ProgressBarWidth is the default width for progress bars
const ProgressBarWidth = 40
ProjectName is the name of the CLI tool and application
const ProjectName = "runvoy"
RegexMatchCountEnvVar is the expected number of regex matches for environment variable parsing
const RegexMatchCountEnvVar = 3
RequestIDLogField is the field name used for request ID in log entries
const RequestIDLogField = "request_id"
ResourceApplicationTagKey is the tag key for Application. This tag is used to identify the application that manages a resource.
const ResourceApplicationTagKey = "Application"
ResourceManagedByTagKey is the tag key for ManagedBy. This tag is used to identify what system or tool manages a resource.
const ResourceManagedByTagKey = "ManagedBy"
ScriptContextTimeout is the timeout for script context operations
const ScriptContextTimeout = 10 * time.Second
SecondsPerMinute is the number of seconds in a minute
const SecondsPerMinute = 60
SecretTokenByteSize is the number of random bytes used to generate secret tokens
const SecretTokenByteSize = 24
ServerIdleTimeout is the HTTP server idle timeout
const ServerIdleTimeout = 60 * time.Second
ServerReadTimeout is the HTTP server read timeout
const ServerReadTimeout = 15 * time.Second
ServerShutdownTimeout is the timeout for graceful server shutdown
const ServerShutdownTimeout = 5 * time.Second
ServerWriteTimeout is the HTTP server write timeout
const ServerWriteTimeout = 15 * time.Second
SpinnerTickerInterval is the interval between spinner frame updates
const SpinnerTickerInterval = 80 * time.Millisecond
TestContextTimeout is the timeout for test contexts
const TestContextTimeout = 5 * time.Second
UUIDByteSize is the number of random bytes used to generate UUIDs 16 bytes = 128 bits, same as a UUID
const UUIDByteSize = 16
Variables
DefaultCORSAllowedOrigins is the default list of allowed CORS origins. Defaults to the web application URL and local development URL.
var DefaultCORSAllowedOrigins = []string{
DefaultWebURL,
LocalDevelopmentURL,
}
PlaybookFileExtensions are the valid file extensions for playbook files
var PlaybookFileExtensions = []string{".yaml", ".yml"}
func CanTransition
func CanTransition(from, to ExecutionStatus) bool
CanTransition checks if a status transition from 'from' to 'to' is valid. Returns true if the transition is allowed, false otherwise. If the source status is not in the validTransitions map, returns false.
func ConfigDirPath
func ConfigDirPath(homeDir string) string
ConfigDirPath returns the full path to the global configuration directory.
func ConfigFilePath
func ConfigFilePath(homeDir string) string
ConfigFilePath returns the full path to the global configuration file
func GetVersion
func GetVersion() *string
GetVersion returns the current version of runvoy.
type BackendProvider
BackendProvider represents the backend infrastructure provider.
type BackendProvider string
const (
// AWS is the Amazon Web Services backend provider.
AWS BackendProvider = "AWS"
)
type ConfigCtxKeyType
ConfigCtxKeyType is the type for the config context key
type ConfigCtxKeyType string
ConfigCtxKey is the key used to store config in context
const ConfigCtxKey ConfigCtxKeyType = "config"
type Environment
Environment represents the execution environment (e.g., CLI, Lambda).
type Environment string
Environment types for logger configuration
const (
Development Environment = "development"
Production Environment = "production"
CLI Environment = "cli"
)
type ExecutionStatus
ExecutionStatus represents the business-level status of a command execution. This is distinct from EcsStatus, which reflects the AWS ECS task lifecycle. Execution statuses are used throughout the API and stored in the database.
type ExecutionStatus string
const (
// ExecutionStarting indicates the command has been accepted and is being scheduled
ExecutionStarting ExecutionStatus = "STARTING"
// ExecutionRunning indicates the command is currently executing
ExecutionRunning ExecutionStatus = "RUNNING"
// ExecutionSucceeded indicates the command completed successfully
ExecutionSucceeded ExecutionStatus = "SUCCEEDED"
// ExecutionFailed indicates the command failed with an error
ExecutionFailed ExecutionStatus = "FAILED"
// ExecutionStopped indicates the command was manually terminated
ExecutionStopped ExecutionStatus = "STOPPED"
// ExecutionTerminating indicates a stop request is in progress
ExecutionTerminating ExecutionStatus = "TERMINATING"
// DefaultExecutionListLimit is the default number of executions returned by the list endpoint
DefaultExecutionListLimit = 10
)
func TerminalExecutionStatuses
func TerminalExecutionStatuses() []ExecutionStatus
TerminalExecutionStatuses returns all statuses that represent completed executions
type Service
Service represents a runvoy service component.
type Service string
const (
// OrchestratorService is the main orchestrator service.
OrchestratorService Service = "orchestrator"
// EventProcessorService is the event processing service.
EventProcessorService Service = "event-processor"
)
type StartTimeCtxKeyType
StartTimeCtxKeyType is the type for start time context keys
type StartTimeCtxKeyType string
StartTimeCtxKey is the key used to store the start time in context
const StartTimeCtxKey StartTimeCtxKeyType = "startTime"
database
import "runvoy/internal/database"
Package database defines repository interfaces for data persistence. It provides abstractions for user and execution storage.
Package database defines the repository interfaces for data persistence. This file contains the SecretsRepository interface for secret metadata management.
Index
- Variables
- type ConnectionRepository
- type ExecutionRepository
- type ImageRepository
- type Repositories
- type SecretsRepository
- type TokenRepository
- type UserRepository
Variables
Errors for secrets operations
var (
ErrSecretNotFound = appErrors.ErrSecretNotFound("secret not found", nil)
ErrSecretAlreadyExists = appErrors.ErrSecretAlreadyExists("secret already exists", nil)
)
type ConnectionRepository
ConnectionRepository defines the interface for WebSocket connection-related database operations.
type ConnectionRepository interface {
// CreateConnection stores a new WebSocket connection record in the database.
CreateConnection(ctx context.Context, connection *api.WebSocketConnection) error
// DeleteConnections removes WebSocket connections from the database.
DeleteConnections(ctx context.Context, connectionIDs []string) (int, error)
// GetConnectionsByExecutionID retrieves all active WebSocket connection records for a given execution ID.
// Returns the complete connection objects including token and other metadata.
GetConnectionsByExecutionID(ctx context.Context, executionID string) ([]*api.WebSocketConnection, error)
}
type ExecutionRepository
ExecutionRepository defines the interface for execution-related database operations.
type ExecutionRepository interface {
// CreateExecution stores a new execution record in the database.
CreateExecution(ctx context.Context, execution *api.Execution) error
// GetExecution retrieves an execution by its execution ID.
GetExecution(ctx context.Context, executionID string) (*api.Execution, error)
// UpdateExecution updates an existing execution record.
UpdateExecution(ctx context.Context, execution *api.Execution) error
// ListExecutions returns executions from the database with optional filtering and pagination.
// Parameters:
// - limit: maximum number of executions to return. Use 0 to fetch all executions.
// - statuses: optional slice of execution statuses to filter by.
// If empty, all executions are returned.
// Results are ordered newest first.
ListExecutions(ctx context.Context, limit int, statuses []string) ([]*api.Execution, error)
// GetExecutionsByRequestID retrieves all executions created or modified by a specific request ID.
GetExecutionsByRequestID(ctx context.Context, requestID string) ([]*api.Execution, error)
}
type ImageRepository
ImageRepository defines the interface for image metadata storage operations.
type ImageRepository interface {
// GetImagesByRequestID retrieves all images created or modified by a specific request ID.
GetImagesByRequestID(ctx context.Context, requestID string) ([]api.ImageInfo, error)
}
type Repositories
Repositories groups all database repository interfaces together. This struct is used to pass repositories as a cohesive unit while maintaining explicit access to individual repositories in service methods.
type Repositories struct {
User UserRepository
Execution ExecutionRepository
Connection ConnectionRepository
Token TokenRepository
Image ImageRepository
Secrets SecretsRepository
}
type SecretsRepository
SecretsRepository defines the interface for persisting secret data. Implementations handle storing and retrieving secrets in their preferred storage backend.
type SecretsRepository interface {
// CreateSecret stores a new secret.
// The secret's CreatedBy field must be set by the caller.
// The repository sets CreatedAt and UpdatedAt timestamps.
// Returns an error if a secret with the same name already exists.
CreateSecret(ctx context.Context, secret *api.Secret) error
// GetSecret retrieves a secret by name.
// If includeValue is true, the secret value will be decrypted and included in the response.
// Returns an error if the secret is not found.
GetSecret(ctx context.Context, name string, includeValue bool) (*api.Secret, error)
// ListSecrets retrieves all secrets.
// If includeValue is true, secret values will be decrypted and included in the response.
ListSecrets(ctx context.Context, includeValue bool) ([]*api.Secret, error)
// UpdateSecret updates a secret's value and/or editable properties.
// The secret's UpdatedBy field must be set by the caller.
// The Name field identifies which secret to update.
// The updatedAt timestamp is always refreshed.
// Returns an error if the secret is not found.
UpdateSecret(ctx context.Context, secret *api.Secret) error
// DeleteSecret removes a secret from storage.
// Returns an error if the secret is not found.
DeleteSecret(ctx context.Context, name string) error
// GetSecretsByRequestID retrieves all secrets created or modified by a specific request ID.
GetSecretsByRequestID(ctx context.Context, requestID string) ([]*api.Secret, error)
}
type TokenRepository
TokenRepository defines the interface for WebSocket token validation operations.
type TokenRepository interface {
// CreateToken stores a new WebSocket authentication token with metadata.
CreateToken(ctx context.Context, token *api.WebSocketToken) error
// GetToken retrieves a token by its value and validates it hasn't expired.
// Returns nil if the token doesn't exist or has expired (DynamoDB TTL handles expiration).
GetToken(ctx context.Context, tokenValue string) (*api.WebSocketToken, error)
// DeleteToken removes a token from the database (used after validation or explicit cleanup).
DeleteToken(ctx context.Context, tokenValue string) error
}
type UserRepository
UserRepository defines the interface for user-related database operations. This abstraction allows for different implementations (DynamoDB, PostgreSQL, etc.) without changing the business logic layer.
type UserRepository interface {
// CreateUser stores a new user with their hashed API key in the database.
// If expiresAtUnix is 0, no TTL is set (permanent user).
// If expiresAtUnix is > 0, it sets expires_at for automatic deletion.
// Returns an error if the user already exists or if the operation fails.
CreateUser(ctx context.Context, user *api.User, apiKeyHash string, expiresAtUnix int64) error
// RemoveExpiration removes the expires_at field from a user record, making them permanent.
RemoveExpiration(ctx context.Context, email string) error
// GetUserByEmail retrieves a user by their email address.
// Returns nil if the user doesn't exist.
GetUserByEmail(ctx context.Context, email string) (*api.User, error)
// GetUserByAPIKeyHash retrieves a user by their hashed API key.
// Used for authentication. Returns nil if no user has this API key.
GetUserByAPIKeyHash(ctx context.Context, apiKeyHash string) (*api.User, error)
// UpdateLastUsed updates the last_used timestamp for a user.
// Called after successful API key authentication.
UpdateLastUsed(ctx context.Context, email string) (*time.Time, error)
// RevokeUser marks a user's API key as revoked without deleting the record.
// Useful for audit trails.
RevokeUser(ctx context.Context, email string) error
// CreatePendingAPIKey stores a pending API key with a secret token.
CreatePendingAPIKey(ctx context.Context, pending *api.PendingAPIKey) error
// GetPendingAPIKey retrieves a pending API key by its secret token.
// Returns nil if the token doesn't exist or has expired.
GetPendingAPIKey(ctx context.Context, secretToken string) (*api.PendingAPIKey, error)
// MarkAsViewed atomically marks a pending key as viewed with the IP address.
MarkAsViewed(ctx context.Context, secretToken string, ipAddress string) error
// DeletePendingAPIKey removes a pending API key from the database.
DeletePendingAPIKey(ctx context.Context, secretToken string) error
// ListUsers returns all users in the system (excluding API key hashes for security).
// Used by admins to view all users and their basic information.
ListUsers(ctx context.Context) ([]*api.User, error)
// GetUsersByRequestID retrieves all users created or modified by a specific request ID.
GetUsersByRequestID(ctx context.Context, requestID string) ([]*api.User, error)
}
errors
import "runvoy/internal/errors"
Package errors provides error types and handling for runvoy. It includes custom error types with HTTP status codes and error codes.
Index
- Constants
- func GetErrorCode(err error) string
- func GetErrorDetails(err error) string
- func GetErrorMessage(err error) string
- func GetStatusCode(err error) int
- type AppError
- func ErrAPIKeyRevoked(cause error) *AppError
- func ErrBadRequest(message string, cause error) *AppError
- func ErrConflict(message string, cause error) *AppError
- func ErrDatabaseError(message string, cause error) *AppError
- func ErrForbidden(message string, cause error) *AppError
- func ErrInternalError(message string, cause error) *AppError
- func ErrInvalidAPIKey(cause error) *AppError
- func ErrNotFound(message string, cause error) *AppError
- func ErrSecretAlreadyExists(message string, cause error) *AppError
- func ErrSecretNotFound(message string, cause error) *AppError
- func ErrServiceUnavailable(message string, cause error) *AppError
- func ErrUnauthorized(message string, cause error) *AppError
- func NewClientError(statusCode int, code, message string, cause error) *AppError
- func NewServerError(statusCode int, code, message string, cause error) *AppError
- func (e *AppError) Error() string
- func (e *AppError) Is(target error) bool
- func (e *AppError) Unwrap() error
Constants
Predefined error codes
const (
// Client error codes
ErrCodeInvalidRequest = "INVALID_REQUEST"
ErrCodeUnauthorized = "UNAUTHORIZED"
ErrCodeForbidden = "FORBIDDEN"
ErrCodeNotFound = "NOT_FOUND"
ErrCodeConflict = "CONFLICT"
ErrCodeSecretNotFound = "SECRET_NOT_FOUND"
ErrCodeSecretExists = "SECRET_ALREADY_EXISTS"
ErrCodeInvalidAPIKey = "INVALID_API_KEY" //nolint:gosec
ErrCodeAPIKeyRevoked = "API_KEY_REVOKED" //nolint:gosec
// Server error codes
ErrCodeInternalError = "INTERNAL_ERROR"
ErrCodeDatabaseError = "DATABASE_ERROR"
ErrCodeServiceUnavailable = "SERVICE_UNAVAILABLE"
)
func GetErrorCode
func GetErrorCode(err error) string
GetErrorCode extracts the error code from an error. Returns empty string if the error is not an AppError.
func GetErrorDetails
func GetErrorDetails(err error) string
GetErrorDetails extracts detailed error information including the underlying cause. Returns the underlying error message if available, otherwise returns the main error message.
func GetErrorMessage
func GetErrorMessage(err error) string
GetErrorMessage extracts a user-friendly message from an error.
func GetStatusCode
func GetStatusCode(err error) int
GetStatusCode extracts the HTTP status code from an error. Returns 500 if the error is not an AppError.
type AppError
AppError represents an application error with an associated HTTP status code.
type AppError struct {
// Code is an optional error code string for programmatic handling
Code string
// Message is a user-friendly error message
Message string
// StatusCode is the HTTP status code to return
StatusCode int
// Cause is the underlying error (for error wrapping)
Cause error
}
func ErrAPIKeyRevoked
func ErrAPIKeyRevoked(cause error) *AppError
ErrAPIKeyRevoked creates an API key revoked error (401).
func ErrBadRequest
func ErrBadRequest(message string, cause error) *AppError
ErrBadRequest creates a bad request error (400).
func ErrConflict
func ErrConflict(message string, cause error) *AppError
ErrConflict creates a conflict error (409).
func ErrDatabaseError
func ErrDatabaseError(message string, cause error) *AppError
ErrDatabaseError creates a database error (503 Service Unavailable). Database failures are typically transient issues.
func ErrForbidden
func ErrForbidden(message string, cause error) *AppError
ErrForbidden creates a forbidden error (403).
func ErrInternalError
func ErrInternalError(message string, cause error) *AppError
ErrInternalError creates an internal server error (500).
func ErrInvalidAPIKey
func ErrInvalidAPIKey(cause error) *AppError
ErrInvalidAPIKey creates an invalid API key error (401).
func ErrNotFound
func ErrNotFound(message string, cause error) *AppError
ErrNotFound creates a not found error (404).
func ErrSecretAlreadyExists
func ErrSecretAlreadyExists(message string, cause error) *AppError
ErrSecretAlreadyExists creates a secret already exists error (409).
func ErrSecretNotFound
func ErrSecretNotFound(message string, cause error) *AppError
ErrSecretNotFound creates a secret not found error (404).
func ErrServiceUnavailable
func ErrServiceUnavailable(message string, cause error) *AppError
ErrServiceUnavailable creates a service unavailable error (503). Use this for resources that are temporarily unavailable but may become available soon.
func ErrUnauthorized
func ErrUnauthorized(message string, cause error) *AppError
ErrUnauthorized creates an unauthorized error (401).
func NewClientError
func NewClientError(statusCode int, code, message string, cause error) *AppError
NewClientError creates a new client error (4xx status codes).
func NewServerError
func NewServerError(statusCode int, code, message string, cause error) *AppError
NewServerError creates a new server error (5xx status codes).
func (*AppError) Error
func (e *AppError) Error() string
Error implements the error interface.
func (*AppError) Is
func (e *AppError) Is(target error) bool
Is allows errors.Is to work with AppError.
func (*AppError) Unwrap
func (e *AppError) Unwrap() error
Unwrap returns the underlying error for error unwrapping.
logger
import "runvoy/internal/logger"
Package logger provides structured logging utilities for runvoy. It includes context-aware logging and log level management.
Index
- func ClearContextExtractors()
- func DeriveRequestLogger(ctx context.Context, base *slog.Logger) *slog.Logger
- func ExtractRequestIDFromContext(ctx context.Context) string
- func GetDeadlineInfo(ctx context.Context) []any
- func GetRequestID(ctx context.Context) string
- func Initialize(env constants.Environment, level slog.Level) *slog.Logger
- func RegisterContextExtractor(extractor ContextExtractor)
- func SliceToMap(args []any) map[string]any
- func WithRequestID(ctx context.Context, requestID string) context.Context
- type ContextExtractor
func ClearContextExtractors
func ClearContextExtractors()
ClearContextExtractors removes all registered context extractors. This is primarily useful for testing.
func DeriveRequestLogger
func DeriveRequestLogger(ctx context.Context, base *slog.Logger) *slog.Logger
DeriveRequestLogger returns a logger enriched with request-scoped fields available in the provided context. It first checks for a request ID set via WithRequestID, then tries all registered ContextExtractors in order. This allows supporting multiple providers (AWS Lambda, HTTP servers, etc.) without hardcoding provider-specific logic.
IMPORTANT: The requestID field is always added at the root level of the log entry (never nested in a "context" object). This ensures we can query logs by requestID directly using e.g. filter requestID = "value". Do NOT add requestID to any "context" map objects in log calls.
func ExtractRequestIDFromContext
func ExtractRequestIDFromContext(ctx context.Context) string
ExtractRequestIDFromContext attempts to extract a request ID from the context using the same priority as DeriveRequestLogger: first checks for a request ID set via WithRequestID, then tries all registered ContextExtractors in order. Returns the first request ID found, or an empty string if none is found. This allows middleware to extract request IDs without knowing about provider-specific implementations (e.g., AWS Lambda).
func GetDeadlineInfo
func GetDeadlineInfo(ctx context.Context) []any
GetDeadlineInfo returns logging attributes for context deadline information. Returns the absolute deadline time and remaining duration if set, or "none" if no deadline.
func GetRequestID
func GetRequestID(ctx context.Context) string
GetRequestID extracts the request ID from the context. The request ID is set by server middleware when available.
func Initialize
func Initialize(env constants.Environment, level slog.Level) *slog.Logger
Initialize sets up the global slog logger based on the environment
func RegisterContextExtractor
func RegisterContextExtractor(extractor ContextExtractor)
RegisterContextExtractor registers a new context extractor. Extractors are called in the order they are registered.
func SliceToMap
func SliceToMap(args []any) map[string]any
SliceToMap converts a slice of alternating key-value pairs to a map[string]any. It expects the slice to have an even number of elements with string keys. Non-string keys are skipped.
func WithRequestID
func WithRequestID(ctx context.Context, requestID string) context.Context
WithRequestID returns a new context with the given request ID attached. This should be used by server middleware to add request IDs to the context.
type ContextExtractor
ContextExtractor defines an interface for extracting request IDs from various context sources (e.g., AWS Lambda, HTTP servers, other cloud providers). This interface allows the logger to remain portable and not bound to any specific provider implementation.
type ContextExtractor interface {
// ExtractRequestID attempts to extract a request ID from the given context.
// Returns the request ID and true if found, empty string and false otherwise.
ExtractRequestID(ctx context.Context) (requestID string, found bool)
}
secrets
import "runvoy/internal/secrets"
Package secrets provides shared utilities for secret detection and handling.
Index
- Variables
- func GetSecretVariableNames(env map[string]string) []string
- func MergeSecretVarNames(known, detected []string) []string
Variables
DefaultSecretPatterns contains the default patterns used to identify environment variable names that should be treated as secrets.
var DefaultSecretPatterns = []string{
"ACCESS_KEY",
"API_KEY",
"API_SECRET",
"GITHUB_SECRET",
"GITHUB_TOKEN",
"PASSWORD",
"PRIVATE_KEY",
"SECRET_KEY",
"SECRET",
"TOKEN",
}
func GetSecretVariableNames
func GetSecretVariableNames(env map[string]string) []string
GetSecretVariableNames returns a list of variable names from the given environment that should be treated as secrets based on pattern matching. These variables will be processed without exposing their values in logs.
func MergeSecretVarNames
func MergeSecretVarNames(known, detected []string) []string
MergeSecretVarNames merges known secret variable names with pattern-detected ones, removing duplicates. This allows combining explicitly known secrets with pattern-based detection for comprehensive coverage.
server
import "runvoy/internal/server"
Package server implements the HTTP server and handlers for runvoy. It provides REST API endpoints for user management and command execution.
Index
- type Router
- func NewRouter(svc *orchestrator.Service, requestTimeout time.Duration, allowedOrigins []string) *Router
- func (r *Router) ChiMux() *chi.Mux
- func (r *Router) GetLoggerFromContext(ctx context.Context) *slog.Logger
- func (r *Router) Handler() http.Handler
- func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request)
- func (r *Router) WithContext(ctx context.Context, svc *orchestrator.Service) context.Context
type Router
Router wraps a chi router with service dependencies for handling API requests.
type Router struct {
// contains filtered or unexported fields
}
func NewRouter
func NewRouter(svc *orchestrator.Service, requestTimeout time.Duration, allowedOrigins []string) *Router
NewRouter creates a new chi router with routes configured. If requestTimeout is > 0, adds a per-request timeout middleware. If requestTimeout is 0, no timeout middleware is added, allowing the environment (e.g., Lambda with its own timeout) to handle timeouts.
func (*Router) ChiMux
func (r *Router) ChiMux() *chi.Mux
ChiMux returns the underlying chi router for advanced usage
func (*Router) GetLoggerFromContext
func (r *Router) GetLoggerFromContext(ctx context.Context) *slog.Logger
GetLoggerFromContext extracts the logger from request context Returns the request-scoped logger (with request ID if available) or falls back to service logger
func (*Router) Handler
func (r *Router) Handler() http.Handler
Handler returns an http.Handler for the router
func (*Router) ServeHTTP
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request)
ServeHTTP implements http.Handler for use with chi router
func (*Router) WithContext
func (r *Router) WithContext(ctx context.Context, svc *orchestrator.Service) context.Context
WithContext adds the service to the request context
testutil
import "runvoy/internal/testutil"
Package testutil provides shared testing utilities and helpers.
Index
- func AssertAppErrorCode(t *testing.T, err error, expectedCode string, _ ...any) bool
- func AssertAppErrorStatus(t *testing.T, err error, expectedStatus int, _ ...any) bool
- func AssertEqual(t *testing.T, expected, actual any, msgAndArgs ...any) bool
- func AssertError(t *testing.T, err error, msgAndArgs ...any) bool
- func AssertErrorType(t *testing.T, err, target error, _ ...any) bool
- func AssertNil(t *testing.T, obj any, msgAndArgs ...any) bool
- func AssertNoError(t *testing.T, err error, msgAndArgs ...any) bool
- func AssertNotEmpty(t *testing.T, obj any, msgAndArgs ...any) bool
- func AssertNotNil(t *testing.T, obj any, msgAndArgs ...any) bool
- func SilentLogger() *slog.Logger
- func TestContext() context.Context
- func TestLogger() *slog.Logger
- type ExecutionBuilder
- func NewExecutionBuilder() *ExecutionBuilder
- func (b *ExecutionBuilder) Build() *api.Execution
- func (b *ExecutionBuilder) Completed() *ExecutionBuilder
- func (b *ExecutionBuilder) Failed() *ExecutionBuilder
- func (b *ExecutionBuilder) WithCommand(cmd string) *ExecutionBuilder
- func (b *ExecutionBuilder) WithCreatedBy(email string) *ExecutionBuilder
- func (b *ExecutionBuilder) WithExecutionID(id string) *ExecutionBuilder
- func (b *ExecutionBuilder) WithLogStreamName(name string) *ExecutionBuilder
- func (b *ExecutionBuilder) WithStatus(status string) *ExecutionBuilder
- type UserBuilder
- func NewUserBuilder() *UserBuilder
- func (b *UserBuilder) Build() *api.User
- func (b *UserBuilder) Revoked() *UserBuilder
- func (b *UserBuilder) WithCreatedAt(t time.Time) *UserBuilder
- func (b *UserBuilder) WithEmail(email string) *UserBuilder
- func (b *UserBuilder) WithLastUsed(t time.Time) *UserBuilder
- func (b *UserBuilder) WithRole(role string) *UserBuilder
func AssertAppErrorCode
func AssertAppErrorCode(t *testing.T, err error, expectedCode string, _ ...any) bool
AssertAppErrorCode checks if the error has a specific error code.
func AssertAppErrorStatus
func AssertAppErrorStatus(t *testing.T, err error, expectedStatus int, _ ...any) bool
AssertAppErrorStatus checks if the error has a specific HTTP status code.
func AssertEqual
func AssertEqual(t *testing.T, expected, actual any, msgAndArgs ...any) bool
AssertEqual is a wrapper around assert.Equal with context.
func AssertError
func AssertError(t *testing.T, err error, msgAndArgs ...any) bool
AssertError is a wrapper around assert.Error with context.
func AssertErrorType
func AssertErrorType(t *testing.T, err, target error, _ ...any) bool
AssertErrorType checks if the error is of a specific type using errors.Is.
func AssertNil
func AssertNil(t *testing.T, obj any, msgAndArgs ...any) bool
AssertNil is a wrapper around assert.Nil with context.
func AssertNoError
func AssertNoError(t *testing.T, err error, msgAndArgs ...any) bool
AssertNoError is a wrapper around assert.NoError with context.
func AssertNotEmpty
func AssertNotEmpty(t *testing.T, obj any, msgAndArgs ...any) bool
AssertNotEmpty is a wrapper around assert.NotEmpty with context.
func AssertNotNil
func AssertNotNil(t *testing.T, obj any, msgAndArgs ...any) bool
AssertNotNil is a wrapper around assert.NotNil with context.
func SilentLogger
func SilentLogger() *slog.Logger
SilentLogger creates a logger that discards all output.
func TestContext
func TestContext() context.Context
TestContext creates a test context with a reasonable timeout. Note: The cancel function is intentionally not returned since test contexts are expected to be short-lived and will be cleaned up when the test completes.
func TestLogger
func TestLogger() *slog.Logger
TestLogger creates a logger suitable for testing (outputs to stderr).
type ExecutionBuilder
ExecutionBuilder provides a fluent interface for building test executions.
type ExecutionBuilder struct {
// contains filtered or unexported fields
}
func NewExecutionBuilder
func NewExecutionBuilder() *ExecutionBuilder
NewExecutionBuilder creates a new ExecutionBuilder with sensible defaults.
func (*ExecutionBuilder) Build
func (b *ExecutionBuilder) Build() *api.Execution
Build returns the constructed Execution.
func (*ExecutionBuilder) Completed
func (b *ExecutionBuilder) Completed() *ExecutionBuilder
Completed marks the execution as completed.
func (*ExecutionBuilder) Failed
func (b *ExecutionBuilder) Failed() *ExecutionBuilder
Failed marks the execution as failed.
func (*ExecutionBuilder) WithCommand
func (b *ExecutionBuilder) WithCommand(cmd string) *ExecutionBuilder
WithCommand sets the execution command.
func (*ExecutionBuilder) WithCreatedBy
func (b *ExecutionBuilder) WithCreatedBy(email string) *ExecutionBuilder
WithCreatedBy sets the creator email.
func (*ExecutionBuilder) WithExecutionID
func (b *ExecutionBuilder) WithExecutionID(id string) *ExecutionBuilder
WithExecutionID sets the execution ID.
func (*ExecutionBuilder) WithLogStreamName
func (b *ExecutionBuilder) WithLogStreamName(name string) *ExecutionBuilder
WithLogStreamName sets the log stream name.
func (*ExecutionBuilder) WithStatus
func (b *ExecutionBuilder) WithStatus(status string) *ExecutionBuilder
WithStatus sets the execution status.
type UserBuilder
UserBuilder provides a fluent interface for building test users.
type UserBuilder struct {
// contains filtered or unexported fields
}
func NewUserBuilder
func NewUserBuilder() *UserBuilder
NewUserBuilder creates a new UserBuilder with sensible defaults.
func (*UserBuilder) Build
func (b *UserBuilder) Build() *api.User
Build returns the constructed User.
func (*UserBuilder) Revoked
func (b *UserBuilder) Revoked() *UserBuilder
Revoked marks the user as revoked.
func (*UserBuilder) WithCreatedAt
func (b *UserBuilder) WithCreatedAt(t time.Time) *UserBuilder
WithCreatedAt sets the user's creation time.
func (*UserBuilder) WithEmail
func (b *UserBuilder) WithEmail(email string) *UserBuilder
WithEmail sets the user's email.
func (*UserBuilder) WithLastUsed
func (b *UserBuilder) WithLastUsed(t time.Time) *UserBuilder
WithLastUsed sets the user's last used time.
func (*UserBuilder) WithRole
func (b *UserBuilder) WithRole(role string) *UserBuilder
WithRole sets the user's role.
axiom-forwarder
import "runvoy/scripts/axiom-forwarder"
Package main implements an AWS Lambda function that forwards CloudWatch Logs to Axiom. This is a standalone utility kept in the runvoy repository for convenience.
Index
create-config-file
import "runvoy/scripts/create-config-file"
Package main provides a utility to create a configuration file for runvoy.
Index
delete-s3-buckets
import "runvoy/scripts/delete-s3-buckets"
Package main provides a utility script to delete non-empty S3 buckets. It deletes all object versions, delete markers, and objects before deleting the bucket.
Index
generate-cli-docs
import "runvoy/scripts/generate-cli-docs"
Package main provides a utility to generate a single markdown file documenting all CLI commands.
Index
seed-admin-user
import "runvoy/scripts/seed-admin-user"
seed-admin-user is a utility script to seed the admin user into the database. This script is intentionally kept for operational purposes (initial setup, recovery, etc.).
Index
sync-env-vars
import "runvoy/scripts/sync-env-vars"
Package main provides a utility to synchronize environment variables between Lambda functions and local .env files.
Index
truncate-dynamodb-table
import "runvoy/scripts/truncate-dynamodb-table"
Package main provides a utility script to truncate (delete all records from) a DynamoDB table. It scans all items from the table and deletes them in batches.
Index
update-readme-help
import "runvoy/scripts/update-readme-help"
Package main provides a utility to update the README.md with the latest CLI help output and version.
Index
cmd
import "runvoy/cmd/cli/cmd"
Package cmd implements the CLI commands for the runvoy tool.
Index
- func Execute()
- func RootCmd() *cobra.Command
- type ClaimService
- func NewClaimService(apiClient client.Interface, outputter OutputInterface, configSaver ConfigSaver) *ClaimService
- func (s *ClaimService) ClaimAPIKey(ctx context.Context, token string, cfg *config.Config) error
- type ConfigLoader
- func NewConfigLoader() ConfigLoader
- type ConfigLoaderFunc
- func (f ConfigLoaderFunc) Load() (*config.Config, error)
- type ConfigPathGetter
- func NewConfigPathGetter() ConfigPathGetter
- type ConfigPathGetterFunc
- func (f ConfigPathGetterFunc) GetConfigPath() (string, error)
- type ConfigSaver
- func NewConfigSaver() ConfigSaver
- type ConfigSaverFunc
- func (f ConfigSaverFunc) Save(cfg *config.Config) error
- type ConfigureService
- func NewConfigureService(outputter OutputInterface, configSaver ConfigSaver, configLoader ConfigLoader, configPathGetter ConfigPathGetter) *ConfigureService
- func (s *ConfigureService) Configure(_ context.Context) error
- type ExecuteCommandRequest
- type ImagesService
- func NewImagesService(apiClient client.Interface, outputter OutputInterface) *ImagesService
- func (s *ImagesService) ListImages(ctx context.Context) error
- func (s *ImagesService) RegisterImage(ctx context.Context, image string, isDefault *bool, taskRoleName, taskExecutionRoleName *string, cpu, memory *int, runtimePlatform *string) error
- func (s *ImagesService) ShowImage(ctx context.Context, image string) error
- func (s *ImagesService) UnregisterImage(ctx context.Context, image string) error
- type KillService
- func NewKillService(apiClient client.Interface, outputter OutputInterface) *KillService
- func (s *KillService) KillExecution(ctx context.Context, executionID string) error
- type ListService
- func NewListService(apiClient client.Interface, outputter OutputInterface) *ListService
- func (s *ListService) ListExecutions(ctx context.Context, limit int, statuses string) error
- type LogsService
- func NewLogsService(apiClient client.Interface, outputter OutputInterface, sleeper Sleeper) *LogsService
- func (s *LogsService) DisplayLogs(ctx context.Context, executionID, webURL string) error
- type OutputInterface
- func NewOutputWrapper() OutputInterface
- type PlaybookOverrides
- type PlaybookService
- func NewPlaybookService(loader *playbooks.PlaybookLoader, executor *playbooks.PlaybookExecutor, outputter OutputInterface) *PlaybookService
- func (s *PlaybookService) ListPlaybooks(_ context.Context) error
- func (s *PlaybookService) RunPlaybook(ctx context.Context, name string, userEnv map[string]string, overrides *PlaybookOverrides, webURL string, runService *RunService) error
- func (s *PlaybookService) ShowPlaybook(_ context.Context, name string) error
- type RealSleeper
- func (r *RealSleeper) Sleep(duration time.Duration)
- type RunService
- func NewRunService(apiClient client.Interface, outputter OutputInterface) *RunService
- func (s *RunService) ExecuteCommand(ctx context.Context, req *ExecuteCommandRequest) error
- type SecretsService
- func NewSecretsService(apiClient client.Interface, outputter OutputInterface) *SecretsService
- func (s *SecretsService) CreateSecret(ctx context.Context, name, keyName, value, description string) error
- func (s *SecretsService) DeleteSecret(ctx context.Context, name string) error
- func (s *SecretsService) GetSecret(ctx context.Context, name string) error
- func (s *SecretsService) ListSecrets(ctx context.Context) error
- func (s *SecretsService) UpdateSecret(ctx context.Context, name, keyName, value, description string) error
- type Sleeper
- type StatusService
- func NewStatusService(apiClient client.Interface, outputter OutputInterface) *StatusService
- func (s *StatusService) DisplayStatus(ctx context.Context, executionID string) error
- type TraceService
- func NewTraceService(apiClient client.Interface, outputter OutputInterface) *TraceService
- func (s *TraceService) DisplayBackendLogs(ctx context.Context, requestID string) error
- type UsersService
- func NewUsersService(apiClient client.Interface, outputter OutputInterface) *UsersService
- func (s *UsersService) CreateUser(ctx context.Context, email, role string) error
- func (s *UsersService) ListUsers(ctx context.Context) error
- func (s *UsersService) RevokeUser(ctx context.Context, email string) error
func Execute
func Execute()
Execute runs the root command and handles cleanup of timeout context.
func RootCmd
func RootCmd() *cobra.Command
RootCmd returns the root command for use by tools like doc generators.
type ClaimService
ClaimService handles API key claiming logic
type ClaimService struct {
// contains filtered or unexported fields
}
func NewClaimService
func NewClaimService(apiClient client.Interface, outputter OutputInterface, configSaver ConfigSaver) *ClaimService
NewClaimService creates a new ClaimService with the provided dependencies
func (*ClaimService) ClaimAPIKey
func (s *ClaimService) ClaimAPIKey(ctx context.Context, token string, cfg *config.Config) error
ClaimAPIKey claims an API key using the provided token and saves it to the config
type ConfigLoader
ConfigLoader defines an interface for loading configuration
type ConfigLoader interface {
Load() (*config.Config, error)
}
func NewConfigLoader
func NewConfigLoader() ConfigLoader
NewConfigLoader creates a ConfigLoader using the global config.Load function
type ConfigLoaderFunc
ConfigLoaderFunc adapts a function to the ConfigLoader interface
type ConfigLoaderFunc func() (*config.Config, error)
func (ConfigLoaderFunc) Load
func (f ConfigLoaderFunc) Load() (*config.Config, error)
Load executes the underlying function to load configuration
type ConfigPathGetter
ConfigPathGetter defines an interface for retrieving the configuration path
type ConfigPathGetter interface {
GetConfigPath() (string, error)
}
func NewConfigPathGetter
func NewConfigPathGetter() ConfigPathGetter
NewConfigPathGetter creates a ConfigPathGetter using the global config.GetConfigPath function
type ConfigPathGetterFunc
ConfigPathGetterFunc adapts a function to the ConfigPathGetter interface
type ConfigPathGetterFunc func() (string, error)
func (ConfigPathGetterFunc) GetConfigPath
func (f ConfigPathGetterFunc) GetConfigPath() (string, error)
GetConfigPath executes the underlying function to retrieve the config path
type ConfigSaver
ConfigSaver defines an interface for saving configuration
type ConfigSaver interface {
Save(*config.Config) error
}
func NewConfigSaver
func NewConfigSaver() ConfigSaver
NewConfigSaver creates a ConfigSaver using the global config.Save function
type ConfigSaverFunc
ConfigSaverFunc adapts a function to the ConfigSaver interface
type ConfigSaverFunc func(*config.Config) error
func (ConfigSaverFunc) Save
func (f ConfigSaverFunc) Save(cfg *config.Config) error
Save executes the underlying function to persist configuration
type ConfigureService
ConfigureService handles configuration logic
type ConfigureService struct {
// contains filtered or unexported fields
}
func NewConfigureService
func NewConfigureService(outputter OutputInterface, configSaver ConfigSaver, configLoader ConfigLoader, configPathGetter ConfigPathGetter) *ConfigureService
NewConfigureService creates a new ConfigureService with the provided dependencies
func (*ConfigureService) Configure
func (s *ConfigureService) Configure(_ context.Context) error
Configure runs the interactive configuration flow
type ExecuteCommandRequest
ExecuteCommandRequest contains all parameters needed to execute a command
type ExecuteCommandRequest struct {
Command string
GitRepo string
GitRef string
GitPath string
Image string
Env map[string]string
Secrets []string
WebURL string
}
type ImagesService
ImagesService handles image management logic
type ImagesService struct {
// contains filtered or unexported fields
}
func NewImagesService
func NewImagesService(apiClient client.Interface, outputter OutputInterface) *ImagesService
NewImagesService creates a new ImagesService with the provided dependencies
func (*ImagesService) ListImages
func (s *ImagesService) ListImages(ctx context.Context) error
ListImages lists all registered images
func (*ImagesService) RegisterImage
func (s *ImagesService) RegisterImage(ctx context.Context, image string, isDefault *bool, taskRoleName, taskExecutionRoleName *string, cpu, memory *int, runtimePlatform *string) error
RegisterImage registers a new image
func (*ImagesService) ShowImage
func (s *ImagesService) ShowImage(ctx context.Context, image string) error
ShowImage shows detailed information about a single image
func (*ImagesService) UnregisterImage
func (s *ImagesService) UnregisterImage(ctx context.Context, image string) error
UnregisterImage unregisters an image
type KillService
KillService handles execution killing logic
type KillService struct {
// contains filtered or unexported fields
}
func NewKillService
func NewKillService(apiClient client.Interface, outputter OutputInterface) *KillService
NewKillService creates a new KillService with the provided dependencies
func (*KillService) KillExecution
func (s *KillService) KillExecution(ctx context.Context, executionID string) error
KillExecution kills a running execution and displays the results
type ListService
ListService handles execution listing and formatting logic
type ListService struct {
// contains filtered or unexported fields
}
func NewListService
func NewListService(apiClient client.Interface, outputter OutputInterface) *ListService
NewListService creates a new ListService with the provided dependencies
func (*ListService) ListExecutions
func (s *ListService) ListExecutions(ctx context.Context, limit int, statuses string) error
ListExecutions lists executions with optional filtering and displays them in a table format
type LogsService
LogsService handles log display logic
type LogsService struct {
// contains filtered or unexported fields
}
func NewLogsService
func NewLogsService(apiClient client.Interface, outputter OutputInterface, sleeper Sleeper) *LogsService
NewLogsService creates a new LogsService with the provided dependencies
func (*LogsService) DisplayLogs
func (s *LogsService) DisplayLogs(ctx context.Context, executionID, webURL string) error
DisplayLogs retrieves static logs and then streams new logs via WebSocket in real-time If the execution has already completed, it displays static logs only and skips WebSocket streaming
type OutputInterface
OutputInterface defines the interface for output operations to enable dependency injection and testing
type OutputInterface interface {
Infof(format string, a ...any)
Errorf(format string, a ...any)
Successf(format string, a ...any)
Warningf(format string, a ...any)
Table(headers []string, rows [][]string)
Blank()
Bold(text string) string
Cyan(text string) string
KeyValue(key, value string)
Prompt(prompt string) string
}
func NewOutputWrapper
func NewOutputWrapper() OutputInterface
NewOutputWrapper creates a new output wrapper that implements OutputInterface
type PlaybookOverrides
PlaybookOverrides contains values to override in a playbook
type PlaybookOverrides struct {
Image string
GitRepo string
GitRef string
GitPath string
Secrets []string
}
type PlaybookService
PlaybookService handles playbook operations
type PlaybookService struct {
// contains filtered or unexported fields
}
func NewPlaybookService
func NewPlaybookService(loader *playbooks.PlaybookLoader, executor *playbooks.PlaybookExecutor, outputter OutputInterface) *PlaybookService
NewPlaybookService creates a new PlaybookService
func (*PlaybookService) ListPlaybooks
func (s *PlaybookService) ListPlaybooks(_ context.Context) error
ListPlaybooks lists all available playbooks
func (*PlaybookService) RunPlaybook
func (s *PlaybookService) RunPlaybook(ctx context.Context, name string, userEnv map[string]string, overrides *PlaybookOverrides, webURL string, runService *RunService) error
RunPlaybook executes a playbook with optional overrides
func (*PlaybookService) ShowPlaybook
func (s *PlaybookService) ShowPlaybook(_ context.Context, name string) error
ShowPlaybook displays the full content of a playbook
type RealSleeper
RealSleeper implements Sleeper using the standard time.Sleep
type RealSleeper struct{}
func (*RealSleeper) Sleep
func (r *RealSleeper) Sleep(duration time.Duration)
Sleep pauses execution for the specified duration
type RunService
RunService handles command execution logic
type RunService struct {
// contains filtered or unexported fields
}
func NewRunService
func NewRunService(apiClient client.Interface, outputter OutputInterface) *RunService
NewRunService creates a new RunService with the provided dependencies
func (*RunService) ExecuteCommand
func (s *RunService) ExecuteCommand(ctx context.Context, req *ExecuteCommandRequest) error
ExecuteCommand executes a command remotely and displays the results
type SecretsService
SecretsService handles secrets management logic
type SecretsService struct {
// contains filtered or unexported fields
}
func NewSecretsService
func NewSecretsService(apiClient client.Interface, outputter OutputInterface) *SecretsService
NewSecretsService creates a new SecretsService with the provided dependencies
func (*SecretsService) CreateSecret
func (s *SecretsService) CreateSecret(ctx context.Context, name, keyName, value, description string) error
CreateSecret creates a new secret with the given name, key name, value, and optional description
func (*SecretsService) DeleteSecret
func (s *SecretsService) DeleteSecret(ctx context.Context, name string) error
DeleteSecret deletes a secret by name
func (*SecretsService) GetSecret
func (s *SecretsService) GetSecret(ctx context.Context, name string) error
GetSecret retrieves a secret by name
func (*SecretsService) ListSecrets
func (s *SecretsService) ListSecrets(ctx context.Context) error
ListSecrets lists all secrets and displays them in a table format
func (*SecretsService) UpdateSecret
func (s *SecretsService) UpdateSecret(ctx context.Context, name, keyName, value, description string) error
UpdateSecret updates a secret's metadata and/or value
type Sleeper
Sleeper provides a testable interface for introducing delays
type Sleeper interface {
Sleep(duration time.Duration)
}
type StatusService
StatusService handles status display logic
type StatusService struct {
// contains filtered or unexported fields
}
func NewStatusService
func NewStatusService(apiClient client.Interface, outputter OutputInterface) *StatusService
NewStatusService creates a new StatusService with the provided dependencies
func (*StatusService) DisplayStatus
func (s *StatusService) DisplayStatus(ctx context.Context, executionID string) error
DisplayStatus retrieves and displays the status of an execution
type TraceService
TraceService handles backend logs display logic
type TraceService struct {
// contains filtered or unexported fields
}
func NewTraceService
func NewTraceService(apiClient client.Interface, outputter OutputInterface) *TraceService
NewTraceService creates a new TraceService with the provided dependencies
func (*TraceService) DisplayBackendLogs
func (s *TraceService) DisplayBackendLogs(ctx context.Context, requestID string) error
DisplayBackendLogs retrieves and displays backend infrastructure logs and related resources for a request ID
type UsersService
UsersService handles user management logic
type UsersService struct {
// contains filtered or unexported fields
}
func NewUsersService
func NewUsersService(apiClient client.Interface, outputter OutputInterface) *UsersService
NewUsersService creates a new UsersService with the provided dependencies
func (*UsersService) CreateUser
func (s *UsersService) CreateUser(ctx context.Context, email, role string) error
CreateUser creates a new user with the given email and role
func (*UsersService) ListUsers
func (s *UsersService) ListUsers(ctx context.Context) error
ListUsers lists all users and displays them in a table format
func (*UsersService) RevokeUser
func (s *UsersService) RevokeUser(ctx context.Context, email string) error
RevokeUser revokes a user's API key
server
import "runvoy/cmd/local/server"
Package server provides the async event processor HTTP server setup.
Index
func NewRouter
func NewRouter(proc processor.Processor, log *slog.Logger) *chi.Mux
NewRouter creates a chi router for the async event processor.
authorization
import "runvoy/internal/auth/authorization"
Package authorization provides Casbin-based authorization enforcement for runvoy. It implements role-based access control (RBAC) with resource ownership support.
Index
- Variables
- func FormatResourceID(resourceType, resourceID string) string
- func FormatRole(role Role) string
- func IsValidRole(roleStr string) bool
- func NewEmbeddedAdapter(fsys fs.FS, pathBase string) persist.Adapter
- func ValidRoles() []string
- type Action
- type Enforcer
- func NewEnforcer(log *slog.Logger) (*Enforcer, error)
- func (e *Enforcer) AddOwnershipForResource(ctx context.Context, resourceID, ownerEmail string) error
- func (e *Enforcer) AddRoleForUser(ctx context.Context, user string, role Role) error
- func (e *Enforcer) Enforce(ctx context.Context, subject, object string, action Action) (bool, error)
- func (e *Enforcer) GetAllNamedGroupingPolicies(ptype string) ([][]string, error)
- func (e *Enforcer) GetRolesForUser(user string) ([]string, error)
- func (e *Enforcer) HasOwnershipForResource(resourceID, ownerEmail string) (bool, error)
- func (e *Enforcer) Hydrate(ctx context.Context, userRepo database.UserRepository, executionRepo database.ExecutionRepository, secretsRepo database.SecretsRepository, imageRepo ImageRepository) error
- func (e *Enforcer) LoadResourceOwnerships(ctx context.Context, ownerships map[string]string) error
- func (e *Enforcer) LoadRolesForUsers(ctx context.Context, userRoles map[string]string) error
- func (e *Enforcer) RemoveAllOwnershipsForResource(ctx context.Context, resourceID string) error
- func (e *Enforcer) RemoveOwnershipForResource(ctx context.Context, resourceID, ownerEmail string) error
- func (e *Enforcer) RemoveRoleForUser(ctx context.Context, user, role string) error
- type ImageRepository
- type Role
- func NewRole(roleStr string) (Role, error)
- func (r Role) String() string
- func (r Role) Valid() bool
Variables
CasbinFS embeds the Casbin model and policy files into the binary. This allows the application to run without requiring these files to be present on the filesystem.
var CasbinFS embed.FS
func FormatResourceID
func FormatResourceID(resourceType, resourceID string) string
FormatResourceID converts a resource type and ID to the Casbin resource format. Example: FormatResourceID("secret", "secret-123") returns "secret:secret-123"
func FormatRole
func FormatRole(role Role) string
FormatRole converts a role to the Casbin role format. Example: FormatRole(RoleAdmin) returns "role:admin"
func IsValidRole
func IsValidRole(roleStr string) bool
IsValidRole checks if a role name string is valid.
func NewEmbeddedAdapter
func NewEmbeddedAdapter(fsys fs.FS, pathBase string) persist.Adapter
NewEmbeddedAdapter creates a new adapter for reading Casbin config from an embedded filesystem. The adapter supports in-memory policy modifications at runtime but does not persist changes back to the embedded files, as they are read-only.
func ValidRoles
func ValidRoles() []string
ValidRoles returns a list of all valid role names as strings.
type Action
Action is a typed string representing an action in the authorization system.
type Action string
Action constants for Casbin enforcement. These correspond to the HTTP methods mapped to CRUD actions.
const (
ActionCreate Action = "create"
ActionRead Action = "read"
ActionUpdate Action = "update"
ActionDelete Action = "delete"
ActionKill Action = "kill"
ActionUse Action = "use"
)
type Enforcer
Enforcer wraps the Casbin enforcer with additional functionality.
type Enforcer struct {
// contains filtered or unexported fields
}
func NewEnforcer
func NewEnforcer(log *slog.Logger) (*Enforcer, error)
NewEnforcer creates a new Casbin enforcer using embedded Casbin configuration files. The model and policy are embedded in the binary at build time, so no filesystem access is required.
func (*Enforcer) AddOwnershipForResource
func (e *Enforcer) AddOwnershipForResource(ctx context.Context, resourceID, ownerEmail string) error
AddOwnershipForResource adds ownership mapping for a resource. This allows the owner to access their own resources.
Example usage:
err := e.AddOwnershipForResource(ctx, "secret:secret-123", "user@example.com")
func (*Enforcer) AddRoleForUser
func (e *Enforcer) AddRoleForUser(ctx context.Context, user string, role Role) error
AddRoleForUser assigns a role to a user. Returns an error if the role is invalid or empty.
Example usage:
err := e.AddRoleForUser(ctx, "user@example.com", RoleDeveloper)
func (*Enforcer) Enforce
func (e *Enforcer) Enforce(ctx context.Context, subject, object string, action Action) (bool, error)
Enforce checks if a subject (user) can perform an action on an object (resource). Returns true if the action is allowed, false otherwise.
Example usage:
allowed, err := e.Enforce(ctx, "user@example.com", "/api/secrets/secret-123", "read")
func (*Enforcer) GetAllNamedGroupingPolicies
func (e *Enforcer) GetAllNamedGroupingPolicies(ptype string) ([][]string, error)
GetAllNamedGroupingPolicies returns all grouping policies for the given policy type (e.g., "g2" for ownership).
func (*Enforcer) GetRolesForUser
func (e *Enforcer) GetRolesForUser(user string) ([]string, error)
GetRolesForUser returns all roles assigned to a user.
func (*Enforcer) HasOwnershipForResource
func (e *Enforcer) HasOwnershipForResource(resourceID, ownerEmail string) (bool, error)
HasOwnershipForResource checks if the provided user currently owns the resource.
func (*Enforcer) Hydrate
func (e *Enforcer) Hydrate(ctx context.Context, userRepo database.UserRepository, executionRepo database.ExecutionRepository, secretsRepo database.SecretsRepository, imageRepo ImageRepository) error
Hydrate loads all user roles and resource ownerships into the Casbin enforcer. This should be called during initialization to populate the enforcer with current data.
func (*Enforcer) LoadResourceOwnerships
func (e *Enforcer) LoadResourceOwnerships(ctx context.Context, ownerships map[string]string) error
LoadResourceOwnerships loads resource ownership mappings into the enforcer.
func (*Enforcer) LoadRolesForUsers
func (e *Enforcer) LoadRolesForUsers(ctx context.Context, userRoles map[string]string) error
LoadRolesForUsers loads role assignments for multiple users into the enforcer. This is typically called at startup to initialize the enforcer with current user roles. The roleStr values should be valid role names (admin, operator, developer, viewer).
Example usage:
roles := map[string]string{
"admin@example.com": "admin",
"dev@example.com": "developer",
}
err := e.LoadRolesForUsers(ctx, roles)
func (*Enforcer) RemoveAllOwnershipsForResource
func (e *Enforcer) RemoveAllOwnershipsForResource(ctx context.Context, resourceID string) error
RemoveAllOwnershipsForResource removes every ownership mapping for the given resource identifier. This is useful when deleting a resource without knowing its owner ahead of time.
func (*Enforcer) RemoveOwnershipForResource
func (e *Enforcer) RemoveOwnershipForResource(ctx context.Context, resourceID, ownerEmail string) error
RemoveOwnershipForResource removes ownership mapping for a resource.
func (*Enforcer) RemoveRoleForUser
func (e *Enforcer) RemoveRoleForUser(ctx context.Context, user, role string) error
RemoveRoleForUser removes a role from a user.
Example usage:
err := e.RemoveRoleForUser(ctx, "user@example.com", "role:developer")
type ImageRepository
ImageRepository defines the interface for listing images. This is a minimal interface to avoid import cycles.
type ImageRepository interface {
ListImages(ctx context.Context) ([]api.ImageInfo, error)
}
type Role
Role is a typed string representing a user role in the authorization system. Valid roles: admin, operator, developer, viewer
type Role string
Role constants for Casbin role-based access control. These correspond to the roles defined in casbin/policy.csv.
const (
// RoleAdmin has full access to all resources and operations.
RoleAdmin Role = "admin"
// RoleOperator can manage images, secrets, and executions but cannot manage users.
RoleOperator Role = "operator"
// RoleDeveloper can create and manage their own resources and execute commands.
RoleDeveloper Role = "developer"
// RoleViewer has read-only access to executions.
RoleViewer Role = "viewer"
)
func NewRole
func NewRole(roleStr string) (Role, error)
NewRole creates a new Role from a string, validating it against known roles. Returns an error if the role string is empty or not a valid role.
func (Role) String
func (r Role) String() string
String returns the string representation of the role.
func (Role) Valid
func (r Role) Valid() bool
Valid checks if the role is a valid known role.
contract
import "runvoy/internal/backend/contract"
Package contract defines all backend interfaces that providers must implement. These interfaces are separated into their own package to avoid circular dependencies between backend services (orchestrator, processor) and provider implementations. This package serves as the single source of truth for all backend provider dependencies.
Index
- type HealthManager
- type ImageRegistry
- type LogManager
- type ObservabilityManager
- type TaskManager
- type WebSocketManager
type HealthManager
HealthManager abstracts provider-specific health checks and resource reconciliation. This interface handles verifying and repairing inconsistencies between metadata storage and cloud resources.
type HealthManager interface {
// Reconcile checks and repairs inconsistencies between metadata storage and actual cloud resources.
// It verifies compute resources (e.g., task definitions, containers), secrets, and identity/access resources.
// Returns a comprehensive health report with all issues found and actions taken.
Reconcile(ctx context.Context) (*api.HealthReport, error)
}
type ImageRegistry
ImageRegistry abstracts provider-specific image management. This interface handles image registration, configuration, and lifecycle management.
type ImageRegistry interface {
// RegisterImage registers a Docker image as a task definition in the execution platform.
// isDefault: if true, explicitly set as default.
// taskRoleName: optional custom task role name (if nil, uses default from config).
// taskExecutionRoleName: optional custom task execution role name (if nil, uses default from config).
// cpu: optional CPU value (e.g., 256, 1024). Defaults to 256 if nil.
// memory: optional Memory value in MB (e.g., 512, 2048). Defaults to 512 if nil.
// runtimePlatform: optional runtime platform (e.g., "Linux/ARM64", "Linux/X86_64"). Defaults to "Linux/ARM64" if nil.
// createdBy: email of the user registering the image.
RegisterImage(
ctx context.Context,
image string,
isDefault *bool,
taskRoleName, taskExecutionRoleName *string,
cpu, memory *int,
runtimePlatform *string,
createdBy string,
) error
// ListImages lists all registered Docker images.
ListImages(ctx context.Context) ([]api.ImageInfo, error)
// GetImage retrieves a single Docker image by ID or name.
// Accepts either an ImageID (e.g., "alpine:latest-a1b2c3d4") or an image name (e.g., "alpine:latest").
GetImage(ctx context.Context, image string) (*api.ImageInfo, error)
// RemoveImage removes a Docker image and deregisters its task definitions.
RemoveImage(ctx context.Context, image string) error
}
type LogManager
LogManager abstracts provider-specific execution log retrieval. This interface handles fetching logs from user task executions.
type LogManager interface {
// FetchLogsByExecutionID retrieves execution logs for a specific execution.
// Returns logs generated by the user's command execution in containers.
// Returns empty slice if logs are not available or not supported by the provider.
FetchLogsByExecutionID(ctx context.Context, executionID string) ([]api.LogEvent, error)
}
type ObservabilityManager
ObservabilityManager provides access to backend infrastructure logs and metrics. This interface is for platform debugging and observability, separate from user execution logs.
type ObservabilityManager interface {
// FetchBackendLogs retrieves logs from the backend services for the provided requestID.
// Returns logs from the backend services for debugging and tracing.
FetchBackendLogs(ctx context.Context, requestID string) ([]api.LogEvent, error)
}
type TaskManager
TaskManager abstracts provider-specific task execution (e.g., AWS ECS, GCP Cloud Run, Azure Container Instances). This interface handles the core responsibility of running and managing task lifecycles.
type TaskManager interface {
// StartTask triggers an execution on the underlying platform and returns
// a stable executionID and the task creation timestamp.
// The createdAt timestamp comes from the provider (e.g., ECS CreatedAt) when available.
StartTask(
ctx context.Context,
userEmail string,
req *api.ExecutionRequest) (executionID string, createdAt *time.Time, err error)
// KillTask terminates a running task identified by executionID.
// Returns an error if the task is already terminated or cannot be terminated.
KillTask(ctx context.Context, executionID string) error
}
type WebSocketManager
WebSocketManager abstracts provider-specific WebSocket management. This interface handles WebSocket connection lifecycle and log streaming.
type WebSocketManager interface {
// HandleRequest processes WebSocket lifecycle events (connect, disconnect, etc.).
// Returns true if the event was handled, false otherwise.
HandleRequest(ctx context.Context, rawEvent *json.RawMessage, reqLogger *slog.Logger) (bool, error)
// NotifyExecutionCompletion sends disconnect notifications to all connected clients for an execution
// and removes the connections.
NotifyExecutionCompletion(ctx context.Context, executionID *string) error
// SendLogsToExecution sends log events to all connected clients for an execution.
SendLogsToExecution(ctx context.Context, executionID *string, logEvents []api.LogEvent) error
// GenerateWebSocketURL creates a WebSocket token and returns the connection URL.
// It stores the token for validation when the client connects.
// Returns an empty string if URL generation fails (errors are logged).
GenerateWebSocketURL(
ctx context.Context,
executionID string,
userEmail *string,
clientIPAtCreationTime *string,
) string
}
health
import "runvoy/internal/backend/health"
Package health provides health management functionality for runvoy. It defines the interface for reconciling resources between metadata storage and cloud provider services.
Index
- type AuthorizerHealthStatus
- type ComputeHealthStatus
- type IdentityHealthStatus
- type Issue
- type Manager
- type Report
- type SecretsHealthStatus
type AuthorizerHealthStatus
AuthorizerHealthStatus contains the health status for authorization data.
type AuthorizerHealthStatus struct {
UsersWithInvalidRoles []string
UsersWithMissingRoles []string
ResourcesWithMissingOwners []string
OrphanedOwnerships []string
MissingOwnerships []string
TotalUsersChecked int
TotalResourcesChecked int
}
type ComputeHealthStatus
ComputeHealthStatus contains the health status for compute resources (e.g., containers, task definitions).
type ComputeHealthStatus struct {
TotalResources int
VerifiedCount int
RecreatedCount int
TagUpdatedCount int
OrphanedCount int
OrphanedResources []string
}
type IdentityHealthStatus
IdentityHealthStatus contains the health status for identity and access management resources.
type IdentityHealthStatus struct {
DefaultRolesVerified bool
CustomRolesVerified int
CustomRolesTotal int
MissingRoles []string
}
type Issue
Issue represents a single health issue found during reconciliation.
type Issue struct {
ResourceType string // Provider-specific resource type (e.g., "ecs_task_definition", "cloud_run_service")
ResourceID string
Severity string // "error", "warning"
Message string
Action string // "recreated", "requires_manual_intervention", "reported", "tag_updated"
}
type Manager
Manager defines the interface for health checks and resource reconciliation. Different cloud providers can implement this interface to support their specific infrastructure.
type Manager interface {
// Reconcile checks and repairs inconsistencies between metadata storage and actual cloud resources.
// It verifies compute resources (e.g., task definitions, containers), secrets, and identity/access resources.
// Returns a comprehensive health report with all issues found and actions taken.
Reconcile(ctx context.Context) (*Report, error)
}
type Report
Report contains the results of a health reconciliation run.
type Report struct {
Timestamp time.Time
ComputeStatus ComputeHealthStatus
SecretsStatus SecretsHealthStatus
IdentityStatus IdentityHealthStatus
AuthorizerStatus AuthorizerHealthStatus
Issues []Issue
ReconciledCount int
ErrorCount int
}
type SecretsHealthStatus
SecretsHealthStatus contains the health status for secrets/parameters.
type SecretsHealthStatus struct {
TotalSecrets int
VerifiedCount int
TagUpdatedCount int
MissingCount int
OrphanedCount int
OrphanedParameters []string
}
orchestrator
import "runvoy/internal/backend/orchestrator"
Package orchestrator provides the core orchestrator service for runvoy. This file contains health reconciliation functionality.
Package orchestrator provides the core orchestrator service for runvoy. It initializes and manages command execution and API request handling.
Index
- type ImageConfig
- type PermissionConfig
- type ResourceConfig
- type RuntimeConfig
- type Service
- func Initialize(ctx context.Context, cfg *config.Config, baseLogger *slog.Logger) (*Service, error)
- func NewService(ctx context.Context, repos *database.Repositories, taskManager contract.TaskManager, imageRegistry contract.ImageRegistry, logManager contract.LogManager, observabilityManager contract.ObservabilityManager, log *slog.Logger, provider constants.BackendProvider, wsManager contract.WebSocketManager, healthManager contract.HealthManager, enforcer *authorization.Enforcer) (*Service, error)
- func (s *Service) AuthenticateUser(ctx context.Context, apiKey string) (*api.User, error)
- func (s *Service) ClaimAPIKey(ctx context.Context, secretToken string, ipAddress string) (*api.ClaimAPIKeyResponse, error)
- func (s *Service) CreateSecret(ctx context.Context, req *api.CreateSecretRequest, userEmail string) error
- func (s *Service) CreateUser(ctx context.Context, req api.CreateUserRequest, createdByEmail string) (*api.CreateUserResponse, error)
- func (s *Service) DeleteSecret(ctx context.Context, name string) error
- func (s *Service) FetchBackendLogs(ctx context.Context, requestID string) ([]api.LogEvent, error)
- func (s *Service) FetchTrace(ctx context.Context, requestID string) (*api.TraceResponse, error)
- func (s *Service) GetEnforcer() *authorization.Enforcer
- func (s *Service) GetExecutionStatus(ctx context.Context, executionID string) (*api.ExecutionStatusResponse, error)
- func (s *Service) GetImage(ctx context.Context, image string) (*api.ImageInfo, error)
- func (s *Service) GetLogsByExecutionID(ctx context.Context, executionID string, userEmail *string, clientIPAtCreationTime *string) (*api.LogsResponse, error)
- func (s *Service) GetSecret(ctx context.Context, name string) (*api.Secret, error)
- func (s *Service) ImageRegistry() contract.ImageRegistry
- func (s *Service) KillExecution(ctx context.Context, executionID string) (*api.KillExecutionResponse, error)
- func (s *Service) ListExecutions(ctx context.Context, limit int, statuses []string) ([]*api.Execution, error)
- func (s *Service) ListImages(ctx context.Context) (*api.ListImagesResponse, error)
- func (s *Service) ListSecrets(ctx context.Context) ([]*api.Secret, error)
- func (s *Service) ListUsers(ctx context.Context) (*api.ListUsersResponse, error)
- func (s *Service) LogManager() contract.LogManager
- func (s *Service) ObservabilityManager() contract.ObservabilityManager
- func (s *Service) ReconcileResources(ctx context.Context) (*api.HealthReport, error)
- func (s *Service) RegisterImage(ctx context.Context, req *api.RegisterImageRequest, createdBy string) (*api.RegisterImageResponse, error)
- func (s *Service) RemoveImage(ctx context.Context, image string) error
- func (s *Service) ResolveImage(ctx context.Context, image string) (*api.ImageInfo, error)
- func (s *Service) RevokeUser(ctx context.Context, email string) error
- func (s *Service) RunCommand(ctx context.Context, userEmail string, req *api.ExecutionRequest, resolvedImage *api.ImageInfo) (*api.ExecutionResponse, error)
- func (s *Service) TaskManager() contract.TaskManager
- func (s *Service) UpdateSecret(ctx context.Context, name string, req *api.UpdateSecretRequest, userEmail string) error
- func (s *Service) UpdateUserLastUsed(ctx context.Context, email string) (*time.Time, error)
- func (s *Service) ValidateExecutionResourceAccess(ctx context.Context, userEmail string, req *api.ExecutionRequest, resolvedImage *api.ImageInfo) error
type ImageConfig
ImageConfig provides a provider-agnostic way to configure image registration. It abstracts away provider-specific details like IAM roles (AWS), service accounts (GCP), etc.
type ImageConfig struct {
// Image is the Docker image reference (e.g., "alpine:latest", "gcr.io/project/image:tag")
Image string
// IsDefault marks this image as the default for executions when no image is specified
IsDefault *bool
// Resources specifies compute resource requirements
Resources *ResourceConfig
// Runtime specifies platform and architecture requirements
Runtime *RuntimeConfig
// Permissions specifies execution permissions and roles
Permissions *PermissionConfig
// RegisteredBy tracks which user registered this image
RegisteredBy string
}
type PermissionConfig
PermissionConfig abstracts execution permissions across providers. Different providers handle permissions differently: - AWS: TaskRole (app permissions) and TaskExecutionRole (infrastructure permissions) - GCP: Service Account - Azure: Managed Identity
type PermissionConfig struct {
// TaskRole grants permissions to the running task/container
// AWS: IAM role name, GCP: service account email, Azure: managed identity client ID
TaskRole *string
// ExecutionRole grants permissions to infrastructure to start the task
// AWS-specific: IAM role for ECS to pull images, write logs, etc.
// Not used by GCP or Azure
ExecutionRole *string
}
type ResourceConfig
ResourceConfig abstracts CPU and memory requirements across providers. Different providers have different granularities and limits: - AWS ECS: CPU in units (256, 512, 1024, etc.), Memory in MB - GCP Cloud Run: CPU in millicores, Memory in MB/GB - Azure Container Instances: CPU cores (0.5, 1, 2, 4), Memory in GB
type ResourceConfig struct {
// CPU in provider-specific units:
// - AWS ECS: 256, 512, 1024, 2048, 4096 (CPU units)
// - GCP Cloud Run: 1000, 2000, 4000 (millicores)
// - Azure ACI: 1, 2, 4 (CPU cores)
CPU *int
// Memory in MB (will be converted to provider-specific units)
Memory *int
}
type RuntimeConfig
RuntimeConfig specifies platform and architecture requirements. Abstracts provider-specific runtime platform specifications.
type RuntimeConfig struct {
// Platform specifies the OS and architecture (e.g., "linux/amd64", "linux/arm64")
// All providers support these standard platform strings
Platform *string
}
type Service
Service provides the core business logic for command execution and user management.
type Service struct {
Logger *slog.Logger
Provider constants.BackendProvider
// contains filtered or unexported fields
}
func Initialize
func Initialize(ctx context.Context, cfg *config.Config, baseLogger *slog.Logger) (*Service, error)
Initialize creates a new Service configured for the specified backend provider. It returns an error if the context is canceled, timed out, or if an unknown provider is specified. Callers should handle errors and potentially panic if initialization fails during startup. Also initializes the Casbin enforcer for authorization.
Supported cloud providers:
- "aws": Uses DynamoDB for storage, Fargate for execution
- "gcp": (future) E.g. using Google Cloud Run and Firestore for storage
func NewService
func NewService(ctx context.Context, repos *database.Repositories, taskManager contract.TaskManager, imageRegistry contract.ImageRegistry, logManager contract.LogManager, observabilityManager contract.ObservabilityManager, log *slog.Logger, provider constants.BackendProvider, wsManager contract.WebSocketManager, healthManager contract.HealthManager, enforcer *authorization.Enforcer) (*Service, error)
NewService creates a new service instance and initializes the enforcer with user roles from the database. Returns an error if the enforcer is configured but user roles cannot be loaded (critical initialization failure). Core repositories (repos.User, repos.Execution) and enforcer are required for initialization and must be non-nil. If wsManager is nil, WebSocket URL generation will be skipped. If repos.Secrets is nil, secrets operations will not be available. If repos.Image is nil, image-by-request-ID queries will not be available. If healthManager is nil, health reconciliation will not be available.
func (*Service) AuthenticateUser
func (s *Service) AuthenticateUser(ctx context.Context, apiKey string) (*api.User, error)
AuthenticateUser verifies an API key and returns the associated user. Returns appropriate errors for invalid API keys, revoked keys, or server errors.
func (*Service) ClaimAPIKey
func (s *Service) ClaimAPIKey(ctx context.Context, secretToken string, ipAddress string) (*api.ClaimAPIKeyResponse, error)
ClaimAPIKey retrieves and claims a pending API key by its secret token.
func (*Service) CreateSecret
func (s *Service) CreateSecret(ctx context.Context, req *api.CreateSecretRequest, userEmail string) error
CreateSecret creates a new secret with the given name, description, key name, and value.
func (*Service) CreateUser
func (s *Service) CreateUser(ctx context.Context, req api.CreateUserRequest, createdByEmail string) (*api.CreateUserResponse, error)
CreateUser creates a new user with an API key and returns a claim token. If no API key is provided in the request, one will be generated. Requires a valid role to be specified in the request.
func (*Service) DeleteSecret
func (s *Service) DeleteSecret(ctx context.Context, name string) error
DeleteSecret deletes a secret and its value.
func (*Service) FetchBackendLogs
func (s *Service) FetchBackendLogs(ctx context.Context, requestID string) ([]api.LogEvent, error)
FetchBackendLogs retrieves backend infrastructure logs for the provided requestID. Returns logs from backend services for debugging and tracing.
func (*Service) FetchTrace
func (s *Service) FetchTrace(ctx context.Context, requestID string) (*api.TraceResponse, error)
FetchTrace retrieves backend logs and related resources for a request ID.
func (*Service) GetEnforcer
func (s *Service) GetEnforcer() *authorization.Enforcer
GetEnforcer returns the Casbin enforcer for authorization checks.
func (*Service) GetExecutionStatus
func (s *Service) GetExecutionStatus(ctx context.Context, executionID string) (*api.ExecutionStatusResponse, error)
GetExecutionStatus returns the current status and metadata for a given execution ID.
func (*Service) GetImage
func (s *Service) GetImage(ctx context.Context, image string) (*api.ImageInfo, error)
GetImage returns a single registered Docker image by ID or name.
func (*Service) GetLogsByExecutionID
func (s *Service) GetLogsByExecutionID(ctx context.Context, executionID string, userEmail *string, clientIPAtCreationTime *string) (*api.LogsResponse, error)
GetLogsByExecutionID returns aggregated Cloud logs for a given execution. WebSocket endpoint is stored without protocol (normalized in config). Always use wss:// for production WebSocket connections. userEmail: authenticated user email for audit trail. clientIPAtCreationTime: client IP captured when the token was created (for tracing). If task is not running, don't return a WebSocket URL.
func (*Service) GetSecret
func (s *Service) GetSecret(ctx context.Context, name string) (*api.Secret, error)
GetSecret retrieves a secret's metadata and value by name.
func (*Service) ImageRegistry
func (s *Service) ImageRegistry() contract.ImageRegistry
ImageRegistry returns the image management interface.
func (*Service) KillExecution
func (s *Service) KillExecution(ctx context.Context, executionID string) (*api.KillExecutionResponse, error)
KillExecution terminates a running execution identified by executionID. It verifies the execution exists in the database and checks task status before termination. Updates the execution status to TERMINATING after successful task stop.
This operation is idempotent: if the execution is already in a terminal state (SUCCEEDED, FAILED, STOPPED, TERMINATING), it returns nil, nil (which results in HTTP 204 No Content), indicating that no action was taken. If termination is initiated, returns a KillExecutionResponse with the execution ID and a success message.
Returns an error if the execution is not found or termination fails.
func (*Service) ListExecutions
func (s *Service) ListExecutions(ctx context.Context, limit int, statuses []string) ([]*api.Execution, error)
ListExecutions returns executions from the database with optional filtering. Parameters:
- limit: maximum number of executions to return
- statuses: optional list of execution statuses to filter by
If statuses is provided, only executions matching one of the specified statuses are returned. Results are returned sorted by started_at in descending order (newest first). Fields with no values are omitted in JSON due to omitempty tags on api.Execution.
func (*Service) ListImages
func (s *Service) ListImages(ctx context.Context) (*api.ListImagesResponse, error)
ListImages returns all registered Docker images.
func (*Service) ListSecrets
func (s *Service) ListSecrets(ctx context.Context) ([]*api.Secret, error)
ListSecrets retrieves all secrets with values.
func (*Service) ListUsers
func (s *Service) ListUsers(ctx context.Context) (*api.ListUsersResponse, error)
ListUsers returns all users in the system sorted by email (excluding API key hashes for security). Returns an error if the query fails. Sorting is delegated to the repository implementation (e.g., DynamoDB GSI).
func (*Service) LogManager
func (s *Service) LogManager() contract.LogManager
LogManager returns the log management interface.
func (*Service) ObservabilityManager
func (s *Service) ObservabilityManager() contract.ObservabilityManager
ObservabilityManager returns the observability interface.
func (*Service) ReconcileResources
func (s *Service) ReconcileResources(ctx context.Context) (*api.HealthReport, error)
ReconcileResources performs health reconciliation for all resources. This method allows synchronous execution via API.
func (*Service) RegisterImage
func (s *Service) RegisterImage(ctx context.Context, req *api.RegisterImageRequest, createdBy string) (*api.RegisterImageResponse, error)
RegisterImage registers a Docker image and creates the corresponding task definition. After successful registration, ownership is synced to the Casbin enforcer to maintain consistency with the database. If ownership sync fails, an error is logged but registration succeeds; ownership will be synced during the next hydration cycle or health reconcile.
func (*Service) RemoveImage
func (s *Service) RemoveImage(ctx context.Context, image string) error
RemoveImage removes a Docker image and deregisters its task definitions.
func (*Service) ResolveImage
func (s *Service) ResolveImage(ctx context.Context, image string) (*api.ImageInfo, error)
ResolveImage resolves a user-provided image string to a specific ImageInfo. If image string is empty, returns the default image. This centralizes image resolution logic for authorization and execution.
func (*Service) RevokeUser
func (s *Service) RevokeUser(ctx context.Context, email string) error
RevokeUser marks a user's API key as revoked. Returns an error if the user does not exist or revocation fails.
func (*Service) RunCommand
func (s *Service) RunCommand(ctx context.Context, userEmail string, req *api.ExecutionRequest, resolvedImage *api.ImageInfo) (*api.ExecutionResponse, error)
RunCommand starts a provider-specific task and records the execution. The resolvedImage parameter contains the validated image that will be used for execution. The request's Image field is replaced with the imageID before passing to the runner. Secret references are resolved to environment variables before starting the task. Execution status is set to STARTING after the task has been accepted by the provider.
func (*Service) TaskManager
func (s *Service) TaskManager() contract.TaskManager
TaskManager returns the task execution interface.
func (*Service) UpdateSecret
func (s *Service) UpdateSecret(ctx context.Context, name string, req *api.UpdateSecretRequest, userEmail string) error
UpdateSecret updates a secret (metadata and/or value).
func (*Service) UpdateUserLastUsed
func (s *Service) UpdateUserLastUsed(ctx context.Context, email string) (*time.Time, error)
UpdateUserLastUsed updates the user's last_used timestamp after successful authentication. This is a best-effort operation; callers may choose to log failures without failing the request.
func (*Service) ValidateExecutionResourceAccess
func (s *Service) ValidateExecutionResourceAccess(ctx context.Context, userEmail string, req *api.ExecutionRequest, resolvedImage *api.ImageInfo) error
ValidateExecutionResourceAccess checks if a user can access all resources required for execution. The resolvedImage parameter contains the image that was resolved from the request and will be validated. All secrets referenced in the execution request are also validated for access. Returns an error if the user lacks access to any required resource.
processor
import "runvoy/internal/backend/processor"
Package processor provides event processing interfaces and utilities.
Package processor provides event processing functionality for cloud provider events. It handles asynchronous events from AWS services like EventBridge, CloudWatch Logs, and WebSocket lifecycle events.
Index
- type Processor
- func Initialize(ctx context.Context, cfg *config.Config, logger *slog.Logger) (Processor, error)
type Processor
Processor defines the interface for event processing across different cloud providers. Each provider implements this interface to handle events specific to their platform.
type Processor interface {
// Handle processes a raw cloud event and returns a result (or nil for non-WebSocket events).
// For WebSocket events, the result is a provider-specific response marshaled as JSON.
Handle(ctx context.Context, rawEvent *json.RawMessage) (*json.RawMessage, error)
// HandleEventJSON is a helper for testing that accepts raw JSON and returns an error.
// It's used for test cases that expect error returns.
HandleEventJSON(ctx context.Context, eventJSON *json.RawMessage) error
}
func Initialize
func Initialize(ctx context.Context, cfg *config.Config, logger *slog.Logger) (Processor, error)
Initialize creates a new Processor configured for the backend provider specified in cfg. It returns an error if the context is canceled, timed out, or if an unknown provider is specified. Callers should handle errors and potentially panic if initialization fails during startup. Also initializes the Casbin enforcer for authorization.
Supported cloud providers:
- "aws": Uses CloudWatch events for ECS task state changes and API Gateway for WebSocket events
- "gcp": (future) Google Cloud Pub/Sub and Cloud Tasks for event processing
websocket
import "runvoy/internal/backend/websocket"
Package websocket provides WebSocket management for runvoy. It handles connection lifecycle events and manages WebSocket connections.
Index
type Manager
Manager exposes the subset of WebSocket manager functionality used by the event processor. Different cloud providers can implement this interface to support their specific WebSocket infrastructure.
type Manager interface {
// HandleRequest processes WebSocket lifecycle events (connect, disconnect, etc.).
// Returns true if the event was handled, false otherwise.
HandleRequest(ctx context.Context, rawEvent *json.RawMessage, reqLogger *slog.Logger) (bool, error)
// NotifyExecutionCompletion sends disconnect notifications to all connected clients for an execution
// and removes the connections.
NotifyExecutionCompletion(ctx context.Context, executionID *string) error
// SendLogsToExecution sends log events to all connected clients for an execution.
SendLogsToExecution(ctx context.Context, executionID *string, logEvents []api.LogEvent) error
// GenerateWebSocketURL creates a WebSocket token and returns the connection URL.
// It stores the token for validation when the client connects.
// Returns an empty string if URL generation fails (errors are logged).
GenerateWebSocketURL(
ctx context.Context,
executionID string,
userEmail *string,
clientIPAtCreationTime *string,
) string
}
infra
import "runvoy/internal/client/infra"
Package infra provides infrastructure deployment functionality.
Package infra provides infrastructure deployment functionality.
Index
- func BuildLogsURL(webURL, executionID string) string
- func ParseParameters(params []string) (map[string]string, error)
- func SeedAdminUser(ctx context.Context, adminEmail, region, tableName string) (string, error)
- type AWSDeployer
- func NewAWSDeployer(ctx context.Context, region string) (*AWSDeployer, error)
- func NewAWSDeployerWithClient(client CloudFormationClient, region string) *AWSDeployer
- func (d *AWSDeployer) CheckStackExists(ctx context.Context, stackName string) (bool, error)
- func (d *AWSDeployer) Deploy(ctx context.Context, opts *DeployOptions) (*DeployResult, error)
- func (d *AWSDeployer) Destroy(ctx context.Context, opts *DestroyOptions) (*DestroyResult, error)
- func (d *AWSDeployer) GetRegion() string
- func (d *AWSDeployer) GetStackOutputs(ctx context.Context, stackName string) (map[string]string, error)
- type CloudFormationClient
- type DeployOptions
- type DeployResult
- type Deployer
- func NewDeployer(ctx context.Context, provider, region string) (Deployer, error)
- type DestroyOptions
- type DestroyResult
- type TemplateSource
- func ResolveTemplate(provider, template, version, region string) (*TemplateSource, error)
func BuildLogsURL
func BuildLogsURL(webURL, executionID string) string
BuildLogsURL constructs a properly formatted URL for viewing logs in the web viewer. It takes a base web URL and an execution ID, and returns a URL string with the /logs path and execution_id query parameter properly encoded.
If URL parsing or path joining fails, it falls back to simple string concatenation to ensure a URL is always returned (though it may not be perfectly formatted).
func ParseParameters
func ParseParameters(params []string) (map[string]string, error)
ParseParameters parses KEY=VALUE parameter strings
func SeedAdminUser
func SeedAdminUser(ctx context.Context, adminEmail, region, tableName string) (string, error)
SeedAdminUser seeds an admin user into the database and returns the generated API key. This function hides the DynamoDB implementation details from callers.
type AWSDeployer
AWSDeployer implements Deployer for AWS CloudFormation
type AWSDeployer struct {
// contains filtered or unexported fields
}
func NewAWSDeployer
func NewAWSDeployer(ctx context.Context, region string) (*AWSDeployer, error)
NewAWSDeployer creates a new AWS deployer with the given region. If region is empty, uses the AWS SDK default.
func NewAWSDeployerWithClient
func NewAWSDeployerWithClient(client CloudFormationClient, region string) *AWSDeployer
NewAWSDeployerWithClient creates a new AWS deployer with a custom client (for testing)
func (*AWSDeployer) CheckStackExists
func (d *AWSDeployer) CheckStackExists(ctx context.Context, stackName string) (bool, error)
CheckStackExists checks if a CloudFormation stack exists
func (*AWSDeployer) Deploy
func (d *AWSDeployer) Deploy(ctx context.Context, opts *DeployOptions) (*DeployResult, error)
Deploy deploys or updates the CloudFormation stack
func (*AWSDeployer) Destroy
func (d *AWSDeployer) Destroy(ctx context.Context, opts *DestroyOptions) (*DestroyResult, error)
Destroy destroys the CloudFormation stack
func (*AWSDeployer) GetRegion
func (d *AWSDeployer) GetRegion() string
GetRegion returns the AWS region being used
func (*AWSDeployer) GetStackOutputs
func (d *AWSDeployer) GetStackOutputs(ctx context.Context, stackName string) (map[string]string, error)
GetStackOutputs retrieves the outputs from a CloudFormation stack
type CloudFormationClient
CloudFormationClient defines the interface for CloudFormation operations. This interface enables mocking for unit tests.
type CloudFormationClient interface {
DescribeStacks(
ctx context.Context,
params *cloudformation.DescribeStacksInput,
optFns ...func(*cloudformation.Options),
) (*cloudformation.DescribeStacksOutput, error)
DescribeStackEvents(
ctx context.Context,
params *cloudformation.DescribeStackEventsInput,
optFns ...func(*cloudformation.Options),
) (*cloudformation.DescribeStackEventsOutput, error)
CreateStack(
ctx context.Context,
params *cloudformation.CreateStackInput,
optFns ...func(*cloudformation.Options),
) (*cloudformation.CreateStackOutput, error)
UpdateStack(
ctx context.Context,
params *cloudformation.UpdateStackInput,
optFns ...func(*cloudformation.Options),
) (*cloudformation.UpdateStackOutput, error)
DeleteStack(
ctx context.Context,
params *cloudformation.DeleteStackInput,
optFns ...func(*cloudformation.Options),
) (*cloudformation.DeleteStackOutput, error)
}
type DeployOptions
DeployOptions contains all options for deploying infrastructure
type DeployOptions struct {
StackName string
Template string // URL, S3 URI, or local file path
Version string // Release version
Parameters []string // KEY=VALUE format
Wait bool // Wait for completion
Region string // Provider region (optional)
}
type DeployResult
DeployResult contains the result of a deployment operation
type DeployResult struct {
StackName string
OperationType string // "CREATE" or "UPDATE"
Status string
Outputs map[string]string
NoChanges bool // True if stack was already up to date
}
type Deployer
Deployer defines the interface for infrastructure deployment. Different cloud providers implement this interface.
type Deployer interface {
// Deploy deploys or updates infrastructure
Deploy(ctx context.Context, opts *DeployOptions) (*DeployResult, error)
// Destroy destroys infrastructure
Destroy(ctx context.Context, opts *DestroyOptions) (*DestroyResult, error)
// CheckStackExists checks if the infrastructure stack exists
CheckStackExists(ctx context.Context, stackName string) (bool, error)
// GetStackOutputs retrieves outputs from a deployed stack
GetStackOutputs(ctx context.Context, stackName string) (map[string]string, error)
// GetRegion returns the region being used
GetRegion() string
}
func NewDeployer
func NewDeployer(ctx context.Context, provider, region string) (Deployer, error)
NewDeployer creates a Deployer for the specified provider. Currently supports: "aws"
type DestroyOptions
DestroyOptions contains all options for destroying infrastructure
type DestroyOptions struct {
StackName string
Wait bool // Wait for completion
Region string // Provider region (optional)
}
type DestroyResult
DestroyResult contains the result of a destroy operation
type DestroyResult struct {
StackName string
Status string
NotFound bool // True if stack was already deleted
}
type TemplateSource
TemplateSource represents the resolved template source
type TemplateSource struct {
URL string // For remote templates (S3/HTTPS)
Body string // For local file templates
}
func ResolveTemplate
func ResolveTemplate(provider, template, version, region string) (*TemplateSource, error)
ResolveTemplate determines the template source from the given input. Returns a TemplateSource with either URL or Body populated. region is the provider region to use for building default template URLs.
output
import "runvoy/internal/client/output"
Package output provides formatted terminal output utilities. It includes colors, spinners, progress bars, and other CLI display helpers.
Index
- Variables
- func Blank()
- func Bold(text string) string
- func Box(text string)
- func Bytes(b int64) string
- func Confirm(prompt string) bool
- func Cyan(text string) string
- func Duration(d time.Duration) string
- func Errorf(format string, a ...any)
- func Fatalf(format string, a ...any)
- func Gray(text string) string
- func Green(text string) string
- func Header(text string)
- func Infof(format string, a ...any)
- func KeyValue(key, value string)
- func KeyValueBold(key, value string)
- func List(items []string)
- func NumberedList(items []string)
- func Printf(format string, a ...any)
- func Println(a ...any)
- func Prompt(prompt string) string
- func PromptRequired(prompt string) string
- func PromptSecret(prompt string) string
- func Red(text string) string
- func StatusBadge(status string) string
- func Step(step, total int, message string)
- func StepError(step, total int, message string)
- func StepSuccess(step, total int, message string)
- func Subheader(text string)
- func Successf(format string, a ...any)
- func Table(headers []string, rows [][]string)
- func Warningf(format string, a ...any)
- func Yellow(text string) string
- type ProgressBar
- func NewProgressBar(total int, message string) *ProgressBar
- func (p *ProgressBar) Complete()
- func (p *ProgressBar) Increment()
- func (p *ProgressBar) Update(current int)
- type Spinner
- func NewSpinner(message string) *Spinner
- func (s *Spinner) Error(message string)
- func (s *Spinner) Start()
- func (s *Spinner) Stop()
- func (s *Spinner) Success(message string)
Variables
var (
// Stdout is the output writer for normal output (can be overridden for testing).
Stdout io.Writer = os.Stdout
// Stderr is the output writer for error output (can be overridden for testing).
Stderr io.Writer = os.Stderr
)
func Blank
func Blank()
Blank prints a blank line
func Bold
func Bold(text string) string
Bold prints text in bold
func Box
func Box(text string)
Box prints text in a rounded box (to stderr) Example: ╭─────────────────────────────╮ │ Configuration saved! │ ╰─────────────────────────────╯
func Bytes
func Bytes(b int64) string
Bytes formats bytes in a human-readable way
func Confirm
func Confirm(prompt string) bool
Confirm prompts the user for yes/no confirmation Returns true if user confirms (y/Y), false otherwise
func Cyan
func Cyan(text string) string
Cyan prints text in cyan
func Duration
func Duration(d time.Duration) string
Duration formats a duration in a human-readable way
func Errorf
func Errorf(format string, a ...any)
Errorf prints an error message with an X symbol (to stderr) Example: ✗ Failed to create stack: permission denied
func Fatalf
func Fatalf(format string, a ...any)
Fatalf prints an error message and exits with code 1
func Gray
func Gray(text string) string
Gray prints text in gray
func Green
func Green(text string) string
Green prints text in green
func Header
func Header(text string)
Header prints a section header with a separator line (to stderr) Example: 🚀 Initializing runvoy infrastructure ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
func Infof
func Infof(format string, a ...any)
Infof prints an informational message with an arrow (to stderr) Example: → Creating CloudFormation stack...
func KeyValue
func KeyValue(key, value string)
KeyValue prints a key-value pair with indentation Example: Stack name: runvoy
func KeyValueBold
func KeyValueBold(key, value string)
KeyValueBold prints a key-value pair with bold value Example: API Key: sk_live_abc123...
func List
func List(items []string)
List prints a bulleted list Example:
- Item one
- Item two
- Item three
func NumberedList
func NumberedList(items []string)
NumberedList prints a numbered list Example:
- First step
- Second step
- Third step
func Printf
func Printf(format string, a ...any)
Printf prints a formatted plain line
func Println
func Println(a ...any)
Println prints a plain line without any formatting
func Prompt
func Prompt(prompt string) string
Prompt prompts the user for input
func PromptRequired
func PromptRequired(prompt string) string
PromptRequired prompts the user for input and requires a non-empty response
func PromptSecret
func PromptSecret(prompt string) string
PromptSecret prompts for sensitive input (like passwords) Note: This is a simple implementation. For production, consider using golang.org/x/term for proper terminal handling
func Red
func Red(text string) string
Red prints text in red
func StatusBadge
func StatusBadge(status string) string
StatusBadge prints a colored status badge
func Step
func Step(step, total int, message string)
Step prints a step in a multi-step process (to stderr) Example: 1/3 Waiting for stack creation
func StepError
func StepError(step, total int, message string)
StepError prints a failed step (to stderr) Example: 2/3 ✗ Failed to generate API key
func StepSuccess
func StepSuccess(step, total int, message string)
StepSuccess prints a successful step completion (to stderr) Example: 1/3 ✓ Stack created
func Subheader
func Subheader(text string)
Subheader prints a smaller section header (to stderr) Example: Configuration Details ────────────────────
func Successf
func Successf(format string, a ...any)
Successf prints a success message with a checkmark (to stderr) Example: ✓ Stack created successfully
func Table
func Table(headers []string, rows [][]string)
Table prints a simple table with headers Example: Execution ID Status Duration ──────────── ────── ──────── exec_abc123 completed 10m 35s exec_def456 running 2m 15s
func Warningf
func Warningf(format string, a ...any)
Warningf prints a warning message with a warning symbol (to stderr) Example: ⚠ Lock already held by alice@acme.com
func Yellow
func Yellow(text string) string
Yellow prints text in yellow
type ProgressBar
ProgressBar represents a simple text progress bar
type ProgressBar struct {
// contains filtered or unexported fields
}
func NewProgressBar
func NewProgressBar(total int, message string) *ProgressBar
NewProgressBar creates a new progress bar
func (*ProgressBar) Complete
func (p *ProgressBar) Complete()
Complete marks the progress bar as complete
func (*ProgressBar) Increment
func (p *ProgressBar) Increment()
Increment increments the progress bar by 1
func (*ProgressBar) Update
func (p *ProgressBar) Update(current int)
Update updates the progress bar to the given value (to stderr)
type Spinner
Spinner represents a simple text spinner for long operations
type Spinner struct {
// contains filtered or unexported fields
}
func NewSpinner
func NewSpinner(message string) *Spinner
NewSpinner creates a new spinner with the given message
func (*Spinner) Error
func (s *Spinner) Error(message string)
Error stops the spinner and prints an error message
func (*Spinner) Start
func (s *Spinner) Start()
Start starts the spinner animation (to stderr)
func (*Spinner) Stop
func (s *Spinner) Stop()
Stop stops the spinner and clears the line
func (*Spinner) Success
func (s *Spinner) Success(message string)
Success stops the spinner and prints a success message
playbooks
import "runvoy/internal/client/playbooks"
Package playbooks provides functionality for loading and managing playbooks.
Package playbooks provides functionality for loading and managing playbooks.
Index
- type PlaybookExecutor
- func NewPlaybookExecutor() *PlaybookExecutor
- func (e *PlaybookExecutor) ToExecutionRequest(playbook *api.Playbook, userEnv map[string]string, userSecrets []string) *api.ExecutionRequest
- type PlaybookLoader
- func NewPlaybookLoader() *PlaybookLoader
- func (l *PlaybookLoader) GetPlaybookDir() (string, error)
- func (l *PlaybookLoader) ListPlaybooks() ([]string, error)
- func (l *PlaybookLoader) LoadPlaybook(name string) (*api.Playbook, error)
type PlaybookExecutor
PlaybookExecutor converts Playbook to ExecutionRequest
type PlaybookExecutor struct{}
func NewPlaybookExecutor
func NewPlaybookExecutor() *PlaybookExecutor
NewPlaybookExecutor creates a new PlaybookExecutor
func (*PlaybookExecutor) ToExecutionRequest
func (e *PlaybookExecutor) ToExecutionRequest(playbook *api.Playbook, userEnv map[string]string, userSecrets []string) *api.ExecutionRequest
ToExecutionRequest converts a Playbook to an ExecutionRequest. Combines multiple commands with && operator and merges env vars and secrets.
type PlaybookLoader
PlaybookLoader handles loading and discovery of playbooks
type PlaybookLoader struct{}
func NewPlaybookLoader
func NewPlaybookLoader() *PlaybookLoader
NewPlaybookLoader creates a new PlaybookLoader
func (*PlaybookLoader) GetPlaybookDir
func (l *PlaybookLoader) GetPlaybookDir() (string, error)
GetPlaybookDir returns the path to the playbook directory. Checks current working directory first, falls back to home directory.
func (*PlaybookLoader) ListPlaybooks
func (l *PlaybookLoader) ListPlaybooks() ([]string, error)
ListPlaybooks scans the playbook directory for YAML files and returns playbook names. Returns empty list if directory doesn't exist.
func (*PlaybookLoader) LoadPlaybook
func (l *PlaybookLoader) LoadPlaybook(name string) (*api.Playbook, error)
LoadPlaybook loads and parses a playbook YAML file.
aws
import "runvoy/internal/config/aws"
Package aws contains AWS-specific configuration helpers for Runvoy services.
Index
- func BindEnvVars(v *viper.Viper)
- func BuildTemplateURL(version, region string) string
- func NormalizeVersion(version string) string
- func NormalizeWebSocketEndpoint(endpoint string) string
- func ValidateEventProcessor(cfg *Config) error
- func ValidateOrchestrator(cfg *Config) error
- type Config
- func (c *Config) LoadSDKConfig(ctx context.Context) error
func BindEnvVars
func BindEnvVars(v *viper.Viper)
BindEnvVars binds AWS-specific environment variables to the provided Viper instance.
func BuildTemplateURL
func BuildTemplateURL(version, region string) string
BuildTemplateURL builds the S3 HTTPS URL for the CloudFormation template. The version is normalized to remove any 'v' prefix before building the URL. If region is empty, defaults to the ReleasesBucketRegion constant.
func NormalizeVersion
func NormalizeVersion(version string) string
NormalizeVersion strips any 'v' prefix from the version string. S3 paths use versions without the 'v' prefix (e.g., "0.1.0" not "v0.1.0").
func NormalizeWebSocketEndpoint
func NormalizeWebSocketEndpoint(endpoint string) string
NormalizeWebSocketEndpoint strips protocol prefixes from WebSocket endpoint URLs. Accepts: https://example.com, http://example.com, wss://example.com, ws://example.com, example.com Returns: example.com (without protocol)
func ValidateEventProcessor
func ValidateEventProcessor(cfg *Config) error
ValidateEventProcessor validates required AWS fields for the event processor service.
func ValidateOrchestrator
func ValidateOrchestrator(cfg *Config) error
ValidateOrchestrator validates required AWS fields for the orchestrator service.
type Config
Config contains AWS-specific configuration. These settings are only used when the backend provider is AWS.
type Config struct {
// DynamoDB Tables
APIKeysTable string `mapstructure:"api_keys_table"`
ExecutionsTable string `mapstructure:"executions_table"`
ImageTaskDefsTable string `mapstructure:"image_taskdefs_table"`
PendingAPIKeysTable string `mapstructure:"pending_api_keys_table"`
SecretsMetadataTable string `mapstructure:"secrets_metadata_table"`
WebSocketConnectionsTable string `mapstructure:"websocket_connections_table"`
WebSocketTokensTable string `mapstructure:"websocket_tokens_table"`
// ECS Configuration
DefaultTaskExecRoleARN string `mapstructure:"default_task_exec_role_arn"`
DefaultTaskRoleARN string `mapstructure:"default_task_role_arn"`
ECSCluster string `mapstructure:"ecs_cluster"`
SecurityGroup string `mapstructure:"security_group"`
Subnet1 string `mapstructure:"subnet_1"`
Subnet2 string `mapstructure:"subnet_2"`
TaskDefinition string `mapstructure:"task_definition"`
// CloudWatch Logs
LogGroup string `mapstructure:"log_group"`
// API Gateway WebSocket
WebSocketAPIEndpoint string `mapstructure:"websocket_api_endpoint"`
// Secrets Management
SecretsPrefix string `mapstructure:"secrets_prefix"`
SecretsKMSKeyARN string `mapstructure:"secrets_kms_key_arn"`
// Infrastructure defaults
InfraDefaultStackName string `mapstructure:"infra_default_stack_name" yaml:"infra_default_stack_name"`
// AWS SDK Configuration (credentials, region, etc.)
SDKConfig *aws.Config `mapstructure:"-"`
}
func (*Config) LoadSDKConfig
func (c *Config) LoadSDKConfig(ctx context.Context) error
LoadSDKConfig loads the AWS SDK configuration from the environment.
client
import "runvoy/internal/providers/aws/client"
Package client provides AWS-specific client interfaces for AWS services. This package contains the interfaces for the AWS clients used by the Runvoy orchestrator.
Index
- type CloudWatchLogsClient
- type CloudWatchLogsClientAdapter
- func NewCloudWatchLogsClientAdapter(client *cloudwatchlogs.Client) *CloudWatchLogsClientAdapter
- func (a *CloudWatchLogsClientAdapter) DescribeLogGroups(ctx context.Context, params *cloudwatchlogs.DescribeLogGroupsInput, optFns ...func(*cloudwatchlogs.Options)) (*cloudwatchlogs.DescribeLogGroupsOutput, error)
- func (a *CloudWatchLogsClientAdapter) DescribeLogStreams(ctx context.Context, params *cloudwatchlogs.DescribeLogStreamsInput, optFns ...func(*cloudwatchlogs.Options)) (*cloudwatchlogs.DescribeLogStreamsOutput, error)
- func (a *CloudWatchLogsClientAdapter) GetLogEvents(ctx context.Context, params *cloudwatchlogs.GetLogEventsInput, optFns ...func(*cloudwatchlogs.Options)) (*cloudwatchlogs.GetLogEventsOutput, error)
- func (a *CloudWatchLogsClientAdapter) GetQueryResults(ctx context.Context, params *cloudwatchlogs.GetQueryResultsInput, optFns ...func(*cloudwatchlogs.Options)) (*cloudwatchlogs.GetQueryResultsOutput, error)
- func (a *CloudWatchLogsClientAdapter) StartQuery(ctx context.Context, params *cloudwatchlogs.StartQueryInput, optFns ...func(*cloudwatchlogs.Options)) (*cloudwatchlogs.StartQueryOutput, error)
- type ECSClient
- type ECSClientAdapter
- func NewECSClientAdapter(client *ecs.Client) *ECSClientAdapter
- func (a *ECSClientAdapter) DeleteTaskDefinitions(ctx context.Context, params *ecs.DeleteTaskDefinitionsInput, optFns ...func(*ecs.Options)) (*ecs.DeleteTaskDefinitionsOutput, error)
- func (a *ECSClientAdapter) DeregisterTaskDefinition(ctx context.Context, params *ecs.DeregisterTaskDefinitionInput, optFns ...func(*ecs.Options)) (*ecs.DeregisterTaskDefinitionOutput, error)
- func (a *ECSClientAdapter) DescribeTaskDefinition(ctx context.Context, params *ecs.DescribeTaskDefinitionInput, optFns ...func(*ecs.Options)) (*ecs.DescribeTaskDefinitionOutput, error)
- func (a *ECSClientAdapter) DescribeTasks(ctx context.Context, params *ecs.DescribeTasksInput, optFns ...func(*ecs.Options)) (*ecs.DescribeTasksOutput, error)
- func (a *ECSClientAdapter) ListTagsForResource(ctx context.Context, params *ecs.ListTagsForResourceInput, optFns ...func(*ecs.Options)) (*ecs.ListTagsForResourceOutput, error)
- func (a *ECSClientAdapter) ListTaskDefinitions(ctx context.Context, params *ecs.ListTaskDefinitionsInput, optFns ...func(*ecs.Options)) (*ecs.ListTaskDefinitionsOutput, error)
- func (a *ECSClientAdapter) ListTasks(ctx context.Context, params *ecs.ListTasksInput, optFns ...func(*ecs.Options)) (*ecs.ListTasksOutput, error)
- func (a *ECSClientAdapter) RegisterTaskDefinition(ctx context.Context, params *ecs.RegisterTaskDefinitionInput, optFns ...func(*ecs.Options)) (*ecs.RegisterTaskDefinitionOutput, error)
- func (a *ECSClientAdapter) RunTask(ctx context.Context, params *ecs.RunTaskInput, optFns ...func(*ecs.Options)) (*ecs.RunTaskOutput, error)
- func (a *ECSClientAdapter) StopTask(ctx context.Context, params *ecs.StopTaskInput, optFns ...func(*ecs.Options)) (*ecs.StopTaskOutput, error)
- func (a *ECSClientAdapter) TagResource(ctx context.Context, params *ecs.TagResourceInput, optFns ...func(*ecs.Options)) (*ecs.TagResourceOutput, error)
- func (a *ECSClientAdapter) UntagResource(ctx context.Context, params *ecs.UntagResourceInput, optFns ...func(*ecs.Options)) (*ecs.UntagResourceOutput, error)
- type IAMClient
- type IAMClientAdapter
- func NewIAMClientAdapter(client *iam.Client) *IAMClientAdapter
- func (a *IAMClientAdapter) GetRole(ctx context.Context, params *iam.GetRoleInput, optFns ...func(*iam.Options)) (*iam.GetRoleOutput, error)
type CloudWatchLogsClient
CloudWatchLogsClient defines the interface for CloudWatch Logs operations used by the runner. This interface makes the code easier to test by allowing mock implementations.
type CloudWatchLogsClient interface {
DescribeLogGroups(
ctx context.Context,
params *cloudwatchlogs.DescribeLogGroupsInput,
optFns ...func(*cloudwatchlogs.Options),
) (*cloudwatchlogs.DescribeLogGroupsOutput, error)
DescribeLogStreams(
ctx context.Context,
params *cloudwatchlogs.DescribeLogStreamsInput,
optFns ...func(*cloudwatchlogs.Options),
) (*cloudwatchlogs.DescribeLogStreamsOutput, error)
GetLogEvents(
ctx context.Context,
params *cloudwatchlogs.GetLogEventsInput,
optFns ...func(*cloudwatchlogs.Options),
) (*cloudwatchlogs.GetLogEventsOutput, error)
StartQuery(
ctx context.Context,
params *cloudwatchlogs.StartQueryInput,
optFns ...func(*cloudwatchlogs.Options),
) (*cloudwatchlogs.StartQueryOutput, error)
GetQueryResults(
ctx context.Context,
params *cloudwatchlogs.GetQueryResultsInput,
optFns ...func(*cloudwatchlogs.Options),
) (*cloudwatchlogs.GetQueryResultsOutput, error)
}
type CloudWatchLogsClientAdapter
CloudWatchLogsClientAdapter wraps the AWS SDK CloudWatch Logs client to implement CloudWatchLogsClient interface. This allows us to use the real AWS client in production while maintaining testability.
type CloudWatchLogsClientAdapter struct {
// contains filtered or unexported fields
}
func NewCloudWatchLogsClientAdapter
func NewCloudWatchLogsClientAdapter(client *cloudwatchlogs.Client) *CloudWatchLogsClientAdapter
NewCloudWatchLogsClientAdapter creates a new adapter wrapping the AWS SDK CloudWatch Logs client.
func (*CloudWatchLogsClientAdapter) DescribeLogGroups
func (a *CloudWatchLogsClientAdapter) DescribeLogGroups(ctx context.Context, params *cloudwatchlogs.DescribeLogGroupsInput, optFns ...func(*cloudwatchlogs.Options)) (*cloudwatchlogs.DescribeLogGroupsOutput, error)
DescribeLogGroups wraps the AWS SDK DescribeLogGroups operation.
func (*CloudWatchLogsClientAdapter) DescribeLogStreams
func (a *CloudWatchLogsClientAdapter) DescribeLogStreams(ctx context.Context, params *cloudwatchlogs.DescribeLogStreamsInput, optFns ...func(*cloudwatchlogs.Options)) (*cloudwatchlogs.DescribeLogStreamsOutput, error)
DescribeLogStreams wraps the AWS SDK DescribeLogStreams operation.
func (*CloudWatchLogsClientAdapter) GetLogEvents
func (a *CloudWatchLogsClientAdapter) GetLogEvents(ctx context.Context, params *cloudwatchlogs.GetLogEventsInput, optFns ...func(*cloudwatchlogs.Options)) (*cloudwatchlogs.GetLogEventsOutput, error)
GetLogEvents wraps the AWS SDK GetLogEvents operation.
func (*CloudWatchLogsClientAdapter) GetQueryResults
func (a *CloudWatchLogsClientAdapter) GetQueryResults(ctx context.Context, params *cloudwatchlogs.GetQueryResultsInput, optFns ...func(*cloudwatchlogs.Options)) (*cloudwatchlogs.GetQueryResultsOutput, error)
GetQueryResults wraps the AWS SDK GetQueryResults operation for CloudWatch Logs Insights.
func (*CloudWatchLogsClientAdapter) StartQuery
func (a *CloudWatchLogsClientAdapter) StartQuery(ctx context.Context, params *cloudwatchlogs.StartQueryInput, optFns ...func(*cloudwatchlogs.Options)) (*cloudwatchlogs.StartQueryOutput, error)
StartQuery wraps the AWS SDK StartQuery operation for CloudWatch Logs Insights.
type ECSClient
ECSClient defines the interface for ECS operations used across AWS provider packages. This interface makes the code easier to test by allowing mock implementations.
type ECSClient interface {
RunTask(
ctx context.Context,
params *ecs.RunTaskInput,
optFns ...func(*ecs.Options),
) (*ecs.RunTaskOutput, error)
TagResource(
ctx context.Context,
params *ecs.TagResourceInput,
optFns ...func(*ecs.Options),
) (*ecs.TagResourceOutput, error)
ListTasks(
ctx context.Context,
params *ecs.ListTasksInput,
optFns ...func(*ecs.Options),
) (*ecs.ListTasksOutput, error)
DescribeTasks(
ctx context.Context,
params *ecs.DescribeTasksInput,
optFns ...func(*ecs.Options),
) (*ecs.DescribeTasksOutput, error)
StopTask(
ctx context.Context,
params *ecs.StopTaskInput,
optFns ...func(*ecs.Options),
) (*ecs.StopTaskOutput, error)
DescribeTaskDefinition(
ctx context.Context,
params *ecs.DescribeTaskDefinitionInput,
optFns ...func(*ecs.Options),
) (*ecs.DescribeTaskDefinitionOutput, error)
ListTagsForResource(
ctx context.Context,
params *ecs.ListTagsForResourceInput,
optFns ...func(*ecs.Options),
) (*ecs.ListTagsForResourceOutput, error)
ListTaskDefinitions(
ctx context.Context,
params *ecs.ListTaskDefinitionsInput,
optFns ...func(*ecs.Options),
) (*ecs.ListTaskDefinitionsOutput, error)
RegisterTaskDefinition(
ctx context.Context,
params *ecs.RegisterTaskDefinitionInput,
optFns ...func(*ecs.Options),
) (*ecs.RegisterTaskDefinitionOutput, error)
DeregisterTaskDefinition(
ctx context.Context,
params *ecs.DeregisterTaskDefinitionInput,
optFns ...func(*ecs.Options),
) (*ecs.DeregisterTaskDefinitionOutput, error)
DeleteTaskDefinitions(
ctx context.Context,
params *ecs.DeleteTaskDefinitionsInput,
optFns ...func(*ecs.Options),
) (*ecs.DeleteTaskDefinitionsOutput, error)
UntagResource(
ctx context.Context,
params *ecs.UntagResourceInput,
optFns ...func(*ecs.Options),
) (*ecs.UntagResourceOutput, error)
}
type ECSClientAdapter
ECSClientAdapter wraps the AWS SDK ECS client to implement ECSClient interface. This allows us to use the real AWS client in production while maintaining testability.
type ECSClientAdapter struct {
// contains filtered or unexported fields
}
func NewECSClientAdapter
func NewECSClientAdapter(client *ecs.Client) *ECSClientAdapter
NewECSClientAdapter creates a new adapter wrapping the AWS SDK ECS client.
func (*ECSClientAdapter) DeleteTaskDefinitions
func (a *ECSClientAdapter) DeleteTaskDefinitions(ctx context.Context, params *ecs.DeleteTaskDefinitionsInput, optFns ...func(*ecs.Options)) (*ecs.DeleteTaskDefinitionsOutput, error)
DeleteTaskDefinitions wraps the AWS SDK DeleteTaskDefinitions operation.
func (*ECSClientAdapter) DeregisterTaskDefinition
func (a *ECSClientAdapter) DeregisterTaskDefinition(ctx context.Context, params *ecs.DeregisterTaskDefinitionInput, optFns ...func(*ecs.Options)) (*ecs.DeregisterTaskDefinitionOutput, error)
DeregisterTaskDefinition wraps the AWS SDK DeregisterTaskDefinition operation.
func (*ECSClientAdapter) DescribeTaskDefinition
func (a *ECSClientAdapter) DescribeTaskDefinition(ctx context.Context, params *ecs.DescribeTaskDefinitionInput, optFns ...func(*ecs.Options)) (*ecs.DescribeTaskDefinitionOutput, error)
DescribeTaskDefinition wraps the AWS SDK DescribeTaskDefinition operation.
func (*ECSClientAdapter) DescribeTasks
func (a *ECSClientAdapter) DescribeTasks(ctx context.Context, params *ecs.DescribeTasksInput, optFns ...func(*ecs.Options)) (*ecs.DescribeTasksOutput, error)
DescribeTasks wraps the AWS SDK DescribeTasks operation.
func (*ECSClientAdapter) ListTagsForResource
func (a *ECSClientAdapter) ListTagsForResource(ctx context.Context, params *ecs.ListTagsForResourceInput, optFns ...func(*ecs.Options)) (*ecs.ListTagsForResourceOutput, error)
ListTagsForResource wraps the AWS SDK ListTagsForResource operation.
func (*ECSClientAdapter) ListTaskDefinitions
func (a *ECSClientAdapter) ListTaskDefinitions(ctx context.Context, params *ecs.ListTaskDefinitionsInput, optFns ...func(*ecs.Options)) (*ecs.ListTaskDefinitionsOutput, error)
ListTaskDefinitions wraps the AWS SDK ListTaskDefinitions operation.
func (*ECSClientAdapter) ListTasks
func (a *ECSClientAdapter) ListTasks(ctx context.Context, params *ecs.ListTasksInput, optFns ...func(*ecs.Options)) (*ecs.ListTasksOutput, error)
ListTasks wraps the AWS SDK ListTasks operation.
func (*ECSClientAdapter) RegisterTaskDefinition
func (a *ECSClientAdapter) RegisterTaskDefinition(ctx context.Context, params *ecs.RegisterTaskDefinitionInput, optFns ...func(*ecs.Options)) (*ecs.RegisterTaskDefinitionOutput, error)
RegisterTaskDefinition wraps the AWS SDK RegisterTaskDefinition operation.
func (*ECSClientAdapter) RunTask
func (a *ECSClientAdapter) RunTask(ctx context.Context, params *ecs.RunTaskInput, optFns ...func(*ecs.Options)) (*ecs.RunTaskOutput, error)
RunTask wraps the AWS SDK RunTask operation.
func (*ECSClientAdapter) StopTask
func (a *ECSClientAdapter) StopTask(ctx context.Context, params *ecs.StopTaskInput, optFns ...func(*ecs.Options)) (*ecs.StopTaskOutput, error)
StopTask wraps the AWS SDK StopTask operation.
func (*ECSClientAdapter) TagResource
func (a *ECSClientAdapter) TagResource(ctx context.Context, params *ecs.TagResourceInput, optFns ...func(*ecs.Options)) (*ecs.TagResourceOutput, error)
TagResource wraps the AWS SDK TagResource operation.
func (*ECSClientAdapter) UntagResource
func (a *ECSClientAdapter) UntagResource(ctx context.Context, params *ecs.UntagResourceInput, optFns ...func(*ecs.Options)) (*ecs.UntagResourceOutput, error)
UntagResource wraps the AWS SDK UntagResource operation.
type IAMClient
IAMClient defines the interface for IAM operations used across AWS provider packages. This interface makes the code easier to test by allowing mock implementations.
type IAMClient interface {
GetRole(
ctx context.Context,
params *iam.GetRoleInput,
optFns ...func(*iam.Options),
) (*iam.GetRoleOutput, error)
}
type IAMClientAdapter
IAMClientAdapter wraps the AWS SDK IAM client to implement IAMClient interface. This allows us to use the real AWS client in production while maintaining testability.
type IAMClientAdapter struct {
// contains filtered or unexported fields
}
func NewIAMClientAdapter
func NewIAMClientAdapter(client *iam.Client) *IAMClientAdapter
NewIAMClientAdapter creates a new adapter wrapping the AWS SDK IAM client.
func (*IAMClientAdapter) GetRole
func (a *IAMClientAdapter) GetRole(ctx context.Context, params *iam.GetRoleInput, optFns ...func(*iam.Options)) (*iam.GetRoleOutput, error)
GetRole wraps the AWS SDK GetRole operation.
constants
import "runvoy/internal/providers/aws/constants"
Package constants provides AWS-specific constants for CloudWatch logging and events.
Package constants provides AWS-specific constants for ECS task execution.
Package constants provides AWS-specific constants for infrastructure deployment.
Package constants provides AWS-specific constants and utilities for log stream handling.
Package constants provides AWS-specific constants for secrets management.
Index
- Constants
- func BuildLogStreamName(executionID string) string
- func ExtractExecutionIDFromLogStream(logStream string) string
- func GetReleaseRegions() []string
- func SupportedRuntimePlatforms() []string
- func ValidateRegion(region string) error
- type EcsStatus
Constants
const (
// DefaultInfraStackName is the default CloudFormation stack name for AWS infra deployments
DefaultInfraStackName = "runvoy-backend"
// ReleasesBucketRegion is the AWS region where the releases bucket is located
ReleasesBucketRegion = "us-east-1"
// ReleasesBucket is the S3 bucket name for runvoy releases
ReleasesBucket = "runvoy-releases-" + ReleasesBucketRegion
// CloudFormationTemplateFile is the filename of the CloudFormation template in releases
CloudFormationTemplateFile = "cloudformation-backend.yaml"
)
CloudWatchLogsDescribeLimit is the limit for CloudWatch Logs DescribeLogStreams API
const CloudWatchLogsDescribeLimit = int32(50)
CloudWatchLogsEventsLimit is the limit for CloudWatch Logs GetLogEvents API
const CloudWatchLogsEventsLimit = int32(10000)
CloudWatchLogsQueryInitialDelay is the initial delay in seconds to allow CloudWatch Logs Insights query to become ready before polling
const CloudWatchLogsQueryInitialDelay = 10 * time.Second
CloudWatchLogsQueryMaxAttempts is the maximum number of polling attempts for CloudWatch Logs Insights query results
const CloudWatchLogsQueryMaxAttempts = 30
CloudWatchLogsQueryPollInterval is the polling interval in milliseconds for checking CloudWatch Logs Insights query results
const CloudWatchLogsQueryPollInterval = time.Second
DefaultCPU is the default CPU units for ECS task definitions
const DefaultCPU = 256
DefaultExecutionListCapacity is the initial slice capacity used when listing executions from DynamoDB without an explicit limit.
const DefaultExecutionListCapacity = 16
DefaultMemory is the default memory (in MB) for ECS task definitions
const DefaultMemory = 512
DefaultRuntimePlatform is the default runtime platform for ECS task definitions
const DefaultRuntimePlatform = DefaultRuntimePlatformOSFamily + "/" + DefaultRuntimePlatformArchitecture
DefaultRuntimePlatformArchitecture is the default architecture for ECS task definitions
const DefaultRuntimePlatformArchitecture = RuntimePlatformArchARM64
DefaultRuntimePlatformOSFamily is the default OS family for ECS task definitions
const DefaultRuntimePlatformOSFamily = "Linux"
ECSEphemeralStorageSizeGiB is the ECS ephemeral storage size in GiB
const ECSEphemeralStorageSizeGiB = 21
ECSTaskDefinitionMaxResults is the maximum number of results for ECS ListTaskDefinitions
const ECSTaskDefinitionMaxResults = int32(100)
LogGroupPrefix is the prefix for all runvoy Lambda log groups
const LogGroupPrefix = "/aws/lambda/" + constants.ProjectName
LogStreamPartsCount is the expected number of parts in a log stream name Format: task/{container}/{execution_id} = 3 parts
const LogStreamPartsCount = 3
LogStreamPrefix is the prefix for all log stream names for ECS tasks
const LogStreamPrefix = "task"
RunnerContainerName is the ECS container name used for task execution. Must match the container override name passed in the ECS RunTask call.
const RunnerContainerName = "runner"
RuntimePlatformArchARM64 is the ARM64 architecture for ECS runtime platform
const RuntimePlatformArchARM64 = "ARM64"
RuntimePlatformArchX8664 is the x86_64 architecture for ECS runtime platform
const RuntimePlatformArchX8664 = "X86_64"
SSMParameterMaxResults is the maximum number of results for SSM DescribeParameters
const SSMParameterMaxResults = int32(50)
ScheduledEventHealthReconcile is the expected runvoy_event payload value for EventBridge scheduled events that trigger health reconciliation.
const ScheduledEventHealthReconcile = "health_reconcile"
SecretsPrefix is the prefix for AWS secrets management.
const SecretsPrefix = "/runvoy/secrets" //nolint:gosec // G101: This is a constant, not a hardcoded credential
SharedVolumeName is the name of the shared volume between containers. Used for sharing the cloned git repository from sidecar to main container.
const SharedVolumeName = "workspace"
SharedVolumePath is the mount path for the shared volume in both containers.
const SharedVolumePath = "/workspace"
SidecarContainerName is the sidecar container name for auxiliary tasks. This container runs before the main runner container and handles tasks like .env file generation from user environment variables, git repository cloning, etc.
const SidecarContainerName = "sidecar"
TaskDefinitionDockerImageTagKey is the ECS tag key used to store the Docker image name for metadata
const TaskDefinitionDockerImageTagKey = "DockerImage"
TaskDefinitionFamilyPrefix is the prefix for all runvoy task definition families Task definitions are named: {ProjectName}-image-{sanitized-image-name} e.g., "runvoy-image-hashicorp-terraform-1-6" for image "hashicorp/terraform:1.6"
const TaskDefinitionFamilyPrefix = constants.ProjectName + "-image"
TaskDefinitionIsDefaultTagKey is the ECS tag key used to mark a task definition as the default image
const TaskDefinitionIsDefaultTagKey = "IsDefault"
TaskDefinitionIsDefaultTagValue is the tag value used to mark a task definition as the default image
const TaskDefinitionIsDefaultTagValue = "true"
func BuildLogStreamName
func BuildLogStreamName(executionID string) string
BuildLogStreamName constructs a CloudWatch Logs stream name for an execution. Format: task/{container}/{execution_id} Example: task/runner/abc123
func ExtractExecutionIDFromLogStream
func ExtractExecutionIDFromLogStream(logStream string) string
ExtractExecutionIDFromLogStream extracts the execution ID from a CloudWatch Logs stream name. Expected format: task/{container}/{execution_id} Returns empty string if the format is not recognized.
func GetReleaseRegions
func GetReleaseRegions() []string
GetReleaseRegions returns a slice of supported AWS regions for releases. The regions are parsed from the comma-separated string injected at build time.
func SupportedRuntimePlatforms
func SupportedRuntimePlatforms() []string
SupportedRuntimePlatforms returns the list of supported ECS runtime platforms.
func ValidateRegion
func ValidateRegion(region string) error
ValidateRegion validates that the given region is in the supported regions list. Returns an error if the region is not supported, or if no regions are configured.
type EcsStatus
EcsStatus represents the AWS ECS Task LastStatus lifecycle values. These are string statuses returned by ECS DescribeTasks for Task.LastStatus.
type EcsStatus string
const (
// EcsStatusProvisioning represents a task being provisioned
EcsStatusProvisioning EcsStatus = "PROVISIONING"
// EcsStatusPending represents a task pending activation
EcsStatusPending EcsStatus = "PENDING"
// EcsStatusActivating represents a task being activated
EcsStatusActivating EcsStatus = "ACTIVATING"
// EcsStatusRunning represents a task currently running
EcsStatusRunning EcsStatus = "RUNNING"
// EcsStatusDeactivating represents a task being deactivated
EcsStatusDeactivating EcsStatus = "DEACTIVATING"
// EcsStatusStopping represents a task being stopped
EcsStatusStopping EcsStatus = "STOPPING"
// EcsStatusDeprovisioning represents a task being deprovisioned
EcsStatusDeprovisioning EcsStatus = "DEPROVISIONING"
// EcsStatusStopped represents a task that has stopped
EcsStatusStopped EcsStatus = "STOPPED"
)
database
import "runvoy/internal/providers/aws/database"
Package database provides AWS-specific database implementations. This file contains a SecretsRepository that coordinates DynamoDB and Parameter Store.
Index
- type MetadataRepository
- type Repositories
- func CreateRepositories(dynamoClient dynamoRepo.Client, ssmClient secrets.Client, cfg *config.Config, log *slog.Logger) *Repositories
- type SecretsRepository
- func NewSecretsRepository(metadataRepo MetadataRepository, valueStore secrets.ValueStore, logger *slog.Logger) *SecretsRepository
- func (sr *SecretsRepository) CreateSecret(ctx context.Context, secret *api.Secret) error
- func (sr *SecretsRepository) DeleteSecret(ctx context.Context, name string) error
- func (sr *SecretsRepository) GetSecret(ctx context.Context, name string, includeValue bool) (*api.Secret, error)
- func (sr *SecretsRepository) GetSecretsByRequestID(ctx context.Context, requestID string) ([]*api.Secret, error)
- func (sr *SecretsRepository) ListSecrets(ctx context.Context, includeValue bool) ([]*api.Secret, error)
- func (sr *SecretsRepository) UpdateSecret(ctx context.Context, secret *api.Secret) error
type MetadataRepository
MetadataRepository defines the interface for secret metadata operations.
type MetadataRepository interface {
CreateSecret(ctx context.Context, secret *api.Secret) error
GetSecret(ctx context.Context, name string) (*api.Secret, error)
ListSecrets(ctx context.Context) ([]*api.Secret, error)
UpdateSecretMetadata(ctx context.Context, name, keyName, description, updatedBy string) error
DeleteSecret(ctx context.Context, name string) error
SecretExists(ctx context.Context, name string) (bool, error)
GetSecretsByRequestID(ctx context.Context, requestID string) ([]*api.Secret, error)
}
type Repositories
Repositories bundles all AWS-backed database repositories.
type Repositories struct {
UserRepo database.UserRepository
ExecutionRepo database.ExecutionRepository
ConnectionRepo database.ConnectionRepository
TokenRepo database.TokenRepository
ImageTaskDefRepo *dynamoRepo.ImageTaskDefRepository
SecretsRepo database.SecretsRepository
}
func CreateRepositories
func CreateRepositories(dynamoClient dynamoRepo.Client, ssmClient secrets.Client, cfg *config.Config, log *slog.Logger) *Repositories
CreateRepositories creates all AWS-backed database repositories from the provided clients and configuration.
type SecretsRepository
SecretsRepository implements database.SecretsRepository for AWS. It coordinates DynamoDB (metadata) and Parameter Store (values) to provide a unified interface.
type SecretsRepository struct {
// contains filtered or unexported fields
}
func NewSecretsRepository
func NewSecretsRepository(metadataRepo MetadataRepository, valueStore secrets.ValueStore, logger *slog.Logger) *SecretsRepository
NewSecretsRepository creates a new AWS secrets repository.
func (*SecretsRepository) CreateSecret
func (sr *SecretsRepository) CreateSecret(ctx context.Context, secret *api.Secret) error
CreateSecret stores a new secret with both metadata and value.
func (*SecretsRepository) DeleteSecret
func (sr *SecretsRepository) DeleteSecret(ctx context.Context, name string) error
DeleteSecret removes both the metadata and value of a secret.
func (*SecretsRepository) GetSecret
func (sr *SecretsRepository) GetSecret(ctx context.Context, name string, includeValue bool) (*api.Secret, error)
GetSecret retrieves a secret with its metadata and optionally its value.
func (*SecretsRepository) GetSecretsByRequestID
func (sr *SecretsRepository) GetSecretsByRequestID(ctx context.Context, requestID string) ([]*api.Secret, error)
GetSecretsByRequestID retrieves all secrets created or modified by a specific request ID.
func (*SecretsRepository) ListSecrets
func (sr *SecretsRepository) ListSecrets(ctx context.Context, includeValue bool) ([]*api.Secret, error)
ListSecrets retrieves all secrets with optionally their values.
func (*SecretsRepository) UpdateSecret
func (sr *SecretsRepository) UpdateSecret(ctx context.Context, secret *api.Secret) error
UpdateSecret updates a secret's metadata and/or value.
ecsdefs
import "runvoy/internal/providers/aws/ecsdefs"
Package ecsdefs contains shared ECS task definition utilities for AWS providers. It is intentionally decoupled from the orchestrator package so it can be reused by both the orchestrator and the health manager without creating import cycles.
Index
- func BuildTaskDefinitionInputForConfig(ctx context.Context, family, image, taskExecRoleARN, taskRoleARN, logGroup, region string, cpu, memory, runtimePlatform string) *ecs.RegisterTaskDefinitionInput
- func BuildTaskDefinitionTags(image string, isDefault *bool) []ecsTypes.Tag
- func RecreateTaskDefinition(ctx context.Context, ecsClient awsClient.ECSClient, cfg *TaskDefinitionConfig, family string, image string, taskRoleARN string, taskExecRoleARN string, cpu, memory int, runtimePlatform string, isDefault bool, reqLogger *slog.Logger) (string, error)
- func UpdateTaskDefinitionTags(ctx context.Context, ecsClient awsClient.ECSClient, taskDefARN string, image string, isDefault bool, reqLogger *slog.Logger) error
- type TaskDefinitionConfig
func BuildTaskDefinitionInputForConfig
func BuildTaskDefinitionInputForConfig(ctx context.Context, family, image, taskExecRoleARN, taskRoleARN, logGroup, region string, cpu, memory, runtimePlatform string) *ecs.RegisterTaskDefinitionInput
BuildTaskDefinitionInputForConfig creates the RegisterTaskDefinitionInput for a new task definition.
func BuildTaskDefinitionTags
func BuildTaskDefinitionTags(image string, isDefault *bool) []ecsTypes.Tag
BuildTaskDefinitionTags creates the tags to be applied to a task definition.
func RecreateTaskDefinition
func RecreateTaskDefinition(ctx context.Context, ecsClient awsClient.ECSClient, cfg *TaskDefinitionConfig, family string, image string, taskRoleARN string, taskExecRoleARN string, cpu, memory int, runtimePlatform string, isDefault bool, reqLogger *slog.Logger) (string, error)
RecreateTaskDefinition recreates a task definition from stored metadata. This function is used by the health manager to restore missing task definitions.
func UpdateTaskDefinitionTags
func UpdateTaskDefinitionTags(ctx context.Context, ecsClient awsClient.ECSClient, taskDefARN string, image string, isDefault bool, reqLogger *slog.Logger) error
UpdateTaskDefinitionTags updates tags on an existing task definition to match expected values.
type TaskDefinitionConfig
TaskDefinitionConfig contains configuration needed to build task definitions.
type TaskDefinitionConfig struct {
LogGroup string
Region string
}
health
import "runvoy/internal/providers/aws/health"
Package health provides AWS-specific health management implementation for runvoy. It reconciles resources between DynamoDB metadata and actual AWS services.
Index
- type Config
- type ImageTaskDefRepository
- type Manager
- func Initialize(ecsClient awsClient.ECSClient, ssmClient secrets.Client, iamClient awsClient.IAMClient, imageRepo ImageTaskDefRepository, secretsRepo database.SecretsRepository, userRepo database.UserRepository, executionRepo database.ExecutionRepository, enforcer *authorization.Enforcer, cfg *Config, log *slog.Logger) *Manager
- func (m *Manager) Reconcile(ctx context.Context) (*api.HealthReport, error)
- func (m *Manager) SetCasbinDependencies(userRepo database.UserRepository, executionRepo database.ExecutionRepository, enforcer *authorization.Enforcer)
type Config
Config holds AWS-specific configuration for the health manager.
type Config struct {
Region string
AccountID string
DefaultTaskRoleARN string
DefaultTaskExecRoleARN string
LogGroup string
SecretsPrefix string
}
type ImageTaskDefRepository
ImageTaskDefRepository defines the interface for image-taskdef mapping operations.
type ImageTaskDefRepository interface {
ListImages(ctx context.Context) ([]api.ImageInfo, error)
}
type Manager
Manager implements the health.Manager interface for AWS.
type Manager struct {
// contains filtered or unexported fields
}
func Initialize
func Initialize(ecsClient awsClient.ECSClient, ssmClient secrets.Client, iamClient awsClient.IAMClient, imageRepo ImageTaskDefRepository, secretsRepo database.SecretsRepository, userRepo database.UserRepository, executionRepo database.ExecutionRepository, enforcer *authorization.Enforcer, cfg *Config, log *slog.Logger) *Manager
Initialize creates a new AWS health manager.
func (*Manager) Reconcile
func (m *Manager) Reconcile(ctx context.Context) (*api.HealthReport, error)
Reconcile performs health checks and reconciliation for ECS task definitions, SSM parameters, and IAM roles.
func (*Manager) SetCasbinDependencies
func (m *Manager) SetCasbinDependencies(userRepo database.UserRepository, executionRepo database.ExecutionRepository, enforcer *authorization.Enforcer)
SetCasbinDependencies sets the Casbin-related dependencies for the health manager. This allows the enforcer to be set after initialization when it becomes available.
identity
import "runvoy/internal/providers/aws/identity"
Package identity provides helpers for retrieving AWS identity information.
Index
func GetAccountID
func GetAccountID(ctx context.Context, awsCfg *awsStd.Config, log *slog.Logger) (string, error)
GetAccountID retrieves the AWS account ID using STS GetCallerIdentity.
lambdaapi
import "runvoy/internal/providers/aws/lambdaapi"
Package lambdaapi provides Lambda handler creation for AWS Lambda, integrating cloud-provider agnostic components with AWS-specific entry points.
Package lambdaapi provides Lambda handler creation for AWS Lambda Function URLs, integrating the application service with the HTTP router through algnhsa adapter.
Index
- func NewEventProcessorHandler(proc processor.Processor) lambda.Handler
- func NewHandler(svc *orchestrator.Service, requestTimeout time.Duration, allowedOrigins []string) lambda.Handler
func NewEventProcessorHandler
func NewEventProcessorHandler(proc processor.Processor) lambda.Handler
NewEventProcessorHandler creates a new Lambda handler for event processing. It wraps the generic event processor and converts responses to AWS Lambda types, allowing the core processor to remain cloud-provider agnostic while still supporting AWS Lambda's specific response formats.
func NewHandler
func NewHandler(svc *orchestrator.Service, requestTimeout time.Duration, allowedOrigins []string) lambda.Handler
NewHandler creates a new Lambda handler with the given service. The request timeout is passed to the router to configure the timeout middleware. It uses algnhsa to adapt the chi router to work with Lambda Function URLs.
orchestrator
import "runvoy/internal/providers/aws/orchestrator"
Package orchestrator provides AWS-specific implementations for runvoy orchestrator. This file contains the ImageManager implementation for image registration and management.
Package orchestrator provides AWS-specific implementations for runvoy orchestrator. This file contains Docker image reference parsing utilities.
Package orchestrator provides AWS-specific implementations for runvoy orchestrator. This file contains image management using DynamoDB for image-taskdef mappings.
Package orchestrator provides AWS-specific implementations for runvoy orchestrator. This file contains the LogManager implementation for execution log retrieval.
Package orchestrator provides AWS-specific implementations for runvoy orchestrator. This file contains the ObservabilityManager implementation for backend log retrieval.
Package orchestrator provides AWS-specific implementations for runvoy orchestrator. It handles ECS task execution and AWS service integration.
Package orchestrator provides AWS-specific implementations for runvoy orchestrator. This file contains shared tagging utilities for AWS resources.
Package orchestrator provides AWS-specific implementations for runvoy orchestrator.
Index
- func BuildTaskDefinitionInput(ctx context.Context, family, image, taskExecRoleARN, taskRoleARN, region string, cpu, memory int, runtimePlatform string, cfg *Config) *ecs.RegisterTaskDefinitionInput
- func DeregisterTaskDefinitionsForImage(ctx context.Context, ecsClient awsClient.ECSClient, image string, log *slog.Logger) error
- func ExtractImageFromTaskDefFamily(familyName string) string
- func GetDefaultImage(ctx context.Context, ecsClient awsClient.ECSClient, log *slog.Logger) (string, error)
- func GetStandardECSTags() []ecsTypes.Tag
- func GetTaskDefinitionForImage(ctx context.Context, ecsClient awsClient.ECSClient, image string, log *slog.Logger) (string, error)
- func SanitizeImageNameForTaskDef(image string) string
- func TaskDefinitionFamilyName(image string) string
- type Config
- type Dependencies
- func Initialize(ctx context.Context, cfg *config.Config, log *slog.Logger, enforcer *authorization.Enforcer) (*Dependencies, error)
- type ImageReference
- func ParseImageReference(image string) ImageReference
- func (r ImageReference) IsDockerHub() bool
- func (r ImageReference) IsECR() bool
- func (r ImageReference) NameWithTag() string
- func (r ImageReference) NormalizeRegistry() string
- func (r ImageReference) ShortName() string
- type ImageRegistryImpl
- func NewImageRegistry(ecsClient awsClient.ECSClient, iamClient awsClient.IAMClient, imageRepo ImageTaskDefRepository, cfg *Config, log *slog.Logger) *ImageRegistryImpl
- func (m *ImageRegistryImpl) GetImage(ctx context.Context, image string) (*api.ImageInfo, error)
- func (m *ImageRegistryImpl) ListImages(ctx context.Context) ([]api.ImageInfo, error)
- func (m *ImageRegistryImpl) RegisterImage(ctx context.Context, image string, isDefault *bool, taskRoleName *string, taskExecutionRoleName *string, cpu *int, memory *int, runtimePlatform *string, createdBy string) error
- func (m *ImageRegistryImpl) RemoveImage(ctx context.Context, image string) error
- type ImageTaskDefRepository
- type LambdaContextExtractor
- func NewLambdaContextExtractor() *LambdaContextExtractor
- func (e *LambdaContextExtractor) ExtractRequestID(ctx context.Context) (string, bool)
- type LogManagerImpl
- func NewLogManager(cwlClient awsClient.CloudWatchLogsClient, cfg *Config, log *slog.Logger) *LogManagerImpl
- func (l *LogManagerImpl) FetchLogsByExecutionID(ctx context.Context, executionID string) ([]api.LogEvent, error)
- type ObservabilityManagerImpl
- func NewObservabilityManager(cwlClient awsClient.CloudWatchLogsClient, log *slog.Logger) *ObservabilityManagerImpl
- func (o *ObservabilityManagerImpl) FetchBackendLogs(ctx context.Context, requestID string) ([]api.LogEvent, error)
- type TaskManagerImpl
- func NewTaskManager(ecsClient awsClient.ECSClient, imageRepo ImageTaskDefRepository, cfg *Config, log *slog.Logger) *TaskManagerImpl
- func (t *TaskManagerImpl) KillTask(ctx context.Context, executionID string) error
- func (t *TaskManagerImpl) StartTask(ctx context.Context, userEmail string, req *api.ExecutionRequest) (string, *time.Time, error)
func BuildTaskDefinitionInput
func BuildTaskDefinitionInput(ctx context.Context, family, image, taskExecRoleARN, taskRoleARN, region string, cpu, memory int, runtimePlatform string, cfg *Config) *ecs.RegisterTaskDefinitionInput
BuildTaskDefinitionInput creates the ECS RegisterTaskDefinitionInput for a new task definition.
func DeregisterTaskDefinitionsForImage
func DeregisterTaskDefinitionsForImage(ctx context.Context, ecsClient awsClient.ECSClient, image string, log *slog.Logger) error
DeregisterTaskDefinitionsForImage deregisters all task definition revisions for a given image. If the removed image was the default and only one image remains, that image becomes the new default.
func ExtractImageFromTaskDefFamily
func ExtractImageFromTaskDefFamily(familyName string) string
ExtractImageFromTaskDefFamily extracts the Docker image name from a task definition family name. Returns empty string if the family name doesn't match the expected format. NOTE: This is approximate - images should be read from container definitions or tags, not family names.
func GetDefaultImage
func GetDefaultImage(ctx context.Context, ecsClient awsClient.ECSClient, log *slog.Logger) (string, error)
GetDefaultImage returns the Docker image marked as default (via IsDefault tag). Returns empty string if no default image is found.
func GetStandardECSTags
func GetStandardECSTags() []ecsTypes.Tag
GetStandardECSTags returns the standard tags in ECS tag format.
func GetTaskDefinitionForImage
func GetTaskDefinitionForImage(ctx context.Context, ecsClient awsClient.ECSClient, image string, log *slog.Logger) (string, error)
GetTaskDefinitionForImage looks up an existing task definition for the given Docker image. Returns an error if the task definition doesn't exist (does not auto-register).
func SanitizeImageNameForTaskDef
func SanitizeImageNameForTaskDef(image string) string
SanitizeImageNameForTaskDef converts a Docker image name to a valid ECS task definition family name. ECS task definition family names must match: [a-zA-Z0-9_-]+ Examples:
- "hashicorp/terraform:1.6" -> "hashicorp-terraform-1-6"
- "myregistry.com/my-image:latest" -> "myregistry-com-my-image-latest"
func TaskDefinitionFamilyName
func TaskDefinitionFamilyName(image string) string
TaskDefinitionFamilyName returns the ECS task definition family name for a given image. Format: {TaskDefinitionFamilyPrefix}-{sanitized-image-name}
type Config
Config holds AWS-specific execution configuration.
type Config struct {
ECSCluster string
TaskDefinition string
Subnet1 string
Subnet2 string
SecurityGroup string
LogGroup string
DefaultTaskRoleARN string
DefaultTaskExecRoleARN string
Region string
AccountID string
SDKConfig *awsStd.Config
}
type Dependencies
Dependencies bundles the AWS-backed implementations required by the app service.
type Dependencies struct {
UserRepo database.UserRepository
ExecutionRepo database.ExecutionRepository
ConnectionRepo database.ConnectionRepository
TokenRepo database.TokenRepository
ImageRepo database.ImageRepository
TaskManager contract.TaskManager
ImageRegistry contract.ImageRegistry
LogManager contract.LogManager
ObservabilityManager contract.ObservabilityManager
WebSocketManager contract.WebSocketManager
SecretsRepo database.SecretsRepository
HealthManager contract.HealthManager
}
func Initialize
func Initialize(ctx context.Context, cfg *config.Config, log *slog.Logger, enforcer *authorization.Enforcer) (*Dependencies, error)
Initialize prepares AWS service dependencies for the app package. Wraps the AWS SDK clients in adapters for improved testability.
type ImageReference
ImageReference represents a parsed Docker image reference.
type ImageReference struct {
// Full is the complete image reference as provided
Full string
// Registry is the registry hostname (empty string = Docker Hub)
// Examples: "", "123456.dkr.ecr.us-east-1.amazonaws.com", "gcr.io"
Registry string
// Name is the image name (may include org/repo structure)
// Examples: "alpine", "hashicorp/terraform", "myapp"
Name string
// Tag is the image tag or digest
// Examples: "latest", "1.6", "sha256:abc123..."
Tag string
}
func ParseImageReference
func ParseImageReference(image string) ImageReference
ParseImageReference parses a Docker image reference into its components. Supports formats:
- alpine:latest → registry="", name="alpine", tag="latest"
- ubuntu → registry="", name="ubuntu", tag="latest"
- myorg/myapp:v1.0 → registry="", name="myorg/myapp", tag="v1.0"
- 123456.dkr.ecr.us-east-1.amazonaws.com/myapp:v1.0 → registry="123456.dkr.ecr.us-east-1.amazonaws.com", name="myapp", tag="v1.0"
- gcr.io/project/image:tag → registry="gcr.io", name="project/image", tag="tag"
func (ImageReference) IsDockerHub
func (r ImageReference) IsDockerHub() bool
IsDockerHub returns true if the image is from Docker Hub.
func (ImageReference) IsECR
func (r ImageReference) IsECR() bool
IsECR returns true if the image is from AWS ECR.
func (ImageReference) NameWithTag
func (r ImageReference) NameWithTag() string
NameWithTag returns the image name with tag but without registry. Examples: "alpine:latest", "hashicorp/terraform:1.6"
func (ImageReference) NormalizeRegistry
func (r ImageReference) NormalizeRegistry() string
NormalizeRegistry returns a normalized registry identifier. Returns "docker.io" for Docker Hub (empty registry), otherwise returns the registry as-is.
func (ImageReference) ShortName
func (r ImageReference) ShortName() string
ShortName returns the image name without registry or tag. Examples: "alpine", "hashicorp/terraform", "myapp"
type ImageRegistryImpl
ImageRegistryImpl implements the ImageRegistry interface for AWS ECS and DynamoDB. It handles Docker image registration, listing, retrieval, and removal.
type ImageRegistryImpl struct {
// contains filtered or unexported fields
}
func NewImageRegistry
func NewImageRegistry(ecsClient awsClient.ECSClient, iamClient awsClient.IAMClient, imageRepo ImageTaskDefRepository, cfg *Config, log *slog.Logger) *ImageRegistryImpl
NewImageRegistry creates a new AWS image manager.
func (*ImageRegistryImpl) GetImage
func (m *ImageRegistryImpl) GetImage(ctx context.Context, image string) (*api.ImageInfo, error)
GetImage retrieves a single Docker image by ID or name. Accepts either an ImageID (e.g., "alpine:latest-a1b2c3d4") or an image name (e.g., "alpine:latest"). If ImageID is provided, queries directly by ID. Otherwise, uses GetAnyImageTaskDef to find any configuration. If image is empty, returns the default image if one is configured.
func (*ImageRegistryImpl) ListImages
func (m *ImageRegistryImpl) ListImages(ctx context.Context) ([]api.ImageInfo, error)
ListImages lists all registered Docker images from DynamoDB.
func (*ImageRegistryImpl) RegisterImage
func (m *ImageRegistryImpl) RegisterImage(ctx context.Context, image string, isDefault *bool, taskRoleName *string, taskExecutionRoleName *string, cpu *int, memory *int, runtimePlatform *string, createdBy string) error
RegisterImage registers a Docker image with optional custom IAM roles, CPU, Memory, and RuntimePlatform. Creates a new task definition with a unique family name and stores the mapping in DynamoDB.
func (*ImageRegistryImpl) RemoveImage
func (m *ImageRegistryImpl) RemoveImage(ctx context.Context, image string) error
RemoveImage removes a Docker image and all its task definition variants from DynamoDB. It also deregisters all associated task definitions from ECS. If deregistration fails for any task definition, it continues to clean up the remaining ones and still removes the mappings from DynamoDB.
NOTE: To avoid accidental deletion of multiple image configurations, this function requires the full ImageID (e.g., "alpine:latest-a1b2c3d4") instead of just the image name/tag. Use ListImages to find the specific ImageID you want to remove.
type ImageTaskDefRepository
ImageTaskDefRepository defines the interface for image-taskdef mapping operations.
type ImageTaskDefRepository interface {
PutImageTaskDef(
ctx context.Context,
imageID string,
image string,
imageRegistry string,
imageName string,
imageTag string,
taskRoleName, taskExecutionRoleName *string,
cpu, memory int,
runtimePlatform string,
taskDefFamily string,
isDefault bool,
registeredBy string,
) error
GetImageTaskDef(
ctx context.Context,
image string,
taskRoleName, taskExecutionRoleName *string,
cpu, memory *int,
runtimePlatform *string,
) (*api.ImageInfo, error)
GetImageTaskDefByID(ctx context.Context, imageID string) (*api.ImageInfo, error)
GetAnyImageTaskDef(ctx context.Context, image string) (*api.ImageInfo, error)
ListImages(ctx context.Context) ([]api.ImageInfo, error)
GetDefaultImage(ctx context.Context) (*api.ImageInfo, error)
UnmarkAllDefaults(ctx context.Context) error
DeleteImage(ctx context.Context, image string) error
SetImageAsOnlyDefault(ctx context.Context, image string, taskRoleName, taskExecutionRoleName *string) error
GetImagesByRequestID(ctx context.Context, requestID string) ([]api.ImageInfo, error)
}
type LambdaContextExtractor
LambdaContextExtractor extracts request IDs from AWS Lambda contexts.
type LambdaContextExtractor struct{}
func NewLambdaContextExtractor
func NewLambdaContextExtractor() *LambdaContextExtractor
NewLambdaContextExtractor creates a new AWS Lambda context extractor.
func (*LambdaContextExtractor) ExtractRequestID
func (e *LambdaContextExtractor) ExtractRequestID(ctx context.Context) (string, bool)
ExtractRequestID extracts the AWS request ID from a Lambda context.
type LogManagerImpl
LogManagerImpl implements the LogManager interface for AWS CloudWatch Logs. It handles retrieving execution logs from CloudWatch.
type LogManagerImpl struct {
// contains filtered or unexported fields
}
func NewLogManager
func NewLogManager(cwlClient awsClient.CloudWatchLogsClient, cfg *Config, log *slog.Logger) *LogManagerImpl
NewLogManager creates a new AWS log manager.
func (*LogManagerImpl) FetchLogsByExecutionID
func (l *LogManagerImpl) FetchLogsByExecutionID(ctx context.Context, executionID string) ([]api.LogEvent, error)
FetchLogsByExecutionID returns CloudWatch log events for the given execution ID.
type ObservabilityManagerImpl
ObservabilityManagerImpl implements the ObservabilityManager interface for AWS CloudWatch Logs Insights. It handles retrieving backend infrastructure logs for debugging and tracing.
type ObservabilityManagerImpl struct {
// contains filtered or unexported fields
}
func NewObservabilityManager
func NewObservabilityManager(cwlClient awsClient.CloudWatchLogsClient, log *slog.Logger) *ObservabilityManagerImpl
NewObservabilityManager creates a new AWS observability manager.
func (*ObservabilityManagerImpl) FetchBackendLogs
func (o *ObservabilityManagerImpl) FetchBackendLogs(ctx context.Context, requestID string) ([]api.LogEvent, error)
FetchBackendLogs retrieves backend infrastructure logs using CloudWatch Logs Insights Queries logs from Lambda execution for debugging and tracing
type TaskManagerImpl
TaskManagerImpl implements the TaskManager interface for AWS ECS Fargate. It handles task lifecycle management including starting and terminating tasks.
type TaskManagerImpl struct {
// contains filtered or unexported fields
}
func NewTaskManager
func NewTaskManager(ecsClient awsClient.ECSClient, imageRepo ImageTaskDefRepository, cfg *Config, log *slog.Logger) *TaskManagerImpl
NewTaskManager creates a new AWS ECS task manager.
func (*TaskManagerImpl) KillTask
func (t *TaskManagerImpl) KillTask(ctx context.Context, executionID string) error
KillTask terminates an ECS task identified by executionID. It checks the task status before termination and only stops tasks that are RUNNING or ACTIVATING. Returns an error if the task is already terminated or not found.
func (*TaskManagerImpl) StartTask
func (t *TaskManagerImpl) StartTask(ctx context.Context, userEmail string, req *api.ExecutionRequest) (string, *time.Time, error)
StartTask triggers an ECS Fargate task and returns identifiers.
aws
import "runvoy/internal/providers/aws/processor"
Package aws provides AWS-specific event processing implementations.
Index
- func ParseTime(timeStr string) (time.Time, error)
- type ContainerDetail
- type ECSTaskStateChangeEvent
- type Processor
- func Initialize(ctx context.Context, cfg *config.Config, enforcer *authorization.Enforcer, log *slog.Logger) (*Processor, error)
- func NewProcessor(executionRepo database.ExecutionRepository, webSocketManager contract.WebSocketManager, healthManager contract.HealthManager, log *slog.Logger) *Processor
- func (p *Processor) Handle(ctx context.Context, rawEvent *json.RawMessage) (*json.RawMessage, error)
- func (p *Processor) HandleEventJSON(ctx context.Context, eventJSON *json.RawMessage) error
func ParseTime
func ParseTime(timeStr string) (time.Time, error)
ParseTime parses an RFC3339 timestamp string
type ContainerDetail
ContainerDetail represents a container within an ECS task
type ContainerDetail struct {
ContainerArn string `json:"containerArn"`
Name string `json:"name"`
ExitCode *int `json:"exitCode,omitempty"`
Reason string `json:"reason,omitempty"`
}
type ECSTaskStateChangeEvent
ECSTaskStateChangeEvent represents the detail structure of an ECS Task State Change event
type ECSTaskStateChangeEvent struct {
ClusterArn string `json:"clusterArn"`
TaskArn string `json:"taskArn"`
LastStatus string `json:"lastStatus"`
DesiredStatus string `json:"desiredStatus"`
Containers []ContainerDetail `json:"containers"`
StartedAt string `json:"startedAt"`
StoppedAt string `json:"stoppedAt"`
StoppedReason string `json:"stoppedReason"`
StopCode string `json:"stopCode"`
CPU string `json:"cpu"`
Memory string `json:"memory"`
}
type Processor
Processor implements the events.Processor interface for AWS. It handles CloudWatch events, CloudWatch Logs, API Gateway WebSocket events, and scheduled events.
type Processor struct {
// contains filtered or unexported fields
}
func Initialize
func Initialize(ctx context.Context, cfg *config.Config, enforcer *authorization.Enforcer, log *slog.Logger) (*Processor, error)
Initialize constructs an AWS-backed event processor with all required dependencies. Wraps the AWS SDK clients in adapters for improved testability.
func NewProcessor
func NewProcessor(executionRepo database.ExecutionRepository, webSocketManager contract.WebSocketManager, healthManager contract.HealthManager, log *slog.Logger) *Processor
NewProcessor creates a new AWS event processor.
func (*Processor) Handle
func (p *Processor) Handle(ctx context.Context, rawEvent *json.RawMessage) (*json.RawMessage, error)
Handle processes a raw AWS event by delegating to the appropriate handler. It supports CloudWatch events, CloudWatch Logs, and WebSocket events.
func (*Processor) HandleEventJSON
func (p *Processor) HandleEventJSON(ctx context.Context, eventJSON *json.RawMessage) error
HandleEventJSON is a helper for testing that accepts raw JSON and returns an error. It's used for test cases that expect error returns.
secrets
import "runvoy/internal/providers/aws/secrets"
Package secrets provides secret management functionality for the Runvoy orchestrator. This file contains the AWS Systems Manager Parameter Store implementation.
Index
- type Client
- type ClientAdapter
- func NewClientAdapter(client *ssm.Client) *ClientAdapter
- func (a *ClientAdapter) AddTagsToResource(ctx context.Context, params *ssm.AddTagsToResourceInput, optFns ...func(*ssm.Options)) (*ssm.AddTagsToResourceOutput, error)
- func (a *ClientAdapter) DeleteParameter(ctx context.Context, params *ssm.DeleteParameterInput, optFns ...func(*ssm.Options)) (*ssm.DeleteParameterOutput, error)
- func (a *ClientAdapter) DescribeParameters(ctx context.Context, params *ssm.DescribeParametersInput, optFns ...func(*ssm.Options)) (*ssm.DescribeParametersOutput, error)
- func (a *ClientAdapter) GetParameter(ctx context.Context, params *ssm.GetParameterInput, optFns ...func(*ssm.Options)) (*ssm.GetParameterOutput, error)
- func (a *ClientAdapter) ListTagsForResource(ctx context.Context, params *ssm.ListTagsForResourceInput, optFns ...func(*ssm.Options)) (*ssm.ListTagsForResourceOutput, error)
- func (a *ClientAdapter) PutParameter(ctx context.Context, params *ssm.PutParameterInput, optFns ...func(*ssm.Options)) (*ssm.PutParameterOutput, error)
- type ParameterStoreManager
- func NewParameterStoreManager(client Client, secretPrefix, kmsKeyARN string, log *slog.Logger) *ParameterStoreManager
- func (m *ParameterStoreManager) DeleteSecret(ctx context.Context, name string) error
- func (m *ParameterStoreManager) RetrieveSecret(ctx context.Context, name string) (string, error)
- func (m *ParameterStoreManager) StoreSecret(ctx context.Context, name, value string) error
- type StandardTag
- func GetStandardTags() []StandardTag
- type ValueStore
type Client
Client defines the interface for SSM operations used by the ParameterStoreManager. This interface makes the code easier to test by allowing mock implementations.
type Client interface {
PutParameter(
ctx context.Context,
params *ssm.PutParameterInput,
optFns ...func(*ssm.Options),
) (*ssm.PutParameterOutput, error)
AddTagsToResource(
ctx context.Context,
params *ssm.AddTagsToResourceInput,
optFns ...func(*ssm.Options),
) (*ssm.AddTagsToResourceOutput, error)
GetParameter(
ctx context.Context,
params *ssm.GetParameterInput,
optFns ...func(*ssm.Options),
) (*ssm.GetParameterOutput, error)
DeleteParameter(
ctx context.Context,
params *ssm.DeleteParameterInput,
optFns ...func(*ssm.Options),
) (*ssm.DeleteParameterOutput, error)
ListTagsForResource(
ctx context.Context,
params *ssm.ListTagsForResourceInput,
optFns ...func(*ssm.Options),
) (*ssm.ListTagsForResourceOutput, error)
DescribeParameters(
ctx context.Context,
params *ssm.DescribeParametersInput,
optFns ...func(*ssm.Options),
) (*ssm.DescribeParametersOutput, error)
}
type ClientAdapter
ClientAdapter wraps the AWS SDK SSM client to implement Client interface. This allows us to use the real AWS client in production while maintaining testability.
type ClientAdapter struct {
// contains filtered or unexported fields
}
func NewClientAdapter
func NewClientAdapter(client *ssm.Client) *ClientAdapter
NewClientAdapter creates a new adapter wrapping the AWS SDK SSM client.
func (*ClientAdapter) AddTagsToResource
func (a *ClientAdapter) AddTagsToResource(ctx context.Context, params *ssm.AddTagsToResourceInput, optFns ...func(*ssm.Options)) (*ssm.AddTagsToResourceOutput, error)
AddTagsToResource wraps the AWS SDK AddTagsToResource operation.
func (*ClientAdapter) DeleteParameter
func (a *ClientAdapter) DeleteParameter(ctx context.Context, params *ssm.DeleteParameterInput, optFns ...func(*ssm.Options)) (*ssm.DeleteParameterOutput, error)
DeleteParameter wraps the AWS SDK DeleteParameter operation.
func (*ClientAdapter) DescribeParameters
func (a *ClientAdapter) DescribeParameters(ctx context.Context, params *ssm.DescribeParametersInput, optFns ...func(*ssm.Options)) (*ssm.DescribeParametersOutput, error)
DescribeParameters wraps the AWS SDK DescribeParameters operation.
func (*ClientAdapter) GetParameter
func (a *ClientAdapter) GetParameter(ctx context.Context, params *ssm.GetParameterInput, optFns ...func(*ssm.Options)) (*ssm.GetParameterOutput, error)
GetParameter wraps the AWS SDK GetParameter operation.
func (*ClientAdapter) ListTagsForResource
func (a *ClientAdapter) ListTagsForResource(ctx context.Context, params *ssm.ListTagsForResourceInput, optFns ...func(*ssm.Options)) (*ssm.ListTagsForResourceOutput, error)
ListTagsForResource wraps the AWS SDK ListTagsForResource operation.
func (*ClientAdapter) PutParameter
func (a *ClientAdapter) PutParameter(ctx context.Context, params *ssm.PutParameterInput, optFns ...func(*ssm.Options)) (*ssm.PutParameterOutput, error)
PutParameter wraps the AWS SDK PutParameter operation.
type ParameterStoreManager
ParameterStoreManager implements secret value storage using AWS Systems Manager Parameter Store. Secrets are stored as SecureString parameters and encrypted with KMS.
type ParameterStoreManager struct {
// contains filtered or unexported fields
}
func NewParameterStoreManager
func NewParameterStoreManager(client Client, secretPrefix, kmsKeyARN string, log *slog.Logger) *ParameterStoreManager
NewParameterStoreManager creates a new Parameter Store-based secrets manager. secretPrefix should include a leading slash, e.g., "/runvoy/secrets"
func (*ParameterStoreManager) DeleteSecret
func (m *ParameterStoreManager) DeleteSecret(ctx context.Context, name string) error
DeleteSecret removes a secret from AWS Systems Manager Parameter Store.
func (*ParameterStoreManager) RetrieveSecret
func (m *ParameterStoreManager) RetrieveSecret(ctx context.Context, name string) (string, error)
RetrieveSecret retrieves a secret value from AWS Systems Manager Parameter Store. The value is automatically decrypted using the KMS key.
func (*ParameterStoreManager) StoreSecret
func (m *ParameterStoreManager) StoreSecret(ctx context.Context, name, value string) error
StoreSecret saves a secret value to AWS Systems Manager Parameter Store as a SecureString. The value is encrypted with the KMS key specified during initialization.
type StandardTag
StandardTag represents a standard AWS resource tag as key-value pairs.
type StandardTag struct {
Key string
Value string
}
func GetStandardTags
func GetStandardTags() []StandardTag
GetStandardTags returns the standard tags applied to all AWS resources managed by runvoy at runtime. These tags are used for resource identification and management tracking.
type ValueStore
ValueStore is the interface for storing and retrieving encrypted secret values. Implementations handle the actual secret payloads (e.g., in AWS Parameter Store).
type ValueStore interface {
// StoreSecret saves a secret value and returns any error.
StoreSecret(ctx context.Context, name, value string) error
// RetrieveSecret gets a secret value by name.
RetrieveSecret(ctx context.Context, name string) (string, error)
// DeleteSecret removes a secret value by name.
DeleteSecret(ctx context.Context, name string) error
}
websocket
import "runvoy/internal/providers/aws/websocket"
Package websocket provides AWS-specific WebSocket management implementation for runvoy. It handles connection lifecycle events via API Gateway and manages WebSocket connections in DynamoDB.
Index
- type Client
- type ClientAdapter
- func NewClientAdapter(client *apigatewaymanagementapi.Client) *ClientAdapter
- func (a *ClientAdapter) PostToConnection(ctx context.Context, params *apigatewaymanagementapi.PostToConnectionInput, optFns ...func(*apigatewaymanagementapi.Options)) (*apigatewaymanagementapi.PostToConnectionOutput, error)
- type Manager
- func Initialize(cfg *config.Config, connRepo database.ConnectionRepository, tokenRepo database.TokenRepository, log *slog.Logger) *Manager
- func (m *Manager) GenerateWebSocketURL(ctx context.Context, executionID string, userEmail *string, clientIPAtCreationTime *string) string
- func (m *Manager) HandleRequest(ctx context.Context, rawEvent *json.RawMessage, reqLogger *slog.Logger) (bool, error)
- func (m *Manager) NotifyExecutionCompletion(ctx context.Context, executionID *string) error
- func (m *Manager) SendLogsToExecution(ctx context.Context, executionID *string, logEvents []api.LogEvent) error
type Client
Client defines the interface for API Gateway Management API operations used by the Manager. This interface makes the code easier to test by allowing mock implementations.
type Client interface {
PostToConnection(
ctx context.Context,
params *apigatewaymanagementapi.PostToConnectionInput,
optFns ...func(*apigatewaymanagementapi.Options),
) (*apigatewaymanagementapi.PostToConnectionOutput, error)
}
type ClientAdapter
ClientAdapter wraps the AWS SDK API Gateway Management API client to implement Client interface. This allows us to use the real AWS client in production while maintaining testability.
type ClientAdapter struct {
// contains filtered or unexported fields
}
func NewClientAdapter
func NewClientAdapter(client *apigatewaymanagementapi.Client) *ClientAdapter
NewClientAdapter creates a new adapter wrapping the AWS SDK API Gateway Management API client.
func (*ClientAdapter) PostToConnection
func (a *ClientAdapter) PostToConnection(ctx context.Context, params *apigatewaymanagementapi.PostToConnectionInput, optFns ...func(*apigatewaymanagementapi.Options)) (*apigatewaymanagementapi.PostToConnectionOutput, error)
PostToConnection wraps the AWS SDK PostToConnection operation.
type Manager
Manager implements the websocket.Manager interface for AWS. It uses API Gateway Management API to communicate with WebSocket clients and DynamoDB to store connection metadata.
type Manager struct {
// contains filtered or unexported fields
}
func Initialize
func Initialize(cfg *config.Config, connRepo database.ConnectionRepository, tokenRepo database.TokenRepository, log *slog.Logger) *Manager
Initialize creates a new AWS WebSocket manager.
func (*Manager) GenerateWebSocketURL
func (m *Manager) GenerateWebSocketURL(ctx context.Context, executionID string, userEmail *string, clientIPAtCreationTime *string) string
GenerateWebSocketURL creates a WebSocket token and returns the connection URL. It stores the token for validation when the client connects.
func (*Manager) HandleRequest
func (m *Manager) HandleRequest(ctx context.Context, rawEvent *json.RawMessage, reqLogger *slog.Logger) (bool, error)
HandleRequest adapts WebSocket events so the generic event processor can route them. It attempts to unmarshal the raw Lambda event as an API Gateway WebSocket request and, when successful, dispatches based on the route key.
func (*Manager) NotifyExecutionCompletion
func (m *Manager) NotifyExecutionCompletion(ctx context.Context, executionID *string) error
NotifyExecutionCompletion sends disconnect notifications to all connected clients for an execution and deletes the connections from DynamoDB.
func (*Manager) SendLogsToExecution
func (m *Manager) SendLogsToExecution(ctx context.Context, executionID *string, logEvents []api.LogEvent) error
SendLogsToExecution sends log events to all connected clients for an execution. Each log event is sent individually to all connected clients concurrently.
orchestrator
import "runvoy/cmd/backend/providers/aws/orchestrator"
Package main implements the AWS Lambda orchestrator for runvoy. It handles API requests and orchestrates ECS task executions.
Index
processor
import "runvoy/cmd/backend/providers/aws/processor"
Package main implements the AWS Lambda event processor for runvoy. It processes various AWS Lambda events including CloudWatch events related to ECS task completions and API Gateway WebSocket events.
Index
dynamodb
import "runvoy/internal/providers/aws/database/dynamodb"
Package dynamodb implements DynamoDB-based storage for runvoy. It provides persistence for execution records using AWS DynamoDB.
Package dynamodb implements DynamoDB-based storage for runvoy. It provides persistence for image-taskdef mappings using AWS DynamoDB.
Index
- func GenerateImageID(imageName, imageTag string, cpu, memory int, runtimePlatform string, taskRoleName, taskExecutionRoleName *string) string
- func NewConnectionRepository(client Client, tableName string, log *slog.Logger) database.ConnectionRepository
- func NewTokenRepository(client Client, tableName string, log *slog.Logger) database.TokenRepository
- type Client
- type ClientAdapter
- func NewClientAdapter(client *dynamodb.Client) *ClientAdapter
- func (a *ClientAdapter) BatchWriteItem(ctx context.Context, params *dynamodb.BatchWriteItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.BatchWriteItemOutput, error)
- func (a *ClientAdapter) DeleteItem(ctx context.Context, params *dynamodb.DeleteItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.DeleteItemOutput, error)
- func (a *ClientAdapter) GetItem(ctx context.Context, params *dynamodb.GetItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.GetItemOutput, error)
- func (a *ClientAdapter) PutItem(ctx context.Context, params *dynamodb.PutItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.PutItemOutput, error)
- func (a *ClientAdapter) Query(ctx context.Context, params *dynamodb.QueryInput, optFns ...func(*dynamodb.Options)) (*dynamodb.QueryOutput, error)
- func (a *ClientAdapter) Scan(ctx context.Context, params *dynamodb.ScanInput, optFns ...func(*dynamodb.Options)) (*dynamodb.ScanOutput, error)
- func (a *ClientAdapter) UpdateItem(ctx context.Context, params *dynamodb.UpdateItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.UpdateItemOutput, error)
- type ConnectionRepository
- func (r *ConnectionRepository) CreateConnection(ctx context.Context, connection *api.WebSocketConnection) error
- func (r *ConnectionRepository) DeleteConnections(ctx context.Context, connectionIDs []string) (int, error)
- func (r *ConnectionRepository) GetConnectionsByExecutionID(ctx context.Context, executionID string) ([]*api.WebSocketConnection, error)
- type ExecutionRepository
- func NewExecutionRepository(client Client, tableName string, log *slog.Logger) *ExecutionRepository
- func (r *ExecutionRepository) CreateExecution(ctx context.Context, execution *api.Execution) error
- func (r *ExecutionRepository) GetExecution(ctx context.Context, executionID string) (*api.Execution, error)
- func (r *ExecutionRepository) GetExecutionsByRequestID(ctx context.Context, requestID string) ([]*api.Execution, error)
- func (r *ExecutionRepository) ListExecutions(ctx context.Context, limit int, statuses []string) ([]*api.Execution, error)
- func (r *ExecutionRepository) UpdateExecution(ctx context.Context, execution *api.Execution) error
- type ImageTaskDefRepository
- func NewImageTaskDefRepository(client Client, tableName string, log *slog.Logger) *ImageTaskDefRepository
- func (r *ImageTaskDefRepository) DeleteImage(ctx context.Context, image string) error
- func (r *ImageTaskDefRepository) GetAnyImageTaskDef(ctx context.Context, image string) (*api.ImageInfo, error)
- func (r *ImageTaskDefRepository) GetDefaultImage(ctx context.Context) (*api.ImageInfo, error)
- func (r *ImageTaskDefRepository) GetImageTaskDef(ctx context.Context, image string, taskRoleName *string, taskExecutionRoleName *string, cpu *int, memory *int, runtimePlatform *string) (*api.ImageInfo, error)
- func (r *ImageTaskDefRepository) GetImageTaskDefByID(ctx context.Context, imageID string) (*api.ImageInfo, error)
- func (r *ImageTaskDefRepository) GetImagesByRequestID(ctx context.Context, requestID string) ([]api.ImageInfo, error)
- func (r *ImageTaskDefRepository) GetImagesCount(ctx context.Context) (int, error)
- func (r *ImageTaskDefRepository) GetUniqueImages(ctx context.Context) ([]string, error)
- func (r *ImageTaskDefRepository) ListImages(ctx context.Context) ([]api.ImageInfo, error)
- func (r *ImageTaskDefRepository) PutImageTaskDef(ctx context.Context, imageID string, image string, imageRegistry string, imageName string, imageTag string, taskRoleName *string, taskExecutionRoleName *string, cpu int, memory int, runtimePlatform string, taskDefFamily string, isDefault bool, createdBy string) error
- func (r *ImageTaskDefRepository) SetImageAsOnlyDefault(ctx context.Context, image string, taskRoleName *string, taskExecutionRoleName *string) error
- func (r *ImageTaskDefRepository) UnmarkAllDefaults(ctx context.Context) error
- type MockDynamoDBClient
- func NewMockDynamoDBClient() *MockDynamoDBClient
- func (m *MockDynamoDBClient) BatchWriteItem(_ context.Context, params *dynamodb.BatchWriteItemInput, _ ...func(*dynamodb.Options)) (*dynamodb.BatchWriteItemOutput, error)
- func (m *MockDynamoDBClient) ClearTables()
- func (m *MockDynamoDBClient) DeleteItem(_ context.Context, params *dynamodb.DeleteItemInput, _ ...func(*dynamodb.Options)) (*dynamodb.DeleteItemOutput, error)
- func (m *MockDynamoDBClient) GetItem(_ context.Context, params *dynamodb.GetItemInput, _ ...func(*dynamodb.Options)) (*dynamodb.GetItemOutput, error)
- func (m *MockDynamoDBClient) PutItem(_ context.Context, params *dynamodb.PutItemInput, _ ...func(*dynamodb.Options)) (*dynamodb.PutItemOutput, error)
- func (m *MockDynamoDBClient) Query(_ context.Context, params *dynamodb.QueryInput, _ ...func(*dynamodb.Options)) (*dynamodb.QueryOutput, error)
- func (m *MockDynamoDBClient) ResetCallCounts()
- func (m *MockDynamoDBClient) Scan(_ context.Context, params *dynamodb.ScanInput, _ ...func(*dynamodb.Options)) (*dynamodb.ScanOutput, error)
- func (m *MockDynamoDBClient) UpdateItem(_ context.Context, params *dynamodb.UpdateItemInput, _ ...func(*dynamodb.Options)) (*dynamodb.UpdateItemOutput, error)
- type SecretsRepository
- func NewSecretsRepository(client Client, tableName string, log *slog.Logger) *SecretsRepository
- func (r *SecretsRepository) CreateSecret(ctx context.Context, secret *api.Secret) error
- func (r *SecretsRepository) DeleteSecret(ctx context.Context, name string) error
- func (r *SecretsRepository) GetSecret(ctx context.Context, name string) (*api.Secret, error)
- func (r *SecretsRepository) GetSecretsByRequestID(ctx context.Context, requestID string) ([]*api.Secret, error)
- func (r *SecretsRepository) ListSecrets(ctx context.Context) ([]*api.Secret, error)
- func (r *SecretsRepository) SecretExists(ctx context.Context, name string) (bool, error)
- func (r *SecretsRepository) UpdateSecretMetadata(ctx context.Context, name, keyName, description, updatedBy string) error
- type TokenRepository
- func (r *TokenRepository) CreateToken(ctx context.Context, token *api.WebSocketToken) error
- func (r *TokenRepository) DeleteToken(ctx context.Context, tokenValue string) error
- func (r *TokenRepository) GetToken(ctx context.Context, tokenValue string) (*api.WebSocketToken, error)
- type UserRepository
- func NewUserRepository(client Client, tableName string, pendingTableName string, log *slog.Logger) *UserRepository
- func (r *UserRepository) CreatePendingAPIKey(ctx context.Context, pending *api.PendingAPIKey) error
- func (r *UserRepository) CreateUser(ctx context.Context, user *api.User, apiKeyHash string, expiresAtUnix int64) error
- func (r *UserRepository) DeletePendingAPIKey(ctx context.Context, secretToken string) error
- func (r *UserRepository) GetPendingAPIKey(ctx context.Context, secretToken string) (*api.PendingAPIKey, error)
- func (r *UserRepository) GetUserByAPIKeyHash(ctx context.Context, apiKeyHash string) (*api.User, error)
- func (r *UserRepository) GetUserByEmail(ctx context.Context, email string) (*api.User, error)
- func (r *UserRepository) GetUsersByRequestID(ctx context.Context, requestID string) ([]*api.User, error)
- func (r *UserRepository) ListUsers(ctx context.Context) ([]*api.User, error)
- func (r *UserRepository) MarkAsViewed(ctx context.Context, secretToken, ipAddress string) error
- func (r *UserRepository) RemoveExpiration(ctx context.Context, email string) error
- func (r *UserRepository) RevokeUser(ctx context.Context, email string) error
- func (r *UserRepository) UpdateLastUsed(ctx context.Context, email string) (*time.Time, error)
func GenerateImageID
func GenerateImageID(imageName, imageTag string, cpu, memory int, runtimePlatform string, taskRoleName, taskExecutionRoleName *string) string
GenerateImageID generates a unique, human-readable ID for an image configuration. Format: {imageName}:{tag}-{first-8-chars-of-hash} Example: alpine:latest-a1b2c3d4 or golang:1.24.5-bookworm-19884ca2
func NewConnectionRepository
func NewConnectionRepository(client Client, tableName string, log *slog.Logger) database.ConnectionRepository
NewConnectionRepository creates a new DynamoDB-backed connection repository.
func NewTokenRepository
func NewTokenRepository(client Client, tableName string, log *slog.Logger) database.TokenRepository
NewTokenRepository creates a new DynamoDB-backed token repository.
type Client
Client defines the interface for DynamoDB operations used by repositories. This interface makes repositories easier to test by allowing mock implementations.
type Client interface {
PutItem(
ctx context.Context,
params *dynamodb.PutItemInput,
optFns ...func(*dynamodb.Options),
) (*dynamodb.PutItemOutput, error)
GetItem(
ctx context.Context,
params *dynamodb.GetItemInput,
optFns ...func(*dynamodb.Options),
) (*dynamodb.GetItemOutput, error)
Query(
ctx context.Context,
params *dynamodb.QueryInput,
optFns ...func(*dynamodb.Options),
) (*dynamodb.QueryOutput, error)
UpdateItem(
ctx context.Context,
params *dynamodb.UpdateItemInput,
optFns ...func(*dynamodb.Options),
) (*dynamodb.UpdateItemOutput, error)
DeleteItem(
ctx context.Context,
params *dynamodb.DeleteItemInput,
optFns ...func(*dynamodb.Options),
) (*dynamodb.DeleteItemOutput, error)
BatchWriteItem(
ctx context.Context,
params *dynamodb.BatchWriteItemInput,
optFns ...func(*dynamodb.Options),
) (*dynamodb.BatchWriteItemOutput, error)
Scan(
ctx context.Context,
params *dynamodb.ScanInput,
optFns ...func(*dynamodb.Options),
) (*dynamodb.ScanOutput, error)
}
type ClientAdapter
ClientAdapter wraps the AWS SDK DynamoDB client to implement Client interface. This allows us to use the real AWS client in production while maintaining testability.
type ClientAdapter struct {
// contains filtered or unexported fields
}
func NewClientAdapter
func NewClientAdapter(client *dynamodb.Client) *ClientAdapter
NewClientAdapter creates a new adapter wrapping the AWS SDK DynamoDB client.
func (*ClientAdapter) BatchWriteItem
func (a *ClientAdapter) BatchWriteItem(ctx context.Context, params *dynamodb.BatchWriteItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.BatchWriteItemOutput, error)
BatchWriteItem wraps the AWS SDK BatchWriteItem operation.
func (*ClientAdapter) DeleteItem
func (a *ClientAdapter) DeleteItem(ctx context.Context, params *dynamodb.DeleteItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.DeleteItemOutput, error)
DeleteItem wraps the AWS SDK DeleteItem operation.
func (*ClientAdapter) GetItem
func (a *ClientAdapter) GetItem(ctx context.Context, params *dynamodb.GetItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.GetItemOutput, error)
GetItem wraps the AWS SDK GetItem operation.
func (*ClientAdapter) PutItem
func (a *ClientAdapter) PutItem(ctx context.Context, params *dynamodb.PutItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.PutItemOutput, error)
PutItem wraps the AWS SDK PutItem operation.
func (*ClientAdapter) Query
func (a *ClientAdapter) Query(ctx context.Context, params *dynamodb.QueryInput, optFns ...func(*dynamodb.Options)) (*dynamodb.QueryOutput, error)
Query wraps the AWS SDK Query operation.
func (*ClientAdapter) Scan
func (a *ClientAdapter) Scan(ctx context.Context, params *dynamodb.ScanInput, optFns ...func(*dynamodb.Options)) (*dynamodb.ScanOutput, error)
Scan wraps the AWS SDK Scan operation.
func (*ClientAdapter) UpdateItem
func (a *ClientAdapter) UpdateItem(ctx context.Context, params *dynamodb.UpdateItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.UpdateItemOutput, error)
UpdateItem wraps the AWS SDK UpdateItem operation.
type ConnectionRepository
ConnectionRepository implements the database.ConnectionRepository interface using DynamoDB.
type ConnectionRepository struct {
// contains filtered or unexported fields
}
func (*ConnectionRepository) CreateConnection
func (r *ConnectionRepository) CreateConnection(ctx context.Context, connection *api.WebSocketConnection) error
CreateConnection stores a new WebSocket connection record in DynamoDB.
func (*ConnectionRepository) DeleteConnections
func (r *ConnectionRepository) DeleteConnections(ctx context.Context, connectionIDs []string) (int, error)
DeleteConnections removes WebSocket connections from DynamoDB by connection IDs using batch delete.
func (*ConnectionRepository) GetConnectionsByExecutionID
func (r *ConnectionRepository) GetConnectionsByExecutionID(ctx context.Context, executionID string) ([]*api.WebSocketConnection, error)
GetConnectionsByExecutionID retrieves all active WebSocket connection records for a given execution ID using the execution_id-index GSI.
type ExecutionRepository
ExecutionRepository implements the database.ExecutionRepository interface using DynamoDB.
type ExecutionRepository struct {
// contains filtered or unexported fields
}
func NewExecutionRepository
func NewExecutionRepository(client Client, tableName string, log *slog.Logger) *ExecutionRepository
NewExecutionRepository creates a new DynamoDB-backed execution repository.
func (*ExecutionRepository) CreateExecution
func (r *ExecutionRepository) CreateExecution(ctx context.Context, execution *api.Execution) error
CreateExecution stores a new execution record in DynamoDB.
func (*ExecutionRepository) GetExecution
func (r *ExecutionRepository) GetExecution(ctx context.Context, executionID string) (*api.Execution, error)
GetExecution retrieves an execution by its execution ID.
func (*ExecutionRepository) GetExecutionsByRequestID
func (r *ExecutionRepository) GetExecutionsByRequestID(ctx context.Context, requestID string) ([]*api.Execution, error)
GetExecutionsByRequestID retrieves all executions created or modified by a specific request ID. This uses Query operations on two GSIs (created_by_request_id-index and modified_by_request_id-index) instead of Scan for better performance.
func (*ExecutionRepository) ListExecutions
func (r *ExecutionRepository) ListExecutions(ctx context.Context, limit int, statuses []string) ([]*api.Execution, error)
ListExecutions queries the executions table using the all-started_at GSI to return execution records sorted by StartedAt descending (newest first). This uses Query instead of Scan for better performance and native sorting by DynamoDB. Status filtering and limiting are handled natively by DynamoDB using FilterExpression and Limit.
Parameters:
- limit: maximum number of executions to return. Use 0 to return all executions.
- statuses: optional slice of execution statuses to filter by. If empty, all executions are returned.
func (*ExecutionRepository) UpdateExecution
func (r *ExecutionRepository) UpdateExecution(ctx context.Context, execution *api.Execution) error
UpdateExecution updates an existing execution record.
type ImageTaskDefRepository
ImageTaskDefRepository implements image-taskdef mapping operations using DynamoDB.
type ImageTaskDefRepository struct {
// contains filtered or unexported fields
}
func NewImageTaskDefRepository
func NewImageTaskDefRepository(client Client, tableName string, log *slog.Logger) *ImageTaskDefRepository
NewImageTaskDefRepository creates a new DynamoDB-backed image-taskdef repository.
func (*ImageTaskDefRepository) DeleteImage
func (r *ImageTaskDefRepository) DeleteImage(ctx context.Context, image string) error
DeleteImage removes all task definition mappings for a specific image. Supports exact matching on both the image field and image_id field (for ImageID format). Returns ErrNotFound if no matching images are found.
func (*ImageTaskDefRepository) GetAnyImageTaskDef
func (r *ImageTaskDefRepository) GetAnyImageTaskDef(ctx context.Context, image string) (*api.ImageInfo, error)
GetAnyImageTaskDef retrieves any task definition configuration for a given image. Supports flexible matching: tries exact match on full image first, then matches by name:tag components. Returns the first matching item, preferring the default configuration if available.
func (*ImageTaskDefRepository) GetDefaultImage
func (r *ImageTaskDefRepository) GetDefaultImage(ctx context.Context) (*api.ImageInfo, error)
GetDefaultImage retrieves the image marked as default.
func (*ImageTaskDefRepository) GetImageTaskDef
func (r *ImageTaskDefRepository) GetImageTaskDef(ctx context.Context, image string, taskRoleName *string, taskExecutionRoleName *string, cpu *int, memory *int, runtimePlatform *string) (*api.ImageInfo, error)
GetImageTaskDef retrieves a specific image-taskdef mapping by generating ImageID from the configuration.
func (*ImageTaskDefRepository) GetImageTaskDefByID
func (r *ImageTaskDefRepository) GetImageTaskDefByID(ctx context.Context, imageID string) (*api.ImageInfo, error)
GetImageTaskDefByID retrieves an image-taskdef mapping by ImageID.
func (*ImageTaskDefRepository) GetImagesByRequestID
func (r *ImageTaskDefRepository) GetImagesByRequestID(ctx context.Context, requestID string) ([]api.ImageInfo, error)
GetImagesByRequestID retrieves all images created or modified by a specific request ID.
func (*ImageTaskDefRepository) GetImagesCount
func (r *ImageTaskDefRepository) GetImagesCount(ctx context.Context) (int, error)
GetImagesCount returns the total number of unique image+role combinations.
func (*ImageTaskDefRepository) GetUniqueImages
func (r *ImageTaskDefRepository) GetUniqueImages(ctx context.Context) ([]string, error)
GetUniqueImages returns a list of unique image names (deduplicated across role combinations).
func (*ImageTaskDefRepository) ListImages
func (r *ImageTaskDefRepository) ListImages(ctx context.Context) ([]api.ImageInfo, error)
ListImages retrieves all registered images with their task definitions.
func (*ImageTaskDefRepository) PutImageTaskDef
func (r *ImageTaskDefRepository) PutImageTaskDef(ctx context.Context, imageID string, image string, imageRegistry string, imageName string, imageTag string, taskRoleName *string, taskExecutionRoleName *string, cpu int, memory int, runtimePlatform string, taskDefFamily string, isDefault bool, createdBy string) error
PutImageTaskDef stores or updates an image-taskdef mapping.
func (*ImageTaskDefRepository) SetImageAsOnlyDefault
func (r *ImageTaskDefRepository) SetImageAsOnlyDefault(ctx context.Context, image string, taskRoleName *string, taskExecutionRoleName *string) error
SetImageAsOnlyDefault marks a specific image configuration as the only default. It first unmarks all other defaults, then sets this one as default.
func (*ImageTaskDefRepository) UnmarkAllDefaults
func (r *ImageTaskDefRepository) UnmarkAllDefaults(ctx context.Context) error
UnmarkAllDefaults removes the default flag from all images.
type MockDynamoDBClient
MockDynamoDBClient is a simple in-memory mock implementation of Client for testing. It provides basic support for Put, Get, Query, Update, Delete, and BatchWrite operations.
type MockDynamoDBClient struct {
// Tables maps table name -> partition key -> sort key -> item
// For tables without sort key, use empty string as sort key
Tables map[string]map[string]map[string]map[string]types.AttributeValue
// Index stores items by index name for Query operations
// Format: tableName -> indexName -> keyValue -> list of items
Indexes map[string]map[string]map[string][]map[string]types.AttributeValue
// Error injection for testing error scenarios
PutItemError error
GetItemError error
QueryError error
UpdateItemError error
DeleteItemError error
BatchWriteItemError error
ScanError error
// Call tracking for test assertions
PutItemCalls int
GetItemCalls int
QueryCalls int
UpdateItemCalls int
DeleteItemCalls int
BatchWriteItemCalls int
ScanCalls int
// contains filtered or unexported fields
}
func NewMockDynamoDBClient
func NewMockDynamoDBClient() *MockDynamoDBClient
NewMockDynamoDBClient creates a new mock DynamoDB client for testing.
func (*MockDynamoDBClient) BatchWriteItem
func (m *MockDynamoDBClient) BatchWriteItem(_ context.Context, params *dynamodb.BatchWriteItemInput, _ ...func(*dynamodb.Options)) (*dynamodb.BatchWriteItemOutput, error)
BatchWriteItem performs batch write operations.
func (*MockDynamoDBClient) ClearTables
func (m *MockDynamoDBClient) ClearTables()
ClearTables removes all data from the mock tables.
func (*MockDynamoDBClient) DeleteItem
func (m *MockDynamoDBClient) DeleteItem(_ context.Context, params *dynamodb.DeleteItemInput, _ ...func(*dynamodb.Options)) (*dynamodb.DeleteItemOutput, error)
DeleteItem removes an item from the mock table.
func (*MockDynamoDBClient) GetItem
func (m *MockDynamoDBClient) GetItem(_ context.Context, params *dynamodb.GetItemInput, _ ...func(*dynamodb.Options)) (*dynamodb.GetItemOutput, error)
GetItem retrieves an item from the mock table.
func (*MockDynamoDBClient) PutItem
func (m *MockDynamoDBClient) PutItem(_ context.Context, params *dynamodb.PutItemInput, _ ...func(*dynamodb.Options)) (*dynamodb.PutItemOutput, error)
PutItem stores an item in the mock table.
func (*MockDynamoDBClient) Query
func (m *MockDynamoDBClient) Query(_ context.Context, params *dynamodb.QueryInput, _ ...func(*dynamodb.Options)) (*dynamodb.QueryOutput, error)
Query searches for items in the mock table.
func (*MockDynamoDBClient) ResetCallCounts
func (m *MockDynamoDBClient) ResetCallCounts()
ResetCallCounts resets all call counters to zero.
func (*MockDynamoDBClient) Scan
func (m *MockDynamoDBClient) Scan(_ context.Context, params *dynamodb.ScanInput, _ ...func(*dynamodb.Options)) (*dynamodb.ScanOutput, error)
Scan scans all items in the mock table.
func (*MockDynamoDBClient) UpdateItem
func (m *MockDynamoDBClient) UpdateItem(_ context.Context, params *dynamodb.UpdateItemInput, _ ...func(*dynamodb.Options)) (*dynamodb.UpdateItemOutput, error)
UpdateItem updates an item in the mock table.
type SecretsRepository
SecretsRepository implements the database.SecretsRepository interface using DynamoDB.
type SecretsRepository struct {
// contains filtered or unexported fields
}
func NewSecretsRepository
func NewSecretsRepository(client Client, tableName string, log *slog.Logger) *SecretsRepository
NewSecretsRepository creates a new DynamoDB-backed secrets repository.
func (*SecretsRepository) CreateSecret
func (r *SecretsRepository) CreateSecret(ctx context.Context, secret *api.Secret) error
CreateSecret stores a new secret's metadata in DynamoDB.
func (*SecretsRepository) DeleteSecret
func (r *SecretsRepository) DeleteSecret(ctx context.Context, name string) error
DeleteSecret removes a secret's metadata from DynamoDB.
func (*SecretsRepository) GetSecret
func (r *SecretsRepository) GetSecret(ctx context.Context, name string) (*api.Secret, error)
GetSecret retrieves a secret's metadata by name from DynamoDB.
func (*SecretsRepository) GetSecretsByRequestID
func (r *SecretsRepository) GetSecretsByRequestID(ctx context.Context, requestID string) ([]*api.Secret, error)
GetSecretsByRequestID retrieves all secrets created or modified by a specific request ID.
func (*SecretsRepository) ListSecrets
func (r *SecretsRepository) ListSecrets(ctx context.Context) ([]*api.Secret, error)
ListSecrets retrieves all secrets.
func (*SecretsRepository) SecretExists
func (r *SecretsRepository) SecretExists(ctx context.Context, name string) (bool, error)
SecretExists checks if a secret with the given name exists in DynamoDB.
func (*SecretsRepository) UpdateSecretMetadata
func (r *SecretsRepository) UpdateSecretMetadata(ctx context.Context, name, keyName, description, updatedBy string) error
UpdateSecretMetadata updates a secret's metadata (description and keyName) in DynamoDB.
type TokenRepository
TokenRepository implements the database.TokenRepository interface using DynamoDB.
type TokenRepository struct {
// contains filtered or unexported fields
}
func (*TokenRepository) CreateToken
func (r *TokenRepository) CreateToken(ctx context.Context, token *api.WebSocketToken) error
CreateToken stores a new WebSocket authentication token with metadata.
func (*TokenRepository) DeleteToken
func (r *TokenRepository) DeleteToken(ctx context.Context, tokenValue string) error
DeleteToken removes a token from the database.
func (*TokenRepository) GetToken
func (r *TokenRepository) GetToken(ctx context.Context, tokenValue string) (*api.WebSocketToken, error)
GetToken retrieves a token by its value. Returns nil if the token doesn't exist (DynamoDB TTL automatically removes expired tokens).
type UserRepository
UserRepository implements the database.UserRepository interface using DynamoDB.
type UserRepository struct {
// contains filtered or unexported fields
}
func NewUserRepository
func NewUserRepository(client Client, tableName string, pendingTableName string, log *slog.Logger) *UserRepository
NewUserRepository creates a new DynamoDB-backed user repository.
func (*UserRepository) CreatePendingAPIKey
func (r *UserRepository) CreatePendingAPIKey(ctx context.Context, pending *api.PendingAPIKey) error
CreatePendingAPIKey stores a pending API key with a secret token.
func (*UserRepository) CreateUser
func (r *UserRepository) CreateUser(ctx context.Context, user *api.User, apiKeyHash string, expiresAtUnix int64) error
CreateUser stores a new user with their hashed API key in DynamoDB. If expiresAtUnix is 0, no TTL is set (permanent user). If expiresAtUnix is > 0, it sets the expires_at field for automatic deletion.
func (*UserRepository) DeletePendingAPIKey
func (r *UserRepository) DeletePendingAPIKey(ctx context.Context, secretToken string) error
DeletePendingAPIKey removes a pending API key from the database.
func (*UserRepository) GetPendingAPIKey
func (r *UserRepository) GetPendingAPIKey(ctx context.Context, secretToken string) (*api.PendingAPIKey, error)
GetPendingAPIKey retrieves a pending API key by its secret token.
func (*UserRepository) GetUserByAPIKeyHash
func (r *UserRepository) GetUserByAPIKeyHash(ctx context.Context, apiKeyHash string) (*api.User, error)
GetUserByAPIKeyHash retrieves a user by their hashed API key (primary key).
func (*UserRepository) GetUserByEmail
func (r *UserRepository) GetUserByEmail(ctx context.Context, email string) (*api.User, error)
GetUserByEmail retrieves a user by their email using the GSI.
func (*UserRepository) GetUsersByRequestID
func (r *UserRepository) GetUsersByRequestID(ctx context.Context, requestID string) ([]*api.User, error)
GetUsersByRequestID retrieves all users created or modified by a specific request ID.
func (*UserRepository) ListUsers
func (r *UserRepository) ListUsers(ctx context.Context) ([]*api.User, error)
ListUsers returns all users in the system sorted by email (excluding API key hashes for security). Uses the all-user_email GSI to retrieve users in sorted order directly from DynamoDB.
func (*UserRepository) MarkAsViewed
func (r *UserRepository) MarkAsViewed(ctx context.Context, secretToken, ipAddress string) error
MarkAsViewed atomically marks a pending key as viewed with the IP address.
func (*UserRepository) RemoveExpiration
func (r *UserRepository) RemoveExpiration(ctx context.Context, email string) error
RemoveExpiration removes the expires_at field from a user record, making them permanent.
func (*UserRepository) RevokeUser
func (r *UserRepository) RevokeUser(ctx context.Context, email string) error
RevokeUser marks a user's API key as revoked.
func (*UserRepository) UpdateLastUsed
func (r *UserRepository) UpdateLastUsed(ctx context.Context, email string) (*time.Time, error)
UpdateLastUsed updates the last_used timestamp for a user.
Generated by gomarkdoc