diff --git a/pkg/runner/deb/packageconfig.go b/pkg/runner/deb/packageconfig.go index b96599b..8d26671 100644 --- a/pkg/runner/deb/packageconfig.go +++ b/pkg/runner/deb/packageconfig.go @@ -2,12 +2,15 @@ package deb import ( "fmt" + "os" + "path/filepath" "strings" ) type PackageConfig struct { - Override *[]Package `pulumi:"override,optional"` - Additional *[]string `pulumi:"additional,optional"` + OverrideDir *string `pulumi:"overrideDir,optional"` + Override *[]Package `pulumi:"override,optional"` + Additional *[]string `pulumi:"additional,optional"` } func (p *PackageConfig) UpdatePackageGroup(g *PackageGroup) error { @@ -15,6 +18,24 @@ func (p *PackageConfig) UpdatePackageGroup(g *PackageGroup) error { g.Add(Package{}.MakePackages(*p.Additional...)...) } + if p.OverrideDir != nil { + localDebs, err := getOverrideDirPackages(*p.OverrideDir) + if err != nil { + return err + } + + overrides := make([]Package, 0, len(g.packages)) + for _, pkg := range g.packages { + if localDeb, ok := localDebs[pkg.Name]; ok { + overrides = append(overrides, Package{ + Name: pkg.Name, + LocalPath: &localDeb, + }) + } + } + g.Add(overrides...) + } + if p.Override != nil { unknownPackages := []string{} @@ -33,3 +54,38 @@ func (p *PackageConfig) UpdatePackageGroup(g *PackageGroup) error { return nil } + +// Assume unique packages in the override dir. Multiple package +// versions will result in an error +func getOverrideDirPackages(dir string) (map[string]string, error) { + info, err := os.Stat(dir) + if err != nil { + if os.IsNotExist(err) { + return nil, fmt.Errorf("directory %q does not exist", dir) + } + return nil, err + } + if !info.IsDir() { + return nil, fmt.Errorf("%q exists but is not a directory", dir) + } + + files, err := filepath.Glob(filepath.Join(dir, "*.deb")) + if err != nil { + return nil, err + } + localDebs := make(map[string]string, len(files)) + for _, p := range files { + base := filepath.Base(p) + parts := strings.Split(base, "_") + if len(parts) < 3 { + return nil, fmt.Errorf("%q invalid debian package name", base) + } + name := strings.Join(parts[:len(parts)-2], "_") + if _, ok := localDebs[name]; ok { + return nil, fmt.Errorf("%q duplicate package name", base) + } else { + localDebs[name] = p + } + } + return localDebs, nil +} diff --git a/pkg/runner/deb/packageconfig_test.go b/pkg/runner/deb/packageconfig_test.go index bae76fa..da747e8 100644 --- a/pkg/runner/deb/packageconfig_test.go +++ b/pkg/runner/deb/packageconfig_test.go @@ -1,9 +1,11 @@ package deb import ( - "testing" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "os" + "path/filepath" + "testing" ) func TestBasicPackageConfig0(t *testing.T) { @@ -67,3 +69,88 @@ func TestBasicPackageConfigErr0(t *testing.T) { assert.Equal(t, []string{"testpkg", "anotherpkg", "newpkg/dev"}, g.Args()) } } + +func TestPackageConfigBadOverrideDir(t *testing.T) { + base := t.TempDir() + overrideDir := filepath.Join(base, "overrides") + overrideDirNone := filepath.Join(base, "NoSuchDir") + overrideFile := filepath.Join(base, "file.txt") + + require.NoError(t, os.Mkdir(overrideDir, 0755)) + require.NoError(t, os.WriteFile(overrideFile, nil, 0644)) + + g := Package{}.MakePackageGroup("testpkg", "anotherpkg") + + assert.Equal(t, []string{"testpkg", "anotherpkg"}, g.Args()) + + { + c := PackageConfig{ + OverrideDir: &overrideDirNone, + } + + assert.ErrorContains(t, c.UpdatePackageGroup(g), "does not exist") + } + + { + c := PackageConfig{ + OverrideDir: &overrideFile, + } + + assert.ErrorContains(t, c.UpdatePackageGroup(g), "exists but is not a directory") + } + + { + c := PackageConfig{ + OverrideDir: &overrideDir, + } + + assert.NoError(t, c.UpdatePackageGroup(g)) + } +} + +func mkdeb(t *testing.T, dir, fname string) string { + t.Helper() + path := filepath.Join(dir, fname) + require.NoError(t, os.WriteFile(path, nil, 0644)) + return path +} + +func TestPackageConfigOverrideDir(t *testing.T) { + overrideDir := t.TempDir() + + mkdeb(t, overrideDir, "testpkg_0.0.0-1_amd64.deb") + mkdeb(t, overrideDir, "anotherpkg_3.2.1-1_amd64.deb") + mkdeb(t, overrideDir, "randompkg_0.0.0-0_amd64.deb") + + g := Package{}.MakePackageGroup("testpkg", "anotherpkg") + + assert.Equal(t, []string{"testpkg", "anotherpkg"}, g.Args()) + + { + c := PackageConfig{ + OverrideDir: &overrideDir, + Override: &[]Package{ + { + Name: "testpkg", + Version: ptr("1.2.3"), + }, + }, + } + + assert.NoError(t, c.UpdatePackageGroup(g)) + assert.Equal(t, []string{"testpkg=1.2.3", "./anotherpkg_3.2.1-1_amd64.deb"}, g.Args()) + } + + { + duplicate := mkdeb(t, overrideDir, "testpkg_3.2.1-2_amd64.deb") + c := PackageConfig{ + OverrideDir: &overrideDir, + } + + assert.ErrorContains(t, c.UpdatePackageGroup(g), "duplicate package name") + require.NoError(t, os.Remove(duplicate)) + + mkdeb(t, overrideDir, "bad-deb-format.deb") + assert.ErrorContains(t, c.UpdatePackageGroup(g), "invalid debian package name") + } +}