Repository: knative-sandbox/kn-plugin-func
Pull request #818 (2022-02-07 15:17:39)

src: error-less ctors
Constructors do only necessary initialization with no possible error.
Errors are deferred until some actual operation is being done.

This allows to initialize all parts of `fn.Client` at once with no error.
We need this to be able to create a shared factory function of `fn.Client` for multiple commands.
Without this such a factory is not possible because the function could fail while initializing something that won't be actually used.
For example: `func create` doesn't need `k8s` configuration set up, but the command would still fail because of it.

codecov[bot]: # [Codecov](https://codecov.io/gh/knative-sandbox/kn-plugin-func/pull/818?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox) Report
> Merging [#818](https://codecov.io/gh/knative-sandbox/kn-plugin-func/pull/818?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox) (b172bac) into [main](https://codecov.io/gh/knative-sandbox/kn-plugin-func/commit/abd4eea0c7e583b346cf895c3c3ef116bbc7a28e?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox) (abd4eea) will **increase** coverage by `0.15%`.
> The diff coverage is `0.00%`.

> :exclamation: Current head b172bac differs from pull request most recent head a5ab188. Consider uploading reports for the commit a5ab188 to get more accurate results

[![Impacted file tree graph](https://codecov.io/gh/knative-sandbox/kn-plugin-func/pull/818/graphs/tree.svg?width=650&height=150&src=pr&token=da1B9bMsQ9&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox)](https://codecov.io/gh/knative-sandbox/kn-plugin-func/pull/818?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox)

```diff
@@            Coverage Diff             @@
##             main     #818      +/-   ##
==========================================
+ Coverage   42.85%   43.00%   +0.15%     
==========================================
  Files          47       47              
  Lines        4749     4732      -17     
==========================================
  Hits         2035     2035              
+ Misses       2422     2405      -17     
  Partials      292      292              
```


| [Impacted Files](https://codecov.io/gh/knative-sandbox/kn-plugin-func/pull/818?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox) | Coverage Δ | |
|---|---|---|
| [cmd/completion\_util.go](https://codecov.io/gh/knative-sandbox/kn-plugin-func/pull/818/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox#diff-Y21kL2NvbXBsZXRpb25fdXRpbC5nbw==) | `0.00% <0.00%> (ø)` | |
| [cmd/delete.go](https://codecov.io/gh/knative-sandbox/kn-plugin-func/pull/818/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox#diff-Y21kL2RlbGV0ZS5nbw==) | `50.53% <0.00%> (+2.08%)` | :arrow_up: |
| [cmd/deploy.go](https://codecov.io/gh/knative-sandbox/kn-plugin-func/pull/818/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox#diff-Y21kL2RlcGxveS5nbw==) | `13.75% <0.00%> (+0.22%)` | :arrow_up: |
| [cmd/info.go](https://codecov.io/gh/knative-sandbox/kn-plugin-func/pull/818/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox#diff-Y21kL2luZm8uZ28=) | `24.67% <0.00%> (+0.62%)` | :arrow_up: |
| [cmd/invoke.go](https://codecov.io/gh/knative-sandbox/kn-plugin-func/pull/818/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox#diff-Y21kL2ludm9rZS5nbw==) | `32.77% <0.00%> (+0.27%)` | :arrow_up: |
| [cmd/list.go](https://codecov.io/gh/knative-sandbox/kn-plugin-func/pull/818/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox#diff-Y21kL2xpc3QuZ28=) | `29.68% <0.00%> (+0.89%)` | :arrow_up: |
| [knative/deployer.go](https://codecov.io/gh/knative-sandbox/kn-plugin-func/pull/818/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox#diff-a25hdGl2ZS9kZXBsb3llci5nbw==) | `5.58% <0.00%> (ø)` | |
| [knative/describer.go](https://codecov.io/gh/knative-sandbox/kn-plugin-func/pull/818/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox#diff-a25hdGl2ZS9kZXNjcmliZXIuZ28=) | `0.00% <0.00%> (ø)` | |
| [knative/lister.go](https://codecov.io/gh/knative-sandbox/kn-plugin-func/pull/818/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox#diff-a25hdGl2ZS9saXN0ZXIuZ28=) | `0.00% <0.00%> (ø)` | |
| [knative/remover.go](https://codecov.io/gh/knative-sandbox/kn-plugin-func/pull/818/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox#diff-a25hdGl2ZS9yZW1vdmVyLmdv) | `0.00% <0.00%> (ø)` | |
| ... and [1 more](https://codecov.io/gh/knative-sandbox/kn-plugin-func/pull/818/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/knative-sandbox/kn-plugin-func/pull/818?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/knative-sandbox/kn-plugin-func/pull/818?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox). Last update [abd4eea...a5ab188](https://codecov.io/gh/knative-sandbox/kn-plugin-func/pull/818?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox).

matejvasek: @zroubalik I updated description.
matejvasek: >This allows to initialize all parts of fn.Client at once with no error.
We need this to be able to create a shared factory function of fn.Client for multiple commands.

meaning instead of `newCreateClient` `newBuildClient` `newDeployClient` `newDeleteClient` `newInfoClient` `newListClient` `newInvokeClient` `newRepositoryClient` `newRunClient` which are partially initializing `fn.Client`,
there would be just single factory function.
knative-prow-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/knative-sandbox/kn-plugin-func/pull/818#pullrequestreview-875273538" title="Approved">lkingland</a>*, *<a href="https://github.com/knative-sandbox/kn-plugin-func/pull/818#" title="Author self-approved">matejvasek</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=knative-sandbox%2Fkn-plugin-func).

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/knative-sandbox/kn-plugin-func/blob/main/OWNERS)~~ [lkingland,matejvasek]

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":[]} -->
matejvasek: /unhold

Patch:
diff --git a/cmd/build.go b/cmd/build.go
index a0702f74..05ca3c3e 100644
--- a/cmd/build.go
+++ b/cmd/build.go
@@ -25,20 +25,16 @@ func newBuildClient(cfg buildConfig) (*fn.Client, error) {
 
 	var (
 		pusher *docker.Pusher
-		err    error
 	)
 	if cfg.Push {
 		credentialsProvider := creds.NewCredentialsProvider(
 			creds.WithPromptForCredentials(newPromptForCredentials()),
 			creds.WithPromptForCredentialStore(newPromptForCredentialStore()),
 			creds.WithTransport(cfg.Transport))
-		pusher, err = docker.NewPusher(
+		pusher = docker.NewPusher(
 			docker.WithCredentialsProvider(credentialsProvider),
 			docker.WithProgressListener(listener),
 			docker.WithTransport(cfg.Transport))
-		if err != nil {
-			return nil, err
-		}
 		pusher.Verbose = cfg.Verbose
 	}
 
diff --git a/cmd/completion_util.go b/cmd/completion_util.go
index c96129c4..4f1943b1 100644
--- a/cmd/completion_util.go
+++ b/cmd/completion_util.go
@@ -15,11 +15,8 @@ import (
 )
 
 func CompleteFunctionList(cmd *cobra.Command, args []string, toComplete string) (strings []string, directive cobra.ShellCompDirective) {
-	lister, err := knative.NewLister("")
-	if err != nil {
-		directive = cobra.ShellCompDirectiveError
-		return
-	}
+	lister := knative.NewLister("")
+
 	list, err := lister.List(cmd.Context())
 	if err != nil {
 		directive = cobra.ShellCompDirectiveError
diff --git a/cmd/delete.go b/cmd/delete.go
index 09407415..a15ff9f7 100644
--- a/cmd/delete.go
+++ b/cmd/delete.go
@@ -20,16 +20,10 @@ import (
 // mocking the remover or the client itself to fabricate test states.
 func newDeleteClient(cfg deleteConfig) (*fn.Client, error) {
 	listener := progress.New()
-	remover, err := knative.NewRemover(cfg.Namespace)
-	if err != nil {
-		return nil, err
-	}
+	remover := knative.NewRemover(cfg.Namespace)
 
-	pipelinesProvider, err := tekton.NewPipelinesProvider(
+	pipelinesProvider := tekton.NewPipelinesProvider(
 		tekton.WithNamespace(cfg.Namespace))
-	if err != nil {
-		return nil, err
-	}
 
 	listener.Verbose = cfg.Verbose
 	remover.Verbose = cfg.Verbose
diff --git a/cmd/deploy.go b/cmd/deploy.go
index 55e3f4b7..f570966d 100644
--- a/cmd/deploy.go
+++ b/cmd/deploy.go
@@ -30,7 +30,6 @@ func newDeployClient(cfg deployConfig) (*fn.Client, error) {
 
 	var (
 		pusher *docker.Pusher
-		err    error
 	)
 
 	credentialsProvider := creds.NewCredentialsProvider(
@@ -39,28 +38,19 @@ func newDeployClient(cfg deployConfig) (*fn.Client, error) {
 		creds.WithTransport(cfg.Transport))
 
 	if cfg.Push {
-		pusher, err = docker.NewPusher(
+		pusher = docker.NewPusher(
 			docker.WithCredentialsProvider(credentialsProvider),
 			docker.WithProgressListener(listener),
 			docker.WithTransport(cfg.Transport))
-		if err != nil {
-			return nil, err
-		}
 		pusher.Verbose = cfg.Verbose
 	}
 
-	deployer, err := knative.NewDeployer(cfg.Namespace)
-	if err != nil {
-		return nil, err
-	}
+	deployer := knative.NewDeployer(cfg.Namespace)
 
-	pipelinesProvider, err := tekton.NewPipelinesProvider(
+	pipelinesProvider := tekton.NewPipelinesProvider(
 		tekton.WithNamespace(cfg.Namespace),
 		tekton.WithProgressListener(listener),
 		tekton.WithCredentialsProvider(credentialsProvider))
-	if err != nil {
-		return nil, err
-	}
 
 	listener.Verbose = cfg.Verbose
 	builder.Verbose = cfg.Verbose
diff --git a/cmd/info.go b/cmd/info.go
index d910327a..eb8b3532 100644
--- a/cmd/info.go
+++ b/cmd/info.go
@@ -16,10 +16,7 @@ import (
 )
 
 func newInfoClient(cfg infoConfig) (*fn.Client, error) {
-	describer, err := knative.NewDescriber(cfg.Namespace)
-	if err != nil {
-		return nil, err
-	}
+	describer := knative.NewDescriber(cfg.Namespace)
 
 	describer.Verbose = cfg.Verbose
 
diff --git a/cmd/invoke.go b/cmd/invoke.go
index 6d64a047..3823f4d3 100644
--- a/cmd/invoke.go
+++ b/cmd/invoke.go
@@ -21,10 +21,7 @@ import (
 type invokeClientFn func(invokeConfig) (*fn.Client, error)
 
 func newInvokeClient(cfg invokeConfig) (*fn.Client, error) {
-	describer, err := knative.NewDescriber(cfg.Namespace)
-	if err != nil {
-		return nil, err
-	}
+	describer := knative.NewDescriber(cfg.Namespace)
 	describer.Verbose = cfg.Verbose
 
 	return fn.New(
diff --git a/cmd/list.go b/cmd/list.go
index e94d2951..a937fda3 100644
--- a/cmd/list.go
+++ b/cmd/list.go
@@ -20,11 +20,7 @@ import (
 func newListClient(cfg listConfig) (*fn.Client, error) {
 	// TODO(lkingland): does an empty namespace mean all namespaces
 	// or the default namespace as defined in user's config?
-	lister, err := knative.NewLister(cfg.Namespace)
-	if err != nil {
-		return nil, err
-	}
-
+	lister := knative.NewLister(cfg.Namespace)
 	lister.Verbose = cfg.Verbose
 
 	return fn.New(
diff --git a/docker/pusher.go b/docker/pusher.go
index 571c4781..ac693cb2 100644
--- a/docker/pusher.go
+++ b/docker/pusher.go
@@ -24,7 +24,7 @@ import (
 	"github.com/google/go-containerregistry/pkg/v1/remote"
 )
 
-type Opt func(*Pusher) error
+type Opt func(*Pusher)
 
 type Credentials struct {
 	Username string
@@ -56,30 +56,26 @@ type Pusher struct {
 }
 
 func WithCredentialsProvider(cp CredentialsProvider) Opt {
-	return func(p *Pusher) error {
+	return func(p *Pusher) {
 		p.credentialsProvider = cp
-		return nil
 	}
 }
 
 func WithProgressListener(pl fn.ProgressListener) Opt {
-	return func(p *Pusher) error {
+	return func(p *Pusher) {
 		p.progressListener = pl
-		return nil
 	}
 }
 
 func WithTransport(transport http.RoundTripper) Opt {
-	return func(pusher *Pusher) error {
+	return func(pusher *Pusher) {
 		pusher.transport = transport
-		return nil
 	}
 }
 
 func WithPusherDockerClientFactory(dockerClientFactory PusherDockerClientFactory) Opt {
-	return func(pusher *Pusher) error {
+	return func(pusher *Pusher) {
 		pusher.dockerClientFactory = dockerClientFactory
-		return nil
 	}
 }
 
@@ -88,7 +84,7 @@ func EmptyCredentialsProvider(ctx context.Context, registry string) (Credentials
 }
 
 // NewPusher creates an instance of a docker-based image pusher.
-func NewPusher(opts ...Opt) (*Pusher, error) {
+func NewPusher(opts ...Opt) *Pusher {
 	result := &Pusher{
 		Verbose:             false,
 		credentialsProvider: EmptyCredentialsProvider,
@@ -100,13 +96,10 @@ func NewPusher(opts ...Opt) (*Pusher, error) {
 		},
 	}
 	for _, opt := range opts {
-		err := opt(result)
-		if err != nil {
-			return nil, err
-		}
+		opt(result)
 	}
 
-	return result, nil
+	return result
 }
 
 func GetRegistry(img string) (string, error) {
diff --git a/knative/deployer.go b/knative/deployer.go
index 77118747..b50cf40e 100644
--- a/knative/deployer.go
+++ b/knative/deployer.go
@@ -36,14 +36,10 @@ type Deployer struct {
 	Verbose bool
 }
 
-func NewDeployer(namespaceOverride string) (deployer *Deployer, err error) {
-	deployer = &Deployer{}
-	namespace, err := k8s.GetNamespace(namespaceOverride)
-	if err != nil {
-		return
+func NewDeployer(namespaceOverride string) *Deployer {
+	return &Deployer{
+		Namespace: namespaceOverride,
 	}
-	deployer.Namespace = namespace
-	return
 }
 
 // Checks the status of the "user-container" for the ImagePullBackOff reason meaning that
@@ -77,6 +73,12 @@ func (d *Deployer) isImageInPrivateRegistry(ctx context.Context, client clientse
 }
 
 func (d *Deployer) Deploy(ctx context.Context, f fn.Function) (result fn.DeploymentResult, err error) {
+	if d.Namespace == "" {
+		d.Namespace, err = k8s.GetNamespace(d.Namespace)
+		if err != nil {
+			return fn.DeploymentResult{}, err
+		}
+	}
 
 	client, err := NewServingClient(d.Namespace)
 	if err != nil {
diff --git a/knative/describer.go b/knative/describer.go
index d87eb941..5fa017b1 100644
--- a/knative/describer.go
+++ b/knative/describer.go
@@ -16,15 +16,10 @@ type Describer struct {
 	namespace string
 }
 
-func NewDescriber(namespaceOverride string) (describer *Describer, err error) {
-	describer = &Describer{}
-	namespace, err := k8s.GetNamespace(namespaceOverride)
-	if err != nil {
-		return
+func NewDescriber(namespaceOverride string) *Describer {
+	return &Describer{
+		namespace: namespaceOverride,
 	}
-
-	describer.namespace = namespace
-	return
 }
 
 // Describe by name. Note that the consuming API uses domain style notation, whereas Kubernetes
@@ -32,6 +27,12 @@ func NewDescriber(namespaceOverride string) (describer *Describer, err error) {
 // detal proper full names have to be escaped on the way in and unescaped on the way out. ex:
 // www.example-site.com -> www-example--site-com
 func (d *Describer) Describe(ctx context.Context, name string) (description fn.Instance, err error) {
+	if d.namespace == "" {
+		d.namespace, err = k8s.GetNamespace(d.namespace)
+		if err != nil {
+			return fn.Instance{}, err
+		}
+	}
 
 	servingClient, err := NewServingClient(d.namespace)
 	if err != nil {
diff --git a/knative/lister.go b/knative/lister.go
index da8ad8aa..5f908083 100644
--- a/knative/lister.go
+++ b/knative/lister.go
@@ -17,19 +17,19 @@ type Lister struct {
 	Namespace string
 }
 
-func NewLister(namespaceOverride string) (l *Lister, err error) {
-	l = &Lister{}
-
-	namespace, err := k8s.GetNamespace(namespaceOverride)
-	if err != nil {
-		return
+func NewLister(namespaceOverride string) *Lister {
+	return &Lister{
+		Namespace: namespaceOverride,
 	}
-	l.Namespace = namespace
-
-	return
 }
 
 func (l *Lister) List(ctx context.Context) (items []fn.ListItem, err error) {
+	if l.Namespace == "" {
+		l.Namespace, err = k8s.GetNamespace(l.Namespace)
+		if err != nil {
+			return nil, err
+		}
+	}
 
 	client, err := NewServingClient(l.Namespace)
 	if err != nil {
diff --git a/knative/remover.go b/knative/remover.go
index a32f3262..c26dfc5d 100644
--- a/knative/remover.go
+++ b/knative/remover.go
@@ -10,15 +10,10 @@ import (
 
 const RemoveTimeout = 120 * time.Second
 
-func NewRemover(namespaceOverride string) (remover *Remover, err error) {
-	remover = &Remover{}
-	namespace, err := k8s.GetNamespace(namespaceOverride)
-	if err != nil {
-		return
+func NewRemover(namespaceOverride string) *Remover {
+	return &Remover{
+		Namespace: namespaceOverride,
 	}
-	remover.Namespace = namespace
-
-	return
 }
 
 type Remover struct {
@@ -27,6 +22,12 @@ type Remover struct {
 }
 
 func (remover *Remover) Remove(ctx context.Context, name string) (err error) {
+	if remover.Namespace == "" {
+		remover.Namespace, err = k8s.GetNamespace(remover.Namespace)
+		if err != nil {
+			return err
+		}
+	}
 
 	client, err := NewServingClient(remover.Namespace)
 	if err != nil {
diff --git a/pipelines/tekton/pipeplines_provider.go b/pipelines/tekton/pipeplines_provider.go
index 96a72e2a..5d048c12 100644
--- a/pipelines/tekton/pipeplines_provider.go
+++ b/pipelines/tekton/pipeplines_provider.go
@@ -24,7 +24,7 @@ import (
 	"knative.dev/pkg/apis"
 )
 
-type Opt func(*PipelinesProvider) error
+type Opt func(*PipelinesProvider)
 
 type PipelinesProvider struct {
 	// namespace with which to override that set on the default configuration (such as the ~/.kube/config).
@@ -36,47 +36,46 @@ type PipelinesProvider struct {
 }
 
 func WithNamespace(namespace string) Opt {
-	return func(pp *PipelinesProvider) error {
-		namespace, err := k8s.GetNamespace(namespace)
-		if err != nil {
-			return err
-		}
+	return func(pp *PipelinesProvider) {
 		pp.namespace = namespace
-		return nil
 	}
 }
 
 func WithProgressListener(pl fn.ProgressListener) Opt {
-	return func(pp *PipelinesProvider) error {
+	return func(pp *PipelinesProvider) {
 		pp.progressListener = pl
-		return nil
 	}
 }
 
 func WithCredentialsProvider(credentialsProvider docker.CredentialsProvider) Opt {
-	return func(pp *PipelinesProvider) error {
+	return func(pp *PipelinesProvider) {
 		pp.credentialsProvider = credentialsProvider
-		return nil
 	}
 }
 
-func NewPipelinesProvider(opts ...Opt) (*PipelinesProvider, error) {
+func NewPipelinesProvider(opts ...Opt) *PipelinesProvider {
 	pp := &PipelinesProvider{}
 
 	for _, opt := range opts {
-		err := opt(pp)
-		if err != nil {
-			return nil, err
-		}
+		opt(pp)
 	}
 
-	return pp, nil
+	return pp
 }
 
 // Run creates a Tekton Pipeline and all necessary resources (PVCs, Secrets, SAs,...) for the input Function.
 // It ensures that all needed resources are present on the cluster so the PipelineRun can be initialized.
 // After the PipelineRun is being intitialized, the progress of the PipelineRun is being watched and printed to the output.
 func (pp *PipelinesProvider) Run(ctx context.Context, f fn.Function) error {
+	var err error
+
+	if pp.namespace == "" {
+		pp.namespace, err = k8s.GetNamespace(pp.namespace)
+		if err != nil {
+			return err
+		}
+	}
+
 	pp.progressListener.Increment("Creating Pipeline resources")
 
 	client, err := NewTektonClient()


Test patch:
diff --git a/client_int_test.go b/client_int_test.go
index 912b8562..fe1f8034 100644
--- a/client_int_test.go
+++ b/client_int_test.go
@@ -59,10 +59,8 @@ func TestList(t *testing.T) {
 	verbose := true
 
 	// Assemble
-	lister, err := knative.NewLister(DefaultNamespace)
-	if err != nil {
-		t.Fatal(err)
-	}
+	lister := knative.NewLister(DefaultNamespace)
+
 	client := fn.New(
 		fn.WithLister(lister),
 		fn.WithVerbose(verbose))
@@ -208,28 +206,16 @@ func newClient(verbose bool) *fn.Client {
 	builder := buildpacks.NewBuilder()
 	builder.Verbose = verbose
 
-	pusher, err := docker.NewPusher()
-	if err != nil {
-		panic(err)
-	}
+	pusher := docker.NewPusher()
 	pusher.Verbose = verbose
 
-	deployer, err := knative.NewDeployer(DefaultNamespace)
-	if err != nil {
-		panic(err) // TODO: remove error from deployer constructor
-	}
+	deployer := knative.NewDeployer(DefaultNamespace)
 	deployer.Verbose = verbose
 
-	remover, err := knative.NewRemover(DefaultNamespace)
-	if err != nil {
-		panic(err) // TODO: remove error from remover constructor
-	}
+	remover := knative.NewRemover(DefaultNamespace)
 	remover.Verbose = verbose
 
-	lister, err := knative.NewLister(DefaultNamespace)
-	if err != nil {
-		panic(err) // TODO: remove error from lister constructor
-	}
+	lister := knative.NewLister(DefaultNamespace)
 	lister.Verbose = verbose
 
 	return fn.New(
diff --git a/docker/pusher_test.go b/docker/pusher_test.go
index be7f052d..5b73fed9 100644
--- a/docker/pusher_test.go
+++ b/docker/pusher_test.go
@@ -105,12 +105,9 @@ func TestDaemonPush(t *testing.T) {
 	dockerClientFactory := func() (docker.PusherDockerClient, error) {
 		return dockerClient, nil
 	}
-	pusher, err := docker.NewPusher(
+	pusher := docker.NewPusher(
 		docker.WithCredentialsProvider(testCredProvider),
 		docker.WithPusherDockerClientFactory(dockerClientFactory))
-	if err != nil {
-		t.Fatal(err)
-	}
 
 	f := fn.Function{
 		Image: functionImageLocal,
@@ -185,13 +182,10 @@ func TestNonDaemonPush(t *testing.T) {
 		return dockerClient, nil
 	}
 
-	pusher, err := docker.NewPusher(
+	pusher := docker.NewPusher(
 		docker.WithTransport(transport),
 		docker.WithCredentialsProvider(testCredProvider),
 		docker.WithPusherDockerClientFactory(dockerClientFactory))
-	if err != nil {
-		t.Fatal(err)
-	}
 
 	f := fn.Function{
 		Image: functionImageRemote,