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(client): add support for custom HTTP headers #1756

Merged
9 changes: 6 additions & 3 deletions api/v1beta1/grafana_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ type GrafanaClient struct {
// TLS Configuration used to talk with the grafana instance.
// +optional
TLS *TLSConfig `json:"tls,omitempty"`
// Custom HTTP headers to use when interacting with this Grafana.
// +optional
Headers map[string]string `json:"headers,omitempty"`
}

// GrafanaPreferences holds Grafana preferences API settings
Expand All @@ -138,8 +141,8 @@ type GrafanaStatus struct {
Version string `json:"version,omitempty"`
}

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status

// Grafana is the Schema for the grafanas API
// +kubebuilder:printcolumn:name="Version",type="string",JSONPath=".status.version",description=""
Expand All @@ -154,7 +157,7 @@ type Grafana struct {
Status GrafanaStatus `json:"status,omitempty"`
}

//+kubebuilder:object:root=true
// +kubebuilder:object:root=true

// GrafanaList contains a list of Grafana
type GrafanaList struct {
Expand Down
7 changes: 7 additions & 0 deletions api/v1beta1/zz_generated.deepcopy.go

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

6 changes: 6 additions & 0 deletions config/crd/bases/grafana.integreatly.org_grafanas.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ spec:
description: Client defines how the grafana-operator talks to the
grafana instance.
properties:
headers:
additionalProperties:
type: string
description: Custom HTTP headers to use when interacting with
this Grafana.
type: object
preferIngress:
description: If the operator should send it's request through
the grafana instances ingress object instead of through the
Expand Down
4 changes: 4 additions & 0 deletions controllers/client/grafana_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ func NewGeneratedGrafanaClient(ctx context.Context, c client.Client, grafana *v1
}

transport := NewInstrumentedRoundTripper(grafana.Name, metrics.GrafanaApiRequests, grafana.IsExternal(), tlsConfig)
if grafana.Spec.Client != nil && grafana.Spec.Client.Headers != nil {
transport.(*instrumentedRoundTripper).addHeaders(grafana.Spec.Client.Headers) //nolint:errcheck
}

client := &http.Client{
Transport: transport,
Expand All @@ -161,6 +164,7 @@ func NewGeneratedGrafanaClient(ctx context.Context, c client.Client, grafana *v1
if credentials.username != "" {
cfg.BasicAuth = url.UserPassword(credentials.username, credentials.password)
}

cl := genapi.NewHTTPClientWithConfig(nil, cfg)

return cl, nil
Expand Down
7 changes: 6 additions & 1 deletion controllers/client/http_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,13 @@ func NewHTTPClient(ctx context.Context, c client.Client, grafana *v1beta1.Grafan
return nil, err
}

transport := NewInstrumentedRoundTripper(grafana.Name, metrics.GrafanaApiRequests, grafana.IsExternal(), tlsConfig)
if grafana.Spec.Client != nil && grafana.Spec.Client.Headers != nil {
transport.(*instrumentedRoundTripper).addHeaders(grafana.Spec.Client.Headers) //nolint:errcheck
}

return &http.Client{
Transport: NewInstrumentedRoundTripper(grafana.Name, metrics.GrafanaApiRequests, grafana.IsExternal(), tlsConfig),
Transport: transport,
Timeout: time.Second * timeout,
}, nil
}
26 changes: 25 additions & 1 deletion controllers/client/round_tripper.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type instrumentedRoundTripper struct {
relatedResource string
wrapped http.RoundTripper
metric *prometheus.CounterVec
headers map[string]string
}

func NewInstrumentedRoundTripper(relatedResource string, metric *prometheus.CounterVec, useProxy bool, tlsConfig *tls.Config) http.RoundTripper {
Expand All @@ -29,15 +30,24 @@ func NewInstrumentedRoundTripper(relatedResource string, metric *prometheus.Coun
transport.Proxy = nil
}

headers := make(map[string]string)
headers["user-agent"] = "grafana-operator/" + embeds.Version

return &instrumentedRoundTripper{
relatedResource: relatedResource,
wrapped: transport,
metric: metric,
headers: headers,
}
}

func (in *instrumentedRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
r.Header.Add("user-agent", "grafana-operator/"+embeds.Version)
if in.headers != nil {
for k, v := range in.headers {
r.Header.Add(k, v)
}
}

resp, err := in.wrapped.RoundTrip(r)
if resp != nil {
in.metric.WithLabelValues(
Expand All @@ -48,3 +58,17 @@ func (in *instrumentedRoundTripper) RoundTrip(r *http.Request) (*http.Response,
}
return resp, err
}

func (in *instrumentedRoundTripper) addHeaders(headers map[string]string) {
if headers == nil {
return
}

if in.headers == nil {
in.headers = make(map[string]string)
}

for k, v := range headers {
in.headers[k] = v
}
}
16 changes: 8 additions & 8 deletions controllers/grafana_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@ type GrafanaReconciler struct {
IsOpenShift bool
}

//+kubebuilder:rbac:groups=grafana.integreatly.org,resources=grafanas,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=grafana.integreatly.org,resources=grafanas/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=grafana.integreatly.org,resources=grafanas/finalizers,verbs=update
//+kubebuilder:rbac:groups=route.openshift.io,resources=routes;routes/custom-host,verbs=get;list;create;update;delete;watch
//+kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups="",resources=events,verbs=get;list;watch;create;patch
//+kubebuilder:rbac:groups="",resources=configmaps;secrets;serviceaccounts;services;persistentvolumeclaims,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=networking.k8s.io,resources=ingresses,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=grafana.integreatly.org,resources=grafanas,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=grafana.integreatly.org,resources=grafanas/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=grafana.integreatly.org,resources=grafanas/finalizers,verbs=update
// +kubebuilder:rbac:groups=route.openshift.io,resources=routes;routes/custom-host,verbs=get;list;create;update;delete;watch
// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups="",resources=events,verbs=get;list;watch;create;patch
// +kubebuilder:rbac:groups="",resources=configmaps;secrets;serviceaccounts;services;persistentvolumeclaims,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=networking.k8s.io,resources=ingresses,verbs=get;list;watch;create;update;patch;delete

func (r *GrafanaReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
controllerLog := log.FromContext(ctx).WithName("GrafanaReconciler")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ spec:
description: Client defines how the grafana-operator talks to the
grafana instance.
properties:
headers:
additionalProperties:
type: string
description: Custom HTTP headers to use when interacting with
this Grafana.
type: object
preferIngress:
description: If the operator should send it's request through
the grafana instances ingress object instead of through the
Expand Down
6 changes: 6 additions & 0 deletions deploy/kustomize/base/crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1882,6 +1882,12 @@ spec:
description: Client defines how the grafana-operator talks to the
grafana instance.
properties:
headers:
additionalProperties:
type: string
description: Custom HTTP headers to use when interacting with
this Grafana.
type: object
preferIngress:
description: If the operator should send it's request through
the grafana instances ingress object instead of through the
Expand Down
7 changes: 7 additions & 0 deletions docs/docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -3785,6 +3785,13 @@ Client defines how the grafana-operator talks to the grafana instance.
</tr>
</thead>
<tbody><tr>
<td><b>headers</b></td>
<td>map[string]string</td>
<td>
Custom HTTP headers to use when interacting with this Grafana.<br/>
</td>
<td>false</td>
</tr><tr>
<td><b>preferIngress</b></td>
<td>boolean</td>
<td>
Expand Down