diff --git a/docs/website/docs/overview/configure.md b/docs/website/docs/overview/configure.md
index 331f63f80fd..b2b110b9d99 100644
--- a/docs/website/docs/overview/configure.md
+++ b/docs/website/docs/overview/configure.md
@@ -190,6 +190,7 @@ Options here are mostly used for debugging and testing `odo` behavior.
| `DEVFILE_PROXY` | Integration tests will use this address as Devfile registry instead of `registry.stage.devfile.io` | v3.0.0-beta3 | `my-registry.example.com` |
| `TELEMETRY_CALLER` | Caller identifier passed to [telemetry](https://github.com/redhat-developer/odo/blob/main/USAGE_DATA.md). Case-insensitive. Acceptable values: `vscode`, `intellij`, `jboss`. | v3.1.0 | `intellij` |
| `ODO_TRACKING_CONSENT` | Useful for controlling [telemetry](https://github.com/redhat-developer/odo/blob/main/USAGE_DATA.md). Acceptable values: `yes` ([enables telemetry](https://github.com/redhat-developer/odo/blob/main/USAGE_DATA.md) and skips consent prompt), `no` (disables telemetry and consent prompt). Takes precedence over the [`ConsentTelemetry`](#preference-key-table) preference. | v3.2.0 | `yes` |
-| `ODO_EXPERIMENTAL_MODE` | Whether to enable experimental features. See [Experimental Mode](../user-guides/advanced/experimental-mode) for more details. Acceptable values: boolean values(1) | v3.3.0 | `true` |
+| `ODO_EXPERIMENTAL_MODE` | Whether to enable experimental features. See [Experimental Mode](../user-guides/advanced/experimental-mode) for more details. Acceptable values: boolean values(1) | v3.3.0 | `true` |
+| `ODO_PUSH_IMAGES` | Whether to push the images once built; this is used only when applying Devfile image components as part of a Dev Session running on Podman; this is useful for integration tests running on Podman. `true` by default | v3.7.0 | `false` |
(1) Accepted boolean values are: `1`, `t`, `T`, `TRUE`, `true`, `True`, `0`, `f`, `F`, `FALSE`, `false`, `False`.
\ No newline at end of file
diff --git a/pkg/config/config.go b/pkg/config/config.go
index de086fd585a..a329d28b230 100644
--- a/pkg/config/config.go
+++ b/pkg/config/config.go
@@ -17,6 +17,7 @@ type Configuration struct {
PodmanCmd string `env:"PODMAN_CMD,default=podman"`
TelemetryCaller string `env:"TELEMETRY_CALLER,default="`
OdoExperimentalMode bool `env:"ODO_EXPERIMENTAL_MODE,default=false"`
+ PushImages bool `env:"ODO_PUSH_IMAGES,default=true"`
}
// GetConfiguration initializes a Configuration for odo by using the system environment.
diff --git a/pkg/dev/podmandev/command.go b/pkg/dev/podmandev/command.go
index 053edd14a65..9e5c183c16f 100644
--- a/pkg/dev/podmandev/command.go
+++ b/pkg/dev/podmandev/command.go
@@ -1,17 +1,24 @@
package podmandev
import (
+ "context"
+
devfilev1 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
"k8s.io/klog"
"github.com/redhat-developer/odo/pkg/component"
+ envcontext "github.com/redhat-developer/odo/pkg/config/context"
+ "github.com/redhat-developer/odo/pkg/devfile/image"
"github.com/redhat-developer/odo/pkg/exec"
"github.com/redhat-developer/odo/pkg/libdevfile"
"github.com/redhat-developer/odo/pkg/log"
"github.com/redhat-developer/odo/pkg/platform"
+ "github.com/redhat-developer/odo/pkg/testingutil/filesystem"
)
type commandHandler struct {
+ ctx context.Context
+ fs filesystem.Filesystem
execClient exec.Client
platformClient platform.Client
componentExists bool
@@ -23,9 +30,7 @@ type commandHandler struct {
var _ libdevfile.Handler = (*commandHandler)(nil)
func (a commandHandler) ApplyImage(img devfilev1.Component) error {
- klog.V(4).Info("apply image commands are not implemented on podman")
- log.Warningf("Apply Image commands are not implemented on Podman. Skipping: %v", img.Name)
- return nil
+ return image.BuildPushSpecificImage(a.ctx, a.fs, img, envcontext.GetEnvConfig(a.ctx).PushImages)
}
func (a commandHandler) ApplyKubernetes(kubernetes devfilev1.Component) error {
diff --git a/pkg/dev/podmandev/podmandev.go b/pkg/dev/podmandev/podmandev.go
index b887dec7d59..875b4c55f68 100644
--- a/pkg/dev/podmandev/podmandev.go
+++ b/pkg/dev/podmandev/podmandev.go
@@ -25,6 +25,7 @@ import (
"github.com/redhat-developer/odo/pkg/podman"
"github.com/redhat-developer/odo/pkg/state"
"github.com/redhat-developer/odo/pkg/sync"
+ "github.com/redhat-developer/odo/pkg/testingutil/filesystem"
"github.com/redhat-developer/odo/pkg/watch"
corev1 "k8s.io/api/core/v1"
@@ -38,6 +39,8 @@ const (
)
type DevClient struct {
+ fs filesystem.Filesystem
+
podmanClient podman.Client
syncClient sync.Client
execClient exec.Client
@@ -51,6 +54,7 @@ type DevClient struct {
var _ dev.Client = (*DevClient)(nil)
func NewDevClient(
+ fs filesystem.Filesystem,
podmanClient podman.Client,
syncClient sync.Client,
execClient exec.Client,
@@ -58,6 +62,7 @@ func NewDevClient(
watchClient watch.Client,
) *DevClient {
return &DevClient{
+ fs: fs,
podmanClient: podmanClient,
syncClient: syncClient,
execClient: execClient,
diff --git a/pkg/dev/podmandev/reconcile.go b/pkg/dev/podmandev/reconcile.go
index dc59ec2db32..0d6511d0b7b 100644
--- a/pkg/dev/podmandev/reconcile.go
+++ b/pkg/dev/podmandev/reconcile.go
@@ -97,6 +97,8 @@ func (o *DevClient) reconcile(
cmdName = options.DebugCommand
}
cmdHandler := commandHandler{
+ ctx: ctx,
+ fs: o.fs,
execClient: o.execClient,
platformClient: o.podmanClient,
componentExists: componentStatus.RunExecuted,
diff --git a/pkg/devfile/image/image.go b/pkg/devfile/image/image.go
index b23b0c92b12..8a09203c8b6 100644
--- a/pkg/devfile/image/image.go
+++ b/pkg/devfile/image/image.go
@@ -83,7 +83,13 @@ func buildPushImage(backend Backend, fs filesystem.Filesystem, image *devfile.Im
if image == nil {
return errors.New("image should not be nil")
}
- log.Sectionf("Building & Pushing Container: %s", image.ImageName)
+ var msg string
+ if push {
+ msg = "Building & Pushing Image: %s"
+ } else {
+ msg = "Building Image: %s"
+ }
+ log.Sectionf(msg, image.ImageName)
err := backend.Build(fs, image, devfilePath)
if err != nil {
return err
diff --git a/pkg/odo/genericclioptions/clientset/clientset.go b/pkg/odo/genericclioptions/clientset/clientset.go
index f1d44e0cc95..160e2d2e5f0 100644
--- a/pkg/odo/genericclioptions/clientset/clientset.go
+++ b/pkg/odo/genericclioptions/clientset/clientset.go
@@ -242,6 +242,7 @@ func Fetch(command *cobra.Command, platform string) (*Clientset, error) {
switch platform {
case commonflags.PlatformPodman:
dep.DevClient = podmandev.NewDevClient(
+ dep.FS,
dep.PodmanClient,
dep.SyncClient,
dep.ExecClient,
diff --git a/tests/helper/component_podman.go b/tests/helper/component_podman.go
index 23767d82674..08b5754e0f4 100644
--- a/tests/helper/component_podman.go
+++ b/tests/helper/component_podman.go
@@ -141,3 +141,15 @@ func (o *PodmanComponent) GetPodLogs() string {
})
return string(stdout)
}
+
+func (o *PodmanComponent) ListImages() string {
+ cmd := exec.Command("podman", "images", "--format", "{{.Repository}}:{{.Tag}}", "--noheading")
+ stdout, err := cmd.Output()
+ Expect(err).ToNot(HaveOccurred(), func() {
+ if exiterr, ok := err.(*exec.ExitError); ok {
+ err = fmt.Errorf("%s: %s", err, string(exiterr.Stderr))
+ }
+ fmt.Fprintln(GinkgoWriter, err)
+ })
+ return string(stdout)
+}
diff --git a/tests/integration/cmd_dev_debug_test.go b/tests/integration/cmd_dev_debug_test.go
index 5a58a50fb39..c34a28d4046 100644
--- a/tests/integration/cmd_dev_debug_test.go
+++ b/tests/integration/cmd_dev_debug_test.go
@@ -246,7 +246,7 @@ var _ = Describe("odo dev debug command tests", func() {
helper.MatchAllInOutput(string(out), deploymentNames)
}
checkImageBuilt := func() {
- Expect(string(sessionOut)).To(ContainSubstring("Building & Pushing Container"))
+ Expect(string(sessionOut)).To(ContainSubstring("Building & Pushing Image"))
Expect(string(sessionOut)).To(ContainSubstring("build -t quay.io/unknown-account/myimage -f " + filepath.Join(commonVar.Context, "Dockerfile ") + commonVar.Context))
Expect(string(sessionOut)).To(ContainSubstring("push quay.io/unknown-account/myimage"))
}
diff --git a/tests/integration/cmd_dev_test.go b/tests/integration/cmd_dev_test.go
index c3b39419996..7aba3bcfb53 100644
--- a/tests/integration/cmd_dev_test.go
+++ b/tests/integration/cmd_dev_test.go
@@ -2923,41 +2923,48 @@ CMD ["npm", "start"]
})
}))
}
- for _, ctx := range []struct {
- title string
- resources, args []string
- }{
- {
- title: "with run command",
- resources: []string{"deploy-k8s-resource", "deploy-a-third-k8s-resource", "image-build-component"},
- },
- {
- title: "with debug command",
- resources: []string{"deploy-another-k8s-resource", "deploy-a-third-k8s-resource", "image-build-component"},
- args: []string{"--debug"},
- },
- } {
- ctx := ctx
- When("using devfile that contains K8s resource to run it on podman", Label(helper.LabelPodman), func() {
- BeforeEach(func() {
- helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project"), commonVar.Context)
- helper.CopyExampleDevFile(
- filepath.Join("source", "devfiles", "nodejs", "devfile-composite-apply-different-commandgk.yaml"),
- filepath.Join(commonVar.Context, "devfile.yaml"),
- helper.DevfileMetadataNameSetter(cmpName))
- })
- It(fmt.Sprintf("should show warning about being unable to create the resource when running odo dev %s on podman", ctx.title), func() {
- err := helper.RunDevMode(helper.DevSessionOpts{RunOnPodman: true, CmdlineArgs: ctx.args}, func(session *gexec.Session, outContents, errContents []byte, ports map[string]string) {
- Expect(string(errContents)).To(ContainSubstring("Kubernetes components are not supported on Podman. Skipping: "))
- Expect(string(errContents)).To(ContainSubstring("Apply Kubernetes components are not supported on Podman. Skipping: "))
- Expect(string(errContents)).To(ContainSubstring("Apply Image commands are not implemented on Podman. Skipping: "))
- helper.MatchAllInOutput(string(errContents), ctx.resources)
- })
- Expect(err).ToNot(HaveOccurred())
- })
+
+ When("using devfile that contains K8s resource to run it on podman", Label(helper.LabelPodman), func() {
+ const (
+ imgName = "quay.io/unknown-account/myimage" // hard coded from the devfile-composite-apply-different-commandgk.yaml
+ )
+ var customImgName string
+
+ var session helper.DevSession
+ var outContents, errContents []byte
+ BeforeEach(func() {
+ customImgName = fmt.Sprintf("%s:%s", imgName, cmpName)
+ helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
+ helper.CopyExampleDevFile(
+ filepath.Join("source", "devfiles", "nodejs", "devfile-composite-apply-different-commandgk.yaml"),
+ filepath.Join(commonVar.Context, "devfile.yaml"),
+ helper.DevfileMetadataNameSetter(cmpName),
+ )
+ helper.ReplaceString(filepath.Join(commonVar.Context, "devfile.yaml"), imgName, customImgName)
+ var err error
+ session, outContents, errContents, _, err = helper.StartDevMode(
+ helper.DevSessionOpts{RunOnPodman: true, EnvVars: []string{"ODO_PUSH_IMAGES=false"}},
+ )
+ Expect(err).ToNot(HaveOccurred())
+ })
+ AfterEach(func() {
+ session.Stop()
+ session.WaitEnd()
+ })
+ It("should show warning about being unable to create the resource when running odo dev on podman", func() {
+ Expect(string(errContents)).To(ContainSubstring("Kubernetes components are not supported on Podman. Skipping: "))
+ Expect(string(errContents)).To(ContainSubstring("Apply Kubernetes components are not supported on Podman. Skipping: "))
+ helper.MatchAllInOutput(string(errContents), []string{"deploy-k8s-resource", "deploy-a-third-k8s-resource"})
})
- }
+ It("should build the images when running odo dev on podman", func() {
+ // we do not test push because then it becomes complex to setup image registry credentials to pull the image
+ // all pods created by odo have a `PullAlways` image policy.
+ Expect(string(outContents)).To(ContainSubstring("Building Image: %s", customImgName))
+ component := helper.NewPodmanComponent(cmpName, "app")
+ Expect(component.ListImages()).To(ContainSubstring(customImgName))
+ })
+ })
for _, podman := range []bool{true, false} {
podman := podman