Files
zeekay b61441f7d7 Volume: node-local persistent volumes, under our own name
A fork of Rancher's local-path-provisioner at v0.0.36. The behaviour is
unchanged and deliberately so — a directory on the node a pod lands on is
the right thing for a disk. What changes is identity.

The provisioner answers to hanzo.ai/volume rather than rancher.io/local-path.
That is not branding: two provisioners sharing one name race for the same
claims, and a stock k3s carries the upstream one, so a cluster running both
would settle our storage by chance. Data lives at /var/lib/hanzo/volume, so
reading a Hanzo cluster does not mean learning another vendor's directory.

Apache-2.0 as published, unaltered, with Rancher's attribution in NOTICE.

The README says what this is not: durability. A volume here dies with its
node. That is hanzoai/replicate's question, one layer up, and keeping the
two apart is what lets the disk stay this simple.
2026-09-07 17:30:01 -07:00

97 lines
3.0 KiB
Go

/*
Copyright 2023 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package wait
import (
"context"
"errors"
)
// ErrWaitTimeout is returned when the condition was not satisfied in time.
//
// Deprecated: This type will be made private in favor of Interrupted()
// for checking errors or ErrorInterrupted(err) for returning a wrapped error.
var ErrWaitTimeout = ErrorInterrupted(errors.New("timed out waiting for the condition"))
// Interrupted returns true if the error indicates a Poll, ExponentialBackoff, or
// Until loop exited for any reason besides the condition returning true or an
// error. A loop is considered interrupted if the calling context is cancelled,
// the context reaches its deadline, or a backoff reaches its maximum allowed
// steps.
//
// Callers should use this method instead of comparing the error value directly to
// ErrWaitTimeout, as methods that cancel a context may not return that error.
//
// Instead of:
//
// err := wait.Poll(...)
// if err == wait.ErrWaitTimeout {
// log.Infof("Wait for operation exceeded")
// } else ...
//
// Use:
//
// err := wait.Poll(...)
// if wait.Interrupted(err) {
// log.Infof("Wait for operation exceeded")
// } else ...
func Interrupted(err error) bool {
switch {
case errors.Is(err, errWaitTimeout),
errors.Is(err, context.Canceled),
errors.Is(err, context.DeadlineExceeded):
return true
default:
return false
}
}
// errInterrupted
type errInterrupted struct {
cause error
}
// ErrorInterrupted returns an error that indicates the wait was ended
// early for a given reason. If no cause is provided a generic error
// will be used but callers are encouraged to provide a real cause for
// clarity in debugging.
func ErrorInterrupted(cause error) error {
switch cause.(type) {
case errInterrupted:
// no need to wrap twice since errInterrupted is only needed
// once in a chain
return cause
default:
return errInterrupted{cause}
}
}
// errWaitTimeout is the private version of the previous ErrWaitTimeout
// and is private to prevent direct comparison. Use ErrorInterrupted(err)
// to get an error that will return true for Interrupted(err).
var errWaitTimeout = errInterrupted{}
func (e errInterrupted) Unwrap() error { return e.cause }
func (e errInterrupted) Is(target error) bool { return target == errWaitTimeout }
func (e errInterrupted) Error() string {
if e.cause == nil {
// returns the same error message as historical behavior
return "timed out waiting for the condition"
}
return e.cause.Error()
}