add public API to detect node providers

This commit is contained in:
Benjamin Elder
2021-02-12 16:17:00 -08:00
parent 1ebe6b0214
commit f960e32c64
2 changed files with 51 additions and 8 deletions

View File

@@ -22,6 +22,7 @@ import (
"sigs.k8s.io/kind/pkg/cluster/constants" "sigs.k8s.io/kind/pkg/cluster/constants"
"sigs.k8s.io/kind/pkg/cluster/nodes" "sigs.k8s.io/kind/pkg/cluster/nodes"
"sigs.k8s.io/kind/pkg/cluster/nodeutils" "sigs.k8s.io/kind/pkg/cluster/nodeutils"
"sigs.k8s.io/kind/pkg/errors"
"sigs.k8s.io/kind/pkg/log" "sigs.k8s.io/kind/pkg/log"
internalcreate "sigs.k8s.io/kind/pkg/cluster/internal/create" internalcreate "sigs.k8s.io/kind/pkg/cluster/internal/create"
@@ -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 { if p.provider == nil {
// auto-detect based on each package IsAvailable() function // DetectNodeProvider does not fallback to allow callers to determine
// default to docker for backwards compatibility // this behavior
if docker.IsAvailable() { // However for compatibility if the caller of NewProvider supplied no
p.provider = docker.NewProvider(p.logger) // option and we autodetect internally, we default to the docker provider
} else if podman.IsAvailable() { // for fallback, to avoid a breaking change for now.
p.provider = podman.NewProvider(p.logger) // This may change in the future.
} else { // TODO: consider breaking this API for earlier errors.
p.provider = docker.NewProvider(p.logger) providerOpt, _ := DetectNodeProvider()
if providerOpt == nil {
providerOpt = ProviderWithDocker()
} }
providerOpt.apply(p)
} }
return 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 // ProviderOption is an option for configuring a provider
type ProviderOption interface { type ProviderOption interface {
apply(p *Provider) apply(p *Provider)

View File

@@ -17,6 +17,8 @@ limitations under the License.
package errors package errors
import ( import (
stderrors "errors"
pkgerrors "github.com/pkg/errors" pkgerrors "github.com/pkg/errors"
) )
@@ -26,6 +28,12 @@ func New(message string) error {
return pkgerrors.New(message) 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 // 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 // value that satisfies error. Errorf also records the stack trace at the
// point it was called. // point it was called.