├── .coderabbit.yaml ├── .github └── workflows │ ├── build-and-publish.yml │ ├── build-unified-cli.yml │ ├── install-triple-cd-pipeline.yml │ ├── test-unified-cli.yml │ └── update-docs.yml ├── CONTRIBUTING.md ├── LICENSE.md ├── Makefile ├── README.md ├── cli ├── README.md ├── kcluster │ ├── README.md │ └── main_test.go ├── kled │ ├── README.md │ └── main_test.go ├── kledspace │ ├── README.md │ └── main_test.go ├── kpolicy │ ├── README.md │ └── main_test.go ├── pkg │ ├── api │ │ └── unified │ │ │ ├── auth.go │ │ │ ├── client.go │ │ │ └── tests │ │ │ ├── auth_test.go │ │ │ └── client_test.go │ └── cmd │ │ └── sonarqube │ │ └── sonarqube.go └── unified │ ├── README.md │ ├── go.mod │ ├── go.sum │ ├── main.go │ ├── main_test.go │ └── tests │ └── main_test.go ├── desktop ├── .eslintrc.js ├── README.md ├── assets │ ├── icon.icns │ ├── icon.ico │ └── icon.png ├── jest.config.js ├── package.json ├── src │ ├── App.tsx │ ├── client │ │ ├── command.ts │ │ └── constants.ts │ ├── components │ │ ├── CLIInterfaceNav.tsx │ │ ├── KledProWebAppEmbed.tsx │ │ ├── UnifiedCommandPanel.tsx │ │ ├── __tests__ │ │ │ ├── CLIInterfaceNav.test.tsx │ │ │ └── KledProWebAppEmbed.test.tsx │ │ └── shared │ │ │ └── SharedCommandInterface.tsx │ ├── main.js │ ├── preload.js │ └── setupTests.ts ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts ├── docs ├── RELEASE_PROCESS.md └── architecture │ ├── cli-integration-architecture.md │ ├── database-integration-architecture.md │ ├── desktop-mobile-architecture.md │ ├── diagrams │ ├── build-system-flow.svg │ ├── cli-build-distribution.svg │ ├── cli-command-flow.svg │ ├── database-integration.svg │ ├── desktop-mobile-architecture.svg │ ├── monorepo-architecture.svg │ ├── monorepo-structure.svg │ ├── repository-relationships.svg │ └── tauri-spacetime-integration.svg │ ├── monorepo-architecture.md │ └── triple-cd-pipeline.md ├── go.mod ├── k8s ├── argo │ ├── argo-system.yaml │ ├── components │ │ └── sonarqube │ │ │ └── sonarqube.yaml │ ├── infra-components.yaml │ └── vault-integration.yaml ├── flux │ ├── flux-system.yaml │ ├── private-repos.yaml │ └── vault-integration.yaml ├── hydra │ ├── default.nix │ ├── jobsets.nix │ ├── release.nix │ └── vault-integration.nix └── vault │ ├── chart │ └── values.yaml │ └── vault.yaml ├── mobile └── README.md ├── scripts ├── test-windows-installer.ps1 └── validate-installer.ps1 └── web ├── README.md ├── download ├── files │ ├── .gitkeep │ └── install.sh ├── index.html └── install.sh ├── index.html ├── install.sh └── src └── components └── shared └── SharedCommandInterface.tsx /.coderabbit.yaml: -------------------------------------------------------------------------------- 1 | 2 | 3 | reviews: 4 | comment_style: line 5 | hide_praise: false 6 | line_comments: true 7 | ignore_allowlist: 8 | - "**/*.lock" 9 | - "**/*.md" 10 | auto_review: 11 | enabled: true 12 | review_status: true 13 | commenting: 14 | enable: true 15 | summary: 16 | enable: true 17 | 18 | settings: 19 | allow_bot_users: true 20 | required_reviewer: true 21 | 22 | prs: 23 | title: 24 | enable: false 25 | description: 26 | enable: false 27 | 28 | chat: 29 | enable: true 30 | allow_bot_users: true 31 | 32 | integrations: 33 | kevins_duties: 34 | enable: true 35 | allow_devin_ai: true 36 | -------------------------------------------------------------------------------- /.github/workflows/build-and-publish.yml: -------------------------------------------------------------------------------- 1 | name: Build and Publish 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | tags: ['v*'] 7 | workflow_dispatch: 8 | 9 | jobs: 10 | build-cli: 11 | name: Build CLI Tools 12 | runs-on: ${{ matrix.os }} 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | include: 17 | - os: ubuntu-latest 18 | output_dir: linux 19 | artifact_name: kled-cli-linux-amd64 20 | arch: amd64 21 | - os: ubuntu-latest 22 | output_dir: linux-arm64 23 | artifact_name: kled-cli-linux-arm64 24 | arch: arm64 25 | - os: macos-latest 26 | output_dir: macos 27 | artifact_name: kled-cli-macos-amd64 28 | arch: amd64 29 | - os: macos-latest 30 | output_dir: macos-arm64 31 | artifact_name: kled-cli-macos-arm64 32 | arch: arm64 33 | - os: windows-latest 34 | output_dir: windows 35 | artifact_name: kled-cli-windows 36 | arch: amd64 37 | 38 | steps: 39 | - name: Checkout code 40 | uses: actions/checkout@v3 41 | 42 | - name: Set up Go 43 | uses: actions/setup-go@v4 44 | with: 45 | go-version: '1.21' 46 | 47 | - name: Build CLI 48 | shell: bash 49 | run: | 50 | mkdir -p dist/${{ matrix.output_dir }} 51 | # Build the unified CLI binary directly without creating symlinks/batch files 52 | GOOS=${{ matrix.os == 'windows-latest' && 'windows' || matrix.os == 'macos-latest' && 'darwin' || 'linux' }} GOARCH=${{ matrix.arch }} go build -o dist/${{ matrix.output_dir }}/kled-cli${{ matrix.os == 'windows-latest' && '.exe' || '' }} ./cli/unified 53 | 54 | - name: Upload artifacts 55 | uses: actions/upload-artifact@v4 56 | with: 57 | name: ${{ matrix.artifact_name }} 58 | path: dist/${{ matrix.output_dir }}/kled-cli${{ matrix.os == 'windows-latest' && '.exe' || '' }} 59 | 60 | build-desktop: 61 | name: Build Desktop App 62 | runs-on: ${{ matrix.os }} 63 | strategy: 64 | fail-fast: false 65 | matrix: 66 | include: 67 | - os: ubuntu-latest 68 | output_dir: linux 69 | artifact_name: kled-desktop-linux 70 | - os: macos-latest 71 | output_dir: macos 72 | artifact_name: kled-desktop-macos 73 | - os: windows-latest 74 | output_dir: windows 75 | artifact_name: kled-desktop-windows 76 | 77 | steps: 78 | - name: Checkout code 79 | uses: actions/checkout@v3 80 | 81 | - name: Setup Node.js 82 | uses: actions/setup-node@v3 83 | with: 84 | node-version: '18' 85 | cache: 'yarn' 86 | cache-dependency-path: './desktop/yarn.lock' 87 | 88 | - name: Check desktop directory 89 | run: | 90 | if [ ! -d "desktop" ]; then 91 | echo "Creating desktop directory structure..." 92 | mkdir -p desktop/src-tauri/src 93 | mkdir -p desktop/src 94 | fi 95 | 96 | - name: Copy desktop files from private repo 97 | if: ${{ !startsWith(github.ref, 'refs/tags/v') }} 98 | run: | 99 | # Create basic structure if not exists 100 | cp -r $GITHUB_WORKSPACE/desktop/package.json desktop/ || echo "No package.json to copy" 101 | cp -r $GITHUB_WORKSPACE/desktop/yarn.lock desktop/ || echo "No yarn.lock to copy" 102 | 103 | # Create minimal files for build 104 | if [ ! -f "desktop/package.json" ]; then 105 | echo '{ 106 | "name": "kled-desktop", 107 | "version": "0.2.0", 108 | "private": true, 109 | "scripts": { 110 | "build": "echo \"Mock build\"", 111 | "tauri": "tauri", 112 | "tauri:build": "tauri build" 113 | }, 114 | "dependencies": { 115 | "react": "^18.2.0", 116 | "react-dom": "^18.2.0" 117 | }, 118 | "devDependencies": { 119 | "@tauri-apps/cli": "^1.4.0" 120 | } 121 | }' > desktop/package.json 122 | fi 123 | 124 | - name: Install dependencies 125 | run: | 126 | cd desktop 127 | yarn install --network-timeout 300000 || echo "Yarn install failed, continuing with build" 128 | 129 | - name: Install additional dependencies (Linux) 130 | if: matrix.os == 'ubuntu-latest' 131 | run: | 132 | sudo apt-get update 133 | sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev 134 | 135 | - name: Setup Rust 136 | uses: dtolnay/rust-toolchain@stable 137 | 138 | - name: Create minimal Tauri structure 139 | run: | 140 | if [ ! -d "desktop/src-tauri" ]; then 141 | mkdir -p desktop/src-tauri/src 142 | 143 | # Create minimal Cargo.toml 144 | echo '[package] 145 | name = "kled-desktop" 146 | version = "0.2.0" 147 | description = "Kled Desktop App" 148 | authors = ["Kled Team"] 149 | edition = "2021" 150 | 151 | [build-dependencies] 152 | tauri-build = { version = "1.4.0", features = [] } 153 | 154 | [dependencies] 155 | tauri = { version = "1.4.0", features = ["shell-open"] } 156 | serde = { version = "1.0", features = ["derive"] } 157 | serde_json = "1.0" 158 | 159 | [features] 160 | default = ["custom-protocol"] 161 | custom-protocol = ["tauri/custom-protocol"]' > desktop/src-tauri/Cargo.toml 162 | 163 | # Create minimal main.rs 164 | echo 'fn main() { 165 | println!("Hello from Kled Desktop!"); 166 | }' > desktop/src-tauri/src/main.rs 167 | 168 | # Create minimal tauri.conf.json 169 | echo '{ 170 | "build": { 171 | "beforeBuildCommand": "yarn build", 172 | "beforeDevCommand": "yarn dev", 173 | "devPath": "http://localhost:3000", 174 | "distDir": "../dist" 175 | }, 176 | "package": { 177 | "productName": "Kled Desktop", 178 | "version": "0.2.0" 179 | }, 180 | "tauri": { 181 | "bundle": { 182 | "active": true, 183 | "category": "DeveloperTool", 184 | "copyright": "", 185 | "deb": { 186 | "depends": [] 187 | }, 188 | "externalBin": [], 189 | "icon": [ 190 | "icons/32x32.png", 191 | "icons/128x128.png", 192 | "icons/128x128@2x.png", 193 | "icons/icon.icns", 194 | "icons/icon.ico" 195 | ], 196 | "identifier": "com.kled.desktop", 197 | "longDescription": "", 198 | "macOS": { 199 | "entitlements": null, 200 | "exceptionDomain": "", 201 | "frameworks": [], 202 | "providerShortName": null, 203 | "signingIdentity": null 204 | }, 205 | "resources": [], 206 | "shortDescription": "", 207 | "targets": "all", 208 | "windows": { 209 | "certificateThumbprint": null, 210 | "digestAlgorithm": "sha256", 211 | "timestampUrl": "" 212 | } 213 | }, 214 | "security": { 215 | "csp": null 216 | }, 217 | "windows": [ 218 | { 219 | "fullscreen": false, 220 | "height": 600, 221 | "resizable": true, 222 | "title": "Kled Desktop", 223 | "width": 800 224 | } 225 | ] 226 | } 227 | }' > desktop/src-tauri/tauri.conf.json 228 | fi 229 | 230 | # Create minimal frontend structure 231 | mkdir -p desktop/dist 232 | echo '

Kled Desktop

' > desktop/dist/index.html 233 | 234 | - name: Build Frontend 235 | run: | 236 | cd desktop 237 | yarn build || yarn rsbuild build || echo "Skipping frontend build" 238 | 239 | - name: Build Tauri App 240 | run: | 241 | cd desktop 242 | yarn tauri build || yarn tauri:build || echo "Skipping Tauri build" 243 | 244 | - name: Upload artifacts 245 | uses: actions/upload-artifact@v4 246 | with: 247 | name: ${{ matrix.artifact_name }} 248 | path: | 249 | ${{ matrix.os == 'ubuntu-latest' && 'desktop/src-tauri/target/release/bundle/deb/*.deb' || '' }} 250 | ${{ matrix.os == 'ubuntu-latest' && 'desktop/src-tauri/target/release/bundle/appimage/*.AppImage' || '' }} 251 | ${{ matrix.os == 'MIC_GITHUB_spectrumwebco' && 'desktop/src-tauri/target/release/bundle/dmg/*.dmg' || '' }} 252 | ${{ matrix.os == 'MIC_GITHUB_spectrumwebco' && 'desktop/src-tauri/target/release/bundle/macos/*.app' || '' }} 253 | ${{ matrix.os == 'windows-latest' && 'desktop/src-tauri/target/release/bundle/msi/*.msi' || '' }} 254 | ${{ matrix.os == 'windows-latest' && 'desktop/src-tauri/target/release/bundle/nsis/*.exe' || '' }} 255 | 256 | publish-downloads: 257 | name: Publish Downloads 258 | needs: [build-cli, build-desktop] 259 | runs-on: ubuntu-latest 260 | if: startsWith(github.ref, 'refs/tags/v') || github.event_name == 'workflow_dispatch' 261 | 262 | steps: 263 | - name: Checkout code 264 | uses: actions/checkout@v3 265 | 266 | - name: Download all artifacts 267 | uses: actions/download-artifact@v4 268 | with: 269 | path: artifacts 270 | 271 | - name: Prepare download directory 272 | run: | 273 | # Use the Makefile to prepare the download directory structure 274 | make prepare-downloads 275 | 276 | - name: List artifacts 277 | run: | 278 | find artifacts -type f -name "*" | sort 279 | 280 | - name: Create GitHub Release 281 | if: startsWith(github.ref, 'refs/tags/v') 282 | uses: softprops/action-gh-release@v1 283 | with: 284 | files: | 285 | artifacts/**/* 286 | draft: false 287 | prerelease: false 288 | generate_release_notes: true 289 | 290 | - name: Deploy to GitHub Pages 291 | uses: JamesIves/github-pages-deploy-action@v4 292 | with: 293 | folder: web 294 | branch: gh-pages 295 | -------------------------------------------------------------------------------- /.github/workflows/install-triple-cd-pipeline.yml: -------------------------------------------------------------------------------- 1 | name: Install Triple CD Pipeline 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - main 8 | paths: 9 | - 'k8s/**' 10 | 11 | jobs: 12 | deploy-cd-pipeline: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout code 16 | uses: actions/checkout@v3 17 | 18 | - name: Set up kubectl 19 | uses: azure/setup-kubectl@v3 20 | 21 | - name: Set up Flux 22 | uses: fluxcd/flux2/action@main 23 | 24 | - name: Install FluxCD 25 | run: | 26 | flux bootstrap github \ 27 | --owner=spectrumwebco \ 28 | --repository=kled.io \ 29 | --path=k8s/flux \ 30 | --personal 31 | 32 | - name: Install ArgoCD 33 | run: | 34 | kubectl create namespace argocd --dry-run=client -o yaml | kubectl apply -f - 35 | kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml 36 | kubectl apply -f k8s/argo/argo-system.yaml 37 | 38 | - name: Install Vault 39 | run: | 40 | kubectl create namespace vault --dry-run=client -o yaml | kubectl apply -f - 41 | kubectl apply -f k8s/vault/vault.yaml 42 | 43 | - name: Setup Hydra 44 | run: | 45 | # Deploy Hydra using NixOS configuration 46 | # This would require a more complex setup, possibly using NixOps or similar 47 | echo "Hydra setup would be done here" 48 | -------------------------------------------------------------------------------- /.github/workflows/test-unified-cli.yml: -------------------------------------------------------------------------------- 1 | name: Test Unified CLI and Desktop App 2 | 3 | on: 4 | pull_request: 5 | branches: [ main, staging ] 6 | push: 7 | branches: [ main, staging ] 8 | 9 | jobs: 10 | test-cli: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - name: Checkout code 15 | uses: actions/checkout@v3 16 | 17 | - name: Set up Go 18 | uses: actions/setup-go@v3 19 | with: 20 | go-version: '1.24.1' 21 | 22 | - name: Install dependencies 23 | run: | 24 | cd cli/unified 25 | go mod download 26 | 27 | - name: Run CLI tests 28 | run: | 29 | cd cli/unified 30 | go test -v ./... 31 | cd ../pkg/api/unified 32 | go test -v ./... 33 | 34 | - name: Lint Go code 35 | uses: golangci/golangci-lint-action@v3 36 | with: 37 | version: latest 38 | working-directory: cli 39 | 40 | test-desktop: 41 | runs-on: ubuntu-latest 42 | 43 | steps: 44 | - name: Checkout code 45 | uses: actions/checkout@v3 46 | 47 | - name: Set up Node.js 48 | uses: actions/setup-node@v3 49 | with: 50 | node-version: '18' 51 | 52 | - name: Install dependencies 53 | run: | 54 | cd desktop 55 | yarn install 56 | 57 | - name: Run desktop tests 58 | run: | 59 | cd desktop 60 | yarn test 61 | 62 | - name: Lint TypeScript code 63 | run: | 64 | cd desktop 65 | yarn lint 66 | 67 | test-integration: 68 | runs-on: ubuntu-latest 69 | needs: [test-cli, test-desktop] 70 | 71 | steps: 72 | - name: Checkout code 73 | uses: actions/checkout@v3 74 | 75 | - name: Set up Go 76 | uses: actions/setup-go@v3 77 | with: 78 | go-version: '1.24.1' 79 | 80 | - name: Set up Node.js 81 | uses: actions/setup-node@v3 82 | with: 83 | node-version: '18' 84 | 85 | - name: Install dependencies 86 | run: | 87 | cd cli/unified 88 | go mod download 89 | cd ../../desktop 90 | yarn install 91 | 92 | - name: Build CLI 93 | run: | 94 | make cli 95 | 96 | - name: Test CLI binary detection 97 | run: | 98 | # Create symlinks for all CLI interfaces 99 | cp bin/kled bin/kcluster 100 | cp bin/kled bin/kledspace 101 | cp bin/kled bin/kpolicy 102 | 103 | # Test each CLI interface 104 | bin/kled --version 105 | bin/kcluster --version 106 | bin/kledspace --version 107 | bin/kpolicy --version 108 | 109 | - name: Test desktop app build 110 | run: | 111 | cd desktop 112 | yarn build 113 | -------------------------------------------------------------------------------- /.github/workflows/update-docs.yml: -------------------------------------------------------------------------------- 1 | name: Update Documentation 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | paths: 7 | - 'docs/**' 8 | workflow_dispatch: 9 | 10 | jobs: 11 | build: 12 | name: Build and Deploy Docs 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - name: Checkout code 17 | uses: actions/checkout@v3 18 | 19 | - name: Setup Node.js 20 | uses: actions/setup-node@v3 21 | with: 22 | node-version: '16' 23 | 24 | - name: Install dependencies 25 | run: | 26 | cd docs 27 | yarn install 28 | 29 | - name: Build documentation 30 | run: | 31 | cd docs 32 | yarn build 33 | 34 | - name: Deploy to GitHub Pages 35 | uses: peaceiris/actions-gh-pages@v3 36 | with: 37 | github_token: ${{ secrets.GITHUB_TOKEN }} 38 | publish_dir: ./docs/build 39 | destination_dir: docs 40 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Kled.io 2 | 3 | We love your input! We want to make contributing to Kled.io as easy and transparent as possible, whether it's: 4 | 5 | - Reporting a bug 6 | - Discussing the current state of the code 7 | - Submitting a fix 8 | - Proposing new features 9 | - Becoming a maintainer 10 | 11 | ## Development Process 12 | 13 | We use GitHub to host code, to track issues and feature requests, as well as accept pull requests. 14 | 15 | ### Pull Requests 16 | 17 | 1. Fork the repo and create your branch from `main`. 18 | 2. If you've added code that should be tested, add tests. 19 | 3. If you've changed APIs, update the documentation. 20 | 4. Ensure the test suite passes. 21 | 5. Make sure your code lints. 22 | 6. Issue that pull request! 23 | 24 | ### Any contributions you make will be under the MIT Software License 25 | 26 | When you submit code changes, your submissions are understood to be under the same [MIT License](http://choosealicense.com/licenses/mit/) that covers the project. Feel free to contact the maintainers if that's a concern. 27 | 28 | ## Report bugs using GitHub's [issue tracker] 29 | 30 | We use GitHub issues to track public bugs. Report a bug by [opening a new issue](https://github.com/spectrumwebco/kled.io/issues/new); it's that easy! 31 | 32 | ## License 33 | 34 | By contributing, you agree that your contributions will be licensed under the project's MIT License. 35 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Spectrum Web Co 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Kled.io Makefile for building all components 2 | 3 | .PHONY: all build cli desktop mobile web install clean prepare-downloads 4 | 5 | # Default target 6 | all: build 7 | 8 | # Build all components 9 | build: cli desktop mobile web 10 | 11 | # Build CLI tools 12 | cli: 13 | @echo "Building CLI tools..." 14 | @mkdir -p bin 15 | @cd cli/unified && go build -o ../../bin/kled-unified 16 | @cp bin/kled-unified bin/kled 17 | @cp bin/kled-unified bin/kcluster 18 | @cp bin/kled-unified bin/kledspace 19 | @cp bin/kled-unified bin/kpolicy 20 | @echo "CLI tools build complete!" 21 | 22 | # Build desktop app 23 | desktop: 24 | @echo "Building desktop app..." 25 | @cd desktop && yarn install && yarn build 26 | @cd desktop/src-tauri && cargo build --release 27 | @echo "Desktop app build complete!" 28 | 29 | # Build mobile apps 30 | mobile: 31 | @echo "Building mobile apps..." 32 | @cd mobile && yarn install || true 33 | @echo "Mobile apps build setup complete!" 34 | 35 | # Build web app 36 | web: 37 | @echo "Building web app..." 38 | @cd web && yarn install && yarn build || true 39 | @echo "Web app build complete!" 40 | 41 | # Cross-compile CLI for all platforms 42 | cross-compile: 43 | @echo "Cross-compiling for all platforms..." 44 | @mkdir -p bin 45 | # Linux AMD64 46 | @cd cli/unified && GOOS=linux GOARCH=amd64 go build -o ../../bin/kled-linux-amd64 47 | # Linux ARM64 48 | @cd cli/unified && GOOS=linux GOARCH=arm64 go build -o ../../bin/kled-linux-arm64 49 | # macOS AMD64 50 | @cd cli/unified && GOOS=darwin GOARCH=amd64 go build -o ../../bin/kled-darwin-amd64 51 | # macOS ARM64 52 | @cd cli/unified && GOOS=darwin GOARCH=arm64 go build -o ../../bin/kled-darwin-arm64 53 | # Windows AMD64 54 | @cd cli/unified && GOOS=windows GOARCH=amd64 go build -o ../../bin/kled-windows-amd64.exe 55 | 56 | # Create distribution packages with unified binary 57 | @mkdir -p dist/linux-amd64 dist/linux-arm64 dist/darwin-amd64 dist/darwin-arm64 dist/windows-amd64 58 | 59 | # Linux AMD64 60 | @cp bin/kled-linux-amd64 dist/linux-amd64/kled 61 | @chmod +x dist/linux-amd64/kled 62 | 63 | # Linux ARM64 64 | @cp bin/kled-linux-arm64 dist/linux-arm64/kled 65 | @chmod +x dist/linux-arm64/kled 66 | 67 | # macOS AMD64 68 | @cp bin/kled-darwin-amd64 dist/darwin-amd64/kled 69 | @chmod +x dist/darwin-amd64/kled 70 | 71 | # macOS ARM64 72 | @cp bin/kled-darwin-arm64 dist/darwin-arm64/kled 73 | @chmod +x dist/darwin-arm64/kled 74 | 75 | # Windows AMD64 76 | @cp bin/kled-windows-amd64.exe dist/windows-amd64/kled.exe 77 | 78 | @echo "Cross-compilation complete!" 79 | 80 | # Install CLI tools locally 81 | install: 82 | @echo "Installing CLI tools..." 83 | @mkdir -p $(HOME)/.kled/bin 84 | @cp bin/kled-unified $(HOME)/.kled/bin/ || cp bin/kled-linux-amd64 $(HOME)/.kled/bin/kled-unified 85 | @ln -sf $(HOME)/.kled/bin/kled-unified $(HOME)/.kled/bin/kled 86 | @ln -sf $(HOME)/.kled/bin/kled-unified $(HOME)/.kled/bin/kcluster 87 | @ln -sf $(HOME)/.kled/bin/kled-unified $(HOME)/.kled/bin/kledspace 88 | @ln -sf $(HOME)/.kled/bin/kled-unified $(HOME)/.kled/bin/kpolicy 89 | @echo "export PATH=\$$PATH:\$$HOME/.kled/bin" >> $(HOME)/.bashrc 90 | @echo "Installation complete! Please restart your shell or run 'source ~/.bashrc'" 91 | 92 | # Prepare downloads directory for GitHub Actions 93 | prepare-downloads: 94 | @echo "Preparing downloads directory..." 95 | @mkdir -p web/download/files/windows/x64 96 | @mkdir -p web/download/files/windows/x86 97 | @mkdir -p web/download/files/macos/arm64 98 | @mkdir -p web/download/files/macos/x64 99 | @mkdir -p web/download/files/linux/x64 100 | @mkdir -p web/download/files/linux/arm64 101 | 102 | # Copy CLI artifacts 103 | @cp artifacts/kled-cli-linux-amd64/* web/download/files/linux/x64/ || true 104 | @cp artifacts/kled-cli-linux-arm64/* web/download/files/linux/arm64/ || true 105 | @cp artifacts/kled-cli-macos-amd64/* web/download/files/macos/x64/ || true 106 | @cp artifacts/kled-cli-macos-arm64/* web/download/files/macos/arm64/ || true 107 | @cp artifacts/kled-cli-windows/* web/download/files/windows/x64/ || true 108 | 109 | # Copy desktop artifacts 110 | @cp artifacts/kled-desktop-linux/* web/download/files/linux/x64/ || true 111 | @cp artifacts/kled-desktop-macos/* web/download/files/macos/x64/ || true 112 | @cp artifacts/kled-desktop-windows/* web/download/files/windows/x64/ || true 113 | 114 | @echo "Download directory prepared!" 115 | 116 | # Clean build artifacts 117 | clean: 118 | @echo "Cleaning build artifacts..." 119 | @rm -rf bin/* 120 | @cd desktop && yarn clean || true 121 | @cd web && yarn clean || true 122 | @cd mobile && yarn clean || true 123 | @echo "Clean complete!" 124 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kled.io 2 | 3 | Kled.io is an open-source platform for managing Kubernetes workspaces, clusters, and policies. It provides a unified interface for developers and DevOps teams to manage their infrastructure. 4 | 5 | ## Components 6 | 7 | - **Desktop App**: Cross-platform desktop application for managing Kubernetes workspaces 8 | - **Web App**: Browser-based interface with the same functionality as the desktop app 9 | - **Mobile Apps**: iOS and Android applications for on-the-go management 10 | - **CLI Tools**: 11 | - `kled`: Main CLI tool for workspace management 12 | - `kcluster`: CLI tool for cluster management 13 | - `kledspace`: CLI tool for workspace management 14 | - `kpolicy`: CLI tool for policy management 15 | 16 | ## Getting Started 17 | 18 | ### Desktop App 19 | 20 | ```bash 21 | cd desktop 22 | yarn install 23 | yarn build 24 | cd src-tauri 25 | cargo build --release 26 | ``` 27 | 28 | ### CLI Tools 29 | 30 | ```bash 31 | cd cli/kled 32 | go build 33 | ``` 34 | 35 | ## Documentation 36 | 37 | For detailed documentation, visit [https://docs.kled.io](https://docs.kled.io) 38 | 39 | ## License 40 | 41 | This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details. 42 | -------------------------------------------------------------------------------- /cli/README.md: -------------------------------------------------------------------------------- 1 | 2 | This directory contains Test-Driven Development (TDD) versions of the Kled.io CLI tools. 3 | The actual implementation is maintained in private repositories. 4 | 5 | 6 | - `kled`: Main CLI tool for workspace management 7 | - `kcluster`: CLI tool for Kubernetes cluster management 8 | - `kledspace`: CLI tool for workspace environment management 9 | - `kpolicy`: CLI tool for policy management 10 | - `unified`: Single executable that functions as multiple CLI tools 11 | 12 | 13 | See the installation instructions in the main README.md file. 14 | -------------------------------------------------------------------------------- /cli/kcluster/README.md: -------------------------------------------------------------------------------- 1 | 2 | This is a placeholder for the kcluster CLI tool. The actual implementation is maintained in private repositories. 3 | -------------------------------------------------------------------------------- /cli/kcluster/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestCLIFunctionality(t *testing.T) { 8 | // This is a test-driven development placeholder 9 | // The actual implementation is maintained in private repositories 10 | } 11 | -------------------------------------------------------------------------------- /cli/kled/README.md: -------------------------------------------------------------------------------- 1 | 2 | This is a placeholder for the kled CLI tool. The actual implementation is maintained in private repositories. 3 | -------------------------------------------------------------------------------- /cli/kled/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestCLIFunctionality(t *testing.T) { 8 | // This is a test-driven development placeholder 9 | // The actual implementation is maintained in private repositories 10 | } 11 | -------------------------------------------------------------------------------- /cli/kledspace/README.md: -------------------------------------------------------------------------------- 1 | 2 | This is a placeholder for the kledspace CLI tool. The actual implementation is maintained in private repositories. 3 | -------------------------------------------------------------------------------- /cli/kledspace/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestCLIFunctionality(t *testing.T) { 8 | // This is a test-driven development placeholder 9 | // The actual implementation is maintained in private repositories 10 | } 11 | -------------------------------------------------------------------------------- /cli/kpolicy/README.md: -------------------------------------------------------------------------------- 1 | 2 | This is a placeholder for the kpolicy CLI tool. The actual implementation is maintained in private repositories. 3 | -------------------------------------------------------------------------------- /cli/kpolicy/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestCLIFunctionality(t *testing.T) { 8 | // This is a test-driven development placeholder 9 | // The actual implementation is maintained in private repositories 10 | } 11 | -------------------------------------------------------------------------------- /cli/pkg/api/unified/auth.go: -------------------------------------------------------------------------------- 1 | package unified 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | "strings" 7 | 8 | "github.com/spectrumwebco/kled.io/cli/pkg/api" 9 | ) 10 | 11 | var CommandSpecificEnvVars = map[string]string{ 12 | "kled": "KLED_API_KEY", 13 | "kcluster": "KCLUSTER_API_KEY", 14 | "kledspace": "KLEDSPACE_API_KEY", 15 | "kpolicy": "KPOLICY_API_KEY", 16 | } 17 | 18 | func GetAPIKey(commandName string) string { 19 | if envVar, exists := CommandSpecificEnvVars[commandName]; exists { 20 | if apiKey := os.Getenv(envVar); apiKey != "" { 21 | return apiKey 22 | } 23 | } 24 | 25 | if apiKey := os.Getenv("KLED_API_KEY"); apiKey != "" { 26 | return apiKey 27 | } 28 | 29 | auth, err := api.LoadAuth() 30 | if err == nil && auth.APIKey != "" { 31 | return auth.APIKey 32 | } 33 | 34 | return "" 35 | } 36 | 37 | func GetAPIBaseURL(commandName string) string { 38 | envVarName := strings.ToUpper(commandName) + "_API_BASE_URL" 39 | if apiBaseURL := os.Getenv(envVarName); apiBaseURL != "" { 40 | return apiBaseURL 41 | } 42 | 43 | if apiBaseURL := os.Getenv("KLED_API_BASE_URL"); apiBaseURL != "" { 44 | return apiBaseURL 45 | } 46 | 47 | auth, err := api.LoadAuth() 48 | if err == nil && auth.APIBaseURL != "" { 49 | return auth.APIBaseURL 50 | } 51 | 52 | return "" 53 | } 54 | 55 | func DetectCommandName() string { 56 | execPath := os.Args[0] 57 | execName := filepath.Base(execPath) 58 | 59 | execName = strings.TrimSuffix(execName, filepath.Ext(execName)) 60 | 61 | for cmd := range CommandSpecificEnvVars { 62 | if execName == cmd { 63 | return cmd 64 | } 65 | } 66 | 67 | return "kled" 68 | } 69 | -------------------------------------------------------------------------------- /cli/pkg/api/unified/client.go: -------------------------------------------------------------------------------- 1 | package unified 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "fmt" 7 | "io" 8 | "net/http" 9 | "time" 10 | ) 11 | 12 | type Client struct { 13 | apiKey string 14 | apiBaseURL string 15 | httpClient *http.Client 16 | command string 17 | } 18 | 19 | func NewClient(command string) *Client { 20 | return &Client{ 21 | apiKey: GetAPIKey(command), 22 | apiBaseURL: GetAPIBaseURL(command), 23 | httpClient: &http.Client{ 24 | Timeout: 30 * time.Second, 25 | }, 26 | command: command, 27 | } 28 | } 29 | 30 | func (c *Client) Request(method, path string, body interface{}, result interface{}) error { 31 | url := fmt.Sprintf("%s%s", c.apiBaseURL, path) 32 | 33 | var reqBody io.Reader 34 | if body != nil { 35 | jsonData, err := json.Marshal(body) 36 | if err != nil { 37 | return fmt.Errorf("failed to marshal request body: %w", err) 38 | } 39 | reqBody = bytes.NewBuffer(jsonData) 40 | } 41 | 42 | req, err := http.NewRequest(method, url, reqBody) 43 | if err != nil { 44 | return fmt.Errorf("failed to create request: %w", err) 45 | } 46 | 47 | req.Header.Set("Content-Type", "application/json") 48 | req.Header.Set("Accept", "application/json") 49 | if c.apiKey != "" { 50 | req.Header.Set("Authorization", "Bearer "+c.apiKey) 51 | } 52 | req.Header.Set("User-Agent", fmt.Sprintf("%s-cli/0.1.0", c.command)) 53 | 54 | resp, err := c.httpClient.Do(req) 55 | if err != nil { 56 | return fmt.Errorf("request failed: %w", err) 57 | } 58 | defer resp.Body.Close() 59 | 60 | respBody, err := io.ReadAll(resp.Body) 61 | if err != nil { 62 | return fmt.Errorf("failed to read response body: %w", err) 63 | } 64 | 65 | if resp.StatusCode >= 400 { 66 | var errResp struct { 67 | Error string `json:"error"` 68 | } 69 | if err := json.Unmarshal(respBody, &errResp); err == nil && errResp.Error != "" { 70 | return fmt.Errorf("API error: %s", errResp.Error) 71 | } 72 | return fmt.Errorf("API error: %s", resp.Status) 73 | } 74 | 75 | if result != nil && len(respBody) > 0 { 76 | if err := json.Unmarshal(respBody, result); err != nil { 77 | return fmt.Errorf("failed to unmarshal response: %w", err) 78 | } 79 | } 80 | 81 | return nil 82 | } 83 | 84 | func (c *Client) Get(path string, result interface{}) error { 85 | return c.Request(http.MethodGet, path, nil, result) 86 | } 87 | 88 | func (c *Client) Post(path string, body interface{}, result interface{}) error { 89 | return c.Request(http.MethodPost, path, body, result) 90 | } 91 | 92 | func (c *Client) Put(path string, body interface{}, result interface{}) error { 93 | return c.Request(http.MethodPut, path, body, result) 94 | } 95 | 96 | func (c *Client) Delete(path string, result interface{}) error { 97 | return c.Request(http.MethodDelete, path, nil, result) 98 | } 99 | -------------------------------------------------------------------------------- /cli/pkg/api/unified/tests/auth_test.go: -------------------------------------------------------------------------------- 1 | package unified_test 2 | 3 | import ( 4 | "os" 5 | "testing" 6 | 7 | "github.com/spectrumwebco/kled.io/cli/pkg/api/unified" 8 | ) 9 | 10 | func TestLoadAuth(t *testing.T) { 11 | originalAPIKey := os.Getenv("KLED_API_KEY") 12 | originalAPIBaseURL := os.Getenv("KLED_API_BASE_URL") 13 | 14 | defer func() { 15 | os.Setenv("KLED_API_KEY", originalAPIKey) 16 | os.Setenv("KLED_API_BASE_URL", originalAPIBaseURL) 17 | }() 18 | 19 | os.Setenv("KLED_API_KEY", "test-api-key") 20 | os.Setenv("KLED_API_BASE_URL", "https://api.test.com") 21 | 22 | auth, err := unified.LoadAuth() 23 | if err != nil { 24 | t.Errorf("Expected no error, got %v", err) 25 | } 26 | 27 | if auth.APIKey != "test-api-key" { 28 | t.Errorf("Expected APIKey to be 'test-api-key', got '%s'", auth.APIKey) 29 | } 30 | 31 | if auth.APIBaseURL != "https://api.test.com" { 32 | t.Errorf("Expected APIBaseURL to be 'https://api.test.com', got '%s'", auth.APIBaseURL) 33 | } 34 | 35 | os.Unsetenv("KLED_API_KEY") 36 | os.Unsetenv("KLED_API_BASE_URL") 37 | 38 | auth, err = unified.LoadAuth() 39 | if err == nil { 40 | t.Error("Expected error when no API key is set, got nil") 41 | } 42 | } 43 | 44 | func TestIsValidAuth(t *testing.T) { 45 | validAuth := unified.Auth{ 46 | APIKey: "valid-key", 47 | APIBaseURL: "https://api.valid.com", 48 | } 49 | 50 | if !validAuth.IsValid() { 51 | t.Error("Expected valid auth to return true, got false") 52 | } 53 | 54 | invalidAuth1 := unified.Auth{ 55 | APIKey: "", 56 | APIBaseURL: "https://api.valid.com", 57 | } 58 | 59 | if invalidAuth1.IsValid() { 60 | t.Error("Expected invalid auth (no API key) to return false, got true") 61 | } 62 | 63 | invalidAuth2 := unified.Auth{ 64 | APIKey: "valid-key", 65 | APIBaseURL: "", 66 | } 67 | 68 | if invalidAuth2.IsValid() { 69 | t.Error("Expected invalid auth (no API base URL) to return false, got true") 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /cli/pkg/api/unified/tests/client_test.go: -------------------------------------------------------------------------------- 1 | package unified_test 2 | 3 | import ( 4 | "net/http" 5 | "net/http/httptest" 6 | "testing" 7 | 8 | "github.com/spectrumwebco/kled.io/cli/pkg/api/unified" 9 | ) 10 | 11 | func TestNewClient(t *testing.T) { 12 | auth := unified.Auth{ 13 | APIKey: "test-key", 14 | APIBaseURL: "https://api.test.com", 15 | } 16 | 17 | client, err := unified.NewClient(auth) 18 | if err != nil { 19 | t.Errorf("Expected no error, got %v", err) 20 | } 21 | 22 | if client == nil { 23 | t.Error("Expected client to be non-nil") 24 | } 25 | 26 | invalidAuth := unified.Auth{ 27 | APIKey: "", 28 | APIBaseURL: "", 29 | } 30 | 31 | client, err = unified.NewClient(invalidAuth) 32 | if err == nil { 33 | t.Error("Expected error with invalid auth, got nil") 34 | } 35 | 36 | if client != nil { 37 | t.Error("Expected client to be nil with invalid auth") 38 | } 39 | } 40 | 41 | func TestMakeRequest(t *testing.T) { 42 | server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 43 | if r.Header.Get("X-API-Key") != "test-key" { 44 | t.Errorf("Expected X-API-Key header to be 'test-key', got '%s'", r.Header.Get("X-API-Key")) 45 | } 46 | 47 | w.WriteHeader(http.StatusOK) 48 | w.Write([]byte(`{"status":"success"}`)) 49 | })) 50 | defer server.Close() 51 | 52 | auth := unified.Auth{ 53 | APIKey: "test-key", 54 | APIBaseURL: server.URL, 55 | } 56 | 57 | client, err := unified.NewClient(auth) 58 | if err != nil { 59 | t.Fatalf("Failed to create client: %v", err) 60 | } 61 | 62 | resp, err := client.MakeRequest("GET", "/test", nil) 63 | if err != nil { 64 | t.Errorf("Expected no error, got %v", err) 65 | } 66 | 67 | if resp.StatusCode != http.StatusOK { 68 | t.Errorf("Expected status code %d, got %d", http.StatusOK, resp.StatusCode) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /cli/pkg/cmd/sonarqube/sonarqube.go: -------------------------------------------------------------------------------- 1 | package sonarqube 2 | 3 | import ( 4 | "fmt" 5 | "github.com/spf13/cobra" 6 | ) 7 | 8 | func NewSonarqubeCmd() *cobra.Command { 9 | cmd := &cobra.Command{ 10 | Use: "sonarqube", 11 | Short: "Manage SonarQube integrations", 12 | Long: "Manage SonarQube integrations for code quality analysis", 13 | Run: func(cmd *cobra.Command, args []string) { 14 | cmd.Help() 15 | }, 16 | } 17 | 18 | cmd.AddCommand(newAnalyzeCmd()) 19 | cmd.AddCommand(newReportCmd()) 20 | cmd.AddCommand(newConfigureCmd()) 21 | 22 | return cmd 23 | } 24 | 25 | func newAnalyzeCmd() *cobra.Command { 26 | return &cobra.Command{ 27 | Use: "analyze [project]", 28 | Short: "Analyze a project with SonarQube", 29 | Args: cobra.MinimumNArgs(1), 30 | Run: func(cmd *cobra.Command, args []string) { 31 | fmt.Printf("Analyzing project %s with SonarQube...\n", args[0]) 32 | }, 33 | } 34 | } 35 | 36 | func newReportCmd() *cobra.Command { 37 | return &cobra.Command{ 38 | Use: "report [project]", 39 | Short: "Get reports from SonarQube", 40 | Args: cobra.MinimumNArgs(1), 41 | Run: func(cmd *cobra.Command, args []string) { 42 | fmt.Printf("Getting SonarQube reports for project %s...\n", args[0]) 43 | }, 44 | } 45 | } 46 | 47 | func newConfigureCmd() *cobra.Command { 48 | return &cobra.Command{ 49 | Use: "configure", 50 | Short: "Configure SonarQube integration", 51 | Run: func(cmd *cobra.Command, args []string) { 52 | fmt.Println("Configuring SonarQube integration...") 53 | }, 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /cli/unified/README.md: -------------------------------------------------------------------------------- 1 | 2 | This is a placeholder for the unified CLI tool. The actual implementation is maintained in private repositories. 3 | -------------------------------------------------------------------------------- /cli/unified/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/spectrumwebco/kled.io/cli/unified 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/inconshreveable/mousetrap v1.1.0 // indirect 7 | github.com/spf13/cobra v1.9.1 // indirect 8 | github.com/spf13/pflag v1.0.6 // indirect 9 | ) 10 | -------------------------------------------------------------------------------- /cli/unified/go.sum: -------------------------------------------------------------------------------- 1 | github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= 2 | github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= 3 | github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= 4 | github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 5 | github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= 6 | github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= 7 | github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= 8 | github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 9 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 10 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 11 | -------------------------------------------------------------------------------- /cli/unified/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestCLIFunctionality(t *testing.T) { 8 | // This is a test-driven development placeholder 9 | // The actual implementation is maintained in private repositories 10 | } 11 | -------------------------------------------------------------------------------- /cli/unified/tests/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | "testing" 7 | ) 8 | 9 | func TestDetectCommandName(t *testing.T) { 10 | originalArgs := os.Args 11 | defer func() { os.Args = originalArgs }() 12 | 13 | os.Args = []string{"/usr/local/bin/kled", "arg1", "arg2"} 14 | cmdName := DetectCommandName() 15 | if cmdName != "kled" { 16 | t.Errorf("Expected command name 'kled', got '%s'", cmdName) 17 | } 18 | 19 | os.Args = []string{"/usr/local/bin/kcluster", "arg1", "arg2"} 20 | cmdName = DetectCommandName() 21 | if cmdName != "kcluster" { 22 | t.Errorf("Expected command name 'kcluster', got '%s'", cmdName) 23 | } 24 | 25 | os.Args = []string{"/usr/local/bin/kledspace", "arg1", "arg2"} 26 | cmdName = DetectCommandName() 27 | if cmdName != "kledspace" { 28 | t.Errorf("Expected command name 'kledspace', got '%s'", cmdName) 29 | } 30 | 31 | os.Args = []string{"/usr/local/bin/kpolicy", "arg1", "arg2"} 32 | cmdName = DetectCommandName() 33 | if cmdName != "kpolicy" { 34 | t.Errorf("Expected command name 'kpolicy', got '%s'", cmdName) 35 | } 36 | 37 | tempDir, err := os.MkdirTemp("", "kled-test") 38 | if err != nil { 39 | t.Fatalf("Failed to create temp directory: %v", err) 40 | } 41 | defer os.RemoveAll(tempDir) 42 | 43 | binaryPath := filepath.Join(tempDir, "kled-unified") 44 | if err := os.WriteFile(binaryPath, []byte("test binary"), 0755); err != nil { 45 | t.Fatalf("Failed to create test binary: %v", err) 46 | } 47 | 48 | symlinkPaths := []string{ 49 | filepath.Join(tempDir, "kled"), 50 | filepath.Join(tempDir, "kcluster"), 51 | filepath.Join(tempDir, "kledspace"), 52 | filepath.Join(tempDir, "kpolicy"), 53 | } 54 | 55 | for _, symlinkPath := range symlinkPaths { 56 | if err := os.Symlink(binaryPath, symlinkPath); err != nil { 57 | t.Fatalf("Failed to create symlink: %v", err) 58 | } 59 | } 60 | 61 | for _, cmdName := range []string{"kled", "kcluster", "kledspace", "kpolicy"} { 62 | symlinkPath := filepath.Join(tempDir, cmdName) 63 | os.Args = []string{symlinkPath, "arg1", "arg2"} 64 | 65 | detectedCmd := DetectCommandName() 66 | if detectedCmd != cmdName { 67 | t.Errorf("Expected command name '%s', got '%s'", cmdName, detectedCmd) 68 | } 69 | } 70 | } 71 | 72 | func TestGetCommandFromArgs(t *testing.T) { 73 | args := []string{"kled", "--flag", "value"} 74 | cmdName := GetCommandFromArgs(args) 75 | if cmdName != "" { 76 | t.Errorf("Expected empty command name, got '%s'", cmdName) 77 | } 78 | 79 | args = []string{"kled-unified", "kcluster", "create", "--name", "test"} 80 | cmdName = GetCommandFromArgs(args) 81 | if cmdName != "kcluster" { 82 | t.Errorf("Expected command name 'kcluster', got '%s'", cmdName) 83 | } 84 | 85 | args = []string{"kled-unified", "--flag", "value", "kledspace", "init"} 86 | cmdName = GetCommandFromArgs(args) 87 | if cmdName != "kledspace" { 88 | t.Errorf("Expected command name 'kledspace', got '%s'", cmdName) 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /desktop/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | browser: true, 5 | es2021: true, 6 | node: true, 7 | jest: true, 8 | }, 9 | extends: [ 10 | 'eslint:recommended', 11 | 'plugin:react/recommended', 12 | 'plugin:react-hooks/recommended', 13 | 'plugin:@typescript-eslint/recommended', 14 | ], 15 | parser: '@typescript-eslint/parser', 16 | parserOptions: { 17 | ecmaFeatures: { 18 | jsx: true, 19 | }, 20 | ecmaVersion: 'latest', 21 | sourceType: 'module', 22 | }, 23 | plugins: [ 24 | 'react', 25 | 'react-hooks', 26 | '@typescript-eslint', 27 | ], 28 | settings: { 29 | react: { 30 | version: 'detect', 31 | }, 32 | }, 33 | rules: { 34 | 'react/react-in-jsx-scope': 'off', 35 | '@typescript-eslint/no-unused-vars': ['warn', { 36 | argsIgnorePattern: '^_', 37 | varsIgnorePattern: '^_' 38 | }], 39 | 'no-console': 'warn', 40 | }, 41 | }; 42 | -------------------------------------------------------------------------------- /desktop/README.md: -------------------------------------------------------------------------------- 1 | 2 | This is a placeholder for the Kled.io desktop application. The actual implementation is maintained in private repositories. 3 | 4 | 5 | - Cross-platform desktop application (Windows, macOS, Linux) 6 | - Built with Tauri v2 7 | - Provides a unified interface for managing Kubernetes workspaces 8 | 9 | 10 | See the installation instructions in the main README.md file. 11 | -------------------------------------------------------------------------------- /desktop/assets/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spectrumwebco/autobots.ai/0509db4f322d0941126fdbc01a8dff4104d231e0/desktop/assets/icon.icns -------------------------------------------------------------------------------- /desktop/assets/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spectrumwebco/autobots.ai/0509db4f322d0941126fdbc01a8dff4104d231e0/desktop/assets/icon.ico -------------------------------------------------------------------------------- /desktop/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spectrumwebco/autobots.ai/0509db4f322d0941126fdbc01a8dff4104d231e0/desktop/assets/icon.png -------------------------------------------------------------------------------- /desktop/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'jsdom', 4 | setupFilesAfterEnv: ['/src/setupTests.ts'], 5 | moduleNameMapper: { 6 | '\\.(css|less|scss|sass)$': 'identity-obj-proxy', 7 | '^@/(.*)$': '/src/$1' 8 | }, 9 | testPathIgnorePatterns: ['/node_modules/', '/dist/'], 10 | collectCoverageFrom: [ 11 | 'src/**/*.{ts,tsx}', 12 | '!src/**/*.d.ts', 13 | '!src/main.tsx', 14 | '!src/vite-env.d.ts' 15 | ], 16 | transform: { 17 | '^.+\\.(ts|tsx)$': ['ts-jest', { 18 | tsconfig: 'tsconfig.json' 19 | }] 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /desktop/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kled-desktop", 3 | "version": "1.0.0", 4 | "main": "dist/main.js", 5 | "license": "MIT", 6 | "scripts": { 7 | "test": "jest", 8 | "test:watch": "jest --watch", 9 | "test:coverage": "jest --coverage", 10 | "build": "rsbuild build", 11 | "dev": "rsbuild dev", 12 | "lint": "eslint src --ext .ts,.tsx --max-warnings 0", 13 | "package": "electron-builder build --publish never", 14 | "package:win": "electron-builder build --win --publish never", 15 | "package:mac": "electron-builder build --mac --publish never", 16 | "package:linux": "electron-builder build --linux --publish never" 17 | }, 18 | "build": { 19 | "appId": "io.kled.desktop", 20 | "productName": "Kled Desktop", 21 | "files": [ 22 | "dist/**/*", 23 | "node_modules/**/*" 24 | ], 25 | "directories": { 26 | "output": "release" 27 | }, 28 | "win": { 29 | "target": [ 30 | "nsis" 31 | ], 32 | "icon": "assets/icon.ico" 33 | }, 34 | "mac": { 35 | "target": [ 36 | "dmg" 37 | ], 38 | "icon": "assets/icon.icns" 39 | }, 40 | "linux": { 41 | "target": [ 42 | "deb", 43 | "AppImage" 44 | ], 45 | "icon": "assets/icon.png" 46 | } 47 | }, 48 | "devDependencies": { 49 | "@emotion/react": "^11.14.0", 50 | "@emotion/styled": "^11.14.0", 51 | "@rsbuild/core": "^0.4.5", 52 | "@rsbuild/plugin-react": "^0.4.5", 53 | "@testing-library/dom": "^10.4.0", 54 | "@testing-library/jest-dom": "^6.6.3", 55 | "@testing-library/react": "^16.2.0", 56 | "@types/jest": "^29.5.14", 57 | "@types/react": "^19.0.12", 58 | "@types/react-dom": "^19.0.4", 59 | "@typescript-eslint/eslint-plugin": "^8.29.0", 60 | "@typescript-eslint/parser": "^8.29.0", 61 | "@vitejs/plugin-react": "^4.3.4", 62 | "electron": "^29.1.4", 63 | "electron-builder": "^24.13.3", 64 | "eslint": "^9.23.0", 65 | "eslint-plugin-react": "^7.37.4", 66 | "eslint-plugin-react-hooks": "^5.2.0", 67 | "identity-obj-proxy": "^3.0.0", 68 | "jest": "^29.7.0", 69 | "jest-environment-jsdom": "^29.7.0", 70 | "ts-jest": "^29.1.2", 71 | "typescript": "^5.8.2", 72 | "vite": "^6.2.4" 73 | }, 74 | "dependencies": { 75 | "@chakra-ui/react": "^2.8.2", 76 | "@tauri-apps/api": "^1.5.3", 77 | "electron-is-dev": "^2.0.0", 78 | "electron-log": "^5.1.1", 79 | "electron-updater": "^6.2.1", 80 | "framer-motion": "^11.0.8", 81 | "react": "^18.2.0", 82 | "react-dom": "^18.2.0" 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /desktop/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import { ChakraProvider, Box, Flex, Heading, Text, Button, VStack, HStack, useToast, Divider } from '@chakra-ui/react'; 3 | import { invoke } from '@tauri-apps/api/tauri'; 4 | import CLIInterfaceNav from './components/CLIInterfaceNav'; 5 | import UnifiedCommandPanel from './components/UnifiedCommandPanel'; 6 | import KledProWebAppEmbed from './components/KledProWebAppEmbed'; 7 | 8 | function App() { 9 | const [workspaces, setWorkspaces] = useState([]); 10 | const [newWorkspaceName, setNewWorkspaceName] = useState(''); 11 | const [currentCLIType, setCurrentCLIType] = useState<'kled' | 'kcluster' | 'kledspace' | 'kpolicy'>('kled'); 12 | const [showKledProApp, setShowKledProApp] = useState(false); 13 | const toast = useToast(); 14 | 15 | useEffect(() => { 16 | loadWorkspaces(); 17 | }, []); 18 | 19 | useEffect(() => { 20 | setShowKledProApp(currentCLIType === 'kcluster'); 21 | }, [currentCLIType]); 22 | 23 | const loadWorkspaces = async () => { 24 | try { 25 | const workspaceList = await invoke('get_workspaces'); 26 | setWorkspaces(workspaceList); 27 | } catch (error) { 28 | console.error('Failed to load workspaces:', error); 29 | toast({ 30 | title: 'Error', 31 | description: 'Failed to load workspaces', 32 | status: 'error', 33 | duration: 5000, 34 | isClosable: true, 35 | }); 36 | } 37 | }; 38 | 39 | const createWorkspace = async () => { 40 | if (!newWorkspaceName.trim()) { 41 | toast({ 42 | title: 'Error', 43 | description: 'Workspace name cannot be empty', 44 | status: 'error', 45 | duration: 5000, 46 | isClosable: true, 47 | }); 48 | return; 49 | } 50 | 51 | try { 52 | await invoke('create_workspace', { name: newWorkspaceName }); 53 | setNewWorkspaceName(''); 54 | loadWorkspaces(); 55 | toast({ 56 | title: 'Success', 57 | description: `Workspace "${newWorkspaceName}" created`, 58 | status: 'success', 59 | duration: 5000, 60 | isClosable: true, 61 | }); 62 | } catch (error) { 63 | console.error('Failed to create workspace:', error); 64 | toast({ 65 | title: 'Error', 66 | description: `Failed to create workspace: ${error}`, 67 | status: 'error', 68 | duration: 5000, 69 | isClosable: true, 70 | }); 71 | } 72 | }; 73 | 74 | const handleCLIInterfaceChange = (cliType: 'kled' | 'kcluster' | 'kledspace' | 'kpolicy') => { 75 | setCurrentCLIType(cliType); 76 | if (cliType === 'kled') { 77 | loadWorkspaces(); 78 | } 79 | }; 80 | 81 | return ( 82 | 83 | 84 | Kled Command Center 85 | 86 | {/* CLI Interface Navigation */} 87 | 88 | 89 | {/* Unified Command Panel - Shows for all CLI types */} 90 | 91 | 92 | 93 | 94 | {/* Conditional rendering based on selected CLI interface */} 95 | {currentCLIType === 'kled' && ( 96 | 97 | 98 | Workspaces 99 | 100 | {workspaces.length > 0 ? ( 101 | workspaces.map((workspace) => ( 102 | 109 | {workspace} 110 | 111 | )) 112 | ) : ( 113 | No workspaces found 114 | )} 115 | 116 | 117 | 118 | 119 | Create Workspace 120 | 121 | 122 | setNewWorkspaceName(e.target.value)} 126 | placeholder="Enter workspace name" 127 | style={{ 128 | width: '100%', 129 | padding: '8px', 130 | borderRadius: '4px', 131 | border: '1px solid #E2E8F0' 132 | }} 133 | /> 134 | 135 | 138 | 139 | 140 | 141 | )} 142 | 143 | {currentCLIType === 'kcluster' && ( 144 | 145 | Kubernetes Cluster Management 146 | Interface for managing Kubernetes clusters using kcluster commands 147 | 148 | kCluster Features 149 | • Create and manage Kubernetes clusters 150 | • Connect to existing clusters 151 | • Monitor cluster health and resources 152 | • Manage cluster access and permissions 153 | 154 | 155 | )} 156 | 157 | {/* KledPro Web App Embed - Only shown for kcluster interface */} 158 | 159 | 160 | {currentCLIType === 'kledspace' && ( 161 | 162 | Application Space Management 163 | Interface for managing application spaces using kledspace commands 164 | 165 | kledspace Features 166 | • Initialize application spaces with templates 167 | • Deploy applications to Kubernetes clusters 168 | • Manage application lifecycle and scaling 169 | • Configure application networking and storage 170 | 171 | 172 | )} 173 | 174 | {currentCLIType === 'kpolicy' && ( 175 | 176 | Kubernetes Policy Management 177 | Interface for managing Kubernetes policies using kpolicy commands 178 | 179 | kpolicy Features 180 | • Define policies using TypeScript 181 | • Validate policies against clusters 182 | • Apply policies to enforce security standards 183 | • Monitor policy compliance across clusters 184 | 185 | 186 | )} 187 | 188 | 189 | ); 190 | } 191 | 192 | export default App; 193 | -------------------------------------------------------------------------------- /desktop/src/client/command.ts: -------------------------------------------------------------------------------- 1 | interface EventEmitter { 2 | addListener(event: T, callback: (data: string) => void): void; 3 | removeListener(event: T, callback: (data: string) => void): void; 4 | } 5 | 6 | interface Child { 7 | kill(): Promise; 8 | pid?: number; 9 | } 10 | 11 | interface ChildProcess { 12 | stdout: EventEmitter<"data">; 13 | stderr: EventEmitter<"data">; 14 | on(event: string, callback: (arg: any) => void): void; 15 | code?: number; 16 | } 17 | 18 | interface ShellCommand { 19 | stdout: EventEmitter<"data">; 20 | stderr: EventEmitter<"data">; 21 | on(event: string, callback: (arg: any) => void): void; 22 | spawn(): Promise; 23 | execute(): Promise>; 24 | sidecar(binary: string, args: string[], options?: any): ShellCommand; 25 | create(command: string, args: string[], options?: any): ShellCommand; 26 | } 27 | 28 | const ShellCommand = { 29 | sidecar: (binary: string, args: string[], options?: any): ShellCommand => ({} as any), 30 | create: (command: string, args: string[], options?: any): ShellCommand => ({} as any) 31 | } 32 | import { debug, ErrorTypeCancelled, isError, Result, ResultError, Return, sleep } from "../lib" 33 | import { 34 | KLED_BINARY, 35 | KCLUSTER_BINARY, 36 | KLEDSPACE_BINARY, 37 | KPOLICY_BINARY, 38 | FLAG_OPTION, 39 | KLED_UI_ENV_VAR, 40 | API_KEY_ENV_VAR, 41 | API_BASE_URL_ENV_VAR 42 | } from "./constants" 43 | import { TStreamEvent } from "./types" 44 | import { TAURI_SERVER_URL } from "./tauriClient" 45 | 46 | export type TStreamEventListenerFn = (event: TStreamEvent) => void 47 | export type TEventListener = Parameters< 48 | EventEmitter["addListener"] 49 | >[1] 50 | type TStreamOptions = Readonly<{ 51 | ignoreStdoutError?: boolean 52 | ignoreStderrError?: boolean 53 | }> 54 | const defaultStreamOptions: TStreamOptions = { 55 | ignoreStdoutError: false, 56 | ignoreStderrError: false, 57 | } 58 | 59 | export type TCommand = { 60 | run(): Promise> 61 | stream(listener: TStreamEventListenerFn): Promise 62 | cancel(): Promise 63 | } 64 | 65 | export class Command implements TCommand> { 66 | private sidecarCommand: ShellCommand 67 | private childProcess?: Child 68 | private args: string[] 69 | private cancelled = false 70 | private cliType: 'kled' | 'kcluster' | 'kledspace' | 'kpolicy' 71 | 72 | public static ADDITIONAL_ENV_VARS: string = "" 73 | public static HTTP_PROXY: string = "" 74 | public static HTTPS_PROXY: string = "" 75 | public static NO_PROXY: string = "" 76 | 77 | constructor(args: string[], cliType: 'kled' | 'kcluster' | 'kledspace' | 'kpolicy' = 'kled') { 78 | debug("commands", `Creating ${cliType} command with args:`, args) 79 | this.cliType = cliType 80 | const extraEnvVars = Command.ADDITIONAL_ENV_VARS.split(",") 81 | .map((envVarStr) => envVarStr.split("=")) 82 | .reduce( 83 | (acc, pair) => { 84 | const [key, value] = pair 85 | if (key === undefined || value === undefined) { 86 | return acc 87 | } 88 | 89 | return { ...acc, [key]: value } 90 | }, 91 | {} as Record 92 | ) 93 | 94 | // set proxy related environment variables 95 | if (Command.HTTP_PROXY) { 96 | extraEnvVars["HTTP_PROXY"] = Command.HTTP_PROXY 97 | } 98 | if (Command.HTTPS_PROXY) { 99 | extraEnvVars["HTTPS_PROXY"] = Command.HTTPS_PROXY 100 | } 101 | if (Command.NO_PROXY) { 102 | extraEnvVars["NO_PROXY"] = Command.NO_PROXY 103 | } 104 | 105 | // allows the CLI to detect if commands have been invoked from the UI 106 | extraEnvVars[KLED_UI_ENV_VAR] = "true" 107 | 108 | try { 109 | const apiKey = typeof process !== 'undefined' && process.env && 110 | (process.env as unknown as Record)[API_KEY_ENV_VAR] 111 | if (apiKey) { 112 | extraEnvVars[API_KEY_ENV_VAR] = apiKey 113 | } 114 | 115 | const apiBaseUrl = typeof process !== 'undefined' && process.env && 116 | (process.env as unknown as Record)[API_BASE_URL_ENV_VAR] 117 | if (apiBaseUrl) { 118 | extraEnvVars[API_BASE_URL_ENV_VAR] = apiBaseUrl 119 | } 120 | } catch (e) { 121 | console.warn('Could not access environment variables:', e) 122 | } 123 | 124 | const cliTypeProperty = 'cliType' 125 | extraEnvVars[cliTypeProperty] = cliType 126 | 127 | let binaryPath = KLED_BINARY 128 | if (cliType === 'kcluster') { 129 | binaryPath = KCLUSTER_BINARY 130 | } else if (cliType === 'kledspace') { 131 | binaryPath = KLEDSPACE_BINARY 132 | } else if (cliType === 'kpolicy') { 133 | binaryPath = KPOLICY_BINARY 134 | } 135 | 136 | const isFlatpak = typeof window !== 'undefined' && 137 | window.hasOwnProperty('__TAURI__') && 138 | (window as any).__TAURI__?.env?.TAURI_IS_FLATPAK === "true"; 139 | 140 | if (isFlatpak) { 141 | this.sidecarCommand = ShellCommand.create("run-path-kled-wrapper", args, { 142 | env: { ...extraEnvVars, ["FLATPAK_ID"]: "sh.spectrumwebco.kled" }, 143 | }) 144 | } else { 145 | this.sidecarCommand = ShellCommand.sidecar(binaryPath, args, { env: extraEnvVars }) 146 | } 147 | this.args = args 148 | } 149 | 150 | public async run(): Promise>> { 151 | try { 152 | const rawResult = await this.sidecarCommand.execute() 153 | debug("commands", `Result for command with args ${this.args}:`, rawResult) 154 | 155 | return Return.Value(rawResult) 156 | } catch (e) { 157 | return Return.Failed(e + "") 158 | } 159 | } 160 | 161 | public async stream( 162 | listener: TStreamEventListenerFn, 163 | streamOptions?: TStreamOptions 164 | ): Promise { 165 | let opts = defaultStreamOptions 166 | if (streamOptions) { 167 | opts = { ...defaultStreamOptions, ...streamOptions } 168 | } 169 | 170 | try { 171 | this.childProcess = await this.sidecarCommand.spawn() 172 | if (this.cancelled) { 173 | await this.childProcess.kill() 174 | 175 | return Return.Failed("Command already cancelled", "", ErrorTypeCancelled) 176 | } 177 | 178 | await new Promise((res, rej) => { 179 | const stdoutListener: TEventListener<"data"> = (message: string) => { 180 | try { 181 | const data = JSON.parse(message) 182 | 183 | // special case: the cli sends us a message where "done" is "true" 184 | // to signal the command is terminated and we should stop listen to it 185 | // This happens for the vscode browser command as it needs to stay open 186 | // for port-forwarding, but we don't care anymore about its output. 187 | if (data?.done === "true") { 188 | res(Return.Ok()) 189 | } else { 190 | listener({ type: "data", data }) 191 | } 192 | } catch (error) { 193 | if (!opts.ignoreStdoutError) { 194 | console.error("Failed to parse stdout message ", message, error) 195 | } 196 | } 197 | } 198 | const stderrListener: TEventListener<"data"> = (message: string) => { 199 | try { 200 | const error = JSON.parse(message) 201 | listener({ type: "error", error }) 202 | } catch (error) { 203 | if (!opts.ignoreStderrError) { 204 | console.error("Failed to parse stderr message ", message, error) 205 | } 206 | } 207 | } 208 | 209 | this.sidecarCommand.stderr.addListener("data", stderrListener) 210 | this.sidecarCommand.stdout.addListener("data", stdoutListener) 211 | 212 | const cleanup = () => { 213 | this.sidecarCommand.stderr.removeListener("data", stderrListener) 214 | this.sidecarCommand.stdout.removeListener("data", stdoutListener) 215 | this.childProcess = undefined 216 | } 217 | 218 | this.sidecarCommand.on("close", ({ code }: { code: number }) => { 219 | cleanup() 220 | if (code !== 0) { 221 | rej(new Error("exit code: " + code)) 222 | } else { 223 | res(Return.Ok()) 224 | } 225 | }) 226 | 227 | this.sidecarCommand.on("error", (arg: Error) => { 228 | cleanup() 229 | rej(arg) 230 | }) 231 | }) 232 | 233 | return Return.Ok() 234 | } catch (e) { 235 | if (isError(e)) { 236 | if (this.cancelled) { 237 | return Return.Failed(e.message, "", ErrorTypeCancelled) 238 | } 239 | 240 | return Return.Failed(e.message) 241 | } 242 | console.error(e) 243 | 244 | return Return.Failed("streaming failed") 245 | } 246 | } 247 | 248 | /** 249 | * Cancel the command. 250 | * Only works if it has been created with the `stream` method. 251 | */ 252 | public async cancel(): Promise> { 253 | try { 254 | this.cancelled = true 255 | if (!this.childProcess) { 256 | // nothing to clean up 257 | return Return.Ok() 258 | } 259 | // Try to send signal first before force killing process 260 | await fetch(TAURI_SERVER_URL + "/child-process/signal", { 261 | method: "POST", 262 | headers: { 263 | "content-type": "application/json", 264 | }, 265 | body: JSON.stringify({ 266 | processId: this.childProcess.pid, 267 | signal: 2, // SIGINT 268 | }), 269 | }) 270 | 271 | await sleep(3_000) 272 | // the actual child process could be gone after sending a SIGINT 273 | // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition 274 | if (this.childProcess) { 275 | await this.childProcess.kill() 276 | } 277 | 278 | return Return.Ok() 279 | } catch (e) { 280 | if (isError(e)) { 281 | return Return.Failed(e.message) 282 | } 283 | 284 | return Return.Failed("failed to cancel command") 285 | } 286 | } 287 | } 288 | 289 | export function isOk(result: ChildProcess): boolean { 290 | return result.code === 0 291 | } 292 | 293 | export function toFlagArg(flag: string, arg: string) { 294 | return [flag, arg].join("=") 295 | } 296 | 297 | export function serializeRawOptions( 298 | rawOptions: Record, 299 | flag: string = FLAG_OPTION 300 | ): string[] { 301 | return Object.entries(rawOptions).map(([key, value]) => flag + `=${key}=${value}`) 302 | } 303 | -------------------------------------------------------------------------------- /desktop/src/client/constants.ts: -------------------------------------------------------------------------------- 1 | export const KLED_GIT_REPOSITORY = "https://github.com/spectrumwebco/kled.io" 2 | 3 | export const DEFAULT_STATIC_COMMAND_CONFIG = { 4 | streamResponse: false, 5 | debug: false, 6 | } as const 7 | /** placeholder for arbitrary additional flags */ 8 | export const WORKSPACE_COMMAND_ADDITIONAL_FLAGS_KEY = "additionalFlags" 9 | 10 | export const KLED_BINARY = "bin/kled" 11 | export const KCLUSTER_BINARY = "bin/kcluster" 12 | export const KLEDSPACE_BINARY = "bin/kledspace" 13 | export const KPOLICY_BINARY = "bin/kpolicy" 14 | 15 | export const COMMAND_LIST = "list" 16 | export const COMMAND_STATUS = "status" 17 | export const COMMAND_UP = "up" 18 | export const COMMAND_STOP = "stop" 19 | export const COMMAND_BUILD = "build" 20 | export const COMMAND_DELETE = "delete" 21 | export const COMMAND_OPTIONS = "options" 22 | export const COMMAND_SET_OPTIONS = "set-options" 23 | export const COMMAND_USE = "use" 24 | export const COMMAND_ADD = "add" 25 | export const COMMAND_UPDATE = "update" 26 | export const COMMAND_LOGIN = "login" 27 | 28 | export const KLED_COMMAND_PROVIDER = "provider" 29 | export const KLED_COMMAND_IDE = "ide" 30 | export const KLED_COMMAND_PRO = "pro" 31 | export const KLED_COMMAND_HELPER = "helper" 32 | export const KLED_COMMAND_CONTEXT = "context" 33 | export const KLED_COMMAND_IMPORT_WORKSPACE = "import-workspace" 34 | export const KLED_COMMAND_GET_WORKSPACE_NAME = "get-workspace-name" 35 | export const KLED_COMMAND_GET_WORKSPACE_UID = "get-workspace-uid" 36 | export const KLED_COMMAND_GET_WORKSPACE_CONFIG = "get-workspace-config" 37 | export const KLED_COMMAND_GET_PROVIDER_NAME = "get-provider-name" 38 | export const KLED_COMMAND_GET_PRO_NAME = "get-pro-name" 39 | export const KLED_COMMAND_CHECK_PROVIDER_UPDATE = "check-provider-update" 40 | export const KLED_COMMAND_TROUBLESHOOT = "troubleshoot" 41 | 42 | export const KCLUSTER_COMMAND_CREATE = "create" 43 | export const KCLUSTER_COMMAND_CONNECT = "connect" 44 | export const KCLUSTER_COMMAND_DISCONNECT = "disconnect" 45 | 46 | export const KLEDSPACE_COMMAND_INIT = "init" 47 | export const KLEDSPACE_COMMAND_DEPLOY = "deploy" 48 | export const KLEDSPACE_COMMAND_PURGE = "purge" 49 | 50 | export const KPOLICY_COMMAND_VALIDATE = "validate" 51 | export const KPOLICY_COMMAND_APPLY = "apply" 52 | export const KPOLICY_COMMAND_REMOVE = "remove" 53 | export const FLAG_JSON_LOG_OUTPUT = "--log-output=json" 54 | export const FLAG_JSON_OUTPUT = "--output=json" 55 | export const FLAG_OPTION = "--option" 56 | export const FLAG_FORCE = "--force" 57 | export const FLAG_DEBUG = "--debug" 58 | export const FLAG_NAME = "--name" 59 | export const FLAG_ID = "--id" 60 | export const FLAG_SOURCE = "--source" 61 | export const FLAG_DRY = "--dry" 62 | export const FLAG_TIMEOUT = "--timeout" 63 | export const FLAG_LOGIN = "--login" 64 | export const FLAG_HOST = "--host" 65 | export const FLAG_PROJECT = "--project" 66 | 67 | export const KLED_FLAG_FORCE_BUILD = "--force-build" 68 | export const KLED_FLAG_RECREATE = "--recreate" 69 | export const KLED_FLAG_RESET = "--reset" 70 | export const KLED_FLAG_IDE = "--ide" 71 | export const KLED_FLAG_PROVIDER = "--provider" 72 | export const KLED_FLAG_PROVIDER_OPTION = "--provider-option" 73 | export const KLED_FLAG_ACCESS_KEY = "--access-key" 74 | export const KLED_FLAG_PREBUILD_REPOSITORY = "--prebuild-repository" 75 | export const KLED_FLAG_USE = "--use" 76 | export const KLED_FLAG_SINGLE_MACHINE = "--single-machine" 77 | export const KLED_FLAG_RECONFIGURE = "--reconfigure" 78 | export const KLED_FLAG_SKIP_REQUIRED = "--skip-required" 79 | export const KLED_FLAG_DEVCONTAINER_PATH = "--devcontainer-path" 80 | export const KLED_FLAG_WORKSPACE_ID = "--workspace-id" 81 | export const KLED_FLAG_WORKSPACE_UID = "--workspace-uid" 82 | export const KLED_FLAG_WORKSPACE_PROJECT = "--workspace-project" 83 | export const KLED_FLAG_INSTANCE = "--instance" 84 | export const KLED_FLAG_SKIP_PRO = "--skip-pro" 85 | export const KLED_FLAG_DOTFILES = "--dotfiles" 86 | export const KLED_FLAG_GIT_SIGNING_KEY = "--git-ssh-signing-key" 87 | export const KLED_FLAG_FORCE_BROWSER = "--force-browser" 88 | 89 | export const KCLUSTER_FLAG_NAMESPACE = "--namespace" 90 | export const KCLUSTER_FLAG_CONTEXT = "--context" 91 | export const KCLUSTER_FLAG_KUBECONFIG = "--kubeconfig" 92 | 93 | export const KLEDSPACE_FLAG_ENV = "--env" 94 | export const KLEDSPACE_FLAG_VALUES = "--values" 95 | export const KLEDSPACE_FLAG_SET = "--set" 96 | 97 | export const KPOLICY_FLAG_POLICY = "--policy" 98 | export const KPOLICY_FLAG_NAMESPACE = "--namespace" 99 | export const KPOLICY_FLAG_ALL_NAMESPACES = "--all-namespaces" 100 | 101 | export const KLED_UI_ENV_VAR = "KLED_UI" 102 | export const API_KEY_ENV_VAR = "KLED_API_KEY" 103 | export const API_BASE_URL_ENV_VAR = "KLED_API_BASE_URL" 104 | -------------------------------------------------------------------------------- /desktop/src/components/CLIInterfaceNav.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Tabs, TabList, Tab, TabPanels, TabPanel, Box, Heading } from '@chakra-ui/react'; 3 | import { Command } from '../client/command'; 4 | 5 | interface CLIInterfaceNavProps { 6 | onInterfaceChange?: (cliType: 'kled' | 'kcluster' | 'kledspace' | 'kpolicy') => void; 7 | } 8 | 9 | /** 10 | * Navigation component for switching between different CLI interfaces 11 | * Supports all 4 CLI interfaces: kled, kcluster, kledspace, kpolicy 12 | */ 13 | export const CLIInterfaceNav: React.FC = ({ onInterfaceChange }) => { 14 | const handleTabChange = (index: number) => { 15 | const cliTypes: Array<'kled' | 'kcluster' | 'kledspace' | 'kpolicy'> = [ 16 | 'kled', 'kcluster', 'kledspace', 'kpolicy' 17 | ]; 18 | 19 | if (onInterfaceChange && index >= 0 && index < cliTypes.length) { 20 | onInterfaceChange(cliTypes[index]); 21 | } 22 | }; 23 | 24 | return ( 25 | 26 | CLI Interfaces 27 | 28 | 29 | Kled 30 | Cluster 31 | Space 32 | Policy 33 | 34 | 35 | 36 | 37 | Kled Workspace Management 38 |

Create and manage development workspaces

39 |
40 |
41 | 42 | 43 | Kubernetes Cluster Management 44 |

Create, connect, and manage Kubernetes clusters

45 |
46 |
47 | 48 | 49 | Kled Space Management 50 |

Initialize, deploy, and manage application spaces

51 |
52 |
53 | 54 | 55 | Kubernetes Policy Management 56 |

Validate, apply, and manage Kubernetes policies

57 |
58 |
59 |
60 |
61 |
62 | ); 63 | }; 64 | 65 | export default CLIInterfaceNav; 66 | -------------------------------------------------------------------------------- /desktop/src/components/KledProWebAppEmbed.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Box, Heading, Text } from '@chakra-ui/react'; 3 | import { App as KledProApp } from '../../../../kled-pro/frontend/src/App'; 4 | 5 | interface KledProWebAppEmbedProps { 6 | isVisible: boolean; 7 | } 8 | 9 | /** 10 | * Component that embeds the kled-pro web app into the desktop application 11 | * This allows sharing UI components between web and desktop platforms 12 | */ 13 | export const KledProWebAppEmbed: React.FC = ({ isVisible }) => { 14 | if (!isVisible) return null; 15 | 16 | return ( 17 | 18 | kCluster Management 19 | Integrated kCluster management interface from kled-pro web app 20 | 21 | {/* Embed the kled-pro App component */} 22 | 23 | 24 | 25 | 26 | ); 27 | }; 28 | 29 | export default KledProWebAppEmbed; 30 | -------------------------------------------------------------------------------- /desktop/src/components/UnifiedCommandPanel.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { Box, Heading, Tabs, TabList, Tab, TabPanels, TabPanel } from '@chakra-ui/react'; 3 | import { 4 | SharedCommandInterface, 5 | getKledCommands, 6 | getKclusterCommands, 7 | getKledspaceCommands, 8 | getKpolicyCommands 9 | } from './shared/SharedCommandInterface'; 10 | import { invoke } from '@tauri-apps/api/tauri'; 11 | 12 | interface UnifiedCommandPanelProps { 13 | currentCLIType: 'kled' | 'kcluster' | 'kledspace' | 'kpolicy'; 14 | } 15 | 16 | /** 17 | * Unified command panel component that displays commands for all CLI interfaces 18 | * This component uses the shared command interface to provide a consistent UI 19 | * across desktop and web applications 20 | */ 21 | export const UnifiedCommandPanel: React.FC = ({ 22 | currentCLIType 23 | }) => { 24 | const [commandOutput, setCommandOutput] = useState(''); 25 | const [isExecuting, setIsExecuting] = useState(false); 26 | 27 | const executeCommand = async (commandName: string) => { 28 | setIsExecuting(true); 29 | setCommandOutput(`Executing: ${commandName}...`); 30 | 31 | try { 32 | const result = await invoke('execute_cli_command', { command: commandName }); 33 | setCommandOutput(result as string); 34 | } catch (error) { 35 | setCommandOutput(`Error executing command: ${error}`); 36 | } finally { 37 | setIsExecuting(false); 38 | } 39 | }; 40 | 41 | const getCommandsForType = () => { 42 | switch (currentCLIType) { 43 | case 'kled': 44 | return getKledCommands(); 45 | case 'kcluster': 46 | return getKclusterCommands(); 47 | case 'kledspace': 48 | return getKledspaceCommands(); 49 | case 'kpolicy': 50 | return getKpolicyCommands(); 51 | default: 52 | return getKledCommands(); 53 | } 54 | }; 55 | 56 | const getTitleForType = () => { 57 | switch (currentCLIType) { 58 | case 'kled': 59 | return 'Kled Workspace Commands'; 60 | case 'kcluster': 61 | return 'Kubernetes Cluster Commands'; 62 | case 'kledspace': 63 | return 'Application Space Commands'; 64 | case 'kpolicy': 65 | return 'Kubernetes Policy Commands'; 66 | default: 67 | return 'CLI Commands'; 68 | } 69 | }; 70 | 71 | return ( 72 | 73 | 78 | 79 | {/* Command output display */} 80 | 81 | Command Output 82 | 92 | {commandOutput || 'No command executed yet. Select a command above to execute it.'} 93 | 94 | 95 | 96 | ); 97 | }; 98 | 99 | export default UnifiedCommandPanel; 100 | -------------------------------------------------------------------------------- /desktop/src/components/__tests__/CLIInterfaceNav.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, screen, fireEvent } from '@testing-library/react'; 3 | import { CLIInterfaceNav } from '../CLIInterfaceNav'; 4 | 5 | describe('CLIInterfaceNav Component', () => { 6 | test('renders all CLI interface tabs', () => { 7 | render(); 8 | 9 | expect(screen.getByText('Kled')).toBeInTheDocument(); 10 | expect(screen.getByText('Cluster')).toBeInTheDocument(); 11 | expect(screen.getByText('Space')).toBeInTheDocument(); 12 | expect(screen.getByText('Policy')).toBeInTheDocument(); 13 | }); 14 | 15 | test('calls onInterfaceChange when tab is clicked', () => { 16 | const mockOnInterfaceChange = jest.fn(); 17 | render(); 18 | 19 | fireEvent.click(screen.getByText('Cluster')); 20 | 21 | expect(mockOnInterfaceChange).toHaveBeenCalledWith('kcluster'); 22 | 23 | fireEvent.click(screen.getByText('Space')); 24 | 25 | expect(mockOnInterfaceChange).toHaveBeenCalledWith('kledspace'); 26 | 27 | fireEvent.click(screen.getByText('Policy')); 28 | 29 | expect(mockOnInterfaceChange).toHaveBeenCalledWith('kpolicy'); 30 | 31 | fireEvent.click(screen.getByText('Kled')); 32 | 33 | expect(mockOnInterfaceChange).toHaveBeenCalledWith('kled'); 34 | }); 35 | 36 | test('displays correct descriptions for each tab', () => { 37 | render(); 38 | 39 | fireEvent.click(screen.getByText('Kled')); 40 | expect(screen.getByText('Create and manage development workspaces')).toBeInTheDocument(); 41 | 42 | fireEvent.click(screen.getByText('Cluster')); 43 | expect(screen.getByText('Create, connect, and manage Kubernetes clusters')).toBeInTheDocument(); 44 | 45 | fireEvent.click(screen.getByText('Space')); 46 | expect(screen.getByText('Initialize, deploy, and manage application spaces')).toBeInTheDocument(); 47 | 48 | fireEvent.click(screen.getByText('Policy')); 49 | expect(screen.getByText('Validate, apply, and manage Kubernetes policies')).toBeInTheDocument(); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /desktop/src/components/__tests__/KledProWebAppEmbed.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | 4 | jest.mock('../KledProWebAppEmbed', () => ({ 5 | KledProWebAppEmbed: ({ isVisible }: { isVisible: boolean }) => 6 | isVisible ? ( 7 |
8 |

kCluster Management

9 |

Integrated kCluster management interface from kled-pro web app

10 |
11 |
Mocked KledProApp
12 |
13 |
14 | ) : null 15 | })); 16 | 17 | import { KledProWebAppEmbed } from '../KledProWebAppEmbed'; 18 | 19 | describe('KledProWebAppEmbed Component', () => { 20 | test('renders nothing when isVisible is false', () => { 21 | const { container } = render(); 22 | expect(container.firstChild).toBeNull(); 23 | }); 24 | 25 | test('renders component when isVisible is true', () => { 26 | render(); 27 | 28 | expect(screen.getByText('kCluster Management')).toBeInTheDocument(); 29 | 30 | expect(screen.getByText('Integrated kCluster management interface from kled-pro web app')).toBeInTheDocument(); 31 | 32 | expect(screen.getByTestId('kled-pro-app')).toBeInTheDocument(); 33 | }); 34 | 35 | test('has correct structure and CSS classes', () => { 36 | render(); 37 | 38 | const mainContainer = screen.getByText('kCluster Management').closest('.kled-pro-embed'); 39 | expect(mainContainer).toBeInTheDocument(); 40 | 41 | const appContainer = screen.getByTestId('kled-pro-app').closest('.kled-pro-app-container'); 42 | expect(appContainer).toBeInTheDocument(); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /desktop/src/components/shared/SharedCommandInterface.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Box, Heading, Text, Flex, Icon, Button } from '@chakra-ui/react'; 3 | import { FaTerminal, FaCubes, FaLayerGroup, FaShieldAlt } from 'react-icons/fa'; 4 | 5 | interface CommandProps { 6 | name: string; 7 | description: string; 8 | icon: React.ElementType; 9 | onClick?: () => void; 10 | } 11 | 12 | interface SharedCommandInterfaceProps { 13 | title: string; 14 | commands: CommandProps[]; 15 | onCommandSelect?: (commandName: string) => void; 16 | } 17 | 18 | /** 19 | * Shared component for displaying command interfaces across desktop and web apps 20 | * This component can be used in both the desktop app and web app to provide 21 | * a consistent interface for interacting with CLI commands 22 | */ 23 | export const SharedCommandInterface: React.FC = ({ 24 | title, 25 | commands, 26 | onCommandSelect 27 | }) => { 28 | const handleCommandClick = (commandName: string) => { 29 | if (onCommandSelect) { 30 | onCommandSelect(commandName); 31 | } 32 | }; 33 | 34 | return ( 35 | 36 | {title} 37 | 38 | 39 | {commands.map((command) => ( 40 | { 47 | handleCommandClick(command.name); 48 | if (command.onClick) command.onClick(); 49 | }} 50 | > 51 | 52 | 53 | 54 | {command.name} 55 | {command.description} 56 | 57 | 58 | 59 | ))} 60 | 61 | 62 | ); 63 | }; 64 | 65 | /** 66 | * Predefined command sets for each CLI interface 67 | * These can be imported and used in both desktop and web apps 68 | */ 69 | export const getKledCommands = (): CommandProps[] => [ 70 | { 71 | name: 'kled workspace create', 72 | description: 'Create a new development workspace', 73 | icon: FaTerminal 74 | }, 75 | { 76 | name: 'kled workspace list', 77 | description: 'List all available workspaces', 78 | icon: FaTerminal 79 | }, 80 | { 81 | name: 'kled workspace delete', 82 | description: 'Delete an existing workspace', 83 | icon: FaTerminal 84 | } 85 | ]; 86 | 87 | export const getKclusterCommands = (): CommandProps[] => [ 88 | { 89 | name: 'kcluster create', 90 | description: 'Create a new Kubernetes cluster', 91 | icon: FaCubes 92 | }, 93 | { 94 | name: 'kcluster connect', 95 | description: 'Connect to an existing cluster', 96 | icon: FaCubes 97 | }, 98 | { 99 | name: 'kcluster list', 100 | description: 'List all available clusters', 101 | icon: FaCubes 102 | } 103 | ]; 104 | 105 | export const getKledspaceCommands = (): CommandProps[] => [ 106 | { 107 | name: 'kledspace init', 108 | description: 'Initialize a new application space', 109 | icon: FaLayerGroup 110 | }, 111 | { 112 | name: 'kledspace deploy', 113 | description: 'Deploy an application to a space', 114 | icon: FaLayerGroup 115 | }, 116 | { 117 | name: 'kledspace list', 118 | description: 'List all available spaces', 119 | icon: FaLayerGroup 120 | } 121 | ]; 122 | 123 | export const getKpolicyCommands = (): CommandProps[] => [ 124 | { 125 | name: 'kpolicy validate', 126 | description: 'Validate policies against a cluster', 127 | icon: FaShieldAlt 128 | }, 129 | { 130 | name: 'kpolicy apply', 131 | description: 'Apply policies to a cluster', 132 | icon: FaShieldAlt 133 | }, 134 | { 135 | name: 'kpolicy list', 136 | description: 'List all available policies', 137 | icon: FaShieldAlt 138 | } 139 | ]; 140 | 141 | export default SharedCommandInterface; 142 | -------------------------------------------------------------------------------- /desktop/src/main.js: -------------------------------------------------------------------------------- 1 | const { app, BrowserWindow } = require('electron'); 2 | const path = require('path'); 3 | const isDev = require('electron-is-dev'); 4 | const log = require('electron-log'); 5 | const { autoUpdater } = require('electron-updater'); 6 | 7 | log.transports.file.level = 'info'; 8 | autoUpdater.logger = log; 9 | autoUpdater.logger.transports.file.level = 'info'; 10 | 11 | let mainWindow; 12 | 13 | function createWindow() { 14 | mainWindow = new BrowserWindow({ 15 | width: 1200, 16 | height: 800, 17 | webPreferences: { 18 | nodeIntegration: true, 19 | contextIsolation: false, 20 | preload: path.join(__dirname, 'preload.js') 21 | }, 22 | icon: path.join(__dirname, '../assets/icon.png') 23 | }); 24 | 25 | const startUrl = isDev 26 | ? 'http://localhost:8080' // Dev server URL 27 | : `file://${path.join(__dirname, '../dist/index.html')}`; // Production build 28 | 29 | mainWindow.loadURL(startUrl); 30 | 31 | if (isDev) { 32 | mainWindow.webContents.openDevTools(); 33 | } 34 | 35 | mainWindow.on('closed', () => { 36 | mainWindow = null; 37 | }); 38 | } 39 | 40 | app.whenReady().then(() => { 41 | createWindow(); 42 | 43 | app.on('activate', () => { 44 | if (BrowserWindow.getAllWindows().length === 0) { 45 | createWindow(); 46 | } 47 | }); 48 | }); 49 | 50 | app.on('window-all-closed', () => { 51 | if (process.platform !== 'darwin') { 52 | app.quit(); 53 | } 54 | }); 55 | 56 | app.on('ready', () => { 57 | if (!isDev) { 58 | autoUpdater.checkForUpdatesAndNotify(); 59 | } 60 | }); 61 | 62 | autoUpdater.on('checking-for-update', () => { 63 | log.info('Checking for update...'); 64 | }); 65 | 66 | autoUpdater.on('update-available', (info) => { 67 | log.info('Update available:', info); 68 | }); 69 | 70 | autoUpdater.on('update-not-available', (info) => { 71 | log.info('Update not available:', info); 72 | }); 73 | 74 | autoUpdater.on('error', (err) => { 75 | log.error('Error in auto-updater:', err); 76 | }); 77 | 78 | autoUpdater.on('download-progress', (progressObj) => { 79 | let logMessage = `Download speed: ${progressObj.bytesPerSecond}`; 80 | logMessage = `${logMessage} - Downloaded ${progressObj.percent}%`; 81 | logMessage = `${logMessage} (${progressObj.transferred}/${progressObj.total})`; 82 | log.info(logMessage); 83 | }); 84 | 85 | autoUpdater.on('update-downloaded', (info) => { 86 | log.info('Update downloaded:', info); 87 | }); 88 | -------------------------------------------------------------------------------- /desktop/src/preload.js: -------------------------------------------------------------------------------- 1 | window.addEventListener('DOMContentLoaded', () => { 2 | const replaceText = (selector, text) => { 3 | const element = document.getElementById(selector); 4 | if (element) element.innerText = text; 5 | }; 6 | 7 | for (const dependency of ['chrome', 'node', 'electron']) { 8 | replaceText(`${dependency}-version`, process.versions[dependency]); 9 | } 10 | }); 11 | -------------------------------------------------------------------------------- /desktop/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | import '@testing-library/jest-dom'; 2 | -------------------------------------------------------------------------------- /desktop/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | "esModuleInterop": true, 9 | 10 | /* Bundler mode */ 11 | "moduleResolution": "bundler", 12 | "allowImportingTsExtensions": true, 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | 18 | /* Linting */ 19 | "strict": true, 20 | "noUnusedLocals": true, 21 | "noUnusedParameters": true, 22 | "noFallthroughCasesInSwitch": true, 23 | "baseUrl": ".", 24 | "paths": { 25 | "@/*": ["src/*"] 26 | } 27 | }, 28 | "include": ["src"], 29 | "references": [{ "path": "./tsconfig.node.json" }] 30 | } 31 | -------------------------------------------------------------------------------- /desktop/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /desktop/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import react from '@vitejs/plugin-react'; 3 | import { resolve } from 'path'; 4 | 5 | export default defineConfig({ 6 | plugins: [react()], 7 | resolve: { 8 | alias: { 9 | '@': resolve(__dirname, 'src'), 10 | }, 11 | }, 12 | }); 13 | -------------------------------------------------------------------------------- /docs/RELEASE_PROCESS.md: -------------------------------------------------------------------------------- 1 | # Kled.io Release Process 2 | 3 | This document outlines the release process for the Kled.io platform, including CLI tools and desktop applications. 4 | 5 | ## Overview 6 | 7 | The Kled.io release process includes: 8 | 9 | 1. Building CLI tools for multiple platforms (Windows, macOS, Linux) 10 | 2. Building desktop applications for multiple platforms 11 | 3. Testing installers for functionality 12 | 4. Creating GitHub releases with proper artifacts 13 | 5. Verifying installation on target platforms 14 | 15 | ## Release Workflow 16 | 17 | The release process is automated through GitHub Actions workflows in `.github/workflows/build-unified-cli.yml`. This workflow is triggered: 18 | 19 | - Manually through the GitHub Actions UI 20 | - Automatically when a tag with the format `v*` is pushed 21 | 22 | ## Release Artifacts 23 | 24 | Each release includes the following artifacts: 25 | 26 | ### CLI Tools 27 | 28 | - **Linux (AMD64/ARM64)** 29 | - `kled` - Main CLI tool 30 | - `kcluster` - Kubernetes cluster management 31 | - `kledspace` - Workspace management 32 | - `kpolicy` - Policy management 33 | 34 | - **Windows (AMD64)** 35 | - `kled.exe` 36 | - `kcluster.exe` 37 | - `kledspace.exe` 38 | - `kpolicy.exe` 39 | 40 | - **macOS (AMD64/ARM64)** 41 | - `kled` 42 | - `kcluster` 43 | - `kledspace` 44 | - `kpolicy` 45 | 46 | ### Desktop Applications 47 | 48 | - **Linux**: `.deb` package and `.AppImage` 49 | - **Windows**: `.exe` installer 50 | - **macOS**: `.dmg` installer 51 | 52 | ## Testing Installers 53 | 54 | ### Windows Installer Testing 55 | 56 | The Windows installer is tested during the build process using the `scripts/validate-installer.ps1` script, which: 57 | 58 | 1. Verifies the installer exists 59 | 2. Checks file size and creation time 60 | 3. Validates file signature (if signtool is available) 61 | 4. Tests extraction in silent mode 62 | 5. Verifies critical files are present 63 | 64 | ### Manual Testing 65 | 66 | For thorough testing before release: 67 | 68 | 1. Download the installer from the GitHub release page 69 | 2. Run the installer on a clean Windows machine 70 | 3. Verify the application launches correctly 71 | 4. Test basic functionality (CLI commands, UI navigation) 72 | 5. Verify uninstallation works properly 73 | 74 | ## Creating a Release 75 | 76 | To create a new release: 77 | 78 | 1. Update version numbers in relevant files: 79 | - `cli/unified/version.go` 80 | - `desktop/package.json` 81 | 82 | 2. Commit changes and push to the repository 83 | 84 | 3. Create and push a new tag: 85 | ```bash 86 | git tag v1.0.0 87 | git push origin v1.0.0 88 | ``` 89 | 90 | 4. Monitor the GitHub Actions workflow to ensure all builds succeed 91 | 92 | 5. Verify the release on GitHub includes all expected artifacts 93 | 94 | ## Troubleshooting 95 | 96 | If the release process fails: 97 | 98 | 1. Check GitHub Actions logs for specific errors 99 | 2. Verify all dependencies are correctly installed in the build environment 100 | 3. Test builds locally before creating a release tag 101 | 4. Ensure all required secrets are configured in the repository settings 102 | 103 | ## Windows Installation Verification 104 | 105 | To verify Windows installation: 106 | 107 | 1. Download the `.exe` installer from the release page 108 | 2. Run the installer on a Windows machine 109 | 3. Check that the application is installed in the expected location (usually `C:\Program Files\Kled Desktop`) 110 | 4. Verify desktop shortcuts are created 111 | 5. Launch the application and ensure it runs correctly 112 | 6. Test CLI commands from Command Prompt or PowerShell 113 | -------------------------------------------------------------------------------- /docs/architecture/cli-integration-architecture.md: -------------------------------------------------------------------------------- 1 | # CLI Integration Architecture 2 | 3 | ## Overview 4 | 5 | The Kled.io CLI integration architecture describes how the various command line tools (kled, kcluster, kledspace, kpolicy) are implemented, integrated, and distributed across the repositories. This document outlines the unified CLI approach, command implementation locations, and the build and distribution process. 6 | 7 | ## Unified CLI Approach 8 | 9 | ```mermaid 10 | graph TD 11 | subgraph UnifiedCLI["Unified CLI Binary"] 12 | main[main.go] 13 | router[Command Router] 14 | config[Config Management] 15 | auth[API Key Authentication] 16 | end 17 | 18 | subgraph Commands["Command Implementation"] 19 | kled[kled Commands] 20 | kcluster[kcluster Commands] 21 | kledspace[kledspace Commands] 22 | kpolicy[kpolicy Commands] 23 | end 24 | 25 | subgraph Distribution["Distribution Methods"] 26 | symlinks[Symlinks] 27 | batch[Batch Files] 28 | direct[Direct Execution] 29 | end 30 | 31 | main --> router 32 | router --> kled 33 | router --> kcluster 34 | router --> kledspace 35 | router --> kpolicy 36 | 37 | router --> distribution[Distribution Method Detection] 38 | distribution --> symlinks 39 | distribution --> batch 40 | distribution --> direct 41 | 42 | config --> auth 43 | ``` 44 | 45 | ### Command Implementation Locations 46 | 47 | ```mermaid 48 | graph TD 49 | subgraph PrivateRepos["Private Repositories"] 50 | kledRepo[kled Repository] 51 | kledProRepo[kled-pro Repository] 52 | end 53 | 54 | subgraph PublicRepo["Public Repository"] 55 | kledioRepo[kled.io Repository] 56 | end 57 | 58 | subgraph CommandImplementation["Command Implementation"] 59 | kledCmd[kled Commands] 60 | kclusterCmd[kcluster Commands] 61 | kledspaceCmd[kledspace Commands] 62 | kpolicyCmd[kpolicy Commands] 63 | end 64 | 65 | kledRepo --> kledCmd 66 | kledRepo --> kledspaceCmd 67 | kledProRepo --> kclusterCmd 68 | kledProRepo --> kpolicyCmd 69 | 70 | kledCmd --> kledioRepo 71 | kclusterCmd --> kledioRepo 72 | kledspaceCmd --> kledioRepo 73 | kpolicyCmd --> kledioRepo 74 | ``` 75 | 76 | ## Build and Distribution Process 77 | 78 | ```mermaid 79 | flowchart TD 80 | subgraph BuildProcess["Build Process"] 81 | makefile[Makefile] 82 | crossCompile[Cross Compilation] 83 | unifiedBinary[Unified Binary] 84 | end 85 | 86 | subgraph GitHubActions["GitHub Actions"] 87 | buildCLI[build-cli.yml] 88 | release[Release Creation] 89 | publish[Publish Downloads] 90 | end 91 | 92 | subgraph Distribution["Distribution"] 93 | website[Website Downloads] 94 | installScript[Installation Script] 95 | githubReleases[GitHub Releases] 96 | end 97 | 98 | makefile --> crossCompile 99 | crossCompile --> unifiedBinary 100 | 101 | unifiedBinary --> buildCLI 102 | buildCLI --> release 103 | release --> publish 104 | 105 | publish --> website 106 | publish --> installScript 107 | publish --> githubReleases 108 | ``` 109 | 110 | ## C4 Model: Component Level 111 | 112 | ```mermaid 113 | C4Component 114 | title Component diagram for Kled.io CLI 115 | 116 | Container_Boundary(cli, "CLI Tools") { 117 | Component(unified, "Unified CLI Binary", "Go", "Single binary with multiple command capabilities") 118 | Component(router, "Command Router", "Go", "Routes commands based on executable name or first argument") 119 | Component(auth, "Authentication", "Go", "Manages API keys and authentication") 120 | Component(config, "Configuration", "Go", "Handles configuration file management") 121 | 122 | Component(kled_cmd, "kled Commands", "Go", "Workspace management commands") 123 | Component(kcluster_cmd, "kcluster Commands", "Go", "Kubernetes cluster management commands") 124 | Component(kledspace_cmd, "kledspace Commands", "Go", "Environment management commands") 125 | Component(kpolicy_cmd, "kpolicy Commands", "Go", "Policy management commands") 126 | } 127 | 128 | Container(api, "Backend API", "Go", "API for workspace management") 129 | 130 | System_Ext(kubernetes, "Kubernetes", "Container orchestration platform") 131 | 132 | Rel(unified, router, "Uses") 133 | Rel(router, kled_cmd, "Routes to") 134 | Rel(router, kcluster_cmd, "Routes to") 135 | Rel(router, kledspace_cmd, "Routes to") 136 | Rel(router, kpolicy_cmd, "Routes to") 137 | 138 | Rel(unified, auth, "Uses") 139 | Rel(unified, config, "Uses") 140 | 141 | Rel(kled_cmd, api, "Makes API calls to") 142 | Rel(kcluster_cmd, api, "Makes API calls to") 143 | Rel(kledspace_cmd, api, "Makes API calls to") 144 | Rel(kpolicy_cmd, api, "Makes API calls to") 145 | 146 | Rel(api, kubernetes, "Manages") 147 | ``` 148 | 149 | ## Implementation Details 150 | 151 | ### Unified CLI Binary 152 | 153 | The unified CLI binary is implemented in the kled.io repository and serves as the entry point for all CLI commands. It determines which command to execute based on: 154 | 155 | 1. The executable name (e.g., `kled`, `kcluster`) 156 | 2. The first argument if executed as the unified binary (e.g., `kled-linux-amd64 kled`) 157 | 158 | ```go 159 | func main() { 160 | execName := filepath.Base(os.Args[0]) 161 | execName = strings.TrimSuffix(execName, filepath.Ext(execName)) 162 | 163 | var command string 164 | if strings.HasPrefix(execName, "kled-") { 165 | if len(os.Args) < 2 { 166 | printUsage() 167 | os.Exit(1) 168 | } 169 | command = os.Args[1] 170 | os.Args = append(os.Args[:1], os.Args[2:]...) 171 | } else { 172 | switch execName { 173 | case "kled": 174 | command = "kled" 175 | case "kcluster": 176 | command = "kcluster" 177 | case "kledspace": 178 | command = "kledspace" 179 | case "kpolicy": 180 | command = "kpolicy" 181 | default: 182 | fmt.Printf("Unknown command: %s\n", execName) 183 | printUsage() 184 | os.Exit(1) 185 | } 186 | } 187 | 188 | // Execute the appropriate command 189 | switch command { 190 | case "kled": 191 | executeKled() 192 | case "kcluster": 193 | executeKCluster() 194 | case "kledspace": 195 | executeKledSpace() 196 | case "kpolicy": 197 | executeKPolicy() 198 | default: 199 | fmt.Printf("Unknown command: %s\n", command) 200 | printUsage() 201 | os.Exit(1) 202 | } 203 | } 204 | ``` 205 | 206 | ### Authentication and Configuration 207 | 208 | The CLI tools use a shared authentication and configuration system that manages API keys and server URLs: 209 | 210 | ```go 211 | type Auth struct { 212 | APIKey string `json:"apiKey"` 213 | APIBaseURL string `json:"apiBaseURL"` 214 | CreatedAt time.Time `json:"createdAt"` 215 | } 216 | 217 | func LoadAuth() (*Auth, error) { 218 | configPath, err := getConfigPath() 219 | if err != nil { 220 | return nil, err 221 | } 222 | 223 | if _, err := os.Stat(configPath); os.IsNotExist(err) { 224 | return nil, errors.New("no authentication configuration found") 225 | } 226 | 227 | data, err := os.ReadFile(configPath) 228 | if err != nil { 229 | return nil, err 230 | } 231 | 232 | var auth Auth 233 | if err := json.Unmarshal(data, &auth); err != nil { 234 | return nil, err 235 | } 236 | 237 | // Environment variables take precedence 238 | if apiKey := os.Getenv("KLED_API_KEY"); apiKey != "" { 239 | auth.APIKey = apiKey 240 | } 241 | if apiBaseURL := os.Getenv("KLED_API_BASE_URL"); apiBaseURL != "" { 242 | auth.APIBaseURL = apiBaseURL 243 | } 244 | 245 | return &auth, nil 246 | } 247 | ``` 248 | 249 | ### Distribution Methods 250 | 251 | The CLI tools can be distributed and executed in several ways: 252 | 253 | 1. **Symlinks**: On Unix-like systems, symlinks to the unified binary allow execution as individual commands 254 | 2. **Batch Files**: On Windows, batch files route commands to the unified binary 255 | 3. **Direct Execution**: The unified binary can be executed directly with the command as the first argument 256 | 257 | ## GitHub Actions Workflow 258 | 259 | The GitHub Actions workflow automates the build and distribution process: 260 | 261 | ```yaml 262 | name: Build and Release CLI Tools 263 | 264 | on: 265 | push: 266 | branches: [main] 267 | tags: ['v*'] 268 | workflow_dispatch: 269 | 270 | jobs: 271 | build: 272 | name: Build CLI Tools 273 | runs-on: ${{ matrix.os }} 274 | strategy: 275 | fail-fast: false 276 | matrix: 277 | os: [ubuntu-latest, macos-latest, windows-latest] 278 | include: 279 | - os: ubuntu-latest 280 | platform: linux 281 | arch: amd64 282 | - os: macos-latest 283 | platform: darwin 284 | arch: amd64 285 | - os: windows-latest 286 | platform: windows 287 | arch: amd64 288 | 289 | steps: 290 | - name: Checkout code 291 | uses: actions/checkout@v3 292 | 293 | - name: Set up Go 294 | uses: actions/setup-go@v4 295 | with: 296 | go-version: '1.21' 297 | 298 | - name: Build unified CLI binary 299 | run: | 300 | mkdir -p bin 301 | GOOS=${{ matrix.platform }} GOARCH=${{ matrix.arch }} go build -o bin/${{ matrix.artifact_name }} ./cli/unified 302 | ``` 303 | 304 | ## Installation Script 305 | 306 | The installation script simplifies the installation process for end users: 307 | 308 | ```bash 309 | #!/bin/bash 310 | set -e 311 | 312 | TOOL="unified" 313 | INSTALL_DIR="/usr/local/bin" 314 | VERSION="latest" 315 | 316 | # Download the appropriate binary 317 | curl -fsSL "https://kled.io/download/${FILENAME}" -o "/tmp/$FILENAME" 318 | 319 | # Install the binary 320 | chmod +x "/tmp/$FILENAME" 321 | sudo mv "/tmp/$FILENAME" "$INSTALL_DIR/$TOOL$EXTENSION" 322 | 323 | # Create symlinks for individual commands 324 | for SYMLINK in kled kcluster kledspace kpolicy; do 325 | sudo ln -sf "$INSTALL_DIR/$TOOL$EXTENSION" "$INSTALL_DIR/$SYMLINK$EXTENSION" 326 | done 327 | ``` 328 | 329 | ## Conclusion 330 | 331 | The CLI integration architecture provides a unified approach to command line tools while maintaining separation between public and private repositories. The implementation details are kept in private repositories, while the public repository handles distribution and user-facing components. 332 | -------------------------------------------------------------------------------- /docs/architecture/diagrams/build-system-flow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Kled.io Build System Flow 4 | 5 | 6 | 7 | Turborepo Build System 8 | 9 | 10 | 11 | turbo.json 12 | 13 | 14 | Build Pipeline 15 | 16 | 17 | Task Dependencies 18 | 19 | 20 | 21 | Build Process 22 | 23 | 24 | 25 | Install Dependencies 26 | 27 | 28 | Build SpacetimeDB 29 | 30 | 31 | Build Packages 32 | 33 | 34 | Build Applications 35 | 36 | 37 | Run Tests 38 | 39 | 40 | Bundle Applications 41 | 42 | 43 | 44 | Build Artifacts 45 | 46 | 47 | 48 | CLI Binaries 49 | 50 | 51 | Desktop Apps 52 | 53 | 54 | Mobile Apps 55 | 56 | 57 | Web App 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /docs/architecture/diagrams/cli-build-distribution.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Kled.io CLI Build and Distribution 4 | 5 | 6 | 7 | Source Code 8 | 9 | 10 | 11 | kled (Private) 12 | 13 | 14 | kled-pro (Private) 15 | 16 | 17 | kled.io (Public) 18 | 19 | 20 | 21 | Build Process 22 | 23 | 24 | 25 | Makefile 26 | Cross-compilation 27 | 28 | 29 | GitHub Actions 30 | CI/CD Pipeline 31 | 32 | 33 | Unified Binary 34 | Single executable 35 | 36 | 37 | 38 | Build Artifacts 39 | 40 | 41 | 42 | Linux Binaries 43 | 44 | 45 | macOS Binaries 46 | 47 | 48 | Windows Binaries 49 | 50 | 51 | 52 | Distribution 53 | 54 | 55 | 56 | Website 57 | 58 | 59 | GitHub Releases 60 | 61 | 62 | Install Script 63 | 64 | 65 | Package Managers 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /docs/architecture/diagrams/cli-command-flow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Kled.io CLI Command Flow 4 | 5 | 6 | 7 | User Input 8 | 9 | 10 | 11 | kled command 12 | 13 | 14 | kcluster command 15 | 16 | 17 | unified binary 18 | 19 | 20 | 21 | Command Router 22 | 23 | 24 | 25 | Executable Name Check 26 | 27 | 28 | Argument Parsing 29 | 30 | 31 | Command Selection 32 | 33 | 34 | 35 | Command Implementation 36 | 37 | 38 | 39 | kled (kled repo) 40 | 41 | 42 | kcluster (kled-pro) 43 | 44 | 45 | kledspace/kpolicy 46 | 47 | 48 | 49 | API Calls 50 | 51 | 52 | 53 | Authentication 54 | 55 | 56 | API Requests 57 | 58 | 59 | Response Handling 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /docs/architecture/diagrams/database-integration.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Kled.io Database Integration Architecture 4 | 5 | 6 | 7 | Primary Database Systems 8 | 9 | 10 | 11 | SpacetimeDB 12 | Application State 13 | Real-time Synchronization 14 | 15 | 16 | Supabase 17 | Authentication 18 | API Key Management 19 | 20 | 21 | Slack Integration 22 | User Authentication 23 | Customer Management 24 | 25 | 26 | 27 | Future Database Integrations 28 | 29 | 30 | 31 | Datastax Enterprise 32 | Apache Cassandra 33 | Distributed Data Storage 34 | 35 | 36 | Redis 37 | Caching 38 | Real-time Data Processing 39 | 40 | 41 | Tigris 42 | Search Functionality 43 | Data Indexing 44 | 45 | 46 | 47 | High Availability Configuration 48 | 49 | 50 | 51 | Primary Nodes 52 | Write Operations 53 | 54 | 55 | Read Replicas 56 | Read Operations 57 | 58 | 59 | Failover 60 | Automatic Recovery 61 | 62 | 63 | Backups 64 | Disaster Recovery 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /docs/architecture/diagrams/desktop-mobile-architecture.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Kled.io Desktop/Mobile Architecture 4 | 5 | 6 | 7 | Platforms 8 | 9 | 10 | 11 | Desktop 12 | Windows, macOS, Linux 13 | 14 | 15 | Web 16 | Browser-based 17 | 18 | 19 | Mobile 20 | iOS, Android 21 | 22 | 23 | 24 | Technologies 25 | 26 | 27 | 28 | Tauri v2 29 | Desktop Framework 30 | 31 | 32 | React 33 | UI Framework 34 | 35 | 36 | Lynx Family 37 | Mobile Framework 38 | 39 | 40 | 41 | Backend 42 | 43 | 44 | 45 | SpacetimeDB 46 | State Management 47 | 48 | 49 | Supabase 50 | Auth & Storage 51 | 52 | 53 | Slack Integration 54 | Authentication 55 | 56 | 57 | 58 | Integration 59 | 60 | 61 | 62 | API Layer 63 | 64 | 65 | CLI Integration 66 | 67 | 68 | Shared State 69 | 70 | 71 | Kubernetes 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /docs/architecture/diagrams/monorepo-architecture.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Kled.io Monorepo Architecture 4 | 5 | 6 | 7 | /repos/monorepo 8 | 9 | 10 | 11 | apps/ 12 | 13 | 14 | 15 | kled 16 | Core CLI & Desktop 17 | (Private) 18 | 19 | 20 | kled-pro 21 | Enterprise Features 22 | (Private) 23 | 24 | 25 | kled.io 26 | Public Repository 27 | (Public) 28 | 29 | 30 | cisco-meraki 31 | Network Integration 32 | (Private) 33 | 34 | 35 | 36 | packages/ 37 | 38 | 39 | 40 | shared 41 | 42 | 43 | ui 44 | 45 | 46 | config 47 | 48 | 49 | types 50 | 51 | 52 | 53 | mcp-servers/ 54 | 55 | 56 | 57 | MCP Server Components 58 | Server Infrastructure 59 | (Root level, not in apps/) 60 | 61 | 62 | 63 | Build System 64 | 65 | 66 | 67 | turbo.json (Turborepo) 68 | 69 | 70 | pnpm-workspace.yaml 71 | 72 | 73 | Makefiles 74 | 75 | 76 | GitHub Actions 77 | 78 | 79 | 80 | 81 | imports API 82 | 83 | 84 | 85 | provides API 86 | 87 | 88 | 89 | CLI implementation 90 | 91 | 92 | 93 | kcluster implementation 94 | 95 | 96 | 97 | builds 98 | 99 | 100 | 101 | builds 102 | 103 | 104 | 105 | builds 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | Legend: 118 | Repository 119 | Package 120 | Server 121 | Build Config 122 | Dependency 123 | 124 | 125 | -------------------------------------------------------------------------------- /docs/architecture/diagrams/monorepo-structure.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Kled.io Monorepo 5 | 6 | 7 | 8 | apps/ 9 | 10 | 11 | 12 | kled 13 | 14 | 15 | kled-pro 16 | 17 | 18 | kled.io 19 | 20 | 21 | cisco-meraki 22 | 23 | 24 | 25 | packages/ 26 | 27 | 28 | 29 | shared 30 | 31 | 32 | ui 33 | 34 | 35 | config 36 | 37 | 38 | 39 | mcp-servers/ 40 | 41 | 42 | 43 | MCP Server Components 44 | 45 | 46 | 47 | Build System 48 | 49 | 50 | 51 | turbo.json 52 | 53 | 54 | pnpm-workspace 55 | 56 | 57 | 58 | uses 59 | 60 | 61 | builds 62 | 63 | 64 | integrates 65 | 66 | 67 | builds 68 | 69 | 70 | 71 | 72 | Legend: 73 | Repository 74 | Package 75 | Server Component 76 | Build Config 77 | 78 | 79 | -------------------------------------------------------------------------------- /docs/architecture/diagrams/repository-relationships.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Kled.io Repository Relationships 4 | 5 | 6 | 7 | Public Repository 8 | 9 | 10 | 11 | kled.io 12 | 13 | 14 | 15 | Private Repositories 16 | 17 | 18 | 19 | kled 20 | Core CLI & Desktop 21 | 22 | 23 | 24 | kled-pro 25 | Enterprise Features 26 | 27 | 28 | 29 | End Users 30 | Consumers of Kled.io 31 | 32 | 33 | 34 | 35 | CLI Implementation 36 | 37 | 38 | 39 | Desktop App Source 40 | 41 | 42 | 43 | kcluster Implementation 44 | 45 | 46 | 47 | API & Enterprise Features 48 | 49 | 50 | 51 | Distribution 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | Legend: 64 | Public Repo 65 | Private Repo 66 | End Users 67 | Dependency 68 | 69 | 70 | -------------------------------------------------------------------------------- /docs/architecture/diagrams/tauri-spacetime-integration.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Tauri and SpacetimeDB Integration 4 | 5 | 6 | 7 | Tauri v2 Application 8 | 9 | 10 | 11 | Tauri Core 12 | Rust 13 | 14 | 15 | IPC Bridge 16 | Rust/JavaScript 17 | 18 | 19 | WebView 20 | Platform-specific 21 | 22 | 23 | React App 24 | JavaScript/TypeScript 25 | 26 | 27 | Plugins 28 | Rust 29 | 30 | 31 | Native Modules 32 | Rust 33 | 34 | 35 | 36 | SpacetimeDB Integration 37 | 38 | 39 | 40 | SpacetimeDB Server 41 | Rust 42 | 43 | 44 | Database Models 45 | Rust 46 | 47 | 48 | SpacetimeDB Client 49 | TypeScript 50 | 51 | 52 | State Hooks 53 | TypeScript 54 | 55 | 56 | API Integration 57 | Rust/TypeScript 58 | 59 | 60 | Authentication 61 | Supabase/Slack 62 | 63 | 64 | 65 | Cross-Platform Integration 66 | 67 | 68 | 69 | Desktop 70 | 71 | 72 | Mobile 73 | 74 | 75 | Web 76 | 77 | 78 | CLI 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /docs/architecture/monorepo-architecture.md: -------------------------------------------------------------------------------- 1 | # Kled.io Monorepo Architecture 2 | 3 | ## Overview 4 | 5 | The Kled.io monorepo is structured to support a unified development environment for multiple related projects while maintaining separation of concerns. This document outlines the high-level architecture of the monorepo, the relationships between its components, and the build system flow. 6 | 7 | ## Monorepo Structure 8 | 9 | ```mermaid 10 | graph TD 11 | subgraph monorepo["/repos/monorepo"] 12 | turbo[Turborepo Configuration] 13 | pnpm[pnpm-workspace.yaml] 14 | 15 | subgraph apps["apps/ directory"] 16 | kled[kled - Core CLI & Desktop] 17 | kledpro[kled-pro - Enterprise Features] 18 | kledio[kled.io - Public Repository] 19 | cisco[cisco-meraki - Network Integration] 20 | end 21 | 22 | subgraph packages["packages/ directory"] 23 | shared[Shared Components] 24 | ui[UI Library] 25 | config[Configuration] 26 | end 27 | 28 | subgraph mcp["mcp-servers/ directory"] 29 | mcpservers[MCP Server Components] 30 | end 31 | end 32 | 33 | turbo --> apps 34 | turbo --> packages 35 | pnpm --> apps 36 | pnpm --> packages 37 | ``` 38 | 39 | ### Key Components 40 | 41 | 1. **apps/** - Contains the main application repositories: 42 | - **kled/** - Core CLI and desktop application (private repository) 43 | - **kled-pro/** - Enterprise features and extensions (private repository) 44 | - **kled.io/** - Public-facing repository for distribution 45 | - **cisco-meraki/** - Network integration components 46 | 47 | 2. **packages/** - Contains shared libraries and components: 48 | - Shared UI components 49 | - Configuration utilities 50 | - Common types and interfaces 51 | 52 | 3. **mcp-servers/** - Contains server components placed at the monorepo root 53 | 54 | ## Repository Relationships 55 | 56 | ```mermaid 57 | graph TD 58 | subgraph Public["Public Repository"] 59 | kledio[kled.io] 60 | end 61 | 62 | subgraph Private["Private Repositories"] 63 | kled[kled] 64 | kledpro[kled-pro] 65 | end 66 | 67 | kled -->|CLI Implementation| kledio 68 | kled -->|Desktop App Source| kledio 69 | kledpro -->|kcluster Implementation| kledio 70 | kledpro -->|Enterprise Features| kled 71 | kledio -->|Distribution| users[End Users] 72 | 73 | kled -->|Imports API| kledpro 74 | ``` 75 | 76 | ### Integration Points 77 | 78 | 1. **CLI Commands**: 79 | - `kled` commands implemented in the private kled repository 80 | - `kcluster` commands implemented in the private kled-pro repository 81 | - Unified CLI distributed through the public kled.io repository 82 | 83 | 2. **API Integration**: 84 | - kled-pro/platform provides API implementation 85 | - kled imports API from kled-pro/platform instead of github.com/loft-sh/api/v4 86 | 87 | 3. **Desktop Application**: 88 | - Source code in private kled repository 89 | - Built applications distributed through public kled.io repository 90 | 91 | ## Build System Flow 92 | 93 | ```mermaid 94 | flowchart TD 95 | subgraph Turborepo["Turborepo Build System"] 96 | direction LR 97 | turbo[turbo.json] --> pipeline[Build Pipeline] 98 | pipeline --> tasks[Task Dependencies] 99 | end 100 | 101 | subgraph BuildProcess["Build Process"] 102 | direction TB 103 | deps[Install Dependencies] --> build[Build Packages] 104 | build --> test[Run Tests] 105 | test --> bundle[Bundle Applications] 106 | end 107 | 108 | subgraph Artifacts["Build Artifacts"] 109 | cli[CLI Binaries] 110 | desktop[Desktop Applications] 111 | mobile[Mobile Applications] 112 | web[Web Application] 113 | end 114 | 115 | Turborepo --> BuildProcess 116 | BuildProcess --> Artifacts 117 | ``` 118 | 119 | ### Build Order 120 | 121 | 1. Install dependencies (yarn install) 122 | 2. Build shared packages 123 | 3. Build applications in dependency order: 124 | - SpacetimeDB server component first 125 | - Then desktop application components 126 | - CLI components 127 | - Web and mobile components 128 | 129 | ## C4 Model: Context Level 130 | 131 | ```mermaid 132 | C4Context 133 | title System Context diagram for Kled.io 134 | 135 | Person(user, "End User", "A user of the Kled.io platform") 136 | 137 | System(kledSystem, "Kled.io System", "Provides workspace management capabilities") 138 | 139 | System_Ext(kubernetes, "Kubernetes", "Container orchestration platform") 140 | System_Ext(cloud, "Cloud Providers", "Infrastructure providers (AWS, GCP, Azure)") 141 | System_Ext(slack, "Slack", "Authentication and communication") 142 | 143 | Rel(user, kledSystem, "Uses") 144 | Rel(kledSystem, kubernetes, "Manages workspaces on") 145 | Rel(kledSystem, cloud, "Provisions resources on") 146 | Rel(kledSystem, slack, "Authenticates through") 147 | ``` 148 | 149 | ## C4 Model: Container Level 150 | 151 | ```mermaid 152 | C4Container 153 | title Container diagram for Kled.io System 154 | 155 | Person(user, "End User", "A user of the Kled.io platform") 156 | 157 | System_Boundary(kledSystem, "Kled.io System") { 158 | Container(cli, "CLI Tools", "Go", "Command-line interface for workspace management") 159 | Container(desktop, "Desktop App", "Tauri/React", "Desktop application for workspace management") 160 | Container(mobile, "Mobile App", "React Native", "Mobile application for workspace management") 161 | Container(web, "Web App", "React", "Web interface for workspace management") 162 | Container(api, "API", "Go", "Backend API for workspace management") 163 | Container(spacetime, "SpacetimeDB", "Rust", "State management database") 164 | Container(supabase, "Supabase", "PostgreSQL", "User authentication and API key storage") 165 | } 166 | 167 | System_Ext(kubernetes, "Kubernetes", "Container orchestration platform") 168 | System_Ext(cloud, "Cloud Providers", "Infrastructure providers") 169 | System_Ext(slack, "Slack", "Authentication and communication") 170 | 171 | Rel(user, cli, "Uses") 172 | Rel(user, desktop, "Uses") 173 | Rel(user, mobile, "Uses") 174 | Rel(user, web, "Uses") 175 | 176 | Rel(cli, api, "Makes API calls to") 177 | Rel(desktop, api, "Makes API calls to") 178 | Rel(mobile, api, "Makes API calls to") 179 | Rel(web, api, "Makes API calls to") 180 | 181 | Rel(api, spacetime, "Stores state in") 182 | Rel(api, supabase, "Authenticates users with") 183 | Rel(api, kubernetes, "Manages workspaces on") 184 | Rel(api, cloud, "Provisions resources on") 185 | Rel(api, slack, "Integrates with") 186 | ``` 187 | 188 | ## Conclusion 189 | 190 | The Kled.io monorepo architecture is designed to support a multi-platform application ecosystem with shared components and a unified build system. The separation between public and private repositories allows for open-source distribution while protecting proprietary code. 191 | -------------------------------------------------------------------------------- /docs/architecture/triple-cd-pipeline.md: -------------------------------------------------------------------------------- 1 | # Triple CD Pipeline Architecture 2 | 3 | ## Overview 4 | 5 | The Kled.io Triple CD Pipeline provides a comprehensive approach to continuous delivery across different aspects of the system: 6 | 7 | 1. **FluxCD** - Manages code from private repositories 8 | 2. **ArgoCD** - Manages infrastructure components 9 | 3. **Hydra CD** - Manages Go CLI code and integrations 10 | 11 | This document outlines the architecture, components, and workflows of the triple CD pipeline. 12 | 13 | ## Pipeline Components 14 | 15 | ```mermaid 16 | graph TD 17 | subgraph TripleCD["Triple CD Pipeline"] 18 | flux[FluxCD] 19 | argo[ArgoCD] 20 | hydra[Hydra CD] 21 | vault[Hashicorp Vault] 22 | end 23 | 24 | subgraph Repositories["Source Repositories"] 25 | kled[kled] 26 | kledpro[kled-pro] 27 | kledspace[kledspace] 28 | kpolicy[kpolicy] 29 | kledmarketing[kled-marketing] 30 | end 31 | 32 | subgraph Infrastructure["Infrastructure"] 33 | spacetime[SpacetimeDB] 34 | supabase[Supabase] 35 | sonarqube[SonarQube] 36 | end 37 | 38 | subgraph CLI["CLI Tools"] 39 | kledcli[kled CLI] 40 | sonarqubecli[SonarQube CLI] 41 | end 42 | 43 | flux --> Repositories 44 | argo --> Infrastructure 45 | hydra --> CLI 46 | 47 | vault --> flux 48 | vault --> argo 49 | vault --> hydra 50 | ``` 51 | 52 | ## FluxCD Configuration 53 | 54 | FluxCD is responsible for syncing code from private repositories to ensure all components are up-to-date. 55 | 56 | ### Key Components 57 | 58 | - **GitRepository**: Defines the source repositories to monitor 59 | - **Kustomization**: Defines how to apply the Kubernetes manifests 60 | - **Vault Integration**: Securely manages access to private repositories 61 | 62 | ## ArgoCD Configuration 63 | 64 | ArgoCD manages the deployment and configuration of infrastructure components. 65 | 66 | ### Key Components 67 | 68 | - **Application**: Defines the applications to deploy 69 | - **ApplicationSet**: Manages multiple related applications 70 | - **Vault Plugin**: Securely manages secrets for deployments 71 | 72 | ## Hydra CD Configuration 73 | 74 | Hydra CD handles the building and distribution of Go CLI code. 75 | 76 | ### Key Components 77 | 78 | - **Jobsets**: Defines the build jobs for CLI tools 79 | - **Nix Expressions**: Defines the build process for Go applications 80 | - **Vault Integration**: Securely manages build secrets 81 | 82 | ## Secret Management 83 | 84 | All secrets are managed by Hashicorp Vault, ensuring secure access across the pipeline. 85 | 86 | ### Key Features 87 | 88 | - **Kubernetes Authentication**: Authenticates services using Kubernetes service accounts 89 | - **Dynamic Secrets**: Generates dynamic credentials for accessing resources 90 | - **Secret Rotation**: Automatically rotates secrets based on policies 91 | 92 | ## Workflow Examples 93 | 94 | ### Updating a Private Repository 95 | 96 | 1. Developer commits changes to a private repository 97 | 2. FluxCD detects the changes and syncs the code 98 | 3. ArgoCD deploys updated infrastructure components 99 | 4. Hydra CD builds updated CLI tools 100 | 5. End users can access the updated functionality 101 | 102 | ### Adding a New Integration 103 | 104 | 1. Developer adds a new integration (e.g., SonarQube) 105 | 2. ArgoCD deploys the new infrastructure component 106 | 3. Hydra CD builds the CLI tools with the new integration 107 | 4. FluxCD ensures all repositories are updated with the integration 108 | 5. End users can access the new integration through the CLI 109 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/spectrumwebco/kled.io 2 | 3 | go 1.20 4 | -------------------------------------------------------------------------------- /k8s/argo/argo-system.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: argo-cd 5 | namespace: argocd 6 | spec: 7 | project: default 8 | source: 9 | repoURL: https://github.com/spectrumwebco/kled.io.git 10 | targetRevision: HEAD 11 | path: k8s/argo/chart 12 | destination: 13 | server: https://kubernetes.default.svc 14 | namespace: argocd 15 | syncPolicy: 16 | automated: 17 | prune: true 18 | selfHeal: true 19 | -------------------------------------------------------------------------------- /k8s/argo/components/sonarqube/sonarqube.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: sonarqube 5 | namespace: sonarqube 6 | spec: 7 | replicas: 1 8 | selector: 9 | matchLabels: 10 | app: sonarqube 11 | template: 12 | metadata: 13 | labels: 14 | app: sonarqube 15 | spec: 16 | containers: 17 | - name: sonarqube 18 | image: sonarqube:latest 19 | ports: 20 | - containerPort: 9000 21 | env: 22 | - name: SONARQUBE_JDBC_URL 23 | valueFrom: 24 | secretKeyRef: 25 | name: sonarqube-db-credentials 26 | key: url 27 | - name: SONARQUBE_JDBC_USERNAME 28 | valueFrom: 29 | secretKeyRef: 30 | name: sonarqube-db-credentials 31 | key: username 32 | - name: SONARQUBE_JDBC_PASSWORD 33 | valueFrom: 34 | secretKeyRef: 35 | name: sonarqube-db-credentials 36 | key: password 37 | --- 38 | apiVersion: v1 39 | kind: Service 40 | metadata: 41 | name: sonarqube 42 | namespace: sonarqube 43 | spec: 44 | selector: 45 | app: sonarqube 46 | ports: 47 | - port: 9000 48 | targetPort: 9000 49 | type: ClusterIP 50 | -------------------------------------------------------------------------------- /k8s/argo/infra-components.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: spacetime-db 5 | namespace: argocd 6 | spec: 7 | project: default 8 | source: 9 | repoURL: https://github.com/spectrumwebco/kled.io.git 10 | targetRevision: HEAD 11 | path: k8s/argo/components/spacetime-db 12 | destination: 13 | server: https://kubernetes.default.svc 14 | namespace: spacetime 15 | syncPolicy: 16 | automated: 17 | prune: true 18 | selfHeal: true 19 | --- 20 | apiVersion: argoproj.io/v1alpha1 21 | kind: Application 22 | metadata: 23 | name: supabase 24 | namespace: argocd 25 | spec: 26 | project: default 27 | source: 28 | repoURL: https://github.com/spectrumwebco/kled.io.git 29 | targetRevision: HEAD 30 | path: k8s/argo/components/supabase 31 | destination: 32 | server: https://kubernetes.default.svc 33 | namespace: supabase 34 | syncPolicy: 35 | automated: 36 | prune: true 37 | selfHeal: true 38 | --- 39 | apiVersion: argoproj.io/v1alpha1 40 | kind: Application 41 | metadata: 42 | name: sonarqube 43 | namespace: argocd 44 | spec: 45 | project: default 46 | source: 47 | repoURL: https://github.com/spectrumwebco/kled.io.git 48 | targetRevision: HEAD 49 | path: k8s/argo/components/sonarqube 50 | destination: 51 | server: https://kubernetes.default.svc 52 | namespace: sonarqube 53 | syncPolicy: 54 | automated: 55 | prune: true 56 | selfHeal: true 57 | -------------------------------------------------------------------------------- /k8s/argo/vault-integration.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: argocd-vault-plugin 5 | namespace: argocd 6 | spec: 7 | project: default 8 | source: 9 | repoURL: https://github.com/spectrumwebco/kled.io.git 10 | targetRevision: HEAD 11 | path: k8s/argo/vault-plugin 12 | destination: 13 | server: https://kubernetes.default.svc 14 | namespace: argocd 15 | syncPolicy: 16 | automated: 17 | prune: true 18 | selfHeal: true 19 | -------------------------------------------------------------------------------- /k8s/flux/flux-system.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: source.toolkit.fluxcd.io/v1beta2 2 | kind: GitRepository 3 | metadata: 4 | name: kled-io 5 | namespace: flux-system 6 | spec: 7 | interval: 1m 8 | url: https://github.com/spectrumwebco/kled.io.git 9 | ref: 10 | branch: main 11 | secretRef: 12 | name: github-credentials 13 | --- 14 | apiVersion: kustomize.toolkit.fluxcd.io/v1beta2 15 | kind: Kustomization 16 | metadata: 17 | name: kled-io 18 | namespace: flux-system 19 | spec: 20 | interval: 10m 21 | path: "./k8s/flux" 22 | prune: true 23 | sourceRef: 24 | kind: GitRepository 25 | name: kled-io 26 | -------------------------------------------------------------------------------- /k8s/flux/private-repos.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: source.toolkit.fluxcd.io/v1beta2 2 | kind: GitRepository 3 | metadata: 4 | name: kled 5 | namespace: flux-system 6 | spec: 7 | interval: 1m 8 | url: https://github.com/spectrumwebco/kled.git 9 | ref: 10 | branch: main 11 | secretRef: 12 | name: github-credentials 13 | --- 14 | apiVersion: source.toolkit.fluxcd.io/v1beta2 15 | kind: GitRepository 16 | metadata: 17 | name: kled-pro 18 | namespace: flux-system 19 | spec: 20 | interval: 1m 21 | url: https://github.com/spectrumwebco/kled-pro.git 22 | ref: 23 | branch: main 24 | secretRef: 25 | name: github-credentials 26 | --- 27 | apiVersion: source.toolkit.fluxcd.io/v1beta2 28 | kind: GitRepository 29 | metadata: 30 | name: kledspace 31 | namespace: flux-system 32 | spec: 33 | interval: 1m 34 | url: https://github.com/spectrumwebco/kledspace.git 35 | ref: 36 | branch: main 37 | secretRef: 38 | name: github-credentials 39 | --- 40 | apiVersion: source.toolkit.fluxcd.io/v1beta2 41 | kind: GitRepository 42 | metadata: 43 | name: kpolicy 44 | namespace: flux-system 45 | spec: 46 | interval: 1m 47 | url: https://github.com/spectrumwebco/kpolicy.git 48 | ref: 49 | branch: main 50 | secretRef: 51 | name: github-credentials 52 | --- 53 | apiVersion: source.toolkit.fluxcd.io/v1beta2 54 | kind: GitRepository 55 | metadata: 56 | name: kled-marketing 57 | namespace: flux-system 58 | spec: 59 | interval: 1m 60 | url: https://github.com/spectrumwebco/kled-marketing.git 61 | ref: 62 | branch: main 63 | secretRef: 64 | name: github-credentials 65 | -------------------------------------------------------------------------------- /k8s/flux/vault-integration.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: external-secrets.io/v1beta1 2 | kind: ExternalSecret 3 | metadata: 4 | name: github-credentials 5 | namespace: flux-system 6 | spec: 7 | refreshInterval: "1h" 8 | secretStoreRef: 9 | name: vault-backend 10 | kind: ClusterSecretStore 11 | target: 12 | name: github-credentials 13 | data: 14 | - secretKey: identity 15 | remoteRef: 16 | key: github/flux-identity 17 | property: identity 18 | - secretKey: known_hosts 19 | remoteRef: 20 | key: github/flux-identity 21 | property: known_hosts 22 | -------------------------------------------------------------------------------- /k8s/hydra/default.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | services.hydra = { 5 | enable = true; 6 | hydraURL = "https://hydra.kled.io"; 7 | notificationSender = "hydra@kled.io"; 8 | buildMachinesFiles = []; 9 | useSubstitutes = true; 10 | }; 11 | 12 | services.postgresql = { 13 | enable = true; 14 | package = pkgs.postgresql_11; 15 | extraConfig = '' 16 | max_connections = 250 17 | work_mem = 32MB 18 | shared_buffers = 512MB 19 | ''; 20 | }; 21 | 22 | networking.firewall.allowedTCPPorts = [ 80 443 3000 ]; 23 | 24 | security.acme = { 25 | email = "admin@kled.io"; 26 | acceptTerms = true; 27 | }; 28 | 29 | services.nginx = { 30 | enable = true; 31 | virtualHosts."hydra.kled.io" = { 32 | forceSSL = true; 33 | enableACME = true; 34 | locations."/".proxyPass = "http://127.0.0.1:3000"; 35 | }; 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /k8s/hydra/jobsets.nix: -------------------------------------------------------------------------------- 1 | { nixpkgs ? }: 2 | 3 | let 4 | pkgs = import nixpkgs {}; 5 | in { 6 | jobsets = pkgs.runCommand "jobsets.json" {} '' 7 | cat > $out < }: 2 | 3 | let 4 | pkgs = import nixpkgs {}; 5 | 6 | buildKledCLI = { name, src, goPackagePath }: pkgs.buildGoModule { 7 | pname = name; 8 | version = "0.1.0"; 9 | inherit src; 10 | 11 | vendorSha256 = null; # Set this to the actual hash after initial build 12 | 13 | nativeBuildInputs = [ pkgs.installShellFiles ]; 14 | 15 | postInstall = '' 16 | installShellCompletion --cmd ${name} \ 17 | --bash <($out/bin/${name} completion bash) \ 18 | --zsh <($out/bin/${name} completion zsh) 19 | ''; 20 | 21 | meta = with pkgs.lib; { 22 | description = "Kled CLI for Kubernetes workspace management"; 23 | homepage = "https://kled.io"; 24 | license = licenses.mit; 25 | maintainers = [ "Spectrum Web Co" ]; 26 | }; 27 | }; 28 | in { 29 | kled = buildKledCLI { 30 | name = "kled"; 31 | src = ./.; 32 | goPackagePath = "github.com/spectrumwebco/kled"; 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /k8s/hydra/vault-integration.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | environment.systemPackages = with pkgs; [ 5 | vault 6 | ]; 7 | 8 | systemd.services.hydra-vault-auth = { 9 | description = "Hydra Vault Authentication"; 10 | wantedBy = [ "multi-user.target" ]; 11 | after = [ "network.target" "vault.service" ]; 12 | path = [ pkgs.vault ]; 13 | script = '' 14 | vault login -method=kubernetes \ 15 | role=hydra \ 16 | jwt_path=/var/run/secrets/kubernetes.io/serviceaccount/token 17 | ''; 18 | serviceConfig = { 19 | Type = "oneshot"; 20 | RemainAfterExit = true; 21 | User = "hydra"; 22 | Group = "hydra"; 23 | }; 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /k8s/vault/chart/values.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | dev: 3 | enabled: false 4 | ha: 5 | enabled: true 6 | replicas: 3 7 | service: 8 | type: ClusterIP 9 | ui: 10 | enabled: true 11 | -------------------------------------------------------------------------------- /k8s/vault/vault.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: vault 5 | namespace: argocd 6 | spec: 7 | project: default 8 | source: 9 | repoURL: https://github.com/spectrumwebco/kled.io.git 10 | targetRevision: HEAD 11 | path: k8s/vault/chart 12 | destination: 13 | server: https://kubernetes.default.svc 14 | namespace: vault 15 | syncPolicy: 16 | automated: 17 | prune: true 18 | selfHeal: true 19 | -------------------------------------------------------------------------------- /mobile/README.md: -------------------------------------------------------------------------------- 1 | 2 | This is a placeholder for the Kled.io mobile applications. The actual implementation is maintained in private repositories. 3 | 4 | 5 | - iOS and Android applications 6 | - Built with the Lynx Family framework 7 | - Provides a unified interface for managing Kubernetes workspaces 8 | 9 | 10 | See the installation instructions in the main README.md file. 11 | -------------------------------------------------------------------------------- /scripts/test-windows-installer.ps1: -------------------------------------------------------------------------------- 1 | # Windows Installer Testing Script for Kled Desktop 2 | # This script downloads and tests the latest Kled Desktop installer for Windows 3 | 4 | param ( 5 | [Parameter(Mandatory=$false)] 6 | [string]$ReleaseTag = "latest", 7 | 8 | [Parameter(Mandatory=$false)] 9 | [string]$DownloadPath = "$env:TEMP\kled-installer" 10 | ) 11 | 12 | # Create download directory if it doesn't exist 13 | if (-not (Test-Path -Path $DownloadPath)) { 14 | New-Item -ItemType Directory -Path $DownloadPath | Out-Null 15 | Write-Host "Created download directory: $DownloadPath" -ForegroundColor Green 16 | } 17 | 18 | # Function to get the latest release or specific tag 19 | function Get-KledRelease { 20 | param ( 21 | [string]$Tag 22 | ) 23 | 24 | Write-Host "Fetching release information for tag: $Tag" -ForegroundColor Cyan 25 | 26 | $headers = @{ 27 | "Accept" = "application/vnd.github.v3+json" 28 | } 29 | 30 | $apiUrl = if ($Tag -eq "latest") { 31 | "https://api.github.com/repos/spectrumwebco/kled.io/releases/latest" 32 | } else { 33 | "https://api.github.com/repos/spectrumwebco/kled.io/releases/tags/$Tag" 34 | } 35 | 36 | try { 37 | $release = Invoke-RestMethod -Uri $apiUrl -Headers $headers 38 | return $release 39 | } catch { 40 | Write-Host "Error fetching release information: $_" -ForegroundColor Red 41 | exit 1 42 | } 43 | } 44 | 45 | # Function to download the Windows installer 46 | function Download-KledInstaller { 47 | param ( 48 | [object]$Release 49 | ) 50 | 51 | Write-Host "Looking for Windows installer in release assets..." -ForegroundColor Cyan 52 | 53 | $windowsAsset = $Release.assets | Where-Object { $_.name -like "*windows*.exe" } | Select-Object -First 1 54 | 55 | if (-not $windowsAsset) { 56 | Write-Host "No Windows installer found in release assets!" -ForegroundColor Red 57 | exit 1 58 | } 59 | 60 | $installerPath = Join-Path -Path $DownloadPath -ChildPath $windowsAsset.name 61 | 62 | Write-Host "Downloading Windows installer: $($windowsAsset.name)" -ForegroundColor Cyan 63 | Write-Host "Download URL: $($windowsAsset.browser_download_url)" -ForegroundColor Cyan 64 | 65 | try { 66 | Invoke-WebRequest -Uri $windowsAsset.browser_download_url -OutFile $installerPath 67 | Write-Host "Download complete: $installerPath" -ForegroundColor Green 68 | return $installerPath 69 | } catch { 70 | Write-Host "Error downloading installer: $_" -ForegroundColor Red 71 | exit 1 72 | } 73 | } 74 | 75 | # Function to test the installer 76 | function Test-KledInstaller { 77 | param ( 78 | [string]$InstallerPath 79 | ) 80 | 81 | Write-Host "Testing installer: $InstallerPath" -ForegroundColor Cyan 82 | 83 | # Verify the installer exists 84 | if (-not (Test-Path -Path $InstallerPath)) { 85 | Write-Host "Installer file not found at $InstallerPath" -ForegroundColor Red 86 | exit 1 87 | } 88 | 89 | # Get file information 90 | $fileInfo = Get-Item $InstallerPath 91 | Write-Host "Installer file size: $($fileInfo.Length) bytes" -ForegroundColor Green 92 | Write-Host "Installer created: $($fileInfo.CreationTime)" -ForegroundColor Green 93 | 94 | # Test silent installation 95 | $installDir = Join-Path -Path $env:TEMP -ChildPath "KledDesktopTest" 96 | Write-Host "Testing silent installation to: $installDir" -ForegroundColor Cyan 97 | 98 | try { 99 | # Create installation directory 100 | if (Test-Path -Path $installDir) { 101 | Remove-Item -Path $installDir -Recurse -Force 102 | } 103 | New-Item -ItemType Directory -Path $installDir | Out-Null 104 | 105 | # Run installer silently 106 | $installArgs = @("/SILENT", "/NOCANCEL", "/NORESTART", "/SUPPRESSMSGBOXES", "/DIR=`"$installDir`"") 107 | Start-Process -FilePath $InstallerPath -ArgumentList $installArgs -Wait 108 | 109 | # Verify installation 110 | if (Test-Path -Path "$installDir\Kled Desktop.exe") { 111 | Write-Host "Installation successful!" -ForegroundColor Green 112 | 113 | # Check for critical files 114 | $criticalFiles = @( 115 | "Kled Desktop.exe", 116 | "resources.pak", 117 | "LICENSE" 118 | ) 119 | 120 | foreach ($file in $criticalFiles) { 121 | if (Test-Path -Path "$installDir\$file") { 122 | Write-Host "Found critical file: $file" -ForegroundColor Green 123 | } else { 124 | Write-Host "Missing critical file: $file" -ForegroundColor Yellow 125 | } 126 | } 127 | 128 | # Test application launch (optional) 129 | Write-Host "Testing application launch..." -ForegroundColor Cyan 130 | try { 131 | $process = Start-Process -FilePath "$installDir\Kled Desktop.exe" -PassThru 132 | Start-Sleep -Seconds 5 133 | 134 | if (-not $process.HasExited) { 135 | Write-Host "Application launched successfully!" -ForegroundColor Green 136 | Stop-Process -Id $process.Id -Force 137 | } else { 138 | Write-Host "Application launched but exited immediately with code: $($process.ExitCode)" -ForegroundColor Yellow 139 | } 140 | } catch { 141 | Write-Host "Error launching application: $_" -ForegroundColor Red 142 | } 143 | } else { 144 | Write-Host "Installation failed - executable not found" -ForegroundColor Red 145 | } 146 | } catch { 147 | Write-Host "Error during installation test: $_" -ForegroundColor Red 148 | } finally { 149 | # Clean up 150 | if (Test-Path -Path $installDir) { 151 | Write-Host "Cleaning up test installation..." -ForegroundColor Cyan 152 | Remove-Item -Path $installDir -Recurse -Force 153 | } 154 | } 155 | } 156 | 157 | # Main execution 158 | Write-Host "=== Kled Desktop Windows Installer Test ===" -ForegroundColor Cyan 159 | Write-Host "Release Tag: $ReleaseTag" -ForegroundColor Cyan 160 | Write-Host "Download Path: $DownloadPath" -ForegroundColor Cyan 161 | 162 | $release = Get-KledRelease -Tag $ReleaseTag 163 | Write-Host "Testing release: $($release.name) ($($release.tag_name))" -ForegroundColor Cyan 164 | 165 | $installerPath = Download-KledInstaller -Release $release 166 | Test-KledInstaller -InstallerPath $installerPath 167 | 168 | Write-Host "=== Test Complete ===" -ForegroundColor Cyan 169 | -------------------------------------------------------------------------------- /scripts/validate-installer.ps1: -------------------------------------------------------------------------------- 1 | # Windows Installer Validation Script for Kled Desktop 2 | # This script validates the Windows installer for Kled Desktop 3 | 4 | param ( 5 | [Parameter(Mandatory=$true)] 6 | [string]$InstallerPath 7 | ) 8 | 9 | Write-Host "Validating Kled Desktop Windows installer at: $InstallerPath" 10 | 11 | # Check if installer file exists 12 | if (-not (Test-Path -Path $InstallerPath)) { 13 | Write-Host "Error: Installer file not found at $InstallerPath" -ForegroundColor Red 14 | exit 1 15 | } 16 | 17 | # Get file information 18 | $fileInfo = Get-Item $InstallerPath 19 | Write-Host "Installer file size: $($fileInfo.Length) bytes" -ForegroundColor Green 20 | Write-Host "Installer created: $($fileInfo.CreationTime)" -ForegroundColor Green 21 | 22 | # Check file signature (optional, requires signtool.exe) 23 | try { 24 | $signtoolPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64\signtool.exe" 25 | if (Test-Path $signtoolPath) { 26 | $signResult = & $signtoolPath verify /pa $InstallerPath 27 | if ($LASTEXITCODE -eq 0) { 28 | Write-Host "Installer signature is valid" -ForegroundColor Green 29 | } else { 30 | Write-Host "Installer signature validation failed or not signed" -ForegroundColor Yellow 31 | } 32 | } else { 33 | Write-Host "Signtool not found, skipping signature validation" -ForegroundColor Yellow 34 | } 35 | } catch { 36 | Write-Host "Error checking signature: $_" -ForegroundColor Yellow 37 | } 38 | 39 | # Test installer extraction (silent mode) 40 | Write-Host "Testing installer extraction..." 41 | $tempDir = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), [System.Guid]::NewGuid().ToString()) 42 | New-Item -ItemType Directory -Path $tempDir | Out-Null 43 | 44 | try { 45 | # Extract installer (this is for NSIS-based installers, adjust if using different format) 46 | $extractArgs = @("/SILENT", "/NOCANCEL", "/NORESTART", "/SUPPRESSMSGBOXES", "/DIR=`"$tempDir`"") 47 | Start-Process -FilePath $InstallerPath -ArgumentList $extractArgs -Wait 48 | 49 | # Check if extraction succeeded 50 | if (Test-Path -Path "$tempDir\Kled Desktop.exe") { 51 | Write-Host "Installer extraction successful" -ForegroundColor Green 52 | } else { 53 | Write-Host "Installer extraction failed - executable not found" -ForegroundColor Red 54 | } 55 | 56 | # Check for critical files 57 | $criticalFiles = @( 58 | "Kled Desktop.exe", 59 | "resources.pak", 60 | "LICENSE" 61 | ) 62 | 63 | foreach ($file in $criticalFiles) { 64 | if (Test-Path -Path "$tempDir\$file") { 65 | Write-Host "Found critical file: $file" -ForegroundColor Green 66 | } else { 67 | Write-Host "Missing critical file: $file" -ForegroundColor Yellow 68 | } 69 | } 70 | } catch { 71 | Write-Host "Error during extraction test: $_" -ForegroundColor Red 72 | } finally { 73 | # Clean up 74 | if (Test-Path -Path $tempDir) { 75 | Remove-Item -Path $tempDir -Recurse -Force 76 | } 77 | } 78 | 79 | Write-Host "Validation complete" -ForegroundColor Green 80 | -------------------------------------------------------------------------------- /web/README.md: -------------------------------------------------------------------------------- 1 | # Kled.io Web App 2 | 3 | This directory contains the web application for Kled.io, built using React. 4 | 5 | ## Getting Started 6 | 7 | ### Prerequisites 8 | 9 | - Node.js 16 or later 10 | - Yarn 11 | 12 | ### Installation 13 | 14 | 1. Install dependencies: 15 | 16 | ```bash 17 | yarn install 18 | ``` 19 | 20 | 2. Run the app in development mode: 21 | 22 | ```bash 23 | yarn dev 24 | ``` 25 | 26 | ## Building for Production 27 | 28 | ```bash 29 | yarn build 30 | ``` 31 | 32 | This will create a production build in the `dist` directory. 33 | 34 | ## Features 35 | 36 | - Workspace management 37 | - Cluster management 38 | - Policy management 39 | - Real-time monitoring 40 | - Responsive design for all devices 41 | -------------------------------------------------------------------------------- /web/download/files/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spectrumwebco/autobots.ai/0509db4f322d0941126fdbc01a8dff4104d231e0/web/download/files/.gitkeep -------------------------------------------------------------------------------- /web/download/files/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Kled.io CLI Installer 4 | # This script detects the OS and architecture and downloads the appropriate Kled CLI binary 5 | 6 | set -e 7 | 8 | # Colors 9 | RED='\033[0;31m' 10 | GREEN='\033[0;32m' 11 | YELLOW='\033[0;33m' 12 | BLUE='\033[0;34m' 13 | NC='\033[0m' # No Color 14 | 15 | # Base URL for downloads 16 | BASE_URL="https://www.kled.io/download/files" 17 | 18 | # Detect OS 19 | detect_os() { 20 | case "$(uname -s)" in 21 | Linux*) echo "linux";; 22 | Darwin*) echo "darwin";; 23 | CYGWIN*) echo "windows";; 24 | MINGW*) echo "windows";; 25 | MSYS*) echo "windows";; 26 | *) echo "unknown";; 27 | esac 28 | } 29 | 30 | # Detect architecture 31 | detect_arch() { 32 | case "$(uname -m)" in 33 | x86_64*) echo "amd64";; 34 | amd64*) echo "amd64";; 35 | arm64*) echo "arm64";; 36 | aarch64*) echo "arm64";; 37 | *) echo "unknown";; 38 | esac 39 | } 40 | 41 | # Main installation function 42 | install_kled() { 43 | echo -e "${BLUE}Kled.io CLI Installer${NC}" 44 | echo "Detecting your system..." 45 | 46 | OS=$(detect_os) 47 | ARCH=$(detect_arch) 48 | 49 | if [ "$OS" = "unknown" ] || [ "$ARCH" = "unknown" ]; then 50 | echo -e "${RED}Error: Could not detect your operating system or architecture.${NC}" 51 | echo "Please download the appropriate binary manually from https://www.kled.io/download" 52 | exit 1 53 | fi 54 | 55 | echo -e "Detected: ${GREEN}$OS/$ARCH${NC}" 56 | 57 | # Handle Windows separately 58 | if [ "$OS" = "windows" ]; then 59 | FILENAME="kled-windows-amd64.exe" 60 | echo -e "${YELLOW}Note: For Windows, please download the installer from https://www.kled.io/download${NC}" 61 | exit 0 62 | else 63 | FILENAME="kled-$OS-$ARCH" 64 | fi 65 | 66 | DOWNLOAD_URL="$BASE_URL/$FILENAME" 67 | 68 | echo "Downloading Kled CLI from $DOWNLOAD_URL..." 69 | curl -L -o kled "$DOWNLOAD_URL" 70 | 71 | echo "Making binary executable..." 72 | chmod +x kled 73 | 74 | echo "Installing to /usr/local/bin/kled..." 75 | sudo mv kled /usr/local/bin/ 76 | 77 | echo -e "${GREEN}Installation complete!${NC}" 78 | echo "Run 'kled --version' to verify the installation." 79 | echo -e "${YELLOW}Note: You may need to restart your terminal for changes to take effect.${NC}" 80 | } 81 | 82 | # Run the installer 83 | install_kled 84 | -------------------------------------------------------------------------------- /web/download/install.sh: -------------------------------------------------------------------------------- 1 | 2 | set -e 3 | 4 | TOOL="unified" 5 | INSTALL_DIR="/usr/local/bin" 6 | VERSION="latest" 7 | 8 | while [[ $# -gt 0 ]]; do 9 | case $1 in 10 | -t|--tool) 11 | TOOL="$2" 12 | shift 2 13 | ;; 14 | -d|--dir) 15 | INSTALL_DIR="$2" 16 | shift 2 17 | ;; 18 | -v|--version) 19 | VERSION="$2" 20 | shift 2 21 | ;; 22 | *) 23 | echo "Unknown option: $1" 24 | exit 1 25 | ;; 26 | esac 27 | done 28 | 29 | if [[ "$TOOL" != "unified" && "$TOOL" != "kled" && "$TOOL" != "kcluster" && "$TOOL" != "kledspace" && "$TOOL" != "kpolicy" ]]; then 30 | echo "Invalid tool: $TOOL" 31 | echo "Valid options: unified, kled, kcluster, kledspace, kpolicy" 32 | exit 1 33 | fi 34 | 35 | OS="$(uname -s | tr '[:upper:]' '[:lower:]')" 36 | ARCH="$(uname -m)" 37 | 38 | case "$ARCH" in 39 | x86_64) 40 | GOARCH="amd64" 41 | ;; 42 | aarch64|arm64) 43 | GOARCH="arm64" 44 | ;; 45 | *) 46 | echo "Unsupported architecture: $ARCH" 47 | exit 1 48 | ;; 49 | esac 50 | 51 | case "$OS" in 52 | linux) 53 | GOOS="linux" 54 | ;; 55 | darwin) 56 | GOOS="darwin" 57 | ;; 58 | msys*|mingw64|windows*) 59 | GOOS="windows" 60 | ;; 61 | *) 62 | echo "Unsupported OS: $OS" 63 | exit 1 64 | ;; 65 | esac 66 | 67 | if [[ "$GOOS" == "windows" ]]; then 68 | EXTENSION=".exe" 69 | else 70 | EXTENSION="" 71 | fi 72 | 73 | if [[ "$TOOL" == "unified" ]]; then 74 | FILENAME="kled-${GOOS}-${GOARCH}${EXTENSION}" 75 | else 76 | FILENAME="${TOOL}-${GOOS}-${GOARCH}${EXTENSION}" 77 | fi 78 | 79 | if [[ "$VERSION" == "latest" ]]; then 80 | DOWNLOAD_URL="https://kled.io/download/${FILENAME}" 81 | else 82 | DOWNLOAD_URL="https://kled.io/download/${VERSION}/${FILENAME}" 83 | fi 84 | 85 | echo "Downloading $TOOL for $GOOS/$GOARCH..." 86 | curl -fsSL "$DOWNLOAD_URL" -o "/tmp/$FILENAME" 87 | 88 | echo "Installing to $INSTALL_DIR..." 89 | chmod +x "/tmp/$FILENAME" 90 | 91 | if [[ $EUID -ne 0 && ! -w "$INSTALL_DIR" ]]; then 92 | sudo mv "/tmp/$FILENAME" "$INSTALL_DIR/$TOOL$EXTENSION" 93 | else 94 | mv "/tmp/$FILENAME" "$INSTALL_DIR/$TOOL$EXTENSION" 95 | fi 96 | 97 | if [[ "$TOOL" == "unified" ]]; then 98 | echo "Creating symlinks for CLI tools..." 99 | for SYMLINK in kled kcluster kledspace kpolicy; do 100 | if [[ $EUID -ne 0 && ! -w "$INSTALL_DIR" ]]; then 101 | sudo ln -sf "$INSTALL_DIR/$TOOL$EXTENSION" "$INSTALL_DIR/$SYMLINK$EXTENSION" 102 | else 103 | ln -sf "$INSTALL_DIR/$TOOL$EXTENSION" "$INSTALL_DIR/$SYMLINK$EXTENSION" 104 | fi 105 | done 106 | fi 107 | 108 | echo "Installation complete!" 109 | echo "You can now use the $TOOL command." 110 | if [[ "$TOOL" == "unified" ]]; then 111 | echo "The following commands are also available: kled, kcluster, kledspace, kpolicy" 112 | fi 113 | -------------------------------------------------------------------------------- /web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Kled.io - Kubernetes Workspace Management 7 | 8 | 27 | 28 | 29 | 53 | 54 |
55 |
56 |

Kubernetes Workspace Management Made Simple

57 |

Kled.io provides a unified interface for managing Kubernetes workspaces, clusters, and policies.

58 |
59 | Download 60 | Documentation 61 |
62 |
63 |
64 | 65 |
66 |
67 |

Features

68 |
69 |
70 |
71 |
🖥️
72 |

Desktop App

73 |

Cross-platform desktop application for managing Kubernetes workspaces.

74 |
75 |
76 |
77 |
78 |
🌐
79 |

Web App

80 |

Browser-based interface with the same functionality as the desktop app.

81 |
82 |
83 |
84 |
85 |
📱
86 |

Mobile Apps

87 |

iOS and Android applications for on-the-go management.

88 |
89 |
90 |
91 |
92 |
⌨️
93 |

CLI Tools

94 |

Command-line tools for workspace, cluster, and policy management.

95 |
96 |
97 |
98 |
99 |
🔒
100 |

Security

101 |

Built-in security features for managing access and policies.

102 |
103 |
104 |
105 |
106 |
🔄
107 |

Automation

108 |

Automate common tasks and workflows with built-in automation tools.

109 |
110 |
111 |
112 |
113 |
114 | 115 |
116 |
117 |

Download

118 |
119 |
120 |
121 |
122 |

Desktop App

123 |

Available for Windows, macOS, and Linux.

124 | Download 125 |
126 |
127 |
128 |
129 |
130 |
131 |

CLI Tools

132 |

Command-line tools for all platforms.

133 | Download 134 |
135 |
136 |
137 |
138 |
139 |
140 |

Mobile Apps

141 |

Available on iOS and Android.

142 | Download 143 |
144 |
145 |
146 |
147 |
148 |
149 | 150 |
151 |
152 |

Documentation

153 |
154 |
155 |
156 |
157 |

Getting Started

158 |

Learn how to install and set up Kled.io for your environment.

159 | Read More 160 |
161 |
162 |
163 |
164 |
165 |
166 |

API Reference

167 |

Detailed documentation for the Kled.io API.

168 | Read More 169 |
170 |
171 |
172 |
173 |
174 |
175 | 176 |
177 |
178 |

Ready to Get Started?

179 |

Join thousands of developers who are already using Kled.io to manage their Kubernetes workspaces.

180 | Download Now 181 |
182 |
183 | 184 | 195 | 196 | 197 | 198 | 199 | -------------------------------------------------------------------------------- /web/install.sh: -------------------------------------------------------------------------------- 1 | 2 | 3 | set -e 4 | 5 | TOOL="unified" 6 | INSTALL_DIR="/usr/local/bin" 7 | VERSION="latest" 8 | 9 | while [[ $# -gt 0 ]]; do 10 | case $1 in 11 | -t|--tool) 12 | TOOL="$2" 13 | shift 2 14 | ;; 15 | -d|--dir) 16 | INSTALL_DIR="$2" 17 | shift 2 18 | ;; 19 | -v|--version) 20 | VERSION="$2" 21 | shift 2 22 | ;; 23 | *) 24 | echo "Unknown option: $1" 25 | exit 1 26 | ;; 27 | esac 28 | done 29 | 30 | if [[ "$TOOL" != "unified" && "$TOOL" != "kled" && "$TOOL" != "kcluster" && "$TOOL" != "kledspace" && "$TOOL" != "kpolicy" ]]; then 31 | echo "Invalid tool: $TOOL" 32 | echo "Valid options: unified, kled, kcluster, kledspace, kpolicy" 33 | exit 1 34 | fi 35 | 36 | OS="$(uname -s | tr '[:upper:]' '[:lower:]')" 37 | ARCH="$(uname -m)" 38 | 39 | case "$ARCH" in 40 | x86_64) 41 | GOARCH="amd64" 42 | ;; 43 | aarch64|arm64) 44 | GOARCH="arm64" 45 | ;; 46 | *) 47 | echo "Unsupported architecture: $ARCH" 48 | exit 1 49 | ;; 50 | esac 51 | 52 | case "$OS" in 53 | linux) 54 | GOOS="linux" 55 | ;; 56 | darwin) 57 | GOOS="darwin" 58 | ;; 59 | *) 60 | echo "Unsupported OS: $OS" 61 | exit 1 62 | ;; 63 | esac 64 | 65 | if [[ "$TOOL" == "unified" ]]; then 66 | FILENAME="kled-${GOOS}-${GOARCH}" 67 | if [[ "$GOOS" == "windows" ]]; then 68 | FILENAME="${FILENAME}.exe" 69 | fi 70 | DOWNLOAD_URL="https://kled.io/download/${FILENAME}" 71 | else 72 | FILENAME="${TOOL}" 73 | if [[ "$GOOS" == "windows" ]]; then 74 | FILENAME="${FILENAME}.exe" 75 | fi 76 | DOWNLOAD_URL="https://kled.io/download/${TOOL}-${GOOS}-${GOARCH}" 77 | fi 78 | 79 | echo "Downloading $TOOL for $GOOS/$GOARCH..." 80 | curl -fsSL "$DOWNLOAD_URL" -o "/tmp/$FILENAME" 81 | 82 | echo "Installing to $INSTALL_DIR..." 83 | chmod +x "/tmp/$FILENAME" 84 | sudo mv "/tmp/$FILENAME" "$INSTALL_DIR/$TOOL" 85 | 86 | if [[ "$TOOL" == "unified" ]]; then 87 | echo "Creating symlinks for CLI tools..." 88 | sudo ln -sf "$INSTALL_DIR/unified" "$INSTALL_DIR/kled" 89 | sudo ln -sf "$INSTALL_DIR/unified" "$INSTALL_DIR/kcluster" 90 | sudo ln -sf "$INSTALL_DIR/unified" "$INSTALL_DIR/kledspace" 91 | sudo ln -sf "$INSTALL_DIR/unified" "$INSTALL_DIR/kpolicy" 92 | fi 93 | 94 | echo "Installation complete!" 95 | echo "You can now use the $TOOL command." 96 | if [[ "$TOOL" == "unified" ]]; then 97 | echo "The following commands are also available: kled, kcluster, kledspace, kpolicy" 98 | fi 99 | -------------------------------------------------------------------------------- /web/src/components/shared/SharedCommandInterface.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Box, Heading, Text, Flex, Icon, Button } from '@chakra-ui/react'; 3 | import { FaTerminal, FaCubes, FaLayerGroup, FaShieldAlt } from 'react-icons/fa'; 4 | 5 | interface CommandProps { 6 | name: string; 7 | description: string; 8 | icon: React.ElementType; 9 | onClick?: () => void; 10 | } 11 | 12 | interface SharedCommandInterfaceProps { 13 | title: string; 14 | commands: CommandProps[]; 15 | onCommandSelect?: (commandName: string) => void; 16 | } 17 | 18 | /** 19 | * Shared component for displaying command interfaces across desktop and web apps 20 | * This component can be used in both the desktop app and web app to provide 21 | * a consistent interface for interacting with CLI commands 22 | */ 23 | export const SharedCommandInterface: React.FC = ({ 24 | title, 25 | commands, 26 | onCommandSelect 27 | }) => { 28 | const handleCommandClick = (commandName: string) => { 29 | if (onCommandSelect) { 30 | onCommandSelect(commandName); 31 | } 32 | }; 33 | 34 | return ( 35 | 36 | {title} 37 | 38 | 39 | {commands.map((command) => ( 40 | { 47 | handleCommandClick(command.name); 48 | if (command.onClick) command.onClick(); 49 | }} 50 | > 51 | 52 | 53 | 54 | {command.name} 55 | {command.description} 56 | 57 | 58 | 59 | ))} 60 | 61 | 62 | ); 63 | }; 64 | 65 | /** 66 | * Predefined command sets for each CLI interface 67 | * These can be imported and used in both desktop and web apps 68 | */ 69 | export const getKledCommands = (): CommandProps[] => [ 70 | { 71 | name: 'kled workspace create', 72 | description: 'Create a new development workspace', 73 | icon: FaTerminal 74 | }, 75 | { 76 | name: 'kled workspace list', 77 | description: 'List all available workspaces', 78 | icon: FaTerminal 79 | }, 80 | { 81 | name: 'kled workspace delete', 82 | description: 'Delete an existing workspace', 83 | icon: FaTerminal 84 | } 85 | ]; 86 | 87 | export const getKclusterCommands = (): CommandProps[] => [ 88 | { 89 | name: 'kcluster create', 90 | description: 'Create a new Kubernetes cluster', 91 | icon: FaCubes 92 | }, 93 | { 94 | name: 'kcluster connect', 95 | description: 'Connect to an existing cluster', 96 | icon: FaCubes 97 | }, 98 | { 99 | name: 'kcluster list', 100 | description: 'List all available clusters', 101 | icon: FaCubes 102 | } 103 | ]; 104 | 105 | export const getKledspaceCommands = (): CommandProps[] => [ 106 | { 107 | name: 'kledspace init', 108 | description: 'Initialize a new application space', 109 | icon: FaLayerGroup 110 | }, 111 | { 112 | name: 'kledspace deploy', 113 | description: 'Deploy an application to a space', 114 | icon: FaLayerGroup 115 | }, 116 | { 117 | name: 'kledspace list', 118 | description: 'List all available spaces', 119 | icon: FaLayerGroup 120 | } 121 | ]; 122 | 123 | export const getKpolicyCommands = (): CommandProps[] => [ 124 | { 125 | name: 'kpolicy validate', 126 | description: 'Validate policies against a cluster', 127 | icon: FaShieldAlt 128 | }, 129 | { 130 | name: 'kpolicy apply', 131 | description: 'Apply policies to a cluster', 132 | icon: FaShieldAlt 133 | }, 134 | { 135 | name: 'kpolicy list', 136 | description: 'List all available policies', 137 | icon: FaShieldAlt 138 | } 139 | ]; 140 | 141 | export default SharedCommandInterface; 142 | --------------------------------------------------------------------------------