Skip to content
Open
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
2 changes: 1 addition & 1 deletion internal/manifest/img/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ func getOCIRef(
accessSpec *localblob.AccessSpec,
) (*OCI, error) {
layerRef := OCI{}
if accessSpec.MediaType == mime.MIME_TAR {
if accessSpec.MediaType == mime.MIME_TAR || accessSpec.MediaType == mime.MIME_TGZ {
layerRef.Type = string(v1beta2.OciDirType)
} else {
layerRef.Type = string(v1beta2.OciRefType)
Expand Down
13 changes: 13 additions & 0 deletions internal/manifest/img/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,19 @@ func TestParse(t *testing.T) {
Type: "oci-dir",
},
},
}, {
"should parse raw-manifest layer from mediaType: application/x-tgz",
"v1beta2_template_operator_tgz_format.yaml",
"1.0.0-tgz-format",
img.Layer{
LayerName: "raw-manifest",
LayerRepresentation: &img.OCI{
Repo: "europe-west3-docker.pkg.dev/sap-kyma-jellyfish-dev/template-operator/component-descriptors",
Name: testutils.DefaultFQDN,
Ref: "sha256:d2cc278224a71384b04963a83e784da311a268a2b3fa8732bc31e70ca0c5bc52",
Type: "oci-dir",
},
},
}, {
"should parse raw-manifest layer from mediaType: application/octet-stream",
"v1beta2_template_operator_current_ocm.yaml",
Expand Down
13 changes: 12 additions & 1 deletion internal/manifest/img/pathextractor.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package img

import (
"archive/tar"
"compress/gzip"
"context"
"errors"
"fmt"
Expand Down Expand Up @@ -135,7 +136,17 @@ func (p PathExtractor) ExtractLayer(tarPath string) (string, error) {
}
defer tarFile.Close()

tarReader := tar.NewReader(tarFile)
var tarReader *tar.Reader
gzipReader, err := gzip.NewReader(tarFile)
if err == nil {
defer gzipReader.Close()
tarReader = tar.NewReader(gzipReader)
} else {
if _, err := tarFile.Seek(0, 0); err != nil {
return "", fmt.Errorf("failed to seek file: %w", err)
}
tarReader = tar.NewReader(tarFile)
}
for {
header, err := tarReader.Next()
if errors.Is(err, io.EOF) {
Expand Down
43 changes: 39 additions & 4 deletions internal/manifest/img/pathextractor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package img_test
import (
"archive/tar"
"bytes"
"compress/gzip"
"fmt"
"os"
"path/filepath"
Expand All @@ -19,7 +20,19 @@ import (
)

func TestPathExtractor_ExtractLayer(t *testing.T) {
content, tarFilePath := generateDummyTarFile(t)
t.Run("should extract uncompressed tar file", func(t *testing.T) {
content, tarFilePath := generateDummyTarFile(t, false)
testExtractLayer(t, content, tarFilePath)
})

t.Run("should extract gzip-compressed tar file", func(t *testing.T) {
content, tarFilePath := generateDummyTarFile(t, true)
testExtractLayer(t, content, tarFilePath)
})
}

func testExtractLayer(t *testing.T, content []byte, tarFilePath string) {
t.Helper()
pathExtractor := img.NewPathExtractor()
numGoroutines := 5
resultCh := make(chan string, numGoroutines)
Expand Down Expand Up @@ -115,9 +128,11 @@ func TestPathExtractor_FetchLayerToFile(t *testing.T) {
}
}

func generateDummyTarFile(t *testing.T) ([]byte, string) {
func generateDummyTarFile(t *testing.T, compress bool) ([]byte, string) {
t.Helper()
var buf bytes.Buffer

// Create tar writer
tarWriter := tar.NewWriter(&buf)

content := []byte("file-content")
Expand All @@ -135,8 +150,28 @@ func generateDummyTarFile(t *testing.T) ([]byte, string) {

err = tarWriter.Close()
require.NoError(t, err)
tarFilePath := filepath.Join(os.TempDir(), "test.tar")
err = os.WriteFile(tarFilePath, buf.Bytes(), 0o600)

// Get tar bytes
tarBytes := buf.Bytes()

// Optionally compress with gzip
if compress {
var gzipBuf bytes.Buffer
gzipWriter := gzip.NewWriter(&gzipBuf)
_, err = gzipWriter.Write(tarBytes)
require.NoError(t, err)
err = gzipWriter.Close()
require.NoError(t, err)
tarBytes = gzipBuf.Bytes()
}

// Write to file
ext := ".tar"
if compress {
ext = ".tar.gz"
}
tarFilePath := filepath.Join(os.TempDir(), "test"+ext)
err = os.WriteFile(tarFilePath, tarBytes, 0o600)
require.NoError(t, err)
return content, tarFilePath
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
apiVersion: operator.kyma-project.io/v1beta2
kind: ModuleTemplate
metadata:
name: template-operator-regular
namespace: kcp-system
annotations:
"operator.kyma-project.io/is-cluster-scoped": "false"
"operator.kyma-project.io/module-version": "1.0.0-tgz-format"
spec:
channel: regular
mandatory: false
data:
apiVersion: operator.kyma-project.io/v1alpha1
kind: Sample
metadata:
name: sample-yaml
spec:
initKey: initValue
resourceFilePath: "./module-data/yaml"
descriptor:
component:
componentReferences: [ ]
creationTime: "2024-07-09T12:22:30Z"
name: kyma-project.io/module/template-operator
provider: kyma-project.io
repositoryContexts:
- baseUrl: europe-west3-docker.pkg.dev
componentNameMapping: urlPath
subPath: sap-kyma-jellyfish-dev/template-operator
type: OCIRegistry
resources:
- access:
imageReference: europe-docker.pkg.dev/kyma-project/prod/template-operator:1.0.0
type: ociArtifact
digest:
hashAlgorithm: SHA-256
normalisationAlgorithm: ociArtifactDigest/v1
value: 03a194e1dca2421755cec5ec1e946de744407e6e1ca3b671f715fee939e8d1fb
name: module-image
relation: external
type: ociArtifact
version: 1.0.0
- access:
localReference: sha256:d2cc278224a71384b04963a83e784da311a268a2b3fa8732bc31e70ca0c5bc52
mediaType: application/x-tgz
type: localBlob
digest:
hashAlgorithm: SHA-256
normalisationAlgorithm: genericBlobDigest/v1
value: d2cc278224a71384b04963a83e784da311a268a2b3fa8732bc31e70ca0c5bc52
name: raw-manifest
relation: local
type: directory
version: 1.0.0
- access:
localReference: sha256:9230471fa6a62ff7b1549e8d0e9ccb545896fabadf82d2ec4503fc798d2bcd8a
mediaType: application/x-tar
type: localBlob
digest:
hashAlgorithm: SHA-256
normalisationAlgorithm: genericBlobDigest/v1
value: 9230471fa6a62ff7b1549e8d0e9ccb545896fabadf82d2ec4503fc798d2bcd8a
name: default-cr
relation: local
type: directory
version: 1.0.0
- access:
localReference: sha256:b46281580f6377bf10672b5a8f156d183d47c0ec3bcda8b807bd8c5d520884bd
mediaType: application/octet-stream
type: localBlob
digest:
hashAlgorithm: SHA-256
normalisationAlgorithm: genericBlobDigest/v1
value: b46281580f6377bf10672b5a8f156d183d47c0ec3bcda8b807bd8c5d520884bd
name: associated-resources
relation: local
type: plainText
version: 1.0.0
sources: [ ]
version: 1.0.0-tgz-format
meta:
schemaVersion: v2
Loading