gruntwork-io / boilerplate

A tool for generating files and folders ("boilerplate") from a set of templates
https://www.gruntwork.io
183 stars 16 forks source link

Add a way to clearly mark a variable as having no value #17

Open brikis98 opened 8 years ago

brikis98 commented 8 years ago

There is some awkwardness in boilerplate, and Go in general, with how to identify when you want to set a variable to "no value". In other languages, this would be done using null or None, but in Go, while some types can be set to nil, most primitives can only be set to their "zero values" (e.g. "" for a string, 0 for an int, etc). This makes it hard to set "no value", both in the default parameter in a boilerplate.yml file and as a user when enter the value via interactive prompt or the --var and --var-file options.

Perhaps a simply, albeit not terribly elegant option is to simply define a placeholder that globally means "use the zero value for this type". A simple one would be something like __NO_VALUE__. This is unlikely to collide with any real value a user is likely to enter and pretty clearly communicates the intent. Example:

variables:
  name: Title
  default: __NO_VALUE__
josh-padnick commented 8 years ago

+1 for supporting empty values, and per https://github.com/gruntwork-io/boilerplate/blob/master/config/get_variables.go#L111, beyond representing a __NOVALUE__ in boilerplate.yml, there's also the CLI user experience: what's the difference between "press enter for default" and "press enter for blank"?

I'd prefer __NOVALUE__ without spaces just because it's easier to type, or maybe even __EMPTY__. Then maybe you could enter that as well on the CLI.

brikis98 commented 8 years ago

__EMPTY__ reads nicely, so that's probably the best bet. And yes, you'd definitely be able to enter it at the command line.

josh-padnick commented 7 years ago

Running into this one again. Here's my use case:

I want to expose a boilerplate var .PortsAccessibleByBastionHost and use an {{ if }} statement in the template to determine whether to include a few security group rules. Ideally, I could just say {{ if len .PortsAccessibleByBastionHost }} ... but since .PortsAccessibleByBastionHost has to be non-empty, I instead have to resort to two separate vars .PortsAccessibleByBastionHost and .EnableAccessOnSpecificPortsFromBastionHost, and even if .EnableAccessOnSpecificPortsFromBastionHost is false, add a dummy not-used value for .PortsAccessibleByBastionHost.