constellation/cli/internal/helm/loader_test.go
2022-11-02 17:47:10 +01:00

183 lines
5.8 KiB
Go

/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package helm
import (
"bytes"
"encoding/json"
"fmt"
"io/fs"
"os"
"path"
"testing"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/deploy/helm"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"helm.sh/helm/v3/pkg/chart/loader"
"helm.sh/helm/v3/pkg/chartutil"
"helm.sh/helm/v3/pkg/engine"
)
// TestLoad checks if the serialized format that Load returns correctly preserves the dependencies of the loaded chart.
func TestLoad(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
chartLoader := ChartLoader{}
release, err := chartLoader.Load(cloudprovider.GCP, true, []byte("secret"), []byte("salt"), nil, false)
require.NoError(err)
var helmReleases helm.Releases
err = json.Unmarshal(release, &helmReleases)
require.NoError(err)
reader := bytes.NewReader(helmReleases.ConstellationServices.Chart)
chart, err := loader.LoadArchive(reader)
require.NoError(err)
assert.NotNil(chart.Dependencies())
}
// TestTemplate checks if the rendered constellation-services chart produces the expected yaml files.
func TestTemplate(t *testing.T) {
testCases := map[string]struct {
csp cloudprovider.Provider
enforceIDKeyDigest bool
valuesModifier func(map[string]any) error
ccmImage string
cnmImage string
}{
"GCP": {
csp: cloudprovider.GCP,
enforceIDKeyDigest: false,
valuesModifier: prepareGCPValues,
ccmImage: "ccmImageForGCP",
},
"Azure": {
csp: cloudprovider.Azure,
enforceIDKeyDigest: true,
valuesModifier: prepareAzureValues,
ccmImage: "ccmImageForAzure",
cnmImage: "cnmImageForAzure",
},
"QEMU": {
csp: cloudprovider.QEMU,
enforceIDKeyDigest: false,
valuesModifier: prepareQEMUValues,
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
chartLoader := ChartLoader{joinServiceImage: "joinServiceImage", kmsImage: "kmsImage", ccmImage: tc.ccmImage, cnmImage: tc.cnmImage}
release, err := chartLoader.Load(tc.csp, true, []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), []uint32{1, 11}, tc.enforceIDKeyDigest)
require.NoError(err)
var helmReleases helm.Releases
err = json.Unmarshal(release, &helmReleases)
require.NoError(err)
reader := bytes.NewReader(helmReleases.ConstellationServices.Chart)
chart, err := loader.LoadArchive(reader)
require.NoError(err)
options := chartutil.ReleaseOptions{
Name: "testRelease",
Namespace: "testNamespace",
Revision: 1,
IsInstall: true,
IsUpgrade: false,
}
caps := &chartutil.Capabilities{}
err = tc.valuesModifier(helmReleases.ConstellationServices.Values)
require.NoError(err)
// This step is needed to enabled/disable subcharts according to their tags/conditions.
err = chartutil.ProcessDependencies(chart, helmReleases.ConstellationServices.Values)
require.NoError(err)
valuesToRender, err := chartutil.ToRenderValues(chart, helmReleases.ConstellationServices.Values, options, caps)
require.NoError(err)
result, err := engine.Render(chart, valuesToRender)
require.NoError(err)
for k, v := range result {
currentFile := path.Join("testdata", tc.csp.String(), k)
content, err := os.ReadFile(currentFile)
// If a file does not exist, we expect the render for that path to be empty.
if errors.Is(err, fs.ErrNotExist) {
assert.YAMLEq("", v, fmt.Sprintf("current file: %s", currentFile))
continue
}
assert.NoError(err)
assert.YAMLEq(string(content), v, fmt.Sprintf("current file: %s", currentFile))
}
})
}
}
func prepareGCPValues(values map[string]any) error {
joinVals, ok := values["join-service"].(map[string]any)
if !ok {
return errors.New("missing 'join-service' key")
}
joinVals["measurements"] = "{'1':'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA','15':'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA='}"
joinVals["measurementSalt"] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
ccmVals, ok := values["ccm"].(map[string]any)
if !ok {
return errors.New("missing 'ccm' key")
}
ccmVals["subnetworkCIDR"] = "192.0.2.0/24"
ccmVals["GCP"].(map[string]any)["projectID"] = "42424242424242"
ccmVals["GCP"].(map[string]any)["uid"] = "242424242424"
ccmVals["GCP"].(map[string]any)["secretData"] = "baaaaaad"
return nil
}
func prepareAzureValues(values map[string]any) error {
joinVals, ok := values["join-service"].(map[string]any)
if !ok {
return errors.New("missing 'join-service' key")
}
joinVals["idkeydigest"] = "baaaaaadbaaaaaadbaaaaaadbaaaaaadbaaaaaadbaaaaaadbaaaaaadbaaaaaad"
joinVals["measurements"] = "{'1':'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA','15':'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA='}"
joinVals["measurementSalt"] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
ccmVals, ok := values["ccm"].(map[string]any)
if !ok {
return errors.New("missing 'ccm' key")
}
ccmVals["subnetworkCIDR"] = "192.0.2.0/24"
ccmVals["Azure"].(map[string]any)["azureConfig"] = "baaaaaad"
return nil
}
func prepareQEMUValues(values map[string]any) error {
joinVals, ok := values["join-service"].(map[string]any)
if !ok {
return errors.New("missing 'join-service' key")
}
joinVals["measurements"] = "{'1':'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA','15':'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA='}"
joinVals["measurementSalt"] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
ccmVals, ok := values["ccm"].(map[string]any)
if !ok {
return errors.New("missing 'ccm' key")
}
ccmVals["subnetworkCIDR"] = "192.0.2.0/24"
return nil
}