Akihiro Suda 6b65b0c982 new driver: kubernetes
Tested with `kind` and GKE.

Note: "nodes" shown in `docker buildx ls` are unrelated to Kubernetes "nodes".
Probably buildx should come up with an alternative term.

Usage:

  $ kind create cluster
  $ export KUBECONFIG="$(kind get kubeconfig-path --name="kind")"

  $ docker buildx create --driver kubernetes --driver-opt replicas=3 --use
  $ docker buildx build -t foo --load .

`--load` loads the image into the local Docker.

Driver opts:

  - `image=IMAGE` - Sets the container image to be used for running buildkit.
  - `namespace=NS` - Sets the Kubernetes namespace. Defaults to the current namespace.
  - `replicas=N` - Sets the number of `Pod` replicas. Defaults to 1.
  - `rootless=(true|false)` - Run the container as a non-root user without `securityContext.privileged`. Defaults to false.
  - `loadbalance=(sticky|random)` - Load-balancing strategy. If set to "sticky", the pod is chosen using the hash of the context path. Defaults to "sticky"

Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
2019-11-21 10:30:39 +09:00

103 lines
2.7 KiB
Go

package gophercloud
import (
"fmt"
"net/url"
"path/filepath"
"strings"
"time"
)
// WaitFor polls a predicate function, once per second, up to a timeout limit.
// This is useful to wait for a resource to transition to a certain state.
// To handle situations when the predicate might hang indefinitely, the
// predicate will be prematurely cancelled after the timeout.
// Resource packages will wrap this in a more convenient function that's
// specific to a certain resource, but it can also be useful on its own.
func WaitFor(timeout int, predicate func() (bool, error)) error {
type WaitForResult struct {
Success bool
Error error
}
start := time.Now().Unix()
for {
// If a timeout is set, and that's been exceeded, shut it down.
if timeout >= 0 && time.Now().Unix()-start >= int64(timeout) {
return fmt.Errorf("A timeout occurred")
}
time.Sleep(1 * time.Second)
var result WaitForResult
ch := make(chan bool, 1)
go func() {
defer close(ch)
satisfied, err := predicate()
result.Success = satisfied
result.Error = err
}()
select {
case <-ch:
if result.Error != nil {
return result.Error
}
if result.Success {
return nil
}
// If the predicate has not finished by the timeout, cancel it.
case <-time.After(time.Duration(timeout) * time.Second):
return fmt.Errorf("A timeout occurred")
}
}
}
// NormalizeURL is an internal function to be used by provider clients.
//
// It ensures that each endpoint URL has a closing `/`, as expected by
// ServiceClient's methods.
func NormalizeURL(url string) string {
if !strings.HasSuffix(url, "/") {
return url + "/"
}
return url
}
// NormalizePathURL is used to convert rawPath to a fqdn, using basePath as
// a reference in the filesystem, if necessary. basePath is assumed to contain
// either '.' when first used, or the file:// type fqdn of the parent resource.
// e.g. myFavScript.yaml => file://opt/lib/myFavScript.yaml
func NormalizePathURL(basePath, rawPath string) (string, error) {
u, err := url.Parse(rawPath)
if err != nil {
return "", err
}
// if a scheme is defined, it must be a fqdn already
if u.Scheme != "" {
return u.String(), nil
}
// if basePath is a url, then child resources are assumed to be relative to it
bu, err := url.Parse(basePath)
if err != nil {
return "", err
}
var basePathSys, absPathSys string
if bu.Scheme != "" {
basePathSys = filepath.FromSlash(bu.Path)
absPathSys = filepath.Join(basePathSys, rawPath)
bu.Path = filepath.ToSlash(absPathSys)
return bu.String(), nil
}
absPathSys = filepath.Join(basePath, rawPath)
u.Path = filepath.ToSlash(absPathSys)
if err != nil {
return "", err
}
u.Scheme = "file"
return u.String(), nil
}