watchtower
watchtower copied to clipboard
Added web dashboard
Hi! I hope this feature can be of some use, and if it's out of scope for this project - that's ok.
This PR introduces a couple of new things to the HTTP part of Watchtower: a List and Check API endpoint and a Dashboard endpoint that serves a small React web application. The application is authenticating with the API token and offers a list of all running containers. The user can perform an update check and then select one or more containers to manually update.
I had to make some minor changes to the existing code to allow for this functionality, but the changes should hopefully not impact any other features in Watchtower.
Let me know what you think!
-
What your PR contributes I have created a simple web dashboard and extended the existing HTTP API to allow users to check for and perform updates using a browser.
-
Which issues it solves (preferrably using auto closing instructions like "closes #123". None, that I know of.
-
Tests that verify the code your contributing I was unsure of how to add tests since it would probably involve mocking some new classes.
-
Updates to the documentation I have updated the arguments.md file, but maybe this feature should be documented in more places.
This looks really nice! I would probably prefer the frontend stuff to be moved to it's own repo though. Not sure about what to do with the distribution though... @simskij, thoughts?
Codecov Report
Base: 64.76% // Head: 64.54% // Decreases project coverage by -0.21%
:warning:
Coverage data is based on head (
ee9475b
) compared to base (d744c34
). Patch coverage: 28.00% of modified lines in pull request are covered.
:exclamation: Current head ee9475b differs from pull request most recent head 4b494de. Consider uploading reports for the commit 4b494de to get more accurate results
Additional details and impacted files
@@ Coverage Diff @@
## main #1468 +/- ##
==========================================
- Coverage 64.76% 64.54% -0.22%
==========================================
Files 24 24
Lines 2310 2327 +17
==========================================
+ Hits 1496 1502 +6
- Misses 718 729 +11
Partials 96 96
Impacted Files | Coverage Δ | |
---|---|---|
pkg/api/api.go | 30.00% <0.00%> (-8.47%) |
:arrow_down: |
pkg/container/client.go | 31.84% <0.00%> (ø) |
|
internal/actions/update.go | 70.98% <100.00%> (ø) |
|
internal/flags/flags.go | 85.87% <100.00%> (+0.15%) |
:arrow_up: |
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.
:umbrella: View full report at Codecov.
:loudspeaker: Do you have feedback about the report comment? Let us know in this issue.
Love it! I think we can keep it in this repo. Since we, for all intents and purposes, are using the Go Standard Project Layout i would put the frontend stuff in /web
.
Thanks for the comments!
I have moved the static files to /web/static
.
Let me know if you have any more feedback.
Why are you not using a package.json and including the dependencies as static libs?
If the content are to be included in the container image they should probably be processed by webpack/vite instead of relying on babel loader in the web browser, but I have not measured the performance hit. Right now it's relying on the contents being contained in the source directory, but it should probably be something like /www/
in the container instead.
It also seems like localhost
and the port is hard-coded into the API builder, which would only work when testing locally.
Thanks for the feedback @piksel!
Why are you not using a package.json and including the dependencies as static libs? If the content are to be included in the container image they should probably be processed by webpack/vite instead of relying on babel loader in the web browser, but I have not measured the performance hit.
I chose not to use npm in an effort to reduce the overall complexity of the PR. Ideally, for larger projects, I agree that one should use a package manager. I would also use Typescript and a module loader, and compile the code to minified JS at build time.
If you can help me to integrate npm into the GO build (or the CI pipeline, if you have one?), and don't mind the extra overhead to maintain, I can take a stab at implementing it.
Right now it's relying on the contents being contained in the source directory, but it should probably be something like /www/ in the container instead.
I'm guessing that there needs to be some modifications to the Dockerfiles, could you give me some pointers on how to accomplish this? Maybe the new port should be exposed as well.
It also seems like localhost and the port is hard-coded into the API builder, which would only work when testing locally.
That's a good point. I will push a commit to fix this.
I made an attempt to make the API URL also work in non-local environments. Please forgive my Go skills, I haven't used it before... :)
I chose not to use npm in an effort to reduce the overall complexity of the PR. Ideally, for larger projects, I agree that one should use a package manager.
Yeah, that is why I initially wanted to move it to it's own repo. But I think that keeping static versions of dependencies that cannot be checked or updated by dependency bot is probably worse.
I can add the Dockerimage and CI integrations if you want.
I made an attempt to make the API URL also work in non-local environments. Please forgive my Go skills, I haven't used it before... :)
Check the Codacy Analysis for some hints. It's mainly the GO naming convention (acronyms in caps) and adding comments starting with the function name for publicly exposed functions.
I chose not to use npm in an effort to reduce the overall complexity of the PR. Ideally, for larger projects, I agree that one should use a package manager.
Yeah, that is why I initially wanted to move it to it's own repo. But I think that keeping static versions of dependencies that cannot be checked or updated by dependency bot is probably worse.
I can add the Dockerimage and CI integrations if you want.
That would be great.
I will start working on implementing a package manager and bundler. Was looking at Vite (https://vitejs.dev/), do you have any experience with that? Or any other preferences?
Added Vite to build the web app. Run npm run dev
to start the dev server and npm run build
to package for production.
The bundled assets are currently placed in /web/dist/
.
Currently when the API is checking for updates it also pulls any new images. This could take some time, and I was wondering if it would be better UX to skip the pull, and postpone it to the actual update.
What do you think @piksel @simskij - can you suggest how I should modify the client class in this case? Maybe expose a new function that skips the check, adding an extra argument seems counter intuitive.
Currently when the API is checking for updates it also pulls any new images. This could take some time, and I was wondering if it would be better UX to skip the pull, and postpone it to the actual update.
If the container repository supports HEAD requests we could do an early bail without pulling, but it would require making sure that we don't break the regular updates (since previously, the updates "knew" that the newest image was always pulled before updating).
We can do that as a separate PR though...
Currently when the API is checking for updates it also pulls any new images. This could take some time, and I was wondering if it would be better UX to skip the pull, and postpone it to the actual update.
If the container repository supports HEAD requests we could do an early bail without pulling, but it would require making sure that we don't break the regular updates (since previously, the updates "knew" that the newest image was always pulled before updating).
We can do that as a separate PR though...
My initial thought was that we could just skip the pull in IsContainerStale
but what you are saying is that HasNewImage
relies on the image being already pulled?
I took a shot at extracting a digest matching function ContainerDigestMatchesWithRegistry
in client.go
, and now the update check uses that instead of pulling the new images. If the digest check is not available, it uses the previous function IsContainerStale
as a fallback.
Sorry for not keeping up with this, I have been busy with work. I will help get this merged as soon as I get some free time :)
Woohoo. Looks great!
Any update on this ?
This PR currently make some changes to the API that affects other functions of watchtower. I started working on splitting the new functionality out to new APIs, but it grew kind of large. I will try to take another look during the summer holidays.
This PR currently make some changes to the API that affects other functions of watchtower. I started working on splitting the new functionality out to new APIs, but it grew kind of large. I will try to take another look during the summer holidays.
No problem take your time, it would be just very to have it
Hello @piksel What is the status of this PR ? If you need, I can help you to work on the API splitting
@piksel are you still looking to get around to this or should we open it up for contributions from others?