From 712ea366c20e97404234d18b7a050a43c2ce2593 Mon Sep 17 00:00:00 2001 From: John Hopper Date: Tue, 30 Jan 2024 14:31:08 -0800 Subject: [PATCH 1/9] chore: analysis wip --- cmd/api/src/daemons/datapipe/analysis.go | 40 +++++++++++++++++++++--- cmd/api/src/daemons/datapipe/datapipe.go | 12 ++++--- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/cmd/api/src/daemons/datapipe/analysis.go b/cmd/api/src/daemons/datapipe/analysis.go index 3ca3be73f9..7899222f1d 100644 --- a/cmd/api/src/daemons/datapipe/analysis.go +++ b/cmd/api/src/daemons/datapipe/analysis.go @@ -18,12 +18,13 @@ package datapipe import ( "context" + "errors" "fmt" + "github.com/specterops/bloodhound/log" "github.com/specterops/bloodhound/analysis" adAnalysis "github.com/specterops/bloodhound/analysis/ad" "github.com/specterops/bloodhound/dawgs/graph" - "github.com/specterops/bloodhound/errors" "github.com/specterops/bloodhound/src/analysis/ad" "github.com/specterops/bloodhound/src/analysis/azure" "github.com/specterops/bloodhound/src/config" @@ -33,20 +34,26 @@ import ( "github.com/specterops/bloodhound/src/services/dataquality" ) +var ( + ErrAnalysisFailed = errors.New("analysis failed") + ErrAnalysisPartiallyFailed = errors.New("analysis partially failed") +) + func RunAnalysisOperations(ctx context.Context, db database.Database, graphDB graph.Database, _ config.Configuration) error { var ( - collector = &errors.ErrorCollector{} + collectedErrors []error ) if err := adAnalysis.FixWellKnownNodeTypes(ctx, graphDB); err != nil { - collector.Collect(fmt.Errorf("fix well known node types failed: %w", err)) + collectedErrors = append(collectedErrors, fmt.Errorf("fix well known node types failed: %w", err)) } if err := adAnalysis.RunDomainAssociations(ctx, graphDB); err != nil { - collector.Collect(fmt.Errorf("domain association and pruning failed: %w", err)) + collectedErrors = append(collectedErrors, fmt.Errorf("domain association and pruning failed: %w", err)) } if err := adAnalysis.LinkWellKnownGroups(ctx, graphDB); err != nil { + // TODO: Continue refactoring like above collector.Collect(fmt.Errorf("well known group linking failed: %w", err)) } @@ -63,27 +70,50 @@ func RunAnalysisOperations(ctx context.Context, db database.Database, graphDB gr } // TODO: Cleanup #ADCSFeatureFlag after full launch. + var ( + adFailed = false + azureFailed = false + agiFailed = false + dataQualityFailed = false + ) + if adcsFlag, err := db.GetFlagByKey(appcfg.FeatureAdcs); err != nil { collector.Collect(fmt.Errorf("error retrieving ADCS feature flag: %w", err)) } else if stats, err := ad.Post(ctx, graphDB, adcsFlag.Enabled); err != nil { collector.Collect(fmt.Errorf("error during ad post: %w", err)) + adFailed = true } else { stats.LogStats() } if stats, err := azure.Post(ctx, graphDB); err != nil { collector.Collect(fmt.Errorf("error during azure post: %w", err)) + azureFailed = true } else { stats.LogStats() } if err := agi.RunAssetGroupIsolationCollections(ctx, db, graphDB, analysis.GetNodeKindDisplayLabel); err != nil { collector.Collect(fmt.Errorf("asset group isolation collection failed: %w", err)) + agiFailed = true } if err := dataquality.SaveDataQuality(ctx, db, graphDB); err != nil { collector.Collect(fmt.Errorf("error saving data quality stat: %v", err)) + dataQualityFailed = true + } + + if len(collectedErrors) > 0 { + for _, err := range collectedErrors { + log.Errorf("Analysis error encountered: %v", err) + } + } + + if adFailed && azureFailed && agiFailed && dataQualityFailed { + return ErrAnalysisFailed + } else if adFailed || azureFailed || agiFailed || dataQualityFailed { + return ErrAnalysisPartiallyFailed } - return collector.Return() + return nil } diff --git a/cmd/api/src/daemons/datapipe/datapipe.go b/cmd/api/src/daemons/datapipe/datapipe.go index 3b6dc9d358..4fa4e5626f 100644 --- a/cmd/api/src/daemons/datapipe/datapipe.go +++ b/cmd/api/src/daemons/datapipe/datapipe.go @@ -19,6 +19,7 @@ package datapipe import ( "context" + "errors" "github.com/specterops/bloodhound/src/bootstrap" "os" "path/filepath" @@ -107,10 +108,13 @@ func (s *Daemon) analyze() { log.LogAndMeasure(log.LevelInfo, "Graph Analysis")() if err := RunAnalysisOperations(s.ctx, s.db, s.graphdb, s.cfg); err != nil { - log.Errorf("Graph analysis failed: %v", err) - FailAnalyzedFileUploadJobs(s.ctx, s.db) - - s.status.Update(model.DatapipeStatusIdle, false) + if errors.Is(err, ErrAnalysisFailed) { + FailAnalyzedFileUploadJobs(s.ctx, s.db) + s.status.Update(model.DatapipeStatusIdle, false) + } else if errors.Is(err, ErrAnalysisPartiallyFailed) { + // TODO: Update to partial complete status + s.status.Update(model.DatapipeStatusIdle, true) + } } else { CompleteAnalyzedFileUploadJobs(s.ctx, s.db) From b1c1d5dcd31a81fbf24d34f6e70003ebad399e52 Mon Sep 17 00:00:00 2001 From: Ben Waples Date: Wed, 31 Jan 2024 11:02:25 -0800 Subject: [PATCH 2/9] finish collected errors and PartialCompleteFileUploadJobs --- cmd/api/src/daemons/datapipe/analysis.go | 23 +++++++++---------- cmd/api/src/daemons/datapipe/datapipe.go | 2 +- cmd/api/src/daemons/datapipe/jobs.go | 18 +++++++++++++++ cmd/api/src/model/jobs.go | 5 ++++ .../src/components/FinishedIngestLog/types.ts | 2 ++ 5 files changed, 37 insertions(+), 13 deletions(-) diff --git a/cmd/api/src/daemons/datapipe/analysis.go b/cmd/api/src/daemons/datapipe/analysis.go index 7899222f1d..586b3484c5 100644 --- a/cmd/api/src/daemons/datapipe/analysis.go +++ b/cmd/api/src/daemons/datapipe/analysis.go @@ -53,53 +53,52 @@ func RunAnalysisOperations(ctx context.Context, db database.Database, graphDB gr } if err := adAnalysis.LinkWellKnownGroups(ctx, graphDB); err != nil { - // TODO: Continue refactoring like above - collector.Collect(fmt.Errorf("well known group linking failed: %w", err)) + collectedErrors = append(collectedErrors, fmt.Errorf("well known group linking failed: %w", err)) } if err := updateAssetGroupIsolationTags(ctx, db, graphDB); err != nil { - collector.Collect(fmt.Errorf("asset group isolation tagging failed: %w", err)) + collectedErrors = append(collectedErrors, fmt.Errorf("asset group isolation tagging failed: %w", err)) } if err := TagActiveDirectoryTierZero(ctx, graphDB); err != nil { - collector.Collect(fmt.Errorf("active directory tier zero tagging failed: %w", err)) + collectedErrors = append(collectedErrors, fmt.Errorf("active directory tier zero tagging failed: %w", err)) } if err := ParallelTagAzureTierZero(ctx, graphDB); err != nil { - collector.Collect(fmt.Errorf("azure tier zero tagging failed: %w", err)) + collectedErrors = append(collectedErrors, fmt.Errorf("azure tier zero tagging failed: %w", err)) } - // TODO: Cleanup #ADCSFeatureFlag after full launch. var ( adFailed = false azureFailed = false agiFailed = false dataQualityFailed = false ) - + + // TODO: Cleanup #ADCSFeatureFlag after full launch. if adcsFlag, err := db.GetFlagByKey(appcfg.FeatureAdcs); err != nil { - collector.Collect(fmt.Errorf("error retrieving ADCS feature flag: %w", err)) + collectedErrors = append(collectedErrors, fmt.Errorf("error retrieving ADCS feature flag: %w", err)) } else if stats, err := ad.Post(ctx, graphDB, adcsFlag.Enabled); err != nil { - collector.Collect(fmt.Errorf("error during ad post: %w", err)) + collectedErrors = append(collectedErrors, fmt.Errorf("error during ad post: %w", err)) adFailed = true } else { stats.LogStats() } if stats, err := azure.Post(ctx, graphDB); err != nil { - collector.Collect(fmt.Errorf("error during azure post: %w", err)) + collectedErrors = append(collectedErrors, fmt.Errorf("error during azure post: %w", err)) azureFailed = true } else { stats.LogStats() } if err := agi.RunAssetGroupIsolationCollections(ctx, db, graphDB, analysis.GetNodeKindDisplayLabel); err != nil { - collector.Collect(fmt.Errorf("asset group isolation collection failed: %w", err)) + collectedErrors = append(collectedErrors, fmt.Errorf("asset group isolation collection failed: %w", err)) agiFailed = true } if err := dataquality.SaveDataQuality(ctx, db, graphDB); err != nil { - collector.Collect(fmt.Errorf("error saving data quality stat: %v", err)) + collectedErrors = append(collectedErrors, fmt.Errorf("error saving data quality stat: %v", err)) dataQualityFailed = true } diff --git a/cmd/api/src/daemons/datapipe/datapipe.go b/cmd/api/src/daemons/datapipe/datapipe.go index 4fa4e5626f..e1c8204091 100644 --- a/cmd/api/src/daemons/datapipe/datapipe.go +++ b/cmd/api/src/daemons/datapipe/datapipe.go @@ -112,7 +112,7 @@ func (s *Daemon) analyze() { FailAnalyzedFileUploadJobs(s.ctx, s.db) s.status.Update(model.DatapipeStatusIdle, false) } else if errors.Is(err, ErrAnalysisPartiallyFailed) { - // TODO: Update to partial complete status + CompleteAnalyzedFileUploadJobs(s.ctx, s.db) s.status.Update(model.DatapipeStatusIdle, true) } } else { diff --git a/cmd/api/src/daemons/datapipe/jobs.go b/cmd/api/src/daemons/datapipe/jobs.go index e0b1c5fb4d..3a847de25d 100644 --- a/cmd/api/src/daemons/datapipe/jobs.go +++ b/cmd/api/src/daemons/datapipe/jobs.go @@ -53,6 +53,24 @@ func FailAnalyzedFileUploadJobs(ctx context.Context, db database.Database) { } } +func PartialCompleteFileUploadJobs(ctx context.Context, db database.Database) { + // Because our database interfaces do not yet accept contexts this is a best-effort check to ensure that we do not + // commit state transitions when we are shutting down. + if ctx.Err() != nil { + return + } + + if fileUploadJobsUnderAnalysis, err := db.GetFileUploadJobsWithStatus(model.JobStatusAnalyzing); err != nil { + log.Errorf("Failed to load file upload jobs under analysis: %v", err) + } else { + for _, job := range fileUploadJobsUnderAnalysis { + if err := fileupload.UpdateFileUploadJobStatus(db, job, model.JobStatusPartiallyComplete, "Analysis Partially Completed"); err != nil { + log.Errorf("Failed updating file upload job %d to failed status: %v", job.ID, err) + } + } + } +} + func CompleteAnalyzedFileUploadJobs(ctx context.Context, db database.Database) { // Because our database interfaces do not yet accept contexts this is a best-effort check to ensure that we do not // commit state transitions when we are shutting down. diff --git a/cmd/api/src/model/jobs.go b/cmd/api/src/model/jobs.go index 4a0ca0841e..a7f942f9e1 100644 --- a/cmd/api/src/model/jobs.go +++ b/cmd/api/src/model/jobs.go @@ -117,6 +117,7 @@ const ( JobStatusFailed JobStatus = 5 JobStatusIngesting JobStatus = 6 JobStatusAnalyzing JobStatus = 7 + JobStatusPartiallyComplete JobStatus = 8 ) func allJobStatuses() []JobStatus { @@ -130,6 +131,7 @@ func allJobStatuses() []JobStatus { JobStatusFailed, JobStatusIngesting, JobStatusAnalyzing, + JobStatusPartiallyComplete, } } @@ -170,6 +172,9 @@ func (s JobStatus) String() string { case JobStatusAnalyzing: return "ANALYZING" + + case JobStatusPartiallyComplete: + return "PARTIALLYCOMPLETE" default: return "INVALIDSTATUS" diff --git a/packages/javascript/bh-shared-ui/src/components/FinishedIngestLog/types.ts b/packages/javascript/bh-shared-ui/src/components/FinishedIngestLog/types.ts index 0e7f785072..36de258110 100644 --- a/packages/javascript/bh-shared-ui/src/components/FinishedIngestLog/types.ts +++ b/packages/javascript/bh-shared-ui/src/components/FinishedIngestLog/types.ts @@ -35,6 +35,7 @@ export enum FileUploadJobStatus { FAILED = 5, INGESTING = 6, ANALYZING = 7, + PARTIALLY_COMPLETE = 8, } export const FileUploadJobStatusToString: Record = { @@ -47,4 +48,5 @@ export const FileUploadJobStatusToString: Record = 5: 'Failed', 6: 'Ingesting', 7: 'Analyzing', + 8: 'PartiallyComplete', }; From c317cd13cf1e6bb1f986cceb7b6bd8ee21e62703 Mon Sep 17 00:00:00 2001 From: Ben Waples Date: Wed, 31 Jan 2024 11:34:11 -0800 Subject: [PATCH 3/9] white space and call the correct function --- cmd/api/src/daemons/datapipe/analysis.go | 2 +- cmd/api/src/daemons/datapipe/datapipe.go | 2 +- .../bh-shared-ui/src/components/FinishedIngestLog/types.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/api/src/daemons/datapipe/analysis.go b/cmd/api/src/daemons/datapipe/analysis.go index 586b3484c5..a1bc46e1a7 100644 --- a/cmd/api/src/daemons/datapipe/analysis.go +++ b/cmd/api/src/daemons/datapipe/analysis.go @@ -74,7 +74,7 @@ func RunAnalysisOperations(ctx context.Context, db database.Database, graphDB gr agiFailed = false dataQualityFailed = false ) - + // TODO: Cleanup #ADCSFeatureFlag after full launch. if adcsFlag, err := db.GetFlagByKey(appcfg.FeatureAdcs); err != nil { collectedErrors = append(collectedErrors, fmt.Errorf("error retrieving ADCS feature flag: %w", err)) diff --git a/cmd/api/src/daemons/datapipe/datapipe.go b/cmd/api/src/daemons/datapipe/datapipe.go index e1c8204091..39a1fffecf 100644 --- a/cmd/api/src/daemons/datapipe/datapipe.go +++ b/cmd/api/src/daemons/datapipe/datapipe.go @@ -112,7 +112,7 @@ func (s *Daemon) analyze() { FailAnalyzedFileUploadJobs(s.ctx, s.db) s.status.Update(model.DatapipeStatusIdle, false) } else if errors.Is(err, ErrAnalysisPartiallyFailed) { - CompleteAnalyzedFileUploadJobs(s.ctx, s.db) + PartialCompleteFileUploadJobs(s.ctx, s.db) s.status.Update(model.DatapipeStatusIdle, true) } } else { diff --git a/packages/javascript/bh-shared-ui/src/components/FinishedIngestLog/types.ts b/packages/javascript/bh-shared-ui/src/components/FinishedIngestLog/types.ts index 36de258110..ecb1fb93ff 100644 --- a/packages/javascript/bh-shared-ui/src/components/FinishedIngestLog/types.ts +++ b/packages/javascript/bh-shared-ui/src/components/FinishedIngestLog/types.ts @@ -48,5 +48,5 @@ export const FileUploadJobStatusToString: Record = 5: 'Failed', 6: 'Ingesting', 7: 'Analyzing', - 8: 'PartiallyComplete', + 8: 'Partially Complete', }; From 1d1f0fef181a67a4c8ffde2cb69573a6e978000d Mon Sep 17 00:00:00 2001 From: Ben Waples Date: Fri, 2 Feb 2024 08:49:57 -0800 Subject: [PATCH 4/9] change naming to partially completed --- cmd/api/src/daemons/datapipe/analysis.go | 6 +++--- cmd/api/src/daemons/datapipe/datapipe.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/api/src/daemons/datapipe/analysis.go b/cmd/api/src/daemons/datapipe/analysis.go index a1bc46e1a7..22a7aeddac 100644 --- a/cmd/api/src/daemons/datapipe/analysis.go +++ b/cmd/api/src/daemons/datapipe/analysis.go @@ -35,8 +35,8 @@ import ( ) var ( - ErrAnalysisFailed = errors.New("analysis failed") - ErrAnalysisPartiallyFailed = errors.New("analysis partially failed") + ErrAnalysisFailed = errors.New("analysis failed") + ErrAnalysisPartiallyCompleted = errors.New("analysis partially failed") ) func RunAnalysisOperations(ctx context.Context, db database.Database, graphDB graph.Database, _ config.Configuration) error { @@ -111,7 +111,7 @@ func RunAnalysisOperations(ctx context.Context, db database.Database, graphDB gr if adFailed && azureFailed && agiFailed && dataQualityFailed { return ErrAnalysisFailed } else if adFailed || azureFailed || agiFailed || dataQualityFailed { - return ErrAnalysisPartiallyFailed + return ErrAnalysisPartiallyCompleted } return nil diff --git a/cmd/api/src/daemons/datapipe/datapipe.go b/cmd/api/src/daemons/datapipe/datapipe.go index 39a1fffecf..ef2b2e2d71 100644 --- a/cmd/api/src/daemons/datapipe/datapipe.go +++ b/cmd/api/src/daemons/datapipe/datapipe.go @@ -111,7 +111,7 @@ func (s *Daemon) analyze() { if errors.Is(err, ErrAnalysisFailed) { FailAnalyzedFileUploadJobs(s.ctx, s.db) s.status.Update(model.DatapipeStatusIdle, false) - } else if errors.Is(err, ErrAnalysisPartiallyFailed) { + } else if errors.Is(err, ErrAnalysisPartiallyCompleted) { PartialCompleteFileUploadJobs(s.ctx, s.db) s.status.Update(model.DatapipeStatusIdle, true) } From 88ab75c9f5f97cc7a5f1225c46eb7e6c48ca523e Mon Sep 17 00:00:00 2001 From: Irshad Ahmed Date: Fri, 2 Feb 2024 16:36:56 -0600 Subject: [PATCH 5/9] refactor error collection to use stdlib --- cmd/api/src/daemons/datapipe/analysis.go | 32 +++++++++++------------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/cmd/api/src/daemons/datapipe/analysis.go b/cmd/api/src/daemons/datapipe/analysis.go index 22a7aeddac..9e1f92fab8 100644 --- a/cmd/api/src/daemons/datapipe/analysis.go +++ b/cmd/api/src/daemons/datapipe/analysis.go @@ -40,32 +40,30 @@ var ( ) func RunAnalysisOperations(ctx context.Context, db database.Database, graphDB graph.Database, _ config.Configuration) error { - var ( - collectedErrors []error - ) + var collectedErrors error if err := adAnalysis.FixWellKnownNodeTypes(ctx, graphDB); err != nil { - collectedErrors = append(collectedErrors, fmt.Errorf("fix well known node types failed: %w", err)) + collectedErrors = errors.Join(collectedErrors, fmt.Errorf("fix well known node types failed: %w", err)) } if err := adAnalysis.RunDomainAssociations(ctx, graphDB); err != nil { - collectedErrors = append(collectedErrors, fmt.Errorf("domain association and pruning failed: %w", err)) + collectedErrors = errors.Join(collectedErrors, fmt.Errorf("domain association and pruning failed: %w", err)) } if err := adAnalysis.LinkWellKnownGroups(ctx, graphDB); err != nil { - collectedErrors = append(collectedErrors, fmt.Errorf("well known group linking failed: %w", err)) + collectedErrors = errors.Join(collectedErrors, fmt.Errorf("well known group linking failed: %w", err)) } if err := updateAssetGroupIsolationTags(ctx, db, graphDB); err != nil { - collectedErrors = append(collectedErrors, fmt.Errorf("asset group isolation tagging failed: %w", err)) + collectedErrors = errors.Join(collectedErrors, fmt.Errorf("asset group isolation tagging failed: %w", err)) } if err := TagActiveDirectoryTierZero(ctx, graphDB); err != nil { - collectedErrors = append(collectedErrors, fmt.Errorf("active directory tier zero tagging failed: %w", err)) + collectedErrors = errors.Join(collectedErrors, fmt.Errorf("active directory tier zero tagging failed: %w", err)) } if err := ParallelTagAzureTierZero(ctx, graphDB); err != nil { - collectedErrors = append(collectedErrors, fmt.Errorf("azure tier zero tagging failed: %w", err)) + collectedErrors = errors.Join(collectedErrors, fmt.Errorf("azure tier zero tagging failed: %w", err)) } var ( @@ -77,35 +75,33 @@ func RunAnalysisOperations(ctx context.Context, db database.Database, graphDB gr // TODO: Cleanup #ADCSFeatureFlag after full launch. if adcsFlag, err := db.GetFlagByKey(appcfg.FeatureAdcs); err != nil { - collectedErrors = append(collectedErrors, fmt.Errorf("error retrieving ADCS feature flag: %w", err)) + collectedErrors = errors.Join(collectedErrors, fmt.Errorf("error retrieving ADCS feature flag: %w", err)) } else if stats, err := ad.Post(ctx, graphDB, adcsFlag.Enabled); err != nil { - collectedErrors = append(collectedErrors, fmt.Errorf("error during ad post: %w", err)) + collectedErrors = errors.Join(collectedErrors, fmt.Errorf("error during ad post: %w", err)) adFailed = true } else { stats.LogStats() } if stats, err := azure.Post(ctx, graphDB); err != nil { - collectedErrors = append(collectedErrors, fmt.Errorf("error during azure post: %w", err)) + collectedErrors = errors.Join(collectedErrors, fmt.Errorf("error during azure post: %w", err)) azureFailed = true } else { stats.LogStats() } if err := agi.RunAssetGroupIsolationCollections(ctx, db, graphDB, analysis.GetNodeKindDisplayLabel); err != nil { - collectedErrors = append(collectedErrors, fmt.Errorf("asset group isolation collection failed: %w", err)) + collectedErrors = errors.Join(collectedErrors, fmt.Errorf("asset group isolation collection failed: %w", err)) agiFailed = true } if err := dataquality.SaveDataQuality(ctx, db, graphDB); err != nil { - collectedErrors = append(collectedErrors, fmt.Errorf("error saving data quality stat: %v", err)) + collectedErrors = errors.Join(collectedErrors, fmt.Errorf("error saving data quality stat: %v", err)) dataQualityFailed = true } - if len(collectedErrors) > 0 { - for _, err := range collectedErrors { - log.Errorf("Analysis error encountered: %v", err) - } + if collectedErrors != nil { + log.Errorf("Analysis errors encountered: %v", collectedErrors) } if adFailed && azureFailed && agiFailed && dataQualityFailed { From a616d58878681e92d40c3e7c156f70469abd452c Mon Sep 17 00:00:00 2001 From: Ben Waples Date: Fri, 2 Feb 2024 14:45:07 -0800 Subject: [PATCH 6/9] fix error msg --- cmd/api/src/daemons/datapipe/analysis.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/api/src/daemons/datapipe/analysis.go b/cmd/api/src/daemons/datapipe/analysis.go index 9e1f92fab8..e935dbf0e4 100644 --- a/cmd/api/src/daemons/datapipe/analysis.go +++ b/cmd/api/src/daemons/datapipe/analysis.go @@ -36,7 +36,7 @@ import ( var ( ErrAnalysisFailed = errors.New("analysis failed") - ErrAnalysisPartiallyCompleted = errors.New("analysis partially failed") + ErrAnalysisPartiallyCompleted = errors.New("analysis partially completed") ) func RunAnalysisOperations(ctx context.Context, db database.Database, graphDB graph.Database, _ config.Configuration) error { From f57fa5d05fe50c64dd13346d7f3bdbf85bce8f7a Mon Sep 17 00:00:00 2001 From: Ben Waples Date: Fri, 2 Feb 2024 16:38:30 -0800 Subject: [PATCH 7/9] fix job log message --- cmd/api/src/daemons/datapipe/jobs.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/api/src/daemons/datapipe/jobs.go b/cmd/api/src/daemons/datapipe/jobs.go index 8343d258c2..c6e1546e02 100644 --- a/cmd/api/src/daemons/datapipe/jobs.go +++ b/cmd/api/src/daemons/datapipe/jobs.go @@ -65,8 +65,8 @@ func PartialCompleteFileUploadJobs(ctx context.Context, db database.Database) { log.Errorf("Failed to load file upload jobs under analysis: %v", err) } else { for _, job := range fileUploadJobsUnderAnalysis { - if err := fileupload.UpdateFileUploadJobStatus(db, job, model.JobStatusPartiallyComplete, "Analysis Partially Completed"); err != nil { - log.Errorf("Failed updating file upload job %d to failed status: %v", job.ID, err) + if err := fileupload.UpdateFileUploadJobStatus(db, job, model.JobStatusPartiallyComplete, "Partially Completed"); err != nil { + log.Errorf("Failed updating file upload job %d to partially completed status: %v", job.ID, err) } } } From 3449430c0be593f4f25299ad29b62972f8f3665a Mon Sep 17 00:00:00 2001 From: Irshad Ahmed Date: Fri, 2 Feb 2024 18:40:35 -0600 Subject: [PATCH 8/9] redo error collectiona --- cmd/api/src/daemons/datapipe/analysis.go | 32 +++++++++++++----------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/cmd/api/src/daemons/datapipe/analysis.go b/cmd/api/src/daemons/datapipe/analysis.go index e935dbf0e4..9b1da5ac59 100644 --- a/cmd/api/src/daemons/datapipe/analysis.go +++ b/cmd/api/src/daemons/datapipe/analysis.go @@ -36,34 +36,36 @@ import ( var ( ErrAnalysisFailed = errors.New("analysis failed") - ErrAnalysisPartiallyCompleted = errors.New("analysis partially completed") + ErrAnalysisPartiallyCompleted = errors.New("analysis partially failed") ) func RunAnalysisOperations(ctx context.Context, db database.Database, graphDB graph.Database, _ config.Configuration) error { - var collectedErrors error + var ( + collectedErrors []error + ) if err := adAnalysis.FixWellKnownNodeTypes(ctx, graphDB); err != nil { - collectedErrors = errors.Join(collectedErrors, fmt.Errorf("fix well known node types failed: %w", err)) + collectedErrors = append(collectedErrors, fmt.Errorf("fix well known node types failed: %w", err)) } if err := adAnalysis.RunDomainAssociations(ctx, graphDB); err != nil { - collectedErrors = errors.Join(collectedErrors, fmt.Errorf("domain association and pruning failed: %w", err)) + collectedErrors = append(collectedErrors, fmt.Errorf("domain association and pruning failed: %w", err)) } if err := adAnalysis.LinkWellKnownGroups(ctx, graphDB); err != nil { - collectedErrors = errors.Join(collectedErrors, fmt.Errorf("well known group linking failed: %w", err)) + collectedErrors = append(collectedErrors, fmt.Errorf("well known group linking failed: %w", err)) } if err := updateAssetGroupIsolationTags(ctx, db, graphDB); err != nil { - collectedErrors = errors.Join(collectedErrors, fmt.Errorf("asset group isolation tagging failed: %w", err)) + collectedErrors = append(collectedErrors, fmt.Errorf("asset group isolation tagging failed: %w", err)) } if err := TagActiveDirectoryTierZero(ctx, graphDB); err != nil { - collectedErrors = errors.Join(collectedErrors, fmt.Errorf("active directory tier zero tagging failed: %w", err)) + collectedErrors = append(collectedErrors, fmt.Errorf("active directory tier zero tagging failed: %w", err)) } if err := ParallelTagAzureTierZero(ctx, graphDB); err != nil { - collectedErrors = errors.Join(collectedErrors, fmt.Errorf("azure tier zero tagging failed: %w", err)) + collectedErrors = append(collectedErrors, fmt.Errorf("azure tier zero tagging failed: %w", err)) } var ( @@ -75,33 +77,33 @@ func RunAnalysisOperations(ctx context.Context, db database.Database, graphDB gr // TODO: Cleanup #ADCSFeatureFlag after full launch. if adcsFlag, err := db.GetFlagByKey(appcfg.FeatureAdcs); err != nil { - collectedErrors = errors.Join(collectedErrors, fmt.Errorf("error retrieving ADCS feature flag: %w", err)) + collectedErrors = append(collectedErrors, fmt.Errorf("error retrieving ADCS feature flag: %w", err)) } else if stats, err := ad.Post(ctx, graphDB, adcsFlag.Enabled); err != nil { - collectedErrors = errors.Join(collectedErrors, fmt.Errorf("error during ad post: %w", err)) + collectedErrors = append(collectedErrors, fmt.Errorf("error during ad post: %w", err)) adFailed = true } else { stats.LogStats() } if stats, err := azure.Post(ctx, graphDB); err != nil { - collectedErrors = errors.Join(collectedErrors, fmt.Errorf("error during azure post: %w", err)) + collectedErrors = append(collectedErrors, fmt.Errorf("error during azure post: %w", err)) azureFailed = true } else { stats.LogStats() } if err := agi.RunAssetGroupIsolationCollections(ctx, db, graphDB, analysis.GetNodeKindDisplayLabel); err != nil { - collectedErrors = errors.Join(collectedErrors, fmt.Errorf("asset group isolation collection failed: %w", err)) + collectedErrors = append(collectedErrors, fmt.Errorf("asset group isolation collection failed: %w", err)) agiFailed = true } if err := dataquality.SaveDataQuality(ctx, db, graphDB); err != nil { - collectedErrors = errors.Join(collectedErrors, fmt.Errorf("error saving data quality stat: %v", err)) + collectedErrors = append(collectedErrors, fmt.Errorf("error saving data quality stat: %v", err)) dataQualityFailed = true } - if collectedErrors != nil { - log.Errorf("Analysis errors encountered: %v", collectedErrors) + if len(collectedErrors) > 0 { + log.Errorf("Analysis errors encountered: %v", errors.Join(collectedErrors...)) } if adFailed && azureFailed && agiFailed && dataQualityFailed { From 2514e7828af78e8ef90cb4a8e4d8b267383e711b Mon Sep 17 00:00:00 2001 From: Ben Waples Date: Fri, 2 Feb 2024 16:52:33 -0800 Subject: [PATCH 9/9] going back to looping errors --- cmd/api/src/daemons/datapipe/analysis.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cmd/api/src/daemons/datapipe/analysis.go b/cmd/api/src/daemons/datapipe/analysis.go index 9b1da5ac59..8f606f0343 100644 --- a/cmd/api/src/daemons/datapipe/analysis.go +++ b/cmd/api/src/daemons/datapipe/analysis.go @@ -36,7 +36,7 @@ import ( var ( ErrAnalysisFailed = errors.New("analysis failed") - ErrAnalysisPartiallyCompleted = errors.New("analysis partially failed") + ErrAnalysisPartiallyCompleted = errors.New("analysis partially completed") ) func RunAnalysisOperations(ctx context.Context, db database.Database, graphDB graph.Database, _ config.Configuration) error { @@ -103,7 +103,9 @@ func RunAnalysisOperations(ctx context.Context, db database.Database, graphDB gr } if len(collectedErrors) > 0 { - log.Errorf("Analysis errors encountered: %v", errors.Join(collectedErrors...)) + for _, err := range collectedErrors { + log.Errorf("Analysis error encountered: %v", err) + } } if adFailed && azureFailed && agiFailed && dataQualityFailed {