Can I have dist-zilla fill in arbitrary fields in a template file? - perl

Is there any way to have a user defined parameter in a file and then have the dist.ini set the value for the parameter. For example, a file might contain {{$THE_ANSWER}} and the dist.ini file would provide a value like THE_ANSWER = 42? I'm pretty new to using dist::zilla to work with perl distributions, and I'm having problems understanding how it treats files as templates. There seem to be only a couple of hard-codeed parameters, varying by plugin, that can be used for any file. One such parameter is the {{$NEXT}} variable made available by [NextRelease] in the Changes file.
I read through the tutorials and searched the modules on CPAN and can't figure out if this is even possible. It is not an acceptable work-around to use the [GenerateFile] plugin to put the whole file in the dist.ini file. Besides a lack of flexibility and just plain ugliness, it doesn't seem possible to add lines with leading white-space that way.

What I would do is use a stash or plugin to store the variables. Stashes are like plugins, but they don't do anything but store data, and they can be put into your global configuration as well as your dist.ini.
[%Vars]
favorite_pie = pumpkin
Then you can get at them like this:
$zilla->stash_named('%Vars')->favorite_pie
This assumes that you've made Dist::Zilla::Stash::Vars and given it a favorite_pie attribute.
You could make a totally generic stash, though, which accepts anything as a key. For that, I'd look at the source of Dist::Zilla::Plugin::Prereqs, which allows arbitrary configuration options and shoves them into a hash attribute in its BUILDSARGS method.
You could make that Dist::Zilla::Stash::Generic, and then register it as many times as you want for different reasons:
[%Generic / Pies]
favorite = pumpkin
hated = rhubarb
firstever = quince
[%Generic / Passwords]
pause = PeasAreDelicious
google = secret
reddit = SecretPeasAreDelicious
...then, as needed, say in templates...
{{ $zilla->stash_named('Passwords')->get_var('pause' }}
If I was making a lot of files that used this sort of generic thing, I'd pass their Text::Template instance a closure called get_password like this:
get_password => sub { $zilla->stash_named('Passwords')->get_var($_[0]) }
Then your template could include:
Login with: {{ get_password("pause") }}
This answer obviously leaves some source digging for you, but I think it should point at all the pieces I'd use to do what you want.

Related

conditionally including part of template

I'm completely new to helm/k8s. Following question might not be best way to do things or it might not make a lot of sense, but I don't know best(or any other) practices yet, and this is my best attempt to solve something much more complex, while not understanding it properly. Thanks(I beg) for patience with me.
In values.yaml say I have something like this:
whatever1: true
whatever2: true
myConfigs:
variantA:
test: tooSteep
variantB:
test: learningCurve
in reality it's a lot bigger, of course. Then I have some template, which I need to generate in 2 (or more) variants and I cannot use whole different configs for it, which would overwrite data in values.yaml(it's complicated). Previous solution by college who understands this more than me involves some heavy copy-pasting. What I'd like to see instead is to have one abstract template, say:
whatever1: true
whatever2: true
test: {{ .Values.myConfigs.$what.test}}
which I'd include/tpl somehow within child templates, and say how it should behave conditionally, say:
{{- $what := "variantA" -}}
{{ tpl (.Files.Get "stubs/abstract.template") . }}
The syntax is obviously wrong, and it does not work. I know this is wrong, I cannot find any way which would enable this. I don't know the correct way how to write that. What I need to do is somehow express, which part of .Values should be used in specific part of template. IIUC if I have all data in 1 file I cannot, just use tpl function, load template and pass it context of specific variant, as won't have access to whatever then. So I need to pass the broader context and somehow pass some selector.
I understand, that correct way is probably restructuring files so that I can actually work effectively with context, but that would require me to actually understand which part of configuration will have to go together every time, and I'm far from ready for this refactoring.
Not sure what is the correct way, but what could be actually used to solve described problem: do the decision when calling template, and alter the passed context to contain all required information. In my case it wasn't possible just to select specific subtree in actual context, so what I was missing was function dict, which creates a new dictionary, which then can be passed as context.

Multiple tables with the same values in TOML

I'm new to TOML and I have several sets of a scenario where two tables are identical. Is it possible to define multiple tables with the same keys without having to repeat everything?
For example, take this TOML file for AWS SAM configuration. When using the sam local commands, the options I require are exactly the same, but I have to define them twice.
version = 0.1
[dev1.local_invoke.parameters]
profile = "dev1"
...
[dev1.local_start_lambda.parameters]
profile = "dev1"
...
[dev2.local_invoke.parameters]
profile = "dev2"
...
[dev2.local_start_lambda.parameters]
profile = "dev2"
...
I've tried the obvious things, but they don't work. I've also looked at the documentation but there is nothing obvious, though as mentioned I'm new to TOML so I may be missing something.
[dev.local_invoke.parameters]
[dev.local_start_lambda.parameters]
...
[dev.local.parameters]
...
It looks like TOML files don't support this feature as a deliberate design choice. In fact, this was discussed in more detail in issue #697.
It seems like the driving philosophy is that as soon as values in the TOML file refer to other values, it ceases to become a flat file and also becomes less readable.
As a workaround, you may be able to keep your TOML files thin-and-readable by consolidating the shared values up front and then having a separate program or script process the TOML file and delegate the repeat values.

Read YAML config through Rest API

I have a really complicated system which use multiple languages and frameworks (Java Python Scala Bash). In each module I need to retrieve configuration values which are similar and change frequently. Currently I'm maintaining multiple conf files which holds lots of duplicates.
I wonder if there is out of the box RestAPI which can retrieve variables by demand from remote location.
All I manage to find by now are ways to load the entire file from remote source which is half a solution from me:
YAML.parse(open('https://link_to_file/file.yaml'))
My goal, which I fail to find a lead to it, is to make a direct call.
MyRemoteAPI.get("level1.level2.x")
P.S
YAML is not mandatory solution for me, I'm Open for suggestions.
I don't know about an out-of-the-box API, but it's fairly trivial to build. Make a service that will read the YAML file and traverse to the appropriate key. e.g. using a dynamic language like Ruby (+Rails), you could do something like
def value
config = YAML.load_file '/local/path/to/config.yaml'
render plain: config.dig(params[:key].split('.'))
end
dig essentially traverses a structure and safely returns nil if a key isn't found, so this returns the value at the "leaf" of the requested path.
You might also want to cache the structure in memory to prevent constantly reading from the file, e.g. could do something like ##config ||= YAML.parse(open('https://link_to_file/file.yaml')) or config = Rails.cache.fetch('config', expire_in: 1.hour) { ... }. And/or cache the API's HTTP response.

loading parameter files for data different sets

I need to analyse several sets of data which are associated with different parameter sets (one single set of parameters for each set of data). I'm currently struggling to find a good way to store these parameters such that they are readily available when analysing a specific dataset.
The first thing I tried was saving them in a script file parameters.m in the data directory and load them with run([path_to_data,'/parameters.m']). I understand, however, that this is not good coding practice and it also gave me scoping problems (I think), as changes in parameters.m were not always reflected in my workspace variables. (Workspace variables were only changed after Clear all and rerunning the code.)
A clean solution would be to define a function parameters() in each data directory, but then again I would need to add the directory to the search path. Also I fear I might run into namespace collisions if I don't give the functions unique names. Using unique names is not very practical on the other hand...
Is there a better solution?
So define a struct or cell array called parameters and store it in the data directory it belongs in. I don't know what your parameters look like, but ours might look like this:
parameters.relative_tolerance = 10e-6
parameters.absolute_tolerance = 10e-6
parameters.solver_type = 3
.
.
.
and I can write
save('parameter_file', 'parameters')
or even
save('parameter_file', '-struct', 'parameters', *fieldnames*)
The online help reveals how to use -struct to store fields from a structure as individual variables should that be useful to you.
Once you've got the parameters saved you can load them with the load command.
To sum up: create a variable (most likely a struct or cell array) called parameters and save it in the data directory for the experiment it refers to. You then have all the usual Matlab tools for reading, writing and investigating the parameters as well as the data. I don't see a need for a solution more complicated than this (though your parameters may be complicated themselves).

Sinatra coffeescript --bare?

I've done some searching on this, but I cannot find info. I'm building an application inside sinatra, and using the coffeescript templating engine. By default the compiled code is wrapped as such:
(function() {
// code
}).call(this);
I'd like to remove that using the --bare flag, so different files can access classes and so forth that I'm defining. I realize that having it more contained helps against variable conflicts and so forth, but I'm working on two main pieces here. One is the business logic, and arrangement of data in class structures. The other is the view functionality using raphaeljs. I would prefer to keep these two pieces in separate files. Since the two files wrapped as such cannot access the data, it obviously won't work. However, if you can think of a better solution than using the --bare option, I'm all ears.
Bare compilation is simply a bad practice. Each file should export to the global scope only the public objects that matter to the rest of your app.
# foo.coffee
class Foo
constructor: (#abc) ->
privateVar = 123
window.Foo = Foo # export
Foo is now globally available. Now if that pattern isn't practical, maybe you should rethink your structure a bit. If you have to export too may things, you nest and namespace things better, so that more data can be exposed through fewer global variables.
I support Alex's answer, but if you absolutely must do this, I believe my answer to the same question for Rails 3.1 is applicable here as well: Put the line
Tilt::CoffeeScriptTemplate.default_bare = true
somewhere in your application.