Avoiding antipatterns
Speaking of things to avoid, there is a language feature that we will only address in order to advise great caution. Puppet comes with a function called defined
, which allows you to query the compiler about resources that have been declared in the manifest:
if defined(File['/etc/motd']) { notify { 'This machine has a MotD': } }
The problem with the concept is that it cannot ever be reliable. Even if the resource appears in the manifest, the compiler might encounter it later than the if
condition. This is potentially very problematic, because some modules will try to make themselves portable through this construct:
if ! defined(Package['apache2']) { package { 'apache2': ensure => 'installed' } }
The module author supposes that this resource definition will be skipped if the manifest declares Package['apache2']
somewhere else. As explained, this method will only be effective if the block is evaluated late enough during the compiler run. The conflict can still occur if the compiler encounters the other declaration after this one.
The manifest's behavior becomes outright unpredictable if a manifest contains multiple occurrences of the same query:
class cacti { if !defined(Package['apache2']) { package { 'apache2': ensure => 'present' } } } class postfixadmin { if !defined(Package['apache2'] { package { 'apache2': ensure => 'latest' } } }
The first block that is seen wins. This can even shift if unrelated parts of the manifest are restructured. You cannot predict whether a given manifest will use ensure=>latest
for the apache2
package or just use installed
. The results become even more bizarre if such a block wants a resource removed through ensure=>absent
, while the other does not.
The defined
function has long been considered harmful, but there is no adequate alternative yet. The ensure_resource
function from the stdlib
module tries to make the scenario less problematic:
ensure_resource('package', 'apache2', { ensure => 'installed' })
By relying on this function instead of the preceding antipattern based around the defined
function, you will avoid the unpredictable behavior of conflicting declarations. Instead, this will cause the compiler to fail when the declarations are passed to ensure_resource
. This is still not a clean practice, though. Failed compilation is not a desirable alternative either.
Both functions should be avoided in favor of clean class structures with nonambiguous resource declarations.
- Embedded Linux Projects Using Yocto Project Cookbook
- 數字媒體應用教程
- ASP.NET Core 5.0開發入門與實戰
- Practical Internet of Things Security
- 基于免疫進化的算法及應用研究
- jQuery開發基礎教程
- OpenCV 4計算機視覺項目實戰(原書第2版)
- Visual Foxpro 9.0數據庫程序設計教程
- Building Dynamics CRM 2015 Dashboards with Power BI
- Python 3 Object:oriented Programming(Second Edition)
- Python硬件編程實戰
- Software-Defined Networking with OpenFlow(Second Edition)
- 軟硬件綜合系統軟件需求建模及可靠性綜合試驗、分析、評價技術
- 深入大型數據集:并行與分布化Python代碼
- Python滲透測試編程技術:方法與實踐(第2版)