2

I'm trying to pipe the output of the first command into the quotation marks at the end of the second command.

kubectl --context foo -n foo get secret postgres.foo-db.credentials -o jsonpath={.data.password}

kubectl --context foo -n foo patch secret postgres.foo-db.credentials -p '{"data":{"password":"    Output from command 1    "}}'

I've already tried this: piping output into middle of bash command, but I get the following error with this command:

kubectl --context foo -n foo patch secret postgres.foo-db.credentials -p '{"data":{"`password":"kubectl --context foo -n foo get secret postgres.foo-db.credentials -o jsonpath={.data.password}`"}}'

The request is invalid: patch: Invalid value: "map[data:map[`password:kubectl --context foo  -n foo  get secret postgres.foo-db.credentials -o jsonpath={.data.password}`]]": error decoding from json: illegal base64 data at input byte 7
Wytrzymały Wiktor
  • 11,492
  • 5
  • 29
  • 37
  • A pipe won't do here. You need [_command substitution_](https://sites.ualberta.ca/dept/chemeng/AIX-43/share/man/info/C/a_doc_lib/aixuser/usrosdev/cmd_subst_korn_shell.htm), because one part of your command is supposed to be substituted by the standard output of a different command. – user1934428 Aug 24 '21 at 07:03
  • 1
    @WytrzymałyWiktor Yes :) – David Huber FF Sep 02 '21 at 11:41

3 Answers3

3

You can split the command in two to make it easier to understand and let the bash shell expand the variable pgsecret in the second line:

pgsecret="$(kubectl --context foo -n foo get secret \
  postgres.foo-db.credentials -o jsonpath={.data.password})"
kubectl \
  --context foo -n foo patch secret \
  postgres.foo-db.credentials -p '{"data":{"password":"'$pgsecret'"}}'
Davide Madrisan
  • 1,969
  • 2
  • 14
  • 22
  • Are you sure, that your answer is correct? I have tested this and on my environment I received an error. IMO `"'$pgsecret'"` should be only with double quotes: `"$pgsecret"`. Look here: https://askubuntu.com/questions/605411 – Mikołaj Głodziak Aug 25 '21 at 10:28
  • I have no such a problem in a bash environment. The single quotes are stripped by bash. – Davide Madrisan Aug 25 '21 at 12:14
  • Successfully tested with `pgsecret=$(echo "XXX" | base64); kubectl -n myns patch secret testsecret -p '{"data":{"password":"'$pgsecret'"}}'` – Davide Madrisan Aug 25 '21 at 15:32
0

The idea of Davide Madrisan is good. The code will be more readable. But with this solution you could probably receive an error. In the command:

kubectl --context foo -n foo patch secret postgres.foo-db.credentials -p '{"data":{"password":"'$pgsecret'"}}'

the reference to a variable "'$pgsecret'" is with the double and single quotes. Double are fine, because it must be "key":"value" structure. But on my environment single quotes were wrong. I have received an error:

Error from server (BadRequest): invalid character '<wrong character>' after object key:value pair

You can read more about the difference between ' and " here.

I suggest to remove single quotes:

pgsecret="$(kubectl --context foo -n foo get secret \
  postgres.foo-db.credentials -o jsonpath={.data.password})"
kubectl \
  --context foo -n foo patch secret \
  postgres.foo-db.credentials -p '{"data":{"password":"$pgsecret"}}'

or if you want to do this in the one line without a variable (less readable code):

kubectl --context foo -n foo patch secret postgres.foo-db.credentials -p '{"data":{"password":"$(kubectl --context foo -n foo get secret postgres.foo-db.credentials -o jsonpath={.data.password})"}}'

should also work with you. This treatment is called command substitution, as user1934428 well mentioned in the comment:

A pipe won't do here. You need command substitution, because one part of your command is supposed to be substituted by the standard output of a different command.

Mikołaj Głodziak
  • 4,775
  • 7
  • 28
  • If `pgsecret` contains for instance `WFhYCg==` thant bash will strip the single quotes and pass {"data":{"password":"WFhYCg=="}} to kubectl, which is exactly what you want. Your version will pass `{"data":{"password":"$pgsecret"}` instead and kubectl will complain with the following error message `The request is invalid: patch: Invalid value: "map[data:map[password:$pgsecret]]": error decoding from json: illegal base64 data at input byte 0` – Davide Madrisan Aug 25 '21 at 15:29
0

backticks (aka $()) are not used as command substitution inside single quotes, but are literal:

$ echo '$(echo foo)'
$(echo foo)

They are interpolated inside double quotes:

$ echo "$(echo foo)"
foo

So you just need to properly quote your substitution:

$ kubectl --context ... -p '{"data":{"password":"'"$(cmd to get passwd)"'"}}'

You could also write:

$ kubectl --context ... -p "{\"data\":{\"password\":\"$(cmd to get passwd)\"}}"
William Pursell
  • 204,365
  • 48
  • 270
  • 300