Using a defined type of an yet unreleased puppet module - puppet

We are currently developing three puppet modules.
One contains a Defined Type which the other two shall use. This module, lets call it ModuleA, is not released yet into our local forge/repository and will not until it was successfully implemented and tested in at least one of the other two modules (company procedure).
The Definded Type is used in the other two modules to create a resource and is referenced via 'include'.
In the metadata.json ModuleA is added as dependency.
When I run pdk test unit it fails because the Defined Type is unknown.
Currently there is only a single it { is_expected.to compile.with_all_deps } test in the other two modules, nothing complex.
How can the other two modules be tested if ModuleA is not released yet?

How can the other two modules be tested if ModuleA is not released yet?
Your tests for the other modules can provide stub implementations of the required defined type. This can be done with a :pre_condition:
describe 'Module_b::Some_class' do
let(:pre_condition) { 'define module_a::some_type($param1, $param2) { }' }
# ...
end
Do be sure that the number and names of the stub match those of the real defined type.

Related

Puppet: Class Ordering / Containment - always wrong order

I read a lot about ordering puppet classes with containment (iam using Puppet 6). But it still does not work for me in one case. Maybe my english is not good enough and i miss something. Maybe somebody know what iam doing wrong.
I have a profile to installing a puppetserver (profile::puppetserver). This profile has three sub-classes which I contain within the profile::puppetserver
class profile::puppetserver(
) {
contain profile::puppetserver::install
contain profile::puppetserver::config
contain profile::puppetserver::firewall
}
That works fine for me. Now I want to expand this profile and install PuppetDB. For this, i use the puppetdb module from puppet forge:
So what i do is add profile::puppetserver::puppetdb and the contain to the profile::puppetserver
class profile::puppetserver::puppetdb(
) {
# Configure puppetdb and its underlying database
class { 'puppetdb': }
# Configure the Puppet master to use puppetdb
class { 'puppetdb::master::config': }
}
When i provision my puppetserver first and add the profile::puppetserver::puppetdb after it, puppetdb installs and everything works fine.
If I add it directly with contain, and provisioning everything at once, it crashes. It's because the puppetdb module is installed randomly during my master server installs (and also the postgresql server and so on). That ends in my puppetserver is not running and my puppetdb generate no local ssl certificates and the service doesn't comes up.
What i try first:
I installed the puppetdb Package in my profile::puppetserver::puppetdb directly and use the required flag. It works when i provision all at once.
class profile::puppetserver::puppetdb (
) {
Package { 'puppetdb':
ensure => installed,
require => Class['profile::puppetserver::config']
}
}
So i think i could do the same in the code above:
class profile::puppetserver::puppetdb(
) {
# Configure puppetdb and its underlying database
class { 'puppetdb':
require => Class['profile::puppetserver::config']
}
# Configure the Puppet master to use puppetdb
class { 'puppetdb::master::config':
require => Class['profile::puppetserver::config']
}
}
But this does not work...
So i read about puppet class containment and ordering by chains. So i did this in my profile::puppetserver
class profile::puppetserver(
) {
contain profile::puppetserver::install
contain profile::puppetserver::config
contain profile::puppetserver::firewall
contain profile::puppetserver::puppetdb
Class['profile::puppetserver::install'] ->
Class['profile::puppetserver::config'] ->
Class['profile::puppetserver::firewall'] ->
Class['profile::puppetserver::puppetdb']
}
But it still does not have any effect... he still starts to install postgresql and the puppetdb package during my "puppetserver provisioning" in the install, config, firewall steps.
How i must write the ordering, that all things from the puppetdb module, which i call in profile::puppetserver::puppetdb, only starts when the rest of the provisioning steps are finished?
I really don't understand it. I think maybe it haves something to do with the fact, that i declare classes from the puppetdb module inside of profile::puppetserver::puppetdb and not the directly Resource Type. Because when i use the Package Resource Type with the Require Flag, it seems to work. But i really don't know how to handle this. I think there must be a way or?
I think maybe it haves something to do with the fact, that i declare
classes from the puppetdb module inside of
profile::puppetserver::puppetdb and not the directly Resource Type.
Because when i use the Package Resource Type with the Require Flag, it
seems to work.
Exactly so.
Resources are ordered with the class or defined-type instance that directly declares them, as well as according to ordering parameters and instructions applying to them directly.
Because classes can be declared multiple times, in different places, ordering is more complicated for them. Resource-like class declarations such as you demonstrate (and which you really ought to avoid as much as possible) do not imply any particular ordering of the declared class. Neither do declarations via the include function.
Class declarations via the require function place a single-ended ordering constraint on the declared class relative to the declaring class or defined type, and declarations via the contain function place a double-ended ordering constraint similar to that applying to all resource declarations. The chaining arrows and ordering metaparameters can place additional ordering constraints on classes.
But i really dont know how to handle this. I think there must be a way or?
Your last example shows a viable way to enforce ordering at the level of profile::puppetserver, but its effectiveness is contingent on each of its contained classes taking the same approach for any classes they themselves declare, at least where those third-level classes must be constrained by the order of the second-level classes. This appears to be where you are falling down.
Note also that although there is definitely a need to order some things relative to some others, it is not necessary or much useful to try to enforce an explicit total order over all resources. Work with the lightest hand possible, placing only those ordering constraints that serve a good purpose.

Why does Rust need to know the code in module belong to whom?

I encountered some problems reading the Rust documentation:
In this example, we have three modules again: client, network, and network::client. Following the same steps we did earlier for extracting modules into files, we would create src/client.rs for the client module. For the network module, we would create src/network.rs. But we wouldn’t be able to extract the network::client module into a src/client.rs file because that already exists for the top-level client module! If we could put the code for both the client and network::client modules in the src/client.rs file, Rust wouldn’t have any way to know whether the code was for client or for network::client
Why does Rust need to know the code in client.rs belongs to client or network::client? Can it belong to both?
The compiler has rules about where the source file for an external module can be. Those rules ensure that there aren't two modules that use the same source file.
If you really want to, you can override the rules with a #[path] attribute:
mod client; // defaults to client.rs relative to the current file
mod network {
#[path="client.rs"] // reads the same source as the outer `mod client;`
mod client;
}
However, doing so would lead to duplicate code, i.e. the code in client.rs would be compiled twice, and everything that's defined in client.rs would be defined twice, in two separate modules. It's as if you made network/client.rs an exact copy of client.rs and didn't write the #[path] attribute.
Another thing you can do is provide an alias for a module by reexporting it elsewhere. This can be useful when building a library: it enables you to present an external module hierarchy that is different from the internal module hierarchy.
mod client; // not accessible externally
pub mod network {
pub use client; // network::client::* will refer to the same definitions as client::*
}
For example, with the above, the client module is defined in client.rs, but clients use it through my_crate::network::client.

Puppet: Declaring a class with inheritance

I currently have two classes that I created within /etc/puppet/modules/params/manifests/init.pp
class modulename ($variable_name = 'Any string') inherits modulename::params{
file { '/tmp/mytoplevelclass.sh' :
mode => '644',
ensure => 'present',
content => $variable_name
}
}
class modulename::params{
}
However, I am having an issue declaring these classes in /etc/puppet/manifests/site.pp. Currently, I have it written as
node default { #client
class { 'modulename':}
class { 'modulename::params':}
}
I know that this is incorrect because when I run puppet agent -t on the client I get an error stating
Could not find declared class modulename at /etc/puppet/manifests/site.pp
I have tried several different configurations and still am unsure on what to do.
Puppet determines the file in which it expects to find a class's definition based on the class's fully-qualified name. The docs go into it in some detail; in particular, you should review the Module Fundamentals. (I am guessing that you are on Puppet 3, but the details I am about to discuss are unchanged in Puppet 4.)
Supposing that /etc/puppet/modules is a directory in your modulepath, it is a fine place to install (or write) your modulename module, as indeed you indicate you are doing. If it is not in your module path, then you'll want either to move your module to a directory in the module path, or to add that directory to the module path. I assume that you will resolve any problem of this sort via the latter alternative, so that /etc/puppet/modules/modulename is a valid module directory.
Now, class 'modulename' is a bit special in that its name is also a module name; as such, it should be defined in /etc/puppet/modules/modulename/manifests/init.pp. Class modulename::params, on the other hand, should follow the normal pattern, being defined in /etc/puppet/modules/modulename/manifests/params.pp. I anticipate that Puppet will find the definitions if you put the definitions in the correct files.
Bonus advice:
Use include-like class declarations in your node blocks, not resource-like declarations
Your node blocks probably should not declare modulename::params at all

RequireJS Multi Injecting

I am building a modular single page application which consumes multiple require config files from different sources. I would like a way in my application to be able to consume a list of all modules of a specific type. something like this:
define('module-type/an-implementation',...)
define('module-type/another-implementation',...)
require('module-type/*', function(modules){
$.each(modules,function(m){ m.doStuff(); });
})
This is similar patterns dependency injectors use with multiple dependency injection (eg. https://github.com/ninject/ninject/wiki/Multi-injection)
Is there a way to do this (or something similar) with require?
RequireJS doesn't know which modules exist until something requires them. Once a module is required / depended upon RequireJS will figure out where to request the module from based on module's name and RequireJS's configuration. Once the module is loaded it can be examined / executed to find out its dependencies and handle them in turn, until all dependencies are loaded and all module bodies are executed.
In order to be able to "consume a list of all modules of a specific type" something would need to be able to find all such modules. RequireJS doesn't have any means to know which modules exist, so it alone wouldn't be enough to implement "Multi Injection".
Speculation
Some kind of module registry could be created and populated with help of the build system: e.g. a file (say module-registry.js) could be generated each time a file in the source directory is added / removed or renamed, then multi inject could be possible like:
multiRequire('module-type/*', function(modules){
$.each(modules,function(m){ m.doStuff(); });
})
which in turn would call
require(findModules(pattern), function() {
callback(Array.prototype.slice.call(arguments, 0));
});
(where multiRequire and findModules are provided by the module registry).

When should I use require() and when to use define()?

I have being playing around with requirejs for the last few days. I am trying to understand the differences between define and require.
Define seems to allow for module separation and allow for dependency ordering to be adhere. But it downloads all the files it needs to begin with. Whilst require only loads what you need when you need it.
Can these two be used together and for what purposes should each of them be used?
With define you register a module in require.js that you can then depend on in other module definitions or require statements.
With require you "just" load/use a module or javascript file that can be loaded by require.js.
For examples have a look at the documentation
My rule of thumb:
Define: If you want to declare a module other parts of your application will depend on.
Require: If you just want to load and use stuff.
From the require.js source code (line 1902):
/**
* The function that handles definitions of modules. Differs from
* require() in that a string for the module should be the first argument,
* and the function to execute after dependencies are loaded should
* return a value to define the module corresponding to the first argument's
* name.
*/
The define() function accepts two optional parameters (a string that represent a module ID and an array of required modules) and one required parameter (a factory method).
The return of the factory method MUST return the implementation for your module (in the same way that the Module Pattern does).
The require() function doesn't have to return the implementation of a new module.
Using define() you are asking something like "run the function that I am passing as a parameter and assign whatever returns to the ID that I am passing but, before, check that these dependencies are loaded".
Using require() you are saying something like "the function that I pass has the following dependencies, check that these dependencies are loaded before running it".
The require() function is where you use your defined modules, in order to be sure that the modules are defined, but you are not defining new modules there.
General rules:
You use define when you want to define a module that will be reused
You use require to simply load a dependency
//sample1.js file : module definition
define(function() {
var sample1 = {};
//do your stuff
return sample1;
});
//sample2.js file : module definition and also has a dependency on jQuery and sample1.js
define(['jquery', 'sample1'], function($,sample1) {
var sample2 = {
getSample1:sample1.getSomeData();
};
var selectSomeElement = $('#someElementId');
//do your stuff....
return sample2;
});
//calling in any file (mainly in entry file)
require(['sample2'], function(sample2) {
// sample1 will be loaded also
});
Hope this helps you.
"define" method for facilitating module definition
and
"require" method for handling dependency loading
define is used to define named or unnamed modules based on the proposal using the following signature:
define(
module_id /*optional*/,
[dependencies] /*optional*/,
definition function /*function for instantiating the module or object*/
);
require on the other hand is typically used to load code in a top-level JavaScript file or within a module should you wish to dynamically fetch dependencies
Refer to https://addyosmani.com/writing-modular-js/ for more information.
require() and define() both used to load dependencies.There is a major difference between these two method.
Its very Simple Guys
Require() : Method is used to run immediate functionalities.
define() : Method is used to define modules for use in multiple locations(reuse).

Resources