Skip to content

Commit 7437af6

Browse files
Merge pull request #337 from benluddy/podman-index-docker-format
Bug 1840370: Configure "podman build" to produce images with Docker manifests.
2 parents 818824c + a9d758c commit 7437af6

File tree

10 files changed

+323
-28
lines changed

10 files changed

+323
-28
lines changed

pkg/appregistry/dbloader.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func NewDbLoader(dbName string, logger *logrus.Entry) (*dbLoader, error) {
3535

3636
type dbLoader struct {
3737
db *sql.DB
38-
loader *sqlite.SQLLoader
38+
loader registry.Load
3939
logger *logrus.Entry
4040
}
4141

pkg/containertools/containertool.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@ func (t ContainerTool) String() (s string) {
2020
return
2121
}
2222

23+
func (t ContainerTool) CommandFactory() CommandFactory {
24+
switch t {
25+
case PodmanTool:
26+
return &PodmanCommandFactory{}
27+
case DockerTool:
28+
return &DockerCommandFactory{}
29+
}
30+
return &StubCommandFactory{}
31+
}
32+
2333
func NewContainerTool(s string, defaultTool ContainerTool) (t ContainerTool) {
2434
switch s {
2535
case "podman":

pkg/containertools/factory.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package containertools
2+
3+
import (
4+
"os/exec"
5+
)
6+
7+
type CommandFactory interface {
8+
BuildCommand(o BuildOptions) (*exec.Cmd, error)
9+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package containertools
2+
3+
import (
4+
"fmt"
5+
"os/exec"
6+
)
7+
8+
type DockerCommandFactory struct{}
9+
10+
func (d *DockerCommandFactory) BuildCommand(o BuildOptions) (*exec.Cmd, error) {
11+
args := []string{"build"}
12+
13+
if o.format != "" && o.format != "docker" {
14+
return nil, fmt.Errorf(`format %q invalid for "docker build"`, o.format)
15+
}
16+
17+
if o.dockerfile != "" {
18+
args = append(args, "-f", o.dockerfile)
19+
}
20+
21+
for _, tag := range o.tags {
22+
args = append(args, "-t", tag)
23+
}
24+
25+
if o.context == "" {
26+
return nil, fmt.Errorf("context not provided")
27+
}
28+
args = append(args, o.context)
29+
30+
return exec.Command("docker", args...), nil
31+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package containertools
2+
3+
import (
4+
"fmt"
5+
"os/exec"
6+
)
7+
8+
type PodmanCommandFactory struct{}
9+
10+
func (p *PodmanCommandFactory) BuildCommand(o BuildOptions) (*exec.Cmd, error) {
11+
args := []string{"build"}
12+
13+
if o.format != "" {
14+
args = append(args, "--format", o.format)
15+
} else {
16+
args = append(args, "--format", "docker")
17+
}
18+
19+
if o.dockerfile != "" {
20+
args = append(args, "-f", o.dockerfile)
21+
}
22+
23+
for _, tag := range o.tags {
24+
args = append(args, "-t", tag)
25+
}
26+
27+
if o.context == "" {
28+
return nil, fmt.Errorf("context not provided")
29+
}
30+
args = append(args, o.context)
31+
32+
return exec.Command("podman", args...), nil
33+
}

pkg/containertools/factory_stub.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package containertools
2+
3+
import (
4+
"fmt"
5+
"os/exec"
6+
)
7+
8+
type StubCommandFactory struct {
9+
name string
10+
}
11+
12+
func (s *StubCommandFactory) BuildCommand(o BuildOptions) (*exec.Cmd, error) {
13+
return nil, fmt.Errorf(`"build" is not supported by tool %q`, s.name)
14+
}

pkg/containertools/factory_test.go

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
package containertools
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
)
8+
9+
func TestBuildCommand(t *testing.T) {
10+
for _, tt := range []struct {
11+
Name string
12+
Factory CommandFactory
13+
Options BuildOptions
14+
Args []string
15+
}{
16+
{
17+
Name: "docker defaults",
18+
Factory: &DockerCommandFactory{},
19+
Options: DefaultBuildOptions(),
20+
Args: []string{
21+
"docker", "build", ".",
22+
},
23+
},
24+
{
25+
Name: "docker unsupported format",
26+
Factory: &DockerCommandFactory{},
27+
Options: BuildOptions{
28+
context: ".",
29+
format: "oci",
30+
},
31+
},
32+
{
33+
Name: "docker context",
34+
Factory: &DockerCommandFactory{},
35+
Options: BuildOptions{
36+
context: "foo",
37+
},
38+
Args: []string{
39+
"docker", "build", "foo",
40+
},
41+
},
42+
{
43+
Name: "docker dockerfile",
44+
Factory: &DockerCommandFactory{},
45+
Options: BuildOptions{
46+
context: ".",
47+
dockerfile: "foo",
48+
},
49+
Args: []string{
50+
"docker", "build", "-f", "foo", ".",
51+
},
52+
},
53+
{
54+
Name: "docker single tag",
55+
Factory: &DockerCommandFactory{},
56+
Options: BuildOptions{
57+
context: ".",
58+
tags: []string{"foo"},
59+
},
60+
Args: []string{
61+
"docker", "build", "-t", "foo", ".",
62+
},
63+
},
64+
{
65+
Name: "docker multiple tags",
66+
Factory: &DockerCommandFactory{},
67+
Options: BuildOptions{
68+
context: ".",
69+
tags: []string{"foo", "bar"},
70+
},
71+
Args: []string{
72+
"docker", "build", "-t", "foo", "-t", "bar", ".",
73+
},
74+
},
75+
{
76+
Name: "podman defaults",
77+
Factory: &PodmanCommandFactory{},
78+
Options: DefaultBuildOptions(),
79+
Args: []string{
80+
"podman", "build", "--format", "docker", ".",
81+
},
82+
},
83+
{
84+
Name: "podman oci format",
85+
Factory: &PodmanCommandFactory{},
86+
Options: BuildOptions{
87+
context: ".",
88+
format: "oci",
89+
},
90+
Args: []string{
91+
"podman", "build", "--format", "oci", ".",
92+
},
93+
},
94+
{
95+
Name: "podman context",
96+
Factory: &PodmanCommandFactory{},
97+
Options: BuildOptions{
98+
context: "foo",
99+
},
100+
Args: []string{
101+
"podman", "build", "--format", "docker", "foo",
102+
},
103+
},
104+
{
105+
Name: "podman dockerfile",
106+
Factory: &PodmanCommandFactory{},
107+
Options: BuildOptions{
108+
context: ".",
109+
dockerfile: "foo",
110+
},
111+
Args: []string{
112+
"podman", "build", "--format", "docker", "-f", "foo", ".",
113+
},
114+
},
115+
{
116+
Name: "podman single tag",
117+
Factory: &PodmanCommandFactory{},
118+
Options: BuildOptions{
119+
context: ".",
120+
tags: []string{"foo"},
121+
},
122+
Args: []string{
123+
"podman", "build", "--format", "docker", "-t", "foo", ".",
124+
},
125+
},
126+
{
127+
Name: "podman multiple tags",
128+
Factory: &PodmanCommandFactory{},
129+
Options: BuildOptions{
130+
context: ".",
131+
tags: []string{"foo", "bar"},
132+
},
133+
Args: []string{
134+
"podman", "build", "--format", "docker", "-t", "foo", "-t", "bar", ".",
135+
},
136+
},
137+
{
138+
Name: "stub defaults",
139+
Factory: &StubCommandFactory{},
140+
Options: DefaultBuildOptions(),
141+
},
142+
} {
143+
t.Run(tt.Name, func(t *testing.T) {
144+
require := require.New(t)
145+
146+
cmd, err := tt.Factory.BuildCommand(tt.Options)
147+
if tt.Args == nil {
148+
require.Nil(cmd)
149+
require.Error(err)
150+
} else {
151+
require.NotNil(cmd)
152+
require.NoError(err)
153+
require.Equal(tt.Args, cmd.Args)
154+
}
155+
})
156+
}
157+
}

pkg/containertools/option_build.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package containertools
2+
3+
type BuildOptions struct {
4+
format string
5+
tags []string
6+
dockerfile string
7+
context string
8+
}
9+
10+
func (o *BuildOptions) SetFormatDocker() {
11+
o.format = "docker"
12+
}
13+
14+
func (o *BuildOptions) SetFormatOCI() {
15+
o.format = "oci"
16+
}
17+
18+
func (o *BuildOptions) AddTag(tag string) {
19+
o.tags = append(o.tags, tag)
20+
}
21+
22+
func (o *BuildOptions) SetDockerfile(dockerfile string) {
23+
o.dockerfile = dockerfile
24+
}
25+
26+
func (o *BuildOptions) SetContext(context string) {
27+
o.context = context
28+
}
29+
30+
func DefaultBuildOptions() BuildOptions {
31+
var o BuildOptions
32+
o.SetFormatDocker()
33+
o.SetContext(".")
34+
return o
35+
}

pkg/containertools/command.go renamed to pkg/containertools/runner.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ type ContainerCommandRunner struct {
2828
// CommandRunner to run commands with that cli tool
2929
func NewCommandRunner(containerTool ContainerTool, logger *logrus.Entry) CommandRunner {
3030
r := ContainerCommandRunner{
31-
logger: logger,
31+
logger: logger,
3232
containerTool: containerTool,
3333
}
3434
return &r
@@ -59,15 +59,16 @@ func (r *ContainerCommandRunner) Pull(image string) error {
5959

6060
// Build takes a dockerfile and a tag and builds a container image
6161
func (r *ContainerCommandRunner) Build(dockerfile, tag string) error {
62-
args := []string{"build", "-f", dockerfile}
63-
62+
o := DefaultBuildOptions()
6463
if tag != "" {
65-
args = append(args, "-t", tag)
64+
o.AddTag(tag)
65+
}
66+
o.SetDockerfile(dockerfile)
67+
o.SetContext(".")
68+
command, err := r.containerTool.CommandFactory().BuildCommand(o)
69+
if err != nil {
70+
return fmt.Errorf("unable to perform build: %v", err)
6671
}
67-
68-
args = append(args, ".")
69-
70-
command := exec.Command(r.containerTool.String(), args...)
7172

7273
r.logger.Infof("running %s build", r.containerTool)
7374
r.logger.Infof("%s", command.Args)

0 commit comments

Comments
 (0)