mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-21 18:58:03 +08:00
commands: add implementations for create, use, rm, stop
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
109
store/nodegroup.go
Normal file
109
store/nodegroup.go
Normal file
@@ -0,0 +1,109 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type NodeGroup struct {
|
||||
Name string
|
||||
Driver string
|
||||
Nodes []Node
|
||||
}
|
||||
|
||||
type Node struct {
|
||||
Name string
|
||||
Endpoint string
|
||||
Platforms []string
|
||||
}
|
||||
|
||||
func (ng *NodeGroup) Leave(name string) error {
|
||||
i := ng.findNode(name)
|
||||
if i == -1 {
|
||||
return errors.Errorf("node %q not found for %s", name, ng.Name)
|
||||
}
|
||||
if len(ng.Nodes) == 1 {
|
||||
return errors.Errorf("can not leave last node, do you want to rm instance instead?")
|
||||
}
|
||||
ng.Nodes = append(ng.Nodes[:i], ng.Nodes[i+1:]...)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ng *NodeGroup) Update(name, endpoint string, platforms []string, endpointsSet bool, actionAppend bool) error {
|
||||
i := ng.findNode(name)
|
||||
if i == -1 && !actionAppend {
|
||||
ng.Nodes = nil
|
||||
}
|
||||
if i != -1 {
|
||||
n := ng.Nodes[i]
|
||||
if endpointsSet {
|
||||
n.Endpoint = endpoint
|
||||
}
|
||||
if len(platforms) > 0 {
|
||||
n.Platforms = platforms
|
||||
}
|
||||
ng.Nodes[i] = n
|
||||
if err := ng.validateDuplicates(endpoint); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if name == "" {
|
||||
name = ng.nextNodeName()
|
||||
}
|
||||
|
||||
name, err := ValidateName(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n := Node{
|
||||
Name: name,
|
||||
Endpoint: endpoint,
|
||||
Platforms: platforms,
|
||||
}
|
||||
ng.Nodes = append(ng.Nodes, n)
|
||||
|
||||
if err := ng.validateDuplicates(endpoint); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ng *NodeGroup) validateDuplicates(ep string) error {
|
||||
// TODO: reset platforms
|
||||
i := 0
|
||||
for _, n := range ng.Nodes {
|
||||
if n.Endpoint == ep {
|
||||
i++
|
||||
}
|
||||
}
|
||||
if i > 1 {
|
||||
return errors.Errorf("invalid duplicate endpoint %s", ep)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ng *NodeGroup) findNode(name string) int {
|
||||
i := -1
|
||||
for ii, n := range ng.Nodes {
|
||||
if n.Name == name {
|
||||
i = ii
|
||||
}
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
func (ng *NodeGroup) nextNodeName() string {
|
||||
i := 0
|
||||
for {
|
||||
name := fmt.Sprintf("%s%d", ng.Name, i)
|
||||
if i := ng.findNode(name); i != -1 {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
return name
|
||||
}
|
||||
}
|
@@ -8,27 +8,13 @@ import (
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/gofrs/flock"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type NodeGroup struct {
|
||||
Name string
|
||||
Driver string
|
||||
Nodes []Node
|
||||
Endpoint string
|
||||
}
|
||||
|
||||
type Node struct {
|
||||
Name string
|
||||
Endpoint string
|
||||
Platforms []string
|
||||
}
|
||||
|
||||
func NewStore(root string) (*Store, error) {
|
||||
func New(root string) (*Store, error) {
|
||||
root = filepath.Join(root, "buildx")
|
||||
if err := os.MkdirAll(filepath.Join(root, "instances"), 0700); err != nil {
|
||||
return nil, err
|
||||
@@ -86,7 +72,7 @@ func (t *Txn) List() ([]*NodeGroup, error) {
|
||||
}
|
||||
|
||||
func (t *Txn) NodeGroupByName(name string) (*NodeGroup, error) {
|
||||
name, err := validateName(name)
|
||||
name, err := ValidateName(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -102,7 +88,7 @@ func (t *Txn) NodeGroupByName(name string) (*NodeGroup, error) {
|
||||
}
|
||||
|
||||
func (t *Txn) Save(ng *NodeGroup) error {
|
||||
name, err := validateName(ng.Name)
|
||||
name, err := ValidateName(ng.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -114,7 +100,7 @@ func (t *Txn) Save(ng *NodeGroup) error {
|
||||
}
|
||||
|
||||
func (t *Txn) Remove(name string) error {
|
||||
name, err := validateName(name)
|
||||
name, err := ValidateName(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -215,14 +201,7 @@ type current struct {
|
||||
Global bool
|
||||
}
|
||||
|
||||
var namePattern = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9\.\-_\+]*$`)
|
||||
|
||||
func validateName(s string) (string, error) {
|
||||
if !namePattern.MatchString(s) {
|
||||
return "", errors.Errorf("invalid name %s, name needs to start with a letter and may not contain symbols, except ._-", s)
|
||||
}
|
||||
return strings.ToLower(s), nil
|
||||
}
|
||||
var namePattern = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9\.\-_]*$`)
|
||||
|
||||
func atomicWriteFile(filename string, data []byte, perm os.FileMode) error {
|
||||
f, err := ioutil.TempFile(filepath.Dir(filename), ".tmp-"+filepath.Base(filename))
|
||||
|
32
store/util.go
Normal file
32
store/util.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/pkg/namesgenerator"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func ValidateName(s string) (string, error) {
|
||||
if !namePattern.MatchString(s) {
|
||||
return "", errors.Errorf("invalid name %s, name needs to start with a letter and may not contain symbols, except ._-", s)
|
||||
}
|
||||
return strings.ToLower(s), nil
|
||||
}
|
||||
|
||||
func GenerateName(txn *Txn) (string, error) {
|
||||
var name string
|
||||
for i := 0; i < 6; i++ {
|
||||
name = namesgenerator.GetRandomName(i)
|
||||
if _, err := txn.NodeGroupByName(name); err != nil {
|
||||
if !os.IsNotExist(errors.Cause(err)) {
|
||||
return "", err
|
||||
}
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
return name, nil
|
||||
}
|
||||
return "", errors.Errorf("failed to generate random name")
|
||||
}
|
Reference in New Issue
Block a user