Skip to content

Commit 25d989a

Browse files
committed
feat(render): render sqlite database files
Signed-off-by: Eric Stroczynski <[email protected]>
1 parent eacb9a4 commit 25d989a

File tree

3 files changed

+139
-9
lines changed

3 files changed

+139
-9
lines changed

cmd/opm/alpha/render/cmd.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ func NewCmd() *cobra.Command {
1919
output string
2020
)
2121
cmd := &cobra.Command{
22-
Use: "render [index-image | bundle-image]...",
23-
Short: "Generate declarative config blobs from the provided index and bundle images",
22+
Use: "render [index-image | bundle-image | sqlite-file]...",
23+
Short: "Generate a declarative config blob from the provided index images, bundle images, and sqlite database files",
2424
Args: cobra.MinimumNArgs(1),
2525
Run: func(cmd *cobra.Command, args []string) {
2626
render.Refs = args

internal/action/render.go

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010
"path/filepath"
1111
"strings"
1212

13+
"github.com/h2non/filetype"
14+
"github.com/h2non/filetype/matchers"
1315
"github.com/sirupsen/logrus"
1416
"k8s.io/apimachinery/pkg/util/sets"
1517

@@ -50,9 +52,17 @@ func (r Render) Run(ctx context.Context) (*declcfg.DeclarativeConfig, error) {
5052
cfg *declcfg.DeclarativeConfig
5153
err error
5254
)
53-
// TODO(joelanford): Add support for detecting and rendering sqlite files.
54-
if stat, serr := os.Stat(ref); serr == nil && stat.IsDir() {
55-
cfg, err = declcfg.LoadFS(os.DirFS(ref))
55+
if stat, serr := os.Stat(ref); serr == nil {
56+
if stat.IsDir() {
57+
cfg, err = declcfg.LoadFS(os.DirFS(ref))
58+
} else {
59+
// The only supported file type is an sqlite DB file,
60+
// since declarative configs will be in a directory.
61+
if err := checkDBFile(ref); err != nil {
62+
return nil, err
63+
}
64+
cfg, err = sqliteToDeclcfg(ctx, ref)
65+
}
5666
} else {
5767
cfg, err = r.imageToDeclcfg(ctx, ref)
5868
}
@@ -141,6 +151,18 @@ func (r Render) imageToDeclcfg(ctx context.Context, imageRef string) (*declcfg.D
141151
return cfg, nil
142152
}
143153

154+
// checkDBFile returns an error if ref is not an sqlite3 database.
155+
func checkDBFile(ref string) error {
156+
typ, err := filetype.MatchFile(ref)
157+
if err != nil {
158+
return err
159+
}
160+
if typ != matchers.TypeSqlite {
161+
return fmt.Errorf("ref %q has unsupported file type: %s", ref, typ)
162+
}
163+
return nil
164+
}
165+
144166
func sqliteToDeclcfg(ctx context.Context, dbFile string) (*declcfg.DeclarativeConfig, error) {
145167
db, err := sqlite.Open(dbFile)
146168
if err != nil {

internal/action/render_test.go

Lines changed: 112 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"testing"
1010
"testing/fstest"
1111

12+
"github.com/stretchr/testify/assert"
1213
"github.com/stretchr/testify/require"
1314
"k8s.io/apimachinery/pkg/util/yaml"
1415

@@ -246,6 +247,113 @@ func TestRender(t *testing.T) {
246247
}
247248
}
248249

250+
func TestRenderDBFile(t *testing.T) {
251+
252+
foov1csv, err := bundleImageV1.ReadFile("testdata/foo-bundle-v0.1.0/manifests/foo.v0.1.0.csv.yaml")
253+
require.NoError(t, err)
254+
foov1crd, err := bundleImageV1.ReadFile("testdata/foo-bundle-v0.1.0/manifests/foos.test.foo.crd.yaml")
255+
require.NoError(t, err)
256+
foov2csv, err := bundleImageV2.ReadFile("testdata/foo-bundle-v0.2.0/manifests/foo.v0.2.0.csv.yaml")
257+
require.NoError(t, err)
258+
foov2crd, err := bundleImageV2.ReadFile("testdata/foo-bundle-v0.2.0/manifests/foos.test.foo.crd.yaml")
259+
require.NoError(t, err)
260+
261+
foov1csv, err = yaml.ToJSON(foov1csv)
262+
require.NoError(t, err)
263+
foov1crd, err = yaml.ToJSON(foov1crd)
264+
require.NoError(t, err)
265+
foov2csv, err = yaml.ToJSON(foov2csv)
266+
require.NoError(t, err)
267+
foov2crd, err = yaml.ToJSON(foov2crd)
268+
require.NoError(t, err)
269+
270+
expectCfg := &declcfg.DeclarativeConfig{
271+
Packages: []declcfg.Package{
272+
{
273+
Schema: "olm.package",
274+
Name: "foo",
275+
DefaultChannel: "beta",
276+
},
277+
},
278+
Bundles: []declcfg.Bundle{
279+
{
280+
Schema: "olm.bundle",
281+
Name: "foo.v0.1.0",
282+
Package: "foo",
283+
Image: "test.registry/foo-operator/foo-bundle:v0.1.0",
284+
Properties: []property.Property{
285+
property.MustBuildChannel("beta", ""),
286+
property.MustBuildGVK("test.foo", "v1", "Foo"),
287+
property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"),
288+
property.MustBuildPackage("foo", "0.1.0"),
289+
property.MustBuildPackageRequired("bar", "v0.1.0"),
290+
property.MustBuildSkipRange("<0.1.0"),
291+
property.MustBuildBundleObjectData(foov1csv),
292+
property.MustBuildBundleObjectData(foov1crd),
293+
},
294+
RelatedImages: []declcfg.RelatedImage{
295+
{
296+
Name: "operator",
297+
Image: "test.registry/foo-operator/foo:v0.1.0",
298+
},
299+
{
300+
Image: "test.registry/foo-operator/foo-bundle:v0.1.0",
301+
},
302+
},
303+
CsvJSON: string(foov1csv),
304+
Objects: []string{string(foov1csv), string(foov1crd)},
305+
},
306+
{
307+
Schema: "olm.bundle",
308+
Name: "foo.v0.2.0",
309+
Package: "foo",
310+
Image: "test.registry/foo-operator/foo-bundle:v0.2.0",
311+
Properties: []property.Property{
312+
property.MustBuildChannel("beta", "foo.v0.1.0"),
313+
property.MustBuildGVK("test.foo", "v1", "Foo"),
314+
property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"),
315+
property.MustBuildPackage("foo", "0.2.0"),
316+
property.MustBuildPackageRequired("bar", "v0.1.0"),
317+
property.MustBuildSkipRange("<0.2.0"),
318+
property.MustBuildSkips("foo.v0.1.1"),
319+
property.MustBuildSkips("foo.v0.1.2"),
320+
property.MustBuildBundleObjectData(foov2csv),
321+
property.MustBuildBundleObjectData(foov2crd),
322+
},
323+
RelatedImages: []declcfg.RelatedImage{
324+
{
325+
Name: "operator",
326+
Image: "test.registry/foo-operator/foo:v0.2.0",
327+
},
328+
{
329+
Image: "test.registry/foo-operator/foo-bundle:v0.2.0",
330+
},
331+
},
332+
CsvJSON: string(foov2csv),
333+
Objects: []string{string(foov2csv), string(foov2crd)},
334+
},
335+
},
336+
}
337+
338+
dir := t.TempDir()
339+
340+
dbFile := filepath.Join(dir, "index.db")
341+
imageMap := map[image.Reference]string{
342+
image.SimpleReference("test.registry/foo-operator/foo-bundle:v0.1.0"): "testdata/foo-bundle-v0.1.0",
343+
image.SimpleReference("test.registry/foo-operator/foo-bundle:v0.2.0"): "testdata/foo-bundle-v0.2.0",
344+
}
345+
assert.NoError(t, generateSqliteFile(dbFile, imageMap))
346+
347+
render := action.Render{
348+
Refs: []string{dbFile},
349+
Registry: &image.MockRegistry{RemoteImages: map[image.Reference]*image.MockImage{}},
350+
}
351+
352+
actualCfg, actualErr := render.Run(context.Background())
353+
assert.NoError(t, actualErr)
354+
assert.Equal(t, expectCfg, actualCfg)
355+
}
356+
249357
//go:embed testdata/foo-bundle-v0.1.0/manifests/*
250358
//go:embed testdata/foo-bundle-v0.1.0/metadata/*
251359
var bundleImageV1 embed.FS
@@ -281,25 +389,25 @@ func newRegistry() (image.Registry, error) {
281389
}
282390
return &image.MockRegistry{
283391
RemoteImages: map[image.Reference]*image.MockImage{
284-
image.SimpleReference("test.registry/foo-operator/foo-index-sqlite:v0.2.0"): &image.MockImage{
392+
image.SimpleReference("test.registry/foo-operator/foo-index-sqlite:v0.2.0"): {
285393
Labels: map[string]string{
286394
containertools.DbLocationLabel: "/database/index.db",
287395
},
288396
FS: subSqliteImage,
289397
},
290-
image.SimpleReference("test.registry/foo-operator/foo-index-declcfg:v0.2.0"): &image.MockImage{
398+
image.SimpleReference("test.registry/foo-operator/foo-index-declcfg:v0.2.0"): {
291399
Labels: map[string]string{
292400
"operators.operatorframework.io.index.configs.v1": "/foo",
293401
},
294402
FS: subDeclcfgImage,
295403
},
296-
image.SimpleReference("test.registry/foo-operator/foo-bundle:v0.1.0"): &image.MockImage{
404+
image.SimpleReference("test.registry/foo-operator/foo-bundle:v0.1.0"): {
297405
Labels: map[string]string{
298406
bundle.PackageLabel: "foo",
299407
},
300408
FS: subBundleImageV1,
301409
},
302-
image.SimpleReference("test.registry/foo-operator/foo-bundle:v0.2.0"): &image.MockImage{
410+
image.SimpleReference("test.registry/foo-operator/foo-bundle:v0.2.0"): {
303411
Labels: map[string]string{
304412
bundle.PackageLabel: "foo",
305413
},

0 commit comments

Comments
 (0)