Skip to content

Commit

Permalink
Add test for getImagesFromContent() function
Browse files Browse the repository at this point in the history
Signed-off-by: Edmund Ochieng <ochienged@gmail.com>
  • Loading branch information
OchiengEd committed Jul 28, 2023
1 parent 32990cc commit 4e4e8d8
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 37 deletions.
14 changes: 7 additions & 7 deletions internal/chartverifier/checks/checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -514,10 +514,11 @@ func certifyImages(r Result, opts *CheckOptions, registry string) Result {
}

images, err := getImageReferences(opts.URI, opts.Values, kubeVersion)

if err != nil {
r.SetResult(false, fmt.Sprintf("%s : Failed to get images, error running helm template : %v", ImageCertifyFailed, err))
} else if len(images) == 0 {
}

if len(images) == 0 {
r.SetResult(true, NoImagesToCertify)
} else {
for _, image := range images {
Expand All @@ -527,16 +528,15 @@ func certifyImages(r Result, opts *CheckOptions, registry string) Result {
continue
}

err = nil
imageRef := parseImageReference(image)

if len(imageRef.Registries) == 0 {
imageRef.Registries, err = pyxis.GetImageRegistries(imageRef.Repository)
if err != nil {
r.AddResult(false, fmt.Sprintf("%s : %s : %v", ImageNotCertified, image, err))
}
}

if err != nil {
r.AddResult(false, fmt.Sprintf("%s : %s : %v", ImageNotCertified, image, err))
} else if len(imageRef.Registries) == 0 {
if len(imageRef.Registries) == 0 {
r.AddResult(false, fmt.Sprintf("%s : %s", ImageNotCertified, image))
} else {
certified, checkImageErr := pyxis.IsImageInRegistry(imageRef)
Expand Down
103 changes: 76 additions & 27 deletions internal/chartverifier/checks/checks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,43 +367,92 @@ func TestHelmLint(t *testing.T) {
}

func TestImageCertify(t *testing.T) {
checkImages(t, ImagesAreCertified, false)

checkImages(t, ImagesAreCertified_V1_1, true)
checkImages(t)
}

func checkImages(t *testing.T, fn func(*CheckOptions) (Result, error), version1_1 bool) {
type testCase struct {
func checkImages(t *testing.T) {
tests := []struct {
description string
uri string
fn CheckFunc
numErrors int
numPasses int
numSkips int
}{
{
description: "chart-0.1.0-v3.valid.tgz check images passes",
uri: "chart-0.1.0-v3.valid.tgz",
fn: ImagesAreCertified,
numErrors: 0,
numPasses: 5,
},
{
description: "Helm check images fails",
uri: "chart-0.1.0-v3.with-crd.tgz",
fn: ImagesAreCertified,
numErrors: 4,
numPasses: 0,
},
{
description: "Helm check images fails",
uri: "chart-0.1.0-v3.with-csi.tgz",
fn: ImagesAreCertified,
numErrors: 2,
numPasses: 0,
},
{
description: "chart-0.1.0-v3.valid.tgz check images passes",
uri: "chart-0.1.0-v3.valid.tgz",
fn: ImagesAreCertified_V1_1,
numErrors: 0,
numPasses: 5,
numSkips: 0,
},
{
description: "chart-0.1.0-v3.valid-skipped-images.tgz check images passes",
uri: "chart-0.1.0-v3.valid-skipped-images.tgz",
fn: ImagesAreCertified_V1_1,
numErrors: 0,
numPasses: 3,
numSkips: 2,
},
{
description: "chart-0.1.0-v3.failed-skipped-images.tgz check images passes",
uri: "chart-0.1.0-v3.failed-skipped-images.tgz",
fn: ImagesAreCertified_V1_1,
numErrors: 1,
numPasses: 0,
numSkips: 4,
},
{
description: "chart-0.1.0-v3.skipped-images.tgz check images passes",
uri: "chart-0.1.0-v3.skipped-images.tgz",
fn: ImagesAreCertified_V1_1,
numErrors: 0,
numPasses: 0,
numSkips: 5,
},
{
description: "Helm check images fails",
uri: "chart-0.1.0-v3.with-crd.tgz",
fn: ImagesAreCertified_V1_1,
numErrors: 4,
numPasses: 0,
numSkips: 0,
},
{
description: "Helm check images fails",
uri: "chart-0.1.0-v3.with-csi.tgz",
fn: ImagesAreCertified_V1_1,
numErrors: 2,
numPasses: 0,
numSkips: 0,
},
}

var testCases []testCase

if !version1_1 {
testCases = []testCase{
{description: "chart-0.1.0-v3.valid.tgz check images passes", uri: "chart-0.1.0-v3.valid.tgz", numErrors: 0, numPasses: 5},
{description: "Helm check images fails", uri: "chart-0.1.0-v3.with-crd.tgz", numErrors: 2, numPasses: 0},
{description: "Helm check images fails", uri: "chart-0.1.0-v3.with-csi.tgz", numErrors: 1, numPasses: 0},
}
} else {
testCases = []testCase{
{description: "chart-0.1.0-v3.valid.tgz check images passes", uri: "chart-0.1.0-v3.valid.tgz", numErrors: 0, numPasses: 5, numSkips: 0},
{description: "chart-0.1.0-v3.valid-skipped-images.tgz check images passes", uri: "chart-0.1.0-v3.valid-skipped-images.tgz", numErrors: 0, numPasses: 3, numSkips: 2},
{description: "chart-0.1.0-v3.failed-skipped-images.tgz check images passes", uri: "chart-0.1.0-v3.failed-skipped-images.tgz", numErrors: 1, numPasses: 0, numSkips: 4},
{description: "chart-0.1.0-v3.skipped-images.tgz check images passes", uri: "chart-0.1.0-v3.skipped-images.tgz", numErrors: 0, numPasses: 0, numSkips: 5},
{description: "Helm check images fails", uri: "chart-0.1.0-v3.with-crd.tgz", numErrors: 2, numPasses: 0, numSkips: 0},
{description: "Helm check images fails", uri: "chart-0.1.0-v3.with-csi.tgz", numErrors: 1, numPasses: 0, numSkips: 0},
}
}

for _, tc := range testCases {
for _, tc := range tests {
t.Run(tc.description, func(t *testing.T) {
config := viper.New()
r, err := fn(&CheckOptions{URI: tc.uri, ViperConfig: config, HelmEnvSettings: cli.New()})
r, err := tc.fn(&CheckOptions{URI: tc.uri, ViperConfig: viper.New(), HelmEnvSettings: cli.New()})
require.NoError(t, err)
require.NotNil(t, r)
if tc.numErrors == 0 {
Expand Down
16 changes: 13 additions & 3 deletions internal/chartverifier/checks/helm.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"path"
"path/filepath"
"regexp"
"strings"

"helm.sh/helm/v3/pkg/chartutil"

Expand Down Expand Up @@ -223,12 +224,21 @@ func getImageReferences(chartURI string, vals map[string]interface{}, kubeVersio
// getImagesFromContent evaluates generated templates from
// helm and extracts images which are returned in a slice
func getImagesFromContent(content string) []string {
var images []string
re := regexp.MustCompile(`\s+image\:\s+(?P<image>.*)`)
re := regexp.MustCompile(`\s+image\:\s+(?P<image>.*)\n`)
matches := re.FindAllStringSubmatch(content, -1)
imageMap := make(map[string]struct{})
for _, match := range matches {
images = append(images, match[re.SubexpIndex("image")])
image := strings.TrimSpace(match[re.SubexpIndex("image")])
image = strings.Trim(image, "\"")
image = strings.Trim(image, "'")
imageMap[image] = struct{}{}
}

var images []string
for k := range imageMap {
images = append(images, k)
}

return images
}

Expand Down
38 changes: 38 additions & 0 deletions internal/chartverifier/checks/helm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package checks
import (
"context"
"os"
"strings"
"testing"

"github.com/spf13/viper"
Expand Down Expand Up @@ -188,3 +189,40 @@ func TestLongLineTemplate(t *testing.T) {
require.Contains(t, images, "1.1.1/cv-test/image1:tag-123")
require.Contains(t, images, "1.1.2/cv-test/image2:tag-223")
}

func TestGetImagesFromContent(t *testing.T) {
test := struct {
name string
content string
want []string
}{
name: "find images in yaml",
content: `
image: "registry.access.redhat.com/rhscl/postgresql-10-rhel7:1-161"
image: 'busybox'
image: " "
image: registry.redhat.io/cpopen/ibmcloud-object-storage-driver@sha256:fc17bb3e89d00b3eb0f50b3ea83aa75c52e43d8e56cf2e0f17475e934eeeeb5f
`,
want: []string{
"registry.access.redhat.com/rhscl/postgresql-10-rhel7:1-161",
"busybox",
"",
"registry.redhat.io/cpopen/ibmcloud-object-storage-driver@sha256:fc17bb3e89d00b3eb0f50b3ea83aa75c52e43d8e56cf2e0f17475e934eeeeb5f",
},
}

t.Run(test.name, func(t *testing.T) {
got := getImagesFromContent(test.content)
if testing.Verbose() {
t.Logf("got %d images", len(got))
}
if len(got) != len(test.want) {
t.Errorf("got %d images but, want %d", len(got), len(test.want))
}
for _, image := range got {
if strings.TrimSpace(image) == "" {
t.Logf("Found empty image")
}
}
})
}

0 comments on commit 4e4e8d8

Please sign in to comment.