Skip to content

Commit

Permalink
test: add integration test
Browse files Browse the repository at this point in the history
  • Loading branch information
LeelaChacha committed Aug 5, 2024
1 parent 92518cf commit 158fa52
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 35 deletions.
55 changes: 34 additions & 21 deletions internal/manifest/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ var (
ErrImageLayerPull = errors.New("failed to pull layer")
ErrInvalidImageSpecType = errors.New("invalid image spec type provided, only 'oci-ref' 'oci-dir' are allowed")
ErrTaintedArchive = errors.New("content filepath tainted")
ErrNoFileInArchive = errors.New("tar archive has no valid yaml file")
)

type PathExtractor struct {
Expand All @@ -48,7 +49,7 @@ func (p PathExtractor) FetchLayerToFile(ctx context.Context,
case v1beta2.OciRefType:
return p.getPathForFetchedLayer(ctx, imageSpec, keyChain, v1beta2.RawManifestLayerName+".yaml")
case v1beta2.OciDirType:
tarFile, err := p.getPathForFetchedLayer(ctx, imageSpec, keyChain, layerName+".yaml")
tarFile, err := p.getPathForFetchedLayer(ctx, imageSpec, keyChain, layerName+".tar")
if err != nil {
return "", err
}
Expand Down Expand Up @@ -154,32 +155,44 @@ func untarLayer(tarPath string) (string, error) {
defer tarFile.Close()

tarReader := tar.NewReader(tarFile)
header, err := tarReader.Next()
if err != nil {
return "", fmt.Errorf("failed to read tar: %w", err)
}

extractedFilePath, err := sanitizeArchivePath(filepath.Dir(tarPath), header.Name)
if err != nil {
return "", fmt.Errorf("failed to read tar: %w", err)
}
for {
header, err := tarReader.Next()
if errors.Is(err, io.EOF) {
break
}
if err != nil {
return "", fmt.Errorf("failed to read tar: %w", err)
}

if _, err := os.Stat(extractedFilePath); err == nil {
return extractedFilePath, nil
}
if strings.HasPrefix(header.Name, "._") {
continue
}

outFile, err := os.Create(extractedFilePath)
if err != nil {
return "", fmt.Errorf("failed to created extracted file: %w", err)
}
defer outFile.Close()
extractedFilePath, err := sanitizeArchivePath(filepath.Dir(tarPath), header.Name)
if err != nil {
return "", fmt.Errorf("failed to sanitize archive path: %w", err)
}

var maxBytes int64 = 1024 * 1024
if _, err := io.CopyN(outFile, tarReader, maxBytes); err != nil {
return "", fmt.Errorf("failed to extract from tar: %w", err)
if _, err := os.Stat(extractedFilePath); err == nil {
return extractedFilePath, nil
}

outFile, err := os.Create(extractedFilePath)
if err != nil {
return "", fmt.Errorf("failed to create extracted file: %w", err)
}
defer outFile.Close()

var maxBytes int64 = 1024 * 1024
if _, err := io.CopyN(outFile, tarReader, maxBytes); err != nil && !errors.Is(err, io.EOF) {
return "", fmt.Errorf("failed to extract from tar: %w", err)
}

return extractedFilePath, nil
}

return extractedFilePath, nil
return "", ErrNoFileInArchive
}

func sanitizeArchivePath(dir, path string) (string, error) {
Expand Down
Binary file added pkg/test_samples/oci/rendered.tar
Binary file not shown.
45 changes: 41 additions & 4 deletions pkg/testutils/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ func PushToRemoteOCIRegistry(server *httptest.Server, manifestFilePath, layerNam
return nil
}

func CreateOCIImageSpec(name, repo, manifestFilePath string, enableCredSecretSelector bool) (v1beta2.ImageSpec, error) {
func CreateOCIImageSpecFromFile(name, repo, manifestFilePath string, enableCredSecretSelector bool) (v1beta2.ImageSpec, error) {
imageSpec := v1beta2.ImageSpec{
Name: name,
Repo: repo,
Expand All @@ -444,11 +444,32 @@ func CreateOCIImageSpec(name, repo, manifestFilePath string, enableCredSecretSel
return imageSpec, nil
}

func CreateOCIImageSpecFromTar(name, repo, manifestTarPath string, enableCredSecretSelector bool) (v1beta2.ImageSpec, error) {
imageSpec := v1beta2.ImageSpec{
Name: name,
Repo: repo,
Type: "oci-dir",
}
if enableCredSecretSelector {
imageSpec.CredSecretSelector = CredSecretLabelSelector("test-secret-label")
}
layer, err := CreateImageSpecLayer(manifestTarPath)
if err != nil {
return imageSpec, err
}
digest, err := layer.Digest()
if err != nil {
return imageSpec, err
}
imageSpec.Ref = digest.String()
return imageSpec, nil
}

func WithInvalidInstallImageSpec(ctx context.Context, clnt client.Client,
enableResource bool, manifestFilePath string,
) func(manifest *v1beta2.Manifest) error {
return func(manifest *v1beta2.Manifest) error {
invalidImageSpec, err := CreateOCIImageSpec("invalid-image-spec", "domain.invalid", manifestFilePath, false)
invalidImageSpec, err := CreateOCIImageSpecFromFile("invalid-image-spec", "domain.invalid", manifestFilePath, false)
if err != nil {
return err
}
Expand All @@ -460,11 +481,27 @@ func WithInvalidInstallImageSpec(ctx context.Context, clnt client.Client,
}
}

func WithValidInstallImageSpec(ctx context.Context, clnt client.Client, name, manifestFilePath, serverURL string,
func WithValidInstallImageSpecFromFile(ctx context.Context, clnt client.Client, name, manifestFilePath, serverURL string,
enableResource, enableCredSecretSelector bool,
) func(manifest *v1beta2.Manifest) error {
return func(manifest *v1beta2.Manifest) error {
validImageSpec, err := CreateOCIImageSpecFromFile(name, serverURL, manifestFilePath, enableCredSecretSelector)
if err != nil {
return err
}
imageSpecByte, err := json.Marshal(validImageSpec)
if err != nil {
return err
}
return InstallManifest(ctx, clnt, manifest, imageSpecByte, enableResource)
}
}

func WithValidInstallImageSpecFromTar(ctx context.Context, clnt client.Client, name, manifestTarPath, serverURL string,
enableResource, enableCredSecretSelector bool,
) func(manifest *v1beta2.Manifest) error {
return func(manifest *v1beta2.Manifest) error {
validImageSpec, err := CreateOCIImageSpec(name, serverURL, manifestFilePath, enableCredSecretSelector)
validImageSpec, err := CreateOCIImageSpecFromTar(name, serverURL, manifestTarPath, enableCredSecretSelector)
if err != nil {
return err
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func registerControlPlaneLifecycleForKyma(kyma *v1beta2.Kyma) {

installName := filepath.Join("main-dir", "installs")
mandatoryManifest.Annotations = map[string]string{shared.FQDN: "kyma-project.io/template-operator"}
validImageSpec, err := CreateOCIImageSpec(installName, server.Listener.Addr().String(), manifestFilePath,
validImageSpec, err := CreateOCIImageSpecFromFile(installName, server.Listener.Addr().String(), manifestFilePath,
false)
Expect(err).NotTo(HaveOccurred())
imageSpecByte, err := json.Marshal(validImageSpec)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ var _ = Describe("Warning state propagation test", Ordered, func() {
By("Install test Manifest CR")
testManifest := testutils.NewTestManifest("warning-check")
manifestName := testManifest.GetName()
validImageSpec, err := testutils.CreateOCIImageSpec(installName, server.Listener.Addr().String(),
validImageSpec, err := testutils.CreateOCIImageSpecFromFile(installName, server.Listener.Addr().String(),
manifestFilePath,
false)
Expect(err).NotTo(HaveOccurred())
Expand Down
59 changes: 52 additions & 7 deletions tests/integration/controller/manifest/manifest_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,17 @@ import (
. "github.com/onsi/gomega"
)

func setupTestEnvironment(ociTempDir, installName string) {
func setupTestEnvironment(ociTempDir, installName string, mediaType v1beta2.MediaTypeMetadata) {
It("setup OCI", func() {
err := testutils.PushToRemoteOCIRegistry(server, manifestFilePath, installName)
var err error
switch mediaType {
case v1beta2.MediaTypeDir:
err = testutils.PushToRemoteOCIRegistry(server, manifestTarPath, installName)
case v1beta2.MediaTypeFile:
fallthrough
default:
err = testutils.PushToRemoteOCIRegistry(server, manifestFilePath, installName)
}
Expect(err).NotTo(HaveOccurred())
})
BeforeEach(
Expand All @@ -27,18 +35,18 @@ func setupTestEnvironment(ociTempDir, installName string) {
}

var _ = Describe(
"Rendering manifest install layer", Ordered, func() {
"Rendering manifest install layer from raw file", Ordered, func() {
ociTempDir := "main-dir"
installName := filepath.Join(ociTempDir, "installs")
var validManifest *v1beta2.Manifest
setupTestEnvironment(ociTempDir, installName)
setupTestEnvironment(ociTempDir, installName, v1beta2.MediaTypeFile)

Context("Given a Manifest CR", func() {
It("When Manifest CR contains a valid install OCI image specification",
func() {
manifest := testutils.NewTestManifest("oci")

Eventually(testutils.WithValidInstallImageSpec(ctx, kcpClient, installName,
Eventually(testutils.WithValidInstallImageSpecFromFile(ctx, kcpClient, installName,
manifestFilePath,
serverAddress, false, false), standardTimeout, standardInterval).
WithArguments(manifest).
Expand All @@ -65,7 +73,7 @@ var _ = Describe(
func() {
manifest := testutils.NewTestManifest("oci")

Eventually(testutils.WithValidInstallImageSpec(ctx, kcpClient, installName,
Eventually(testutils.WithValidInstallImageSpecFromFile(ctx, kcpClient, installName,
manifestFilePath,
serverAddress, true, false), standardTimeout, standardInterval).
WithArguments(manifest).
Expand Down Expand Up @@ -155,6 +163,43 @@ var _ = Describe(
},
)

var _ = Describe(
"Rendering manifest install layer from tar", Ordered, func() {
ociTempDir := "main-dir"
installName := filepath.Join(ociTempDir, "installs")
setupTestEnvironment(ociTempDir, installName, v1beta2.MediaTypeDir)

Context("Given a Manifest CR", func() {
It("When Manifest CR contains a valid install OCI image specification",
func() {
manifest := testutils.NewTestManifest("oci")

Eventually(testutils.WithValidInstallImageSpecFromTar(ctx, kcpClient, installName,
manifestTarPath,
serverAddress, false, false), standardTimeout, standardInterval).
WithArguments(manifest).
Should(Succeed())
By("Then Manifest CR is in Ready State", func() {
Eventually(testutils.ExpectManifestStateIn(ctx, kcpClient, shared.StateReady),
standardTimeout, standardInterval).
WithArguments(manifest.GetName()).
Should(Succeed())
})
By("And OCI-Sync-Ref Annotation exists", func() {
Eventually(testutils.ExpectOCISyncRefAnnotationExists(ctx, kcpClient, true),
standardTimeout,
standardInterval).
WithArguments(manifest.GetName()).
Should(Succeed())
})
Eventually(testutils.DeleteManifestAndVerify(ctx, kcpClient, manifest), standardTimeout,
standardInterval).Should(Succeed())
},
)
})
},
)

var _ = Describe(
"Given manifest with private registry", func() {
mainOciTempDir := "private-oci"
Expand All @@ -174,7 +219,7 @@ var _ = Describe(

It("Manifest should be in Error state with no auth secret found error message", func() {
manifestWithInstall := testutils.NewTestManifest("private-oci-registry")
Eventually(testutils.WithValidInstallImageSpec(ctx, kcpClient, installName, manifestFilePath,
Eventually(testutils.WithValidInstallImageSpecFromFile(ctx, kcpClient, installName, manifestFilePath,
server.Listener.Addr().String(), false, true),
standardTimeout,
standardInterval).
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/controller/manifest/ready_check_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ var _ = Describe("Manifest readiness check", Ordered, func() {
It("Install OCI specs including an nginx deployment", func() {
testManifest := testutils.NewTestManifest("custom-check-oci")
manifestName := testManifest.GetName()
validImageSpec, err := testutils.CreateOCIImageSpec(installName, server.Listener.Addr().String(),
validImageSpec, err := testutils.CreateOCIImageSpecFromFile(installName, server.Listener.Addr().String(),
manifestFilePath,
false)
Expect(err).NotTo(HaveOccurred())
Expand Down
3 changes: 3 additions & 0 deletions tests/integration/controller/manifest/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ var (
server *httptest.Server
serverAddress string
manifestFilePath string
manifestTarPath string
)

const (
Expand All @@ -82,6 +83,8 @@ var _ = BeforeSuite(func() {
ctx, cancel = context.WithCancel(context.TODO())
manifestFilePath = filepath.Join(integration.GetProjectRoot(), "pkg", "test_samples", "oci",
"rendered.yaml")
manifestTarPath = filepath.Join(integration.GetProjectRoot(), "pkg", "test_samples", "oci",
"rendered.tar")
logf.SetLogger(log.ConfigLogger(9, zapcore.AddSync(GinkgoWriter)))

// create registry and server
Expand Down

0 comments on commit 158fa52

Please sign in to comment.