-
Notifications
You must be signed in to change notification settings - Fork 1
Pr/reports #1865
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
Pr/reports #1865
Changes from all commits
45341ca
270c097
a88d32e
8b34baa
ad405f0
27a19bb
b0f2168
1d3b03a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,222 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package query | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "fmt" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "strings" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "time" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/flanksource/duty/context" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/flanksource/duty/pkg/kube/labels" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/flanksource/duty/types" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/google/uuid" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/timberio/go-datemath" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "gorm.io/gorm" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "gorm.io/gorm/clause" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type BaseCatalogSearch struct { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CatalogID string `query:"id" json:"id"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ConfigType string `query:"config_type" json:"config_type"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| IncludeDeletedConfigs bool `query:"include_deleted_configs" json:"include_deleted_configs"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Depth int `query:"depth" json:"depth"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Tags string `query:"tags" json:"tags"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AgentID string `query:"agent_id" json:"agent_id"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| From string `query:"from" json:"from"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| To string `query:"to" json:"to"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PageSize int `query:"page_size" json:"page_size"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Page int `query:"page" json:"page"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SortBy string `query:"sort_by" json:"sort_by"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Recursive ChangeRelationDirection `query:"recursive" json:"recursive"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Soft bool `query:"soft" json:"soft"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Lenient silently ignores invalid filters, inapplicable columns, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // and validation errors instead of returning errors. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Useful for global search where the same filters are applied across different table types. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Lenient bool `query:"lenient" json:"lenient"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sortOrder string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| configIDs []uuid.UUID | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| FromTime *time.Time `query:"-" json:"-"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ToTime *time.Time `query:"-" json:"-"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func (b *BaseCatalogSearch) SetDefaults() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if b.PageSize <= 0 { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| b.PageSize = 50 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if b.Page <= 0 { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| b.Page = 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if b.Depth <= 0 { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| b.Depth = 5 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if b.Recursive == "" { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| b.Recursive = CatalogChangeRecursiveDownstream | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if b.AgentID == "local" { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| b.AgentID = uuid.Nil.String() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func (b *BaseCatalogSearch) Validate() error { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if b.From != "" && b.FromTime == nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expr, err := datemath.Parse(b.From) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !b.Lenient { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return fmt.Errorf("invalid 'from' param: %w", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| b.From = "" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| t := expr.Time() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| b.FromTime = &t | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if b.To != "" && b.ToTime == nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expr, err := datemath.Parse(b.To) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !b.Lenient { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return fmt.Errorf("invalid 'to' param: %w", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| b.To = "" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| t := expr.Time() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| b.ToTime = &t | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if b.FromTime != nil && b.ToTime != nil && !b.FromTime.Before(*b.ToTime) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !b.Lenient { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return fmt.Errorf("'from' must be before 'to'") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| b.ToTime = nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if b.AgentID != "" { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if _, err := uuid.Parse(b.AgentID); err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !b.Lenient { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return fmt.Errorf("agent_id(%s) must either be a valid uuid or `local`", b.AgentID) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| b.AgentID = "" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func (b *BaseCatalogSearch) ResolveConfigIDs(ctx context.Context) ([]uuid.UUID, error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if b.CatalogID == "" { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parts := strings.Split(b.CatalogID, ",") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var ids []uuid.UUID | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| allValid := true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for _, p := range parts { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if id, err := uuid.Parse(strings.TrimSpace(p)); err == nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ids = append(ids, id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| allValid = false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| break | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if allValid && len(ids) > 0 { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| b.configIDs = ids | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ids, nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| response, err := SearchResources(ctx, SearchResourcesRequest{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Configs: []types.ResourceSelector{{Search: b.CatalogID, Cache: "no-cache"}}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Limit: 200, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, fmt.Errorf("failed to resolve catalog query %q: %w", b.CatalogID, err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for _, c := range response.Configs { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if id, err := uuid.Parse(c.ID); err == nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ids = append(ids, id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| b.configIDs = ids | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ids, nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+123
to
+136
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prevent broad queries when catalog resolution returns zero matches. At Line 104, a selector lookup that returns no configs currently falls through as success and returns 💡 Proposed fix response, err := SearchResources(ctx, SearchResourcesRequest{
Configs: []types.ResourceSelector{{Search: b.CatalogID, Cache: "no-cache"}},
Limit: 200,
})
if err != nil {
return nil, fmt.Errorf("failed to resolve catalog query %q: %w", b.CatalogID, err)
}
for _, c := range response.Configs {
if id, err := uuid.Parse(c.ID); err == nil {
ids = append(ids, id)
}
}
+if len(ids) == 0 {
+ return nil, fmt.Errorf("catalog query %q matched no configs", b.CatalogID)
+}
b.configIDs = ids
return ids, nil📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func (b *BaseCatalogSearch) ConfigIDs() []uuid.UUID { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return b.configIDs | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func (b *BaseCatalogSearch) ApplyClauses(excludeColumns ...string) ([]clause.Expression, func(*gorm.DB) *gorm.DB, error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| excluded := make(map[string]bool, len(excludeColumns)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for _, c := range excludeColumns { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| excluded[c] = true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var clauses []clause.Expression | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var tagsFn func(*gorm.DB) *gorm.DB | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if b.AgentID != "" && !excluded["agent_id"] { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| c, err := parseAndBuildFilteringQuery(b.AgentID, "agent_id", false) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil && !b.Lenient { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, nil, fmt.Errorf("invalid agent_id filter: %w", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else if err == nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| clauses = append(clauses, c...) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if b.ConfigType != "" && !excluded["type"] { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| c, err := parseAndBuildFilteringQuery(b.ConfigType, "type", false) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil && !b.Lenient { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, nil, fmt.Errorf("invalid config_type filter: %w", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else if err == nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| clauses = append(clauses, c...) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if b.FromTime != nil && !excluded["created_at"] { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| clauses = append(clauses, clause.Gte{Column: clause.Column{Name: "created_at"}, Value: *b.FromTime}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if b.ToTime != nil && !excluded["created_at"] { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| clauses = append(clauses, clause.Lte{Column: clause.Column{Name: "created_at"}, Value: *b.ToTime}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !b.IncludeDeletedConfigs && !excluded["deleted_at"] { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| clauses = append(clauses, clause.Eq{Column: clause.Column{Name: "deleted_at"}, Value: nil}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if b.Tags != "" && !excluded["tags"] { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parsedLabelSelector, err := labels.Parse(b.Tags) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil && !b.Lenient { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, nil, fmt.Errorf("invalid tags filter: %w", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else if err == nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| requirements, _ := parsedLabelSelector.Requirements() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tagsFn = func(db *gorm.DB) *gorm.DB { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for _, r := range requirements { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| db = jsonColumnRequirementsToSQLClause(db, "tags", r) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return db | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return clauses, tagsFn, nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func (b *BaseCatalogSearch) String() string { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| s := "" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if b.AgentID != "" { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| s += fmt.Sprintf("agent=%s ", b.AgentID) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if b.CatalogID != "" { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| s += fmt.Sprintf("id=%s ", b.CatalogID) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if b.ConfigType != "" { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| s += fmt.Sprintf("config_type=%s ", b.ConfigType) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if b.Tags != "" { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| s += fmt.Sprintf("tags=%s ", b.Tags) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if b.From != "" { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| s += fmt.Sprintf("from=%s ", b.From) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else if b.FromTime != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| s += fmt.Sprintf("from=%s ", b.FromTime.Format("2006-01-02")) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if b.To != "" { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| s += fmt.Sprintf("to=%s ", b.To) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else if b.ToTime != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| s += fmt.Sprintf("to=%s ", b.ToTime.Format("2006-01-02")) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if b.Recursive != "" { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| s += fmt.Sprintf("recursive=%s ", b.Recursive) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return strings.TrimSpace(s) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: flanksource/duty
Length of output: 1770
🏁 Script executed:
# Read the full GCPConnection implementation head -100 connection/gcp.goRepository: flanksource/duty
Length of output: 2888
🏁 Script executed:
Repository: flanksource/duty
Length of output: 432
🏁 Script executed:
Repository: flanksource/duty
Length of output: 113
Enforcing
google.ServiceAccounttype creates an inconsistency with sibling GCP connections and may break existing workflows.Using
google.CredentialsFromJSONWithTypewithgoogle.ServiceAccountrejects credentials that aren't service account credentials (e.g., authorized user, workload identity). This differs from sibling connections:GCSConnection(gcs.go) usesCredentialsFromJSONwithout type constraintGKEConnection(gke.go) usesCredentialsFromJSONwithout type constraintWithout documentation explaining this restriction, it appears unintentional. Revert to
CredentialsFromJSONunless ServiceAccount-only credentials are required by design.🔧 Proposed fix
func (g *GCPConnection) TokenSource(ctx context.Context, scopes ...string) (oauth2.TokenSource, error) { - creds, err := google.CredentialsFromJSONWithType(ctx, []byte(g.Credentials.ValueStatic), google.ServiceAccount, scopes...) + creds, err := google.CredentialsFromJSON(ctx, []byte(g.Credentials.ValueStatic), scopes...) if err != nil { return nil, err }🤖 Prompt for AI Agents