Merge pull request #36 from NeilHanlon/software-collections

This commit is contained in:
Mustafa Gezen 2022-10-20 11:11:15 +02:00 committed by GitHub
commit 23248641fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 241 additions and 28 deletions

View File

@ -36,9 +36,6 @@ import (
"database/sql" "database/sql"
"errors" "errors"
"fmt" "fmt"
"github.com/google/uuid"
"go.temporal.io/sdk/activity"
"google.golang.org/protobuf/types/known/wrapperspb"
"io" "io"
"io/fs" "io/fs"
"io/ioutil" "io/ioutil"
@ -46,21 +43,26 @@ import (
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"peridot.resf.org/peridot/db/models"
peridotpb "peridot.resf.org/peridot/pb"
"peridot.resf.org/peridot/rpmbuild"
"peridot.resf.org/secparse/rpmutils"
"peridot.resf.org/servicecatalog"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/google/uuid"
"go.temporal.io/sdk/activity"
"google.golang.org/protobuf/types/known/wrapperspb"
"peridot.resf.org/peridot/db/models"
peridotpb "peridot.resf.org/peridot/pb"
"peridot.resf.org/peridot/rpmbuild"
"peridot.resf.org/secparse/rpmutils"
"peridot.resf.org/servicecatalog"
) )
var ( var (
releaseDistRegex = regexp.MustCompile(".+\\.(el[^. \\t\\n]+)") releaseDistRegex = regexp.MustCompile(".+\\.(el[^. \\t\\n]+)")
BuildPkgGroup = []string{ // defaults are for el9
DefaultBuildPkgGroup = []string{
"bash", "bash",
"bzip2", "bzip2",
"coreutils", "coreutils",
@ -83,7 +85,8 @@ var (
"which", "which",
"xz", "xz",
} }
SrpmBuildPkgGroup = []string{ // defaults are for EL9
DefaultSrpmBuildPkgGroup = []string{
"bash", "bash",
"glibc-minimal-langpack", "glibc-minimal-langpack",
"gnupg2", "gnupg2",
@ -659,8 +662,20 @@ func (c *Controller) BuildArchActivity(ctx context.Context, projectId string, pa
return err return err
} }
var pkgGroup = DefaultBuildPkgGroup
if len(project.BuildStagePackages) != 0 {
pkgGroup = project.BuildStagePackages
}
if len(pkgEo.DependsOn) != 0 {
for _, pkg := range pkgEo.DependsOn {
pkgGroup = append(pkgGroup, pkg)
}
}
hostArch := os.Getenv("REAL_BUILD_ARCH") hostArch := os.Getenv("REAL_BUILD_ARCH")
err = c.writeMockConfig(&project, packageVersion, extraOptions, arch, hostArch, BuildPkgGroup) err = c.writeMockConfig(&project, packageVersion, extraOptions, arch, hostArch, pkgGroup)
if err != nil { if err != nil {
return fmt.Errorf("could not write mock config: %v", err) return fmt.Errorf("could not write mock config: %v", err)
} }

View File

@ -39,6 +39,14 @@ import (
"encoding/hex" "encoding/hex"
"errors" "errors"
"fmt" "fmt"
"io"
"io/fs"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
"github.com/cavaliergopher/rpm" "github.com/cavaliergopher/rpm"
"github.com/go-git/go-billy/v5/osfs" "github.com/go-git/go-billy/v5/osfs"
"github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5"
@ -48,16 +56,9 @@ import (
"go.temporal.io/sdk/activity" "go.temporal.io/sdk/activity"
"google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/known/anypb"
"google.golang.org/protobuf/types/known/wrapperspb" "google.golang.org/protobuf/types/known/wrapperspb"
"io"
"io/fs"
"os"
"os/exec"
"path/filepath"
"peridot.resf.org/peridot/db/models" "peridot.resf.org/peridot/db/models"
peridotpb "peridot.resf.org/peridot/pb" peridotpb "peridot.resf.org/peridot/pb"
"peridot.resf.org/peridot/rpmbuild" "peridot.resf.org/peridot/rpmbuild"
"strings"
"time"
) )
func gitlabify(str string) string { func gitlabify(str string) string {
@ -415,9 +416,20 @@ func (c *Controller) BuildSRPMActivity(ctx context.Context, upstreamPrefix strin
return fmt.Errorf("could not find spec file: %v", err) return fmt.Errorf("could not find spec file: %v", err)
} }
var pkgGroup = DefaultSrpmBuildPkgGroup
if len(project.SrpmStagePackages) != 0 {
pkgGroup = project.SrpmStagePackages
}
if len(pkgEo.DependsOn) != 0 {
for _, pkg := range pkgEo.DependsOn {
pkgGroup = append(pkgGroup, pkg)
}
}
hostArch := os.Getenv("REAL_BUILD_ARCH") hostArch := os.Getenv("REAL_BUILD_ARCH")
extraOptions.EnableNetworking = true extraOptions.EnableNetworking = true
err = c.writeMockConfig(&project, packageVersion, extraOptions, "noarch", hostArch, SrpmBuildPkgGroup) err = c.writeMockConfig(&project, packageVersion, extraOptions, "noarch", hostArch, pkgGroup)
if err != nil { if err != nil {
return fmt.Errorf("could not write mock config: %v", err) return fmt.Errorf("could not write mock config: %v", err)
} }

View File

@ -35,6 +35,15 @@ import (
"encoding/base64" "encoding/base64"
"encoding/xml" "encoding/xml"
"fmt" "fmt"
"github.com/gobwas/glob"
"io/ioutil"
"os"
"path"
"path/filepath"
"regexp"
"strings"
"time"
"github.com/go-git/go-billy/v5" "github.com/go-git/go-billy/v5"
"github.com/go-git/go-billy/v5/memfs" "github.com/go-git/go-billy/v5/memfs"
"github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5"
@ -47,19 +56,12 @@ import (
"go.temporal.io/sdk/workflow" "go.temporal.io/sdk/workflow"
"google.golang.org/protobuf/encoding/prototext" "google.golang.org/protobuf/encoding/prototext"
"google.golang.org/protobuf/types/known/wrapperspb" "google.golang.org/protobuf/types/known/wrapperspb"
"io/ioutil"
"os"
"path"
"path/filepath"
peridotdb "peridot.resf.org/peridot/db" peridotdb "peridot.resf.org/peridot/db"
"peridot.resf.org/peridot/db/models" "peridot.resf.org/peridot/db/models"
peridotpb "peridot.resf.org/peridot/pb" peridotpb "peridot.resf.org/peridot/pb"
"peridot.resf.org/peridot/yummeta" "peridot.resf.org/peridot/yummeta"
yumrepofspb "peridot.resf.org/peridot/yumrepofs/pb" yumrepofspb "peridot.resf.org/peridot/yumrepofs/pb"
"peridot.resf.org/utils" "peridot.resf.org/utils"
"regexp"
"strings"
"time"
) )
var ( var (
@ -450,6 +452,97 @@ func kindCatalogSync(tx peridotdb.Access, req *peridotpb.SyncCatalogRequest, cat
return &ret, nil return &ret, nil
} }
func processGroupInstallScopedPackageOptions(tx peridotdb.Access, req *peridotpb.SyncCatalogRequest, groupInstallOptionSet *peridotpb.CatalogGroupInstallOption) (scopedPackages *peridotpb.CatalogGroupInstallScopedPackage, err error) {
// handle scoped packages relationships on packages for injection into build root
for _, scopedPackage := range groupInstallOptionSet.ScopedPackage {
filters := &peridotpb.PackageFilters{NameExact: wrapperspb.String(scopedPackage.Name)}
isGlob := false
if strings.HasPrefix(scopedPackage.Name, "*") || strings.HasSuffix(scopedPackage.Name, "*") {
filters.Name = wrapperspb.String(strings.TrimSuffix(strings.TrimPrefix(scopedPackage.Name, "*"), "*"))
filters.NameExact = nil
isGlob = true
}
pkgs, err := tx.GetPackagesInProject(filters, req.ProjectId.Value, 0, -1)
if err != nil {
return nil, fmt.Errorf("failed to get package %s: %w", scopedPackage.Name, err)
}
if len(pkgs) == 0 {
return nil, fmt.Errorf("package %s not found in project %s (scoped package)", scopedPackage.Name, req.ProjectId.Value)
}
var dbPkgs []models.Package
if isGlob {
for _, p := range pkgs {
g, err := glob.Compile(scopedPackage.Name)
if err != nil {
return nil, fmt.Errorf("failed to compile glob %s: %w", scopedPackage.Name, err)
}
if g.Match(p.Name) {
dbPkgs = append(dbPkgs, p)
}
}
} else {
if scopedPackage.Name != pkgs[0].Name {
return nil, fmt.Errorf("package %s not found in project %s (cannot set extra options, not glob)", scopedPackage.Name, req.ProjectId.Value)
}
dbPkgs = append(dbPkgs, pkgs[0])
}
if len(dbPkgs) == 0 {
return nil, fmt.Errorf("package %s not found in project %s (cannot set extra options, glob)", scopedPackage.Name, req.ProjectId.Value)
}
for _, dbPkg := range dbPkgs {
err = tx.SetGroupInstallOptionsForPackage(req.ProjectId.Value, dbPkg.Name, scopedPackage.DependsOn)
if err != nil {
return nil, fmt.Errorf("failed to set scoped package options for package %s", scopedPackage.Name)
}
}
}
return scopedPackages, nil
}
func processGroupInstallOptionSet(groupInstallOptionSet *peridotpb.CatalogGroupInstallOption) (packages []string, err error) {
for _, name := range groupInstallOptionSet.Name {
packages = append(packages, name)
}
if len(packages) == 0 {
return nil, fmt.Errorf("failed to parse packages from GroupInstall options")
}
return packages, nil
}
func kindCatalogGroupInstallOptions(tx peridotdb.Access, req *peridotpb.SyncCatalogRequest, groupInstallOptions []*peridotpb.CatalogGroupInstallOptions) (*peridotpb.KindCatalogGroupInstallOptions, error) {
ret := &peridotpb.KindCatalogGroupInstallOptions{}
for _, groupInstallOption := range groupInstallOptions {
// Proces scoped packages
scopedPackages, err := processGroupInstallScopedPackageOptions(tx, req, groupInstallOption.Srpm)
if err != nil {
return nil, fmt.Errorf("failed to parse srpm groupinstall options: %s", err.Error())
}
ret.ScopedPackage = append(ret.ScopedPackage, scopedPackages)
// Process build root packages
srpmPackages, err := processGroupInstallOptionSet(groupInstallOption.Srpm)
if err != nil {
return nil, fmt.Errorf("failed to parse srpm groupinstall options: %w", err)
}
buildPackages, err := processGroupInstallOptionSet(groupInstallOption.Build)
if err != nil {
return nil, fmt.Errorf("failed to parse build groupinstall options: %w", err)
}
err = tx.SetBuildRootPackages(req.ProjectId.Value, srpmPackages, buildPackages)
ret.SrpmPackages = append(ret.SrpmPackages, srpmPackages...)
ret.BuildPackages = append(ret.BuildPackages, buildPackages...)
}
return ret, nil
}
func kindCatalogExtraOptions(tx peridotdb.Access, req *peridotpb.SyncCatalogRequest, extraOptions []*peridotpb.CatalogExtraOptions) (*peridotpb.KindCatalogExtraOptions, error) { func kindCatalogExtraOptions(tx peridotdb.Access, req *peridotpb.SyncCatalogRequest, extraOptions []*peridotpb.CatalogExtraOptions) (*peridotpb.KindCatalogExtraOptions, error) {
ret := &peridotpb.KindCatalogExtraOptions{} ret := &peridotpb.KindCatalogExtraOptions{}
@ -704,6 +797,7 @@ func (c *Controller) SyncCatalogActivity(req *peridotpb.SyncCatalogRequest) (*pe
var catalogs []*peridotpb.CatalogSync var catalogs []*peridotpb.CatalogSync
var extraOptions []*peridotpb.CatalogExtraOptions var extraOptions []*peridotpb.CatalogExtraOptions
var groupInstallOptions []*peridotpb.CatalogGroupInstallOptions
files, err := recursiveSearchBillyFs(w.Filesystem, ".", ".cfg") files, err := recursiveSearchBillyFs(w.Filesystem, ".", ".cfg")
if err != nil { if err != nil {
@ -745,6 +839,13 @@ func (c *Controller) SyncCatalogActivity(req *peridotpb.SyncCatalogRequest) (*pe
return nil, fmt.Errorf("failed to parse kind resf.peridot.v1.CatalogExtraOptions: %w", err) return nil, fmt.Errorf("failed to parse kind resf.peridot.v1.CatalogExtraOptions: %w", err)
} }
extraOptions = append(extraOptions, ce1) extraOptions = append(extraOptions, ce1)
case "resf.peridot.v1.CatalogGroupInstallOptions":
cg1 := &peridotpb.CatalogGroupInstallOptions{}
err = prototext.Unmarshal(bts, cg1)
if err != nil {
return nil, fmt.Errorf("failed to parse kind resf.peridot.v1.CatalogGroupInstallOptions: %w", err)
}
groupInstallOptions = append(groupInstallOptions, cg1)
default: default:
return nil, fmt.Errorf("unknown format %s", format) return nil, fmt.Errorf("unknown format %s", format)
} }
@ -768,6 +869,12 @@ func (c *Controller) SyncCatalogActivity(req *peridotpb.SyncCatalogRequest) (*pe
} }
ret.ExtraOptions = resKindCatalogExtraOptions ret.ExtraOptions = resKindCatalogExtraOptions
resKindCatalogGroupInstallOptions, err := kindCatalogGroupInstallOptions(tx, req, groupInstallOptions)
if err != nil {
return nil, fmt.Errorf("failed to process kind CatalogSyncGroupInstallOptions: %w", err)
}
ret.GroupInstallOptions = resKindCatalogGroupInstallOptions
var buildIDs []string var buildIDs []string
var newBuildPackages []string var newBuildPackages []string
for _, newPackage := range ret.CatalogSync.NewPackages { for _, newPackage := range ret.CatalogSync.NewPackages {

View File

@ -45,6 +45,7 @@ type Access interface {
CreateProject(project *peridotpb.Project) (*models.Project, error) CreateProject(project *peridotpb.Project) (*models.Project, error)
UpdateProject(id string, project *peridotpb.Project) (*models.Project, error) UpdateProject(id string, project *peridotpb.Project) (*models.Project, error)
SetProjectKeys(projectId string, username string, password string) error SetProjectKeys(projectId string, username string, password string) error
SetBuildRootPackages(projectId string, srpmPackages []string, buildPackages []string) error
CreateBuild(packageId string, packageVersionId string, taskId string, projectId string) (*models.Build, error) CreateBuild(packageId string, packageVersionId string, taskId string, projectId string) (*models.Build, error)
GetArtifactsForBuild(buildId string) (models.TaskArtifacts, error) GetArtifactsForBuild(buildId string) (models.TaskArtifacts, error)
@ -96,6 +97,7 @@ type Access interface {
GetPackageID(name string) (string, error) GetPackageID(name string) (string, error)
SetExtraOptionsForPackage(projectId string, packageName string, withFlags pq.StringArray, withoutFlags pq.StringArray) error SetExtraOptionsForPackage(projectId string, packageName string, withFlags pq.StringArray, withoutFlags pq.StringArray) error
GetExtraOptionsForPackage(projectId string, packageName string) (*models.ExtraOptions, error) GetExtraOptionsForPackage(projectId string, packageName string) (*models.ExtraOptions, error)
SetGroupInstallOptionsForPackage(projectId string, packageName string, dependsOn pq.StringArray) error
CreateTask(user *utils.ContextUser, arch string, taskType peridotpb.TaskType, projectId *string, parentTaskId *string) (*models.Task, error) CreateTask(user *utils.ContextUser, arch string, taskType peridotpb.TaskType, projectId *string, parentTaskId *string) (*models.Task, error)
SetTaskStatus(id string, status peridotpb.TaskStatus) error SetTaskStatus(id string, status peridotpb.TaskStatus) error

View File

@ -77,6 +77,7 @@ type ExtraOptions struct {
PackageName string `json:"packageName" db:"package_name"` PackageName string `json:"packageName" db:"package_name"`
WithFlags pq.StringArray `json:"withFlags" db:"with_flags"` WithFlags pq.StringArray `json:"withFlags" db:"with_flags"`
WithoutFlags pq.StringArray `json:"withoutFlags" db:"without_flags"` WithoutFlags pq.StringArray `json:"withoutFlags" db:"without_flags"`
DependsOn pq.StringArray `json:"dependsOn" db:"depends_on"`
} }
func (p *Package) ToProto() *peridotpb.Package { func (p *Package) ToProto() *peridotpb.Package {

View File

@ -70,6 +70,9 @@ type Project struct {
VendorMacro sql.NullString `json:"vendorMacro" db:"vendor_macro"` VendorMacro sql.NullString `json:"vendorMacro" db:"vendor_macro"`
PackagerMacro sql.NullString `json:"packagerMacro" db:"packager_macro"` PackagerMacro sql.NullString `json:"packagerMacro" db:"packager_macro"`
SrpmStagePackages pq.StringArray `json:"srpmStagePackages" db:"srpm_stage_packages"`
BuildStagePackages pq.StringArray `json:"buildStagePackages" db:"build_stage_packages"`
} }
type Projects []Project type Projects []Project

View File

@ -335,7 +335,7 @@ func (a *Access) GetExtraOptionsForPackage(projectId string, packageName string)
var ret models.ExtraOptions var ret models.ExtraOptions
err := a.query.Get( err := a.query.Get(
&ret, &ret,
"select id, created_at, updated_at, project_id, package_name, with_flags, without_flags from extra_package_options where project_id = $1 and package_name = $2", "select id, created_at, updated_at, project_id, package_name, with_flags, without_flags, depends_on from extra_package_options where project_id = $1 and package_name = $2",
projectId, projectId,
packageName, packageName,
) )
@ -344,3 +344,21 @@ func (a *Access) GetExtraOptionsForPackage(projectId string, packageName string)
} }
return &ret, nil return &ret, nil
} }
func (a *Access) SetGroupInstallOptionsForPackage(projectId string, packageName string, dependsOn pq.StringArray) error {
if dependsOn == nil {
dependsOn = pq.StringArray{}
}
_, err := a.query.Exec(
`
insert into extra_package_options (project_id, package_name, depends_on)
values ($1, $2, $3)
on conflict on constraint extra_package_options_uniq do
update set depends_on = $3, updated_at = now()
`,
projectId,
packageName,
dependsOn,
)
return err
}

View File

@ -310,3 +310,16 @@ func (a *Access) SetProjectKeys(projectId string, username string, password stri
) )
return err return err
} }
func (a *Access) SetBuildRootPackages(projectId string, srpmPackages []string, buildPackages []string) error {
_, err := a.query.Exec(
`
update projects set srpm_stage_packages = $2, build_stage_packages = $3
where project_id = $1
`,
projectId,
srpmPackages,
buildPackages,
)
return err
}

View File

@ -0,0 +1,6 @@
ALTER TABLE
IF EXISTS extra_package_options DROP COLUMN IF EXISTS depends_on;
ALTER TABLE
IF EXISTS projects DROP COLUMN IF EXISTS srpm_stage_packages,
DROP COLUMN IF EXISTS build_stage_packages;

View File

@ -0,0 +1,11 @@
ALTER TABLE
IF EXISTS extra_package_options
ADD
COLUMN IF NOT EXISTS depends_on text [] not null default array [] :: text [];
ALTER TABLE
IF EXISTS projects
ADD
COLUMN IF NOT EXISTS srpm_stage_packages text [] not null default array [] :: text [],
ADD
COLUMN IF NOT EXISTS build_stage_packages text [] not null default array [] :: text [];

View File

@ -55,6 +55,23 @@ message CatalogExtraPackageOptions {
repeated string without = 3 [(validate.rules).repeated = {unique: true}]; repeated string without = 3 [(validate.rules).repeated = {unique: true}];
} }
message CatalogGroupInstallScopedPackage {
string name = 1 [(validate.rules).string.min_bytes = 1];
repeated string depends_on = 2 [(validate.rules).repeated = {unique: true}];
}
message CatalogGroupInstallOption {
// list of all packages required to be installed in the build root per project
repeated string name = 1 [(validate.rules).repeated.items.string.min_bytes = 1];
// Scoped packages allow for dynamically injecting build requirements into the build root e.g. when building SCLs
repeated CatalogGroupInstallScopedPackage scoped_package = 2;
}
message CatalogGroupInstallOptions {
CatalogGroupInstallOption srpm = 1;
CatalogGroupInstallOption build = 2;
}
message CatalogExtraOptions { message CatalogExtraOptions {
repeated CatalogExtraPackageOptions package_options = 1; repeated CatalogExtraPackageOptions package_options = 1;
} }
@ -71,8 +88,15 @@ message KindCatalogExtraOptions {
repeated string modified_packages = 1; repeated string modified_packages = 1;
} }
message KindCatalogGroupInstallOptions {
repeated string srpm_packages = 1;
repeated string build_packages = 2;
repeated CatalogGroupInstallScopedPackage scoped_package = 3;
}
message SyncCatalogTask { message SyncCatalogTask {
KindCatalogSync catalog_sync = 1; KindCatalogSync catalog_sync = 1;
KindCatalogExtraOptions extra_options = 2; KindCatalogExtraOptions extra_options = 2;
KindCatalogGroupInstallOptions group_install_options = 4;
repeated string reprocess_build_ids = 3; repeated string reprocess_build_ids = 3;
} }

View File

@ -119,5 +119,6 @@ func Bool(b bool) *bool {
} }
func Pointer[T any](t T) *T { func Pointer[T any](t T) *T {
return &t s := t
return &s
} }