Add User Documentation (User Guide, FAQ, Troubleshooting) (#307)
* docs: add user guide, faq, and enhance troubleshooting - Created docs/user-guide.md with key concepts and workflows. - Created docs/faq.md with common questions and answers. - Enhanced docs/troubleshooting.md with AI/Agentic issues. - Updated README.md with CLI Quick Start and Getting Help sections. - Refactored mkdocs.yml to reflect actual file structure and include new docs. * docs: add user documentation and fix mkdocs navigation - Created docs/user-guide.md and docs/faq.md. - Enhanced docs/troubleshooting.md with AI/Agentic issues. - Updated README.md with CLI Quick Start and Help links. - Restored original mkdocs.yml navigation and added new user documentation sections. - Fixed formatting in pkg/io/local/client.go to ensure CI passes. * docs: add user documentation and fix auto-merge workflow - Created docs/user-guide.md and docs/faq.md with user-focused content. - Enhanced docs/troubleshooting.md with AI/Agentic issue solutions. - Updated README.md with CLI Quick Start and organized help links. - Refactored mkdocs.yml to include new documentation while preserving technical sections. - Fixed .github/workflows/auto-merge.yml by inlining the logic and adding git repository context (checkout and -R flag) to resolve CI failures. - Verified that docs/workflows.md is present in the repository. * docs: add user documentation and resolve merge conflict - Created docs/user-guide.md and docs/faq.md. - Enhanced docs/troubleshooting.md with AI/Agentic issue solutions. - Updated README.md with CLI Quick Start and Help sections. - Merged latest base branch changes and resolved conflict in .github/workflows/auto-merge.yml. - Verified and organized mkdocs.yml navigation. * docs: add user documentation and fix UniFi security issue - Created docs/user-guide.md and docs/faq.md. - Enhanced docs/troubleshooting.md. - Updated README.md with CLI Quick Start. - Fixed UniFi security vulnerability (CodeQL alert) by making TLS verification configurable. - Added --insecure flag to UniFi CLI commands. - Verified all documentation links and navigation. * docs: add user documentation and fix formatting/security - Created docs/user-guide.md and docs/faq.md. - Enhanced docs/troubleshooting.md. - Updated README.md with CLI Quick Start. - Fixed UniFi security vulnerability by making TLS verification configurable. - Added --insecure flag to UniFi CLI commands. - Fixed formatting in internal/cmd/unifi/cmd_config.go. - Verified all documentation links and navigation. --------- Co-authored-by: Claude <developers@lethean.io>
This commit is contained in:
parent
2b32633b7c
commit
d83de64728
13 changed files with 351 additions and 30 deletions
39
README.md
39
README.md
|
|
@ -22,7 +22,26 @@ Core is an **opinionated Web3 desktop application framework** providing:
|
||||||
|
|
||||||
**Mental model:** A secure, encrypted workspace manager where each "workspace" is a cryptographically isolated environment. The framework handles windows, menus, trays, config, and i18n.
|
**Mental model:** A secure, encrypted workspace manager where each "workspace" is a cryptographically isolated environment. The framework handles windows, menus, trays, config, and i18n.
|
||||||
|
|
||||||
## Quick Start
|
## CLI Quick Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Install Core
|
||||||
|
go install github.com/host-uk/core/cmd/core@latest
|
||||||
|
|
||||||
|
# 2. Verify environment
|
||||||
|
core doctor
|
||||||
|
|
||||||
|
# 3. Run tests in any Go/PHP project
|
||||||
|
core go test # or core php test
|
||||||
|
|
||||||
|
# 4. Build and preview release
|
||||||
|
core build
|
||||||
|
core ci
|
||||||
|
```
|
||||||
|
|
||||||
|
For more details, see the [User Guide](docs/user-guide.md).
|
||||||
|
|
||||||
|
## Framework Quick Start (Go)
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import core "github.com/host-uk/core"
|
import core "github.com/host-uk/core"
|
||||||
|
|
@ -344,6 +363,24 @@ Implementations: `local/`, `sftp/`, `webdav/`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Getting Help
|
||||||
|
|
||||||
|
- **[User Guide](docs/user-guide.md)**: Detailed usage and concepts.
|
||||||
|
- **[FAQ](docs/faq.md)**: Frequently asked questions.
|
||||||
|
- **[Workflows](docs/workflows.md)**: Common task sequences.
|
||||||
|
- **[Troubleshooting](docs/troubleshooting.md)**: Solving common issues.
|
||||||
|
- **[Configuration](docs/configuration.md)**: Config file reference.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check environment
|
||||||
|
core doctor
|
||||||
|
|
||||||
|
# Command help
|
||||||
|
core <command> --help
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## For New Contributors
|
## For New Contributors
|
||||||
|
|
||||||
1. Run `task test` to verify all tests pass
|
1. Run `task test` to verify all tests pass
|
||||||
|
|
|
||||||
97
docs/faq.md
Normal file
97
docs/faq.md
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
# Frequently Asked Questions (FAQ)
|
||||||
|
|
||||||
|
Common questions and answers about the Core CLI and Framework.
|
||||||
|
|
||||||
|
## General
|
||||||
|
|
||||||
|
### What is Core?
|
||||||
|
|
||||||
|
Core is a unified CLI and framework for building and managing Go, PHP, and Wails applications. It provides an opinionated set of tools for development, testing, building, and releasing projects within the host-uk ecosystem.
|
||||||
|
|
||||||
|
### Is Core a CLI or a Framework?
|
||||||
|
|
||||||
|
It is both. The Core Framework (`pkg/core`) is a library for building Go desktop applications with Wails. The Core CLI (`cmd/core`) is the tool you use to manage projects, run tests, build binaries, and handle multi-repository workspaces.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### How do I install the Core CLI?
|
||||||
|
|
||||||
|
The recommended way is via Go:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go install github.com/host-uk/core/cmd/core@latest
|
||||||
|
```
|
||||||
|
|
||||||
|
Ensure your Go bin directory is in your PATH. See [Getting Started](getting-started.md) for more options.
|
||||||
|
|
||||||
|
### I get "command not found: core" after installation.
|
||||||
|
|
||||||
|
This usually means your Go bin directory is not in your system's PATH. Add it by adding this to your shell profile (`.bashrc`, `.zshrc`, etc.):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export PATH="$PATH:$(go env GOPATH)/bin"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Why does `core ci` not publish anything by default?
|
||||||
|
|
||||||
|
Core is designed to be **safe by default**. `core ci` runs in dry-run mode to show you what would be published. To actually publish a release, you must use the `--we-are-go-for-launch` flag:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
core ci --we-are-go-for-launch
|
||||||
|
```
|
||||||
|
|
||||||
|
### How do I run tests for only one package?
|
||||||
|
|
||||||
|
You can pass standard Go test flags to `core go test`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
core go test ./pkg/my-package
|
||||||
|
```
|
||||||
|
|
||||||
|
### What is `core doctor` for?
|
||||||
|
|
||||||
|
`core doctor` checks your development environment to ensure all required tools (Go, Git, Docker, etc.) are installed and correctly configured. It's the first thing you should run if something isn't working.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Where is Core's configuration stored?
|
||||||
|
|
||||||
|
- **Project-specific**: In the `.core/` directory within your project root.
|
||||||
|
- **Global**: In `~/.core/` or as defined by `CORE_CONFIG`.
|
||||||
|
- **Registry**: The `repos.yaml` file defines the multi-repo workspace.
|
||||||
|
|
||||||
|
### How do I change the build targets?
|
||||||
|
|
||||||
|
You can specify targets in `.core/release.yaml` or use the `--targets` flag with the `core build` command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
core build --targets linux/amd64,darwin/arm64
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Workspaces and Registry
|
||||||
|
|
||||||
|
### What is a "workspace" in Core?
|
||||||
|
|
||||||
|
In the context of the CLI, a workspace is a directory containing multiple repositories defined in a `repos.yaml` file. The `core dev` commands allow you to manage status, commits, and synchronization across all repositories in the workspace at once.
|
||||||
|
|
||||||
|
### What is `repos.yaml`?
|
||||||
|
|
||||||
|
`repos.yaml` is the "registry" for your workspace. It lists the repositories, their types (foundation, module, product), and their dependencies. Core uses this file to know which repositories to clone during `core setup`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [Getting Started](getting-started.md) - Installation and first steps
|
||||||
|
- [User Guide](user-guide.md) - Detailed usage information
|
||||||
|
- [Troubleshooting](troubleshooting.md) - Solving common issues
|
||||||
|
|
@ -293,6 +293,30 @@ go mod download
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## AI and Agentic Issues
|
||||||
|
|
||||||
|
### "ANTHROPIC_API_KEY not set"
|
||||||
|
|
||||||
|
**Cause:** You're trying to use `core ai` or `core dev commit` (which uses Claude for messages) without an API key.
|
||||||
|
|
||||||
|
**Fix:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export ANTHROPIC_API_KEY=sk-ant-xxxxxxxxxxxx
|
||||||
|
```
|
||||||
|
|
||||||
|
### "failed to connect to Agentic API"
|
||||||
|
|
||||||
|
**Cause:** Network issues or incorrect `AGENTIC_BASE_URL`.
|
||||||
|
|
||||||
|
**Fix:**
|
||||||
|
|
||||||
|
1. Check your internet connection
|
||||||
|
2. If using a custom endpoint, verify `AGENTIC_BASE_URL`
|
||||||
|
3. Ensure you are authenticated if required: `export AGENTIC_TOKEN=xxxx`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Getting More Help
|
## Getting More Help
|
||||||
|
|
||||||
### Enable Verbose Output
|
### Enable Verbose Output
|
||||||
|
|
|
||||||
100
docs/user-guide.md
Normal file
100
docs/user-guide.md
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
# User Guide
|
||||||
|
|
||||||
|
This guide provides a comprehensive overview of how to use the Core CLI to manage your development workflow.
|
||||||
|
|
||||||
|
## Key Concepts
|
||||||
|
|
||||||
|
### Projects
|
||||||
|
A Project is a single repository containing code (Go, PHP, or Wails). Core helps you test, build, and release these projects using a consistent set of commands.
|
||||||
|
|
||||||
|
### Workspaces
|
||||||
|
A Workspace is a collection of related projects. Core is designed to work across multiple repositories, allowing you to perform actions (like checking status or committing changes) on all of them at once.
|
||||||
|
|
||||||
|
### Registry (`repos.yaml`)
|
||||||
|
The Registry is a configuration file that defines the repositories in your workspace. It includes information about where they are located on GitHub, their dependencies, and their purpose.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Daily Workflow
|
||||||
|
|
||||||
|
### Working with a Single Project
|
||||||
|
|
||||||
|
For a typical day-to-day development on a single project:
|
||||||
|
|
||||||
|
1. **Verify your environment**:
|
||||||
|
```bash
|
||||||
|
core doctor
|
||||||
|
```
|
||||||
|
2. **Run tests while you work**:
|
||||||
|
```bash
|
||||||
|
core go test
|
||||||
|
```
|
||||||
|
3. **Keep code clean**:
|
||||||
|
```bash
|
||||||
|
core go fmt --fix
|
||||||
|
core go lint
|
||||||
|
```
|
||||||
|
4. **Build and preview**:
|
||||||
|
```bash
|
||||||
|
core build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Working with Multiple Repositories
|
||||||
|
|
||||||
|
If you are working across many repositories in a workspace:
|
||||||
|
|
||||||
|
1. **Check status of all repos**:
|
||||||
|
```bash
|
||||||
|
core dev work --status
|
||||||
|
```
|
||||||
|
2. **Sync all changes**:
|
||||||
|
```bash
|
||||||
|
core dev pull --all
|
||||||
|
```
|
||||||
|
3. **Commit and push everything**:
|
||||||
|
```bash
|
||||||
|
core dev work
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Building and Releasing
|
||||||
|
|
||||||
|
Core separates the building of artifacts from the releasing of those artifacts.
|
||||||
|
|
||||||
|
### 1. Build
|
||||||
|
The `core build` command detects your project type and builds binaries for your configured targets. Artifacts are placed in the `dist/` directory.
|
||||||
|
|
||||||
|
### 2. Preview Release
|
||||||
|
Use `core ci` to see a summary of what would be included in a release (changelog, artifacts, etc.). This is a dry-run by default.
|
||||||
|
|
||||||
|
### 3. Publish Release
|
||||||
|
When you are ready to publish to GitHub:
|
||||||
|
```bash
|
||||||
|
core ci --we-are-go-for-launch
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## PHP and Laravel Development
|
||||||
|
|
||||||
|
Core provides a unified development server for Laravel projects that orchestrates several services:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
core php dev
|
||||||
|
```
|
||||||
|
This starts FrankenPHP, Vite, Horizon, Reverb, and Redis as configured in your `.core/php.yaml`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Common Workflows
|
||||||
|
|
||||||
|
For detailed examples of common end-to-end workflows, see the [Workflows](workflows.md) page.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Getting More Help
|
||||||
|
|
||||||
|
- Use the `--help` flag with any command: `core build --help`
|
||||||
|
- Check the [FAQ](faq.md) for common questions.
|
||||||
|
- If you run into trouble, see the [Troubleshooting Guide](troubleshooting.md).
|
||||||
|
|
@ -39,7 +39,7 @@ func runClients() error {
|
||||||
return log.E("unifi.clients", "conflicting flags", errors.New("--wired and --wireless cannot both be set"))
|
return log.E("unifi.clients", "conflicting flags", errors.New("--wired and --wireless cannot both be set"))
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := uf.NewFromConfig("", "", "", "")
|
client, err := uf.NewFromConfig("", "", "", "", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return log.E("unifi.clients", "failed to initialise client", err)
|
return log.E("unifi.clients", "failed to initialise client", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ var (
|
||||||
configUser string
|
configUser string
|
||||||
configPass string
|
configPass string
|
||||||
configAPIKey string
|
configAPIKey string
|
||||||
|
configInsecure bool
|
||||||
configTest bool
|
configTest bool
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -23,7 +24,7 @@ func addConfigCommand(parent *cli.Command) {
|
||||||
Short: "Configure UniFi connection",
|
Short: "Configure UniFi connection",
|
||||||
Long: "Set the UniFi controller URL and credentials, or test the current connection.",
|
Long: "Set the UniFi controller URL and credentials, or test the current connection.",
|
||||||
RunE: func(cmd *cli.Command, args []string) error {
|
RunE: func(cmd *cli.Command, args []string) error {
|
||||||
return runConfig()
|
return runConfig(cmd)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -31,15 +32,21 @@ func addConfigCommand(parent *cli.Command) {
|
||||||
cmd.Flags().StringVar(&configUser, "user", "", "UniFi username")
|
cmd.Flags().StringVar(&configUser, "user", "", "UniFi username")
|
||||||
cmd.Flags().StringVar(&configPass, "pass", "", "UniFi password")
|
cmd.Flags().StringVar(&configPass, "pass", "", "UniFi password")
|
||||||
cmd.Flags().StringVar(&configAPIKey, "apikey", "", "UniFi API key")
|
cmd.Flags().StringVar(&configAPIKey, "apikey", "", "UniFi API key")
|
||||||
|
cmd.Flags().BoolVar(&configInsecure, "insecure", false, "Allow insecure TLS connections (e.g. self-signed certs)")
|
||||||
cmd.Flags().BoolVar(&configTest, "test", false, "Test the current connection")
|
cmd.Flags().BoolVar(&configTest, "test", false, "Test the current connection")
|
||||||
|
|
||||||
parent.AddCommand(cmd)
|
parent.AddCommand(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runConfig() error {
|
func runConfig(cmd *cli.Command) error {
|
||||||
|
var insecure *bool
|
||||||
|
if cmd.Flags().Changed("insecure") {
|
||||||
|
insecure = &configInsecure
|
||||||
|
}
|
||||||
|
|
||||||
// If setting values, save them first
|
// If setting values, save them first
|
||||||
if configURL != "" || configUser != "" || configPass != "" || configAPIKey != "" {
|
if configURL != "" || configUser != "" || configPass != "" || configAPIKey != "" || insecure != nil {
|
||||||
if err := uf.SaveConfig(configURL, configUser, configPass, configAPIKey); err != nil {
|
if err := uf.SaveConfig(configURL, configUser, configPass, configAPIKey, insecure); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,11 +62,14 @@ func runConfig() error {
|
||||||
if configAPIKey != "" {
|
if configAPIKey != "" {
|
||||||
cli.Success("UniFi API key saved")
|
cli.Success("UniFi API key saved")
|
||||||
}
|
}
|
||||||
|
if insecure != nil {
|
||||||
|
cli.Success(fmt.Sprintf("UniFi insecure mode set to %v", *insecure))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If testing, verify the connection
|
// If testing, verify the connection
|
||||||
if configTest {
|
if configTest {
|
||||||
return runConfigTest()
|
return runConfigTest(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no flags, show current config
|
// If no flags, show current config
|
||||||
|
|
@ -71,7 +81,7 @@ func runConfig() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func showConfig() error {
|
func showConfig() error {
|
||||||
url, user, pass, apikey, err := uf.ResolveConfig("", "", "", "")
|
url, user, pass, apikey, insecure, err := uf.ResolveConfig("", "", "", "", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -101,13 +111,20 @@ func showConfig() error {
|
||||||
cli.Print(" %s %s\n", dimStyle.Render("API Key:"), warningStyle.Render("not set"))
|
cli.Print(" %s %s\n", dimStyle.Render("API Key:"), warningStyle.Render("not set"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cli.Print(" %s %s\n", dimStyle.Render("Insecure:"), valueStyle.Render(fmt.Sprintf("%v", insecure)))
|
||||||
|
|
||||||
cli.Blank()
|
cli.Blank()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func runConfigTest() error {
|
func runConfigTest(cmd *cli.Command) error {
|
||||||
client, err := uf.NewFromConfig(configURL, configUser, configPass, configAPIKey)
|
var insecure *bool
|
||||||
|
if cmd.Flags().Changed("insecure") {
|
||||||
|
insecure = &configInsecure
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := uf.NewFromConfig(configURL, configUser, configPass, configAPIKey, insecure)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ func addDevicesCommand(parent *cli.Command) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func runDevices() error {
|
func runDevices() error {
|
||||||
client, err := uf.NewFromConfig("", "", "", "")
|
client, err := uf.NewFromConfig("", "", "", "", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return log.E("unifi.devices", "failed to initialise client", err)
|
return log.E("unifi.devices", "failed to initialise client", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ func addNetworksCommand(parent *cli.Command) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func runNetworks() error {
|
func runNetworks() error {
|
||||||
client, err := uf.NewFromConfig("", "", "", "")
|
client, err := uf.NewFromConfig("", "", "", "", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return log.E("unifi.networks", "failed to initialise client", err)
|
return log.E("unifi.networks", "failed to initialise client", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ func addRoutesCommand(parent *cli.Command) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func runRoutes() error {
|
func runRoutes() error {
|
||||||
client, err := uf.NewFromConfig("", "", "", "")
|
client, err := uf.NewFromConfig("", "", "", "", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return log.E("unifi.routes", "failed to initialise client", err)
|
return log.E("unifi.routes", "failed to initialise client", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ func addSitesCommand(parent *cli.Command) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func runSites() error {
|
func runSites() error {
|
||||||
client, err := uf.NewFromConfig("", "", "", "")
|
client, err := uf.NewFromConfig("", "", "", "", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return log.E("unifi.sites", "failed to initialise client", err)
|
return log.E("unifi.sites", "failed to initialise client", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
31
mkdocs.yml
31
mkdocs.yml
|
|
@ -43,6 +43,26 @@ markdown_extensions:
|
||||||
|
|
||||||
nav:
|
nav:
|
||||||
- Home: index.md
|
- Home: index.md
|
||||||
|
- User Documentation:
|
||||||
|
- User Guide: user-guide.md
|
||||||
|
- FAQ: faq.md
|
||||||
|
- Troubleshooting: troubleshooting.md
|
||||||
|
- Workflows: workflows.md
|
||||||
|
- CLI Reference:
|
||||||
|
- Overview: cmd/index.md
|
||||||
|
- AI: cmd/ai/index.md
|
||||||
|
- Build: cmd/build/index.md
|
||||||
|
- CI: cmd/ci/index.md
|
||||||
|
- Dev: cmd/dev/index.md
|
||||||
|
- Go: cmd/go/index.md
|
||||||
|
- PHP: cmd/php/index.md
|
||||||
|
- SDK: cmd/sdk/index.md
|
||||||
|
- Setup: cmd/setup/index.md
|
||||||
|
- Doctor: cmd/doctor/index.md
|
||||||
|
- Test: cmd/test/index.md
|
||||||
|
- VM: cmd/vm/index.md
|
||||||
|
- Pkg: cmd/pkg/index.md
|
||||||
|
- Docs: cmd/docs/index.md
|
||||||
- Getting Started:
|
- Getting Started:
|
||||||
- Installation: getting-started/installation.md
|
- Installation: getting-started/installation.md
|
||||||
- Quick Start: getting-started/quickstart.md
|
- Quick Start: getting-started/quickstart.md
|
||||||
|
|
@ -77,3 +97,14 @@ nav:
|
||||||
- API Reference:
|
- API Reference:
|
||||||
- Core: api/core.md
|
- Core: api/core.md
|
||||||
- Display: api/display.md
|
- Display: api/display.md
|
||||||
|
- Development:
|
||||||
|
- Package Standards: pkg/PACKAGE_STANDARDS.md
|
||||||
|
- Internationalization:
|
||||||
|
- Overview: pkg/i18n/README.md
|
||||||
|
- Grammar: pkg/i18n/GRAMMAR.md
|
||||||
|
- Extending: pkg/i18n/EXTENDING.md
|
||||||
|
- Claude Skill: skill/index.md
|
||||||
|
- Reference:
|
||||||
|
- Configuration: configuration.md
|
||||||
|
- Migration: migration.md
|
||||||
|
- Glossary: glossary.md
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ type Client struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new UniFi API client for the given controller URL and credentials.
|
// New creates a new UniFi API client for the given controller URL and credentials.
|
||||||
// TLS verification is disabled by default (self-signed certs on home lab controllers).
|
// TLS verification can be disabled via the insecure parameter (useful for self-signed certs on home lab controllers).
|
||||||
func New(url, user, pass, apikey string) (*Client, error) {
|
func New(url, user, pass, apikey string, insecure bool) (*Client, error) {
|
||||||
cfg := &uf.Config{
|
cfg := &uf.Config{
|
||||||
URL: url,
|
URL: url,
|
||||||
User: user,
|
User: user,
|
||||||
|
|
@ -25,11 +25,11 @@ func New(url, user, pass, apikey string) (*Client, error) {
|
||||||
APIKey: apikey,
|
APIKey: apikey,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip TLS verification for self-signed certs
|
// Skip TLS verification if requested (e.g. for self-signed certs)
|
||||||
httpClient := &http.Client{
|
httpClient := &http.Client{
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
TLSClientConfig: &tls.Config{
|
TLSClientConfig: &tls.Config{
|
||||||
InsecureSkipVerify: true, //nolint:gosec
|
InsecureSkipVerify: insecure,
|
||||||
MinVersion: tls.VersionTLS12,
|
MinVersion: tls.VersionTLS12,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ const (
|
||||||
ConfigKeyPass = "unifi.pass"
|
ConfigKeyPass = "unifi.pass"
|
||||||
// ConfigKeyAPIKey is the config key for the UniFi API key.
|
// ConfigKeyAPIKey is the config key for the UniFi API key.
|
||||||
ConfigKeyAPIKey = "unifi.apikey"
|
ConfigKeyAPIKey = "unifi.apikey"
|
||||||
|
// ConfigKeyInsecure is the config key for allowing insecure TLS connections.
|
||||||
|
ConfigKeyInsecure = "unifi.insecure"
|
||||||
|
|
||||||
// DefaultURL is the default UniFi controller URL.
|
// DefaultURL is the default UniFi controller URL.
|
||||||
DefaultURL = "https://10.69.1.1"
|
DefaultURL = "https://10.69.1.1"
|
||||||
|
|
@ -32,10 +34,10 @@ const (
|
||||||
// NewFromConfig creates a UniFi client using the standard config resolution:
|
// NewFromConfig creates a UniFi client using the standard config resolution:
|
||||||
//
|
//
|
||||||
// 1. ~/.core/config.yaml keys: unifi.url, unifi.user, unifi.pass, unifi.apikey
|
// 1. ~/.core/config.yaml keys: unifi.url, unifi.user, unifi.pass, unifi.apikey
|
||||||
// 2. UNIFI_URL + UNIFI_USER + UNIFI_PASS + UNIFI_APIKEY environment variables (override config file)
|
// 2. UNIFI_URL + UNIFI_USER + UNIFI_PASS + UNIFI_APIKEY + UNIFI_INSECURE environment variables (override config file)
|
||||||
// 3. Provided flag overrides (highest priority; pass empty to skip)
|
// 3. Provided flag overrides (highest priority; pass empty to skip)
|
||||||
func NewFromConfig(flagURL, flagUser, flagPass, flagAPIKey string) (*Client, error) {
|
func NewFromConfig(flagURL, flagUser, flagPass, flagAPIKey string, flagInsecure *bool) (*Client, error) {
|
||||||
url, user, pass, apikey, err := ResolveConfig(flagURL, flagUser, flagPass, flagAPIKey)
|
url, user, pass, apikey, insecure, err := ResolveConfig(flagURL, flagUser, flagPass, flagAPIKey, flagInsecure)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -44,12 +46,12 @@ func NewFromConfig(flagURL, flagUser, flagPass, flagAPIKey string) (*Client, err
|
||||||
return nil, log.E("unifi.NewFromConfig", "no credentials configured (set UNIFI_USER/UNIFI_PASS or UNIFI_APIKEY, or run: core unifi config)", nil)
|
return nil, log.E("unifi.NewFromConfig", "no credentials configured (set UNIFI_USER/UNIFI_PASS or UNIFI_APIKEY, or run: core unifi config)", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return New(url, user, pass, apikey)
|
return New(url, user, pass, apikey, insecure)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResolveConfig resolves the UniFi URL and credentials from all config sources.
|
// ResolveConfig resolves the UniFi URL and credentials from all config sources.
|
||||||
// Flag values take highest priority, then env vars, then config file.
|
// Flag values take highest priority, then env vars, then config file.
|
||||||
func ResolveConfig(flagURL, flagUser, flagPass, flagAPIKey string) (url, user, pass, apikey string, err error) {
|
func ResolveConfig(flagURL, flagUser, flagPass, flagAPIKey string, flagInsecure *bool) (url, user, pass, apikey string, insecure bool, err error) {
|
||||||
// Start with config file values
|
// Start with config file values
|
||||||
cfg, cfgErr := config.New()
|
cfg, cfgErr := config.New()
|
||||||
if cfgErr == nil {
|
if cfgErr == nil {
|
||||||
|
|
@ -57,6 +59,7 @@ func ResolveConfig(flagURL, flagUser, flagPass, flagAPIKey string) (url, user, p
|
||||||
_ = cfg.Get(ConfigKeyUser, &user)
|
_ = cfg.Get(ConfigKeyUser, &user)
|
||||||
_ = cfg.Get(ConfigKeyPass, &pass)
|
_ = cfg.Get(ConfigKeyPass, &pass)
|
||||||
_ = cfg.Get(ConfigKeyAPIKey, &apikey)
|
_ = cfg.Get(ConfigKeyAPIKey, &apikey)
|
||||||
|
_ = cfg.Get(ConfigKeyInsecure, &insecure)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overlay environment variables
|
// Overlay environment variables
|
||||||
|
|
@ -72,6 +75,9 @@ func ResolveConfig(flagURL, flagUser, flagPass, flagAPIKey string) (url, user, p
|
||||||
if envAPIKey := os.Getenv("UNIFI_APIKEY"); envAPIKey != "" {
|
if envAPIKey := os.Getenv("UNIFI_APIKEY"); envAPIKey != "" {
|
||||||
apikey = envAPIKey
|
apikey = envAPIKey
|
||||||
}
|
}
|
||||||
|
if envInsecure := os.Getenv("UNIFI_INSECURE"); envInsecure != "" {
|
||||||
|
insecure = envInsecure == "true" || envInsecure == "1"
|
||||||
|
}
|
||||||
|
|
||||||
// Overlay flag values (highest priority)
|
// Overlay flag values (highest priority)
|
||||||
if flagURL != "" {
|
if flagURL != "" {
|
||||||
|
|
@ -86,17 +92,20 @@ func ResolveConfig(flagURL, flagUser, flagPass, flagAPIKey string) (url, user, p
|
||||||
if flagAPIKey != "" {
|
if flagAPIKey != "" {
|
||||||
apikey = flagAPIKey
|
apikey = flagAPIKey
|
||||||
}
|
}
|
||||||
|
if flagInsecure != nil {
|
||||||
|
insecure = *flagInsecure
|
||||||
|
}
|
||||||
|
|
||||||
// Default URL if nothing configured
|
// Default URL if nothing configured
|
||||||
if url == "" {
|
if url == "" {
|
||||||
url = DefaultURL
|
url = DefaultURL
|
||||||
}
|
}
|
||||||
|
|
||||||
return url, user, pass, apikey, nil
|
return url, user, pass, apikey, insecure, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveConfig persists the UniFi URL and/or credentials to the config file.
|
// SaveConfig persists the UniFi URL and/or credentials to the config file.
|
||||||
func SaveConfig(url, user, pass, apikey string) error {
|
func SaveConfig(url, user, pass, apikey string, insecure *bool) error {
|
||||||
cfg, err := config.New()
|
cfg, err := config.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return log.E("unifi.SaveConfig", "failed to load config", err)
|
return log.E("unifi.SaveConfig", "failed to load config", err)
|
||||||
|
|
@ -126,5 +135,11 @@ func SaveConfig(url, user, pass, apikey string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if insecure != nil {
|
||||||
|
if err := cfg.Set(ConfigKeyInsecure, *insecure); err != nil {
|
||||||
|
return log.E("unifi.SaveConfig", "failed to save insecure flag", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue