Merge "Use document filesystem in config object to read/write files"

This commit is contained in:
Zuul 2021-02-25 15:56:45 +00:00 committed by Gerrit Code Review
commit b360d6de22
9 changed files with 57 additions and 132 deletions

View File

@ -16,13 +16,13 @@ package config
import ( import (
"fmt" "fmt"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"sort" "sort"
"sigs.k8s.io/yaml" "sigs.k8s.io/yaml"
"opendev.org/airship/airshipctl/pkg/fs"
"opendev.org/airship/airshipctl/pkg/log" "opendev.org/airship/airshipctl/pkg/log"
"opendev.org/airship/airshipctl/pkg/util" "opendev.org/airship/airshipctl/pkg/util"
) )
@ -62,6 +62,7 @@ type Config struct {
// file from which this config was loaded // file from which this config was loaded
// +not persisted in file // +not persisted in file
loadedConfigPath string loadedConfigPath string
fileSystem fs.FileSystem
} }
// Permissions has the permissions for file and directory // Permissions has the permissions for file and directory
@ -125,11 +126,12 @@ func (c *Config) initConfigPath(airshipConfigPath string) {
func (c *Config) LoadConfig() error { func (c *Config) LoadConfig() error {
// If I can read from the file, load from it // If I can read from the file, load from it
// throw an error otherwise // throw an error otherwise
if _, err := os.Stat(c.loadedConfigPath); err != nil { data, err := c.fileSystem.ReadFile(c.loadedConfigPath)
if err != nil {
return err return err
} }
return util.ReadYAMLFile(c.loadedConfigPath, c) return yaml.Unmarshal(data, c)
} }
// EnsureComplete verifies that a Config object is ready to use. // EnsureComplete verifies that a Config object is ready to use.
@ -189,26 +191,26 @@ func (c *Config) PersistConfig(overwrite bool) error {
} }
// WriteFile doesn't create the directory, create it if needed // WriteFile doesn't create the directory, create it if needed
configDir := filepath.Dir(c.loadedConfigPath) dir := c.fileSystem.Dir(c.loadedConfigPath)
err = os.MkdirAll(configDir, os.FileMode(c.Permissions.DirectoryPermission)) err = c.fileSystem.MkdirAll(dir)
if err != nil {
return err
}
// Write the Airship Config file
err = ioutil.WriteFile(c.loadedConfigPath, airshipConfigYaml, os.FileMode(c.Permissions.FilePermission))
if err != nil { if err != nil {
return err return err
} }
// Change the permission of directory // Change the permission of directory
err = os.Chmod(configDir, os.FileMode(c.Permissions.DirectoryPermission)) err = c.fileSystem.Chmod(dir, os.FileMode(c.Permissions.DirectoryPermission))
if err != nil {
return err
}
// Write the Airship Config file
err = c.fileSystem.WriteFile(c.loadedConfigPath, airshipConfigYaml)
if err != nil { if err != nil {
return err return err
} }
// Change the permission of config file // Change the permission of config file
err = os.Chmod(c.loadedConfigPath, os.FileMode(c.Permissions.FilePermission)) err = c.fileSystem.Chmod(c.loadedConfigPath, os.FileMode(c.Permissions.FilePermission))
if err != nil { if err != nil {
return err return err
} }
@ -551,7 +553,7 @@ func (c *Config) CurrentContextManagementConfig() (*ManagementConfiguration, err
// Purge removes the config file // Purge removes the config file
func (c *Config) Purge() error { func (c *Config) Purge() error {
return os.Remove(c.loadedConfigPath) return c.fileSystem.RemoveAll(c.loadedConfigPath)
} }
// CurrentContextManifestMetadata gets manifest metadata // CurrentContextManifestMetadata gets manifest metadata
@ -569,7 +571,13 @@ func (c *Config) CurrentContextManifestMetadata() (*Metadata, error) {
Inventory: &InventoryMeta{}, Inventory: &InventoryMeta{},
PhaseMeta: &PhaseMeta{}, PhaseMeta: &PhaseMeta{},
} }
err = util.ReadYAMLFile(filepath.Join(manifest.TargetPath, phaseRepoDir, manifest.MetadataPath), meta)
data, err := c.fileSystem.ReadFile(filepath.Join(manifest.TargetPath, phaseRepoDir, manifest.MetadataPath))
if err != nil {
return nil, err
}
err = yaml.Unmarshal(data, meta)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -16,7 +16,9 @@ package config_test
import ( import (
"fmt" "fmt"
"io/ioutil"
"os" "os"
"path/filepath"
"strings" "strings"
"testing" "testing"
@ -96,19 +98,14 @@ func TestLoadConfig(t *testing.T) {
} }
func TestPersistConfig(t *testing.T) { func TestPersistConfig(t *testing.T) {
conf, cleanup := testutil.InitConfig(t) testDir, err := ioutil.TempDir("", "airship-test")
defer cleanup(t) require.NoError(t, err)
configPath := filepath.Join(testDir, "config")
conf.SetLoadedConfigPath(conf.LoadedConfigPath() + ".new") err = config.CreateConfig(configPath, true)
require.NoError(t, err)
err := conf.PersistConfig(true) assert.FileExists(t, configPath)
err = os.RemoveAll(testDir)
require.NoError(t, err) require.NoError(t, err)
// Check that the files were created
assert.FileExists(t, conf.LoadedConfigPath())
err = conf.PersistConfig(false)
require.Error(t, err, config.ErrConfigFileExists{Path: conf.LoadedConfigPath()})
} }
func TestEnsureComplete(t *testing.T) { func TestEnsureComplete(t *testing.T) {

View File

@ -16,6 +16,8 @@ package config
import ( import (
"encoding/base64" "encoding/base64"
"opendev.org/airship/airshipctl/pkg/fs"
) )
// NewConfig returns a newly initialized Config object // NewConfig returns a newly initialized Config object
@ -53,6 +55,7 @@ func NewConfig() *Config {
MetadataPath: DefaultManifestMetadataFile, MetadataPath: DefaultManifestMetadataFile,
}, },
}, },
fileSystem: fs.NewDocumentFs(),
} }
} }

View File

@ -555,9 +555,9 @@ manifests:
metadataPath: valid_site/metadata.yaml metadataPath: valid_site/metadata.yaml
repositories: repositories:
primary: primary:
url: "empty/filename/" url: "empty/filename/"`
`
conf := &config.Config{} conf := config.NewConfig()
err := yaml.Unmarshal([]byte(confString), conf) err := yaml.Unmarshal([]byte(confString), conf)
require.NoError(t, err) require.NoError(t, err)
return conf return conf

View File

@ -1,31 +0,0 @@
/*
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 util
import (
"io/ioutil"
"sigs.k8s.io/yaml"
)
// ReadYAMLFile reads YAML-formatted configuration file and
// de-serializes it to a given object
func ReadYAMLFile(filePath string, cfg interface{}) error {
data, err := ioutil.ReadFile(filePath)
if err != nil {
return err
}
return yaml.Unmarshal(data, cfg)
}

View File

@ -1,47 +0,0 @@
/*
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 util_test
import (
"testing"
"github.com/stretchr/testify/assert"
"opendev.org/airship/airshipctl/pkg/util"
)
func TestReadYAMLFile(t *testing.T) {
assert := assert.New(t)
var actual map[string]interface{}
tests := []struct {
testFile string
isError bool
}{
{"testdata/test.yaml", false},
{"testdata/incorrect.yaml", true},
{"testdata/notfound.yaml", true},
}
for _, test := range tests {
err := util.ReadYAMLFile(test.testFile, &actual)
if test.isError {
assert.Error(err)
} else {
assert.NoError(err)
}
}
}

View File

@ -1,3 +0,0 @@
--
testString: incorrectYamlSyntax
...

View File

@ -1 +0,0 @@
testString: test

View File

@ -29,27 +29,26 @@ import (
// DummyConfig used by tests, to initialize min set of data // DummyConfig used by tests, to initialize min set of data
func DummyConfig() *config.Config { func DummyConfig() *config.Config {
conf := &config.Config{ conf := config.NewConfig()
Kind: config.AirshipConfigKind, conf.Kind = config.AirshipConfigKind
APIVersion: config.AirshipConfigAPIVersion, conf.APIVersion = config.AirshipConfigAPIVersion
Permissions: config.Permissions{ conf.Permissions = config.Permissions{
DirectoryPermission: config.AirshipDefaultDirectoryPermission, DirectoryPermission: config.AirshipDefaultDirectoryPermission,
FilePermission: config.AirshipDefaultFilePermission, FilePermission: config.AirshipDefaultFilePermission,
},
Contexts: map[string]*config.Context{
"dummy_context": DummyContext(),
},
Manifests: map[string]*config.Manifest{
"dummy_manifest": DummyManifest(),
},
ManagementConfiguration: map[string]*config.ManagementConfiguration{
"dummy_management_config": DummyManagementConfiguration(),
},
EncryptionConfigs: map[string]*config.EncryptionConfig{
"dummy_encryption_config": DummyEncryptionConfig(),
},
CurrentContext: "dummy_context",
} }
conf.Contexts = map[string]*config.Context{
"dummy_context": DummyContext(),
}
conf.Manifests = map[string]*config.Manifest{
"dummy_manifest": DummyManifest(),
}
conf.ManagementConfiguration = map[string]*config.ManagementConfiguration{
"dummy_management_config": DummyManagementConfiguration(),
}
conf.EncryptionConfigs = map[string]*config.EncryptionConfig{
"dummy_encryption_config": DummyEncryptionConfig(),
}
conf.CurrentContext = "dummy_context"
return conf return conf
} }