From 049ef34b550e9f2418f39cc9fea32fc7277e5bb2 Mon Sep 17 00:00:00 2001 From: Derek Su Date: Mon, 19 Feb 2024 03:45:22 +0000 Subject: [PATCH 1/2] ns: executor supports environment variables Longhorn 7672 Signed-off-by: Derek Su --- ns/crypto.go | 2 +- ns/executor.go | 19 ++++++++++++------- ns/executor_test.go | 6 +++--- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/ns/crypto.go b/ns/crypto.go index d8988dda..5638b37d 100644 --- a/ns/crypto.go +++ b/ns/crypto.go @@ -65,5 +65,5 @@ func (nsexec *Executor) CryptsetupWithPassphrase(passphrase string, args []strin // For Talos Linux, cryptsetup comes pre-installed in the host namespace // (ref: https://github.com/siderolabs/pkgs/blob/release-1.4/reproducibility/pkg.yaml#L10) // for the [Disk Encryption](https://www.talos.dev/v1.4/talos-guides/configuration/disk-encryption/). - return nsexec.ExecuteWithStdin(types.BinaryCryptsetup, args, passphrase, timeout) + return nsexec.ExecuteWithStdin(nil, types.BinaryCryptsetup, args, passphrase, timeout) } diff --git a/ns/executor.go b/ns/executor.go index 617f21e0..a850e771 100644 --- a/ns/executor.go +++ b/ns/executor.go @@ -46,7 +46,7 @@ func NewNamespaceExecutor(processName, procDirectory string, namespaces []types. } // prepareCommandArgs prepares the nsenter command arguments. -func (nsexec *Executor) prepareCommandArgs(binary string, args []string) []string { +func (nsexec *Executor) prepareCommandArgs(binary string, args, envs []string) []string { cmdArgs := []string{} for _, ns := range nsexec.namespaces { nsPath := filepath.Join(nsexec.nsDirectory, ns.String()) @@ -59,24 +59,29 @@ func (nsexec *Executor) prepareCommandArgs(binary string, args []string) []strin cmdArgs = append(cmdArgs, "--net="+nsPath) } } + if len(envs) > 0 { + cmdArgs = append(cmdArgs, "env", "-i") + cmdArgs = append(cmdArgs, envs...) + } + cmdArgs = append(cmdArgs, binary) return append(cmdArgs, args...) } // Execute executes the command in the namespace. If NsDirectory is empty, // it will execute the command in the current namespace. -func (nsexec *Executor) Execute(binary string, args []string, timeout time.Duration) (string, error) { - return nsexec.executor.Execute(nil, types.NsBinary, nsexec.prepareCommandArgs(binary, args), timeout) +func (nsexec *Executor) Execute(envs []string, binary string, args []string, timeout time.Duration) (string, error) { + return nsexec.executor.Execute(nil, types.NsBinary, nsexec.prepareCommandArgs(binary, args, envs), timeout) } // ExecuteWithStdin executes the command in the namespace with stdin. // If NsDirectory is empty, it will execute the command in the current namespace. -func (nsexec *Executor) ExecuteWithStdin(binary string, args []string, stdinString string, timeout time.Duration) (string, error) { - return nsexec.executor.ExecuteWithStdin(types.NsBinary, nsexec.prepareCommandArgs(binary, args), stdinString, timeout) +func (nsexec *Executor) ExecuteWithStdin(envs []string, binary string, args []string, stdinString string, timeout time.Duration) (string, error) { + return nsexec.executor.ExecuteWithStdin(types.NsBinary, nsexec.prepareCommandArgs(binary, args, envs), stdinString, timeout) } // ExecuteWithStdinPipe executes the command in the namespace with stdin pipe. // If NsDirectory is empty, it will execute the command in the current namespace. -func (nsexec *Executor) ExecuteWithStdinPipe(binary string, args []string, stdinString string, timeout time.Duration) (string, error) { - return nsexec.executor.ExecuteWithStdinPipe(types.NsBinary, nsexec.prepareCommandArgs(binary, args), stdinString, timeout) +func (nsexec *Executor) ExecuteWithStdinPipe(envs []string, binary string, args []string, stdinString string, timeout time.Duration) (string, error) { + return nsexec.executor.ExecuteWithStdinPipe(types.NsBinary, nsexec.prepareCommandArgs(binary, args, envs), stdinString, timeout) } diff --git a/ns/executor_test.go b/ns/executor_test.go index b64cebe0..27be475b 100644 --- a/ns/executor_test.go +++ b/ns/executor_test.go @@ -29,7 +29,7 @@ func (s *TestSuite) TestExecute(c *C) { nsexec.nsDirectory = testCase.nsDirectory nsexec.executor = &fake.Executor{} - output, err := nsexec.Execute("binary", []string{"arg1", "arg2"}, types.ExecuteDefaultTimeout) + output, err := nsexec.Execute(nil, "binary", []string{"arg1", "arg2"}, types.ExecuteDefaultTimeout) c.Assert(err, IsNil) c.Assert(output, Equals, "output") } @@ -62,7 +62,7 @@ func (s *TestSuite) TestExecuteWithTimeout(c *C) { nsexec.executor = &fake.Executor{} - output, err := nsexec.Execute("binary", []string{"arg1", "arg2"}, testCase.timeout) + output, err := nsexec.Execute(nil, "binary", []string{"arg1", "arg2"}, testCase.timeout) c.Assert(err, IsNil) c.Assert(output, Equals, "output") } @@ -88,7 +88,7 @@ func (s *TestSuite) TestExecuteWithStdinPipe(c *C) { nsexec.nsDirectory = testCase.nsDirectory nsexec.executor = &fake.Executor{} - output, err := nsexec.ExecuteWithStdinPipe("binary", []string{"arg1", "arg2"}, "stdin", types.ExecuteDefaultTimeout) + output, err := nsexec.ExecuteWithStdinPipe(nil, "binary", []string{"arg1", "arg2"}, "stdin", types.ExecuteDefaultTimeout) c.Assert(err, IsNil) c.Assert(output, Equals, "output") } From c592afb4849a115d59813731bb0822c5487f94f0 Mon Sep 17 00:00:00 2001 From: Derek Su Date: Mon, 19 Feb 2024 04:28:03 +0000 Subject: [PATCH 2/2] test: add TestExecuteWithEnvs Test namespaced execution with environment variables Longhorn 7672 Signed-off-by: Derek Su --- ns/executor_test.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/ns/executor_test.go b/ns/executor_test.go index 27be475b..04bf3204 100644 --- a/ns/executor_test.go +++ b/ns/executor_test.go @@ -93,3 +93,28 @@ func (s *TestSuite) TestExecuteWithStdinPipe(c *C) { c.Assert(output, Equals, "output") } } + +func (s *TestSuite) TestExecuteWithEnvs(c *C) { + type testCase struct { + timeout time.Duration + } + testCases := map[string]testCase{ + "Execute(...)": { + timeout: types.ExecuteNoTimeout, + }, + "Execute(...): with namespace": { + timeout: types.ExecuteNoTimeout, + }, + } + for testName := range testCases { + c.Logf("testing namespace.%v", testName) + + namespaces := []types.Namespace{} + nsexec, err := NewNamespaceExecutor(types.ProcessNone, types.HostProcDirectory, namespaces) + c.Assert(err, IsNil) + + output, err := nsexec.Execute([]string{"K1=V1", "K2=V2"}, "env", nil, types.ExecuteDefaultTimeout) + c.Assert(err, IsNil) + c.Assert(output, Equals, "K1=V1\nK2=V2\n") + } +}