Skip to content

Commit

Permalink
Merge pull request helm#12177 from sabre1041/oci-annotation-created
Browse files Browse the repository at this point in the history
Add created OCI annotation
  • Loading branch information
sabre1041 authored Jul 5, 2023
2 parents 03911ae + d72b42d commit 49fe297
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 13 deletions.
10 changes: 9 additions & 1 deletion pkg/registry/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,7 @@ type (
pushOperation struct {
provData []byte
strictMode bool
test bool
}
)

Expand Down Expand Up @@ -551,7 +552,7 @@ func (c *Client) Push(data []byte, ref string, options ...PushOption) (*PushResu
descriptors = append(descriptors, provDescriptor)
}

ociAnnotations := generateOCIAnnotations(meta)
ociAnnotations := generateOCIAnnotations(meta, operation.test)

manifestData, manifest, err := content.GenerateManifest(&configDescriptor, ociAnnotations, descriptors...)
if err != nil {
Expand Down Expand Up @@ -616,6 +617,13 @@ func PushOptStrictMode(strictMode bool) PushOption {
}
}

// PushOptTest returns a function that sets whether test setting on push
func PushOptTest(test bool) PushOption {
return func(operation *pushOperation) {
operation.test = test
}
}

// Tags provides a sorted list all semver compliant tags for a given repository
func (c *Client) Tags(ref string) ([]string, error) {
parsedReference, err := registry.ParseReference(ref)
Expand Down
13 changes: 10 additions & 3 deletions pkg/registry/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ import (
"io"
"net/http"
"strings"
"time"

helmtime "helm.sh/helm/v3/pkg/time"

"github.com/Masterminds/semver/v3"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
Expand Down Expand Up @@ -163,10 +166,10 @@ func NewRegistryClientWithTLS(out io.Writer, certFile, keyFile, caFile string, i
}

// generateOCIAnnotations will generate OCI annotations to include within the OCI manifest
func generateOCIAnnotations(meta *chart.Metadata) map[string]string {
func generateOCIAnnotations(meta *chart.Metadata, test bool) map[string]string {

// Get annotations from Chart attributes
ociAnnotations := generateChartOCIAnnotations(meta)
ociAnnotations := generateChartOCIAnnotations(meta, test)

// Copy Chart annotations
annotations:
Expand All @@ -187,14 +190,18 @@ annotations:
}

// getChartOCIAnnotations will generate OCI annotations from the provided chart
func generateChartOCIAnnotations(meta *chart.Metadata) map[string]string {
func generateChartOCIAnnotations(meta *chart.Metadata, test bool) map[string]string {
chartOCIAnnotations := map[string]string{}

chartOCIAnnotations = addToMap(chartOCIAnnotations, ocispec.AnnotationDescription, meta.Description)
chartOCIAnnotations = addToMap(chartOCIAnnotations, ocispec.AnnotationTitle, meta.Name)
chartOCIAnnotations = addToMap(chartOCIAnnotations, ocispec.AnnotationVersion, meta.Version)
chartOCIAnnotations = addToMap(chartOCIAnnotations, ocispec.AnnotationURL, meta.Home)

if !test {
chartOCIAnnotations = addToMap(chartOCIAnnotations, ocispec.AnnotationCreated, helmtime.Now().UTC().Format(time.RFC3339))
}

if len(meta.Sources) > 0 {
chartOCIAnnotations = addToMap(chartOCIAnnotations, ocispec.AnnotationSource, meta.Sources[0])
}
Expand Down
28 changes: 26 additions & 2 deletions pkg/registry/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,12 @@ package registry // import "helm.sh/helm/v3/pkg/registry"
import (
"reflect"
"testing"
"time"

ocispec "github.com/opencontainers/image-spec/specs-go/v1"

"helm.sh/helm/v3/pkg/chart"
helmtime "helm.sh/helm/v3/pkg/time"
)

func TestGenerateOCIChartAnnotations(t *testing.T) {
Expand Down Expand Up @@ -137,7 +141,7 @@ func TestGenerateOCIChartAnnotations(t *testing.T) {

for _, tt := range tests {

result := generateChartOCIAnnotations(tt.chart)
result := generateChartOCIAnnotations(tt.chart, true)

if !reflect.DeepEqual(tt.expect, result) {
t.Errorf("%s: expected map %v, got %v", tt.name, tt.expect, result)
Expand Down Expand Up @@ -206,11 +210,31 @@ func TestGenerateOCIAnnotations(t *testing.T) {

for _, tt := range tests {

result := generateOCIAnnotations(tt.chart)
result := generateOCIAnnotations(tt.chart, true)

if !reflect.DeepEqual(tt.expect, result) {
t.Errorf("%s: expected map %v, got %v", tt.name, tt.expect, result)
}

}
}

func TestGenerateOCICreatedAnnotations(t *testing.T) {
chart := &chart.Metadata{
Name: "oci",
Version: "0.0.1",
}

result := generateOCIAnnotations(chart, false)

// Check that created annotation exists
if _, ok := result[ocispec.AnnotationCreated]; !ok {
t.Errorf("%s annotation not created", ocispec.AnnotationCreated)
}

// Verify value of created artifact in RFC3339 format
if _, err := helmtime.Parse(time.RFC3339, result[ocispec.AnnotationCreated]); err != nil {
t.Errorf("%s annotation with value '%s' not in RFC3339 format", ocispec.AnnotationCreated, result[ocispec.AnnotationCreated])
}

}
14 changes: 7 additions & 7 deletions pkg/registry/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ func initCompromisedRegistryTestServer() string {
func testPush(suite *TestSuite) {
// Bad bytes
ref := fmt.Sprintf("%s/testrepo/testchart:1.2.3", suite.DockerRegistryHost)
_, err := suite.RegistryClient.Push([]byte("hello"), ref)
_, err := suite.RegistryClient.Push([]byte("hello"), ref, PushOptTest(true))
suite.NotNil(err, "error pushing non-chart bytes")

// Load a test chart
Expand All @@ -227,20 +227,20 @@ func testPush(suite *TestSuite) {

// non-strict ref (chart name)
ref = fmt.Sprintf("%s/testrepo/boop:%s", suite.DockerRegistryHost, meta.Version)
_, err = suite.RegistryClient.Push(chartData, ref)
_, err = suite.RegistryClient.Push(chartData, ref, PushOptTest(true))
suite.NotNil(err, "error pushing non-strict ref (bad basename)")

// non-strict ref (chart name), with strict mode disabled
_, err = suite.RegistryClient.Push(chartData, ref, PushOptStrictMode(false))
_, err = suite.RegistryClient.Push(chartData, ref, PushOptStrictMode(false), PushOptTest(true))
suite.Nil(err, "no error pushing non-strict ref (bad basename), with strict mode disabled")

// non-strict ref (chart version)
ref = fmt.Sprintf("%s/testrepo/%s:latest", suite.DockerRegistryHost, meta.Name)
_, err = suite.RegistryClient.Push(chartData, ref)
_, err = suite.RegistryClient.Push(chartData, ref, PushOptTest(true))
suite.NotNil(err, "error pushing non-strict ref (bad tag)")

// non-strict ref (chart version), with strict mode disabled
_, err = suite.RegistryClient.Push(chartData, ref, PushOptStrictMode(false))
_, err = suite.RegistryClient.Push(chartData, ref, PushOptStrictMode(false), PushOptTest(true))
suite.Nil(err, "no error pushing non-strict ref (bad tag), with strict mode disabled")

// basic push, good ref
Expand All @@ -249,7 +249,7 @@ func testPush(suite *TestSuite) {
meta, err = extractChartMeta(chartData)
suite.Nil(err, "no error extracting chart meta")
ref = fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version)
_, err = suite.RegistryClient.Push(chartData, ref)
_, err = suite.RegistryClient.Push(chartData, ref, PushOptTest(true))
suite.Nil(err, "no error pushing good ref")

_, err = suite.RegistryClient.Pull(ref)
Expand All @@ -267,7 +267,7 @@ func testPush(suite *TestSuite) {

// push with prov
ref = fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version)
result, err := suite.RegistryClient.Push(chartData, ref, PushOptProvData(provData))
result, err := suite.RegistryClient.Push(chartData, ref, PushOptProvData(provData), PushOptTest(true))
suite.Nil(err, "no error pushing good ref with prov")

_, err = suite.RegistryClient.Pull(ref)
Expand Down

0 comments on commit 49fe297

Please sign in to comment.