2020-05-18 08:55:25 +02:00
|
|
|
package cmd
|
|
|
|
|
|
|
|
import (
|
2022-02-28 14:57:23 +02:00
|
|
|
"fmt"
|
2020-05-18 08:55:25 +02:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
piperDocker "github.com/SAP/jenkins-library/pkg/docker"
|
|
|
|
"github.com/SAP/jenkins-library/pkg/log"
|
2022-02-28 14:57:23 +02:00
|
|
|
"github.com/SAP/jenkins-library/pkg/piperutils"
|
2020-05-18 08:55:25 +02:00
|
|
|
"github.com/SAP/jenkins-library/pkg/telemetry"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
)
|
|
|
|
|
|
|
|
func containerSaveImage(config containerSaveImageOptions, telemetryData *telemetry.CustomData) {
|
|
|
|
var cachePath = "./cache"
|
|
|
|
|
|
|
|
dClientOptions := piperDocker.ClientOptions{ImageName: config.ContainerImage, RegistryURL: config.ContainerRegistryURL, LocalPath: config.FilePath, IncludeLayers: config.IncludeLayers}
|
|
|
|
dClient := &piperDocker.Client{}
|
|
|
|
dClient.SetOptions(dClientOptions)
|
|
|
|
|
2022-02-28 14:57:23 +02:00
|
|
|
_, err := runContainerSaveImage(&config, telemetryData, cachePath, "", dClient, piperutils.Files{})
|
2020-05-18 08:55:25 +02:00
|
|
|
if err != nil {
|
|
|
|
log.Entry().WithError(err).Fatal("step execution failed")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-28 14:57:23 +02:00
|
|
|
func runContainerSaveImage(config *containerSaveImageOptions, telemetryData *telemetry.CustomData, cachePath, rootPath string, dClient piperDocker.Download, fileUtils piperutils.FileUtils) (string, error) {
|
|
|
|
if err := correctContainerDockerConfigEnvVar(config, fileUtils); err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
2020-05-18 08:55:25 +02:00
|
|
|
err := os.RemoveAll(cachePath)
|
|
|
|
if err != nil {
|
2022-01-24 10:48:01 +02:00
|
|
|
return "", errors.Wrap(err, "failed to prepare cache")
|
2020-05-18 08:55:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
err = os.Mkdir(cachePath, 0755)
|
|
|
|
if err != nil {
|
2022-01-24 10:48:01 +02:00
|
|
|
return "", errors.Wrap(err, "failed to create cache")
|
2020-05-18 08:55:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ensure that download cache is cleaned up at the end
|
|
|
|
defer os.RemoveAll(cachePath)
|
|
|
|
|
|
|
|
imageSource, err := dClient.GetImageSource()
|
|
|
|
if err != nil {
|
2022-01-24 10:48:01 +02:00
|
|
|
return "", errors.Wrap(err, "failed to get docker image source")
|
2020-05-18 08:55:25 +02:00
|
|
|
}
|
|
|
|
image, err := dClient.DownloadImageToPath(imageSource, cachePath)
|
|
|
|
if err != nil {
|
2022-01-24 10:48:01 +02:00
|
|
|
return "", errors.Wrap(err, "failed to download docker image")
|
2020-05-18 08:55:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
tarfilePath := config.FilePath
|
|
|
|
if len(tarfilePath) == 0 {
|
|
|
|
tarfilePath = filenameFromContainer(rootPath, config.ContainerImage)
|
2021-12-13 17:14:32 +02:00
|
|
|
} else {
|
|
|
|
tarfilePath = filenameFromContainer(rootPath, tarfilePath)
|
2020-05-18 08:55:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
tarFile, err := os.Create(tarfilePath)
|
|
|
|
if err != nil {
|
2022-01-24 10:48:01 +02:00
|
|
|
return "", errors.Wrapf(err, "failed to create %v for docker image", tarfilePath)
|
2020-05-18 08:55:25 +02:00
|
|
|
}
|
|
|
|
defer tarFile.Close()
|
|
|
|
|
|
|
|
if err := os.Chmod(tarfilePath, 0644); err != nil {
|
2022-01-24 10:48:01 +02:00
|
|
|
return "", errors.Wrapf(err, "failed to adapt permissions on %v", tarfilePath)
|
2020-05-18 08:55:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
err = dClient.TarImage(tarFile, image)
|
|
|
|
if err != nil {
|
2022-01-24 10:48:01 +02:00
|
|
|
return "", errors.Wrap(err, "failed to tar container image")
|
2020-05-18 08:55:25 +02:00
|
|
|
}
|
|
|
|
|
2022-01-24 10:48:01 +02:00
|
|
|
return tarfilePath, nil
|
2020-05-18 08:55:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func filenameFromContainer(rootPath, containerImage string) string {
|
|
|
|
return filepath.Join(rootPath, strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(containerImage, "/", "_"), ":", "_"), ".", "_")+".tar")
|
|
|
|
}
|
2022-02-28 14:57:23 +02:00
|
|
|
|
|
|
|
func correctContainerDockerConfigEnvVar(config *containerSaveImageOptions, utils piperutils.FileUtils) error {
|
|
|
|
dockerConfigDir, err := utils.TempDir("", "docker")
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "unable to create docker config dir")
|
|
|
|
}
|
|
|
|
|
|
|
|
dockerConfigFile := fmt.Sprintf("%s/%s", dockerConfigDir, "config.json")
|
|
|
|
|
|
|
|
if len(config.DockerConfigJSON) > 0 {
|
|
|
|
log.Entry().Infof("Docker credentials configuration: %v", config.DockerConfigJSON)
|
|
|
|
|
|
|
|
if exists, _ := utils.FileExists(config.DockerConfigJSON); exists {
|
|
|
|
if _, err = utils.Copy(config.DockerConfigJSON, dockerConfigFile); err != nil {
|
|
|
|
return errors.Wrap(err, "unable to copy docker config")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
log.Entry().Info("Docker credentials configuration: NONE")
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(config.ContainerRegistryURL) > 0 && len(config.ContainerRegistryUser) > 0 && len(config.ContainerRegistryPassword) > 0 {
|
|
|
|
if _, err = piperDocker.CreateDockerConfigJSON(config.ContainerRegistryURL, config.ContainerRegistryUser, config.ContainerRegistryPassword, dockerConfigFile, dockerConfigFile, utils); err != nil {
|
|
|
|
log.Entry().Warningf("failed to update Docker config.json: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
os.Setenv("DOCKER_CONFIG", dockerConfigDir)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|