feat: allow secrets collector to retreive all key data if specified (#1801)

* allow secrets collector retreival all key data if specified

* add new line

* remove unneeded comments
This commit is contained in:
Diamon Wiggins
2025-06-30 10:06:14 -04:00
committed by GitHub
parent 4281c67066
commit f57a2b487c
10 changed files with 232 additions and 15 deletions
@@ -17077,6 +17077,8 @@ spec:
type: string
exclude:
type: BoolString
includeAllData:
type: boolean
includeValue:
type: boolean
key:
@@ -18897,6 +18897,8 @@ spec:
type: string
exclude:
type: BoolString
includeAllData:
type: boolean
includeValue:
type: boolean
key:
@@ -18928,6 +18928,8 @@ spec:
type: string
exclude:
type: BoolString
includeAllData:
type: boolean
includeValue:
type: boolean
key:
@@ -0,0 +1,50 @@
apiVersion: troubleshoot.sh/v1beta2
kind: SupportBundle
metadata:
name: secret-collector-examples
spec:
collectors:
# Basic secret collection (no key-value data included)
- secret:
collectorName: basic-secret
name: my-app-config
namespace: default
# Collect specific key with value
- secret:
collectorName: specific-key-with-value
name: my-app-config
namespace: default
key: database-password
includeValue: true
# NEW: Collect all key-value pairs from a secret
- secret:
collectorName: all-secret-data
name: my-app-config
namespace: default
includeAllData: true
# NEW: Collect all key-value pairs AND a specific key (combined approach)
- secret:
collectorName: combined-collection
name: my-app-config
namespace: default
key: database-password
includeValue: true
includeAllData: true
# NEW: Collect all secrets matching a selector with all their data
- secret:
collectorName: secrets-by-selector-all-data
namespace: default
selector:
- app=my-app
includeAllData: true
# Collect secrets by selector (traditional approach)
- secret:
collectorName: secrets-by-selector-basic
namespace: default
selector:
- app=my-app
@@ -51,12 +51,13 @@ type NodeMetrics struct {
}
type Secret struct {
CollectorMeta `json:",inline" yaml:",inline"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Selector []string `json:"selector,omitempty" yaml:"selector,omitempty"`
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
Key string `json:"key,omitempty" yaml:"key,omitempty"`
IncludeValue bool `json:"includeValue,omitempty" yaml:"includeValue,omitempty"`
CollectorMeta `json:",inline" yaml:",inline"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Selector []string `json:"selector,omitempty" yaml:"selector,omitempty"`
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
Key string `json:"key,omitempty" yaml:"key,omitempty"`
IncludeValue bool `json:"includeValue,omitempty" yaml:"includeValue,omitempty"`
IncludeAllData bool `json:"includeAllData,omitempty" yaml:"includeAllData,omitempty"`
}
type ConfigMap struct {
+18 -9
View File
@@ -18,12 +18,13 @@ import (
)
type SecretOutput struct {
Namespace string `json:"namespace"`
Name string `json:"name"`
Key string `json:"key"`
SecretExists bool `json:"secretExists"`
KeyExists bool `json:"keyExists"`
Value string `json:"value,omitempty"`
Namespace string `json:"namespace"`
Name string `json:"name"`
Key string `json:"key"`
SecretExists bool `json:"secretExists"`
KeyExists bool `json:"keyExists"`
Value string `json:"value,omitempty"`
Data map[string]string `json:"data,omitempty"`
}
type CollectSecret struct {
@@ -93,7 +94,13 @@ func secretToOutput(secretCollector *troubleshootv1beta2.Secret, secret *corev1.
if secret != nil {
foundSecret.SecretExists = true
if secretCollector.Key != "" {
if secretCollector.IncludeAllData {
foundSecret.Data = make(map[string]string)
for k, v := range secret.Data {
foundSecret.Data[k] = string(v)
}
} else if secretCollector.Key != "" {
if val, ok := secret.Data[secretCollector.Key]; ok {
foundSecret.KeyExists = true
if secretCollector.IncludeValue {
@@ -134,7 +141,8 @@ func marshalSecretOutput(secretCollector *troubleshootv1beta2.Secret, secret Sec
func GetSecretFileName(secretCollector *troubleshootv1beta2.Secret, name string) string {
parts := []string{"secrets", secretCollector.Namespace, name}
if secretCollector.Key != "" {
// Only include key in filename when doing key-specific processing
if secretCollector.Key != "" && !secretCollector.IncludeAllData {
parts = append(parts, secretCollector.Key)
}
return fmt.Sprintf("%s.json", filepath.Join(parts...))
@@ -147,7 +155,8 @@ func GetSecretErrorsFileName(secretCollector *troubleshootv1beta2.Secret) string
} else {
parts = append(parts, selectorToString(secretCollector.Selector))
}
if secretCollector.Key != "" {
// Only include key in filename when doing key-specific processing
if secretCollector.Key != "" && !secretCollector.IncludeAllData {
parts = append(parts, secretCollector.Key)
}
return fmt.Sprintf("%s.json", filepath.Join(parts...))
+142
View File
@@ -209,6 +209,148 @@ func TestSecret(t *testing.T) {
}),
},
},
{
name: "with includeAllData",
secretCollector: &troubleshootv1beta2.Secret{
Namespace: "test-namespace",
Name: "test-secret",
IncludeAllData: true,
},
mockSecrets: []corev1.Secret{
{
ObjectMeta: metav1.ObjectMeta{
Name: "test-secret",
Namespace: "test-namespace",
},
Data: map[string][]byte{
"database-password": []byte("secret123"),
"api-key": []byte("abc123xyz"),
"jwt-secret": []byte("mysupersecret"),
},
},
},
want: CollectorResult{
"secrets/test-namespace/test-secret.json": mustJSONMarshalIndent(t, SecretOutput{
Namespace: "test-namespace",
Name: "test-secret",
SecretExists: true,
Data: map[string]string{
"database-password": "secret123",
"api-key": "abc123xyz",
"jwt-secret": "mysupersecret",
},
}),
},
},
{
name: "with includeAllData and specific key",
secretCollector: &troubleshootv1beta2.Secret{
Namespace: "test-namespace",
Name: "test-secret",
Key: "database-password",
IncludeValue: true,
IncludeAllData: true,
},
mockSecrets: []corev1.Secret{
{
ObjectMeta: metav1.ObjectMeta{
Name: "test-secret",
Namespace: "test-namespace",
},
Data: map[string][]byte{
"database-password": []byte("secret123"),
"api-key": []byte("abc123xyz"),
"jwt-secret": []byte("mysupersecret"),
},
},
},
want: CollectorResult{
"secrets/test-namespace/test-secret.json": mustJSONMarshalIndent(t, SecretOutput{
Namespace: "test-namespace",
Name: "test-secret",
Key: "database-password",
SecretExists: true,
Data: map[string]string{
"database-password": "secret123",
"api-key": "abc123xyz",
"jwt-secret": "mysupersecret",
},
}),
},
},
{
name: "with includeAllData secret not found",
secretCollector: &troubleshootv1beta2.Secret{
Namespace: "test-namespace",
Name: "test-secret",
IncludeAllData: true,
},
mockSecrets: []corev1.Secret{
{
ObjectMeta: metav1.ObjectMeta{
Name: "other-secret",
Namespace: "test-namespace",
},
Data: map[string][]byte{
"test-key": []byte("test-value"),
},
},
},
want: CollectorResult{
"secrets/test-namespace/test-secret.json": mustJSONMarshalIndent(t, SecretOutput{
Namespace: "test-namespace",
Name: "test-secret",
SecretExists: false,
}),
"secrets-errors/test-namespace/test-secret.json": mustJSONMarshalIndent(t, []string{
`secrets "test-secret" not found`,
}),
},
},
{
name: "with includeAllData by selector",
secretCollector: &troubleshootv1beta2.Secret{
Namespace: "test-namespace",
Selector: []string{
"app=my-app",
},
IncludeAllData: true,
},
mockSecrets: []corev1.Secret{
{
ObjectMeta: metav1.ObjectMeta{
Name: "test-secret",
Namespace: "test-namespace",
Labels: map[string]string{"app": "my-app"},
},
Data: map[string][]byte{
"database-password": []byte("secret123"),
"api-key": []byte("abc123xyz"),
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "other-secret",
Namespace: "test-namespace",
Labels: map[string]string{"app": "not-my-app"},
},
Data: map[string][]byte{
"test-key": []byte("test-value"),
},
},
},
want: CollectorResult{
"secrets/test-namespace/test-secret.json": mustJSONMarshalIndent(t, SecretOutput{
Namespace: "test-namespace",
Name: "test-secret",
SecretExists: true,
Data: map[string]string{
"database-password": "secret123",
"api-key": "abc123xyz",
},
}),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -14527,6 +14527,9 @@
"exclude": {
"oneOf": [{"type": "string"},{"type": "boolean"}]
},
"includeAllData": {
"type": "boolean"
},
"includeValue": {
"type": "boolean"
},
@@ -17313,6 +17313,9 @@
"exclude": {
"oneOf": [{"type": "string"},{"type": "boolean"}]
},
"includeAllData": {
"type": "boolean"
},
"includeValue": {
"type": "boolean"
},
@@ -17359,6 +17359,9 @@
"exclude": {
"oneOf": [{"type": "string"},{"type": "boolean"}]
},
"includeAllData": {
"type": "boolean"
},
"includeValue": {
"type": "boolean"
},