Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hotfix/add missing mocks #53

Merged
merged 5 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 61 additions & 32 deletions policy/policy_handler/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,26 @@ func getLocalSubscriptionData(_ context.Context, req skill.RequestContext) (*goa
return nil, skill.Configuration{}, nil
}

mockCommonSubscriptionData := goals.CommonSubscriptionQueryResult{
ImageDigest: "localDigest",
_, sbom, err := parseMetadata(req)
if err != nil {
return nil, skill.Configuration{}, err
}

var mockCommonSubscriptionData goals.CommonSubscriptionQueryResult
if sbom != nil {
mockCommonSubscriptionData = goals.CommonSubscriptionQueryResult{
ImageDigest: sbom.Source.Image.Digest,
ImagePlatforms: []goals.ImagePlatform{{
Architecture: sbom.Source.Image.Platform.Architecture,
Os: sbom.Source.Image.Platform.Os,
}},
}
} else {
mockCommonSubscriptionData = goals.CommonSubscriptionQueryResult{
ImageDigest: "localDigest",
}
}

subscriptionData, err := edn.Marshal(mockCommonSubscriptionData)
if err != nil {
return nil, skill.Configuration{}, err
Expand All @@ -61,39 +78,14 @@ func buildLocalDataSources(ctx context.Context, req skill.RequestContext, _ goal
return []data.DataSource{}, nil
}

var srMeta SyncRequestMetadata
err := edn.Unmarshal(req.Event.Context.SyncRequest.Metadata, &srMeta)
srMeta, sbom, err := parseMetadata(req)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal SyncRequest metadata: %w", err)
return nil, err
}

if srMeta.SBOM != "" {
decodedSBOM, err := base64.StdEncoding.DecodeString(srMeta.SBOM)
if err != nil {
return nil, fmt.Errorf("failed to base64-decode SBOM: %w", err)
}
if srMeta.Encoding == "base64+gzip" {
reader := bytes.NewReader(decodedSBOM)
gzreader, err := gzip.NewReader(reader)
defer gzreader.Close() //nolint:errcheck
if err != nil {
return nil, fmt.Errorf("failed to decompress SBOM: %w", err)
}
decodedSBOM, err = io.ReadAll(gzreader)
if err != nil {
return nil, fmt.Errorf("failed to base64-decode SBOM: %w", err)
}
}

var sbom *types.SBOM
// THE SBOM is a JSON here, not edn
if err := json.Unmarshal(decodedSBOM, &sbom); err != nil {
return nil, fmt.Errorf("failed to unmarshal SBOM: %w", err)
}
srMeta.QueryResults, err = mocks.BuildLocalEvalMocks(ctx, req, sbom)
if err != nil {
return nil, fmt.Errorf("failed to build local evaluation mocks: %w", err)
}
srMeta.QueryResults, err = mocks.BuildLocalEvalMocks(ctx, req, sbom)
if err != nil {
return nil, fmt.Errorf("failed to build local evaluation mocks: %w", err)
}

fixedQueryResults := map[string][]byte{}
Expand Down Expand Up @@ -123,3 +115,40 @@ func buildLocalDataSources(ctx context.Context, req skill.RequestContext, _ goal
func shouldTransactLocal(_ context.Context, req skill.RequestContext) bool {
return req.Event.Context.SyncRequest.Name != eventNameLocalEval
}

func parseMetadata(req skill.RequestContext) (SyncRequestMetadata, *types.SBOM, error) {
var srMeta SyncRequestMetadata
err := edn.Unmarshal(req.Event.Context.SyncRequest.Metadata, &srMeta)
if err != nil {
return SyncRequestMetadata{}, nil, fmt.Errorf("failed to unmarshal SyncRequest metadata: %w", err)
}

if srMeta.SBOM == "" {
return srMeta, nil, nil
}

decodedSBOM, err := base64.StdEncoding.DecodeString(srMeta.SBOM)
if err != nil {
return srMeta, nil, fmt.Errorf("failed to base64-decode SBOM: %w", err)
}
if srMeta.Encoding == "base64+gzip" {
reader := bytes.NewReader(decodedSBOM)
gzreader, err := gzip.NewReader(reader)
defer gzreader.Close() //nolint:errcheck
if err != nil {
return srMeta, nil, fmt.Errorf("failed to decompress SBOM: %w", err)
}
decodedSBOM, err = io.ReadAll(gzreader)
if err != nil {
return srMeta, nil, fmt.Errorf("failed to base64-decode SBOM: %w", err)
}
}

var sbom *types.SBOM
// THE SBOM is a JSON here, not edn
if err := json.Unmarshal(decodedSBOM, &sbom); err != nil {
return srMeta, nil, fmt.Errorf("failed to unmarshal SBOM: %w", err)
}

return srMeta, sbom, nil
}
77 changes: 0 additions & 77 deletions policy/policy_handler/local_test.go

This file was deleted.

66 changes: 66 additions & 0 deletions policy/policy_handler/mocks/base_image.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package mocks

import (
"fmt"
"strings"

"github.com/atomist-skills/go-skill/policy/types"
)

const (
GetBaseImageQueryName = "get-base-image"
)

type BaseImageQueryResult struct {
FromReference *SubscriptionImage `edn:"docker.image/from"`
FromRepo *SubscriptionRepository `edn:"docker.image/from-repository"`
FromTag *string `edn:"docker.image/from-tag"`
}

type SubscriptionImage struct {
Digest string `edn:"docker.image/digest"`
}

type SubscriptionRepository struct {
Host string `edn:"docker.repository/host"`
Repository string `edn:"docker.repository/repository"`
}

func MockBaseImage(sb *types.SBOM) BaseImageQueryResult {
return BaseImageQueryResult{
FromReference: &SubscriptionImage{
Digest: sb.Source.Provenance.BaseImage.Digest,
},
FromRepo: parseFromReference(sb.Source.Provenance.BaseImage.Name),
FromTag: &sb.Source.Provenance.BaseImage.Tag,
}
}

func parseFromReference(ref string) *SubscriptionRepository {
// this is registry.com/namespace/repository form
// but minified (omits hub.docker.com and library/ if unnecessary)
if ref == "" {
return nil
}

parts := strings.SplitN(ref, "/", 3)
switch len(parts) {
case 1:
return &SubscriptionRepository{
Host: "hub.docker.com",
Repository: fmt.Sprintf("library/%s", parts[0]),
}

case 2:
return &SubscriptionRepository{
Host: "hub.docker.com",
Repository: fmt.Sprintf("%s/%s", parts[0], parts[1]),
}

default:
return &SubscriptionRepository{
Host: parts[0],
Repository: fmt.Sprintf("%s/%s", parts[1], parts[2]),
}
}
}
54 changes: 54 additions & 0 deletions policy/policy_handler/mocks/base_image_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package mocks

import (
"reflect"
"testing"
)

func Test_parseFromReference(t *testing.T) {
type args struct {
ref string
}
tests := []struct {
name string
args args
want *SubscriptionRepository
}{
{
name: "empty",
args: args{ref: ""},
want: nil,
},
{
name: "one part",
args: args{ref: "nginx"},
want: &SubscriptionRepository{
Host: "hub.docker.com",
Repository: "library/nginx",
},
},
{
name: "two parts",
args: args{ref: "john/nginx"},
want: &SubscriptionRepository{
Host: "hub.docker.com",
Repository: "john/nginx",
},
},
{
name: "three parts",
args: args{ref: "docker.io/john/nginx"},
want: &SubscriptionRepository{
Host: "docker.io",
Repository: "john/nginx",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := parseFromReference(tt.args.ref); !reflect.DeepEqual(got, tt.want) {
t.Errorf("parseFromReference() = %v, want %v", got, tt.want)
}
})
}
}
11 changes: 11 additions & 0 deletions policy/policy_handler/mocks/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,16 @@ func BuildLocalEvalMocks(ctx context.Context, req skill.RequestContext, sb *type
}
}

// Base image
if sb.Source.Provenance == nil {
req.Log.Info("Skipping base image mock, no provenance in SBOM")
} else {
baseImageMock := MockBaseImage(sb)
m[GetBaseImageQueryName], err = edn.Marshal(baseImageMock)
if err != nil {
return m, fmt.Errorf("failed to marshal base image mock: %w", err)
}
}

return m, nil
}
Loading