func (cli *DogestryCli) getLayerIdsToDownload(fromId remote.ID, imageRoot string, r remote.Remote, client *docker.Client) ([]remote.ID, error) { toDownload := make([]remote.ID, 0) err := r.WalkImages(fromId, func(id remote.ID, image docker.Image, err error) error { fmt.Printf("Examining id '%s' on remote docker host...\n", id.Short()) if err != nil { return err } _, err = client.InspectImage(string(id)) if err == docker.ErrNoSuchImage { toDownload = append(toDownload, id) return nil } else if err != nil { return err } else { fmt.Printf("Docker host already has id '%s', stop scanning.\n", id.Short()) return remote.BreakWalk } return nil }) return toDownload, err }
func (cli *DogestryCli) pullImage(fromId remote.ID, imageRoot string, r remote.Remote) error { toDownload, err := cli.getLayerIdsToDownload(fromId, imageRoot, r, cli.Client) if err != nil { return err } for _, id := range toDownload { downloadPath := filepath.Join(imageRoot, string(id)) fmt.Printf("Pulling image id '%s' to: %v\n", id.Short(), downloadPath) err := r.PullImageId(id, downloadPath) if err != nil { return err } } return nil }
func (cli *DogestryCli) downloadImages(r remote.Remote, downloadMap DownloadMap, imageRoot string) error { pullImagesErrMap := make(map[string]error) for id, _ := range downloadMap { downloadPath := filepath.Join(imageRoot, string(id)) fmt.Printf("Pulling image id '%s' to: %v\n", id.Short(), downloadPath) err := r.PullImageId(id, downloadPath) if err != nil { pullImagesErrMap[downloadPath] = err } } if len(pullImagesErrMap) > 0 { fmt.Printf("Errors pulling images: %v\n", pullImagesErrMap) return fmt.Errorf("Error downloading files from S3") } return nil }
func (cli *DogestryCli) exportToFiles(image string, r remote.Remote, imageRoot string) error { imageHistory, err := cli.Client.ImageHistory(image) if err != nil { fmt.Printf("Error getting image history: %v\n", err) return err } fmt.Println("Checking layers on remote") imageID := remote.ID(imageHistory[0].ID) repoName, repoTag := remote.NormaliseImageName(image) // Check the remote to see what layers are missing. Only missing Ids will // need to be saved to disk when exporting the docker image. missingIds := make(set) for _, i := range imageHistory { id := remote.ID(i.ID) _, err = r.ImageMetadata(id) if err == nil { fmt.Printf(" exists : %v\n", id) } else { fmt.Printf(" not found: %v\n", id) missingIds[id] = empty } } if len(missingIds) > 0 { if err := cli.exportImageToFiles(image, imageRoot, missingIds); err != nil { return err } } if err := cli.exportMetaDataToFiles(repoName, repoTag, imageID, imageRoot); err != nil { return err } return nil }
func (cli *DogestryCli) createRepositoriesJsonFile(image, imageRoot string, r remote.Remote) error { repoName, repoTag := remote.NormaliseImageName(image) id, err := r.ParseTag(repoName, repoTag) if err != nil { return err } else if id == "" { return nil } reposPath := filepath.Join(imageRoot, "repositories") reposFile, err := os.Create(reposPath) if err != nil { return err } defer reposFile.Close() repositories := map[string]Repository{} repositories[repoName] = Repository{} repositories[repoName][repoTag] = string(id) return json.NewEncoder(reposFile).Encode(&repositories) }