├── .nvmrc ├── keys ├── my-own-ca.srl ├── server.ext ├── server.csr ├── my-own-ca.crt ├── server.crt ├── my-own-ca.key └── server.key ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── config.yml │ └── bug_report.yaml ├── workflows │ ├── release.yml │ └── run-tests.yml └── dependabot.yml ├── .eslintrc ├── jest-setup.js ├── .config ├── webpack │ ├── constants.ts │ ├── utils.ts │ └── webpack.config.ts ├── .eslintrc ├── .prettierrc.js ├── types │ └── custom.d.ts ├── Dockerfile ├── tsconfig.json ├── jest-setup.js ├── jest │ ├── mocks │ │ └── react-inlinesvg.tsx │ └── utils.js ├── jest.config.js └── README.md ├── sql_builder.png ├── src ├── img │ ├── sql_builder.png │ └── logo.svg ├── test │ └── setupTests.ts ├── components │ ├── questdb-sql │ │ ├── types.ts │ │ ├── operators.ts │ │ ├── getTableCompletions.ts │ │ ├── getLanguageCompletions.ts │ │ ├── conf.ts │ │ ├── getColumnCompletions.ts │ │ ├── getMacroAndVarCompletions.ts │ │ ├── language.ts │ │ ├── utils.ts │ │ └── createSchemaCompletionProvider.ts │ ├── queryBuilder │ │ ├── Preview.test.tsx │ │ ├── Limit.test.tsx │ │ ├── ModeEditor.test.tsx │ │ ├── Preview.tsx │ │ ├── GroupBy.test.tsx │ │ ├── Metrics.test.tsx │ │ ├── SampleByAlignment.test.tsx │ │ ├── Limit.tsx │ │ ├── TableSelect.test.tsx │ │ ├── ModeEditor.tsx │ │ ├── QueryBuilder.test.tsx │ │ ├── GroupBy.tsx │ │ ├── SampleByAlignment.tsx │ │ ├── PartitionByEditor.tsx │ │ ├── TableSelect.tsx │ │ ├── Fields.tsx │ │ ├── Fields.test.tsx │ │ ├── SampleByFillEditor.tsx │ │ ├── OrderBy.tsx │ │ └── Metrics.tsx │ ├── FormatSelect.test.tsx │ ├── Divider.tsx │ ├── editor.ts │ ├── FormatSelect.tsx │ ├── ui │ │ └── CertificationKey.tsx │ ├── sqlProvider.ts │ ├── SQLEditor.test.tsx │ ├── QueryTypeSwitcher.test.tsx │ ├── QueryHeader.tsx │ ├── SQLEditor.tsx │ └── QueryTypeSwitcher.tsx ├── styles.ts ├── module.ts ├── __mocks__ │ ├── ConfigEditor.ts │ └── datasource.ts ├── views │ ├── QuestDBQueryEditor.test.tsx │ ├── QuestDBQueryEditor.tsx │ └── QuestDBConfigEditor.test.tsx ├── plugin.json ├── utils │ ├── version.ts │ └── version.test.ts ├── data │ ├── ast.test.ts │ ├── adHocFilter.ts │ ├── ast.ts │ └── adHocFilter.test.ts └── selectors.ts ├── tsconfig.json ├── .prettierrc.js ├── scripts ├── ca.ext ├── ca.sh └── ca-cert.sh ├── jest-runner-serial.js ├── jest.config.js ├── Magefile.go ├── pkg ├── plugin │ ├── errors.go │ ├── settings_test.go │ └── settings.go ├── main.go ├── converters │ ├── converters_test.go │ └── converters.go └── macros │ ├── macros.go │ └── macros_test.go ├── provisioning └── datasources │ └── questdb_questdb_datasource.yaml ├── .gitignore ├── docker-compose.yml ├── cspell.config.json ├── CHANGELOG.md ├── CONTRIBUTING.md ├── package.json └── DEV_GUIDE.md /.nvmrc: -------------------------------------------------------------------------------- 1 | 18 -------------------------------------------------------------------------------- /keys/my-own-ca.srl: -------------------------------------------------------------------------------- 1 | F1882B6FB9749F92 2 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @questdb/engineering 2 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.config/.eslintrc" 3 | } -------------------------------------------------------------------------------- /jest-setup.js: -------------------------------------------------------------------------------- 1 | // Jest setup provided by Grafana scaffolding 2 | import './.config/jest-setup'; 3 | -------------------------------------------------------------------------------- /.config/webpack/constants.ts: -------------------------------------------------------------------------------- 1 | export const SOURCE_DIR = 'src'; 2 | export const DIST_DIR = 'dist'; 3 | -------------------------------------------------------------------------------- /sql_builder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/questdb/grafana-questdb-datasource/HEAD/sql_builder.png -------------------------------------------------------------------------------- /src/img/sql_builder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/questdb/grafana-questdb-datasource/HEAD/src/img/sql_builder.png -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.config/tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "." 5 | }, 6 | } -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // Prettier configuration provided by Grafana scaffolding 3 | ...require("./.config/.prettierrc.js") 4 | }; -------------------------------------------------------------------------------- /src/test/setupTests.ts: -------------------------------------------------------------------------------- 1 | import '@testing-library/jest-dom'; 2 | import '@testing-library/jest-dom/extend-expect'; 3 | 4 | process.on('unhandledRejection', (err) => { 5 | console.warn(err); 6 | }); 7 | -------------------------------------------------------------------------------- /scripts/ca.ext: -------------------------------------------------------------------------------- 1 | authorityKeyIdentifier=keyid,issuer 2 | basicConstraints=CA:FALSE 3 | keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment 4 | subjectAltName = @alt_names 5 | 6 | [alt_names] 7 | DNS.1 = qdb_root 8 | -------------------------------------------------------------------------------- /keys/server.ext: -------------------------------------------------------------------------------- 1 | authorityKeyIdentifier=keyid,issuer 2 | basicConstraints=CA:FALSE 3 | keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment 4 | subjectAltName = @alt_names 5 | 6 | [alt_names] 7 | DNS.1 = localhost 8 | DNS.2 = grafana-qdb-server 9 | -------------------------------------------------------------------------------- /jest-runner-serial.js: -------------------------------------------------------------------------------- 1 | const JestRunner = require('jest-runner'); 2 | 3 | class SerialJestRunner extends JestRunner { 4 | constructor(...args) { 5 | super(...args); 6 | this.isSerial = true; 7 | // this.maxConcurrency = 1 8 | } 9 | } 10 | 11 | module.exports = SerialJestRunner; 12 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | // force timezone to UTC to allow tests to work regardless of local timezone 2 | // generally used by snapshots, but can affect specific tests 3 | process.env.TZ = 'UTC'; 4 | 5 | module.exports = { 6 | // Jest configuration provided by Grafana scaffolding 7 | ...require('./.config/jest.config'), 8 | }; 9 | -------------------------------------------------------------------------------- /scripts/ca.sh: -------------------------------------------------------------------------------- 1 | # create a ca certificate 2 | 3 | openssl genrsa -out $PWD/config-secure/keys/my-own-ca.key 2048 4 | openssl req -new -x509 -days 3650 -key $PWD/config-secure/keys/my-own-ca.key \ 5 | -subj "/CN=qdb_root" \ 6 | -addext "subjectAltName = DNS:qdb_root" \ 7 | -sha256 -extensions v3_ca -out $PWD/config-secure/keys/my-own-ca.crt 8 | -------------------------------------------------------------------------------- /src/components/questdb-sql/types.ts: -------------------------------------------------------------------------------- 1 | export type InformationSchemaColumn = { 2 | tableName: string 3 | ordinalPosition: number 4 | columnName: string 5 | dataType: string 6 | } 7 | 8 | export enum CompletionItemPriority { 9 | High = "1", 10 | MediumHigh = "2", 11 | Medium = "3", 12 | MediumLow = "4", 13 | Low = "5", 14 | } 15 | -------------------------------------------------------------------------------- /src/components/queryBuilder/Preview.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import { Preview } from './Preview'; 4 | 5 | describe('Preview', () => { 6 | it('renders correctly', () => { 7 | const result = render(); 8 | expect(result.container.firstChild).not.toBeNull(); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /Magefile.go: -------------------------------------------------------------------------------- 1 | //+build mage 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | // mage:import 8 | build "github.com/grafana/grafana-plugin-sdk-go/build" 9 | ) 10 | 11 | // Hello prints a message (shows that you can define custom Mage targets). 12 | func Hello() { 13 | fmt.Println("hello plugin developer!") 14 | } 15 | 16 | // Default configures the default target. 17 | var Default = build.BuildAll 18 | -------------------------------------------------------------------------------- /src/components/queryBuilder/Limit.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import { LimitEditor } from './Limit'; 4 | 5 | describe('LimitEditor', () => { 6 | it('renders correctly', () => { 7 | const result = render( {}} />); 8 | expect(result.container.firstChild).not.toBeNull(); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Stack Overflow Community 4 | url: https://stackoverflow.com/questions/tagged/questdb 5 | about: Ask Stack Overflow community or search for popular solutions. 6 | - name: Community on Slack 7 | url: https://slack.questdb.io 8 | about: Ask generic questions or meet other developers who are building with QuestDB. 9 | -------------------------------------------------------------------------------- /.config/.eslintrc: -------------------------------------------------------------------------------- 1 | /* 2 | * ⚠️⚠️⚠️ THIS FILE WAS SCAFFOLDED BY `@grafana/create-plugin`. DO NOT EDIT THIS FILE DIRECTLY. ⚠️⚠️⚠️ 3 | * 4 | * In order to extend the configuration follow the steps in 5 | * https://grafana.github.io/plugin-tools/docs/advanced-configuration#extending-the-eslint-config 6 | */ 7 | { 8 | "extends": ["@grafana/eslint-config"], 9 | "root": true, 10 | "rules": { 11 | "react/prop-types": "off" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/components/FormatSelect.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import { FormatSelect } from './FormatSelect'; 4 | import { Format } from '../types'; 5 | 6 | describe('FormatSelect', () => { 7 | it('renders a format', () => { 8 | const result = render( {}} />); 9 | expect(result.container.firstChild).not.toBeNull(); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /.config/.prettierrc.js: -------------------------------------------------------------------------------- 1 | /* 2 | * ⚠️⚠️⚠️ THIS FILE WAS SCAFFOLDED BY `@grafana/create-plugin`. DO NOT EDIT THIS FILE DIRECTLY. ⚠️⚠️⚠️ 3 | * 4 | * In order to extend the configuration follow the steps in .config/README.md 5 | */ 6 | 7 | module.exports = { 8 | "endOfLine": "auto", 9 | "printWidth": 120, 10 | "trailingComma": "es5", 11 | "semi": true, 12 | "jsxSingleQuote": false, 13 | "singleQuote": true, 14 | "useTabs": false, 15 | "tabWidth": 2 16 | }; -------------------------------------------------------------------------------- /src/components/queryBuilder/ModeEditor.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import { ModeEditor } from './ModeEditor'; 4 | import { BuilderMode } from 'types'; 5 | 6 | describe('ModeEditor', () => { 7 | it('renders correctly', () => { 8 | const result = render( {}} />); 9 | expect(result.container.firstChild).not.toBeNull(); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /pkg/plugin/errors.go: -------------------------------------------------------------------------------- 1 | package plugin 2 | 3 | import "github.com/pkg/errors" 4 | 5 | var ( 6 | ErrorMessageInvalidJSON = errors.New("could not parse json") 7 | ErrorMessageInvalidServerName = errors.New("invalid server name. Either empty or not set") 8 | ErrorMessageInvalidPort = errors.New("invalid port") 9 | ErrorMessageInvalidUserName = errors.New("username is either empty or not set") 10 | ErrorMessageInvalidPassword = errors.New("password is either empty or not set") 11 | ) 12 | -------------------------------------------------------------------------------- /src/styles.ts: -------------------------------------------------------------------------------- 1 | import { css } from '@emotion/css'; 2 | 3 | export const styles = { 4 | Common: { 5 | wrapper: css` 6 | position: relative; 7 | width: 100%; 8 | `, 9 | smallBtn: css` 10 | margin-top: 5px; 11 | margin-inline: 5px; 12 | `, 13 | inlineSelect: css` 14 | margin-right: 5px; 15 | `, 16 | expand: css` 17 | position: absolute; 18 | top: 2px; 19 | left: 6px; 20 | z-index: 100; 21 | color: gray; 22 | ` 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /src/module.ts: -------------------------------------------------------------------------------- 1 | import { DataSourcePlugin/*, DashboardLoadedEvent*/ } from '@grafana/data'; 2 | import { Datasource } from './data/QuestDbDatasource'; 3 | import { ConfigEditor } from './views/QuestDBConfigEditor'; 4 | import { QuestDBQueryEditor } from './views/QuestDBQueryEditor'; 5 | import { QuestDBQuery, QuestDBConfig } from './types'; 6 | 7 | export const plugin = new DataSourcePlugin(Datasource) 8 | .setConfigEditor(ConfigEditor) 9 | .setQueryEditor(QuestDBQueryEditor); 10 | 11 | -------------------------------------------------------------------------------- /provisioning/datasources/questdb_questdb_datasource.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | datasources: 3 | - name: QuestDB-test 4 | type: questdb-questdb-datasource 5 | jsonData: 6 | server: grafana-questdb-server 7 | port: 8812 8 | username: admin 9 | tlsMode: disable 10 | # timeout: 11 | # queryTimeout: 12 | maxOpenConnections: 100 13 | maxIdleConnections: 100 14 | maxConnectionLifetime: 14400 15 | secureJsonData: 16 | password: quest 17 | # tlsCACert: 18 | -------------------------------------------------------------------------------- /src/components/Divider.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Divider as GrafanaDivider, useTheme2 } from '@grafana/ui'; 3 | import { config } from '@grafana/runtime'; 4 | import { isVersionGtOrEq } from '../utils/version'; 5 | 6 | export function Divider() { 7 | const theme = useTheme2(); 8 | return isVersionGtOrEq(config.buildInfo.version, '10.1.0') ? ( 9 | 10 | ) : ( 11 |
14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /scripts/ca-cert.sh: -------------------------------------------------------------------------------- 1 | # Generate server.key and server.crt signed by our local CA. 2 | openssl genrsa -out $PWD/keys/server.key 2048 3 | 4 | openssl req -sha256 -new -key $PWD/keys/server.key -out $PWD/keys/server.csr \ 5 | -subj "/CN=localhost" \ 6 | 7 | openssl x509 -req -in $PWD/keys/server.csr -CA $PWD/keys/my-own-ca.crt -CAkey $PWD/keys/my-own-ca.key \ 8 | -CAcreateserial -out $PWD/keys/server.crt -days 825 -sha256 -extfile $PWD/keys/server.ext 9 | 10 | # Confirm the certificate is valid. 11 | openssl verify -CAfile $PWD/keys/my-own-ca.crt $PWD/keys/server.crt 12 | -------------------------------------------------------------------------------- /src/__mocks__/ConfigEditor.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | import { Props } from '../views/QuestDBConfigEditor'; 3 | import { QuestDBConfig } from 'types'; 4 | 5 | const pluginJson = JSON.parse(fs.readFileSync('./src/plugin.json', 'utf-8')); 6 | 7 | export const mockConfigEditorProps = (overrides?: Partial): Props => ({ 8 | options: { 9 | ...pluginJson, 10 | jsonData: { 11 | server: 'questdb.com', 12 | port: 8812, 13 | username: 'user', 14 | ...overrides 15 | }, 16 | }, 17 | onOptionsChange: jest.fn(), 18 | }); 19 | -------------------------------------------------------------------------------- /src/components/queryBuilder/Preview.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { selectors } from './../../selectors'; 3 | import { EditorField, EditorRow } from '@grafana/plugin-ui'; 4 | interface PreviewProps { 5 | sql: string; 6 | } 7 | export const Preview = (props: PreviewProps) => { 8 | const { label, tooltip } = selectors.components.QueryEditor.QueryBuilder.PREVIEW; 9 | return ( 10 | 11 | 12 |
{props.sql !== '' ? props.sql : 'Query SQL will show here'}
13 |
14 |
15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /src/components/questdb-sql/operators.ts: -------------------------------------------------------------------------------- 1 | export const operators = [ 2 | // Logical 3 | "ALL", 4 | "AND", 5 | "ANY", 6 | "BETWEEN", 7 | "EXISTS", 8 | "IN", 9 | "LIKE", 10 | "NOT", 11 | "OR", 12 | "SOME", 13 | // Set 14 | "EXCEPT", 15 | "INTERSECT", 16 | "UNION", 17 | // Join 18 | "APPLY", 19 | "CROSS", 20 | "FULL", 21 | "INNER", 22 | "JOIN", 23 | "LEFT", 24 | "OUTER", 25 | "RIGHT", 26 | // Predicates 27 | "CONTAINS", 28 | "FREETEXT", 29 | "IS", 30 | "NULL", 31 | // Pivoting 32 | "PIVOT", 33 | "UNPIVOT", 34 | // Merging 35 | "MATCHED", 36 | "EXPLAIN" 37 | ] 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | node_modules/ 9 | 10 | # Runtime data 11 | pids 12 | *.pid 13 | *.seed 14 | *.pid.lock 15 | 16 | # Directory for instrumented libs generated by jscoverage/JSCover 17 | lib-cov 18 | 19 | # Coverage directory used by tools like istanbul 20 | coverage 21 | 22 | # Compiled binary addons (https://nodejs.org/api/addons.html) 23 | dist/ 24 | artifacts/ 25 | work/ 26 | ci/ 27 | 28 | # config test file 29 | test_grafana.ini 30 | 31 | # Editor 32 | .idea 33 | 34 | pkg/__debug_bin 35 | 36 | **/.DS_Store 37 | .eslintcache 38 | .levitate_output 39 | -------------------------------------------------------------------------------- /src/components/queryBuilder/GroupBy.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import { GroupByEditor } from './GroupBy'; 4 | import { selectors } from '../../selectors'; 5 | 6 | describe('GroupByEditor', () => { 7 | it('renders correctly', () => { 8 | const result = render( 9 | {}} 13 | isDisabled={false} 14 | labelAndTooltip={selectors.components.QueryEditor.QueryBuilder.SAMPLE_BY} 15 | /> 16 | ); 17 | expect(result.container.firstChild).not.toBeNull(); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - "v*" # Run workflow on version tags, e.g. v1.0.0. 7 | 8 | # necessary to create releases 9 | permissions: 10 | contents: write 11 | 12 | jobs: 13 | release: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v3 17 | 18 | - uses: grafana/plugin-actions/build-plugin@main 19 | with: 20 | # see https://grafana.com/developers/plugin-tools/publish-a-plugin/sign-a-plugin#generate-an-access-policy-token to generate it 21 | # save the value in your repository secrets 22 | policy_token: ${{ secrets.GRAFANA_ACCESS_POLICY_TOKEN }} 23 | -------------------------------------------------------------------------------- /src/components/queryBuilder/Metrics.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import { MetricsEditor } from './Metrics'; 4 | import { selectors } from './../../selectors'; 5 | 6 | describe('MetricsEditor', () => { 7 | it('renders correctly', () => { 8 | const result = render( {}} />); 9 | expect(result.container.firstChild).not.toBeNull(); 10 | if (selectors.components.QueryEditor.QueryBuilder.AGGREGATES.AddLabel) { 11 | expect(result.getByText(selectors.components.QueryEditor.QueryBuilder.AGGREGATES.AddLabel)).toBeInTheDocument(); 12 | } 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /src/components/queryBuilder/SampleByAlignment.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {render} from '@testing-library/react'; 3 | import {SampleByAlignEditor} from './SampleByAlignment'; 4 | import {SampleByAlignToMode} from "../../types"; 5 | 6 | describe('SampleByAlignEditor', () => { 7 | it('renders correctly', () => { 8 | const result = render( 9 | {}} 15 | onSampleByAlignToValueChange={()=>{}} 16 | /> 17 | ); 18 | expect(result.container.firstChild).not.toBeNull(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /.config/types/custom.d.ts: -------------------------------------------------------------------------------- 1 | // Image declarations 2 | declare module '*.gif' { 3 | const src: string; 4 | export default src; 5 | } 6 | 7 | declare module '*.jpg' { 8 | const src: string; 9 | export default src; 10 | } 11 | 12 | declare module '*.jpeg' { 13 | const src: string; 14 | export default src; 15 | } 16 | 17 | declare module '*.png' { 18 | const src: string; 19 | export default src; 20 | } 21 | 22 | declare module '*.webp' { 23 | const src: string; 24 | export default src; 25 | } 26 | 27 | declare module '*.svg' { 28 | const content: string; 29 | export default content; 30 | } 31 | 32 | // Font declarations 33 | declare module '*.woff'; 34 | declare module '*.woff2'; 35 | declare module '*.eot'; 36 | declare module '*.ttf'; 37 | declare module '*.otf'; 38 | -------------------------------------------------------------------------------- /.config/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG grafana_version=latest 2 | ARG grafana_image=grafana-enterprise 3 | 4 | FROM grafana/${grafana_image}:${grafana_version} 5 | 6 | # Make it as simple as possible to access the grafana instance for development purposes 7 | # Do NOT enable these settings in a public facing / production grafana instance 8 | ENV GF_AUTH_ANONYMOUS_ORG_ROLE "Admin" 9 | ENV GF_AUTH_ANONYMOUS_ENABLED "true" 10 | ENV GF_AUTH_BASIC_ENABLED "false" 11 | # Set development mode so plugins can be loaded without the need to sign 12 | ENV GF_DEFAULT_APP_MODE "development" 13 | 14 | # Inject livereload script into grafana index.html 15 | USER root 16 | RUN sed -i 's/<\/body><\/html>/