diff --git a/cni/client/client.go b/cni/client/client.go index 745f8dde48..d78aa8790b 100644 --- a/cni/client/client.go +++ b/cni/client/client.go @@ -9,14 +9,11 @@ import ( "github.com/Azure/azure-container-networking/cni" "github.com/Azure/azure-container-networking/cni/api" "github.com/Azure/azure-container-networking/log" + "github.com/Azure/azure-container-networking/platform" semver "github.com/hashicorp/go-version" utilexec "k8s.io/utils/exec" ) -const ( - azureVnetExecutable = "/opt/cni/bin/azure-vnet" -) - type Client interface { GetEndpointState() (*api.AzureCNIState, error) } @@ -32,7 +29,7 @@ func New(exec utilexec.Interface) *client { } func (c *client) GetEndpointState() (*api.AzureCNIState, error) { - cmd := c.exec.Command(azureVnetExecutable) + cmd := c.exec.Command(platform.CNIBinaryPath) envs := os.Environ() cmdenv := fmt.Sprintf("%s=%s", cni.Cmd, cni.CmdGetEndpointsState) @@ -54,7 +51,7 @@ func (c *client) GetEndpointState() (*api.AzureCNIState, error) { } func (c *client) GetVersion() (*semver.Version, error) { - cmd := c.exec.Command(azureVnetExecutable, "-v") + cmd := c.exec.Command(platform.CNIBinaryPath, "-v") output, err := cmd.CombinedOutput() if err != nil { diff --git a/cns/cnireconciler/statefile.go b/cns/cnireconciler/statefile.go index 5dcc128a46..58649b1b57 100644 --- a/cns/cnireconciler/statefile.go +++ b/cns/cnireconciler/statefile.go @@ -6,6 +6,7 @@ import ( "os" "github.com/Azure/azure-container-networking/cns/logger" + "github.com/Azure/azure-container-networking/platform" ) // WriteObjectToCNIStatefile checks for a file at the CNI statefile path, @@ -18,7 +19,7 @@ import ( // empty file on the host filesystem, crashing older CNI because it doesn't know // how to handle empty statefiles. func WriteObjectToCNIStatefile() error { - filename := "/var/run/azure-vnet.json" + filename := platform.CNIStateFilePath return writeObjectToFile(filename) } diff --git a/cns/configuration/configuration.go b/cns/configuration/configuration.go index 382bed1613..b1414a2fc7 100644 --- a/cns/configuration/configuration.go +++ b/cns/configuration/configuration.go @@ -66,7 +66,12 @@ type ManagedSettings struct { NodeSyncIntervalInSeconds int } -func getConfigFilePath() (string, error) { +func getConfigFilePath(cmdLineConfigPath string) (string, error) { + // If config path is set from cmd line, return that + if cmdLineConfigPath != "" { + return cmdLineConfigPath, nil + } + // Check if env set for config path otherwise use default path configpath, found := os.LookupEnv(EnvCNSConfig) if !found { @@ -80,8 +85,8 @@ func getConfigFilePath() (string, error) { } // ReadConfig returns a CNS config from file or an error. -func ReadConfig() (*CNSConfig, error) { - configpath, err := getConfigFilePath() +func ReadConfig(cmdLineConfigPath string) (*CNSConfig, error) { + configpath, err := getConfigFilePath(cmdLineConfigPath) if err != nil { return nil, err } diff --git a/cns/configuration/configuration_test.go b/cns/configuration/configuration_test.go index bb984fd429..eee4c61b99 100644 --- a/cns/configuration/configuration_test.go +++ b/cns/configuration/configuration_test.go @@ -14,15 +14,20 @@ func TestGetConfigFilePath(t *testing.T) { execpath, _ := common.GetExecutableDirectory() // env unset - f, err := getConfigFilePath() + f, err := getConfigFilePath("") assert.NoError(t, err) assert.Equal(t, filepath.Join(execpath, defaultConfigName), f) // env set os.Setenv(EnvCNSConfig, "test.cfg") - f, err = getConfigFilePath() + f, err = getConfigFilePath("") assert.NoError(t, err) assert.Equal(t, "test.cfg", f) + + // test with cmdline config path + f, err = getConfigFilePath("/var/lib/cns_config.json") + assert.NoError(t, err) + assert.Equal(t, "/var/lib/cns_config.json", f) } func TestReadConfigFromFile(t *testing.T) { diff --git a/cns/restserver/util.go b/cns/restserver/util.go index c06e37ac2c..c5835eeb98 100644 --- a/cns/restserver/util.go +++ b/cns/restserver/util.go @@ -454,6 +454,11 @@ func (service *HTTPRestService) restoreNetworkState() error { return nil } + if !service.store.Exists() { + logger.Printf("[Azure CNS] Store does not exist, nothing to restore for network state.") + return nil + } + rebooted := false modTime, err := service.store.GetModificationTime() diff --git a/cns/service/main.go b/cns/service/main.go index 09672bac3c..06b8749b9b 100644 --- a/cns/service/main.go +++ b/cns/service/main.go @@ -251,6 +251,13 @@ var args = acn.ArgumentList{ Type: "string", DefaultValue: "", }, + { + Name: acn.OptCNSConfigPath, + Shorthand: acn.OptCNSConfigPathAlias, + Description: "Path to cns config file", + Type: "string", + DefaultValue: "", + }, } // init() is executed before main() whenever this package is imported @@ -385,6 +392,7 @@ func main() { nodeID := acn.GetArg(acn.OptNodeID).(string) clientDebugCmd := acn.GetArg(acn.OptDebugCmd).(string) clientDebugArg := acn.GetArg(acn.OptDebugArg).(string) + cmdLineConfigPath := acn.GetArg(acn.OptCNSConfigPath).(string) if vers { printVersion() @@ -418,7 +426,8 @@ func main() { logger.Errorf("[Azure CNS] Cannot disable telemetry via cmdline. Update cns_config.json to disable telemetry.") } - cnsconfig, err := configuration.ReadConfig() + logger.Printf("[Azure CNS] cmdLineConfigPath: %s", cmdLineConfigPath) + cnsconfig, err := configuration.ReadConfig(cmdLineConfigPath) if err != nil { logger.Errorf("[Azure CNS] Error reading cns config: %v", err) } diff --git a/common/config.go b/common/config.go index 024349a4ce..b1e7b199e6 100644 --- a/common/config.go +++ b/common/config.go @@ -122,4 +122,8 @@ const ( // Client mode, args for cmd OptDebugArg = "debugarg" OptDebugArgAlias = "darg" + + // CNS config path + OptCNSConfigPath = "config-path" + OptCNSConfigPathAlias = "cp" ) diff --git a/platform/os_linux.go b/platform/os_linux.go index cc2417769f..0403ea422b 100644 --- a/platform/os_linux.go +++ b/platform/os_linux.go @@ -21,6 +21,10 @@ const ( CNIRuntimePath = "/var/run/" // CNILockPath is the path where CNI lock files are stored. CNILockPath = "/var/run/azure-vnet/" + // CNIStateFilePath is the path to the CNI state file + CNIStateFilePath = "/var/run/azure-vnet.json" + // CNIBinaryPath is the path to the CNI binary + CNIBinaryPath = "/opt/cni/bin/azure-vnet" // CNSRuntimePath is the path where CNS state files are stored. CNSRuntimePath = "/var/run/" // CNI runtime path on a Kubernetes cluster diff --git a/platform/os_windows.go b/platform/os_windows.go index 811bc7fd2b..38652396dd 100644 --- a/platform/os_windows.go +++ b/platform/os_windows.go @@ -26,6 +26,12 @@ const ( // CNILockPath is the path where CNI lock files are stored. CNILockPath = "" + // CNIStateFilePath is the path to the CNI state file + CNIStateFilePath = "C:\\k\\azure-vnet.json" + + // CNIBinaryPath is the path to the CNI binary + CNIBinaryPath = "C:\\k\\azurecni\\bin\\azure-vnet.exe" + // CNI runtime path on a Kubernetes cluster K8SCNIRuntimePath = "C:\\k\\azurecni\\bin" diff --git a/store/json.go b/store/json.go index ff0552d58f..5e2711014c 100644 --- a/store/json.go +++ b/store/json.go @@ -54,6 +54,13 @@ func NewJsonFileStore(fileName string, lockclient processlock.Interface) (KeyVal return kvs, nil } +func (kvs *jsonFileStore) Exists() bool { + if _, err := os.Stat(kvs.fileName); err != nil { + return false + } + return true +} + // Read restores the value for the given key from persistent store. func (kvs *jsonFileStore) Read(key string, value interface{}) error { kvs.Mutex.Lock() diff --git a/store/mockstore.go b/store/mockstore.go index c3acfff2af..4077510d6b 100644 --- a/store/mockstore.go +++ b/store/mockstore.go @@ -15,6 +15,10 @@ func NewMockStore(lockFilePath string) KeyValueStore { } } +func (ms *mockStore) Exists() bool { + return false +} + // Read restores the value for the given key from persistent store. func (ms *mockStore) Read(key string, value interface{}) error { return nil diff --git a/store/store.go b/store/store.go index 0408310925..73b9e3fc72 100644 --- a/store/store.go +++ b/store/store.go @@ -10,6 +10,7 @@ import ( // KeyValueStore represents a persistent store of (key,value) pairs. type KeyValueStore interface { + Exists() bool Read(key string, value interface{}) error Write(key string, value interface{}) error Flush() error diff --git a/testutils/store_mock.go b/testutils/store_mock.go index 5ddd66f9a5..cead32138c 100644 --- a/testutils/store_mock.go +++ b/testutils/store_mock.go @@ -12,6 +12,7 @@ import ( var _ store.KeyValueStore = (*KeyValueStoreMock)(nil) type KeyValueStoreMock struct { + ExistsBool bool ReadError error WriteError error FlushError error @@ -21,6 +22,10 @@ type KeyValueStoreMock struct { GetModificationTimeError error } +func (mockst *KeyValueStoreMock) Exists() bool { + return mockst.ExistsBool +} + func (mockst *KeyValueStoreMock) Read(key string, value interface{}) error { return mockst.ReadError }