Conditional logic on whether to include subclass - puppet

I'm trying to edit the init.pp file to only include a subclass if a variable has been set. I've initialized the variables as undef, however when I do the IF statement as below it errors and says:
Syntax error at 'if'; expected '}'
When I write it as a case statement, it works fine but not as an IF. Any idea why that is?
class {'wlsvr':
}
->
case $jdbc_filename {
undef: {}
default: {class {'jdbc':}}
}
->
if $managedsvr_name != undef {
class {'managedsvr':
}
}

Please rid yourself of the unfortunate habit of using
->
between every other Puppet statement.
This chainging arrow introduces a dependency between the resources/classes it connects. This should be used only when a dependency is actually needed. Issues you are opening yourself to
gratuitous dependency trees when building dependencies between classes (you do that here)
issues when refactoring code, because if and cases statements do not (always) form the equivalent of resources or classes
As an aside, it is also beneficial to avoid the
class { 'classname': }
syntax for declaring classes and prefer
include classname
instead, because the former costs you the singleton semantics of Puppet classes.

Using an chaining arrow before an if statement is illegal syntax. From the puppet documentation on Relationships and Ordering:
Operands
The chaining arrows accept the following types of operands on either side of the arrow:
Resource references, including multi-resource references
Resource declarations
Resource collectors
I'm not sure why it allows case statements and not if statements, but I don't think it's best practice to chain either of them.

Related

How to define and call a function in Jenkinsfile?

I've seen a bunch of questions related to this subject, but none of them offers anything that would be an acceptable solution (please, no loading external Groovy scripts, no calling to sh step etc.)
The operation I need to perform is a oneliner, but pipeline limitations made it impossible to write anything useful in that unter-language...
So, here's minimal example:
#NonCPS
def encodeProperties(Map properties) {
properties.collect { k, v -> "$k=$v" }.join('|')
}
node('dockerized') {
stage('Whatever') {
properties = [foo: 123, bar: "foo"]
echo encodeProperties(properties)
}
}
Depending on whether I add or remove #NonCPS annotation, or type declaration of the argument, the error changes, but it never gives any reason for what happened. It's basically random noise, that contradicts the reality of the situation (at times it would claim that some irrelevant object doesn't have a method encodeProperties, other times it would say that it cannot find a method encodeProperties with a signature that nobody was trying to call it with (like two arguments instead of one) and so on.
From reading the documentation, which is of disastrous quality, I sort of understood that maybe functions in general aren't serializable, and that is why you need to explain this explicitly to the Groovy interpreter... I'm sorry, this makes no sense, but this is roughly what documentation says.
Obviously, trying to use collect inside stage creates a load of new errors... Which are, at least understandable in that the author confesses that their version of Groovy doesn't implement most of the Groovy standard...
It's just a typo. You defined encodeProperties but called encodeProprties.

Groovy - Type Check Closure Code Before Execution

I have a Groovy script that lets the user define some dynamic properties and methods and later executes a user-defined closure. A script would look like this:
// init properties and methods dynamically at runtime
context.prop1 = "Some test value"
context.method1 = { String input ->
"exec " + input.toUpperCase()
}
// "this" is set to the context variable from above
run {
println method1( prop1 )
}
So in the beginning of the script, a context is initialized with user-defined properties (e.g. prop1) and methods (e.g. method1). The context is then used as this pointer in the run closure. I have achieved this by dynamically extending the meta class of the context and setting the context as delegate of the run closure (with DELEGATE_FIRST as resolves strategy).
Currently I am struggling at type checking. Before executing the run closure, I would like to check if method1 really expects prop1. I have looked into the DelegatesTo annotation, but that doesn't seem to work for dynamically extended objects. I have also played with the AST, but since my knowledge on that topic is limited, I haven't come up with a solution. If what I want to achieve is possible, any pointers in the right direction would be greatly appreciated.
You want to add a method to a context at runtime and then type check this before execution of that method.
Type checking is done at compile time. That is before anything of your program is executed. There is normally no chance this can ever check anything that will only happen at runtime, unless you have a way to statically declare it and give the compiler the power to do the check. But this means normally, you will have to do static compilation.
One way would be to use type checking extensions, but I think in your case that might be overkill. A more simple way would be to use extension modules. And the most simple way would be to use custom script base class.
But for any of these solution you will need static compilation to really have type checking, same for DelegatesTo (which is more used in combination with extension modules). For a type checked DSL a mix of type checking extensions and extension modules can work very well. But you will of course loose more dynamic features of the language and some simplicity.

xtext inferrer: multiple entities

I am very new to Xtext/Xtend, therefore apologies in advance if the answer is obvious.
I would like to allow the end-users of my DSL to define a 'filter', that when applied and 'returns' true it means that they want to 'filter out' the given entity of data from consideration.
I want to allow them 2 ways of defining the filter
A) by introspecting the attributes of a given data object and apply basic rules like
if (obj.field1<CURRENT_DATE && obj.field2=="EXPIRED)
{ return true;} else {return false;}
B) by executing a controlled snippet using 'eval' of my host language
In other words, the user would be expected to type into a string/code block a valid
code snippet of the hosting language
I had decided that the easiest way for me support case A) would be to leverage the XBase rules (including expressions/etc)
Therefore I defined filters (mostly copying the ideas from Lorenzo's book)
Filter:
(FilterDSL | FilterCode);
FilterDSL:
'filterDSL' (type=JvmTypeReference)? name=ID
'(' (params+=FullJvmFormalParameter (',' params+=FullJvmFormalParameter)*)? ')'
body=XBlockExpression ;
FilterCode:
'filterCode' (type=JvmTypeReference)? name=ID
'(' (params+=FullJvmFormalParameter (',' params+=FullJvmFormalParameter)*)? ')'
'{'
body=STRING
'}';
Now when trying to implement the Java mapping for my DSL, via the inferrer stub in Xtend -- I am running into multiple problems.
All of them likely indicate that I am missing some fundamental understanding
Problem 1) fl.body is not defined. fl Is of type Filter, not FilterDSL or FilterCode
And I do not understand how to check what type a given instance is of, so that I can access the content of a 'body' feature.
Problem 2) I do not understand where 'body' attribute in the inferrer method is defined and why. Is this part of ECore? (I could not find it)
Problem 3) what's the proper way to allow a user to specify a code block? String seems to be not the right thing as it does not allow multiline
Problem 4) How do I correctly convert a code block into something that is accepted by the 'body' such that it ends up in the generated code.
Problem 5) How do I setup multiple inferrers (as I have more than one thing for which I need the code generated (mostly) by xBase code generator)
Appreciate in advance any suggestions, or pointer to code examples solving similar problems.
As a side observation, Inferrer and its interplay with XBase has sofar been the most confusing and difficult thing to understand.
in general: have a look at the xtend docs at xtend-lang.org
You can do a if (x instanceof Type) or a switch statement with Type guards (see domain model example)
i dont get that question. both your FilterDSL and FilterCode EClasses should have a field+getter/setter named body, FilterCode of type String, FilterDSL of type XBlockExpression. The JvmTypesBuilder add extension methods to JvmOperation called setBody(String) and setBody(XExpression), syntax sugar lets you call body = .... instead of setBody(...)
(btw you can do crtl+click to find out where a thing is defined)
strings are actually multiline
is answered by (2)
you dont need multiple inferrers, you can infer multiple stuff e.g. by calling toClass or toField multiple times for the same input

puppet style, what does "prefer metaparameters to relationship declarations" *mean*?

Looking at the Relationship Declarations section in the Puppet Style Guide about the '->' arrows, where 'x->y' means that y requires x to be installed before y, it says:
When possible, you should prefer metaparameters to relationship declarations.
that's a lot of syllables. Is that saying that you should prefer this
file { "/home/${user}/.ssh":
require => User[$user],
...
}
and not use the arrows like this?
User[$user] -> file { "/home/${user}/.ssh":
...
}
file { "/home/${user}/.ssh":
require => User[$user],
...
}
1.The above code even works with different manifests, when they are part of same catalog. So if you use metaparameters you have less work when you get a modification in future(unfortunately).
2.Chaining arrows is best used for Resource collectors, when you have to make relationship more than one resource, you can have this instead of putting require/before in all the resources.

Ignore certain TypeScript compile errors?

I am wondering if there is a way to ignore certain TypeScript errors upon compilation?
I basically have the same issues most people with large projects have around using the this keyword, and I don't want to put all my classes methods into the constructor.
So I have got an example like so:
TypeScript Example
Which seems to create perfectly valid JS and allows me to get around the this keyword issue, however as you can see in the example the typescript compiler tells me that I cannot compile that code as the keyword this is not valid within that scope. However I don't see why it is an error as it produces okay code.
So is there a way to tell it to ignore certain errors? I am sure given time there will be a nice way to manage the this keyword, but currently I find it pretty dire.
== Edit ==
(Do not read unless you care about context of this question and partial rant)
Just to add some context to all this to show that I'm not just some nut-job (I am sure a lot of you will still think I am) and that I have some good reasons why I want to be able to allow these errors to go through.
Here are some previous questions I have made which highlight some major problems (imo) with TypeScript current this implementation.
Using lawnchair with Typescript
Issue with child scoping of this in Typescript
https://typescript.codeplex.com/discussions/429350 (And some comments I make down the bottom)
The underlying problem I have is that I need to guarantee that all logic is within a consistent scope, I need to be able to access things within knockout, jQuery etc and the local instance of a class. I used to do this with the var self = this; within the class declaration in JavaScript and worked great. As mentioned in some of these previous questions I cannot do that now, so the only way I can guarantee the scope is to use lambda methods, and the only way I can define one of these as a method within a class is within the constructor, and this part is HEAVILY down to personal preference, but I find it horrific that people seem to think that using that syntax is classed as a recommended pattern and not just a work around.
I know TypeScript is in alpha phase and a lot will change, and I HOPE so much that we get some nicer way to deal with this but currently I either make everything a huge mess just to get typescript working (and this is within Hundreds of files which I'm migrating over to TypeScript ) or I just make the call that I know better than the compiler in this case (VERY DANGEROUS I KNOW) so I can keep my code nice and hopefully when a better pattern comes out for handling this I can migrate it then.
Also just on a side note I know a lot of people are loving the fact that TypeScript is embracing and trying to stay as close to the new JavaScript features and known syntax as possible which is great, but typescript is NOT the next version of JavaScript so I don't see a problem with adding some syntactic sugar to the language as people who want to use the latest and greatest official JavaScript implementation can still do so.
The author's specific issue with this seems to be solved but the question is posed about ignoring errors, and for those who end up here looking how to ignore errors:
If properly fixing the error or using more decent workarounds like already suggested here are not an option, as of TypeScript 2.6 (released on Oct 31, 2017), now there is a way to ignore all errors from a specific line using // #ts-ignore comments before the target line.
The mendtioned documentation is succinct enough, but to recap:
// #ts-ignore
const s : string = false
disables error reporting for this line.
However, this should only be used as a last resort when fixing the error or using hacks like (x as any) is much more trouble than losing all type checking for a line.
As for specifying certain errors, the current (mid-2018) state is discussed here, in Design Meeting Notes (2/16/2018) and further comments, which is basically
"no conclusion yet"
and strong opposition to introducing this fine tuning.
I think your question as posed is an XY problem. What you're going for is how can I ensure that some of my class methods are guaranteed to have a correct this context?
For that problem, I would propose this solution:
class LambdaMethods {
constructor(private message: string) {
this.DoSomething = this.DoSomething.bind(this);
}
public DoSomething() {
alert(this.message);
}
}
This has several benefits.
First, you're being explicit about what's going on. Most programmers are probably not going to understand the subtle semantics about what the difference between the member and method syntax are in terms of codegen.
Second, it makes it very clear, from looking at the constructor, which methods are going to have a guaranteed this context. Critically, from a performance, perspective, you don't want to write all your methods this way, just the ones that absolutely need it.
Finally, it preserves the OOP semantics of the class. You'll actually be able to use super.DoSomething from a derived class implementation of DoSomething.
I'm sure you're aware of the standard form of defining a function without the arrow notation. There's another TypeScript expression that generates the exact same code but without the compile error:
class LambdaMethods {
private message: string;
public DoSomething: () => void;
constructor(message: string) {
this.message = message;
this.DoSomething = () => { alert(this.message); };
}
}
So why is this legal and the other one isn't? Well according to the spec: an arrow function expression preserves the this of its enclosing context. So it preserves the meaning of this from the scope it was declared. But declaring a function at the class level this doesn't actually have a meaning.
Here's an example that's wrong for the exact same reason that might be more clear:
class LambdaMethods {
private message: string;
constructor(message: string) {
this.message = message;
}
var a = this.message; // can't do this
}
The way that initializer works by being combined with the constructor is an implementation detail that can't be relied upon. It could change.
I am sure given time there will be a nice way to manage the this keyword, but currently I find it pretty dire.
One of the high-level goals (that I love) in TypeScript is to extend the JavaScript language and work with it, not fight it. How this operates is tricky but worth learning.

Resources