Skip to content

Commit 8ea2dea

Browse files
committed
feat(providerconfig): add stackSecretRef for stack connection details
Add an optional StackSecretRef field to all ProviderConfigSpec types (cluster, namespaced, and cluster-namespaced). When set, the referenced Secret is fetched and its keys are merged into the credential map with key remapping (oncall_api_url -> oncall_url, id -> stack_id). Precedence (lowest to highest): 1. Primary credential secret (credentials.secretRef) 2. Stack secret (stackSecretRef) 3. ProviderConfig spec fields (url, oncallUrl, etc.)
1 parent e3f8c1c commit 8ea2dea

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed

apis/cluster/v1beta1/types.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@ type ProviderConfigSpec struct {
3333

3434
// Credentials required to authenticate to this provider.
3535
Credentials ProviderCredentials `json:"credentials"`
36+
37+
// StackSecretRef is an optional reference to a Secret containing Stack
38+
// connection details (e.g., from a grafana_cloud_stack resource's
39+
// writeConnectionSecretToRef). All keys in the Secret are merged into
40+
// the credential map. Key remapping is applied (e.g., oncall_api_url
41+
// becomes oncall_url, id becomes stack_id). Values from this secret
42+
// override the primary credentials secret and are in turn overridden by
43+
// explicit spec fields (url, oncallUrl, etc.).
44+
// +optional
45+
StackSecretRef *xpv1.SecretReference `json:"stackSecretRef,omitempty"`
3646
}
3747

3848
// ProviderCredentials required to authenticate.

apis/namespaced/v1beta1/types.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ type ProviderConfigSpec struct {
2525
StackID *int `json:"stackId,omitempty"`
2626

2727
Credentials ProviderCredentials `json:"credentials"`
28+
29+
// StackSecretRef is an optional reference to a Secret containing Stack
30+
// connection details (e.g., from a grafana_cloud_stack resource's
31+
// writeConnectionSecretToRef). All keys in the Secret are merged into
32+
// the credential map. Key remapping is applied (e.g., oncall_api_url
33+
// becomes oncall_url, id becomes stack_id). Values from this secret
34+
// override the primary credentials secret and are in turn overridden by
35+
// explicit spec fields (url, oncallUrl, etc.).
36+
// +optional
37+
StackSecretRef *xpv1.SecretReference `json:"stackSecretRef,omitempty"`
2838
}
2939

3040
type ProviderCredentials struct {

internal/clients/grafana.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
grafanaProvider "github.com/grafana/terraform-provider-grafana/v4/pkg/provider"
1616
terraformSDK "github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
1717
"github.com/pkg/errors"
18+
corev1 "k8s.io/api/core/v1"
1819
"k8s.io/apimachinery/pkg/types"
1920
"sigs.k8s.io/controller-runtime/pkg/client"
2021

@@ -30,8 +31,16 @@ const (
3031
errUpdateStatus = "cannot update ProviderConfig status"
3132
errExtractCredentials = "cannot extract credentials"
3233
errUnmarshalCredentials = "cannot unmarshal grafana credentials as JSON"
34+
errGetStackSecret = "cannot get referenced stack secret"
3335
)
3436

37+
// stackSecretKeyRemap maps Stack connection secret keys (Terraform attribute
38+
// names) to the ProviderConfig credential keys expected by BuildTFConfig.
39+
var stackSecretKeyRemap = map[string]string{
40+
"oncall_api_url": "oncall_url",
41+
"id": "stack_id",
42+
}
43+
3544
type Credentials struct {
3645
Source v1.CredentialsSource
3746
v1.CommonCredentialSelectors `json:",inline"`
@@ -48,6 +57,32 @@ type Config struct {
4857
OrgID *int
4958
StackID *int
5059
Credentials Credentials
60+
StackSecretRef *v1.SecretReference
61+
}
62+
63+
// mergeStackSecret fetches the Secret referenced by cfg.StackSecretRef and
64+
// merges its keys into the credential map. Keys are remapped according to
65+
// stackSecretKeyRemap (e.g. oncall_api_url → oncall_url, id → stack_id).
66+
// Stack secret values override existing credential values.
67+
func mergeStackSecret(ctx context.Context, c client.Client, cfg *Config, creds map[string]string) error {
68+
if cfg.StackSecretRef == nil {
69+
return nil
70+
}
71+
secret := &corev1.Secret{}
72+
if err := c.Get(ctx, types.NamespacedName{
73+
Name: cfg.StackSecretRef.Name,
74+
Namespace: cfg.StackSecretRef.Namespace,
75+
}, secret); err != nil {
76+
return errors.Wrap(err, errGetStackSecret)
77+
}
78+
for k, v := range secret.Data {
79+
key := k
80+
if remapped, ok := stackSecretKeyRemap[k]; ok {
81+
key = remapped
82+
}
83+
creds[key] = string(v)
84+
}
85+
return nil
5186
}
5287

5388
func useLegacyProviderConfig(ctx context.Context, c client.Client, mg resource.LegacyManaged) (*Config, error) {
@@ -85,6 +120,13 @@ func useLegacyProviderConfig(ctx context.Context, c client.Client, mg resource.L
85120
StackID: pc.Spec.StackID,
86121
}
87122

123+
if sr := pc.Spec.StackSecretRef; sr != nil {
124+
config.StackSecretRef = &v1.SecretReference{
125+
Name: sr.Name,
126+
Namespace: sr.Namespace,
127+
}
128+
}
129+
88130
// Convert v1 to v2 types explicitly
89131
// Best-effort simple field copies (types differ between v1 and v2 runtime packages); we only use SecretRef today.
90132
config.Credentials.Source = v1.CredentialsSource(string(pc.Spec.Credentials.Source))
@@ -154,6 +196,7 @@ func useModernProviderConfig(ctx context.Context, c client.Client, mg resource.M
154196
SMURL: spec.SMURL,
155197
OrgID: spec.OrgID,
156198
StackID: spec.StackID,
199+
StackSecretRef: spec.StackSecretRef,
157200
Credentials: Credentials{
158201
Source: spec.Credentials.Source,
159202
CommonCredentialSelectors: spec.Credentials.CommonCredentialSelectors,
@@ -195,6 +238,10 @@ func TerraformSetupBuilder() terraform.SetupFn {
195238
return ps, errors.Wrap(err, errUnmarshalCredentials)
196239
}
197240

241+
if err := mergeStackSecret(ctx, client, &credSpec, creds); err != nil {
242+
return ps, err
243+
}
244+
198245
// Resolve ProbeNames to Probes for SM Check resources
199246
if err := resolveSMCheckProbeNames(ctx, client, mg, creds, credSpec); err != nil {
200247
return ps, errors.Wrap(err, "failed to resolve probe names")
@@ -228,6 +275,10 @@ func ExtractModernConfig(ctx context.Context, c client.Client, mg resource.Moder
228275
return nil, nil, errors.Wrap(err, errUnmarshalCredentials)
229276
}
230277

278+
if err := mergeStackSecret(ctx, c, cfg, creds); err != nil {
279+
return nil, nil, err
280+
}
281+
231282
return cfg, creds, nil
232283
}
233284

0 commit comments

Comments
 (0)