summarylogtreecommitdiffstats
path: root/get-docker-cache-id.go
diff options
context:
space:
mode:
Diffstat (limited to 'get-docker-cache-id.go')
-rw-r--r--get-docker-cache-id.go149
1 files changed, 149 insertions, 0 deletions
diff --git a/get-docker-cache-id.go b/get-docker-cache-id.go
new file mode 100644
index 000000000000..cbaf367cda6a
--- /dev/null
+++ b/get-docker-cache-id.go
@@ -0,0 +1,149 @@
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "os"
+ "strings"
+ "io/ioutil"
+)
+
+const DOCKER_DB_DIR = "/var/lib/docker/image/btrfs"
+const REPO_FILE = DOCKER_DB_DIR + "/repositories.json"
+const CFG_FILE = "/etc/docker-btrfs.json"
+
+func getImageTag() (string, string) {
+ buf, err := ioutil.ReadFile(CFG_FILE)
+ if err != nil {
+ panic(err)
+ }
+ var dat map[string]interface{}
+ err = json.Unmarshal(buf, &dat)
+ if err != nil {
+ panic(err)
+ }
+ return dat["docker_image"].(string), dat["docker_tag"].(string)
+}
+
+func getImageId(image string, tag string) string {
+ buf, err := ioutil.ReadFile(REPO_FILE)
+ if err != nil {
+ panic(err)
+ }
+ var dat map[string]interface{}
+ err = json.Unmarshal(buf, &dat)
+ if err != nil {
+ panic(err)
+ }
+ repositories := dat["Repositories"].(map[string]interface{})
+ imageTags := repositories[image].(map[string]interface{})
+ return imageTags[image+":"+tag].(string)
+}
+
+func getDiffIds(imgId string) []string {
+ imgPath := strings.Replace(imgId, ":", "/", 1)
+ buf, err := ioutil.ReadFile(DOCKER_DB_DIR + "/imagedb/content/" + imgPath)
+ if err != nil {
+ panic(err)
+ }
+ var dat map[string]interface{}
+ err = json.Unmarshal(buf, &dat)
+ if err != nil {
+ panic(err)
+ }
+ rootfs := dat["rootfs"].(map[string]interface{})
+ diffIdsInterface := rootfs["diff_ids"].([]interface{})
+ diffIdsStr := make([]string, len(diffIdsInterface))
+ for i, v := range diffIdsInterface {
+ diffIdsStr[i] = strings.Replace(v.(string), "sha256:", "", 1)
+ }
+ return diffIdsStr
+}
+
+type Node struct {
+ parent string
+ id string
+ diff string
+ cache string
+}
+
+func getNode(id string) Node {
+ var node Node
+
+ node.id = id
+
+ buf, err := ioutil.ReadFile(DOCKER_DB_DIR + "/layerdb/sha256/" + id + "/cache-id")
+ if err != nil {
+ panic(err)
+ }
+ node.cache = strings.Replace(string(buf), "sha256:", "", 1)
+
+ buf, err = ioutil.ReadFile(DOCKER_DB_DIR + "/layerdb/sha256/" + id + "/diff")
+ if err != nil {
+ panic(err)
+ }
+ node.diff = strings.Replace(string(buf), "sha256:", "", 1)
+
+ buf, err = ioutil.ReadFile(DOCKER_DB_DIR + "/layerdb/sha256/" + id + "/parent")
+ if os.IsNotExist(err) {
+ node.parent = ""
+ } else if err != nil {
+ panic(err)
+ } else {
+ node.parent = strings.Replace(string(buf), "sha256:", "", 1)
+ }
+ return node
+}
+
+func readLayerInfo() map[string]Node {
+ files, err := ioutil.ReadDir(DOCKER_DB_DIR + "/layerdb/sha256/")
+ if err != nil {
+ panic(err)
+ }
+ nodes := make(map[string]Node)
+ for i, _ := range files {
+ id := files[i].Name()
+ nodes[id] = getNode(id)
+ }
+ return nodes
+}
+
+func searchForCacheId(diffIds []string, layers map[string]Node) string {
+ candidates := make([]string, 0, len(layers))
+ last := diffIds[len(diffIds)-1]
+ for i, v := range layers {
+ if v.diff == last {
+ sz := len(candidates)
+ candidates = candidates[:sz+1]
+ candidates[sz] = i
+ }
+ }
+ candidatesCurrent := make([]string, len(candidates))
+ for i, v := range candidates {
+ candidatesCurrent[i] = layers[v].parent
+ }
+ for i := len(diffIds)-2; i>=0; i-- {
+ for j := 0; j < len(candidates); {
+ if layers[candidatesCurrent[j]].diff == diffIds[i] {
+ candidatesCurrent[j] = layers[candidatesCurrent[j]].parent
+ j++;
+ } else {
+ oldLen := len(candidates)
+ candidates[j] = candidates[oldLen-1]
+ candidatesCurrent[j] = candidatesCurrent[oldLen-1]
+ candidates = candidates[:oldLen-1]
+ candidatesCurrent = candidatesCurrent[:oldLen - 1]
+ }
+ }
+ }
+ return candidates[0]
+}
+
+func main() {
+ image, tag := getImageTag()
+ imgId := getImageId(image, tag)
+ diffIds := getDiffIds(imgId)
+ layers := readLayerInfo()
+ cacheId := searchForCacheId(diffIds, layers)
+ fmt.Print(cacheId)
+}