Merge "Refactor management of config file paths"

This commit is contained in:
Zuul 2020-02-10 18:39:39 +00:00 committed by Gerrit Code Review
commit 6e8ca5b010
7 changed files with 237 additions and 157 deletions

View File

@ -29,21 +29,20 @@ import (
"sigs.k8s.io/yaml"
"k8s.io/client-go/tools/clientcmd"
kubeconfig "k8s.io/client-go/tools/clientcmd/api"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"opendev.org/airship/airshipctl/pkg/util"
)
// Called from root to Load the initial configuration
func (c *Config) LoadConfig(configFileArg string, kPathOptions *clientcmd.PathOptions) error {
err := c.loadFromAirConfig(configFileArg)
// LoadConfig populates the Config object using the files found at
// airshipConfigPath and kubeConfigPath
func (c *Config) LoadConfig(airshipConfigPath, kubeConfigPath string) error {
err := c.loadFromAirConfig(airshipConfigPath)
if err != nil {
return err
}
// Load or initialize the kubeconfig object from a file
err = c.loadKubeConfig(kPathOptions)
err = c.loadKubeConfig(kubeConfigPath)
if err != nil {
return err
}
@ -52,36 +51,45 @@ func (c *Config) LoadConfig(configFileArg string, kPathOptions *clientcmd.PathOp
return c.reconcileConfig()
}
func (c *Config) loadFromAirConfig(configFileArg string) error {
// If it exists, Read the ConfigFile data
// Only care about the errors here, because there is a file
// And essentially I cannot use its data.
// airshipctl probable should stop
if configFileArg == "" {
// loadFromAirConfig populates the Config from the file found at airshipConfigPath.
// If there is no file at airshipConfigPath, this function does nothing.
// An error is returned if:
// * airshipConfigPath is the empty string
// * the file at airshipConfigPath is inaccessible
// * the file at airshipConfigPath cannot be marshaled into Config
func (c *Config) loadFromAirConfig(airshipConfigPath string) error {
if airshipConfigPath == "" {
return errors.New("Configuration file location was not provided.")
}
// Remember where I loaded the Config from
c.loadedConfigPath = configFileArg
// If I have a file to read, load from it
c.loadedConfigPath = airshipConfigPath
if _, err := os.Stat(configFileArg); os.IsNotExist(err) {
// If I can read from the file, load from it
if _, err := os.Stat(airshipConfigPath); os.IsNotExist(err) {
return nil
}
return util.ReadYAMLFile(configFileArg, c)
}
func (c *Config) loadKubeConfig(kPathOptions *clientcmd.PathOptions) error {
// Will need this for Persisting the changes
c.loadedPathOptions = kPathOptions
// Now at this point what I load might not reflect the associated kubeconfig yet
kConfig, err := kPathOptions.GetStartingConfig()
if err != nil {
} else if err != nil {
return err
}
// Store the kubeconfig object into an airship managed kubeconfig object
c.kubeConfig = kConfig
return nil
return util.ReadYAMLFile(airshipConfigPath, c)
}
func (c *Config) loadKubeConfig(kubeConfigPath string) error {
// Will need this for persisting the changes
c.kubeConfigPath = kubeConfigPath
// If I can read from the file, load from it
var err error
if _, err = os.Stat(kubeConfigPath); os.IsNotExist(err) {
c.kubeConfig = clientcmdapi.NewConfig()
return nil
} else if err != nil {
return err
}
c.kubeConfig, err = clientcmd.LoadFromFile(kubeConfigPath)
return err
}
// reconcileConfig serves two functions:
@ -198,6 +206,7 @@ func (c *Config) rmConfigClusterStragglers(persistIt bool) bool {
}
return rccs
}
func (c *Config) reconcileContexts(updatedClusterNames map[string]string) {
for key, context := range c.kubeConfig.Contexts {
// Check if the Cluster name referred to by the context
@ -254,7 +263,7 @@ func (c *Config) reconcileAuthInfos() {
func (c *Config) reconcileCurrentContext() {
// If the Airship current context is different that the current context in the kubeconfig
// then
// - if the airship current context is valid, then updated kubeconfiug CC
// - if the airship current context is valid, then updated kubeconfig CC
// - if the airship currentcontext is invalid, and the kubeconfig CC is valid, then create the reference
// - otherwise , they are both empty. Make sure
@ -326,20 +335,17 @@ func (c *Config) EnsureComplete() error {
return nil
}
// This function is called to update the configuration in the file defined by the
// ConfigFile name
// It will completely overwrite the existing file,
// If the file specified by ConfigFile exists ts updates with the contents of the Config object
// If the file specified by ConfigFile does not exist it will create a new file.
// PersistConfig updates the airshipctl config and kubeconfig files to match
// the current Config and KubeConfig objects.
// If either file did not previously exist, the file will be created.
// Otherwise, the file will be overwritten
func (c *Config) PersistConfig() error {
// Dont care if the file exists or not, will create if needed
// We are 100% overwriting the existing file
configyaml, err := c.ToYaml()
airshipConfigYaml, err := c.ToYaml()
if err != nil {
return err
}
// 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)
err = os.MkdirAll(configDir, 0755)
if err != nil {
@ -347,19 +353,13 @@ func (c *Config) PersistConfig() error {
}
// Write the Airship Config file
err = ioutil.WriteFile(c.loadedConfigPath, configyaml, 0644)
err = ioutil.WriteFile(c.loadedConfigPath, airshipConfigYaml, 0644)
if err != nil {
return err
}
// FIXME(howell): if this fails, then the results from the previous
// actions will persist, meaning that we might have overwritten our
// airshipconfig without updating our kubeconfig. A possible solution
// is to generate brand new config files and then write them at the
// end. That could still fail, but should be more robust
// Persist the kubeconfig file referenced
if err := clientcmd.ModifyConfig(c.loadedPathOptions, *c.kubeConfig, true); err != nil {
if err := clientcmd.WriteToFile(*c.kubeConfig, c.kubeConfigPath); err != nil {
return err
}
@ -386,14 +386,15 @@ func (c *Config) SetLoadedConfigPath(lcp string) {
c.loadedConfigPath = lcp
}
func (c *Config) LoadedPathOptions() *clientcmd.PathOptions {
return c.loadedPathOptions
}
func (c *Config) SetLoadedPathOptions(po *clientcmd.PathOptions) {
c.loadedPathOptions = po
func (c *Config) KubeConfigPath() string {
return c.kubeConfigPath
}
func (c *Config) KubeConfig() *kubeconfig.Config {
func (c *Config) SetKubeConfigPath(kubeConfigPath string) {
c.kubeConfigPath = kubeConfigPath
}
func (c *Config) KubeConfig() *clientcmdapi.Config {
return c.kubeConfig
}
@ -441,7 +442,7 @@ func (c *Config) AddCluster(theCluster *ClusterOptions) (*Cluster, error) {
nCluster := NewCluster()
c.Clusters[theCluster.Name].ClusterTypes[theCluster.ClusterType] = nCluster
// Create a new Kubeconfig Cluster object as well
kcluster := kubeconfig.NewCluster()
kcluster := clientcmdapi.NewCluster()
clusterName := NewClusterComplexName()
clusterName.WithType(theCluster.Name, theCluster.ClusterType)
nCluster.NameInKubeconf = clusterName.Name()
@ -541,7 +542,7 @@ func (c *Config) AddContext(theContext *ContextOptions) *Context {
nContext := NewContext()
c.Contexts[theContext.Name] = nContext
// Create a new Kubeconfig Context object as well
kContext := kubeconfig.NewContext()
kContext := clientcmdapi.NewContext()
nContext.NameInKubeconf = theContext.Name
contextName := NewClusterComplexName()
contextName.WithType(theContext.Name, theContext.ClusterType)
@ -645,7 +646,7 @@ func (c *Config) AddAuthInfo(theAuthInfo *AuthInfoOptions) *AuthInfo {
nAuthInfo := NewAuthInfo()
c.AuthInfos[theAuthInfo.Name] = nAuthInfo
// Create a new Kubeconfig AuthInfo object as well
kAuthInfo := kubeconfig.NewAuthInfo()
kAuthInfo := clientcmdapi.NewAuthInfo()
nAuthInfo.SetKubeAuthInfo(kAuthInfo)
c.KubeConfig().AuthInfos[theAuthInfo.Name] = kAuthInfo
@ -739,10 +740,10 @@ func (c *Cluster) PrettyString() string {
clusterName.ClusterName(), clusterName.ClusterType(), c)
}
func (c *Cluster) KubeCluster() *kubeconfig.Cluster {
func (c *Cluster) KubeCluster() *clientcmdapi.Cluster {
return c.kCluster
}
func (c *Cluster) SetKubeCluster(kc *kubeconfig.Cluster) {
func (c *Cluster) SetKubeCluster(kc *clientcmdapi.Cluster) {
c.kCluster = kc
}
@ -777,11 +778,11 @@ func (c *Context) PrettyString() string {
clusterName.ClusterName(), c.String())
}
func (c *Context) KubeContext() *kubeconfig.Context {
func (c *Context) KubeContext() *clientcmdapi.Context {
return c.kContext
}
func (c *Context) SetKubeContext(kc *kubeconfig.Context) {
func (c *Context) SetKubeContext(kc *clientcmdapi.Context) {
c.kContext = kc
}
@ -808,10 +809,10 @@ func (c *AuthInfo) String() string {
return string(kyaml)
}
func (c *AuthInfo) KubeAuthInfo() *kubeconfig.AuthInfo {
func (c *AuthInfo) KubeAuthInfo() *clientcmdapi.AuthInfo {
return c.kAuthInfo
}
func (c *AuthInfo) SetKubeAuthInfo(kc *kubeconfig.AuthInfo) {
func (c *AuthInfo) SetKubeAuthInfo(kc *clientcmdapi.AuthInfo) {
c.kAuthInfo = kc
}
@ -979,7 +980,7 @@ PLACEHOLDER UNTIL I IDENTIFY if CLIENTADM
HAS SOMETHING LIKE THIS
*/
func KClusterString(kCluster *kubeconfig.Cluster) string {
func KClusterString(kCluster *clientcmdapi.Cluster) string {
yamlData, err := yaml.Marshal(&kCluster)
if err != nil {
return ""
@ -987,7 +988,8 @@ func KClusterString(kCluster *kubeconfig.Cluster) string {
return string(yamlData)
}
func KContextString(kContext *kubeconfig.Context) string {
func KContextString(kContext *clientcmdapi.Context) string {
yamlData, err := yaml.Marshal(&kContext)
if err != nil {
return ""
@ -995,7 +997,8 @@ func KContextString(kContext *kubeconfig.Context) string {
return string(yamlData)
}
func KAuthInfoString(kAuthInfo *kubeconfig.AuthInfo) string {
func KAuthInfoString(kAuthInfo *clientcmdapi.AuthInfo) string {
yamlData, err := yaml.Marshal(&kAuthInfo)
if err != nil {
return ""

View File

@ -26,7 +26,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"k8s.io/client-go/tools/clientcmd"
kubeconfig "k8s.io/client-go/tools/clientcmd/api"
"opendev.org/airship/airshipctl/testutil"
@ -224,10 +223,11 @@ func TestPersistConfig(t *testing.T) {
config := InitConfig(t)
err := config.PersistConfig()
assert.NoErrorf(t, err, "Unable to persist configuration expected at %v", config.LoadedConfigPath())
require.NoError(t, err)
kpo := config.LoadedPathOptions()
assert.NotNil(t, kpo)
// Check that the files were created
assert.FileExists(t, config.LoadedConfigPath())
assert.FileExists(t, config.KubeConfigPath())
}
func TestEnsureComplete(t *testing.T) {
@ -347,11 +347,10 @@ func TestPurge(t *testing.T) {
require.NoError(t, err)
airConfigFile := filepath.Join(tempDir, AirshipConfig)
kConfigFile := filepath.Join(tempDir, AirshipKubeConfig)
config.SetLoadedConfigPath(airConfigFile)
kubePathOptions := clientcmd.NewDefaultPathOptions()
kubePathOptions.GlobalFile = kConfigFile
config.SetLoadedPathOptions(kubePathOptions)
kConfigFile := filepath.Join(tempDir, AirshipKubeConfig)
config.kubeConfigPath = kConfigFile
// Store it
err = config.PersistConfig()

View File

@ -11,19 +11,22 @@ const (
AirshipClusterDefaultType = Target
)
//Sorted
// Sorted
var AllClusterTypes = [2]string{Ephemeral, Target}
// Constants defining default values
const (
AirshipConfigEnv = "airshipconf"
AirshipConfig = "config"
AirshipConfigDir = ".airship"
AirshipConfigKind = "Config"
AirshipConfigVersion = "v1alpha1"
AirshipConfigGroup = "airshipit.org"
AirshipConfigVersion = "v1alpha1"
AirshipConfigApiVersion = AirshipConfigGroup + "/" + AirshipConfigVersion
AirshipKubeConfig = "kubeconfig"
AirshipConfigKind = "Config"
AirshipConfigDir = ".airship"
AirshipConfig = "config"
AirshipKubeConfig = "kubeconfig"
AirshipConfigEnv = "AIRSHIPCONFIG"
AirshipKubeConfigEnv = "AIRSHIP_KUBECONFIG"
)
// Constants defining CLI flags
@ -37,7 +40,7 @@ const (
FlagClusterType = "cluster-type"
FlagContext = "context"
FlagCurrentContext = "current-context"
FlagConfigFilePath = AirshipConfigEnv
FlagConfigFilePath = "airshipconf"
FlagEmbedCerts = "embed-certs"
FlagImpersonate = "as"
FlagImpersonateGroup = "as-group"

View File

@ -22,7 +22,6 @@ import (
"path/filepath"
"testing"
"k8s.io/client-go/tools/clientcmd"
kubeconfig "k8s.io/client-go/tools/clientcmd/api"
"github.com/stretchr/testify/require"
@ -145,9 +144,7 @@ func InitConfig(t *testing.T) *Config {
conf := NewConfig()
kubePathOptions := clientcmd.NewDefaultPathOptions()
kubePathOptions.GlobalFile = kubeConfigPath
err = conf.LoadConfig(configPath, kubePathOptions)
err = conf.LoadConfig(configPath, kubeConfigPath)
require.NoError(t, err)
return conf

View File

@ -19,7 +19,6 @@ package config
import (
"net/url"
"k8s.io/client-go/tools/clientcmd"
kubeconfig "k8s.io/client-go/tools/clientcmd/api"
)
@ -57,15 +56,15 @@ type Config struct {
// Such as Bootstrap, Workflows, Document, etc
ModulesConfig *Modules `json:"modules-config"`
// Private LoadedConfigPath is the full path to the the location of the config file
// from which these config was loaded
// loadedConfigPath is the full path to the the location of the config
// file from which this config was loaded
// +not persisted in file
loadedConfigPath string
// Private loadedPathOptions is the full path to the the location of the kubeconfig file
// associated with this airship config instance
// kubeConfigPath is the full path to the the location of the
// kubeconfig file associated with this airship config instance
// +not persisted in file
loadedPathOptions *clientcmd.PathOptions
kubeConfigPath string
// Private instance of Kube Config content as an object
kubeConfig *kubeconfig.Config

View File

@ -3,7 +3,6 @@ package environment
import (
"os"
"path/filepath"
"strings"
"github.com/spf13/cobra"
@ -64,67 +63,64 @@ func (a *AirshipCTLSettings) SetKubeConfigPath(kcp string) {
func (a *AirshipCTLSettings) InitConfig() {
a.SetConfig(config.NewConfig())
a.setAirshipConfigPath()
a.initAirshipConfigPath()
a.initKubeConfigPath()
//Pass the airshipConfigPath and kubeConfig object
err := a.Config().LoadConfig(a.AirshipConfigPath(), a.setKubePathOptions())
err := a.Config().LoadConfig(a.AirshipConfigPath(), a.KubeConfigPath())
if err != nil {
// Should stop airshipctl
log.Fatal(err)
}
}
func (a *AirshipCTLSettings) setAirshipConfigPath() {
// (1) If the airshipConfigPath was received as an argument its already set
if a.airshipConfigPath == "" {
// (2) If not , we can check if we got the Path via ENVIRONMENT variable,
// set the appropriate fields
a.setAirshipConfigPathFromEnv()
func (a *AirshipCTLSettings) initAirshipConfigPath() {
// The airshipConfigPath may already have been received as a command line argument
if a.airshipConfigPath != "" {
return
}
// (3) Check if the a.airshipConfigPath is empty still at this point , use the defaults
acp, home := a.replaceHomePlaceholder(a.airshipConfigPath)
a.airshipConfigPath = acp
if a.airshipConfigPath == "" {
a.airshipConfigPath = filepath.Join(home, config.AirshipConfigDir, config.AirshipConfig)
}
}
// setAirshipConfigPathFromEnv Get AIRSHIP CONFIG from an environment variable if set
func (a *AirshipCTLSettings) setAirshipConfigPathFromEnv() {
// Check if AIRSHIPCONF env variable was set
// I have the path and name for the airship config file
// Otherwise, we can check if we got the path via ENVIRONMENT variable
a.airshipConfigPath = os.Getenv(config.AirshipConfigEnv)
}
func (a *AirshipCTLSettings) setKubePathOptions() *clientcmd.PathOptions {
// USe default expectations for Kubeconfig
kubePathOptions := clientcmd.NewDefaultPathOptions()
// No need to check the Environment , since we are relying on the kubeconfig defaults
// If we did not get an explicit kubeconfig definition on airshipctl
// as far as airshipctl is concerned will use the default expectations for the kubeconfig
// file location . This avoids messing up someones kubeconfig if they didnt explicitly want
// airshipctl to use it.
kcp, home := a.replaceHomePlaceholder(a.kubeConfigPath)
a.kubeConfigPath = kcp
if a.kubeConfigPath == "" {
a.kubeConfigPath = filepath.Join(home, config.AirshipConfigDir, config.AirshipKubeConfig)
if a.airshipConfigPath != "" {
return
}
// We will always rely on tha airshipctl cli args or default for where to find kubeconfig
kubePathOptions.GlobalFile = a.kubeConfigPath
kubePathOptions.GlobalFileSubpath = a.kubeConfigPath
return kubePathOptions
// Otherwise, we'll try putting it in the home directory
homeDir := userHomeDir()
a.airshipConfigPath = filepath.Join(homeDir, config.AirshipConfigDir, config.AirshipConfig)
}
func (a *AirshipCTLSettings) replaceHomePlaceholder(configPath string) (string, string) {
home, err := os.UserHomeDir()
func (a *AirshipCTLSettings) initKubeConfigPath() {
// NOTE(howell): This function will set the kubeConfigPath to the
// default location under the airship directory unless the user
// *explicitly* specifies a different location, either by setting the
// ENVIRONMENT variable or by passing a command line argument.
// This avoids messing up the user's kubeconfig if they didn't
// explicitly want airshipctl to use it.
// The kubeConfigPath may already have been received as a command line argument
if a.kubeConfigPath != "" {
return
}
// Otherwise, we can check if we got the path via ENVIRONMENT variable
a.kubeConfigPath = os.Getenv(config.AirshipKubeConfigEnv)
if a.kubeConfigPath != "" {
return
}
// Otherwise, we'll try putting it in the home directory
homeDir := userHomeDir()
a.kubeConfigPath = filepath.Join(homeDir, config.AirshipConfigDir, config.AirshipKubeConfig)
}
// userHomeDir is a utility function that wraps os.UserHomeDir and returns no
// errors. If the user has no home directory, the returned value will be the
// empty string
func userHomeDir() string {
homeDir, err := os.UserHomeDir()
if err != nil {
// Use defaults under current directory
home = ""
homeDir = ""
}
if configPath == "" {
return configPath, home
}
return strings.Replace(configPath, HomePlaceholder, home, 1), home
return homeDir
}

View File

@ -17,6 +17,7 @@ limitations under the License.
package environment
import (
"io/ioutil"
"os"
"path/filepath"
"testing"
@ -36,25 +37,107 @@ func TestInitFlags(t *testing.T) {
assert.True(t, testCmd.HasPersistentFlags())
}
func TestSpecifyAirConfigFromEnv(t *testing.T) {
fakeConfig := "FakeConfigPath"
err := os.Setenv(config.AirshipConfigEnv, fakeConfig)
func TestInitConfig(t *testing.T) {
t.Run("DefaultToHomeDirectory", func(subTest *testing.T) {
// Set up a fake $HOME directory
testDir := makeTestDir(t)
defer deleteTestDir(t, testDir)
defer setHome(testDir)()
var testSettings AirshipCTLSettings
expectedAirshipConfig := filepath.Join(testDir, config.AirshipConfigDir, config.AirshipConfig)
expectedKubeConfig := filepath.Join(testDir, config.AirshipConfigDir, config.AirshipKubeConfig)
testSettings.InitConfig()
assert.Equal(t, expectedAirshipConfig, testSettings.AirshipConfigPath())
assert.Equal(t, expectedKubeConfig, testSettings.KubeConfigPath())
})
t.Run("PreferEnvToDefault", func(subTest *testing.T) {
// Set up a fake $HOME directory
testDir := makeTestDir(t)
defer deleteTestDir(t, testDir)
defer setHome(testDir)()
var testSettings AirshipCTLSettings
expectedAirshipConfig := filepath.Join(testDir, "airshipEnv")
expectedKubeConfig := filepath.Join(testDir, "kubeEnv")
os.Setenv(config.AirshipConfigEnv, expectedAirshipConfig)
os.Setenv(config.AirshipKubeConfigEnv, expectedKubeConfig)
defer os.Unsetenv(config.AirshipConfigEnv)
defer os.Unsetenv(config.AirshipKubeConfigEnv)
testSettings.InitConfig()
assert.Equal(t, expectedAirshipConfig, testSettings.AirshipConfigPath())
assert.Equal(t, expectedKubeConfig, testSettings.KubeConfigPath())
})
t.Run("PreferCmdLineArgToDefault", func(subTest *testing.T) {
// Set up a fake $HOME directory
testDir := makeTestDir(t)
defer deleteTestDir(t, testDir)
defer setHome(testDir)()
var testSettings AirshipCTLSettings
expectedAirshipConfig := filepath.Join(testDir, "airshipCmdLine")
expectedKubeConfig := filepath.Join(testDir, "kubeCmdLine")
testSettings.SetAirshipConfigPath(expectedAirshipConfig)
testSettings.SetKubeConfigPath(expectedKubeConfig)
// InitConfig should not change any values
testSettings.InitConfig()
assert.Equal(t, expectedAirshipConfig, testSettings.AirshipConfigPath())
assert.Equal(t, expectedKubeConfig, testSettings.KubeConfigPath())
})
t.Run("PreferCmdLineArgToEnv", func(subTest *testing.T) {
// Set up a fake $HOME directory
testDir := makeTestDir(t)
defer deleteTestDir(t, testDir)
defer setHome(testDir)()
var testSettings AirshipCTLSettings
expectedAirshipConfig := filepath.Join(testDir, "airshipCmdLine")
expectedKubeConfig := filepath.Join(testDir, "kubeCmdLine")
// set up "decoy" environment variables. These should be
// ignored, since we're simulating passing in command line
// arguments
wrongAirshipConfig := filepath.Join(testDir, "wrongAirshipConfig")
wrongKubeConfig := filepath.Join(testDir, "wrongKubeConfig")
os.Setenv(config.AirshipConfigEnv, wrongAirshipConfig)
os.Setenv(config.AirshipKubeConfigEnv, wrongKubeConfig)
defer os.Unsetenv(config.AirshipConfigEnv)
defer os.Unsetenv(config.AirshipKubeConfigEnv)
testSettings.SetAirshipConfigPath(expectedAirshipConfig)
testSettings.SetKubeConfigPath(expectedKubeConfig)
testSettings.InitConfig()
assert.Equal(t, expectedAirshipConfig, testSettings.AirshipConfigPath())
assert.Equal(t, expectedKubeConfig, testSettings.KubeConfigPath())
})
}
func makeTestDir(t *testing.T) string {
testDir, err := ioutil.TempDir("", "airship-test")
require.NoError(t, err)
settings := &AirshipCTLSettings{}
settings.InitConfig()
assert.EqualValues(t, fakeConfig, settings.AirshipConfigPath())
return testDir
}
func TestGetSetPaths(t *testing.T) {
settings := &AirshipCTLSettings{}
settings.InitConfig()
airConfigFile := filepath.Join(config.AirshipConfigDir, config.AirshipConfig)
kConfigFile := filepath.Join(config.AirshipConfigDir, config.AirshipKubeConfig)
settings.SetAirshipConfigPath(airConfigFile)
assert.EqualValues(t, airConfigFile, settings.AirshipConfigPath())
settings.SetKubeConfigPath(kConfigFile)
assert.EqualValues(t, kConfigFile, settings.KubeConfigPath())
func deleteTestDir(t *testing.T, path string) {
err := os.Remove(path)
require.NoError(t, err)
}
// setHome sets the HOME environment variable to `path`, and returns a function
// that can be used to reset HOME to its original value
func setHome(path string) (resetHome func()) {
oldHome := os.Getenv("HOME")
os.Setenv("HOME", path)
return func() {
os.Setenv("HOME", oldHome)
}
}