/* 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) }) } }