blob: 5caf004815f98a94f45b2514155db28f3bdc59b9 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You 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 bufmanifest
import (
"context"
"fmt"
"io"
)
import (
"go.uber.org/multierr"
)
import (
modulev1alpha1 "github.com/apache/dubbo-kubernetes/pkg/bufman/gen/proto/go/module/v1alpha1"
"github.com/apache/dubbo-kubernetes/pkg/bufman/pkg/manifest"
)
var (
protoDigestTypeToDigestType = map[modulev1alpha1.DigestType]manifest.DigestType{
modulev1alpha1.DigestType_DIGEST_TYPE_SHAKE256: manifest.DigestTypeShake256,
}
digestTypeToProtoDigestType = map[manifest.DigestType]modulev1alpha1.DigestType{
manifest.DigestTypeShake256: modulev1alpha1.DigestType_DIGEST_TYPE_SHAKE256,
}
)
// NewDigestFromProtoDigest maps a modulev1alpha1.Digest to a Digest.
func NewDigestFromProtoDigest(digest *modulev1alpha1.Digest) (*manifest.Digest, error) {
if digest == nil {
return nil, fmt.Errorf("nil digest")
}
dType, ok := protoDigestTypeToDigestType[digest.DigestType]
if !ok {
return nil, fmt.Errorf("unsupported digest kind: %s", digest.DigestType.String())
}
return manifest.NewDigestFromBytes(dType, digest.Digest)
}
// AsProtoBlob returns the passed blob as a proto module blob.
func AsProtoBlob(ctx context.Context, b manifest.Blob) (_ *modulev1alpha1.Blob, retErr error) {
digestType, ok := digestTypeToProtoDigestType[b.Digest().Type()]
if !ok {
return nil, fmt.Errorf("digest type %q not supported by module proto", b.Digest().Type())
}
rc, err := b.Open(ctx)
if err != nil {
return nil, fmt.Errorf("cannot open blob: %w", err)
}
defer func() {
retErr = multierr.Append(retErr, rc.Close())
}()
content, err := io.ReadAll(rc)
if err != nil {
return nil, fmt.Errorf("cannot read blob contents: %w", err)
}
return &modulev1alpha1.Blob{
Digest: &modulev1alpha1.Digest{
DigestType: digestType,
Digest: b.Digest().Bytes(),
},
Content: content,
}, nil
}
// NewManifestFromProto returns a Manifest from a proto module blob. It makes sure the
// digest and content matches.
func NewManifestFromProto(ctx context.Context, b *modulev1alpha1.Blob) (_ *manifest.Manifest, retErr error) {
blob, err := NewBlobFromProto(b)
if err != nil {
return nil, fmt.Errorf("invalid manifest: %w", err)
}
r, err := blob.Open(ctx)
if err != nil {
return nil, err
}
defer func() {
retErr = multierr.Append(retErr, r.Close())
}()
return manifest.NewFromReader(r)
}
// NewBlobSetFromProto returns a BlobSet from a slice of proto module blobs.
// It makes sure the digest and content matches for each blob.
func NewBlobSetFromProto(ctx context.Context, blobs []*modulev1alpha1.Blob) (*manifest.BlobSet, error) {
var memBlobs []manifest.Blob
for i, modBlob := range blobs {
memBlob, err := NewBlobFromProto(modBlob)
if err != nil {
return nil, fmt.Errorf("invalid blob at index %d: %w", i, err)
}
memBlobs = append(memBlobs, memBlob)
}
return manifest.NewBlobSet(ctx, memBlobs)
}
// NewBlobFromProto returns a Blob from a proto module blob. It makes sure the
// digest and content matches.
func NewBlobFromProto(b *modulev1alpha1.Blob) (manifest.Blob, error) {
if b == nil {
return nil, fmt.Errorf("nil blob")
}
digest, err := NewDigestFromProtoDigest(b.Digest)
if err != nil {
return nil, fmt.Errorf("digest from proto digest: %w", err)
}
memBlob, err := manifest.NewMemoryBlob(
*digest,
b.Content,
manifest.MemoryBlobWithDigestValidation(),
)
if err != nil {
return nil, fmt.Errorf("new memory blob: %w", err)
}
return memBlob, nil
}
// ToProtoManifestAndBlobs converts a Manifest and BlobSet to the protobuf types.
func ToProtoManifestAndBlobs(ctx context.Context, manifest *manifest.Manifest, blobs *manifest.BlobSet) (*modulev1alpha1.Blob, []*modulev1alpha1.Blob, error) {
manifestBlob, err := manifest.Blob()
if err != nil {
return nil, nil, err
}
manifestProtoBlob, err := AsProtoBlob(ctx, manifestBlob)
if err != nil {
return nil, nil, err
}
filesBlobs := blobs.Blobs()
filesProtoBlobs := make([]*modulev1alpha1.Blob, len(filesBlobs))
for i, b := range filesBlobs {
pb, err := AsProtoBlob(ctx, b)
if err != nil {
return nil, nil, err
}
filesProtoBlobs[i] = pb
}
return manifestProtoBlob, filesProtoBlobs, nil
}