diff --git a/pkg/compiler/types/artifact/artifact.go b/pkg/compiler/types/artifact/artifact.go index 8aa2f033..2b3c28b2 100644 --- a/pkg/compiler/types/artifact/artifact.go +++ b/pkg/compiler/types/artifact/artifact.go @@ -63,6 +63,7 @@ type PackageArtifact struct { CompressionType compression.Implementation `json:"compressiontype"` Files []string `json:"files"` PackageCacheImage string `json:"package_cacheimage"` + Runtime *pkg.DefaultPackage `json:"runtime,omitempty"` } func (p *PackageArtifact) ShallowCopy() *PackageArtifact { @@ -108,12 +109,16 @@ func (a *PackageArtifact) WriteYaml(dst string) error { return errors.Wrap(err, "Failed generating checksums for artifact") } - //p := a.CompileSpec.GetPackage().GetPath() + // Update runtime package information + if a.CompileSpec != nil && a.CompileSpec.Package != nil { + runtime, err := a.CompileSpec.Package.GetRuntimePackage() + if err != nil { + return errors.Wrapf(err, "getting runtime package for '%s'", a.CompileSpec.Package.HumanReadableString()) + } + + a.Runtime = runtime + } - //a.CompileSpec.GetPackage().SetPath("") - // for _, ass := range a.CompileSpec.GetSourceAssertion() { - // ass.Package.SetPath("") - // } data, err := yaml.Marshal(a) if err != nil { return errors.Wrap(err, "While marshalling for PackageArtifact YAML") diff --git a/pkg/installer/repository.go b/pkg/installer/repository.go index b51c5b7b..d9af9a1d 100644 --- a/pkg/installer/repository.go +++ b/pkg/installer/repository.go @@ -318,13 +318,17 @@ func GenerateRepository(p ...RepositoryOption) (*LuetSystemRepository, error) { } if _, err := runtimeTree.FindPackage(art.CompileSpec.Package); err != nil && art.CompileSpec.Package.Name != "" { Debug("Adding", art.CompileSpec.Package.HumanReadableString(), "from metadata file", currentpath) - // We don't have runtime at this point. So we import the package as is - r := []*pkg.DefaultPackage{} - p := art.CompileSpec.Package.Clone() - p.Requires(r) - p.SetProvides(r) - p.Conflicts(r) - runtimeTree.CreatePackage(p) + if art.Runtime != nil && art.Runtime.Name != "" { + runtimeTree.CreatePackage(art.Runtime) + } else { + // We don't have runtime at this point. So we import the package as is + r := []*pkg.DefaultPackage{} + p := art.CompileSpec.Package.Clone() + p.Requires(r) + p.SetProvides(r) + p.Conflicts(r) + runtimeTree.CreatePackage(p) + } } return nil diff --git a/pkg/installer/system.go b/pkg/installer/system.go index bd0604bc..6e37b4e5 100644 --- a/pkg/installer/system.go +++ b/pkg/installer/system.go @@ -29,7 +29,7 @@ func (s *System) ExecuteFinalizers(packs []pkg.Package) error { executedFinalizer := map[string]bool{} for _, p := range packs { if fileHelper.Exists(p.Rel(tree.FinalizerFile)) { - out, err := helpers.RenderFiles(helpers.ChartFile(p.Rel(tree.FinalizerFile)), p.Rel(tree.DefinitionFile)) + out, err := helpers.RenderFiles(helpers.ChartFile(p.Rel(tree.FinalizerFile)), p.Rel(pkg.PackageDefinitionFile)) if err != nil { Warning("Failed rendering finalizer for ", p.HumanReadableString(), err.Error()) errs = multierror.Append(errs, err) diff --git a/pkg/package/package.go b/pkg/package/package.go index d2481746..6985fcf9 100644 --- a/pkg/package/package.go +++ b/pkg/package/package.go @@ -21,11 +21,14 @@ import ( "encoding/json" "fmt" "io" + "io/ioutil" "path/filepath" "regexp" "strconv" "strings" + fileHelper "github.com/mudler/luet/pkg/helpers/file" + "github.com/mudler/luet/pkg/helpers/docker" "github.com/mudler/luet/pkg/helpers/match" version "github.com/mudler/luet/pkg/versioner" @@ -124,7 +127,11 @@ type Package interface { JSON() ([]byte, error) } -const PackageMetaSuffix = "metadata.yaml" +const ( + PackageMetaSuffix = "metadata.yaml" + PackageCollectionFile = "collection.yaml" + PackageDefinitionFile = "definition.yaml" +) type Tree interface { GetPackageSet() PackageDatabase @@ -215,11 +222,14 @@ func GetRawPackages(yml []byte) (rawPackages, error) { return rawPackages.Packages, nil } -func DefaultPackagesFromYaml(yml []byte) ([]DefaultPackage, error) { - var unescaped struct { - Packages []DefaultPackage `json:"packages"` - } +type Collection struct { + Packages []DefaultPackage `json:"packages"` +} + +func DefaultPackagesFromYAML(yml []byte) ([]DefaultPackage, error) { + + var unescaped Collection source, err := yaml.YAMLToJSON(yml) if err != nil { return []DefaultPackage{}, err @@ -381,6 +391,10 @@ func (p *DefaultPackage) MatchLabel(r *regexp.Regexp) bool { return match.MapMatchRegex(&p.Labels, r) } +func (p DefaultPackage) IsCollection() bool { + return fileHelper.Exists(filepath.Join(p.Path, PackageCollectionFile)) +} + func (p *DefaultPackage) HasAnnotation(label string) bool { return match.MapHasKey(&p.Annotations, label) } @@ -703,6 +717,39 @@ func (set Packages) Unique() Packages { return result } +func (p *DefaultPackage) GetRuntimePackage() (*DefaultPackage, error) { + var r *DefaultPackage + if p.IsCollection() { + collectionFile := filepath.Join(p.Path, PackageCollectionFile) + dat, err := ioutil.ReadFile(collectionFile) + if err != nil { + return r, errors.Wrapf(err, "failed while reading '%s'", collectionFile) + } + coll, err := DefaultPackagesFromYAML(dat) + if err != nil { + return r, errors.Wrapf(err, "failed while parsing YAML '%s'", collectionFile) + } + for _, c := range coll { + if c.Matches(p) { + r = &c + break + } + } + } else { + definitionFile := filepath.Join(p.Path, PackageDefinitionFile) + dat, err := ioutil.ReadFile(definitionFile) + if err != nil { + return r, errors.Wrapf(err, "failed while reading '%s'", definitionFile) + } + d, err := DefaultPackageFromYaml(dat) + if err != nil { + return r, errors.Wrapf(err, "failed while parsing YAML '%s'", definitionFile) + } + r = &d + } + return r, nil +} + func (pack *DefaultPackage) buildFormula(definitiondb PackageDatabase, db PackageDatabase, visited map[string]interface{}) ([]bf.Formula, error) { if _, ok := visited[pack.HumanReadableString()]; ok { return nil, nil diff --git a/pkg/tree/compiler_recipe.go b/pkg/tree/compiler_recipe.go index 22ee1931..20d3057e 100644 --- a/pkg/tree/compiler_recipe.go +++ b/pkg/tree/compiler_recipe.go @@ -90,12 +90,12 @@ func (r *CompilerRecipe) Load(path string) error { return errors.Wrap(err, "Error on walk path "+currentpath) } - if info.Name() != DefinitionFile && info.Name() != CollectionFile { + if info.Name() != pkg.PackageDefinitionFile && info.Name() != pkg.PackageCollectionFile { return nil // Skip with no errors } switch info.Name() { - case DefinitionFile: + case pkg.PackageDefinitionFile: pack, err := ReadDefinitionFile(currentpath) if err != nil { @@ -130,14 +130,14 @@ func (r *CompilerRecipe) Load(path string) error { return errors.Wrap(err, "Error creating package "+pack.GetName()) } - case CollectionFile: + case pkg.PackageCollectionFile: dat, err := ioutil.ReadFile(currentpath) if err != nil { return errors.Wrap(err, "Error reading file "+currentpath) } - packs, err := pkg.DefaultPackagesFromYaml(dat) + packs, err := pkg.DefaultPackagesFromYAML(dat) if err != nil { return errors.Wrap(err, "Error reading yaml "+currentpath) } diff --git a/pkg/tree/installer_recipe.go b/pkg/tree/installer_recipe.go index cc2496f3..974e0af6 100644 --- a/pkg/tree/installer_recipe.go +++ b/pkg/tree/installer_recipe.go @@ -56,7 +56,7 @@ func (r *InstallerRecipe) Save(path string) error { if err != nil { return err } - err = ioutil.WriteFile(filepath.Join(dir, DefinitionFile), data, 0644) + err = ioutil.WriteFile(filepath.Join(dir, pkg.PackageDefinitionFile), data, 0644) if err != nil { return err } @@ -86,7 +86,7 @@ func (r *InstallerRecipe) Load(path string) error { // the function that handles each file or dir var ff = func(currentpath string, info os.FileInfo, err error) error { - if info.Name() != DefinitionFile && info.Name() != CollectionFile { + if info.Name() != pkg.PackageDefinitionFile && info.Name() != pkg.PackageCollectionFile { return nil // Skip with no errors } @@ -96,7 +96,7 @@ func (r *InstallerRecipe) Load(path string) error { } switch info.Name() { - case DefinitionFile: + case pkg.PackageDefinitionFile: pack, err := pkg.DefaultPackageFromYaml(dat) if err != nil { return errors.Wrap(err, "Error reading yaml "+currentpath) @@ -109,8 +109,8 @@ func (r *InstallerRecipe) Load(path string) error { return errors.Wrap(err, "Error creating package "+pack.GetName()) } - case CollectionFile: - packs, err := pkg.DefaultPackagesFromYaml(dat) + case pkg.PackageCollectionFile: + packs, err := pkg.DefaultPackagesFromYAML(dat) if err != nil { return errors.Wrap(err, "Error reading yaml "+currentpath) } diff --git a/pkg/tree/recipes.go b/pkg/tree/recipes.go index 28a48e64..2738839b 100644 --- a/pkg/tree/recipes.go +++ b/pkg/tree/recipes.go @@ -33,11 +33,6 @@ import ( "github.com/pkg/errors" ) -const ( - DefinitionFile = "definition.yaml" - CollectionFile = "collection.yaml" -) - func NewGeneralRecipe(db pkg.PackageDatabase) Builder { return &Recipe{Database: db} } // Recipe is the "general" reciper for Trees @@ -64,7 +59,7 @@ func (r *Recipe) Save(path string) error { dir := filepath.Join(path, p.GetCategory(), p.GetName(), p.GetVersion()) os.MkdirAll(dir, os.ModePerm) - err := WriteDefinitionFile(p, filepath.Join(dir, DefinitionFile)) + err := WriteDefinitionFile(p, filepath.Join(dir, pkg.PackageDefinitionFile)) if err != nil { return err } @@ -96,7 +91,7 @@ func (r *Recipe) Load(path string) error { // the function that handles each file or dir var ff = func(currentpath string, info os.FileInfo, err error) error { - if info.Name() != DefinitionFile && info.Name() != CollectionFile { + if info.Name() != pkg.PackageDefinitionFile && info.Name() != pkg.PackageCollectionFile { return nil // Skip with no errors } @@ -106,7 +101,7 @@ func (r *Recipe) Load(path string) error { } switch info.Name() { - case DefinitionFile: + case pkg.PackageDefinitionFile: pack, err := pkg.DefaultPackageFromYaml(dat) if err != nil { return errors.Wrap(err, "Error reading yaml "+currentpath) @@ -118,8 +113,8 @@ func (r *Recipe) Load(path string) error { if err != nil { return errors.Wrap(err, "Error creating package "+pack.GetName()) } - case CollectionFile: - packs, err := pkg.DefaultPackagesFromYaml(dat) + case pkg.PackageCollectionFile: + packs, err := pkg.DefaultPackagesFromYAML(dat) if err != nil { return errors.Wrap(err, "Error reading yaml "+currentpath) }