mirror of https://github.com/docker/buildx.git
buildx: rollback configuration if create fails
This builds on the added warnings from initialized builders, now erroring the command, and additionally attempting to revert to the previous configuration. To preserve the previous configuration, we add a deep Copy() function to the NodeGroup and Node so that we can easily restore it later if we encounter a failure. Signed-off-by: Justin Chadwell <me@jedevc.com>
This commit is contained in:
parent
309c49413c
commit
86825a95ce
|
@ -134,6 +134,11 @@ func runCreate(dockerCli command.Cli, in createOptions, args []string) error {
|
|||
}
|
||||
}
|
||||
|
||||
ngOriginal := ng
|
||||
if ngOriginal != nil {
|
||||
ngOriginal = ngOriginal.Copy()
|
||||
}
|
||||
|
||||
if ng == nil {
|
||||
ng = &store.NodeGroup{
|
||||
Name: name,
|
||||
|
@ -224,16 +229,6 @@ func runCreate(dockerCli command.Cli, in createOptions, args []string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if in.use && ep != "" {
|
||||
current, err := storeutil.GetCurrentEndpoint(dockerCli)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := txn.SetCurrent(current, ng.Name, false, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
ngi := &nginfo{ng: ng}
|
||||
|
||||
timeoutCtx, cancel := context.WithTimeout(ctx, 20*time.Second)
|
||||
|
@ -244,7 +239,27 @@ func runCreate(dockerCli command.Cli, in createOptions, args []string) error {
|
|||
}
|
||||
for _, info := range ngi.drivers {
|
||||
if err := info.di.Err; err != nil {
|
||||
logrus.Errorf("failed to initialize builder %s (%s): %s", ng.Name, info.di.Name, err)
|
||||
err := errors.Errorf("failed to initialize builder %s (%s): %s", ng.Name, info.di.Name, err)
|
||||
var err2 error
|
||||
if ngOriginal == nil {
|
||||
err2 = txn.Remove(ng.Name)
|
||||
} else {
|
||||
err2 = txn.Save(ngOriginal)
|
||||
}
|
||||
if err2 != nil {
|
||||
logrus.Warnf("Could not rollback to previous state: %s", err2)
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if in.use && ep != "" {
|
||||
current, err := storeutil.GetCurrentEndpoint(dockerCli)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := txn.SetCurrent(current, ng.Name, false, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -110,6 +110,44 @@ func (ng *NodeGroup) Update(name, endpoint string, platforms []string, endpoints
|
|||
return nil
|
||||
}
|
||||
|
||||
func (ng *NodeGroup) Copy() *NodeGroup {
|
||||
nodes := make([]Node, len(ng.Nodes))
|
||||
for i, node := range ng.Nodes {
|
||||
nodes[i] = *node.Copy()
|
||||
}
|
||||
return &NodeGroup{
|
||||
Name: ng.Name,
|
||||
Driver: ng.Driver,
|
||||
Nodes: nodes,
|
||||
Dynamic: ng.Dynamic,
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Node) Copy() *Node {
|
||||
platforms := []specs.Platform{}
|
||||
copy(platforms, n.Platforms)
|
||||
flags := []string{}
|
||||
copy(flags, n.Flags)
|
||||
driverOpts := map[string]string{}
|
||||
for k, v := range n.DriverOpts {
|
||||
driverOpts[k] = v
|
||||
}
|
||||
files := map[string][]byte{}
|
||||
for k, v := range n.Files {
|
||||
vv := []byte{}
|
||||
copy(vv, v)
|
||||
files[k] = vv
|
||||
}
|
||||
return &Node{
|
||||
Name: n.Name,
|
||||
Endpoint: n.Endpoint,
|
||||
Platforms: platforms,
|
||||
Flags: flags,
|
||||
DriverOpts: driverOpts,
|
||||
Files: files,
|
||||
}
|
||||
}
|
||||
|
||||
func (ng *NodeGroup) validateDuplicates(ep string, idx int) error {
|
||||
i := 0
|
||||
for _, n := range ng.Nodes {
|
||||
|
|
Loading…
Reference in New Issue