Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,21 @@ Work on this branch is **3.0** (M1–M3 plus the follow-on issues below). Linux

- **ITSI search groups results**: `spa apps search itsi` in human mode groups hits into "Core ITSI" (1841), "Content packs (from Library 5391)", "Single content packs", and "Other apps". The library section shows the `content-packs list 5391` and `--content-pack NAME` commands, and each single pack shows its add command and that Core ITSI 1841 is added first when missing. Library 5391 is pinned for ITSI queries, so its row appears even when the page omits it. Agent output and non-ITSI searches are unchanged.

- **ITSI content pack help**: `spa apps search --help` now explains the ITSI path (`spa apps search itsi`, then `spa apps content-packs list 5391`, then `spa apps add 5391 --content-pack NAME`) and what each ITSI `--kind` means. The agent schema for `apps search` names the pack list and uses an ITSI example, and `apps content-packs list` says it lists ITSI content packs in Content Library 5391. Search rows still do not list packs inside 5391.

- **Apps ask for roles**: `/spa-apps` and the `/spa-create-config` apps phase ask with AskQuestion which roles a normal app goes to, even with one host and one role. ITSI (1841) and content packs do not ask. The create-config app table now shows the real `--roles` flag.

- **terraform.aws rejects unknown keys**: a misspelled key such as `ami` next to `ami_id` now fails validation instead of being ignored.
- **AWS discovery uses the environment region**: `spa aws` without `--region` searches `terraform.aws.region` from the environment config before `AWS_REGION`, `AWS_DEFAULT_REGION`, or `~/.aws/config`. The skills pass `--region` on every AMI and survey lookup.

- **Environment cleanup**: `spa environment cleanup` lists the registered environments whose directory is missing and removes only their registry entries after a yes (`--yes`, or a prompt on a terminal). It deletes no directories. With `--yes` it prints each entry it removed. A removed default moves to the first remaining environment.

- **Init needs a provider**: `spa init` and `spa environment init` require `--provider aws|virtualbox|external` unless a default is saved with `spa environment set --provider NAME`. With neither, init stops before it writes anything and names the three choices. Saving `aws` as the default now writes `providers.yml` (it used to delete the file), so an explicit `aws` counts as a choice. In agent mode, a failed init returns `ok` false and `error` only, with no `data`.

- **Hidden per-environment fact cache**: the Ansible fact cache for each environment moved from `$SPA_ENV_DIR/ansible_facts` to the hidden `$SPA_ENV_DIR/.ansible_facts`. An existing visible `ansible_facts` directory is left in place and is no longer read; the cache rebuilds on the next run.

- **Baseconfig check looks for `org_s2_indexer_indexes`**: the Software check (`spa validate`, deploy preflight, and the Ansible inventory check) now requires `*/org_s2_indexer_indexes` and `*/org_cluster_manager_base`. A Software directory that has only `org_ds_secure_server` now fails the check.

### Added

- **Skills pack** ([#67](https://github.com/splunk/splunk-platform-automator/issues/67)): three operator skills (`spa`, `spa-create-config`, `spa-apps`). Agents ask in chat and wait before provision, deploy, destroy, suspend, resume, and environment remove. `spa validate --splunk-config aws` checks that provider from the environment config. App-scope scenario steps live in `tests/README.md`.
Expand Down Expand Up @@ -79,7 +87,7 @@ Work on this branch is **3.0** (M1–M3 plus the follow-on issues below). Linux

### Changed

- **Per-environment Ansible fact cache**: `spa` sets `ANSIBLE_CACHE_PLUGIN_CONNECTION` to `$SPA_ENV_DIR/ansible_facts`, so two environments that reuse a hostname do not share facts. `/tmp/ansible_facts` remains the fallback when that variable is unset. `spa hosts check` and a successful `spa hosts register` drop that host's cached interpreter in the current environment before Ansible runs, so a previous machine's Python path is not reused. A missing remote interpreter is reported as a missing interpreter. Passwordless sudo is reported only when sudo itself failed.
- **Per-environment Ansible fact cache**: `spa` sets `ANSIBLE_CACHE_PLUGIN_CONNECTION` to `$SPA_ENV_DIR/.ansible_facts`, so two environments that reuse a hostname do not share facts. `/tmp/ansible_facts` remains the fallback when that variable is unset. `spa hosts check` and a successful `spa hosts register` drop that host's cached interpreter in the current environment before Ansible runs, so a previous machine's Python path is not reused. A missing remote interpreter is reported as a missing interpreter. Passwordless sudo is reported only when sudo itself failed.

- **Test venv installs the config editor YAML library**: `tests/requirements.txt` includes `ruamel.yaml`, so a fresh CI environment can import the config editor. The operator venv already installed it from `requirements.txt`.

Expand Down Expand Up @@ -129,7 +137,7 @@ Work on this branch is **3.0** (M1–M3 plus the follow-on issues below). Linux

- **`spa venv`**: `spa venv path` prints the target; `create`, `reinstall`, `upgrade`, and `rebuild` manage the shared `SPA_HOME/.venv` (default) or `--environment` venv and require `--yes`. `--upgrade` runs `pip install --upgrade -r requirements.txt` and `ansible-galaxy collection install --upgrade`. `--shared` / `--environment` ignore a stale exported `SPA_VENV_DIR`. Progress streams (`Creating virtual environment...`, `Installing packages...` / `Upgrading packages...`, `Installing Ansible collections...` / `Updating Ansible collections...`); pip/galaxy logs stay hidden unless the command fails or `spa -v venv` is used. Confirmation is local (`will change the Python environment for this framework`; `spa venv rebuild` deletes and recreates it). `bin/spa` re-execs into a venv that can import `yaml` / `pydantic`. Commands that need those packages fail with the state of each candidate and the matching `spa venv` repair (`create` / `reinstall` / `rebuild`); `spa venv`, `doctor`, `init`, and `environment` stay available without a complete venv. `PyYAML` and `boto3` are in `requirements.txt`.

- **Main `/spa` skill and environment registry** ([#54](https://github.com/splunk/splunk-platform-automator/issues/54)): `skills/spa/spa/` (`name: spa`). Software checklist in the [user guide](docs/user-guide.md#prepare-software) (employee baseconfig download: [https://go2.cisco.com/baseconfigs](https://go2.cisco.com/baseconfigs)). `spa environment` (alias `env`) `list` / `init` / `set` / `remove`; `spa init` aliases `environment init`. Default env parent `~/Splunk-Platform-Automator`; `spa environment set --env-dir` writes `paths.yml` `env_dir` only when non-default; `--software-dir` / `--baseconfig-dir` / `--apps-dir` write the same file for the shared installer, PS baseconfig, and local-apps trees. Init fills any still-unset shared path from its explicit options or discovered directories without replacing established globals. `spa environment set --default NAME` selects the registered fallback. One-off `init --env-dir PARENT --name NAME` (same as a dest path) does not persist the parent. `--name` is the registry key. `spa env init NAME --force` adopts an existing lab into the list. Default provider is aws (`providers.yml` only when set to virtualbox). `spa` resolves `--env`, cwd, or the registered default and applies its environment internally. `spa env --export` remains for external tools. `spa environment remove` deletes the local env dir (`--yes`; `--force` if it looks deployed) and does not call `spa destroy`. A registered path that no longer exists is shown as `(missing)` and is ignored as the default. Test runs isolate `XDG_CONFIG_HOME` so they never write the operator's `~/.config/spa/environments.yml`.
- **Main `/spa` skill and environment registry** ([#54](https://github.com/splunk/splunk-platform-automator/issues/54)): `skills/spa/spa/` (`name: spa`). Software checklist in the [user guide](docs/user-guide.md#prepare-software) (employee baseconfig download). `spa environment` (alias `env`) `list` / `init` / `set` / `remove`; `spa init` aliases `environment init`. Default env parent `~/Splunk-Platform-Automator`; `spa environment set --env-dir` writes `paths.yml` `env_dir` only when non-default; `--software-dir` / `--baseconfig-dir` / `--apps-dir` write the same file for the shared installer, PS baseconfig, and local-apps trees. Init fills any still-unset shared path from its explicit options or discovered directories without replacing established globals. `spa environment set --default NAME` selects the registered fallback. One-off `init --env-dir PARENT --name NAME` (same as a dest path) does not persist the parent. `--name` is the registry key. `spa env init NAME --force` adopts an existing lab into the list. Default provider is aws (`providers.yml` only when set to virtualbox). `spa` resolves `--env`, cwd, or the registered default and applies its environment internally. `spa env --export` remains for external tools. `spa environment remove` deletes the local env dir (`--yes`; `--force` if it looks deployed) and does not call `spa destroy`. A registered path that no longer exists is shown as `(missing)` and is ignored as the default. Test runs isolate `XDG_CONFIG_HOME` so they never write the operator's `~/.config/spa/environments.yml`.

- **Generated `docs/commands.md`**: `spa --no-agent agent schema --markdown` renders `COMMAND_SCHEMA` as a checked-in CLI catalog (not a second user guide). `--json` / agent mode still print the JSON envelope. Drift-tested against the committed file.

Expand Down
51 changes: 44 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,62 @@
![Python](https://img.shields.io/badge/Python-3.9%2B-blue.svg?logo=python&logoColor=white)
![Terraform](https://img.shields.io/badge/Terraform-1.3.0%2B-purple.svg?logo=terraform&logoColor=white)

SPA provisions and configures Splunk Enterprise—clustering, apps, AWS or VirtualBox—from **testing and training through staging and production**. One config file, one CLI: **`spa`**. The install follows Splunk best-practice config apps. There are many valid conf layouts; this is one automated path.
> **From architecture diagram to running Splunk cluster in less than an hour.**
> Splunk Platform Automator turns a single YAML file into a fully built,
> best-practice Splunk Enterprise environment: indexer clusters, multisite,
> search head clusters, forwarders, and the works. No hand-built hosts, no
> copy-pasting `.conf` files, no guessing at the bootstrap order.

SPA provisions and configures Splunk Enterprise—clustering, apps, AWS, VirtualBox, or existing hosts (external provider)—from **testing and training through staging and production**. One config file, one CLI: `spa`. The install follows Splunk best-practice config apps. There are many valid conf layouts; this is one automated path.

## Why SPA

Splunk Platform Automator is the deployment engine for the Splunk Enterprise
topologies you designed. Describe the environment once, then let SPA build it
the same way every time.

- **One file, the whole environment.** Describe your topology in
`splunk_config.yml` and let SPA handle the rest: hosts, cluster bootstrap,
and apps.
- **Ready-made topologies.** Examples cover single-node through multisite search
head clusters with Enterprise Security, so you start from a tested layout
instead of a blank page.
- **Your choice of infrastructure.** Provision on AWS with Terraform, spin up
local VirtualBox VMs, or deploy onto hosts you already have.
- **Best practices built in.** Base configuration apps, secrets from environment
lookups or Ansible Vault, and validation before anything is deployed.
- **Agent-ready.** `spa skills install cursor` links the `/spa`,
`/spa-create-config`, and `/spa-apps` skills into Cursor, so an agent can
design, validate, and deploy an environment with you, waiting for your yes at
each step.

## Support

**This framework is not officially supported by Splunk.** It is developed on a best-effort basis.

## Features

- Reproducible Splunk Enterprise: cluster manager, indexer clusters, deployer, search head clusters, deployment server, forwarders, license manager, monitoring console
- One YAML definition (`splunk_config.yml`); topology examples composed at `spa init`
- **Apps:** Splunkbase, local, or URL via `splunk_app_deployment` — [Apps](docs/apps.md)
- **Secrets:** environment lookups or Ansible Vault — [Secrets](docs/secrets.md)
- **AWS:** Terraform from the same config (`spa provision` / `destroy`)
- **VirtualBox:** local VMs through `spa` (Vagrant only as an implementation detail)
- **Multiple environments:** `spa environment list`, `init`, `set`, and `remove` keep each lab or deployment in its own directory, with a default you can change.
- **Guided config editing:** `spa config set|add|merge|topology|provider` and `spa apps add|remove` make schema-checked edits with dry-run support, so you don't hand-edit `splunk_config.yml`. `spa config search` and `spa config explain` look up any setting.
- **Preflight checks:** `spa validate` checks the config, inventory, and license pairings. `spa doctor` checks host tools. A missing environment variable stops the run before anything changes.
- **Lifecycle control:** `spa suspend` and `spa resume` stop and start instances to save cost, and `spa destroy` removes the environment. Changing commands require an explicit `--yes`.
- **Run logs:** provision, deploy, and run write a log under the environment's `logs/` folder. `spa logs` replays any run, and live progress shows each step as it happens.
- **Playbook catalog:** `spa run list` shows the shipped playbooks, including rolling upgrades for indexer and search head clusters, plus your own. `spa run NAME --help` describes each one.
- **Verification:** verification playbooks confirm that deployed apps match the config.
- **Splunkbase and ITSI discovery:** `spa apps search` finds apps, `spa apps snippet` generates the config entry, and `spa apps content-packs list 5391` lists ITSI content packs and the command to add each one.
- **Existing hosts:** `spa init --provider external` with `spa hosts register` manages machines you already run. SPA does not create, stop, or terminate them.
- **Host access:** `spa hosts list --status`, `spa hosts ssh`, and `spa hosts copy` work with the hosts in your environment.
- **Shell completion:** `spa completion bash` and `spa completion zsh` add tab completion for commands, flags, and config paths.
- **Sizing guidance:** the `/spa-create-config` skill maps Splunk Validated Architectures to topologies and sizes replication and search factors.
- **Platform coverage:** Splunk 9 and 10 on Amazon Linux 2023, RHEL 10, and Ubuntu 24.04, on amd64 or arm64, with optional FIPS mode.

## Install

Requires **Python 3.9+** with the `venv` module (`python3` on PATH). The installer creates a virtualenv and fails if that interpreter is missing or too old.

```sh
curl -fsSL https://github.com/splunk/splunk-platform-automator/releases/latest/download/install.sh | sh
spa skills install cursor
```

That installs the latest GitHub Release into `~/.local/share/spa` and puts `spa` on `PATH` via `~/.local/bin/spa`. Add `~/.local/bin` to `PATH` if `spa` is not found. Flags, uninstall, and clone/develop: [docs/install.md](docs/install.md). Put Splunk installers and PS baseconfig apps in a shared `Software/` directory ([Prepare Software](docs/user-guide.md#prepare-software)).
Expand All @@ -44,6 +79,8 @@ spa provision --yes && spa deploy --yes

VirtualBox: `--provider virtualbox` (for example `single_node`). Full narrative: [user guide](docs/user-guide.md).

Existing servers: `spa init --example TOPOLOGY --provider external ENV`, then `spa hosts register NAME --ssh-host HOST --user USER --key PATH --yes`.

## Docs

| Audience | Link |
Expand Down
2 changes: 1 addition & 1 deletion ansible.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ forks = 20
gathering = smart
fact_caching = jsonfile
# Fallback when spa has not set ANSIBLE_CACHE_PLUGIN_CONNECTION.
# spa points that variable at $SPA_ENV_DIR/ansible_facts.
# spa points that variable at $SPA_ENV_DIR/.ansible_facts.
fact_caching_connection = /tmp/ansible_facts
fact_caching_timeout = 86400

Expand Down
2 changes: 1 addition & 1 deletion ansible/group_vars/all/ansible.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Ansible runtime settings used by SPA playbooks (see also ansible.cfg).

# jsonfile fact cache. spa sets ANSIBLE_CACHE_PLUGIN_CONNECTION to
# $SPA_ENV_DIR/ansible_facts so two environments can reuse a hostname.
# $SPA_ENV_DIR/.ansible_facts so two environments can reuse a hostname.
# The /tmp path is only the ansible.cfg fallback when that variable is unset.
spa_ansible_fact_cache_dir: "{{ lookup('env', 'ANSIBLE_CACHE_PLUGIN_CONNECTION') | default('/tmp/ansible_facts', true) }}"

Expand Down
2 changes: 1 addition & 1 deletion ansible/plugins/inventory/splunk-platform-automator.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ def _populate(self):
splunk_baseconfig_dir = self._resolve_override_dir(
lab_dir, self.groups['all']['splunk_baseconfig_dir'], 'SPA_BASECONFIG_DIR'
)
check_base = glob.glob(os.path.join(splunk_baseconfig_dir, "*/org_ds_secure_server"))
check_base = glob.glob(os.path.join(splunk_baseconfig_dir, "*/org_s2_indexer_indexes"))
check_cluster = glob.glob(os.path.join(splunk_baseconfig_dir, "*/org_cluster_manager_base"))
if len(check_base) < 1 or len(check_cluster) < 1:
lab_sw = os.path.normpath(os.path.join(lab_dir, '..', 'Software'))
Expand Down
6 changes: 3 additions & 3 deletions docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -926,7 +926,7 @@ spa --agent apps search unix

## `apps search`

Search Splunkbase (compact rows: app_id, name, title, type, kind, version, summary)
Search Splunkbase (compact rows: app_id, name, title, type, kind, version, summary). An itsi query lists Core ITSI 1841 and Content Library 5391 first. ITSI content packs are not in search rows: list the packs in 5391 with spa apps content-packs list 5391.

| Flag | Description |
| --- | --- |
Expand All @@ -937,12 +937,12 @@ Search Splunkbase (compact rows: app_id, name, title, type, kind, version, summa
Example:

```bash
spa --agent apps search unix
spa --agent apps search itsi
```

## `apps content-packs list`

Inspect Content Library 5391 from --archive, apps_dir, an existing install archive, or cached pack app.conf files. An install archive is left in place. --version selects the release (default latest).
List ITSI content packs in Content Library 5391 from --archive, apps_dir, an existing install archive, or cached pack app.conf files. An install archive is left in place. --version selects the release (default latest).

| Flag | Description |
| --- | --- |
Expand Down
Loading
Loading