diff --git a/CHANGELOG.md b/CHANGELOG.md index a307d42bf1..9a9e49f667 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ NOTE: As semantic versioning states all 0.y.z releases can contain breaking chan We use *breaking :warning:* to mark changes that are not backward compatible (relates only to v0.y.z releases.) ## Unreleased +- [#3259](https://github.com/thanos-io/thanos/pull/3259) Thanos BlockViewer: Added a button in the blockviewer that allows users to download the metadata of a block. - [#3261](https://github.com/thanos-io/thanos/pull/3261) Thanos Store: Use segment files specified in meta.json file, if present. If not present, Store does the LIST operation as before. - [#3276](https://github.com/thanos-io/thanos/pull/3276) Query Frontend: Support query splitting and retry for labels and series requests. diff --git a/pkg/ui/react-app/src/pages/graph/PanelList.tsx b/pkg/ui/react-app/src/pages/graph/PanelList.tsx index ceaec5acd1..bec45a9a6b 100644 --- a/pkg/ui/react-app/src/pages/graph/PanelList.tsx +++ b/pkg/ui/react-app/src/pages/graph/PanelList.tsx @@ -41,8 +41,8 @@ export const PanelListContent: FC = ({ useEffect(() => { // Convert stores data to a unified stores array. - let storeList: Store[] = []; - for (let type in stores) { + const storeList: Store[] = []; + for (const type in stores) { storeList.push(...stores[type]); } setStoreData(storeList); diff --git a/pkg/ui/react-app/src/thanos/pages/blocks/BlockDetails.test.tsx b/pkg/ui/react-app/src/thanos/pages/blocks/BlockDetails.test.tsx index d327276255..23bf869dea 100644 --- a/pkg/ui/react-app/src/thanos/pages/blocks/BlockDetails.test.tsx +++ b/pkg/ui/react-app/src/thanos/pages/blocks/BlockDetails.test.tsx @@ -16,7 +16,7 @@ describe('BlockDetails', () => { // do nothing }, }; - + window.URL.createObjectURL = jest.fn(); const blockDetails = mount(); it('renders a heading with block ulid', () => { @@ -79,6 +79,13 @@ describe('BlockDetails', () => { expect(div.find('span').text()).toBe(sampleBlock.thanos.source); }); + it('renders the download button', () => { + const div = blockDetails.find({ 'data-testid': 'download' }); + window.URL.createObjectURL = jest.fn(() => 'details'); + expect(div).toHaveLength(1); + expect(div.find('a').text()).toBe('Download meta.json'); + }); + it('renders a list of the labels', () => { const div = blockDetails.find({ 'data-testid': 'labels' }); const list = div.find('ul'); diff --git a/pkg/ui/react-app/src/thanos/pages/blocks/BlockDetails.tsx b/pkg/ui/react-app/src/thanos/pages/blocks/BlockDetails.tsx index 8ba061f351..a767a9a1de 100644 --- a/pkg/ui/react-app/src/thanos/pages/blocks/BlockDetails.tsx +++ b/pkg/ui/react-app/src/thanos/pages/blocks/BlockDetails.tsx @@ -2,6 +2,8 @@ import React, { FC } from 'react'; import { Block } from './block'; import styles from './blocks.module.css'; import moment from 'moment'; +import { Button } from 'reactstrap'; +import { download } from './helpers'; export interface BlockDetailsProps { block: Block | undefined; @@ -63,6 +65,12 @@ export const BlockDetails: FC = ({ block, selectBlock }) => { ))} +
+
+ + + +
)} diff --git a/pkg/ui/react-app/src/thanos/pages/blocks/helpers.ts b/pkg/ui/react-app/src/thanos/pages/blocks/helpers.ts index 7faac98144..3381a56936 100644 --- a/pkg/ui/react-app/src/thanos/pages/blocks/helpers.ts +++ b/pkg/ui/react-app/src/thanos/pages/blocks/helpers.ts @@ -54,3 +54,9 @@ export const sortBlocks = (blocks: Block[], label: string): { [source: string]: }); return sortedPool; }; + +export const download = (blob: Block): string => { + const url = window.URL.createObjectURL(new Blob([JSON.stringify(blob, null, 2)], { type: 'application/json' })); + + return url; +};