porter icon indicating copy to clipboard operation
porter copied to clipboard

Direct way of consuming parameters/credentials as JSON objects?

Open philliphoff opened this issue 4 years ago • 5 comments

Is there a direct way of consuming parameters or credentials in porter.yaml as JSON objects (i.e. use their sub-properties as inputs to commands)? Currently one might feed a parameter/credential into an exec command, which calls a bash script, which simply echos the value, which can then be teased into individual outputs using jsonPath. Is there a better way?

philliphoff avatar Mar 18 '21 20:03 philliphoff

We don't currently support that right now, you would need to do the workaround you laid out (using exec mixin to grab the piece you want and output a sub-property).

However it could be possible for parameters with a bit of work in Porter. We support this for custom values defined in porter.yaml, where you can use templating like {{ bundle.custom.myobj.subfield }}.

Let me lay out what I think it could look like, and let me know if it works with your use case:

config.json

{
  "color": "blue"
}

porter.yaml

parameters:
- name: config
   type: object
   path: /cnab/app/config.json # User passes in a json document for this parameter

install:
- exec:
     description: Use a sub field on the config property document
     command: ./helpers.sh
     arguments:
     - "{{ bundle.parameters.config.color }}" # passes in "blue"

Porter would need to do some special handling for parameters of type "object" and expand them in the template (instead of providing it as a string) which I think is the right thing here, we just missed it the first time around.

carolynvs avatar Mar 19 '21 15:03 carolynvs

I'm going to assume that this (above) is a workable design but if anyone has feedback on how they would like to use parameters that are a structured object (instead of a simple value), please leave a comment!

carolynvs avatar Mar 30 '21 16:03 carolynvs

Yes, I think that design would work for us.

philliphoff avatar Mar 30 '21 23:03 philliphoff

Thanks for letting me know! I think it's a straightforward change for someone familiar with Go. We would need to attempt to unmarshal the parameter as json, and if it works assign that to the parameter's value. If it can't be read as json, that would be a hard error, since the parameter validation which occurrs before the bundle is run should have checked that it's a json document already.

The change should be made in this function, so that it returns an (interface{}, error) instead of a string.

https://github.com/getporter/porter/blob/9f608fffee0a203c406915a5e5f66acd9ee32b67/pkg/runtime/runtime-manifest.go#L106

If anyone is interested in trying to fix this, I'm happy to help. Otherwise it's on the v1.0 roadmap now.

carolynvs avatar Mar 31 '21 15:03 carolynvs

We can make this work in a v1 minor patch, without a breaking change. To do this we need to preserve this existing functionality

install:
  - exec:
       command: foo
       arguments:
         - "{{ bundle.parameters.config }}" # should still inject the string representation of the json document

carolynvs avatar Jun 16 '22 16:06 carolynvs