func()

in kinder/pkg/build/alter/alter.go [280:405]


func (c *Context) alterImage(bitsInstallers []bits.Installer, bc *bits.BuildContext) error {
	// get the container runtime from the base image
	runtime, err := status.InspectCRIinImage(c.baseImage)
	if err != nil {
		return errors.Wrap(err, "error detecting CRI!")
	}
	log.Infof("Detected %s as container runtime", runtime)

	alterHelper, err := nodes.NewAlterHelper(runtime)
	if err != nil {
		return err
	}

	// get the args for the alter container depending on the underlying CR
	runArgs, containerArgs := alterHelper.GetAlterContainerArgs()

	// create final alter container
	// NOTE: we are using docker run + docker commit so we can install
	// debians without permanently copying them into the image.
	// if docker gets proper squash support, we can rm them instead
	// This also allows the KubeBit implementations to perform programmatic
	// install in the image
	log.Debug("Starting alter container ...")
	containerID, err := c.createAlterContainer(bc, runArgs, containerArgs)
	// ensure we will delete it
	if containerID != "" {
		defer func() {
			exec.NewHostCmd("docker", "rm", "-f", "-v", containerID).Run()
		}()
	}
	if err != nil {
		log.Errorf("Image alter Failed! %v", err)
		return err
	}

	// alter the image, tagged as tagImageAs, using the our tempdir as the context
	log.Debug("Starting image alter ...")

	// binds the BuildContext the container
	bc.BindToContainer(containerID)

	// Make sure the /kind/images folder exists
	if err := bc.RunInContainer("mkdir", "-p", "/kind/images"); err != nil {
		return err
	}

	// install the bits that are used to alter the image
	log.Info("Starting bits install ...")
	for _, b := range bitsInstallers {
		if err = b.Install(bc); err != nil {
			log.Errorf("Image build Failed! %v", err)
			return err
		}
	}

	log.Info("Setup CRI ...")
	if err := alterHelper.SetupCRI(bc); err != nil {
		return errors.Wrapf(err, "image build Failed! Failed to setup %s", runtime)
	}

	log.Info("Start CRI ...")
	if err := alterHelper.StartCRI(bc); err != nil {
		return errors.Wrapf(err, "image build Failed! Failed to start %s", runtime)
	}

	log.Info("Pre-loading images ...")
	if err := alterHelper.PreLoadInitImages(bc, "/kind/images"); err != nil {
		return errors.Wrapf(err, "image build Failed! Failed to start %s", runtime)
	}

	if c.prePullAdditionalImages {
		log.Info("Pre-pulling additional images ...")

		// pull images required for init / join
		initPath := "/kind"
		images, err := alterHelper.GetImagesForKubeadmBinary(bc, filepath.Join(initPath, "bin", "kubeadm"))
		if err != nil {
			return err
		}

		if err := pullImages(alterHelper, bc, images, filepath.Join(initPath, "images"), containerID); err != nil {
			return err
		}

		// pull images required for upgrade
		upgradePath := "/kinder/upgrade"
		// check if the version file for the upgrade artifacts is in place
		versionFile := filepath.Join(upgradePath, "version")
		version, err := bc.CombinedOutputLinesInContainer(
			"bash",
			"-c",
			"cat "+versionFile+" 2> /dev/null",
		)

		// don't return the error if the version file is missing
		if err == nil {
			if len(version) != 1 {
				return errors.Errorf("expected the version file %q to have 1 line, got: %v", versionFile, version)
			}

			// use the resulting upgrade path e.g. /kinder/upgrade/v1.19.0-alpha.3.36+8c4e3faed35411
			upgradeImages, err := alterHelper.GetImagesForKubeadmBinary(bc, filepath.Join(upgradePath, version[0], "kubeadm"))
			if err != nil {
				return err
			}

			if err := pullImages(alterHelper, bc, upgradeImages, filepath.Join(upgradePath, version[0]), containerID); err != nil {
				return err
			}
		}
	}

	log.Info("Stop CRI ...")
	if err := alterHelper.StopCRI(bc); err != nil {
		return errors.Wrapf(err, "image build Failed! Failed to stop %s", runtime)
	}

	log.Infof("Commit to %s ...", c.image)
	if err = alterHelper.Commit(containerID, c.image); err != nil {
		return errors.Wrap(err, "image alter Failed! Failed to commit image")
	}

	log.Info("Image alter completed.")

	return nil
}