Documentation
¶
Overview ¶
Package ork provides a framework for remote server automation.
Package ork provides a simple, intuitive API for SSH-based server automation.
The core concept is the Node - a representation of a remote server that you can connect to and run commands or playbooks against.
Basic usage:
node := ork.NewNode("server.example.com")
output, err := node.Run("uptime")
With configuration:
node := ork.NewNode("server.example.com").
SetPort("2222").
SetUser("deploy")
output, err := node.Run("uptime")
Persistent connections for multiple operations:
node := ork.NewNode("server.example.com")
if err := node.Connect(); err != nil {
log.Fatal(err)
}
defer node.Close()
output1, _ := node.Run("uptime")
output2, _ := node.Run("df -h")
Running playbooks:
node := ork.NewNode("server.example.com").
SetArg("username", "alice")
err := node.Playbook("user-create")
For advanced use cases, the internal packages remain accessible:
- config - Configuration types
- ssh - SSH client
- types - Shared types (PlaybookInterface, Registry, Result, Command)
- playbook - Playbook interface (re-exports from types for backward compatibility)
- playbooks - Built-in playbook implementations
Package ork provides a framework for remote server automation.
Index ¶
- Constants
- func GetGlobalPlaybookRegistry() (*types.Registry, error)
- func NewDefaultRegistry() (*types.Registry, error)
- func NewPlaybookRegistry() *types.Registry
- func PromptPassword(prompt string) (string, error)
- func VaultContentToEnv(vaultContent, vaultPassword string) (err error)
- func VaultContentToEnvWithPrompt(vaultContent string) (err error)
- func VaultContentToKeys(vaultContent, vaultPassword string) (keys map[string]string, err error)
- func VaultContentToKeysWithPrompt(vaultContent string) (keys map[string]string, err error)
- func VaultFileToEnv(vaultFilePath, vaultPassword string) (err error)
- func VaultFileToEnvWithPrompt(vaultFilePath string) (err error)
- func VaultFileToKeys(vaultFilePath string, vaultPassword string) (keys map[string]string, err error)
- func VaultFileToKeysWithPrompt(vaultFilePath string) (keys map[string]string, err error)
- type GroupInterface
- type InventoryInterface
- type NodeInterface
- type RunnableInterface
Constants ¶
const ( // PlaybookPing checks SSH connectivity PlaybookPing = playbooks.IDPing // PlaybookAptUpdate refreshes the package database PlaybookAptUpdate = playbooks.IDAptUpdate // PlaybookAptUpgrade installs available updates PlaybookAptUpgrade = playbooks.IDAptUpgrade // PlaybookAptStatus shows available updates PlaybookAptStatus = playbooks.IDAptStatus // PlaybookReboot reboots the server PlaybookReboot = playbooks.IDReboot // PlaybookSwapCreate creates a swap file (requires "size" arg in GB) PlaybookSwapCreate = playbooks.IDSwapCreate // PlaybookSwapDelete removes the swap file PlaybookSwapDelete = playbooks.IDSwapDelete // PlaybookSwapStatus shows swap status PlaybookSwapStatus = playbooks.IDSwapStatus // PlaybookUserCreate creates a user with sudo (requires "username" arg) PlaybookUserCreate = playbooks.IDUserCreate // PlaybookUserDelete deletes a user (requires "username" arg) PlaybookUserDelete = playbooks.IDUserDelete // PlaybookUserList lists all non-system users PlaybookUserList = playbooks.IDUserList // PlaybookUserStatus shows user info (requires "username" arg) PlaybookUserStatus = playbooks.IDUserStatus )
Playbook ID constants for use with RunPlaybook. These constants provide compile-time safety and IDE autocomplete for playbook IDs. They are aliases to the constants in the playbooks package.
Example:
node := ork.NewNodeForHost("server.example.com")
err := node.RunPlaybook(ork.PlaybookPing)
Variables ¶
This section is empty.
Functions ¶
func GetGlobalPlaybookRegistry ¶ added in v0.10.0
GetGlobalPlaybookRegistry returns the global playbook registry singleton. This is syntactic sugar for user convenience - it lazily initializes and returns the global registry with all built-in playbooks pre-registered.
For most use cases, users should call this function. For testing or custom configurations, use NewDefaultRegistry() to create isolated registries.
The registry is lazily initialized on first call using sync.Once to ensure thread-safe singleton behavior. Returns an error if initialization fails.
func NewDefaultRegistry ¶ added in v0.10.0
NewDefaultRegistry creates a new playbook registry with all built-in playbooks registered. This creates a fresh registry instance (not a singleton), which is useful for: - Testing with isolated registries - Custom configurations without global state - Multiple independent registries in the same application
For most production use cases, use GetGlobalPlaybookRegistry() instead for convenience. Returns an error if any playbook registration fails.
func NewPlaybookRegistry ¶ added in v0.10.0
NewPlaybookRegistry creates a new empty playbook registry. This is a convenience method (sugar) for types.NewRegistry() with a more intuitive name. This creates a fresh empty registry instance, which is useful for: - Testing with isolated registries - Custom configurations with selective playbook registration - Multiple independent registries in the same application
Returns an empty registry ready for custom playbook registration.
func PromptPassword ¶ added in v0.10.0
PromptPassword securely prompts for a password from stdin. The password is not echoed to the terminal.
func VaultContentToEnv ¶ added in v0.10.0
VaultContentToEnv hydrates environment variables from a vault content string.
func VaultContentToEnvWithPrompt ¶ added in v0.10.0
VaultContentToEnvWithPrompt prompts for password and hydrates environment variables from a vault content string.
func VaultContentToKeys ¶ added in v0.10.0
VaultContentToKeys loads keys from a vault content string.
func VaultContentToKeysWithPrompt ¶ added in v0.10.0
VaultContentToKeysWithPrompt prompts for password and loads keys from a vault content string.
func VaultFileToEnv ¶ added in v0.10.0
VaultFileToEnv decrypts vault and hydrates environment variables.
func VaultFileToEnvWithPrompt ¶ added in v0.10.0
VaultFileToEnvWithPrompt prompts for password and hydrates environment variables from a vault file.
Types ¶
type GroupInterface ¶ added in v0.9.0
type GroupInterface interface {
// RunnableInterface is embedded for command and playbook execution.
// Operations run on all nodes in this group only.
RunnableInterface
// GetName returns the group's name.
GetName() string
// AddNode adds a node to this group.
// The node can be configured using the returned NodeInterface.
AddNode(node NodeInterface) GroupInterface
// GetNodes returns all nodes in this group.
GetNodes() []NodeInterface
// SetArg sets an argument for this group.
// Group arguments are inherited by all nodes in the group.
SetArg(key, value string) GroupInterface
// GetArg retrieves an argument value by key.
// Returns empty string if not set.
GetArg(key string) string
// GetArgs returns a copy of all arguments defined for this group.
GetArgs() map[string]string
}
GroupInterface defines operations for managing a group of nodes. It embeds RunnableInterface for executing operations on the group's nodes.
func NewGroup ¶ added in v0.9.0
func NewGroup(name string) GroupInterface
NewGroup creates a new group with the given name.
type InventoryInterface ¶ added in v0.9.0
type InventoryInterface interface {
// RunnableInterface is embedded for command and playbook execution.
// Operations run concurrently across all nodes in the inventory.
RunnableInterface
// AddGroup adds a group to the inventory.
AddGroup(group GroupInterface) InventoryInterface
// GetGroup retrieves a group by name.
// Returns nil if the group does not exist.
GetGroupByName(name string) GroupInterface
// AddNode adds a node directly to the inventory (not in any specific group).
// The node can be configured using the returned NodeInterface.
AddNode(node NodeInterface) InventoryInterface
// GetNodes returns all nodes in the inventory across all groups.
GetNodes() []NodeInterface
// SetMaxConcurrency sets the maximum number of concurrent operations.
// Default is 10. Set to 0 for unlimited.
SetMaxConcurrency(max int) InventoryInterface
}
InventoryInterface defines operations for managing a collection of nodes organized into groups. It embeds RunnableInterface for executing operations across all nodes in the inventory.
func NewInventory ¶ added in v0.9.0
func NewInventory() InventoryInterface
NewInventory creates a new empty inventory.
type NodeInterface ¶
type NodeInterface interface {
// RunnableInterface defines operations that can be performed on the node.
// NodeInterface embeds RunnableInterface for unified API with Group and Inventory.
RunnableInterface
// GetArg retrieves a single argument value by key.
// Returns empty string if the argument is not set.
//
// Example:
//
// node := ork.NewNode("server.example.com").SetArg("username", "alice")
// fmt.Println(node.GetArg("username")) // Output: alice
GetArg(key string) string
// GetArgs returns a copy of the entire arguments map.
// Modifying the returned map will not affect the node's internal state.
//
// Example:
//
// node := ork.NewNode("server.example.com").SetArg("username", "alice")
// args := node.GetArgs()
// fmt.Println(args["username"]) // Output: alice
GetArgs() map[string]string
// GetNodeConfig returns a copy of the underlying config.NodeConfig.
// This allows integration with code that uses the config package directly.
// The returned configuration includes all accumulated settings (host, port, user, key, args).
//
// Example:
//
// node := ork.NewNode("server.example.com").
// SetPort("2222").
// SetUser("deploy")
// cfg := node.GetNodeConfig()
// fmt.Printf("Connecting to %s\n", cfg.SSHAddr())
GetNodeConfig() config.NodeConfig
// GetHost returns the configured SSH host (hostname or IP address).
//
// Example:
//
// node := ork.NewNode("server.example.com")
// fmt.Println(node.GetHost()) // Output: server.example.com
GetHost() string
// GetUser returns the configured SSH user.
// Returns "root" if not explicitly set.
//
// Example:
//
// node := ork.NewNode("server.example.com").SetUser("deploy")
// fmt.Println(node.GetUser()) // Output: deploy
GetUser() string
// GetKey returns the configured SSH private key filename.
// Returns "id_rsa" if not explicitly set.
//
// Example:
//
// node := ork.NewNode("server.example.com").SetKey("production.prv")
// fmt.Println(node.GetKey()) // Output: production.prv
GetKey() string
// GetPort returns the configured SSH port.
// Returns "22" if not explicitly set.
//
// Example:
//
// node := ork.NewNode("server.example.com").SetPort("2222")
// fmt.Println(node.GetPort()) // Output: 2222
GetPort() string
// SetPort sets the SSH port for the connection.
// Returns the NodeInterface to enable method chaining.
// Default is "22" if not set.
//
// Example:
//
// node := ork.NewNode("server.example.com").SetPort("2222")
SetPort(port string) NodeInterface
// SetUser sets the SSH user for the connection.
// Returns the NodeInterface to enable method chaining.
// Default is "root" if not set.
//
// Example:
//
// node := ork.NewNode("server.example.com").SetUser("deploy")
SetUser(user string) NodeInterface
// SetKey sets the SSH private key filename for authentication.
// The key is resolved to ~/.ssh/<keyname>.
// Returns the NodeInterface to enable method chaining.
// Default is "id_rsa" if not set.
//
// Example:
//
// node := ork.NewNode("server.example.com").SetKey("production.prv")
SetKey(key string) NodeInterface
// SetArg adds a single argument to the arguments map.
// This adds to existing arguments without replacing them.
// Arguments are passed to playbooks for configuration.
// Returns the NodeInterface to enable method chaining.
//
// Example:
//
// node := ork.NewNode("server.example.com").
// SetArg("username", "alice").
// SetArg("shell", "/bin/bash")
SetArg(key, value string) NodeInterface
// SetArgs replaces the entire arguments map with the provided map.
// Any existing arguments are discarded.
// Arguments are passed to playbooks for configuration.
// Returns the NodeInterface to enable method chaining.
//
// Example:
//
// args := map[string]string{
// "username": "alice",
// "shell": "/bin/bash",
// }
// node := ork.NewNode("server.example.com").SetArgs(args)
SetArgs(args map[string]string) NodeInterface
// Connect establishes a persistent SSH connection to the remote server.
// The connection is maintained until Close() is called.
// Subsequent RunCommand() and RunPlaybook() calls will reuse this connection.
//
// Returns an error if the connection fails, with a descriptive message
// including the host and port.
//
// Example:
//
// node := ork.NewNode("server.example.com")
// if err := node.Connect(); err != nil {
// log.Fatalf("Failed to connect: %v", err)
// }
// defer node.Close()
Connect() error
// Close terminates the persistent SSH connection and releases resources.
// After calling Close(), IsConnected() will return false.
// It is safe to call Close() multiple times or on a non-connected node.
//
// Returns an error if closing the connection fails.
//
// Example:
//
// node := ork.NewNode("server.example.com")
// node.Connect()
// defer node.Close()
Close() error
// IsConnected returns true if a persistent SSH connection is currently active.
// Returns false if Connect() has not been called or if Close() was called.
//
// Example:
//
// node := ork.NewNode("server.example.com")
// fmt.Println(node.IsConnected()) // Output: false
// node.Connect()
// fmt.Println(node.IsConnected()) // Output: true
// node.Close()
// fmt.Println(node.IsConnected()) // Output: false
IsConnected() bool
// RunPlaybookByID executes a playbook by ID from the registry.
// Deprecated: Use RunPlaybook() instead. Run playbooks by creating the playbook
// instance directly (e.g., playbooks.NewPing()) and passing it to RunPlaybook().
// This provides better type safety and IDE autocomplete support.
//
// Optional PlaybookOptions can be provided to override node-level arguments for this
// specific execution. This allows per-playbook variable scoping without affecting
// the node's state.
RunPlaybookByID(id string, opts ...types.PlaybookOptions) types.Results
}
NodeInterface defines the contract for managing a remote server via SSH. Implementations must support configuration via setter methods, connection management, command execution, and playbook execution.
The interface provides two patterns for configuration:
- Fluent builder pattern: Chain setter methods for readable configuration
- Getter methods: Inspect current configuration state
Connection management is explicit, allowing users to control the SSH connection lifecycle. Operations (RunCommand, RunPlaybook) can work with or without a persistent connection.
Example usage with fluent builder pattern:
node := ork.NewNode("server.example.com").
SetPort("2222").
SetUser("deploy").
SetKey("production.prv")
if err := node.Connect(); err != nil {
log.Fatal(err)
}
defer node.Close()
output, err := node.RunCommand("uptime")
if err != nil {
log.Fatal(err)
}
fmt.Println(output)
Example usage without persistent connection:
node := ork.NewNode("server.example.com")
output, err := node.RunCommand("uptime") // Creates one-time connection
Example usage with playbooks:
node := ork.NewNode("server.example.com").
SetArg("username", "alice").
SetArg("shell", "/bin/bash")
if err := node.RunPlaybook("user-create"); err != nil {
log.Fatal(err)
}
func NewNode ¶
func NewNode() NodeInterface
NewNode creates a new Node with default configuration values. Unlike NewNodeForHost, this function takes no arguments and creates a node with an empty host. Use SetArg or SetArgs to configure the node.
Default values:
- Host: "" (empty - must be set before connecting)
- Port: "22"
- User: "root"
- Key: "id_rsa"
- Args: empty map
Example:
node := ork.NewNode().
SetHost("server.example.com").
SetPort("2222").
SetUser("deploy")
if err := node.Connect(); err != nil {
log.Fatal(err)
}
func NewNodeForHost ¶ added in v0.3.0
func NewNodeForHost(host string) NodeInterface
NewNode creates a new Node with default configuration values. The host parameter specifies the remote server (hostname or IP address).
Default values:
- Port: "22"
- User: "root"
- Key: "id_rsa"
- Args: empty map
The returned NodeInterface can be configured using setter methods (SetPort, SetUser, SetKey, SetArg, SetArgs) before connecting.
Example:
node := ork.NewNode("server.example.com")
// Equivalent to:
// Node{
// cfg: config.NodeConfig{
// SSHHost: "server.example.com",
// SSHPort: "22",
// RootUser: "root",
// SSHKey: "id_rsa",
// Args: map[string]string{},
// },
// connected: false,
// }
Example with configuration:
node := ork.NewNode("server.example.com").
SetPort("2222").
SetUser("deploy").
SetKey("production.prv")
func NewNodeFromConfig ¶ added in v0.3.0
func NewNodeFromConfig(cfg config.NodeConfig) NodeInterface
NewNodeFromConfig creates a new Node from an existing config.NodeConfig. This is useful when you have a pre-built configuration and want to create a Node from it directly.
The config is copied internally, so modifications to the original config after calling this function will not affect the Node.
Example:
cfg := config.NodeConfig{
SSHHost: "server.example.com",
SSHPort: "2222",
RootUser: "deploy",
SSHKey: "production.prv",
Args: map[string]string{"env": "production"},
}
node := ork.NewNodeFromConfig(cfg)
if err := node.Connect(); err != nil {
log.Fatal(err)
}
type RunnableInterface ¶ added in v0.9.0
type RunnableInterface interface {
// RunCommand executes a shell command and returns the output.
// For Inventory, runs concurrently across all nodes.
RunCommand(cmd string) types.Results
// RunPlaybook executes a playbook instance.
// For Inventory, runs concurrently across all nodes.
RunPlaybook(pb types.PlaybookInterface) types.Results
// RunPlaybookByID executes a playbook by ID from the registry.
// Deprecated: Use RunPlaybook() instead.
RunPlaybookByID(id string, opts ...types.PlaybookOptions) types.Results
// CheckPlaybook runs the playbook's check mode to determine if changes would be made.
// Sets Changed=true on result if changes are needed.
CheckPlaybook(pb types.PlaybookInterface) types.Results
// GetLogger returns the logger. Returns slog.Default() if not set.
GetLogger() *slog.Logger
// SetLogger sets a custom logger. Returns self for chaining.
SetLogger(logger *slog.Logger) RunnableInterface
// SetDryRunMode sets whether to simulate execution without making changes.
// When true, ssh.Run() will log commands and return "[dry-run]" marker instead of executing.
// Returns self for chaining.
SetDryRunMode(dryRun bool) RunnableInterface
// GetDryRunMode returns true if dry-run mode is enabled.
// When true, commands are logged but not executed on the server.
GetDryRunMode() bool
}
RunnableInterface defines operations that can be performed on either a single Node or an Inventory of nodes.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package config provides configuration types for SSH-based automation.
|
Package config provides configuration types for SSH-based automation. |
|
internal
|
|
|
Package playbooks provides built-in reusable playbook implementations for common server automation tasks.
|
Package playbooks provides built-in reusable playbook implementations for common server automation tasks. |
|
apt
Package apt provides playbooks for managing Debian/Ubuntu packages via apt.
|
Package apt provides playbooks for managing Debian/Ubuntu packages via apt. |
|
fail2ban
Package fail2ban provides playbooks for managing the fail2ban intrusion prevention system.
|
Package fail2ban provides playbooks for managing the fail2ban intrusion prevention system. |
|
mariadb
Package mariadb provides playbooks for managing MariaDB database servers.
|
Package mariadb provides playbooks for managing MariaDB database servers. |
|
ping
Package ping provides a playbook for testing SSH connectivity to remote servers.
|
Package ping provides a playbook for testing SSH connectivity to remote servers. |
|
reboot
Package reboot provides a playbook for rebooting remote servers.
|
Package reboot provides a playbook for rebooting remote servers. |
|
security
Package security provides playbooks for system security hardening and configuration.
|
Package security provides playbooks for system security hardening and configuration. |
|
swap
Package swap provides playbooks for managing swap files on Linux systems.
|
Package swap provides playbooks for managing swap files on Linux systems. |
|
ufw
Package ufw provides playbooks for managing the Uncomplicated Firewall (UFW).
|
Package ufw provides playbooks for managing the Uncomplicated Firewall (UFW). |
|
user
Package user provides playbooks for managing Linux user accounts.
|
Package user provides playbooks for managing Linux user accounts. |
|
Package ssh provides SSH connectivity utilities for remote server automation.
|
Package ssh provides SSH connectivity utilities for remote server automation. |
|
Package types provides shared types for ork packages.
|
Package types provides shared types for ork packages. |