Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for image component on podman #6577

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/website/docs/overview/configure.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<sup>(1)</sup> | 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<sup>(1)</sup> | 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`.
1 change: 1 addition & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
11 changes: 8 additions & 3 deletions pkg/dev/podmandev/command.go
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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 {
Expand Down
5 changes: 5 additions & 0 deletions pkg/dev/podmandev/podmandev.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -38,6 +39,8 @@ const (
)

type DevClient struct {
fs filesystem.Filesystem

podmanClient podman.Client
syncClient sync.Client
execClient exec.Client
Expand All @@ -51,13 +54,15 @@ type DevClient struct {
var _ dev.Client = (*DevClient)(nil)

func NewDevClient(
fs filesystem.Filesystem,
podmanClient podman.Client,
syncClient sync.Client,
execClient exec.Client,
stateClient state.Client,
watchClient watch.Client,
) *DevClient {
return &DevClient{
fs: fs,
podmanClient: podmanClient,
syncClient: syncClient,
execClient: execClient,
Expand Down
2 changes: 2 additions & 0 deletions pkg/dev/podmandev/reconcile.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
8 changes: 7 additions & 1 deletion pkg/devfile/image/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions pkg/odo/genericclioptions/clientset/clientset.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
12 changes: 12 additions & 0 deletions tests/helper/component_podman.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
2 changes: 1 addition & 1 deletion tests/integration/cmd_dev_debug_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
}
Expand Down
73 changes: 40 additions & 33 deletions tests/integration/cmd_dev_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down