watchtower icon indicating copy to clipboard operation
watchtower copied to clipboard

Added web dashboard

Open AndersSahlin opened this issue 2 years ago • 22 comments

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!

Log in page

Container list

Container has update

Updating containers

Everything updated

  • 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.

AndersSahlin avatar Nov 10 '22 22:11 AndersSahlin

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?

piksel avatar Nov 11 '22 09:11 piksel

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.

codecov[bot] avatar Nov 11 '22 09:11 codecov[bot]

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.

simskij avatar Nov 11 '22 09:11 simskij

Thanks for the comments!

I have moved the static files to /web/static.

Let me know if you have any more feedback.

AndersSahlin avatar Nov 11 '22 11:11 AndersSahlin

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.

piksel avatar Nov 11 '22 15:11 piksel

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.

AndersSahlin avatar Nov 12 '22 10:11 AndersSahlin

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... :)

AndersSahlin avatar Nov 13 '22 20:11 AndersSahlin

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.

piksel avatar Nov 14 '22 08:11 piksel

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.

piksel avatar Nov 14 '22 08:11 piksel

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?

AndersSahlin avatar Nov 14 '22 12:11 AndersSahlin

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/.

AndersSahlin avatar Nov 14 '22 23:11 AndersSahlin

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.

AndersSahlin avatar Nov 16 '22 21:11 AndersSahlin

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...

piksel avatar Nov 18 '22 09:11 piksel

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?

AndersSahlin avatar Nov 18 '22 10:11 AndersSahlin

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.

AndersSahlin avatar Nov 27 '22 17:11 AndersSahlin

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 :)

piksel avatar Nov 28 '22 10:11 piksel

Woohoo. Looks great!

MajorTomDE avatar Dec 31 '22 14:12 MajorTomDE

Any update on this ?

Gauvino avatar Jun 24 '23 12:06 Gauvino

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.

piksel avatar Jun 26 '23 09:06 piksel

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

Gauvino avatar Jun 26 '23 10:06 Gauvino

Hello @piksel What is the status of this PR ? If you need, I can help you to work on the API splitting

GridexX avatar Jul 27 '23 09:07 GridexX

@piksel are you still looking to get around to this or should we open it up for contributions from others?

simskij avatar Nov 13 '23 16:11 simskij