// SquashLayers receives a list of ACI layer file names ordered from base image // to application image and squashes them into one ACI func SquashLayers(images []acirenderer.Image, aciRegistry acirenderer.ACIRegistry, parsedDockerURL types.ParsedDockerURL, outputDir string) (string, error) { util.Debug("Squashing layers...") util.Debug("Rendering ACI...") renderedACI, err := acirenderer.GetRenderedACIFromList(images, aciRegistry) if err != nil { return "", fmt.Errorf("error rendering squashed image: %v", err) } manifests, err := getManifests(renderedACI, aciRegistry) if err != nil { return "", fmt.Errorf("error getting manifests: %v", err) } squashedFilename := getSquashedFilename(parsedDockerURL) squashedImagePath := path.Join(outputDir, squashedFilename) squashedImageFile, err := os.Create(squashedImagePath) if err != nil { return "", err } defer squashedImageFile.Close() util.Debug("Writing squashed ACI...") if err := writeSquashedImage(squashedImageFile, renderedACI, aciRegistry, manifests); err != nil { return "", fmt.Errorf("error writing squashed image: %v", err) } util.Debug("Validating squashed ACI...") if err := common.ValidateACI(squashedImagePath); err != nil { return "", fmt.Errorf("error validating image: %v", err) } util.Debug("ACI squashed!") return squashedImagePath, nil }
func (lb *FileBackend) BuildACI(layerNumber int, layerID string, dockerURL *types.ParsedDockerURL, outputDir string, tmpBaseDir string, curPwl []string, compression common.Compression) (string, *schema.ImageManifest, error) { tmpDir, err := ioutil.TempDir(tmpBaseDir, "docker2aci-") if err != nil { return "", nil, fmt.Errorf("error creating dir: %v", err) } defer os.RemoveAll(tmpDir) j, err := getJson(lb.file, layerID) if err != nil { return "", nil, fmt.Errorf("error getting image json: %v", err) } layerData := types.DockerImageData{} if err := json.Unmarshal(j, &layerData); err != nil { return "", nil, fmt.Errorf("error unmarshaling layer data: %v", err) } tmpLayerPath := path.Join(tmpDir, layerID) tmpLayerPath += ".tar" layerFile, err := extractEmbeddedLayer(lb.file, layerID, tmpLayerPath) if err != nil { return "", nil, fmt.Errorf("error getting layer from file: %v", err) } defer layerFile.Close() util.Debug("Generating layer ACI...") aciPath, manifest, err := common.GenerateACI(layerNumber, layerData, dockerURL, outputDir, layerFile, curPwl, compression) if err != nil { return "", nil, fmt.Errorf("error generating ACI: %v", err) } return aciPath, manifest, nil }
func convertPorts(dockerExposedPorts map[string]struct{}, dockerPortSpecs []string) ([]appctypes.Port, error) { ports := []appctypes.Port{} for ep := range dockerExposedPorts { appcPort, err := parseDockerPort(ep) if err != nil { return nil, err } ports = append(ports, *appcPort) } if dockerExposedPorts == nil && dockerPortSpecs != nil { util.Debug("warning: docker image uses deprecated PortSpecs field") for _, ep := range dockerPortSpecs { appcPort, err := parseDockerPort(ep) if err != nil { return nil, err } ports = append(ports, *appcPort) } } sort.Sort(appcPortSorter(ports)) return ports, nil }
func (rb *RepositoryBackend) buildACIV1(layerNumber int, layerID string, dockerURL *types.ParsedDockerURL, outputDir string, tmpBaseDir string, curPwl []string, compression common.Compression) (string, *schema.ImageManifest, error) { tmpDir, err := ioutil.TempDir(tmpBaseDir, "docker2aci-") if err != nil { return "", nil, fmt.Errorf("error creating dir: %v", err) } defer os.RemoveAll(tmpDir) j, size, err := rb.getJsonV1(layerID, rb.repoData.Endpoints[0], rb.repoData) if err != nil { return "", nil, fmt.Errorf("error getting image json: %v", err) } layerData := types.DockerImageData{} if err := json.Unmarshal(j, &layerData); err != nil { return "", nil, fmt.Errorf("error unmarshaling layer data: %v", err) } layerFile, err := rb.getLayerV1(layerID, rb.repoData.Endpoints[0], rb.repoData, size, tmpDir) if err != nil { return "", nil, fmt.Errorf("error getting the remote layer: %v", err) } defer layerFile.Close() util.Debug("Generating layer ACI...") aciPath, manifest, err := common.GenerateACI(layerNumber, layerData, dockerURL, outputDir, layerFile, curPwl, compression) if err != nil { return "", nil, fmt.Errorf("error generating ACI: %v", err) } return aciPath, manifest, nil }
// SquashLayers receives a list of ACI layer file names ordered from base image // to application image and squashes them into one ACI func SquashLayers(images []acirenderer.Image, aciRegistry acirenderer.ACIRegistry, parsedDockerURL types.ParsedDockerURL, outputDir string, compression common.Compression) (path string, err error) { util.Debug("Squashing layers...") util.Debug("Rendering ACI...") renderedACI, err := acirenderer.GetRenderedACIFromList(images, aciRegistry) if err != nil { return "", fmt.Errorf("error rendering squashed image: %v", err) } manifests, err := getManifests(renderedACI, aciRegistry) if err != nil { return "", fmt.Errorf("error getting manifests: %v", err) } squashedFilename := getSquashedFilename(parsedDockerURL) squashedImagePath := filepath.Join(outputDir, squashedFilename) squashedTempFile, err := ioutil.TempFile(outputDir, "docker2aci-squashedFile-") if err != nil { return "", err } defer func() { if err == nil { err = squashedTempFile.Close() } else { // remove temp file on error // we ignore its error to not mask the real error os.Remove(squashedTempFile.Name()) } }() util.Debug("Writing squashed ACI...") if err := writeSquashedImage(squashedTempFile, renderedACI, aciRegistry, manifests, compression); err != nil { return "", fmt.Errorf("error writing squashed image: %v", err) } util.Debug("Validating squashed ACI...") if err := common.ValidateACI(squashedTempFile.Name()); err != nil { return "", fmt.Errorf("error validating image: %v", err) } if err := os.Rename(squashedTempFile.Name(), squashedImagePath); err != nil { return "", err } util.Debug("ACI squashed!") return squashedImagePath, nil }
func convertReal(backend Docker2ACIBackend, dockerURL string, squash bool, outputDir string, tmpDir string, compression common.Compression) ([]string, error) { util.Debug("Getting image info...") ancestry, parsedDockerURL, err := backend.GetImageInfo(dockerURL) if err != nil { return nil, err } layersOutputDir := outputDir if squash { layersOutputDir, err = ioutil.TempDir(tmpDir, "docker2aci-") if err != nil { return nil, fmt.Errorf("error creating dir: %v", err) } defer os.RemoveAll(layersOutputDir) } conversionStore := NewConversionStore() var images acirenderer.Images var aciLayerPaths []string var curPwl []string for i := len(ancestry) - 1; i >= 0; i-- { layerID := ancestry[i] // only compress individual layers if we're not squashing layerCompression := compression if squash { layerCompression = common.NoCompression } aciPath, manifest, err := backend.BuildACI(i, layerID, parsedDockerURL, layersOutputDir, tmpDir, curPwl, layerCompression) if err != nil { return nil, fmt.Errorf("error building layer: %v", err) } key, err := conversionStore.WriteACI(aciPath) if err != nil { return nil, fmt.Errorf("error inserting in the conversion store: %v", err) } images = append(images, acirenderer.Image{Im: manifest, Key: key, Level: uint16(i)}) aciLayerPaths = append(aciLayerPaths, aciPath) curPwl = manifest.PathWhitelist } // acirenderer expects images in order from upper to base layer images = util.ReverseImages(images) if squash { squashedImagePath, err := SquashLayers(images, conversionStore, *parsedDockerURL, outputDir, compression) if err != nil { return nil, fmt.Errorf("error squashing image: %v", err) } aciLayerPaths = []string{squashedImagePath} } return aciLayerPaths, nil }
func (rb *RepositoryBackend) buildACIV2(layerNumber int, layerID string, dockerURL *types.ParsedDockerURL, outputDir string, tmpBaseDir string, curPwl []string, compression common.Compression) (string, *schema.ImageManifest, error) { manifest := rb.imageManifests[*dockerURL] layerIndex, err := getLayerIndex(layerID, manifest) if err != nil { return "", nil, err } if len(manifest.History) <= layerIndex { return "", nil, fmt.Errorf("history not found for layer %s", layerID) } layerData := types.DockerImageData{} if err := json.Unmarshal([]byte(manifest.History[layerIndex].V1Compatibility), &layerData); err != nil { return "", nil, fmt.Errorf("error unmarshaling layer data: %v", err) } tmpDir, err := ioutil.TempDir(tmpBaseDir, "docker2aci-") if err != nil { return "", nil, fmt.Errorf("error creating dir: %v", err) } defer os.RemoveAll(tmpDir) layerFile, err := rb.getLayerV2(layerID, dockerURL, tmpDir) if err != nil { return "", nil, fmt.Errorf("error getting the remote layer: %v", err) } defer layerFile.Close() util.Debug("Generating layer ACI...") aciPath, aciManifest, err := common.GenerateACI(layerNumber, layerData, dockerURL, outputDir, layerFile, curPwl, compression) if err != nil { return "", nil, fmt.Errorf("error generating ACI: %v", err) } return aciPath, aciManifest, nil }