| 
									
										
										
										
											2023-11-23 05:28:49 +08:00
										 |  |  | package server | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"crypto/sha256" | 
					
						
							| 
									
										
										
										
											2024-08-06 08:13:52 +08:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2023-11-23 05:28:49 +08:00
										 |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"io" | 
					
						
							|  |  |  | 	"os" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type Layer struct { | 
					
						
							|  |  |  | 	MediaType string `json:"mediaType"` | 
					
						
							|  |  |  | 	Digest    string `json:"digest"` | 
					
						
							|  |  |  | 	Size      int64  `json:"size"` | 
					
						
							|  |  |  | 	From      string `json:"from,omitempty"` | 
					
						
							| 
									
										
										
										
											2024-04-13 04:55:12 +08:00
										 |  |  | 	status    string | 
					
						
							| 
									
										
										
										
											2023-11-23 05:28:49 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-08 05:22:17 +08:00
										 |  |  | func NewLayer(r io.Reader, mediatype string) (Layer, error) { | 
					
						
							| 
									
										
										
										
											2023-11-23 05:28:49 +08:00
										 |  |  | 	blobs, err := GetBlobsPath("") | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2024-08-08 05:22:17 +08:00
										 |  |  | 		return Layer{}, err | 
					
						
							| 
									
										
										
										
											2023-11-23 05:28:49 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-13 04:55:12 +08:00
										 |  |  | 	temp, err := os.CreateTemp(blobs, "sha256-") | 
					
						
							| 
									
										
										
										
											2023-11-23 05:28:49 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2024-08-08 05:22:17 +08:00
										 |  |  | 		return Layer{}, err | 
					
						
							| 
									
										
										
										
											2023-11-23 05:28:49 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	defer temp.Close() | 
					
						
							| 
									
										
										
										
											2024-04-13 04:55:12 +08:00
										 |  |  | 	defer os.Remove(temp.Name()) | 
					
						
							| 
									
										
										
										
											2023-11-23 05:28:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	sha256sum := sha256.New() | 
					
						
							|  |  |  | 	n, err := io.Copy(io.MultiWriter(temp, sha256sum), r) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2024-08-08 05:22:17 +08:00
										 |  |  | 		return Layer{}, err | 
					
						
							| 
									
										
										
										
											2023-11-23 05:28:49 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-13 04:55:12 +08:00
										 |  |  | 	if err := temp.Close(); err != nil { | 
					
						
							| 
									
										
										
										
											2024-08-08 05:22:17 +08:00
										 |  |  | 		return Layer{}, err | 
					
						
							| 
									
										
										
										
											2024-04-13 04:55:12 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	digest := fmt.Sprintf("sha256:%x", sha256sum.Sum(nil)) | 
					
						
							|  |  |  | 	blob, err := GetBlobsPath(digest) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2024-08-08 05:22:17 +08:00
										 |  |  | 		return Layer{}, err | 
					
						
							| 
									
										
										
										
											2024-04-13 04:55:12 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	status := "using existing layer" | 
					
						
							|  |  |  | 	if _, err := os.Stat(blob); err != nil { | 
					
						
							|  |  |  | 		status = "creating new layer" | 
					
						
							|  |  |  | 		if err := os.Rename(temp.Name(), blob); err != nil { | 
					
						
							| 
									
										
										
										
											2024-08-08 05:22:17 +08:00
										 |  |  | 			return Layer{}, err | 
					
						
							| 
									
										
										
										
											2024-04-13 04:55:12 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-08 05:22:17 +08:00
										 |  |  | 	return Layer{ | 
					
						
							| 
									
										
										
										
											2024-04-13 04:55:12 +08:00
										 |  |  | 		MediaType: mediatype, | 
					
						
							|  |  |  | 		Digest:    digest, | 
					
						
							|  |  |  | 		Size:      n, | 
					
						
							|  |  |  | 		status:    fmt.Sprintf("%s %s", status, digest), | 
					
						
							| 
									
										
										
										
											2023-11-23 05:28:49 +08:00
										 |  |  | 	}, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-08 05:22:17 +08:00
										 |  |  | func NewLayerFromLayer(digest, mediatype, from string) (Layer, error) { | 
					
						
							| 
									
										
										
										
											2024-08-06 08:13:52 +08:00
										 |  |  | 	if digest == "" { | 
					
						
							| 
									
										
										
										
											2024-08-08 05:22:17 +08:00
										 |  |  | 		return Layer{}, errors.New("creating new layer from layer with empty digest") | 
					
						
							| 
									
										
										
										
											2024-08-06 08:13:52 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-23 05:28:49 +08:00
										 |  |  | 	blob, err := GetBlobsPath(digest) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2024-08-08 05:22:17 +08:00
										 |  |  | 		return Layer{}, err | 
					
						
							| 
									
										
										
										
											2023-11-23 05:28:49 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fi, err := os.Stat(blob) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2024-08-08 05:22:17 +08:00
										 |  |  | 		return Layer{}, err | 
					
						
							| 
									
										
										
										
											2023-11-23 05:28:49 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-08 05:22:17 +08:00
										 |  |  | 	return Layer{ | 
					
						
							| 
									
										
										
										
											2023-11-23 05:28:49 +08:00
										 |  |  | 		MediaType: mediatype, | 
					
						
							|  |  |  | 		Digest:    digest, | 
					
						
							|  |  |  | 		Size:      fi.Size(), | 
					
						
							|  |  |  | 		From:      from, | 
					
						
							| 
									
										
										
										
											2024-04-13 04:55:12 +08:00
										 |  |  | 		status:    fmt.Sprintf("using existing layer %s", digest), | 
					
						
							| 
									
										
										
										
											2023-11-23 05:28:49 +08:00
										 |  |  | 	}, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-11 06:48:41 +08:00
										 |  |  | func (l *Layer) Open() (io.ReadSeekCloser, error) { | 
					
						
							| 
									
										
										
										
											2024-08-06 08:13:52 +08:00
										 |  |  | 	if l.Digest == "" { | 
					
						
							|  |  |  | 		return nil, errors.New("opening layer with empty digest") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-23 05:28:49 +08:00
										 |  |  | 	blob, err := GetBlobsPath(l.Digest) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2024-04-13 04:55:12 +08:00
										 |  |  | 		return nil, err | 
					
						
							| 
									
										
										
										
											2023-11-23 05:28:49 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-13 04:55:12 +08:00
										 |  |  | 	return os.Open(blob) | 
					
						
							| 
									
										
										
										
											2023-11-23 05:28:49 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2024-04-18 08:23:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | func (l *Layer) Remove() error { | 
					
						
							| 
									
										
										
										
											2024-08-06 08:13:52 +08:00
										 |  |  | 	if l.Digest == "" { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-18 08:23:19 +08:00
										 |  |  | 	ms, err := Manifests() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, m := range ms { | 
					
						
							| 
									
										
										
										
											2024-08-08 05:22:17 +08:00
										 |  |  | 		for _, layer := range append(m.Layers, m.Config) { | 
					
						
							| 
									
										
										
										
											2024-04-18 08:23:19 +08:00
										 |  |  | 			if layer.Digest == l.Digest { | 
					
						
							|  |  |  | 				// something is using this layer
 | 
					
						
							|  |  |  | 				return nil | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	blob, err := GetBlobsPath(l.Digest) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return os.Remove(blob) | 
					
						
							|  |  |  | } |