Beispiel #1
0
// 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
}
Beispiel #2
0
func (rb *RepositoryBackend) buildACIV1(layerNumber int, layerID string, dockerURL *types.ParsedDockerURL, outputDir string, tmpBaseDir string, curPwl []string, compress bool) (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, compress)
	if err != nil {
		return "", nil, fmt.Errorf("error generating ACI: %v", err)
	}

	return aciPath, manifest, nil
}
Beispiel #3
0
func (lb *FileBackend) BuildACI(layerID string, dockerURL *types.ParsedDockerURL, outputDir string, curPwl []string, compress bool) (string, *schema.ImageManifest, error) {
	tmpDir, err := ioutil.TempDir("", "docker2aci-")
	if err != nil {
		return "", nil, fmt.Errorf("error creating dir: %v", err)
	}

	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(layerData, dockerURL, outputDir, layerFile, curPwl, compress)
	if err != nil {
		return "", nil, fmt.Errorf("error generating ACI: %v", err)
	}

	return aciPath, manifest, nil
}
Beispiel #4
0
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
}
Beispiel #5
0
// 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) (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); 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
}
Beispiel #6
0
func convertReal(backend Docker2ACIBackend, dockerURL string, squash bool, outputDir string, tmpDir string) ([]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
		aciPath, manifest, err := backend.BuildACI(i, layerID, parsedDockerURL, layersOutputDir, tmpDir, curPwl, !squash)
		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)
		if err != nil {
			return nil, fmt.Errorf("error squashing image: %v", err)
		}
		aciLayerPaths = []string{squashedImagePath}
	}

	return aciLayerPaths, nil
}
Beispiel #7
0
func (rb *RepositoryBackend) buildACIV2(layerNumber int, layerID string, dockerURL *types.ParsedDockerURL, outputDir string, tmpBaseDir string, curPwl []string, compress bool) (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, compress)
	if err != nil {
		return "", nil, fmt.Errorf("error generating ACI: %v", err)
	}

	return aciPath, aciManifest, nil
}