airshipctl/pkg/clusterctl/implementations/repository_test.go

303 lines
7.3 KiB
Go

/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package implementations_test
import (
"sort"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
versionclient "k8s.io/apimachinery/pkg/util/version"
clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3"
"sigs.k8s.io/yaml"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"opendev.org/airship/airshipctl/pkg/clusterctl/implementations"
)
type Version struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec VersionSpec `json:"spec"`
}
type VersionSpec struct {
Version string `json:"version"`
}
func TestNewRepository(t *testing.T) {
tests := []struct {
name string
root string
versions map[string]string
defaultVersion string
Error error
}{
{
name: "simple repository success",
root: "testdata",
versions: map[string]string{
"v0.0.1": "functions/capi",
},
Error: nil,
defaultVersion: "v0.0.1",
},
{
name: "invalid version",
root: "testdata",
versions: map[string]string{
"malformed-version": "functions/capi",
},
Error: implementations.ErrNoVersionsAvailable{Versions: map[string]string{}},
},
{
name: "multiple repository versions",
root: "testdata",
versions: map[string]string{
"v0.0.1": "functions/1",
"v0.2.3": "functions/2",
"v7.0.2": "functions/3",
"v0.3.2": "functions/4",
"v4.0.2": "functions/5",
"v1.0.2": "functions/6",
},
Error: nil,
defaultVersion: "v7.0.2",
},
{
name: "Empty version",
root: "testdata",
versions: map[string]string{},
Error: implementations.ErrNoVersionsAvailable{Versions: map[string]string{}},
},
}
for _, tt := range tests {
repo, err := implementations.NewRepository(tt.root, tt.versions)
expectedErr := tt.Error
defaultVersion := tt.defaultVersion
t.Run(tt.name, func(t *testing.T) {
if expectedErr != nil {
assert.Equal(t, expectedErr, err)
assert.Nil(t, repo)
} else {
assert.NoError(t, err)
assert.NotNil(t, repo)
assert.Equal(t, defaultVersion, repo.DefaultVersion())
}
})
}
}
func TestGetFile(t *testing.T) {
tests := []struct {
name string
root string
versions map[string]string
expectErr bool
resultVersion string
versionToUse string
fileToUse string
resultContract string
}{
{
name: "single version",
root: "testdata",
versions: map[string]string{
"v0.0.1": "functions/1",
},
expectErr: false,
resultVersion: "v0.0.1",
versionToUse: "v0.0.1",
},
{
name: "latest version",
root: "testdata",
versions: map[string]string{
"v0.0.1": "functions/1",
"v0.0.2": "functions/2",
"v0.0.3": "functions/3",
},
expectErr: false,
resultVersion: "v0.0.3",
versionToUse: "latest",
},
{
name: "failed to bundle",
root: "testdata",
versions: map[string]string{
"v1.3.2": "does-not-exist",
},
versionToUse: "v1.3.2",
expectErr: true,
},
{
name: "multiple repository versions",
root: "testdata",
versions: map[string]string{
"v0.0.1": "functions/1",
"v0.2.3": "functions/2",
"v7.0.2": "functions/3",
},
expectErr: false,
resultVersion: "v0.0.2",
versionToUse: "v0.2.3",
},
{
name: "version doesn't exist",
root: "testdata",
versions: map[string]string{
"v1.3.2": "does-not-exist",
},
versionToUse: "v1.3.3",
expectErr: true,
},
{
name: "test valid metadata",
root: "testdata",
versions: map[string]string{
"v0.2.3": "functions/2",
},
expectErr: false,
versionToUse: "v0.2.3",
fileToUse: "metadata.yaml",
resultContract: "v1alpha2",
},
{
name: "test valid metadata",
root: "testdata",
versions: map[string]string{
"v0.2.0": "functions/1",
},
expectErr: true,
versionToUse: "v0.2.3",
fileToUse: "metadata.yaml",
resultContract: "v1alpha2",
},
}
for _, tt := range tests {
root := tt.root
versions := tt.versions
resultVersion := tt.resultVersion
versionToUse := tt.versionToUse
expectErr := tt.expectErr
fileToUse := tt.fileToUse
resultContract := tt.resultContract
t.Run(tt.name, func(t *testing.T) {
repo, err := implementations.NewRepository(root, versions)
require.NoError(t, err)
assert.NotNil(t, repo)
b, err := repo.GetFile(versionToUse, fileToUse)
if expectErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
if fileToUse == "metadata.yaml" {
gotMetadata := metadata(t, b)
parsedVersion, err := versionclient.ParseSemantic(versionToUse)
require.NoError(t, err)
assert.Equal(t, resultContract, gotMetadata.GetReleaseSeriesForVersion(parsedVersion).Contract)
} else {
gotVersion := version(t, b)
assert.Equal(t, resultVersion, gotVersion.Spec.Version)
}
}
})
}
}
func version(t *testing.T, versionBytes []byte) *Version {
t.Helper()
ver := &Version{}
err := yaml.Unmarshal(versionBytes, ver)
require.NoError(t, err)
return ver
}
func metadata(t *testing.T, metadataBytes []byte) *clusterctlv1.Metadata {
t.Helper()
m := &clusterctlv1.Metadata{}
err := yaml.Unmarshal(metadataBytes, m)
require.NoError(t, err)
return m
}
func TestComponentsPath(t *testing.T) {
versions := map[string]string{
"v0.0.1": "functions/1",
}
repo, err := implementations.NewRepository("testdata", versions)
require.NoError(t, err)
assert.NotEmpty(t, repo.ComponentsPath())
}
func TestRootPath(t *testing.T) {
versions := map[string]string{
"v0.0.1": "functions/1",
}
repo, err := implementations.NewRepository("testdata", versions)
require.NoError(t, err)
assert.Equal(t, "testdata", repo.RootPath())
}
func TestGetVersions(t *testing.T) {
tests := []struct {
name string
root string
versions map[string]string
expectedVersions []string
}{
{
name: "single version",
root: "testdata",
versions: map[string]string{
"v0.0.1": "functions/1",
},
expectedVersions: []string{"v0.0.1"},
},
{
name: "multiple repository versions",
root: "testdata",
versions: map[string]string{
"v0.0.1": "functions/1",
"v0.2.3": "functions/2",
"v7.0.2": "functions/3",
"malformed-version": "doesn't matter",
},
expectedVersions: []string{"v0.0.1", "v0.2.3", "v7.0.2"},
},
}
for _, tt := range tests {
root := tt.root
versions := tt.versions
expectedVersions := tt.expectedVersions
t.Run(tt.name, func(t *testing.T) {
repo, err := implementations.NewRepository(root, versions)
require.NoError(t, err)
actualVersions, err := repo.GetVersions()
assert.NoError(t, err)
// this will make sure that slices are sorted in a same way
sort.Strings(expectedVersions)
sort.Strings(actualVersions)
assert.Equal(t, expectedVersions, actualVersions)
})
}
}