Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Systems data source template #3

Merged
merged 11 commits into from
Jul 19, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: CI

on:
push:
branches:
- master
- main
pull_request:
branches:
- master
- main

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js environment
uses: actions/setup-node@v3
with:
node-version: '16'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Check types
run: npm run typecheck
- name: Lint
run: npm run lint
- name: Unit tests
run: npm run test:ci
- name: Build frontend
run: npm run build

- name: Check for backend
id: check-for-backend
run: |
if [ -f "Magefile.go" ]
then
echo "has-backend=true" >> $GITHUB_OUTPUT
fi

- name: Setup Go environment
if: steps.check-for-backend.outputs.has-backend == 'true'
uses: actions/setup-go@v3
with:
go-version: '1.20'

- name: Test backend
if: steps.check-for-backend.outputs.has-backend == 'true'
uses: magefile/mage-action@v2
with:
version: latest
args: coverage

- name: Build backend
if: steps.check-for-backend.outputs.has-backend == 'true'
uses: magefile/mage-action@v2
with:
version: latest
args: buildAll

- name: Check for E2E
id: check-for-e2e
run: |
if [ -d "cypress" ]
then
echo "has-e2e=true" >> $GITHUB_OUTPUT
fi

- name: Start grafana docker
if: steps.check-for-e2e.outputs.has-e2e == 'true'
run: docker-compose up -d

- name: Run e2e tests
if: steps.check-for-e2e.outputs.has-e2e == 'true'
run: npm run e2e

- name: Stop grafana docker
if: steps.check-for-e2e.outputs.has-e2e == 'true'
run: docker-compose down

- name: Archive E2E output
uses: actions/upload-artifact@v3
if: steps.check-for-e2e.outputs.has-e2e == 'true' && steps.run-e2e-tests.outcome != 'success'
with:
name: cypress-videos
path: cypress/videos
retention-days: 5
2 changes: 1 addition & 1 deletion .github/workflows/is-compatible.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ jobs:
- name: Build plugin
run: npm run build
- name: Compatibility check
run: npx @grafana/levitate@latest is-compatible --path src/module.ts --target @grafana/data,@grafana/ui,@grafana/runtime
run: npx @grafana/levitate@latest is-compatible --path src/module.ts --target @grafana/data,@grafana/ui,@grafana/runtime
131 changes: 131 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
name: Release

on:
push:
tags:
- 'v*' # Run workflow on version tags, e.g. v1.0.0.

jobs:
release:
runs-on: ubuntu-latest
env:
GRAFANA_API_KEY: ${{ secrets.GRAFANA_API_KEY }} # Requires a Grafana API key from Grafana.com.
steps:
- uses: actions/checkout@v3
- name: Setup Node.js environment
uses: actions/setup-node@v3
with:
node-version: '16'
cache: 'npm'

- name: Setup Go environment
uses: actions/setup-go@v3
with:
go-version: '1.19'

- name: Install dependencies
run: npm ci

- name: Build and test frontend
run: npm run build

- name: Check for backend
id: check-for-backend
run: |
if [ -f "Magefile.go" ]
then
echo "has-backend=true" >> $GITHUB_OUTPUT
fi

- name: Test backend
if: steps.check-for-backend.outputs.has-backend == 'true'
uses: magefile/mage-action@v2
with:
version: latest
args: coverage

- name: Build backend
if: steps.check-for-backend.outputs.has-backend == 'true'
uses: magefile/mage-action@v2
with:
version: latest
args: buildAll

- name: Warn missing Grafana API key
run: |
echo Please generate a Grafana API key: https://grafana.com/docs/grafana/latest/developers/plugins/sign-a-plugin/#generate-an-api-key
echo Once done please follow the instructions found here: https://github.com/${{github.repository}}/blob/main/README.md#using-github-actions-release-workflow
if: ${{ env.GRAFANA_API_KEY == '' }}

- name: Sign plugin
run: npm run sign
if: ${{ env.GRAFANA_API_KEY != '' }}

- name: Get plugin metadata
id: metadata
run: |
sudo apt-get install jq

export GRAFANA_PLUGIN_ID=$(cat dist/plugin.json | jq -r .id)
export GRAFANA_PLUGIN_VERSION=$(cat dist/plugin.json | jq -r .info.version)
export GRAFANA_PLUGIN_TYPE=$(cat dist/plugin.json | jq -r .type)
export GRAFANA_PLUGIN_ARTIFACT=${GRAFANA_PLUGIN_ID}-${GRAFANA_PLUGIN_VERSION}.zip
export GRAFANA_PLUGIN_ARTIFACT_CHECKSUM=${GRAFANA_PLUGIN_ARTIFACT}.md5

echo "plugin-id=${GRAFANA_PLUGIN_ID}" >> $GITHUB_OUTPUT
echo "plugin-version=${GRAFANA_PLUGIN_VERSION}" >> $GITHUB_OUTPUT
echo "plugin-type=${GRAFANA_PLUGIN_TYPE}" >> $GITHUB_OUTPUT
echo "archive=${GRAFANA_PLUGIN_ARTIFACT}" >> $GITHUB_OUTPUT
echo "archive-checksum=${GRAFANA_PLUGIN_ARTIFACT_CHECKSUM}" >> $GITHUB_OUTPUT

echo "github-tag=${GITHUB_REF#refs/*/}" >> $GITHUB_OUTPUT

- name: Read changelog
id: changelog
run: |
awk '/^## / {s++} s == 1 {print}' CHANGELOG.md > release_notes.md
echo "path=release_notes.md" >> $GITHUB_OUTPUT

- name: Check package version
run: if [ "v${{ steps.metadata.outputs.plugin-version }}" != "${{ steps.metadata.outputs.github-tag }}" ]; then printf "\033[0;31mPlugin version doesn't match tag name\033[0m\n"; exit 1; fi

- name: Package plugin
id: package-plugin
run: |
mv dist ${{ steps.metadata.outputs.plugin-id }}
zip ${{ steps.metadata.outputs.archive }} ${{ steps.metadata.outputs.plugin-id }} -r
md5sum ${{ steps.metadata.outputs.archive }} > ${{ steps.metadata.outputs.archive-checksum }}
echo "checksum=$(cat ./${{ steps.metadata.outputs.archive-checksum }} | cut -d' ' -f1)" >> $GITHUB_OUTPUT

- name: Validate plugin
run: |
git clone https://github.com/grafana/plugin-validator
pushd ./plugin-validator/pkg/cmd/plugincheck2
go install
popd
plugincheck2 -config ./plugin-validator/config/default.yaml ${{ steps.metadata.outputs.archive }}

- name: Create Github release
uses: softprops/action-gh-release@v1
with:
draft: true
generate_release_notes: true
files: |
./${{ steps.metadata.outputs.archive }}
./${{ steps.metadata.outputs.archive-checksum }}
body: |
**This Github draft release has been created for your plugin.**

_Note: if this is the first release for your plugin please consult the [distributing-your-plugin section](https://github.com/${{github.repository}}/blob/main/README.md#distributing-your-plugin) of the README_

If you would like to submit this release to Grafana please consider the following steps:

- Check the Validate plugin step in the [release workflow](https://github.com/${{github.repository}}/commit/${{github.sha}}/checks/${{github.run_id}}) for any warnings that need attention
- Navigate to https://grafana.com/auth/sign-in/ to sign into your account
- Once logged in click **My Plugins** in the admin navigation
- Click the **Submit Plugin** button
- Fill in the Plugin Submission form:
- Paste this [.zip asset link](https://github.com/${{ github.repository }}/releases/download/v${{ steps.metadata.outputs.plugin-version }}/${{ steps.metadata.outputs.archive }}) in the Plugin URL field
- Paste this [.zip.md5 link](https://github.com/${{ github.repository }}/releases/download/v${{ steps.metadata.outputs.plugin-version }}/${{ steps.metadata.outputs.archive-checksum }}) in the MD5 field

Once done please remove these instructions and publish this release.
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
18
18
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,4 @@
"rxjs": "7.8.0",
"tslib": "2.5.3"
}
}
}
2 changes: 1 addition & 1 deletion src/datasources/data-frame/DataFrameDataSource.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,4 +285,4 @@ const defaultQuery: DataQueryRequest<DataFrameQuery> = {
app: 'explore',
startTime: 0,
targets: [],
};
};
13 changes: 9 additions & 4 deletions src/datasources/data-frame/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# Systemlink Data Frame data source

<!--
TODO: Write a short description of your plugin and document any extra
configuration that is required for development.
-->
This plugin will have three main workflows:

- Populating a
[query variable](https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#add-a-query-variable)
with a list of user-accessible systems

- Visualizing system connection status counts on a dashboard

- Visualizing system metadata on a dashboard
mure marked this conversation as resolved.
Show resolved Hide resolved
6 changes: 6 additions & 0 deletions src/datasources/system/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Systemlink System data source

<!--
TODO: Write a short description of your plugin and document any extra
configuration that is required for development.
-->
mure marked this conversation as resolved.
Show resolved Hide resolved
46 changes: 46 additions & 0 deletions src/datasources/system/SystemDataSource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import {
DataQueryRequest,
DataQueryResponse,
DataSourceApi,
DataSourceInstanceSettings,
MutableDataFrame,
FieldType,
} from '@grafana/data';

import { TestingStatus, getBackendSrv } from '@grafana/runtime';

import { SystemQuery } from './types';

export class SystemDataSource extends DataSourceApi<SystemQuery> {
baseUrl: string;
constructor(private instanceSettings: DataSourceInstanceSettings) {
super(instanceSettings);
// TODO: set base path of the service
this.baseUrl = this.instanceSettings.url + '/nifoo/v2';
}

async query(options: DataQueryRequest<SystemQuery>): Promise<DataQueryResponse> {
const { range } = options;
const from = range!.from.valueOf();
const to = range!.to.valueOf();

// Return a constant for each query.
const data = options.targets.map((target) => {
return new MutableDataFrame({
refId: target.refId,
fields: [
{ name: 'Time', values: [from, to], type: FieldType.time },
{ name: 'Value', values: [target.constant, target.constant], type: FieldType.number },
],
});
});

return { data };
}

async testDatasource(): Promise<TestingStatus> {
// TODO: Implement a health and authentication check
await getBackendSrv().get(this.baseUrl + '/bar');
return { status: 'success', message: 'Data source connected and authentication successful!' };
}
}
32 changes: 32 additions & 0 deletions src/datasources/system/components/SystemQueryEditor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React, { ChangeEvent } from 'react';
import { InlineField, Input } from '@grafana/ui';
import { QueryEditorProps } from '@grafana/data';
import { SystemDataSource } from '../SystemDataSource';
import { SystemQuery } from '../types';

type Props = QueryEditorProps<SystemDataSource, SystemQuery>;

export function SystemQueryEditor({ query, onChange, onRunQuery }: Props) {
const onQueryTextChange = (event: ChangeEvent<HTMLInputElement>) => {
onChange({ ...query, queryText: event.target.value });
};

const onConstantChange = (event: ChangeEvent<HTMLInputElement>) => {
onChange({ ...query, constant: parseFloat(event.target.value) });
// executes the query
onRunQuery();
};

const { queryText, constant } = query;

return (
<div className="gf-form">
<InlineField label="Constant">
<Input onChange={onConstantChange} value={constant} width={8} type="number" step="0.1" />
</InlineField>
<InlineField label="Query Text" labelWidth={16} tooltip="Not used yet">
<Input onChange={onQueryTextChange} value={queryText || ''} />
</InlineField>
</div>
);
}
11 changes: 11 additions & 0 deletions src/datasources/system/img/logo-ni.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions src/datasources/system/module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { DataSourcePlugin } from '@grafana/data';
import { SystemDataSource } from './SystemDataSource';
import { SystemQueryEditor } from './components/SystemQueryEditor';
import { HttpConfigEditor } from 'core/HttpConfigEditor';

export const plugin = new DataSourcePlugin(SystemDataSource)
.setConfigEditor(HttpConfigEditor)
.setQueryEditor(SystemQueryEditor);
6 changes: 6 additions & 0 deletions src/datasources/system/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { DataQuery } from '@grafana/schema'

export interface SystemQuery extends DataQuery {
queryText?: string;
constant: number;
}