From 44d68a9583a51b750a0e7e84115e02f2b0925f99 Mon Sep 17 00:00:00 2001 From: Daniele Rondina Date: Sat, 23 May 2020 09:25:26 +0200 Subject: [PATCH] Add annotations option to package spec --- pkg/helpers/match.go | 49 +++++++++++++++++++ pkg/package/package.go | 44 ++++++++++------- pkg/package/package_test.go | 31 ++++++++++++ pkg/spectooling/definition.go | 3 ++ pkg/tree/tree_test.go | 20 ++++++++ .../fixtures/annotations/pkgA/0.1/build.yaml | 3 ++ .../annotations/pkgA/0.1/definition.yaml | 6 +++ 7 files changed, 139 insertions(+), 17 deletions(-) create mode 100644 pkg/helpers/match.go create mode 100644 tests/fixtures/annotations/pkgA/0.1/build.yaml create mode 100644 tests/fixtures/annotations/pkgA/0.1/definition.yaml diff --git a/pkg/helpers/match.go b/pkg/helpers/match.go new file mode 100644 index 00000000..ade789ac --- /dev/null +++ b/pkg/helpers/match.go @@ -0,0 +1,49 @@ +// Copyright © 2019-2020 Ettore Di Giacinto +// Daniele Rondina +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, see . + +package helpers + +import ( + "regexp" +) + +func MapMatchRegex(m *map[string]string, r *regexp.Regexp) bool { + ans := false + + if m != nil { + for k, v := range *m { + if r.MatchString(k + "=" + v) { + ans = true + break + } + } + } + + return ans +} + +func MapHasKey(m *map[string]string, label string) bool { + ans := false + if m != nil { + for k, _ := range *m { + if k == label { + ans = true + break + } + } + } + return ans +} diff --git a/pkg/package/package.go b/pkg/package/package.go index 1e03123b..4d9cf7e5 100644 --- a/pkg/package/package.go +++ b/pkg/package/package.go @@ -26,6 +26,7 @@ import ( "strconv" "strings" + "github.com/mudler/luet/pkg/helpers" version "github.com/mudler/luet/pkg/versioner" gentoo "github.com/Sabayon/pkgs-checker/pkg/gentoo" @@ -93,6 +94,11 @@ type Package interface { HasLabel(string) bool MatchLabel(*regexp.Regexp) bool + AddAnnotation(string, string) + GetAnnotations() map[string]string + HasAnnotation(string) bool + MatchAnnotation(*regexp.Regexp) bool + IsSelector() bool VersionMatchSelector(string, version.Versioner) (bool, error) SelectorMatchVersion(string, version.Versioner) (bool, error) @@ -158,7 +164,8 @@ type DefaultPackage struct { IsSet bool `json:"set,omitempty"` // Affects YAML field names too. Provides []*DefaultPackage `json:"provides,omitempty"` // Affects YAML field names too. - // TODO: Annotations? + // Annotations are used for core features/options + Annotations map[string]string `json:"annotations,omitempty"` // Affects YAML field names too // Path is set only internally when tree is loaded from disk Path string `json:"path,omitempty"` @@ -240,25 +247,19 @@ func (p *DefaultPackage) IsSelector() bool { } func (p *DefaultPackage) HasLabel(label string) bool { - ans := false - for k, _ := range p.Labels { - if k == label { - ans = true - break - } - } - return ans + return helpers.MapHasKey(&p.Labels, label) } func (p *DefaultPackage) MatchLabel(r *regexp.Regexp) bool { - ans := false - for k, v := range p.Labels { - if r.MatchString(k + "=" + v) { - ans = true - break - } - } - return ans + return helpers.MapMatchRegex(&p.Labels, r) +} + +func (p *DefaultPackage) HasAnnotation(label string) bool { + return helpers.MapHasKey(&p.Annotations, label) +} + +func (p *DefaultPackage) MatchAnnotation(r *regexp.Regexp) bool { + return helpers.MapMatchRegex(&p.Annotations, r) } // AddUse adds a use to a package @@ -355,9 +356,18 @@ func (p *DefaultPackage) AddLabel(k, v string) { } p.Labels[k] = v } +func (p *DefaultPackage) AddAnnotation(k, v string) { + if p.Annotations == nil { + p.Annotations = make(map[string]string, 0) + } + p.Annotations[k] = v +} func (p *DefaultPackage) GetLabels() map[string]string { return p.Labels } +func (p *DefaultPackage) GetAnnotations() map[string]string { + return p.Annotations +} func (p *DefaultPackage) GetProvides() []*DefaultPackage { return p.Provides } diff --git a/pkg/package/package_test.go b/pkg/package/package_test.go index 91c0ae43..9b786bcf 100644 --- a/pkg/package/package_test.go +++ b/pkg/package/package_test.go @@ -46,6 +46,7 @@ var _ = Describe("Package", func() { a1 := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) a11 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{}) a01 := NewPackage("A", "0.1", []*DefaultPackage{}, []*DefaultPackage{}) + re := regexp.MustCompile("project[0-9][=].*") It("Expands correctly", func() { definitions := NewInMemoryDatabase(false) for _, p := range []Package{a1, a11, a01} { @@ -60,6 +61,8 @@ var _ = Describe("Package", func() { Expect(len(lst)).To(Equal(2)) p := lst.Best(nil) Expect(p).To(Equal(a11)) + // Test annotation with null map + Expect(a.MatchAnnotation(re)).To(Equal(false)) }) }) @@ -91,6 +94,34 @@ var _ = Describe("Package", func() { }) }) + Context("Find annotations on packages", func() { + a := NewPackage("A", ">=1.0", []*DefaultPackage{}, []*DefaultPackage{}) + a.AddAnnotation("project1", "test1") + a.AddAnnotation("label2", "value1") + b := NewPackage("B", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) + b.AddAnnotation("project2", "test2") + b.AddAnnotation("label2", "value1") + It("Expands correctly", func() { + var err error + definitions := NewInMemoryDatabase(false) + for _, p := range []Package{a, b} { + _, err = definitions.CreatePackage(p) + Expect(err).ToNot(HaveOccurred()) + } + re := regexp.MustCompile("project[0-9][=].*") + Expect(err).ToNot(HaveOccurred()) + Expect(re).ToNot(BeNil()) + Expect(a.HasAnnotation("label2")).To(Equal(true)) + Expect(a.HasAnnotation("label3")).To(Equal(false)) + Expect(a.HasAnnotation("project1")).To(Equal(true)) + Expect(b.HasAnnotation("project2")).To(Equal(true)) + Expect(b.HasAnnotation("label2")).To(Equal(true)) + Expect(b.MatchAnnotation(re)).To(Equal(true)) + Expect(a.MatchAnnotation(re)).To(Equal(true)) + + }) + }) + Context("Check description", func() { a := NewPackage("A", ">=1.0", []*DefaultPackage{}, []*DefaultPackage{}) a.SetDescription("Description A") diff --git a/pkg/spectooling/definition.go b/pkg/spectooling/definition.go index 6cce7224..6a235b80 100644 --- a/pkg/spectooling/definition.go +++ b/pkg/spectooling/definition.go @@ -32,6 +32,8 @@ type DefaultPackageSanitized struct { IsSet bool `json:"set,omitempty" yaml:"set,omitempty"` Provides []*DefaultPackageSanitized `json:"provides,omitempty" yaml:"provides,omitempty"` + Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"` + // Path is set only internally when tree is loaded from disk Path string `json:"path,omitempty" yaml:"path,omitempty"` @@ -54,6 +56,7 @@ func NewDefaultPackageSanitized(p pkg.Package) *DefaultPackageSanitized { Uri: p.GetURI(), License: p.GetLicense(), Labels: p.GetLabels(), + Annotations: p.GetAnnotations(), } if p.GetRequires() != nil && len(p.GetRequires()) > 0 { diff --git a/pkg/tree/tree_test.go b/pkg/tree/tree_test.go index 2550e297..e33b88e3 100644 --- a/pkg/tree/tree_test.go +++ b/pkg/tree/tree_test.go @@ -23,6 +23,7 @@ package tree_test import ( "io/ioutil" "os" + "regexp" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -171,4 +172,23 @@ var _ = Describe("Tree", func() { }) }) + Context("Simple tree with annotations", func() { + It("Read tree with annotations", func() { + db := pkg.NewInMemoryDatabase(false) + generalRecipe := NewCompilerRecipe(db) + r := regexp.MustCompile("^label") + + err := generalRecipe.Load("../../tests/fixtures/annotations") + Expect(err).ToNot(HaveOccurred()) + + Expect(len(generalRecipe.GetDatabase().World())).To(Equal(1)) + pack, err := generalRecipe.GetDatabase().FindPackage(&pkg.DefaultPackage{Name: "pkgA", Category: "test", Version: "0.1"}) + Expect(err).ToNot(HaveOccurred()) + + Expect(pack.HasAnnotation("label1")).To(Equal(true)) + Expect(pack.HasAnnotation("label3")).To(Equal(false)) + Expect(pack.MatchAnnotation(r)).To(Equal(true)) + }) + }) + }) diff --git a/tests/fixtures/annotations/pkgA/0.1/build.yaml b/tests/fixtures/annotations/pkgA/0.1/build.yaml new file mode 100644 index 00000000..6c7e610a --- /dev/null +++ b/tests/fixtures/annotations/pkgA/0.1/build.yaml @@ -0,0 +1,3 @@ +image: "alpine" +steps: + - echo "test" > /file1 diff --git a/tests/fixtures/annotations/pkgA/0.1/definition.yaml b/tests/fixtures/annotations/pkgA/0.1/definition.yaml new file mode 100644 index 00000000..0887e02b --- /dev/null +++ b/tests/fixtures/annotations/pkgA/0.1/definition.yaml @@ -0,0 +1,6 @@ +category: "test" +name: "pkgA" +version: "0.1" +annotations: + label1: "value1" + label2: "value2"