File: corrupted_test.go

package info (click to toggle)
golang-github-containers-common 0.64.1%2Bds1-2
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 5,932 kB
  • sloc: makefile: 132; sh: 111
file content (93 lines) | stat: -rw-r--r-- 3,288 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
//go:build !remote

package libimage

import (
	"context"
	"os"
	"path/filepath"
	"testing"

	"github.com/containers/common/pkg/config"
	"github.com/containers/storage"
	"github.com/containers/storage/pkg/ioutils"
	"github.com/stretchr/testify/require"
)

func TestCorruptedLayers(t *testing.T) {
	// Regression tests for https://bugzilla.redhat.com/show_bug.cgi?id=1966872.
	runtime := testNewRuntime(t)
	ctx := context.Background()
	pullOptions := &PullOptions{}
	pullOptions.Writer = os.Stdout

	imageName := "quay.io/libpod/alpine_nginx:latest"

	exists, err := runtime.Exists(imageName)
	require.NoError(t, err, "image does not exist yet")
	require.False(t, exists, "image does not exist yet")

	pulledImages, err := runtime.Pull(ctx, imageName, config.PullPolicyAlways, pullOptions)
	require.NoError(t, err)
	require.Len(t, pulledImages, 1)
	image := pulledImages[0]

	// Inspecting a healthy image should work.
	_, err = image.Inspect(ctx, nil)
	require.NoError(t, err, "inspecting healthy image should work")

	exists, err = runtime.Exists(imageName)
	require.NoError(t, err, "healthy image exists")
	require.True(t, exists, "healthy image exists")

	// Disk usage works.
	_, _, err = runtime.DiskUsage(ctx)
	require.NoError(t, err, "disk usage works on healthy image")

	// Now remove one layer from the layers.json index in the storage.  The
	// image will still be listed in the container storage but attempting
	// to use it will yield "layer not known" errors.
	indexPath := filepath.Join(runtime.store.GraphRoot(), "vfs-layers/layers.json")
	data, err := os.ReadFile(indexPath)
	require.NoError(t, err, "loading layers.json")
	layers := []*storage.Layer{}
	err = json.Unmarshal(data, &layers)
	require.NoError(t, err, "unmarshaling layers.json")
	require.LessOrEqual(t, 1, len(layers), "at least one layer must be present")

	// Now write back the layers without the first layer!
	data, err = json.Marshal(layers[1:])
	require.NoError(t, err, "unmarshaling layers.json")
	err = ioutils.AtomicWriteFile(indexPath, data, 0o600) // nolint
	require.NoError(t, err, "writing back layers.json")

	err = image.reload() // clear the cached data
	require.NoError(t, err)

	// Now inspecting the image must fail!
	_, err = image.Inspect(ctx, nil)
	require.Error(t, err, "inspecting corrupted image should fail")

	err = image.isCorrupted(ctx, imageName)
	require.Error(t, err, "image is corrupted")

	exists, err = runtime.Exists(imageName)
	require.NoError(t, err, "corrupted image exists should not fail")
	require.False(t, exists, "corrupted image should not be marked to exist")

	// Disk usage does not work.
	_, _, err = runtime.DiskUsage(ctx)
	require.Error(t, err, "disk usage does not work on corrupted image")
	require.Contains(t, err.Error(), "exists in local storage but may be corrupted", "disk usage reports corrupted image")

	// Now make sure that pull will detect the corrupted image and repulls
	// if needed which will repair the data corruption.
	pulledImages, err = runtime.Pull(ctx, imageName, config.PullPolicyNewer, pullOptions)
	require.NoError(t, err)
	require.Len(t, pulledImages, 1)
	image = pulledImages[0]

	// Inspecting a repaired image should work.
	_, err = image.Inspect(ctx, nil)
	require.NoError(t, err, "inspecting repaired image should work")
}