diff options
author | Brent Baude <bbaude@redhat.com> | 2021-08-10 08:10:56 -0500 |
---|---|---|
committer | Brent Baude <bbaude@redhat.com> | 2021-08-18 09:55:24 -0500 |
commit | cd40c875ac51b32f7b4e5479d02faee14e0ab12d (patch) | |
tree | 403914c909beea71186002553e09006e08ae2953 /pkg/domain | |
parent | a3d8b48fd56a722642f7cbcad52b2fa88f12b656 (diff) | |
download | podman-cd40c875ac51b32f7b4e5479d02faee14e0ab12d.tar.gz podman-cd40c875ac51b32f7b4e5479d02faee14e0ab12d.tar.bz2 podman-cd40c875ac51b32f7b4e5479d02faee14e0ab12d.zip |
Add ability to build images in play kube
When playing a kube YAML file, it can be desirable to be able to build
an image on the fly. This is good for development of an image and YAML
files and somewhat mocks what compose does.
Signed-off-by: Brent Baude <bbaude@redhat.com>
Diffstat (limited to 'pkg/domain')
-rw-r--r-- | pkg/domain/entities/play.go | 2 | ||||
-rw-r--r-- | pkg/domain/infra/abi/play.go | 131 |
2 files changed, 106 insertions, 27 deletions
diff --git a/pkg/domain/entities/play.go b/pkg/domain/entities/play.go index 89dfc08e9..01de73ebe 100644 --- a/pkg/domain/entities/play.go +++ b/pkg/domain/entities/play.go @@ -10,6 +10,8 @@ import ( type PlayKubeOptions struct { // Authfile - path to an authentication file. Authfile string + // Indicator to build all images with Containerfile or Dockerfile + Build bool // CertDir - to a directory containing TLS certifications and keys. CertDir string // Username for authenticating against the registry. diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go index d257bad18..6224feff5 100644 --- a/pkg/domain/infra/abi/play.go +++ b/pkg/domain/infra/abi/play.go @@ -7,9 +7,11 @@ import ( "io" "io/ioutil" "os" + "path/filepath" "strconv" "strings" + buildahDefine "github.com/containers/buildah/define" "github.com/containers/common/libimage" "github.com/containers/common/pkg/config" "github.com/containers/image/v5/types" @@ -266,39 +268,69 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY } containers := make([]*libpod.Container, 0, len(podYAML.Spec.Containers)) + cwd, err := os.Getwd() + if err != nil { + return nil, err + } for _, container := range podYAML.Spec.Containers { // Contains all labels obtained from kube labels := make(map[string]string) - - // NOTE: set the pull policy to "newer". This will cover cases - // where the "latest" tag requires a pull and will also - // transparently handle "localhost/" prefixed files which *may* - // refer to a locally built image OR an image running a - // registry on localhost. - pullPolicy := config.PullPolicyNewer - if len(container.ImagePullPolicy) > 0 { - // Make sure to lower the strings since K8s pull policy - // may be capitalized (see bugzilla.redhat.com/show_bug.cgi?id=1985905). - rawPolicy := string(container.ImagePullPolicy) - pullPolicy, err = config.ParsePullPolicy(strings.ToLower(rawPolicy)) - if err != nil { - return nil, err - } + var pulledImage *libimage.Image + buildFile, err := getBuildFile(container.Image, cwd) + if err != nil { + return nil, err } - // This ensures the image is the image store - pullOptions := &libimage.PullOptions{} - pullOptions.AuthFilePath = options.Authfile - pullOptions.CertDirPath = options.CertDir - pullOptions.SignaturePolicyPath = options.SignaturePolicy - pullOptions.Writer = writer - pullOptions.Username = options.Username - pullOptions.Password = options.Password - pullOptions.InsecureSkipTLSVerify = options.SkipTLSVerify - - pulledImages, err := ic.Libpod.LibimageRuntime().Pull(ctx, container.Image, pullPolicy, pullOptions) + existsLocally, err := ic.Libpod.LibimageRuntime().Exists(container.Image) if err != nil { return nil, err } + if (len(buildFile) > 0 && !existsLocally) || (len(buildFile) > 0 && options.Build) { + buildOpts := new(buildahDefine.BuildOptions) + commonOpts := new(buildahDefine.CommonBuildOptions) + buildOpts.ConfigureNetwork = buildahDefine.NetworkDefault + buildOpts.Isolation = buildahDefine.IsolationChroot + buildOpts.CommonBuildOpts = commonOpts + buildOpts.Output = container.Image + if _, _, err := ic.Libpod.Build(ctx, *buildOpts, []string{buildFile}...); err != nil { + return nil, err + } + i, _, err := ic.Libpod.LibimageRuntime().LookupImage(container.Image, new(libimage.LookupImageOptions)) + if err != nil { + return nil, err + } + pulledImage = i + } else { + // NOTE: set the pull policy to "newer". This will cover cases + // where the "latest" tag requires a pull and will also + // transparently handle "localhost/" prefixed files which *may* + // refer to a locally built image OR an image running a + // registry on localhost. + pullPolicy := config.PullPolicyNewer + if len(container.ImagePullPolicy) > 0 { + // Make sure to lower the strings since K8s pull policy + // may be capitalized (see bugzilla.redhat.com/show_bug.cgi?id=1985905). + rawPolicy := string(container.ImagePullPolicy) + pullPolicy, err = config.ParsePullPolicy(strings.ToLower(rawPolicy)) + if err != nil { + return nil, err + } + } + // This ensures the image is the image store + pullOptions := &libimage.PullOptions{} + pullOptions.AuthFilePath = options.Authfile + pullOptions.CertDirPath = options.CertDir + pullOptions.SignaturePolicyPath = options.SignaturePolicy + pullOptions.Writer = writer + pullOptions.Username = options.Username + pullOptions.Password = options.Password + pullOptions.InsecureSkipTLSVerify = options.SkipTLSVerify + + pulledImages, err := ic.Libpod.LibimageRuntime().Pull(ctx, container.Image, pullPolicy, pullOptions) + if err != nil { + return nil, err + } + pulledImage = pulledImages[0] + } // Handle kube annotations for k, v := range annotations { @@ -318,7 +350,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY specgenOpts := kube.CtrSpecGenOptions{ Container: container, - Image: pulledImages[0], + Image: pulledImage, Volumes: volumes, PodID: pod.ID(), PodName: podName, @@ -509,3 +541,48 @@ func sortKubeKinds(documentList [][]byte) ([][]byte, error) { return sortedDocumentList, nil } +func imageNamePrefix(imageName string) string { + prefix := imageName + s := strings.Split(prefix, ":") + if len(s) > 0 { + prefix = s[0] + } + s = strings.Split(prefix, "/") + if len(s) > 0 { + prefix = s[len(s)-1] + } + s = strings.Split(prefix, "@") + if len(s) > 0 { + prefix = s[0] + } + return prefix +} + +func getBuildFile(imageName string, cwd string) (string, error) { + buildDirName := imageNamePrefix(imageName) + containerfilePath := filepath.Join(cwd, buildDirName, "Containerfile") + dockerfilePath := filepath.Join(cwd, buildDirName, "Dockerfile") + + _, err := os.Stat(filepath.Join(containerfilePath)) + if err == nil { + logrus.Debugf("building %s with %s", imageName, containerfilePath) + return containerfilePath, nil + } + // If the error is not because the file does not exist, take + // a mulligan and try Dockerfile. If that also fails, return that + // error + if err != nil && !os.IsNotExist(err) { + logrus.Errorf("%v: unable to check for %s", err, containerfilePath) + } + + _, err = os.Stat(filepath.Join(dockerfilePath)) + if err == nil { + logrus.Debugf("building %s with %s", imageName, dockerfilePath) + return dockerfilePath, nil + } + // Strike two + if os.IsNotExist(err) { + return "", nil + } + return "", err +} |