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