summaryrefslogtreecommitdiff
path: root/pkg/domain
diff options
context:
space:
mode:
authorBrent Baude <bbaude@redhat.com>2021-08-10 08:10:56 -0500
committerBrent Baude <bbaude@redhat.com>2021-08-18 09:55:24 -0500
commitcd40c875ac51b32f7b4e5479d02faee14e0ab12d (patch)
tree403914c909beea71186002553e09006e08ae2953 /pkg/domain
parenta3d8b48fd56a722642f7cbcad52b2fa88f12b656 (diff)
downloadpodman-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.go2
-rw-r--r--pkg/domain/infra/abi/play.go131
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
+}