Skip to content

Commit

Permalink
add public API to detect node providers
Browse files Browse the repository at this point in the history
  • Loading branch information
BenTheElder committed Feb 13, 2021
1 parent 1ebe6b0 commit f960e32
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 8 deletions.
51 changes: 43 additions & 8 deletions pkg/cluster/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"sigs.k8s.io/kind/pkg/cluster/constants"
"sigs.k8s.io/kind/pkg/cluster/nodes"
"sigs.k8s.io/kind/pkg/cluster/nodeutils"
"sigs.k8s.io/kind/pkg/errors"
"sigs.k8s.io/kind/pkg/log"

internalcreate "sigs.k8s.io/kind/pkg/cluster/internal/create"
Expand Down Expand Up @@ -68,20 +69,54 @@ func NewProvider(options ...ProviderOption) *Provider {
}
}

// ensure a provider if none was set
// NOTE: depends on logger being set (see sorting above)
if p.provider == nil {
// auto-detect based on each package IsAvailable() function
// default to docker for backwards compatibility
if docker.IsAvailable() {
p.provider = docker.NewProvider(p.logger)
} else if podman.IsAvailable() {
p.provider = podman.NewProvider(p.logger)
} else {
p.provider = docker.NewProvider(p.logger)
// DetectNodeProvider does not fallback to allow callers to determine
// this behavior
// However for compatibility if the caller of NewProvider supplied no
// option and we autodetect internally, we default to the docker provider
// for fallback, to avoid a breaking change for now.
// This may change in the future.
// TODO: consider breaking this API for earlier errors.
providerOpt, _ := DetectNodeProvider()
if providerOpt == nil {
providerOpt = ProviderWithDocker()
}
providerOpt.apply(p)
}
return p
}

// NoNodeProviderDetectedError indicates that we could not autolocate an available
// NodeProvider backend on the host
var NoNodeProviderDetectedError = errors.NewWithoutStack("failed to detect any supported node provider")

// DetectNodeProvider allows callers to autodetect the node provider
// *without* fallback to the default.
//
// Pass the returned ProviderOption to NewProvider to pass the auto-detect Docker
// or Podman option explicitly (in the future there will be more options)
//
// NOTE: The kind *cli* also checks `KIND_EXPERIMENTAL_PROVIDER` for "podman" or
// "docker" currently and does not auto-detect / respects this if set.
//
// This will be replaced with some other mechanism in the future (likely when
// podman support is GA), in the meantime though your tool may wish to match this.
//
// In the future when this is not considered experimental,
// that logic will be in a public API as well.
func DetectNodeProvider() (ProviderOption, error) {
// auto-detect based on each node provider's IsAvailable() function
if docker.IsAvailable() {
return ProviderWithDocker(), nil
}
if podman.IsAvailable() {
return ProviderWithPodman(), nil
}
return nil, errors.WithStack(NoNodeProviderDetectedError)
}

// ProviderOption is an option for configuring a provider
type ProviderOption interface {
apply(p *Provider)
Expand Down
8 changes: 8 additions & 0 deletions pkg/errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ limitations under the License.
package errors

import (
stderrors "errors"

pkgerrors "github.com/pkg/errors"
)

Expand All @@ -26,6 +28,12 @@ func New(message string) error {
return pkgerrors.New(message)
}

// NewWithoutStack is like new but does NOT wrap with a stack
// This is useful for exported errors
func NewWithoutStack(message string) error {
return stderrors.New(message)
}

// Errorf formats according to a format specifier and returns the string as a
// value that satisfies error. Errorf also records the stack trace at the
// point it was called.
Expand Down

0 comments on commit f960e32

Please sign in to comment.