mirror of
https://github.com/amir20/dozzle.git
synced 2026-08-07 17:31:57 +00:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8055512bc4 | |||
| 61f26b7bc3 | |||
| e6528a7fc1 | |||
| 378de1a12b | |||
| c803fe3119 | |||
| 0e1541b78d | |||
| 1d14c6c6e7 | |||
| b78b70b233 | |||
| f9465a2d66 | |||
| a5da85d603 | |||
| 2140fe3d37 | |||
| ff2e766324 | |||
| 336e8acd0b | |||
| a6c2c7dbbc | |||
| 8d844b4302 | |||
| ac66969126 | |||
| b896e16941 | |||
| 5b1b2463b0 | |||
| 07d0c7fac5 | |||
| d2d573c399 | |||
| 54ad9d094b | |||
| afb9bc971c | |||
| 3e0d010390 | |||
| 76e5b960aa | |||
| 152bdb8c8f | |||
| 77e49d132f | |||
| 3fe087935c | |||
| b47cf7940a | |||
| 420b398e50 | |||
| 91d79c99ea | |||
| 28c2cdc571 | |||
| d67f2da1ba | |||
| a99672a5da | |||
| eefa472516 | |||
| 11cde3d5fc |
@@ -31,7 +31,7 @@ jobs:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.21.x
|
||||
go-version: 1.22.x
|
||||
check-latest: true
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
@@ -84,7 +84,7 @@ jobs:
|
||||
with:
|
||||
images: amir20/dozzle
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
|
||||
uses: docker/setup-buildx-action@0d103c3126aa41d772a8362f6aa67afac040f80c # v3.1.0
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v3.0.0
|
||||
with:
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
with:
|
||||
images: amir20/dozzle
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
|
||||
uses: docker/setup-buildx-action@0d103c3126aa41d772a8362f6aa67afac040f80c # v3.1.0
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v3.0.0
|
||||
with:
|
||||
|
||||
@@ -54,7 +54,7 @@ jobs:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.21.x
|
||||
go-version: 1.22.x
|
||||
check-latest: true
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
@@ -93,19 +93,21 @@ If you do not want to be tracked at all, see the `--no-analytics` flag below.
|
||||
|
||||
Dozzle follows the [12-factor](https://12factor.net/) model. Configurations can use the CLI flags or environment variables. The table below outlines all supported options and their respective env vars.
|
||||
|
||||
| Flag | Env Variable | Default |
|
||||
| ---------------- | ---------------------- | ------- |
|
||||
| `--addr` | `DOZZLE_ADDR` | `:8080` |
|
||||
| `--base` | `DOZZLE_BASE` | `/` |
|
||||
| `--hostname` | `DOZZLE_HOSTNAME` | `""` |
|
||||
| `--level` | `DOZZLE_LEVEL` | `info` |
|
||||
| `--filter` | `DOZZLE_FILTER` | `""` |
|
||||
| `--username` | `DOZZLE_USERNAME` | `""` |
|
||||
| `--password` | `DOZZLE_PASSWORD` | `""` |
|
||||
| `--usernamefile` | `DOZZLE_USERNAME_FILE` | `""` |
|
||||
| `--passwordfile` | `DOZZLE_PASSWORD_FILE` | `""` |
|
||||
| `--no-analytics` | `DOZZLE_NO_ANALYTICS` | false |
|
||||
| `--remote-host` | `DOZZLE_REMOTE_HOST` | |
|
||||
| Flag | Env Variable | Default |
|
||||
| --------------------------- | -------------------------------- | -------------- |
|
||||
| `--addr` | `DOZZLE_ADDR` | `:8080` |
|
||||
| `--base` | `DOZZLE_BASE` | `/` |
|
||||
| `--hostname` | `DOZZLE_HOSTNAME` | `""` |
|
||||
| `--level` | `DOZZLE_LEVEL` | `info` |
|
||||
| `--auth-provider` | `DOZZLE_AUTH_PROVIDER` | `none` |
|
||||
| `--auth-header-user` | `DOZZLE_AUTH_HEADER_USER` | `Remote-User` |
|
||||
| `--auth-header-email` | `DOZZLE_AUTH_HEADER_EMAIL` | `Remote-Email` |
|
||||
| `--auth-header-name` | `DOZZLE_AUTH_HEADER_NAME` | `Remote-Name` |
|
||||
| `--enable-actions` | `DOZZLE_ENABLE_ACTIONS` | false |
|
||||
| `--wait-for-docker-seconds` | `DOZZLE_WAIT_FOR_DOCKER_SECONDS` | 0 |
|
||||
| `--filter` | `DOZZLE_FILTER` | `""` |
|
||||
| `--no-analytics` | `DOZZLE_NO_ANALYTICS` | false |
|
||||
| `--remote-host` | `DOZZLE_REMOTE_HOST` | |
|
||||
|
||||
## Support
|
||||
|
||||
|
||||
@@ -129,6 +129,7 @@ const sortedContainers = computedWithControl(
|
||||
const totalPages = computed(() => Math.ceil(sortedContainers.value.length / perPage.value));
|
||||
const isPaginated = computed(() => totalPages.value > 1);
|
||||
const currentPage = ref(1);
|
||||
watch(perPage, () => (currentPage.value = 1));
|
||||
const paginated = computed(() => {
|
||||
const start = (currentPage.value - 1) * perPage.value;
|
||||
const end = start + perPage.value;
|
||||
|
||||
@@ -73,7 +73,7 @@ describe("<FuzzySearchModal />", () => {
|
||||
test("choose baz", async () => {
|
||||
const wrapper = createFuzzySearchModal();
|
||||
await wrapper.find("input").setValue("baz");
|
||||
await wrapper.find("input").trigger("keyup.enter");
|
||||
await wrapper.find("input").trigger("keydown.enter");
|
||||
expect(useRouter().push).toHaveBeenCalledWith({ name: "container-id", params: { id: "567" } });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<mdi:magnify class="flex size-8" />
|
||||
<input
|
||||
tabindex="0"
|
||||
class="input input-ghost input-lg flex-1 px-1"
|
||||
class="input input-lg input-ghost flex-1 px-1"
|
||||
ref="input"
|
||||
@keyup.down="selectedIndex = Math.min(selectedIndex + 1, data.length - 1)"
|
||||
@keyup.up="selectedIndex = Math.max(selectedIndex - 1, 0)"
|
||||
@keyup.enter.exact="selected(data[selectedIndex].item)"
|
||||
@keyup.alt.enter="addColumn(data[selectedIndex])"
|
||||
@keydown.down="selectedIndex = Math.min(selectedIndex + 1, data.length - 1)"
|
||||
@keydown.up="selectedIndex = Math.max(selectedIndex - 1, 0)"
|
||||
@keydown.enter.exact="selected(data[selectedIndex].item)"
|
||||
@keydown.alt.enter="addColumn(data[selectedIndex])"
|
||||
v-model="query"
|
||||
:placeholder="$t('placeholder.search-containers')"
|
||||
/>
|
||||
@@ -148,4 +148,8 @@ function matchedName({ item, matches = [] }: { item: { name: string }; matches?:
|
||||
:deep(mark) {
|
||||
@apply bg-transparent text-inherit underline underline-offset-2;
|
||||
}
|
||||
|
||||
.menu a {
|
||||
@apply transition-none duration-0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -40,7 +40,7 @@ const onMouseLeave = () => {
|
||||
glopbalShow.value = false;
|
||||
};
|
||||
|
||||
const el = useCurrentElement();
|
||||
const el: Ref<HTMLElement> = useCurrentElement();
|
||||
useEventListener(() => el.value?.nextElementSibling, "mouseenter", onMouseEnter);
|
||||
useEventListener(() => el.value?.nextElementSibling, "mouseleave", onMouseLeave);
|
||||
</script>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div>
|
||||
<mobile-menu v-if="isMobile" @search="showFuzzySearch"></mobile-menu>
|
||||
<mobile-menu v-if="isMobile && !forceMenuHidden" @search="showFuzzySearch"></mobile-menu>
|
||||
<splitpanes @resized="onResized($event)">
|
||||
<pane min-size="10" :size="menuWidth" v-if="!isMobile && !collapseNav">
|
||||
<pane min-size="10" :size="menuWidth" v-if="!isMobile && !collapseNav && !forceMenuHidden">
|
||||
<side-panel @search="showFuzzySearch"></side-panel>
|
||||
</pane>
|
||||
<pane min-size="10">
|
||||
@@ -27,7 +27,7 @@
|
||||
<label
|
||||
class="btn btn-circle swap btn-neutral swap-rotate fixed -left-12 bottom-4 w-16 transition-all hover:-left-4"
|
||||
:class="{ '!-left-6': collapseNav }"
|
||||
v-if="!isMobile"
|
||||
v-if="!isMobile && !forceMenuHidden"
|
||||
>
|
||||
<input type="checkbox" v-model="collapseNav" />
|
||||
<mdi:chevron-right class="swap-on" />
|
||||
@@ -79,6 +79,8 @@ const { toasts, removeToast } = useToast();
|
||||
|
||||
const modal = ref<HTMLDialogElement>();
|
||||
const open = ref(false);
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
const forceMenuHidden = ref(searchParams.has("hideMenu"));
|
||||
|
||||
watch(open, () => {
|
||||
if (open.value) {
|
||||
|
||||
@@ -47,6 +47,7 @@ let error = $ref(false);
|
||||
let username = $ref("");
|
||||
let password = $ref("");
|
||||
let form: HTMLFormElement | undefined = $ref();
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
|
||||
async function onLogin() {
|
||||
const url = config.authProvider === "simple" ? "/api/token" : "/api/validateCredentials";
|
||||
@@ -57,7 +58,11 @@ async function onLogin() {
|
||||
|
||||
if (response.status == 200) {
|
||||
error = false;
|
||||
window.location.href = withBase("/");
|
||||
if (params.has("redirectUrl")) {
|
||||
window.location.href = withBase(params.get("redirectUrl")!);
|
||||
} else {
|
||||
window.location.href = withBase("/");
|
||||
}
|
||||
} else {
|
||||
error = true;
|
||||
}
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ services:
|
||||
|
||||
playwright:
|
||||
container_name: playwright
|
||||
image: mcr.microsoft.com/playwright:v1.41.2-jammy
|
||||
image: mcr.microsoft.com/playwright:v1.42.1-jammy
|
||||
working_dir: /app
|
||||
volumes:
|
||||
- .:/app
|
||||
|
||||
@@ -17,19 +17,20 @@ require (
|
||||
github.com/sergi/go-diff v1.1.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/spf13/afero v1.11.0
|
||||
github.com/stretchr/objx v0.5.0 // indirect
|
||||
github.com/stretchr/testify v1.8.4
|
||||
golang.org/x/net v0.20.0 // indirect
|
||||
golang.org/x/sys v0.16.0 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.9.0
|
||||
golang.org/x/net v0.21.0 // indirect
|
||||
golang.org/x/sys v0.17.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/PuerkitoBio/goquery v1.8.1
|
||||
github.com/go-chi/chi/v5 v5.0.11
|
||||
github.com/PuerkitoBio/goquery v1.9.1
|
||||
github.com/go-chi/chi/v5 v5.0.12
|
||||
github.com/go-chi/jwtauth/v5 v5.3.0
|
||||
github.com/go-logfmt/logfmt v0.6.0
|
||||
github.com/puzpuzpuz/xsync/v3 v3.0.2
|
||||
github.com/goccy/go-json v0.10.2
|
||||
github.com/puzpuzpuz/xsync/v3 v3.1.0
|
||||
github.com/yuin/goldmark v1.7.0
|
||||
)
|
||||
|
||||
@@ -43,7 +44,6 @@ require (
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/go-logr/logr v1.4.1 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/kr/pretty v0.2.1 // indirect
|
||||
github.com/lestrrat-go/blackmagic v1.0.2 // indirect
|
||||
github.com/lestrrat-go/httpcc v1.0.1 // indirect
|
||||
@@ -60,7 +60,7 @@ require (
|
||||
go.opentelemetry.io/otel/metric v1.22.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.22.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.22.0 // indirect
|
||||
golang.org/x/crypto v0.18.0 // indirect
|
||||
golang.org/x/crypto v0.19.0 // indirect
|
||||
golang.org/x/mod v0.14.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/tools v0.17.0 // indirect
|
||||
|
||||
@@ -4,6 +4,10 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc
|
||||
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||
github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM=
|
||||
github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ=
|
||||
github.com/PuerkitoBio/goquery v1.9.0 h1:zgjKkdpRY9T97Q5DCtcXwfqkcylSFIVCocZmn2huTp8=
|
||||
github.com/PuerkitoBio/goquery v1.9.0/go.mod h1:cW1n6TmIMDoORQU5IU/P1T3tGFunOeXEpGP2WHRwkbY=
|
||||
github.com/PuerkitoBio/goquery v1.9.1 h1:mTL6XjbJTZdpfL+Gwl5U2h1l9yEkJjhmlTeV9VPW7UI=
|
||||
github.com/PuerkitoBio/goquery v1.9.1/go.mod h1:cW1n6TmIMDoORQU5IU/P1T3tGFunOeXEpGP2WHRwkbY=
|
||||
github.com/alexflint/go-arg v1.4.3 h1:9rwwEBpMXfKQKceuZfYcwuc/7YY7tWJbFsgG5cAU/uo=
|
||||
github.com/alexflint/go-arg v1.4.3/go.mod h1:3PZ/wp/8HuqRZMUUgu7I+e1qcpUbvmS258mRXkFH4IA=
|
||||
github.com/alexflint/go-scalar v1.1.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o=
|
||||
@@ -42,6 +46,8 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/go-chi/chi/v5 v5.0.11 h1:BnpYbFZ3T3S1WMpD79r7R5ThWX40TaFB7L31Y8xqSwA=
|
||||
github.com/go-chi/chi/v5 v5.0.11/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s=
|
||||
github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/jwtauth/v5 v5.3.0 h1:X7RKGks1lrVeIe2omGyz47pNaNjG2YmwlRN5UKhN8qg=
|
||||
github.com/go-chi/jwtauth/v5 v5.3.0/go.mod h1:2PoGm/KbnzRN9ILY6HFZAI6fTnb1gEZAKogAyqkd6fY=
|
||||
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
|
||||
@@ -101,6 +107,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/puzpuzpuz/xsync/v3 v3.0.2 h1:3yESHrRFYr6xzkz61LLkvNiPFXxJEAABanTQpKbAaew=
|
||||
github.com/puzpuzpuz/xsync/v3 v3.0.2/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
|
||||
github.com/puzpuzpuz/xsync/v3 v3.1.0 h1:EewKT7/LNac5SLiEblJeUu8z5eERHrmRLnMQL2d7qX4=
|
||||
github.com/puzpuzpuz/xsync/v3 v3.1.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
|
||||
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
|
||||
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
@@ -114,6 +122,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
@@ -122,6 +132,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
@@ -151,6 +163,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
@@ -170,6 +184,8 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -191,6 +207,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
|
||||
@@ -2,7 +2,6 @@ package docker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"path/filepath"
|
||||
@@ -12,6 +11,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/goccy/go-json"
|
||||
|
||||
"github.com/amir20/dozzle/internal/utils"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
@@ -333,8 +334,8 @@ func (d *_client) ContainerLogsBetweenDates(ctx context.Context, id string, from
|
||||
ShowStdout: stdType&STDOUT != 0,
|
||||
ShowStderr: stdType&STDERR != 0,
|
||||
Timestamps: true,
|
||||
Since: from.Format(time.RFC3339),
|
||||
Until: to.Format(time.RFC3339),
|
||||
Since: from.Format(time.RFC3339Nano),
|
||||
Until: to.Format(time.RFC3339Nano),
|
||||
}
|
||||
|
||||
log.Debugf("fetching logs from Docker with option: %+v", options)
|
||||
|
||||
@@ -65,7 +65,6 @@ func (s *ContainerStore) init(ctx context.Context) {
|
||||
|
||||
if containers, err := s.client.ListContainers(); err == nil {
|
||||
for _, c := range containers {
|
||||
c := c // create a new variable to avoid capturing the loop variable
|
||||
s.containers.Store(c.ID, &c)
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash/fnv"
|
||||
@@ -14,6 +13,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/goccy/go-json"
|
||||
|
||||
"github.com/go-logfmt/logfmt"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"sync"
|
||||
|
||||
"github.com/goccy/go-json"
|
||||
)
|
||||
|
||||
type RingBuffer[T any] struct {
|
||||
|
||||
@@ -37,9 +37,9 @@ HTTP/1.1 307 Temporary Redirect
|
||||
Connection: close
|
||||
Content-Security-Policy: default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;
|
||||
Content-Type: text/html; charset=utf-8
|
||||
Location: /login
|
||||
Location: /login?redirectUrl=/
|
||||
|
||||
<a href="/login">Temporary Redirect</a>.
|
||||
<a href="/login?redirectUrl=/">Temporary Redirect</a>.
|
||||
|
||||
/* snapshot: Test_createRoutes_username_password */
|
||||
HTTP/1.1 307 Temporary Redirect
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/goccy/go-json"
|
||||
|
||||
"github.com/amir20/dozzle/internal/analytics"
|
||||
"github.com/amir20/dozzle/internal/docker"
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"html/template"
|
||||
"io"
|
||||
"sort"
|
||||
|
||||
"github.com/goccy/go-json"
|
||||
|
||||
"net/http"
|
||||
"path"
|
||||
|
||||
@@ -65,7 +66,7 @@ func (h *handler) executeTemplate(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
} else if h.config.Authorization.Provider == SIMPLE && req.URL.Path != "login" {
|
||||
log.Debugf("Redirecting to login page for url /%s", req.URL.String())
|
||||
http.Redirect(w, req, path.Clean(h.config.Base+"/login"), http.StatusTemporaryRedirect)
|
||||
http.Redirect(w, req, path.Clean(h.config.Base+"/login")+"?redirectUrl=/"+req.URL.String(), http.StatusTemporaryRedirect)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
+18
-6
@@ -3,7 +3,9 @@ package web
|
||||
import (
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/goccy/go-json"
|
||||
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -29,12 +31,22 @@ func (h *handler) downloadLogs(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
nowFmt := now.Format("2006-01-02T15-04-05")
|
||||
|
||||
contentDisposition := fmt.Sprintf("attachment; filename=%s-%s.log", container.Name, nowFmt)
|
||||
|
||||
if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
|
||||
w.Header().Set("Content-Disposition", contentDisposition)
|
||||
w.Header().Set("Content-Encoding", "gzip")
|
||||
w.Header().Set("Content-Type", "application/text")
|
||||
} else {
|
||||
w.Header().Set("Content-Disposition", contentDisposition+".gz")
|
||||
w.Header().Set("Content-Type", "application/gzip")
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s-%s.log.gz", container.Name, now.Format("2006-01-02T15-04-05")))
|
||||
w.Header().Set("Content-Type", "application/gzip")
|
||||
zw := gzip.NewWriter(w)
|
||||
defer zw.Close()
|
||||
zw.Name = fmt.Sprintf("%s-%s.log", container.Name, now.Format("2006-01-02T15-04-05"))
|
||||
zw.Name = fmt.Sprintf("%s-%s.log", container.Name, nowFmt)
|
||||
zw.Comment = "Logs generated by Dozzle"
|
||||
zw.ModTime = now
|
||||
|
||||
@@ -53,8 +65,8 @@ func (h *handler) downloadLogs(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *handler) fetchLogsBetweenDates(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/x-jsonl; charset=UTF-8")
|
||||
|
||||
from, _ := time.Parse(time.RFC3339, r.URL.Query().Get("from"))
|
||||
to, _ := time.Parse(time.RFC3339, r.URL.Query().Get("to"))
|
||||
from, _ := time.Parse(time.RFC3339Nano, r.URL.Query().Get("from"))
|
||||
to, _ := time.Parse(time.RFC3339Nano, r.URL.Query().Get("to"))
|
||||
id := chi.URLParam(r, "id")
|
||||
|
||||
var stdTypes docker.StdType
|
||||
|
||||
@@ -115,6 +115,8 @@ func createRouter(h *handler) *chi.Mux {
|
||||
}
|
||||
|
||||
r.Get("/healthcheck", h.healthcheck)
|
||||
|
||||
// r.Mount("/debug", middleware.Profiler())
|
||||
})
|
||||
|
||||
if base != "/" {
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
toolbar:
|
||||
clear: Pulisci
|
||||
download: Scarica
|
||||
search: Cerca
|
||||
show: Mostra solo {std}
|
||||
show-all: Mostra tutto
|
||||
stop: Stop
|
||||
start: Start
|
||||
restart: Restart
|
||||
label:
|
||||
containers: Container
|
||||
running-containers: Container in esecuzione
|
||||
all-containers: Tutti i Container
|
||||
total-containers: Container Totali
|
||||
running: In esecuzione
|
||||
total-cpu-usage: Utilizzo Totale della CPU
|
||||
total-mem-usage: Utilizzo Totale della Memoria
|
||||
dozzle-version: Versione Dozzle
|
||||
all: Tutto
|
||||
host: Host
|
||||
password: Password
|
||||
username: Username
|
||||
container-name: Nome Container
|
||||
status: Stato
|
||||
created: Creato
|
||||
avg-cpu: CPU (%)
|
||||
avg-mem: MEM (%)
|
||||
pinned: Spuntato
|
||||
tooltip:
|
||||
search: Ricerca container (⌘ + k, ⌃k)
|
||||
pin-column: Blocca come colonna
|
||||
error:
|
||||
page-not-found: Questa pagina non esiste
|
||||
invalid-auth: Username o password non valide
|
||||
logs-skipped: Saltato {total} registrazioni
|
||||
container-not-found: Container non trovato
|
||||
events-stream:
|
||||
title: Errore inaspettato
|
||||
message: >-
|
||||
Dozzle UI non è stato in grado di connettersi alle API. Controlla la tua configurazione di rete.
|
||||
Se stai utilizzando un reverse proxy, assicurati di averlo configurato correttamente.
|
||||
events-timeout:
|
||||
title: Qualcosa non è corretto
|
||||
message: >-
|
||||
Dozzle UI timed out durante la connessione alle API. Controlla la configurazione di rete e riprova.
|
||||
alert:
|
||||
redirected:
|
||||
title: Reindirizzamento ad un nuovo container
|
||||
message: Dozzle automaticamente si è reindirizzato ad un nuovo container {containerId}.
|
||||
similar-container-found:
|
||||
title: Trovato un Container simile
|
||||
message: >-
|
||||
Dozzle ha trovato un Container soimile {containerId} in esecuzione sullo stesso Host and verrà automaticamente agganciato ad esso se non premi 'Cancel'.
|
||||
title:
|
||||
page-not-found: Pagina non trovata
|
||||
login: Autenticazione richiesta
|
||||
dashboard: 1 container | {count} container
|
||||
settings: Configurazione
|
||||
button:
|
||||
logout: Logout
|
||||
login: Login
|
||||
settings: Configurazione
|
||||
placeholder:
|
||||
search-containers: Ricerca container (⌘ + k, ⌃k)
|
||||
settings:
|
||||
display: Visualizza
|
||||
locale: Sovrascrivi Linguaggio
|
||||
small-scrollbars: Usa una scrollbars più piccola
|
||||
show-timesamps: Visualizza timestamp
|
||||
soft-wrap: Linee morbide
|
||||
datetime-format: Sovrascrivi data e formato dell'ora
|
||||
font-size: Grandezza del Font da usare nei log
|
||||
color-scheme: Schema colori
|
||||
options: Opzioni
|
||||
show-stopped-containers: Visualizza i container fermi
|
||||
about: Circa
|
||||
search: Abilita la ricerca attraverso Dozzle
|
||||
using-version: Stai utilizzando Dozzle {version}.
|
||||
update-available: >-
|
||||
Nuova versione disponibile! Aggiorna a <a href="{href}" target="_blank"
|
||||
rel="noreferrer noopener">{nextVersion}</a>.
|
||||
show-std: Visualizza stdout e stderr
|
||||
automatic-redirect: Automaticamente reindirizza al nuovo container con lo stesso nome
|
||||
compact: Abilita il compact mode per i log
|
||||
releases:
|
||||
features: nuova funzione | {count} funzioni
|
||||
bugFixes: nuovo bug fix | {count} fix
|
||||
breaking: nuovo breaking change | {count} breaking change
|
||||
three_parts: "{first}, {second} e {third}"
|
||||
two_parts: "{first} e {second}"
|
||||
latest: Ultimo
|
||||
no_releases: Stai utilizzando l'ultima versione
|
||||
log_actions:
|
||||
copy_log: Copia log
|
||||
jump_to_context: Vai a
|
||||
toasts:
|
||||
copied:
|
||||
title: Copiato
|
||||
message: Log copiato nella clipboard
|
||||
+23
-26
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "dozzle",
|
||||
"version": "6.2.2",
|
||||
"version": "6.2.7",
|
||||
"description": "Realtime log viewer for docker containers.",
|
||||
"homepage": "https://github.com/amir20/dozzle#readme",
|
||||
"bugs": {
|
||||
"url": "https://github.com/amir20/dozzle/issues"
|
||||
},
|
||||
"packageManager": "pnpm@8.15.1",
|
||||
"packageManager": "pnpm@8.15.4",
|
||||
"type": "module",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -28,7 +28,7 @@
|
||||
"docs:preview": "vitepress preview docs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@iconify-json/carbon": "^1.1.28",
|
||||
"@iconify-json/carbon": "^1.1.31",
|
||||
"@iconify-json/cil": "^1.1.8",
|
||||
"@iconify-json/ic": "^1.1.17",
|
||||
"@iconify-json/mdi": "^1.1.64",
|
||||
@@ -38,42 +38,41 @@
|
||||
"@intlify/unplugin-vue-i18n": "^2.0.0",
|
||||
"@tailwindcss/container-queries": "^0.1.1",
|
||||
"@tailwindcss/typography": "^0.5.10",
|
||||
"@vueuse/components": "^10.7.2",
|
||||
"@vueuse/core": "^10.7.2",
|
||||
"@vueuse/integrations": "^10.7.2",
|
||||
"@vueuse/math": "^10.7.2",
|
||||
"@vueuse/router": "^10.7.2",
|
||||
"autoprefixer": "^10.4.17",
|
||||
"@vueuse/components": "^10.9.0",
|
||||
"@vueuse/core": "^10.9.0",
|
||||
"@vueuse/integrations": "^10.9.0",
|
||||
"@vueuse/router": "^10.9.0",
|
||||
"autoprefixer": "^10.4.18",
|
||||
"d3-array": "^3.2.4",
|
||||
"d3-ease": "^3.0.1",
|
||||
"d3-scale": "^4.0.2",
|
||||
"d3-selection": "^3.0.0",
|
||||
"d3-shape": "^3.2.0",
|
||||
"d3-transition": "^3.0.1",
|
||||
"daisyui": "^4.6.2",
|
||||
"daisyui": "^4.7.2",
|
||||
"date-fns": "^3.3.1",
|
||||
"entities": "^4.5.0",
|
||||
"fuse.js": "^7.0.0",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"pinia": "^2.1.7",
|
||||
"postcss": "^8.4.35",
|
||||
"postcss-mixins": "^9.0.4",
|
||||
"postcss-mixins": "^10.0.0",
|
||||
"splitpanes": "^3.1.5",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"unplugin-auto-import": "^0.17.5",
|
||||
"unplugin-icons": "^0.18.5",
|
||||
"unplugin-vue-components": "^0.26.0",
|
||||
"unplugin-vue-macros": "^2.7.10",
|
||||
"vite": "5.0.12",
|
||||
"vite": "5.1.5",
|
||||
"vite-plugin-pages": "^0.32.0",
|
||||
"vite-plugin-vue-layouts": "^0.11.0",
|
||||
"vue": "^3.4.15",
|
||||
"vue-i18n": "^9.9.1",
|
||||
"vue-router": "^4.2.5"
|
||||
"vue": "^3.4.21",
|
||||
"vue-i18n": "^9.10.1",
|
||||
"vue-router": "^4.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@pinia/testing": "^0.1.3",
|
||||
"@playwright/test": "^1.41.2",
|
||||
"@playwright/test": "^1.42.1",
|
||||
"@types/d3-array": "^3.2.1",
|
||||
"@types/d3-ease": "^3.0.2",
|
||||
"@types/d3-scale": "^4.0.8",
|
||||
@@ -81,26 +80,24 @@
|
||||
"@types/d3-shape": "^3.1.6",
|
||||
"@types/d3-transition": "^3.0.8",
|
||||
"@types/lodash.debounce": "^4.0.9",
|
||||
"@types/node": "^20.11.16",
|
||||
"@types/semver": "^7.5.6",
|
||||
"@vitejs/plugin-vue": "5.0.3",
|
||||
"@vue/compiler-sfc": "^3.4.15",
|
||||
"@types/node": "^20.11.24",
|
||||
"@vitejs/plugin-vue": "5.0.4",
|
||||
"@vue/compiler-sfc": "^3.4.21",
|
||||
"@vue/test-utils": "^2.4.4",
|
||||
"bumpp": "^9.3.0",
|
||||
"bumpp": "^9.4.0",
|
||||
"c8": "^9.1.0",
|
||||
"concurrently": "^8.2.2",
|
||||
"eventsourcemock": "^2.0.0",
|
||||
"jest-serializer-vue": "^3.1.0",
|
||||
"jsdom": "^24.0.0",
|
||||
"lint-staged": "^15.2.2",
|
||||
"prettier": "^3.2.5",
|
||||
"prettier-plugin-tailwindcss": "^0.5.11",
|
||||
"simple-git-hooks": "^2.9.0",
|
||||
"simple-git-hooks": "^2.10.0",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.3.3",
|
||||
"vitepress": "1.0.0-rc.42",
|
||||
"vitest": "^1.2.2",
|
||||
"vue-tsc": "^1.8.27"
|
||||
"vitepress": "1.0.0-rc.44",
|
||||
"vitest": "^1.3.1",
|
||||
"vue-tsc": "^2.0.4"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,vue,css,ts,html,md}": [
|
||||
|
||||
Generated
+495
-597
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user