I'm new to puppet so any help would be appreciated. I'm trying to pass static data into variable apache_version inside Puppet class depending on OS release version. This variable will be later used in .erb template file to configure apache according to version. For now my class looks like this:
class some_class_name () {
case $::operatingsystem {
'RedHat' : {
case $::operatingsystemrelease {
/^7\..*/ : { }
/^6\..*/ : { }
}
}
}
}
How can I define inside {} brackets this variable? As for .erb file it should be used like this:
<%- if #apache_version >= '2.4' -%>
set something
<%- else -%>
set something else
<%- end -%>
I was aiming for something like this:
class some_class_name () {
case $::operatingsystem {
'RedHat' : {
case $::operatingsystemrelease {
/^7\..*/ : { $apache_version = '2.4' }
/^6\..*/ : { $apache_version = '2.2' }
}
}
}
}
but it doesn't work.
Ok, I've managed to solve the issue. Now I'm using:
if $::operatingsystemrelease =~ /^7\..*/ {
$apache_version = '2.4'
} else {
$apache_version = '2.2'
}
in params.pp file. With this everything is being configured correctly.
It is better to use the $::operatingsystemmajrelease fact here:
if $::operatingsystemmajrelease == 7 {
$apache_version = '2.4'
} else {
$apache_version = '2.2'
}
I also think this is a good use-case for Puppet's selector:
$apache_version = $::operatingsystemmajrelease ? { 7 => '2.4', default => '2.2' }
Related
I'm using generator-jhipster and I want to create blueprints for entity-client. After writing entity files, a postWriting function will call addEnitiyToMenu in generator-jhipster/generators/client/needle-api/needle-client-react.js to add new entity generated to file menu/entities.tsx
I need to override this function to write a different entityEntry with original one.
But I can't find the template for it. What should I do?
I found that I can write these function by my own. There is example code if you need
function generateFileModel(aFile, needleTag, ...content) {
return {
file: aFile,
needle: needleTag,
splicable: content,
};
}
function addBlockContentToFile(rewriteFileModel, generator) {
try {
return jhipsterUtils.rewriteFile(rewriteFileModel, generator);
} catch (e) {
console.error(e);
return null;
}
}
function addToMenu() {
if (this.skipClient) return;
if (!this.embedded) {
this.addEntityToModule();
const entityMenuPath = `${this.CLIENT_MAIN_SRC_DIR}app/shared/layout/menus/entities.tsx`;
const entityEntry =
// prettier-ignore
this.stripMargin(`|<Menu.Item key="${this.entityStateName}" icon={<FileOutlined />}>
| <Link to="/${this.entityStateName}">
| ${this.enableTranslation ? `<Translate contentKey="global.menu.entities.${this.entityTranslationKeyMenu}" />` : `${_.startCase(this.entityStateName)}`}
| </Link>
| </Menu.Item>`);
const rewriteFileModel = generateFileModel(entityMenuPath, 'jhipster-needle-add-entity-to-menu', entityEntry);
addBlockContentToFile(rewriteFileModel, this);
}
}
function replaceTranslations() {
if (this.clientFramework === VUE && !this.enableTranslation) {
if (!this.readOnly) {
utils.vueReplaceTranslation(this, [
`app/entities/${this.entityFolderName}/${this.entityFileName}.vue`,
`app/entities/${this.entityFolderName}/${this.entityFileName}-update.vue`,
`app/entities/${this.entityFolderName}/${this.entityFileName}-details.vue`,
]);
} else {
utils.vueReplaceTranslation(this, [
`app/entities/${this.entityFolderName}/${this.entityFileName}.vue`,
`app/entities/${this.entityFolderName}/${this.entityFileName}-details.vue`,
]);
}
}
}
A little bit confuse about this simple use case :
I want to add a closure around an other one only with conditions.
For the moment, I only succeed to do this :
if(condition) {
my_root_closure {
my_main_closure {
do_stuff()
}
}
} else {
my_main_closure {
do_stuff()
}
}
I would like to do this without repeat the my_main_closure bloc.
To avoid repetition, you could create new closure that calls my_main_closure and store it in a variable:
def mmc = {
my_main_closure {
do_stuff()
}
}
if(condition) {
my_root_closure( mmc )
} else {
mmc()
}
Why does this not work?
When I run the feature file as "Run as Cucumber Feature" I get an error
java.lang.AssertionError: Undefined default URL for page object PageObject
Page Object
#DefaultUrl("page:register.page")
public class AccountCreationPage extends PageObject {
...
}
Config File (serenity.config)
environments {
local {
webdriver.base.url = "https://localhost"
}
demo {
webdriver.base.url = "https://demo.example.com"
}
prod {
webdriver.base.url = "https://example.com"
}
all {
home.page = "#{webdriver.base.url}"
register.page = "#{webdriver.base.url}/register"
}
}
https://johnfergusonsmart.com/environment-specific-configuration-in-serenity-bdd/
shows the use of #DefaultUrl("page:register.page")
Serenity-Cucumber4. Java. Eclipse.
the config file is required to have default as an entry 🤦
environments {
default {
webdriver.base.url = "https://localhost"
}
...
all {
home.page = "#{webdriver.base.url}"
register.page = "#{webdriver.base.url}/register"
}
}
I am trying to overwrite a template file located in vendor/bolt/bolt/app/view/twig/editcontent/fields/_block.twig (I want to replace the "block selection" dropdown). Regarding to #1173, #1269, #5588, #3768 and #5102 this is not supported by default so I have to write a extension for this. So I tried this:
BackendBlockSelectionExtension:
namespace Bundle\Site;
use Bolt\Filesystem\Adapter\Local;
use Bolt\Filesystem\Filesystem;
use Silex\Application;
use Bolt\Extension\SimpleExtension;
class BackendBlockSelectionExtension extends SimpleExtension
{
public function getServiceProviders()
{
return [
$this,
new BackendBlockSelectionProvider(),
];
}
}
BackendBlockSelectionProvider:
namespace Bundle\Site;
use Bolt\Filesystem\Adapter\Local;
use Bolt\Filesystem\Filesystem;
use Silex\Application;
use Silex\ServiceProviderInterface;
class BackendBlockSelectionProvider implements ServiceProviderInterface
{
public function register(Application $app)
{
$side = $app['config']->getWhichEnd();
if ($side == 'backend') {
$path = __DIR__ . '/App/templates/Backend';
$filesystem = $app['filesystem'];
$filesystem->mountFilesystem('bolt', new Filesystem(new Local($path)));
$app['twig.loader.bolt_filesystem'] = $app->share(
$app->extend(
'twig.loader.bolt_filesystem',
function ($filesystem, $app) {
$path = __DIR__ . 'src/App/templates/Backend/';
$filesystem->prependPath($path, 'bolt');
return $filesystem;
}
)
);
}
}
public function boot(Application $app)
{
}
}
This seems to do the job, but I got an error I don't understand at all: The "bolt://app/theme_defaults" directory does not exist.
So my final question is: Does anyone have some example code how to overwrite/modify vendor/bolt/bolt/app/view/twig/editcontent/fields/_block.twig without touching the vendor folder?
This should be much simplier than this.
In your extension class overwrite protected function registerTwigPaths() function like this:
protected function registerTwigPaths()
{
if ($this->getEnd() == 'backend') {
return [
'view' => ['position' => 'prepend', 'namespace' => 'bolt']
];
}
return [];
}
private function getEnd()
{
$backendPrefix = $this->container['config']->get('general/branding/path');
$end = $this->container['config']->getWhichEnd();
switch ($end) {
case 'backend':
return 'backend';
case 'async':
// we have async request
// if the request begin with "/admin" (general/branding/path)
// it has been made on backend else somewhere else
$url = '/' . ltrim($_SERVER['REQUEST_URI'], $this->container['paths']['root']);
$adminUrl = '/' . trim($backendPrefix, '/');
if (strpos($url, $adminUrl) === 0) {
return 'backend';
}
default:
return $end;
}
}
Now you can crete a view directory in your extensions directory in which you can define templates in structure like in Bolt's default. I would start with copy and overwrite.
In Objective-C, I know how passing a protocol as parameter:
- (void)MyMethod:(Protocol *)myparameter
But in Swift there is no more Protocol type.
How can I pass a protocol as parameter without knowing which is ?
In one of your comments you say:
"I want create a method which return an array of type of class which implements a desired protocol."
Have you tried something like the following:
//notice the use of #objc here
#objc protocol AlertProtocol
{
func getMyName()->String
}
class Class1 : AlertProtocol
{
let name = "Object 1"
func getMyName() -> String
{
return name
}
}
class Class2 : AlertProtocol
{
let name = "Object 2"
func getMyName() -> String
{
return name
}
}
//borrowing from and refactoring siLo's answer
func classesConformingToProtocol(proto:Protocol) -> [AnyClass]
{
let availableClasses : [AnyClass] = [ Class1.self, Class2.self ]
var conformingClasses = Array<AnyClass>()
for myClass : AnyClass in availableClasses
{
if myClass.conforms(to: proto)
{
conformingClasses.append(myClass)
}
}
return conformingClasses
}
Then use the above structure like this:
let classes = classesConformingToProtocol(AlertProtocol.self)
The tricky part that does the work is the "#objc" that exposes the protocol to the objective c runtime and allows us to pass any "Protocol Type" as a parameter.
Probably at some point in the future we will be able to do this in a "pure" Swift way.
Here is what I have tried:
#objc protocol Walker
{
func walk()
}
#objc protocol Runner
{
func run()
}
#objc class Zombie : Walker
{
func walk () { println("Brains...") }
}
#objc class Survivor : Runner
{
func run() { println("Aaaah, zombies!") }
}
func classesConformingToProtocol(proto:Protocol) -> AnyClass[]
{
let availableClasses : AnyClass[] = [ Zombie.self, Survivor.self ]
var conformingClasses = Array<AnyClass>()
for myClass : AnyClass in availableClasses
{
if myClass.conformsToProtocol(proto)
{
conformingClasses.append(myClass)
}
}
return conformingClasses
}
// This does not work
let walkers = classesConformingToProtocol(Walker.self)
let runners = classesConformingToProtocol(Runner.self)
I have been unable to convert Swift's Metatype information into a Protocol object.
In swift 2.0, I use it like this before:
classA.conformsToProtocol(XXXProtocol.self as! Protocol)
It doesn't works fine...
Look the definition of Protocol:
// All methods of class Protocol are unavailable.
// Use the functions in objc/runtime.h instead.
#available(iOS 2.0, *)
public class Protocol {
}
All are unavailable...and I don't know which to use instead in objc/runtime.h
So I have to use this method:
if ClassA is protocol<XXXProtocol> {
// do something
}
Currently, it works...
If you don't allow use #objc (because yours protocols have property, for example), the only solution that I found is with closure. Then, you need use a closure to use a protocol and return a value.
protocol Proto { }
protocol Proto2 { }
class Foo: Proto { }
class Bar: Proto, Proto2 { }
class Baz: Proto2 { }
class Qux { }
func printConforms(classList: [AnyClass], protoCond: (AnyClass) -> Any?) {
for i in classList {
print(i, terminator: " -> ")
if protoCond(i) != nil {
print("is subscriber")
} else {
print("NOT IS subscriber")
}
}
}
let myClasses: [AnyClass] = [Foo.self, Bar.self, Baz.self, Qux.self]
printConforms(classList: myClasses, protoCond: { $0 as? Proto.Type })
More complete example: https://gist.github.com/brunomacabeusbr/eea343bb9119b96eed3393e41dcda0c9
Edit
Another better solution is using generics, for example:
protocol Proto { }
class Foo: Proto { }
class Bar: Proto { }
class Baz { }
func filter<T>(classes: [AnyClass], byConformanceTo: T.Type) -> [AnyClass] {
return classes.filter { $0 is T }
}
filter(classes: [Foo.self, Bar.self, Baz.self], byConformanceTo: Proto.Type.self)
// return [Foo.self, Bar.self]
Worked out a way today (Xcode 6.1):
Firstly, the protocol must be marked as #objc for any checking to work.
Then use an "if let" cast to check for conformance.
#objc protocol MyProtocol {
var protocolValue: Int { get set }
}
if let conformingObject = someObject as? MyProtocol {
// conformingObject is now someObject cast to MyProtocol
conformingObject.protocolValue = 3
}