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:
@@ -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;
|
||||
});
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user