diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e5be2c28..2a4a41ff 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,323 +1,330 @@ # Contributing to OpenFrame CLI -We're excited that you're interested in contributing to OpenFrame CLI! This guide will help you get started with contributing to the project. +Thank you for your interest in contributing to OpenFrame CLI! This document describes the code style conventions, branching strategy, commit message format, and PR review process. -## Getting Started +--- -### Prerequisites +## Community First -Before you begin, ensure you have: +OpenFrame is a community-driven project. All discussions, questions, bug reports, and feature requests happen in the **OpenMSP Slack**: -- Go 1.24.6 or higher -- Docker 20.10+ (with daemon running) -- kubectl 1.25+ -- Helm 3.10+ -- K3D 5.0+ -- Git +πŸ‘‰ [https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) -### Development Environment Setup +> We do **not** use GitHub Issues or GitHub Discussions. Please bring questions and bug reports to the Slack community at [https://www.openmsp.ai/](https://www.openmsp.ai/). -1. **Fork and Clone the Repository** -```bash -# Fork the repo on GitHub, then clone your fork -git clone https://github.com/YOUR_USERNAME/openframe-cli.git -cd openframe-cli +--- -# Add upstream remote -git remote add upstream https://github.com/flamingo-stack/openframe-cli.git -``` +## Getting Started as a Contributor -2. **Set Up Your Development Environment** +### 1. Set Up Your Development Environment -Follow the [Development Environment Setup](./docs/development/setup/environment.md) guide for detailed IDE configuration, tools, and environment variables. +Review the [Development Environment Setup](./docs/development/setup/environment.md) guide to install Go 1.22+, Docker, K3D, kubectl, Helm, mkcert, and the development linting tools. -3. **Install Go Tools** -```bash -# Install essential Go development tools -go install golang.org/x/tools/cmd/goimports@latest -go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest -go install github.com/rakyll/gotest@latest -``` +### 2. Clone and Build -4. **Build and Test** ```bash -# Build the project +git clone https://github.com/flamingo-stack/openframe-cli.git +cd openframe-cli +go mod download go build -o openframe main.go +./openframe --version +``` + +### 3. Run the Tests -# Run tests +```bash +# All unit tests go test ./... -# Run linter -golangci-lint run +# With race detection +go test -race ./... + +# Lint +golangci-lint run ./... ``` -## Development Workflow +--- -### Branch Management +## Code Style and Conventions -1. **Create a Feature Branch** -```bash -git checkout -b feature/your-feature-name -``` +### Go Formatting + +All Go code must be formatted with `goimports` before committing: -2. **Keep Your Branch Up to Date** ```bash -git fetch upstream -git rebase upstream/main +goimports -w . ``` -### Code Standards +### Naming Conventions + +| Construct | Convention | Example | +|---|---|---| +| Packages | lowercase, no underscores | `cluster`, `executor` | +| Exported types | PascalCase | `ClusterService`, `K3dManager` | +| Unexported types | camelCase | `clusterConfig`, `helmValues` | +| Interfaces | PascalCase, noun or adjective | `ClusterLister`, `HelmProvider` | +| Functions/Methods | PascalCase (exported), camelCase (unexported) | `CreateCluster`, `validateInputs` | +| Constants | PascalCase (exported), camelCase (unexported) | `DeploymentModeOSS` | +| Test files | `_test.go` suffix | `service_test.go` | +| Mock files | `mock.go` or `_mock.go` | `mock.go` | -#### Go Code Style -- Follow standard Go conventions and idioms -- Use `gofmt` and `goimports` for formatting -- Write clear, self-documenting code with meaningful names -- Include comments for exported functions and complex logic +### Layered Architecture + +The CLI strictly follows a layered architecture. **Never skip a layer.** -#### Project Structure ```text -openframe-cli/ -β”œβ”€β”€ cmd/ # CLI command definitions -β”œβ”€β”€ internal/ -β”‚ β”œβ”€β”€ cluster/ # Cluster management logic -β”‚ β”œβ”€β”€ chart/ # Chart and ArgoCD management -β”‚ β”œβ”€β”€ dev/ # Development tools -β”‚ β”œβ”€β”€ bootstrap/ # Environment bootstrapping -β”‚ └── shared/ # Common utilities -β”œβ”€β”€ docs/ # Documentation -β”œβ”€β”€ scripts/ # Build and utility scripts -└── main.go # Application entry point +cmd/ β†’ Command definitions only (flag parsing, delegation to services) +internal/ β†’ All business logic + └── / + β”œβ”€β”€ service.go # Main service struct and methods + β”œβ”€β”€ models/ # Domain types and flag structs + β”œβ”€β”€ providers// # External tool wrappers + β”œβ”€β”€ prerequisites/ # Tool prerequisite checkers + └── ui/ # Interactive prompts and display ``` -#### Testing Guidelines -- Write unit tests for all business logic -- Include integration tests for external tool interactions -- Use table-driven tests where appropriate -- Mock external dependencies using interfaces +**Rules:** +- Commands in `cmd/` must not call external tools directly β€” delegate to service layer +- Services must not call external tools directly β€” delegate to providers +- Providers must use `shared/executor` for all subprocess execution +- Interfaces must be defined in `utils/types/interfaces.go` for testability + +### Error Handling + +Use the typed error constructors from `internal/shared/errors/`: -Example test structure: ```go -func TestClusterCreate(t *testing.T) { - tests := []struct { - name string - input ClusterConfig - expected error - }{ - { - name: "valid cluster creation", - input: ClusterConfig{ - Name: "test-cluster", - Nodes: 3, - }, - expected: nil, - }, - // Add more test cases... - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := CreateCluster(tt.input) - assert.Equal(t, tt.expected, err) - }) - } -} +// For user input validation failures +return errors.CreateValidationError("cluster-name", name, "must be alphanumeric") + +// For external command failures +return errors.CreateCommandError("k3d", args, originalErr) +``` + +Do not return raw `fmt.Errorf` from user-facing code paths. + +### Interface Compliance + +Always add a compile-time interface assertion when implementing an interface: + +```go +var _ types.ClusterLister = (*ClusterService)(nil) ``` -### Commit Guidelines +### Command Injection Prevention -Follow conventional commit format: +Always pass external tool arguments as slices β€” never concatenate user input into shell strings: + +```go +// CORRECT +executor.Execute("k3d", []string{"cluster", "create", clusterName, "--agents", "2"}) + +// WRONG β€” injection risk +exec.Command("sh", "-c", "k3d cluster create " + clusterName) +``` + +--- + +## Branch Naming + +| Type | Pattern | Example | +|---|---|---| +| Feature | `feature/` | `feature/add-cluster-resize` | +| Bug fix | `fix/` | `fix/k3d-wsl2-ip-detection` | +| Documentation | `docs/` | `docs/update-intercept-guide` | +| Refactor | `refactor/` | `refactor/executor-abstraction` | +| Chore | `chore/` | `chore/update-dependencies` | + +- Use lowercase and hyphens (no underscores) +- Keep descriptions concise (2–5 words) +- Branch from `main` for features and fixes + +--- + +## Commit Message Format + +OpenFrame CLI follows the [Conventional Commits](https://www.conventionalcommits.org/) specification: ```text -[optional scope]: +(): [optional body] [optional footer(s)] ``` -**Types:** -- `feat:` New feature -- `fix:` Bug fix -- `docs:` Documentation changes -- `style:` Code style changes (formatting, etc.) -- `refactor:` Code refactoring -- `test:` Adding or updating tests -- `chore:` Build process or auxiliary tool changes +### Types -**Examples:** -```bash -git commit -m "feat(cluster): add support for custom node configurations" -git commit -m "fix(bootstrap): resolve ArgoCD installation timeout" -git commit -m "docs: update prerequisites and installation guide" -``` +| Type | When to Use | +|---|---| +| `feat` | A new feature | +| `fix` | A bug fix | +| `docs` | Documentation only changes | +| `refactor` | Code change that neither fixes a bug nor adds a feature | +| `test` | Adding or correcting tests | +| `chore` | Build process, dependency updates, tooling | +| `perf` | Performance improvement | -### Pull Request Process +### Scopes -1. **Prepare Your PR** -```bash -# Ensure your branch is up to date -git fetch upstream -git rebase upstream/main +Use the top-level package or area name: `cluster`, `chart`, `bootstrap`, `dev`, `executor`, `ui`, `errors`, `config`, `prereqs`, `ci` -# Run all checks -go fmt ./... -goimports -w . -golangci-lint run -go test ./... -``` +### Examples -2. **Submit Your Pull Request** -- Use a clear, descriptive title -- Include a detailed description of changes -- Reference any related issues -- Add screenshots/logs for UI or behavioral changes -- Ensure all CI checks pass +```text +feat(cluster): add support for multi-node k3d clusters -3. **PR Template** -```markdown -## Description -Brief description of the changes and their purpose. +fix(dev): resolve WSL2 IP detection for Telepresence intercepts -## Type of Change -- [ ] Bug fix (non-breaking change which fixes an issue) -- [ ] New feature (non-breaking change which adds functionality) -- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) -- [ ] Documentation update +docs(chart): update configuration wizard documentation -## Testing -- [ ] Unit tests pass -- [ ] Integration tests pass -- [ ] Manual testing completed - -## Checklist -- [ ] My code follows the project's style guidelines -- [ ] I have performed a self-review of my code -- [ ] I have commented my code, particularly in hard-to-understand areas -- [ ] I have made corresponding changes to the documentation -- [ ] My changes generate no new warnings +test(executor): add mock response patterns for helm upgrade + +chore(deps): update k8s.io/client-go to v0.30.0 ``` -## Code Review Process +### Breaking Changes -### For Contributors -- Respond promptly to review feedback -- Address all comments and suggestions -- Ask questions if feedback is unclear -- Update documentation if your changes affect user-facing behavior +Add `BREAKING CHANGE:` in the commit footer: -### For Reviewers -- Provide constructive, actionable feedback -- Focus on code quality, maintainability, and correctness -- Check that tests adequately cover new functionality -- Verify documentation updates are included +```text +feat(bootstrap): change default deployment mode to oss-tenant -## Testing +BREAKING CHANGE: The default --deployment-mode flag value has changed +from "saas-tenant" to "oss-tenant". Update your CI/CD pipelines to +explicitly specify --deployment-mode=saas-tenant if needed. +``` -### Running Tests -```bash -# Run all tests -go test ./... +--- -# Run tests with coverage -go test -race -coverprofile=coverage.out ./... -go tool cover -html=coverage.out +## Pull Request Process -# Run specific package tests -go test ./internal/cluster/... +### Before Opening a PR -# Run integration tests (requires Docker) -go test -tags=integration ./... +- [ ] Run `go test -race ./...` β€” all tests pass +- [ ] Run `golangci-lint run ./...` β€” no lint errors +- [ ] Run `goimports -w .` β€” code is formatted +- [ ] Run `govulncheck ./...` β€” no new vulnerabilities +- [ ] Add tests for any new functionality +- [ ] Update relevant documentation if behavior changes + +### PR Title + +Follow the same Conventional Commits format: + +```text +feat(cluster): add cluster resize command +fix(chart): handle missing ArgoCD CRD during wait ``` -### Test Categories -- **Unit Tests**: Test individual functions and components -- **Integration Tests**: Test interactions with external tools (Docker, kubectl, etc.) -- **End-to-End Tests**: Test complete workflows from CLI to cluster +### PR Description Template -### Writing Good Tests -- Test both happy path and error conditions -- Use descriptive test names that explain what is being tested -- Keep tests focused and atomic -- Use test fixtures and helpers to reduce duplication +```markdown +## Summary +Brief description of what this PR does. -## Documentation +## Changes +- Added X +- Fixed Y +- Updated Z -### Types of Documentation -- **Code Comments**: Explain complex logic and public APIs -- **README Updates**: Keep installation and usage instructions current -- **Developer Docs**: Architecture, design decisions, and development guides -- **User Guides**: Step-by-step tutorials and reference material +## Testing +How you tested this change (unit tests added, manual testing steps). -### Documentation Guidelines -- Write clear, concise instructions -- Include code examples where helpful -- Update docs when making user-facing changes -- Use proper Markdown formatting +## Breaking Changes +Any breaking changes and migration steps. +``` -## Release Process +### PR Size Guidelines -### Version Management -We use semantic versioning (SemVer): -- **MAJOR**: Breaking changes -- **MINOR**: New features (backward compatible) -- **PATCH**: Bug fixes (backward compatible) +- **Small PRs** (< 200 lines): Preferred β€” easier to review and merge quickly +- **Medium PRs** (200–500 lines): Acceptable β€” include a detailed description +- **Large PRs** (> 500 lines): Split into smaller PRs where possible -### Creating a Release -1. Update version in `main.go` -2. Update `CHANGELOG.md` -3. Create and push version tag -4. GitHub Actions handles the build and release +--- -## Issue Management +## Writing Tests -### Reporting Issues -When reporting bugs or requesting features: -- Check existing issues first -- Use issue templates when available -- Provide detailed reproduction steps for bugs -- Include system information and versions +### Unit Test Pattern -### Working on Issues -- Comment on issues before starting work -- Ask for clarification if requirements are unclear -- Link your PR to the issue when ready +```go +func TestMyNewFeature(t *testing.T) { + testutil.InitializeTestMode() // Disables interactive UI + executor := testutil.NewTestMockExecutor() + + executor.SetResponse("some-tool --arg value", &executor.CommandResult{ + ExitCode: 0, + Stdout: "expected output", + }) + + svc := NewMyService(executor, false) + result, err := svc.DoSomething(context.Background(), "input") + require.NoError(t, err) + assert.Equal(t, "expected result", result) +} +``` -## Community Guidelines +Always test failure scenarios alongside happy paths. Coverage targets: -### Communication Channels -- **Primary Support**: [OpenMSP Slack](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) -- **Development Discussion**: GitHub PR comments and code reviews -- **Feature Requests**: GitHub Issues +| Package | Minimum Coverage | +|---|---| +| `internal/cluster/` | 70% | +| `internal/chart/` | 70% | +| `internal/dev/` | 60% | +| `internal/shared/` | 80% | +| `cmd/` | 50% | -### Code of Conduct -- Be respectful and inclusive in all interactions -- Focus on constructive feedback and solutions -- Help newcomers get started -- Follow the project's technical standards and conventions +--- -## Getting Help +## Code Review Checklist -Need assistance? Here's how to get help: +Reviewers should check: -1. **Development Questions**: Ask in OpenMSP Slack #dev channel -2. **Documentation Issues**: Create a GitHub issue with the "documentation" label -3. **Bug Reports**: File a GitHub issue with reproduction steps -4. **Feature Ideas**: Discuss in Slack first, then create GitHub issue +- [ ] Code follows the layered architecture (cmd β†’ service β†’ provider β†’ executor) +- [ ] Error types use the shared error constructors +- [ ] External commands use argument slices (no shell string interpolation) +- [ ] User input is validated before use in system commands +- [ ] New public types and functions have Go doc comments +- [ ] Tests cover the happy path and at least one error path +- [ ] No hardcoded secrets, tokens, or passwords +- [ ] Interface compliance assertions are present for new interface implementations +- [ ] `--non-interactive` mode works correctly for any new wizard prompts -## External Dependencies +--- -### CLI Tools Integration -This repository contains OpenFrame CLI code. The main OpenFrame application code is maintained separately: +## Security Guidelines Summary -- **OpenFrame Main Repository**: [flamingo-stack/openframe-oss-tenant](https://github.com/flamingo-stack/openframe-oss-tenant) -- **CLI Documentation**: [CLI Documentation](https://github.com/flamingo-stack/openframe-oss-tenant/tree/main/docs) +- **Never commit secrets** β€” credentials are always prompted at runtime or passed via environment variables +- **Never use shell string interpolation** for external commands β€” always use argument slices via the `shared/executor` +- **`InsecureTLSConfig` is only for local K3D clusters** β€” never apply it to production cluster connections +- **Validate all user input** before passing to system commands using `ValidateClusterName()` and similar validators -When contributing CLI-related changes, coordinate with the main repository team through Slack. +Report security vulnerabilities privately via [OpenMSP Slack](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) β€” do **not** open a public GitHub issue. + +--- + +## Developer Certificate of Origin + +By contributing to this project, you certify that your contribution is your original work (or that you have the right to submit it) and that you agree to license it under the project's open-source license. + +--- -## Acknowledgments +## Quick Reference: Common Development Commands -Thank you for contributing to OpenFrame CLI! Your efforts help make IT operations more accessible and cost-effective for MSPs worldwide. +| Task | Command | +|---|---| +| Build binary | `go build -o openframe main.go` | +| Run all tests | `go test ./...` | +| Run with race detection | `go test -race ./...` | +| Run specific test | `go test -v -run TestClusterCreate ./internal/cluster/...` | +| Lint | `golangci-lint run ./...` | +| Format code | `goimports -w .` | +| Check vulnerabilities | `govulncheck ./...` | +| Download deps | `go mod download` | +| Tidy deps | `go mod tidy` | --- -**Questions?** Join our [OpenMSP Slack community](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) - we're here to help! \ No newline at end of file +
+ Built with πŸ’› by the Flamingo team +
diff --git a/README.md b/README.md index dc599187..11caacf6 100644 --- a/README.md +++ b/README.md @@ -12,197 +12,233 @@ # OpenFrame CLI -OpenFrame CLI is a modern, interactive command-line tool for managing OpenFrame Kubernetes clusters and development workflows. It provides seamless cluster lifecycle management, chart installation with ArgoCD, and developer-friendly tools for service intercepts and scaffolding. +**OpenFrame CLI** is a modern, interactive command-line tool for bootstrapping and managing [OpenFrame](https://openframe.ai) Kubernetes environments. Part of the [Flamingo](https://flamingo.run) AI-powered MSP platform, it replaces fragile shell-script workflows with a structured Go application that supports both guided wizard modes for new users and fully non-interactive CI/CD automation for production pipelines. -[![OpenFrame Preview Webinar](https://img.youtube.com/vi/bINdW0CQbvY/maxresdefault.jpg)](https://www.youtube.com/watch?v=bINdW0CQbvY) +> **In one command**, `openframe bootstrap`, you get a fully operational K3D Kubernetes cluster with ArgoCD GitOps pipelines and all OpenFrame services installed and healthy. -## What is OpenFrame CLI? - -OpenFrame CLI is part of the broader [OpenFrame](https://openframe.ai) ecosystem - an AI-powered MSP platform that replaces expensive proprietary software with open-source alternatives enhanced by intelligent automation. The CLI serves as the entry point for developers and operators to bootstrap, manage, and develop on OpenFrame environments. +--- -## Key Features +[![OpenFrame Product Walkthrough](https://img.youtube.com/vi/bINdW0CQbvY/hqdefault.jpg)](https://www.youtube.com/watch?v=bINdW0CQbvY) -### πŸš€ Complete Environment Bootstrapping -- **One-command setup**: Bootstrap entire OpenFrame environments with `openframe bootstrap` -- **Multi-mode deployment**: Support for OSS tenant, SaaS tenant, and SaaS shared modes -- **Automated cluster creation**: Creates K3D clusters with all necessary components -- **ArgoCD integration**: Automatic chart installation and application management +--- -### πŸ”§ Cluster Management -- **Lifecycle operations**: Create, delete, list, and monitor Kubernetes clusters -- **K3D integration**: Lightweight Kubernetes for development and testing -- **Status monitoring**: Real-time cluster health and resource monitoring -- **Easy cleanup**: Remove clusters and associated resources with simple commands +## Features -### πŸ“¦ Chart & Application Management -- **Helm chart installation**: Streamlined chart deployment with dependency management -- **ArgoCD applications**: GitOps-based application lifecycle management -- **App-of-apps pattern**: Hierarchical application management for complex deployments -- **Synchronization monitoring**: Track deployment progress with detailed logging +- **One-Command Bootstrap** β€” Full environment setup: K3D cluster + ArgoCD + app-of-apps deployment in a single `openframe bootstrap` call +- **Interactive Wizards** β€” Step-by-step guided setup for clusters, charts, and developer workflows +- **Cluster Lifecycle Management** β€” Create, delete, list, and inspect K3D Kubernetes clusters +- **GitOps via ArgoCD** β€” Automated chart installation using the App-of-Apps pattern with health/sync polling +- **Developer Intercepts** β€” Route live Kubernetes service traffic to your local machine via Telepresence +- **Live Reload Development** β€” Skaffold-powered hot-reload development sessions inside the cluster +- **CI/CD Ready** β€” `--non-interactive` flags for every operation, fully suitable for automation pipelines +- **Prerequisite Checking** β€” Automatically validates and guides installation of required tools (Docker, kubectl, k3d, Helm, mkcert) +- **WSL2 Support** β€” First-class Windows WSL2 compatibility with automatic IP detection and platform-specific optimizations +- **Multiple Deployment Modes** β€” Supports `oss-tenant`, `saas-tenant`, and `saas-shared` deployment targets -### πŸ›  Development Tools -- **Service intercepts**: Local development with Telepresence integration -- **Scaffolding**: Generate boilerplate code and configurations -- **Live debugging**: Debug services running in Kubernetes from your local environment -- **Hot reload**: Rapid development cycles with instant feedback +--- -## Architecture Overview +## Architecture ```mermaid graph TB - subgraph "CLI Commands" - Bootstrap[openframe bootstrap] - Cluster[openframe cluster] - Chart[openframe chart] - Dev[openframe dev] + subgraph CLI["CLI Entry Points"] + Root["openframe (root)"] + Bootstrap["bootstrap"] + Cluster["cluster"] + Chart["chart"] + Dev["dev"] end - - subgraph "Core Services" - ClusterSvc[Cluster Management] - ChartSvc[Chart Installation] - DevSvc[Development Tools] + + subgraph Services["Service Layer"] + BootstrapSvc["bootstrap.Service"] + ClusterSvc["cluster.ClusterService"] + ChartSvc["chart.ChartService"] + DevSvc["dev.Service"] end - - subgraph "External Tools" - K3D[K3D Clusters] - Helm[Helm Charts] - ArgoCD[ArgoCD Apps] - Telepresence[Service Intercepts] + + subgraph Providers["Provider Layer"] + K3dMgr["k3d.K3dManager"] + HelmMgr["helm.HelmManager"] + ArgoCDMgr["argocd.Manager"] + TelepresenceProv["telepresence.Provider"] end - - subgraph "Target Environment" - K8s[Kubernetes] - Apps[Applications] - Services[Microservices] + + subgraph External["External Tools"] + K3D["K3D CLI"] + HelmCLI["Helm CLI"] + ArgoCD["ArgoCD API"] + TelepresenceCLI["Telepresence"] + SkaffoldCLI["Skaffold"] end - - Bootstrap --> ClusterSvc - Bootstrap --> ChartSvc + + Root --> Bootstrap + Root --> Cluster + Root --> Chart + Root --> Dev + + Bootstrap --> BootstrapSvc Cluster --> ClusterSvc Chart --> ChartSvc Dev --> DevSvc - - ClusterSvc --> K3D - ChartSvc --> Helm - ChartSvc --> ArgoCD - DevSvc --> Telepresence - - K3D --> K8s - Helm --> Apps - ArgoCD --> Apps - Telepresence --> Services + + BootstrapSvc --> ClusterSvc + BootstrapSvc --> ChartSvc + ClusterSvc --> K3dMgr + ChartSvc --> HelmMgr + ChartSvc --> ArgoCDMgr + DevSvc --> TelepresenceProv + + K3dMgr --> K3D + HelmMgr --> HelmCLI + ArgoCDMgr --> ArgoCD + TelepresenceProv --> TelepresenceCLI + TelepresenceProv --> SkaffoldCLI ``` -## Quick Start +The CLI follows a strict layered architecture: **Commands β†’ Services β†’ Providers β†’ Shared Executor β†’ External Tools**. Every workflow supports both interactive wizard-guided mode and non-interactive flag-driven mode. -Get OpenFrame CLI up and running in 5 minutes! +--- -### System Requirements +## Hardware Requirements -| Resource | Minimum | Recommended | -|----------|---------|-------------| -| **RAM** | 24GB | 32GB | -| **CPU Cores** | 6 cores | 12 cores | -| **Disk Space** | 50GB free | 100GB free | +| Tier | RAM | CPU Cores | Disk Space | +|---|---|---|---| +| **Minimum** | 24 GB | 6 cores | 50 GB | +| **Recommended** | 32 GB | 12 cores | 100 GB | -### Prerequisites +> K3D runs Kubernetes nodes as Docker containers. Insufficient memory is the most common cause of failed bootstraps. -Before installation, ensure you have: -- [Docker](https://docs.docker.com/get-docker/) 20.10+ -- [kubectl](https://kubernetes.io/docs/tasks/tools/) 1.25+ -- [Helm](https://helm.sh/docs/intro/install/) 3.10+ -- [K3D](https://k3d.io/v5.4.6/#installation) 5.0+ +--- + +## Quick Start -### Installation +[![Getting Started with OpenFrame](https://img.youtube.com/vi/-_56_qYvMWk/maxresdefault.jpg)](https://www.youtube.com/watch?v=-_56_qYvMWk) -Choose your platform and install OpenFrame CLI: +### Step 1: Install the OpenFrame CLI + +**Linux (amd64):** -#### Linux (AMD64) ```bash -curl -fsSL https://github.com/flamingo-stack/openframe-cli/releases/latest/download/openframe-cli_linux_amd64.tar.gz | tar -xz -sudo mv openframe /usr/local/bin/ -chmod +x /usr/local/bin/openframe +curl -Lo openframe https://github.com/flamingo-stack/openframe-cli/releases/latest/download/openframe-cli_linux_amd64 +chmod +x openframe +sudo mv openframe /usr/local/bin/openframe ``` -#### macOS (Apple Silicon) +**macOS (Apple Silicon):** + ```bash -curl -fsSL https://github.com/flamingo-stack/openframe-cli/releases/latest/download/openframe-cli_darwin_arm64.tar.gz | tar -xz -sudo mv openframe /usr/local/bin/ -chmod +x /usr/local/bin/openframe +curl -Lo openframe https://github.com/flamingo-stack/openframe-cli/releases/latest/download/openframe-cli_darwin_arm64 +chmod +x openframe +sudo mv openframe /usr/local/bin/openframe ``` -#### Windows (WSL2) -1. Download: https://github.com/flamingo-stack/openframe-cli/releases/latest/download/openframe-cli_windows_amd64.zip -2. Extract and move `openframe.exe` to a directory in your `PATH` -3. Open WSL2 terminal and verify access +**Windows (AMD64):** -### Bootstrap Your Environment +1. Download [openframe-cli_windows_amd64.zip](https://github.com/flamingo-stack/openframe-cli/releases/latest/download/openframe-cli_windows_amd64.zip) +2. Extract the archive +3. Move `openframe.exe` to a directory on your `$PATH` -Create a complete OpenFrame environment with a single command: +**Build from source:** + +```bash +git clone https://github.com/flamingo-stack/openframe-cli.git +cd openframe-cli +go build -o openframe main.go +sudo mv openframe /usr/local/bin/openframe +``` + +### Step 2: Verify Installation ```bash -# Verify installation openframe --version +openframe --help +``` + +### Step 3: Bootstrap Your First Environment -# Bootstrap complete environment +**Interactive mode (recommended for first-time users):** + +```bash openframe bootstrap +``` -# Check cluster status -openframe cluster status +The wizard will guide you through cluster naming, deployment mode selection, and configuration. + +**Non-interactive / CI mode:** + +```bash +openframe bootstrap my-cluster --deployment-mode=oss-tenant --non-interactive ``` -The bootstrap process creates: -- K3D Kubernetes cluster -- ArgoCD for GitOps deployment -- Traefik ingress controller -- Core monitoring and logging components +### Step 4: Verify the Environment -## Core Commands +```bash +openframe cluster list +openframe cluster status my-cluster --detailed +``` -| Command | Description | Example | -|---------|-------------|---------| -| `openframe bootstrap` | Complete environment setup | `openframe bootstrap my-cluster` | -| `openframe cluster create` | Create Kubernetes cluster | `openframe cluster create --nodes 3` | -| `openframe cluster delete` | Remove existing cluster | `openframe cluster delete my-cluster` | -| `openframe cluster status` | Show cluster information | `openframe cluster status` | -| `openframe chart install` | Install charts with ArgoCD | `openframe chart install` | -| `openframe dev intercept` | Start service intercepts | `openframe dev intercept my-service` | +--- -## Technology Stack +## Command Reference + +| Command | Description | +|---|---| +| `openframe bootstrap [cluster-name]` | Full environment setup: cluster + ArgoCD + app-of-apps | +| `openframe cluster create [name]` | Create a K3D Kubernetes cluster | +| `openframe cluster list` | List all managed clusters | +| `openframe cluster status [name]` | Show cluster health and ArgoCD app status | +| `openframe cluster delete [name]` | Delete a cluster | +| `openframe cluster cleanup [name]` | Remove unused Docker resources from cluster nodes | +| `openframe chart install [cluster-name]` | Install ArgoCD and app-of-apps on an existing cluster | +| `openframe dev intercept [service-name]` | Intercept Kubernetes service traffic locally via Telepresence | +| `openframe dev skaffold [cluster-name]` | Run a live-reload development session with Skaffold | -OpenFrame CLI integrates with industry-standard tools: +--- -- **Kubernetes**: Container orchestration with K3D for development -- **ArgoCD**: GitOps continuous deployment -- **Helm**: Package management for Kubernetes -- **Telepresence**: Local development with remote services -- **Docker**: Container runtime and image management -- **Cobra**: Modern CLI framework with rich help and completion +## Deployment Modes -## Documentation +| Mode | Repository | Use Case | +|---|---|---| +| `oss-tenant` | `flamingo-stack/openframe-oss-tenant` | Default self-hosted OpenFrame | +| `saas-tenant` | `flamingo-stack/openframe-saas-tenant` | SaaS tenant deployment | +| `saas-shared` | `flamingo-stack/openframe-saas-shared` | Shared SaaS platform | -πŸ“š See the [Documentation](./docs/README.md) for comprehensive guides including: +--- -- **Getting Started**: Prerequisites, installation, and first steps -- **Development**: Local setup, architecture, and contribution guidelines -- **Reference**: Technical documentation, API specs, and configuration -- **CLI Tools**: Links to external repositories and tools +## Technology Stack -## Community and Support +| Layer | Technology | +|---|---| +| **Language** | Go 1.22+ | +| **CLI Framework** | [Cobra](https://github.com/spf13/cobra) | +| **Terminal UI** | [pterm](https://github.com/pterm/pterm), [promptui](https://github.com/manifoldco/promptui) | +| **Kubernetes Client** | [client-go](https://github.com/kubernetes/client-go) | +| **GitOps** | [ArgoCD](https://argoproj.github.io/cd/) via native K8s client | +| **Cluster Provider** | [K3D](https://k3d.io) | +| **Package Manager** | [Helm](https://helm.sh) | +| **Dev Intercept** | [Telepresence](https://www.telepresence.io) | +| **Live Reload** | [Skaffold](https://skaffold.dev) | +| **Testing** | [testify](https://github.com/stretchr/testify) | -OpenFrame is built by the community for the community: +--- -- **OpenMSP Slack**: [Join the community](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) - Primary support channel -- **Website**: [https://flamingo.run](https://flamingo.run) -- **OpenFrame Platform**: [https://openframe.ai](https://openframe.ai) +## Documentation -> **Note**: We don't use GitHub Issues or Discussions. All support and community interaction happens in the OpenMSP Slack community. +πŸ“š See the [Documentation](./docs/README.md) for comprehensive guides including getting started tutorials, development setup, architecture reference, and contributing guidelines. -## License +--- + +## Community & Support + +> We do **not** use GitHub Issues or GitHub Discussions. All questions, bug reports, and feature requests are handled in the OpenMSP Slack community. -This project is licensed under the Flamingo AI Unified License v1.0 - see the [LICENSE.md](LICENSE.md) file for details. +- πŸ’¬ **OpenMSP Slack**: [Join here](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) +- 🌐 **OpenMSP Community**: [https://www.openmsp.ai/](https://www.openmsp.ai/) +- 🌐 **OpenFrame**: [https://openframe.ai](https://openframe.ai) +- 🌐 **Flamingo**: [https://flamingo.run](https://flamingo.run) --- +
Built with πŸ’› by the Flamingo team -
\ No newline at end of file + diff --git a/SECURITY.md b/SECURITY.md index c6999183..49b47610 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -81,7 +81,12 @@ Flamingo AI implements reasonable technical and organizational safeguards, but * Use of Flamingo AI products is entirely at your own risk. Customers are solely responsible for compliance with applicable data protection laws when deploying Flamingo AI software or participating in OpenMSP. -## 11. Contact Information +## 11. Text Messaging Opt-In Data + +Text messaging originator opt-in data and consent will not be shared with any third parties, excluding aggregators and providers of the Text Message services. + + +## 12. Contact Information **Privacy Inquiries:** privacy@flamingo.so **General Information:** info@flamingo.so @@ -89,3 +94,4 @@ Use of Flamingo AI products is entirely at your own risk. Customers are solely r --- *By using Flamingo AI products, you acknowledge and agree to this Privacy Policy.* + diff --git a/docs/README.md b/docs/README.md index 5d0cad47..a3a42f77 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,120 +1,90 @@ # OpenFrame CLI Documentation -Welcome to the comprehensive documentation for OpenFrame CLI - a modern, interactive command-line tool for managing OpenFrame Kubernetes clusters and development workflows. +Welcome to the OpenFrame CLI documentation. This is your central navigation hub for all guides, references, and architecture documentation. -## πŸ“š Table of Contents - -### Getting Started +> **Community Support**: All questions, bug reports, and feature discussions happen in the [OpenMSP Slack](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA). We do not use GitHub Issues or GitHub Discussions. -New to OpenFrame CLI? Start here to get up and running quickly: +--- -- [Introduction](./getting-started/introduction.md) - Overview of OpenFrame CLI and key concepts -- [Prerequisites](./getting-started/prerequisites.md) - System requirements and dependency installation -- [Quick Start](./getting-started/quick-start.md) - Get OpenFrame running in 5 minutes -- [First Steps](./getting-started/first-steps.md) - Explore key features and workflows +## πŸ“š Table of Contents -### Development +- [Getting Started](#-getting-started) +- [Development](#-development) +- [Reference Architecture](#-reference-architecture) +- [Architecture Diagrams](#-architecture-diagrams) +- [Quick Links](#-quick-links) -Resources for developers working on or with OpenFrame CLI: +--- -- [Development Overview](./development/README.md) - Developer documentation index -- [Environment Setup](./development/setup/environment.md) - IDE configuration, tools, and development environment -- [Local Development](./development/setup/local-development.md) - Clone, build, and run OpenFrame CLI locally -- [Architecture Overview](./development/architecture/README.md) - System design and component relationships +## πŸš€ Getting Started -### Reference +New to OpenFrame CLI? Start here. -Technical reference documentation generated from source code analysis: +| Guide | Description | +|---|---| +| [Introduction](./getting-started/introduction.md) | What OpenFrame CLI is, who it's for, and key features | +| [Prerequisites](./getting-started/prerequisites.md) | Hardware requirements, required tools, and OS support | +| [Quick Start](./getting-started/quick-start.md) | Install the CLI and bootstrap your first environment | +| [First Steps](./getting-started/first-steps.md) | What to do after your first successful bootstrap | -- [Architecture Documentation](./architecture/overview.md) - Comprehensive system architecture and component design +**New users:** Start with [Introduction](./getting-started/introduction.md), then follow [Prerequisites](./getting-started/prerequisites.md) β†’ [Quick Start](./getting-started/quick-start.md) β†’ [First Steps](./getting-started/first-steps.md). -### Diagrams +--- -Visual documentation to understand system architecture and workflows: +## πŸ›  Development -- [Architecture Diagrams](./diagrams/architecture/README.md) - Mermaid diagrams showing system design, data flows, and component relationships +Everything you need to contribute to or extend the OpenFrame CLI codebase. -### CLI Tools +| Guide | Description | +|---|---| +| [Development Overview](./development/README.md) | Overview of all development documentation and technology stack | +| [Environment Setup](./development/setup/environment.md) | IDE recommendations, Go toolchain setup, required dev tools | +| [Local Development](./development/setup/local-development.md) | Clone, build, run, debug, and test the CLI locally | +| [Architecture Overview](./development/architecture/README.md) | High-level design, layered architecture, and key data flows | +| [Testing Guide](./development/testing/README.md) | Test structure, running tests, writing unit and integration tests | +| [Security Guidelines](./development/security/README.md) | Authentication, secrets management, and secure coding practices | +| [Contributing Guidelines](./development/contributing/guidelines.md) | Code style, branch naming, commit conventions, and PR process | -The OpenFrame Main code Repository is maintained in a separate repository: -- **Repository**: [flamingo-stack/openframe-oss-tenant](https://github.com/flamingo-stack/openframe-oss-tenant) -- **Documentation**: [CLI Documentation](https://github.com/flamingo-stack/openframe-oss-tenant/tree/main/docs) +--- -**Note**: CLI tools are NOT located in this repository. Always refer to the external repository for installation and usage. +## πŸ“– Reference Architecture -## πŸš€ Quick Navigation +Technical reference documentation generated from source code analysis. -### For New Users -1. Check [Prerequisites](./getting-started/prerequisites.md) -2. Follow [Quick Start](./getting-started/quick-start.md) -3. Explore [First Steps](./getting-started/first-steps.md) +| Document | Description | +|---|---| +| [Architecture Overview](./reference/architecture/overview.md) | Complete architecture reference: components, dependencies, CLI commands, data flows, and key files | -### For Developers -1. Set up [Development Environment](./development/setup/environment.md) -2. Review [Architecture Documentation](./architecture/overview.md) -3. Check [Contributing Guidelines](../CONTRIBUTING.md) +--- -### For System Administrators -1. Review [Prerequisites](./getting-started/prerequisites.md) for system requirements -2. Follow [Bootstrap Guide](./getting-started/quick-start.md#step-3-bootstrap-your-first-environment) -3. Explore cluster management commands in [First Steps](./getting-started/first-steps.md) +## πŸ—Ί Architecture Diagrams -## 🎯 Key Features Covered +Visual representations of the OpenFrame CLI architecture. -This documentation covers all major OpenFrame CLI capabilities: +| Diagram | Description | +|---|---| +| [High-Level Architecture](./diagrams/architecture/high-level-architecture-diagram.mmd) | Top-level view of CLI entry points, services, providers, and external tools | +| [Dependency Flowchart](./diagrams/architecture/dependency-flowchart.mmd) | Layer-by-layer dependency relationships from commands to shared infrastructure | +| [Dependency Interaction Pattern](./diagrams/architecture/dependency-interaction-pattern.mmd) | UI, Kubernetes, CLI framework, and testing dependency groupings | +| [Bootstrap Sequence](./diagrams/architecture/bootstrap-sequence-full-environment-setup.mmd) | Full sequence diagram for the `openframe bootstrap` workflow | +| [Interactive Chart Install](./diagrams/architecture/interactive-chart-install-with-configuration-wizard.mmd) | Sequence diagram for `openframe chart install` with configuration wizard | +| [Diagrams README](./diagrams/architecture/README.md) | Index of all architecture diagrams | -- **Complete Environment Bootstrapping**: One-command setup with `openframe bootstrap` -- **Cluster Management**: Create, delete, and monitor K3D Kubernetes clusters -- **Chart & Application Management**: Helm charts and ArgoCD GitOps workflows -- **Development Tools**: Service intercepts, scaffolding, and local development workflows -- **Multi-mode Deployment**: OSS tenant, SaaS tenant, and SaaS shared configurations +--- ## πŸ“– Quick Links -- [Project README](../README.md) - Main project overview and installation -- [Contributing](../CONTRIBUTING.md) - How to contribute to OpenFrame CLI -- [License](../LICENSE.md) - Project license information - -## πŸ—οΈ System Requirements - -Before using OpenFrame CLI, ensure your system meets these requirements: - -| Resource | Minimum | Recommended | -|----------|---------|-------------| -| **RAM** | 24GB | 32GB | -| **CPU Cores** | 6 cores | 12 cores | -| **Disk Space** | 50GB free | 100GB free | - -## πŸ› οΈ Core Dependencies - -Required tools that must be installed: -- [Docker](https://docs.docker.com/get-docker/) 20.10+ -- [kubectl](https://kubernetes.io/docs/tasks/tools/) 1.25+ -- [Helm](https://helm.sh/docs/intro/install/) 3.10+ -- [K3D](https://k3d.io/v5.4.6/#installation) 5.0+ - -## 🌟 What Makes OpenFrame CLI Different - -- **One-Command Bootstrap**: Complete environment setup with single command -- **Developer-Friendly**: Interactive prompts, clear error messages, rich terminal UI -- **GitOps Native**: Built-in ArgoCD integration for modern deployment practices -- **Local Development**: Telepresence service intercepts for debugging -- **Multi-Platform**: Linux, macOS, and Windows (WSL2) support -- **Open Source**: Complete transparency and community-driven development - -## 🀝 Community and Support - -Need help or want to contribute? - -- **Primary Support**: [OpenMSP Slack](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) -- **Website**: [https://flamingo.run](https://flamingo.run) -- **OpenFrame Platform**: [https://openframe.ai](https://openframe.ai) - -> **Note**: We don't monitor GitHub Issues for support. All community support and discussion happens in our Slack workspace. - -## πŸ“ Documentation Maintenance - -This documentation is automatically generated and maintained by the OpenFrame development team. If you find errors or have suggestions for improvement, please reach out in the OpenMSP Slack community. +| Resource | Link | +|---|---| +| Project README | [../README.md](../README.md) | +| Contributing Guide | [../CONTRIBUTING.md](../CONTRIBUTING.md) | +| License | [../LICENSE.md](../LICENSE.md) | +| GitHub Releases | [https://github.com/flamingo-stack/openframe-cli/releases](https://github.com/flamingo-stack/openframe-cli/releases) | +| OpenMSP Slack | [https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) | +| OpenMSP Community | [https://www.openmsp.ai/](https://www.openmsp.ai/) | +| OpenFrame | [https://openframe.ai](https://openframe.ai) | +| Flamingo | [https://flamingo.run](https://flamingo.run) | --- -*Documentation generated by [OpenFrame Doc Orchestrator](https://github.com/flamingo-stack/openframe-oss-tenant)* \ No newline at end of file + +*Documentation generated by [OpenFrame Doc Orchestrator](https://github.com/flamingo-stack/openframe-oss-tenant)* diff --git a/docs/architecture/overview.md b/docs/architecture/overview.md deleted file mode 100644 index 87ceae9f..00000000 --- a/docs/architecture/overview.md +++ /dev/null @@ -1,321 +0,0 @@ -# openframe-cli Module Documentation - -# OpenFrame CLI Architecture Documentation - -OpenFrame CLI is a modern, interactive command-line tool for managing OpenFrame Kubernetes clusters and development workflows, providing seamless cluster lifecycle management, chart installation with ArgoCD, and developer-friendly tools for service intercepts and scaffolding. - -## Architecture - -### High-Level System Design - -```mermaid -graph TB - subgraph "CLI Layer" - Root[Root Command] - Bootstrap[Bootstrap Command] - Cluster[Cluster Commands] - Chart[Chart Commands] - Dev[Dev Commands] - end - - subgraph "Service Layer" - ClusterSvc[Cluster Service] - ChartSvc[Chart Service] - InterceptSvc[Intercept Service] - ScaffoldSvc[Scaffold Service] - end - - subgraph "Provider Layer" - K3D[K3D Provider] - Helm[Helm Provider] - ArgoCD[ArgoCD Provider] - Telepresence[Telepresence Provider] - Kubectl[Kubectl Provider] - end - - subgraph "External Systems" - Docker[Docker] - K8s[Kubernetes] - Git[Git Repositories] - Registry[Container Registry] - end - - Root --> Bootstrap - Root --> Cluster - Root --> Chart - Root --> Dev - - Bootstrap --> ClusterSvc - Bootstrap --> ChartSvc - Cluster --> ClusterSvc - Chart --> ChartSvc - Dev --> InterceptSvc - Dev --> ScaffoldSvc - - ClusterSvc --> K3D - ChartSvc --> Helm - ChartSvc --> ArgoCD - InterceptSvc --> Telepresence - InterceptSvc --> Kubectl - ScaffoldSvc --> Kubectl - - K3D --> Docker - Helm --> K8s - ArgoCD --> K8s - ArgoCD --> Git - Telepresence --> K8s - Kubectl --> K8s -``` - -## Core Components - -| Component | Package | Responsibility | -|-----------|---------|---------------| -| **CLI Commands** | `cmd/` | Command definitions and argument parsing using Cobra | -| **Cluster Service** | `internal/cluster/` | Kubernetes cluster lifecycle management (K3D) | -| **Chart Service** | `internal/chart/` | Helm chart and ArgoCD application management | -| **Dev Tools** | `internal/dev/` | Development workflows (Telepresence, Skaffold) | -| **Bootstrap Service** | `internal/bootstrap/` | Complete environment setup orchestration | -| **K3D Provider** | `internal/cluster/providers/k3d/` | K3D cluster operations and configuration | -| **Helm Provider** | `internal/chart/providers/helm/` | Helm chart installation and management | -| **ArgoCD Provider** | `internal/chart/providers/argocd/` | ArgoCD application lifecycle and monitoring | -| **Telepresence Provider** | `internal/dev/providers/telepresence/` | Traffic interception for local development | -| **Shared Utilities** | `internal/shared/` | Common functionality (UI, config, errors, execution) | -| **Prerequisites** | `internal/*/prerequisites/` | Tool installation and validation | - -## Component Relationships - -### Dependency Flow Between Modules - -```mermaid -graph TD - subgraph "Command Layer" - RootCmd[Root Command] - BootstrapCmd[Bootstrap Command] - ClusterCmd[Cluster Commands] - ChartCmd[Chart Commands] - DevCmd[Dev Commands] - end - - subgraph "Service Orchestration" - BootstrapSvc[Bootstrap Service] - end - - subgraph "Domain Services" - ClusterSvc[Cluster Service] - ChartSvc[Chart Service] - InterceptSvc[Intercept Service] - ScaffoldSvc[Scaffold Service] - end - - subgraph "Provider Implementations" - K3DMgr[K3D Manager] - HelmMgr[Helm Manager] - ArgoCDMgr[ArgoCD Manager] - TelepresenceProv[Telepresence Provider] - KubectlProv[Kubectl Provider] - GitRepo[Git Repository] - end - - subgraph "Shared Infrastructure" - Executor[Command Executor] - UI[UI Components] - Config[Configuration] - Prerequisites[Prerequisites] - end - - RootCmd --> BootstrapCmd - RootCmd --> ClusterCmd - RootCmd --> ChartCmd - RootCmd --> DevCmd - - BootstrapCmd --> BootstrapSvc - ClusterCmd --> ClusterSvc - ChartCmd --> ChartSvc - DevCmd --> InterceptSvc - DevCmd --> ScaffoldSvc - - BootstrapSvc --> ClusterSvc - BootstrapSvc --> ChartSvc - - ClusterSvc --> K3DMgr - ChartSvc --> HelmMgr - ChartSvc --> ArgoCDMgr - ChartSvc --> GitRepo - InterceptSvc --> TelepresenceProv - InterceptSvc --> KubectlProv - ScaffoldSvc --> KubectlProv - - K3DMgr --> Executor - HelmMgr --> Executor - ArgoCDMgr --> Executor - TelepresenceProv --> Executor - KubectlProv --> Executor - GitRepo --> Executor - - ClusterSvc --> UI - ChartSvc --> UI - InterceptSvc --> UI - ScaffoldSvc --> UI - - ClusterSvc --> Config - ChartSvc --> Config - - ClusterSvc --> Prerequisites - ChartSvc --> Prerequisites - DevCmd --> Prerequisites -``` - -## Data Flow - -### Complete Bootstrap Workflow - -```mermaid -sequenceDiagram - participant User - participant Bootstrap as Bootstrap Service - participant Cluster as Cluster Service - participant K3D as K3D Provider - participant Chart as Chart Service - participant Helm as Helm Provider - participant ArgoCD as ArgoCD Provider - participant K8s as Kubernetes API - - User->>Bootstrap: openframe bootstrap - Bootstrap->>Bootstrap: Check prerequisites - Bootstrap->>Cluster: Create cluster - Cluster->>K3D: Create K3D cluster - K3D->>K8s: Initialize cluster - K8s-->>K3D: Cluster ready - K3D-->>Cluster: Cluster config - Cluster-->>Bootstrap: rest.Config - - Bootstrap->>Chart: Install charts - Chart->>Helm: Install ArgoCD - Helm->>K8s: Deploy ArgoCD - K8s-->>Helm: ArgoCD running - Helm-->>Chart: Installation complete - - Chart->>ArgoCD: Install app-of-apps - ArgoCD->>K8s: Create Application CRDs - K8s-->>ArgoCD: Applications created - ArgoCD->>ArgoCD: Sync applications - ArgoCD-->>Chart: Applications synced - Chart-->>Bootstrap: Charts installed - Bootstrap-->>User: Environment ready -``` - -### Development Intercept Workflow - -```mermaid -sequenceDiagram - participant Dev as Developer - participant Intercept as Intercept Service - participant Kubectl as Kubectl Provider - participant Telepresence as Telepresence Provider - participant K8s as Kubernetes - participant Local as Local Development - - Dev->>Intercept: openframe dev intercept - Intercept->>Kubectl: Get services - Kubectl->>K8s: List services - K8s-->>Kubectl: Service list - Kubectl-->>Intercept: Available services - Intercept->>Dev: Select service/port - Dev->>Intercept: Service selection - - Intercept->>Telepresence: Setup intercept - Telepresence->>K8s: Create intercept - K8s->>Telepresence: Traffic routing active - Telepresence->>Local: Forward traffic - Local->>Dev: Local debugging - - Note over Dev,Local: Development session active - - Dev->>Intercept: Stop intercept (Ctrl+C) - Intercept->>Telepresence: Cleanup intercept - Telepresence->>K8s: Remove routing - K8s-->>Telepresence: Cleanup complete - Telepresence-->>Intercept: Disconnected - Intercept-->>Dev: Session ended -``` - -## Key Files - -| File | Purpose | -|------|---------| -| `main.go` | Application entry point and version configuration | -| `cmd/root.go` | Root command definition and global flag management | -| `cmd/bootstrap/bootstrap.go` | Complete environment bootstrap command | -| `internal/cluster/service.go` | Core cluster management business logic | -| `internal/cluster/providers/k3d/manager.go` | K3D cluster provider implementation | -| `internal/chart/services/chart_service.go` | Chart installation orchestration | -| `internal/chart/providers/helm/manager.go` | Helm chart deployment logic | -| `internal/chart/providers/argocd/applications.go` | ArgoCD application management | -| `internal/dev/services/intercept/service.go` | Telepresence intercept workflow | -| `internal/shared/executor/executor.go` | Command execution abstraction with WSL support | -| `internal/shared/ui/logo.go` | Terminal UI and branding components | - -## Dependencies - -The project integrates with several external tools and libraries: - -### Core Kubernetes Libraries -- **client-go**: Native Kubernetes API access for cluster operations -- **apiextensions**: CRD management for ArgoCD applications -- **kubectl**: Command-line cluster interaction fallback - -### CLI Framework -- **cobra**: Command structure, argument parsing, and help generation -- **pterm**: Rich terminal UI components, spinners, and progress bars -- **promptui**: Interactive prompts and user input validation - -### External Tool Integration -- **K3D**: Lightweight Kubernetes cluster management -- **Helm**: Chart packaging and deployment via command execution -- **ArgoCD**: GitOps application lifecycle through API and CLI -- **Telepresence**: Service mesh traffic interception -- **Docker**: Container runtime for K3D clusters - -### Configuration and State -- **YAML**: Configuration file parsing for Helm values and cluster specs -- **JSON**: Structured data exchange with Kubernetes APIs -- **Home directory**: User configuration and certificate storage - -## CLI Commands - -### Core Commands - -| Command | Description | Example | -|---------|-------------|---------| -| `openframe bootstrap` | Complete environment setup (cluster + charts) | `openframe bootstrap my-cluster` | -| `openframe cluster create` | Create new Kubernetes cluster | `openframe cluster create --nodes 3` | -| `openframe cluster delete` | Remove existing cluster | `openframe cluster delete my-cluster` | -| `openframe cluster list` | Show all available clusters | `openframe cluster list` | -| `openframe cluster status` | Detailed cluster information | `openframe cluster status my-cluster` | -| `openframe chart install` | Install ArgoCD and applications | `openframe chart install` | -| `openframe dev intercept` | Start Telepresence traffic intercept | `openframe dev intercept my-service --port 8080` | -| `openframe dev skaffold` | Development workflow with hot reload | `openframe dev skaffold my-cluster` | - -### Command Options - -**Global Flags:** -- `--verbose, -v`: Enable detailed logging and progress information -- `--dry-run`: Show planned operations without execution -- `--force, -f`: Skip confirmation prompts for automation - -**Bootstrap Flags:** -- `--deployment-mode`: Pre-select deployment type (oss-tenant, saas-tenant, saas-shared) -- `--non-interactive`: Use existing configuration without prompts - -**Cluster Creation Flags:** -- `--nodes, -n`: Number of worker nodes (default: 3) -- `--type, -t`: Cluster type (k3d, gke) -- `--version`: Kubernetes version -- `--skip-wizard`: Use defaults without interactive configuration - -**Development Flags:** -- `--port`: Local port for traffic forwarding -- `--namespace`: Kubernetes namespace for operations -- `--mount`: Mount remote volumes locally -- `--env-file`: Load environment variables from file diff --git a/docs/development/README.md b/docs/development/README.md index 8ef86fdf..419d800d 100644 --- a/docs/development/README.md +++ b/docs/development/README.md @@ -1,180 +1,91 @@ # Development Documentation -This section contains comprehensive guides for developing with and contributing to OpenFrame CLI. Whether you're setting up a development environment, understanding the architecture, or contributing code, these guides will help you get started. +Welcome to the OpenFrame CLI development documentation. This section covers everything you need to contribute to, extend, and work with the OpenFrame CLI codebase. -## πŸ—οΈ Architecture & Design - -Understanding how OpenFrame CLI is structured and how its components interact: - -- **[Architecture Overview](architecture/README.md)** - High-level system design, component relationships, and data flows - -## πŸ› οΈ Development Setup - -Get your development environment ready: - -- **[Environment Setup](setup/environment.md)** - IDE configuration, tools, and development dependencies -- **[Local Development](setup/local-development.md)** - Clone, build, run, and debug OpenFrame CLI locally - -## πŸ”’ Security - -Security best practices and guidelines: +--- -- **[Security Guidelines](security/README.md)** - Authentication patterns, data protection, and vulnerability prevention +## Overview -## πŸ§ͺ Testing +OpenFrame CLI is written in **Go** and uses the **Cobra** framework for CLI command definitions. The project follows a clean layered architecture: commands β†’ services β†’ providers β†’ shared infrastructure. -Comprehensive testing approaches: +[![OpenFrame Preview Webinar](https://img.youtube.com/vi/bINdW0CQbvY/hqdefault.jpg)](https://www.youtube.com/watch?v=bINdW0CQbvY) -- **[Testing Guide](testing/README.md)** - Test structure, running tests, writing new tests, and coverage requirements +--- -## 🀝 Contributing +## Documentation Index -Guidelines for contributing to the project: +| Section | Description | +|---|---| +| [Environment Setup](setup/environment.md) | IDE recommendations, editor plugins, development tools | +| [Local Development](setup/local-development.md) | Cloning, building, running, and debugging locally | +| [Architecture Overview](architecture/README.md) | High-level design, component relationships, data flow diagrams | +| [Security Guidelines](security/README.md) | Authentication, secrets management, secure coding practices | +| [Testing Guide](testing/README.md) | Test structure, running tests, writing new tests | +| [Contributing Guidelines](contributing/guidelines.md) | Code style, PR process, commit conventions | -- **[Contributing Guidelines](contributing/guidelines.md)** - Code standards, review process, and submission guidelines +--- ## Quick Navigation -### New Contributors -If you're new to OpenFrame CLI development, start here: -1. [Architecture Overview](architecture/README.md) - Understand the system -2. [Environment Setup](setup/environment.md) - Configure your tools -3. [Local Development](setup/local-development.md) - Get the code running -4. [Contributing Guidelines](contributing/guidelines.md) - Learn the process - -### Experienced Developers -Jump to specific areas: -- **Architecture**: Deep dive into design patterns and component interactions -- **Security**: Review security models and best practices -- **Testing**: Understand test patterns and coverage expectations - -### Operations & DevOps -Focus on deployment and operational aspects: -- **Architecture**: Service dependencies and operational considerations -- **Security**: Production security requirements and configurations -- **Testing**: Integration and end-to-end testing strategies - -## Development Workflow Overview - -```mermaid -flowchart TD - A[Fork Repository] --> B[Setup Dev Environment] - B --> C[Create Feature Branch] - C --> D[Write Code & Tests] - D --> E[Run Local Tests] - E --> F{Tests Pass?} - F -->|No| D - F -->|Yes| G[Commit Changes] - G --> H[Push to Fork] - H --> I[Create Pull Request] - I --> J[Code Review] - J --> K{Review Approved?} - K -->|No| D - K -->|Yes| L[Merge to Main] - L --> M[CI/CD Pipeline] - M --> N[Deploy & Test] -``` +### "I want to..." -## Key Technologies +| Goal | Go To | +|---|---| +| Set up my dev environment for the first time | [Environment Setup](setup/environment.md) | +| Run the CLI locally from source | [Local Development](setup/local-development.md) | +| Understand how the CLI is structured | [Architecture Overview](architecture/README.md) | +| Add a new CLI command | [Architecture Overview](architecture/README.md) + [Contributing Guidelines](contributing/guidelines.md) | +| Write or run tests | [Testing Guide](testing/README.md) | +| Submit a pull request | [Contributing Guidelines](contributing/guidelines.md) | +| Understand security considerations | [Security Guidelines](security/README.md) | -OpenFrame CLI is built with: +--- -| Technology | Purpose | Version | -|------------|---------|---------| -| **Go** | Primary language | 1.24.6+ | -| **Cobra** | CLI framework | v1.8.1+ | -| **Kubernetes** | Container orchestration | v1.31.2+ | -| **K3D** | Local Kubernetes clusters | v5.0+ | -| **Helm** | Package management | v3.10+ | -| **ArgoCD** | GitOps deployments | v2.14+ | -| **Telepresence** | Service intercepts | v2.10+ | +## Technology Stack + +| Layer | Technology | +|---|---| +| **Language** | Go 1.22+ | +| **CLI Framework** | [Cobra](https://github.com/spf13/cobra) | +| **Terminal UI** | [pterm](https://github.com/pterm/pterm), [promptui](https://github.com/manifoldco/promptui) | +| **Kubernetes Client** | [client-go](https://github.com/kubernetes/client-go) | +| **GitOps** | [ArgoCD](https://argoproj.github.io/cd/) via native K8s client | +| **Cluster Provider** | [K3D](https://k3d.io) | +| **Package Manager** | [Helm](https://helm.sh) | +| **Dev Intercept** | [Telepresence](https://www.telepresence.io) | +| **Live Reload** | [Skaffold](https://skaffold.dev) | +| **Testing** | [testify](https://github.com/stretchr/testify) | -## Project Structure +--- + +## Project Structure at a Glance ```text openframe-cli/ -β”œβ”€β”€ cmd/ # CLI command definitions -β”‚ β”œβ”€β”€ bootstrap/ # Bootstrap command -β”‚ β”œβ”€β”€ cluster/ # Cluster management commands -β”‚ β”œβ”€β”€ chart/ # Chart installation commands -β”‚ β”œβ”€β”€ dev/ # Development workflow commands -β”‚ └── root.go # Root command setup -β”œβ”€β”€ internal/ # Internal packages -β”‚ β”œβ”€β”€ bootstrap/ # Bootstrap orchestration -β”‚ β”œβ”€β”€ cluster/ # Cluster lifecycle management -β”‚ β”œβ”€β”€ chart/ # Chart and ArgoCD integration -β”‚ β”œβ”€β”€ dev/ # Development tools -β”‚ └── shared/ # Common utilities -β”œβ”€β”€ tests/ # Test suites -β”‚ β”œβ”€β”€ integration/ # Integration tests -β”‚ β”œβ”€β”€ mocks/ # Test mocks -β”‚ └── testutil/ # Test utilities -β”œβ”€β”€ docs/ # Documentation -β”œβ”€β”€ examples/ # Usage examples -β”œβ”€β”€ scripts/ # Build and utility scripts -β”œβ”€β”€ go.mod # Go module definition -β”œβ”€β”€ go.sum # Go dependency checksums -└── main.go # Application entry point +β”œβ”€β”€ cmd/ # Cobra command definitions +β”‚ β”œβ”€β”€ root.go # Root command, global flags +β”‚ β”œβ”€β”€ bootstrap/ # bootstrap command +β”‚ β”œβ”€β”€ cluster/ # cluster subcommands (create, delete, list, status, cleanup) +β”‚ β”œβ”€β”€ chart/ # chart subcommands (install) +β”‚ └── dev/ # dev subcommands (intercept, skaffold) +β”œβ”€β”€ internal/ # Internal packages (not exported) +β”‚ β”œβ”€β”€ bootstrap/ # Bootstrap orchestration service +β”‚ β”œβ”€β”€ cluster/ # Cluster lifecycle management +β”‚ β”œβ”€β”€ chart/ # Chart/ArgoCD installation +β”‚ β”œβ”€β”€ dev/ # Developer workflow services +β”‚ └── shared/ # Shared utilities (executor, ui, errors, config) +β”œβ”€β”€ tests/ # Test suites +β”‚ β”œβ”€β”€ integration/ # Integration tests (requires real k3d) +β”‚ β”œβ”€β”€ mocks/ # Mock implementations +β”‚ └── testutil/ # Test utilities and helpers +└── main.go # Application entry point ``` -## Development Principles - -### Code Quality -- **Clean Architecture**: Clear separation of concerns with layered design -- **Testability**: All components designed for easy testing and mocking -- **Error Handling**: Comprehensive error handling with user-friendly messages -- **Documentation**: Code is self-documenting with clear comments - -### User Experience -- **Interactive Design**: Wizard-style interfaces for complex operations -- **Clear Feedback**: Progress indicators and status messages -- **Error Recovery**: Helpful error messages with suggested solutions -- **Consistency**: Uniform command patterns and flag usage - -### Operational Excellence -- **Observability**: Comprehensive logging and monitoring capabilities -- **Reliability**: Robust error handling and recovery mechanisms -- **Performance**: Efficient resource usage and fast execution -- **Security**: Secure defaults and best practices - -## Getting Started - -### Prerequisites -Before diving into development, ensure you have: -- Go 1.24.6 or later installed -- Docker and Kubernetes tools (kubectl, helm, k3d) -- Git and a code editor/IDE -- Basic familiarity with Kubernetes concepts - -### Quick Start -1. **Read the [Architecture Overview](architecture/README.md)** to understand the system -2. **Follow the [Environment Setup](setup/environment.md)** guide -3. **Complete the [Local Development](setup/local-development.md)** setup -4. **Review [Contributing Guidelines](contributing/guidelines.md)** before making changes +--- ## Community & Support -### Getting Help -- **OpenMSP Slack**: [Join the community](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) for development questions -- **Documentation**: Browse these guides for detailed information -- **Code Reviews**: Learn from existing pull requests and code reviews - -### Contributing -We welcome contributions! Here's how to get involved: -1. **Start Small**: Begin with bug fixes or documentation improvements -2. **Discuss Large Changes**: Use Slack to discuss major features or architectural changes -3. **Follow Guidelines**: Adhere to coding standards and review processes -4. **Be Patient**: Maintain a collaborative and respectful approach - -### Code of Conduct -- Be respectful and inclusive in all interactions -- Focus on constructive feedback and learning -- Help others learn and grow in the community -- Follow the project's established patterns and conventions - ---- - -Ready to start developing? Choose your path: -- **New to the project**: Start with [Architecture Overview](architecture/README.md) -- **Ready to code**: Jump to [Local Development](setup/local-development.md) -- **Want to contribute**: Review [Contributing Guidelines](contributing/guidelines.md) \ No newline at end of file +- πŸ’¬ **OpenMSP Slack**: [Join here](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) +- 🌐 **OpenMSP Community**: [https://www.openmsp.ai/](https://www.openmsp.ai/) +- 🌐 **OpenFrame**: [https://openframe.ai](https://openframe.ai) +- 🌐 **Flamingo**: [https://flamingo.run](https://flamingo.run) diff --git a/docs/development/architecture/README.md b/docs/development/architecture/README.md index c42f299d..c48aaf17 100644 --- a/docs/development/architecture/README.md +++ b/docs/development/architecture/README.md @@ -1,574 +1,290 @@ # Architecture Overview -OpenFrame CLI is built with a clean, layered architecture that separates concerns and provides extensibility. This guide provides a comprehensive overview of the system design, component relationships, and key architectural decisions. +OpenFrame CLI is a structured Go application that orchestrates complex Kubernetes infrastructure operations through a clean layered architecture. This document describes the high-level design, component relationships, and key data flows. -## High-Level Architecture - -OpenFrame CLI follows a layered architecture pattern with clear separation between the CLI interface, business logic, and external integrations: - -```mermaid -graph TB - subgraph "User Interface Layer" - CLI[CLI Commands] - UI[Interactive UI] - Wizard[Setup Wizards] - end - - subgraph "Application Layer" - Bootstrap[Bootstrap Orchestrator] - ClusterMgr[Cluster Manager] - ChartMgr[Chart Manager] - DevTools[Development Tools] - end - - subgraph "Provider Layer" - K3DProvider[K3D Provider] - HelmProvider[Helm Provider] - ArgoCDProvider[ArgoCD Provider] - TelepresenceProvider[Telepresence Provider] - KubectlProvider[kubectl Provider] - GitProvider[Git Provider] - end - - subgraph "Infrastructure Layer" - Executor[Command Executor] - Config[Configuration] - Logger[Logging] - ErrorHandler[Error Handling] - FileSystem[File Operations] - end - - subgraph "External Systems" - Docker[Docker Engine] - K8s[Kubernetes API] - Git[Git Repositories] - Registry[Container Registry] - ArgoCD[ArgoCD Server] - end - - CLI --> Bootstrap - CLI --> ClusterMgr - CLI --> ChartMgr - CLI --> DevTools - - Bootstrap --> ClusterMgr - Bootstrap --> ChartMgr - ClusterMgr --> K3DProvider - ChartMgr --> HelmProvider - ChartMgr --> ArgoCDProvider - DevTools --> TelepresenceProvider - DevTools --> KubectlProvider - - K3DProvider --> Executor - HelmProvider --> Executor - ArgoCDProvider --> Executor - TelepresenceProvider --> Executor - KubectlProvider --> Executor - GitProvider --> Executor - - K3DProvider --> Docker - HelmProvider --> K8s - ArgoCDProvider --> ArgoCD - TelepresenceProvider --> K8s - KubectlProvider --> K8s - GitProvider --> Git -``` +--- -## Core Components +## Design Philosophy -### Command Layer (`cmd/`) +The CLI is designed around three principles: -The command layer implements the CLI interface using the Cobra framework: +1. **Layered separation** β€” Commands never touch infrastructure directly; they delegate to Services, which delegate to Providers, which wrap external tools via a unified Executor. +2. **Interface-driven** β€” All infrastructure providers implement typed interfaces (`ArgoCDService`, `HelmProvider`, `ClusterLister`, etc.) defined in `internal/chart/utils/types/interfaces.go`, enabling easy mocking for tests. +3. **Dual-mode operation** β€” Every workflow supports both interactive (wizard-guided) and non-interactive (flag-driven) modes, making the same binary suitable for human use and CI/CD automation. -| Component | Purpose | Key Features | -|-----------|---------|--------------| -| **Root Command** | Entry point and version management | Interactive help, global flags, subcommand routing | -| **Bootstrap Command** | Complete environment setup | Orchestrates cluster + chart installation | -| **Cluster Commands** | Kubernetes cluster lifecycle | Create, delete, list, status operations | -| **Chart Commands** | Application deployment | Helm charts, ArgoCD applications | -| **Dev Commands** | Development workflows | Service intercepts, scaffolding | - -### Service Layer (`internal/`) - -The service layer contains the core business logic: - -#### Bootstrap Service (`internal/bootstrap/`) -- **Purpose**: Orchestrates complete environment setup -- **Key Functions**: - - Validates prerequisites - - Creates Kubernetes clusters - - Installs core charts (ArgoCD, Traefik) - - Configures GitOps workflows - -```mermaid -sequenceDiagram - participant User - participant Bootstrap - participant Cluster - participant Chart - participant ArgoCD - - User->>Bootstrap: openframe bootstrap - Bootstrap->>Bootstrap: Check prerequisites - Bootstrap->>Cluster: Create K3D cluster - Cluster-->>Bootstrap: Cluster ready - Bootstrap->>Chart: Install ArgoCD - Chart-->>Bootstrap: ArgoCD installed - Bootstrap->>ArgoCD: Deploy app-of-apps - ArgoCD-->>Bootstrap: Applications synced - Bootstrap-->>User: Environment ready -``` - -#### Cluster Service (`internal/cluster/`) -- **Purpose**: Manages Kubernetes cluster lifecycle -- **Key Functions**: - - K3D cluster creation and deletion - - Cluster status monitoring - - Node management and scaling - - Configuration and context management - -#### Chart Service (`internal/chart/`) -- **Purpose**: Manages application deployments -- **Key Functions**: - - Helm chart installation - - ArgoCD application management - - GitOps workflow configuration - - Application synchronization monitoring - -#### Development Services (`internal/dev/`) -- **Purpose**: Provides development workflow tools -- **Key Functions**: - - Service intercepts with Telepresence - - Code scaffolding and templates - - Local development environment setup - - Debug and testing utilities - -### Provider Layer - -The provider layer abstracts external tool integrations: - -#### K3D Provider (`internal/cluster/providers/k3d/`) -```go -type Manager interface { - CreateCluster(config ClusterConfig) (*rest.Config, error) - DeleteCluster(name string) error - ListClusters() ([]ClusterInfo, error) - GetClusterStatus(name string) (*ClusterStatus, error) -} -``` +--- -Key responsibilities: -- Docker container management for K3D nodes -- Kubernetes API server configuration -- Network and port forwarding setup -- Cluster lifecycle management - -#### Helm Provider (`internal/chart/providers/helm/`) -```go -type Manager interface { - InstallChart(release string, chart string, values map[string]interface{}) error - UpgradeChart(release string, chart string, values map[string]interface{}) error - UninstallChart(release string) error - ListReleases() ([]Release, error) -} -``` - -Key responsibilities: -- Helm repository management -- Chart installation and upgrades -- Release lifecycle management -- Value overrides and templating - -#### ArgoCD Provider (`internal/chart/providers/argocd/`) -```go -type Manager interface { - CreateApplication(app ApplicationSpec) error - SyncApplication(name string) error - DeleteApplication(name string) error - WaitForSync(name string, timeout time.Duration) error -} -``` - -Key responsibilities: -- ArgoCD application CRD management -- Git repository synchronization -- Application health monitoring -- Sync policy configuration - -### Shared Infrastructure (`internal/shared/`) - -Common utilities and cross-cutting concerns: - -#### Command Executor (`internal/shared/executor/`) -- **Purpose**: Standardized external command execution -- **Features**: - - Command building and execution - - Output capture and streaming - - Error handling and retry logic - - Timeout management - - Mock support for testing - -#### Configuration Management (`internal/shared/config/`) -- **Purpose**: Application configuration and settings -- **Features**: - - YAML/JSON configuration files - - Environment variable overrides - - Default value management - - Validation and type safety - -#### User Interface (`internal/shared/ui/`) -- **Purpose**: Consistent user interaction patterns -- **Features**: - - Interactive prompts and wizards - - Progress indicators and spinners - - Colored output and formatting - - Table rendering and alignment - - Error message presentation - -## Data Flow Architecture - -### Bootstrap Workflow - -The bootstrap process follows a carefully orchestrated sequence: - -```mermaid -flowchart TD - A[Start Bootstrap] --> B[Check Prerequisites] - B --> C{Prerequisites OK?} - C -->|No| D[Install Missing Tools] - C -->|Yes| E[Validate Configuration] - D --> E - E --> F[Create K3D Cluster] - F --> G[Wait for Cluster Ready] - G --> H[Install ArgoCD] - H --> I[Configure Git Repositories] - I --> J[Deploy App-of-Apps] - J --> K[Wait for Application Sync] - K --> L{All Apps Healthy?} - L -->|No| M[Troubleshoot & Retry] - L -->|Yes| N[Bootstrap Complete] - M --> K -``` - -### Service Interaction Patterns - -Services interact through well-defined interfaces: +## High-Level Architecture ```mermaid -classDiagram - class BootstrapService { - +Execute(config BootstrapConfig) error - -validatePrerequisites() error - -createCluster() error - -installCharts() error - } - - class ClusterService { - +Create(name string) error - +Delete(name string) error - +Status(name string) ClusterStatus - +List() []ClusterInfo - } - - class ChartService { - +Install(chart ChartSpec) error - +List() []ChartInfo - +Sync(name string) error - +WaitForReady(name string) error - } - - BootstrapService --> ClusterService - BootstrapService --> ChartService - ChartService --> ArgocdProvider - ClusterService --> K3dProvider -``` - -## Key Design Decisions - -### 1. Layered Architecture - -**Decision**: Implement strict layering with dependency injection -**Rationale**: -- Clear separation of concerns -- Easier testing through interface mocking -- Flexibility to swap implementations -- Maintainable and extensible codebase - -### 2. Provider Pattern - -**Decision**: Abstract external tools behind provider interfaces -**Rationale**: -- Support multiple Kubernetes distributions (K3D, Kind, etc.) -- Enable testing without external dependencies -- Simplify adding new tool integrations -- Consistent error handling and logging - -### 3. Command Executor Abstraction - -**Decision**: Centralize external command execution -**Rationale**: -- Consistent error handling across all external calls -- Unified logging and debugging capabilities -- Simplified testing with command mocking -- Retry logic and timeout management - -### 4. Interactive CLI Design - -**Decision**: Provide both interactive and non-interactive modes -**Rationale**: -- User-friendly for manual operations -- Scriptable for automation and CI/CD -- Progressive disclosure of complexity -- Clear error messages and guidance +graph TB + subgraph CLI["CLI Entry Points (cmd/)"] + Root["openframe (root)"] + Bootstrap["bootstrap"] + Cluster["cluster"] + Chart["chart"] + Dev["dev"] + end -### 5. GitOps-First Approach + subgraph Services["Service Layer (internal/)"] + BootstrapSvc["bootstrap.Service"] + ClusterSvc["cluster.ClusterService"] + ChartSvc["chart.ChartService"] + DevSvc["dev.Service"] + end -**Decision**: Default to GitOps workflows with ArgoCD -**Rationale**: -- Industry best practices for Kubernetes deployments -- Declarative infrastructure management -- Audit trails and rollback capabilities -- Team collaboration through Git workflows + subgraph Providers["Provider Layer"] + K3dMgr["k3d.K3dManager"] + HelmMgr["helm.HelmManager"] + ArgoCDMgr["argocd.Manager"] + GitRepo["git.Repository"] + TelepresenceProv["telepresence.Provider"] + KubectlProv["kubectl.Provider"] + end -## Error Handling Strategy + subgraph Shared["Shared Infrastructure"] + Executor["shared/executor"] + SharedUI["shared/ui"] + SharedErrors["shared/errors"] + SharedConfig["shared/config"] + end -### Error Types and Handling + subgraph External["External Tools"] + K3D["K3D CLI"] + HelmCLI["Helm CLI"] + ArgoCD["ArgoCD API"] + KubectlCLI["kubectl"] + TelepresenceCLI["Telepresence"] + SkaffoldCLI["Skaffold"] + end -```mermaid -graph TD - A[Error Occurs] --> B{Error Type?} - B -->|Validation Error| C[Show Usage Help] - B -->|External Tool Error| D[Parse Tool Output] - B -->|Network Error| E[Suggest Connectivity Check] - B -->|Resource Error| F[Check Resource Availability] - - C --> G[Exit with Code 1] - D --> H{Recoverable?} - E --> H - F --> H - - H -->|Yes| I[Retry with Backoff] - H -->|No| J[Show Error + Solutions] - - I --> K{Max Retries?} - K -->|No| A - K -->|Yes| J - - J --> G + Root --> Bootstrap + Root --> Cluster + Root --> Chart + Root --> Dev + + Bootstrap --> BootstrapSvc + Cluster --> ClusterSvc + Chart --> ChartSvc + Dev --> DevSvc + + BootstrapSvc --> ClusterSvc + BootstrapSvc --> ChartSvc + ClusterSvc --> K3dMgr + ChartSvc --> HelmMgr + ChartSvc --> ArgoCDMgr + ChartSvc --> GitRepo + DevSvc --> TelepresenceProv + DevSvc --> KubectlProv + + K3dMgr --> Executor + HelmMgr --> Executor + ArgoCDMgr --> Executor + GitRepo --> Executor + TelepresenceProv --> Executor + KubectlProv --> Executor + + Executor --> K3D + Executor --> HelmCLI + ArgoCDMgr --> ArgoCD + Executor --> KubectlCLI + Executor --> TelepresenceCLI + Executor --> SkaffoldCLI + + ClusterSvc --> SharedUI + ChartSvc --> SharedUI + ClusterSvc --> SharedErrors + ChartSvc --> SharedErrors + SharedConfig --> Shared ``` -### Error Categories - -| Category | Examples | Handling Strategy | -|----------|----------|------------------| -| **User Input** | Invalid flags, missing config | Show usage help, suggest corrections | -| **Prerequisites** | Missing tools, permissions | Guide installation, check prerequisites | -| **Network** | Connection timeouts, DNS issues | Retry with backoff, check connectivity | -| **Resource** | Insufficient memory, disk space | Check resources, suggest alternatives | -| **External Tools** | kubectl errors, helm failures | Parse tool output, provide context | - -## Configuration Architecture - -### Configuration Sources (Priority Order) - -1. **Command-line flags** - Highest priority -2. **Environment variables** - Override config files -3. **Configuration files** - User and system configs -4. **Default values** - Built-in sensible defaults - -### Configuration Structure - -```yaml -# ~/.openframe/config.yaml -openframe: - log_level: "info" - config_dir: "~/.openframe" - -cluster: - provider: "k3d" - default_name: "openframe-local" - nodes: 1 - -bootstrap: - mode: "oss-tenant" - timeout: "15m" - interactive: true - -chart: - timeout: "10m" - wait_for_ready: true - -dev: - intercept_timeout: "5m" - scaffold_template_dir: "~/.openframe/templates" -``` +--- -## Testing Architecture +## Core Components -### Test Strategy +| Package | Path | Responsibility | +|---|---|---| +| `cmd` | `cmd/` | Cobra command definitions, flag parsing, entry points | +| `bootstrap` | `internal/bootstrap/` | Orchestrates cluster creation + chart installation sequentially | +| `cluster` | `internal/cluster/` | Cluster lifecycle: create, delete, list, status via K3D | +| `chart/services` | `internal/chart/services/` | ArgoCD + app-of-apps workflow orchestration | +| `chart/providers/argocd` | `internal/chart/providers/argocd/` | Native Kubernetes API calls to ArgoCD, application polling | +| `chart/providers/helm` | `internal/chart/providers/helm/` | Helm CLI wrapper, chart install/upgrade | +| `chart/providers/git` | `internal/chart/providers/git/` | Git clone of app-of-apps repos to temp directories | +| `chart/ui/configuration` | `internal/chart/ui/configuration/` | Interactive wizard for deployment mode, Docker, ingress | +| `cluster/providers/k3d` | `internal/cluster/providers/k3d/` | K3D cluster CRUD, kubeconfig management, WSL2 support | +| `cluster/prerequisites` | `internal/cluster/prerequisites/` | Validates Docker, kubectl, k3d, helm prerequisites | +| `chart/prerequisites` | `internal/chart/prerequisites/` | Validates Git, Helm, mkcert, memory requirements | +| `dev/services/intercept` | `internal/dev/services/intercept/` | Telepresence intercept lifecycle management | +| `dev/services/scaffold` | `internal/dev/services/scaffold/` | Skaffold workflow: cluster bootstrap + live reload | +| `shared/executor` | `internal/shared/executor/` | Unified command execution (real + mock), WSL2 helpers | +| `shared/ui` | `internal/shared/ui/` | Logo, prompts, tables, progress, message templates | +| `shared/errors` | `internal/shared/errors/` | Typed errors, retry policies, user-facing formatting | +| `shared/config` | `internal/shared/config/` | TLS config, credentials prompting | + +--- + +## Bootstrap Data Flow + +The `openframe bootstrap` command is the primary workflow. Here is the full sequence: ```mermaid -graph TB - subgraph "Unit Tests" - A[Service Logic Tests] - B[Provider Tests with Mocks] - C[Utility Function Tests] - end - - subgraph "Integration Tests" - D[End-to-End Command Tests] - E[Provider Integration Tests] - F[External Tool Integration] - end - - subgraph "Acceptance Tests" - G[Complete Bootstrap Workflow] - H[Multi-Cluster Scenarios] - I[Development Workflow Tests] - end - - A --> D - B --> E - C --> F - D --> G - E --> H - F --> I +sequenceDiagram + participant User + participant CLI as "cmd/bootstrap" + participant BSvc as "bootstrap.Service" + participant CSvc as "cluster.ClusterService" + participant K3dMgr as "k3d.K3dManager" + participant ChartSvc as "chart.ChartService" + participant HelmMgr as "helm.HelmManager" + participant ArgoCDMgr as "argocd.Manager" + participant GitRepo as "git.Repository" + + User->>CLI: openframe bootstrap [cluster-name] + CLI->>BSvc: Execute(cmd, args) + BSvc->>CSvc: CreateClusterWithPrerequisitesNonInteractive() + CSvc->>K3dMgr: CreateCluster(config) + K3dMgr-->>CSvc: rest.Config (kubeConfig) + CSvc-->>BSvc: rest.Config + + BSvc->>ChartSvc: InstallChartsWithConfig(InstallationRequest) + ChartSvc->>HelmMgr: InstallArgoCDWithProgress(ctx, cfg) + HelmMgr-->>ChartSvc: ArgoCD deployed + + ChartSvc->>GitRepo: CloneChartRepository(ctx, appConfig) + GitRepo-->>ChartSvc: CloneResult{TempDir, ChartPath} + + ChartSvc->>HelmMgr: InstallAppOfAppsFromLocal(ctx, config) + HelmMgr-->>ChartSvc: App-of-apps deployed + + ChartSvc->>ArgoCDMgr: WaitForApplications(ctx, config) + ArgoCDMgr->>ArgoCDMgr: Poll ArgoCD health/sync status + ArgoCDMgr-->>ChartSvc: All applications Healthy + Synced + + ChartSvc-->>BSvc: success + BSvc-->>User: Environment ready ``` -### Mock Strategy - -- **External Commands**: Mock command executor for tool interactions -- **Kubernetes API**: Use fake clientsets for API testing -- **File System**: Mock file operations for config testing -- **Network**: Mock HTTP clients for external service calls - -## Security Architecture - -### Security Principles +--- -1. **Least Privilege**: Request minimal permissions necessary -2. **Secure Defaults**: Safe configurations out of the box -3. **Input Validation**: Sanitize all user inputs -4. **Secret Management**: Secure handling of credentials and keys -5. **Audit Logging**: Track security-relevant operations - -### Trust Boundaries +## Dependency Layers ```mermaid graph LR - subgraph "Trusted Zone" - A[OpenFrame CLI] - B[Local Kubernetes] - C[Local Docker] - end - - subgraph "Semi-Trusted Zone" - D[Container Images] - E[Helm Charts] - F[Git Repositories] - end - - subgraph "Untrusted Zone" - G[Public Internet] - H[External APIs] - I[User Input] + subgraph Commands["cmd Layer"] + CmdBootstrap["cmd/bootstrap"] + CmdCluster["cmd/cluster"] + CmdChart["cmd/chart"] + CmdDev["cmd/dev"] end - - A --> B - A --> C - B --> D - A --> E - A --> F - - E --> G - F --> G - A --> H - I --> A -``` -## Performance Considerations + subgraph Services["Service Layer"] + SvcBootstrap["bootstrap/service.go"] + SvcCluster["cluster/service.go"] + SvcChart["chart/services/chart_service.go"] + SvcInstaller["chart/services/installer.go"] + SvcIntercept["dev/services/intercept"] + SvcScaffold["dev/services/scaffold"] + end -### Optimization Strategies + subgraph Providers["Provider Layer"] + ProvK3d["cluster/providers/k3d"] + ProvHelm["chart/providers/helm"] + ProvArgoCD["chart/providers/argocd"] + ProvGit["chart/providers/git"] + ProvTelepresence["dev/providers/telepresence"] + end -1. **Lazy Loading**: Load providers and tools only when needed -2. **Concurrent Operations**: Parallel execution where safe -3. **Caching**: Cache expensive operations (cluster status, etc.) -4. **Resource Monitoring**: Track memory and CPU usage -5. **Efficient Data Structures**: Use appropriate data types + subgraph Shared["Shared Infrastructure"] + Executor["shared/executor"] + UI["shared/ui"] + Errors["shared/errors"] + Config["shared/config"] + end -### Resource Management + CmdBootstrap --> SvcBootstrap + CmdCluster --> SvcCluster + CmdChart --> SvcChart + CmdDev --> SvcIntercept + CmdDev --> SvcScaffold + + SvcBootstrap --> SvcCluster + SvcBootstrap --> SvcChart + SvcChart --> SvcInstaller + SvcCluster --> ProvK3d + SvcInstaller --> ProvHelm + SvcInstaller --> ProvArgoCD + SvcInstaller --> ProvGit + SvcIntercept --> ProvTelepresence + + ProvK3d --> Executor + ProvHelm --> Executor + ProvArgoCD --> Executor + ProvGit --> Executor + ProvTelepresence --> Executor + + SvcCluster --> UI + SvcChart --> UI + SvcChart --> Errors + ProvHelm --> Config + ProvArgoCD --> Config +``` -- **Memory**: Stream large outputs, avoid loading everything in memory -- **CPU**: Use worker pools for concurrent operations -- **Disk**: Clean up temporary files, use appropriate buffer sizes -- **Network**: Connection pooling, request batching where possible +--- -## Extensibility Points +## Key Design Decisions -### Adding New Commands +### 1. CommandExecutor Abstraction -1. **Create command file** in appropriate `cmd/` subdirectory -2. **Implement service logic** in `internal/` package -3. **Add provider interface** if external tool needed -4. **Write comprehensive tests** for all components -5. **Update documentation** and help text +All external tool invocations go through `internal/shared/executor`. This abstraction: +- Allows injecting `MockCommandExecutor` in unit tests with pattern-based response injection +- Handles WSL2 detection and WSL recovery transparently +- Provides consistent error wrapping across all providers -### Adding New Providers +### 2. Interface-Driven Providers -1. **Define provider interface** in appropriate service package -2. **Implement provider** in `internal/*/providers/` directory -3. **Add configuration support** for provider-specific settings -4. **Implement comprehensive testing** including mocks -5. **Update factory functions** to instantiate new provider +All provider types are defined as Go interfaces in `internal/chart/utils/types/interfaces.go`: -### Plugin Architecture (Future) +```go +// Example from the codebase +type ArgoCDService interface { ... } +type HelmProvider interface { ... } +type ClusterLister interface { ... } +``` -Future extensibility through plugins: +This means any provider can be swapped for a mock in tests without changing service code. -```mermaid -graph TB - A[OpenFrame Core] --> B[Plugin Manager] - B --> C[Command Plugins] - B --> D[Provider Plugins] - B --> E[UI Plugins] - - C --> F[Custom Commands] - D --> G[New Tool Integrations] - E --> H[Custom Interfaces] -``` +### 3. Prerequisite Checking Pattern -## Migration and Upgrade Strategy +Both the cluster and chart subsystems use a `PrerequisiteChecker` struct that: +- Checks each tool via a configurable `check` function +- Returns per-tool `Requirement` structs with install instructions +- Can skip auto-install checks in CI environments -### Backward Compatibility +### 4. Wizard vs. Flag Mode -- **Configuration**: Support old config format with migration -- **Commands**: Maintain command compatibility across versions -- **Data**: Migrate user data automatically when needed -- **Dependencies**: Graceful handling of version mismatches +Every command that accepts wizard prompts also accepts equivalent flags. The `--non-interactive` flag disables all prompts and uses provided flags or defaults. This is enforced at the command layer (`cmd/`), not the service layer. -### Version Management +--- -```go -type VersionInfo struct { - Version string // Semantic version - Commit string // Git commit hash - Date string // Build timestamp - Go string // Go version used -} -``` +## External Dependencies -## Next Steps +| Library | Role | +|---|---| +| `github.com/spf13/cobra` | CLI command definitions, flag parsing, subcommand routing | +| `github.com/pterm/pterm` | Spinners, tables, colored output, progress bars | +| `github.com/manifoldco/promptui` | Interactive select menus and text input | +| `k8s.io/client-go` | Native Kubernetes API client for ArgoCD monitoring | +| `github.com/argoproj/argo-cd/v2` | ArgoCD typed clientset | +| `k8s.io/apimachinery` | Kubernetes API types | +| `gopkg.in/yaml.v3` | YAML parsing for Helm values files | +| `sigs.k8s.io/yaml` | YAML marshaling for K8s manifests | +| `github.com/stretchr/testify` | Test assertions | -To deepen your understanding of OpenFrame CLI architecture: +--- -1. **[Security Guidelines](../security/README.md)** - Learn about security implementations -2. **[Testing Guide](../testing/README.md)** - Understand testing strategies -3. **[Contributing Guidelines](../contributing/guidelines.md)** - Learn development processes +## Reference Documentation -## Additional Resources +For detailed per-package documentation, see the full architecture reference: -- **[Architecture Documentation](./architecture/overview.md)** - Generated architecture docs from code -- **Go Design Patterns**: https://golang.org/doc/effective_go -- **Kubernetes Client Libraries**: https://kubernetes.io/docs/reference/using-api/client-libraries/ -- **Cobra CLI Framework**: https://cobra.dev/ -- **OpenMSP Community**: [Join Slack](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) \ No newline at end of file +- [Full Architecture Reference](../../reference/architecture/overview.md) diff --git a/docs/development/contributing/guidelines.md b/docs/development/contributing/guidelines.md new file mode 100644 index 00000000..bd4947ab --- /dev/null +++ b/docs/development/contributing/guidelines.md @@ -0,0 +1,231 @@ +# Contributing Guidelines + +Thank you for contributing to OpenFrame CLI! This document describes the code style conventions, branching strategy, commit message format, and PR review process. + +--- + +## Community First + +OpenFrame is a community-driven project. All discussions, questions, and feature requests happen in the **OpenMSP Slack**: + +πŸ‘‰ [https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) + +> We do **not** use GitHub Issues or GitHub Discussions. Please bring questions, bug reports, and feature ideas to the Slack community at [https://www.openmsp.ai/](https://www.openmsp.ai/). + +--- + +## Code Style and Conventions + +### Go Formatting + +All Go code must be formatted with `goimports` before committing: + +```bash +goimports -w . +``` + +The project uses the standard `gofmt` style with the additional rule that imports are grouped and organized by `goimports`. + +### Naming Conventions + +| Construct | Convention | Example | +|---|---|---| +| Packages | lowercase, no underscores | `cluster`, `executor` | +| Exported types | PascalCase | `ClusterService`, `K3dManager` | +| Unexported types | camelCase | `clusterConfig`, `helmValues` | +| Interfaces | PascalCase, noun or adjective | `ClusterLister`, `HelmProvider` | +| Functions/Methods | PascalCase (exported), camelCase (unexported) | `CreateCluster`, `validateInputs` | +| Constants | PascalCase (exported), camelCase (unexported) | `DeploymentModeOSS` | +| Test files | `_test.go` suffix | `service_test.go` | +| Mock files | `mock.go` or `_mock.go` | `mock.go` | + +### Code Organization + +Follow the existing layered architecture: + +```text +cmd/ β†’ Command definitions only (flag parsing, delegation to services) +internal/ β†’ All business logic + └── / + β”œβ”€β”€ service.go # Main service struct and methods + β”œβ”€β”€ models/ # Domain types and flag structs + β”œβ”€β”€ providers// # External tool wrappers + β”œβ”€β”€ prerequisites/ # Tool prerequisite checkers + └── ui/ # Interactive prompts and display +``` + +**Rules:** +- Commands in `cmd/` must not call external tools directly β€” delegate to service layer +- Services must not call external tools directly β€” delegate to providers +- Providers must use `shared/executor` for all subprocess execution +- Interfaces must be defined in `utils/types/interfaces.go` for testability + +### Error Handling + +Use the typed error constructors from `internal/shared/errors/`: + +```go +// For user input validation failures +return errors.CreateValidationError("cluster-name", name, "must be alphanumeric") + +// For external command failures +return errors.CreateCommandError("k3d", args, originalErr) + +// For git branch not found +return &errors.BranchNotFoundError{Branch: branchName} +``` + +Do not return raw `fmt.Errorf` from user-facing code paths. The error handler uses type switching to display appropriate messages and troubleshooting tips. + +### Interface Compliance + +Always add compile-time interface assertion when implementing an interface: + +```go +// At the top of your implementation file, not in tests +var _ types.ClusterLister = (*ClusterService)(nil) +``` + +--- + +## Branch Naming + +| Type | Pattern | Example | +|---|---|---| +| Feature | `feature/` | `feature/add-cluster-resize` | +| Bug fix | `fix/` | `fix/k3d-wsl2-ip-detection` | +| Documentation | `docs/` | `docs/update-intercept-guide` | +| Refactor | `refactor/` | `refactor/executor-abstraction` | +| Chore | `chore/` | `chore/update-dependencies` | + +**Rules:** +- Use lowercase and hyphens (no underscores, no slashes after the type prefix) +- Keep descriptions concise (2–5 words) +- Branch from `main` for features and fixes + +--- + +## Commit Message Format + +OpenFrame CLI follows the [Conventional Commits](https://www.conventionalcommits.org/) specification: + +```text +(): + +[optional body] + +[optional footer(s)] +``` + +### Types + +| Type | When to Use | +|---|---| +| `feat` | A new feature | +| `fix` | A bug fix | +| `docs` | Documentation only changes | +| `refactor` | Code change that neither fixes a bug nor adds a feature | +| `test` | Adding or correcting tests | +| `chore` | Build process, dependency updates, tooling | +| `perf` | Performance improvement | + +### Scopes + +Use the top-level package or area name as the scope: + +`cluster`, `chart`, `bootstrap`, `dev`, `executor`, `ui`, `errors`, `config`, `prereqs`, `ci` + +### Examples + +```text +feat(cluster): add support for multi-node k3d clusters + +fix(dev): resolve WSL2 IP detection for Telepresence intercepts + +docs(chart): update wizard configuration wizard documentation + +test(executor): add mock response patterns for helm upgrade + +chore(deps): update k8s.io/client-go to v0.30.0 +``` + +### Breaking Changes + +Add `BREAKING CHANGE:` in the commit footer: + +```text +feat(bootstrap): change default deployment mode to oss-tenant + +BREAKING CHANGE: The default --deployment-mode flag value has changed +from "saas-tenant" to "oss-tenant". Update your CI/CD pipelines to +explicitly specify --deployment-mode=saas-tenant if needed. +``` + +--- + +## Pull Request Process + +### Before Opening a PR + +- [ ] Run `go test -race ./...` β€” all tests pass +- [ ] Run `golangci-lint run ./...` β€” no lint errors +- [ ] Run `goimports -w .` β€” code is formatted +- [ ] Run `govulncheck ./...` β€” no new vulnerabilities +- [ ] Add tests for any new functionality +- [ ] Update relevant documentation if behavior changes + +### PR Title + +Follow the same Conventional Commits format as commit messages: + +```text +feat(cluster): add cluster resize command +fix(chart): handle missing ArgoCD CRD during wait +``` + +### PR Description Template + +```markdown +## Summary +Brief description of what this PR does. + +## Changes +- Added X +- Fixed Y +- Updated Z + +## Testing +How you tested this change (unit tests added, manual testing steps). + +## Breaking Changes +Any breaking changes and migration steps. +``` + +### PR Size Guidelines + +- **Small PRs** (< 200 lines changed): Preferred β€” easier to review and merge quickly +- **Medium PRs** (200–500 lines): Acceptable β€” include detailed description +- **Large PRs** (> 500 lines): Split into smaller PRs where possible + +--- + +## Review Checklist + +Reviewers should check: + +- [ ] Code follows the layered architecture (cmd β†’ service β†’ provider β†’ executor) +- [ ] New commands delegate to services, not external tools directly +- [ ] Error types use the shared error constructors +- [ ] External command invocations use the executor abstraction (no `exec.Command` directly) +- [ ] User input is validated before use in system commands +- [ ] New public types and functions have Go doc comments +- [ ] Tests cover the happy path and at least one error path +- [ ] No hardcoded secrets, tokens, or passwords +- [ ] Interface compliance assertions are present for new interface implementations +- [ ] `--non-interactive` mode works correctly for any new wizard prompts + +--- + +## Developer Certificate of Origin + +By contributing to this project, you certify that your contribution is your original work (or that you have the right to submit it) and that you agree to license it under the project's open-source license. diff --git a/docs/development/security/README.md b/docs/development/security/README.md new file mode 100644 index 00000000..9b234f01 --- /dev/null +++ b/docs/development/security/README.md @@ -0,0 +1,189 @@ +# Security Guidelines + +This document outlines the security practices, patterns, and considerations for developing and operating the OpenFrame CLI. + +--- + +## Authentication and Authorization + +### Kubernetes Access Control + +OpenFrame CLI uses `kubeconfig` for all Kubernetes API authentication. The CLI never stores Kubernetes credentials; it reads them from the standard kubeconfig file at the path specified by the `$KUBECONFIG` environment variable or the default `~/.kube/config`. + +```bash +# Use a specific kubeconfig +export KUBECONFIG="$HOME/.kube/my-cluster-config" +openframe cluster status my-cluster +``` + +**Best practices:** +- Use dedicated kubeconfig contexts per cluster (do not use the `admin` context in production) +- Rotate kubeconfig credentials regularly +- Do not share kubeconfig files across team members + +### ArgoCD Authentication + +The CLI communicates with ArgoCD using the native Kubernetes API client (`k8s.io/client-go`) β€” it reads ArgoCD `Application` resources directly from the cluster rather than through ArgoCD's HTTP API. This avoids storing ArgoCD passwords and relies on the RBAC already granted via kubeconfig. + +### GitHub Credentials + +For `saas-tenant` and `saas-shared` deployment modes that require access to private GHCR (GitHub Container Registry) images, the CLI prompts for GitHub credentials at runtime using the `CredentialsPrompter`: + +- Credentials are provided interactively via masked terminal input +- Credentials are **never stored to disk** by the CLI +- They are passed directly to Helm as chart values or to Docker login commands in-process + +```bash +# The CLI will prompt you when credentials are needed: +# Enter GitHub username: +# Enter GitHub personal access token (PAT): **** +``` + +Use a **Personal Access Token (PAT)** with only the `read:packages` scope for GHCR access β€” never use your GitHub password. + +--- + +## Secrets Management + +### Do Not Store Secrets in Code + +Never commit credentials, tokens, or certificates to the repository. The project's `internal/shared/config/credentials.go` provides runtime prompting specifically to avoid hardcoded secrets. + +```go +// CORRECT β€” prompt at runtime +creds, err := prompter.PromptForGitHubCredentials(repoURL) + +// WRONG β€” never do this +const githubToken = "ghp_abc123..." // ❌ Never hardcode secrets +``` + +### Environment Variables + +For CI/CD pipelines, pass secrets via environment variables rather than CLI flags (flags may appear in process listings): + +```bash +# CI/CD: pass via environment variables to your pipeline secrets manager +# Then reference them in non-interactive mode +openframe bootstrap my-cluster \ + --deployment-mode=oss-tenant \ + --non-interactive +``` + +### TLS Certificates + +The CLI uses `mkcert` to generate locally-trusted TLS certificates for K3D clusters. Key behaviors: + +- `internal/shared/config/transport.go` applies `ApplyInsecureTLSConfig()` only for K3D local clusters (never for production clusters) +- Certificate files are written to a temp directory and cleaned up after use +- The `chart/prerequisites/certificates` module manages certificate lifecycle + +> **Important:** The `InsecureTLSConfig` is **only** applied for local K3D development environments. Do not use this configuration pattern for connecting to production clusters. + +--- + +## Input Validation and Sanitization + +### Cluster Name Validation + +All user-provided cluster names go through `ValidateClusterName()` in `internal/cluster/models/flags.go` before being used in any system command. This prevents command injection via specially crafted cluster names. + +```go +// Validation enforces safe name format before use +if err := models.ValidateClusterName(clusterName); err != nil { + return errors.CreateValidationError("cluster-name", clusterName, err.Error()) +} +``` + +### Port Validation + +Intercept port values are validated by `validateInputs()` in `internal/dev/services/intercept/service.go` to ensure they are valid TCP port numbers before being passed to Telepresence. + +### Command Injection Prevention + +The `shared/executor` abstraction executes all external tool commands by passing arguments as a slice (not a shell-interpolated string). This is the idiomatic Go pattern that prevents shell injection: + +```go +// CORRECT β€” args are individual slice elements, no shell interpolation +executor.Execute("k3d", []string{"cluster", "create", clusterName, "--agents", "2"}) + +// WRONG β€” never build shell strings with user input +exec.Command("sh", "-c", "k3d cluster create " + clusterName) // ❌ Injection risk +``` + +--- + +## Sensitive Data in Logs + +### Verbose Mode Caution + +The `--verbose` flag enables detailed logging including ArgoCD sync progress. Review verbose output before sharing logs publicly β€” it may include: + +- Kubernetes namespace names and resource names +- Helm chart values (which may reference registry URLs) +- kubeconfig context names + +Do not share verbose output in public channels without reviewing it first. + +### Error Messages + +The `shared/errors` package formats user-facing error messages using `pterm`. Error messages are designed to be informative without leaking internal details. If you add new error types, follow this pattern: + +```go +// CORRECT β€” descriptive but safe +return CreateValidationError("port", portValue, "must be between 1 and 65535") + +// WRONG β€” may expose internal state +return fmt.Errorf("internal state: %+v failed at %s", internalStruct, secretPath) +``` + +--- + +## Dependency Security + +### Vulnerability Scanning + +Run the Go vulnerability scanner against the project dependencies regularly: + +```bash +govulncheck ./... +``` + +Fix any identified vulnerabilities by updating the affected dependency in `go.mod`: + +```bash +go get github.com/vulnerable/package@latest +go mod tidy +``` + +### Dependency Review + +When adding new dependencies, evaluate: +1. Is the package actively maintained? +2. Does it have known CVEs? +3. Is the scope minimal (does not pull in unnecessary transitive dependencies)? +4. Is it from a trusted source? + +--- + +## Code Review Security Checklist + +When reviewing pull requests, check for: + +- [ ] No hardcoded secrets, tokens, passwords, or API keys +- [ ] User input is validated before use in system commands +- [ ] External commands use argument slices (not shell string interpolation) +- [ ] Sensitive values are not logged in verbose output +- [ ] New error types do not expose internal implementation details +- [ ] TLS configuration is not relaxed outside the K3D local context +- [ ] New dependencies have been reviewed for security issues +- [ ] Certificate or credentials handling matches existing patterns in `internal/shared/config/` + +--- + +## Reporting Security Issues + +Do not report security vulnerabilities in public GitHub Issues. Instead, reach out directly through the **OpenMSP Slack** community: + +πŸ‘‰ [https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) + +- 🌐 OpenMSP Community: [https://www.openmsp.ai/](https://www.openmsp.ai/) diff --git a/docs/development/setup/environment.md b/docs/development/setup/environment.md index 9f95aa1e..9f4c19db 100644 --- a/docs/development/setup/environment.md +++ b/docs/development/setup/environment.md @@ -1,621 +1,193 @@ # Development Environment Setup -This guide walks you through setting up a complete development environment for OpenFrame CLI, including IDEs, tools, extensions, and configuration for maximum productivity. +This guide walks you through configuring your local development environment for contributing to or extending the OpenFrame CLI. -## IDE and Editor Setup +--- -### Visual Studio Code (Recommended) +## Required Development Tools + +| Tool | Version | Purpose | +|---|---|---| +| **Go** | 1.22+ | Primary language β€” compile and test the CLI | +| **Git** | 2.x+ | Version control | +| **Docker** | 20.x+ (daemon running) | K3D cluster container runtime | +| **k3d** | 5.x+ | Local Kubernetes clusters for integration testing | +| **kubectl** | 1.25+ | Kubernetes API client | +| **Helm** | 3.x+ | Kubernetes package manager | +| **mkcert** | Latest | Local TLS certificate generation | +| **make** | Any | Build task runner (optional, but helpful) | + +--- + +## Installing Go -VS Code provides excellent Go support and Kubernetes tooling: +### Linux / macOS -#### Installation ```bash -# macOS -brew install --cask visual-studio-code - -# Ubuntu/Debian -wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > packages.microsoft.gpg -sudo install -o root -g root -m 644 packages.microsoft.gpg /etc/apt/trusted.gpg.d/ -sudo sh -c 'echo "deb [arch=amd64,arm64,armhf signed-by=/etc/apt/trusted.gpg.d/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main" > /etc/apt/sources.list.d/vscode.list' -sudo apt update -sudo apt install code +# Download and install Go (replace VERSION with latest, e.g. 1.22.4) +curl -Lo go.tar.gz https://go.dev/dl/go1.22.4.linux-amd64.tar.gz +sudo tar -C /usr/local -xzf go.tar.gz +echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.profile +source ~/.profile ``` -#### Essential Extensions - -Install these extensions for Go and Kubernetes development: +Verify: ```bash -# Core Go development -code --install-extension golang.Go -code --install-extension golang.Go-nightly +go version +``` -# Kubernetes and YAML -code --install-extension ms-kubernetes-tools.vscode-kubernetes-tools -code --install-extension redhat.vscode-yaml +### Windows (WSL2) -# Git and GitHub integration -code --install-extension GitHub.vscode-pull-request-github -code --install-extension eamodio.gitlens +Install Go inside your WSL2 environment using the Linux instructions above. Do not install the Windows Go binary for CLI development β€” the project compiles inside the WSL2 Linux environment. -# Code quality and testing -code --install-extension ms-vscode.test-adapter-converter -code --install-extension hbenl.vscode-test-explorer -code --install-extension SonarSource.sonarlint-vscode +--- -# Docker and containers -code --install-extension ms-azuretools.vscode-docker +## IDE Recommendations -# Markdown and documentation -code --install-extension yzhang.markdown-all-in-one -code --install-extension bierner.markdown-mermaid +### Visual Studio Code (Recommended) -# Productivity -code --install-extension vscodevim.vim # Optional: Vim keybindings -code --install-extension ms-vscode.vscode-json -``` +VS Code with the official Go extension provides the best experience for this project. -#### VS Code Configuration +**Required Extensions:** -Create `.vscode/settings.json` in your workspace: +| Extension | ID | Purpose | +|---|---|---| +| Go | `golang.go` | Language server, debugging, testing | +| YAML | `redhat.vscode-yaml` | Helm values file editing | +| Docker | `ms-azuretools.vscode-docker` | Dockerfile and container management | + +**Install all at once:** + +```bash +code --install-extension golang.go +code --install-extension redhat.vscode-yaml +code --install-extension ms-azuretools.vscode-docker +``` + +**Recommended VS Code settings for this project** (`.vscode/settings.json`): ```json { - "go.toolsManagement.autoUpdate": true, "go.useLanguageServer": true, - "go.gopath": "", - "go.goroot": "", "go.lintTool": "golangci-lint", - "go.lintFlags": [ - "--fast" - ], - "go.vetOnSave": "package", "go.formatTool": "goimports", - "go.buildOnSave": "package", - "go.testFlags": ["-v"], - "go.testTimeout": "30s", - "go.coverOnSave": false, - "go.coverOnSingleTest": true, - "go.coverOnSingleTestFile": true, - "go.coverOnTestPackage": true, + "go.testFlags": ["-v", "-race"], "editor.formatOnSave": true, - "editor.codeActionsOnSave": { - "source.organizeImports": true - }, - "files.eol": "\n", - "yaml.schemas": { - "https://json.schemastore.org/kustomization": [ - "kustomization.yaml", - "kustomization.yml" - ], - "https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/crds/application-crd.yaml": [ - "**/argocd-apps/*.yaml", - "**/argocd-apps/*.yml" - ] - }, - "kubernetes.namespace": "default", - "kubernetes.defaultLogLevel": "info" -} -``` - -Create `.vscode/launch.json` for debugging: - -```json -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Launch OpenFrame CLI", - "type": "go", - "request": "launch", - "mode": "auto", - "program": "${workspaceFolder}/main.go", - "args": ["--help"], - "env": { - "GO_ENV": "development" - } - }, - { - "name": "Debug Bootstrap Command", - "type": "go", - "request": "launch", - "mode": "auto", - "program": "${workspaceFolder}/main.go", - "args": ["bootstrap", "--verbose", "--non-interactive"], - "env": { - "GO_ENV": "development" - } - }, - { - "name": "Debug Cluster Status", - "type": "go", - "request": "launch", - "mode": "auto", - "program": "${workspaceFolder}/main.go", - "args": ["cluster", "status"], - "env": { - "GO_ENV": "development" - } - } - ] + "[go]": { + "editor.defaultFormatter": "golang.go" + } } ``` -### GoLand/IntelliJ IDEA +### GoLand (JetBrains) -For JetBrains IDEs: +GoLand provides excellent built-in Go support with no additional plugins required. Recommended for developers who prefer a full IDE experience. -#### Installation -```bash -# macOS -brew install --cask goland +--- -# Or download from https://www.jetbrains.com/go/ -``` +## Go Toolchain Setup -#### Configuration -1. **Go Settings**: File β†’ Settings β†’ Go β†’ GOROOT and GOPATH -2. **Code Style**: File β†’ Settings β†’ Editor β†’ Code Style β†’ Go -3. **Live Templates**: File β†’ Settings β†’ Editor β†’ Live Templates -4. **Kubernetes Plugin**: File β†’ Settings β†’ Plugins β†’ Install "Kubernetes" - -### Vim/Neovim - -For terminal-based editing: - -#### Installation -```bash -# Install vim-go plugin manager -curl -fLo ~/.vim/autoload/plug.vim --create-dirs \ - https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim -``` - -Add to `~/.vimrc`: -```vim -call plug#begin('~/.vim/plugged') -Plug 'fatih/vim-go', { 'do': ':GoUpdateBinaries' } -Plug 'neoclide/coc.nvim', {'branch': 'release'} -Plug 'preservim/nerdtree' -Plug 'airblade/vim-gitgutter' -call plug#end() - -" Go-specific settings -let g:go_fmt_command = "goimports" -let g:go_auto_type_info = 1 -let g:go_highlight_types = 1 -let g:go_highlight_fields = 1 -let g:go_highlight_functions = 1 -let g:go_highlight_function_calls = 1 -``` - -## Development Tools - -### Go Tools Installation - -Install essential Go development tools: +After installing Go, install these additional development tools: ```bash -# Core Go tools +# Install goimports (code formatter that also manages imports) go install golang.org/x/tools/cmd/goimports@latest -go install golang.org/x/tools/cmd/godoc@latest -go install golang.org/x/tools/cmd/gofmt@latest - -# Linting and code quality -go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest -go install honnef.co/go/tools/cmd/staticcheck@latest -go install github.com/kisielk/errcheck@latest - -# Testing tools -go install github.com/rakyll/gotest@latest -go install github.com/axw/gocov/gocov@latest -go install github.com/AlekSi/gocov-xml@latest -# Documentation tools -go install golang.org/x/tools/cmd/godoc@latest +# Install golangci-lint (comprehensive linter) +curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.57.0 -# Binary management -go install github.com/cosmtrek/air@latest # Hot reload -go install github.com/goreleaser/goreleaser@latest # Release management +# Install govulncheck (security vulnerability scanner) +go install golang.org/x/vuln/cmd/govulncheck@latest ``` -### Configure golangci-lint - -Create `.golangci.yml` in the project root: - -```yaml -run: - timeout: 5m - issues-exit-code: 1 - tests: true - -linters-settings: - golint: - min-confidence: 0 - gocyclo: - min-complexity: 15 - goimports: - local-prefixes: github.com/flamingo-stack/openframe-cli - govet: - check-shadowing: true - errcheck: - check-type-assertions: true - check-blank: true - unused: - check-exported: false - -linters: - enable: - - bodyclose - - deadcode - - depguard - - dogsled - - dupl - - errcheck - - exportloopref - - exhaustive - - goconst - - gocritic - - gofmt - - goimports - - golint - - goprintffuncname - - gosec - - gosimple - - govet - - ineffassign - - misspell - - nakedret - - noctx - - nolintlint - - rowserrcheck - - staticcheck - - structcheck - - stylecheck - - typecheck - - unconvert - - unparam - - unused - - varcheck - - whitespace - -issues: - exclude-rules: - - path: _test\.go - linters: - - gosec - - dupl - exclude-use-default: false - exclude: - - "Error return value of .((os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*print.*|os\.(Un)?Setenv). is not checked" -``` - -### Shell Configuration - -Add helpful aliases and functions to your shell profile: +Verify the linter: ```bash -# Add to ~/.bashrc, ~/.zshrc, or ~/.fish -# OpenFrame development aliases -alias of="go run main.go" -alias oft="go test ./..." -alias ofb="go build -o openframe main.go" -alias ofl="golangci-lint run" - -# Go development aliases -alias gob="go build" -alias got="go test" -alias gor="go run" -alias gof="go fmt ./..." -alias goi="goimports -w ." -alias gol="golangci-lint run" - -# Kubernetes aliases for development -alias k="kubectl" -alias kgp="kubectl get pods" -alias kgs="kubectl get svc" -alias kgd="kubectl get deployment" -alias kdp="kubectl describe pod" -alias kl="kubectl logs" -alias kex="kubectl exec -it" - -# OpenFrame specific kubectl contexts -alias kof="kubectl config use-context k3d-openframe-local" -alias kctx="kubectl config current-context" -alias kns="kubectl config set-context --current --namespace" - -# Docker aliases -alias d="docker" -alias dc="docker compose" -alias dps="docker ps" -alias di="docker images" -alias dl="docker logs" - -# Git aliases for development workflow -alias gs="git status" -alias ga="git add" -alias gc="git commit" -alias gp="git push" -alias gl="git pull" -alias gb="git branch" -alias gco="git checkout" -alias gd="git diff" +golangci-lint --version ``` -## Environment Variables +--- -Set up development environment variables: +## Environment Variables for Development -```bash -# Add to your shell profile (~/.bashrc, ~/.zshrc, etc.) +Set these in your shell profile (`~/.bashrc`, `~/.zshrc`, or equivalent): -# Go development +```bash +# Go workspace export GOPATH="$HOME/go" -export GOROOT="$(go env GOROOT)" -export PATH="$GOPATH/bin:$GOROOT/bin:$PATH" - -# OpenFrame CLI development -export OPENFRAME_LOG_LEVEL="debug" -export OPENFRAME_CONFIG_DIR="$HOME/.openframe-dev" -export OPENFRAME_DEV_MODE="true" +export PATH="$PATH:$GOPATH/bin" -# Kubernetes development +# Optional: use a specific kubeconfig for development export KUBECONFIG="$HOME/.kube/config" -export KUBECTL_EXTERNAL_DIFF="diff -u" - -# Docker development -export DOCKER_BUILDKIT=1 -export COMPOSE_DOCKER_CLI_BUILD=1 - -# Development tools -export EDITOR="code" # or vim, nano, etc. -export BROWSER="chrome" # or firefox, safari, etc. - -# Testing -export GO_TEST_TIMEOUT="30s" -export COVERAGE_OUTPUT="coverage.out" -``` - -## Kubernetes Development Setup - -### Configure kubectl contexts - -```bash -# Create separate contexts for development -kubectl config set-context openframe-dev \ - --cluster=k3d-openframe-local \ - --user=admin@k3d-openframe-local - -kubectl config set-context openframe-test \ - --cluster=k3d-openframe-test \ - --user=admin@k3d-openframe-test - -# Use development context by default -kubectl config use-context openframe-dev ``` -### Install Kubernetes development tools +For `saas-tenant` or `saas-shared` development, you may also need: ```bash -# Helm -curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash - -# K3D -curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash - -# Stern for log streaming -brew install stern # macOS -# or download from https://github.com/stern/stern/releases - -# kubectx and kubens for context switching -brew install kubectx # macOS -# or download from https://github.com/ahmetb/kubectx/releases - -# K9s for cluster management -brew install k9s # macOS -# or download from https://github.com/derailed/k9s/releases +# GitHub credentials for private GHCR access (SaaS modes only) +export GITHUB_TOKEN="your-personal-access-token" ``` -## Testing Environment Setup - -### Configure test databases and services +> **Security note:** Never commit tokens to version control. Use environment variables or a secrets manager. -```bash -# Create test namespace -kubectl create namespace openframe-test +--- -# Install test dependencies -helm repo add bitnami https://charts.bitnami.com/bitnami -helm install test-redis bitnami/redis \ - --namespace openframe-test \ - --set auth.enabled=false +## Docker Desktop Configuration (macOS / Windows) -# Install test monitoring -kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/kind/deploy.yaml -``` +For local K3D development, configure Docker Desktop with sufficient resources: -### Test configuration +| Resource | Minimum | Recommended | +|---|---|---| +| Memory | 12 GB | 16+ GB | +| CPUs | 4 | 6+ | +| Disk | 50 GB | 100 GB | -Create `test.env` for test environment variables: +On macOS: **Docker Desktop β†’ Settings β†’ Resources** and adjust sliders accordingly. -```bash -# Test environment configuration -export OPENFRAME_TEST_MODE=true -export OPENFRAME_TEST_CLUSTER="k3d-openframe-test" -export OPENFRAME_TEST_NAMESPACE="openframe-test" -export OPENFRAME_TEST_TIMEOUT="60s" - -# Test database connections -export TEST_REDIS_URL="redis://localhost:6379" -export TEST_DATABASE_URL="postgres://localhost:5432/openframe_test" - -# Integration test settings -export INTEGRATION_TEST_ENABLED=true -export E2E_TEST_ENABLED=false # Disable by default -``` +--- -## Performance and Debugging Tools +## WSL2-Specific Setup -### Install profiling tools +If developing on Windows with WSL2: ```bash -# Go profiling tools -go install github.com/google/pprof@latest -go install github.com/uber/go-torch@latest +# Increase inotify limits (required for Skaffold file watching inside WSL2) +echo "fs.inotify.max_user_watches=524288" | sudo tee -a /etc/sysctl.conf +sudo sysctl -p -# Memory and performance analysis -go install github.com/pkg/profile@latest +# Verify Docker is accessible from WSL2 +docker info ``` -### Configure debugging +The OpenFrame CLI automatically detects WSL2 and applies platform-specific configuration (IP detection, kubeconfig permission fixes) when creating K3D clusters. -Add debug configuration to your project: +--- -```go -// debug/profile.go -// +build debug +## Verifying Your Dev Environment -package debug - -import ( - "github.com/pkg/profile" - "os" -) - -func init() { - if os.Getenv("CPUPROFILE") != "" { - defer profile.Start().Stop() - } - if os.Getenv("MEMPROFILE") != "" { - defer profile.Start(profile.MemProfile).Stop() - } -} -``` - -## Pre-commit Hooks - -Set up git hooks for code quality: +Run this checklist to confirm your environment is ready for development: ```bash -# Install pre-commit (optional but recommended) -pip install pre-commit - -# Create .pre-commit-config.yaml -cat > .pre-commit-config.yaml << 'EOF' -repos: - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 - hooks: - - id: trailing-whitespace - - id: end-of-file-fixer - - id: check-yaml - - id: check-added-large-files - - - repo: https://github.com/dnephin/pre-commit-golang - rev: v0.5.1 - hooks: - - id: go-fmt - - id: go-imports - - id: go-vet-mod - - id: go-unit-tests-mod - - id: golangci-lint-mod -EOF - -# Install the hooks -pre-commit install -``` - -Or create a simple git hook manually: - -```bash -# Create .git/hooks/pre-commit -cat > .git/hooks/pre-commit << 'EOF' -#!/bin/bash -# Pre-commit hook for OpenFrame CLI - -set -e - -echo "Running pre-commit checks..." +# Language +go version # Should show 1.22+ -# Format code -echo "Running gofmt..." -gofmt -l -w . +# VCS +git --version # Should show 2.x+ -# Organize imports -echo "Running goimports..." -goimports -l -w . +# Container runtime +docker info # Should show Docker daemon info (not an error) -# Run linter -echo "Running golangci-lint..." -golangci-lint run +# Kubernetes tools +k3d version # Should show k3d 5.x+ +kubectl version --client # Should show 1.25+ +helm version # Should show 3.x+ -# Run tests -echo "Running tests..." -go test -short ./... +# Certificate tool +mkcert --version # Should show a version -echo "Pre-commit checks passed!" -EOF - -chmod +x .git/hooks/pre-commit -``` - -## Troubleshooting - -### Common Go Issues - -#### GOPATH/GOROOT Problems -```bash -# Check Go environment -go env - -# Reset Go environment -go env -w GOPATH="" -go env -w GOROOT="" -``` - -#### Module Issues -```bash -# Clean module cache -go clean -modcache - -# Reinstall dependencies -go mod tidy -go mod download -``` - -### Kubernetes Issues - -#### Context Not Found -```bash -# List available contexts -kubectl config get-contexts - -# Create new context -kubectl config set-context openframe-dev \ - --cluster=k3d-openframe-local \ - --user=admin@k3d-openframe-local -``` - -#### Tools Not Found -```bash -# Verify PATH includes Go bin directory -echo $PATH | grep go - -# Add Go bin to PATH -export PATH="$GOPATH/bin:$PATH" +# Linter +golangci-lint --version # Should show installed version ``` -## Next Steps - -Your development environment is now ready! Continue with: - -1. **[Local Development Guide](local-development.md)** - Clone and run OpenFrame CLI locally -2. **[Architecture Overview](../architecture/README.md)** - Understand the system design -3. **[Contributing Guidelines](../contributing/guidelines.md)** - Learn the development workflow - -## Additional Resources - -- **Go Documentation**: https://golang.org/doc/ -- **Kubernetes Documentation**: https://kubernetes.io/docs/ -- **Cobra CLI Documentation**: https://cobra.dev/ -- **VS Code Go Extension**: https://marketplace.visualstudio.com/items?itemName=golang.Go -- **OpenMSP Slack**: [Join the community](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) \ No newline at end of file +All checks passing? You're ready to move on to [Local Development](local-development.md). diff --git a/docs/development/setup/local-development.md b/docs/development/setup/local-development.md index 66002a68..d77becba 100644 --- a/docs/development/setup/local-development.md +++ b/docs/development/setup/local-development.md @@ -1,590 +1,271 @@ # Local Development Guide -This guide covers cloning, building, running, and debugging OpenFrame CLI in your local development environment. Follow these steps to get the code running and start contributing. +This guide covers cloning the repository, building the CLI from source, running it locally, and configuring your debug environment. -## Prerequisites - -Before starting local development, ensure you have completed: -- **[Prerequisites](../../getting-started/prerequisites.md)** - System requirements and dependencies -- **[Environment Setup](environment.md)** - IDE, tools, and development configuration +--- ## Clone the Repository -### Fork and Clone (Recommended for Contributors) - -1. **Fork the repository** on GitHub: - - Go to https://github.com/flamingo-stack/openframe-cli - - Click "Fork" in the top-right corner - - Choose your GitHub account - -2. **Clone your fork**: - ```bash - # Clone your fork - git clone https://github.com/YOUR-USERNAME/openframe-cli.git - cd openframe-cli - - # Add upstream remote for syncing - git remote add upstream https://github.com/flamingo-stack/openframe-cli.git - - # Verify remotes - git remote -v - ``` - -### Direct Clone (Read-only) - -For read-only access or testing: - ```bash git clone https://github.com/flamingo-stack/openframe-cli.git cd openframe-cli ``` -## Project Structure Overview +--- -Familiarize yourself with the codebase structure: +## Project Layout ```text openframe-cli/ -β”œβ”€β”€ main.go # Application entry point -β”œβ”€β”€ go.mod # Go module definition -β”œβ”€β”€ go.sum # Go dependency checksums -β”œβ”€β”€ cmd/ # CLI command definitions -β”‚ β”œβ”€β”€ root.go # Root command and version info -β”‚ β”œβ”€β”€ bootstrap/ # Complete environment bootstrap -β”‚ β”œβ”€β”€ cluster/ # Kubernetes cluster management -β”‚ β”œβ”€β”€ chart/ # Helm chart and ArgoCD operations -β”‚ └── dev/ # Development workflow tools -β”œβ”€β”€ internal/ # Private application code -β”‚ β”œβ”€β”€ bootstrap/ # Bootstrap orchestration service -β”‚ β”œβ”€β”€ cluster/ # Cluster lifecycle management -β”‚ β”œβ”€β”€ chart/ # Chart installation and ArgoCD integration -β”‚ β”œβ”€β”€ dev/ # Development tools (intercept, scaffold) -β”‚ └── shared/ # Common utilities and adapters -β”œβ”€β”€ tests/ # Test suites and utilities -β”‚ β”œβ”€β”€ integration/ # Integration tests -β”‚ β”œβ”€β”€ mocks/ # Test mocks and fixtures -β”‚ └── testutil/ # Test helper functions -β”œβ”€β”€ docs/ # Documentation -β”œβ”€β”€ examples/ # Usage examples and samples -└── scripts/ # Build and utility scripts +β”œβ”€β”€ main.go # Binary entry point +β”œβ”€β”€ cmd/ # CLI command definitions (Cobra) +β”‚ β”œβ”€β”€ root.go # Root command, global flags, version +β”‚ β”œβ”€β”€ bootstrap/bootstrap.go # bootstrap command +β”‚ β”œβ”€β”€ cluster/ # cluster subcommands +β”‚ β”œβ”€β”€ chart/ # chart subcommands +β”‚ └── dev/ # dev subcommands +β”œβ”€β”€ internal/ # Private packages +β”‚ β”œβ”€β”€ bootstrap/service.go # Bootstrap orchestration +β”‚ β”œβ”€β”€ cluster/ # Cluster lifecycle (K3D) +β”‚ β”œβ”€β”€ chart/ # ArgoCD + Helm chart installation +β”‚ β”œβ”€β”€ dev/ # Telepresence + Skaffold workflows +β”‚ └── shared/ # Executor, UI, errors, config +β”œβ”€β”€ tests/ +β”‚ β”œβ”€β”€ integration/ # Integration tests (real k3d required) +β”‚ β”œβ”€β”€ mocks/ # Mock implementations +β”‚ └── testutil/ # Test helpers and fixtures +└── go.mod # Go module definition ``` -## Build and Run +--- -### Build the Binary +## Install Dependencies ```bash -# Build for your current platform -go build -o openframe main.go - -# Build with version information -VERSION=$(git describe --tags --always --dirty) -COMMIT=$(git rev-parse --short HEAD) -DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") - -go build -ldflags "-X main.version=$VERSION -X main.commit=$COMMIT -X main.date=$DATE" -o openframe main.go - -# Test the build -./openframe --version +go mod download ``` -### Run During Development - -For rapid development cycles, run directly with Go: - -```bash -# Run with go run (rebuilds automatically) -go run main.go --help +This downloads all Go module dependencies declared in `go.mod` and `go.sum`. -# Run specific commands -go run main.go bootstrap --help -go run main.go cluster status -go run main.go chart list -``` +--- -### Hot Reload with Air +## Build the CLI -Install and use Air for automatic rebuilds: +### Quick Build ```bash -# Install Air -go install github.com/cosmtrek/air@latest - -# Create .air.toml configuration -cat > .air.toml << 'EOF' -root = "." -testdata_dir = "testdata" -tmp_dir = "tmp" - -[build] -args_bin = [] -bin = "./tmp/main" -cmd = "go build -o ./tmp/main main.go" -delay = 1000 -exclude_dir = ["assets", "tmp", "vendor", "testdata", "docs"] -exclude_file = [] -exclude_regex = ["_test.go"] -exclude_unchanged = false -follow_symlink = false -full_bin = "" -include_dir = [] -include_ext = ["go", "tpl", "tmpl", "html"] -kill_delay = "0s" -log = "build-errors.log" -send_interrupt = false -stop_on_root = false - -[color] -app = "" -build = "yellow" -main = "magenta" -runner = "green" -watcher = "cyan" - -[log] -time = false - -[misc] -clean_on_exit = false -EOF - -# Run with hot reload -air +go build -o openframe main.go ``` -Now changes to Go files will automatically trigger rebuilds. +This produces an `openframe` binary in the current directory. -## Running Tests - -### Unit Tests +### Build with Version Info ```bash -# Run all tests -go test ./... - -# Run tests with verbose output -go test -v ./... - -# Run tests with coverage -go test -cover ./... - -# Generate detailed coverage report -go test -coverprofile=coverage.out ./... -go tool cover -html=coverage.out -o coverage.html -open coverage.html # macOS -# or xdg-open coverage.html # Linux +go build \ + -ldflags "-X main.Version=dev-local -X main.Commit=$(git rev-parse --short HEAD) -X main.Date=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ + -o openframe \ + main.go ``` -### Integration Tests - -Integration tests require a running Kubernetes cluster: +### Verify the Build ```bash -# Start a test cluster -k3d cluster create openframe-test - -# Run integration tests -go test -tags=integration ./tests/integration/... - -# Clean up -k3d cluster delete openframe-test -``` - -### Test Specific Packages - -```bash -# Test specific packages -go test ./internal/cluster/... -go test ./internal/chart/... -go test ./cmd/bootstrap/... - -# Test with timeout -go test -timeout=30s ./internal/bootstrap/... - -# Run specific tests -go test -run TestClusterCreate ./internal/cluster/... -go test -run TestBootstrapService ./internal/bootstrap/... +./openframe --version +./openframe --help ``` -## Development Workflow - -### Create a Feature Branch +--- -```bash -# Sync with upstream (if using fork) -git fetch upstream -git checkout main -git merge upstream/main +## Run Locally -# Create feature branch -git checkout -b feature/your-feature-name - -# Or for bug fixes -git checkout -b fix/issue-description -``` - -### Make Changes - -1. **Write Code**: Implement your feature or fix -2. **Write Tests**: Add or update tests for your changes -3. **Run Tests**: Ensure all tests pass -4. **Format Code**: Use `gofmt` and `goimports` -5. **Lint Code**: Run `golangci-lint` +You can run the CLI directly without installing it system-wide: ```bash -# Format and organize imports -gofmt -w . -goimports -w . - -# Run linter -golangci-lint run - -# Run all tests -go test ./... +# Run from the project root +./openframe --help +./openframe cluster list +./openframe bootstrap --help ``` -### Commit Changes - -Follow conventional commit format: +Or add the project directory to your `$PATH` temporarily: ```bash -# Stage changes -git add . - -# Commit with descriptive message -git commit -m "feat(cluster): add support for custom node labels" -git commit -m "fix(bootstrap): handle timeout errors gracefully" -git commit -m "docs(readme): update installation instructions" - -# Push to your fork -git push origin feature/your-feature-name +export PATH="$PWD:$PATH" +openframe --help ``` -## Debugging - -### VS Code Debugging +--- -Use the launch configurations from [Environment Setup](environment.md): +## Running Tests -1. **Set breakpoints** in your code -2. **Press F5** or go to Run β†’ Start Debugging -3. **Choose configuration**: - - "Launch OpenFrame CLI" - Debug with `--help` - - "Debug Bootstrap Command" - Debug bootstrap process - - "Debug Cluster Status" - Debug cluster operations +### Unit Tests -### Command-line Debugging with Delve +Unit tests use mock executors and do not require Docker or K3D: ```bash -# Install Delve -go install github.com/go-delve/delve/cmd/dlv@latest - -# Debug the application -dlv debug main.go -- bootstrap --verbose - -# Debug tests -dlv test ./internal/bootstrap/ - -# Debug with arguments -dlv debug main.go -- cluster create --name=test-cluster -``` - -### Debug Commands in Delve - -```text -(dlv) break main.main # Set breakpoint at main function -(dlv) break bootstrap.go:45 # Set breakpoint at line 45 in bootstrap.go -(dlv) continue # Continue execution -(dlv) next # Execute next line -(dlv) step # Step into function calls -(dlv) print variable_name # Print variable value -(dlv) goroutines # List all goroutines -(dlv) exit # Exit debugger +go test ./... ``` -### Debugging with Print Statements - -For quick debugging, add log statements: - -```go -package main +Run with verbose output: -import ( - "log" - "os" -) - -func debugFunction() { - log.Printf("DEBUG: variable value: %+v", variable) - - // Pretty print structs - log.Printf("DEBUG: struct: %#v", structVariable) - - // Print with file and line info - log.Printf("DEBUG [%s:%d]: message", "filename.go", 123) -} - -func init() { - // Enable debug logging during development - if os.Getenv("DEBUG") == "true" { - log.SetFlags(log.LstdFlags | log.Lshortfile) - } -} -``` - -Run with debug logging: ```bash -DEBUG=true go run main.go bootstrap +go test -v ./... ``` -## Testing Your Changes - -### Manual Testing - -Create test scenarios to verify your changes: +Run with race detection: ```bash -# Test bootstrap functionality -go run main.go bootstrap --mode=oss-tenant --non-interactive - -# Test cluster operations -go run main.go cluster create test-cluster -go run main.go cluster status test-cluster -go run main.go cluster delete test-cluster - -# Test chart operations -go run main.go chart install test-app --repo=https://charts.example.com -go run main.go chart list - -# Test development tools -go run main.go dev scaffold my-service --template=microservice -go run main.go dev intercept my-service --port=3000:8080 +go test -race ./... ``` -### Integration Testing - -Test with real Kubernetes clusters: +Run a specific package: ```bash -# Create test cluster -k3d cluster create openframe-test --agents 2 - -# Run your changes against the cluster -KUBECONFIG=$(k3d kubeconfig write openframe-test) go run main.go bootstrap - -# Verify results -kubectl get pods --all-namespaces -kubectl get applications -n argocd - -# Clean up -k3d cluster delete openframe-test +go test -v ./internal/cluster/... +go test -v ./internal/chart/... ``` -### Performance Testing +### Integration Tests -Monitor resource usage and performance: +Integration tests execute real K3D operations and require Docker + K3D installed and running: ```bash -# Build optimized binary -go build -ldflags="-s -w" -o openframe main.go - -# Monitor memory usage -/usr/bin/time -v ./openframe bootstrap +# Ensure K3D and Docker are running first +docker info +k3d version -# Profile CPU usage -CPUPROFILE=cpu.prof go run main.go bootstrap -go tool pprof cpu.prof - -# Profile memory usage -MEMPROFILE=mem.prof go run main.go bootstrap -go tool pprof mem.prof +# Run integration tests +go test -v -tags integration ./tests/integration/... ``` -## Code Quality - -### Automated Checks - -Run all quality checks before committing: - -```bash -#!/bin/bash -# quality-check.sh - -echo "Running code quality checks..." - -# Format code -echo "Formatting code..." -gofmt -l -w . -goimports -l -w . - -# Vet code -echo "Vetting code..." -go vet ./... - -# Run linter -echo "Running linter..." -golangci-lint run +> **Warning:** Integration tests create and delete real K3D clusters. They take several minutes to run and should not be run in environments without sufficient resources (see [Prerequisites](../../../getting-started/prerequisites.md)). -# Run tests -echo "Running tests..." -go test -race -cover ./... +--- -# Check for security issues -echo "Checking security..." -gosec ./... +## Watch Mode (Auto-Rebuild) -# Check dependencies -echo "Checking dependencies..." -go mod tidy -go mod verify +For a fast feedback loop during development, use `go run` with automatic reloads via [air](https://github.com/air-verse/air): -echo "All checks passed!" -``` - -Make it executable and run: ```bash -chmod +x quality-check.sh -./quality-check.sh -``` - -### Manual Code Review +# Install air +go install github.com/air-verse/air@latest -Before submitting changes, review: - -1. **Code Structure**: Is the code well-organized and follows Go conventions? -2. **Error Handling**: Are errors properly handled and user-friendly? -3. **Documentation**: Are public functions and packages documented? -4. **Tests**: Are there adequate unit and integration tests? -5. **Performance**: Are there any obvious performance issues? - -## Advanced Development +# Run with hot reload +air +``` -### Working with Dependencies +Or simply use `go run` for quick iteration: ```bash -# Add a new dependency -go get github.com/new/dependency@latest - -# Update dependencies -go get -u ./... - -# Vendor dependencies (if needed) -go mod vendor - -# Remove unused dependencies -go mod tidy +go run main.go --help +go run main.go cluster list ``` -### Working with Build Tags - -Use build tags for conditional compilation: - -```go -// +build debug - -package debug - -func init() { - // Debug-only initialization +--- + +## Debug Configuration + +### VS Code Debug Launch Config + +Create `.vscode/launch.json` in the project root: + +```json +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug: openframe bootstrap", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${workspaceFolder}/main.go", + "args": ["bootstrap", "--verbose"], + "env": { + "KUBECONFIG": "${env:HOME}/.kube/config" + } + }, + { + "name": "Debug: cluster list", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${workspaceFolder}/main.go", + "args": ["cluster", "list"] + }, + { + "name": "Debug: chart install", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${workspaceFolder}/main.go", + "args": ["chart", "install", "--verbose"] + } + ] } ``` -```bash -# Build with debug tag -go build -tags debug -o openframe-debug main.go +### GoLand / IntelliJ Run Configuration -# Run tests with integration tag -go test -tags integration ./... -``` +1. Go to **Run β†’ Edit Configurations** +2. Click **+** β†’ **Go Build** +3. Set **Run kind** to `File` +4. Set **Files** to `main.go` +5. Set **Program arguments** to e.g. `bootstrap --verbose` +6. Click **OK** and press **Debug** -### Cross-platform Development +--- -Build for multiple platforms: +## Linting -```bash -# Build for Linux -GOOS=linux GOARCH=amd64 go build -o openframe-linux main.go +Run the linter before committing: -# Build for Windows -GOOS=windows GOARCH=amd64 go build -o openframe.exe main.go - -# Build for macOS (Intel) -GOOS=darwin GOARCH=amd64 go build -o openframe-darwin-amd64 main.go - -# Build for macOS (Apple Silicon) -GOOS=darwin GOARCH=arm64 go build -o openframe-darwin-arm64 main.go +```bash +golangci-lint run ./... ``` -## Troubleshooting - -### Common Development Issues +Auto-fix simple issues: -#### Module Problems ```bash -# Clear module cache -go clean -modcache - -# Reinitialize modules -rm go.sum -go mod tidy +golangci-lint run --fix ./... ``` -#### Build Errors -```bash -# Clean build cache -go clean -cache +--- -# Rebuild everything -go build -a main.go -``` +## Code Formatting -#### Test Failures ```bash -# Run tests with verbose output -go test -v -race ./... +# Format all Go files +gofmt -w . -# Run specific failing test -go test -v -run TestSpecificFunction ./path/to/package +# Format and fix imports +goimports -w . ``` -#### Kubernetes Context Issues -```bash -# Check current context -kubectl config current-context - -# Switch to correct context -kubectl config use-context k3d-openframe-local - -# Verify cluster connectivity -kubectl cluster-info -``` +--- -### Debug Environment Variables +## Build the CLI Binary for Integration Tests -Set these for debugging: +The integration test suite uses a pre-built binary. To build it: ```bash -export GODEBUG="gctrace=1" # GC tracing -export GOTRACEBACK="all" # Full stack traces -export OPENFRAME_LOG_LEVEL="debug" # Detailed logging -export KUBECONFIG="$HOME/.kube/config" +go build -o tests/integration/openframe main.go ``` -## Next Steps - -Now that you have a working development environment: - -1. **[Architecture Overview](../architecture/README.md)** - Understand the system design -2. **[Contributing Guidelines](../contributing/guidelines.md)** - Learn the contribution process -3. **[Testing Guide](../testing/README.md)** - Deep dive into testing strategies - -## Getting Help +The test suite (`tests/integration/common/cli_runner.go`) will automatically detect and cache this binary based on source file timestamps. -If you encounter issues: +--- -- **Check existing issues**: Search GitHub issues for similar problems -- **Ask in Slack**: Join the [OpenMSP community](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) -- **Review documentation**: Check other guides in this repository -- **Debug systematically**: Use logging and debugging tools to isolate issues +## Common Development Commands Reference -Happy coding! πŸš€ \ No newline at end of file +| Task | Command | +|---|---| +| Build binary | `go build -o openframe main.go` | +| Run all tests | `go test ./...` | +| Run with race detection | `go test -race ./...` | +| Lint | `golangci-lint run ./...` | +| Format code | `goimports -w .` | +| Run specific test | `go test -v -run TestClusterCreate ./internal/cluster/...` | +| Download deps | `go mod download` | +| Tidy deps | `go mod tidy` | +| Check vulnerabilities | `govulncheck ./...` | diff --git a/docs/development/testing/README.md b/docs/development/testing/README.md new file mode 100644 index 00000000..f50e4abc --- /dev/null +++ b/docs/development/testing/README.md @@ -0,0 +1,286 @@ +# Testing Guide + +This guide describes the test structure, how to run tests, how to write new tests, and coverage requirements for the OpenFrame CLI project. + +--- + +## Test Structure and Organization + +The OpenFrame CLI test suite is organized into three layers: + +```text +tests/ +β”œβ”€β”€ integration/ +β”‚ └── common/ +β”‚ β”œβ”€β”€ cli_runner.go # Build + execute CLI binary in tests +β”‚ β”œβ”€β”€ cluster_management.go # K3D cluster lifecycle helpers +β”‚ └── dependencies.go # Shared test dependency setup +β”œβ”€β”€ mocks/ +β”‚ └── dev/ +β”‚ └── kubernetes.go # Kubernetes mock implementations +└── testutil/ + β”œβ”€β”€ setup.go # Test environment initialization + β”œβ”€β”€ assertions.go # Custom assertion helpers + β”œβ”€β”€ cluster.go # Cluster test utilities + β”œβ”€β”€ patterns.go # Reusable test patterns + └── utilities.go # General test utilities +``` + +### Unit Tests + +Unit tests live alongside source files in their respective packages under `internal/`. They use `MockCommandExecutor` to simulate external tool responses without requiring real K3D, Docker, or Kubernetes. + +Example: `internal/cluster/service_test.go`, `internal/chart/services/installer_test.go` + +### Integration Tests + +Integration tests live in `tests/integration/`. They use a real K3D installation and Docker daemon. The `CLIRunner` utility builds the CLI binary (with timestamp-based caching) and executes it as a subprocess, capturing stdout/stderr and exit codes. + +--- + +## Running Tests + +### All Unit Tests + +```bash +go test ./... +``` + +### Verbose Output + +```bash +go test -v ./... +``` + +### With Race Detection + +```bash +go test -race ./... +``` + +### Specific Package + +```bash +# Test cluster package only +go test -v ./internal/cluster/... + +# Test chart package only +go test -v ./internal/chart/... + +# Test dev package only +go test -v ./internal/dev/... + +# Test shared utilities +go test -v ./internal/shared/... +``` + +### Single Test Case + +```bash +go test -v -run TestClusterCreate ./internal/cluster/... +go test -v -run TestBootstrapService ./internal/bootstrap/... +``` + +### Integration Tests + +Integration tests require Docker and K3D to be installed and running: + +```bash +# Run integration tests (creates/deletes real clusters) +go test -v -tags integration ./tests/integration/... +``` + +> **Warning:** Integration tests are slow (several minutes) and resource-intensive. Run them before submitting a PR, not on every code change. + +### Test with Coverage + +```bash +go test -coverprofile=coverage.out ./... +go tool cover -html=coverage.out -o coverage.html +``` + +Open `coverage.html` in a browser to explore line-by-line coverage. + +--- + +## Test Utilities + +### `testutil.InitializeTestMode()` + +Call this at the start of any test that involves UI components to disable interactive prompts: + +```go +func TestMyFeature(t *testing.T) { + testutil.InitializeTestMode() // Disables pterm/promptui interactive elements + // ... rest of test +} +``` + +### `testutil.NewTestMockExecutor()` + +Creates a `MockCommandExecutor` with pre-configured responses for standard K3D commands: + +```go +func TestClusterList(t *testing.T) { + testutil.InitializeTestMode() + executor := testutil.NewTestMockExecutor() + + // Inject a custom response for a specific command + executor.SetResponse("k3d cluster list", &executor.CommandResult{ + ExitCode: 0, + Stdout: `[{"name":"test-cluster","nodes":[]}]`, + }) + + manager := k3d.NewK3dManager(executor, false) + clusters, err := manager.ListClusters(context.Background()) + + assert.NoError(t, err) + assert.Len(t, clusters, 1) +} +``` + +### `testutil.CreateStandardTestFlags()` + +Sets up a fully mocked dependency container for testing command handlers: + +```go +flags := testutil.CreateStandardTestFlags() +testutil.SetVerboseMode(flags, true) + +// Use flags to test service behavior with mocked K3D +``` + +### `testutil.CreateIntegrationTestFlags()` + +Creates a real dependency container for integration tests that exercise actual K3D operations: + +```go +flags := testutil.CreateIntegrationTestFlags() +// This will use real k3d commands β€” requires Docker + K3D +``` + +--- + +## Writing New Tests + +### Unit Test Pattern + +```go +package mypackage_test + +import ( + "testing" + "context" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/flamingo-stack/openframe-cli/tests/testutil" +) + +func TestMyNewFeature(t *testing.T) { + // 1. Initialize test mode (disables UI) + testutil.InitializeTestMode() + + // 2. Create mock executor + executor := testutil.NewTestMockExecutor() + + // 3. Set up mock responses + executor.SetResponse("some-tool --arg value", &executor.CommandResult{ + ExitCode: 0, + Stdout: "expected output", + }) + + // 4. Create the system under test with injected mock + svc := NewMyService(executor, false) + + // 5. Execute and assert + result, err := svc.DoSomething(context.Background(), "input") + require.NoError(t, err) + assert.Equal(t, "expected result", result) +} +``` + +### Error Path Testing + +Always test failure scenarios alongside happy paths: + +```go +func TestMyFeature_CommandFails(t *testing.T) { + testutil.InitializeTestMode() + executor := testutil.NewTestMockExecutor() + + executor.SetResponse("some-tool --arg value", &executor.CommandResult{ + ExitCode: 1, + Stderr: "command failed: permission denied", + }) + + svc := NewMyService(executor, false) + _, err := svc.DoSomething(context.Background(), "input") + + require.Error(t, err) + assert.Contains(t, err.Error(), "permission denied") +} +``` + +### Interface Compliance Tests + +When implementing a new provider, add a compile-time interface check: + +```go +// At the top of your implementation file +var _ types.MyProviderInterface = (*MyProvider)(nil) +``` + +This causes a compile error if `MyProvider` doesn't satisfy the interface, catching issues before tests run. + +--- + +## Mocking External Commands + +The `MockCommandExecutor` in `internal/shared/executor/mock.go` uses pattern-based response injection. Patterns are matched against the full command string `"tool arg1 arg2 ..."`: + +```go +executor.SetResponse("k3d cluster create my-cluster", &CommandResult{ + ExitCode: 0, + Stdout: "INFO[0000] Cluster 'my-cluster' created successfully!", +}) + +// Wildcard patterns (if supported) +executor.SetResponse("kubectl get pods", &CommandResult{ + ExitCode: 0, + Stdout: "No resources found.", +}) +``` + +--- + +## Coverage Requirements + +| Package | Minimum Coverage Target | +|---|---| +| `internal/cluster/` | 70% | +| `internal/chart/` | 70% | +| `internal/dev/` | 60% | +| `internal/shared/` | 80% | +| `cmd/` | 50% | + +> Coverage is checked during CI. PRs that significantly reduce coverage for a package will be flagged for review. + +--- + +## CI Integration + +Tests run automatically on every pull request. The CI pipeline runs: + +```bash +# Unit tests with race detection +go test -race ./... + +# Linting +golangci-lint run ./... + +# Vulnerability scan +govulncheck ./... +``` + +Integration tests are run on a separate schedule (not on every PR) due to their resource requirements. diff --git a/docs/diagrams/architecture/README.md b/docs/diagrams/architecture/README.md index 7b3e892e..ea2d0a9d 100644 --- a/docs/diagrams/architecture/README.md +++ b/docs/diagrams/architecture/README.md @@ -4,10 +4,11 @@ This directory contains Mermaid diagrams generated from architecture analysis. ## Diagrams -- **[High-Level System Design](./high-level-system-design.mmd)** - `.mmd` file -- **[Dependency Flow Between Modules](./dependency-flow-between-modules.mmd)** - `.mmd` file -- **[Complete Bootstrap Workflow](./complete-bootstrap-workflow.mmd)** - `.mmd` file -- **[Development Intercept Workflow](./development-intercept-workflow.mmd)** - `.mmd` file +- **[High-Level Architecture Diagram](./high-level-architecture-diagram.mmd)** - `.mmd` file +- **[Dependency Flowchart](./dependency-flowchart.mmd)** - `.mmd` file +- **[Bootstrap Sequence (Full Environment Setup)](./bootstrap-sequence-full-environment-setup.mmd)** - `.mmd` file +- **[Interactive Chart Install with Configuration Wizard](./interactive-chart-install-with-configuration-wizard.mmd)** - `.mmd` file +- **[Dependency Interaction Pattern](./dependency-interaction-pattern.mmd)** - `.mmd` file ## Viewing Diagrams diff --git a/docs/diagrams/architecture/bootstrap-sequence-full-environment-setup.mmd b/docs/diagrams/architecture/bootstrap-sequence-full-environment-setup.mmd new file mode 100644 index 00000000..7fb46464 --- /dev/null +++ b/docs/diagrams/architecture/bootstrap-sequence-full-environment-setup.mmd @@ -0,0 +1,41 @@ +sequenceDiagram + participant User + participant CLI as "cmd/bootstrap" + participant BSvc as "bootstrap.Service" + participant CSvc as "cluster.ClusterService" + participant K3dMgr as "k3d.K3dManager" + participant ChartSvc as "chart.ChartService" + participant Installer as "chart.Installer" + participant HelmMgr as "helm.HelmManager" + participant ArgoCDMgr as "argocd.Manager" + participant GitRepo as "git.Repository" + + User->>CLI: openframe bootstrap [cluster-name] + CLI->>BSvc: Execute(cmd, args) + BSvc->>CSvc: CreateClusterWithPrerequisitesNonInteractive() + CSvc->>K3dMgr: CreateCluster(config) + K3dMgr->>K3dMgr: createK3dConfigFile() + K3dMgr-->>CSvc: *rest.Config + CSvc-->>BSvc: *rest.Config (kubeConfig) + + BSvc->>ChartSvc: InstallChartsWithConfig(InstallationRequest) + ChartSvc->>ChartSvc: SelectCluster() or use provided name + ChartSvc->>HelmMgr: NewHelmManager(kubeConfig) + ChartSvc->>Installer: InstallChartsWithContext(ctx, config) + + Installer->>HelmMgr: InstallArgoCDWithProgress(ctx, cfg) + HelmMgr-->>Installer: ArgoCD deployed + + Installer->>GitRepo: CloneChartRepository(ctx, appConfig) + GitRepo-->>Installer: CloneResult{TempDir, ChartPath} + + Installer->>HelmMgr: InstallAppOfAppsFromLocal(ctx, config, certFile, keyFile) + HelmMgr-->>Installer: App-of-apps deployed + + Installer->>ArgoCDMgr: WaitForApplications(ctx, config) + ArgoCDMgr->>ArgoCDMgr: Poll ArgoCD application health/sync status + ArgoCDMgr-->>Installer: All applications Healthy + Synced + + Installer-->>ChartSvc: success + ChartSvc-->>BSvc: success + BSvc-->>User: Environment ready diff --git a/docs/diagrams/architecture/complete-bootstrap-workflow.mmd b/docs/diagrams/architecture/complete-bootstrap-workflow.mmd deleted file mode 100644 index 366b0980..00000000 --- a/docs/diagrams/architecture/complete-bootstrap-workflow.mmd +++ /dev/null @@ -1,32 +0,0 @@ -sequenceDiagram - participant User - participant Bootstrap as Bootstrap Service - participant Cluster as Cluster Service - participant K3D as K3D Provider - participant Chart as Chart Service - participant Helm as Helm Provider - participant ArgoCD as ArgoCD Provider - participant K8s as Kubernetes API - - User->>Bootstrap: openframe bootstrap - Bootstrap->>Bootstrap: Check prerequisites - Bootstrap->>Cluster: Create cluster - Cluster->>K3D: Create K3D cluster - K3D->>K8s: Initialize cluster - K8s-->>K3D: Cluster ready - K3D-->>Cluster: Cluster config - Cluster-->>Bootstrap: rest.Config - - Bootstrap->>Chart: Install charts - Chart->>Helm: Install ArgoCD - Helm->>K8s: Deploy ArgoCD - K8s-->>Helm: ArgoCD running - Helm-->>Chart: Installation complete - - Chart->>ArgoCD: Install app-of-apps - ArgoCD->>K8s: Create Application CRDs - K8s-->>ArgoCD: Applications created - ArgoCD->>ArgoCD: Sync applications - ArgoCD-->>Chart: Applications synced - Chart-->>Bootstrap: Charts installed - Bootstrap-->>User: Environment ready diff --git a/docs/diagrams/architecture/dependency-flow-between-modules.mmd b/docs/diagrams/architecture/dependency-flow-between-modules.mmd deleted file mode 100644 index 4141f827..00000000 --- a/docs/diagrams/architecture/dependency-flow-between-modules.mmd +++ /dev/null @@ -1,76 +0,0 @@ -graph TD - subgraph "Command Layer" - RootCmd[Root Command] - BootstrapCmd[Bootstrap Command] - ClusterCmd[Cluster Commands] - ChartCmd[Chart Commands] - DevCmd[Dev Commands] - end - - subgraph "Service Orchestration" - BootstrapSvc[Bootstrap Service] - end - - subgraph "Domain Services" - ClusterSvc[Cluster Service] - ChartSvc[Chart Service] - InterceptSvc[Intercept Service] - ScaffoldSvc[Scaffold Service] - end - - subgraph "Provider Implementations" - K3DMgr[K3D Manager] - HelmMgr[Helm Manager] - ArgoCDMgr[ArgoCD Manager] - TelepresenceProv[Telepresence Provider] - KubectlProv[Kubectl Provider] - GitRepo[Git Repository] - end - - subgraph "Shared Infrastructure" - Executor[Command Executor] - UI[UI Components] - Config[Configuration] - Prerequisites[Prerequisites] - end - - RootCmd --> BootstrapCmd - RootCmd --> ClusterCmd - RootCmd --> ChartCmd - RootCmd --> DevCmd - - BootstrapCmd --> BootstrapSvc - ClusterCmd --> ClusterSvc - ChartCmd --> ChartSvc - DevCmd --> InterceptSvc - DevCmd --> ScaffoldSvc - - BootstrapSvc --> ClusterSvc - BootstrapSvc --> ChartSvc - - ClusterSvc --> K3DMgr - ChartSvc --> HelmMgr - ChartSvc --> ArgoCDMgr - ChartSvc --> GitRepo - InterceptSvc --> TelepresenceProv - InterceptSvc --> KubectlProv - ScaffoldSvc --> KubectlProv - - K3DMgr --> Executor - HelmMgr --> Executor - ArgoCDMgr --> Executor - TelepresenceProv --> Executor - KubectlProv --> Executor - GitRepo --> Executor - - ClusterSvc --> UI - ChartSvc --> UI - InterceptSvc --> UI - ScaffoldSvc --> UI - - ClusterSvc --> Config - ChartSvc --> Config - - ClusterSvc --> Prerequisites - ChartSvc --> Prerequisites - DevCmd --> Prerequisites diff --git a/docs/diagrams/architecture/dependency-flowchart.mmd b/docs/diagrams/architecture/dependency-flowchart.mmd new file mode 100644 index 00000000..692589b4 --- /dev/null +++ b/docs/diagrams/architecture/dependency-flowchart.mmd @@ -0,0 +1,78 @@ +graph LR + subgraph Commands["cmd Layer"] + CmdRoot["cmd/root.go"] + CmdBootstrap["cmd/bootstrap"] + CmdCluster["cmd/cluster"] + CmdChart["cmd/chart"] + CmdDev["cmd/dev"] + end + + subgraph Services["Service Layer"] + SvcBootstrap["internal/bootstrap/service.go"] + SvcCluster["internal/cluster/service.go"] + SvcChart["internal/chart/services/chart_service.go"] + SvcInstaller["internal/chart/services/installer.go"] + SvcArgoCD["internal/chart/services/argocd.go"] + SvcAppOfApps["internal/chart/services/appofapps.go"] + SvcIntercept["internal/dev/services/intercept"] + SvcScaffold["internal/dev/services/scaffold"] + end + + subgraph Providers["Provider Layer"] + ProvK3d["internal/cluster/providers/k3d"] + ProvHelm["internal/chart/providers/helm"] + ProvArgoCD["internal/chart/providers/argocd"] + ProvGit["internal/chart/providers/git"] + ProvKubectl["internal/dev/providers/kubectl"] + ProvTelepresence["internal/dev/providers/telepresence"] + ProvChartDev["internal/dev/providers/chart"] + end + + subgraph Shared["Shared Infrastructure"] + Executor["shared/executor"] + UI["shared/ui"] + Errors["shared/errors"] + Config["shared/config"] + Files["shared/files"] + end + + CmdRoot --> CmdBootstrap + CmdRoot --> CmdCluster + CmdRoot --> CmdChart + CmdRoot --> CmdDev + + CmdBootstrap --> SvcBootstrap + CmdCluster --> SvcCluster + CmdChart --> SvcChart + CmdDev --> SvcIntercept + CmdDev --> SvcScaffold + + SvcBootstrap --> SvcCluster + SvcBootstrap --> SvcChart + + SvcChart --> SvcInstaller + SvcInstaller --> SvcArgoCD + SvcInstaller --> SvcAppOfApps + + SvcCluster --> ProvK3d + SvcArgoCD --> ProvHelm + SvcArgoCD --> ProvArgoCD + SvcAppOfApps --> ProvHelm + SvcAppOfApps --> ProvGit + SvcIntercept --> ProvTelepresence + SvcScaffold --> ProvChartDev + SvcScaffold --> ProvKubectl + + ProvK3d --> Executor + ProvHelm --> Executor + ProvArgoCD --> Executor + ProvGit --> Executor + ProvKubectl --> Executor + ProvTelepresence --> Executor + + SvcCluster --> UI + SvcChart --> UI + SvcChart --> Errors + SvcChart --> Files + ProvHelm --> Config + ProvArgoCD --> Config diff --git a/docs/diagrams/architecture/dependency-interaction-pattern.mmd b/docs/diagrams/architecture/dependency-interaction-pattern.mmd new file mode 100644 index 00000000..b041c304 --- /dev/null +++ b/docs/diagrams/architecture/dependency-interaction-pattern.mmd @@ -0,0 +1,44 @@ +graph TD + OpenFrameCLI["OpenFrame CLI Core"] + + subgraph UILayer["UI Dependencies"] + Pterm["pterm (spinners, tables, colors)"] + Promptui["promptui (select, input)"] + Term["golang.org/x/term"] + end + + subgraph K8sLayer["Kubernetes Dependencies"] + ClientGo["k8s.io/client-go"] + APIExtensions["k8s.io/apiextensions-apiserver"] + ArgoCDClient["argoproj/argo-cd clientset"] + APIMachinery["k8s.io/apimachinery"] + end + + subgraph CLILayer["CLI Framework"] + Cobra["spf13/cobra"] + end + + subgraph ConfigLayer["Config / Serialization"] + YamlV3["gopkg.in/yaml.v3"] + SigsYaml["sigs.k8s.io/yaml"] + end + + subgraph TestLayer["Testing"] + Testify["stretchr/testify"] + end + + OpenFrameCLI --> Cobra + OpenFrameCLI --> Pterm + OpenFrameCLI --> Promptui + OpenFrameCLI --> Term + OpenFrameCLI --> ClientGo + OpenFrameCLI --> APIExtensions + OpenFrameCLI --> ArgoCDClient + OpenFrameCLI --> APIMachinery + OpenFrameCLI --> YamlV3 + OpenFrameCLI --> SigsYaml + OpenFrameCLI --> Testify + + ArgoCDClient --> ClientGo + APIExtensions --> ClientGo + APIMachinery --> ClientGo diff --git a/docs/diagrams/architecture/development-intercept-workflow.mmd b/docs/diagrams/architecture/development-intercept-workflow.mmd deleted file mode 100644 index ec78ee72..00000000 --- a/docs/diagrams/architecture/development-intercept-workflow.mmd +++ /dev/null @@ -1,30 +0,0 @@ -sequenceDiagram - participant Dev as Developer - participant Intercept as Intercept Service - participant Kubectl as Kubectl Provider - participant Telepresence as Telepresence Provider - participant K8s as Kubernetes - participant Local as Local Development - - Dev->>Intercept: openframe dev intercept - Intercept->>Kubectl: Get services - Kubectl->>K8s: List services - K8s-->>Kubectl: Service list - Kubectl-->>Intercept: Available services - Intercept->>Dev: Select service/port - Dev->>Intercept: Service selection - - Intercept->>Telepresence: Setup intercept - Telepresence->>K8s: Create intercept - K8s->>Telepresence: Traffic routing active - Telepresence->>Local: Forward traffic - Local->>Dev: Local debugging - - Note over Dev,Local: Development session active - - Dev->>Intercept: Stop intercept (Ctrl+C) - Intercept->>Telepresence: Cleanup intercept - Telepresence->>K8s: Remove routing - K8s-->>Telepresence: Cleanup complete - Telepresence-->>Intercept: Disconnected - Intercept-->>Dev: Session ended diff --git a/docs/diagrams/architecture/high-level-architecture-diagram.mmd b/docs/diagrams/architecture/high-level-architecture-diagram.mmd new file mode 100644 index 00000000..622b7558 --- /dev/null +++ b/docs/diagrams/architecture/high-level-architecture-diagram.mmd @@ -0,0 +1,81 @@ +graph TB + subgraph CLI["CLI Entry Points"] + Root["openframe (root)"] + Bootstrap["bootstrap"] + Cluster["cluster"] + Chart["chart"] + Dev["dev"] + end + + subgraph Internal["Internal Services"] + BootstrapSvc["bootstrap.Service"] + ClusterSvc["cluster.ClusterService"] + ChartSvc["chart.ChartService"] + DevSvc["dev.Service"] + end + + subgraph Providers["Infrastructure Providers"] + K3dMgr["k3d.K3dManager"] + HelmMgr["helm.HelmManager"] + ArgoCDMgr["argocd.Manager"] + GitRepo["git.Repository"] + TelepresenceProv["telepresence.Provider"] + KubectlProv["kubectl.Provider"] + end + + subgraph External["External Tools"] + K3D["K3D CLI"] + HelmCLI["Helm CLI"] + ArgoCD["ArgoCD API"] + KubectlCLI["kubectl"] + TelepresenceCLI["Telepresence CLI"] + SkaffoldCLI["Skaffold CLI"] + end + + subgraph SharedLayer["Shared Layer"] + Executor["executor.CommandExecutor"] + SharedUI["shared/ui"] + SharedErrors["shared/errors"] + SharedConfig["shared/config"] + end + + Root --> Bootstrap + Root --> Cluster + Root --> Chart + Root --> Dev + + Bootstrap --> BootstrapSvc + Cluster --> ClusterSvc + Chart --> ChartSvc + Dev --> DevSvc + + BootstrapSvc --> ClusterSvc + BootstrapSvc --> ChartSvc + + ClusterSvc --> K3dMgr + ChartSvc --> HelmMgr + ChartSvc --> ArgoCDMgr + ChartSvc --> GitRepo + DevSvc --> TelepresenceProv + DevSvc --> KubectlProv + + K3dMgr --> Executor + HelmMgr --> Executor + ArgoCDMgr --> Executor + GitRepo --> Executor + TelepresenceProv --> Executor + KubectlProv --> Executor + + Executor --> K3D + Executor --> HelmCLI + ArgoCDMgr --> ArgoCD + Executor --> KubectlCLI + Executor --> TelepresenceCLI + Executor --> SkaffoldCLI + + ClusterSvc --> SharedUI + ChartSvc --> SharedUI + DevSvc --> SharedUI + ClusterSvc --> SharedErrors + ChartSvc --> SharedErrors + SharedConfig --> SharedLayer diff --git a/docs/diagrams/architecture/high-level-system-design.mmd b/docs/diagrams/architecture/high-level-system-design.mmd deleted file mode 100644 index 7f3080f4..00000000 --- a/docs/diagrams/architecture/high-level-system-design.mmd +++ /dev/null @@ -1,56 +0,0 @@ -graph TB - subgraph "CLI Layer" - Root[Root Command] - Bootstrap[Bootstrap Command] - Cluster[Cluster Commands] - Chart[Chart Commands] - Dev[Dev Commands] - end - - subgraph "Service Layer" - ClusterSvc[Cluster Service] - ChartSvc[Chart Service] - InterceptSvc[Intercept Service] - ScaffoldSvc[Scaffold Service] - end - - subgraph "Provider Layer" - K3D[K3D Provider] - Helm[Helm Provider] - ArgoCD[ArgoCD Provider] - Telepresence[Telepresence Provider] - Kubectl[Kubectl Provider] - end - - subgraph "External Systems" - Docker[Docker] - K8s[Kubernetes] - Git[Git Repositories] - Registry[Container Registry] - end - - Root --> Bootstrap - Root --> Cluster - Root --> Chart - Root --> Dev - - Bootstrap --> ClusterSvc - Bootstrap --> ChartSvc - Cluster --> ClusterSvc - Chart --> ChartSvc - Dev --> InterceptSvc - Dev --> ScaffoldSvc - - ClusterSvc --> K3D - ChartSvc --> Helm - ChartSvc --> ArgoCD - InterceptSvc --> Telepresence - InterceptSvc --> Kubectl - ScaffoldSvc --> Kubectl - - K3D --> Docker - Helm --> K8s - ArgoCD --> K8s - ArgoCD --> Git - Telepresence --> K8s - Kubectl --> K8s diff --git a/docs/diagrams/architecture/interactive-chart-install-with-configuration-wizard.mmd b/docs/diagrams/architecture/interactive-chart-install-with-configuration-wizard.mmd new file mode 100644 index 00000000..a0616cd2 --- /dev/null +++ b/docs/diagrams/architecture/interactive-chart-install-with-configuration-wizard.mmd @@ -0,0 +1,30 @@ +sequenceDiagram + participant User + participant CLI as "cmd/chart install" + participant ChartSvc as "chart.ChartService" + participant Wizard as "configuration.ConfigurationWizard" + participant Builder as "config.Builder" + participant Installer as "chart.Installer" + + User->>CLI: openframe chart install + CLI->>ChartSvc: InstallWithContextDeferred(ctx, req) + ChartSvc->>ChartSvc: SelectCluster() interactive + + alt No deployment-mode flag + ChartSvc->>Wizard: ConfigureHelmValues() + Wizard->>User: Select deployment mode (OSS/SaaS/SaaS-Shared) + User-->>Wizard: oss-tenant + Wizard->>User: Default or interactive config? + User-->>Wizard: interactive + Wizard->>User: Branch, Docker, Ingress prompts + User-->>Wizard: configuration answers + Wizard->>Wizard: CreateTemporaryValuesFile() + Wizard-->>ChartSvc: ChartConfiguration{TempHelmValuesPath} + else deployment-mode flag provided + ChartSvc->>Builder: BuildInstallConfig(...) + Builder->>Builder: ReadHelmValuesFile() for branch override + Builder-->>ChartSvc: ChartInstallConfig + end + + ChartSvc->>Installer: InstallChartsWithContext(ctx, config) + Installer-->>User: success diff --git a/docs/getting-started/first-steps.md b/docs/getting-started/first-steps.md index 24c144d6..eeb26ca8 100644 --- a/docs/getting-started/first-steps.md +++ b/docs/getting-started/first-steps.md @@ -1,467 +1,205 @@ -# First Steps with OpenFrame CLI +# First Steps -Now that you have OpenFrame CLI installed and your first environment bootstrapped, let's explore the key features and workflows. This guide covers the essential first steps to get you productive with OpenFrame. +Congratulations on your first successful OpenFrame bootstrap! This guide walks you through the first five things to do after your environment is up and running. -## Your First 5 Actions +[![OpenFrame v0.3.7 - Enhanced Developer Experience](https://img.youtube.com/vi/O8hbBO5Mym8/maxresdefault.jpg)](https://www.youtube.com/watch?v=O8hbBO5Mym8) -### 1. Explore the CLI Structure - -Get familiar with the command hierarchy: - -```bash -# See all available commands -openframe --help - -# Explore each command group -openframe cluster --help -openframe chart --help -openframe dev --help -openframe bootstrap --help -``` +--- -The CLI is organized into logical groups: -- **bootstrap**: One-time environment setup -- **cluster**: Kubernetes cluster lifecycle -- **chart**: Application and service deployment -- **dev**: Development and debugging tools +## 1. Explore Your Cluster -### 2. Check Your Environment Status +Start by familiarizing yourself with what was created. -Verify everything is running correctly: +### List All Clusters ```bash -# Overall cluster health -openframe cluster status - -# List all running clusters openframe cluster list - -# Check installed charts and applications -openframe chart list -``` - -Expected healthy output: -```text -πŸ“Š Cluster Status: openframe-local -βœ… Cluster is running -βœ… ArgoCD is healthy -βœ… All core services operational ``` -### 3. Access the ArgoCD Dashboard +This displays a formatted table of all K3D clusters managed by OpenFrame, including their names, types, and states. -ArgoCD provides a web interface for GitOps deployments: +### Check Detailed Status ```bash -# Get admin password -kubectl -n argocd get secret argocd-initial-admin-secret \ - -o jsonpath="{.data.password}" | base64 -d; echo - -# Port forward to access UI -kubectl port-forward svc/argocd-server -n argocd 8080:443 - -# Open in browser: https://localhost:8080 -# Username: admin -# Password: (from command above) +openframe cluster status my-cluster --detailed ``` -In the ArgoCD UI, you'll see: -- **Applications**: Deployed services and components -- **Repositories**: Connected Git repositories -- **Settings**: Configuration and policies -- **User Info**: Access controls and authentication +The `--detailed` flag shows: +- Cluster node health and roles +- All ArgoCD applications and their sync/health status +- Any applications that need attention -### 4. Deploy Your First Application - -Let's deploy a simple application to test the workflow: +### Check Without App Details ```bash -# Create a test namespace -kubectl create namespace hello-world - -# Deploy a sample application -kubectl apply -f - <> ~/.bashrc << 'EOF' -# OpenFrame aliases -alias of="openframe" -alias ofcs="openframe cluster status" -alias ofcl="openframe cluster list" -alias k="kubectl" -alias kgp="kubectl get pods" -alias kgs="kubectl get svc" -alias kgn="kubectl get nodes" -EOF - -# Reload shell configuration -source ~/.bashrc -``` - -## Key Workflows to Learn - -### Cluster Management Workflow - -```mermaid -flowchart TD - A[Create Cluster] --> B[Check Status] - B --> C[Deploy Applications] - C --> D[Monitor Health] - D --> E{Issues?} - E -->|Yes| F[Debug & Fix] - E -->|No| G[Continue Development] - F --> D - G --> H[Scale or Update] - H --> D -``` +# View all namespaces +kubectl get namespaces -#### Common Cluster Commands -```bash -# Create a new cluster -openframe cluster create my-new-cluster +# Check ArgoCD applications +kubectl get applications -n argocd -# List all clusters -openframe cluster list +# Check all pods across namespaces +kubectl get pods --all-namespaces +``` -# Get detailed status -openframe cluster status my-cluster +> **Tip:** If you manage multiple clusters, use `kubectl config get-contexts` to see which context is currently active, and `kubectl config use-context k3d-my-cluster` to switch. -# Delete a cluster -openframe cluster delete my-cluster +--- -# Clean up resources -openframe cluster cleanup -``` +## 3. Install Charts on an Existing Cluster -### Application Deployment Workflow - -```mermaid -sequenceDiagram - participant Dev as Developer - participant CLI as OpenFrame CLI - participant ArgoCD as ArgoCD - participant K8s as Kubernetes - - Dev->>CLI: openframe chart install - CLI->>ArgoCD: Create Application - ArgoCD->>K8s: Deploy Resources - K8s-->>ArgoCD: Resource Status - ArgoCD-->>CLI: Sync Status - CLI-->>Dev: Deployment Complete -``` +If you want to re-install or update the OpenFrame charts on a cluster that already exists, use the `chart install` command: -#### Common Chart Commands ```bash -# Install a chart from repository -openframe chart install my-app \ - --repo=https://github.com/my-org/my-app \ - --path=charts/my-app - -# List installed applications -openframe chart list +# Interactive mode β€” launches the configuration wizard +openframe chart install -# Check application sync status -kubectl get applications -n argocd - -# Manually sync an application -kubectl patch application my-app -n argocd \ - --type=json \ - -p='[{"op": "replace", "path": "/spec/syncPolicy", "value": {"automated": {"selfHeal": true}}}]' +# Direct mode β€” specify cluster and deployment mode +openframe chart install my-cluster --deployment-mode=oss-tenant --verbose ``` -### Development Workflow +### Configuration Wizard -For local development with live Kubernetes integration: +When running interactively, the configuration wizard guides you through: -```bash -# Start a development intercept -openframe dev intercept my-service \ - --namespace=default \ - --port=3000:8080 - -# Generate scaffold for new service -openframe dev scaffold my-new-service \ - --template=microservice \ - --language=go -``` +1. **Deployment mode selection**: `oss-tenant`, `saas-tenant`, or `saas-shared` +2. **Configuration mode**: Default (recommended) or interactive (custom branch, Docker, ingress) +3. **GitHub repository settings** (if using a custom branch) +4. **Docker registry configuration** (for SaaS modes) +5. **Ingress configuration** (domain and routing settings) -## Essential Configuration +--- + +## 4. Set Up a Developer Intercept -### Customize OpenFrame Settings +One of OpenFrame CLI's most powerful features for developers is **Telepresence service intercepts** β€” the ability to route live Kubernetes traffic to your local machine for debugging. -Create a configuration file for personalized settings: +### Interactive Intercept Setup ```bash -mkdir -p ~/.openframe -cat > ~/.openframe/config.yaml << 'EOF' -# OpenFrame CLI Configuration -default: - cluster_name: "openframe-local" - namespace: "default" - log_level: "info" - -bootstrap: - mode: "oss-tenant" - interactive: true - timeout: "15m" - -cluster: - provider: "k3d" - nodes: 1 - -chart: - timeout: "10m" - wait: true - -dev: - intercept_timeout: "5m" - scaffold_templates_dir: "~/.openframe/templates" -EOF +openframe dev intercept ``` -### Configure Git Integration +The wizard prompts you to: +1. Select the target namespace +2. Select the service to intercept +3. Specify the local port to forward traffic to -For ArgoCD to access your repositories: +### Direct Intercept ```bash -# Add a Git repository to ArgoCD -kubectl apply -f - < - username: -EOF +# Intercept a specific service on port 3000 in the development namespace +openframe dev intercept my-api-service --port 3000 --namespace development + +# Intercept with environment variable export and custom header +openframe dev intercept my-api-service --port 8080 --env-file .env.local --header "x-user=developer" ``` -### Set Up Ingress (Optional) +When an intercept is active, all traffic sent to `my-api-service` inside the cluster is forwarded to your local process on the specified port. -Configure Traefik ingress for external access: +> **Prerequisites:** Telepresence must be installed. See [Prerequisites](prerequisites.md) for installation links. -```bash -# Create an ingress for your application -kubectl apply -f - < -n +> **Prerequisites:** Skaffold must be installed. If it is missing, the CLI will offer to install it automatically. -# Check logs -kubectl logs -n +--- -# Check resource constraints -kubectl get resourcequota -n -``` +## Common Initial Configuration -#### Service Not Accessible -```bash -# Check service endpoints -kubectl get endpoints -n +### Verbose Output -# Test internal connectivity -kubectl run test-pod --image=busybox -it --rm -- sh -# Inside pod: -wget -q -O- http://..svc.cluster.local -``` +For any command, add `-v` or `--verbose` to get detailed logs including ArgoCD sync progress: -#### ArgoCD Application Not Syncing ```bash -# Check application status -kubectl get application -n argocd -o yaml - -# Force refresh -kubectl patch application -n argocd \ - --type=json \ - -p='[{"op": "replace", "path": "/spec/source/targetRevision", "value": "HEAD"}]' - -# Manual sync -kubectl patch application -n argocd \ - --type=json \ - -p='[{"op": "add", "path": "/metadata/annotations/argocd.argoproj.io~1sync", "value": ""}]' +openframe bootstrap --verbose +openframe chart install my-cluster --verbose ``` -## Best Practices +### Silent Mode -### Development Environment -1. **Use namespaces**: Organize applications by environment or team -2. **Resource limits**: Set appropriate CPU/memory limits -3. **Health checks**: Implement liveness and readiness probes -4. **Secrets management**: Use Kubernetes secrets, not hardcoded values +Suppress all output except errors (useful in scripts): -### GitOps Workflow -1. **Infrastructure as Code**: Store all configurations in Git -2. **Automated sync**: Enable ArgoCD auto-sync for non-production -3. **Manual approval**: Require manual sync for production deployments -4. **Rollback strategy**: Use Git reverts for quick rollbacks +```bash +openframe cluster list --silent +``` -### Cluster Management -1. **Regular backups**: Backup cluster state and data -2. **Monitor resources**: Set up alerts for resource usage -3. **Update strategy**: Plan regular updates for cluster components -4. **Security scanning**: Regularly scan images and configurations +### Force Delete -## Next Steps +If a cluster deletion gets stuck, use `--force`: -Now that you're familiar with OpenFrame basics, explore advanced topics: +```bash +openframe cluster delete my-cluster --force +``` -### Development Workflows -Learn how to set up a complete development environment: -- Configure your IDE and editor -- Set up local development workflows -- Use service intercepts for debugging +### Cluster Cleanup -### Architecture Understanding -Dive deeper into how OpenFrame components work: -- Study the service architecture -- Understand data flows and dependencies -- Learn about security models and best practices +Remove unused Docker images and resources from cluster nodes: -### Advanced Deployment Patterns -Master sophisticated deployment strategies: -- Blue/green deployments -- Canary releases -- Multi-environment promotion pipelines +```bash +openframe cluster cleanup my-cluster +``` -## Getting Help +--- -### Community Resources -- **OpenMSP Slack**: [Join the community](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) for questions and support -- **Documentation**: Explore other guides in this repository -- **Examples**: Check the examples directory for sample configurations +## Deployment Mode Summary -### Useful Commands Reference -```bash -# Quick status check -openframe cluster status +| Mode | What Gets Deployed | When to Use | +|---|---|---| +| `oss-tenant` | Full self-hosted OpenFrame stack | Default β€” self-hosted MSP setup | +| `saas-tenant` | SaaS tenant configuration | When connecting to hosted Flamingo infrastructure | +| `saas-shared` | Shared SaaS platform | Multi-tenant shared platform deployment | -# View all resources -kubectl get all --all-namespaces +--- -# Emergency cluster reset -openframe cluster delete -openframe bootstrap +## Getting Help -# Export current configuration -kubectl get all -o yaml > backup.yaml +Every command has built-in help: -# View OpenFrame CLI logs -openframe --verbose +```bash +openframe --help +openframe cluster --help +openframe cluster create --help +openframe chart install --help +openframe dev intercept --help ``` -### Debugging Resources -- ArgoCD UI: https://localhost:8080 (after port forward) -- Traefik Dashboard: https://localhost:9000 (after port forward) -- Kubernetes Dashboard: Install with `kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml` +For community support and discussions, join the **OpenMSP Slack**: + +πŸ‘‰ [https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) -You're now ready to be productive with OpenFrame CLI! Explore the features, experiment with deployments, and join the community for support and sharing experiences. \ No newline at end of file +- 🌐 OpenMSP Community: [https://www.openmsp.ai/](https://www.openmsp.ai/) +- 🌐 OpenFrame: [https://openframe.ai](https://openframe.ai) +- 🌐 Flamingo: [https://flamingo.run](https://flamingo.run) diff --git a/docs/getting-started/introduction.md b/docs/getting-started/introduction.md index 2c2771af..93ef291b 100644 --- a/docs/getting-started/introduction.md +++ b/docs/getting-started/introduction.md @@ -1,142 +1,143 @@ # Introduction to OpenFrame CLI -OpenFrame CLI is a modern, interactive command-line tool for managing OpenFrame Kubernetes clusters and development workflows. It provides seamless cluster lifecycle management, chart installation with ArgoCD, and developer-friendly tools for service intercepts and scaffolding. - -[![OpenFrame Product Walkthrough (Beta Access)](https://img.youtube.com/vi/awc-yAnkhIo/maxresdefault.jpg)](https://www.youtube.com/watch?v=awc-yAnkhIo) +[![OpenFrame Product Walkthrough](https://img.youtube.com/vi/awc-yAnkhIo/maxresdefault.jpg)](https://www.youtube.com/watch?v=awc-yAnkhIo) ## What is OpenFrame CLI? -OpenFrame CLI is part of the broader OpenFrame ecosystem - an AI-powered MSP platform that replaces expensive proprietary software with open-source alternatives enhanced by intelligent automation. The CLI serves as the entry point for developers and operators to bootstrap, manage, and develop on OpenFrame environments. +**OpenFrame CLI** is a modern, interactive command-line tool for bootstrapping and managing [OpenFrame](https://openframe.ai) Kubernetes environments. It is part of the [Flamingo](https://flamingo.run) platform β€” an AI-powered MSP solution that replaces expensive proprietary software with open-source alternatives enhanced by intelligent automation. + +The CLI replaces fragile shell-script workflows with a structured Go application that supports both **guided wizard modes** for new users and fully **non-interactive CI/CD automation** for production pipelines. + +> **In one command**, `openframe bootstrap`, you get a fully operational K3D Kubernetes cluster with ArgoCD GitOps pipelines and all OpenFrame services installed and healthy. + +--- ## Key Features -### πŸš€ Complete Environment Bootstrapping -- **One-command setup**: Bootstrap entire OpenFrame environments with `openframe bootstrap` -- **Multi-mode deployment**: Support for OSS tenant, SaaS tenant, and SaaS shared modes -- **Automated cluster creation**: Creates K3D clusters with all necessary components -- **ArgoCD integration**: Automatic chart installation and application management - -### πŸ”§ Cluster Management -- **Lifecycle operations**: Create, delete, list, and monitor Kubernetes clusters -- **K3D integration**: Lightweight Kubernetes for development and testing -- **Status monitoring**: Real-time cluster health and resource monitoring -- **Easy cleanup**: Remove clusters and associated resources with simple commands - -### πŸ“¦ Chart & Application Management -- **Helm chart installation**: Streamlined chart deployment with dependency management -- **ArgoCD applications**: GitOps-based application lifecycle management -- **App-of-apps pattern**: Hierarchical application management for complex deployments -- **Synchronization monitoring**: Track deployment progress with detailed logging - -### πŸ›  Development Tools -- **Service intercepts**: Local development with Telepresence integration -- **Scaffolding**: Generate boilerplate code and configurations -- **Live debugging**: Debug services running in Kubernetes from your local environment -- **Hot reload**: Rapid development cycles with instant feedback +| Feature | Description | +|---|---| +| **Interactive Wizards** | Step-by-step guided setup for clusters, charts, and developer workflows | +| **One-Command Bootstrap** | Full environment setup: K3D cluster + ArgoCD + app-of-apps deployment | +| **Cluster Lifecycle Management** | Create, delete, list, and inspect K3D Kubernetes clusters | +| **GitOps via ArgoCD** | Automated chart installation using the App-of-Apps pattern | +| **Developer Intercepts** | Route Kubernetes service traffic to your local machine via Telepresence | +| **Live Reload Development** | Skaffold-powered hot-reload development sessions inside the cluster | +| **CI/CD Ready** | Non-interactive flags for every operation, suitable for automation pipelines | +| **Prerequisite Checking** | Automatically validates and guides installation of required tools | +| **WSL2 Support** | First-class Windows WSL2 compatibility with platform-specific optimizations | +| **Multiple Deployment Modes** | Supports `oss-tenant`, `saas-tenant`, and `saas-shared` deployment targets | + +--- ## Target Audience -### DevOps Engineers -- Simplify Kubernetes cluster management -- Automate deployment pipelines with GitOps -- Monitor and maintain OpenFrame environments - -### Software Developers -- Develop and test microservices locally -- Debug applications running in Kubernetes -- Scaffold new services and components quickly +OpenFrame CLI is designed for: -### System Administrators -- Bootstrap complete OpenFrame environments -- Manage multiple clusters and deployments -- Monitor system health and performance +- **MSP Engineers** setting up self-hosted OpenFrame environments +- **Platform Engineers** automating Kubernetes cluster provisioning in CI/CD +- **Developers** who need to intercept and locally debug services running inside a Kubernetes cluster +- **DevOps Teams** managing GitOps deployments via ArgoCD on K3D -### MSP Teams -- Deploy OpenFrame for multiple tenants -- Manage client environments efficiently -- Reduce vendor costs with open-source alternatives +--- ## Architecture Overview ```mermaid graph TB - subgraph "CLI Commands" - Bootstrap[openframe bootstrap] - Cluster[openframe cluster] - Chart[openframe chart] - Dev[openframe dev] + subgraph CLI["CLI Entry Points"] + Root["openframe (root)"] + Bootstrap["bootstrap"] + Cluster["cluster"] + Chart["chart"] + Dev["dev"] end - - subgraph "Core Services" - ClusterSvc[Cluster Management] - ChartSvc[Chart Installation] - DevSvc[Development Tools] + + subgraph Internal["Internal Services"] + BootstrapSvc["bootstrap.Service"] + ClusterSvc["cluster.ClusterService"] + ChartSvc["chart.ChartService"] + DevSvc["dev.Service"] end - - subgraph "External Tools" - K3D[K3D Clusters] - Helm[Helm Charts] - ArgoCD[ArgoCD Apps] - Telepresence[Service Intercepts] + + subgraph Providers["Infrastructure Providers"] + K3dMgr["k3d.K3dManager"] + HelmMgr["helm.HelmManager"] + ArgoCDMgr["argocd.Manager"] + TelepresenceProv["telepresence.Provider"] end - - subgraph "Target Environment" - K8s[Kubernetes] - Apps[Applications] - Services[Microservices] + + subgraph External["External Tools"] + K3D["K3D CLI"] + HelmCLI["Helm CLI"] + ArgoCD["ArgoCD"] + TelepresenceCLI["Telepresence"] + SkaffoldCLI["Skaffold"] end - - Bootstrap --> ClusterSvc - Bootstrap --> ChartSvc + + Root --> Bootstrap + Root --> Cluster + Root --> Chart + Root --> Dev + + Bootstrap --> BootstrapSvc Cluster --> ClusterSvc Chart --> ChartSvc Dev --> DevSvc - - ClusterSvc --> K3D - ChartSvc --> Helm - ChartSvc --> ArgoCD - DevSvc --> Telepresence - - K3D --> K8s - Helm --> Apps - ArgoCD --> Apps - Telepresence --> Services + + BootstrapSvc --> ClusterSvc + BootstrapSvc --> ChartSvc + ClusterSvc --> K3dMgr + ChartSvc --> HelmMgr + ChartSvc --> ArgoCDMgr + DevSvc --> TelepresenceProv + + K3dMgr --> K3D + HelmMgr --> HelmCLI + ArgoCDMgr --> ArgoCD + TelepresenceProv --> TelepresenceCLI + TelepresenceProv --> SkaffoldCLI ``` -## Key Benefits +--- + +## Command Overview -| Benefit | Description | -|---------|-------------| -| **Rapid Setup** | Go from zero to running OpenFrame environment in minutes | -| **Developer Friendly** | Interactive prompts, helpful error messages, and clear documentation | -| **Production Ready** | Battle-tested components with enterprise-grade reliability | -| **Open Source** | Complete transparency, community-driven development | -| **Cost Effective** | Replace expensive proprietary tools with open-source alternatives | -| **GitOps Native** | Built-in ArgoCD integration for modern deployment practices | +| Command | What It Does | +|---|---| +| `openframe bootstrap` | Full environment setup: cluster + ArgoCD + app-of-apps | +| `openframe cluster create` | Create a K3D Kubernetes cluster | +| `openframe cluster list` | List all managed clusters | +| `openframe cluster status` | Show cluster health and ArgoCD app status | +| `openframe cluster delete` | Delete a cluster | +| `openframe chart install` | Install ArgoCD and charts on an existing cluster | +| `openframe dev intercept` | Intercept Kubernetes service traffic locally via Telepresence | +| `openframe dev skaffold` | Run a live-reload development session with Skaffold | -## How It Works +--- -1. **Bootstrap**: Run `openframe bootstrap` to create a complete environment -2. **Develop**: Use `openframe dev` commands for local development workflows -3. **Deploy**: Manage applications with `openframe chart` commands -4. **Monitor**: Check cluster status with `openframe cluster` commands +## Deployment Modes -The CLI handles all the complexity of Kubernetes cluster management, chart installations, and development tool configuration, allowing you to focus on building and deploying applications. +OpenFrame CLI supports three deployment modes targeting different repository configurations: -## Next Steps +| Mode | Repository | Use Case | +|---|---|---| +| `oss-tenant` | `flamingo-stack/openframe-oss-tenant` | Default self-hosted OpenFrame | +| `saas-tenant` | `flamingo-stack/openframe-saas-tenant` | SaaS tenant deployment | +| `saas-shared` | `flamingo-stack/openframe-saas-shared` | Shared SaaS platform | -Ready to get started? Continue with these guides: +--- -- **[Prerequisites](prerequisites.md)** - Check system requirements and install dependencies -- **[Quick Start](quick-start.md)** - Get OpenFrame running in 5 minutes -- **[First Steps](first-steps.md)** - Explore key features and workflows +## Where to Get Help -## Community and Support +- πŸ’¬ **Community**: Join the [OpenMSP Slack](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) +- 🌐 **OpenMSP Community**: [https://www.openmsp.ai/](https://www.openmsp.ai/) +- 🌐 **OpenFrame**: [https://openframe.ai](https://openframe.ai) +- 🌐 **Flamingo**: [https://flamingo.run](https://flamingo.run) -OpenFrame is built by the community for the community. Get help and connect with other users: +--- -- **OpenMSP Slack**: [Join the community](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) -- **Website**: [https://flamingo.run](https://flamingo.run) -- **OpenFrame Platform**: [https://openframe.ai](https://openframe.ai) +## Continue Reading -> **Note**: We don't use GitHub Issues or Discussions - all support and community interaction happens in the OpenMSP Slack community. \ No newline at end of file +- Review [Prerequisites](prerequisites.md) to prepare your environment +- Follow the [Quick Start Guide](quick-start.md) to get up and running in minutes +- Explore [First Steps](first-steps.md) after your first successful bootstrap diff --git a/docs/getting-started/prerequisites.md b/docs/getting-started/prerequisites.md index 314e0978..b92eed03 100644 --- a/docs/getting-started/prerequisites.md +++ b/docs/getting-started/prerequisites.md @@ -1,315 +1,138 @@ # Prerequisites -Before installing and using OpenFrame CLI, ensure your system meets the following requirements and has the necessary dependencies installed. +Before you can install and use OpenFrame CLI, you need to ensure your system meets the hardware requirements and has the required tools installed. The CLI automatically checks for prerequisites and will guide you through installing anything that is missing. -## System Requirements +--- -### Hardware Requirements +## Hardware Requirements -| Resource | Minimum | Recommended | -|----------|---------|-------------| -| **RAM** | 24GB | 32GB | -| **CPU Cores** | 6 cores | 12 cores | -| **Disk Space** | 50GB free | 100GB free | -| **Architecture** | x86_64, ARM64 | x86_64, ARM64 | +| Tier | RAM | CPU Cores | Disk Space | +|---|---|---|---| +| **Minimum** | 24 GB | 6 cores | 50 GB | +| **Recommended** | 32 GB | 12 cores | 100 GB | -### Operating System Support +> **Note:** K3D runs Kubernetes nodes as Docker containers. Insufficient memory is the most common cause of failed bootstraps. Always ensure you have at least 24 GB of RAM available before running `openframe bootstrap`. -| OS | Version | Status | -|---|---------|--------| -| **Linux** | Ubuntu 20.04+, CentOS 8+, RHEL 8+ | βœ… Fully Supported | -| **macOS** | 11+ (Big Sur and later) | βœ… Fully Supported | -| **Windows** | Windows 10/11 with WSL2 | ⚠️ Supported via WSL2 | +--- -> **Windows Users**: OpenFrame CLI requires WSL2 for proper Kubernetes integration. Native Windows support is not currently available. +## Required Software -## Required Dependencies +The following tools must be installed and accessible on your `$PATH` before running cluster or chart operations. The OpenFrame CLI prerequisite checker will validate all of these at startup. -### Core Dependencies +### Cluster Prerequisites -These tools must be installed before using OpenFrame CLI: +| Tool | Minimum Version | Purpose | Install Guide | +|---|---|---|---| +| **Docker** | 20.x+ (daemon running) | Container runtime for K3D nodes | [docker.com/get-docker](https://docs.docker.com/get-docker/) | +| **kubectl** | 1.25+ | Kubernetes API client | [kubernetes.io/docs/tasks/tools](https://kubernetes.io/docs/tasks/tools/) | +| **k3d** | 5.x+ | K3D cluster management | [k3d.io](https://k3d.io/#installation) | +| **Helm** | 3.x+ | Kubernetes package manager | [helm.sh/docs/intro/install](https://helm.sh/docs/intro/install/) | -| Tool | Version | Purpose | Installation | -|------|---------|---------|--------------| -| **Docker** | 20.10+ | Container runtime for K3D clusters | [Docker Install Guide](https://docs.docker.com/get-docker/) | -| **kubectl** | 1.25+ | Kubernetes command-line tool | [kubectl Install Guide](https://kubernetes.io/docs/tasks/tools/) | -| **Helm** | 3.10+ | Kubernetes package manager | [Helm Install Guide](https://helm.sh/docs/intro/install/) | -| **K3D** | 5.0+ | Lightweight Kubernetes clusters | [K3D Install Guide](https://k3d.io/v5.4.6/#installation) | +### Chart Prerequisites -### Development Dependencies (Optional) +| Tool | Minimum Version | Purpose | Install Guide | +|---|---|---|---| +| **Git** | 2.x+ | Cloning app-of-apps repositories | [git-scm.com/downloads](https://git-scm.com/downloads) | +| **Helm** | 3.x+ | Helm chart operations | [helm.sh/docs/intro/install](https://helm.sh/docs/intro/install/) | +| **mkcert** | Latest | Local TLS certificate generation | [github.com/FiloSottile/mkcert](https://github.com/FiloSottile/mkcert) | -Required only if using development features (`openframe dev` commands): +### Developer Workflow Prerequisites (Optional) -| Tool | Version | Purpose | Installation | -|------|---------|---------|--------------| -| **Telepresence** | 2.10+ | Service intercepts for local development | [Telepresence Install](https://www.telepresence.io/docs/latest/install/) | -| **jq** | 1.6+ | JSON processing for dev scripts | [jq Install Guide](https://jqlang.github.io/jq/download/) | +These are only required if you use `openframe dev` commands: -## Installation Verification +| Tool | Purpose | Install Guide | +|---|---|---| +| **Telepresence** | Service traffic interception | [telepresence.io/docs/install](https://www.telepresence.io/docs/install/client) | +| **Skaffold** | Live-reload development sessions | [skaffold.dev/docs/install](https://skaffold.dev/docs/install/) | -### Check Docker -```bash -docker --version -docker ps -``` +--- -Expected output: -```text -Docker version 20.10.0 or higher -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -``` +## Operating System Support -### Check kubectl -```bash -kubectl version --client -``` +| OS | Status | Notes | +|---|---|---| +| **Linux** (x86_64, arm64) | βœ… Fully supported | Primary development platform | +| **macOS** (Intel & Apple Silicon) | βœ… Fully supported | Docker Desktop required | +| **Windows** (via WSL2) | βœ… Supported | WSL2 + Docker Desktop required; WSL2 IP detection is automatic | -Expected output: -```text -Client Version: version.Info{Major:"1", Minor:"25"+...} -``` +### Windows Requirements -### Check Helm -```bash -helm version -``` +Windows users must use **WSL2** (Windows Subsystem for Linux 2). The CLI includes first-class WSL2 support with automatic IP detection and inotify limit configuration. -Expected output: -```text -version.BuildInfo{Version:"v3.10.0"+...} -``` +1. Install [WSL2](https://docs.microsoft.com/en-us/windows/wsl/install) +2. Install [Docker Desktop for Windows](https://www.docker.com/products/docker-desktop/) and enable WSL2 integration +3. Install the OpenFrame CLI inside your WSL2 environment or use the Windows AMD64 binary -### Check K3D -```bash -k3d version -``` - -Expected output: -```text -k3d version v5.0.0+ -``` +**Windows AMD64 binary**: [openframe-cli_windows_amd64.zip](https://github.com/flamingo-stack/openframe-cli/releases/latest/download/openframe-cli_windows_amd64.zip) -### Check Telepresence (Optional) -```bash -telepresence version -``` +--- -Expected output: -```text -Client: v2.10.0+ -``` +## Go Build Requirements (Source Builds Only) -### Check jq (Optional) -```bash -jq --version -``` +If you are building from source, you also need: -Expected output: -```text -jq-1.6+ -``` +| Tool | Version | Purpose | +|---|---|---| +| **Go** | 1.22+ | Compiling the CLI from source | -## Network Requirements - -### Outbound Connectivity -OpenFrame CLI requires internet access for: -- Pulling Docker images -- Downloading Helm charts -- Accessing Git repositories -- Installing prerequisites - -### Port Requirements -| Port Range | Protocol | Purpose | -|------------|----------|---------| -| 80, 443 | TCP | HTTPS/HTTP for downloads | -| 6443 | TCP | Kubernetes API server | -| 30000-32767 | TCP | Kubernetes NodePort range | -| 2376, 2377 | TCP | Docker daemon (if remote) | - -### Firewall Considerations -Ensure your firewall allows: -- Docker daemon communication -- Kubernetes cluster communication -- Outbound HTTPS connections +--- ## Environment Variables -Set these environment variables for optimal experience: - -### Required -```bash -# Docker daemon configuration -export DOCKER_HOST="unix:///var/run/docker.sock" +The following environment variables may be relevant depending on your deployment mode: -# Kubernetes configuration -export KUBECONFIG="$HOME/.kube/config" -``` +| Variable | Required For | Description | +|---|---|---| +| `KUBECONFIG` | All cluster operations | Path to your kubeconfig file (defaults to `~/.kube/config`) | +| GitHub Personal Access Token | `saas-tenant` / `saas-shared` modes | Accessing private GHCR container registry | -### Optional -```bash -# OpenFrame CLI configuration -export OPENFRAME_LOG_LEVEL="info" -export OPENFRAME_CONFIG_DIR="$HOME/.openframe" +> **Tip:** For `oss-tenant` mode (the default self-hosted deployment), no special environment variables are required beyond a working Docker daemon. -# Development tools -export TELEPRESENCE_LOGIN_DOMAIN="auth.datawire.io" -``` +--- -## Account Requirements +## Verification Commands -### Container Registry Access -- **Public registries**: Docker Hub, GHCR.io (no authentication required) -- **Private registries**: Configure Docker credentials if using private images +Run these commands to confirm all prerequisites are installed and ready: -### Git Repository Access -- **Public repositories**: No authentication required -- **Private repositories**: Configure SSH keys or personal access tokens +```bash +# Verify Docker is running +docker info -## Quick Setup Script +# Verify kubectl +kubectl version --client -For convenience, here's a script to verify all prerequisites: +# Verify k3d +k3d version -```bash -#!/bin/bash -# prerequisites-check.sh - -echo "πŸ” Checking OpenFrame CLI prerequisites..." - -# Function to check if command exists -command_exists() { - command -v "$1" >/dev/null 2>&1 -} - -# Function to check version -check_version() { - local tool="$1" - local min_version="$2" - local current_version="$3" - - echo " $tool: $current_version (required: $min_version+)" -} - -errors=0 - -# Check Docker -if command_exists docker; then - docker_version=$(docker --version | cut -d' ' -f3 | cut -d',' -f1) - check_version "Docker" "20.10.0" "$docker_version" - if ! docker ps >/dev/null 2>&1; then - echo " ❌ Docker daemon is not running or accessible" - ((errors++)) - fi -else - echo " ❌ Docker not found" - ((errors++)) -fi - -# Check kubectl -if command_exists kubectl; then - kubectl_version=$(kubectl version --client -o json 2>/dev/null | jq -r '.clientVersion.gitVersion' 2>/dev/null || echo "unknown") - check_version "kubectl" "1.25.0" "$kubectl_version" -else - echo " ❌ kubectl not found" - ((errors++)) -fi - -# Check Helm -if command_exists helm; then - helm_version=$(helm version --short | cut -d'+' -f1) - check_version "Helm" "3.10.0" "$helm_version" -else - echo " ❌ Helm not found" - ((errors++)) -fi - -# Check K3D -if command_exists k3d; then - k3d_version=$(k3d version | grep k3d | cut -d' ' -f2) - check_version "K3D" "5.0.0" "$k3d_version" -else - echo " ❌ K3D not found" - ((errors++)) -fi - -# Check optional tools -echo "" -echo "πŸ“‹ Optional development tools:" - -if command_exists telepresence; then - telepresence_version=$(telepresence version --output=json 2>/dev/null | jq -r '.client.version' 2>/dev/null || "unknown") - check_version "Telepresence" "2.10.0" "$telepresence_version" -else - echo " ⚠️ Telepresence not found (optional for dev workflows)" -fi - -if command_exists jq; then - jq_version=$(jq --version | cut -d'-' -f2) - check_version "jq" "1.6" "$jq_version" -else - echo " ⚠️ jq not found (optional for dev scripts)" -fi - -echo "" -if [ $errors -eq 0 ]; then - echo "βœ… All required prerequisites are installed!" - echo "πŸš€ You're ready to install OpenFrame CLI" -else - echo "❌ $errors required dependencies are missing" - echo "πŸ“– Please install missing dependencies before proceeding" - exit 1 -fi -``` +# Verify Helm +helm version -Save this as `prerequisites-check.sh`, make it executable, and run: +# Verify Git +git --version -```bash -chmod +x prerequisites-check.sh -./prerequisites-check.sh +# Verify mkcert +mkcert --version ``` -## Troubleshooting Common Issues +All commands should return version information without errors. If Docker is not running, start it before proceeding. -### Docker Permission Issues -If you get permission denied errors: +--- -```bash -# Add your user to the docker group -sudo usermod -aG docker $USER +## Automatic Prerequisite Checking -# Log out and back in, or run: -newgrp docker -``` +When you run any `cluster` or `chart` command, the CLI automatically runs a prerequisite check. Missing tools are listed with platform-specific installation instructions: -### kubectl Not Finding Config ```bash -# Create kubeconfig directory -mkdir -p ~/.kube - -# Verify KUBECONFIG environment variable -echo `$KUBECONFIG` +openframe cluster create +# If prerequisites are missing, you will see: +# βœ— Missing: k3d +# Install: curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash ``` -### K3D Installation Issues on macOS -```bash -# If using Homebrew -brew install k3d - -# If using curl -curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash -``` +You don't need to memorize all installation commands β€” the CLI's built-in checker will guide you interactively. -### WSL2 Setup on Windows -1. Enable WSL2: `wsl --install` -2. Install Ubuntu from Microsoft Store -3. Install Docker Desktop with WSL2 backend -4. Install all prerequisites inside WSL2 environment +--- ## Next Steps -Once all prerequisites are installed and verified: - -1. **[Quick Start Guide](quick-start.md)** - Install OpenFrame CLI and bootstrap your first environment -2. **[First Steps Guide](first-steps.md)** - Explore key features and workflows - -Need help? Join our community: -- **OpenMSP Slack**: [Join here](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) \ No newline at end of file +Once your prerequisites are confirmed, continue to the [Quick Start Guide](quick-start.md) to bootstrap your first OpenFrame environment. diff --git a/docs/getting-started/quick-start.md b/docs/getting-started/quick-start.md index 72253b3f..78cc4b39 100644 --- a/docs/getting-started/quick-start.md +++ b/docs/getting-started/quick-start.md @@ -1,355 +1,189 @@ -# Quick Start Guide +# Quick Start -Get OpenFrame CLI up and running in 5 minutes! This guide will walk you through installing OpenFrame CLI and bootstrapping your first environment. +Get a fully operational OpenFrame Kubernetes environment running in under 5 minutes. -[![OpenFrame: 5-Minute MSP Platform Walkthrough - Cut Vendor Costs & Automate Ops](https://img.youtube.com/vi/er-z6IUnAps/maxresdefault.jpg)](https://www.youtube.com/watch?v=er-z6IUnAps) +[![Getting Started with OpenFrame](https://img.youtube.com/vi/-_56_qYvMWk/maxresdefault.jpg)](https://www.youtube.com/watch?v=-_56_qYvMWk) -## TL;DR - 5-Minute Setup +--- -If you have all prerequisites installed, here's the fastest path: +## TL;DR β€” One-Command Bootstrap -```bash -# 1. Download and install OpenFrame CLI (choose your platform) -# Linux/macOS -curl -fsSL https://github.com/flamingo-stack/openframe-cli/releases/latest/download/openframe-cli_linux_amd64.tar.gz | tar -xz -sudo mv openframe /usr/local/bin/ - -# Windows (download manually) -# Download: https://github.com/flamingo-stack/openframe-cli/releases/latest/download/openframe-cli_windows_amd64.zip +If you already have Docker, kubectl, k3d, Helm, Git, and mkcert installed, this is all you need: -# 2. Verify installation -openframe --version - -# 3. Bootstrap complete environment +```bash openframe bootstrap - -# 4. Check cluster status -openframe cluster status ``` -That's it! Continue reading for detailed steps and explanations. +The interactive wizard will guide you through the rest. For a fully automated, non-interactive setup: -## Step 1: Install OpenFrame CLI +```bash +openframe bootstrap my-cluster --deployment-mode=oss-tenant --non-interactive +``` -### Option A: Download Pre-built Binary (Recommended) +--- -Choose your platform and download the latest release: +## Step 1: Install the OpenFrame CLI -#### Linux (AMD64) -```bash -curl -fsSL https://github.com/flamingo-stack/openframe-cli/releases/latest/download/openframe-cli_linux_amd64.tar.gz | tar -xz -sudo mv openframe /usr/local/bin/ -chmod +x /usr/local/bin/openframe -``` +### Linux / macOS -#### Linux (ARM64) -```bash -curl -fsSL https://github.com/flamingo-stack/openframe-cli/releases/latest/download/openframe-cli_linux_arm64.tar.gz | tar -xz -sudo mv openframe /usr/local/bin/ -chmod +x /usr/local/bin/openframe -``` +Download the latest release for your platform from the [GitHub Releases page](https://github.com/flamingo-stack/openframe-cli/releases/latest) and place the binary on your `$PATH`: -#### macOS (AMD64) ```bash -curl -fsSL https://github.com/flamingo-stack/openframe-cli/releases/latest/download/openframe-cli_darwin_amd64.tar.gz | tar -xz -sudo mv openframe /usr/local/bin/ -chmod +x /usr/local/bin/openframe +# Example for Linux amd64 +curl -Lo openframe https://github.com/flamingo-stack/openframe-cli/releases/latest/download/openframe-cli_linux_amd64 +chmod +x openframe +sudo mv openframe /usr/local/bin/openframe ``` -#### macOS (Apple Silicon) ```bash -curl -fsSL https://github.com/flamingo-stack/openframe-cli/releases/latest/download/openframe-cli_darwin_arm64.tar.gz | tar -xz -sudo mv openframe /usr/local/bin/ -chmod +x /usr/local/bin/openframe +# Example for macOS arm64 (Apple Silicon) +curl -Lo openframe https://github.com/flamingo-stack/openframe-cli/releases/latest/download/openframe-cli_darwin_arm64 +chmod +x openframe +sudo mv openframe /usr/local/bin/openframe ``` -#### Windows (AMD64) -1. Download: https://github.com/flamingo-stack/openframe-cli/releases/latest/download/openframe-cli_windows_amd64.zip -2. Extract the ZIP file -3. Move `openframe.exe` to a directory in your `PATH` -4. Open WSL2 terminal and verify access +### Windows (AMD64) -### Option B: Build from Source +1. Download [openframe-cli_windows_amd64.zip](https://github.com/flamingo-stack/openframe-cli/releases/latest/download/openframe-cli_windows_amd64.zip) +2. Extract the archive +3. Move `openframe.exe` to a directory on your `$PATH` (or run from its extracted location) -If you have Go 1.24.6+ installed: +### Build from Source ```bash -# Clone the repository git clone https://github.com/flamingo-stack/openframe-cli.git cd openframe-cli - -# Build the binary go build -o openframe main.go - -# Move to PATH -sudo mv openframe /usr/local/bin/ +sudo mv openframe /usr/local/bin/openframe ``` -## Step 2: Verify Installation +--- -Confirm OpenFrame CLI is installed correctly: +## Step 2: Verify the Installation ```bash openframe --version ``` Expected output: + ```text -openframe version v1.x.x (commit: abc123, built: 2024-01-01) +dev (none) built on unknown ``` -Check available commands: +(Release builds will show the actual version number.) + ```bash openframe --help ``` -You should see the main command groups: -- `bootstrap` - Complete environment setup -- `cluster` - Kubernetes cluster management -- `chart` - Helm chart and ArgoCD management -- `dev` - Development tools and workflows +You should see the OpenFrame ASCII logo and the list of available commands. + +--- ## Step 3: Bootstrap Your First Environment -The bootstrap command creates a complete OpenFrame environment with a single command: +### Option A β€” Interactive Mode (Recommended for First-Time Users) ```bash openframe bootstrap ``` -### Interactive Bootstrap - -The command will guide you through setup with prompts: +The wizard will ask you to: -```text -πŸš€ OpenFrame Bootstrap Wizard - -? Select deployment mode: - > oss-tenant (Single tenant, open source) - saas-tenant (Multi-tenant SaaS mode) - saas-shared (Shared SaaS infrastructure) - -? Enable verbose logging? (y/N): y +1. **Enter a cluster name** (or accept the default) +2. **Select a deployment mode** (`oss-tenant` is the default self-hosted option) +3. **Choose default or custom configuration** (default is recommended to start) -πŸ” Checking prerequisites... -βœ… Docker is running -βœ… kubectl is available -βœ… Helm is available -βœ… K3D is available +The bootstrap process will: -🎯 Creating K3D cluster... -βœ… Cluster 'openframe-local' created +- Check and install prerequisites (Docker, kubectl, k3d, Helm, Git, mkcert) +- Create a K3D Kubernetes cluster +- Install ArgoCD via Helm +- Clone your app-of-apps repository +- Install the OpenFrame app-of-apps chart +- Wait for all ArgoCD applications to reach `Healthy + Synced` -🎭 Installing ArgoCD... -βœ… ArgoCD installed and ready - -πŸ“¦ Installing application charts... -βœ… App-of-apps synchronized -βœ… All applications healthy - -πŸŽ‰ OpenFrame environment is ready! -``` - -### Non-Interactive Bootstrap - -For scripts and CI/CD, use flags to skip prompts: +### Option B β€” Non-Interactive / CI Mode ```bash -openframe bootstrap \ - --mode=oss-tenant \ - --non-interactive \ - --verbose +openframe bootstrap my-cluster --deployment-mode=oss-tenant --non-interactive ``` -## Step 4: Verify Your Environment +This bypasses all prompts and uses defaults for every option. Suitable for CI/CD pipelines. -### Check Cluster Status -```bash -openframe cluster status -``` +--- -Expected output: -```text -πŸ“Š Cluster Status: openframe-local - -Cluster Info: - Name: openframe-local - Status: Running βœ… - Nodes: 1 (1 ready) - Kubernetes Version: v1.28.6+k3s1 - -Resource Usage: - CPU: 2 cores (25% used) - Memory: 8Gi (45% used) - Storage: 50Gi (12% used) - -Key Services: - ArgoCD: Healthy βœ… - Traefik: Healthy βœ… - CoreDNS: Healthy βœ… -``` +## Step 4: Verify the Environment -### Access ArgoCD UI -The bootstrap process installs ArgoCD. Access the web interface: +After bootstrap completes, check your cluster status: ```bash -# Get ArgoCD URL and credentials -kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echo -kubectl port-forward svc/argocd-server -n argocd 8080:443 +openframe cluster list ``` -Then open: http://localhost:8080 -- Username: `admin` -- Password: (from the command above) - -### View Running Applications ```bash -# List all pods across namespaces -kubectl get pods --all-namespaces - -# Check ArgoCD applications -kubectl get applications -n argocd +openframe cluster status my-cluster --detailed ``` -## Step 5: Test Basic Functionality +Expected output shows your cluster nodes as `Ready` and all ArgoCD applications as `Healthy`. -### Create a Test Namespace -```bash -kubectl create namespace test-app -kubectl get namespaces -``` +--- -### Deploy a Simple Application -```bash -# Create a test deployment -kubectl create deployment nginx --image=nginx:latest -n test-app -kubectl expose deployment nginx --port=80 --target-port=80 -n test-app +## Expected Output -# Check deployment -kubectl get pods -n test-app -kubectl get svc -n test-app -``` +A successful bootstrap looks like this: -### Test Service Access -```bash -# Port forward to test connectivity -kubectl port-forward svc/nginx -n test-app 8081:80 & +```text + ____ _____ _ + / __ \___ ___ ____ / ___/| | +/ /_/ / _ \/ -_) _ \/ /__ |_| +\____/ .__/\__/_//_/\___/ (_) + /_/ CLI v1.x.x -# Test the service -curl http://localhost:8081 +βœ” Checking prerequisites... +βœ” Docker: running +βœ” kubectl: installed +βœ” k3d: installed +βœ” Helm: installed +βœ” Creating cluster: my-cluster +βœ” Cluster created successfully +βœ” Installing ArgoCD... +βœ” ArgoCD deployed +βœ” Cloning app-of-apps repository... +βœ” Installing app-of-apps chart... +βœ” Waiting for applications to sync... +βœ” All applications: Healthy + Synced -# Clean up -kill %1 # Stop port-forward -kubectl delete namespace test-app +Environment ready! πŸš€ ``` -## What Just Happened? - -The bootstrap process created: - -1. **K3D Cluster**: A lightweight Kubernetes cluster running in Docker -2. **ArgoCD**: GitOps deployment tool for application management -3. **Traefik**: Ingress controller for routing traffic -4. **Core Services**: DNS, metrics, and monitoring components -5. **Application Templates**: Ready-to-use deployment patterns - -## Expected Results - -After successful bootstrap: - -| Component | Status | Access Method | -|-----------|--------|---------------| -| **Kubernetes API** | βœ… Running | `kubectl` commands | -| **ArgoCD UI** | βœ… Running | Port forward to 8080 | -| **Traefik Dashboard** | βœ… Running | Port forward to 9000 | -| **Container Registry** | βœ… Running | Docker daemon | +--- -## Troubleshooting +## Quick Cluster Commands -### Bootstrap Fails with Docker Error -```bash -# Check Docker status -docker ps -docker info - -# Restart Docker if needed -sudo systemctl restart docker # Linux -# or restart Docker Desktop on macOS/Windows -``` +Once your cluster is running, here are the most useful commands: -### Kubectl Cannot Connect ```bash -# Check kubeconfig -kubectl config current-context -kubectl config get-contexts +# List all clusters +openframe cluster list -# Switch to openframe context if needed -kubectl config use-context k3d-openframe-local -``` +# Check cluster status with app details +openframe cluster status my-cluster --detailed -### ArgoCD Not Accessible -```bash -# Check ArgoCD pods -kubectl get pods -n argocd +# Install charts on an existing cluster +openframe chart install my-cluster --deployment-mode=oss-tenant -# Restart ArgoCD if needed -kubectl rollout restart deployment argocd-server -n argocd +# Delete a cluster when done +openframe cluster delete my-cluster ``` -### Port Already in Use -```bash -# Find and kill processes using required ports -lsof -ti:6443,8080,9000 | xargs kill -9 - -# Or use different ports -kubectl port-forward svc/argocd-server -n argocd 8081:443 -``` +--- ## Next Steps -πŸŽ‰ **Congratulations!** You now have a running OpenFrame environment. Here's what to explore next: - -- **[First Steps Guide](first-steps.md)** - Learn key workflows and features -- **[Architecture Overview](../development/architecture/README.md)** - Understand how components work together -- **[Development Setup](../development/setup/local-development.md)** - Configure your development environment - -## Common Next Actions - -### Deploy Your First Application -```bash -# Use ArgoCD to deploy from Git -openframe chart install my-app \ - --repo=https://github.com/your-org/your-app \ - --path=helm-chart -``` - -### Start Local Development -```bash -# Intercept a service for local development -openframe dev intercept my-service \ - --namespace=default \ - --port=8080:3000 -``` - -### Explore the Environment -```bash -# List available commands -openframe --help - -# Get cluster information -openframe cluster list -openframe cluster status - -# Check chart installations -openframe chart list -``` - -## Getting Help - -Need assistance? The OpenFrame community is here to help: - -- **OpenMSP Slack**: [Join the community](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) -- **Documentation**: Browse other guides in this repository -- **GitHub Issues**: Report bugs or request features (but use Slack for general support) +After your first successful bootstrap: -> **Note**: All community support happens in Slack - we don't monitor GitHub Issues for support requests. \ No newline at end of file +- Follow the [First Steps Guide](first-steps.md) to explore key features +- Review [Prerequisites](prerequisites.md) to understand all system requirements +- Join the [OpenMSP Community Slack](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA) for support and updates diff --git a/docs/architecture/.gitignore b/docs/reference/architecture/.gitignore similarity index 100% rename from docs/architecture/.gitignore rename to docs/reference/architecture/.gitignore diff --git a/docs/reference/architecture/overview.md b/docs/reference/architecture/overview.md new file mode 100644 index 00000000..873e8b58 --- /dev/null +++ b/docs/reference/architecture/overview.md @@ -0,0 +1,462 @@ +# openframe-cli Module Documentation + +# OpenFrame CLI Architecture Documentation + +[![OpenFrame Preview Webinar](https://img.youtube.com/vi/bINdW0CQbvY/hqdefault.jpg)](https://www.youtube.com/watch?v=bINdW0CQbvY) + +## Overview + +OpenFrame CLI is a modern, interactive command-line tool for bootstrapping and managing OpenFrame Kubernetes environments. It orchestrates the complete lifecycle of K3D clusters, ArgoCD GitOps deployments, and developer workflows (service intercepts via Telepresence, live reloading via Skaffold) through a unified interface. As part of the [OpenFrame](https://openframe.ai) ecosystem built by [Flamingo](https://flamingo.run), it replaces shell script workflows with a structured Go CLI that supports both interactive wizard modes and fully non-interactive CI/CD automation. + +--- + +## Architecture + +### High-Level Architecture Diagram + +```mermaid +graph TB + subgraph CLI["CLI Entry Points"] + Root["openframe (root)"] + Bootstrap["bootstrap"] + Cluster["cluster"] + Chart["chart"] + Dev["dev"] + end + + subgraph Internal["Internal Services"] + BootstrapSvc["bootstrap.Service"] + ClusterSvc["cluster.ClusterService"] + ChartSvc["chart.ChartService"] + DevSvc["dev.Service"] + end + + subgraph Providers["Infrastructure Providers"] + K3dMgr["k3d.K3dManager"] + HelmMgr["helm.HelmManager"] + ArgoCDMgr["argocd.Manager"] + GitRepo["git.Repository"] + TelepresenceProv["telepresence.Provider"] + KubectlProv["kubectl.Provider"] + end + + subgraph External["External Tools"] + K3D["K3D CLI"] + HelmCLI["Helm CLI"] + ArgoCD["ArgoCD API"] + KubectlCLI["kubectl"] + TelepresenceCLI["Telepresence CLI"] + SkaffoldCLI["Skaffold CLI"] + end + + subgraph SharedLayer["Shared Layer"] + Executor["executor.CommandExecutor"] + SharedUI["shared/ui"] + SharedErrors["shared/errors"] + SharedConfig["shared/config"] + end + + Root --> Bootstrap + Root --> Cluster + Root --> Chart + Root --> Dev + + Bootstrap --> BootstrapSvc + Cluster --> ClusterSvc + Chart --> ChartSvc + Dev --> DevSvc + + BootstrapSvc --> ClusterSvc + BootstrapSvc --> ChartSvc + + ClusterSvc --> K3dMgr + ChartSvc --> HelmMgr + ChartSvc --> ArgoCDMgr + ChartSvc --> GitRepo + DevSvc --> TelepresenceProv + DevSvc --> KubectlProv + + K3dMgr --> Executor + HelmMgr --> Executor + ArgoCDMgr --> Executor + GitRepo --> Executor + TelepresenceProv --> Executor + KubectlProv --> Executor + + Executor --> K3D + Executor --> HelmCLI + ArgoCDMgr --> ArgoCD + Executor --> KubectlCLI + Executor --> TelepresenceCLI + Executor --> SkaffoldCLI + + ClusterSvc --> SharedUI + ChartSvc --> SharedUI + DevSvc --> SharedUI + ClusterSvc --> SharedErrors + ChartSvc --> SharedErrors + SharedConfig --> SharedLayer +``` + +--- + +## Core Components + +| Package | Path | Responsibility | +|---|---|---| +| `cmd` | `cmd/` | Cobra command definitions, flag parsing, entry points for all subcommands | +| `bootstrap` | `internal/bootstrap/` | Orchestrates sequential cluster creation + chart installation | +| `cluster` | `internal/cluster/` | Cluster lifecycle: create, delete, list, status, cleanup via K3D | +| `chart/services` | `internal/chart/services/` | ArgoCD + app-of-apps installation workflow orchestration | +| `chart/providers/argocd` | `internal/chart/providers/argocd/` | Native Kubernetes API calls to ArgoCD, application wait/sync logic | +| `chart/providers/helm` | `internal/chart/providers/helm/` | Helm CLI wrapper, chart install/upgrade operations | +| `chart/providers/git` | `internal/chart/providers/git/` | Git clone of app-of-apps repositories to temp directories | +| `chart/ui/configuration` | `internal/chart/ui/configuration/` | Interactive wizard for deployment mode, SaaS, ingress, Docker, GHCR config | +| `cluster/providers/k3d` | `internal/cluster/providers/k3d/` | K3D cluster CRUD, kubeconfig management, WSL2 support | +| `cluster/prerequisites` | `internal/cluster/prerequisites/` | Checks & installs Docker, kubectl, k3d, helm prerequisites | +| `chart/prerequisites` | `internal/chart/prerequisites/` | Checks & installs Git, Helm, mkcert certificates, memory requirements | +| `dev/services/intercept` | `internal/dev/services/intercept/` | Telepresence intercept lifecycle management | +| `dev/services/scaffold` | `internal/dev/services/scaffold/` | Skaffold workflow: cluster bootstrap + live reload | +| `dev/providers/kubectl` | `internal/dev/providers/kubectl/` | kubectl namespace/service queries for interactive intercept setup | +| `shared/executor` | `internal/shared/executor/` | Unified command execution abstraction (real + mock), WSL2 helpers | +| `shared/ui` | `internal/shared/ui/` | Logo, prompts, tables, progress tracking, message templates | +| `shared/errors` | `internal/shared/errors/` | Typed errors, retry policies, user-facing error formatting | +| `shared/config` | `internal/shared/config/` | TLS config helpers, system initialization, credentials prompting | +| `cluster/models` | `internal/cluster/models/` | Domain types: `ClusterConfig`, `ClusterInfo`, flag structs, error types | +| `chart/utils/types` | `internal/chart/utils/types/` | Interfaces (`ArgoCDService`, `HelmProvider`, etc.), `InstallationRequest` | + +--- + +## Component Relationships + +### Dependency Flowchart + +```mermaid +graph LR + subgraph Commands["cmd Layer"] + CmdRoot["cmd/root.go"] + CmdBootstrap["cmd/bootstrap"] + CmdCluster["cmd/cluster"] + CmdChart["cmd/chart"] + CmdDev["cmd/dev"] + end + + subgraph Services["Service Layer"] + SvcBootstrap["internal/bootstrap/service.go"] + SvcCluster["internal/cluster/service.go"] + SvcChart["internal/chart/services/chart_service.go"] + SvcInstaller["internal/chart/services/installer.go"] + SvcArgoCD["internal/chart/services/argocd.go"] + SvcAppOfApps["internal/chart/services/appofapps.go"] + SvcIntercept["internal/dev/services/intercept"] + SvcScaffold["internal/dev/services/scaffold"] + end + + subgraph Providers["Provider Layer"] + ProvK3d["internal/cluster/providers/k3d"] + ProvHelm["internal/chart/providers/helm"] + ProvArgoCD["internal/chart/providers/argocd"] + ProvGit["internal/chart/providers/git"] + ProvKubectl["internal/dev/providers/kubectl"] + ProvTelepresence["internal/dev/providers/telepresence"] + ProvChartDev["internal/dev/providers/chart"] + end + + subgraph Shared["Shared Infrastructure"] + Executor["shared/executor"] + UI["shared/ui"] + Errors["shared/errors"] + Config["shared/config"] + Files["shared/files"] + end + + CmdRoot --> CmdBootstrap + CmdRoot --> CmdCluster + CmdRoot --> CmdChart + CmdRoot --> CmdDev + + CmdBootstrap --> SvcBootstrap + CmdCluster --> SvcCluster + CmdChart --> SvcChart + CmdDev --> SvcIntercept + CmdDev --> SvcScaffold + + SvcBootstrap --> SvcCluster + SvcBootstrap --> SvcChart + + SvcChart --> SvcInstaller + SvcInstaller --> SvcArgoCD + SvcInstaller --> SvcAppOfApps + + SvcCluster --> ProvK3d + SvcArgoCD --> ProvHelm + SvcArgoCD --> ProvArgoCD + SvcAppOfApps --> ProvHelm + SvcAppOfApps --> ProvGit + SvcIntercept --> ProvTelepresence + SvcScaffold --> ProvChartDev + SvcScaffold --> ProvKubectl + + ProvK3d --> Executor + ProvHelm --> Executor + ProvArgoCD --> Executor + ProvGit --> Executor + ProvKubectl --> Executor + ProvTelepresence --> Executor + + SvcCluster --> UI + SvcChart --> UI + SvcChart --> Errors + SvcChart --> Files + ProvHelm --> Config + ProvArgoCD --> Config +``` + +--- + +## Data Flow + +### Bootstrap Sequence (Full Environment Setup) + +```mermaid +sequenceDiagram + participant User + participant CLI as "cmd/bootstrap" + participant BSvc as "bootstrap.Service" + participant CSvc as "cluster.ClusterService" + participant K3dMgr as "k3d.K3dManager" + participant ChartSvc as "chart.ChartService" + participant Installer as "chart.Installer" + participant HelmMgr as "helm.HelmManager" + participant ArgoCDMgr as "argocd.Manager" + participant GitRepo as "git.Repository" + + User->>CLI: openframe bootstrap [cluster-name] + CLI->>BSvc: Execute(cmd, args) + BSvc->>CSvc: CreateClusterWithPrerequisitesNonInteractive() + CSvc->>K3dMgr: CreateCluster(config) + K3dMgr->>K3dMgr: createK3dConfigFile() + K3dMgr-->>CSvc: *rest.Config + CSvc-->>BSvc: *rest.Config (kubeConfig) + + BSvc->>ChartSvc: InstallChartsWithConfig(InstallationRequest) + ChartSvc->>ChartSvc: SelectCluster() or use provided name + ChartSvc->>HelmMgr: NewHelmManager(kubeConfig) + ChartSvc->>Installer: InstallChartsWithContext(ctx, config) + + Installer->>HelmMgr: InstallArgoCDWithProgress(ctx, cfg) + HelmMgr-->>Installer: ArgoCD deployed + + Installer->>GitRepo: CloneChartRepository(ctx, appConfig) + GitRepo-->>Installer: CloneResult{TempDir, ChartPath} + + Installer->>HelmMgr: InstallAppOfAppsFromLocal(ctx, config, certFile, keyFile) + HelmMgr-->>Installer: App-of-apps deployed + + Installer->>ArgoCDMgr: WaitForApplications(ctx, config) + ArgoCDMgr->>ArgoCDMgr: Poll ArgoCD application health/sync status + ArgoCDMgr-->>Installer: All applications Healthy + Synced + + Installer-->>ChartSvc: success + ChartSvc-->>BSvc: success + BSvc-->>User: Environment ready +``` + +### Interactive Chart Install with Configuration Wizard + +```mermaid +sequenceDiagram + participant User + participant CLI as "cmd/chart install" + participant ChartSvc as "chart.ChartService" + participant Wizard as "configuration.ConfigurationWizard" + participant Builder as "config.Builder" + participant Installer as "chart.Installer" + + User->>CLI: openframe chart install + CLI->>ChartSvc: InstallWithContextDeferred(ctx, req) + ChartSvc->>ChartSvc: SelectCluster() interactive + + alt No deployment-mode flag + ChartSvc->>Wizard: ConfigureHelmValues() + Wizard->>User: Select deployment mode (OSS/SaaS/SaaS-Shared) + User-->>Wizard: oss-tenant + Wizard->>User: Default or interactive config? + User-->>Wizard: interactive + Wizard->>User: Branch, Docker, Ingress prompts + User-->>Wizard: configuration answers + Wizard->>Wizard: CreateTemporaryValuesFile() + Wizard-->>ChartSvc: ChartConfiguration{TempHelmValuesPath} + else deployment-mode flag provided + ChartSvc->>Builder: BuildInstallConfig(...) + Builder->>Builder: ReadHelmValuesFile() for branch override + Builder-->>ChartSvc: ChartInstallConfig + end + + ChartSvc->>Installer: InstallChartsWithContext(ctx, config) + Installer-->>User: success +``` + +--- + +## Key Files + +| File | Purpose | +|---|---| +| `main.go` | Binary entry point, delegates to `cmd.Execute()` | +| `cmd/root.go` | Root Cobra command, registers all subcommands, version info, global flags | +| `cmd/bootstrap/bootstrap.go` | Bootstrap command definition with deployment-mode and non-interactive flags | +| `cmd/cluster/create.go` | Cluster create command; wizard vs skip-wizard mode selection | +| `cmd/cluster/cluster.go` | Cluster parent command, prerequisite checks via `PersistentPreRunE` | +| `cmd/chart/install.go` | Chart install command, flag extraction, delegates to `services.InstallChartsWithConfig` | +| `internal/bootstrap/service.go` | Orchestrates cluster creation β†’ chart installation sequentially | +| `internal/cluster/service.go` | `ClusterService`: wraps K3dManager, handles UI suppression for automation | +| `internal/cluster/providers/k3d/manager.go` | Core K3D operations: config file generation, cluster CRUD, kubeconfig, WSL2 support | +| `internal/chart/services/chart_service.go` | Central chart service: deferred HelmManager init, workflow coordination | +| `internal/chart/services/installer.go` | `Installer.InstallChartsWithContext`: ArgoCD β†’ app-of-apps β†’ wait sequence | +| `internal/chart/providers/argocd/applications.go` | Native K8s client setup (ArgoCD clientset, apiextensions), app status monitoring | +| `internal/chart/providers/argocd/wait.go` | `WaitForApplications`: polls ArgoCD health/sync with spinner, stabilization checks | +| `internal/chart/providers/helm/manager.go` | Helm CLI invocation, ArgoCD values, app-of-apps from local path | +| `internal/chart/providers/argocd/argocd_values.go` | Embedded ArgoCD Helm values (resource limits, annotations, timeouts) | +| `internal/chart/ui/configuration/wizard.go` | Configuration wizard entry point: deployment mode β†’ default/interactive flow | +| `internal/chart/ui/configuration/modes.go` | `configureWithDefaults` and `configureInteractive` deployment mode flows | +| `internal/chart/utils/types/interfaces.go` | All service interfaces (`ArgoCDService`, `HelmProvider`, `ClusterLister`, etc.) | +| `internal/chart/utils/types/configuration.go` | `InstallationRequest`, `ChartConfiguration`, deployment mode constants | +| `internal/cluster/models/cluster.go` | `ClusterConfig`, `ClusterInfo`, `NodeInfo` domain types | +| `internal/cluster/models/flags.go` | All command flag structs, `ValidateClusterName`, flag add helpers | +| `internal/cluster/utils/cmd_helpers.go` | Global flag container, `WrapCommandWithCommonSetup`, service factory functions | +| `internal/dev/services/intercept/service.go` | `StartIntercept`: validates, connects Telepresence, creates intercept, waits | +| `internal/dev/services/scaffold/service.go` | `RunScaffoldWorkflow`: select skaffold config β†’ bootstrap β†’ run skaffold dev | +| `internal/shared/executor/executor.go` | `RealCommandExecutor`, WSL availability caching, WSL recovery utilities | +| `internal/shared/executor/mock.go` | `MockCommandExecutor` for unit testing with pattern-based response injection | +| `internal/shared/config/transport.go` | `ApplyInsecureTLSConfig`: disables TLS verification for k3d local clusters | +| `internal/shared/errors/errors.go` | Typed errors (`ValidationError`, `BranchNotFoundError`), `ErrorHandler` | +| `internal/shared/ui/logo.go` | ASCII logo rendering with terminal detection and test-mode suppression | +| `tests/testutil/setup.go` | Test infrastructure: `CreateStandardTestFlags`, `MockCommandExecutor` setup | +| `tests/integration/common/cluster_management.go` | Integration test helpers for k3d cluster lifecycle | + +--- + +## Dependencies + +The project uses the following key library dependencies: + +| Library | Usage in OpenFrame CLI | +|---|---| +| `github.com/spf13/cobra` | All CLI command definitions, flag parsing, help generation, subcommand routing | +| `github.com/pterm/pterm` | Spinners, tables, boxes, colored output, interactive confirms, progress bars | +| `github.com/manifoldco/promptui` | Interactive select menus and text input prompts in wizards | +| `k8s.io/client-go` | Native Kubernetes API client for ArgoCD application monitoring and cluster connectivity | +| `k8s.io/apiextensions-apiserver` | CRD client for verifying ArgoCD CRD installation before polling applications | +| `github.com/argoproj/argo-cd/v2` | ArgoCD typed clientset for listing and watching Application resources | +| `k8s.io/apimachinery` | Kubernetes API types, `metav1`, `unstructured`, `schema` for dynamic resource operations | +| `sigs.k8s.io/yaml` | YAML marshaling for Helm values file generation and Kubernetes manifests | +| `gopkg.in/yaml.v3` | YAML parsing for `helm-values.yaml` reading and modification | +| `github.com/stretchr/testify` | Test assertions (`assert`, `require`) in unit and integration tests | +| `golang.org/x/term` | Raw terminal detection for single-keypress confirmation prompts | + +### Dependency Interaction Pattern + +```mermaid +graph TD + OpenFrameCLI["OpenFrame CLI Core"] + + subgraph UILayer["UI Dependencies"] + Pterm["pterm (spinners, tables, colors)"] + Promptui["promptui (select, input)"] + Term["golang.org/x/term"] + end + + subgraph K8sLayer["Kubernetes Dependencies"] + ClientGo["k8s.io/client-go"] + APIExtensions["k8s.io/apiextensions-apiserver"] + ArgoCDClient["argoproj/argo-cd clientset"] + APIMachinery["k8s.io/apimachinery"] + end + + subgraph CLILayer["CLI Framework"] + Cobra["spf13/cobra"] + end + + subgraph ConfigLayer["Config / Serialization"] + YamlV3["gopkg.in/yaml.v3"] + SigsYaml["sigs.k8s.io/yaml"] + end + + subgraph TestLayer["Testing"] + Testify["stretchr/testify"] + end + + OpenFrameCLI --> Cobra + OpenFrameCLI --> Pterm + OpenFrameCLI --> Promptui + OpenFrameCLI --> Term + OpenFrameCLI --> ClientGo + OpenFrameCLI --> APIExtensions + OpenFrameCLI --> ArgoCDClient + OpenFrameCLI --> APIMachinery + OpenFrameCLI --> YamlV3 + OpenFrameCLI --> SigsYaml + OpenFrameCLI --> Testify + + ArgoCDClient --> ClientGo + APIExtensions --> ClientGo + APIMachinery --> ClientGo +``` + +--- + +## CLI Commands + +### Command Reference + +| Command | Flags | Description | +|---|---|---| +| `openframe bootstrap [cluster-name]` | `--deployment-mode`, `--non-interactive`, `--verbose/-v` | Full environment setup: create K3D cluster + install ArgoCD + app-of-apps | +| `openframe cluster create [name]` | `--type/-t`, `--nodes/-n`, `--version`, `--skip-wizard`, `--dry-run` | Create a K3D Kubernetes cluster, with interactive wizard or direct flags | +| `openframe cluster delete [name]` | `--force/-f` | Delete a cluster and clean up Docker resources | +| `openframe cluster list` | `--quiet/-q`, `--verbose/-v` | List all managed clusters in a formatted table | +| `openframe cluster status [name]` | `--detailed/-d`, `--no-apps` | Show cluster health, nodes, and ArgoCD application status | +| `openframe cluster cleanup [name]` | `--force/-f` | Remove unused Docker images and resources from cluster nodes | +| `openframe chart install [cluster-name]` | `--deployment-mode`, `--non-interactive`, `--github-repo`, `--github-branch`, `--cert-dir`, `--force`, `--dry-run`, `--verbose/-v` | Install ArgoCD and app-of-apps on an existing cluster | +| `openframe dev intercept [service-name]` | `--port`, `--namespace`, `--mount`, `--env-file`, `--global`, `--header`, `--replace`, `--remote-port` | Intercept Kubernetes service traffic to local dev environment via Telepresence | +| `openframe dev skaffold [cluster-name]` | `--port`, `--namespace`, `--image`, `--sync-local`, `--sync-remote`, `--skip-bootstrap`, `--helm-values` | Deploy services with Skaffold live reloading, optionally bootstrapping cluster | + +### Deployment Modes + +| Mode Flag | Repository | Use Case | +|---|---|---| +| `oss-tenant` | `flamingo-stack/openframe-oss-tenant` | Default self-hosted OpenFrame | +| `saas-tenant` | `flamingo-stack/openframe-saas-tenant` | SaaS tenant deployment (requires GHCR credentials) | +| `saas-shared` | `flamingo-stack/openframe-saas-shared` | Shared SaaS platform deployment (requires GHCR credentials) | + +### Usage Examples + +```bash +# Verify installation +openframe --version + +# Interactive full bootstrap +openframe bootstrap + +# CI/CD non-interactive bootstrap +openframe bootstrap my-cluster --deployment-mode=oss-tenant --non-interactive + +# Create cluster only +openframe cluster create --nodes 4 --skip-wizard + +# Install charts on existing cluster with verbose output +openframe chart install my-cluster --deployment-mode=oss-tenant -v + +# Interactive service intercept +openframe dev intercept + +# Direct service intercept +openframe dev intercept my-api --port 8080 --namespace production + +# List clusters +openframe cluster list + +# Check cluster status +openframe cluster status my-cluster --detailed +``` diff --git a/internal/chart/providers/argocd/.applications.md b/internal/chart/providers/argocd/.applications.md index 47096c92..bcb68554 100644 --- a/internal/chart/providers/argocd/.applications.md +++ b/internal/chart/providers/argocd/.applications.md @@ -1,48 +1,38 @@ - -This Go file provides ArgoCD application management functionality with support for both native Kubernetes API clients and kubectl fallback operations, specifically designed for k3d cluster environments. + +Parses raw JSON output from kubectl into a slice of `Application` structs, extracting health, sync, condition, and operation state details for each ArgoCD application. ## Key Components -### Manager Struct -- **Manager**: Primary ArgoCD manager with command executor and multiple Kubernetes client interfaces -- **NewManager()**: Basic constructor with command executor -- **NewManagerWithCluster()**: Constructor with explicit cluster context -- **NewManagerWithConfig()**: Preferred constructor with pre-configured Kubernetes client +**Types** +- `Manager` β€” Core struct managing ArgoCD operations; holds Kubernetes/ArgoCD native clients, executor, cluster context, and stabilization settings +- `Application` β€” Represents the status snapshot of a single ArgoCD application (health, sync, conditions, source info) +- `argoAppList` / `argoApp` β€” Internal JSON deserialization structs for kubectl output -### Application Types -- **Application**: Represents ArgoCD application status with health, sync, and operational details -- **argoApp/argoAppList**: Internal JSON parsing structures for kubectl output +**Constructors** +- `NewManager(exec)` β€” Basic manager with command executor only +- `NewManagerWithCluster(exec, clusterName)` β€” Manager with explicit k3d cluster context +- `NewManagerWithConfig(exec, config)` β€” Preferred constructor when a `*rest.Config` is already available; initializes all native clients immediately -### Core Methods -- **initKubernetesClients()**: Lazy initialization of native Kubernetes clients with TLS bypass for local clusters -- **getTotalExpectedApplications()**: Determines expected application count using native clients or kubectl fallback -- **parseApplications()**: Retrieves ArgoCD application status (implementation appears truncated) +**Methods** +- `initKubernetesClients()` β€” Lazily initializes kube, apiext, and ArgoCD native clients from kubeconfig +- `getTotalExpectedApplications(ctx, config)` β€” Counts expected apps via native ArgoCD client (falls back to kubectl on Windows) +- `getTotalExpectedApplicationsViaKubectl(ctx, config)` β€” kubectl-based fallback for app discovery +- `getKubeconfigPath()` β€” Resolves kubeconfig path from `$KUBECONFIG` env or `~/.kube/config` +- `getKubectlArgs(args...)` β€” Prepends `--context k3d-` to kubectl args when cluster name is set ## Usage Example ```go -import ( - "context" - "github.com/flamingo-stack/openframe-cli/internal/shared/executor" -) - -// Basic usage with command executor -exec := executor.NewCommandExecutor() -manager := argocd.NewManager(exec) - -// Usage with specific cluster context -manager = argocd.NewManagerWithCluster(exec, "openframe") - -// Usage with pre-configured Kubernetes config (preferred) -manager, err := argocd.NewManagerWithConfig(exec, kubeConfig) +// Preferred: inject existing rest.Config (e.g., post-cluster creation) +mgr, err := argocd.NewManagerWithConfig(executor, restConfig) if err != nil { log.Fatal(err) } -// Get total expected applications -ctx := context.Background() -count := manager.getTotalExpectedApplications(ctx, config) -fmt.Printf("Expected applications: %d\n", count) -``` +// Or: lazily resolved from kubeconfig +mgr := argocd.NewManagerWithCluster(executor, "openframe") +mgr.StabilizationChecks = 3 // speed up in tests -The manager includes Windows-specific handling for k3d clusters and provides both native Kubernetes API access and kubectl command fallbacks for reliability across different environments. \ No newline at end of file +total := mgr.getTotalExpectedApplications(ctx, installConfig) +fmt.Printf("Expecting %d ArgoCD applications\n", total) +``` \ No newline at end of file diff --git a/internal/chart/providers/argocd/.argocd_values.md b/internal/chart/providers/argocd/.argocd_values.md index 9c1233df..20bddf42 100644 --- a/internal/chart/providers/argocd/.argocd_values.md +++ b/internal/chart/providers/argocd/.argocd_values.md @@ -1,46 +1,38 @@ - -Provides pre-configured Helm chart values for ArgoCD deployment with optimized resource allocation and monitoring integration. + +Provides the default ArgoCD Helm chart values as a YAML string for use during ArgoCD installation and configuration within the OpenFrame platform. ## Key Components -- **GetArgoCDValues()** - Returns a complete YAML configuration string for ArgoCD Helm chart deployment +- **`GetArgoCDValues() string`** β€” Returns a pre-configured YAML string containing Helm chart overrides for all ArgoCD components. -## Configuration Features +## Configuration Highlights -The returned YAML includes: +| Component | CPU Request/Limit | Memory Request/Limit | +|---|---|---| +| `controller` | 200m / 400m | 800Mi / 1Gi | +| `server` | 200m / 300m | 400Mi / 600Mi | +| `repoServer` | 200m / 400m | 400Mi / 800Mi | +| `redis` | 50m / 100m | 64Mi / 128Mi | +| `dex` | 50m / 100m | 64Mi / 128Mi | +| `applicationSet` | 50m / 100m | 64Mi / 128Mi | +| `notifications` | 50m / 100m | 64Mi / 128Mi | -- **Custom Health Checks** - Application health status monitoring via Lua script -- **Resource Limits** - CPU and memory constraints for all ArgoCD components -- **Loki Integration** - Pod annotations for log scraping (`loki.grafana.com/scrape: "true"`) -- **Extended Timeouts** - Controller sync timeout (1800s) and repo server exec timeout (180s) -- **Component Scaling** - Optimized resource requests/limits for controller, server, repo server, Redis, Dex, ApplicationSet, and notifications +**Notable settings:** +- Custom Application health check via Lua script for accurate `argoproj.io/Application` status propagation +- Sync timeout set to `1800s` (30 minutes) +- `ARGOCD_EXEC_TIMEOUT` on `repoServer` set to `180s` +- All pods annotated with `loki.grafana.com/scrape: "true"` for Loki log scraping ## Usage Example ```go -package main - -import ( - "fmt" - "github.com/your-org/your-project/argocd" -) - -func main() { - // Get ArgoCD Helm values for deployment - values := argocd.GetArgoCDValues() - - // Write to values.yaml file for Helm deployment - err := os.WriteFile("argocd-values.yaml", []byte(values), 0644) - if err != nil { - log.Fatal(err) - } - - // Or use directly with Helm Go SDK - fmt.Println("ArgoCD values configured with:") - fmt.Println("- Resource limits for all components") - fmt.Println("- Loki scraping enabled") - fmt.Println("- Custom health checks") -} -``` +import "github.com/flamingo-stack/openframe/argocd" + +values := argocd.GetArgoCDValues() -The configuration optimizes ArgoCD for production use with appropriate resource constraints and observability features. \ No newline at end of file +// Pass to Helm install +err := helmClient.InstallOrUpgrade("argocd", "argo/argo-cd", values) +if err != nil { + log.Fatalf("failed to install ArgoCD: %v", err) +} +``` \ No newline at end of file diff --git a/internal/chart/providers/argocd/.wait.md b/internal/chart/providers/argocd/.wait.md index 8dd7d7ef..db881ffe 100644 --- a/internal/chart/providers/argocd/.wait.md +++ b/internal/chart/providers/argocd/.wait.md @@ -1,41 +1,50 @@ - -This file provides ArgoCD application monitoring and synchronization logic for OpenFrame CLI deployments. + +Polls ArgoCD application status until all deployed applications reach `Healthy + Synced` state, with resilience handling for cluster connectivity issues, WSL recovery, and repo-server health on Windows/Linux/macOS environments. ## Key Components -- **WaitForApplications()** - Main function that waits for all ArgoCD applications to reach Healthy and Synced status -- **Context Management** - Handles cancellation signals, timeouts, and graceful shutdown via signal handlers -- **Health Monitoring** - Periodic cluster connectivity checks and resource monitoring during bootstrap and main phases -- **Progress Tracking** - Visual spinner with timer and verbose logging for application synchronization progress -- **Recovery Logic** - WSL-specific recovery mechanisms and repo-server issue detection/recovery -- **Timeout Handling** - 60-minute timeout with early exit conditions for dry-run mode and cancelled contexts +### `WaitForApplications(ctx, config)` +Primary entry point that orchestrates the full wait lifecycle: +- **Dry-run bypass** β€” returns immediately when `config.DryRun` is true +- **Bootstrap phase** β€” 30-second warm-up with 5-second cluster health checks before main polling begins +- **Main monitoring loop** β€” polls every 2 seconds up to a 60-minute timeout +- **Stabilization gate** β€” requires `consecutiveAllReady` (default 15 Γ— 2s = 30s) before declaring success + +### Signal Handling +Creates a local derived context (`localCtx`) and registers `os.Interrupt` / `syscall.SIGTERM` handlers to ensure immediate spinner shutdown and clean exit on Ctrl+C. + +### Cluster Connectivity Recovery +- Checks connectivity every 10 seconds (2 seconds when failures are active) +- On Windows, calls `executor.TryRecoverWSL()` before exhausting retry attempts +- Exponential backoff up to 10 seconds between consecutive failures +- Prints cluster diagnostics after `maxConsecutiveFailures` (5) are reached + +### Repo-Server Health Tracking +- `appsWithRepoServerIssues` β€” counts consecutive failures per application +- `repoServerRecoveryAttempts` β€” caps proactive restarts at 3 +- Diagnostics logged every 2 minutes; resource checks every 30 seconds + +### State Tracking Fields +| Variable | Purpose | +|---|---| +| `everReadyApps` | Apps that have reached Healthy+Synced at least once | +| `maxAppsSeenTotal` | High-water mark for discovered app count | +| `totalAppsExpected` | Target derived from install config | +| `consecutiveAllReady` | Consecutive checks where all apps are ready | ## Usage Example ```go -// Initialize ArgoCD manager -manager := &Manager{ - clusterName: "my-cluster", -} +mgr := argocd.NewManager(kubeClient, "my-cluster") +mgr.StabilizationChecks = 10 // 20s stabilization window -// Configure installation -config := config.ChartInstallConfig{ +err := mgr.WaitForApplications(ctx, config.ChartInstallConfig{ ClusterName: "my-cluster", Verbose: true, DryRun: false, Silent: false, - SkipCRDs: false, -} - -// Wait for applications with context timeout -ctx, cancel := context.WithTimeout(context.Background(), 60*time.Minute) -defer cancel() - -// Monitor ArgoCD application synchronization -err := manager.WaitForApplications(ctx, config) +}) if err != nil { - log.Fatalf("Failed to wait for ArgoCD applications: %v", err) + log.Fatalf("ArgoCD sync failed: %v", err) } -``` - -The function includes comprehensive error handling for cluster connectivity issues, WSL recovery on Windows systems, and graceful handling of interrupt signals during long-running synchronization operations. \ No newline at end of file +``` \ No newline at end of file diff --git a/internal/chart/providers/helm/.manager.md b/internal/chart/providers/helm/.manager.md index a21dbb18..27f46e67 100644 --- a/internal/chart/providers/helm/.manager.md +++ b/internal/chart/providers/helm/.manager.md @@ -1,48 +1,53 @@ - -A comprehensive Helm operations manager for OpenFrame that handles chart installations, Kubernetes cluster operations, and ArgoCD deployment with support for both Windows and Linux environments. + +Manages Helm chart installation and Kubernetes resource operations for the OpenFrame CLI, providing both native Go client and `kubectl` fallback capabilities for deploying charts like ArgoCD into k3d clusters. ## Key Components -- **HelmManager**: Main struct containing Kubernetes clients and command executor -- **NewHelmManager()**: Constructor that initializes Kubernetes clients with TLS bypass for local clusters -- **IsHelmInstalled()**: Verifies Helm CLI availability -- **IsChartInstalled()**: Checks if a Helm release exists in a namespace -- **InstallArgoCD()**: Core ArgoCD installation with Helm -- **InstallArgoCDWithProgress()**: ArgoCD installation with progress indicators and cluster connectivity verification -- **getHelmEnv()**: Platform-specific environment configuration for Helm directories +| Symbol | Type | Description | +|--------|------|-------------| +| `HelmManager` | struct | Core manager holding Kubernetes clients (`dynamic`, `kubeClient`, `crdClient`), executor, and REST config | +| `NewHelmManager` | constructor | Initializes `HelmManager` with graduated fallback β€” returns partial clients on non-fatal errors; applies insecure TLS bypass for local k3d clusters | +| `getHelmEnv` | method | Returns writable Helm environment dirs (`/tmp/helm/{cache,config,data}`); skips directory creation on Windows | +| `IsHelmInstalled` | method | Verifies Helm binary availability via `helm version --short` | +| `IsChartInstalled` | method | Checks for an existing Helm release in a given namespace using `helm list -q` | +| `InstallArgoCD` | method | Installs ArgoCD via `helm upgrade --install`, writing values to a temp file, with optional dry-run and explicit kube-context support | +| `InstallArgoCDWithProgress` | method | Wraps `InstallArgoCD` with spinner/progress output and cluster connectivity retries (up to 10 attempts); handles CRD pre-installation to avoid race conditions | ## Usage Example ```go -// Initialize Helm manager with Kubernetes config -config, err := rest.InClusterConfig() -if err != nil { - return err -} +import ( + "context" + "github.com/flamingo-stack/openframe-cli/internal/chart/helm" + "github.com/flamingo-stack/openframe-cli/internal/chart/utils/config" + "github.com/flamingo-stack/openframe-cli/internal/shared/executor" +) + +restCfg, _ := clientcmd.BuildConfigFromFlags("", kubeConfigPath) +exec := executor.NewDefaultExecutor() -executor := executor.NewCommandExecutor() -helmManager, err := NewHelmManager(executor, config, true) +manager, err := helm.NewHelmManager(exec, restCfg, true) if err != nil { - return err + log.Fatal(err) } -// Check if Helm is available ctx := context.Background() -if err := helmManager.IsHelmInstalled(ctx); err != nil { - return fmt.Errorf("helm not available: %w", err) -} -// Install ArgoCD with configuration -installConfig := config.ChartInstallConfig{ - ClusterName: "my-cluster", - DryRun: false, - Verbose: true, +if err := manager.IsHelmInstalled(ctx); err != nil { + log.Fatal("Helm not found") } -err = helmManager.InstallArgoCDWithProgress(ctx, installConfig) -if err != nil { - return fmt.Errorf("argocd installation failed: %w", err) +installed, _ := manager.IsChartInstalled(ctx, "argo-cd", "argocd") +if !installed { + cfg := config.ChartInstallConfig{ + ClusterName: "openframe", + DryRun: false, + Verbose: true, + } + if err := manager.InstallArgoCDWithProgress(ctx, cfg); err != nil { + log.Fatal(err) + } } ``` -The manager provides robust error handling, platform compatibility (Windows/WSL support), and comprehensive logging for Helm operations within the OpenFrame ecosystem. \ No newline at end of file +> **Note:** When `rest.Config` is `nil`, `NewHelmManager` returns a minimal manager that executes Helm commands but falls back to `kubectl` for deployment verification. TLS verification is always bypassed for local k3d clusters via `sharedconfig.ApplyInsecureTLSConfig`. \ No newline at end of file