Skip to content

Commit 5b35118

Browse files
Enable PDC on Github Datasource (#527)
This PR adds support for PDC on the GitHub datasource: <img width="547" height="315" alt="Screenshot 2025-11-07 at 10 12 06 AM" src="https://github.com/user-attachments/assets/b79ee82b-2c2f-483d-b728-ad9b563a9b40" /> I tested using: https://wiki.grafana-ops.net/w/index.php/Engineering/Grafana/Data_Sources/API_servers/Testing_datasources_with_PDC_Locally. Confirmed that after enabling PDC, and the secure socks proxy toggle, I could see logs coming from the Agent. Similarly when I turned the agent off, I could see queries begin to fail. Fixes [#120](https://github.com/orgs/grafana/projects/457/views/40?pane=issue&itemId=136225987&issue=grafana%7Coss-big-tent-squad%7C120) --------- Co-authored-by: Zoltán Bedi <zoltan.bedi@gmail.com>
1 parent 6afb05c commit 5b35118

File tree

5 files changed

+59
-17
lines changed

5 files changed

+59
-17
lines changed

.changeset/lazy-planes-reply.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'grafana-github-datasource': minor
3+
---
4+
5+
Add support for PDC

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ Watch this video to learn more about setting up the Grafana GitHub data source p
2222

2323
This data source uses the [`githubv4` package](https://github.com/shurcooL/githubv4), which is under active development.
2424

25+
## Private data source connect - Only for Grafana Cloud users.
26+
27+
Establishes a private, secured connection between a Grafana Cloud stack and data sources within a private network. Use the drop-down to locate the PDC URL. For setup instructions, refer to [Private data source connect (PDC)](https://grafana.com/docs/grafana-cloud/connect-externally-hosted/private-data-source-connect/) and [Configure PDC](https://grafana.com/docs/grafana-cloud/connect-externally-hosted/private-data-source-connect/configure-pdc/#configure-grafana-private-data-source-connect-pdc). Click Manage private data source connect to open your PDC connection page and view your configuration details.
28+
2529
## Frequently Asked Questions
2630

2731
- **Why does it sometimes take up to 5 minutes for my new pull request / new issue / new commit to show up?**

pkg/github/client/client.go

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
googlegithub "github.com/google/go-github/v72/github"
1414
"github.com/grafana/grafana-plugin-sdk-go/backend"
1515
"github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
16+
"github.com/grafana/grafana-plugin-sdk-go/backend/proxy"
1617
"github.com/influxdata/tdigest"
1718
"github.com/shurcooL/githubv4"
1819
"golang.org/x/oauth2"
@@ -54,27 +55,33 @@ var runnerPerMinuteRate = map[string]float64{
5455

5556
// New instantiates a new GitHub API client.
5657
func New(ctx context.Context, settings models.Settings) (*Client, error) {
58+
plugin := backend.PluginConfigFromContext(ctx)
59+
opts, err := plugin.DataSourceInstanceSettings.HTTPClientOptions(ctx)
60+
if err != nil {
61+
return nil, err
62+
}
63+
5764
if settings.SelectedAuthType == models.AuthTypeGithubApp {
58-
return createAppClient(settings)
65+
return createAppClient(settings, opts)
5966
}
6067
if settings.SelectedAuthType == models.AuthTypePAT {
61-
return createAccessTokenClient(ctx, settings)
68+
return createAccessTokenClient(ctx, settings, opts)
6269
}
6370
return nil, backend.DownstreamError(errors.New("access token or app token are required"))
6471
}
6572

66-
func createAppClient(settings models.Settings) (*Client, error) {
67-
transport, err := httpclient.GetDefaultTransport()
73+
func createAppClient(settings models.Settings, opts httpclient.Options) (*Client, error) {
74+
httpClient, err := httpclient.New(opts)
6875
if err != nil {
69-
return nil, backend.DownstreamError(errors.New("error: http.DefaultTransport is not of type *http.Transport"))
76+
return nil, backend.DownstreamErrorf("error creating http client: %w", err)
7077
}
71-
itr, err := ghinstallation.New(transport, settings.AppIdInt64, settings.InstallationIdInt64, []byte(settings.PrivateKey))
78+
79+
itr, err := ghinstallation.New(httpClient.Transport, settings.AppIdInt64, settings.InstallationIdInt64, []byte(settings.PrivateKey))
7280
if err != nil {
7381
return nil, backend.DownstreamError(errors.New("error creating token source"))
7482
}
7583

76-
httpClient := &http.Client{Transport: itr}
77-
84+
httpClient.Transport = itr
7885
if settings.GitHubURL == "" {
7986
return &Client{
8087
restClient: googlegithub.NewClient(httpClient),
@@ -87,13 +94,26 @@ func createAppClient(settings models.Settings) (*Client, error) {
8794
return useGitHubEnterprise(httpClient, settings)
8895
}
8996

90-
func createAccessTokenClient(ctx context.Context, settings models.Settings) (*Client, error) {
97+
func createAccessTokenClient(ctx context.Context, settings models.Settings, opts httpclient.Options) (*Client, error) {
9198
src := oauth2.StaticTokenSource(
9299
&oauth2.Token{AccessToken: settings.AccessToken},
93100
)
94101

95102
httpClient := oauth2.NewClient(ctx, src)
96103

104+
cli := proxy.New(opts.ProxyOptions)
105+
if cli.SecureSocksProxyEnabled() {
106+
// only override the Transport if Secure Proxy is enabled.
107+
transport, err := httpclient.GetTransport(opts)
108+
if err != nil {
109+
return nil, backend.DownstreamErrorf("error getting the transport: %w", err)
110+
}
111+
112+
httpClient.Transport = &oauth2.Transport{
113+
Base: transport,
114+
Source: oauth2.ReuseTokenSource(nil, src),
115+
}
116+
}
97117
if settings.GitHubURL == "" {
98118
return &Client{
99119
restClient: googlegithub.NewClient(httpClient),

pkg/plugin/instance.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ func NewGitHubInstance(ctx context.Context, settings models.Settings) (instancem
2828
}
2929

3030
// NewDataSourceInstance creates a new instance
31-
func NewDataSourceInstance(_ context.Context, settings backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
31+
func NewDataSourceInstance(ctx context.Context, settings backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
3232
datasourceSettings, err := models.LoadSettings(settings)
3333
if err != nil {
3434
return nil, err
3535
}
36-
36+
3737
datasourceSettings.CachingEnabled = true
3838

39-
instance, err := NewGitHubInstance(context.Background(), datasourceSettings)
39+
instance, err := NewGitHubInstance(ctx, datasourceSettings)
4040
if err != nil {
4141
return instance, fmt.Errorf("instantiating github instance: %w", err)
4242
}

src/views/ConfigEditor.tsx

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,28 @@
11
import React, { ChangeEvent, useCallback, useEffect, useState } from 'react';
22
import { css } from '@emotion/css';
3-
import { Collapse, Field, Input, Label, RadioButtonGroup, SecretInput, SecretTextArea, useStyles2 } from '@grafana/ui';
4-
import { ConfigSection, DataSourceDescription } from '@grafana/plugin-ui';
5-
import { Divider } from 'components/Divider';
6-
import { components as selectors } from '../components/selectors';
73
import {
84
onUpdateDatasourceJsonDataOption,
95
onUpdateDatasourceSecureJsonDataOption,
106
type DataSourcePluginOptionsEditorProps,
117
type GrafanaTheme2,
128
type SelectableValue,
139
} from '@grafana/data';
10+
import { ConfigSection, DataSourceDescription } from '@grafana/plugin-ui';
11+
import { config } from '@grafana/runtime';
12+
import {
13+
Collapse,
14+
Field,
15+
Input,
16+
Label,
17+
RadioButtonGroup,
18+
SecretInput,
19+
SecretTextArea,
20+
SecureSocksProxySettings,
21+
useStyles2,
22+
} from '@grafana/ui';
23+
import { Divider } from 'components/Divider';
1424
import type { GitHubAuthType, GitHubLicenseType, GitHubDataSourceOptions, GitHubSecureJsonData } from 'types/config';
25+
import { components as selectors } from '../components/selectors';
1526

1627
export type ConfigEditorProps = DataSourcePluginOptionsEditorProps<GitHubDataSourceOptions, GitHubSecureJsonData>;
1728

@@ -196,7 +207,9 @@ const ConfigEditor = (props: ConfigEditorProps) => {
196207
</>
197208
)}
198209
</ConfigSection>
199-
210+
{config.secureSocksDSProxyEnabled && (
211+
<SecureSocksProxySettings options={options} onOptionsChange={onOptionsChange} />
212+
)}
200213
<Divider />
201214

202215
<ConfigSection title="Connection" isCollapsible>

0 commit comments

Comments
 (0)