Skip to content

Commit cf18f90

Browse files
Shalin Patelfaiq
Shalin Patel
andauthored
feat: podman as a supported container engine (#809)
* feat: podman as a supported container engine in konvoy image builder (#789) * feat: podman as a supported container engine in konvoy image builder * ci: run gcp e2e tests using podman * fix linting error * revert back github action job * ci: run gcp e2e tests using podman * removeme: test github actions flow * build using goreleaser build command * test podman * ci: run sample GHA aws e2e job using podman * run podman as root user * Faiq/kib podman (#801) * fix: move dir to /opt * fix: only mount /etc/grp and /etc/usr * fix: set user and group only in docker * fix: adds nolint * add security opt only for podman engine * ci: run podman kib e2e tests in github actions --------- Co-authored-by: shalin patel <[email protected]> * remove setting container engine using env variable * add user id mapping only for docker runner * allow users to specify container engine * inline export KIB_CONTAINER_ENGINE Co-authored-by: Faiq <[email protected]> --------- Co-authored-by: Faiq <[email protected]> * chore: fix embedded image's tag --------- Co-authored-by: Faiq <[email protected]>
1 parent 0a26aa9 commit cf18f90

File tree

8 files changed

+160
-107
lines changed

8 files changed

+160
-107
lines changed

.github/workflows/podman-aws-e2e.yaml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Runs Azure tests when pull request opened, repopened or synchronized
2+
name: Podman E2E Tests - Build AWS AMI
3+
on:
4+
workflow_dispatch:
5+
pull_request:
6+
types: [labeled, synchronize]
7+
8+
permissions:
9+
contents: read
10+
id-token: write
11+
12+
jobs:
13+
rune2e:
14+
runs-on: ubuntu-latest
15+
continue-on-error: false
16+
if: |
17+
github.event_name == 'pull_request' &&
18+
(
19+
(github.event.action == 'labeled' && (github.event.label.name == 'runs-e2e-tests' || github.event.label.name == 'runs-aws-tests')) ||
20+
(github.event.action == 'synchronize' && (contains(github.event.pull_request.labels.*.name, 'runs-e2e-tests') || contains(github.event.pull_request.labels.*.name, 'runs-aws-tests')))
21+
)
22+
steps:
23+
- name: Checkout konvoy-image-builder repository
24+
uses: actions/checkout@v3
25+
with:
26+
fetch-depth: 0
27+
ref: ${{ github.ref }}
28+
29+
- name: Set up Go
30+
uses: actions/setup-go@v4
31+
with:
32+
go-version-file: 'go.mod'
33+
cache: true
34+
35+
- name: Login to dockerhub Registry
36+
uses: docker/login-action@v2
37+
with:
38+
username: ${{ secrets.NEXUS_USERNAME }}
39+
password: ${{ secrets.NEXUS_PASSWORD }}
40+
41+
- name: Login to D2iQ's Mirror Registry
42+
uses: docker/login-action@v2
43+
with:
44+
registry: ${{ secrets.D2IQ_DOCKER_MIRROR_REGISTRY}}
45+
username: ${{ secrets.NEXUS_USERNAME }}
46+
password: ${{ secrets.NEXUS_PASSWORD }}
47+
48+
- name: Setup buildkit
49+
uses: docker/setup-buildx-action@v2
50+
51+
- name: Configure AWS Credentials
52+
uses: aws-actions/configure-aws-credentials@v2
53+
with:
54+
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/konvoy-image-builder
55+
aws-region: us-west-2
56+
57+
- name: Download GoReleaser
58+
run: go install github.com/goreleaser/[email protected]
59+
60+
- name: Build snapshot
61+
run: make build.snapshot
62+
63+
- name: Run E2E test for AWS centos 7.9 using podman
64+
run: |-
65+
KIB_CONTAINER_ENGINE=podman dist/konvoy-image-wrapper_linux_amd64_v1/konvoy-image build aws images/ami/centos-79.yaml --dry-run
66+
env:
67+
GITHUB_TOKEN: ${{ secrets.MESOSPHERECI_USER_TOKEN }}
68+
KIB_CONTAINER_ENGINE: podman

.goreleaser.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ builds:
6767
env:
6868
- DOCKER_DEVKIT_DEFAULT_ARGS="--rm"
6969
- BUILDARCH={{.Arch }}
70+
- REPO_REV=v{{trimprefix .Version "v"}}
7071

7172
archives:
7273
- id: konvoy-image-bundle

Dockerfile

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,8 @@ COPY --from=devkit /usr/local/bin/govc /usr/local/bin/
3838
COPY --from=devkit /root/.config/packer/plugins/ ${PACKER_PLUGIN_PATH}
3939
COPY --from=devkit /usr/share/ansible/collections/ansible_collections/ /usr/share/ansible/collections/ansible_collections/
4040
COPY bin/konvoy-image-${BUILDARCH} /usr/local/bin/konvoy-image
41-
COPY images /root/images
42-
COPY ansible /root/ansible
43-
COPY packer /root/packer
41+
COPY images /opt/images
42+
COPY ansible /opt/ansible
4443

45-
WORKDIR /root
44+
WORKDIR /opt
4645
ENTRYPOINT ["/usr/local/bin/konvoy-image"]

Makefile

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -497,19 +497,12 @@ mod-tidy: ## go mod tidy
497497
$(call print-target)
498498
go mod tidy
499499

500+
GORELEASER_SINGLE_TARGET ?= true
500501
.PHONY: build.snapshot
501502
build.snapshot: dist/konvoy-image_linux_amd64/konvoy-image
502503
build.snapshot:
503504
$(call print-target)
504-
# NOTE(jkoelker) shenanigans to get around goreleaser and
505-
# `make release-bundle` being able to share the same
506-
# `Dockerfile`. Unfortunatly goreleaser forbids
507-
# copying the dist folder into the temporary folder
508-
# that it uses as its docker build context ;(.
509-
# NOTE (faiq): does anyone use this target?
510-
mkdir -p bin
511-
cp dist/konvoy-image_linux_$(BUILDARCH)/konvoy-image bin/konvoy-image
512-
goreleaser --parallelism=1 --skip-publish --snapshot --clean
505+
goreleaser build --parallelism=1 --snapshot --single-target=$(GORELEASER_SINGLE_TARGET) --clean
513506

514507
.PHONY: diff
515508
diff: ## git diff

cmd/konvoy-image-wrapper/cmd/wrapper.go

Lines changed: 71 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cmd
22

33
import (
4+
"bytes"
45
"errors"
56
"fmt"
67
"log"
@@ -60,8 +61,11 @@ const (
6061
envHTTPProxy = "HTTP_PROXY"
6162
envNoProxy = "NO_PROXY"
6263

63-
containerWorkingDir = "/tmp/kib"
64-
windows = "windows"
64+
containerWorkingDir = "/tmp/kib"
65+
windows = "windows"
66+
containerEngineEnv = "KIB_CONTAINER_ENGINE"
67+
containerEngineDocker = "docker"
68+
containerEnginePodman = "podman"
6569
)
6670

6771
var ErrEnv = errors.New("manifest not support")
@@ -71,8 +75,6 @@ func EnvError(o string) error {
7175
}
7276

7377
type Runner struct {
74-
version string
75-
7678
usr *user.User
7779
usrGroup *user.Group
7880
homeDir string
@@ -81,6 +83,7 @@ type Runner struct {
8183
workingDir string
8284
env map[string]string
8385
volumes []volume
86+
containerEngine string
8487
}
8588

8689
type volume struct {
@@ -95,11 +98,23 @@ func NewRunner() *Runner {
9598
if err != nil {
9699
log.Fatalf("error getting user home directory: %v", err)
97100
}
101+
var containerEngine string
102+
switch p := os.Getenv(containerEngineEnv); p {
103+
case "":
104+
containerEngine = detectContainerEngine()
105+
case "podman":
106+
containerEngine = containerEnginePodman
107+
case "docker":
108+
containerEngine = containerEngineDocker
109+
default:
110+
log.Printf("ignoring unknown value %q for %s", p, containerEngineEnv)
111+
}
98112

99113
return &Runner{
100114
homeDir: home,
101115
supplementaryGroupIDs: []int{},
102116
env: map[string]string{},
117+
containerEngine: containerEngine,
103118
}
104119
}
105120

@@ -289,16 +304,20 @@ func (r *Runner) setupSSHAgent() {
289304
}
290305

291306
func (r *Runner) dockerRun(args []string) error {
307+
//nolint:gosec // we validate this
292308
cmd := exec.Command(
293-
"docker", "run",
309+
r.containerEngine, "run",
294310
"--interactive",
295311
"--tty=false",
296312
"--rm",
297313
"--net=host",
298314
"-w", containerWorkingDir,
299315
)
316+
if r.containerEngine == containerEnginePodman {
317+
cmd.Args = append(cmd.Args, "--userns=keep-id", "--security-opt", "label=disable")
318+
}
300319

301-
if runtime.GOOS != windows {
320+
if runtime.GOOS != windows && r.containerEngine == containerEngineDocker {
302321
cmd.Args = append(cmd.Args, "-u", r.usr.Uid+":"+r.usr.Gid)
303322
r.addBindVolume(r.tempDir, r.homeDir)
304323
}
@@ -341,44 +360,6 @@ func (r *Runner) dockerRun(args []string) error {
341360
return nil
342361
}
343362

344-
// checkDockerVersion checks whether the docker version is greater than then
345-
// minimum required.
346-
func (r *Runner) checkDockerVersion() error {
347-
_, err := exec.Command("docker", "version", "-f", "{{.Client.Version}}").Output()
348-
if err != nil {
349-
if ee, ok := err.(*exec.ExitError); ok {
350-
os.Stderr.Write(ee.Stderr)
351-
}
352-
return err
353-
}
354-
return nil
355-
}
356-
357-
// checkDockerRunning checks whether the docker daemon is running.
358-
func (r *Runner) checkDockerRunning() error {
359-
out, err := exec.Command("docker", "info", "-f", "{{json .ServerVersion}}").Output()
360-
if err != nil || len(out) == 0 {
361-
if ee, ok := err.(*exec.ExitError); ok {
362-
os.Stderr.Write(ee.Stderr)
363-
}
364-
return err
365-
}
366-
return nil
367-
}
368-
369-
func (r *Runner) checkRequirements() error {
370-
err := r.checkDockerVersion()
371-
if err != nil {
372-
return err
373-
}
374-
375-
err = r.checkDockerRunning()
376-
if err != nil {
377-
return err
378-
}
379-
return nil
380-
}
381-
382363
func (r *Runner) setUserMapping() error {
383364
if runtime.GOOS == windows {
384365
return nil
@@ -474,13 +455,6 @@ func (r *Runner) maskSSHKnownHosts() error {
474455
func (r *Runner) Run(args []string) error {
475456
// Get the Konvoy image version for marker file
476457
var err error
477-
r.version = ""
478-
479-
err = r.checkRequirements()
480-
if err != nil {
481-
return err
482-
}
483-
484458
// Lookup for current user and its group ID.
485459
// This also look for supplementary group IDs to set.
486460
err = r.setUserAndGroups()
@@ -506,13 +480,15 @@ func (r *Runner) Run(args []string) error {
506480

507481
// Setup the user and group mappings in the container so that uid and
508482
// gid on the host can be properly resolved in the container too.
509-
err = r.setUserMapping()
510-
if err != nil {
511-
return fmt.Errorf("failed to set user mapping %w", err)
512-
}
513-
err = r.setGroupMapping()
514-
if err != nil {
515-
return fmt.Errorf("failed to set group mapping %w", err)
483+
if r.containerEngine == containerEngineDocker {
484+
err = r.setUserMapping()
485+
if err != nil {
486+
return fmt.Errorf("failed to set user mapping %w", err)
487+
}
488+
err = r.setGroupMapping()
489+
if err != nil {
490+
return fmt.Errorf("failed to set group mapping %w", err)
491+
}
516492
}
517493

518494
err = r.maskSSHConfig()
@@ -541,7 +517,7 @@ func (r *Runner) Run(args []string) error {
541517

542518
r.setHTTPProxyEnv()
543519

544-
err = image.LoadImage()
520+
err = image.LoadImage(r.containerEngine)
545521
if err != nil {
546522
return fmt.Errorf("failed to load image %w", err)
547523
}
@@ -551,3 +527,39 @@ func (r *Runner) Run(args []string) error {
551527
// Run the command in the konvoy docker container.
552528
return r.dockerRun(args)
553529
}
530+
531+
// detectContainerEngine determines which container engine should be used.
532+
// if both docker and podman installed then docker engine takes precedence
533+
// if none of them are detected then fallback to existing behavior of using
534+
// docker as a container engine.
535+
func detectContainerEngine() string {
536+
if isDockerAvailable() {
537+
return containerEngineDocker
538+
} else if isPodmanAvailable() {
539+
return containerEnginePodman
540+
}
541+
// fall back to current behavior for backward compatibility
542+
return containerEngineDocker
543+
}
544+
545+
func isPodmanAvailable() bool {
546+
cmd := exec.Command("podman", "-v")
547+
var buff bytes.Buffer
548+
cmd.Stdout = &buff
549+
err := cmd.Run()
550+
if err != nil {
551+
return false
552+
}
553+
return strings.HasPrefix(buff.String(), "podman version")
554+
}
555+
556+
func isDockerAvailable() bool {
557+
cmd := exec.Command("docker", "-v")
558+
var buff bytes.Buffer
559+
cmd.Stdout = &buff
560+
err := cmd.Run()
561+
if err != nil {
562+
return false
563+
}
564+
return strings.HasPrefix(buff.String(), "Docker version")
565+
}

cmd/konvoy-image-wrapper/image/common.go

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,19 @@ package image
33
import (
44
"bytes"
55
"fmt"
6-
"os"
76
"os/exec"
87

98
"github.com/mesosphere/konvoy-image-builder/pkg/version"
109
)
1110

12-
func imageLoaded(image string) (bool, error) {
13-
cmd := exec.Command("docker", "image", "inspect", image)
11+
func imageLoaded(containerEngine, image string) bool {
12+
cmd := exec.Command(containerEngine, "image", "inspect", image)
1413
stdErrBuf := bytes.NewBuffer(make([]byte, 0))
1514
cmd.Stderr = stdErrBuf
16-
1715
if err := cmd.Run(); err != nil {
18-
stdErr := stdErrBuf.Bytes()
19-
if bytes.Index(stdErr, []byte("No such image")) > 0 {
20-
return false, nil
21-
}
22-
fmt.Fprintf(os.Stderr, "docker error: %s", stdErr)
23-
return false, err
16+
return false
2417
}
25-
return true, nil
18+
return true
2619
}
2720

2821
func Tag() string {

cmd/konvoy-image-wrapper/image/image.go

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,30 +9,23 @@ import (
99
_ "embed"
1010
"os"
1111
"os/exec"
12-
13-
"github.com/pkg/errors"
1412
)
1513

1614
const Repository = "mesosphere/konvoy-image-builder"
1715

1816
//go:embed konvoy-image-builder.tar.gz
1917
var konvoyImageTar []byte // memory is cheap, right?
2018

21-
func LoadImage() error {
19+
func LoadImage(containerEngine string) error {
2220
image := Tag()
23-
present, err := imageLoaded(image)
24-
if err != nil {
25-
return errors.Wrap(err, "error querying docker for images")
21+
if imageLoaded(containerEngine, image) {
22+
return nil
2623
}
24+
cmd := exec.Command(containerEngine, "image", "load")
25+
cmd.Stdin = bytes.NewReader(konvoyImageTar)
2726

28-
if !present {
29-
cmd := exec.Command("docker", "image", "load")
30-
cmd.Stdin = bytes.NewReader(konvoyImageTar)
31-
32-
cmd.Stdout = os.Stdout
33-
cmd.Stderr = os.Stderr
27+
cmd.Stdout = os.Stdout
28+
cmd.Stderr = os.Stderr
3429

35-
return cmd.Run()
36-
}
37-
return nil
30+
return cmd.Run()
3831
}

0 commit comments

Comments
 (0)