Puppet and Apache: ${name} gives 'main' instead of class name - apache

I'm trying to configure a few Apache virtual hosts with the puppetlabs/apache module. My issue is with the ${name} variable. I expected DocumentRoot to be set to /var/www/atoms.one, but instead it is set to /var/www/main.
What am I doing wrong?
My manifest:
class { apache: }
apache::vhost { 'atoms.one':
port => '80',
serveraliases => [ "*.${name}" ],
docroot => "/var/www/${name}",
directories => [
{ path => "/var/www/${name}", },
],
}

Inside a defined type's body, the special variable $name represents the name / title of the defined type instance. But you have not presented a defined-type body -- rather, you have presented a declaration of a defined-type instance, and one that appears at top scope, at that. The declaration does not create a scope for $name to mean anything different within than it does without.
I'm having trouble finding documentation for the meaning of $name outside the scope of a defined-type body, but I know from experience that inside a class it represents the class name. I suppose you are seeing the name of the top scope, for which "main" is a plausible value.
The bottom line is that $name does not provide the kind of shortcut you are trying to use it for. You could instead create a defined type wrapper of your own around apache::vhost, and do the shortcutting there. Alternatively, you could create your own variable to use instead of $name.

Related

Conditonal resource attributes

To install packages, I feed in data from Hiera into a for loop. Some packages require additional arguments. For packages that do not require an argument, I've set the value to undef, however, Chocolatey reads undef and complains.
How do I get the package resource to ignore the install_options attribute when it is blank or undef?
Hiera snippet:
profile::business::packages:
office365business:
version: latest
provider: chocolatey
arguments: ['/productid:O365BusinessRetail']
xmind:
version: latest
provider: chocolatey
arguments: undef
slack:
version: latest
provider: chocolatey
arguments: undef
Class example:
class profile::business(
Hash $packages,
){
if $::kernel == 'windows' {
$packages.each | $key, $value | {
package { "install_${key}" :
name => $key,
ensure => $value['version'],
provider => $value['provider'],
install_options => $value['arguments'],
notify => Reboot['after_profile_business'],
}
}
reboot { 'after_profile_business' :
apply => finished,
message => 'Reboot: Business profile applied.'
}
}
}
The best I can come up with is using an if clause to apply different instances of the package resource with or without install_options, depending on the value of arguments:
$packages.each | $key, $value | {
if $value['arguments'] != 'undef' {
package { "install_${key}" :
name => $key,
ensure => $value['version'],
provider => $value['provider'],
install_options => $value['arguments'],
notify => Reboot['after_profile_admin'],
}
} else {
package { "install_${key}" :
name => $key,
ensure => $value['version'],
provider => $value['provider'],
notify => Reboot['after_profile_admin'],
}
}
}
However, this seems rather clunky and I'm hoping someone might be able to show me a better way?
I've seen the Puppet Selector condition example, but I do not know if this will work for me.
T.I.A
This YAML fragment ...
arguments: undef
... sets the value of the 'arguments' key to the string 'undef'. That doesn;t mean the same thing on the Puppet side as the Puppet literal undef.
There are solutions. All of the best, IMO, revolve around representing absence of data via bona fide absence of data. That avoids any need for special reserved words. So suppose your data looked like this, instead:
profile::business::packages:
office365business:
version: latest
provider: chocolatey
arguments: ['/productid:O365BusinessRetail']
xmind:
version: latest
provider: chocolatey
slack:
version: latest
provider: chocolatey
Note that there is no entry bearing the arguments key where there are in fact no arguments to specify. If you have been rigorous and thorough about defining data types, then you may need to adjust your data type for these data to accommodate that, but so much the better because that would better describe the actual data semantics. That data modification probably resolves your issue by itself, because looking up a key that does not exist in a hash that does exist should yield undef (and there's also dig() if the undefinedness can occur at a higher level of a deep data structure).
Consider also, however, that Puppet has a shortcut for declaring that resource property values are drawn from a hash. That won't quite fit your present data because your keys are not the same as the needed property names, but you could either change the keys in your data or map them at the Puppet level. The latter might look like this:
# Defining the key / property name mappings here makes them clear, and is easy to
# change if you need to update the mappings
$mappings = { 'version' => 'ensure', 'arguments' => 'install_options' }
$packages.each |$package, $properties| {
# map the keys appearing in the data to Puppet property names, based on
# the hash defined above
$filtered_props = $properties.reduce({}) |$memo, $pair| {
$mapped_key = $pair[0] in $mappings ? { true => $mappings[$pair[0]], default => $pair[0] }
$memo + { $mapped_key => $pair[1] }
}
# one declaration covering all cases
package { "install_${package}" :
name => $package,
provider => $value['provider'],
notify => Reboot['after_profile_admin'],
* => $filtered_props,
}
}

Yii2 adding a property to the application

I would like to add a new property 'business' to the Yii2 application so I can access it like:
Yii::$app->business
I have tried adding it directly to the config file:
'Id' => 'app-frontend',
'name' => 'Application Name',
'business' => 'Business Name',
....
Which gives me an 'unknown property exception' for 'buisness'
After some searching I tried:
Yii::$app->session->set('app.business','Business Name');
Yii::$app->session->get('app.buisness');
But only works when I access it by session
I know how to create it in the params set up, but rather us the app->name. method.
I imagine I need to add the business property in the root model? But not sure where to drill into it at.
Any help to point me in the right direction please.
You can extend Application class, add required properties, and use it on bootstrap.
Create class for web:
class MyApplication extends \yii\web\Application {
public $supportname;
}
And use it in index.php:
(new MyApplication($config))->run();
You need to do the same for \yii\console\Application and yii script.

In Puppet, how to use defined node variables in an if clause

In a puppet class how should I test if a variable has been set in a node?
I use a VM name (like server1) and a domain name (like example.org) where users can reach the page. "example.org" won't be conveyed via a fact, so I need to pass it via a class parameter. I came up with this way to define the variable in a node block and use it in my test class for my settings.
node "VM1" {
class { 'test':
domainname => "example.org",
}
[...]
class test ($domainname) {
ini_setting {
'set_property':
ensure => present,
path => '/tmp/test.ini',
section => 'main',
setting => 'url',
value => "https://$domainname";
}
[...]
But now I want to add a condition that if $domainname isn't set then the $hostname fact should be used in its place.
ini_setting {
'set_property':
ensure => present,
path => '/tmp/test.ini',
section => 'main',
setting => 'url',
if $domainname !~ $hostname {
value => "https://$domainname";
} else {
value => "https://$hostname";
}
But now I get an error like this every time:
Error: Could not retrieve catalog from remote server: Error 500 on SERVER: Server Error: Syntax error at 'domainname'
What should I do instead?
The error message is explaining to you that if statements cannot appear inside resource declarations. There is, however, a different conditional form, called a "selector" that can appear inside resource declarations. It is Puppet's analog of the ternary ?: operator that appears in several languages.
Stylistically, though, it is usually better form to keep resource declarations as simple as possible. To that end, you should probably set a variable, conditionally, outside the resource declaration, and then use its value inside. Using your own conditional, that might look like this:
if $domainname !~ $hostname {
$url_value = "https://$domainname";
} else {
$url_value = "https://$hostname";
}
ini_setting {
'set_property':
ensure => present,
path => '/tmp/test.ini',
section => 'main',
setting => 'url',
value => $url_value;
}
Additionally, however, I note that your particular condition, repeated above, is highly suspect. In recent Puppet (version 4 and above), you should be using Puppet data types to both declare your class parameters and check them. In particular, if it is permissible to declare class test without providing a $domainname parameter, then you would declare that class like so:
# Using the Puppet v4+ type system
class test(
Optional[String] $domainname = undef
) {
# ...
, and would test whether a value was provided for $domainname like so:
if $domainname =~ Undef {
# ...
}
You cannot use the type system in earlier Puppet, but there you can rely on undefined variables to expand to nothing when you interpolate them:
# Using the Puppet v3- behavior
class test(
$domainname = undef
) {
# ...
if "$domainname" == "" {
# ...
}
# ...
}

Symfony 3 get all avaliable locales

Have some trouble getting all available locales in Symfony 3.
The idea is to create a custom language switcher.
I have
parameters:
locale: en
app.locales: en|fr|ru
I can get requested locale or user stored in session locale.
But how can i get all parameters.app.locales in Service of Controller on finally in Twig? So that i can have ar array like en|fr|ru and so on.
Thanks.
Because you have the locales specified as a parameter you can retrieve the parameter value depending on where you want it:
1. As service argument:
Pass the locales via constructor parameters by specifying in the service definition:
Service:
class SomeService {
private $locales;
public function __construct(array $locales)
{
$this->locales = $locales;
}
...
}
Service definition:
...\Service\SomeService:
arguments:
- '%app.locales%'
2. With the service container:
You can also retrieve parameters via the service container:
$locales = $this->container->getParameter('app.locales');
3. Pass locales to Twig
After getting the locales via above ways you can just pass them as variable just like normal Twig variables when rendering a template:
return $this->render('some.template.html.twig', [
'locales' => $locales,
]);
4. Set specific Twig parameters:
How to get config parameters in Symfony2 Twig Templates
Just came across this in Symfony 5.
Seems that there is no method for it in TranslatorInterface
Therefore the simplest way in my case would be to get all values from parameters
$locales = $this->getParameter('app_locales');
In my case
app_locales: en|fr|de|es|cs|nl|ru|uk|ro|pt_BR|pl|it|ja|id|ca|sl|hr|zh_CN|bg|tr|lt
defined in services.yaml

Defaults in Symfony2 routing not being passed properly

I am currently trying to configure a routing option in Symfony2 so /cms will route to /cms/role/view. However, the passing of defaults doesn't seem to work properly.
/src/MyProject/CMSBundle/Resources/config/routing.yml
MyProjectCMS_specific:
pattern: /cms/{page}/{option}
defaults: { _controller: MyProjectCMSBundle:Main:index, page: role, option: view }
requirements:
_method: GET
/src/MyProject/CMSBundle/Controller/MainController.php
<?php
namespace MyProject\CMSBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class MainController extends Controller
{
public function indexAction($page, $option)
{
$response = null;
/* Switch statement that determines the page to be loaded. */
return $response;
}
}
?>
The problem is that when I try to go to `localhost/app_dev.php/cms', it gives me the following error:
Controller "MyProject\CMSBundle\Controller\MainController::indexAction()" requires that you provide a value for the "$page" argument (because there is no default value or because there is a non optional argument after this one).
500 Internal Server Error - RuntimeException
However, if I try to visit localhost/app_dev.php/cms/role or localhost/app_dev.php/cms/role/view, it gives me the correct page. I've tried adding a default route to /cms, but it still gives me the same error. How is this possible and how can I fix this?
Thanks in advance.
I don't know what is the difference between what you wrote and
public function indexAction($page = "role", $option = "view")
but maybe you could try it and tell us.