github.com/Axway/agent-sdk@v1.1.101/pkg/cmd/cmd_test.go (about)

     1  package cmd
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"encoding/json"
     7  	"errors"
     8  	"io/ioutil"
     9  	"net/http"
    10  	"net/http/httptest"
    11  	"os"
    12  	"strings"
    13  	"testing"
    14  	"time"
    15  
    16  	"github.com/Axway/agent-sdk/pkg/apic/definitions"
    17  	"github.com/Axway/agent-sdk/pkg/cmd/properties"
    18  
    19  	"github.com/spf13/cobra"
    20  	flag "github.com/spf13/pflag"
    21  	"github.com/spf13/viper"
    22  	"github.com/stretchr/testify/assert"
    23  
    24  	v1 "github.com/Axway/agent-sdk/pkg/apic/apiserver/models/api/v1"
    25  	management "github.com/Axway/agent-sdk/pkg/apic/apiserver/models/management/v1alpha1"
    26  	corecfg "github.com/Axway/agent-sdk/pkg/config"
    27  )
    28  
    29  func getPFlag(cmd AgentRootCmd, flagName string) *flag.Flag {
    30  	return cmd.RootCmd().Flags().Lookup(flagName)
    31  }
    32  
    33  func assertCmdFlag(t *testing.T, cmd AgentRootCmd, flagName, fType, description string) {
    34  	pflag := getPFlag(cmd, flagName)
    35  	assert.NotNil(t, &pflag)
    36  	assert.Equal(t, fType, pflag.Value.Type())
    37  	assert.Equal(t, description, pflag.Usage)
    38  }
    39  
    40  func assertStringCmdFlag(t *testing.T, cmd AgentRootCmd, propertyName, flagName, defaultVal, description string) {
    41  	assertCmdFlag(t, cmd, flagName, "string", description)
    42  	assert.Equal(t, defaultVal, viper.GetString(propertyName))
    43  }
    44  
    45  func assertStringSliceCmdFlag(t *testing.T, cmd AgentRootCmd, propertyName, flagName string, defaultVal []string, description string) {
    46  	assertCmdFlag(t, cmd, flagName, "stringSlice", description)
    47  	assert.Equal(t, defaultVal, viper.GetStringSlice(propertyName))
    48  }
    49  
    50  func assertBooleanCmdFlag(t *testing.T, cmd AgentRootCmd, propertyName, flagName string, defaultVal bool, description string) {
    51  	assertCmdFlag(t, cmd, flagName, "bool", description)
    52  	assert.Equal(t, defaultVal, viper.GetBool(propertyName))
    53  }
    54  
    55  func assertDurationCmdFlag(t *testing.T, cmd AgentRootCmd, propertyName, flagName string, defaultVal time.Duration, description string) {
    56  	assertCmdFlag(t, cmd, flagName, "duration", description)
    57  	assert.Equal(t, defaultVal, viper.GetDuration(propertyName))
    58  }
    59  
    60  type agentConfig struct {
    61  	bProp                 bool
    62  	dProp                 time.Duration
    63  	iProp                 int
    64  	sProp                 string
    65  	sPropExt              string
    66  	ssProp                []string
    67  	agentValidationCalled bool
    68  }
    69  
    70  func (a *agentConfig) ValidateCfg() error {
    71  	a.agentValidationCalled = true
    72  	if a.sProp == "" {
    73  		return errors.New("agentConfig: String prop not set")
    74  	}
    75  	return nil
    76  }
    77  
    78  type configWithValidation struct {
    79  	configValidationCalled bool
    80  	CentralCfg             corecfg.CentralConfig
    81  	AgentCfg               *agentConfig
    82  }
    83  
    84  func (c *configWithValidation) ValidateCfg() error {
    85  	c.configValidationCalled = true
    86  	if c.AgentCfg.sProp == "" {
    87  		return errors.New("configWithValidation: String prop not set")
    88  	}
    89  	return nil
    90  }
    91  
    92  type configWithNoValidation struct {
    93  	configValidationCalled bool
    94  	CentralCfg             corecfg.CentralConfig
    95  	AgentCfg               corecfg.IConfigValidator
    96  }
    97  
    98  func TestRootCmdFlags(t *testing.T) {
    99  	// Discovery Agent
   100  	rootCmd := NewRootCmd("Test", "TestRootCmd", nil, nil, corecfg.DiscoveryAgent)
   101  	assertStringCmdFlag(t, rootCmd, "central.url", "centralUrl", "", "URL of Amplify Central")              // assert to empty "" - set by region settings
   102  	assertStringCmdFlag(t, rootCmd, "central.platformURL", "centralPlatformURL", "", "URL of the platform") // assert to empty "" - set by region settings
   103  	assertStringCmdFlag(t, rootCmd, "central.singleURL", "centralSingleURL", "", "Alternate Connection for Agent if using static IP")
   104  	assertStringCmdFlag(t, rootCmd, "central.organizationID", "centralOrganizationID", "", "Tenant ID for the owner of the environment")
   105  	assertStringCmdFlag(t, rootCmd, "central.team", "centralTeam", "", "Team name for creating catalog")
   106  	assertStringCmdFlag(t, rootCmd, "central.environment", "centralEnvironment", "", "The Environment that the APIs will be associated with in Amplify Central")
   107  	assertStringCmdFlag(t, rootCmd, "central.auth.privateKey", "centralAuthPrivateKey", "/etc/private_key.pem", "Path to the private key for Amplify Central Authentication")
   108  	assertStringCmdFlag(t, rootCmd, "central.auth.publicKey", "centralAuthPublicKey", "/etc/public_key", "Path to the public key for Amplify Central Authentication")
   109  	assertStringCmdFlag(t, rootCmd, "central.auth.word", "centralAuthKeyPassword", "", "Path to the password file required by the private key for Amplify Central Authentication")
   110  	assertStringCmdFlag(t, rootCmd, "central.auth.url", "centralAuthUrl", "", "Amplify Central authentication URL") // assert to empty "" - set by region settings
   111  	assertStringCmdFlag(t, rootCmd, "central.auth.realm", "centralAuthRealm", "Broker", "Amplify Central authentication Realm")
   112  	assertStringCmdFlag(t, rootCmd, "central.auth.clientId", "centralAuthClientId", "", "Client ID for the service account")
   113  	assertDurationCmdFlag(t, rootCmd, "central.auth.timeout", "centralAuthTimeout", 10*time.Second, "Timeout waiting for AxwayID response")
   114  	assertStringSliceCmdFlag(t, rootCmd, "central.ssl.nextProtos", "centralSslNextProtos", []string{}, "List of supported application level protocols, comma separated")
   115  	assertBooleanCmdFlag(t, rootCmd, "central.ssl.insecureSkipVerify", "centralSslInsecureSkipVerify", false, "Controls whether a client verifies the server's certificate chain and host name")
   116  	assertStringSliceCmdFlag(t, rootCmd, "central.ssl.cipherSuites", "centralSslCipherSuites", corecfg.TLSDefaultCipherSuitesStringSlice(), "List of supported cipher suites, comma separated")
   117  	assertStringCmdFlag(t, rootCmd, "central.ssl.minVersion", "centralSslMinVersion", corecfg.TLSDefaultMinVersionString(), "Minimum acceptable SSL/TLS protocol version")
   118  	assertStringCmdFlag(t, rootCmd, "central.ssl.maxVersion", "centralSslMaxVersion", "0", "Maximum acceptable SSL/TLS protocol version")
   119  	assertBooleanCmdFlag(t, rootCmd, "central.migration.cleanInstances", "centralMigrationCleanInstances", false, "Set this to clean all but latest instance, per stage, within an API Service")
   120  
   121  	// Traceability Agent
   122  	rootCmd = NewRootCmd("Test", "TestRootCmd", nil, nil, corecfg.TraceabilityAgent)
   123  	assertStringCmdFlag(t, rootCmd, "central.deployment", "centralDeployment", "", "Amplify Central")       // assert to empty "" - set by region settings
   124  	assertStringCmdFlag(t, rootCmd, "central.url", "centralUrl", "", "URL of Amplify Central")              // assert to empty "" - set by region settings
   125  	assertStringCmdFlag(t, rootCmd, "central.platformURL", "centralPlatformURL", "", "URL of the platform") // assert to empty "" - set by region settings
   126  	assertStringCmdFlag(t, rootCmd, "central.singleURL", "centralSingleURL", "", "Alternate Connection for Agent if using static IP")
   127  	assertStringCmdFlag(t, rootCmd, "central.organizationID", "centralOrganizationID", "", "Tenant ID for the owner of the environment")
   128  	assertStringCmdFlag(t, rootCmd, "central.auth.privateKey", "centralAuthPrivateKey", "/etc/private_key.pem", "Path to the private key for Amplify Central Authentication")
   129  	assertStringCmdFlag(t, rootCmd, "central.auth.publicKey", "centralAuthPublicKey", "/etc/public_key", "Path to the public key for Amplify Central Authentication")
   130  	assertStringCmdFlag(t, rootCmd, "central.auth.keyPassword", "centralAuthKeyPassword", "", "Path to the password file required by the private key for Amplify Central Authentication")
   131  	assertStringCmdFlag(t, rootCmd, "central.auth.url", "centralAuthUrl", "", "Amplify Central authentication URL") // assert to empty "" - set by region settings
   132  	assertStringCmdFlag(t, rootCmd, "central.auth.realm", "centralAuthRealm", "Broker", "Amplify Central authentication Realm")
   133  	assertStringCmdFlag(t, rootCmd, "central.auth.clientId", "centralAuthClientId", "", "Client ID for the service account")
   134  	assertDurationCmdFlag(t, rootCmd, "central.auth.timeout", "centralAuthTimeout", 10*time.Second, "Timeout waiting for AxwayID response")
   135  	assertStringSliceCmdFlag(t, rootCmd, "central.ssl.nextProtos", "centralSslNextProtos", []string{}, "List of supported application level protocols, comma separated")
   136  	assertBooleanCmdFlag(t, rootCmd, "central.ssl.insecureSkipVerify", "centralSslInsecureSkipVerify", false, "Controls whether a client verifies the server's certificate chain and host name")
   137  	assertStringSliceCmdFlag(t, rootCmd, "central.ssl.cipherSuites", "centralSslCipherSuites", corecfg.TLSDefaultCipherSuitesStringSlice(), "List of supported cipher suites, comma separated")
   138  	assertStringCmdFlag(t, rootCmd, "central.ssl.minVersion", "centralSslMinVersion", corecfg.TLSDefaultMinVersionString(), "Minimum acceptable SSL/TLS protocol version")
   139  	assertStringCmdFlag(t, rootCmd, "central.ssl.maxVersion", "centralSslMaxVersion", "0", "Maximum acceptable SSL/TLS protocol version")
   140  
   141  	// Log yaml properties and command flags
   142  	assertStringCmdFlag(t, rootCmd, "log.level", "logLevel", "info", "Log level (trace, debug, info, warn, error)")
   143  	assertStringCmdFlag(t, rootCmd, "log.format", "logFormat", "json", "Log format (json, line)")
   144  	assertStringCmdFlag(t, rootCmd, "log.output", "logOutput", "stdout", "Log output type (stdout, file, both)")
   145  	assertStringCmdFlag(t, rootCmd, "log.file.path", "logFilePath", "logs", "Log file path if output type is file or both")
   146  }
   147  
   148  func TestNewCmd(t *testing.T) {
   149  	rootCmd := &cobra.Command{}
   150  	newCmd := NewCmd(
   151  		rootCmd,
   152  		"test",
   153  		"discovery agent",
   154  		func(centralConfig corecfg.CentralConfig) (interface{}, error) {
   155  			return nil, nil
   156  		},
   157  		func() error {
   158  			return nil
   159  		},
   160  		corecfg.DiscoveryAgent,
   161  	)
   162  
   163  	assert.NotNil(t, newCmd)
   164  
   165  }
   166  
   167  func TestRootCmdConfigFileLoad(t *testing.T) {
   168  
   169  	rootCmd := NewRootCmd("Test", "TestRootCmd", nil, nil, corecfg.DiscoveryAgent)
   170  
   171  	err := rootCmd.Execute()
   172  
   173  	// should be FileNotFound error
   174  	assert.NotNil(t, err, err.Error())
   175  	if err != nil {
   176  		_, ok := err.(viper.ConfigFileNotFoundError)
   177  		assert.True(t, ok, "Incorrect error returned: %s", err.Error())
   178  	}
   179  
   180  	rootCmd = NewRootCmd("test_no_overide", "test_no_overide", nil, nil, corecfg.DiscoveryAgent)
   181  	viper.AddConfigPath("./testdata")
   182  	err = rootCmd.Execute()
   183  
   184  	// should NOT be FileNotFound error
   185  	assert.NotNil(t, err, err.Error())
   186  	if err != nil {
   187  		_, ok := err.(viper.ConfigFileNotFoundError)
   188  		assert.False(t, ok, "Incorrect error returned: %s", err.Error())
   189  	}
   190  
   191  	errBuf := new(bytes.Buffer)
   192  	rootCmd.RootCmd().SetErr(errBuf)
   193  
   194  	assert.Contains(t, "Error central.organizationID not set in config", errBuf.String())
   195  }
   196  
   197  func TestRootCmdConfigDefault(t *testing.T) {
   198  	discoveryInitConfigHandler := func(centralConfig corecfg.CentralConfig) (interface{}, error) {
   199  		assert.Equal(t, "https://apicentral.axway.com", centralConfig.GetURL())
   200  		assert.Equal(t, "222222", centralConfig.GetTeamName())
   201  		assert.Equal(t, "https://login.axway.com/auth/realms/Broker", centralConfig.GetAuthConfig().GetAudience())
   202  		assert.Equal(t, "https://login.axway.com/auth/realms/Broker/protocol/openid-connect/token", centralConfig.GetAuthConfig().GetTokenURL())
   203  		assert.Equal(t, "cccc", centralConfig.GetAuthConfig().GetClientID())
   204  		assert.Equal(t, "Broker", centralConfig.GetAuthConfig().GetRealm())
   205  		assert.Equal(t, "/etc/private_key.pem", centralConfig.GetAuthConfig().GetPrivateKey())
   206  		assert.Equal(t, "/etc/public_key", centralConfig.GetAuthConfig().GetPublicKey())
   207  		assert.Equal(t, "", centralConfig.GetAuthConfig().GetKeyPassword())
   208  		assert.Equal(t, 10*time.Second, centralConfig.GetAuthConfig().GetTimeout())
   209  		return centralConfig, errors.New("Test return error from init config handler")
   210  	}
   211  
   212  	traceabilityInitConfigHandler := func(centralConfig corecfg.CentralConfig) (interface{}, error) {
   213  		assert.Equal(t, "prod", centralConfig.GetAPICDeployment())
   214  		assert.Equal(t, "https://login.axway.com/auth/realms/Broker", centralConfig.GetAuthConfig().GetAudience())
   215  		assert.Equal(t, "https://login.axway.com/auth/realms/Broker/protocol/openid-connect/token", centralConfig.GetAuthConfig().GetTokenURL())
   216  		assert.Equal(t, "cccc", centralConfig.GetAuthConfig().GetClientID())
   217  		assert.Equal(t, "Broker", centralConfig.GetAuthConfig().GetRealm())
   218  		assert.Equal(t, "/etc/private_key.pem", centralConfig.GetAuthConfig().GetPrivateKey())
   219  		assert.Equal(t, "/etc/public_key", centralConfig.GetAuthConfig().GetPublicKey())
   220  		assert.Equal(t, "", centralConfig.GetAuthConfig().GetKeyPassword())
   221  		assert.Equal(t, 10*time.Second, centralConfig.GetAuthConfig().GetTimeout())
   222  		return centralConfig, errors.New("Test return error from init config handler")
   223  	}
   224  
   225  	// Discovery
   226  	rootCmd := NewRootCmd("test_with_non_defaults", "test_with_non_defaults", discoveryInitConfigHandler, nil, corecfg.DiscoveryAgent)
   227  	viper.AddConfigPath("./testdata")
   228  	err := rootCmd.Execute()
   229  
   230  	// should NOT be FileNotFound error
   231  	assert.NotNil(t, err, err.Error())
   232  	if err != nil {
   233  		_, ok := err.(viper.ConfigFileNotFoundError)
   234  		assert.False(t, ok, "Incorrect error returned: %s", err.Error())
   235  	}
   236  
   237  	errBuf := new(bytes.Buffer)
   238  	rootCmd.RootCmd().SetErr(errBuf)
   239  	assert.Contains(t, "Test return error from init config handler, Discovery Agent", errBuf.String())
   240  
   241  	// Traceability
   242  	rootCmd = NewRootCmd("test_with_non_defaults", "test_with_non_defaults", traceabilityInitConfigHandler, nil, corecfg.TraceabilityAgent)
   243  	viper.AddConfigPath("./testdata")
   244  	err = rootCmd.Execute()
   245  
   246  	// should NOT be FileNotFound error
   247  	assert.NotNil(t, err, err.Error())
   248  	if err != nil {
   249  		_, ok := err.(viper.ConfigFileNotFoundError)
   250  		assert.False(t, ok, "Incorrect error returned: %s", err.Error())
   251  	}
   252  
   253  	errBuf = new(bytes.Buffer)
   254  	rootCmd.RootCmd().SetErr(errBuf)
   255  	assert.Contains(t, "Test return error from init config handler, Traceability Agent", errBuf.String())
   256  }
   257  
   258  func TestRootCmdAgentConfigValidation(t *testing.T) {
   259  	s := newTestServer()
   260  	defer s.Close()
   261  
   262  	var rootCmd AgentRootCmd
   263  	var cfg *configWithValidation
   264  	initConfigHandler := func(centralConfig corecfg.CentralConfig) (interface{}, error) {
   265  		cfg = &configWithValidation{
   266  			configValidationCalled: false,
   267  			CentralCfg:             centralConfig,
   268  			AgentCfg: &agentConfig{
   269  				agentValidationCalled: false,
   270  				bProp:                 rootCmd.GetProperties().BoolPropertyValue("agent.bool"),
   271  				dProp:                 rootCmd.GetProperties().DurationPropertyValue("agent.duration"),
   272  				iProp:                 rootCmd.GetProperties().IntPropertyValue("agent.int"),
   273  				sProp:                 rootCmd.GetProperties().StringPropertyValue("agent.string"),
   274  				ssProp:                rootCmd.GetProperties().StringSlicePropertyValue("agent.stringSlice"),
   275  			},
   276  		}
   277  		return cfg, nil
   278  	}
   279  
   280  	os.Setenv("CENTRAL_AUTH_PRIVATEKEY", "../transaction/testdata/private_key.pem")
   281  	os.Setenv("CENTRAL_AUTH_PUBLICKEY", "../transaction/testdata/public_key")
   282  	os.Setenv("CENTRAL_AUTH_CLIENTID", "serviceaccount_1234")
   283  	os.Setenv("CENTRAL_AUTH_URL", s.URL)
   284  	os.Setenv("CENTRAL_URL", s.URL)
   285  	os.Setenv("CENTRAL_SINGLEURL", s.URL)
   286  	os.Setenv("CENTRAL_PLATFORMURL", s.URL)
   287  
   288  	rootCmd = NewRootCmd("test_with_non_defaults", "test_with_non_defaults", initConfigHandler, nil, corecfg.DiscoveryAgent)
   289  	viper.AddConfigPath("./testdata")
   290  
   291  	rootCmd.GetProperties().AddBoolProperty("agent.bool", false, "Agent Bool Property")
   292  	rootCmd.GetProperties().AddDurationProperty("agent.duration", 10*time.Second, "Agent Duration Property", properties.WithLowerLimit(10*time.Second))
   293  	rootCmd.GetProperties().AddIntProperty("agent.int", 0, "Agent Int Property")
   294  	rootCmd.GetProperties().AddStringProperty("agent.string", "", "Agent String Property")
   295  	rootCmd.GetProperties().AddStringSliceProperty("agent.stringSlice", nil, "Agent String Slice Property")
   296  
   297  	err := rootCmd.Execute()
   298  
   299  	// should NOT be FileNotFound error
   300  	assert.NotNil(t, err, err.Error())
   301  	if err != nil {
   302  		_, ok := err.(viper.ConfigFileNotFoundError)
   303  		assert.False(t, ok, "Incorrect error returned: %s", err.Error())
   304  	}
   305  
   306  	errBuf := new(bytes.Buffer)
   307  	rootCmd.RootCmd().SetErr(errBuf)
   308  	assert.Contains(t, "configWithValidation: String prop not set", errBuf.String())
   309  	assert.Equal(t, true, cfg.configValidationCalled)
   310  	assert.Equal(t, false, cfg.AgentCfg.agentValidationCalled)
   311  }
   312  
   313  func TestRootCmdAgentConfigChildValidation(t *testing.T) {
   314  	s := newTestServer()
   315  	defer s.Close()
   316  
   317  	var rootCmd AgentRootCmd
   318  	var cfg *configWithNoValidation
   319  	initConfigHandler := func(centralConfig corecfg.CentralConfig) (interface{}, error) {
   320  		cfg = &configWithNoValidation{
   321  			configValidationCalled: false,
   322  			CentralCfg:             centralConfig,
   323  			AgentCfg: &agentConfig{
   324  				agentValidationCalled: false,
   325  				bProp:                 rootCmd.GetProperties().BoolPropertyValue("agent.bool"),
   326  				dProp:                 rootCmd.GetProperties().DurationPropertyValue("agent.duration"),
   327  				iProp:                 rootCmd.GetProperties().IntPropertyValue("agent.int"),
   328  				sProp:                 rootCmd.GetProperties().StringPropertyValue("agent.string"),
   329  				ssProp:                rootCmd.GetProperties().StringSlicePropertyValue("agent.stringSlice"),
   330  			},
   331  		}
   332  		return cfg, nil
   333  	}
   334  
   335  	os.Setenv("CENTRAL_AUTH_PRIVATEKEY", "../transaction/testdata/private_key.pem")
   336  	os.Setenv("CENTRAL_AUTH_PUBLICKEY", "../transaction/testdata/public_key")
   337  	os.Setenv("CENTRAL_AUTH_CLIENTID", "serviceaccount_1234")
   338  	os.Setenv("CENTRAL_AUTH_URL", s.URL)
   339  	os.Setenv("CENTRAL_URL", s.URL)
   340  	os.Setenv("CENTRAL_SINGLEURL", s.URL)
   341  
   342  	rootCmd = NewRootCmd("test_with_non_defaults", "test_with_non_defaults", initConfigHandler, nil, corecfg.DiscoveryAgent)
   343  	viper.AddConfigPath("./testdata")
   344  
   345  	rootCmd.GetProperties().AddBoolProperty("agent.bool", false, "Agent Bool Property")
   346  	rootCmd.GetProperties().AddDurationProperty("agent.duration", 10*time.Second, "Agent Duration Property", properties.WithLowerLimit(10*time.Second))
   347  	rootCmd.GetProperties().AddIntProperty("agent.int", 0, "Agent Int Property")
   348  	rootCmd.GetProperties().AddStringProperty("agent.string", "", "Agent String Property")
   349  	rootCmd.GetProperties().AddStringSliceProperty("agent.stringSlice", nil, "Agent String Slice Property")
   350  
   351  	err := rootCmd.Execute()
   352  
   353  	// should NOT be FileNotFound error
   354  	assert.NotNil(t, err, err.Error())
   355  	if err != nil {
   356  		_, ok := err.(viper.ConfigFileNotFoundError)
   357  		assert.False(t, ok, "Incorrect error returned: %s", err.Error())
   358  	}
   359  
   360  	errBuf := new(bytes.Buffer)
   361  	rootCmd.RootCmd().SetErr(errBuf)
   362  	assert.Contains(t, "agentConfig: String prop not set", errBuf.String())
   363  	assert.Equal(t, false, cfg.configValidationCalled)
   364  	assert.Equal(t, true, cfg.AgentCfg.(*agentConfig).agentValidationCalled)
   365  }
   366  
   367  func TestRootCmdHandlersWithError(t *testing.T) {
   368  	s := newTestServer()
   369  	defer s.Close()
   370  
   371  	initConfigHandler := func(centralConfig corecfg.CentralConfig) (interface{}, error) {
   372  		return centralConfig, nil
   373  	}
   374  	cmdHandler := func() error {
   375  		return nil
   376  	}
   377  
   378  	os.Setenv("CENTRAL_AUTH_PRIVATEKEY", "../transaction/testdata/private_key.pem")
   379  	os.Setenv("CENTRAL_AUTH_PUBLICKEY", "../transaction/testdata/public_key")
   380  	os.Setenv("CENTRAL_AUTH_CLIENTID", "serviceaccount_1234")
   381  	os.Setenv("CENTRAL_AUTH_URL", s.URL)
   382  	os.Setenv("CENTRAL_URL", s.URL)
   383  	os.Setenv("CENTRAL_SINGLEURL", s.URL)
   384  
   385  	rootCmd := NewRootCmd("Test", "TestRootCmd", initConfigHandler, cmdHandler, corecfg.DiscoveryAgent)
   386  	err := rootCmd.Execute()
   387  
   388  	// should be FileNotFound error
   389  	assert.NotNil(t, err, err.Error())
   390  	if err != nil {
   391  		_, ok := err.(viper.ConfigFileNotFoundError)
   392  		assert.True(t, ok, "Incorrect error returned: %s", err.Error())
   393  	}
   394  
   395  	rootCmd = NewRootCmd("test_no_overide", "test_no_overide", initConfigHandler, cmdHandler, corecfg.DiscoveryAgent)
   396  	viper.AddConfigPath("./testdata")
   397  	err = rootCmd.Execute()
   398  
   399  	// should NOT be FileNotFound error
   400  	assert.NotNil(t, err, err.Error())
   401  	if err != nil {
   402  		_, ok := err.(viper.ConfigFileNotFoundError)
   403  		assert.False(t, ok, "Incorrect error returned: %s", err.Error())
   404  	}
   405  }
   406  
   407  func TestRootCmdHandlers(t *testing.T) {
   408  	s := newTestServer()
   409  	defer s.Close()
   410  
   411  	var rootCmd AgentRootCmd
   412  	var cfg *configWithNoValidation
   413  	initConfigHandler := func(centralConfig corecfg.CentralConfig) (interface{}, error) {
   414  		cfg = &configWithNoValidation{
   415  			configValidationCalled: false,
   416  			CentralCfg:             centralConfig,
   417  			AgentCfg: &agentConfig{
   418  				agentValidationCalled: false,
   419  				bProp:                 rootCmd.GetProperties().BoolPropertyValue("agent.bool"),
   420  				dProp:                 rootCmd.GetProperties().DurationPropertyValue("agent.duration"),
   421  				iProp:                 rootCmd.GetProperties().IntPropertyValue("agent.int"),
   422  				sProp:                 rootCmd.GetProperties().StringPropertyValue("agent.string"),
   423  				ssProp:                rootCmd.GetProperties().StringSlicePropertyValue("agent.stringSlice"),
   424  			},
   425  		}
   426  		return cfg, nil
   427  	}
   428  	var cmdHandlerInvoked bool
   429  	cmdHandler := func() error {
   430  		cmdHandlerInvoked = true
   431  		return nil
   432  	}
   433  
   434  	os.Setenv("CENTRAL_AUTH_PRIVATEKEY", "../transaction/testdata/private_key.pem")
   435  	os.Setenv("CENTRAL_AUTH_PUBLICKEY", "../transaction/testdata/public_key")
   436  	os.Setenv("CENTRAL_AUTH_CLIENTID", "serviceaccount_1234")
   437  	os.Setenv("CENTRAL_AUTH_URL", s.URL)
   438  	os.Setenv("CENTRAL_URL", s.URL)
   439  	os.Setenv("CENTRAL_SINGLEURL", s.URL)
   440  
   441  	rootCmd = NewRootCmd("test_with_agent_cfg", "test_with_agent_cfg", initConfigHandler, cmdHandler, corecfg.DiscoveryAgent)
   442  	viper.AddConfigPath("./testdata")
   443  
   444  	rootCmd.GetProperties().AddBoolProperty("agent.bool", false, "Agent Bool Property")
   445  	rootCmd.GetProperties().AddDurationProperty("agent.duration", 10*time.Second, "Agent Duration Property", properties.WithLowerLimit(10*time.Second))
   446  	rootCmd.GetProperties().AddIntProperty("agent.int", 0, "Agent Int Property")
   447  	rootCmd.GetProperties().AddStringProperty("agent.string", "", "Agent String Property")
   448  	rootCmd.GetProperties().AddStringSliceProperty("agent.stringSlice", nil, "Agent String Slice Property")
   449  
   450  	err := rootCmd.Execute()
   451  
   452  	// should NOT be FileNotFound error
   453  	assert.Nil(t, err, "An unexpected error returned")
   454  	if err != nil {
   455  		_, ok := err.(viper.ConfigFileNotFoundError)
   456  		assert.False(t, ok, "Incorrect error returned: %s", err.Error())
   457  	}
   458  
   459  	errBuf := new(bytes.Buffer)
   460  	rootCmd.RootCmd().SetErr(errBuf)
   461  	assert.Empty(t, "", errBuf.String())
   462  	assert.Equal(t, false, cfg.configValidationCalled)
   463  	agentCfg := cfg.AgentCfg.(*agentConfig)
   464  	assert.Equal(t, true, agentCfg.agentValidationCalled)
   465  	assert.Equal(t, true, agentCfg.bProp)
   466  	assert.Equal(t, 30*time.Second, agentCfg.dProp)
   467  	assert.Equal(t, 555, agentCfg.iProp)
   468  	assert.Equal(t, true, cmdHandlerInvoked)
   469  
   470  }
   471  
   472  func TestRootCommandLoggerStdout(t *testing.T) {
   473  	s := newTestServer()
   474  	defer s.Close()
   475  
   476  	initConfigHandler := noOpInitConfigHandler
   477  	cmdHandler := noOpCmdHandler
   478  
   479  	os.Setenv("CENTRAL_AUTH_PRIVATEKEY", "../transaction/testdata/private_key.pem")
   480  	os.Setenv("CENTRAL_AUTH_PUBLICKEY", "../transaction/testdata/public_key")
   481  	os.Setenv("CENTRAL_AUTH_CLIENTID", "serviceaccount_1234")
   482  	os.Setenv("CENTRAL_AUTH_URL", s.URL)
   483  	os.Setenv("CENTRAL_URL", s.URL)
   484  	os.Setenv("CENTRAL_SINGLEURL", s.URL)
   485  
   486  	rootCmd := NewRootCmd("test_with_non_defaults", "test_with_non_defaults", initConfigHandler, cmdHandler, corecfg.DiscoveryAgent)
   487  	viper.AddConfigPath("./testdata")
   488  
   489  	rescueStdout := os.Stdout
   490  	r, w, _ := os.Pipe()
   491  	os.Stdout = w
   492  
   493  	err := rootCmd.Execute()
   494  
   495  	// should NOT be FileNotFound error
   496  	assert.Nil(t, err, "An unexpected error was received")
   497  	if err != nil {
   498  		_, ok := err.(viper.ConfigFileNotFoundError)
   499  		assert.False(t, ok, "Incorrect error returned: %s", err.Error())
   500  	}
   501  
   502  	w.Close()
   503  
   504  	var logData map[string]string
   505  	scanner := bufio.NewScanner(r)
   506  
   507  	level := "info"
   508  	msg := "Starting test_with_non_defaults version -, Amplify Agents SDK version "
   509  
   510  	for scanner.Scan() {
   511  		out := scanner.Text()
   512  		err := json.Unmarshal([]byte(out), &logData)
   513  		assert.Nil(t, err, "failed to unmarshal log data")
   514  		if logData["level"] == level && logData["message"] == msg {
   515  			break
   516  		}
   517  	}
   518  
   519  	os.Stdout = rescueStdout
   520  
   521  	assert.Equal(t, level, logData["level"])
   522  	assert.Equal(t, msg, logData["message"])
   523  }
   524  
   525  func TestRootCommandLoggerFile(t *testing.T) {
   526  	initConfigHandler := noOpInitConfigHandler
   527  	cmdHandler := noOpCmdHandler
   528  
   529  	s := newTestServer()
   530  	defer s.Close()
   531  
   532  	os.Setenv("CENTRAL_AUTH_PRIVATEKEY", "../transaction/testdata/private_key.pem")
   533  	os.Setenv("CENTRAL_AUTH_PUBLICKEY", "../transaction/testdata/public_key")
   534  	os.Setenv("CENTRAL_AUTH_CLIENTID", "serviceaccount_1234")
   535  	os.Setenv("CENTRAL_AUTH_URL", s.URL)
   536  	os.Setenv("CENTRAL_URL", s.URL)
   537  	os.Setenv("CENTRAL_SINGLEURL", s.URL)
   538  
   539  	rootCmd := NewRootCmd("test_with_non_defaults", "test_with_non_defaults", initConfigHandler, cmdHandler, corecfg.DiscoveryAgent)
   540  	viper.AddConfigPath("./testdata")
   541  	rootCmd.RootCmd().SetArgs([]string{
   542  		"--logOutput",
   543  		"file",
   544  		"--logFilePath",
   545  		"./tmplogs",
   546  		"--logFileName",
   547  		"test_with_non_defaults.log",
   548  	},
   549  	)
   550  	// Make sure to delete file
   551  	os.RemoveAll("./tmplogs/test_with_non_defaults.log")
   552  
   553  	fExecute := func() {
   554  		rootCmd.Execute()
   555  	}
   556  	assert.NotPanics(t, fExecute)
   557  
   558  	dat, err := ioutil.ReadFile("./tmplogs/test_with_non_defaults.log")
   559  	assert.Nil(t, err, "failed to read file")
   560  	scanner := bufio.NewScanner(bytes.NewReader(dat))
   561  
   562  	var logData map[string]string
   563  	level := "info"
   564  	msg := "Starting test_with_non_defaults version -, Amplify Agents SDK version "
   565  
   566  	for scanner.Scan() {
   567  		out := scanner.Text()
   568  		err := json.Unmarshal([]byte(out), &logData)
   569  		assert.Nil(t, err, "failed to unmarshal log data")
   570  		if logData["level"] == level && logData["message"] == msg {
   571  			break
   572  		}
   573  	}
   574  
   575  	assert.Equal(t, level, logData["level"])
   576  	assert.Equal(t, msg, logData["message"])
   577  }
   578  
   579  func TestRootCommandLoggerStdoutAndFile(t *testing.T) {
   580  	initConfigHandler := noOpInitConfigHandler
   581  	cmdHandler := noOpCmdHandler
   582  
   583  	s := newTestServer()
   584  	defer s.Close()
   585  
   586  	os.Setenv("CENTRAL_AUTH_PRIVATEKEY", "../transaction/testdata/private_key.pem")
   587  	os.Setenv("CENTRAL_AUTH_PUBLICKEY", "../transaction/testdata/public_key")
   588  	os.Setenv("CENTRAL_AUTH_CLIENTID", "serviceaccount_1234")
   589  	os.Setenv("CENTRAL_AUTH_URL", s.URL)
   590  	os.Setenv("CENTRAL_URL", s.URL)
   591  	os.Setenv("CENTRAL_SINGLEURL", s.URL)
   592  
   593  	rootCmd := NewRootCmd("test_with_non_defaults", "test_with_non_defaults", initConfigHandler, cmdHandler, corecfg.DiscoveryAgent)
   594  	viper.AddConfigPath("./testdata")
   595  	rootCmd.RootCmd().SetArgs([]string{
   596  		"--logOutput",
   597  		"both",
   598  		"--logFilePath",
   599  		"./tmplogs",
   600  		"--logFileName",
   601  		"test_with_non_defaults.log",
   602  	},
   603  	)
   604  	rescueStdout := os.Stdout
   605  	r, w, _ := os.Pipe()
   606  	os.Stdout = w
   607  
   608  	fExecute := func() {
   609  		rootCmd.Execute()
   610  	}
   611  	// Make sure to delete file
   612  	os.Remove("./tmplogs/test_with_non_defaults.log")
   613  	assert.NotPanics(t, fExecute)
   614  	w.Close()
   615  	out, _ := ioutil.ReadAll(r)
   616  	os.Stdout = rescueStdout
   617  	var logData map[string]string
   618  	json.Unmarshal([]byte(out), &logData)
   619  
   620  	dat, err := ioutil.ReadFile("./tmplogs/test_with_non_defaults.log")
   621  	assert.Nil(t, err)
   622  	assert.Equal(t, out, dat)
   623  }
   624  
   625  func TestRootCmdHandlerWithSecretRefProperties(t *testing.T) {
   626  	secret := management.Secret{
   627  		ResourceMeta: v1.ResourceMeta{Name: "agentSecret"},
   628  		Spec: management.SecretSpec{
   629  			Data: map[string]string{
   630  				"secretKey":               "secretValue",
   631  				"cachedSecretKey":         "cachedSecretValue",
   632  				"keyElement1.keyElement2": "secretValue2",
   633  			},
   634  		},
   635  	}
   636  
   637  	teams := []definitions.PlatformTeam{
   638  		{
   639  			ID:      "123",
   640  			Name:    "name",
   641  			Default: true,
   642  		},
   643  	}
   644  
   645  	environmentRes := &management.Environment{
   646  		ResourceMeta: v1.ResourceMeta{
   647  			Metadata: v1.Metadata{ID: "123"},
   648  			Name:     "test",
   649  			Title:    "test",
   650  		},
   651  	}
   652  
   653  	s := httptest.NewServer(http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
   654  		if strings.Contains(req.RequestURI, "/auth") {
   655  			token := "{\"access_token\":\"somevalue\",\"expires_in\": 12235677}"
   656  			resp.Write([]byte(token))
   657  			return
   658  		}
   659  
   660  		if strings.Contains(req.RequestURI, "/apis/management/v1alpha1/environments/test/secrets/agentSecret") {
   661  			buf, _ := json.Marshal(secret)
   662  			resp.Write(buf)
   663  			return
   664  		}
   665  
   666  		if strings.Contains(req.RequestURI, "/apis/management/v1alpha1/environments/test") {
   667  			buf, _ := json.Marshal(environmentRes)
   668  			resp.Write(buf)
   669  			return
   670  		}
   671  
   672  		if strings.Contains(req.RequestURI, "/api/v1/platformTeams") {
   673  			buf, _ := json.Marshal(teams)
   674  			resp.Write(buf)
   675  			return
   676  		}
   677  	}))
   678  	defer s.Close()
   679  
   680  	var rootCmd AgentRootCmd
   681  	var cfg *configWithNoValidation
   682  	initConfigHandler := func(centralConfig corecfg.CentralConfig) (interface{}, error) {
   683  		cfg = &configWithNoValidation{
   684  			configValidationCalled: false,
   685  			CentralCfg:             centralConfig,
   686  			AgentCfg: &agentConfig{
   687  				agentValidationCalled: false,
   688  				sProp:                 rootCmd.GetProperties().StringPropertyValue("agent.string"),
   689  				sPropExt:              rootCmd.GetProperties().StringPropertyValue("agent.stringExt"),
   690  			},
   691  		}
   692  		return cfg, nil
   693  	}
   694  	var cmdHandlerInvoked bool
   695  	cmdHandler := func() error {
   696  		cmdHandlerInvoked = true
   697  		return nil
   698  	}
   699  
   700  	os.Setenv("CENTRAL_AUTH_URL", s.URL+"/auth")
   701  	os.Setenv("CENTRAL_AUTH_CLIENTID", "serviceaccount_1234")
   702  	os.Setenv("CENTRAL_AUTH_PRIVATEKEY", "../transaction/testdata/private_key.pem")
   703  	os.Setenv("CENTRAL_AUTH_PUBLICKEY", "../transaction/testdata/public_key")
   704  	os.Setenv("CENTRAL_URL", s.URL)
   705  	os.Setenv("CENTRAL_SINGLEURL", s.URL)
   706  	os.Setenv("CENTRAL_ENVIRONMENT", "test")
   707  
   708  	rootCmd = NewRootCmd("test_with_agent_cfg", "test_with_agent_cfg", initConfigHandler, cmdHandler, corecfg.DiscoveryAgent)
   709  	viper.AddConfigPath("./testdata")
   710  
   711  	rootCmd.GetProperties().AddStringProperty("agent.string", "", "Agent String Property")
   712  	rootCmd.GetProperties().AddStringSliceProperty("agent.stringSlice", nil, "Agent String Slice Property")
   713  
   714  	// Case 1 : No secret resolution - use the value in config
   715  	os.Setenv("AGENT_STRING", "testValue")
   716  	os.Setenv("AGENT_STRINGEXT", "anotherTestValue")
   717  	err := rootCmd.Execute()
   718  	assert.Nil(t, err, "An unexpected error returned")
   719  	agentCfg := cfg.AgentCfg.(*agentConfig)
   720  	assert.Equal(t, true, agentCfg.agentValidationCalled)
   721  	assert.Equal(t, "testValue", agentCfg.sProp)
   722  	assert.Equal(t, "anotherTestValue", agentCfg.sPropExt)
   723  	assert.Equal(t, true, cmdHandlerInvoked)
   724  
   725  	// Case 2 : Invalid secret resolution - secret ref with invalid secret name,
   726  	// config value will be set to empty string
   727  	cfg = nil
   728  	agentCfg.agentValidationCalled = false
   729  	cmdHandlerInvoked = false
   730  	os.Setenv("AGENT_STRING", "@Secret.invalidSecret.secretKey")
   731  	os.Setenv("AGENT_STRINGEXT", "@Secret.invalidSecret.cachedSecretKey")
   732  	err = rootCmd.Execute()
   733  	assert.NotNil(t, err)
   734  	assert.Equal(t, "agentConfig: String prop not set", err.Error())
   735  	agentCfg = cfg.AgentCfg.(*agentConfig)
   736  	assert.Equal(t, true, agentCfg.agentValidationCalled)
   737  	assert.Equal(t, "", agentCfg.sProp)
   738  	assert.Equal(t, "", agentCfg.sPropExt)
   739  	assert.Equal(t, false, cmdHandlerInvoked)
   740  
   741  	// Case 3 : Invalid secret resolution - secret ref with invalid key in secret
   742  	// config value will be set to empty string
   743  	cfg = nil
   744  	agentCfg.agentValidationCalled = false
   745  	cmdHandlerInvoked = false
   746  
   747  	os.Setenv("AGENT_STRING", "@Secret.agentSecret.invalidKey")
   748  	os.Setenv("AGENT_STRINGEXT", "@Secret.invalidSecret.cachedSecretKey")
   749  	err = rootCmd.Execute()
   750  	assert.NotNil(t, err)
   751  	assert.Equal(t, "agentConfig: String prop not set", err.Error())
   752  	agentCfg = cfg.AgentCfg.(*agentConfig)
   753  	assert.Equal(t, true, agentCfg.agentValidationCalled)
   754  	assert.Equal(t, "", agentCfg.sProp)
   755  	assert.Equal(t, "", agentCfg.sPropExt)
   756  	assert.Equal(t, false, cmdHandlerInvoked)
   757  
   758  	// Case 4 : Successful secret resolution - use value in secret key
   759  	// config value will be set to specified key in secret
   760  	cfg = nil
   761  	agentCfg.agentValidationCalled = false
   762  	cmdHandlerInvoked = false
   763  
   764  	os.Setenv("AGENT_STRING", "@Secret.agentSecret.secretKey")
   765  	os.Setenv("AGENT_STRINGEXT", "@Secret.agentSecret.cachedSecretKey")
   766  	err = rootCmd.Execute()
   767  	assert.Nil(t, err)
   768  	agentCfg = cfg.AgentCfg.(*agentConfig)
   769  	assert.Equal(t, true, agentCfg.agentValidationCalled)
   770  	assert.Equal(t, "secretValue", agentCfg.sProp)
   771  	assert.Equal(t, "cachedSecretValue", agentCfg.sPropExt)
   772  	assert.Equal(t, true, cmdHandlerInvoked)
   773  
   774  	// Case 5 : Successful secret resolution with key separate with dots(.) - use value in secret key
   775  	// config value will be set to specified key in secret
   776  	cfg = nil
   777  	agentCfg.agentValidationCalled = false
   778  	cmdHandlerInvoked = false
   779  
   780  	os.Setenv("AGENT_STRING", "@Secret.agentSecret.keyElement1.keyElement2")
   781  	err = rootCmd.Execute()
   782  	assert.Nil(t, err)
   783  	agentCfg = cfg.AgentCfg.(*agentConfig)
   784  	assert.Equal(t, true, agentCfg.agentValidationCalled)
   785  	assert.Equal(t, "secretValue2", agentCfg.sProp)
   786  	assert.Equal(t, true, cmdHandlerInvoked)
   787  }
   788  
   789  func noOpInitConfigHandler(centralConfig corecfg.CentralConfig) (interface{}, error) {
   790  	return centralConfig, nil
   791  }
   792  
   793  func noOpCmdHandler() error {
   794  	return nil
   795  }
   796  
   797  func newTestServer() *httptest.Server {
   798  	teams := []definitions.PlatformTeam{
   799  		{
   800  			ID:      "123",
   801  			Name:    "name",
   802  			Default: true,
   803  		},
   804  	}
   805  
   806  	environmentRes := &management.Environment{
   807  		ResourceMeta: v1.ResourceMeta{
   808  			Metadata: v1.Metadata{ID: "123"},
   809  			Name:     "test",
   810  			Title:    "test",
   811  		},
   812  	}
   813  
   814  	secret := management.Secret{
   815  		ResourceMeta: v1.ResourceMeta{Name: "agentSecret"},
   816  		Spec: management.SecretSpec{
   817  			Data: map[string]string{
   818  				"secretKey":               "secretValue",
   819  				"cachedSecretKey":         "cachedSecretValue",
   820  				"keyElement1.keyElement2": "secretValue2",
   821  			},
   822  		},
   823  	}
   824  
   825  	s := httptest.NewServer(http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
   826  		if strings.Contains(req.RequestURI, "/auth") {
   827  			token := "{\"access_token\":\"somevalue\",\"expires_in\": 12235677}"
   828  			resp.Write([]byte(token))
   829  			return
   830  		}
   831  
   832  		if strings.Contains(req.RequestURI, "/apis/management/v1alpha1/environments/test/secrets/agentSecret") {
   833  			buf, _ := json.Marshal(secret)
   834  			resp.Write(buf)
   835  		}
   836  
   837  		if strings.Contains(req.RequestURI, "/realms/Broker/protocol/openid-connect/token") {
   838  			token := "{\"access_token\":\"somevalue\",\"expires_in\": 12235677}"
   839  			resp.Write([]byte(token))
   840  			return
   841  		}
   842  
   843  		if strings.Contains(req.RequestURI, "/apis/management/v1alpha1/environments/test/apiservices") {
   844  			resp.Write([]byte("response"))
   845  			return
   846  		}
   847  
   848  		if strings.Contains(req.RequestURI, "/apis/management/v1alpha1/environments/environment") {
   849  			buf, _ := json.Marshal(environmentRes)
   850  			resp.Write(buf)
   851  			return
   852  		}
   853  
   854  		if strings.Contains(req.RequestURI, "/api/v1/platformTeams") {
   855  			buf, _ := json.Marshal(teams)
   856  			resp.Write(buf)
   857  			return
   858  		}
   859  	}))
   860  
   861  	return s
   862  }
   863  
   864  func TestLowerAndUpperLimitDurations(t *testing.T) {
   865  	testCases := []struct {
   866  		name             string
   867  		durationProperty string
   868  		defaultDuration  time.Duration
   869  		description      string
   870  		lowerLimit       time.Duration
   871  		upperLimit       time.Duration
   872  		expectPanic      bool
   873  	}{
   874  		{
   875  			// valid range
   876  			name:             "Agent Duration Property - valid range",
   877  			durationProperty: "agent.duration",
   878  			defaultDuration:  25 * time.Second,
   879  			description:      "Agent Duration Property - valid range",
   880  			lowerLimit:       20 * time.Second,
   881  			upperLimit:       40 * time.Second,
   882  		},
   883  		{
   884  			// lower limit is invalid
   885  			/*
   886  				{"level":"warning","message":"value 30s is lower than the supported lower limit (40s) for configuration agentDuration","time":"2022-07-26T14:42:54-07:00"}
   887  				{"level":"warning","message":"config agentDuration has been set to the the default value of 25s.","time":"2022-07-26T14:42:54-07:00"}
   888  			*/
   889  			name:             "Agent Duration Property - invalid lower limit",
   890  			durationProperty: "agent.duration",
   891  			defaultDuration:  40 * time.Second,
   892  			description:      "Agent Duration Property - invalid lower limit",
   893  			lowerLimit:       40 * time.Second,
   894  			upperLimit:       50 * time.Second,
   895  		},
   896  		{
   897  			// default lower than lower limit
   898  			name:             "Agent Duration Property - invalid upper limit",
   899  			durationProperty: "agent.duration",
   900  			defaultDuration:  5 * time.Second,
   901  			description:      "Agent Duration Property - invalid upper limit",
   902  			lowerLimit:       10 * time.Second,
   903  			upperLimit:       20 * time.Second,
   904  			expectPanic:      true,
   905  		},
   906  		{
   907  			// upper limit is invalid
   908  			/*
   909  				{"level":"warning","message":"value 30s is higher than the supported higher limit (20s) for configuration agentDuration","time":"2022-07-26T14:42:54-07:00"}
   910  				{"level":"warning","message":"config agentDuration has been set to the the default value of 30s.","time":"2022-07-26T14:42:54-07:00"}
   911  			*/
   912  			name:             "Agent Duration Property - invalid upper limit",
   913  			durationProperty: "agent.duration",
   914  			defaultDuration:  20 * time.Second,
   915  			description:      "Agent Duration Property - invalid upper limit",
   916  			lowerLimit:       10 * time.Second,
   917  			upperLimit:       20 * time.Second,
   918  		},
   919  		{
   920  			// default higher than upper limit
   921  			name:             "Agent Duration Property - invalid upper limit",
   922  			durationProperty: "agent.duration",
   923  			defaultDuration:  40 * time.Second,
   924  			description:      "Agent Duration Property - invalid upper limit",
   925  			lowerLimit:       10 * time.Second,
   926  			upperLimit:       20 * time.Second,
   927  			expectPanic:      true,
   928  		},
   929  		{
   930  			// upper lower than lower limit
   931  			name:             "Agent Duration Property - invalid upper limit",
   932  			durationProperty: "agent.duration",
   933  			defaultDuration:  15 * time.Second,
   934  			description:      "Agent Duration Property - invalid upper limit",
   935  			lowerLimit:       10 * time.Second,
   936  			upperLimit:       5 * time.Second,
   937  			expectPanic:      true,
   938  		},
   939  	}
   940  
   941  	for _, test := range testCases {
   942  		t.Run(test.name, func(t *testing.T) {
   943  			s := newTestServer()
   944  			defer s.Close()
   945  
   946  			var rootCmd AgentRootCmd
   947  			var cfg *configWithValidation
   948  			initConfigHandler := func(centralConfig corecfg.CentralConfig) (interface{}, error) {
   949  				cfg = &configWithValidation{
   950  					configValidationCalled: false,
   951  					CentralCfg:             centralConfig,
   952  					AgentCfg: &agentConfig{
   953  						agentValidationCalled: false,
   954  						dProp:                 rootCmd.GetProperties().DurationPropertyValue("agent.duration"),
   955  					},
   956  				}
   957  				return cfg, nil
   958  			}
   959  
   960  			os.Setenv("CENTRAL_AUTH_PRIVATEKEY", "../transaction/testdata/private_key.pem")
   961  			os.Setenv("CENTRAL_AUTH_PUBLICKEY", "../transaction/testdata/public_key")
   962  			os.Setenv("CENTRAL_AUTH_CLIENTID", "serviceaccount_1234")
   963  			os.Setenv("CENTRAL_AUTH_URL", s.URL)
   964  			os.Setenv("CENTRAL_URL", s.URL)
   965  			os.Setenv("CENTRAL_SINGLEURL", s.URL)
   966  			os.Setenv("AGENT_DURATION", "30s")
   967  
   968  			rootCmd = NewRootCmd("test_with_non_defaults", "test_with_non_defaults", initConfigHandler, nil, corecfg.DiscoveryAgent)
   969  			viper.AddConfigPath("./testdata")
   970  			fExecute := func() {
   971  				rootCmd.GetProperties().AddDurationProperty(test.durationProperty, test.defaultDuration, test.description, properties.WithLowerLimit(test.lowerLimit), properties.WithUpperLimit(test.upperLimit))
   972  			}
   973  			if test.expectPanic {
   974  				assert.Panics(t, fExecute)
   975  			} else {
   976  				assert.NotPanics(t, fExecute)
   977  				_ = rootCmd.Execute()
   978  			}
   979  		})
   980  	}
   981  }