How to format chocolatey params in puppet manifest - puppet

The following choco install command works fine:
choco Install 'InstallTest' -y --source 'C:\installtest' --params="'/serverinstance:MyServer /buildtype:OTP'"
I now have the following, in a Puppet manifest:
package { 'InstallTest':
ensure => installed,
install_options => ['-params','"', /serverinstance:MyServer, /buildtype:OTP, '"'],
source => 'c:\installtest',
}
I thought that I was correctly covering spaces with commas, etc, but puppet parser throws the following error:
puppet : [1;31mError: Could not parse for environment production: invalid byte sequence in UTF-8[0m
Without the install_options line, it compiles fine.
What should the correct syntax be?

The problem is here:
install_options => ['-params','"', /serverinstance:MyServer, /buildtype:OTP, '"'],
Although Puppet can accept bare words as strings, there are limitations on the content of such strings. The one relevant here is that they must
Begin with a lower case letter, and contain only letters, digits, hyphens (-), and underscores (_).
Thus, you're looking for this:
install_options => ['-params', '"', '/serverinstance:MyServer', '/buildtype:OTP', '"'],
Overall, its better style to quote substantially all strings, whether they need it or not. That's clearer, and it will keep you out of trouble.

Related

parsing SVG in webpack

I have created a project on Symfony 5. I am receiving an error in webpack when I run 'yarn build'. I am trying to fix it from few days but without success, so I decided to ask for some help :)
This is the error I am getting:
I have enabled postCssLoader in my webpack.config and created postss.config.js in my root directory
.enablePostCssLoader()
postss.config.js File
module.exports = {
plugins: [
require('autoprefixer'),
require('postcss-svgo'),
require('postcss-inline-svg'),
require('postcss-write-svg'),
]
}
And here is a sample of svg I am trying to write in my css
.custom-checkbox .custom-control-input:checked~.custom-control-label::after {
background-image: url('data:image/svg+xml,%3csvg xmlns=\'http://www.w3.org/2000/svg\' width=\'8\'
height=\'8\' viewBox=\'0 0 8 8\'%3e%3cpath fill=\'%23fff\' d=\'M6.564.75l-3.59 3.612-1.538-
1.55L0 4.26l2.974 2.99L8 2.193z\'/%3e%3c/svg%3e')
}
If the error transfers code verbatim, then there are two line breaks (and indentation) that makes the property invalid (see "CRLF": ..width=\'8\'CRLF height.. - this one you can backslash-escape in CSS, and ..1.538-CRLF 1.55L.. - this one with indentation separates numeral making path data invalid - you have to remove all whitespace between minus and digit). If this is it, simply removing line breaks (and suprefluous whitespace) should fix it:
background-image: url('data:image/svg+xml,%3csvg xmlns=\'http://www.w3.org/2000/svg\' width=\'8\' height=\'8\' viewBox=\'0 0 8 8\'%3e%3cpath fill=\'%23fff\' d=\'M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z\'/%3e%3c/svg%3e')
If code snippet you provided is not directly from your source code, then you have probably some formarrter breaking it in the process (?)
N.B. you don't usually have to escape SVG datauris so much, you could go with url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8' fill='%23fff'><path d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/></svg>") (i.e. the only escaped sequence is #->%23) and most interpreters should pick it up just fine. I'm not sure about your build stack, but I'd guess that "safe over-escaped format for obsolete IEs" could be produced as the build result; and if you use preprocessor you can embed 'dataurized' external resources, what could prevent such formatting accidents. (Ah, that's probably what the postcss-inline-svg is doing for you.)

cookie cutter: what's the easiest way to specify variables for the prompts

Is there anything that offers replay-type functionality, by pointing at a predefined prompt-answer file?
What works and what I'd like to achieve.
Let's take an example, using a cookiecutter to prep a Python package for pypi
cookiecutter https://github.com/audreyr/cookiecutter-pypackage.git
You've downloaded /Users/jluc/.cookiecutters/cookiecutter-pypackage before. Is it okay to delete and re-download it? [yes]:
full_name [Audrey Roy Greenfeld]: Spartacus πŸ‘ˆ constant for me/my organization
email [audreyr#example.com]: spartacus#example.com πŸ‘ˆ constant for me/my organization
...
project_name [Python Boilerplate]: GladiatorRevolt πŸ‘ˆ this will vary.
project_slug [q]: gladiator-revolt πŸ‘ˆ this too
...
OK, done.
Now, I can easily redo this, for this project, via:
cookiecutter https://github.com/audreyr/cookiecutter-pypackage.git --replay
This is great!
What I want:
Say I create another project, UnleashHell.
I want to prep a file somehow that has my developer-info and project level info for Unleash. And I want to be able to run it multiple times against this template, without having to deal with prompts. This particular pypi template gets regular updates, for example python 2.7 support has been dropped.
The problem:
A --replay will just inject the last run for this cookiecutter template. If it was run against a different pypi project, too bad.
I'm good with my developer-level info, but I need to vary all the project level info.
I tried copying the replay file via:
cp ~/.cookiecutter_replay/cookiecutter-pypackage.json unleash.json
Edit unleash.json to reflect necessary changes.
Then specify it via --config-file flag
cookiecutter https://github.com/audreyr/cookiecutter-pypackage.git --config-file unleash.json
I get an ugly error, it wants YAML, apparently.
cookiecutter.exceptions.InvalidConfiguration: Unable to parse YAML file .../000.packaging/unleash.json. Error: None of the known patterns match for {
"cookiecutter": {
"full_name": "Spartacus",
No problem, json2yaml to the rescue.
That doesn't work either.
cookiecutter.exceptions.InvalidConfiguration: Unable to parse YAML file ./cookie.yaml. Error: Unable to determine type for "
full_name: "Spartacus"
I also tried a < stdin redirect:
cookiecutter.prompts.txt:
yes
Spartacus
...
It doesn't seem to use it and just aborts.
cookiecutter https://github.com/audreyr/cookiecutter-pypackage.git < ./cookiecutter.prompts.txt
You've downloaded ~/.cookiecutters/cookiecutter-pypackage before. Is it okay to delete and re-download it? [yes]
: full_name [Audrey Roy Greenfeld]
: email [audreyr#example.com]
: Aborted
I suspect I am missing something obvious, not sure what. To start with, what is the intent and format expected for the --config file?
Debrief - how I got it working from accepted answer.
Took accepted answer, but adjusted it for ~/.cookiecutterrc usage. It works but the format is not super clear. Especially not on the rc which has to be yaml, though that's not always/often the case with rc files.
This ended up working:
file ~/.cookiecutterrc:
without nesting under default_context... tons of unhelpful yaml parse errors (on a valid yaml doc).
default_context:
#... cut out for privacy
add_pyup_badge: y
command_line_interface: "Click"
create_author_file: "y"
open_source_license: "MIT license"
# the names to use here are:
# full_name:
# email:
# github_username:
# project_name:
# project_slug:
# project_short_description:
# pypi_username:
# version:
# use_pytest:
# use_pypi_deployment_with_travis:
# add_pyup_badge:
# command_line_interface:
# create_author_file:
# open_source_license:
I still could not get a combination of ~/.cookiecutterrc and a project-specific config.yaml to work. Too bad that expected configuration format is so lightly documented.
So I will use the .rc but enter the project name, slug and description each time. Oh well, good enough for now.
You are near.
Try this cookiecutter https://github.com/audreyr/cookiecutter-pypackage.git --no-input --config-file config.yaml
The --no-input parameter will suppress the terminal user input, it is optional of course.
The config.yaml file could look like this:
default_context:
full_name: "Audrey Roy"
email: "audreyr#example.com"
github_username: "audreyr"
cookiecutters_dir: "/home/audreyr/my-custom-cookiecutters-dir/"
replay_dir: "/home/audreyr/my-custom-replay-dir/"
abbreviations:
pp: https://github.com/audreyr/cookiecutter-pypackage.git
gh: https://github.com/{0}.git
bb: https://bitbucket.org/{0}
Reference to this example file: https://cookiecutter.readthedocs.io/en/1.7.0/advanced/user_config.html
You probably just need the default_context block since that is where the user input goes.

Win10: ASDF can't load system (ASDF_OUTPUT_TRANSLATION error)

Update 2
I think #farΓ© is right, it's an output translation problem.
So I declared the evironment variable ASDF_OUTPUT_TRANSLATIONS and set it to E:/. Now (asdf:require-system "my-system") yields a different error: Uneven number of components in source to destination mapping: "E:/" which led me to this SO-topic.
Unfortunately, his solution doesn't work for me. So I tried the other answer and set ASDF_OUTPUT_TRANSLATIONS to (:output-translations (t "E:/")). Now I get yet another error:
Invalid source registry (:OUTPUT-TRANSLATIONS (T "E:/")).
One and only one of
:INHERIT-CONFIGURATION or
:IGNORE-INHERITED-CONFIGURATION
is required.
(will be skipped)
Original Posting
I have a simple system definition but can't get ASDF to load it.
(asdf-version 3.1.5, sbcl 1.3.12 (upgraded to 1.3.18 AMD64), slime 2.19, Windows 10)
What I have tried so far
Following the ASDF manual: "4.1 Configuring ASDF to find your systems"
There it says:
For Windows users, and starting with ASDF 3.1.5, start from your
%LOCALAPPDATA%, which is usually ~/AppData/Local/ (but you can ask in
a CMD.EXE terminal echo %LOCALAPPDATA% to make sure) and underneath
create a subpath config/common-lisp/source-registry.conf.d/
That's exactly what I did:
Echoing %LOCALAPPDATA% which evaluates to C:\Users\my-username\AppData\Local
Underneath I created the subfolders config\common-lisp\source-registry.conf.d\ (In total: C:\Users\my-username\AppData\Local\config\common-lisp\source-registry.conf.d\
The manual continues:
there create a file with any name of your choice but with the type conf, for instance 50-luser-lisp.conf; in this file, add the following line to tell ASDF to recursively scan all the subdirectories under /home/luser/lisp/ for .asd files: (:tree "/home/luser/lisp/")
That’s enough. You may replace /home/luser/lisp/ by wherever you want to install your source code.
In the source-registry.conf.d folder I created the file my.conf and put in it (:tree "C:/Users/my-username/my-systems/"). This folder contains a my-system.asd.
And here comes the weird part:
If I now type (asdf:require-system "my-system") in the REPL I get the following error:
Can't create directory C:\Users\my-username\AppData\Local\common-lisp\sbcl-1.3.12-win-x86\C\Users\my-username\my-systems\C:\
So the problem is not that ASDF doesn't find the file, it does -- but (whatever the reason) it tries to create a really weird subfolder hierarchy which ultimately fails because at the end it tries to create the folder C: but Windows doesn't allow foldernames containing a colon.
Another approach: (push path asdf:*central-registry*)
If I try
> (push #P"C:/Users/my-username/my-systems/" asdf:*central-registry*)
(#P"C:/Users/my-username/my-systems/"
#P"C:/Users/my-username/AppData/Roaming/quicklisp/quicklisp/")
> (asdf:require-system "my-system")
I get the exact same error.
I don't know what to do.
Update
Because of the nature of the weird path ASDF was trying to create I thought maybe I could bypass the problem by specifying a relative path instead of an absolute one.
So I tried
  (:tree "\\Users\\my-username\\my-systems")
in my conf file. Still the same error.
Ahem. It looks like an output-translations problem.
I don't have a Windows machine right now, but this all used to work last time I tried.
Can you setup some ad hoc output-translations for now that will make it work?

Inserting a string into a file with Puppet with iteration

I'm running a .each iteration with Puppet:
$extensions_list = ["RT::Extension::ActivityReports",
"RT::Extension::JSGantt",
]
$extensions_list.each |$extls| {
cpan { $extls:
ensure => present,
require => Class['::cpan'],
}
}
As you can see I'm just installing two Perl modules with a cpan module from Puppet Forge. This part works just as expected.
What I would like to happen is each time a new Perl module is installed in this way it will be added to added to the config line of RT (Request Tracker). That file lives here:
/opt/rt4/etc/RT_SiteConfig.pm
and the format of the line is:
Plugins('RT::MODULE::ONE RT::MODULE::TWO');
So, in the end I would like it to look like this:
Plugins('RT::Extension::ActivityReports RT::Extension::JSGantt');
Having Puppet add each new module in turn to that line as they are installed. As in if I decided to install RT::Authen::ExternalAuth a month from now I can just add it to my above iteration and after Puppet runs this:
Plugins('RT::Extension::ActivityReports RT::Extension::JSGantt');
would become this:
Plugins('RT::Extension::ActivityReports RT::Extension::JSGantt RT::Authen::ExternalAuth');
With no other intervention on my part then to add it to the iteration statement.
Assuming that you don't have any other Puppet code managing /opt/rt4/etc/RT_SiteConfig.pm, then you have a few options for making sure that you have the correct Plugins line in that file.
If you only want to manage just that one line then I would recommend using join and a file_line resource from stdlib.
For example:
include stdlib
$ext_string = join($extensions_list, ' ')
file_line { 'rt extensions':
ensure => present,
path => '/opt/rt4/etc/RT_SiteConfig.pm',
line => "Plugins('${ext_string}');",
match => '^\s*Plugins\(',
}
This will add a line containing the list of plugins and will replace any existing plugin line.
If there are several settings that you want to manage then it might make sense to just templatize the entire file. In that case you could simply have the line
Plugins('<%= #extensions_list.join(' ') %>');
in your template.

CFENGINE: policy to perform bunch of commands on bunch of packages

I have to create one CFENGINE 3 Policy which should take input from defined input list and then want to perform some bunch of commands on that set one by one.
For Eg:
For only one Package here I have the example:
bundle agent test_tester_install
{
commands:
"/usr/bin/wget http://something.example.com/perl-modules/Test-Tester-0.104.tar.gz;
/usr/bin/gunzip Test-Tester-0.104.tar.gz;
tar -xf Test-Tester-0.104.tar;
cd Test-Tester-0.104;
/usr/bin/perl Makefile.PL;
/usr/bin/make;
/usr/bin/make install"
contain => standard,
classes => satisfied("Test-Tester Installed");
}
body contain standard
{
useshell => "true";
exec_owner => "root";
}
body classes satisfied(new_class)
{
promise_repaired => { "$(new_class)" };
}
But I am not sure that how to do it if I want to do the same for 100 packages. I think "slist would do this but how exactly i need to draft that policy i am not sure"
This is very similar to applying "for" loop in bash shell where we iterate input one by one and perform some operations
Experts Please help
The way to do something like this is to use CFEngine's implicit looping. You store the values in a list, and then iterate over them in the promises. For your example, it would be something like this:
bundle agent install
{
vars:
"packages" slist => { "Test-Tester-0.104", "Foo-Bar-1.001" }; # etc.
commands:
"/usr/bin/wget http://something.example.com/perl-modules/$(packages).tar.gz;
/usr/bin/gunzip $(packages).tar.gz;
tar -xf $(packages).tar;
cd $(packages);
/usr/bin/perl Makefile.PL;
/usr/bin/make;
/usr/bin/make install"
contain => standard,
classes => satisfied(canonify("$(packages)-installed"));
}
Note that I'm using $(package) whenever you previously had Test-Tester-0.104. Of course this only works if all the names are consistent in this respect. To add more, you'd only need to add the names to the packages variable. Not also that I used canonify() to make the string that gets passed to the satisfied() body a valid class name.
Now, if you are going to be doing a lot of installs like this, what I would suggest is defining a new package_method definition, which takes care of following the right steps internally, so that in your policy you can have something much cleaner, like this:
vars:
"packages" slist => { "Test-Tester-0.104", "Foo-Bar-1.001" }; # etc.
packages:
"$(packages)"
package_policy => "add",
package_method => perlsrcpkg; # or whatever you call your new package_method
You can find the documentation for packages promises here: http://cfengine.com/docs/3.5/reference-promise-types-packages.html#packages, and a bunch of package_method definition examples in the CFEngine Standard Library: https://github.com/cfengine/masterfiles/blob/master/lib/3.5/packages.cf
Finally, if the packages you are installing are from CPAN, you could just use the Packages::Installed::cpanm sketch from the Design Center: https://cfengine.com/cfengine-design-center/sketches/packages-cpan-cpanm

Resources