1
0
mirror of https://github.com/amir20/dozzle.git synced 2025-12-26 07:13:41 +01:00

feat: downloads visible streams only instead of all (#2924)

This commit is contained in:
Amir Raminfar
2024-04-30 09:40:27 -07:00
committed by GitHub
parent 448341c343
commit cc8e715cc5
3 changed files with 30 additions and 7 deletions

View File

@@ -12,9 +12,7 @@
</a>
</li>
<li>
<a :href="`${base}/api/hosts/${container.host}/containers/${container.id}/logs/download`" download>
<octicon:download-24 /> {{ $t("toolbar.download") }}
</a>
<a :href="downloadUrl" download> <octicon:download-24 /> {{ $t("toolbar.download") }} </a>
</li>
<li>
<a @click.prevent="showSearch = true">
@@ -104,7 +102,7 @@
<script lang="ts" setup>
const { showSearch } = useSearchFilter();
const { base, enableActions } = config;
const { enableActions } = config;
const clear = defineEmit();
@@ -113,6 +111,18 @@ const { container, streamConfig } = useContainerContext();
// container context is provided in the parent component: <LogContainer>
const { actionStates, start, stop, restart } = useContainerActions();
const downloadParams = computed(() =>
Object.entries(streamConfig)
.filter(([, value]) => value)
.reduce((acc, [key]) => ({ ...acc, [key]: "1" }), {}),
);
const downloadUrl = computed(() =>
withBase(
`/api/hosts/${container.value.host}/containers/${container.value.id}/logs/download?${new URLSearchParams(downloadParams.value).toString()}`,
),
);
const disableRestart = computed(() => {
return actionStates.stop || actionStates.start || actionStates.restart;
});

View File

@@ -17,7 +17,7 @@ import (
func Test_handler_download_logs(t *testing.T) {
id := "123456"
req, err := http.NewRequest("GET", "/api/hosts/localhost/containers/"+id+"/logs/download", nil)
req, err := http.NewRequest("GET", "/api/hosts/localhost/containers/"+id+"/logs/download?stdout=1", nil)
require.NoError(t, err, "NewRequest should not return an error.")
mockedClient := new(MockedClient)
@@ -25,7 +25,7 @@ func Test_handler_download_logs(t *testing.T) {
data := makeMessage("INFO Testing logs...", docker.STDOUT)
mockedClient.On("FindContainer", id).Return(docker.Container{ID: id, Tty: false}, nil)
mockedClient.On("ContainerLogsBetweenDates", mock.Anything, id, mock.Anything, mock.Anything, docker.STDALL).Return(io.NopCloser(bytes.NewReader(data)), nil)
mockedClient.On("ContainerLogsBetweenDates", mock.Anything, id, mock.Anything, mock.Anything, docker.STDOUT).Return(io.NopCloser(bytes.NewReader(data)), nil)
handler := createDefaultHandler(mockedClient)
rr := httptest.NewRecorder()

View File

@@ -44,13 +44,26 @@ func (h *handler) downloadLogs(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/gzip")
}
var stdTypes docker.StdType
if r.URL.Query().Has("stdout") {
stdTypes |= docker.STDOUT
}
if r.URL.Query().Has("stderr") {
stdTypes |= docker.STDERR
}
if stdTypes == 0 {
http.Error(w, "stdout or stderr is required", http.StatusBadRequest)
return
}
zw := gzip.NewWriter(w)
defer zw.Close()
zw.Name = fmt.Sprintf("%s-%s.log", container.Name, nowFmt)
zw.Comment = "Logs generated by Dozzle"
zw.ModTime = now
reader, err := h.clientFromRequest(r).ContainerLogsBetweenDates(r.Context(), id, time.Time{}, now, docker.STDALL)
reader, err := h.clientFromRequest(r).ContainerLogsBetweenDates(r.Context(), id, time.Time{}, now, stdTypes)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return