diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index f5ec281..5f451aa 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -36,7 +36,7 @@ convention: - Python >= 3.11; use modern syntax (PEP 604 unions, f-strings, `match` where appropriate). - Linter: `ruff` (line length 99, target py311). Run `ruff check python/`. - All new Python code should have type hints. -- Never hardcode credentials — use env vars, Ansible Vault, or Terraform `sensitive`. +- Never hardcode credentials - use env vars, Ansible Vault, or Terraform `sensitive`. - Ansible playbooks use `netapp.ontap` FQCNs with `use_rest: always`. - Terraform modules use the `NetApp/netapp-ontap` provider `~> 2.5`. - Every generated source file (`.py`, `.yml`, `.tf`, `.sh`, `.html`) MUST start @@ -59,17 +59,17 @@ Exempt files: Markdown, `requirements.*`, `ansible/inventory/*`, ## ONTAP API rules -- Use ONLY ONTAP REST APIs — no ZAPI, no CLI passthrough, no SSH. +- Use ONLY ONTAP REST APIs - no ZAPI, no CLI passthrough, no SSH. - Target ONTAP 9.8+ REST endpoints. - See `docs/ontap-api-patterns.md` for endpoints, auth, async job handling. ## Python conventions -- Import and use `python/ontap_client.py` — never build a new HTTP client. +- Import and use `python/ontap_client.py` - never build a new HTTP client. - Authenticate via `OntapClient.from_env()` (reads `ONTAP_HOST`, `ONTAP_PASS`). - Operational params via `argparse` with env-var fallbacks. - Async jobs: `client.poll_job(resp["job"]["uuid"])`. -- Logging via `logging` module — never `print()`. +- Logging via `logging` module - never `print()`. ## Ansible conventions diff --git a/.github/prompts/generate-ansible.prompt.md b/.github/prompts/generate-ansible.prompt.md index 2e6aff8..90e5db8 100644 --- a/.github/prompts/generate-ansible.prompt.md +++ b/.github/prompts/generate-ansible.prompt.md @@ -16,22 +16,22 @@ collection, which calls exclusively REST APIs. Use these repository files as the authoritative source for conventions: -- [ansible/nfs_provision.yml](../../ansible/nfs_provision.yml) — NFS reference implementation -- [ansible/cifs_provision.yml](../../ansible/cifs_provision.yml) — CIFS reference implementation -- [ansible/group_vars/ontap.yml.example](../../ansible/group_vars/ontap.yml.example) — variable defaults -- [ansible/inventory/hosts.yml](../../ansible/inventory/hosts.yml) — inventory structure -- [ansible/requirements.yml](../../ansible/requirements.yml) — collection version pin -- [docs/ontap-api-patterns.md](../../docs/ontap-api-patterns.md) — API endpoints, auth, async jobs -- [docs/example-template/ansible/example.yml](../../docs/example-template/ansible/example.yml) — skeleton -- [CONTRIBUTING.md](../../CONTRIBUTING.md) — naming, CI, quality bar +- [ansible/nfs_provision.yml](../../ansible/nfs_provision.yml) - NFS reference implementation +- [ansible/cifs_provision.yml](../../ansible/cifs_provision.yml) - CIFS reference implementation +- [ansible/group_vars/ontap.yml.example](../../ansible/group_vars/ontap.yml.example) - variable defaults +- [ansible/inventory/hosts.yml](../../ansible/inventory/hosts.yml) - inventory structure +- [ansible/requirements.yml](../../ansible/requirements.yml) - collection version pin +- [docs/ontap-api-patterns.md](../../docs/ontap-api-patterns.md) - API endpoints, auth, async jobs +- [docs/example-template/ansible/example.yml](../../docs/example-template/ansible/example.yml) - skeleton +- [CONTRIBUTING.md](../../CONTRIBUTING.md) - naming, CI, quality bar -## Step 1 — Clarify Inputs +## Step 1 - Clarify Inputs Before writing YAML, identify what information is missing and ask me. Common inputs: SVM name, volume name/size, aggregate, protocol details, cluster hostname, special options (snapshot policy, QoS, junction path). -## Step 2 — API Sequence +## Step 2 - API Sequence Even though Ansible modules abstract the API, list the underlying REST calls and map each to its `netapp.ontap` module: @@ -40,14 +40,14 @@ and map each to its `netapp.ontap` module: |---|---------------|--------|----------------|-----| Rules: -- REST only — `use_rest: always` on every ONTAP module. +- REST only - `use_rest: always` on every ONTAP module. - Target ONTAP 9.8+. - Fully-qualified collection names: `netapp.ontap.na_ontap_*`. - Collection version: `netapp.ontap >= 22.12.0`. Wait for my confirmation before generating the playbook. -## Step 3 — Generate Playbook +## Step 3 - Generate Playbook File: `ansible/.yml` (snake_case filename) @@ -55,7 +55,7 @@ File: `ansible/.yml` (snake_case filename) ```yaml --- -# .yml — Brief description. +# .yml - Brief description. # # Usage: # ansible-playbook -i inventory/hosts.yml .yml @@ -106,11 +106,11 @@ svm_name, volume_name, volume_size, volume_size_unit, aggregate_name, client_match (NFS), share_name (CIFS), etc. ``` -## Step 4 — Validate +## Step 4 - Validate After the playbook, provide: 1. Exact `ansible-playbook` command to run it. -2. Idempotency behavior — what happens on re-run for each task. +2. Idempotency behavior - what happens on re-run for each task. 3. Teardown playbook or reversal instructions. ## Copyright header (required) @@ -128,4 +128,4 @@ See the NOTICE file in the repo root for trademark and attribution details. Place after any shebang (`#!/usr/bin/env python3`), YAML directive (`---`), or `` line. Do **not** duplicate the full trademark text in -source files — it lives in [NOTICE](../../NOTICE) and the LICENSE appendix. +source files - it lives in [NOTICE](../../NOTICE) and the LICENSE appendix. diff --git a/.github/prompts/generate-python.prompt.md b/.github/prompts/generate-python.prompt.md index f44f849..bc0087c 100644 --- a/.github/prompts/generate-python.prompt.md +++ b/.github/prompts/generate-python.prompt.md @@ -15,19 +15,19 @@ The script automates a NetApp ONTAP storage task using exclusively REST APIs. Use these repository files as the authoritative source for conventions: -- [python/ontap_client.py](../../python/ontap_client.py) — shared REST client (MUST import and use this) -- [python/nfs_provision.py](../../python/nfs_provision.py) — reference implementation pattern -- [docs/ontap-api-patterns.md](../../docs/ontap-api-patterns.md) — API endpoints, auth, async jobs -- [docs/example-template/python/example.py](../../docs/example-template/python/example.py) — skeleton to start from -- [CONTRIBUTING.md](../../CONTRIBUTING.md) — naming, CI, quality bar +- [python/ontap_client.py](../../python/ontap_client.py) - shared REST client (MUST import and use this) +- [python/nfs_provision.py](../../python/nfs_provision.py) - reference implementation pattern +- [docs/ontap-api-patterns.md](../../docs/ontap-api-patterns.md) - API endpoints, auth, async jobs +- [docs/example-template/python/example.py](../../docs/example-template/python/example.py) - skeleton to start from +- [CONTRIBUTING.md](../../CONTRIBUTING.md) - naming, CI, quality bar -## Step 1 — Clarify Inputs +## Step 1 - Clarify Inputs Before writing code, identify what information is missing and ask me. Common inputs: SVM name, volume name/size, aggregate, protocol details, cluster hostname, special options (snapshot policy, QoS, junction path). -## Step 2 — API Sequence +## Step 2 - API Sequence List the ONTAP REST API calls in execution order: @@ -35,14 +35,14 @@ List the ONTAP REST API calls in execution order: |---|--------|----------|-----------------------|------------|-----| Rules: -- ONTAP REST only — no ZAPI, no CLI passthrough, no SSH. +- ONTAP REST only - no ZAPI, no CLI passthrough, no SSH. - Target ONTAP 9.8+ endpoints. - Full endpoint paths (e.g. `/api/storage/volumes`). - For async calls, include the poll step: `GET /api/cluster/jobs/{uuid}`. Wait for my confirmation before generating code. -## Step 3 — Generate Python Script +## Step 3 - Generate Python Script File: `python/.py` (snake_case filename) @@ -72,7 +72,7 @@ File: `python/.py` (snake_case filename) ``` - Async job polling: `client.poll_job(resp["job"]["uuid"])` - Logging: `logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)-8s %(message)s")` - - `logger = logging.getLogger(__name__)` — never use `print()`. + - `logger = logging.getLogger(__name__)` - never use `print()`. - Entry point: ```python if __name__ == "__main__": @@ -86,7 +86,7 @@ File: `python/.py` (snake_case filename) ``` - Type hints on all functions. No hardcoded credentials. -## Step 4 — Validate +## Step 4 - Validate After the code, provide: 1. Exact shell commands to run the script. @@ -108,4 +108,4 @@ See the NOTICE file in the repo root for trademark and attribution details. Place after any shebang (`#!/usr/bin/env python3`), YAML directive (`---`), or `` line. Do **not** duplicate the full trademark text in -source files — it lives in [NOTICE](../../NOTICE) and the LICENSE appendix. +source files - it lives in [NOTICE](../../NOTICE) and the LICENSE appendix. diff --git a/.github/prompts/generate-terraform.prompt.md b/.github/prompts/generate-terraform.prompt.md index 11f8ea6..7416b71 100644 --- a/.github/prompts/generate-terraform.prompt.md +++ b/.github/prompts/generate-terraform.prompt.md @@ -16,21 +16,21 @@ provider, which calls exclusively REST APIs. Use these repository files as the authoritative source for conventions: -- [terraform/nfs-provision/main.tf](../../terraform/nfs-provision/main.tf) — reference implementation -- [terraform/nfs-provision/variables.tf](../../terraform/nfs-provision/variables.tf) — variable patterns -- [terraform/nfs-provision/outputs.tf](../../terraform/nfs-provision/outputs.tf) — output patterns -- [terraform/nfs-provision/terraform.tfvars.example](../../terraform/nfs-provision/terraform.tfvars.example) — tfvars template -- [docs/example-template/terraform/](../../docs/example-template/terraform/) — skeleton files -- [docs/ontap-api-patterns.md](../../docs/ontap-api-patterns.md) — API endpoints and conventions -- [CONTRIBUTING.md](../../CONTRIBUTING.md) — naming, CI, quality bar +- [terraform/nfs-provision/main.tf](../../terraform/nfs-provision/main.tf) - reference implementation +- [terraform/nfs-provision/variables.tf](../../terraform/nfs-provision/variables.tf) - variable patterns +- [terraform/nfs-provision/outputs.tf](../../terraform/nfs-provision/outputs.tf) - output patterns +- [terraform/nfs-provision/terraform.tfvars.example](../../terraform/nfs-provision/terraform.tfvars.example) - tfvars template +- [docs/example-template/terraform/](../../docs/example-template/terraform/) - skeleton files +- [docs/ontap-api-patterns.md](../../docs/ontap-api-patterns.md) - API endpoints and conventions +- [CONTRIBUTING.md](../../CONTRIBUTING.md) - naming, CI, quality bar -## Step 1 — Clarify Inputs +## Step 1 - Clarify Inputs Before writing HCL, identify what information is missing and ask me. Common inputs: SVM name, volume name/size, aggregate, protocol details, cluster hostname, special options (snapshot policy, QoS, junction path). -## Step 2 — API Sequence & Resource Mapping +## Step 2 - API Sequence & Resource Mapping List the REST API calls the provider makes and map each to a Terraform resource or data source: @@ -47,7 +47,7 @@ Rules: Wait for my confirmation before generating HCL. -## Step 3 — Generate Module +## Step 3 - Generate Module Directory: `terraform//` (kebab-case directory name) @@ -56,7 +56,7 @@ Create four files: ### main.tf ```hcl -# — Brief description. +# - Brief description. terraform { required_version = ">= 1.4" @@ -101,7 +101,7 @@ provider "netapp-ontap" { - Placeholder values with comments. Never include real credentials. -## Step 4 — Validate +## Step 4 - Validate After the module, provide: 1. Exact commands: `terraform init`, `terraform plan`, `terraform apply`. @@ -123,4 +123,4 @@ See the NOTICE file in the repo root for trademark and attribution details. Place after any shebang (`#!/usr/bin/env python3`), YAML directive (`---`), or `` line. Do **not** duplicate the full trademark text in -source files — it lives in [NOTICE](../../NOTICE) and the LICENSE appendix. +source files - it lives in [NOTICE](../../NOTICE) and the LICENSE appendix. diff --git a/.github/prompts/generate-workflow.prompt.md b/.github/prompts/generate-workflow.prompt.md index 5a09f44..c44618e 100644 --- a/.github/prompts/generate-workflow.prompt.md +++ b/.github/prompts/generate-workflow.prompt.md @@ -1,5 +1,5 @@ --- -description: "Generate a complete ONTAP workflow — Python + Ansible + Terraform — for a storage task" +description: "Generate a complete ONTAP workflow - Python + Ansible + Terraform - for a storage task" --- # Generate Complete ONTAP Workflow (All Three Tools) @@ -14,16 +14,16 @@ implementations so users can compare side-by-side. ## Reference Files -- [python/ontap_client.py](../../python/ontap_client.py) — shared Python REST client -- [python/nfs_provision.py](../../python/nfs_provision.py) — Python reference -- [ansible/nfs_provision.yml](../../ansible/nfs_provision.yml) — Ansible reference -- [ansible/cifs_provision.yml](../../ansible/cifs_provision.yml) — Ansible CIFS reference -- [terraform/nfs-provision/](../../terraform/nfs-provision/) — Terraform reference -- [docs/ontap-api-patterns.md](../../docs/ontap-api-patterns.md) — API endpoints, auth, async jobs -- [docs/example-template/](../../docs/example-template/) — skeleton files for all tools -- [CONTRIBUTING.md](../../CONTRIBUTING.md) — naming, CI, quality bar +- [python/ontap_client.py](../../python/ontap_client.py) - shared Python REST client +- [python/nfs_provision.py](../../python/nfs_provision.py) - Python reference +- [ansible/nfs_provision.yml](../../ansible/nfs_provision.yml) - Ansible reference +- [ansible/cifs_provision.yml](../../ansible/cifs_provision.yml) - Ansible CIFS reference +- [terraform/nfs-provision/](../../terraform/nfs-provision/) - Terraform reference +- [docs/ontap-api-patterns.md](../../docs/ontap-api-patterns.md) - API endpoints, auth, async jobs +- [docs/example-template/](../../docs/example-template/) - skeleton files for all tools +- [CONTRIBUTING.md](../../CONTRIBUTING.md) - naming, CI, quality bar -## Phase 1 — Clarify Inputs +## Phase 1 - Clarify Inputs Before generating any code, ask me for anything missing: - SVM name, volume name/size, aggregate @@ -32,7 +32,7 @@ Before generating any code, ask me for anything missing: - Authentication approach - Non-default options (snapshot policy, tiering, QoS, junction path) -## Phase 2 — API Sequence +## Phase 2 - API Sequence Present a numbered list of ONTAP REST API calls in execution order. For each: @@ -41,16 +41,16 @@ For each: |---|--------|----------|----------------|------------|-----| Rules: -- ONTAP REST only — no ZAPI, no CLI passthrough, no SSH. +- ONTAP REST only - no ZAPI, no CLI passthrough, no SSH. - Target ONTAP 9.8+ endpoints. - Full paths (e.g. `/api/storage/volumes`). - Include poll steps for async calls. **Wait for my approval before Phase 3.** -## Phase 3 — Generate All Three Implementations +## Phase 3 - Generate All Three Implementations -### 3A. Python — `python/.py` +### 3A. Python - `python/.py` - `#!/usr/bin/env python3`, `from __future__ import annotations` - Module docstring: steps, prerequisites, usage with CLI flags. @@ -62,7 +62,7 @@ Rules: - `if __name__ == "__main__":` with try/except guard. - Type hints throughout. No hardcoded credentials. -### 3B. Ansible — `ansible/.yml` +### 3B. Ansible - `ansible/.yml` - `---` header with filename, description, usage comment. - `hosts: ontap`, `gather_facts: false`, `connection: local`. @@ -72,7 +72,7 @@ Rules: - `vars:` for operational defaults (overridable with `-e`). - Final `ansible.builtin.debug` summary. No hardcoded credentials. -### 3C. Terraform — `terraform//` +### 3C. Terraform - `terraform//` - `main.tf`: `required_version >= 1.4`, provider `NetApp/netapp-ontap ~> 2.5`, `connection_profiles` with `cx_profile_name = "cluster1"`. @@ -81,7 +81,7 @@ Rules: - `terraform.tfvars.example`: placeholder values, no real credentials. - `depends_on` where ordering matters. -## Phase 4 — Validate +## Phase 4 - Validate For each implementation: 1. Exact commands to run it. @@ -103,4 +103,4 @@ See the NOTICE file in the repo root for trademark and attribution details. Place after any shebang (`#!/usr/bin/env python3`), YAML directive (`---`), or `` line. Do **not** duplicate the full trademark text in -source files — it lives in [NOTICE](../../NOTICE) and the LICENSE appendix. +source files - it lives in [NOTICE](../../NOTICE) and the LICENSE appendix. diff --git a/.github/prompts/plan-api-sequence.prompt.md b/.github/prompts/plan-api-sequence.prompt.md index ce48b1e..e53136b 100644 --- a/.github/prompts/plan-api-sequence.prompt.md +++ b/.github/prompts/plan-api-sequence.prompt.md @@ -5,7 +5,7 @@ description: "Design the ONTAP REST API call sequence for a storage operation be # Plan ONTAP REST API Sequence You are an ONTAP REST API specialist. Design the exact sequence of API calls -for a storage operation — **no code yet**, just the API plan. +for a storage operation - **no code yet**, just the API plan. ## Task @@ -13,7 +13,7 @@ for a storage operation — **no code yet**, just the API plan. ## Reference -- [docs/ontap-api-patterns.md](../../docs/ontap-api-patterns.md) — endpoints, auth, query params, async jobs +- [docs/ontap-api-patterns.md](../../docs/ontap-api-patterns.md) - endpoints, auth, query params, async jobs - ONTAP REST API docs: https://docs.netapp.com/us-en/ontap-restapi/swagger-ui/index.html ## Output Format @@ -22,11 +22,11 @@ For each API call, fill in this table: | # | Method | Endpoint | Key Body / Query Params | Sync/Async | Idempotent? | Why | |---|--------|----------|-------------------------|------------|-------------|-----| -| 1 | GET | /api/svm/svms?name=vs0&fields=uuid | — | Sync | Yes | Resolve SVM UUID | +| 1 | GET | /api/svm/svms?name=vs0&fields=uuid | - | Sync | Yes | Resolve SVM UUID | ## Rules -1. **REST only** — no ZAPI, no CLI passthrough, no SSH. +1. **REST only** - no ZAPI, no CLI passthrough, no SSH. 2. **ONTAP 9.8+** target minimum. 3. Full endpoint paths (e.g. `/api/storage/volumes`, not just "volumes"). 4. For POST/PATCH returning a job, include the poll step: diff --git a/.github/prompts/review-contribution.prompt.md b/.github/prompts/review-contribution.prompt.md index bf19591..81b74b6 100644 --- a/.github/prompts/review-contribution.prompt.md +++ b/.github/prompts/review-contribution.prompt.md @@ -14,12 +14,12 @@ I provide and prepare it for a pull request. ## Reference Files -- [CONTRIBUTING.md](../../CONTRIBUTING.md) — full contribution guide -- [docs/ontap-api-patterns.md](../../docs/ontap-api-patterns.md) — API conventions -- [python/ontap_client.py](../../python/ontap_client.py) — shared client -- [python/nfs_provision.py](../../python/nfs_provision.py) — Python reference -- [ansible/nfs_provision.yml](../../ansible/nfs_provision.yml) — Ansible reference -- [terraform/nfs-provision/](../../terraform/nfs-provision/) — Terraform reference +- [CONTRIBUTING.md](../../CONTRIBUTING.md) - full contribution guide +- [docs/ontap-api-patterns.md](../../docs/ontap-api-patterns.md) - API conventions +- [python/ontap_client.py](../../python/ontap_client.py) - shared client +- [python/nfs_provision.py](../../python/nfs_provision.py) - Python reference +- [ansible/nfs_provision.yml](../../ansible/nfs_provision.yml) - Ansible reference +- [terraform/nfs-provision/](../../terraform/nfs-provision/) - Terraform reference ## 1. Naming & File Structure @@ -74,9 +74,9 @@ I provide and prepare it for a pull request. ## 4. Documentation Updates Generate README update snippets for each tool's README: -- `python/README.md` — new section with description + run instructions -- `ansible/README.md` — new section with description + run instructions -- `terraform/README.md` — new section with description + run instructions +- `python/README.md` - new section with description + run instructions +- `ansible/README.md` - new section with description + run instructions +- `terraform/README.md` - new section with description + run instructions ## 5. Commit Message diff --git a/CHANGELOG.md b/CHANGELOG.md index 517d6b6..be935d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- TruffleHog flag mismatch: pre-commit used `--fail` but CI did not — both now use `--only-verified --fail` +- TruffleHog flag mismatch: pre-commit used `--fail` but CI did not - both now use `--only-verified --fail` [Unreleased]: https://github.com/NetApp/pace/commits/main diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 150bced..a876e7a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -43,18 +43,18 @@ Each new use case should be implemented across all three tools where practical. Use `docs/example-template/` as a starting point. **Python** (`python/`): -- `.py` — self-contained script +- `.py` - self-contained script - Update `python/README.md` with a section for the new example **Ansible** (`ansible/`): -- `.yml` — playbook using `netapp.ontap` FQCNs +- `.yml` - playbook using `netapp.ontap` FQCNs - Update `ansible/README.md` with a section for the new example **Terraform** (`terraform/`): -- `/main.tf` — provider + resources -- `/variables.tf` — input variables with descriptions -- `/outputs.tf` — useful output values -- `/terraform.tfvars.example` — variable template +- `/main.tf` - provider + resources +- `/variables.tf` - input variables with descriptions +- `/outputs.tf` - useful output values +- `/terraform.tfvars.example` - variable template - Update `terraform/README.md` with a section for the new example ### Quality bar @@ -62,7 +62,7 @@ Use `docs/example-template/` as a starting point. Every example must: - Be self-contained (copy one directory and it works) -- Never hardcode credentials — use env vars, Ansible Vault, or Terraform `sensitive` +- Never hardcode credentials - use env vars, Ansible Vault, or Terraform `sensitive` - Include clear run instructions in the parent README - Pass CI lint checks (see below) - Follow the conventions of the target tool (idiomatic Python, Ansible FQCNs, HCL style) @@ -85,16 +85,16 @@ The `insert-license` pre-commit hook (configured in [.pre-commit-config.yaml](.pre-commit-config.yaml)) inserts and verifies the header automatically; CI rejects PRs that drop it. Exempt files: Markdown, `requirements.*`, `ansible/inventory/*`, `ansible/group_vars/*`, `*.example`, -and `dependabot.yml` — all covered by the root [NOTICE](NOTICE). +and `dependabot.yml` - all covered by the root [NOTICE](NOTICE). > **Testing:** Every PR that touches `python/`, `ansible/`, or `terraform/` -> must include a populated **Test Report** in the PR body — see +> must include a populated **Test Report** in the PR body - see > [TESTING.md](TESTING.md) for what to capture (environment, ONTAP > version, first-run output, idempotency / re-run check, teardown). A > soft-gate workflow applies a `needs-test-report` label until the > section is filled in. > -> CI continues to validate lint, format, syntax, and secrets only — the +> CI continues to validate lint, format, syntax, and secrets only - the > end-to-end run evidence is contributor-supplied. ### ONTAP API reference @@ -124,7 +124,7 @@ Optional (only needed for example validation): | **tflint** | any | Terraform linting | [github.com/terraform-linters/tflint](https://github.com/terraform-linters/tflint) | `make install` automatically creates a `.venv/` and installs **ruff** -inside it — you do not need to install it manually. +inside it - you do not need to install it manually. ### First-time setup @@ -155,7 +155,7 @@ The workspace `.vscode/settings.json` configures: - **Terraform format-on-save** via the Terraform extension - **Python interpreter** pointed at `.venv/bin/python` (from `make install`) -No manual formatter configuration needed — just save the file and it formats. +No manual formatter configuration needed - just save the file and it formats. ### Running checks locally @@ -188,7 +188,7 @@ docker compose run --rm dev bash ``` The container includes Python 3.11, Ruff, pre-commit, Ansible, ansible-lint, -Terraform, and tflint — everything CI expects. +Terraform, and tflint - everything CI expects. ### Pre-commit hooks @@ -219,7 +219,7 @@ PRs are validated by GitHub Actions workflows: | **Terraform lint** | `validate-examples.yml` | `terraform/**` changes | `terraform fmt -check`, `terraform validate`, `tflint` | | **Test Report check** | `test-report-check.yml` | PRs only | Soft gate: labels PR `needs-test-report` if the body's Test Report section is unfilled (see [TESTING.md](TESTING.md)) | -All checks except the Test Report check are **hard gates** — PRs must +All checks except the Test Report check are **hard gates** - PRs must pass them before merge. The Test Report check is informational and reviewer-enforced. diff --git a/README.md b/README.md index d2d18c3..339b45d 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ --- Pace is an open-source library of ready-to-run **NetApp ONTAP** automation -examples, implemented three ways — side by side — so you can pick the +examples, implemented three ways - side by side - so you can pick the style your team already uses. | Style | Tool | In a sentence | @@ -27,7 +27,7 @@ style your team already uses. | **Declarative playbooks** | Ansible | You describe the outcome. | | **Stateful blueprints** | Terraform | The tool tracks every change. | -Same task, same outcome — different trade-offs in readability, idempotency, +Same task, same outcome - different trade-offs in readability, idempotency, and lifecycle management. > Visit **[netapp.github.io/pace](https://netapp.github.io/pace/)** for the @@ -38,10 +38,10 @@ and lifecycle management. ## Quick start Pick a style and run the matching block. All examples use placeholder host -names and credentials — swap them for your own before running. +names and credentials - swap them for your own before running.
-Imperative scripts — Python +Imperative scripts - Python ```bash cd python @@ -53,7 +53,7 @@ python cluster_info.py
-Declarative playbooks — Ansible +Declarative playbooks - Ansible ```bash cd ansible @@ -65,7 +65,7 @@ ansible-playbook -i inventory/hosts.yml cluster_info.yml
-Stateful blueprints — Terraform +Stateful blueprints - Terraform ```bash cd terraform/cluster-info @@ -87,7 +87,7 @@ and example output. - Network access to the cluster management LIF Credentials are never hardcoded. Each style uses its native secret -mechanism — environment variables, Ansible Vault, or Terraform `sensitive` +mechanism - environment variables, Ansible Vault, or Terraform `sensitive` variables.
diff --git a/SUPPORT.md b/SUPPORT.md index 29f1e53..8599677 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -20,13 +20,13 @@ We recommend always running the latest version. We use GitHub for tracking bugs and feature requests. -- **Bug reports** — [open an issue](https://github.com/NetApp/pace/issues/new?template=bug_report.md) -- **Feature requests** — [open an issue](https://github.com/NetApp/pace/issues/new?template=feature_request.md) -- **Questions and discussion** — [GitHub Discussions](https://github.com/NetApp/pace/discussions) +- **Bug reports** - [open an issue](https://github.com/NetApp/pace/issues/new?template=bug_report.md) +- **Feature requests** - [open an issue](https://github.com/NetApp/pace/issues/new?template=feature_request.md) +- **Questions and discussion** - [GitHub Discussions](https://github.com/NetApp/pace/discussions) ## Documentation -* [README](README.md) — project overview and quick start -* [Contributing](CONTRIBUTING.md) — how to add examples and what CI expects -* [ONTAP API Patterns](docs/ontap-api-patterns.md) — REST endpoint conventions -* [Troubleshooting](docs/troubleshooting.md) — common errors and how to fix them +* [README](README.md) - project overview and quick start +* [Contributing](CONTRIBUTING.md) - how to add examples and what CI expects +* [ONTAP API Patterns](docs/ontap-api-patterns.md) - REST endpoint conventions +* [Troubleshooting](docs/troubleshooting.md) - common errors and how to fix them diff --git a/TESTING.md b/TESTING.md index a03d1c8..fff4e27 100644 --- a/TESTING.md +++ b/TESTING.md @@ -53,7 +53,7 @@ Pick the style(s) your PR touches and capture the matching evidence. ### Python (`python/`) -1. **First run** — execute the script with realistic args: +1. **First run** - execute the script with realistic args: ```bash python