Skip to content

Commit 8aeabe9

Browse files
committed
Match bundle image directory structure
This commit introduces a change to the way that the way the API function bundle.GenerateFunc manages directory structure. Currently, the output of that function creates a metadata folder with generated annotations inside the given manifest directory. However, this is not how bundle images are actually formatted, and the Dockerfile does some indirection in order to copy the files into the correct directory. However, we should consider the default behvaior of `generate` to be "run once" (especially given that by default the regeneration does not happen in the build function by default). The expectation is that generate is a scaffolding method. Given that, we should scaffold the metadata directory in the same manner as it would actually appear in the union filesystem on the resulting container image. In order to accomplish this, this PR makes a few functional changes: - By default, create the metadata directory in the same parent directory as the given manifest directory. This, at a high level, mirrors the directory tree that will exist on the resulting bundle. - Generates the dockerfile in the current working directory that the function is called from. Modifies the dockerfile to point to the relative path of the generated files - Adds an option output directory parameter to the function (as well as the shadowed `opm alpha bundle build/generate` commands) to allow the user to generate a *new* bundle directory.
1 parent 4357be1 commit 8aeabe9

17 files changed

+12038
-51
lines changed

cmd/opm/alpha/bundle/build.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ var (
1313
packageNameArgs string
1414
channelsArgs string
1515
channelDefaultArgs string
16+
outputDirArgs string
1617
overwriteArgs bool
1718
)
1819

@@ -69,11 +70,13 @@ func newBundleBuildCmd() *cobra.Command {
6970

7071
bundleBuildCmd.Flags().BoolVarP(&overwriteArgs, "overwrite", "o", false, "To overwrite annotations.yaml locally if existed. By default, overwrite is set to `false`.")
7172

73+
bundleBuildCmd.Flags().StringVarP(&outputDirArgs, "output-dir", "u", "", "Optional output directory for operator manifests")
74+
7275
return bundleBuildCmd
7376
}
7477

7578
func buildFunc(cmd *cobra.Command, args []string) error {
76-
err := bundle.BuildFunc(dirBuildArgs, tagBuildArgs, imageBuilderArgs,
79+
err := bundle.BuildFunc(dirBuildArgs, outputDirArgs, tagBuildArgs, imageBuilderArgs,
7780
packageNameArgs, channelsArgs, channelDefaultArgs, overwriteArgs)
7881
if err != nil {
7982
return err

cmd/opm/alpha/bundle/generate.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,13 @@ func newBundleGenerateCmd() *cobra.Command {
4141

4242
bundleGenerateCmd.Flags().StringVarP(&channelDefaultArgs, "default", "e", "", "The default channel for the bundle image")
4343

44+
bundleGenerateCmd.Flags().StringVarP(&outputDirArgs, "output-dir", "u", "", "Optional output directory for operator manifests")
45+
4446
return bundleGenerateCmd
4547
}
4648

4749
func generateFunc(cmd *cobra.Command, args []string) error {
48-
err := bundle.GenerateFunc(dirBuildArgs, packageNameArgs, channelsArgs, channelDefaultArgs, true)
50+
err := bundle.GenerateFunc(dirBuildArgs, outputDirArgs, packageNameArgs, channelsArgs, channelDefaultArgs, true)
4951
if err != nil {
5052
return err
5153
}

docs/design/operator-bundle.md

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,14 @@ Flags:
119119
-e, --default string The default channel for the bundle image
120120
-d, --directory string The directory where bundle manifests for a specific version are located.
121121
-h, --help help for generate
122+
-u, --output-dir string Optional output directory for operator manifests
122123
-p, --package string The name of the package that bundle image belongs to
123124
124125
Note:
125126
* All manifests yaml must be in the same directory.
126127
```
127128

128-
The `--directory/-d`, `--channels/-c`, `--package/-p` are required flags while `--default/-e` is optional.
129+
The `--directory/-d`, `--channels/-c`, `--package/-p` are required flags while `--default/-e` and `--output-dir/-u` are optional.
129130

130131
The command for `generate` task is:
131132
```bash
@@ -145,17 +146,35 @@ The `--package` or `-p` is the name of package fo the operator such as `etcd` wh
145146

146147
All information in `annotations.yaml` is also existed in `LABEL` section of `Dockerfile`.
147148

148-
After the generate command is executed, the `Dockerfile` is generated in the same directory where the YAML manifests are located while the `annotations.yaml` file is located in a folder named `metadata`. For example:
149+
After the generate command is executed, the `Dockerfile` is generated in the directory where command is run. By default, the `annotations.yaml` file is located in a folder named `metadata` in the same root directory as the input directory containing manifests. For example:
149150
```bash
150151
$ tree test
151152
test
152-
├── etcdcluster.crd.yaml
153-
├── etcdoperator.clusterserviceversion.yaml
153+
├── my-manifests
154+
│ ├── etcdcluster.crd.yaml
155+
│ └── etcdoperator.clusterserviceversion.yaml
154156
├── metadata
155157
│   └── annotations.yaml
156158
└── Dockerfile
157159
```
158160

161+
If the `--output-dir` parameter is specified, that directory becomes the parent for a new pair of folders `manifests/` and `metadata/`, where `manifests/` is a copy of the passed in directory of manifests and `metadata/` is the folder containing annotations.yaml:
162+
163+
```bash
164+
$ tree test
165+
test
166+
├── my-manifests
167+
│ ├── etcdcluster.crd.yaml
168+
│ └── etcdoperator.clusterserviceversion.yaml
169+
├── my-output-manifest-dir
170+
│ ├── manifests
171+
│ │ ├── etcdoperator.clusterserviceversion.yaml
172+
│ │ └── etcdoperator.clusterserviceversion.yaml
173+
│   └── metadata
174+
│ └── annotations.yaml
175+
└── Dockerfile
176+
```
177+
159178
The `Dockerfile` can be used manually to build the bundle image using container image tools such as Docker, Podman or Buildah. For example, the Docker build command would be:
160179

161180
```bash
@@ -175,7 +194,8 @@ Flags:
175194
-d, --directory string The directory where bundle manifests for a specific version are located
176195
-h, --help help for build
177196
-b, --image-builder string Tool to build container images. One of: [docker, podman, buildah] (default "docker")
178-
-0, --overwrite To overwrite annotations.yaml if existing
197+
-u, --output-dir string Optional output directory for operator manifests
198+
-0, --overwrite To overwrite annotations.yaml if existing
179199
-p, --package string The name of the package that bundle image belongs to
180200
-t, --tag string The name of the bundle image will be built
181201

pkg/lib/bundle/build.go

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,19 @@ import (
44
"fmt"
55
"os"
66
"os/exec"
7-
"path"
87

98
log "github.com/sirupsen/logrus"
109
)
1110

1211
// Create build command to build bundle manifests image
13-
func BuildBundleImage(directory, imageTag, imageBuilder string) (*exec.Cmd, error) {
12+
func BuildBundleImage(imageTag, imageBuilder string) (*exec.Cmd, error) {
1413
var args []string
1514

16-
dockerfilePath := path.Join(directory, DockerFile)
17-
1815
switch imageBuilder {
1916
case "docker", "podman":
20-
args = append(args, "build", "-f", dockerfilePath, "-t", imageTag, directory)
17+
args = append(args, "build", "-f", DockerFile, "-t", imageTag, ".")
2118
case "buildah":
22-
args = append(args, "bud", "--format=docker", "-f", dockerfilePath, "-t", imageTag, directory)
19+
args = append(args, "bud", "--format=docker", "-f", DockerFile, "-t", imageTag, ".")
2320
default:
2421
return nil, fmt.Errorf("%s is not supported image builder", imageBuilder)
2522
}
@@ -53,21 +50,21 @@ func ExecuteCommand(cmd *exec.Cmd) error {
5350
// @channels: The list of channels that bundle image belongs to
5451
// @channelDefault: The default channel for the bundle image
5552
// @overwrite: Boolean flag to enable overwriting annotations.yaml locally if existed
56-
func BuildFunc(directory, imageTag, imageBuilder, packageName, channels, channelDefault string, overwrite bool) error {
53+
func BuildFunc(directory, outputDir, imageTag, imageBuilder, packageName, channels, channelDefault string, overwrite bool) error {
5754
_, err := os.Stat(directory)
5855
if os.IsNotExist(err) {
5956
return err
6057
}
6158

6259
// Generate annotations.yaml and Dockerfile
63-
err = GenerateFunc(directory, packageName, channels, channelDefault, overwrite)
60+
err = GenerateFunc(directory, outputDir, packageName, channels, channelDefault, overwrite)
6461
if err != nil {
6562
return err
6663
}
6764

6865
// Build bundle image
6966
log.Info("Building bundle image")
70-
buildCmd, err := BuildBundleImage(path.Clean(directory), imageTag, imageBuilder)
67+
buildCmd, err := BuildBundleImage(imageTag, imageBuilder)
7168
if err != nil {
7269
return err
7370
}

pkg/lib/bundle/build_test.go

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,35 +12,30 @@ func TestBuildBundleImage(t *testing.T) {
1212
defer cleanup()
1313

1414
tests := []struct {
15-
directory string
1615
imageTag string
1716
imageBuilder string
1817
commandStr string
1918
errorMsg string
2019
}{
2120
{
22-
testOperatorDir,
2321
"test",
2422
"docker",
25-
"docker build -f /test-operator/Dockerfile -t test /test-operator",
23+
"docker build -f bundle.Dockerfile -t test .",
2624
"",
2725
},
2826
{
29-
testOperatorDir,
3027
"test",
3128
"buildah",
32-
"buildah bud --format=docker -f /test-operator/Dockerfile -t test /test-operator",
29+
"buildah bud --format=docker -f bundle.Dockerfile -t test .",
3330
"",
3431
},
3532
{
36-
testOperatorDir,
3733
"test",
3834
"podman",
39-
"podman build -f /test-operator/Dockerfile -t test /test-operator",
35+
"podman build -f bundle.Dockerfile -t test .",
4036
"",
4137
},
4238
{
43-
testOperatorDir,
4439
"test",
4540
"hello",
4641
"",
@@ -50,7 +45,7 @@ func TestBuildBundleImage(t *testing.T) {
5045

5146
for _, item := range tests {
5247
var cmd *exec.Cmd
53-
cmd, err := BuildBundleImage(item.directory, item.imageTag, item.imageBuilder)
48+
cmd, err := BuildBundleImage(item.imageTag, item.imageBuilder)
5449
if item.errorMsg == "" {
5550
require.Contains(t, cmd.String(), item.commandStr)
5651
} else {

0 commit comments

Comments
 (0)