Conversation
|
Oh, I expected the fix to be in ddev-mongo! So wonderful that we have tests using this from so many angles. |
|
Download the artifacts for this pull request:
See Testing a PR. |
| // Add potential ports that might not be in use by current containers | ||
| // 8142/8143 are for xhgui, which might not be enabled, but we don't want to | ||
| // have to rebuild traefik when it does get enabled. | ||
| routerPorts = []string{nodeps.DdevDefaultXHGuiHTTPSPort, nodeps.DdevDefaultXHGuiHTTPPort} |
There was a problem hiding this comment.
This PR makes port detection dynamic, so we no longer need to hardcode XHGui.
Though if the service isn't started, it's unclear why the ports should be occupied.
But this comment gives some justification:
we don't want to have to rebuild traefik when it does get enabled.
What I see is that if we don't add xhgui all the time, then the project configuration in .ddev/traefik/config/<project>.yaml won't work as expected for people removing #ddev-generated from that file.
I didn't look deep into it.
rfay
left a comment
There was a problem hiding this comment.
I haven't studied this carefully, but this seems like an important improvement that needs a test?
There was a problem hiding this comment.
I spent some time with this and stepped through and it all seems good to me.
The one TODO if you think it's appropriate is to see if a test can be added. If you think the xhgui stuff is testing it adequately, that's OK.
Below is Claude's opinion. Seems all fine.
Overview
This PR addresses router health issues with optional services by improving Traefik entrypoint port discovery and optimizing YAML file writes. The changes fix the issue where the router wasn't becoming healthy due to missing entrypoints for services defined in project configurations but not yet running.
Key Changes
1. Enhanced Port Discovery (pkg/ddevapp/router.go:341-418)
Strengths:
- Comprehensive port detection: Now reads from both project configuration files AND running containers, fixing the core issue where optional services weren't detected
- Cleaner code structure: Extracted
processExposePorts()helper function for better maintainability - Robust error handling: Continues processing other projects if one fails to read
- Better documentation: Clear comments explaining the port mapping logic
Technical details:
- Calls
ReadDockerComposeYAML()for all active projects to extract HTTP_EXPOSE/HTTPS_EXPOSE from service environments - Properly handles pointer dereferencing for environment variables
- Maintains existing behavior for running containers while adding configuration-based discovery
2. YAML Write Optimization (pkg/ddevapp/compose_yaml.go:19-132)
Strengths:
- Performance improvement: Avoids unnecessary file writes when content is unchanged using
bytes.Equal() - Maintains atomicity: Still uses proper file creation/closing patterns
- Added ReadDockerComposeYAML(): New function to read compose files, supporting the router port discovery
Technical details:
- Implements content comparison before writing both base and full YAML files
- Uses
bytes.Equal()instead of string comparison for better performance - Preserves existing error handling and file closing patterns
3. File Utility Enhancement (pkg/fileutil/embed.go:46-49)
Strengths:
- Consistency: Uses same
bytes.Equal()optimization pattern - Minor but effective: Removes unnecessary string conversion
Code Quality Assessment
Positive aspects:
- ✅ Passes all static analysis (
make staticrequired) - ✅ Follows existing code patterns and conventions
- ✅ Proper error handling throughout
- ✅ Clear, descriptive function and variable names
- ✅ Good separation of concerns with the new helper function
Areas that could be improved:
- The
determineRouterPorts()function is getting quite long (70+ lines). Consider splitting the config-based and container-based logic into separate functions - Could benefit from unit tests for
processExposePorts()function - The error handling for
ReadDockerComposeYAML()usesutil.Warning()but continues - consider if this is the right approach
Testing Considerations
The PR description provides good manual testing instructions. However, automated tests would strengthen confidence:
Suggested tests:
- Unit test for
processExposePorts()with various port formats - Integration test verifying port discovery from stopped services
- Test for YAML write optimization (verify files aren't rewritten when unchanged)
Impact Analysis
Positive impacts:
- ✅ Fixes router health issues with optional services (addresses ddev/ddev-mongo#24)
- ✅ Reduces unnecessary disk I/O through YAML write optimization
- ✅ More reliable port discovery for Traefik configuration
- ✅ Better user experience with optional add-ons
Risk assessment:
- 🟡 Low risk: Changes are primarily additive, maintaining backward compatibility
- 🟡 Performance: Additional file reads for all active projects during router startup (acceptable trade-off)
Recommendation
✅ APPROVE with minor suggestions
This is a well-implemented fix that solves a real problem. The code quality is good, follows established patterns, and the optimizations are beneficial. The approach of reading project configurations in addition to running containers is the right solution for detecting optional services.
Minor suggestions for follow-up:
- Consider splitting
determineRouterPorts()for better maintainability - Add unit tests for the new
processExposePorts()function - Consider caching the project configuration reads if this becomes a performance concern
The PR successfully addresses the core issue and includes valuable optimizations as a bonus.
b77b4ca to
426b0b4
Compare
Done with Claude Code.
I modified
|
|
It's picking up the |
🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
NOT debugged or fixed by Claude :)
I should have added this years ago, as I often run using the ddev from the path. But for this particular setup I needed things to work with direnv and GoLand, and I couldn't know what was working without this change.
426b0b4 to
ecd1220
Compare
rfay
left a comment
There was a problem hiding this comment.
It's still great, thanks, and thanks for understanding, studying, and solving this, and caring for ddev-mongo.
I wonder if this means that we could now start/restart traefik before everything else is up and ready, which might slightly improve user experience. (Related idea: Most people in most situations don't really need to wait for everything to be fully ready. We might want to give them an out like "press return to get to work")
This is possible, most likely requires moving all dynamic Traefik configuration to the start of |
The Issue
Router doesn't become healthy because of missing Traefik entrypoints for optional services.
How This PR Solves The Issue
.ddev/.ddev-docker-compose-full.yaml.ddev/.ddev-docker-compose-base.yamland.ddev/.ddev-docker-compose-full.yamlif the content is not changed.Manual Testing Instructions
Start a project with optional profiles:
Check
~/.ddev/traefik/.static_config.yaml:Automated Testing Overview
Release/Deployment Notes