Repository: redhat-openshift-ecosystem/openshift-preflight
Pull request #809 (2022-10-20 22:00:42)

Add lib to preflight
Work in progress!

Related to: 
- https://github.com/test-network-function/cnf-certification-test/pull/592
- https://github.com/redhat-openshift-ecosystem/openshift-preflight/issues/639

This PR provides some changes needed to implement the `lib`.  (Name is subject to change 😄)

I want to go through some of the files to describe my notable changes:

- certification/runtime/config.go
In this file, I added `NewManualContainerConfig` and `NewManualOperatorConfig` for being able to create config objects geared towards their individual purposes.

- cmd/check_container.go and cmd/check_operator.go
These files have had their "NewOperator/Container" funcs moved to the lib.

- fakes.go and types.go
Moved to the lib folder, because it contains funcs like `NewFakePyxisClientNoop` and `NewNoopSubmitter`.
The `NoopSubmitter` has had appropriate setters added.

- lib/check_container_test.go and cmd/check_container_test.go
I split these two files into files more geared towards their testing purposes.  The `cmd` package one tests stuff that has to do with the `cmd` package, for example.

openshift-ci[bot]: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/redhat-openshift-ecosystem/openshift-preflight/pull/809#" title="Author self-approved">sebrandon1</a>*
**Once this PR has been reviewed and has the lgtm label**, please assign acornett21 for approval by writing `/assign @acornett21` in a comment. For more information see [the Kubernetes Code Review Process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process).

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=redhat-openshift-ecosystem%2Fopenshift-preflight).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/redhat-openshift-ecosystem/openshift-preflight/blob/main/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["acornett21"]} -->
openshift-ci[bot]: Hi @sebrandon1. Thanks for your PR.

I'm waiting for a [redhat-openshift-ecosystem](https://github.com/orgs/redhat-openshift-ecosystem/people) member to verify that this patch is reasonable to test. If it is, they should reply with `/ok-to-test` on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should [join the org](https://github.com/orgs/redhat-openshift-ecosystem/people) to skip this step.

Once the patch is verified, the new status will be reflected by the `ok-to-test` label.

I understand the commands that are listed [here](https://go.k8s.io/bot-commands?repo=redhat-openshift-ecosystem%2Fopenshift-preflight).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>

dcibot: - SUCCESS https://www.distributed-ci.io/jobs/67a66f18-027a-4581-822c-ddda74e890e7/jobStates
 from https://github.com/redhat-openshift-ecosystem/openshift-preflight/pull/809
bcrochet: /ok-to-test
dcibot: - SUCCESS https://www.distributed-ci.io/jobs/bd55371d-df1d-45de-9d34-18094856546f/jobStates
 from https://github.com/redhat-openshift-ecosystem/openshift-preflight/pull/809
openshift-ci[bot]: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/redhat-openshift-ecosystem/openshift-preflight/pull/809#" title="Author self-approved">sebrandon1</a>*
**Once this PR has been reviewed and has the lgtm label**, please ask for approval from acornett21 by writing `/assign @acornett21` in a comment. For more information see [the Kubernetes Code Review Process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process).

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=redhat-openshift-ecosystem%2Fopenshift-preflight).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/redhat-openshift-ecosystem/openshift-preflight/blob/main/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["acornett21"]} -->
dcibot: - SUCCESS https://www.distributed-ci.io/jobs/80c7feb6-35c3-4274-8264-abffe91f0522/jobStates
 from https://github.com/redhat-openshift-ecosystem/openshift-preflight/pull/809
sebrandon1: @komish Thanks for the review!  Yes, actually what you propose makes a lot of sense by pushing some of that logic farther into the code and only getting two functions `CheckContainer(...) and CheckOperator(...)` with appropriate parameters exposed that would make things much easier.  Those two functions could return your `runtime.Results` structs and handle everything internally versus me interpreting a JSON blob and unmarshalling it back into your structs.  Removes a lot of complexity on the whoever "consumes" the lib so I'm fine with that.

With my initial PoC approach I didn't want to _change_ too much to get this working but this makes more sense for future-proofing the effort.  Very exciting!


komish: @sebrandon1 for sure. I’ll give some folks time to look and then we can chart the path to get this merged!

komish: @sebrandon1 I'll have you move `lib` to `internal/lib`, and then rewire the import statements to use that new path. From there, we'll expose hooks for you to be able to run the checks. This temporarily breaks your use case, but we'll fast-follow this on our end and I'll ping you into the PR that adds the exported functionality for your use case.
sebrandon1: @komish Sounds excellent!  I'll do that right now.
sebrandon1: Okay in [7a84034](https://github.com/redhat-openshift-ecosystem/openshift-preflight/pull/809/commits/7a840340848c31f59c81fc2b31ab9086980bb95d) I moved the lib into a new "internal" folder in the top level and changed the references.
dcibot: - FAILURE https://www.distributed-ci.io/jobs/1666b931-760e-4b62-8390-6dc61c3a3a7f/jobStates
 from https://github.com/redhat-openshift-ecosystem/openshift-preflight/pull/809
komish: @sebrandon1 

The CI failure reports:

```
internal/lib/lib.go:10                goimports  File is not `goimports`-ed with -local github.com/redhat-openshift-ecosystem/openshift-preflight
internal/lib/types.go:12              goimports  File is not `goimports`-ed with -local github.com/redhat-openshift-ecosystem/openshift-preflight
certification/internal/lib/lib.go:10  goimports  File is not `goimports`-ed with -local github.com/redhat-openshift-ecosystem/openshift-preflight
```

Given that's the only failure I see right at this moment, I think running this and committing the changes should fix the issue:

```
./bin/golangci-lint run --fix
```
sebrandon1: Okay fixed.  I ran `./bin/golangci-lint run --fix`.
coveralls: 
[![Coverage Status](https://coveralls.io/builds/53559167/badge)](https://coveralls.io/builds/53559167)

Coverage decreased (-15.2%) to 69.32% when pulling **8dd7fbc16c7b34b3b151a849bc640cac60f4501b on sebrandon1:rename_lib** into **a41492be4530b5740231d4c11933cbf067a3ad40 on redhat-openshift-ecosystem:main**.

dcibot: - FAILURE https://www.distributed-ci.io/jobs/cd10419b-a0cd-41c0-8009-12bbed6190b5/jobStates
 from https://github.com/redhat-openshift-ecosystem/openshift-preflight/pull/809
komish: Added on two commits to fix the coverage issues and fix a couple of case issues in comments for exported functions.

Coverage issues were fixed by:
- adding suite_test.go to the `internal/lib`. They were being skipped.
- moving NewCheckOperatorRunner-related tests to `internal/lib` where that function now lives
- moving fakes.go to fakes_test.go which excludes it in coverage evaluation.


komish: https://github.com/redhat-openshift-ecosystem/openshift-preflight/pull/809/commits/0d08e685ab63ee3e980cf0a75274382d7ab19239 removes a duplicate bit of code and moves the test to the correct location.
komish: @sebrandon1 @bcrochet @acornett21 as I've made changes here, PTAL.
dcibot: - FAILURE https://www.distributed-ci.io/jobs/84825c44-a20d-4c21-845d-0aec82dd6322/jobStates
 from https://github.com/redhat-openshift-ecosystem/openshift-preflight/pull/809
komish: > 



> * FAILURE https://www.distributed-ci.io/jobs/84825c44-a20d-4c21-845d-0aec82dd6322/jobStates
>   from [Add lib to preflight #809](https://github.com/redhat-openshift-ecosystem/openshift-preflight/pull/809)

@tkrishtop Just a heads up that it seems like this is a problem in the infrastructure's ability to RW files on the filesystem (permission denied) and doesn't seem related to the PR's changes at first glance.
acornett21: @komish I think this addresses everything, the only thing we'd need is the commits squashed.

openshift-ci[bot]: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/redhat-openshift-ecosystem/openshift-preflight/pull/809#pullrequestreview-1155494188" title="Approved">acornett21</a>*, *<a href="https://github.com/redhat-openshift-ecosystem/openshift-preflight/pull/809#" title="Author self-approved">sebrandon1</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=redhat-openshift-ecosystem%2Fopenshift-preflight).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/redhat-openshift-ecosystem/openshift-preflight/blob/main/OWNERS)~~ [acornett21]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
openshift-ci[bot]: New changes are detected. LGTM label has been removed.
dcibot: - FAILURE https://www.distributed-ci.io/jobs/926f7a49-8de3-429e-97b1-0c4c86d991f0/jobStates
 from https://github.com/redhat-openshift-ecosystem/openshift-preflight/pull/809
openshift-ci[bot]: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/redhat-openshift-ecosystem/openshift-preflight/pull/809#pullrequestreview-1155494188" title="Approved">acornett21</a>*, *<a href="https://github.com/redhat-openshift-ecosystem/openshift-preflight/pull/809#pullrequestreview-1155511589" title="LGTM">bcrochet</a>*, *<a href="https://github.com/redhat-openshift-ecosystem/openshift-preflight/pull/809#" title="Author self-approved">sebrandon1</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=redhat-openshift-ecosystem%2Fopenshift-preflight).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/redhat-openshift-ecosystem/openshift-preflight/blob/main/OWNERS)~~ [acornett21,bcrochet]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->

Patch:
diff --git a/certification/runtime/result_writer.go b/certification/runtime/result_writer.go
index 9603334..876d820 100644
--- a/certification/runtime/result_writer.go
+++ b/certification/runtime/result_writer.go
@@ -5,7 +5,7 @@ import (
 	"os"
 )
 
-// ResultWriterFile implements a resultWriter for use at preflight runtime.
+// ResultWriterFile implements a ResultWriter for use at preflight runtime.
 type ResultWriterFile struct {
 	file *os.File
 }
diff --git a/cmd/check.go b/cmd/check.go
index 68d30e9..39561c3 100644
--- a/cmd/check.go
+++ b/cmd/check.go
@@ -1,16 +1,8 @@
 package cmd
 
 import (
-	"bytes"
-	"context"
-	"fmt"
 	"strings"
 
-	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/artifacts"
-	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/formatters"
-	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/runtime"
-
-	log "github.com/sirupsen/logrus"
 	"github.com/spf13/cobra"
 	"github.com/spf13/viper"
 )
@@ -36,52 +28,10 @@ func checkCmd() *cobra.Command {
 	return checkCmd
 }
 
-// writeJUnit will write results as JUnit XML using the built-in formatter.
-func writeJUnit(ctx context.Context, results runtime.Results) error {
-	var cfg runtime.Config
-	cfg.ResponseFormat = "junitxml"
-
-	junitformatter, err := formatters.NewForConfig(cfg.ReadOnly())
-	if err != nil {
-		return err
-	}
-	junitResults, err := junitformatter.Format(ctx, results)
-	if err != nil {
-		return err
-	}
-
-	junitFilename, err := artifacts.WriteFile("results-junit.xml", bytes.NewReader((junitResults)))
-	if err != nil {
-		return err
-	}
-	log.Tracef("JUnitXML written to %s", junitFilename)
-
-	return nil
-}
-
 func resultsFilenameWithExtension(ext string) string {
 	return strings.Join([]string{"results", ext}, ".")
 }
 
-func buildConnectURL(projectID string) string {
-	connectURL := fmt.Sprintf("https://connect.redhat.com/projects/%s", projectID)
-
-	pyxisEnv := viper.GetString("pyxis_env")
-	if len(pyxisEnv) > 0 && pyxisEnv != "prod" {
-		connectURL = fmt.Sprintf("https://connect.%s.redhat.com/projects/%s", viper.GetString("pyxis_env"), projectID)
-	}
-
-	return connectURL
-}
-
-func buildOverviewURL(projectID string) string {
-	return fmt.Sprintf("%s/overview", buildConnectURL(projectID))
-}
-
-func buildScanResultsURL(projectID string, imageID string) string {
-	return fmt.Sprintf("%s/images/%s/scan-results", buildConnectURL(projectID), imageID)
-}
-
 func convertPassedOverall(passedOverall bool) string {
 	if passedOverall {
 		return "PASSED"
diff --git a/cmd/check_container.go b/cmd/check_container.go
index 8e0a218..9911a74 100644
--- a/cmd/check_container.go
+++ b/cmd/check_container.go
@@ -1,15 +1,13 @@
 package cmd
 
 import (
-	"context"
 	"fmt"
 	"strings"
 
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification"
-	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/engine"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/formatters"
-	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/policy"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/runtime"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/internal/lib"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/version"
 
 	log "github.com/sirupsen/logrus"
@@ -52,53 +50,6 @@ func checkContainerCmd() *cobra.Command {
 	return checkContainerCmd
 }
 
-// checkContainerRunner contains all of the components necessary to run checkContainer.
-type checkContainerRunner struct {
-	cfg       *runtime.Config
-	pc        pyxisClient
-	eng       engine.CheckEngine
-	formatter formatters.ResponseFormatter
-	rw        resultWriter
-	rs        resultSubmitter
-}
-
-func newCheckContainerRunner(ctx context.Context, cfg *runtime.Config) (*checkContainerRunner, error) {
-	cfg.Policy = policy.PolicyContainer
-	cfg.Submit = submit
-
-	pyxisClient := newPyxisClient(ctx, cfg.ReadOnly())
-	// If we have a pyxisClient, we can query for container policy exceptions.
-	if pyxisClient != nil {
-		policy, err := getContainerPolicyExceptions(ctx, pyxisClient)
-		if err != nil {
-			return nil, err
-		}
-
-		cfg.Policy = policy
-	}
-
-	engine, err := engine.NewForConfig(ctx, cfg.ReadOnly())
-	if err != nil {
-		return nil, err
-	}
-
-	fmttr, err := formatters.NewForConfig(cfg.ReadOnly())
-	if err != nil {
-		return nil, err
-	}
-
-	rs := resolveSubmitter(pyxisClient, cfg.ReadOnly())
-
-	return &checkContainerRunner{
-		cfg:       cfg,
-		pc:        pyxisClient,
-		eng:       engine,
-		formatter: fmttr,
-		rw:        &runtime.ResultWriterFile{},
-		rs:        rs,
-	}, nil
-}
-
 // checkContainerRunE executes checkContainer using the user args to inform the execution.
 func checkContainerRunE(cmd *cobra.Command, args []string) error {
 	log.Info("certification library version ", version.Version.String())
@@ -114,62 +65,23 @@ func checkContainerRunE(cmd *cobra.Command, args []string) error {
 	cfg.Image = containerImage
 	cfg.ResponseFormat = formatters.DefaultFormat
 
-	checkContainer, err := newCheckContainerRunner(ctx, cfg)
+	checkContainer, err := lib.NewCheckContainerRunner(ctx, cfg, submit)
 	if err != nil {
 		return err
 	}
 
 	// Run the  container check.
 	cmd.SilenceUsage = true
-	return preflightCheck(ctx,
-		checkContainer.cfg,
-		checkContainer.pc,
-		checkContainer.eng,
-		checkContainer.formatter,
-		checkContainer.rw,
-		checkContainer.rs,
+	return lib.PreflightCheck(ctx,
+		checkContainer.Cfg,
+		checkContainer.Pc,
+		checkContainer.Eng,
+		checkContainer.Formatter,
+		checkContainer.Rw,
+		checkContainer.Rs,
 	)
 }
 
-// resolveSubmitter will build out a resultSubmitter if the provided pyxisClient, pc, is not nil.
-// The pyxisClient is a required component of the submitter. If pc is nil, then a noop submitter
-// is returned instead, which does nothing.
-func resolveSubmitter(pc pyxisClient, cfg certification.Config) resultSubmitter {
-	if pc != nil {
-		return &containerCertificationSubmitter{
-			certificationProjectID: cfg.CertificationProjectID(),
-			pyxis:                  pc,
-			dockerConfig:           cfg.DockerConfig(),
-			preflightLogFile:       cfg.LogFile(),
-		}
-	}
-
-	return &noopSubmitter{emitLog: true}
-}
-
-// getContainerPolicyExceptions will query Pyxis to determine if
-// a given project has a certification excemptions, such as root or scratch.
-// This will then return the corresponding policy.
-//
-// If no policy exception flags are found on the project, the standard
-// container policy is returned.
-func getContainerPolicyExceptions(ctx context.Context, pc pyxisClient) (policy.Policy, error) {
-	certProject, err := pc.GetProject(ctx)
-	if err != nil {
-		return "", fmt.Errorf("could not retrieve project: %w", err)
-	}
-	log.Debugf("Certification project name is: %s", certProject.Name)
-	if certProject.Container.Type == "scratch" {
-		return policy.PolicyScratch, nil
-	}
-
-	// if a partner sets `Host Level Access` in connect to `Privileged`, enable RootExceptionContainerPolicy checks
-	if certProject.Container.Privileged {
-		return policy.PolicyRoot, nil
-	}
-	return policy.PolicyContainer, nil
-}
-
 func checkContainerPositionalArgs(cmd *cobra.Command, args []string) error {
 	if len(args) != 1 {
 		return fmt.Errorf("a container image positional argument is required")
diff --git a/cmd/check_operator.go b/cmd/check_operator.go
index 6199720..daef676 100644
--- a/cmd/check_operator.go
+++ b/cmd/check_operator.go
@@ -1,14 +1,12 @@
 package cmd
 
 import (
-	"context"
 	"fmt"
 	"os"
 
-	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/engine"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/formatters"
-	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/policy"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/runtime"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/internal/lib"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/version"
 
 	log "github.com/sirupsen/logrus"
@@ -48,38 +46,6 @@ func checkOperatorCmd() *cobra.Command {
 	return checkOperatorCmd
 }
 
-// checkOperatorRunner contains all of the components necessary to run checkOperator.
-type checkOperatorRunner struct {
-	cfg       *runtime.Config
-	eng       engine.CheckEngine
-	formatter formatters.ResponseFormatter
-	rw        resultWriter
-}
-
-// newCheckOperatorRunner returns a checkOperatorRunner containing all of the tooling necessary
-// to run checkOperator.
-func newCheckOperatorRunner(ctx context.Context, cfg *runtime.Config) (*checkOperatorRunner, error) {
-	cfg.Policy = policy.PolicyOperator
-	cfg.Submit = false // there's no such thing as submitting for operators today.
-
-	engine, err := engine.NewForConfig(ctx, cfg.ReadOnly())
-	if err != nil {
-		return nil, err
-	}
-
-	fmttr, err := formatters.NewForConfig(cfg.ReadOnly())
-	if err != nil {
-		return nil, err
-	}
-
-	return &checkOperatorRunner{
-		cfg:       cfg,
-		eng:       engine,
-		formatter: fmttr,
-		rw:        &runtime.ResultWriterFile{},
-	}, nil
-}
-
 // ensureKubeconfigIsSet ensures that the KUBECONFIG environment variable has a value.
 func ensureKubeconfigIsSet() error {
 	if _, ok := os.LookupEnv("KUBECONFIG"); !ok {
@@ -116,20 +82,20 @@ func checkOperatorRunE(cmd *cobra.Command, args []string) error {
 	cfg.Bundle = true
 	cfg.Scratch = true
 
-	checkOperator, err := newCheckOperatorRunner(ctx, cfg)
+	checkOperator, err := lib.NewCheckOperatorRunner(ctx, cfg)
 	if err != nil {
 		return err
 	}
 
 	// Run the operator check
 	cmd.SilenceUsage = true
-	return preflightCheck(ctx,
-		checkOperator.cfg,
+	return lib.PreflightCheck(ctx,
+		checkOperator.Cfg,
 		nil, // no pyxisClient is necessary
-		checkOperator.eng,
-		checkOperator.formatter,
-		checkOperator.rw,
-		&noopSubmitter{}, // we do not submit these results.
+		checkOperator.Eng,
+		checkOperator.Formatter,
+		checkOperator.Rw,
+		&lib.NoopSubmitter{}, // we do not submit these results.
 	)
 }
 
diff --git a/cmd/preflight_check.go b/cmd/preflight_check.go
deleted file mode 100644
index acdd4af..0000000
--- a/cmd/preflight_check.go
+++ /dev/null
@@ -1,76 +0,0 @@
-package cmd
-
-import (
-	"context"
-	"fmt"
-	"io"
-	"os"
-	"strings"
-
-	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/artifacts"
-	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/engine"
-	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/formatters"
-	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/runtime"
-
-	log "github.com/sirupsen/logrus"
-)
-
-// preflightCheck executes checks, interacts with pyxis, format output, writes, and submits results.
-func preflightCheck(
-	ctx context.Context,
-	cfg *runtime.Config,
-	pc pyxisClient, //nolint:unparam // pyxisClient is currently unused.
-	eng engine.CheckEngine,
-	formatter formatters.ResponseFormatter,
-	rw resultWriter,
-	rs resultSubmitter,
-) error {
-	// configure the artifacts directory if the user requested a different directory.
-	if cfg.Artifacts != "" {
-		artifacts.SetDir(cfg.Artifacts)
-	}
-
-	// create the results file early to catch cases where we are not
-	// able to write to the filesystem before we attempt to execute checks.
-	resultsFilePath, err := artifacts.WriteFile(resultsFilenameWithExtension(formatter.FileExtension()), strings.NewReader(""))
-	if err != nil {
-		return err
-	}
-	resultsFile, err := rw.OpenFile(resultsFilePath)
-	if err != nil {
-		return err
-	}
-	defer resultsFile.Close()
-
-	resultsOutputTarget := io.MultiWriter(os.Stdout, resultsFile)
-
-	// execute the checks
-	if err := eng.ExecuteChecks(ctx); err != nil {
-		return err
-	}
-	results := eng.Results(ctx)
-
-	// return results to the user and then close output files
-	formattedResults, err := formatter.Format(ctx, results)
-	if err != nil {
-		return err
-	}
-
-	fmt.Fprintln(resultsOutputTarget, string(formattedResults))
-
-	if cfg.WriteJUnit {
-		if err := writeJUnit(ctx, results); err != nil {
-			return err
-		}
-	}
-
-	if cfg.Submit {
-		if err := rs.Submit(ctx); err != nil {
-			return err
-		}
-	}
-
-	log.Infof("Preflight result: %s", convertPassedOverall(results.PassedOverall))
-
-	return nil
-}
diff --git a/internal/lib/lib.go b/internal/lib/lib.go
new file mode 100644
index 0000000..f9d038b
--- /dev/null
+++ b/internal/lib/lib.go
@@ -0,0 +1,230 @@
+package lib
+
+import (
+	"bytes"
+	"context"
+	"fmt"
+	"io"
+	"os"
+	"strings"
+
+	log "github.com/sirupsen/logrus"
+
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/artifacts"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/engine"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/formatters"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/policy"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/runtime"
+)
+
+// CheckContainerRunner contains all of the components necessary to run checkContainer.
+type CheckContainerRunner struct {
+	Cfg       *runtime.Config
+	Pc        PyxisClient
+	Eng       engine.CheckEngine
+	Formatter formatters.ResponseFormatter
+	Rw        ResultWriter
+	Rs        ResultSubmitter
+}
+
+func NewCheckContainerRunner(ctx context.Context, cfg *runtime.Config, submit bool) (*CheckContainerRunner, error) {
+	cfg.Policy = policy.PolicyContainer
+	cfg.Submit = submit
+
+	pyxisClient := NewPyxisClient(ctx, cfg.ReadOnly())
+	// If we have a pyxisClient, we can query for container policy exceptions.
+	if pyxisClient != nil {
+		policy, err := GetContainerPolicyExceptions(ctx, pyxisClient)
+		if err != nil {
+			return nil, err
+		}
+
+		cfg.Policy = policy
+	}
+
+	engine, err := engine.NewForConfig(ctx, cfg.ReadOnly())
+	if err != nil {
+		return nil, err
+	}
+
+	fmttr, err := formatters.NewForConfig(cfg.ReadOnly())
+	if err != nil {
+		return nil, err
+	}
+
+	rs := ResolveSubmitter(pyxisClient, cfg.ReadOnly())
+
+	return &CheckContainerRunner{
+		Cfg:       cfg,
+		Pc:        pyxisClient,
+		Eng:       engine,
+		Formatter: fmttr,
+		Rw:        &runtime.ResultWriterFile{},
+		Rs:        rs,
+	}, nil
+}
+
+// CheckOperatorRunner contains all of the components necessary to run checkOperator.
+type CheckOperatorRunner struct {
+	Cfg       *runtime.Config
+	Eng       engine.CheckEngine
+	Formatter formatters.ResponseFormatter
+	Rw        ResultWriter
+}
+
+// NewCheckOperatorRunner returns a CheckOperatorRunner containing all of the tooling necessary
+// to run checkOperator.
+func NewCheckOperatorRunner(ctx context.Context, cfg *runtime.Config) (*CheckOperatorRunner, error) {
+	cfg.Policy = policy.PolicyOperator
+	cfg.Submit = false // there's no such thing as submitting for operators today.
+
+	engine, err := engine.NewForConfig(ctx, cfg.ReadOnly())
+	if err != nil {
+		return nil, err
+	}
+
+	fmttr, err := formatters.NewForConfig(cfg.ReadOnly())
+	if err != nil {
+		return nil, err
+	}
+
+	return &CheckOperatorRunner{
+		Cfg:       cfg,
+		Eng:       engine,
+		Formatter: fmttr,
+		Rw:        &runtime.ResultWriterFile{},
+	}, nil
+}
+
+// ResolveSubmitter will build out a ResultSubmitter if the provided pyxisClient, pc, is not nil.
+// The pyxisClient is a required component of the submitter. If pc is nil, then a noop submitter
+// is returned instead, which does nothing.
+func ResolveSubmitter(pc PyxisClient, cfg certification.Config) ResultSubmitter {
+	if pc != nil {
+		return &ContainerCertificationSubmitter{
+			CertificationProjectID: cfg.CertificationProjectID(),
+			Pyxis:                  pc,
+			DockerConfig:           cfg.DockerConfig(),
+			PreflightLogFile:       cfg.LogFile(),
+		}
+	}
+	return NewNoopSubmitter(true, "", nil)
+}
+
+// GetContainerPolicyExceptions will query Pyxis to determine if
+// a given project has a certification excemptions, such as root or scratch.
+// This will then return the corresponding policy.
+//
+// If no policy exception flags are found on the project, the standard
+// container policy is returned.
+func GetContainerPolicyExceptions(ctx context.Context, pc PyxisClient) (policy.Policy, error) {
+	certProject, err := pc.GetProject(ctx)
+	if err != nil {
+		return "", fmt.Errorf("could not retrieve project: %w", err)
+	}
+	// log.Debugf("Certification project name is: %s", certProject.Name)
+	if certProject.Container.Type == "scratch" {
+		return policy.PolicyScratch, nil
+	}
+
+	// if a partner sets `Host Level Access` in connect to `Privileged`, enable RootExceptionContainerPolicy checks
+	if certProject.Container.Privileged {
+		return policy.PolicyRoot, nil
+	}
+	return policy.PolicyContainer, nil
+}
+
+// PreflightCheck executes checks, interacts with pyxis, format output, writes, and submits results.
+func PreflightCheck(
+	ctx context.Context,
+	cfg *runtime.Config,
+	pc PyxisClient, //nolint:unparam // PyxisClient is currently unused.
+	eng engine.CheckEngine,
+	formatter formatters.ResponseFormatter,
+	rw ResultWriter,
+	rs ResultSubmitter,
+) error {
+	// configure the artifacts directory if the user requested a different directory.
+	if cfg.Artifacts != "" {
+		artifacts.SetDir(cfg.Artifacts)
+	}
+
+	// create the results file early to catch cases where we are not
+	// able to write to the filesystem before we attempt to execute checks.
+	resultsFilePath, err := artifacts.WriteFile(resultsFilenameWithExtension(formatter.FileExtension()), strings.NewReader(""))
+	if err != nil {
+		return err
+	}
+	resultsFile, err := rw.OpenFile(resultsFilePath)
+	if err != nil {
+		return err
+	}
+	defer resultsFile.Close()
+
+	resultsOutputTarget := io.MultiWriter(os.Stdout, resultsFile)
+
+	// execute the checks
+	if err := eng.ExecuteChecks(ctx); err != nil {
+		return err
+	}
+	results := eng.Results(ctx)
+
+	// return results to the user and then close output files
+	formattedResults, err := formatter.Format(ctx, results)
+	if err != nil {
+		return err
+	}
+
+	fmt.Fprintln(resultsOutputTarget, string(formattedResults))
+
+	if cfg.WriteJUnit {
+		if err := writeJUnit(ctx, results); err != nil {
+			return err
+		}
+	}
+
+	if cfg.Submit {
+		if err := rs.Submit(ctx); err != nil {
+			return err
+		}
+	}
+
+	log.Infof("Preflight result: %s", convertPassedOverall(results.PassedOverall))
+
+	return nil
+}
+
+func writeJUnit(ctx context.Context, results runtime.Results) error {
+	var cfg runtime.Config
+	cfg.ResponseFormat = "junitxml"
+
+	junitformatter, err := formatters.NewForConfig(cfg.ReadOnly())
+	if err != nil {
+		return err
+	}
+	junitResults, err := junitformatter.Format(ctx, results)
+	if err != nil {
+		return err
+	}
+
+	junitFilename, err := artifacts.WriteFile("results-junit.xml", bytes.NewReader((junitResults)))
+	if err != nil {
+		return err
+	}
+	log.Tracef("JUnitXML written to %s", junitFilename)
+
+	return nil
+}
+
+func resultsFilenameWithExtension(ext string) string {
+	return strings.Join([]string{"results", ext}, ".")
+}
+
+func convertPassedOverall(passedOverall bool) string {
+	if passedOverall {
+		return "PASSED"
+	}
+
+	return "FAILED"
+}
diff --git a/cmd/types.go b/internal/lib/types.go
similarity index 68%
rename from cmd/types.go
rename to internal/lib/types.go
index 472031d..95d7443 100644
--- a/cmd/types.go
+++ b/internal/lib/types.go
@@ -1,4 +1,4 @@
-package cmd
+package lib
 
 import (
 	"context"
@@ -10,6 +10,8 @@ import (
 	"path/filepath"
 	"time"
 
+	"github.com/spf13/viper"
+
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/artifacts"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/pyxis"
@@ -17,19 +19,19 @@ import (
 	log "github.com/sirupsen/logrus"
 )
 
-// resultWriter defines methods associated with writing check results.
-type resultWriter interface {
+// ResultWriter defines methods associated with writing check results.
+type ResultWriter interface {
 	OpenFile(name string) (io.WriteCloser, error)
 	io.WriteCloser
 }
 
-// resultSubmitter defines methods associated with submitting results to Red HAt.
-type resultSubmitter interface {
+// ResultSubmitter defines methods associated with submitting results to Red HAt.
+type ResultSubmitter interface {
 	Submit(context.Context) error
 }
 
-// pyxisClient defines pyxis API interactions that are relevant to check executions in cmd.
-type pyxisClient interface {
+// PyxisClient defines pyxis API interactions that are relevant to check executions in cmd.
+type PyxisClient interface {
 	FindImagesByDigest(ctx context.Context, digests []string) ([]pyxis.CertImage, error)
 	GetProject(context.Context) (*pyxis.CertProject, error)
 	SubmitResults(context.Context, *pyxis.CertificationInput) (*pyxis.CertificationResults, error)
@@ -40,7 +42,7 @@ type pyxisClient interface {
 // Callers should treat a nil pyxis client as an indicator that pyxis calls should not be made.
 //
 //nolint:unparam // ctx is unused. Keep for future use.
-func newPyxisClient(ctx context.Context, cfg certification.Config) pyxisClient {
+func NewPyxisClient(ctx context.Context, cfg certification.Config) PyxisClient {
 	if cfg.CertificationProjectID() == "" || cfg.PyxisAPIToken() == "" || cfg.PyxisHost() == "" {
 		return nil
 	}
@@ -53,20 +55,20 @@ func newPyxisClient(ctx context.Context, cfg certification.Config) pyxisClient {
 	)
 }
 
-// containerCertificationSubmitter submits container results to Pyxis, and implements
-// a resultSubmitter.
-type containerCertificationSubmitter struct {
-	certificationProjectID string
-	pyxis                  pyxisClient
-	dockerConfig           string
-	preflightLogFile       string
+// ContainerCertificationSubmitter submits container results to Pyxis, and implements
+// a ResultSubmitter.
+type ContainerCertificationSubmitter struct {
+	CertificationProjectID string
+	Pyxis                  PyxisClient
+	DockerConfig           string
+	PreflightLogFile       string
 }
 
-func (s *containerCertificationSubmitter) Submit(ctx context.Context) error {
+func (s *ContainerCertificationSubmitter) Submit(ctx context.Context) error {
 	log.Info("preparing results that will be submitted to Red Hat")
 
 	// get the project info from pyxis
-	certProject, err := s.pyxis.GetProject(ctx)
+	certProject, err := s.Pyxis.GetProject(ctx)
 	if err != nil {
 		return fmt.Errorf("could not retrieve project: %w", err)
 	}
@@ -83,11 +85,11 @@ func (s *containerCertificationSubmitter) Submit(ctx context.Context) error {
 
 	// only read the dockerfile if the user provides a location for the file
 	// at this point in the flow, if `cfg.DockerConfig` is empty we know the repo is public and can continue the submission flow
-	if s.dockerConfig != "" {
-		dockerConfigJSONBytes, err := os.ReadFile(s.dockerConfig)
+	if s.DockerConfig != "" {
+		dockerConfigJSONBytes, err := os.ReadFile(s.DockerConfig)
 		if err != nil {
 			return fmt.Errorf("could not open file for submission: %s: %w",
-				s.dockerConfig,
+				s.DockerConfig,
 				err,
 			)
 		}
@@ -100,7 +102,7 @@ func (s *containerCertificationSubmitter) Submit(ctx context.Context) error {
 	// if we were to send what pyixs just sent us in a update call, pyxis would throw a validation error saying it's not valid json
 	// the below code aims to set the DockerConfigJSON to an empty string, and since this field is `omitempty` when we marshall it
 	// we will not get a validation error
-	if s.dockerConfig == "" {
+	if s.DockerConfig == "" {
 		certProject.Container.DockerConfigJSON = ""
 	}
 
@@ -137,11 +139,11 @@ func (s *containerCertificationSubmitter) Submit(ctx context.Context) error {
 	}
 	defer rpmManifest.Close()
 
-	logfile, err := os.Open(s.preflightLogFile)
+	logfile, err := os.Open(s.PreflightLogFile)
 	if err != nil {
 		return fmt.Errorf(
 			"could not open file for submission: %s: %w",
-			s.preflightLogFile,
+			s.PreflightLogFile,
 			err,
 		)
 	}
@@ -155,14 +157,14 @@ func (s *containerCertificationSubmitter) Submit(ctx context.Context) error {
 		// The certification engine writes the rpmManifest for images not based on scratch.
 		WithRPMManifest(rpmManifest).
 		// Include the preflight execution log file.
-		WithArtifact(logfile, filepath.Base(s.preflightLogFile))
+		WithArtifact(logfile, filepath.Base(s.PreflightLogFile))
 
 	input, err := submission.Finalize()
 	if err != nil {
 		return fmt.Errorf("unable to finalize data that would be sent to pyxis: %w", err)
 	}
 
-	certResults, err := s.pyxis.SubmitResults(ctx, input)
+	certResults, err := s.Pyxis.SubmitResults(ctx, input)
 	if err != nil {
 		return fmt.Errorf("could not submit to pyxis: %w", err)
 	}
@@ -170,23 +172,31 @@ func (s *containerCertificationSubmitter) Submit(ctx context.Context) error {
 	log.Info("Test results have been submitted to Red Hat.")
 	log.Info("These results will be reviewed by Red Hat for final certification.")
 	log.Infof("The container's image id is: %s.", certResults.CertImage.ID)
-	log.Infof("Please check %s to view scan results.", buildScanResultsURL(s.certificationProjectID, certResults.CertImage.ID))
-	log.Infof("Please check %s to monitor the progress.", buildOverviewURL(s.certificationProjectID))
+	log.Infof("Please check %s to view scan results.", BuildScanResultsURL(s.CertificationProjectID, certResults.CertImage.ID))
+	log.Infof("Please check %s to monitor the progress.", BuildOverviewURL(s.CertificationProjectID))
 
 	return nil
 }
 
-// noopSubmitter is a no-op resultSubmitter that optionally logs a message
+// NoopSubmitter is a no-op ResultSubmitter that optionally logs a message
 // and a reason as to why results were not submitted.
-type noopSubmitter struct {
+type NoopSubmitter struct {
 	emitLog bool
 	reason  string
 	log     *log.Logger
 }
 
-var _ resultSubmitter = &noopSubmitter{}
+func NewNoopSubmitter(emitLog bool, reason string, log *log.Logger) *NoopSubmitter {
+	return &NoopSubmitter{
+		emitLog: emitLog,
+		reason:  reason,
+		log:     log,
+	}
+}
 
-func (s *noopSubmitter) Submit(ctx context.Context) error {
+var _ ResultSubmitter = &NoopSubmitter{}
+
+func (s *NoopSubmitter) Submit(ctx context.Context) error {
 	if s.emitLog {
 		msg := "Results are not being sent for submission."
 		if s.reason != "" {
@@ -198,3 +208,30 @@ func (s *noopSubmitter) Submit(ctx context.Context) error {
 
 	return nil
 }
+
+func (s *NoopSubmitter) SetEmitLog(emitLog bool) {
+	s.emitLog = emitLog
+}
+
+func (s *NoopSubmitter) SetReason(reason string) {
+	s.reason = reason
+}
+
+func BuildConnectURL(projectID string) string {
+	connectURL := fmt.Sprintf("https://connect.redhat.com/projects/%s", projectID)
+
+	pyxisEnv := viper.GetString("pyxis_env")
+	if len(pyxisEnv) > 0 && pyxisEnv != "prod" {
+		connectURL = fmt.Sprintf("https://connect.%s.redhat.com/projects/%s", viper.GetString("pyxis_env"), projectID)
+	}
+
+	return connectURL
+}
+
+func BuildOverviewURL(projectID string) string {
+	return fmt.Sprintf("%s/overview", BuildConnectURL(projectID))
+}
+
+func BuildScanResultsURL(projectID string, imageID string) string {
+	return fmt.Sprintf("%s/images/%s/scan-results", BuildConnectURL(projectID), imageID)
+}


Test patch:
diff --git a/cmd/check_container_test.go b/cmd/check_container_test.go
index b35d556..6d7dbfe 100644
--- a/cmd/check_container_test.go
+++ b/cmd/check_container_test.go
@@ -3,25 +3,16 @@ package cmd
 import (
 	"bytes"
 	"context"
-	"encoding/json"
 	"os"
-	"path"
 	"path/filepath"
-	"strings"
-
-	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification"
-	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/artifacts"
-	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/engine"
-	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/formatters"
-	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/policy"
-	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/pyxis"
-	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/runtime"
 
 	. "github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/gomega"
-	"github.com/sirupsen/logrus"
-	"github.com/spf13/afero"
 	"github.com/spf13/viper"
+
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/formatters"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/runtime"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/internal/lib"
 )
 
 var _ = Describe("Check Container Command", func() {
@@ -36,432 +27,6 @@ var _ = Describe("Check Container Command", func() {
 		})
 	})
 
-	Context("When determining container policy exceptions", func() {
-		var fakePC *fakePyxisClient
-		BeforeEach(func() {
-			// reset the fake pyxis client before each execution
-			// as a precaution.
-			fakePC = &fakePyxisClient{
-				findImagesByDigestFunc: fidbFuncNoop,
-				getProjectsFunc:        gpFuncNoop,
-				submitResultsFunc:      srFuncNoop,
-			}
-		})
-
-		It("should throw an error if unable to get the project from the API", func() {
-			fakePC.getProjectsFunc = gpFuncReturnError
-			_, err := getContainerPolicyExceptions(context.TODO(), fakePC)
-			Expect(err).To(HaveOccurred())
-		})
-
-		It("should return a scratch policy exception if the project has the flag in the API", func() {
-			fakePC.getProjectsFunc = gpFuncReturnScratchException
-			p, err := getContainerPolicyExceptions(context.TODO(), fakePC)
-			Expect(p).To(Equal(policy.PolicyScratch))
-			Expect(err).ToNot(HaveOccurred())
-		})
-
-		It("should return a root policy exception if the project has the flag in the API", func() {
-			fakePC.getProjectsFunc = gpFuncReturnRootException
-			p, err := getContainerPolicyExceptions(context.TODO(), fakePC)
-			Expect(p).To(Equal(policy.PolicyRoot))
-			Expect(err).ToNot(HaveOccurred())
-		})
-
-		It("should return a container policy exception if the project no exceptions in the API", func() {
-			fakePC.getProjectsFunc = gpFuncReturnNoException
-			p, err := getContainerPolicyExceptions(context.TODO(), fakePC)
-			Expect(p).To(Equal(policy.PolicyContainer))
-			Expect(err).ToNot(HaveOccurred())
-		})
-	})
-
-	Context("When using the containerCertificationSubmitter", func() {
-		var sbmt *containerCertificationSubmitter
-		var fakePC *fakePyxisClient
-		var dockerConfigPath string
-		var preflightLogPath string
-
-		preflightLogFilename := "preflight.log"
-		dockerconfigFilename := "dockerconfig.json"
-		BeforeEach(func() {
-			dockerConfigPath = path.Join(artifacts.Path(), dockerconfigFilename)
-			preflightLogPath = path.Join(artifacts.Path(), preflightLogFilename)
-			// Normalize a fakePyxisClient with noop functions.
-			fakePC = &fakePyxisClient{
-				findImagesByDigestFunc: fidbFuncNoop,
-				getProjectsFunc:        gpFuncNoop,
-				submitResultsFunc:      srFuncNoop,
-			}
-
-			// Most tests will need a passing getProjects func so set that to
-			// avoid having to perform multiple BeforeEaches
-			fakePC.setGPFuncReturnBaseProject("")
-
-			// configure the submitter
-			sbmt = &containerCertificationSubmitter{
-				certificationProjectID: fakePC.baseProject("").ID,
-				pyxis:                  fakePC,
-				dockerConfig:           dockerConfigPath,
-				preflightLogFile:       preflightLogPath,
-			}
-
-			certImageJSONBytes, err := json.Marshal(pyxis.CertImage{
-				ID: "111111111111",
-			})
-			Expect(err).ToNot(HaveOccurred())
-
-			preflightTestResultsJSONBytes, err := json.Marshal(runtime.Results{
-				TestedImage:   "foo",
-				PassedOverall: true,
-			})
-			Expect(err).ToNot(HaveOccurred())
-
-			rpmManifestJSONBytes, err := json.Marshal(pyxis.RPMManifest{
-				ID:      "foo",
-				ImageID: "foo",
-			})
-			Expect(err).ToNot(HaveOccurred())
-
-			// Create expected files. Use of Gomega's Expect here (without a subsequent test) is intentional.
-			// Expect automatically checks that additional return values are nil, and thus will fail if they
-			// are not.
-			Expect(artifacts.WriteFile(dockerconfigFilename, strings.NewReader("dockerconfig")))
-			Expect(artifacts.WriteFile(preflightLogFilename, strings.NewReader("preflight log")))
-			Expect(artifacts.WriteFile(certification.DefaultCertImageFilename, bytes.NewReader(certImageJSONBytes)))
-			Expect(artifacts.WriteFile(certification.DefaultTestResultsFilename, bytes.NewReader(preflightTestResultsJSONBytes)))
-			Expect(artifacts.WriteFile(certification.DefaultRPMManifestFilename, bytes.NewReader(rpmManifestJSONBytes)))
-		})
-
-		Context("and project cannot be obtained from the API", func() {
-			BeforeEach(func() {
-				fakePC.getProjectsFunc = gpFuncReturnError
-			})
-			It("should throw an error", func() {
-				err := sbmt.Submit(context.TODO())
-				Expect(err).To(HaveOccurred())
-			})
-		})
-
-		Context("and the provided docker config cannot be read from disk", func() {
-			It("should throw an error", func() {
-				err := os.Remove(dockerConfigPath)
-				Expect(err).ToNot(HaveOccurred())
-
-				err = sbmt.Submit(context.TODO())
-				Expect(err).To(HaveOccurred())
-				Expect(err.Error()).To(ContainSubstring(dockerconfigFilename))
-			})
-		})
-
-		Context("and no docker config command argument was provided", func() {
-			BeforeEach(func() {
-				fakePC.setSRFuncSubmitSuccessfully("", "")
-			})
-			It("should not throw an error", func() {
-				sbmt.dockerConfig = ""
-				err := os.Remove(dockerConfigPath)
-				Expect(err).ToNot(HaveOccurred())
-
-				err = sbmt.Submit(context.TODO())
-				Expect(err).ToNot(HaveOccurred())
-			})
-		})
-
-		Context("and the cert image cannot be read from disk", func() {
-			It("should throw an error", func() {
-				err := os.Remove(path.Join(artifacts.Path(), certification.DefaultCertImageFilename))
-				Expect(err).ToNot(HaveOccurred())
-
-				err = sbmt.Submit(context.TODO())
-				Expect(err).To(HaveOccurred())
-				Expect(err.Error()).To(ContainSubstring(certification.DefaultCertImageFilename))
-			})
-		})
-
-		Context("and the preflight results cannot be read from disk", func() {
-			It("should throw an error", func() {
-				err := os.Remove(path.Join(artifacts.Path(), certification.DefaultTestResultsFilename))
-				Expect(err).ToNot(HaveOccurred())
-
-				err = sbmt.Submit(context.TODO())
-				Expect(err).To(HaveOccurred())
-				Expect(err.Error()).To(ContainSubstring(certification.DefaultTestResultsFilename))
-			})
-		})
-
-		Context("and the rpmManifest cannot be read from disk", func() {
-			It("should throw an error", func() {
-				err := os.Remove(path.Join(artifacts.Path(), certification.DefaultRPMManifestFilename))
-				Expect(err).ToNot(HaveOccurred())
-
-				err = sbmt.Submit(context.TODO())
-				Expect(err).To(HaveOccurred())
-				Expect(err.Error()).To(ContainSubstring(certification.DefaultRPMManifestFilename))
-			})
-		})
-
-		Context("and the preflight logfile cannot be read from disk", func() {
-			It("should throw an error", func() {
-				err := os.Remove(preflightLogPath)
-				Expect(err).ToNot(HaveOccurred())
-
-				err = sbmt.Submit(context.TODO())
-				Expect(err).To(HaveOccurred())
-				Expect(err.Error()).To(ContainSubstring(preflightLogFilename))
-			})
-		})
-
-		Context("and the submission fails", func() {
-			BeforeEach(func() {
-				fakePC.submitResultsFunc = srFuncReturnError
-			})
-
-			It("should throw an error", func() {
-				err := sbmt.Submit(context.TODO())
-				Expect(err).To(HaveOccurred())
-			})
-		})
-
-		Context("and the certproject returned from pyxis is nil, but no error was returned", func() {
-			BeforeEach(func() {
-				fakePC.getProjectsFunc = gpFuncNoop
-			})
-
-			It("should throw an error", func() {
-				err := sbmt.Submit(context.TODO())
-				Expect(err).To(HaveOccurred())
-			})
-		})
-
-		Context("and one of the submission artifacts is malformed", func() {
-			JustBeforeEach(func() {
-				afs := afero.NewBasePathFs(afero.NewOsFs(), artifacts.Path())
-				Expect(afs.Remove(certification.DefaultRPMManifestFilename)).To(Succeed())
-				Expect(artifacts.WriteFile(certification.DefaultRPMManifestFilename, strings.NewReader("malformed"))).To(ContainSubstring(certification.DefaultRPMManifestFilename))
-			})
-
-			It("should throw an error finalizing the submission", func() {
-				err := sbmt.Submit(context.TODO())
-				Expect(err).To(HaveOccurred())
-				Expect(err.Error()).To(ContainSubstring("unable to finalize data"))
-			})
-		})
-
-		Context("and the submission succeeds", func() {
-			BeforeEach(func() {
-				fakePC.setSRFuncSubmitSuccessfully("", "")
-			})
-			It("should not throw an error", func() {
-				err := sbmt.Submit(context.TODO())
-				Expect(err).ToNot(HaveOccurred())
-			})
-		})
-	})
-
-	Context("When using the noop submitter", func() {
-		var bf *bytes.Buffer
-		var noop *noopSubmitter
-
-		BeforeEach(func() {
-			bufferLogger := logrus.New()
-			bf = bytes.NewBuffer([]byte{})
-			bufferLogger.SetOutput(bf)
-
-			noop = &noopSubmitter{log: bufferLogger}
-		})
-
-		Context("and enabling log emitting", func() {
-			BeforeEach(func() {
-				noop.emitLog = true
-			})
-
-			It("should include the reason in the emitted log if specified", func() {
-				testReason := "test reason"
-				noop.reason = testReason
-				err := noop.Submit(context.TODO())
-				Expect(err).ToNot(HaveOccurred())
-				Expect(bf.String()).To(ContainSubstring(testReason))
-			})
-
-			It("should emit logs when calling submit", func() {
-				err := noop.Submit(context.TODO())
-				Expect(err).ToNot(HaveOccurred())
-				Expect(bf.String()).To(ContainSubstring("Results are not being sent for submission."))
-			})
-		})
-
-		Context("and disabling log emitting", func() {
-			It("should not emit logs when calling submit", func() {
-				noop.emitLog = false
-				err := noop.Submit(context.TODO())
-				Expect(err).ToNot(HaveOccurred())
-				Expect(bf.String()).To(BeEmpty())
-			})
-		})
-	})
-
-	Context("When resolving the submitter", func() {
-		Context("with a valid pyxis client", func() {
-			cfg := runtime.Config{
-				CertificationProjectID: "projectid",
-				PyxisHost:              "host",
-				PyxisAPIToken:          "apitoken",
-				DockerConfig:           "dockercfg",
-				LogFile:                "logfile",
-			}
-
-			pc := newPyxisClient(context.TODO(), cfg.ReadOnly())
-			Expect(pc).ToNot(BeNil())
-
-			It("should return a containerCertificationSubmitter", func() {
-				submitter := resolveSubmitter(pc, cfg.ReadOnly())
-				typed, ok := submitter.(*containerCertificationSubmitter)
-				Expect(typed).ToNot(BeNil())
-				Expect(ok).To(BeTrue())
-			})
-		})
-
-		Context("With no pyxis client", func() {
-			cfg := runtime.Config{}
-			It("should return a no-op submitter", func() {
-				submitter := resolveSubmitter(nil, cfg.ReadOnly())
-				typed, ok := submitter.(*noopSubmitter)
-				Expect(typed).ToNot(BeNil())
-				Expect(ok).To(BeTrue())
-			})
-		})
-	})
-
-	Context("When establishing a pyxis client.", func() {
-		Context("with none of the required values", func() {
-			cfgNoCertProjectID := runtime.Config{}
-
-			It("Should return a nil pyxis client", func() {
-				pc := newPyxisClient(context.TODO(), cfgNoCertProjectID.ReadOnly())
-				Expect(pc).To(BeNil())
-			})
-		})
-
-		Context("Missing any of the required values", func() {
-			cfgMissingCertProjectID := runtime.Config{
-				PyxisHost:     "foo",
-				PyxisAPIToken: "bar",
-			}
-
-			cfgMissingPyxisHost := runtime.Config{
-				CertificationProjectID: "foo",
-				PyxisAPIToken:          "bar",
-			}
-
-			cfgMissingPyxisAPIToken := runtime.Config{
-				CertificationProjectID: "foo",
-				PyxisHost:              "bar",
-			}
-
-			It("Should return a nil pyxis client", func() {
-				pc := newPyxisClient(context.TODO(), cfgMissingCertProjectID.ReadOnly())
-				Expect(pc).To(BeNil())
-
-				pc = newPyxisClient(context.TODO(), cfgMissingPyxisHost.ReadOnly())
-				Expect(pc).To(BeNil())
-
-				pc = newPyxisClient(context.TODO(), cfgMissingPyxisAPIToken.ReadOnly())
-				Expect(pc).To(BeNil())
-			})
-		})
-
-		Context("With all the required values", func() {
-			cfgValid := runtime.Config{
-				CertificationProjectID: "foo",
-				PyxisHost:              "bar",
-				PyxisAPIToken:          "baz",
-			}
-
-			It("should return a pyxis client", func() {
-				pc := newPyxisClient(context.TODO(), cfgValid.ReadOnly())
-				Expect(pc).ToNot(BeNil())
-			})
-		})
-	})
-
-	Context("When instantiating a checkContainerRunner", func() {
-		var cfg *runtime.Config
-
-		BeforeEach(func() {
-			cfg = &runtime.Config{
-				Image:          "quay.io/example/foo:latest",
-				ResponseFormat: formatters.DefaultFormat,
-			}
-		})
-
-		Context("and the user passed the submit flag, but no credentials", func() {
-			It("should return a noop submitter as credentials are required for submission", func() {
-				runner, err := newCheckContainerRunner(context.TODO(), cfg)
-				Expect(err).ToNot(HaveOccurred())
-				_, rsIsCorrectType := runner.rs.(*noopSubmitter)
-				Expect(rsIsCorrectType).To(BeTrue())
-			})
-		})
-
-		Context("and the user did not pass the submit flag", func() {
-			var origSubmitValue bool
-			BeforeEach(func() {
-				origSubmitValue = submit
-				submit = false
-			})
-
-			AfterEach(func() {
-				submit = origSubmitValue
-			})
-			It("should return a noopSubmitter resultSubmitter", func() {
-				runner, err := newCheckContainerRunner(context.TODO(), cfg)
-				Expect(err).ToNot(HaveOccurred())
-				_, rsIsCorrectType := runner.rs.(*noopSubmitter)
-				Expect(rsIsCorrectType).To(BeTrue())
-			})
-		})
-
-		Context("with a valid policy formatter", func() {
-			It("should return with no error, and the appropriate formatter", func() {
-				cfg.ResponseFormat = "xml"
-				runner, err := newCheckContainerRunner(context.TODO(), cfg)
-				Expect(err).ToNot(HaveOccurred())
-				expectedFormatter, err := formatters.NewByName(cfg.ResponseFormat)
-				Expect(err).ToNot(HaveOccurred())
-				Expect(runner.formatter.PrettyName()).To(Equal(expectedFormatter.PrettyName()))
-			})
-		})
-
-		Context("with an invalid policy definition", func() {
-			It("should return the container policy engine anyway", func() {
-				runner, err := newCheckContainerRunner(context.TODO(), cfg)
-				Expect(err).ToNot(HaveOccurred())
-
-				expectedEngine, err := engine.NewForConfig(context.TODO(), cfg.ReadOnly())
-				Expect(runner.eng).To(BeEquivalentTo(expectedEngine))
-				Expect(err).ToNot(HaveOccurred())
-			})
-		})
-		// NOTE(): There's no way to test policy exceptions here because
-		// without valid credentials to pyxis.
-
-		Context("with an invalid formatter definition", func() {
-			It("should return an error", func() {
-				cfg.ResponseFormat = "foo"
-				_, err := newCheckContainerRunner(context.TODO(), cfg)
-				Expect(err).To(HaveOccurred())
-			})
-		})
-
-		It("should contain a ResultWriterFile resultWriter", func() {
-			runner, err := newCheckContainerRunner(context.TODO(), cfg)
-			Expect(err).ToNot(HaveOccurred())
-			_, rwIsExpectedType := runner.rw.(*runtime.ResultWriterFile)
-			Expect(rwIsExpectedType).To(BeTrue())
-		})
-	})
-
 	Context("When validating check container arguments and flags", func() {
 		Context("and the user provided more than 1 positional arg", func() {
 			It("should fail to run", func() {
@@ -574,4 +139,31 @@ certification_project_id: mycertid`
 			})
 		})
 	})
+
+	Context("When instantiating a checkContainerRunner", func() {
+		var cfg *runtime.Config
+
+		Context("and the user did not pass the submit flag", func() {
+			var origSubmitValue bool
+			BeforeEach(func() {
+				origSubmitValue = submit
+				submit = false
+
+				cfg = &runtime.Config{
+					Image:          "quay.io/example/foo:latest",
+					ResponseFormat: formatters.DefaultFormat,
+				}
+			})
+
+			AfterEach(func() {
+				submit = origSubmitValue
+			})
+			It("should return a noopSubmitter ResultSubmitter", func() {
+				runner, err := lib.NewCheckContainerRunner(context.TODO(), cfg, false)
+				Expect(err).ToNot(HaveOccurred())
+				_, rsIsCorrectType := runner.Rs.(*lib.NoopSubmitter)
+				Expect(rsIsCorrectType).To(BeTrue())
+			})
+		})
+	})
 })
diff --git a/cmd/check_operator_test.go b/cmd/check_operator_test.go
index a4844d7..2e2a2f1 100644
--- a/cmd/check_operator_test.go
+++ b/cmd/check_operator_test.go
@@ -1,14 +1,8 @@
 package cmd
 
 import (
-	"context"
 	"os"
 
-	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/engine"
-	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/formatters"
-	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/policy"
-	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/runtime"
-
 	. "github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/gomega"
 	"github.com/spf13/viper"
@@ -116,64 +110,6 @@ var _ = Describe("Check Operator", func() {
 		})
 	})
 
-	Context("When instantiating a checkOperatorRunner", func() {
-		var cfg *runtime.Config
-		BeforeEach(func() {
-			cfg = &runtime.Config{
-				Image:          "quay.io/example/foo:latest",
-				ResponseFormat: formatters.DefaultFormat,
-			}
-		})
-
-		Context("with a valid policy formatter", func() {
-			It("should return with no error, and the appropriate formatter", func() {
-				cfg.ResponseFormat = "xml"
-				runner, err := newCheckOperatorRunner(context.TODO(), cfg)
-				Expect(err).ToNot(HaveOccurred())
-				expectedFormatter, err := formatters.NewByName(cfg.ResponseFormat)
-				Expect(err).ToNot(HaveOccurred())
-				Expect(runner.formatter.PrettyName()).To(Equal(expectedFormatter.PrettyName()))
-			})
-		})
-
-		Context("with an invalid policy formatter", func() {
-			It("should return an error", func() {
-				cfg.ResponseFormat = "foo"
-				_, err := newCheckOperatorRunner(context.TODO(), cfg)
-				Expect(err).To(HaveOccurred())
-			})
-		})
-
-		Context("with an invalid policy definition", func() {
-			It("should return the container policy engine anyway", func() {
-				cfg.Policy = "badpolicy"
-				beforeCfg := *cfg
-				runner, err := newCheckOperatorRunner(context.TODO(), cfg)
-				Expect(err).ToNot(HaveOccurred())
-
-				_, err = engine.NewForConfig(context.TODO(), cfg.ReadOnly())
-				Expect(runner.cfg.Policy).ToNot(Equal(beforeCfg.Policy))
-				Expect(runner.cfg.Policy).To(Equal(policy.PolicyOperator))
-				Expect(err).ToNot(HaveOccurred())
-			})
-		})
-
-		Context("with an invalid formatter definition", func() {
-			It("should return an error", func() {
-				cfg.ResponseFormat = "foo"
-				_, err := newCheckOperatorRunner(context.TODO(), cfg)
-				Expect(err).To(HaveOccurred())
-			})
-		})
-
-		It("should contain a ResultWriterFile resultWriter", func() {
-			runner, err := newCheckOperatorRunner(context.TODO(), cfg)
-			Expect(err).ToNot(HaveOccurred())
-			_, rwIsExpectedType := runner.rw.(*runtime.ResultWriterFile)
-			Expect(rwIsExpectedType).To(BeTrue())
-		})
-	})
-
 	Context("When testing positional arg parsing", func() {
 		// failure cases are tested earlier in this file by running executeCommand.
 		// This tests the success case using the standalone function in order
diff --git a/cmd/check_test.go b/cmd/check_test.go
index 3422ff0..8267190 100644
--- a/cmd/check_test.go
+++ b/cmd/check_test.go
@@ -1,12 +1,10 @@
 package cmd
 
 import (
-	"context"
 	"os"
-	"path/filepath"
 
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/artifacts"
-	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/runtime"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/internal/lib"
 
 	. "github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/gomega"
@@ -46,7 +44,7 @@ var _ = Describe("cmd package check command", func() {
 		Context("Regular Connect URL", func() {
 			It("should return a URL with just a project ID", func() {
 				expected := "https://connect.redhat.com/projects/this-is-my-project-id"
-				actual := buildConnectURL(projectID)
+				actual := lib.BuildConnectURL(projectID)
 				Expect(expected).To(Equal(actual))
 			})
 		})
@@ -56,7 +54,7 @@ var _ = Describe("cmd package check command", func() {
 			})
 			It("should return a URL for QA", func() {
 				expected := "https://connect.qa.redhat.com/projects/this-is-my-project-id"
-				actual := buildConnectURL(projectID)
+				actual := lib.BuildConnectURL(projectID)
 				Expect(expected).To(Equal(actual))
 			})
 		})
@@ -66,7 +64,7 @@ var _ = Describe("cmd package check command", func() {
 			})
 			It("should return a URL for UAT", func() {
 				expected := "https://connect.uat.redhat.com/projects/this-is-my-project-id/images/my-image-id/scan-results"
-				actual := buildScanResultsURL(projectID, imageID)
+				actual := lib.BuildScanResultsURL(projectID, imageID)
 				Expect(expected).To(Equal(actual))
 			})
 		})
@@ -76,7 +74,7 @@ var _ = Describe("cmd package check command", func() {
 			})
 			It("should return a URL for QA", func() {
 				expected := "https://connect.qa.redhat.com/projects/this-is-my-project-id/overview"
-				actual := buildOverviewURL(projectID)
+				actual := lib.BuildOverviewURL(projectID)
 				Expect(expected).To(Equal(actual))
 			})
 		})
@@ -86,40 +84,14 @@ var _ = Describe("cmd package check command", func() {
 			})
 			It("should return a Prod overview URL", func() {
 				expected := "https://connect.redhat.com/projects/this-is-my-project-id/overview"
-				actual := buildOverviewURL(projectID)
+				actual := lib.BuildOverviewURL(projectID)
 				Expect(expected).To(Equal(actual))
 			})
 			It("should return a Prod scan URL", func() {
 				expected := "https://connect.redhat.com/projects/this-is-my-project-id/images/my-image-id/scan-results"
-				actual := buildScanResultsURL(projectID, imageID)
+				actual := lib.BuildScanResultsURL(projectID, imageID)
 				Expect(expected).To(Equal(actual))
 			})
 		})
 	})
-
-	Describe("JUnit", func() {
-		var results *runtime.Results
-		var junitfile string
-
-		BeforeEach(func() {
-			results = &runtime.Results{
-				TestedImage:       "registry.example.com/example/image:0.0.1",
-				PassedOverall:     true,
-				TestedOn:          runtime.UnknownOpenshiftClusterVersion(),
-				CertificationHash: "sha256:deadb33f",
-				Passed:            []runtime.Result{},
-				Failed:            []runtime.Result{},
-				Errors:            []runtime.Result{},
-			}
-			junitfile = filepath.Join(artifacts.Path(), "results-junit.xml")
-		})
-
-		When("The additional JUnitXML results file is requested", func() {
-			It("should be written to the artifacts directory without error", func() {
-				Expect(writeJUnit(context.TODO(), *results)).To(Succeed())
-				_, err := os.Stat(junitfile)
-				Expect(err).ToNot(HaveOccurred())
-			})
-		})
-	})
 })
diff --git a/cmd/fakes_test.go b/internal/lib/fakes_test.go
similarity index 85%
rename from cmd/fakes_test.go
rename to internal/lib/fakes_test.go
index af36864..0b9b24d 100644
--- a/cmd/fakes_test.go
+++ b/internal/lib/fakes_test.go
@@ -1,4 +1,4 @@
-package cmd
+package lib
 
 import (
 	"context"
@@ -19,9 +19,17 @@ type (
 	srFunc   func(context.Context, *pyxis.CertificationInput) (*pyxis.CertificationResults, error)
 )
 
-// fakePyxisClient is a configurable pyxisClient for use in testing. It accepts function definitions to
+func NewFakePyxisClientNoop() *FakePyxisClient {
+	return &FakePyxisClient{
+		findImagesByDigestFunc: fidbFuncNoop,
+		getProjectsFunc:        gpFuncNoop,
+		submitResultsFunc:      srFuncNoop,
+	}
+}
+
+// FakePyxisClient is a configurable pyxisClient for use in testing. It accepts function definitions to
 // use to implement a cmd.pyxisClient.
-type fakePyxisClient struct {
+type FakePyxisClient struct {
 	findImagesByDigestFunc fibdFunc
 	getProjectsFunc        gpFunc
 	submitResultsFunc      srFunc
@@ -29,7 +37,7 @@ type fakePyxisClient struct {
 
 // baseProject returns a pyxis.CertProject with an id of projectID, or a base value
 // if none is provided.
-func (pc *fakePyxisClient) baseProject(projectID string) pyxis.CertProject {
+func (pc *FakePyxisClient) baseProject(projectID string) pyxis.CertProject {
 	pid := "000000000000"
 	if len(projectID) > 0 {
 		pid = projectID
@@ -44,7 +52,7 @@ func (pc *fakePyxisClient) baseProject(projectID string) pyxis.CertProject {
 
 // successfulCertResults returns a pyxis.CertificationResults for use in tests emulating successful
 // submission.
-func (pc *fakePyxisClient) successfulCertResults(projectID, certImageID string) pyxis.CertificationResults {
+func (pc *FakePyxisClient) successfulCertResults(projectID, certImageID string) pyxis.CertificationResults {
 	pid := "000000000000"
 	if len(projectID) > 0 {
 		pid = projectID
@@ -65,14 +73,14 @@ func (pc *fakePyxisClient) successfulCertResults(projectID, certImageID string)
 }
 
 // setGPFuncReturnBaseProject sets pc.getProjectFunc to a function that returns baseProject.
-// This is a fakePyxisClient method because it enables standardizing on a single value of
-// a CertificationProject for GetProject calls, tied to the instance of fakePyxisClient
-func (pc *fakePyxisClient) setGPFuncReturnBaseProject(projectID string) {
+// This is a FakePyxisClient method because it enables standardizing on a single value of
+// a CertificationProject for GetProject calls, tied to the instance of FakePyxisClient
+func (pc *FakePyxisClient) setGPFuncReturnBaseProject(projectID string) {
 	baseproj := pc.baseProject(projectID)
 	pc.getProjectsFunc = func(context.Context) (*pyxis.CertProject, error) { return &baseproj, nil }
 }
 
-func (pc *fakePyxisClient) setSRFuncSubmitSuccessfully(projectID, certImageID string) {
+func (pc *FakePyxisClient) setSRFuncSubmitSuccessfully(projectID, certImageID string) {
 	baseproj := pc.baseProject(projectID)
 	certresults := pc.successfulCertResults(baseproj.ID, certImageID)
 	pc.submitResultsFunc = func(context.Context, *pyxis.CertificationInput) (*pyxis.CertificationResults, error) {
@@ -80,15 +88,15 @@ func (pc *fakePyxisClient) setSRFuncSubmitSuccessfully(projectID, certImageID st
 	}
 }
 
-func (pc *fakePyxisClient) FindImagesByDigest(ctx context.Context, digests []string) ([]pyxis.CertImage, error) {
+func (pc *FakePyxisClient) FindImagesByDigest(ctx context.Context, digests []string) ([]pyxis.CertImage, error) {
 	return pc.findImagesByDigestFunc(ctx, digests)
 }
 
-func (pc *fakePyxisClient) GetProject(ctx context.Context) (*pyxis.CertProject, error) {
+func (pc *FakePyxisClient) GetProject(ctx context.Context) (*pyxis.CertProject, error) {
 	return pc.getProjectsFunc(ctx)
 }
 
-func (pc *fakePyxisClient) SubmitResults(ctx context.Context, ci *pyxis.CertificationInput) (*pyxis.CertificationResults, error) {
+func (pc *FakePyxisClient) SubmitResults(ctx context.Context, ci *pyxis.CertificationInput) (*pyxis.CertificationResults, error) {
 	return pc.submitResultsFunc(ctx, ci)
 }
 
@@ -131,17 +139,17 @@ func srFuncReturnError(ctx context.Context, ci *pyxis.CertificationInput) (*pyxi
 	return nil, errors.New("some submission error")
 }
 
-// fidbFuncNoop implements a fidbFunc, best to use while instantiating fakePyxisClient.
+// fidbFuncNoop implements a fidbFunc, best to use while instantiating FakePyxisClient.
 func fidbFuncNoop(ctx context.Context, digests []string) ([]pyxis.CertImage, error) {
 	return nil, nil
 }
 
-// gpFuncNoop implements a gpFunc, best to use while instantiating fakePyxisClient.
+// gpFuncNoop implements a gpFunc, best to use while instantiating FakePyxisClient.
 func gpFuncNoop(ctx context.Context) (*pyxis.CertProject, error) {
 	return nil, nil
 }
 
-// srFuncNoop implements a srFuncNoop, best to use while instantiating fakePyxisClient.
+// srFuncNoop implements a srFuncNoop, best to use while instantiating FakePyxisClient.
 func srFuncNoop(ctx context.Context, ci *pyxis.CertificationInput) (*pyxis.CertificationResults, error) {
 	return nil, nil
 }
@@ -190,7 +198,7 @@ func (e fakeCheckEngine) Results(ctx context.Context) runtime.Results {
 	}
 }
 
-// badResultWriter implements resultWriter and will automatically fail with the
+// badResultWriter implements ResultWriter and will automatically fail with the
 // provided errmsg.
 type badResultWriter struct {
 	errmsg string
@@ -225,7 +233,7 @@ func (f *badFormatter) Format(ctx context.Context, r runtime.Results) ([]byte, e
 	return nil, errors.New(f.errormsg)
 }
 
-// badResultSubmitter implements resultSubmitter and fails to submit with the included errmsg.
+// badResultSubmitter implements ResultSubmitter and fails to submit with the included errmsg.
 type badResultSubmitter struct {
 	errmsg string
 }
diff --git a/internal/lib/lib_container_test.go b/internal/lib/lib_container_test.go
new file mode 100644
index 0000000..e46c4ff
--- /dev/null
+++ b/internal/lib/lib_container_test.go
@@ -0,0 +1,458 @@
+package lib
+
+import (
+	"bytes"
+	"context"
+	"encoding/json"
+	"os"
+	"path"
+	"path/filepath"
+	"strings"
+
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/artifacts"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/engine"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/formatters"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/policy"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/pyxis"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/runtime"
+
+	. "github.com/onsi/ginkgo/v2"
+	. "github.com/onsi/gomega"
+	"github.com/sirupsen/logrus"
+	"github.com/spf13/afero"
+)
+
+var _ = Describe("Lib Container Functions", func() {
+	BeforeEach(createAndCleanupDirForArtifactsAndLogs)
+
+	Context("When determining container policy exceptions", func() {
+		var fakePC *FakePyxisClient
+		BeforeEach(func() {
+			// reset the fake pyxis client before each execution
+			// as a precaution.
+			fakePC = &FakePyxisClient{
+				findImagesByDigestFunc: fidbFuncNoop,
+				getProjectsFunc:        gpFuncNoop,
+				submitResultsFunc:      srFuncNoop,
+			}
+		})
+
+		It("should throw an error if unable to get the project from the API", func() {
+			fakePC.getProjectsFunc = gpFuncReturnError
+			_, err := GetContainerPolicyExceptions(context.TODO(), fakePC)
+			Expect(err).To(HaveOccurred())
+		})
+
+		It("should return a scratch policy exception if the project has the flag in the API", func() {
+			fakePC.getProjectsFunc = gpFuncReturnScratchException
+			p, err := GetContainerPolicyExceptions(context.TODO(), fakePC)
+			Expect(p).To(Equal(policy.PolicyScratch))
+			Expect(err).ToNot(HaveOccurred())
+		})
+
+		It("should return a root policy exception if the project has the flag in the API", func() {
+			fakePC.getProjectsFunc = gpFuncReturnRootException
+			p, err := GetContainerPolicyExceptions(context.TODO(), fakePC)
+			Expect(p).To(Equal(policy.PolicyRoot))
+			Expect(err).ToNot(HaveOccurred())
+		})
+
+		It("should return a container policy exception if the project no exceptions in the API", func() {
+			fakePC.getProjectsFunc = gpFuncReturnNoException
+			p, err := GetContainerPolicyExceptions(context.TODO(), fakePC)
+			Expect(p).To(Equal(policy.PolicyContainer))
+			Expect(err).ToNot(HaveOccurred())
+		})
+	})
+
+	Context("When using the containerCertificationSubmitter", func() {
+		var sbmt *ContainerCertificationSubmitter
+		var fakePC *FakePyxisClient
+		var dockerConfigPath string
+		var preflightLogPath string
+
+		preflightLogFilename := "preflight.log"
+		dockerconfigFilename := "dockerconfig.json"
+		BeforeEach(func() {
+			dockerConfigPath = path.Join(artifacts.Path(), dockerconfigFilename)
+			preflightLogPath = path.Join(artifacts.Path(), preflightLogFilename)
+			// Normalize a FakePyxisClient with noop functions.
+			fakePC = NewFakePyxisClientNoop()
+
+			// Most tests will need a passing getProjects func so set that to
+			// avoid having to perform multiple BeforeEaches
+			fakePC.setGPFuncReturnBaseProject("")
+
+			// configure the submitter
+			sbmt = &ContainerCertificationSubmitter{
+				CertificationProjectID: fakePC.baseProject("").ID,
+				Pyxis:                  fakePC,
+				DockerConfig:           dockerConfigPath,
+				PreflightLogFile:       preflightLogPath,
+			}
+
+			certImageJSONBytes, err := json.Marshal(pyxis.CertImage{
+				ID: "111111111111",
+			})
+			Expect(err).ToNot(HaveOccurred())
+
+			preflightTestResultsJSONBytes, err := json.Marshal(runtime.Results{
+				TestedImage:   "foo",
+				PassedOverall: true,
+			})
+			Expect(err).ToNot(HaveOccurred())
+
+			rpmManifestJSONBytes, err := json.Marshal(pyxis.RPMManifest{
+				ID:      "foo",
+				ImageID: "foo",
+			})
+			Expect(err).ToNot(HaveOccurred())
+
+			// Create expected files. Use of Gomega's Expect here (without a subsequent test) is intentional.
+			// Expect automatically checks that additional return values are nil, and thus will fail if they
+			// are not.
+			Expect(artifacts.WriteFile(dockerconfigFilename, strings.NewReader("dockerconfig")))
+			Expect(artifacts.WriteFile(preflightLogFilename, strings.NewReader("preflight log")))
+			Expect(artifacts.WriteFile(certification.DefaultCertImageFilename, bytes.NewReader(certImageJSONBytes)))
+			Expect(artifacts.WriteFile(certification.DefaultTestResultsFilename, bytes.NewReader(preflightTestResultsJSONBytes)))
+			Expect(artifacts.WriteFile(certification.DefaultRPMManifestFilename, bytes.NewReader(rpmManifestJSONBytes)))
+		})
+
+		Context("and project cannot be obtained from the API", func() {
+			BeforeEach(func() {
+				fakePC.getProjectsFunc = gpFuncReturnError
+			})
+			It("should throw an error", func() {
+				err := sbmt.Submit(context.TODO())
+				Expect(err).To(HaveOccurred())
+			})
+		})
+
+		Context("and the provided docker config cannot be read from disk", func() {
+			It("should throw an error", func() {
+				err := os.Remove(dockerConfigPath)
+				Expect(err).ToNot(HaveOccurred())
+
+				err = sbmt.Submit(context.TODO())
+				Expect(err).To(HaveOccurred())
+				Expect(err.Error()).To(ContainSubstring(dockerconfigFilename))
+			})
+		})
+
+		Context("and no docker config command argument was provided", func() {
+			BeforeEach(func() {
+				fakePC.setSRFuncSubmitSuccessfully("", "")
+			})
+			It("should not throw an error", func() {
+				sbmt.DockerConfig = ""
+				err := os.Remove(dockerConfigPath)
+				Expect(err).ToNot(HaveOccurred())
+
+				err = sbmt.Submit(context.TODO())
+				Expect(err).ToNot(HaveOccurred())
+			})
+		})
+
+		Context("and the cert image cannot be read from disk", func() {
+			It("should throw an error", func() {
+				err := os.Remove(path.Join(artifacts.Path(), certification.DefaultCertImageFilename))
+				Expect(err).ToNot(HaveOccurred())
+
+				err = sbmt.Submit(context.TODO())
+				Expect(err).To(HaveOccurred())
+				Expect(err.Error()).To(ContainSubstring(certification.DefaultCertImageFilename))
+			})
+		})
+
+		Context("and the preflight results cannot be read from disk", func() {
+			It("should throw an error", func() {
+				err := os.Remove(path.Join(artifacts.Path(), certification.DefaultTestResultsFilename))
+				Expect(err).ToNot(HaveOccurred())
+
+				err = sbmt.Submit(context.TODO())
+				Expect(err).To(HaveOccurred())
+				Expect(err.Error()).To(ContainSubstring(certification.DefaultTestResultsFilename))
+			})
+		})
+
+		Context("and the rpmManifest cannot be read from disk", func() {
+			It("should throw an error", func() {
+				err := os.Remove(path.Join(artifacts.Path(), certification.DefaultRPMManifestFilename))
+				Expect(err).ToNot(HaveOccurred())
+
+				err = sbmt.Submit(context.TODO())
+				Expect(err).To(HaveOccurred())
+				Expect(err.Error()).To(ContainSubstring(certification.DefaultRPMManifestFilename))
+			})
+		})
+
+		Context("and the preflight logfile cannot be read from disk", func() {
+			It("should throw an error", func() {
+				err := os.Remove(preflightLogPath)
+				Expect(err).ToNot(HaveOccurred())
+
+				err = sbmt.Submit(context.TODO())
+				Expect(err).To(HaveOccurred())
+				Expect(err.Error()).To(ContainSubstring(preflightLogFilename))
+			})
+		})
+
+		Context("and the submission fails", func() {
+			BeforeEach(func() {
+				fakePC.submitResultsFunc = srFuncReturnError
+			})
+
+			It("should throw an error", func() {
+				err := sbmt.Submit(context.TODO())
+				Expect(err).To(HaveOccurred())
+			})
+		})
+
+		Context("and the certproject returned from pyxis is nil, but no error was returned", func() {
+			BeforeEach(func() {
+				fakePC.getProjectsFunc = gpFuncNoop
+			})
+
+			It("should throw an error", func() {
+				err := sbmt.Submit(context.TODO())
+				Expect(err).To(HaveOccurred())
+			})
+		})
+
+		Context("and one of the submission artifacts is malformed", func() {
+			JustBeforeEach(func() {
+				afs := afero.NewBasePathFs(afero.NewOsFs(), artifacts.Path())
+				Expect(afs.Remove(certification.DefaultRPMManifestFilename)).To(Succeed())
+				Expect(artifacts.WriteFile(certification.DefaultRPMManifestFilename, strings.NewReader("malformed"))).To(ContainSubstring(certification.DefaultRPMManifestFilename))
+			})
+
+			It("should throw an error finalizing the submission", func() {
+				err := sbmt.Submit(context.TODO())
+				Expect(err).To(HaveOccurred())
+				Expect(err.Error()).To(ContainSubstring("unable to finalize data"))
+			})
+		})
+
+		Context("and the submission succeeds", func() {
+			BeforeEach(func() {
+				fakePC.setSRFuncSubmitSuccessfully("", "")
+			})
+			It("should not throw an error", func() {
+				err := sbmt.Submit(context.TODO())
+				Expect(err).ToNot(HaveOccurred())
+			})
+		})
+	})
+
+	Context("When using the noop submitter", func() {
+		var bf *bytes.Buffer
+		var noop *NoopSubmitter
+
+		BeforeEach(func() {
+			bufferLogger := logrus.New()
+			bf = bytes.NewBuffer([]byte{})
+			bufferLogger.SetOutput(bf)
+
+			noop = NewNoopSubmitter(false, "", bufferLogger)
+		})
+
+		Context("and enabling log emitting", func() {
+			BeforeEach(func() {
+				noop.SetEmitLog(true)
+			})
+
+			It("should include the reason in the emitted log if specified", func() {
+				testReason := "test reason"
+				noop.SetReason(testReason)
+				err := noop.Submit(context.TODO())
+				Expect(err).ToNot(HaveOccurred())
+				Expect(bf.String()).To(ContainSubstring(testReason))
+			})
+
+			It("should emit logs when calling submit", func() {
+				err := noop.Submit(context.TODO())
+				Expect(err).ToNot(HaveOccurred())
+				Expect(bf.String()).To(ContainSubstring("Results are not being sent for submission."))
+			})
+		})
+
+		Context("and disabling log emitting", func() {
+			It("should not emit logs when calling submit", func() {
+				noop.SetEmitLog(false)
+				err := noop.Submit(context.TODO())
+				Expect(err).ToNot(HaveOccurred())
+				Expect(bf.String()).To(BeEmpty())
+			})
+		})
+	})
+
+	Context("When resolving the submitter", func() {
+		Context("with a valid pyxis client", func() {
+			cfg := runtime.Config{
+				CertificationProjectID: "projectid",
+				PyxisHost:              "host",
+				PyxisAPIToken:          "apitoken",
+				DockerConfig:           "dockercfg",
+				LogFile:                "logfile",
+			}
+
+			pc := NewPyxisClient(context.TODO(), cfg.ReadOnly())
+			Expect(pc).ToNot(BeNil())
+
+			It("should return a containerCertificationSubmitter", func() {
+				submitter := ResolveSubmitter(pc, cfg.ReadOnly())
+				typed, ok := submitter.(*ContainerCertificationSubmitter)
+				Expect(typed).ToNot(BeNil())
+				Expect(ok).To(BeTrue())
+			})
+		})
+
+		Context("With no pyxis client", func() {
+			cfg := runtime.Config{}
+			It("should return a no-op submitter", func() {
+				submitter := ResolveSubmitter(nil, cfg.ReadOnly())
+				typed, ok := submitter.(*NoopSubmitter)
+				Expect(typed).ToNot(BeNil())
+				Expect(ok).To(BeTrue())
+			})
+		})
+	})
+
+	Context("When establishing a pyxis client.", func() {
+		Context("with none of the required values", func() {
+			cfgNoCertProjectID := runtime.Config{}
+
+			It("Should return a nil pyxis client", func() {
+				pc := NewPyxisClient(context.TODO(), cfgNoCertProjectID.ReadOnly())
+				Expect(pc).To(BeNil())
+			})
+		})
+
+		Context("Missing any of the required values", func() {
+			cfgMissingCertProjectID := runtime.Config{
+				PyxisHost:     "foo",
+				PyxisAPIToken: "bar",
+			}
+
+			cfgMissingPyxisHost := runtime.Config{
+				CertificationProjectID: "foo",
+				PyxisAPIToken:          "bar",
+			}
+
+			cfgMissingPyxisAPIToken := runtime.Config{
+				CertificationProjectID: "foo",
+				PyxisHost:              "bar",
+			}
+
+			It("Should return a nil pyxis client", func() {
+				pc := NewPyxisClient(context.TODO(), cfgMissingCertProjectID.ReadOnly())
+				Expect(pc).To(BeNil())
+
+				pc = NewPyxisClient(context.TODO(), cfgMissingPyxisHost.ReadOnly())
+				Expect(pc).To(BeNil())
+
+				pc = NewPyxisClient(context.TODO(), cfgMissingPyxisAPIToken.ReadOnly())
+				Expect(pc).To(BeNil())
+			})
+		})
+
+		Context("With all the required values", func() {
+			cfgValid := runtime.Config{
+				CertificationProjectID: "foo",
+				PyxisHost:              "bar",
+				PyxisAPIToken:          "baz",
+			}
+
+			It("should return a pyxis client", func() {
+				pc := NewPyxisClient(context.TODO(), cfgValid.ReadOnly())
+				Expect(pc).ToNot(BeNil())
+			})
+		})
+	})
+
+	Context("When instantiating a checkContainerRunner", func() {
+		var cfg *runtime.Config
+
+		BeforeEach(func() {
+			cfg = &runtime.Config{
+				Image:          "quay.io/example/foo:latest",
+				ResponseFormat: formatters.DefaultFormat,
+			}
+		})
+
+		Context("and the user passed the submit flag, but no credentials", func() {
+			It("should return a noop submitter as credentials are required for submission", func() {
+				runner, err := NewCheckContainerRunner(context.TODO(), cfg, false)
+				Expect(err).ToNot(HaveOccurred())
+				_, rsIsCorrectType := runner.Rs.(*NoopSubmitter)
+				Expect(rsIsCorrectType).To(BeTrue())
+			})
+		})
+
+		Context("with a valid policy formatter", func() {
+			It("should return with no error, and the appropriate formatter", func() {
+				cfg.ResponseFormat = "xml"
+				runner, err := NewCheckContainerRunner(context.TODO(), cfg, false)
+				Expect(err).ToNot(HaveOccurred())
+				expectedFormatter, err := formatters.NewByName(cfg.ResponseFormat)
+				Expect(err).ToNot(HaveOccurred())
+				Expect(runner.Formatter.PrettyName()).To(Equal(expectedFormatter.PrettyName()))
+			})
+		})
+
+		Context("with an invalid policy definition", func() {
+			It("should return the container policy engine anyway", func() {
+				runner, err := NewCheckContainerRunner(context.TODO(), cfg, false)
+				Expect(err).ToNot(HaveOccurred())
+
+				expectedEngine, err := engine.NewForConfig(context.TODO(), cfg.ReadOnly())
+				Expect(runner.Eng).To(BeEquivalentTo(expectedEngine))
+				Expect(err).ToNot(HaveOccurred())
+			})
+		})
+		// NOTE(): There's no way to test policy exceptions here because
+		// without valid credentials to pyxis.
+
+		Context("with an invalid formatter definition", func() {
+			It("should return an error", func() {
+				cfg.ResponseFormat = "foo"
+				_, err := NewCheckContainerRunner(context.TODO(), cfg, false)
+				Expect(err).To(HaveOccurred())
+			})
+		})
+
+		It("should contain a ResultWriterFile ResultWriter", func() {
+			runner, err := NewCheckContainerRunner(context.TODO(), cfg, false)
+			Expect(err).ToNot(HaveOccurred())
+			_, rwIsExpectedType := runner.Rw.(*runtime.ResultWriterFile)
+			Expect(rwIsExpectedType).To(BeTrue())
+		})
+	})
+
+	Describe("JUnit", func() {
+		var results *runtime.Results
+		var junitfile string
+
+		BeforeEach(func() {
+			results = &runtime.Results{
+				TestedImage:       "registry.example.com/example/image:0.0.1",
+				PassedOverall:     true,
+				TestedOn:          runtime.UnknownOpenshiftClusterVersion(),
+				CertificationHash: "sha256:deadb33f",
+				Passed:            []runtime.Result{},
+				Failed:            []runtime.Result{},
+				Errors:            []runtime.Result{},
+			}
+			junitfile = filepath.Join(artifacts.Path(), "results-junit.xml")
+		})
+
+		When("The additional JUnitXML results file is requested", func() {
+			It("should be written to the artifacts directory without error", func() {
+				Expect(writeJUnit(context.TODO(), *results)).To(Succeed())
+				_, err := os.Stat(junitfile)
+				Expect(err).ToNot(HaveOccurred())
+			})
+		})
+	})
+})
diff --git a/internal/lib/lib_operator_test.go b/internal/lib/lib_operator_test.go
new file mode 100644
index 0000000..a5c41b8
--- /dev/null
+++ b/internal/lib/lib_operator_test.go
@@ -0,0 +1,75 @@
+package lib
+
+import (
+	"context"
+
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/engine"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/formatters"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/policy"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/runtime"
+
+	. "github.com/onsi/ginkgo/v2"
+	. "github.com/onsi/gomega"
+)
+
+var _ = Describe("Lib Operator Functions", func() {
+	BeforeEach(createAndCleanupDirForArtifactsAndLogs)
+
+	Context("When instantiating a CheckOperatorRunner", func() {
+		var cfg *runtime.Config
+		BeforeEach(func() {
+			cfg = &runtime.Config{
+				Image:          "quay.io/example/foo:latest",
+				ResponseFormat: formatters.DefaultFormat,
+			}
+		})
+
+		Context("with a valid policy formatter", func() {
+			It("should return with no error, and the appropriate formatter", func() {
+				cfg.ResponseFormat = "xml"
+				runner, err := NewCheckOperatorRunner(context.TODO(), cfg)
+				Expect(err).ToNot(HaveOccurred())
+				expectedFormatter, err := formatters.NewByName(cfg.ResponseFormat)
+				Expect(err).ToNot(HaveOccurred())
+				Expect(runner.Formatter.PrettyName()).To(Equal(expectedFormatter.PrettyName()))
+			})
+		})
+
+		Context("with an invalid policy formatter", func() {
+			It("should return an error", func() {
+				cfg.ResponseFormat = "foo"
+				_, err := NewCheckOperatorRunner(context.TODO(), cfg)
+				Expect(err).To(HaveOccurred())
+			})
+		})
+
+		Context("with an invalid policy definition", func() {
+			It("should return the container policy engine anyway", func() {
+				cfg.Policy = "badpolicy"
+				beforeCfg := *cfg
+				runner, err := NewCheckOperatorRunner(context.TODO(), cfg)
+				Expect(err).ToNot(HaveOccurred())
+
+				_, err = engine.NewForConfig(context.TODO(), cfg.ReadOnly())
+				Expect(runner.Cfg.Policy).ToNot(Equal(beforeCfg.Policy))
+				Expect(runner.Cfg.Policy).To(Equal(policy.PolicyOperator))
+				Expect(err).ToNot(HaveOccurred())
+			})
+		})
+
+		Context("with an invalid formatter definition", func() {
+			It("should return an error", func() {
+				cfg.ResponseFormat = "foo"
+				_, err := NewCheckOperatorRunner(context.TODO(), cfg)
+				Expect(err).To(HaveOccurred())
+			})
+		})
+
+		It("should contain a ResultWriterFile ResultWriter", func() {
+			runner, err := NewCheckOperatorRunner(context.TODO(), cfg)
+			Expect(err).ToNot(HaveOccurred())
+			_, rwIsExpectedType := runner.Rw.(*runtime.ResultWriterFile)
+			Expect(rwIsExpectedType).To(BeTrue())
+		})
+	})
+})
diff --git a/cmd/preflight_check_test.go b/internal/lib/preflight_check_test.go
similarity index 87%
rename from cmd/preflight_check_test.go
rename to internal/lib/preflight_check_test.go
index 8597db1..da7321c 100644
--- a/cmd/preflight_check_test.go
+++ b/internal/lib/preflight_check_test.go
@@ -1,4 +1,4 @@
-package cmd
+package lib
 
 import (
 	"context"
@@ -23,11 +23,11 @@ var _ = Describe("Preflight Check Func", func() {
 		var localArtifactsDir string
 
 		var cfg *runtime.Config
-		var pc pyxisClient
+		var pc PyxisClient
 		var eng engine.CheckEngine
 		var fmttr formatters.ResponseFormatter
-		var rw resultWriter
-		var rs resultSubmitter
+		var rw ResultWriter
+		var rs ResultSubmitter
 
 		BeforeEach(func() {
 			// instantiate err to make sure we can equal-assign in the following line.
@@ -45,7 +45,7 @@ var _ = Describe("Preflight Check Func", func() {
 				Artifacts: localArtifactsDir,
 			}
 
-			pc = &fakePyxisClient{
+			pc = &FakePyxisClient{
 				findImagesByDigestFunc: fidbFuncNoop,
 				getProjectsFunc:        gpFuncNoop,
 				submitResultsFunc:      srFuncNoop,
@@ -58,7 +58,7 @@ var _ = Describe("Preflight Check Func", func() {
 
 			fmttr, _ = formatters.NewByName(formatters.DefaultFormat)
 			rw = &runtime.ResultWriterFile{}
-			rs = &noopSubmitter{}
+			rs = NewNoopSubmitter(false, "", nil)
 
 			DeferCleanup(os.RemoveAll, localTempDir)
 			DeferCleanup(os.RemoveAll, localArtifactsDir)
@@ -68,7 +68,7 @@ var _ = Describe("Preflight Check Func", func() {
 		Context("with a customized artifacts directory", func() {
 			It("should set the artifacts directory accordingly", func() {
 				// it's possible this will throw an error, but we dont' care for this test.
-				_ = preflightCheck(context.TODO(), cfg, pc, eng, fmttr, rw, rs)
+				_ = PreflightCheck(context.TODO(), cfg, pc, eng, fmttr, rw, rs)
 				Expect(artifacts.Path()).To(Equal(localArtifactsDir))
 			})
 		})
@@ -79,7 +79,7 @@ var _ = Describe("Preflight Check Func", func() {
 			})
 
 			It("should throw an error", func() {
-				err := preflightCheck(context.TODO(), cfg, pc, eng, fmttr, rw, rs)
+				err := PreflightCheck(context.TODO(), cfg, pc, eng, fmttr, rw, rs)
 				Expect(err).To(HaveOccurred())
 				Expect(err.Error()).To(ContainSubstring("some result writer error"))
 			})
@@ -92,7 +92,7 @@ var _ = Describe("Preflight Check Func", func() {
 				eng = fakeCheckEngine{errorRunningChecks: true, errorMsg: msg}
 			})
 			It("should thrown an error", func() {
-				err := preflightCheck(context.TODO(), cfg, pc, eng, fmttr, rw, rs)
+				err := PreflightCheck(context.TODO(), cfg, pc, eng, fmttr, rw, rs)
 				Expect(err).To(HaveOccurred())
 				Expect(err.Error()).To(ContainSubstring(msg))
 			})
@@ -106,7 +106,7 @@ var _ = Describe("Preflight Check Func", func() {
 			})
 
 			It("should throw an error", func() {
-				err := preflightCheck(context.TODO(), cfg, pc, eng, fmttr, rw, rs)
+				err := PreflightCheck(context.TODO(), cfg, pc, eng, fmttr, rw, rs)
 				Expect(err).To(HaveOccurred())
 				Expect(err.Error()).To(ContainSubstring(msg))
 			})
@@ -117,7 +117,7 @@ var _ = Describe("Preflight Check Func", func() {
 				cfg.WriteJUnit = true
 			})
 			It("should write a junit file in the artifacts directory", func() {
-				err := preflightCheck(context.TODO(), cfg, pc, eng, fmttr, rw, rs)
+				err := PreflightCheck(context.TODO(), cfg, pc, eng, fmttr, rw, rs)
 				Expect(err).ToNot(HaveOccurred())
 				Expect(path.Join(artifacts.Path(), "results-junit.xml")).To(BeAnExistingFile())
 			})
@@ -134,7 +134,7 @@ var _ = Describe("Preflight Check Func", func() {
 			})
 
 			It("should throw an error", func() {
-				err := preflightCheck(context.TODO(), cfg, pc, eng, fmttr, rw, rs)
+				err := PreflightCheck(context.TODO(), cfg, pc, eng, fmttr, rw, rs)
 				Expect(err).To(HaveOccurred())
 				Expect(err.Error()).To(ContainSubstring(msg))
 			})
@@ -146,7 +146,7 @@ var _ = Describe("Preflight Check Func", func() {
 			})
 
 			It("should complete with no errors", func() {
-				err := preflightCheck(context.TODO(), cfg, pc, eng, fmttr, rw, rs)
+				err := PreflightCheck(context.TODO(), cfg, pc, eng, fmttr, rw, rs)
 				Expect(err).ToNot(HaveOccurred())
 			})
 		})
diff --git a/internal/lib/suite_test.go b/internal/lib/suite_test.go
new file mode 100644
index 0000000..4c7ad2b
--- /dev/null
+++ b/internal/lib/suite_test.go
@@ -0,0 +1,28 @@
+package lib
+
+import (
+	"os"
+	"path/filepath"
+	"testing"
+
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/artifacts"
+
+	. "github.com/onsi/ginkgo/v2"
+	. "github.com/onsi/gomega"
+)
+
+func TestCMD(t *testing.T) {
+	RegisterFailHandler(Fail)
+	RunSpecs(t, "lib Suite")
+}
+
+var createAndCleanupDirForArtifactsAndLogs = func() {
+	tmpDir, err := os.MkdirTemp("", "lib-execute-*")
+	Expect(err).ToNot(HaveOccurred())
+	artifacts.SetDir(filepath.Join(tmpDir, "artifacts"))
+	os.Setenv("PFLT_ARTIFACTS", artifacts.Path())
+	os.Setenv("PFLT_LOGFILE", filepath.Join(tmpDir, "preflight.log"))
+	DeferCleanup(os.RemoveAll, tmpDir)
+	DeferCleanup(os.Unsetenv, "PFLT_ARTIFACTS")
+	DeferCleanup(os.Unsetenv, "PFLT_LOGFILE")
+}