Fix 500 error when creating applications#102
Merged
JoshuaAFerguson merged 30 commits intoNov 19, 2025
Merged
Conversation
When the ApplicationInstall CRD is not registered in the Kubernetes cluster, the InstallApplication handler now logs a warning and continues with the database record creation instead of returning a 500 error. This change: - Allows the API to work in development without the full K8s CRD setup - Provides a helpful message showing how to install the missing CRD - Still creates the database record so the UI can display applications - Maintains existing error handling for other K8s errors The user should install the CRD for full functionality: kubectl apply -f manifests/crds/applicationinstall.yaml
Planning documents for removing direct K8s dependencies from API: - K8S_CLIENT_REFACTORING_ANALYSIS.md - Technical analysis - K8S_CLIENT_REFACTORING_ROADMAP.md - Implementation plan - K8S_CLIENT_OPERATIONS_CHECKLIST.md - Operations checklist - README_K8S_CLIENT_ANALYSIS.md - Navigation guide These support the architectural change to make the API platform-agnostic so controllers can run sessions on K8s, Docker, Hyper-V, vCenter, etc.
This commit establishes the foundational infrastructure for removing direct Kubernetes dependencies from the API, enabling multi-platform support (Kubernetes, Docker, Hyper-V, vCenter). Changes: - Add NATS event architecture design document - Create events package with types, subjects, and publisher - Add NATS dependency to go.mod (v1.37.0) - Add database tables: platform_controllers, event_log - Add platform fields to installed_applications and sessions tables The API will publish events to NATS subjects, and platform-specific controllers will subscribe and perform the actual operations. This decouples the API from Kubernetes and allows multiple platform controllers to run simultaneously. Next steps: - Update API handlers to publish NATS events instead of direct K8s calls - Update controller to subscribe to NATS events - Add NATS to docker-compose for development
This commit updates the ApplicationHandler to use NATS event publishing instead of direct Kubernetes API calls, enabling multi-platform support. Changes: - ApplicationHandler now uses events.Publisher instead of k8s.Client - InstallApplication publishes AppInstallEvent to NATS - DeleteApplication publishes AppUninstallEvent to NATS - Added updateInstallStatus helper for tracking installation state - Initialize NATS publisher in main.go with config from environment - Platform is now configurable (kubernetes, docker, hyperv, vcenter) Environment variables: - NATS_URL: NATS server URL (optional, disables events if not set) - NATS_USER: NATS username for authentication - NATS_PASSWORD: NATS password for authentication - PLATFORM: Target platform (default: kubernetes) The API now publishes events that controllers subscribe to, completely decoupling the API from Kubernetes-specific operations.
Update API handlers to publish NATS events for platform-agnostic operation. This enables controllers to subscribe to events and perform platform-specific operations (Kubernetes, Docker, Hyper-V, vCenter). Changes: - Add NATS publisher and platform to Handler struct - Update CreateSession to publish SessionCreateEvent - Update UpdateSession to publish SessionHibernateEvent/SessionWakeEvent - Update DeleteSession to publish SessionDeleteEvent - Update CreateTemplate to publish TemplateCreateEvent - Update DeleteTemplate to publish TemplateDeleteEvent - Initialize NATS publisher in main.go with environment config This completes the API-side NATS integration for the event-driven architecture, moving Kubernetes operations toward the controller.
Update NodeHandler to publish NATS events for cordon, uncordon, and drain operations. This enables platform-specific controllers to handle node management operations. Changes: - Add NodeUncordonEvent type to events package - Add PublishNodeUncordon method to publisher - Update TemplateCreateEvent to use TemplateID field - Add publisher and platform to NodeHandler struct - Update CordonNode to publish NodeCordonEvent - Update UncordonNode to publish NodeUncordonEvent - Update DrainNode to publish NodeDrainEvent - Update main.go to pass publisher and platform to NodeHandler This continues the migration toward a platform-agnostic API that communicates with controllers via NATS events.
Update activity tracker to publish NATS events when auto-hibernating idle sessions. This ensures platform controllers are notified of hibernation events triggered by the idle monitor. Changes: - Add publisher and platform to activity.Tracker struct - Update NewTracker to accept publisher and platform parameters - Publish SessionHibernateEvent when auto-hibernating idle sessions - Update main.go to pass eventPublisher and platform to NewTracker This ensures consistent event publishing for all hibernation events, whether triggered by user action or automatic idle detection.
Update connection tracker to publish NATS events when auto-starting hibernated sessions and auto-hibernating idle sessions. This ensures platform controllers are notified of state changes triggered by the connection tracker. Changes: - Add publisher and platform to ConnectionTracker struct - Update NewConnectionTracker to accept publisher and platform - Publish SessionWakeEvent when auto-starting hibernated sessions - Publish SessionHibernateEvent when auto-hibernating idle sessions - Update main.go to pass eventPublisher and platform to tracker This provides consistent event publishing for all session state changes, whether triggered by user action or automatic connection tracking.
Implement NATS event subscription in the controller to receive events from the API and perform Kubernetes operations. This enables the event-driven architecture for multi-platform support. New files: - controller/pkg/events/subscriber.go - NATS connection and subscription - controller/pkg/events/types.go - Event type definitions matching API - controller/pkg/events/handlers.go - Event handlers for K8s operations Controller changes: - Add NATS configuration flags (--nats-url, --nats-user, --nats-password) - Add namespace and controller-id flags for event routing - Initialize NATS subscriber after manager creation - Start subscriber in background goroutine Event handlers implemented: - Session: create, delete, hibernate, wake - Application: install, uninstall - Template: create, delete (passthrough for now) - Node: cordon, uncordon, drain The controller now can receive events via NATS in addition to watching CRDs directly, enabling future migration to pure event-driven operation.
- Add NATS with JetStream to docker-compose for local development - Create complete Docker platform controller with container lifecycle management - Add JetStream streams for durable event delivery (sessions, apps, templates, nodes, controllers) - Docker controller subscribes to platform-specific NATS subjects - Support for session create, delete, hibernate, and wake operations via Docker API
- Create subscriber.go to receive session and app status events - Update main.go to initialize and start the subscriber - API now updates database when controllers publish status changes - Completes the event-driven feedback loop for multi-platform support
- Create SessionDB with comprehensive session management methods - Add database migrations for new session fields (pod_name, memory, cpu, etc.) - Update ListSessions and GetSession to use database with k8s fallback - Add conversion functions for database sessions to API response format - Update cacheSessionInDB to use SessionDB for consistency This enables platform-agnostic session queries from the database, with automatic fallback to Kubernetes for backward compatibility.
…ecture Add comprehensive development scripts for the new NATS-based multi-platform architecture: New scripts: - docker-dev.sh: Start Docker Compose environment with NATS/PostgreSQL - docker-dev-stop.sh: Stop development environment with cleanup options - build-docker-controller.sh: Build Docker platform controller image - test-nats.sh: Test NATS connectivity, publish/subscribe events Updated scripts: - local-build.sh: Add Docker controller image build - local-teardown.sh: Add Docker controller image cleanup - local-port-forward.sh: Add NATS port forwarding support - README.md: Document new Docker Compose development workflow
…orm clarity Rename the Kubernetes controller to explicitly reflect its platform-specific role in the new multi-platform NATS architecture: - Image: streamspace/streamspace-controller → streamspace/streamspace-kubernetes-controller - Controller ID: streamspace-controller-1 → streamspace-kubernetes-controller-1 - NATS client name: streamspace-controller → streamspace-kubernetes-controller Updates across: - chart/values.yaml: Controller image repository and documentation - controller/cmd/main.go: Default controller ID - controller/pkg/events/subscriber.go: NATS connection name - scripts/local-build.sh: Build function and image names - scripts/local-deploy.sh: Image check list - scripts/local-teardown.sh: Image cleanup list This change distinguishes the Kubernetes platform controller from the Docker platform controller (docker-controller/) in the event-driven architecture.
Rename the Kubernetes controller directory to explicitly identify it as the Kubernetes-specific platform controller in the multi-platform architecture. Directory change: - controller/ → k8s-controller/ Updated references in: - CLAUDE.md: Repository structure documentation - DEPLOYMENT.md: Deployment instructions - MIGRATION_SUMMARY.md: Directory structure - scripts/local-build.sh: Build context paths This change complements the image rename (streamspace-kubernetes-controller) and clearly distinguishes the Kubernetes controller from the Docker controller (docker-controller/) in the NATS-based multi-platform architecture.
…roller image name - Update all path references from controller/ to k8s-controller/ - Rename image from streamspace-controller to streamspace-kubernetes-controller - Update matrix components in security-scan.yml to use k8s-controller - Update build contexts, cache keys, and artifact names
- Add multi-platform support as core feature (Kubernetes, Docker) - Update architecture diagrams to show NATS JetStream messaging - Add Docker controller documentation and development instructions - Update all controller references from controller/ to k8s-controller/ - Add new development scripts (docker-dev.sh, test-nats.sh) - Update Troubleshooting to reference kubernetes-controller deployment
Add DeepCopyInto, DeepCopy, and DeepCopyObject methods for ApplicationInstall, ApplicationInstallList, ApplicationInstallSpec, and ApplicationInstallStatus types to fix build error where ApplicationInstall did not implement runtime.Object interface.
- Replace undefined streamv1alpha1.ResourceSpec with corev1.ResourceRequirements - Use proper resource.MustParse for memory and CPU values - Change IconURL field to Icon to match ApplicationInstallSpec
- Use TemplateName instead of TemplateID in TemplateDeleteEvent (API's event type uses TemplateName, not TemplateID) - Remove unused fmt import from applications.go
The docker-controller was missing go.sum file causing build failures. Updated Dockerfile to copy source first then run go mod tidy to generate the missing go.sum before building.
- Add types and volume package imports - Use string "unless-stopped" for RestartPolicy (not constant) - Use types.ContainerStartOptions instead of container.StartOptions - Use types.ContainerRemoveOptions instead of container.RemoveOptions - Use types.ContainerListOptions instead of container.ListOptions - Use volume.CreateOptions from proper import - Remove dummy volume struct
Cache middleware was generating cache keys using only the request URI, causing all users to receive the same cached response for user-specific endpoints like /applications/user. Now includes userID from auth context in cache key generation, ensuring each user gets their own cached response for endpoints that return user-specific data.
Ensure configuration JSON is passed as string instead of []byte to PostgreSQL JSONB columns to prevent "invalid syntax for type json" errors.
Prevent caching of X-CSRF-Token, Set-Cookie, Authorization, and X-Request-Id headers to avoid CSRF token mismatches and other security issues when serving cached responses. This fixes 403 Forbidden errors caused by stale CSRF tokens being returned from cached responses.
Use sql.NullInt64 to properly handle NULL catalog_template_id values when scanning from the database. This fixes false 404 errors when deleting or getting applications that have NULL foreign key references.
Add server-side session management to address security concern where JWT tokens persist after application restart. Changes: - Create SessionStore for tracking active sessions in Redis - Modify JWT generation to include session ID (jti claim) - Store session metadata (user, IP, user-agent) on token creation - Validate sessions against Redis store in auth middleware - Invalidate sessions on logout (DELETE from Redis) - Clear all sessions on application startup (force re-login) This enables: - True logout (immediate session invalidation) - Forced re-authentication after server restart - Ability to revoke all sessions for a user - Session audit trail (IP, user-agent tracking) The implementation gracefully degrades when Redis is unavailable.
Add user-specific endpoints to the no-cache list in CacheControl middleware to prevent stale browser-cached responses. Added endpoints: - /api/v1/applications/user - User's installed applications - /api/v1/dashboard/me - User dashboard - /api/v1/notifications - User notifications - /api/v1/preferences - User preferences These endpoints return user-specific data that should not be cached by the browser as it can lead to stale data being displayed.
Add more specific error messages that include the app ID and wrap database errors to help diagnose the DELETE 404 issue.
The pq driver for PostgreSQL requires JSONB columns to be scanned into string types, not []byte. Changed configJSON from []byte to sql.NullString to properly handle the configuration column and NULL values. This fixes the "pq: invalid input syntax for type json" error when retrieving applications for DELETE operations.
| - streamspace | ||
|
|
||
| # NATS message broker for event-driven architecture | ||
| nats: |
Check warning
Code scanning / Semgrep OSS
Semgrep Finding: yaml.docker-compose.security.no-new-privileges.no-new-privileges Warning
| - streamspace | ||
|
|
||
| # NATS message broker for event-driven architecture | ||
| nats: |
Check warning
Code scanning / Semgrep OSS
Semgrep Finding: yaml.docker-compose.security.writable-filesystem-service.writable-filesystem-service Warning
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.