internal/testrunner/runners/policy/runner.go (152 lines of code) (raw):

// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. package policy import ( "context" "fmt" "path/filepath" "strings" "github.com/elastic/elastic-package/internal/kibana" "github.com/elastic/elastic-package/internal/logger" "github.com/elastic/elastic-package/internal/packages" "github.com/elastic/elastic-package/internal/resources" "github.com/elastic/elastic-package/internal/testrunner" ) const ( TestType testrunner.TestType = "policy" ) type runner struct { packageRootPath string kibanaClient *kibana.Client dataStreams []string failOnMissingTests bool generateTestResult bool globalTestConfig testrunner.GlobalRunnerTestConfig withCoverage bool coverageType string resourcesManager *resources.Manager cleanup func(context.Context) error } // Ensures that runner implements testrunner.TestRunner interface var _ testrunner.TestRunner = new(runner) type PolicyTestRunnerOptions struct { KibanaClient *kibana.Client PackageRootPath string DataStreams []string FailOnMissingTests bool GenerateTestResult bool GlobalTestConfig testrunner.GlobalRunnerTestConfig WithCoverage bool CoverageType string } func NewPolicyTestRunner(options PolicyTestRunnerOptions) *runner { runner := runner{ packageRootPath: options.PackageRootPath, kibanaClient: options.KibanaClient, dataStreams: options.DataStreams, failOnMissingTests: options.FailOnMissingTests, generateTestResult: options.GenerateTestResult, globalTestConfig: options.GlobalTestConfig, withCoverage: options.WithCoverage, coverageType: options.CoverageType, } runner.resourcesManager = resources.NewManager() runner.resourcesManager.RegisterProvider(resources.DefaultKibanaProviderName, &resources.KibanaProvider{Client: runner.kibanaClient}) return &runner } // SetupRunner prepares global resources required by the test runner. func (r *runner) SetupRunner(ctx context.Context) error { cleanup, err := r.setupSuite(ctx, r.resourcesManager) if err != nil { return fmt.Errorf("failed to setup test runner: %w", err) } r.cleanup = cleanup return nil } // TearDownRunner cleans up any global test runner resources. It must be called // after the test runner has finished executing all its tests. func (r *runner) TearDownRunner(ctx context.Context) error { logger.Debug("Uninstalling package...") err := r.cleanup(context.WithoutCancel(ctx)) if err != nil { return fmt.Errorf("failed to clean up test runner: %w", err) } return nil } func (r *runner) GetTests(ctx context.Context) ([]testrunner.Tester, error) { var folders []testrunner.TestFolder manifest, err := packages.ReadPackageManifestFromPackageRoot(r.packageRootPath) if err != nil { return nil, fmt.Errorf("reading package manifest failed (path: %s): %w", r.packageRootPath, err) } hasDataStreams, err := testrunner.PackageHasDataStreams(manifest) if err != nil { return nil, fmt.Errorf("cannot determine if package has data streams: %w", err) } if hasDataStreams { var dataStreams []string if len(r.dataStreams) > 0 { dataStreams = r.dataStreams } folders, err = testrunner.FindTestFolders(r.packageRootPath, dataStreams, r.Type()) if err != nil { return nil, fmt.Errorf("unable to determine test folder paths: %w", err) } if r.failOnMissingTests && len(folders) == 0 { if len(dataStreams) > 0 { return nil, fmt.Errorf("no %s tests found for %s data stream(s)", r.Type(), strings.Join(dataStreams, ",")) } return nil, fmt.Errorf("no %s tests found", r.Type()) } } else { folders, err = testrunner.FindTestFolders(r.packageRootPath, nil, r.Type()) if err != nil { return nil, fmt.Errorf("unable to determine test folder paths: %w", err) } if r.failOnMissingTests && len(folders) == 0 { return nil, fmt.Errorf("no %s tests found", r.Type()) } } var testers []testrunner.Tester for _, folder := range folders { tests, err := filepath.Glob(filepath.Join(folder.Path, "test-*.yml")) if err != nil { return nil, fmt.Errorf("failed to look for test files in %s: %w", folder.Path, err) } for _, test := range tests { testers = append(testers, NewPolicyTester(PolicyTesterOptions{ PackageRootPath: r.packageRootPath, TestFolder: folder, KibanaClient: r.kibanaClient, GenerateTestResult: r.generateTestResult, TestPath: test, GlobalTestConfig: r.globalTestConfig, WithCoverage: r.withCoverage, CoverageType: r.coverageType, })) } } return testers, nil } func (r *runner) Type() testrunner.TestType { return TestType } func (r *runner) setupSuite(ctx context.Context, manager *resources.Manager) (cleanup func(ctx context.Context) error, err error) { packageResource := resources.FleetPackage{ RootPath: r.packageRootPath, } setupResources := resources.Resources{ &packageResource, } cleanup = func(ctx context.Context) error { packageResource.Absent = true _, err := manager.ApplyCtx(ctx, setupResources) return err } logger.Debugf("Installing package...") _, err = manager.ApplyCtx(ctx, setupResources) if err != nil { if ctx.Err() == nil { cleanupErr := cleanup(ctx) if cleanupErr != nil { return nil, fmt.Errorf("setup failed: %w (with cleanup error: %w)", err, cleanupErr) } } return nil, fmt.Errorf("setup failed: %w", err) } return cleanup, err }