From 4e64e74b6f8c92f446b0e8f1c81da1e9c91e6708 Mon Sep 17 00:00:00 2001 From: Matt McEuen Date: Thu, 14 May 2020 14:42:43 -0500 Subject: [PATCH] Add a setting for kustomize plugins This adds an env var-driven configuration for the filesystem path in which kustomize should expect its plugins (including airshipctl) to be. The value defaults to a subfolder off the `.airshipit` folder. The config is persisted as a singleton rather than a member of AirshipCTLSettings (or the Config) because 1. the settings object would have had to have been passed around a couple dozen additional files/functions, 2. it's reasonable to expect the plugin location to be consistent across threads in a multi-threaded, airshipctl-as-library context. Settings_test.go was moved in to an environment_test package to avoid a circular import dependency. Change-Id: Icdd21bd3687ef42492e388af982d7b490af3eff3 --- pkg/config/constants.go | 2 ++ pkg/document/bundle.go | 3 ++- pkg/environment/settings.go | 28 ++++++++++++++++++++++++++++ pkg/environment/settings_test.go | 19 +++++++++++++------ 4 files changed, 45 insertions(+), 7 deletions(-) diff --git a/pkg/config/constants.go b/pkg/config/constants.go index 521bdda34..c4318910c 100644 --- a/pkg/config/constants.go +++ b/pkg/config/constants.go @@ -51,6 +51,8 @@ const ( AirshipDefaultManifestRepoLocation = "https://opendev.org/airship/" + AirshipDefaultManifestRepo AirshipKubeConfig = "kubeconfig" AirshipKubeConfigEnv = "AIRSHIP_KUBECONFIG" + AirshipPluginPath = "kustomize-plugins" + AirshipPluginPathEnv = "AIRSHIP_KUSTOMIZE_PLUGINS" // Modules AirshipDefaultBootstrapImage = "quay.io/airshipit/isogen:latest-debian_stable" diff --git a/pkg/document/bundle.go b/pkg/document/bundle.go index 1cdd01b36..b64e5b4dd 100644 --- a/pkg/document/bundle.go +++ b/pkg/document/bundle.go @@ -22,6 +22,7 @@ import ( "sigs.k8s.io/kustomize/api/resmap" "sigs.k8s.io/kustomize/api/types" + "opendev.org/airship/airshipctl/pkg/environment" utilyaml "opendev.org/airship/airshipctl/pkg/util/yaml" ) @@ -85,7 +86,7 @@ func NewBundle(fSys FileSystem, kustomizePath string) (Bundle, error) { LoadRestrictions: options.LoadRestrictions, DoPrune: false, // Default PluginConfig: &types.PluginConfig{ - AbsPluginHome: kustomizePath, + AbsPluginHome: environment.PluginPath(), PluginRestrictions: types.PluginRestrictionsNone, }, } diff --git a/pkg/environment/settings.go b/pkg/environment/settings.go index f1b0a1dec..f9e1fa894 100644 --- a/pkg/environment/settings.go +++ b/pkg/environment/settings.go @@ -17,6 +17,7 @@ package environment import ( "os" "path/filepath" + "sync" "github.com/spf13/cobra" @@ -35,6 +36,10 @@ type AirshipCTLSettings struct { Config *config.Config } +// A singleton for the kustomize plugin path configuration +var pluginPath string +var pluginPathLock = &sync.Mutex{} + // InitFlags adds the default settings flags to cmd func (a *AirshipCTLSettings) InitFlags(cmd *cobra.Command) { flags := cmd.PersistentFlags() @@ -67,6 +72,7 @@ func (a *AirshipCTLSettings) InitConfig() { a.initAirshipConfigPath() a.initKubeConfigPath() + initPluginPath() err := a.Config.LoadConfig(a.AirshipConfigPath, a.KubeConfigPath) if err != nil { @@ -116,6 +122,28 @@ func (a *AirshipCTLSettings) initKubeConfigPath() { a.KubeConfigPath = filepath.Join(homeDir, config.AirshipConfigDir, config.AirshipKubeConfig) } +// Sets the location to look for kustomize plugins (including airshipctl itself). +func initPluginPath() { + pluginPathLock.Lock() + defer pluginPathLock.Unlock() + + // Check if we got the path via ENVIRONMENT variable + pluginPath = os.Getenv(config.AirshipPluginPathEnv) + if pluginPath != "" { + return + } + + // Otherwise, we'll try putting it in the home directory + homeDir := userHomeDir() + pluginPath = filepath.Join(homeDir, config.AirshipConfigDir, config.AirshipPluginPath) +} + +func PluginPath() string { + pluginPathLock.Lock() + defer pluginPathLock.Unlock() + return pluginPath +} + // 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 diff --git a/pkg/environment/settings_test.go b/pkg/environment/settings_test.go index e8c327962..c5895fc40 100644 --- a/pkg/environment/settings_test.go +++ b/pkg/environment/settings_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package environment +package environment_test import ( "os" @@ -25,12 +25,13 @@ import ( "github.com/stretchr/testify/assert" "opendev.org/airship/airshipctl/pkg/config" + "opendev.org/airship/airshipctl/pkg/environment" "opendev.org/airship/airshipctl/testutil" ) func TestInitFlags(t *testing.T) { // Get the Environment - settings := &AirshipCTLSettings{} + settings := &environment.AirshipCTLSettings{} testCmd := &cobra.Command{} settings.InitFlags(testCmd) assert.True(t, testCmd.HasPersistentFlags()) @@ -43,13 +44,15 @@ func TestInitConfig(t *testing.T) { defer cleanup(t) defer setHome(testDir)() - var testSettings AirshipCTLSettings + var testSettings environment.AirshipCTLSettings expectedAirshipConfig := filepath.Join(testDir, config.AirshipConfigDir, config.AirshipConfig) expectedKubeConfig := filepath.Join(testDir, config.AirshipConfigDir, config.AirshipKubeConfig) + expectedPluginPath := filepath.Join(testDir, config.AirshipConfigDir, config.AirshipPluginPath) testSettings.InitConfig() assert.Equal(t, expectedAirshipConfig, testSettings.AirshipConfigPath) assert.Equal(t, expectedKubeConfig, testSettings.KubeConfigPath) + assert.Equal(t, expectedPluginPath, environment.PluginPath()) }) t.Run("PreferEnvToDefault", func(subTest *testing.T) { @@ -58,18 +61,22 @@ func TestInitConfig(t *testing.T) { defer cleanup(t) defer setHome(testDir)() - var testSettings AirshipCTLSettings + var testSettings environment.AirshipCTLSettings expectedAirshipConfig := filepath.Join(testDir, "airshipEnv") expectedKubeConfig := filepath.Join(testDir, "kubeEnv") + expectedPluginPath := filepath.Join(testDir, "pluginPath") os.Setenv(config.AirshipConfigEnv, expectedAirshipConfig) os.Setenv(config.AirshipKubeConfigEnv, expectedKubeConfig) + os.Setenv(config.AirshipPluginPathEnv, expectedPluginPath) defer os.Unsetenv(config.AirshipConfigEnv) defer os.Unsetenv(config.AirshipKubeConfigEnv) + defer os.Unsetenv(config.AirshipPluginPathEnv) testSettings.InitConfig() assert.Equal(t, expectedAirshipConfig, testSettings.AirshipConfigPath) assert.Equal(t, expectedKubeConfig, testSettings.KubeConfigPath) + assert.Equal(t, expectedPluginPath, environment.PluginPath()) }) t.Run("PreferCmdLineArgToDefault", func(subTest *testing.T) { @@ -81,7 +88,7 @@ func TestInitConfig(t *testing.T) { expectedAirshipConfig := filepath.Join(testDir, "airshipCmdLine") expectedKubeConfig := filepath.Join(testDir, "kubeCmdLine") - testSettings := AirshipCTLSettings{ + testSettings := environment.AirshipCTLSettings{ AirshipConfigPath: expectedAirshipConfig, KubeConfigPath: expectedKubeConfig, } @@ -111,7 +118,7 @@ func TestInitConfig(t *testing.T) { defer os.Unsetenv(config.AirshipConfigEnv) defer os.Unsetenv(config.AirshipKubeConfigEnv) - testSettings := AirshipCTLSettings{ + testSettings := environment.AirshipCTLSettings{ AirshipConfigPath: expectedAirshipConfig, KubeConfigPath: expectedKubeConfig, }