Merge pull request '[agent/codex] A specs/RFC.md stub has been injected. Read the actual sourc...' (#16) from agent/upgrade-this-package-to-dappco-re-go-cor into dev
This commit is contained in:
commit
b87b226c08
2 changed files with 379 additions and 0 deletions
15
cmd/ansible/specs/RFC.md
Normal file
15
cmd/ansible/specs/RFC.md
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# anscmd
|
||||
**Import:** `dappco.re/go/core/ansible/cmd/ansible`
|
||||
**Files:** 3
|
||||
|
||||
## Types
|
||||
This package has no exported structs, interfaces, or type aliases.
|
||||
|
||||
## Functions
|
||||
### Register
|
||||
`func Register(c *core.Core)`
|
||||
|
||||
Registers two CLI commands on `c`:
|
||||
|
||||
- `ansible`: Runs a playbook through `ansible.Executor`. The command exposes `inventory`, `limit`, `tags`, `skip-tags`, `extra-vars`, `verbose`, and `check` flags.
|
||||
- `ansible/test`: Opens an SSH connection to a host, prints basic host facts, and exposes `user`, `password`, `key`, and `port` flags.
|
||||
364
specs/RFC.md
Normal file
364
specs/RFC.md
Normal file
|
|
@ -0,0 +1,364 @@
|
|||
# ansible
|
||||
**Import:** `dappco.re/go/core/ansible`
|
||||
**Files:** 6
|
||||
|
||||
## Types
|
||||
This package exports structs only. It has no exported interfaces or type aliases.
|
||||
|
||||
### Playbook
|
||||
`type Playbook struct`
|
||||
|
||||
Top-level playbook wrapper for YAML documents that decode to an inline list of plays.
|
||||
|
||||
Fields:
|
||||
- `Plays []Play`: Inlined play definitions in declaration order.
|
||||
|
||||
### Play
|
||||
`type Play struct`
|
||||
|
||||
One play in a playbook, including host targeting, privilege settings, vars, task lists, roles, handlers, and run controls.
|
||||
|
||||
Fields:
|
||||
- `Name string`: Human-readable play name used in output and callbacks.
|
||||
- `Hosts string`: Inventory pattern resolved before the play runs.
|
||||
- `Connection string`: Optional connection type; `"local"` skips SSH fact gathering.
|
||||
- `Become bool`: Enables privilege escalation for tasks in the play.
|
||||
- `BecomeUser string`: Override user for privilege escalation.
|
||||
- `GatherFacts *bool`: Optional fact-gathering switch; `nil` means facts are gathered.
|
||||
- `Vars map[string]any`: Play-scoped variables merged into parser and executor state.
|
||||
- `PreTasks []Task`: Tasks run before roles and main tasks.
|
||||
- `Tasks []Task`: Main task list.
|
||||
- `PostTasks []Task`: Tasks run after the main task list.
|
||||
- `Roles []RoleRef`: Role references executed between `PreTasks` and `Tasks`.
|
||||
- `Handlers []Task`: Handler tasks that may run after normal tasks when notified.
|
||||
- `Tags []string`: Tags attached to the play.
|
||||
- `Environment map[string]string`: Environment variables attached to the play.
|
||||
- `Serial any`: Serial batch setting; the YAML accepts either an `int` or a `string`.
|
||||
- `MaxFailPercent int`: Maximum tolerated failure percentage for the play.
|
||||
|
||||
### RoleRef
|
||||
`type RoleRef struct`
|
||||
|
||||
Role entry used in `Play.Roles`. The YAML may be either a scalar role name or a mapping.
|
||||
|
||||
Fields:
|
||||
- `Role string`: Canonical role name used by the executor.
|
||||
- `Name string`: Alternate YAML field that is normalised into `Role` during unmarshalling.
|
||||
- `TasksFrom string`: Task file loaded from the role's `tasks/` directory.
|
||||
- `Vars map[string]any`: Variables merged while the role runs.
|
||||
- `When any`: Optional condition evaluated before the role runs.
|
||||
- `Tags []string`: Tags declared on the role reference.
|
||||
|
||||
### Task
|
||||
`type Task struct`
|
||||
|
||||
Single Ansible task, including the selected module, module args, flow-control settings, includes, blocks, notifications, and privilege settings.
|
||||
|
||||
Fields:
|
||||
- `Name string`: Optional task name.
|
||||
- `Module string`: Module name extracted from the YAML key rather than a fixed field.
|
||||
- `Args map[string]any`: Module arguments extracted from the YAML value.
|
||||
- `Register string`: Variable name used to store the task result.
|
||||
- `When any`: Conditional expression or expression list.
|
||||
- `Loop any`: Loop source, typically a slice or templated string.
|
||||
- `LoopControl *LoopControl`: Optional loop metadata such as custom variable names.
|
||||
- `Vars map[string]any`: Task-local variables.
|
||||
- `Environment map[string]string`: Task-local environment overrides.
|
||||
- `ChangedWhen any`: Override for changed-state evaluation.
|
||||
- `FailedWhen any`: Override for failure evaluation.
|
||||
- `IgnoreErrors bool`: Continue after task failure when true.
|
||||
- `NoLog bool`: Marker for suppressing logging.
|
||||
- `Become *bool`: Per-task privilege-escalation override.
|
||||
- `BecomeUser string`: Per-task privilege-escalation user.
|
||||
- `Delegate string`: `delegate_to` target host.
|
||||
- `RunOnce bool`: Runs the task once rather than on every host.
|
||||
- `Tags []string`: Tags attached to the task.
|
||||
- `Block []Task`: Main block tasks for `block` syntax.
|
||||
- `Rescue []Task`: Rescue tasks run after a block failure.
|
||||
- `Always []Task`: Tasks that always run after a block.
|
||||
- `Notify any`: Handler notification target, either a string or a list.
|
||||
- `Retries int`: Retry count for `until` loops.
|
||||
- `Delay int`: Delay between retries.
|
||||
- `Until string`: Condition checked for retry loops.
|
||||
- `IncludeTasks string`: Path used by `include_tasks`.
|
||||
- `ImportTasks string`: Path used by `import_tasks`.
|
||||
- `IncludeRole *struct{...}`: Role inclusion payload with `Name`, optional `TasksFrom`, and optional `Vars`.
|
||||
- `ImportRole *struct{...}`: Role import payload with `Name`, optional `TasksFrom`, and optional `Vars`.
|
||||
|
||||
### LoopControl
|
||||
`type LoopControl struct`
|
||||
|
||||
Loop metadata attached to a task.
|
||||
|
||||
Fields:
|
||||
- `LoopVar string`: Name assigned to the current loop item.
|
||||
- `IndexVar string`: Name assigned to the current loop index.
|
||||
- `Label string`: Display label for loop items.
|
||||
- `Pause int`: Pause between loop iterations.
|
||||
- `Extended bool`: Enables extended loop metadata.
|
||||
|
||||
### TaskResult
|
||||
`type TaskResult struct`
|
||||
|
||||
Normalised execution result returned by module handlers and stored in registered variables.
|
||||
|
||||
Fields:
|
||||
- `Changed bool`: Whether the task changed remote state.
|
||||
- `Failed bool`: Whether the task failed.
|
||||
- `Skipped bool`: Whether the task was skipped.
|
||||
- `Msg string`: Summary message.
|
||||
- `Stdout string`: Standard output captured from command-based modules.
|
||||
- `Stderr string`: Standard error captured from command-based modules.
|
||||
- `RC int`: Command exit status when applicable.
|
||||
- `Results []TaskResult`: Per-item loop results.
|
||||
- `Data map[string]any`: Module-specific result payload.
|
||||
- `Duration time.Duration`: Execution duration recorded by the executor.
|
||||
|
||||
### Inventory
|
||||
`type Inventory struct`
|
||||
|
||||
Root inventory object.
|
||||
|
||||
Fields:
|
||||
- `All *InventoryGroup`: Root inventory group decoded from the `all` key.
|
||||
|
||||
### InventoryGroup
|
||||
`type InventoryGroup struct`
|
||||
|
||||
Inventory group containing hosts, child groups, and inherited variables.
|
||||
|
||||
Fields:
|
||||
- `Hosts map[string]*Host`: Hosts defined directly in the group.
|
||||
- `Children map[string]*InventoryGroup`: Nested child groups.
|
||||
- `Vars map[string]any`: Variables inherited by descendant hosts unless overridden.
|
||||
|
||||
### Host
|
||||
`type Host struct`
|
||||
|
||||
Per-host inventory entry with Ansible connection settings and inline custom vars.
|
||||
|
||||
Fields:
|
||||
- `AnsibleHost string`: Remote address or hostname to connect to.
|
||||
- `AnsiblePort int`: SSH port.
|
||||
- `AnsibleUser string`: SSH user.
|
||||
- `AnsiblePassword string`: SSH password.
|
||||
- `AnsibleSSHPrivateKeyFile string`: Private key path for SSH authentication.
|
||||
- `AnsibleConnection string`: Connection transport hint.
|
||||
- `AnsibleBecomePassword string`: Password used for privilege escalation.
|
||||
- `Vars map[string]any`: Additional host variables stored inline in YAML.
|
||||
|
||||
### Facts
|
||||
`type Facts struct`
|
||||
|
||||
Subset of gathered host facts stored by the executor.
|
||||
|
||||
Fields:
|
||||
- `Hostname string`: Short hostname.
|
||||
- `FQDN string`: Fully qualified domain name.
|
||||
- `OS string`: OS family.
|
||||
- `Distribution string`: Distribution identifier.
|
||||
- `Version string`: Distribution version.
|
||||
- `Architecture string`: Machine architecture.
|
||||
- `Kernel string`: Kernel release.
|
||||
- `Memory int64`: Total memory in MiB.
|
||||
- `CPUs int`: Virtual CPU count.
|
||||
- `IPv4 string`: Default IPv4 address.
|
||||
|
||||
### Parser
|
||||
`type Parser struct`
|
||||
|
||||
Stateful YAML parser for playbooks, inventories, task files, and roles. Its internal path and variable cache are unexported.
|
||||
|
||||
### Executor
|
||||
`type Executor struct`
|
||||
|
||||
Playbook execution engine that combines parser state, inventory, vars, gathered facts, registered results, handler notifications, and SSH client reuse.
|
||||
|
||||
Fields:
|
||||
- `OnPlayStart func(play *Play)`: Optional callback fired before a play starts.
|
||||
- `OnTaskStart func(host string, task *Task)`: Optional callback fired before a task runs on a host.
|
||||
- `OnTaskEnd func(host string, task *Task, result *TaskResult)`: Optional callback fired after a task result is produced.
|
||||
- `OnPlayEnd func(play *Play)`: Optional callback fired after a play finishes.
|
||||
- `Limit string`: Additional host filter applied after normal play host resolution.
|
||||
- `Tags []string`: Inclusive tag filter for task execution.
|
||||
- `SkipTags []string`: Exclusive tag filter that always skips matching tasks.
|
||||
- `CheckMode bool`: Public execution flag exposed for callers and CLI wiring.
|
||||
- `Diff bool`: Public execution flag exposed for callers and CLI wiring.
|
||||
- `Verbose int`: Verbosity level used by executor logging and CLI callbacks.
|
||||
|
||||
### SSHClient
|
||||
`type SSHClient struct`
|
||||
|
||||
Lazy SSH client that owns connection, authentication, privilege-escalation, and timeout state. All fields are unexported.
|
||||
|
||||
### SSHConfig
|
||||
`type SSHConfig struct`
|
||||
|
||||
Configuration used to construct an `SSHClient`.
|
||||
|
||||
Fields:
|
||||
- `Host string`: Target host.
|
||||
- `Port int`: Target SSH port; defaults to `22`.
|
||||
- `User string`: SSH user; defaults to `"root"`.
|
||||
- `Password string`: SSH password.
|
||||
- `KeyFile string`: Private key path.
|
||||
- `Become bool`: Enables privilege escalation on the client.
|
||||
- `BecomeUser string`: User used for privilege escalation.
|
||||
- `BecomePass string`: Password used for privilege escalation.
|
||||
- `Timeout time.Duration`: Connection timeout; defaults to `30 * time.Second`.
|
||||
|
||||
## Functions
|
||||
### NewParser
|
||||
`func NewParser(basePath string) *Parser`
|
||||
|
||||
Constructs a parser rooted at `basePath` and initialises its internal variable map. `basePath` is later used to resolve role search paths.
|
||||
|
||||
### (*Parser).ParsePlaybook
|
||||
`func (p *Parser) ParsePlaybook(path string) ([]Play, error)`
|
||||
|
||||
Reads a playbook YAML file, unmarshals it into `[]Play`, and post-processes every `PreTasks`, `Tasks`, `PostTasks`, and handler entry to extract `Task.Module` and `Task.Args`.
|
||||
|
||||
### (*Parser).ParsePlaybookIter
|
||||
`func (p *Parser) ParsePlaybookIter(path string) (iter.Seq[Play], error)`
|
||||
|
||||
Wrapper around `ParsePlaybook` that yields parsed plays through an `iter.Seq`.
|
||||
|
||||
### (*Parser).ParseInventory
|
||||
`func (p *Parser) ParseInventory(path string) (*Inventory, error)`
|
||||
|
||||
Reads an inventory YAML file and unmarshals it into the public `Inventory` model.
|
||||
|
||||
### (*Parser).ParseTasks
|
||||
`func (p *Parser) ParseTasks(path string) ([]Task, error)`
|
||||
|
||||
Reads a task file, unmarshals it into `[]Task`, and extracts module names and args for every task entry.
|
||||
|
||||
### (*Parser).ParseTasksIter
|
||||
`func (p *Parser) ParseTasksIter(path string) (iter.Seq[Task], error)`
|
||||
|
||||
Wrapper around `ParseTasks` that yields parsed tasks through an `iter.Seq`.
|
||||
|
||||
### (*Parser).ParseRole
|
||||
`func (p *Parser) ParseRole(name string, tasksFrom string) ([]Task, error)`
|
||||
|
||||
Resolves `roles/<name>/tasks/<tasksFrom>` across several search patterns rooted around `basePath`, defaults `tasksFrom` to `main.yml`, merges role defaults without overwriting existing parser vars, merges role vars with overwrite semantics, and then parses the resolved task file.
|
||||
|
||||
### (*RoleRef).UnmarshalYAML
|
||||
`func (r *RoleRef) UnmarshalYAML(unmarshal func(any) error) error`
|
||||
|
||||
Accepts either a scalar role name or a structured role mapping. When the mapping only sets `Name`, the method copies it into `Role`.
|
||||
|
||||
### (*Task).UnmarshalYAML
|
||||
`func (t *Task) UnmarshalYAML(node *yaml.Node) error`
|
||||
|
||||
Decodes the standard task fields, scans the remaining YAML keys for the first recognised module name, stores free-form arguments in `Args["_raw_params"]`, accepts module mappings and nil-valued modules, and maps `with_items` into `Loop` when `Loop` is unset.
|
||||
|
||||
### NormalizeModule
|
||||
`func NormalizeModule(name string) string`
|
||||
|
||||
Returns `ansible.builtin.<name>` for short module names and leaves dotted names unchanged.
|
||||
|
||||
### GetHosts
|
||||
`func GetHosts(inv *Inventory, pattern string) []string`
|
||||
|
||||
Resolves hosts from a non-nil inventory by handling `all`, `localhost`, group names, and explicit host names. Patterns containing `:` are recognised as future work and currently return `nil`.
|
||||
|
||||
### GetHostsIter
|
||||
`func GetHostsIter(inv *Inventory, pattern string) iter.Seq[string]`
|
||||
|
||||
Iterator wrapper around `GetHosts`.
|
||||
|
||||
### AllHostsIter
|
||||
`func AllHostsIter(group *InventoryGroup) iter.Seq[string]`
|
||||
|
||||
Yields every host reachable from a group tree in deterministic order by sorting host keys and child-group keys at each level.
|
||||
|
||||
### GetHostVars
|
||||
`func GetHostVars(inv *Inventory, hostname string) map[string]any`
|
||||
|
||||
Builds the effective variable map for `hostname` by walking the group tree, applying direct-group vars, host connection settings, inline host vars, and then parent-group vars for keys not already set by a nearer scope.
|
||||
|
||||
### NewExecutor
|
||||
`func NewExecutor(basePath string) *Executor`
|
||||
|
||||
Constructs an executor with a parser rooted at `basePath` and fresh maps for vars, facts, registered results, handlers, notifications, and SSH clients.
|
||||
|
||||
### (*Executor).SetInventory
|
||||
`func (e *Executor) SetInventory(path string) error`
|
||||
|
||||
Parses an inventory file through the embedded parser and stores the resulting `Inventory` on the executor.
|
||||
|
||||
### (*Executor).SetInventoryDirect
|
||||
`func (e *Executor) SetInventoryDirect(inv *Inventory)`
|
||||
|
||||
Stores a caller-supplied inventory pointer on the executor without parsing.
|
||||
|
||||
### (*Executor).SetVar
|
||||
`func (e *Executor) SetVar(key string, value any)`
|
||||
|
||||
Stores an executor-scoped variable under a write lock.
|
||||
|
||||
### (*Executor).Run
|
||||
`func (e *Executor) Run(ctx context.Context, playbookPath string) error`
|
||||
|
||||
Parses the playbook at `playbookPath` and runs plays sequentially. Each play resolves hosts, merges play vars, gathers facts by default, runs `PreTasks`, roles, `Tasks`, `PostTasks`, and finally any handlers that were notified during the play.
|
||||
|
||||
### (*Executor).Close
|
||||
`func (e *Executor) Close()`
|
||||
|
||||
Closes every cached `SSHClient` and replaces the client cache with a fresh empty map.
|
||||
|
||||
### (*Executor).TemplateFile
|
||||
`func (e *Executor) TemplateFile(src, host string, task *Task) (string, error)`
|
||||
|
||||
Reads a template file, performs a basic Jinja2-to-Go-template token conversion, and executes it against a context built from executor vars, host vars, and gathered facts. If parsing or execution fails, it falls back to the executor's simpler string-templating path.
|
||||
|
||||
### NewSSHClient
|
||||
`func NewSSHClient(cfg SSHConfig) (*SSHClient, error)`
|
||||
|
||||
Applies defaults for `Port`, `User`, and `Timeout`, then constructs an `SSHClient` from `cfg`.
|
||||
|
||||
### (*SSHClient).Connect
|
||||
`func (c *SSHClient) Connect(ctx context.Context) error`
|
||||
|
||||
Lazily establishes the SSH connection. Authentication is attempted in this order: explicit key file, default keys from `~/.ssh`, then password-based auth. The method also ensures `known_hosts` exists and uses it for host-key verification.
|
||||
|
||||
### (*SSHClient).Close
|
||||
`func (c *SSHClient) Close() error`
|
||||
|
||||
Closes the active SSH connection, if any, and clears the cached client pointer.
|
||||
|
||||
### (*SSHClient).Run
|
||||
`func (c *SSHClient) Run(ctx context.Context, cmd string) (stdout, stderr string, exitCode int, err error)`
|
||||
|
||||
Runs a command on the remote host, opening a new SSH session after calling `Connect`. When privilege escalation is enabled, the command is wrapped with `sudo`, using either the become password, the SSH password, or passwordless `sudo -n`. The method returns stdout, stderr, an exit code, and honours context cancellation by signalling the session.
|
||||
|
||||
### (*SSHClient).RunScript
|
||||
`func (c *SSHClient) RunScript(ctx context.Context, script string) (stdout, stderr string, exitCode int, err error)`
|
||||
|
||||
Wraps `script` in a heredoc passed to `bash` and delegates execution to `Run`.
|
||||
|
||||
### (*SSHClient).Upload
|
||||
`func (c *SSHClient) Upload(ctx context.Context, local io.Reader, remote string, mode fs.FileMode) error`
|
||||
|
||||
Reads all content from `local`, creates the remote parent directory, writes the file via `cat >`, applies the requested mode with `chmod`, and handles both normal and `sudo`-mediated uploads.
|
||||
|
||||
### (*SSHClient).Download
|
||||
`func (c *SSHClient) Download(ctx context.Context, remote string) ([]byte, error)`
|
||||
|
||||
Downloads a remote file by running `cat` and returning the captured bytes. A non-zero remote exit status is reported as an error.
|
||||
|
||||
### (*SSHClient).FileExists
|
||||
`func (c *SSHClient) FileExists(ctx context.Context, path string) (bool, error)`
|
||||
|
||||
Checks remote path existence with `test -e`.
|
||||
|
||||
### (*SSHClient).Stat
|
||||
`func (c *SSHClient) Stat(ctx context.Context, path string) (map[string]any, error)`
|
||||
|
||||
Returns a minimal stat map parsed from remote shell output. The current implementation reports boolean `exists` and `isdir` keys.
|
||||
|
||||
### (*SSHClient).SetBecome
|
||||
`func (c *SSHClient) SetBecome(become bool, user, password string)`
|
||||
|
||||
Updates the client's privilege-escalation flag and replaces the stored become user and password only when non-empty override values are supplied.
|
||||
Loading…
Add table
Reference in a new issue