Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot specify integer/bool/base64 types in templates #3946

Closed
nstrug opened this issue Jul 29, 2015 · 23 comments · Fixed by #11421
Closed

Cannot specify integer/bool/base64 types in templates #3946

nstrug opened this issue Jul 29, 2015 · 23 comments · Fixed by #11421

Comments

@nstrug
Copy link

nstrug commented Jul 29, 2015

It is not currently possible to specify integer types in template parameters.

For example, we want to be able to specify a parameter:

- name: N_MIAMI
  description: Number of Miami pods
  value: 1

where N_MIAMI will actually be fed to a replication controller to specify the number of replicas.
As written, this fails during oc process with:
error: unable to load "agree21-template.yaml": json: cannot unmarshal number into Go value of type string

We can fix this with:

- name: N_MIAMI
  description: Number of Miami pods
  value: "1"

which now successfully processes. However, the output now contains:

"replicas": "1"
which fails on creation with:
json: cannot unmarshall string into Go value of type int

A possible fix would be to be able to specify the expected parameter type (string, int or float should cover it) in the parameter definition.

@liggitt
Copy link
Contributor

liggitt commented Aug 3, 2015

Even if you find a way to make the parameter typed, doing the actual replacement is more complicated. The template with the replaceable token has to be valid JSON, so you couldn't do this:

      "spec": {
        "replicas": ${MY_REPLICA_COUNT},

We'd have to find a way to:

  1. Make a template with a replacement token which was valid JSON (which implies a string)
  2. Indicate when the token is replaced, it should replace as a number (e.g. remove the wrapping quotes).

I can't think of a clean way to do that off the top of my head

@bparees
Copy link
Contributor

bparees commented Aug 27, 2015

@liggitt and I discussed this and he had a proposal of a format like:

"replicas": ${MY_REPLICA_COUNT}{INTEGER}

(ok we didn't discus the exact formatting so he may disagree there).

then we'd do normal parameter generation but then cast/convert the generated/overridden value into the appropriate type and specify it in the json in the correct format (eg stripping quotes for non-stirngs).

this would also enable parameterizing secrets with a format like:

"mySecret": ${SOME_PARAM}{BASE64}

though it would still not make it possible to supply a binary value or disk file as a secret parameter since you still have to first provide it in the Parameter definition and that only takes strings right now.

@liggitt
Copy link
Contributor

liggitt commented Aug 27, 2015

the whole syntax would have to be in a string to be valid JSON and parameterize the value. also, my preference would be to include it in the parameter syntax, e.g.

"replicas":"${MY_REPLICA_COUNT | int}"

the pipe syntax would only be allowed if the parameter was the entire value (you couldn't do "${FOO | int}${BAR | int}"

Possible transformations:

For the conversion cases, we'd have to define what happens in error cases, either the template processing fails, or a default value (probably empty, so 0, 0.0, false, respectively) is used. I think my preference would be to fail processing in conversion error cases (with the possible exception of empty strings, which I would be ok converting to 0,0.0, and false)

@jorgemoralespou
Copy link

Hey @bparees @liggitt ,
What would be the problem extending the https://docs.openshift.org/latest/rest_api/openshift_v1.html#v1-parameter with a "type", like it has been done with the required?

Like it says on the 1.0.5 release notes:

Added required attribute to template parameters. Templates now cannot be instantiated without supplying a value for all required parameters.

@liggitt
Copy link
Contributor

liggitt commented Aug 27, 2015

validating the input and describing the format of the output are different. What if you wanted to validate a numeric input (like "1"), but you wanted to set it in an envvar definition (which expects a string, so "1").

@jorgemoralespou
Copy link

And is there an issue to validate the input? This should be also needed, as this could allow to fail soon before doing the template processing.
We are seeing many templates process and resources created and then falling for to some invalid value.

@mfojtik
Copy link
Contributor

mfojtik commented Aug 28, 2015

@liggitt @bparees alternative proposal (just brainstorming)...
Let allow to specify the 'JSONPath' as part of the parameter definition:

    {
      "name": "INITIAL_REPLICAS_COUNT",
      "description": "The number of initial replicas",
      "path": ".deploymentConfig[name=foo]....",
      "value": 2,
    },

This will allow us to substitute basically any type (bool, array, etc..).

@bparees
Copy link
Contributor

bparees commented Aug 28, 2015

That feels harder to me as a user and more work to maintain if I rename
something or otherwise restructure my template. (and more error prone if I
mess up a path)

I take it your point is we could just do direct assignment then? "value"
would be an untyped interface?

Ben Parees | OpenShift
On Aug 28, 2015 04:52, "Michal Fojtik" [email protected] wrote:

@liggitt https://github.com/liggitt @bparees
https://github.com/bparees alternative proposal (just brainstorming)...
Let allow to specify the 'JSONPath' as part of the parameter definition:

{
  "name": "INITIAL_REPLICAS_COUNT",
  "description": "The number of initial replicas",
  "path": ".deploymentConfig[name=foo]....",
  "value": 2,
},


Reply to this email directly or view it on GitHub
#3946 (comment).

@bparees
Copy link
Contributor

bparees commented Aug 28, 2015

Is failing at processing so bad? Processing is fast.

Whether we should do more validation as part of process is a valid
question/separate issue though.

Ben Parees | OpenShift
On Aug 28, 2015 02:51, "Jorge Morales Pou" [email protected] wrote:

And is there an issue to validate the input? This should be also needed,
as this could allow to fail soon before doing the template processing.
We are seeing many templates process and resources created and then
falling for to some invalid value.


Reply to this email directly or view it on GitHub
#3946 (comment).

@mfojtik
Copy link
Contributor

mfojtik commented Aug 28, 2015

@bparees yes, the value is interface{}

Making the integer and boolean accepting string values with parameters seems to be much harder to implement (the JSON parser will have to be more relaxed on it).

@liggitt
Copy link
Contributor

liggitt commented Aug 28, 2015

Validation is orthogonal. I might want to validate something as an integer, even if it is going to be plugged in as a string.

the JSON parser will have to be more relaxed on it

Which parser, parsing when we process the template?

@mfojtik
Copy link
Contributor

mfojtik commented Aug 28, 2015

@liggitt yes, like if you parse replicas: "${NUM | integer}". When reading the template, we will have to treat all fields as strings, do substitution and then change them to integers/bools?

@liggitt
Copy link
Contributor

liggitt commented Aug 28, 2015

any field that contains a parameter substitution already has to be a string, in order to contain the param name syntax... I think we have to let that be transformed from a string to a non-string

@bparees
Copy link
Contributor

bparees commented Aug 29, 2015

It is a problem since the template today consists of (among other things) a list of API Structs, so the assumption is that the json in the template can be directly deserialized into an api object. (which is what we do, and then we iterate the objects/fields and do the substitution).

So @mfojtik makes a valid point that we can't just put String values into non-String fields in the template json, because it won't deserialize anymore (without some help)

@liggitt
Copy link
Contributor

liggitt commented Aug 29, 2015

I thought this meant the objects could be arbitrary JSON:

    Objects []runtime.RawExtension `json:"objects" description:"list of objects to include in the template"`

I thought the template process visited all the structs using reflection, and could swap a string value out with an int value, then reserialize. I didn't think templates items got converted to actual API structs during processing.

@bparees
Copy link
Contributor

bparees commented Aug 29, 2015

could be. i'm guilty of assuming/speculating w/o checking the code.

@sosiouxme
Copy link
Member

If we're adding types, how about a file type?

"${FOO | file}"
"${BAR | base64file}"
$ oc process -v FOO=./foo -v BAR=./bar 
  -> FOO replaced with contents of ./foo, BAR replaced with base64-encoded contents of ./bar

Ref. https://trello.com/c/70O1sCBv

@liggitt
Copy link
Contributor

liggitt commented Dec 1, 2015

this is about how parameters are rendered into the template, not input... you can already do

oc process -v "FOO=`cat foo`"

@sosiouxme
Copy link
Member

You can, at least under bash and if your file has no commas, but is that what we want to tell users? Anyway, point taken, this might be too much overloading of the "types" concept.

jwendell added a commit to jwendell/origin that referenced this issue Jan 1, 2016
This is done through the new boolean field "disableSSLCheck" inside GitBuildSource
object.

The use case is to allow the user to specify a git repository with a self-signed
SSL certificate. Currently sti build fails at git (ls-remote|clone) stage.

So, one can write a template like this
               ...
                "source": {
                    "contextDir": "${CONTEXT_DIR}",
                    "git": {
                        "disableSSLCheck": true,
                        "ref": "${SOURCE_REPOSITORY_REF}",
                        "uri": "${SOURCE_REPOSITORY_URL}"
                    },
                    "type": "Git"
                ...

In the future, with openshift#3946 implemented, one might use a boolean parameter in the
template and have it rendered into a checkbox in the UI.
@liggitt liggitt changed the title Cannot specify integer types in templates Cannot specify integer/bool/base64 types in templates Jan 29, 2016
@donovanmuller
Copy link

Any update on this? I just gained a few new grey hairs because of this 😀

As a temporary hack I'm doing the following:
Given that the containerPort/port is parameterised with ${SERVER_PORT} and that the value is say 8080:

oc process a-template \
  -v SERVER_PORT="8080" | sed 's/"8080"/8080/g' \
  | oc create -f -

Nasty but works

@bparees
Copy link
Contributor

bparees commented Mar 1, 2016

At this point we're looking to address this as part of moving templates upstream to kubernetes, you can see the proposal here: https://github.com/kubernetes/kubernetes/blob/master/docs/proposals/templates.md

it includes support for handling this sort of scenario.

dgoodwin added a commit to dgoodwin/online-analytics that referenced this issue Oct 25, 2017
Similar to what we just merged for archivist, the role to deploy the app
will no longer destroy the running app and trigger a build. Instead we
maintain the OpenShift objects, update them if necessary, and check if a
start-build is required on each run.

Several parameters in the template which user integers now fail to
process citing a "int32" error on OpenShift 3.7. Suspect related to:
openshift/origin#3946. These parameters were
never customized so to work around they have been removed and just hard
coded. We can update the template and re-run ansible to adjust in
future, which would be required even to reprocess the template.
dgoodwin added a commit to dgoodwin/online-analytics that referenced this issue Oct 25, 2017
Similar to what we just merged for archivist, the role to deploy the app
will no longer destroy the running app and trigger a build. Instead we
maintain the OpenShift objects, update them if necessary, and check if a
start-build is required on each run.

Several parameters in the template which user integers now fail to
process citing a "int32" error on OpenShift 3.7. Suspect related to:
openshift/origin#3946. These parameters were
never customized so to work around they have been removed and just hard
coded. We can update the template and re-run ansible to adjust in
future, which would be required even to reprocess the template.
@alwinmark
Copy link

As referenced here: #11068

There is a workaround using ${{ VARIABLE }} instead of ${ VARIABLE}, but I missed that. Hopefully this comment helps somebody in the same situation

@030
Copy link

030 commented Apr 6, 2020

In my case I had to remove the spaces as well: ${{VARIABLE}}. @alwinmark thanks for pointing me in the right direction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment