From 1969866b0a884b1001fb36063ca3fd1c02580805 Mon Sep 17 00:00:00 2001 From: Kostiantyn Kalynovskyi Date: Tue, 28 Apr 2020 16:21:42 -0500 Subject: [PATCH] Add metadata support for clusterctl repository implementation Change-Id: Ie9285cbba0fb590392b975be1eb2b02b28de56d1 --- pkg/clusterctl/implementations/repository.go | 20 +++--- .../implementations/repository_test.go | 63 +++++++++++++++---- .../testdata/functions/2/version.yaml | 12 ++++ pkg/document/constants.go | 6 +- pkg/document/selectors.go | 7 +++ pkg/document/selectors_test.go | 6 ++ .../selectors/valid/kustomization.yaml | 3 +- .../testdata/selectors/valid/metadata.yaml | 12 ++++ 8 files changed, 109 insertions(+), 20 deletions(-) create mode 100644 pkg/document/testdata/selectors/valid/metadata.yaml diff --git a/pkg/clusterctl/implementations/repository.go b/pkg/clusterctl/implementations/repository.go index 98fda1269..228fe8da2 100644 --- a/pkg/clusterctl/implementations/repository.go +++ b/pkg/clusterctl/implementations/repository.go @@ -12,9 +12,7 @@ import ( ) const ( - // TODO Add metadata support. Clusterctl uses repository to read metadata.yaml file - // to get clusterctl metadata which is a link between provider version and api version - // that it supports, for example v0.3.0 --> v1alpha3 + metaDataFilePath = "metadata.yaml" dummyComponentPath = "components.yaml" ) @@ -57,10 +55,7 @@ func (r *Repository) RootPath() string { } // GetFile returns all kubernetes resources that belong to cluster-api -// TODO Add metadata support(don't ignore filepath). Clusterctl uses repository to read -// metadata.yaml file to get clusterctl metadata which is a link between provider version -// and api version that it supports, for example v0.3.0 --> v1alpha3 -func (r *Repository) GetFile(version string, _ string) ([]byte, error) { +func (r *Repository) GetFile(version string, filePath string) ([]byte, error) { if version == "latest" { // default should be latest version = r.defaultVersion @@ -74,10 +69,21 @@ func (r *Repository) GetFile(version string, _ string) ([]byte, error) { if err != nil { return nil, err } + // TODO when clusterctl will have a defined set of expected files in repository + // revisit this implementation + // metadata.yaml should return a bytes containing clusterctlv1.Metadata or error + if filePath == metaDataFilePath { + doc, errMeta := bundle.SelectOne(document.NewClusterctlMetadataSelector()) + if errMeta != nil { + return nil, errMeta + } + return doc.AsYAML() + } filteredBundle, err := bundle.SelectBundle(document.NewDeployToK8sSelector()) if err != nil { return nil, err } + buffer := bytes.NewBuffer([]byte{}) err = filteredBundle.Write(buffer) if err != nil { diff --git a/pkg/clusterctl/implementations/repository_test.go b/pkg/clusterctl/implementations/repository_test.go index 1692308bf..7ced253e1 100644 --- a/pkg/clusterctl/implementations/repository_test.go +++ b/pkg/clusterctl/implementations/repository_test.go @@ -6,6 +6,8 @@ import ( "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" @@ -90,12 +92,14 @@ func TestNewRepository(t *testing.T) { func TestGetFile(t *testing.T) { tests := []struct { - name string - root string - versions map[string]string - expectErr bool - resultVersion string - versionToUse string + name string + root string + versions map[string]string + expectErr bool + resultVersion string + versionToUse string + fileToUse string + resultContract string }{ { name: "single version", @@ -149,6 +153,28 @@ func TestGetFile(t *testing.T) { 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 @@ -156,19 +182,26 @@ func TestGetFile(t *testing.T) { 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.NoError(t, err) assert.NotNil(t, repo) - b, err := repo.GetFile(versionToUse, "") + b, err := repo.GetFile(versionToUse, fileToUse) if expectErr { assert.Error(t, err) } else { assert.NoError(t, err) - gotVersion := version(t, b) - assert.Equal(t, resultVersion, gotVersion.Spec.Version) + if fileToUse == "metadata.yaml" { + gotMetdata := metadata(t, b) + parsedVersion, err := versionclient.ParseSemantic(versionToUse) + require.NoError(t, err) + assert.Equal(t, resultContract, gotMetdata.GetReleaseSeriesForVersion(parsedVersion).Contract) + } else { + gotVersion := version(t, b) + assert.Equal(t, resultVersion, gotVersion.Spec.Version) + } } }) } @@ -183,6 +216,14 @@ func version(t *testing.T, versionBytes []byte) *Version { 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", diff --git a/pkg/clusterctl/implementations/testdata/functions/2/version.yaml b/pkg/clusterctl/implementations/testdata/functions/2/version.yaml index e7d74275f..2f73e855b 100644 --- a/pkg/clusterctl/implementations/testdata/functions/2/version.yaml +++ b/pkg/clusterctl/implementations/testdata/functions/2/version.yaml @@ -5,3 +5,15 @@ metadata: name: version-2 spec: version: v0.0.2 +--- +apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3 +kind: Metadata +metadata: + name: repository-metadata +releaseSeries: +- major: 0 + minor: 3 + contract: v1alpha3 +- major: 0 + minor: 2 + contract: v1alpha2 \ No newline at end of file diff --git a/pkg/document/constants.go b/pkg/document/constants.go index 72be95e86..e95065e12 100644 --- a/pkg/document/constants.go +++ b/pkg/document/constants.go @@ -26,8 +26,12 @@ const ( DeployToK8sSelector = "airshipit.org/deploy-k8s notin (False, false)" ) -// Kinds +// GVKs const ( SecretKind = "Secret" BareMetalHostKind = "BareMetalHost" + + ClusterctlMetadataKind = "Metadata" + ClusterctlMetadataVersion = "v1alpha3" + ClusterctlMetadataGroup = "clusterctl.cluster.x-k8s.io" ) diff --git a/pkg/document/selectors.go b/pkg/document/selectors.go index f8f18d548..4d6090c95 100644 --- a/pkg/document/selectors.go +++ b/pkg/document/selectors.go @@ -157,3 +157,10 @@ func NewNetworkDataSelector(bmhDoc Document) (Selector, error) { func NewDeployToK8sSelector() Selector { return NewSelector().ByLabel(DeployToK8sSelector) } + +// NewClusterctlMetadataSelector returns selector to get clusterctl metadata documents +func NewClusterctlMetadataSelector() Selector { + return NewSelector().ByGvk(ClusterctlMetadataGroup, + ClusterctlMetadataVersion, + ClusterctlMetadataKind) +} diff --git a/pkg/document/selectors_test.go b/pkg/document/selectors_test.go index aa704dac8..8b4ce1e47 100644 --- a/pkg/document/selectors_test.go +++ b/pkg/document/selectors_test.go @@ -48,6 +48,12 @@ func TestSelectorsPositive(t *testing.T) { require.NoError(t, err) assert.Len(t, doc, 1) }) + + t.Run("TestNewClusterctlMetadataSelector", func(t *testing.T) { + doc, err := bundle.Select(document.NewClusterctlMetadataSelector()) + require.NoError(t, err) + assert.Len(t, doc, 1) + }) } func TestSelectorsNegative(t *testing.T) { diff --git a/pkg/document/testdata/selectors/valid/kustomization.yaml b/pkg/document/testdata/selectors/valid/kustomization.yaml index 6f83d2cc2..a3c4e8b39 100644 --- a/pkg/document/testdata/selectors/valid/kustomization.yaml +++ b/pkg/document/testdata/selectors/valid/kustomization.yaml @@ -1,4 +1,5 @@ resources: - baremetal.yaml - secret.yaml - - argo.yaml \ No newline at end of file + - argo.yaml + - metadata.yaml \ No newline at end of file diff --git a/pkg/document/testdata/selectors/valid/metadata.yaml b/pkg/document/testdata/selectors/valid/metadata.yaml new file mode 100644 index 000000000..eafea1c5a --- /dev/null +++ b/pkg/document/testdata/selectors/valid/metadata.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3 +kind: Metadata +metadata: + name: repository-metadata +releaseSeries: +- major: 0 + minor: 3 + contract: v1alpha3 +- major: 0 + minor: 2 + contract: v1alpha2 \ No newline at end of file