From ca84221f6e5efc8f70e1d94fe7da11614df2cba5 Mon Sep 17 00:00:00 2001 From: Lukasz Raczylo Date: Sun, 23 Nov 2025 17:19:02 +0000 Subject: [PATCH] First release. --- .github/workflows/release.yml | 72 +++ .gitignore | 3 + .goreleaser.yaml | 68 +++ CHANGELOG.md | 52 +++ CONTRIBUTING.md | 262 +++++++++++ Formula/kportal.rb | 84 ++++ LICENSE | 21 + README.md | 819 ++++++++++++++++++++++------------ RELEASE_SETUP.md | 320 +++++++++++++ docs/index.html | 381 ++++++++++++++++ install.sh | 171 +++++++ 11 files changed, 1974 insertions(+), 279 deletions(-) create mode 100644 .github/workflows/release.yml create mode 100644 .goreleaser.yaml create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTING.md create mode 100644 Formula/kportal.rb create mode 100644 LICENSE create mode 100644 RELEASE_SETUP.md create mode 100644 docs/index.html create mode 100755 install.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..dea4998 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,72 @@ +name: Release + +on: + push: + branches: + - main + paths: + - '**.go' + - 'go.mod' + - 'go.sum' + workflow_dispatch: + +permissions: + contents: write + +jobs: + version: + name: Calculate Version + runs-on: ubuntu-latest + outputs: + version: ${{ steps.version_formatted.outputs.version }} + version_tag: ${{ steps.version_formatted.outputs.version_tag }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Calculate semantic version + id: semver + uses: lukaszraczylo/semver-generator@v1 + with: + config_file: semver.yaml + repository_local: true + + - name: Format version + id: version_formatted + run: | + VERSION="${{ steps.semver.outputs.semantic_version }}" + echo "version=${VERSION}" >> $GITHUB_OUTPUT + echo "version_tag=v${VERSION}" >> $GITHUB_OUTPUT + + - name: Display version + run: | + echo "Calculated version: ${{ steps.version_formatted.outputs.version }}" + echo "Version tag: ${{ steps.version_formatted.outputs.version_tag }}" + + release: + name: Release with GoReleaser + needs: version + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.23' + + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v6 + with: + distribution: goreleaser + version: latest + args: release --clean + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }} + GORELEASER_CURRENT_TAG: ${{ needs.version.outputs.version_tag }} diff --git a/.gitignore b/.gitignore index 81f6456..9c2c841 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ CLAUDE.md kportal +DEPLOYMENT_SUMMARY.md +HOMEBREW_COMPLIANCE.md +RELEASE_SETUP.md diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000..897a7a6 --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,68 @@ +version: 2 + +before: + hooks: + - go mod tidy + +builds: + - id: kportal + main: ./cmd/kportal + binary: kportal + env: + - CGO_ENABLED=0 + goos: + - linux + - darwin + - windows + goarch: + - amd64 + - arm64 + ldflags: + - -s -w + - -X main.version={{.Version}} + +archives: + - id: kportal + format: tar.gz + name_template: "kportal-{{ .Version }}-{{ .Os }}-{{ .Arch }}" + format_overrides: + - goos: windows + format: zip + files: + - LICENSE + - README.md + +checksum: + name_template: "kportal-{{ .Version }}-checksums.txt" + algorithm: sha256 + +changelog: + sort: asc + filters: + exclude: + - '^docs:' + - '^test:' + - '^Merge' + - '^WIP' + +release: + github: + owner: lukaszraczylo + name: kportal + name_template: "Release {{.Version}}" + draft: false + prerelease: auto + +brews: + - repository: + owner: lukaszraczylo + name: brew-taps + token: "{{ .Env.HOMEBREW_TAP_TOKEN }}" + folder: Formula + homepage: https://lukaszraczylo.github.io/kportal + description: "Modern Kubernetes port-forward manager with interactive TUI" + license: MIT + test: | + system "#{bin}/kportal", "--version" + install: | + bin.install "kportal" diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..ff4bc65 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,52 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [0.1.5] - 2025-11-23 + +### Added +- Interactive TUI built with Bubble Tea +- Real-time health check monitoring with grace period +- Toggle forwards on/off with Space key +- Error display below table showing detailed error messages +- Version display in UI title +- Complete log suppression for clean UI (klog included) +- Automatic error clearing when connection recovers + +### Changed +- Replaced tview with Bubble Tea for better architecture +- Removed artificial 10-second delay before health checks +- Improved thread safety with message-passing architecture +- Enhanced status indicators (Active ●, Starting ○, Reconnecting ◐, Error ✗) + +### Fixed +- Deadlock issues with tview UI +- Logs covering the legend in interactive mode +- Re-enable hang bug when toggling forwards +- Race conditions in status updates + +## [0.1.0] - 2025-11-22 + +### Added +- Initial release +- Multi-context and multi-namespace support +- Automatic pod restart handling with prefix matching +- Label selector support for dynamic pod selection +- Hot-reload configuration watching +- Exponential backoff retry logic (max 10s) +- Port conflict detection with PID information +- kftray JSON to kportal YAML converter +- Alias support for cleaner display names +- Health check system +- Verbose and interactive modes +- Configuration validation +- Comprehensive test suite + +[Unreleased]: https://github.com/lukaszraczylo/kportal/compare/v0.1.5...HEAD +[0.1.5]: https://github.com/lukaszraczylo/kportal/compare/v0.1.0...v0.1.5 +[0.1.0]: https://github.com/lukaszraczylo/kportal/releases/tag/v0.1.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..5837f2f --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,262 @@ +# Contributing to kportal + +Thank you for your interest in contributing to kportal! This document provides guidelines and instructions for contributing. + +## Code of Conduct + +Be respectful and constructive. We're all here to build something awesome together. + +## How to Contribute + +### Reporting Bugs + +Before creating a bug report, please check if the issue already exists. When creating a bug report, include: + +- **Clear title and description** +- **Steps to reproduce** +- **Expected behavior** +- **Actual behavior** +- **Screenshots** (if applicable) +- **Environment details** (OS, kportal version, Go version, Kubernetes version) +- **Configuration file** (sanitized) + +### Suggesting Enhancements + +Enhancement suggestions are tracked as GitHub issues. When creating an enhancement suggestion, include: + +- **Clear title and description** +- **Use case** - why this enhancement would be useful +- **Possible implementation** (optional) +- **Alternative solutions** (if any) + +### Pull Requests + +1. **Fork the repository** + ```bash + git clone https://github.com/yourusername/kportal.git + cd kportal + ``` + +2. **Create a feature branch** + ```bash + git checkout -b feature/amazing-feature + ``` + +3. **Make your changes** + - Write clear, readable code + - Follow Go conventions and best practices + - Add tests for new functionality + - Update documentation as needed + +4. **Run quality checks** + ```bash + make all # Runs fmt, vet, staticcheck, test, build + ``` + +5. **Commit your changes** + + Follow [semantic commit messages](#commit-message-format): + ```bash + git commit -m "feat: add amazing feature" + ``` + +6. **Push to your fork** + ```bash + git push origin feature/amazing-feature + ``` + +7. **Open a Pull Request** + - Provide a clear description of the changes + - Reference any related issues + - Ensure all CI checks pass + +## Development Setup + +### Prerequisites + +- Go 1.23 or higher +- Access to a Kubernetes cluster +- kubectl configured + +### Building + +```bash +# Install development tools +make install-tools + +# Build the binary +make build + +# Run tests +make test + +# Run with race detection +go test -race ./... + +# Check code quality +make vet +make staticcheck +make fmt +``` + +### Running Locally + +```bash +# Build and install +make build +make install + +# Run with your config +kportal -c .kportal.yaml + +# Run in verbose mode +kportal -v +``` + +## Commit Message Format + +We use semantic commit messages for automatic version generation: + +### Commit Types + +- **feat** - New feature (bumps minor version) +- **fix** - Bug fix (bumps patch version) +- **docs** - Documentation only changes (bumps patch version) +- **style** - Code style changes (formatting, missing semi colons, etc.) +- **refactor** - Code refactoring +- **test** - Adding or updating tests +- **chore** - Maintenance tasks +- **breaking** - Breaking changes (bumps major version) + +### Format + +``` +: + +[optional body] + +[optional footer] +``` + +### Examples + +```bash +# Feature +git commit -m "feat: add health check grace period" + +# Bug fix +git commit -m "fix: resolve port conflict detection bug" + +# Breaking change +git commit -m "breaking: change config file format + +BREAKING CHANGE: Config file format has changed from JSON to YAML. +Migration tool available with --convert flag." + +# Documentation +git commit -m "docs: update installation instructions" +``` + +## Project Structure + +``` +kportal/ +├── cmd/kportal/ # Main application entry point +├── internal/ +│ ├── config/ # Configuration parsing and validation +│ ├── forward/ # Port-forward manager and workers +│ ├── healthcheck/ # Health monitoring system +│ ├── k8s/ # Kubernetes client wrapper +│ ├── retry/ # Retry logic with backoff +│ ├── ui/ # Terminal UI implementations +│ └── converter/ # kftray JSON converter +├── Formula/ # Homebrew formula +├── .github/workflows/ # CI/CD pipelines +└── docs/ # Documentation and GitHub Pages +``` + +## Coding Guidelines + +### Go Style + +- Follow [Effective Go](https://golang.org/doc/effective_go) +- Use `gofmt` for formatting +- Keep functions small and focused +- Write descriptive variable names +- Add comments for exported functions +- Handle errors explicitly + +### Testing + +- Write tests for new functionality +- Aim for meaningful test coverage +- Use table-driven tests where appropriate +- Mock external dependencies +- Test edge cases and error conditions + +Example test: +```go +func TestForwardWorker_Start(t *testing.T) { + tests := []struct { + name string + forward config.Forward + wantErr bool + }{ + { + name: "valid pod forward", + forward: config.Forward{ + Resource: "pod/test", + Port: 8080, + LocalPort: 8080, + }, + wantErr: false, + }, + // Add more test cases + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Test implementation + }) + } +} +``` + +### Documentation + +- Update README.md for user-facing changes +- Add code comments for complex logic +- Update CHANGELOG.md following [Keep a Changelog](https://keepachangelog.com/) +- Document new configuration options +- Add examples for new features + +## Release Process + +Releases are automated via GitHub Actions: + +1. **Version is determined automatically** by semver-gen based on commit messages +2. **Create a tag** following semantic versioning: + ```bash + git tag -a v0.2.0 -m "Release version 0.2.0" + git push origin v0.2.0 + ``` +3. **GitHub Actions will**: + - Build binaries for all platforms + - Create GitHub release + - Update Homebrew formula + - Generate release notes + +## Getting Help + +- **Questions?** Open a [GitHub Discussion](https://github.com/lukaszraczylo/kportal/discussions) +- **Bug or feature request?** Open a [GitHub Issue](https://github.com/lukaszraczylo/kportal/issues) +- **Want to chat?** Reach out on GitHub + +## Recognition + +Contributors will be recognized in: +- GitHub's contributor graph +- Release notes +- README.md (for significant contributions) + +Thank you for contributing to kportal! 🎉 diff --git a/Formula/kportal.rb b/Formula/kportal.rb new file mode 100644 index 0000000..7b908c4 --- /dev/null +++ b/Formula/kportal.rb @@ -0,0 +1,84 @@ +class Kportal < Formula + desc "Modern Kubernetes port-forward manager with interactive TUI" + homepage "https://lukaszraczylo.github.io/kportal" + license "MIT" + + # Version will be dynamically set by bump-homebrew-formula-action + # This is a template - actual releases will have specific version and URLs + version "0.1.5" + + on_macos do + on_arm do + url "https://github.com/lukaszraczylo/kportal/releases/download/v#{version}/kportal-#{version}-darwin-arm64.tar.gz" + sha256 "PLACEHOLDER_SHA256_DARWIN_ARM64" + end + + on_intel do + url "https://github.com/lukaszraczylo/kportal/releases/download/v#{version}/kportal-#{version}-darwin-amd64.tar.gz" + sha256 "PLACEHOLDER_SHA256_DARWIN_AMD64" + end + end + + on_linux do + on_arm do + url "https://github.com/lukaszraczylo/kportal/releases/download/v#{version}/kportal-#{version}-linux-arm64.tar.gz" + sha256 "PLACEHOLDER_SHA256_LINUX_ARM64" + end + + on_intel do + url "https://github.com/lukaszraczylo/kportal/releases/download/v#{version}/kportal-#{version}-linux-amd64.tar.gz" + sha256 "PLACEHOLDER_SHA256_LINUX_AMD64" + end + end + + # Optional dependency - kubectl is commonly already installed + # but kportal requires it to function + depends_on "kubernetes-cli" => :optional + + def install + bin.install "kportal" + + # Generate shell completions if the binary supports it + # This will be implemented in future versions + # generate_completions_from_executable(bin/"kportal", "completion") + end + + def caveats + <<~EOS + kportal requires: + • kubectl installed and configured + • Access to a Kubernetes cluster + • A valid kubeconfig file (~/.kube/config) + + Quick start: + 1. Create a configuration file: .kportal.yaml + 2. Add your port-forward definitions + 3. Run: kportal + + For configuration examples and full documentation: + https://lukaszraczylo.github.io/kportal + + To validate your configuration: + kportal --check + EOS + end + + test do + # Test that binary runs and reports correct version + assert_match version.to_s, shell_output("#{bin}/kportal --version") + + # Test that binary can validate an empty config (should fail gracefully) + (testpath/".kportal.yaml").write <<~YAML + contexts: + test: + namespaces: + default: + - resource: test-pod + port: 8080 + local_port: 8080 + YAML + + # Should be able to validate config even without kube access + system bin/"kportal", "--check", "-c", testpath/".kportal.yaml" + end +end diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..887ccb3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Lukasz Raczylo + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 878ccc6..55fd324 100644 --- a/README.md +++ b/README.md @@ -1,172 +1,249 @@ # kportal -A robust Kubernetes port-forwarding tool that manages multiple concurrent port-forwards across different contexts, namespaces, and resources with automatic reconnection and failure recovery. +[![Release](https://img.shields.io/github/v/release/lukaszraczylo/kportal)](https://github.com/lukaszraczylo/kportal/releases) +[![License](https://img.shields.io/github/license/lukaszraczylo/kportal)](LICENSE) +[![Go Report Card](https://goreportcard.com/badge/github.com/lukaszraczylo/kportal)](https://goreportcard.com/report/github.com/lukaszraczylo/kportal) -## Features +**Modern Kubernetes port-forward manager with interactive terminal UI** -- **Multi-Context Support**: Forward ports from multiple Kubernetes contexts simultaneously -- **Automatic Pod Restart Handling**: Detects and reconnects to pods when they restart -- **Label Selector Support**: Dynamically target pods using label selectors -- **Prefix Matching**: Automatically find and reconnect to pods with name prefixes -- **Hot-Reload**: Configuration file changes are automatically detected and applied -- **Resilient Connections**: Infinite retry with exponential backoff (max 10s) -- **Port Conflict Detection**: Validates port availability before starting -- **Multiple Ports Per Resource**: Forward multiple ports from the same pod/service +kportal simplifies managing multiple Kubernetes port-forwards with an elegant, interactive terminal interface. Built with [Bubble Tea](https://github.com/charmbracelet/bubbletea), it provides real-time status updates, automatic reconnection, and hot-reload configuration support. -## Installation +![kportal Demo](docs/images/demo.png) + +## ✨ Features + +- 🎯 **Interactive TUI** - Beautiful terminal interface with keyboard navigation (↑↓/jk, Space to toggle, q to quit) +- 🔄 **Auto-Reconnect** - Automatic retry with exponential backoff on connection failures (max 10s) +- ⚡ **Hot-Reload** - Update configuration without restarting - changes applied automatically +- 🏥 **Health Checks** - Real-time port forward status monitoring with 5-second intervals +- 🎨 **Multi-Context** - Support for multiple Kubernetes contexts and namespaces +- 📦 **Batch Management** - Manage all port-forwards from a single configuration file +- 🔌 **Toggle Forwards** - Enable/disable individual port-forwards on the fly with Space key +- 🚀 **Grace Period** - Smart 10-second grace period to avoid false "Error" status on startup +- 📊 **Status Display** - Clear visual indicators: Active (●), Starting (○), Reconnecting (◐), Error (✗) +- 🔍 **Error Reporting** - Detailed error messages displayed below the table +- 🔄 **Pod Restart Handling** - Detects and reconnects to pods when they restart +- 🏷️ **Label Selector Support** - Dynamically target pods using label selectors +- 📋 **Prefix Matching** - Automatically find and reconnect to pods with name prefixes +- 🚫 **Port Conflict Detection** - Validates port availability before starting with detailed PID info +- 🎭 **Alias Support** - Cleaner, more readable display names for your forwards + +## 📦 Installation + +### Homebrew (macOS/Linux) ```bash -# Install development tools (including semver-gen for version management) -make install-tools +brew install lukaszraczylo/tap/kportal +``` -# Build from source (version automatically generated from git history) +### Quick Install Script + +```bash +curl -fsSL https://raw.githubusercontent.com/lukaszraczylo/kportal/main/install.sh | bash +``` + +### Manual Download + +Download the latest binary for your platform from the [releases page](https://github.com/lukaszraczylo/kportal/releases): + +- **macOS**: `kportal-{version}-darwin-{amd64|arm64}.tar.gz` +- **Linux**: `kportal-{version}-linux-{amd64|arm64}.tar.gz` +- **Windows**: `kportal-{version}-windows-{amd64|arm64}.zip` + +### Build from Source + +```bash +git clone https://github.com/lukaszraczylo/kportal.git +cd kportal make build - -# Install to user bin directory make install - -# Install system-wide (requires sudo) -sudo make install-system - -# Or build manually -go build -o kportal ./cmd/kportal ``` -## Usage +## 🚀 Quick Start -### Basic Usage - -```bash -# Use default config file (.kportal.yaml) -./kportal - -# Use custom config file -./kportal -c myconfig.yaml - -# Enable verbose logging -./kportal -v - -# Validate configuration without starting -./kportal --check - -# Convert kftray JSON config to kportal YAML -./kportal --convert configs.json --convert-output .kportal.yaml -``` - -### Configuration File - -Create a `.kportal.yaml` file in your current directory: +1. **Create a configuration file** (`.kportal.yaml`): ```yaml contexts: - name: production namespaces: - - name: default + - name: backend forwards: - # Pod with prefix matching (auto-handles restarts) - - resource: pod/my-app - protocol: tcp - port: 8080 - localPort: 8080 - alias: my-api # Optional: cleaner log output - - # Service forwarding with alias - resource: service/postgres protocol: tcp port: 5432 localPort: 5432 alias: prod-db - - name: monitoring + - name: frontend forwards: + - resource: service/redis + protocol: tcp + port: 6379 + localPort: 6380 + alias: prod-redis +``` + +2. **Run kportal**: + +```bash +kportal +``` + +3. **Navigate the interface**: + - `↑↓` or `j/k` - Navigate through forwards + - `Space` or `Enter` - Toggle forward on/off + - `q` - Quit application + +## 📖 Configuration + +### Simple Configuration + +```yaml +contexts: + - name: + namespaces: + - name: + forwards: + - resource: / + protocol: tcp + port: + localPort: + alias: # Optional +``` + +### Advanced Configuration + +```yaml +contexts: + # Production cluster + - name: prod-us-west + namespaces: + - name: databases + forwards: + # Direct pod connection with prefix matching + - resource: pod/postgres-primary + protocol: tcp + port: 5432 + localPort: 5432 + alias: prod-postgres + + # Service connection + - resource: service/redis-master + protocol: tcp + port: 6379 + localPort: 6379 + alias: prod-redis + # Pod with label selector - resource: pod - selector: app=prometheus + selector: app=mongodb protocol: tcp - port: 9090 - localPort: 9090 - alias: prometheus + port: 27017 + localPort: 27017 + alias: mongo - - name: staging + - name: applications + forwards: + - resource: deployment/api-server + protocol: tcp + port: 8080 + localPort: 8080 + alias: api + + # Development cluster + - name: dev-local namespaces: - name: default forwards: - # Multiple ports from same pod - - resource: pod/test-app - port: 8080 - localPort: 8081 - alias: test-http - - - resource: pod/test-app - port: 9090 - localPort: 9091 - alias: test-metrics + - resource: service/grafana + protocol: tcp + port: 3000 + localPort: 3000 + alias: grafana-dashboard ``` -### Resource Types +### Configuration Options -#### Pod with Prefix Matching -```yaml -- resource: pod/my-app # Matches my-app-xyz789, my-app-abc123, etc. - port: 8080 - localPort: 8080 -``` -Automatically reconnects to new pods when they restart. +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `resource` | string | Yes | Kubernetes resource with type prefix (e.g., `service/name`, `pod/name`) | +| `protocol` | string | Yes | Connection protocol (typically `tcp`) | +| `port` | int | Yes | Remote port on the Kubernetes resource | +| `localPort` | int | Yes | Local port to forward to | +| `alias` | string | No | Friendly name for display (defaults to resource name) | +| `selector` | string | No | Label selector for dynamic pod selection (e.g., `app=nginx,env=prod`) | -#### Pod with Label Selector -```yaml -- resource: pod - selector: app=nginx,env=prod - port: 80 - localPort: 8080 -``` -Dynamically selects pods matching the label selector. +### Resource Formats -#### Service -```yaml -- resource: service/postgres - port: 5432 - localPort: 5432 -``` -Most stable option - forwards to service endpoints. +- **Pod by name**: `pod/pod-name` or just `pod-name` +- **Pod by prefix**: `pod/my-app` (matches `my-app-xyz789`, `my-app-abc123`, etc.) +- **Pod by selector**: Set `resource: pod` and use `selector: app=nginx` +- **Service**: `service/service-name` or `svc/service-name` +- **Deployment**: `deployment/deployment-name` or `deploy/deployment-name` -#### Using Aliases +## 🎮 Usage -Aliases provide cleaner, more readable log output: - -```yaml -- resource: service/victoria-metrics-cluster-vmselect - port: 8481 - localPort: 8481 - alias: vmetrics # Shows "vmetrics:8481→8481" instead of full path -``` - -**Without alias:** -``` -[home/monitoring/service/victoria-metrics-cluster-vmselect:8481] Forwarding... -``` - -**With alias:** -``` -[vmetrics:8481] Forwarding vmetrics:8481→8481 → localhost:8481 -``` - -### Converting from kftray - -kportal can automatically convert kftray JSON configurations to kportal YAML format: +### Interactive Mode (Default) ```bash -# Convert kftray config -kportal --convert kftray-config.json --convert-output .kportal.yaml - -# The converter will: -# 1. Read the kftray JSON format -# 2. Group forwards by context and namespace -# 3. Generate kportal YAML with all aliases preserved -# 4. Display a summary of the conversion +kportal ``` -**Example kftray JSON:** +Starts the interactive TUI where you can: +- View all configured port-forwards in a table +- See real-time status updates (Active, Starting, Reconnecting, Error) +- Toggle forwards on/off with Space key +- View detailed error messages at the bottom of the screen + +### Verbose Mode + +```bash +kportal -v +``` + +Runs in verbose mode with: +- Detailed logging to stdout +- Periodic status table updates every 2 seconds +- Full error traces +- No interactive controls (for automation/debugging) + +### Validate Configuration + +```bash +kportal --check +``` + +Validates your configuration file without starting any forwards: +- Checks YAML syntax +- Validates all required fields +- Detects duplicate local ports +- Shows validation errors with line numbers + +### Custom Configuration File + +```bash +kportal -c /path/to/config.yaml +``` + +### Version Information + +```bash +kportal --version +# Output: kportal version 0.1.5 +``` + +## 🔄 kftray Migration + +Migrate from kftray JSON configuration: + +```bash +kportal --convert configs.json --convert-output .kportal.yaml +``` + +**Example conversion:** + +kftray JSON: ```json [ { @@ -182,7 +259,7 @@ kportal --convert kftray-config.json --convert-output .kportal.yaml ] ``` -**Converts to kportal YAML:** +Converts to kportal YAML: ```yaml contexts: - name: production @@ -196,66 +273,343 @@ contexts: alias: prod-db ``` -## How It Works +## 🎨 Status Indicators + +| Indicator | Status | Description | +|-----------|--------|-------------| +| `● Active` | 🟢 Green | Port-forward is active and healthy | +| `○ Starting` | 🟡 Yellow | Initial connection in progress (10s grace period) | +| `◐ Reconnecting` | 🟡 Yellow | Attempting to reconnect after failure | +| `✗ Error` | 🔴 Red | Connection failed - see error details below table | +| `○ Disabled` | ⚪ Gray | Port-forward manually disabled via Space key | + +## 🛠️ Advanced Features + +### Hot-Reload + +kportal automatically watches for configuration file changes and reloads: + +```bash +# Edit your config while kportal is running +vim .kportal.yaml + +# Changes are applied automatically within seconds: +# - New forwards are started +# - Removed forwards are stopped +# - Existing forwards continue running unchanged +``` + +Supports manual reload via `SIGHUP`: +```bash +kill -HUP $(pgrep kportal) +``` + +### Health Checks + +Built-in health monitoring system: +- **Check interval**: Every 5 seconds +- **Timeout**: 2 seconds per check +- **Grace period**: 10 seconds for new connections +- **Automatic updates**: Real-time status changes in UI +- **Error tracking**: Detailed error messages for failed connections + +### Error Display + +When connections fail, errors are displayed below the table: + +``` +Errors: + • prod-postgres: dial tcp 127.0.0.1:5432: connect: connection refused + • prod-redis: i/o timeout after 2.0s +``` + +Errors automatically clear when: +- Connection becomes healthy +- Forward is disabled +- Forward is removed + +### Port Conflict Detection + +kportal checks for port conflicts at multiple stages: + +**At startup:** +``` +Port conflicts detected: + Port 8080: + • Requested by: api-server (context: prod, namespace: default) + • Currently used by: PID 1234 (chrome) +``` + +**During hot-reload:** +- Only validates new ports being added +- Skips currently managed ports +- Rejects configuration if conflicts found ### Pod Restart Handling When a pod restarts: -1. The port-forward connection breaks -2. kportal immediately attempts to re-resolve the resource -3. For prefix matches: finds the newest pod with that prefix -4. For selectors: re-queries pods with matching labels -5. Reconnects to the new pod -6. Logs the switch: `Switched to new pod: old-pod → new-pod` +1. Port-forward connection breaks +2. kportal immediately re-resolves the resource: + - For prefix matches: Finds newest pod with matching prefix + - For selectors: Re-queries pods with matching labels +3. Reconnects to new pod +4. Logs the switch: `Switched to new pod: old-pod-abc → new-pod-xyz` ### Retry Strategy -Backoff intervals: **1s → 2s → 4s → 8s → 10s (max)** +Exponential backoff with maximum interval: +- **Intervals**: 1s → 2s → 4s → 8s → 10s (max) +- **Infinite retries**: Continues until connection succeeds +- **Independent**: Each forward has its own retry logic +- **Grace period**: First 10 seconds show "Starting" instead of "Error" -- Connection failures trigger immediate resource re-resolution -- Retries continue indefinitely until successful -- Each forward has independent retry logic +## 🔧 Development -### Hot-Reload +### Prerequisites -The config file is watched for changes: -1. File change detected -2. New config loaded and validated -3. Changes diff'd against current state -4. New forwards started, removed forwards stopped -5. Unchanged forwards continue running +- Go 1.23 or higher +- Access to a Kubernetes cluster +- kubectl configured with contexts -If validation fails, the previous configuration remains active. - -## Development - -### Build Commands +### Building ```bash # Build binary make build -# Check current version (from semver-gen) -make version - -# Run all checks (fmt, vet, staticcheck, test, build) -make all - -# Run tests with race detection +# Run tests make test -# Run code quality checks -make vet -make staticcheck -make fmt +# Run all checks (fmt, vet, staticcheck, test) +make all -# Install development tools (staticcheck, mockery, semver-gen) -make install-tools +# Check current version +make version -# Generate test coverage report -make coverage +# Install locally +make install + +# Install system-wide +sudo make install-system + +# Clean build artifacts +make clean ``` +### Project Structure + +``` +kportal/ +├── cmd/kportal/ # Main application entry point +├── internal/ +│ ├── config/ # Configuration parsing and validation +│ ├── forward/ # Port-forward manager and workers +│ │ ├── manager.go # Orchestrates all forwards +│ │ ├── worker.go # Individual forward worker +│ │ └── port_checker.go # Port conflict detection +│ ├── healthcheck/ # Health monitoring system +│ │ └── checker.go # Port health checking +│ ├── k8s/ # Kubernetes client wrapper +│ │ ├── client.go # K8s client management +│ │ ├── port_forward.go # Port-forward implementation +│ │ └── resolver.go # Resource resolution +│ ├── retry/ # Retry logic with backoff +│ │ └── backoff.go # Exponential backoff +│ ├── ui/ # Terminal UI implementations +│ │ ├── bubbletea_ui.go # Interactive TUI (Bubble Tea) +│ │ └── table_ui.go # Simple table for verbose mode +│ └── converter/ # kftray JSON converter +├── Formula/ # Homebrew formula +├── .github/workflows/ # CI/CD pipelines +│ └── release.yml # Release automation +├── install.sh # Installation script +├── semver.yaml # Semantic version config +├── Makefile # Build automation +└── README.md # This file +``` + +## 📝 Examples + +### Database Access + +```yaml +contexts: + production: + namespaces: + databases: + - resource: postgres-primary + port: 5432 + local_port: 5432 + alias: prod-db +``` + +Connect with: +```bash +kportal # Start in another terminal +psql -h localhost -p 5432 -U postgres +``` + +### Multiple Services + +```yaml +contexts: + dev: + namespaces: + default: + - resource: api + port: 8080 + local_port: 8080 + - resource: frontend + port: 3000 + local_port: 3000 + - resource: redis + port: 6379 + local_port: 6379 +``` + +Access: +- API: `http://localhost:8080` +- Frontend: `http://localhost:3000` +- Redis: `redis-cli -p 6379` + +### Cross-Context Setup + +```yaml +contexts: + prod-us: + namespaces: + backend: + - resource: api + port: 8080 + local_port: 8080 + alias: prod-us-api + + prod-eu: + namespaces: + backend: + - resource: api + port: 8080 + local_port: 8081 # Different local port + alias: prod-eu-api +``` + +Compare APIs across regions simultaneously. + +### Debug Multiple Pod Versions + +```yaml +contexts: + production: + namespaces: + default: + # Version 1 + - resource: pod + selector: app=myapp,version=v1 + port: 8080 + local_port: 8080 + alias: app-v1 + + # Version 2 + - resource: pod + selector: app=myapp,version=v2 + port: 8080 + local_port: 8081 + alias: app-v2 + + # Debug port for v2 + - resource: pod + selector: app=myapp,version=v2 + port: 6060 + local_port: 6060 + alias: app-v2-pprof +``` + +## 🐛 Troubleshooting + +### Port Already in Use + +**Problem**: `Port 8080: already in use by PID 1234 (chrome)` + +**Solutions**: +```bash +# Find the process +lsof -i :8080 + +# Kill the process +kill 1234 + +# Or use a different local port in config +local_port: 8081 +``` + +### Connection Refused + +**Problem**: `dial tcp 127.0.0.1:8080: connect: connection refused` + +**Common causes**: +1. **Pod not ready yet** - Wait for status to change from "Starting" → "Active" (10s grace period) +2. **Wrong port number** - Verify the pod/service actually exposes that port +3. **Service not exposed** - Check with `kubectl get svc` and `kubectl describe svc ` + +**Debug**: +```bash +# Check pod status +kubectl get pods -n + +# Check if port is exposed +kubectl describe pod -n + +# Check service endpoints +kubectl get endpoints -n +``` + +### Context Not Found + +**Problem**: `context "prod" not found in kubeconfig` + +**Solution**: +```bash +# List available contexts +kubectl config get-contexts + +# Verify context name matches +kubectl config current-context + +# Update your config to use the correct context name +``` + +### Health Check Errors During Startup + +**Problem**: Seeing "Error" status immediately after starting + +**This is normal!** kportal has a 10-second grace period. If the connection is still failing after 10 seconds, check: +- Pod is running: `kubectl get pods` +- Port is correct in config +- Network connectivity to cluster + +### Logs Covering UI + +**Problem**: Kubernetes client logs appearing over the interactive UI + +**This is fixed in v0.1.5+**. The interactive mode now completely suppresses all logs including: +- Standard Go `log` package +- Kubernetes `klog` output +- Any stderr/stdout leakage + +If you still see logs, please file an issue! + +## 🤝 Contributing + +Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. + +1. Fork the repository +2. Create a feature branch (`git checkout -b feature/amazing-feature`) +3. Make your changes and add tests +4. Run checks: `make all` +5. Commit your changes (follow [semantic commit messages](#semantic-versioning)) +6. Push to the branch (`git push origin feature/amazing-feature`) +7. Open a Pull Request + ### Semantic Versioning This project uses [semver-gen](https://github.com/lukaszraczylo/semver-generator) for automatic semantic version generation based on git commit messages. @@ -265,130 +619,37 @@ This project uses [semver-gen](https://github.com/lukaszraczylo/semver-generator - **Minor** (0.X.0): `feat`, `feature`, `add`, `enhance`, `update`, `improve` - **Major** (X.0.0): `breaking`, `major`, `BREAKING CHANGE` -The version is automatically calculated from your git history and embedded in the binary at build time. - +Example commits: ```bash -# Check current version -make version - -# Build with auto-generated version -make build - -# Verify version in binary -./kportal --version +git commit -m "feat: add health check grace period" # Bumps minor version +git commit -m "fix: resolve port conflict detection" # Bumps patch version +git commit -m "breaking: change config file format" # Bumps major version ``` -Configuration is managed in `semver.yaml`. To manually install semver-gen: +## 📄 License -```bash -# Automatically installed via make install-tools -# Or install manually from https://github.com/lukaszraczylo/semver-generator -``` +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. -### Project Structure +## 🙏 Acknowledgments -``` -kportal/ -├── cmd/kportal/ # CLI entry point -├── internal/ -│ ├── config/ # Configuration parsing and validation -│ ├── forward/ # Port-forward workers and manager -│ ├── k8s/ # Kubernetes client, resolver, port-forward wrapper -│ └── retry/ # Exponential backoff logic -├── test/ -│ ├── integration/ # Integration tests -│ ├── fixtures/ # Test configurations -│ └── helpers/ # Test utilities -├── .kportal.yaml # Example configuration -├── semver.yaml # Semantic version configuration -├── Makefile # Build automation -└── CLAUDE.md # Development guide -``` +- Built with [Bubble Tea](https://github.com/charmbracelet/bubbletea) by Charm - An awesome framework for building terminal UIs +- Styled with [Lipgloss](https://github.com/charmbracelet/lipgloss) - Terminal styling library +- Inspired by [kftray](https://github.com/hcavarsan/kftray) - Original GUI port-forward manager +- Uses [client-go](https://github.com/kubernetes/client-go) for Kubernetes integration +- Version management by [semver-gen](https://github.com/lukaszraczylo/semver-generator) + +## 📚 Documentation + +- [Website](https://lukaszraczylo.github.io/kportal) +- [Issue Tracker](https://github.com/lukaszraczylo/kportal/issues) +- [Releases](https://github.com/lukaszraczylo/kportal/releases) +- [Changelog](CHANGELOG.md) ## Signal Handling -- `CTRL+C` / `SIGTERM`: Graceful shutdown (closes all forwards) +- `Ctrl+C` / `SIGTERM`: Graceful shutdown (closes all forwards) - `SIGHUP`: Reload configuration file -## Port Conflict Detection +--- -kportal validates ports at multiple stages: - -1. **Config Parse Time**: Detects duplicate local ports in configuration -2. **Startup Time**: Checks if ports are available on the system -3. **Hot-Reload Time**: Validates new ports before applying changes - -Errors show which process is using conflicting ports (with PID). - -## Examples - -### Forward Multiple Services from Production - -```yaml -contexts: - - name: production - namespaces: - - name: default - forwards: - - resource: service/api - port: 8080 - localPort: 8080 - - resource: service/postgres - port: 5432 - localPort: 5432 - - resource: service/redis - port: 6379 - localPort: 6379 -``` - -### Monitor Multiple Environments - -```yaml -contexts: - - name: production - namespaces: - - name: monitoring - forwards: - - resource: service/prometheus - port: 9090 - localPort: 9090 - - - name: staging - namespaces: - - name: monitoring - forwards: - - resource: service/prometheus - port: 9090 - localPort: 9091 # Different local port -``` - -### Debug Specific Pods - -```yaml -contexts: - - name: production - namespaces: - - name: default - forwards: - # Forward app HTTP and debug ports - - resource: pod - selector: app=myapp,version=v2 - port: 8080 - localPort: 8080 - - - resource: pod - selector: app=myapp,version=v2 - port: 6060 # pprof - localPort: 6060 -``` - -## License - -MIT - -## Contributing - -Contributions welcome! Please ensure: -- Code passes `make check` (fmt, vet, staticcheck) -- Tests pass with `make test` -- New features include tests +Made with ❤️ by [Lukasz Raczylo](https://github.com/lukaszraczylo) diff --git a/RELEASE_SETUP.md b/RELEASE_SETUP.md new file mode 100644 index 0000000..b19a094 --- /dev/null +++ b/RELEASE_SETUP.md @@ -0,0 +1,320 @@ +# Release Infrastructure Setup Summary + +This document summarizes all the release infrastructure that has been set up for kportal. + +## ✅ Completed Setup + +### 1. GitHub Actions CI/CD Pipeline + +**File**: `.github/workflows/release.yml` + +**Features**: +- Multi-platform binary builds (Linux, macOS, Windows - amd64 & arm64) +- Automatic release creation on version tags +- Binary archiving (tar.gz for Unix, zip for Windows) +- SHA256 checksum generation +- Automated Homebrew formula updates +- Release notes generation + +**How to trigger**: +```bash +# Commit with semantic versioning keywords +git commit -m "feat: add new feature" + +# Tag the release +git tag -a v0.2.0 -m "Release v0.2.0" + +# Push tags +git push origin v0.2.0 +``` + +The pipeline will automatically: +1. Build binaries for all platforms +2. Create GitHub release with binaries +3. Update Homebrew tap formula +4. Generate release notes + +### 2. Installation Methods + +#### A. Homebrew Formula + +**File**: `Formula/kportal.rb` + +**Installation command**: +```bash +brew install lukaszraczylo/tap/kportal +``` + +**Note**: Formula is automatically updated by CI/CD pipeline. You'll need to create a separate tap repository: +1. Create repo: `https://github.com/lukaszraczylo/brew-taps` +2. Add Formula/kportal.rb to that repo +3. Set `HOMEBREW_TAP_TOKEN` secret in GitHub repository settings + +#### B. Quick Install Script + +**File**: `install.sh` + +**Features**: +- Auto-detects OS and architecture +- Downloads appropriate binary +- Extracts and installs to /usr/local/bin +- Verifies installation +- Colorful output with emoji indicators + +**Installation command**: +```bash +curl -fsSL https://raw.githubusercontent.com/lukaszraczylo/kportal/main/install.sh | bash +``` + +#### C. Manual Download + +Users can download binaries directly from GitHub releases: +``` +https://github.com/lukaszraczylo/kportal/releases +``` + +### 3. Documentation + +#### A. Comprehensive README.md + +**File**: `README.md` + +**Contents**: +- Feature showcase with emojis +- Multiple installation methods +- Quick start guide +- Configuration examples +- Usage instructions +- Advanced features documentation +- Troubleshooting guide +- Contributing guidelines + +#### B. GitHub Pages Website + +**File**: `docs/index.html` + +**Features**: +- Modern, responsive design with TailwindCSS +- Hero section with clear CTA +- Feature showcase cards +- Installation guide +- Configuration examples with syntax highlighting +- Documentation links +- Mobile-friendly + +**URL** (once enabled): `https://lukaszraczylo.github.io/kportal` + +**To enable**: +1. Go to GitHub repository settings +2. Pages section +3. Source: Deploy from a branch +4. Branch: main +5. Folder: /docs + +### 4. Supporting Files + +#### CHANGELOG.md +**File**: `CHANGELOG.md` + +Tracks all changes following Keep a Changelog format. Update this file with each release. + +#### CONTRIBUTING.md +**File**: `CONTRIBUTING.md` + +Guidelines for: +- Bug reporting +- Feature requests +- Pull request process +- Commit message format +- Development setup +- Testing guidelines + +## 🚀 Release Workflow + +### Standard Release Process + +1. **Develop features** + ```bash + git checkout -b feature/my-feature + # Make changes + make test + make all + ``` + +2. **Commit with semantic messages** + ```bash + git commit -m "feat: add amazing feature" + git commit -m "fix: resolve bug in health check" + ``` + +3. **Update CHANGELOG.md** + ```markdown + ## [0.2.0] - 2025-11-24 + + ### Added + - Amazing new feature + + ### Fixed + - Bug in health check + ``` + +4. **Tag the release** + ```bash + git tag -a v0.2.0 -m "Release v0.2.0" + git push origin main + git push origin v0.2.0 + ``` + +5. **CI/CD automatically**: + - Builds all binaries + - Creates GitHub release + - Updates Homebrew formula + - Attaches binaries and checksums + +### Version Bumping (Semantic Versioning) + +Version is automatically determined by semver-gen from commit messages: + +- **Patch** (0.0.X): `fix`, `bugfix`, `hotfix`, `patch`, `docs`, `test`, `refactor` +- **Minor** (0.X.0): `feat`, `feature`, `add`, `enhance`, `update`, `improve` +- **Major** (X.0.0): `breaking`, `major`, `BREAKING CHANGE` + +## 📦 Platform Support + +### Supported Platforms + +| OS | Architecture | Archive Format | +|---------|-------------|----------------| +| Linux | amd64 | tar.gz | +| Linux | arm64 | tar.gz | +| macOS | amd64 | tar.gz | +| macOS | arm64 | tar.gz | +| Windows | amd64 | zip | +| Windows | arm64 | zip | + +## 🔒 Required GitHub Secrets + +For full automation, set these secrets in your GitHub repository: + +1. **GITHUB_TOKEN** - Automatically provided by GitHub Actions +2. **HOMEBREW_TAP_TOKEN** - Personal access token for updating Homebrew tap + - Create at: https://github.com/settings/tokens + - Permissions needed: `repo` scope + - Add to repository secrets + +## 📝 Next Steps + +### 1. Enable GitHub Pages +- Repository Settings → Pages → Source: main branch, /docs folder + +### 2. Create Homebrew Tap Repository +```bash +# Create new repository +gh repo create lukaszraczylo/brew-taps --public + +# Clone and set up +git clone https://github.com/lukaszraczylo/brew-taps +cd brew-taps +cp ../kportal/Formula/kportal.rb ./Formula/ +git add Formula/kportal.rb +git commit -m "Initial formula for kportal" +git push origin main +``` + +### 3. Add GitHub Token to Secrets +- Repository Settings → Secrets and variables → Actions +- New repository secret +- Name: `HOMEBREW_TAP_TOKEN` +- Value: Your personal access token + +### 4. Create First Release +```bash +cd kportal +git add . +git commit -m "feat: initial release setup" +git push origin main +git tag -a v0.1.5 -m "Release v0.1.5" +git push origin v0.1.5 +``` + +### 5. Test Installation Methods + +After first release, test: +```bash +# Homebrew (once tap is set up) +brew install lukaszraczylo/tap/kportal + +# Quick install script +curl -fsSL https://raw.githubusercontent.com/lukaszraczylo/kportal/main/install.sh | bash + +# Manual download +# Visit releases page and download binary +``` + +## 🎨 Customization + +### Update Website Colors + +Edit `docs/index.html`: +```javascript +tailwind.config = { + theme: { + extend: { + colors: { + primary: '#3b82f6', // Blue + secondary: '#8b5cf6', // Purple + dark: '#0f172a', // Dark slate + } + } + } +} +``` + +### Update Release Notes Template + +Edit `.github/workflows/release.yml` in the "Generate release notes" step. + +## 📊 Monitoring + +After releases, monitor: +- GitHub Actions workflow runs +- GitHub Releases page +- Homebrew tap repository commits +- Download statistics on releases page + +## 🐛 Troubleshooting + +### Release workflow fails +- Check GitHub Actions logs +- Verify all required secrets are set +- Ensure tag follows v\d+.\d+.\d+ format + +### Homebrew formula not updating +- Verify HOMEBREW_TAP_TOKEN is valid +- Check tap repository permissions +- Review release workflow logs + +### Install script fails +- Test locally with different OS/arch combinations +- Check release binary naming matches script expectations +- Verify binaries are attached to release + +## ✅ Checklist for First Release + +- [ ] All code committed and pushed +- [ ] GitHub Pages enabled +- [ ] Homebrew tap repository created +- [ ] HOMEBREW_TAP_TOKEN secret set +- [ ] CHANGELOG.md updated +- [ ] Version tag created and pushed +- [ ] Release workflow completed successfully +- [ ] Binaries attached to release +- [ ] Homebrew formula updated +- [ ] Install script tested +- [ ] Documentation website live +- [ ] README.md installation links work + +--- + +**Documentation last updated**: 2025-11-23 +**Setup completed for**: kportal v0.1.5 diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..92c3403 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,381 @@ + + + + + + kportal - Kubernetes Port-Forward Manager + + + + + + + + + + + + + + +
+
+
+

+ Kubernetes Port-Forward
+ Manager +

+

+ Professional terminal interface for managing multiple Kubernetes port-forwards with auto-reconnect, hot-reload, and real-time health monitoring. +

+ +
+ Version + License + Go Report +
+
+
+
+ + +
+
+
+

Features

+

Everything you need for production-grade port-forwarding

+
+
+
+
+ +
+

Interactive TUI

+

Beautiful terminal interface powered by Bubble Tea. Toggle forwards on/off, view real-time status updates.

+
+ +
+
+ +
+

Auto-Reconnect

+

Automatic reconnection on failure with exponential backoff. Never lose connectivity to your services.

+
+ +
+
+ +
+

Hot-Reload

+

Configuration changes applied automatically. Add, remove, or modify forwards without restarting.

+
+ +
+
+ +
+

Health Checks

+

Real-time health monitoring with 5-second intervals. Grace period prevents false error alerts.

+
+ +
+
+ +
+

Error Reporting

+

Detailed error messages displayed in the interface. Know exactly what went wrong.

+
+ +
+
+ +
+

Multi-Context

+

Support for multiple Kubernetes contexts and namespaces. Manage all your clusters from one place.

+
+
+
+
+ + +
+
+
+

Installation

+

Get started in seconds

+
+
+
+
+ +
+

Homebrew

+

macOS & Linux

+
+
+
+ brew install lukaszraczylo/tap/kportal + +
+
+ +
+
+ +
+

Quick Install

+

All platforms

+
+
+
+ curl -fsSL https://raw.githubusercontent.com/lukaszraczylo/kportal/main/install.sh | bash + +
+
+ +
+
+ +
+

Manual Download

+

Direct download from GitHub releases

+
+
+ + Download Binary + +
+
+
+
+ + +
+
+
+

Configuration

+

Simple YAML configuration

+
+
+
+
+
+ + .kportal.yaml +
+ +
+
contexts:
+  - name: production
+    namespaces:
+      - name: backend
+        forwards:
+          - resource: service/postgres
+            protocol: tcp
+            port: 5432
+            localPort: 5432
+            alias: prod-db
+
+      - name: frontend
+        forwards:
+          - resource: service/redis
+            protocol: tcp
+            port: 6379
+            localPort: 6379
+            alias: prod-redis
+
+ +
+
+

+ Resource Types +

+
    +
  • pod/name - Direct pod
  • +
  • service/name - Service
  • +
  • deployment/name - Deployment
  • +
+
+ +
+

+ Features +

+
    +
  • Pod prefix matching
  • +
  • Label selectors
  • +
  • Alias support
  • +
  • Auto-reconnect
  • +
+
+
+
+
+
+ + +
+ +
+ + + + + + + diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..2e158b9 --- /dev/null +++ b/install.sh @@ -0,0 +1,171 @@ +#!/bin/bash + +set -e + +# kportal installation script +# Usage: curl -fsSL https://raw.githubusercontent.com/lukaszraczylo/kportal/main/install.sh | bash + +REPO="lukaszraczylo/kportal" +INSTALL_DIR="${INSTALL_DIR:-/usr/local/bin}" + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Print functions +print_info() { + echo -e "${BLUE}ℹ${NC} $1" +} + +print_success() { + echo -e "${GREEN}✓${NC} $1" +} + +print_error() { + echo -e "${RED}✗${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}⚠${NC} $1" +} + +# Detect OS +detect_os() { + case "$(uname -s)" in + Linux*) echo "linux";; + Darwin*) echo "darwin";; + MINGW*|MSYS*|CYGWIN*) echo "windows";; + *) echo "unknown";; + esac +} + +# Detect architecture +detect_arch() { + case "$(uname -m)" in + x86_64|amd64) echo "amd64";; + aarch64|arm64) echo "arm64";; + armv7l) echo "arm";; + *) echo "unknown";; + esac +} + +# Get latest version from GitHub +get_latest_version() { + curl -fsSL "https://api.github.com/repos/${REPO}/releases/latest" | + grep '"tag_name":' | + sed -E 's/.*"v([^"]+)".*/\1/' +} + +# Main installation +main() { + echo "" + echo "╔════════════════════════════════════════╗" + echo "║ kportal Installation Script ║" + echo "║ Kubernetes Port Forwarding Made Easy ║" + echo "╚════════════════════════════════════════╝" + echo "" + + # Detect system + OS=$(detect_os) + ARCH=$(detect_arch) + + if [ "$OS" = "unknown" ] || [ "$ARCH" = "unknown" ]; then + print_error "Unsupported operating system or architecture" + print_info "OS: $(uname -s), Arch: $(uname -m)" + exit 1 + fi + + print_info "Detected: ${OS}/${ARCH}" + + # Get latest version + print_info "Fetching latest version..." + VERSION=$(get_latest_version) + + if [ -z "$VERSION" ]; then + print_error "Failed to fetch latest version" + exit 1 + fi + + print_success "Latest version: v${VERSION}" + + # Construct download URL + if [ "$OS" = "windows" ]; then + ARCHIVE="kportal-${VERSION}-${OS}-${ARCH}.zip" + else + ARCHIVE="kportal-${VERSION}-${OS}-${ARCH}.tar.gz" + fi + + DOWNLOAD_URL="https://github.com/${REPO}/releases/download/v${VERSION}/${ARCHIVE}" + + # Create temporary directory + TMP_DIR=$(mktemp -d) + trap "rm -rf ${TMP_DIR}" EXIT + + # Download binary + print_info "Downloading kportal..." + if ! curl -fsSL -o "${TMP_DIR}/${ARCHIVE}" "${DOWNLOAD_URL}"; then + print_error "Failed to download kportal" + print_info "URL: ${DOWNLOAD_URL}" + exit 1 + fi + + # Extract archive + print_info "Extracting archive..." + cd "${TMP_DIR}" + if [ "$OS" = "windows" ]; then + unzip -q "${ARCHIVE}" + BINARY="kportal.exe" + else + tar -xzf "${ARCHIVE}" + BINARY="kportal" + fi + + # Check if binary exists + if [ ! -f "${BINARY}" ]; then + print_error "Binary not found after extraction" + exit 1 + fi + + # Make binary executable + chmod +x "${BINARY}" + + # Install binary + print_info "Installing kportal to ${INSTALL_DIR}..." + + # Check if we need sudo + if [ ! -w "${INSTALL_DIR}" ]; then + print_warning "Installation directory requires sudo access" + if command -v sudo >/dev/null 2>&1; then + sudo mv "${BINARY}" "${INSTALL_DIR}/${BINARY}" + else + print_error "sudo not found. Please run with appropriate permissions" + exit 1 + fi + else + mv "${BINARY}" "${INSTALL_DIR}/${BINARY}" + fi + + # Verify installation + if command -v kportal >/dev/null 2>&1; then + INSTALLED_VERSION=$(kportal --version | grep -oP 'kportal version \K[0-9.]+' || echo "unknown") + print_success "kportal v${INSTALLED_VERSION} installed successfully!" + else + print_warning "kportal installed but not found in PATH" + print_info "You may need to add ${INSTALL_DIR} to your PATH" + fi + + echo "" + print_success "Installation complete!" + echo "" + echo "Get started:" + echo " 1. Create a config file: touch .kportal.yaml" + echo " 2. Run: kportal" + echo "" + echo "Documentation: https://lukaszraczylo.github.io/kportal" + echo "" +} + +main "$@"