Как выполнить несколько команд в контейнере Pod с клиентом - go? - PullRequest
2 голосов
/ 18 марта 2020

Итак, я попытался выполнить цепочку, т.е. несколько команд в контейнере Pod, используя client-go, и кажется, что она работает только для некоторых команд, таких как ls.

. Вот что я пробовал:

    req := client.CoreV1().RESTClient().Post().Resource("pods").Name(pod.Name).Namespace(pod.ObjectMeta.Namespace).SubResource("exec") // .Param("container", containerName)
    scheme := runtime.NewScheme()
    if err := _v1.AddToScheme(scheme); err != nil {
        panic(err.Error())
    }
    parameterCodec := runtime.NewParameterCodec(scheme)
    req.VersionedParams(&_v1.PodExecOptions{
        Stdin:     false,
        Stdout:    true,
        Stderr:    true,
        TTY:       false,
        Container: containerName,
        Command:   strings.Fields("/bin/sh -c " + command),
    }, parameterCodec)
    exec, err := remotecommand.NewSPDYExecutor(restConfig, "POST", req.URL())
    if err != nil {
        panic(err.Error())
    }
    var stdout, stderr bytes.Buffer
    err = exec.Stream(remotecommand.StreamOptions{
        Stdin:  nil,
        Stdout: &stdout,
        Stderr: &stderr,
        Tty:    false,
    })
    if err != nil {
        panic(err.Error())
    }
log.Printf("Output from pod: %v", stdout.String())
log.Printf("Error from pod: %v", stderr.String())

Когда переменная command является просто простой ls -l, я получаю желаемый результат. Но когда я пытаюсь сделать что-то вроде 'ls -l && echo hello', выдается ошибка command terminated with exit code 2. Ничего не выводится, если я только поставлю echo hello. Тем не менее, он выдает желаемый результат hello, если я удаляю префикс Bourne Shell /bin/sh -c и атрибут Command равен string.Fields("echo hello"), но этот подход не позволяет мне объединять команды.

В общем, я пытаюсь выполнить цепочку команд над контейнером контейнера.

1 Ответ

2 голосов
/ 19 марта 2020

corev1.PodExecOptions.Command принимает значение типа []string.

req.VersionedParams(&_v1.PodExecOptions{
  Stdin:     false,
  Stdout:    true,
  Stderr:    true,
  TTY:       false,
  Container: containerName,
  Command:   cmds,
}, parameterCodec)

, где cmds может быть:

cmds := []string{
    "sh",
    "-c",
    "echo $HOME; ls -l && echo hello",
    }

Выход:

/root
total 68
drwxr-xr-x   2 root root 4096 Feb 24 00:00 bin
drwxr-xr-x   2 root root 4096 Feb  1 17:09 boot
drwxr-xr-x   2 root root 4096 Feb 24 00:00 mnt
drwxr-xr-x   2 root root 4096 Feb 24 00:00 opt
dr-xr-xr-x 396 root root    0 Mar 19 11:47 proc
drwx------   2 root root 4096 Feb 24 00:00 root
.
.
hello

Объяснение: Ответ Тима

command: ["/bin/sh","-c"]
args: ["command one; command two && command three"]

Команда ["/bin/sh", "-c"] говорит «запустить оболочку и выполнить следующие инструкции», Аргументы затем передаются в виде команд в оболочку. В сценариях оболочки semicolon разделяет команды, а && условно запускает следующую команду, если первая удалась. В приведенном выше примере он всегда запускает команду one, за которой следует команда two, и запускает команду three, только если команда two выполнена успешно.

NB: Для bash, это будет похоже на что-то вроде ниже:

cmds := []string{
     "bash",
     "-c",
     `export MYSQL_PWD=${MYSQL_ROOT_PASSWORD}
mysql -h localhost -nsLNE -e "select 1;" 2>/dev/null | grep -v "*"`,
                    },
...