Repository: deislabs/ratify
Pull request #699 (2023-03-09 23:07:08)

fix: update plugin download logic for oci image support
# Description

## What this PR does / why we need it:
- updates OCI external plugin download logic to support OCI Image and OCI Artifact manifests

## Type of change

Please delete options that are not relevant.

- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update

# How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Please also list any relevant details for your test configuration

- [x] Unit Tests
- [ ] E2e tests

# Checklist:

- [ ] Does the affected code have corresponding tests?
- [ ] Are the changes documented, not just with inline documentation, but also with conceptual documentation such as an overview of a new feature, or task-based documentation like a tutorial? Consider if this change should be announced on your project blog.
- [ ] Does this introduce breaking changes that would require an announcement or bumping the major version?
- [x] Do all new files have appropriate license header?


akashsinghal: cc: @noelbundick-msft 
codecov[bot]: ## [Codecov](https://codecov.io/gh/deislabs/ratify/pull/699?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) Report
Patch coverage: **`36.36`**% and project coverage change: **`-0.15`** :warning:
> Comparison is base [(`4cf9838`)](https://codecov.io/gh/deislabs/ratify/commit/4cf98388ef33c587ef86b82e05cb0f7de2da2ea8?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) 44.51% compared to head [(`146aefc`)](https://codecov.io/gh/deislabs/ratify/pull/699?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) 44.36%.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main     #699      +/-   ##
==========================================
- Coverage   44.51%   44.36%   -0.15%     
==========================================
  Files          56       57       +1     
  Lines        3266     3277      +11     
==========================================
  Hits         1454     1454              
- Misses       1664     1675      +11     
  Partials      148      148              
```


| [Impacted Files](https://codecov.io/gh/deislabs/ratify/pull/699?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) | Coverage Δ | |
|---|---|---|
| [pkg/common/plugin/download.go](https://codecov.io/gh/deislabs/ratify/pull/699?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2NvbW1vbi9wbHVnaW4vZG93bmxvYWQuZ28=) | `7.36% <0.00%> (-0.97%)` | :arrow_down: |
| [pkg/referrerstore/oras/oras.go](https://codecov.io/gh/deislabs/ratify/pull/699?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL3JlZmVycmVyc3RvcmUvb3Jhcy9vcmFzLmdv) | `0.68% <0.00%> (ø)` | |
| [pkg/referrerstore/oras/utils.go](https://codecov.io/gh/deislabs/ratify/pull/699?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL3JlZmVycmVyc3RvcmUvb3Jhcy91dGlscy5nbw==) | `0.00% <ø> (-29.63%)` | :arrow_down: |
| [pkg/common/utils/utils.go](https://codecov.io/gh/deislabs/ratify/pull/699?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2NvbW1vbi91dGlscy91dGlscy5nbw==) | `100.00% <100.00%> (ø)` | |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None)

</details>

[:umbrella: View full report in Codecov by Sentry](https://codecov.io/gh/deislabs/ratify/pull/699?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None).   
:loudspeaker: Do you have feedback about the report comment? [Let us know in this issue](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None).


Patch:
diff --git a/pkg/common/plugin/download.go b/pkg/common/plugin/download.go
index 3b60bd6..565928e 100644
--- a/pkg/common/plugin/download.go
+++ b/pkg/common/plugin/download.go
@@ -25,7 +25,9 @@ import (
 	"time"
 
 	"github.com/deislabs/ratify/pkg/common/oras/authprovider"
+	commonutils "github.com/deislabs/ratify/pkg/common/utils"
 	"github.com/deislabs/ratify/pkg/ocispecs"
+	oci "github.com/opencontainers/image-spec/specs-go/v1"
 	"github.com/sirupsen/logrus"
 	"oras.land/oras-go/v2/registry/remote"
 	"oras.land/oras-go/v2/registry/remote/auth"
@@ -108,8 +110,19 @@ func DownloadPlugin(source PluginSource, targetPath string) error {
 	}
 
 	referenceManifest := ocispecs.ReferenceManifest{}
-	if err := json.Unmarshal(manifestBytes, &referenceManifest); err != nil {
-		return err
+	// marshal manifest bytes into reference manifest descriptor
+	if referenceManifestDescriptor.MediaType == oci.MediaTypeImageManifest {
+		var imageManifest oci.Manifest
+		if err := json.Unmarshal(manifestBytes, &imageManifest); err != nil {
+			return err
+		}
+		referenceManifest = commonutils.OciManifestToReferenceManifest(imageManifest)
+	} else if referenceManifestDescriptor.MediaType == oci.MediaTypeArtifactManifest {
+		if err := json.Unmarshal(manifestBytes, &referenceManifest); err != nil {
+			return err
+		}
+	} else {
+		return fmt.Errorf("unsupported manifest media type: %s", referenceManifestDescriptor.MediaType)
 	}
 
 	// download the first blob to the target path
diff --git a/pkg/common/utils/utils.go b/pkg/common/utils/utils.go
new file mode 100644
index 0000000..c0980ce
--- /dev/null
+++ b/pkg/common/utils/utils.go
@@ -0,0 +1,31 @@
+/*
+Copyright The Ratify Authors.
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package utils
+
+import (
+	"github.com/deislabs/ratify/pkg/ocispecs"
+	oci "github.com/opencontainers/image-spec/specs-go/v1"
+)
+
+func OciManifestToReferenceManifest(ociManifest oci.Manifest) ocispecs.ReferenceManifest {
+	return ocispecs.ReferenceManifest{
+		MediaType:    ociManifest.MediaType,
+		ArtifactType: ociManifest.Config.MediaType,
+		Blobs:        ociManifest.Layers,
+		Subject:      ociManifest.Subject,
+		Annotations:  ociManifest.Annotations,
+	}
+}
diff --git a/pkg/referrerstore/oras/oras.go b/pkg/referrerstore/oras/oras.go
index a6a7713..af08385 100644
--- a/pkg/referrerstore/oras/oras.go
+++ b/pkg/referrerstore/oras/oras.go
@@ -42,6 +42,7 @@ import (
 	"github.com/deislabs/ratify/pkg/common/oras/authprovider"
 	_ "github.com/deislabs/ratify/pkg/common/oras/authprovider/aws"
 	_ "github.com/deislabs/ratify/pkg/common/oras/authprovider/azure"
+	commonutils "github.com/deislabs/ratify/pkg/common/utils"
 	"github.com/deislabs/ratify/pkg/homedir"
 	"github.com/deislabs/ratify/pkg/ocispecs"
 	"github.com/deislabs/ratify/pkg/referrerstore"
@@ -347,7 +348,7 @@ func (store *orasStore) GetReferenceManifest(ctx context.Context, subjectReferen
 		if err := json.Unmarshal(manifestBytes, &imageManifest); err != nil {
 			return ocispecs.ReferenceManifest{}, err
 		}
-		referenceManifest = OciManifestToReferenceManifest(imageManifest)
+		referenceManifest = commonutils.OciManifestToReferenceManifest(imageManifest)
 	} else if referenceDesc.Descriptor.MediaType == oci.MediaTypeArtifactManifest {
 		if err := json.Unmarshal(manifestBytes, &referenceManifest); err != nil {
 			return ocispecs.ReferenceManifest{}, err
diff --git a/pkg/referrerstore/oras/utils.go b/pkg/referrerstore/oras/utils.go
index 9984ae3..4d4b7dd 100644
--- a/pkg/referrerstore/oras/utils.go
+++ b/pkg/referrerstore/oras/utils.go
@@ -53,13 +53,3 @@ func OciDescriptorToReferenceDescriptor(ociDescriptor oci.Descriptor) ocispecs.R
 		ArtifactType: ociDescriptor.ArtifactType,
 	}
 }
-
-func OciManifestToReferenceManifest(ociManifest oci.Manifest) ocispecs.ReferenceManifest {
-	return ocispecs.ReferenceManifest{
-		MediaType:    ociManifest.MediaType,
-		ArtifactType: ociManifest.Config.MediaType,
-		Blobs:        ociManifest.Layers,
-		Subject:      ociManifest.Subject,
-		Annotations:  ociManifest.Annotations,
-	}
-}


Test patch:
diff --git a/pkg/common/utils/utils_test.go b/pkg/common/utils/utils_test.go
new file mode 100644
index 0000000..25665ae
--- /dev/null
+++ b/pkg/common/utils/utils_test.go
@@ -0,0 +1,93 @@
+/*
+Copyright The Ratify Authors.
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package utils
+
+import (
+	"reflect"
+	"testing"
+
+	"github.com/deislabs/ratify/pkg/ocispecs"
+	oci "github.com/opencontainers/image-spec/specs-go/v1"
+)
+
+func TestOciManifestToReferenceManifest(t *testing.T) {
+	type args struct {
+		ociManifest oci.Manifest
+	}
+	tests := []struct {
+		name string
+		args args
+		want ocispecs.ReferenceManifest
+	}{
+		{
+			name: "empty",
+			args: args{
+				ociManifest: oci.Manifest{},
+			},
+			want: ocispecs.ReferenceManifest{
+				MediaType:    "",
+				ArtifactType: "",
+			},
+		},
+		{
+			name: "simple",
+			args: args{
+				ociManifest: oci.Manifest{
+					MediaType: "application/vnd.oci.image.manifest.v1+json",
+					Config: oci.Descriptor{
+						MediaType: "application/vnd.oci.image.config.v1+json",
+					},
+				},
+			},
+			want: ocispecs.ReferenceManifest{
+				MediaType:    "application/vnd.oci.image.manifest.v1+json",
+				ArtifactType: "application/vnd.oci.image.config.v1+json",
+			},
+		},
+		{
+			name: "layers",
+			args: args{
+				ociManifest: oci.Manifest{
+					MediaType: "application/vnd.oci.image.manifest.v1+json",
+					Config: oci.Descriptor{
+						MediaType: "application/vnd.oci.image.config.v1+json",
+					},
+					Layers: []oci.Descriptor{
+						{
+							MediaType: "application/vnd.oci.image.layer.v1.tar+gzip",
+						},
+					},
+				},
+			},
+			want: ocispecs.ReferenceManifest{
+				MediaType:    "application/vnd.oci.image.manifest.v1+json",
+				ArtifactType: "application/vnd.oci.image.config.v1+json",
+				Blobs: []oci.Descriptor{
+					{
+						MediaType: "application/vnd.oci.image.layer.v1.tar+gzip",
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := OciManifestToReferenceManifest(tt.args.ociManifest); !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("OciManifestToReferenceManifest() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
diff --git a/pkg/referrerstore/oras/utils_test.go b/pkg/referrerstore/oras/utils_test.go
index db2c5c7..4eb5f2a 100644
--- a/pkg/referrerstore/oras/utils_test.go
+++ b/pkg/referrerstore/oras/utils_test.go
@@ -16,7 +16,6 @@ limitations under the License.
 package oras
 
 import (
-	"reflect"
 	"testing"
 
 	"github.com/deislabs/ratify/pkg/ocispecs"
@@ -98,72 +97,3 @@ func TestOciDescriptorToReferenceDescriptor(t *testing.T) {
 		t.Fatalf("mismatch of reference descriptor: expected %v, actual %v", expected, output)
 	}
 }
-
-func TestOciManifestToReferenceManifest(t *testing.T) {
-	type args struct {
-		ociManifest oci.Manifest
-	}
-	tests := []struct {
-		name string
-		args args
-		want ocispecs.ReferenceManifest
-	}{
-		{
-			name: "empty",
-			args: args{
-				ociManifest: oci.Manifest{},
-			},
-			want: ocispecs.ReferenceManifest{
-				MediaType:    "",
-				ArtifactType: "",
-			},
-		},
-		{
-			name: "simple",
-			args: args{
-				ociManifest: oci.Manifest{
-					MediaType: "application/vnd.oci.image.manifest.v1+json",
-					Config: oci.Descriptor{
-						MediaType: "application/vnd.oci.image.config.v1+json",
-					},
-				},
-			},
-			want: ocispecs.ReferenceManifest{
-				MediaType:    "application/vnd.oci.image.manifest.v1+json",
-				ArtifactType: "application/vnd.oci.image.config.v1+json",
-			},
-		},
-		{
-			name: "layers",
-			args: args{
-				ociManifest: oci.Manifest{
-					MediaType: "application/vnd.oci.image.manifest.v1+json",
-					Config: oci.Descriptor{
-						MediaType: "application/vnd.oci.image.config.v1+json",
-					},
-					Layers: []oci.Descriptor{
-						{
-							MediaType: "application/vnd.oci.image.layer.v1.tar+gzip",
-						},
-					},
-				},
-			},
-			want: ocispecs.ReferenceManifest{
-				MediaType:    "application/vnd.oci.image.manifest.v1+json",
-				ArtifactType: "application/vnd.oci.image.config.v1+json",
-				Blobs: []oci.Descriptor{
-					{
-						MediaType: "application/vnd.oci.image.layer.v1.tar+gzip",
-					},
-				},
-			},
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			if got := OciManifestToReferenceManifest(tt.args.ociManifest); !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("OciManifestToReferenceManifest() = %v, want %v", got, tt.want)
-			}
-		})
-	}
-}