码迷,mamicode.com
首页 > 其他好文 > 详细

自动化运维工具puppet(二)

时间:2015-10-04 06:46:48      阅读:294      评论:0      收藏:0      [点我收藏+]

标签:puppet

一、Puppet作域与变量

1、作用域

   作域的作就是指定特定的代码与其他的代码进隔离。 变量与默认资源将接受这些限制, 资 源标题、 资源引将不接受这样的限制。 接受范围限制的有:

  • 变量 

  • 默认资源

不接受范围限制的有:

  • 资源标题 

  • 资源引 

   在任何给定作域内, 可访问在本域中定义的变量或资源默认值, 同时继承作域中的内容, 依 此类推。 因此, 任何局部作域都可访问顶级作域中的内容。 使的范围是从该节点作域内直到 全局作域, 如下图所。

技术分享


从上图可以看到:

  • 在全局作域内只能访问作域的变量及默认值。 

  • 节点作域内可以访问其的作域和全局作域的变量和默认值。 

  • example:: parent、 example: : other、 example: : four类可以访问的变量和默认值是属于 、 节点及全局作域的。 

  • example: : child类可以访问的, 以及example: : parent、 节点、 全局作域的变量和默 认值。 

通常我们将全局作域内的变量称为全局变量, 将节点作域内的变量称为节点变量, 将局部作 域的变量称为局部变量。 

下将结合例介绍作域在变量中是如何体现的。

2、全局作域

   全局作域通常定义在站点件site.pp中, 以便作域下所有代码进引。 在如下测试例中 定义个全局变量$variable, 并赋值为Hi!, 在example类中定义notify资源执变量的引。

# site.pp
$variable = "Hi!"
class example {
notify {"Message from elsewhere: $variable":}
} 
include example

3、节点作域

   节点作域通常定义在节点( Node) 内, 可以在节点内引变量, 也可以引上层作域的变 量。 如果在全局作域下对节点作域内的变量进引, 将会失败。 配置例如下:

# site.pp
$top_variable = "Available!"
node ‘puppet.example.com‘ {
$variable = "Hi!"
notify {"Message from here: $variable":}
notify {"Top scope: $top_variable":}
} 
notify {"Message from top scope: $variable":}

   在以上代码中, 定义全局变量$top_variable与节点变量$variable, 在节点内对这两个变量进引 , 同时在全局作域进节点变量$variable的引。 通过puppet apply site.pp的命令我们可以看到节点作域下的两个变量被成功引, 全局作域下的变量引失败。 

4、局部作域

   局部作域通常定义在类内, 可以引类内的变量, 可以引上层节点作域的变量, 也可以引 全局作域的变量。 如果想在节点作域和全局作域下进局部作域的引, 将会失败。 配置例如下:

# /etc/puppet/modules/scope_example/manifests/init.pp
class scope_example {
$variable = "Hi!"
notify {"Message from here: $variable":}
notify {"Node scope: $node_variable Top scope: $top_variable":}
} 
# /etc/puppet/manifests/site.pp
$top_variable = "Available!"
node ‘puppet.example.com‘ {
$node_variable = "Available!"
include scope_example
notify {"Message from node scope: $variable":}
}
notify {"Message from top scope: $variable":}

   在以上代码中: 定义了局部变量$variable、 全局变量$top_variable及节点变量$node_variable, 在 类内对这三个变量进引, 同时在节点作域及全局作域内对局部变量$variable进引。 通过puppet apply site.pp的应我们可以看到: 节点作域下的两个变量被成功引, 节点作域及全局作域下的变量引失败。

5、变量覆盖

   如果是同时在全局作域、 节点作域、 局部作域由定义的相同的变量名, Puppet将以局部变量 为准。 如果是同时在全局作域、 节点作域中定义的相同的变量名, 则Puppet以节点作域为准。 示例如下:

# /etc/puppet/modules/scope_example/manifests/init.pp
class scope_example {
$variable = "Hi, I‘m local!"
notify {"Message from here: $variable":}
} 
# /etc/puppet/manifests/site.pp
$variable = "Hi, I‘m top!"
node ‘puppet.example.com‘ {
$variable = "Hi, I‘m node!"
include scope_example
}

   在以上代码中定义了三个变量: 局部变量$variable、 全局变量$variable、 节点变量$variable。 我们 可以看到三个变量名相同, 只是在不同的作域中进了引。 运puppet apply site.pp命令可以看到Puppet只以局部变量为准, 却不报错。

6、属性合并

   当在不同的作域中定义的同个资源具有不同属性值时, 声明不同的属性将会进合并操作, 只 是冲突属性值将会被覆盖。 通过如下例可以看下Puppet如何处理合并与覆盖操作。

$ /etc/puppet/modules/scope_example/manifests/init.pp
class scope_example {
File { ensure => directory, }
file {‘/tmp/example‘:}
}
$ /etc/puppet/manifests/site.pp
File {
ensure => file,
owner => ‘puppet‘,
}
include scope_example

   在以上代码中, 定义个件资源, 在全局作域中设置了件资源的默认值enusre=> file, 同时在局域类作域中设置了件资源的默认值ensure=>directory, 根据覆盖原则, file{ ‘/tmp/example‘: } 的ensure属性将会是directory。 执命令我们可以看到在客户端创建 了"/tmp/example"录, 其户为"puppet", 节点作域的件属性被覆盖, 两个作域的不同属性被合并。 


二、变量

   变量名以美元符“$”开头, 通过赋值运算符“=”赋值。 任何个正则表达式的数据类型的值都可以 赋值给变量。 变量只能使被分配的短名称。 在指定的作域内不能向作域名外的变量赋值, 即变量只持在作域内赋值。 变量在作域内只能赋值次, 通过“+=”运算符进值追加, 同样赋值也只能是次, 但可以同时赋多个, 也可以使内插法赋值。

1、变量赋值与引

举例:

class example {
$content = "Hi, I‘m variable!" #声明了个变量
File {‘/tmp/testing‘:
content => "{$content}", #直接引这个变量
}
}

将两个变量的值以字符串的形式拼接起来, 命令如下:

$value = "${one}${two}"

2、变量内插

举例:

$rule = "Allow * from ${ipaddress}"
file { "${homedir}/.vim":
ensure => directory,
…
}

Puppet可以解决双引号中的字符串的变量, 这就是所谓的“内插法”。

3、变量的追加

举例:

$ssh_users = [‘myself‘, ‘someone‘]
class test {
$ssh_users += [‘someone_else‘]
}

通过“+=”附加操作符进变量追加, 变量$ssh_users现在的值为〔 ‘myself‘, ‘someone‘, ‘someone_else‘〕 。 附加操作符“+=”的值必须为相同数据类型的、 可以接收的值。 这个操作符只能 于字符串、 数组和哈希表, 详细信息如下:

  • 将两个字符串连接起来。 

  • 对数组元素进合并。 

  • 合并两个哈希表。

4、变量的作域

   跟其他的开发语有所不同, 在Puppet中, 在给定的作域内变量只能被赋值次, 且不能改变这 个值, 但可以在不同的作域内赋不同的值给同变量。 

约定的变量的作域命名规则如下:

$myvar = $class::params::myvar

举例:

node ‘www1.example.com‘ {
$myvar = "Node scope value" #变量赋值
notice( "from www1: $myvar" ) #直接引变量
$myvar = "Local scope value" #不可中途改变其值
} 
class myclass {
$myvar = "Local scope value"
notice( "from myclass: $myvar" )
}

以上代码在Node节点信息中配置了相同的变量, 试图通过第次对变量myvar进赋值来改变其 值, 这在Puppet中是不允许的, 这点不同于其他程序语。 代码测试执时抛出的错误如下:

Error: Could not retrieve catalog from remote server: Error 400 on SERVER: Cannot reassign variab

我们可以在不同的作域下赋值, 代码如下:

node ‘www1.example.com‘ {
$myvar = "Node scope value"
notice( "from www1: $myvar" )
} 
class myclass {
$myvar = "Local scope value" #覆盖Node中定义的变量值
notice( "from myclass: $myvar" )
}

以上代码通过在类中定义myvar变量的形式覆盖Node节点中定义的值, 执结果如下:

(Scope(Node[agent.domain.com])) from www1: Node scope value
(Scope(Class[Test])) from myclass: Local scope value
Compiled catalog for agent.domain.com in environment production in 0.04 seconds

同理, 相同的变量可以存在于不同的节点配置中, 这也是作域的特征:

node ‘www1.example.com‘ {
$myvar = "Node1 scope value"
notice( "from www1: $myvar" )
}
node ‘www2.example.com‘ {
$myvar = "Node2 scope value"
notice( "from www2: $myvar" )
}

5、Facts和内置变量

   Puppet提供了些客户端及服务端的内置变量。 Facts即运facter命令收集到的系统信息。 除了内 置的变量外, 我们还可以进定义。 

客户端的内置变量有:

  • $environment: 节点环境。 

  • $clientcert: 节点名称certname。 

  • $clientversion: 客户端Puppet版本。

服务端的内置变量有:

  • $servername: 服务端完整、 合格的域名, 主机名即facter中的fqdn。 

  • $serverip: 服务端IP。 

  • $serverversion: 服务端Puppet版本。

  • $settings: : <name of setting>: 服务端设置项的值。 

  • $module_name: 模块名称。

使用举例:

[root@example.com tmp]# vim test7.pp
file {‘/tmp/nginx.conf‘:
        ensure   => file,
        content  => "worker_processes $processorcount;\n",
}
[root@example.com tmp]# puppet apply test7.pp
notice: /Stage[main]//File[/tmp/nginx.conf]/content: content changed ‘{md5}c53bae3bb726fbdb9f38267014545f7b‘ to ‘{md5}960f3bee4b6ea036b058cacc20650d67‘
notice: Finished catalog run in 0.05 seconds
[root@example.com tmp]# cat nginx.conf 
worker_processes 1;


三、数据类型

Puppet允许多种数据类型, 包括变量、 属性值、 函数参数。 数据类型也是我们编写代码时需要掌握 的内容。

1、布尔类型

   布尔类型仅有两个值: true和false。 "if"语句条件与较表达式最后的值都是布尔值。 如果需要个 布尔值进依赖处理, Puppet将会动进转换。注意一定不能加引号!

  • 字符串: 空字符串都是false, 其他字符串为true。 可以使puppetlabs-stdlib模块str2bool函数 进转换。 

  • 数字: 所有数字都是true, 包括0和负数。 同样可以使puppetlabs-stdlib 模块num2bool函数 进转换。 

  • 未定义: 特殊数据类型的undef都为false。 

  • 数组和哈希: 任何数组或哈希表都为true, 包括空数组和空哈希表。 

  • 资源引: 任何资源引都是true, 不管资源是否已被引、 资源是否存在、 数据类型是否有 效。

2、未定义

   Puppet特殊的undef值致相当于( nil) 。 在Ruby中, 从未声明的变量值为undef。 书写undef时 必须是不加引号的。 

   undef值通常是有的, 于测试个变量是否已经设置。 它也可以作为个资源属性, 当没有设 置任何值从resource default继承, 或者定义该资源的这个属性不被管理时, 我们也可以使defined 函数来测试个类或资源是否已定义, 同时, 还可以将继承于类的资源属性值反设置( 即清空个之前在类中定义好的资源属性值) , 不再让Puppet管理此项内容。 作为个布尔值, undef是false。

3、字符串

字符串是任何长度的结构化本段。 简单来说可以概括为如下四类。

( 1) 裸词

所谓裸词即没有引号, 通常被视为单字符, 或字符串。 必须满以下条件:

  • 不能是保留字。 

  • 以字母开头, 只包含字母、 数字、 连接符( -) 、 下划线( _) 。 

   前Puppet建议所有的字符串为UTF8, 或许以后Puppet将强制所有字符串的编码必须为UTF8。 特 别是以后和Puppetdb结合更加紧密时, 建议家采UTF8以避免以后升级带来的烦。

( 2) 单引号

表个值或者是定义个资源的名称的时候使单引号。 使单引号时, 字符串不允许变量内 插, 只需要对“’”和“\”转义。 

( 3) 双引号

双引号通常于定义个变量的引, 例如: “${ name} ”。 使双引号时, 字符串允许变量内 插, 并持多种转义字符, 例如"\n"代表换。 

( 4) 换

在UNIX中换符为\n, 在Windows中为\r\n, 在Puppet 2.7.20及以后版本中, 持在字符串中使 \r \n 作为换符。 

4、资源引

   资源引是通过类型和title来定位个已存在的Puppet资源, 在使关系元参数定义资源间的顺序 依赖时, 需要使资源引。 资源引的使法如下:

subscribe => File[‘/etc/ntp.conf‘],

资源引的格式是:

   资源类型( 字母必须写) +个左括号+资源的标题( 或以逗号分隔列表标题) +个右括 与变量不同, 资源引与书写顺序关, 在资源定义之前就可以使它的引。 个资源可以同时引多个资源, 配置法如下:

require => File[‘/etc/apache2/httpd.conf‘, ‘/etc/apache2/magic‘, ‘/etc/apache2/mime.types‘],

也可以使数组的法对多个资源进引:

$my_files = [‘/etc/apache2/httpd.conf‘, ‘/etc/apache2/magic‘, ‘/etc/apache2/mime.types‘] 
require => File[$my_files]

5、数字

  Puppet算术表达式只接受整数和浮点数。 数字可以写为个裸词或带引号的字符串, 仅由个可选 的负号( -) 和数点组成, 例如:

$some_number = 8 * -7.992
$another_number = $some_number / 4

数字不能包含加号, -1到1之间的数字需要使前缀0, 例如:

$product = 8 * +4 # syntax error
$product = 8 * 4 # OK
$product = 8 * .12 # syntax error
$product = 8 * 0.12 # OK

6、哈希类型

哈希类型的写法为:

“括号”+“哈希键”+“=>”+“哈希值”

如果有多个哈希类型, 采逗号分隔。 哈希键是字符串, 但值可以是任何数据类型, 包括数组或哈 希的哈希值, 例如:

{ key1 => ‘val1‘, key2 => ‘val2‘ }
# Equivalent:
{ key1 => ‘val1‘, key2 => ‘val2‘, }

使法如下:

$myhash = { key => "some value",
other_key => "some other value" }
notice( $myhash[key] )

上述代码输出$myhash的值为"some value"。

7、正则表达式

   正则表达式主要运在判断语句、 case语句、 选择器及节点定义中, 且必须是标准的Ruby正则表达 式。 下笔者列举种常见的正则表达式写法。 

主机名正则匹配写法:

if $host =~ /^www(\d+)\./ {
notify { "Welcome web server #$1": }
}

if判断语句的匹配写法:

if ( $processor_count > 2 ) and (( $ram >= 16 * $gigabyte ) or ( $disksize > 1000 )) {
include for_big_irons
} else {
include for_small_box
}

case语句正则匹配写法:

case $hostname {
/^j(ack|ill)$/: { include hill } # apply the hill class
/^[hd]umpty$/: { include wall } # apply the wall clascf
default: { include generic } # apply the generic class
}

selector选择器正则匹配写法:

$owner = $operatingsystem ? {
/(redhat|debian)/ => ‘bin‘,
default => undef,
}

正则表达式的写法与表达式密切相关, 因此在写正则表达式时需要查看6.9节中介绍的关于表达式 的相关内容。

8、数组

数组被写成使逗号分隔的列表, 使括号括起来。 个数组中的数值可以是任何数据类型, 包 括哈希类型和多个阵列, 例如:

[ ‘one‘, ‘two‘, ‘three‘ ]

上述代码等价于:

[ ‘one‘, ‘two‘, ‘three‘, ]

访问数组中的数字索引, 从零开始计算, 括号主要于索引, 例如:

$foo = [ ‘one‘, ‘two‘, ‘three‘ ]
notice( $foo[1] )

在以上代码中, $foo〔 1〕 将会是two。

嵌套数组和哈希表也可以通过链接索引进访问, 例如:

$foo = [ ‘one‘, {‘second‘ => ‘two‘, ‘third‘ => ‘three‘} ]
notice( $foo[1][‘third‘] )

在以上代码中, $foo〔 1〕 将会是three。 其中$foo〔 1〕 是个哈希值, 访问的key的名字 是"third"所对应的值为three。 

Puppetlabs-stdlib模块中包含了些额外的功能, 如

delete、 grep、 hash、 range、 size、 sort、 zip等, 这些功能主要于处理数组。

注意:数组可变, 可以将新添加的数值分配给未使的索引或现存的索引。 这是个Bug, 建议不要使 , 在Puppet 2.7版本中, 这个错误不会被删除。 哈希与数组都有这个Bug。


四、表达式

   表达式解析的值, 可以使在需要标准数据类型( 数据类型有: 布尔、 数组、 哈希等) 的地。 表 达式可以和其他表达式进整合进合并成复合表达式。 表达式在Puppet中运较泛, 本节将从表达式、 操作数、 运位置、 操作顺序、 较运算符、 布尔运算符等讲解表达式的应。

1、什么是表达式

   Puppet表达式般由两个操作数和个运算符组成, 例如==, 但( !) 操作符除外, 它只有个 操作数, 于表操作。 

表达式的格式如下:

表达式 = ( 操作数 运算符 操作数)

常见表达式举例如下:

1) 5<9

2) $kernel in 〔 ‘linux‘, ‘solaris‘〕

3) ( $operatingsystem!=‘Solaris‘)

4) ( $operatingsystem==‘Centos‘)

  • 表达式可以使括号括起来, 也可以不使括号。 

  • 操作数可以是字值、 变量、 其他表达式、 函数调返回值。 

  • 运算符可以是较运算符、 布尔运算符。 

  • 每个操作数的数据类型由操作者决定。 

  • 当创建复合表达式时使其他表达式作为操作数, 应该使括号括起来, 使代码更加清晰。 

2、运位置

表达式可以运在以下地:

  • 操作数的表达式 

  • if条件语句 

  • case语句 

  • 变量的分配 

  • 资源属性值 

  • 函数调的参数 

需要注意的是: 表达式不能于选择器或资源标题。

3、操作顺序

   表达式的操作顺序遵守运算符的优先级, 复合表达式有标准的操作顺序, 使括号将覆盖操作顺 序。 例如, 下表达式的结果是30不是23。 

notice( (7+8)*2 )

通常我们为了表达更清晰, 使括号将表达式括起来。

运算符优先级, 从最到最低为:

1) !( )

2) in( 在什么)

3) *、 /( 乘法和除法)

4) -、 +( 减法和加法)

5) <<、 >>( 左移、 右移)

6) ==、 !=( 等于、 不等于)

7) >=、 <=、 >、 <( 于或等于、 于或等于、 于、 于)

8) and、 or( 和、 或)

4、较运算符

较运算符具有以下特点:

  • 可以接受多种数据类型的操作数; 

  • 结果是布尔类型。 

下图中的运算符的各项说明来了解Puppet较运算符的含义。

技术分享

5、布尔运算符

   布尔运算符的特点是: 如果操作数不是布尔类型, Puppet会动将其转化为布尔值。 这个运算符在 创建复合表达式时是最有的。 下图中对各种布尔运算符进了说明。

技术分享

6、算术运算符

算术运算符主要于进算术运算, 较简单。 下图是对算术运算符的说明。

技术分享


五、条件语句

   Puppet条件语句允许你根据变量值或表达式值的不同来应不同代码。 通常来判断系统、 内存 等, 根据操作系统、 内存的差异应不同的代码, 如Centos采Yum命令, Ubuntu采Aptget命令。 常的条件语句有if、 case、 selector( 选择器) 。 Puppetlabs不推荐在配置代码中使过多的条件判断, 过多的判断会影响Puppet执效率, 也会带来维护性的问题。 当涉及过多的判断时尽可能使模块来实现。 下来介绍条件语句的法。

1、if语句

if语句在其他程序语运也常泛, 其配置法也常简单。 if语句在Puppet下的配置法 与其他程序语样:

if $operatingsystem == "Ubuntu" {
notify { "Ubuntu-type operating system detected": }
}

   以上代码判断当前系统是否为Ubuntu( 是通过本地facter命令的operatingsystem变量实现的) , 如 果表达式的结果为真, 则执花括号中的代码, 即判断当前系统是Ubuntu则执notify资源, 输出"Ubuntu-type operating system detected"。 如果表达式的结果不为真呢? 代码中没有任何提。Puppet本也不推荐这么做, 因为代码不完整, 也不漂亮, 当然也不便于维护。

可以采如下法来解决:

if $operatingsystem == "Ubuntu" {
notify { "Ubuntu-type operating system detected": }
}
elsif $operatingsystem == "CentOS" {
notify { "CentOS-type operating system detected": }
}
else {
notify { "Some other operating system detected": }
}

   在以上代码中进了两次判断, 第次判断系统是不是Ubuntu, 第次判断系统是不是Centos, 如 果既不是Ubuntu也不是Centos则执最后的notify输出。 这也是notify资源最主要的作。 

   通过以上两段代码我们可以看到, if语句的语法常简单, 仅包括if关键字、 条件、 花括号及代码。 可以使elsif或else配置多重选择。 如果采elsif, 则判断表达式的结果是否为true, 是则执, 如果采else, 则判断表达式的结果是否为false, 是则执。

   if语句判断表达式返回结果: 如果为真, 则执, 如果为假且有elsif或else, 则需要进次判断, 如果都为假, 执默认判断语句。 如果if语句的判断表达式的返回值不为布尔类型, 则Puppet会动将其转换为布尔类型, 下介绍具体的转换规则

  • 字符串: 空字符串为false, 其他所有的都是true, 包括"false"。 注意前Puppet所有Facts都是 字符串。 

  • 数字: 所有的数字都是true, 包括0和负数。 

  • undef: false。 

  • 数据和哈希: 默认为true, 同时包括空数组和空哈希。 

  • 资源引: 默认为true, 包含所有的资源引。

   在以上5种情况下, Puppet会将表达式返回的值转换成布尔类型。 在进布尔值较运算时, 最常运算符的是等于( ==) 、 不等于( !=) 。

当同类型的操作系统具有同样特性时, 我们可以采Puppet 2.6版本以上的新特性, 例如:

if $operatingsystem in [ "Ubuntu", "Debian" ] {
notify { "Ubuntu-type operating system detected": }
}
elsif $operatingsystem in [ "RedHat", "Fedora", "SuSE", "CentOS"
] {
notify { "Centos-type operating system detected": }
} 
else {
notify { "Some other operating system detected": }
}

上述代码中采的法是system in $OS。 如果system在$OS内, 则执相应的代码。 本例所定义的 $OS采数组的形式, 其优点就是减少更多的判断。

应用举例:

[root@example.com tmp]# vim test8.pp
if $operatingsystem == ‘CentOS‘{
        notify {‘CentOS‘: message => "Welcome to CentOS Linux.",}
} elsif $operatingsystem == ‘RedHat‘{
        notify {‘RedHat‘: message => "Welcome to RedHat Linux.",}
} elsif $operatingsystem == ‘Fedora‘{
        notify {‘Fedora‘: message => "Welcome to Fedora Linux.",}
}
[root@example.com tmp]# puppet apply test8.pp
notice: Welcome to CentOS Linux.
notice: /Stage[main]//Notify[CentOS]/message: defined ‘message‘ as ‘Welcome to CentOS Linux.‘
notice: Finished catalog run in 0.03 seconds

2、case语句

   case语句实现的效果和if语句致, 但case语句没有返回值, 没有notify资源的调。 if语句也可以 没有返回值, 但必须有notify资源的调。 case语句是依赖于表达式的不同值执不同的代码。 case语句会将控制表达式的值与各个case的值对, 并执第个匹配的case对应的语句, 忽略其他的。 如果变量$operatingsystem与系统致, 则执括号中的代码。 case语句需要有个默认值, 使代码更加全、 更健壮。

case语句配置代码如下:

case $operatingsystem {
‘Solaris‘: { include role::solaris } # apply the solaris class
‘RedHat‘, ‘CentOS‘: { include role::redhat } # apply the redhat class
/^(Debian|Ubuntu)$/:{ include role::debian } # apply the debian class
default: { include role::generic } # apply the generic class
}

与if语句的不同之处在于, case语句表达式看起来较为复杂, 不够直观, 但实质很简单。

应用举例:

case $operatingsystem {
            /^(?i-mx:redhat|centos|fedora)/: { package {‘httpd‘: ensure => present, provider => yum, } }
            /^(?i-mx:ubuntu|debian)/: { package {‘apache2‘: ensure => present, provider => apt, } }
            default: { notify {‘notice‘: message => "unknown system.", }}
        }

3、selector选择器

   selector是Puppet中的选择器, 类似于case语句, 不过只返回个值, 不是执个代码。 选择器 必须在代码中需要简单值的地, 包括: 变量的赋值、 资源属性、 功能参数、 资源标题、 表达式、 另 个selector中的值。 我们不能在case中使选择器, 也不能将个selector作为另个selector的case, 因为Puppet会认为这不是合法的代码。 

   选择器的法是: 先定义变量$rootgroup, 然后通过变量$osfamily判断系统版本, 从将参数传递 给变量$rootgroup。 这点类似于C或Ruby中的三元操作, 只不过选择器从两个选项中选择个值。

$rootgroup = $osfamily ? {
‘Solaris‘ => ‘wheel‘,
/(Darwin|FreeBSD)/ => ‘wheel‘,
default => ‘root‘,
}
file { ‘/etc/passwd‘:
ensure => file,
owner => ‘root‘,
group => $rootgroup,
}

   Puppet会较我们提供的每种可能, 在以上代码中我们只使字字符串进对, 成功匹配 后, selector中的表达式会返回与之匹配的字符串的值。 如果$osfamily的值为"Solaris", 则selector表达式会返回"wheel"字符串, 这个字符串将赋值给变量$rootgroup。 Puppet在较时可以是字符串、 通配符、 正则表达式等。 

   Puppet按照每个case的书写顺序与控制表达式进对, 若找到第个匹配项则返回对应的值, 不 继续匹配。 在对的过程中, 如果case是简单的字符串, 则不会区分写, 如果是正则表达式, 则区分写, 最后的default case会匹配任意值。 

   Puppet在发现个匹配的情况时, 会对该值进声明, 即将该值分配给定义的控制变量, 忽略其 余的配置语句。 其中常的较运算符有:

  • 等于: ==( 不区分写) 。

  • 正则表达式: =~操作符( 区分写) 。

应用举例:

$webserver = $operatingsystem ? {
        /^(?i-mx:centos|fedora|redhat)/ => ‘httpd‘,
        /^(?i-mx:ubuntu|debian)/        => ‘apache2‘,
}
$webprovider = $operatingsystem ? {
        /^(?i-mx:centos|fedora|redhat)/ => ‘yum‘,
        /^(?i-mx:ubuntu|debian)/        => ‘apt‘,
}
package {"$webserver":
        ensure   => present,
        provider => $webprovider,
}




本文出自 “粗茶淡饭” 博客,请务必保留此出处http://cuchadanfan.blog.51cto.com/9940284/1700070

自动化运维工具puppet(二)

标签:puppet

原文地址:http://cuchadanfan.blog.51cto.com/9940284/1700070

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!