diff --git a/cmd/config/testdata/TestGetManifestConfigCmdGoldenOutput/get-all-manifests.golden b/cmd/config/testdata/TestGetManifestConfigCmdGoldenOutput/get-all-manifests.golden index 44b7858fe..53434041b 100644 --- a/cmd/config/testdata/TestGetManifestConfigCmdGoldenOutput/get-all-manifests.golden +++ b/cmd/config/testdata/TestGetManifestConfigCmdGoldenOutput/get-all-manifests.golden @@ -1,11 +1,14 @@ +metadataPath: "" primaryRepositoryName: bar_primary_repo subPath: "" targetPath: bar_target_path +metadataPath: "" primaryRepositoryName: baz_primary_repo subPath: "" targetPath: baz_target_path +metadataPath: "" primaryRepositoryName: foo_primary_repo subPath: "" targetPath: foo_target_path diff --git a/cmd/config/testdata/TestGetManifestConfigCmdGoldenOutput/get-manifest.golden b/cmd/config/testdata/TestGetManifestConfigCmdGoldenOutput/get-manifest.golden index c85391380..4306f08ed 100644 --- a/cmd/config/testdata/TestGetManifestConfigCmdGoldenOutput/get-manifest.golden +++ b/cmd/config/testdata/TestGetManifestConfigCmdGoldenOutput/get-manifest.golden @@ -1,3 +1,4 @@ +metadataPath: "" primaryRepositoryName: foo_primary_repo subPath: "" targetPath: foo_target_path diff --git a/pkg/config/config.go b/pkg/config/config.go index ad3936c0e..065343992 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -1079,6 +1079,20 @@ func (c *Config) Purge() error { return os.Remove(c.loadedConfigPath) } +// CurrentContextManifestMetadata gets manifest metadata +func (c *Config) CurrentContextManifestMetadata() (*Metadata, error) { + manifest, err := c.CurrentContextManifest() + if err != nil { + return nil, err + } + meta := &Metadata{} + err = util.ReadYAMLFile(manifest.MetadataPath, meta) + if err != nil { + return nil, err + } + return meta, nil +} + // DecodeAuthInfo returns authInfo with credentials decoded func DecodeAuthInfo(authinfo *clientcmdapi.AuthInfo) (*clientcmdapi.AuthInfo, error) { password := authinfo.Password diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index af919bc12..615be4590 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -21,6 +21,7 @@ import ( "io/ioutil" "os" "path/filepath" + "strings" "testing" "github.com/stretchr/testify/assert" @@ -551,6 +552,87 @@ func TestCurrentContextClusterName(t *testing.T) { assert.Equal(t, expectedClusterName, actualClusterName) } +func TestCurrentContextManifestMetadata(t *testing.T) { + expectedMeta := &config.Metadata{ + Inventory: &config.InventoryMeta{ + Path: "manifests/site/inventory", + }, + PhaseMeta: &config.PhaseMeta{ + Path: "manifests/site/phases", + }, + } + conf, cleanup := testutil.InitConfig(t) + defer cleanup(t) + tests := []struct { + name string + metaPath string + currentContext string + expectErr bool + errorChecker func(error) bool + meta *config.Metadata + }{ + { + name: "default metadata", + metaPath: "testdata/metadata.yaml", + expectErr: false, + currentContext: "testContext", + meta: &config.Metadata{ + Inventory: &config.InventoryMeta{ + Path: "manifests/site/inventory", + }, + PhaseMeta: &config.PhaseMeta{ + Path: "manifests/site/phases", + }, + }, + }, + { + name: "no such file or directory", + metaPath: "does not exist", + currentContext: "testContext", + expectErr: true, + errorChecker: os.IsNotExist, + }, + { + name: "missing context", + currentContext: "doesn't exist", + expectErr: true, + errorChecker: func(err error) bool { + return strings.Contains(err.Error(), "Missing configuration") + }, + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + context := &config.Context{ + Manifest: "testManifest", + } + manifest := &config.Manifest{ + MetadataPath: tt.metaPath, + TargetPath: ".", + } + conf.Manifests = map[string]*config.Manifest{ + "testManifest": manifest, + } + conf.Contexts = map[string]*config.Context{ + "testContext": context, + } + conf.CurrentContext = tt.currentContext + meta, err := conf.CurrentContextManifestMetadata() + if tt.expectErr { + t.Logf("error is %v", err) + require.Error(t, err) + require.NotNil(t, tt.errorChecker) + assert.True(t, tt.errorChecker(err)) + } else { + require.NoError(t, err) + require.NotNil(t, meta) + assert.Equal(t, expectedMeta, meta) + } + }) + } +} + func TestNewClusterComplexNameFromKubeClusterName(t *testing.T) { tests := []struct { name string diff --git a/pkg/config/constants.go b/pkg/config/constants.go index 1fee03085..8ef76ce2c 100644 --- a/pkg/config/constants.go +++ b/pkg/config/constants.go @@ -74,4 +74,6 @@ const ( DefaultTargetPath = "/tmp/default" // DefaultSubPath holds default sub path DefaultSubPath = "manifest/default" + // DefaultManifestMetadataFile default path to manifest metadata file + DefaultManifestMetadataFile = "manifests/site/test-site/metadata.yaml" ) diff --git a/pkg/config/manifest.go b/pkg/config/manifest.go index 06880f31e..d9370cf1b 100644 --- a/pkg/config/manifest.go +++ b/pkg/config/manifest.go @@ -35,6 +35,8 @@ type Manifest struct { // you would expect that at treasuremap/manifests you would have ephemeral/initinfra and // ephemera/target directories, containing kustomize.yaml. SubPath string `json:"subPath"` + // MetadataPath path to a metadata file relative to TargetPath + MetadataPath string `json:"metadataPath"` } // Repository is a tuple that holds the information for the remote sources of manifest yaml documents. @@ -84,6 +86,25 @@ type RepoCheckout struct { ForceCheckout bool `json:"force"` } +// Metadata holds entrypoints for phases, inventory and clusterctl +type Metadata struct { + Inventory *InventoryMeta `json:"inventory,omitempty"` + PhaseMeta *PhaseMeta `json:"phase,omitempty"` +} + +// InventoryMeta holds inventory metadata, this is to be extended in the future +// when we have more information how to handle non-baremetal inventories +// path is a kustomize entrypoint against which we will build bundle containing bmh hosts +type InventoryMeta struct { + Path string `json:"path,omitempty"` +} + +// PhaseMeta holds phase metadata, right now it is only path, but maybe extended further +// path is a kustomize entrypoint against which we will build bundle with phase objects +type PhaseMeta struct { + Path string `json:"path,omitempty"` +} + // Manifest functions func (m *Manifest) String() string { yamlData, err := yaml.Marshal(&m) diff --git a/pkg/config/testdata/config-string.yaml b/pkg/config/testdata/config-string.yaml index 39895fdb4..cdf3db40a 100644 --- a/pkg/config/testdata/config-string.yaml +++ b/pkg/config/testdata/config-string.yaml @@ -32,6 +32,7 @@ managementConfiguration: type: redfish manifests: dummy_manifest: + metadataPath: manifests/site/test-site/metadata.yaml primaryRepositoryName: primary repositories: primary: diff --git a/pkg/config/testdata/manifest-string.yaml b/pkg/config/testdata/manifest-string.yaml index 05fb213f0..2a7eba873 100644 --- a/pkg/config/testdata/manifest-string.yaml +++ b/pkg/config/testdata/manifest-string.yaml @@ -1,3 +1,4 @@ +metadataPath: manifests/site/test-site/metadata.yaml primaryRepositoryName: primary repositories: primary: diff --git a/pkg/config/testdata/metadata.yaml b/pkg/config/testdata/metadata.yaml new file mode 100644 index 000000000..f31396a98 --- /dev/null +++ b/pkg/config/testdata/metadata.yaml @@ -0,0 +1,4 @@ +inventory: + path: "manifests/site/inventory" +phase: + path: "manifests/site/phases" \ No newline at end of file diff --git a/pkg/config/utils.go b/pkg/config/utils.go index 104824f38..210dd1c01 100644 --- a/pkg/config/utils.go +++ b/pkg/config/utils.go @@ -93,6 +93,7 @@ func NewManifest() *Manifest { TargetPath: DefaultTargetPath, SubPath: DefaultSubPath, Repositories: map[string]*Repository{DefaultTestPrimaryRepo: NewRepository()}, + MetadataPath: DefaultManifestMetadataFile, } }