diff --git a/internal/install/recipe_installer.go b/internal/install/recipe_installer.go index 7c19c2fde..bc41efa7b 100644 --- a/internal/install/recipe_installer.go +++ b/internal/install/recipe_installer.go @@ -351,6 +351,7 @@ func (i *RecipeInstall) install(ctx context.Context) error { return nil } +// TODO: remove? func (i *RecipeInstall) printStartInstallingMessage(repo *recipes.RecipeRepository) { message := "\n\nInstalling New Relic" if i.RecipeNamesProvided() && len(i.RecipeNames) > 0 { diff --git a/internal/install/recipes/mock_process_evaluator.go b/internal/install/recipes/mock_process_evaluator.go index 9856a0e3d..90dddd5d2 100644 --- a/internal/install/recipes/mock_process_evaluator.go +++ b/internal/install/recipes/mock_process_evaluator.go @@ -25,7 +25,7 @@ func (pe *MockProcessEvaluator) GetOrLoadProcesses(ctx context.Context) []types. return pe.processes } -func (pe *MockProcessEvaluator) DetectionStatus(ctx context.Context, r *types.OpenInstallationRecipe) execution.RecipeStatusType { +func (pe *MockProcessEvaluator) DetectionStatus(ctx context.Context, r *types.OpenInstallationRecipe, recipeNames []string) execution.RecipeStatusType { return execution.RecipeStatusTypes.AVAILABLE } diff --git a/internal/install/recipes/mock_recipe_evaluator.go b/internal/install/recipes/mock_recipe_evaluator.go index 2f387b9d2..abbc0491f 100644 --- a/internal/install/recipes/mock_recipe_evaluator.go +++ b/internal/install/recipes/mock_recipe_evaluator.go @@ -21,7 +21,7 @@ func (mre *MockRecipeEvaluator) WithRecipeStatus(recipe *types.OpenInstallationR mre.recipeStatus[recipe.Name] = status } -func (mre *MockRecipeEvaluator) DetectionStatus(ctx context.Context, recipe *types.OpenInstallationRecipe) execution.RecipeStatusType { +func (mre *MockRecipeEvaluator) DetectionStatus(ctx context.Context, recipe *types.OpenInstallationRecipe, recipeNames []string) execution.RecipeStatusType { if status, ok := mre.recipeStatus[recipe.Name]; ok { return status } diff --git a/internal/install/recipes/process_evaluator.go b/internal/install/recipes/process_evaluator.go index c5e168bcb..561d1118a 100644 --- a/internal/install/recipes/process_evaluator.go +++ b/internal/install/recipes/process_evaluator.go @@ -2,7 +2,10 @@ package recipes import ( "context" + "fmt" + "github.com/newrelic/newrelic-cli/internal/install/execution" + "golang.org/x/exp/slices" "github.com/shirou/gopsutil/v3/process" log "github.com/sirupsen/logrus" @@ -12,7 +15,7 @@ import ( type ProcessEvaluatorInterface interface { GetOrLoadProcesses(ctx context.Context) []types.GenericProcess - DetectionStatus(ctx context.Context, r *types.OpenInstallationRecipe) execution.RecipeStatusType + DetectionStatus(ctx context.Context, r *types.OpenInstallationRecipe, recipeNames []string) execution.RecipeStatusType FindProcess(process string) bool } @@ -73,7 +76,7 @@ func (pe *ProcessEvaluator) GetOrLoadProcesses(ctx context.Context) []types.Gene return pe.processFetcher(ctx) } -func (pe *ProcessEvaluator) DetectionStatus(ctx context.Context, r *types.OpenInstallationRecipe) execution.RecipeStatusType { +func (pe *ProcessEvaluator) DetectionStatus(ctx context.Context, r *types.OpenInstallationRecipe, recipeNames []string) execution.RecipeStatusType { if len(r.ProcessMatch) == 0 { return execution.RecipeStatusTypes.AVAILABLE } @@ -81,6 +84,12 @@ func (pe *ProcessEvaluator) DetectionStatus(ctx context.Context, r *types.OpenIn processes := pe.GetOrLoadProcesses(ctx) matches := pe.processMatchFinder.FindMatches(ctx, processes, *r) if len(matches) == 0 { + if slices.Contains(recipeNames, r.Name) { + log.Errorf("Unsupported (%s): Unable to match any of the following processes:\n", r.DisplayName) + for _, v := range r.ProcessMatch { + fmt.Println("-", v) + } + } log.Tracef("recipe %s is not matching any process", r.Name) return execution.RecipeStatusTypes.NULL } diff --git a/internal/install/recipes/process_evaluator_test.go b/internal/install/recipes/process_evaluator_test.go index 9f74ede71..c253142bf 100644 --- a/internal/install/recipes/process_evaluator_test.go +++ b/internal/install/recipes/process_evaluator_test.go @@ -16,7 +16,7 @@ import ( func TestProcessEvaluatorShouldGetAvailable(t *testing.T) { recipe := NewRecipeBuilder().Build() - status := GivenProcessEvaluator().DetectionStatus(context.Background(), recipe) + status := GivenProcessEvaluator().DetectionStatus(context.Background(), recipe, []string{}) require.Equal(t, execution.RecipeStatusTypes.AVAILABLE, status) } @@ -25,7 +25,7 @@ func TestProcessEvaluatorShouldGetAvailable_Matching(t *testing.T) { recipe := NewRecipeBuilder().ProcessMatch("abc").Build() processEvaluator := GivenProcessEvaluatorMatchedProcess() - status := processEvaluator.DetectionStatus(context.Background(), recipe) + status := processEvaluator.DetectionStatus(context.Background(), recipe, []string{}) require.Equal(t, execution.RecipeStatusTypes.AVAILABLE, status) } @@ -34,7 +34,7 @@ func TestProcessEvaluatorShouldNotDetect_NoMatch(t *testing.T) { recipe := NewRecipeBuilder().ProcessMatch("abc").Build() processEvaluator := GivenProcessEvaluator() - status := processEvaluator.DetectionStatus(context.Background(), recipe) + status := processEvaluator.DetectionStatus(context.Background(), recipe, []string{}) require.Equal(t, execution.RecipeStatusTypes.NULL, status) } diff --git a/internal/install/recipes/recipe_detector.go b/internal/install/recipes/recipe_detector.go index ba347d9e3..948cbfc22 100644 --- a/internal/install/recipes/recipe_detector.go +++ b/internal/install/recipes/recipe_detector.go @@ -12,7 +12,7 @@ import ( ) type DetectionStatusProvider interface { - DetectionStatus(context.Context, *types.OpenInstallationRecipe) execution.RecipeStatusType + DetectionStatus(context.Context, *types.OpenInstallationRecipe, []string) execution.RecipeStatusType } type RecipeDetectionResult struct { @@ -106,11 +106,13 @@ func (dt *RecipeDetector) detectRecipe(recipe *types.OpenInstallationRecipe) *Re } } - status := dt.processEvaluator.DetectionStatus(dt.context, recipe) + recipeNames := dt.installerContext.RecipeNames + + status := dt.processEvaluator.DetectionStatus(dt.context, recipe, recipeNames) durationMs := time.Since(start).Milliseconds() if status == execution.RecipeStatusTypes.AVAILABLE && recipe.PreInstall.RequireAtDiscovery != "" { - status = dt.scriptEvaluator.DetectionStatus(dt.context, recipe) + status = dt.scriptEvaluator.DetectionStatus(dt.context, recipe, recipeNames) durationMs = time.Since(start).Milliseconds() log.Debugf("ScriptEvaluation for recipe:%s completed in %dms with status:%s", recipe.Name, durationMs, status) } diff --git a/internal/install/recipes/script_evaluator.go b/internal/install/recipes/script_evaluator.go index 72e682881..88ab10c28 100644 --- a/internal/install/recipes/script_evaluator.go +++ b/internal/install/recipes/script_evaluator.go @@ -4,6 +4,7 @@ import ( "context" log "github.com/sirupsen/logrus" + "golang.org/x/exp/slices" "github.com/newrelic/newrelic-cli/internal/install/execution" "github.com/newrelic/newrelic-cli/internal/install/types" @@ -24,7 +25,7 @@ func newScriptEvaluator(executor execution.RecipeExecutor) *ScriptEvaluator { } } -func (se *ScriptEvaluator) DetectionStatus(ctx context.Context, r *types.OpenInstallationRecipe) (statusResult execution.RecipeStatusType) { +func (se *ScriptEvaluator) DetectionStatus(ctx context.Context, r *types.OpenInstallationRecipe, recipeNames []string) (statusResult execution.RecipeStatusType) { defer func() { if err := recover(); err != nil { @@ -36,6 +37,10 @@ func (se *ScriptEvaluator) DetectionStatus(ctx context.Context, r *types.OpenIns if err := se.executor.ExecutePreInstall(ctx, *r, types.RecipeVars{}); err != nil { log.Debugf("recipe %s failed script evaluation %s", r.Name, err) + if slices.Contains(recipeNames, r.Name) { + log.Errorf("Unsupported (%s): Requirements not satisfied:\n- %s", r.DisplayName, err) + } + if utils.IsExitStatusCode(132, err) { statusResult = execution.RecipeStatusTypes.DETECTED } else if utils.IsExitStatusCode(131, err) { diff --git a/internal/install/recipes/script_evaluator_test.go b/internal/install/recipes/script_evaluator_test.go index 38e1ff160..e7650e3a2 100644 --- a/internal/install/recipes/script_evaluator_test.go +++ b/internal/install/recipes/script_evaluator_test.go @@ -13,7 +13,7 @@ import ( func TestScriptEvaluatorShouldGetAvailable(t *testing.T) { recipe := NewRecipeBuilder().Build() - status := GivenScriptEvaluator().DetectionStatus(context.Background(), recipe) + status := GivenScriptEvaluator().DetectionStatus(context.Background(), recipe, []string{}) require.Equal(t, execution.RecipeStatusTypes.AVAILABLE, status) } @@ -22,7 +22,7 @@ func TestScriptEvaluatorShouldDetect(t *testing.T) { recipe := NewRecipeBuilder().Build() evaluator := GivenScriptEvaluatorError("This is the specific message with exit status 132 special case") - status := evaluator.DetectionStatus(context.Background(), recipe) + status := evaluator.DetectionStatus(context.Background(), recipe, []string{}) require.Equal(t, execution.RecipeStatusTypes.DETECTED, status) } @@ -31,7 +31,7 @@ func TestScriptEvaluatorShouldNotDetect(t *testing.T) { recipe := NewRecipeBuilder().Build() evaluator := GivenScriptEvaluatorError("something went wrong") - status := evaluator.DetectionStatus(context.Background(), recipe) + status := evaluator.DetectionStatus(context.Background(), recipe, []string{}) require.Equal(t, execution.RecipeStatusTypes.NULL, status) } @@ -42,7 +42,7 @@ func TestScriptEvaluatorShouldReturnWhenPanic(t *testing.T) { recipeExecutor.ShouldPanic = true evaluator := newScriptEvaluator(recipeExecutor) - status := evaluator.DetectionStatus(context.Background(), recipe) + status := evaluator.DetectionStatus(context.Background(), recipe, []string{}) require.Equal(t, execution.RecipeStatusTypes.NULL, status) } @@ -62,7 +62,7 @@ func TestScriptEvaluatorShouldBeUnSupported(t *testing.T) { recipe := NewRecipeBuilder().Build() evaluator := GivenScriptEvaluatorError("This is the specific message with exit status 131 un-support case") - status := evaluator.DetectionStatus(context.Background(), recipe) + status := evaluator.DetectionStatus(context.Background(), recipe, []string{}) require.Equal(t, execution.RecipeStatusTypes.UNSUPPORTED, status) }