Merge pull request #5998 from influxdata/feat/setup_v2_dbrp

feat: setup DBRP mapping automatically for a v2 connection
BNP_sign_artifacts
Pavel Závora 2022-08-23 14:10:46 +02:00 committed by GitHub
commit 3b181b1d9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 139 additions and 6 deletions

View File

@ -14,6 +14,7 @@
1. [#5959](https://github.com/influxdata/chronograf/pull/5959): Allow to customize annotation color.
1. [#5967](https://github.com/influxdata/chronograf/pull/5967): Remember whether to start with shown annotations on Dashboard page.
1. [#5977](https://github.com/influxdata/chronograf/pull/5977): Select current value in dropdown search input.
1. [#5998](https://github.com/influxdata/chronograf/pull/5998): Setup DBRP mapping automatically for a v2 connection.
### Bug Fixes

View File

@ -204,6 +204,7 @@ func NewMux(opts MuxOpts, service Service) http.Handler {
// Source Proxy to Influx's flux endpoint; compression because the responses from
// flux could be large.
router.Handler("POST", "/chronograf/v1/sources/:id/proxy/flux", EnsureReader(service.ProxyFlux))
router.Handler("GET", "/chronograf/v1/sources/:id/proxy/flux", EnsureReader(service.ProxyFlux))
// Write proxies line protocol write requests to InfluxDB
router.POST("/chronograf/v1/sources/:id/write", EnsureViewer(service.Write))

View File

@ -0,0 +1,85 @@
import {SOURCE_TYPE_INFLUX_V2} from 'src/shared/constants'
import {Source} from 'src/types'
import AJAX from 'src/utils/ajax'
export interface DBRP {
id: string
bucketID: string
database: string
retention_policy: string
default: boolean
}
async function getTelegrafBucketID(
source: Source
): Promise<string | undefined> {
// try to get bucket of the same name
const v2BucketsPath = `/api/v2/buckets?org=${encodeURIComponent(
source.username
)}&name=${encodeURIComponent(source.telegraf)}`
try {
const response = await AJAX({
method: 'GET',
url: `${source.links.flux}?version=${encodeURIComponent(
source.version
)}&path=${encodeURIComponent(v2BucketsPath)}`,
data: '',
})
if (response.status !== 200) {
return undefined
}
return response.data?.buckets?.[0]?.id
// eslint-disable-next-line no-empty
} catch (e) {}
}
async function createDBRPMapping(
source: Source,
bucketID: string
): Promise<DBRP | undefined> {
// try to get bucket of the same name
const body = {
bucketID,
database: source.telegraf,
retention_policy: source.defaultRP || 'autogen',
default: true,
org: source.username,
}
try {
const response = await AJAX({
method: 'POST',
url: `${source.links.flux}?version=${encodeURIComponent(
source.version
)}&path=/api/v2/dbrps`,
data: body,
headers: {'Content-Type': 'application/json'},
})
if (response.status === 201 && response.data.id) {
return response.data as DBRP
}
console.warn('Cannot create v1 DBRP mapping', response.data)
} catch (e) {
console.warn('Cannot create v1 DBRP mapping', e)
}
}
export async function createDBRP(source: Source): Promise<DBRP | undefined> {
if (
!source.links?.flux ||
source.type !== SOURCE_TYPE_INFLUX_V2 ||
!source.telegraf
) {
return
}
const bucketID = await getTelegrafBucketID(source)
if (!bucketID) {
console.warn(
`Cannot verify existence of ${source.telegraf} bucket, v1 DBRP mapping cannot be created`
)
return
}
// create DBRP mappings for bucket id
return await createDBRPMapping(source, bucketID)
}

View File

@ -4,6 +4,8 @@ import _ from 'lodash'
import {proxy} from 'src/utils/queryUrlGenerator'
// Types
import {Source, Protoboard} from 'src/types'
import {SOURCE_TYPE_INFLUX_V2} from 'src/shared/constants'
import {createDBRP, DBRP} from './createDBRP'
interface SeriesObject {
measurement: string
@ -32,9 +34,10 @@ interface HostsSeries {
export const getSuggestedProtoboards = async (
source: Source,
protoboards: Protoboard[]
protoboards: Protoboard[],
afterCreatedDBRP: (dbrp: DBRP) => void = () => undefined
): Promise<string[]> => {
const hosts = await getHosts(source)
const hosts = await getHosts(source, afterCreatedDBRP)
if (!hosts) {
return []
@ -94,16 +97,38 @@ export const addAppsToHosts = async (
return newHosts
}
export const getHosts = async (source: Source): Promise<Hosts> => {
const getHosts = async (
source: Source,
afterCreatedDBRP: (dbrp: DBRP) => void
): Promise<Hosts> => {
const hosts = {}
const query = `SHOW TAG VALUES WITH KEY = "host" WHERE TIME > now() - 10m;`
const resp = await proxy({
let resp = await proxy({
source: source.links.proxy,
query,
db: source.telegraf,
})
const loadError = _.get(resp, ['data', 'results', '0', 'error'])
if (loadError) {
console.warn('Cannot suggest protoboards:', loadError)
if (source.type === SOURCE_TYPE_INFLUX_V2) {
// try to create DBRP mapping for ${source.telegraf} bucket
const dbrp = await createDBRP(source)
if (dbrp) {
if (afterCreatedDBRP) {
afterCreatedDBRP(dbrp)
}
// reload query
resp = await proxy({
source: source.links.proxy,
query,
db: source.telegraf,
})
}
}
}
const allHostsSeries: HostsSeries[] = _.get(
resp,

View File

@ -928,3 +928,13 @@ export const fluxWizardError = (message: string): Notification => ({
duration: FIVE_SECONDS,
message,
})
export const notifyDBRPCreated = (
bucket: string,
db: string,
rp: string
): Notification => ({
...defaultSuccessNotification,
duration: TEN_SECONDS,
message: `Default V1 DBRP mapping created. V2 bucket '${bucket}' is mapped to v1 database '${db}' with retention policy '${rp}'.`,
})

View File

@ -27,11 +27,13 @@ import {notify as notifyAction} from 'src/shared/actions/notifications'
import {
notifyDashboardCreated,
notifyDashboardCreationFailed,
notifyDBRPCreated,
} from 'src/shared/copy/notifications'
// Types
import {Protoboard, Source, RemoteDataState} from 'src/types'
import {NextReturn} from 'src/types/wizard'
import {DBRP} from 'src/dashboards/utils/createDBRP'
interface SelectedDashboard {
[x: string]: boolean
@ -237,7 +239,7 @@ class DashboardStep extends Component<Props, State> {
private handleSuggest = async () => {
const {protoboards} = this.state
const {source} = this.props
const {source, notify} = this.props
if (source) {
if (this.isComponentMounted) {
@ -247,7 +249,16 @@ class DashboardStep extends Component<Props, State> {
try {
const suggestedProtoboardsList = await getSuggestedProtoboards(
source,
protoboards
protoboards,
(dbrp: DBRP) => {
notify(
notifyDBRPCreated(
source.telegraf,
dbrp.database,
dbrp.retention_policy
)
)
}
)
if (suggestedProtoboardsList.length === 0) {