Fantoche - Estilo de Codificação
No Puppet, o estilo de codificação define todos os padrões que devem ser seguidos ao tentar converter a infraestrutura da configuração da máquina em um código. O Puppet trabalha e executa todas as suas tarefas definidas usando recursos.
A definição da linguagem do Puppet ajuda a especificar todos os recursos de uma forma estruturada, que é necessária para gerenciar qualquer máquina de destino que precise ser gerenciada. O Puppet usa Ruby como linguagem de codificação, que possui vários recursos embutidos que tornam muito fácil fazer as coisas com uma configuração simples no lado do código.
Unidades Fundamentais
O Puppet usa vários estilos de codificação fundamentais que são fáceis de entender e gerenciar. A seguir está uma lista de alguns.
Recursos
No Puppet, os recursos são conhecidos como unidades de modelagem fundamentais, usados para gerenciar ou modificar qualquer sistema de destino. Os recursos cobrem todos os aspectos de um sistema, como arquivo, serviço e pacote. O Puppet vem com um recurso embutido no qual permite que os usuários ou desenvolvedores desenvolvam recursos personalizados, que ajudam no gerenciamento de qualquer unidade específica de uma máquina
No Puppet, todos os recursos são agregados usando “define” ou “classes”. Esses recursos de agregação ajudam na organização de um módulo. A seguir está um recurso de amostra que consiste em vários tipos, um título e uma lista de atributos com os quais o Puppet pode oferecer suporte a vários atributos. Cada recurso no Puppet tem seu próprio valor padrão, que pode ser substituído quando necessário.
Exemplo de recurso de fantoche para arquivo
No comando a seguir, estamos tentando especificar uma permissão para um arquivo específico.
file {
'/etc/passwd':
owner => superuser,
group => superuser,
mode => 644,
}
Sempre que o comando acima for executado em qualquer máquina, ele verificará se o arquivo passwd no sistema está configurado conforme descrito. O arquivo antes de: dois pontos é o título do recurso, que pode ser referido como recurso em outras partes da configuração do Puppet.
Especificando o nome local além do título
file { 'sshdconfig':
name => $operaSystem ? {
solaris => '/usr/local/etc/ssh/sshd_config',
default => '/etc/ssh/sshd_config',
},
owner => superuser,
group => superuser,
mode => 644,
}
Ao usar o título, que é sempre o mesmo, é muito fácil referir o recurso do arquivo na configuração sem ter que repetir a lógica relacionada ao SO.
Outro exemplo pode ser o uso de um serviço que depende de um arquivo.
service { 'sshd':
subscribe => File[sshdconfig],
}
Com esta dependência, o sshd o serviço sempre será reiniciado quando o sshdconfigalterações de arquivo. O ponto a ser lembrado aqui éFile[sshdconfig] é uma declaração como Arquivo em minúsculas, mas se mudarmos para FILE[sshdconfig] então teria sido uma referência.
Um ponto fundamental que se deve ter em mente ao declarar um recurso é que ele pode ser declarado apenas uma vez por arquivo de configuração. A repetição da declaração do mesmo recurso mais de uma vez causará um erro. Através deste conceito fundamental, o Puppet garante que a configuração seja bem modelada.
Temos até a capacidade de gerenciar a dependência de recursos, o que ajuda a gerenciar vários relacionamentos.
service { 'sshd':
require => File['sshdconfig', 'sshconfig', 'authorized_keys']
}
Metaparameters
Os meta-parâmetros são conhecidos como parâmetros globais no Puppet. Uma das principais características do meta-parâmetro é que ele funciona com qualquer tipo de recurso no Puppet.
Padrão de recurso
Quando é necessário definir um valor de atributo de recurso padrão, o Puppet fornece um conjunto de sintaxe para arquivá-lo, usando uma especificação de recurso em maiúscula sem título.
Por exemplo, se quisermos definir o caminho padrão de todos os executáveis, isso pode ser feito com o seguinte comando.
Exec { path => '/usr/bin:/bin:/usr/sbin:/sbin' }
exec { 'echo Testing mataparamaters.': }
No comando acima, a primeira instrução Exec definirá o valor padrão para o recurso exec. O recurso Exec requer um caminho totalmente qualificado ou um caminho que se parece com um executável. Com isso, pode-se definir um único caminho padrão para toda a configuração. Os padrões funcionam com qualquer tipo de recurso no Puppet.
Os padrões não são valores globais, no entanto, eles afetam apenas o escopo em que são definidos ou a variável seguinte a ele. Se alguém quiser definirdefault para uma configuração completa, então definimos o default e a classe na próxima seção.
Coleções de recursos
Agregação é o método de reunir coisas. O Puppet oferece suporte a um conceito de agregação muito poderoso. No Puppet, a agregação é usada para agrupar recursos que são a unidade fundamental do Puppet. Este conceito de agregação no Puppet é alcançado usando dois métodos poderosos conhecidos comoclasses e definition.
Classes e Definição
As classes são responsáveis por modelar os aspectos fundamentais do nó. Eles podem dizer que o nó é um servidor da web e este nó específico é um deles. No Puppet, as classes de programação são singleton e podem ser avaliadas uma vez por nó.
A definição, por outro lado, pode ser usada muitas vezes em um único nó. Eles funcionam da mesma forma que alguém criou seu próprio tipo de fantoche usando a linguagem. Eles são criados para serem usados várias vezes com entradas diferentes a cada vez. Isso significa que é possível passar valores de variáveis para a definição.
Diferença entre classe e definição
A única diferença fundamental entre uma classe e definição é que ao definir a estrutura do edifício e alocar recursos, a classe é avaliada apenas uma vez por nó, em que, por outro lado, uma definição é usada várias vezes no mesmo nó único.
Aulas
As classes no Puppet são introduzidas usando a palavra-chave class e o conteúdo dessa classe em particular é colocado dentro das chaves, conforme mostrado no exemplo a seguir.
class unix {
file {
'/etc/passwd':
owner => 'superuser',
group => 'superuser',
mode => 644;
'/etc/shadow':
owner => 'vipin',
group => 'vipin',
mode => 440;
}
}
No exemplo a seguir, usamos uma mão curta semelhante à anterior.
class unix {
file {
'/etc/passwd':
owner => 'superuser',
group => 'superuser',
mode => 644;
}
file {'/etc/shadow':
owner => 'vipin',
group => 'vipin',
mode => 440;
}
}
Herança em aulas de fantoches
No Puppet, o conceito OOP de herança é suportado por padrão em que as classes podem estender a funcionalidade do anterior sem copiar e colar o bit de código completo novamente na classe recém-criada. A herança permite que a subclasse substitua as configurações de recursos definidas na classe pai. Uma coisa importante a se ter em mente ao usar herança é que uma classe só pode herdar recursos de apenas uma classe pai, não mais de uma.
class superclass inherits testsubclass {
File['/etc/passwd'] { group => wheel }
File['/etc/shadow'] { group => wheel }
}
Se houver necessidade de desfazer alguma lógica especificada em uma classe pai, podemos usar undef command.
class superclass inherits testsubcalss {
File['/etc/passwd'] { group => undef }
}
Maneira Alternativa de Usar Herança
class tomcat {
service { 'tomcat': require => Package['httpd'] }
}
class open-ssl inherits tomcat {
Service[tomcat] { require +> File['tomcat.pem'] }
}
Classe aninhada no fantoche
O Puppet suporta o conceito de aninhamento de classes no qual permite o uso de classes aninhadas, o que significa uma classe dentro da outra. Isso ajuda a alcançar modularidade e escopo.
class testclass {
class nested {
file {
'/etc/passwd':
owner => 'superuser',
group => 'superuser',
mode => 644;
}
}
}
class anotherclass {
include myclass::nested
}
Classes Parametrizadas
No Puppet, as classes podem estender sua funcionalidade para permitir a passagem de parâmetros para uma classe.
Para passar um parâmetro em uma classe, pode-se usar a seguinte construção -
class tomcat($version) {
... class contents ...
}
Um ponto chave a ser lembrado no Puppet é que as classes com parâmetros não são adicionadas usando a função de inclusão, em vez disso, a classe resultante pode ser adicionada como uma definição.
node webserver {
class { tomcat: version => "1.2.12" }
}
Valores padrão como parâmetros na classe
class tomcat($version = "1.2.12",$home = "/var/www") {
... class contents ...
}
Executar etapas
O Puppet suporta o conceito de estágio de execução, o que significa que o usuário pode adicionar vários números de estágios de acordo com o requisito, a fim de gerenciar qualquer recurso específico ou vários recursos. Este recurso é muito útil quando o usuário deseja desenvolver um catálogo complexo. Em um catálogo complexo, há um grande número de recursos que precisam ser compilados, lembrando que as dependências entre os recursos definidos não devem ser afetadas.
O Run Stage é muito útil no gerenciamento de dependências de recursos. Isso pode ser feito adicionando classes em estágios definidos em que uma classe particular contém uma coleção de recursos. Com o estágio de execução, o Puppet garante que os estágios definidos serão executados em uma ordem previsível especificada toda vez que o catálogo for executado e aplicado em qualquer nó do Puppet.
Para usar isso, é necessário declarar estágios adicionais além dos estágios já presentes e o Puppet pode ser configurado para gerenciar cada estágio em uma ordem especificada usando a mesma sintaxe de relacionamento de recursos antes de exigir “->” e “+>”. O relacionamento irá garantir a ordem das classes associadas a cada estágio.
Declarando Estágios Adicionais com Sintaxe Declarativa de Puppet
stage { "first": before => Stage[main] }
stage { "last": require => Stage[main] }
Uma vez que os estágios tenham sido declarados, uma classe pode ser associada ao estágio diferente da principal usando o estágio.
class {
"apt-keys": stage => first;
"sendmail": stage => main;
"apache": stage => last;
}
Todos os recursos associados à classe apt-key serão executados primeiro. Todos os recursos do Sendmail serão a classe principal e os recursos associados ao Apache serão o último estágio.
Definições
No Puppet, a coleta de recursos em qualquer arquivo de manifesto é feita por classes ou definições. As definições são muito semelhantes a uma classe no Puppet, no entanto, são introduzidas com umdefine keyword (not class)e eles apóiam o argumento, não a herança. Eles podem ser executados no mesmo sistema várias vezes com parâmetros diferentes.
Por exemplo, se alguém deseja criar uma definição que controle os repositórios de código-fonte onde se está tentando criar vários repositórios no mesmo sistema, pode-se usar a definição, não a classe.
define perforce_repo($path) {
exec {
"/usr/bin/svnadmin create $path/$title":
unless => "/bin/test -d $path",
}
}
svn_repo { puppet_repo: path => '/var/svn_puppet' }
svn_repo { other_repo: path => '/var/svn_other' }
O ponto chave a ser observado aqui é como uma variável pode ser usada com uma definição. Nós usamos ($) variável de cifrão. Acima, usamos $ title. As definições podem ter um $ title e $ name com os quais o nome e o título podem ser representados. Por padrão, $ title e $ name são definidos com o mesmo valor, mas pode-se definir um atributo title e passar um nome diferente como parâmetro. $ title e $ name só funcionam por definição, não em classe ou outro recurso.
Módulos
Um módulo pode ser definido como uma coleção de todas as configurações que seriam usadas pelo mestre Puppet para aplicar mudanças de configuração em qualquer nó Puppet particular (agente). Eles também são conhecidos como coleção portátil de diferentes tipos de configurações, que são necessários para realizar uma tarefa específica. Por exemplo, um módulo pode conter todos os recursos necessários para configurar o Postfix e o Apache.
Nós
Os nós são etapas restantes muito simples, que é como combinamos o que definimos (“é assim que um servidor da web se parece”) com quais máquinas são escolhidas para cumprir essas instruções.
A definição do nó se parece exatamente com as classes, incluindo a herança de suporte, no entanto, eles são especiais de forma que quando um nó (um computador gerenciado executando um cliente fantoche) se conecta ao daemon mestre do Puppet, seu nome será visto na lista de nós definida. As informações definidas serão avaliadas para o nó, e então o nó enviará essa configuração.
O nome do nó pode ser um nome de host abreviado ou o nome de domínio totalmente qualificado (FQDN).
node 'www.vipin.com' {
include common
include apache, squid
}
A definição acima cria um nó chamado www.vipin.com e inclui o comum, Apache e Squid classe
Podemos enviar a mesma configuração para nós diferentes, separando cada um com vírgula.
node 'www.testing.com', 'www.testing2.com', 'www3.testing.com' {
include testing
include tomcat, squid
}
Expressão regular para nós correspondentes
node /^www\d+$/ {
include testing
}
Herança de Nó
O Node oferece suporte a um modelo de herança limitado. Como classes, os nós só podem herdar de um outro nó.
node 'www.testing2.com' inherits 'www.testing.com' {
include loadbalancer
}
No código acima, www.testing2.com herda todas as funcionalidades de www.testing.com, além de uma classe loadbalancer adicional.
Recursos avançados com suporte
Quoting- Na maioria dos casos, não precisamos citar uma string no Puppet. Qualquer string alfanumérica que comece com uma letra deve ser deixada sem aspas. No entanto, é sempre uma prática recomendada colocar uma string entre aspas para quaisquer valores não negativos.
Interpolação variável com cotações
Até agora mencionamos a variável em termos de definição. Se for necessário usar essas variáveis com uma string, use aspas duplas, não aspas simples. A string de aspas simples não fará nenhuma interpolação de variável, a string de aspas duplas fará. A variável pode estar entre colchetes{} o que os torna mais fáceis de usar juntos e mais fáceis de entender.
$value = "${one}${two}"
Como prática recomendada, deve-se usar aspas simples para todas as strings que não requerem interpolação de string.
Capitalização
A capitalização é um processo usado para referência, herança e definição de atributos padrão de um recurso específico. Existem basicamente duas maneiras fundamentais de usá-lo.
Referencing- É a forma de referenciar um recurso já criado. É usado principalmente para fins de dependência, é necessário colocar o nome do recurso em maiúscula. Exemplo, requerer => arquivo [sshdconfig]
Inheritance- Ao substituir a configuração da classe pai da subclasse, use a versão em maiúsculas do nome do recurso. Usar a versão em minúsculas resultará em erro.
Setting Default Attribute Value - Usar o recurso capitalizado sem nenhum título funciona para definir o padrão do recurso.
Arrays
O Puppet permite o uso de matrizes em várias áreas [Um, dois, três].
Vários membros de tipo, como alias na definição de host, aceitam matrizes em seus valores. Um recurso de host com vários aliases terá a seguinte aparência.
host { 'one.vipin.com':
alias => [ 'satu', 'dua', 'tiga' ],
ip => '192.168.100.1',
ensure => present,
}
O código acima irá adicionar um host ‘one.brcletest.com’ para a lista de hosts com três aliases ‘satu’ ‘dua’ ‘tiga’. Se quisermos adicionar vários recursos a um recurso, isso pode ser feito conforme mostrado no exemplo a seguir.
resource { 'baz':
require => [ Package['rpm'], File['testfile'] ],
}
Variáveis
O Puppet suporta múltiplas variáveis como a maioria das outras linguagens de programação. Variáveis fantoches são denotadas com$.
$content = 'some content\n'
file { '/tmp/testing': content => $content }
Como afirmado anteriormente, o Puppet é uma linguagem declarativa, o que significa que seu escopo e regras de atribuição são diferentes da linguagem imperativa. A principal diferença é que não se pode alterar a variável dentro de um único escopo, porque eles dependem da ordem do arquivo para determinar o valor de uma variável. A ordem não importa na linguagem declarativa.
$user = root
file {
'/etc/passwd':
owner => $user,
}
$user = bin
file {
'/bin':
owner => $user,
recurse => true,
}
Escopo Variável
O escopo da variável define se todas as variáveis definidas são válidas. Tal como acontece com os recursos mais recentes, o Puppet tem atualmente um escopo dinâmico, o que em termos do Puppet significa que todas as variáveis definidas são avaliadas em seu escopo, e não no local em que foram definidas.
$test = 'top'
class Testclass {
exec { "/bin/echo $test": logoutput => true }
}
class Secondtestclass {
$test = 'other'
include myclass
}
include Secondtestclass
Variável Qualificada
O Puppet suporta o uso de variáveis qualificadas dentro de uma classe ou definição. Isso é muito útil quando o usuário deseja usar a mesma variável em outras classes, que ele definiu ou vai definir.
class testclass {
$test = 'content'
}
class secondtestclass {
$other = $myclass::test
}
No código acima, o valor de $ outra variável avalia o conteúdo.
Condicionais
Condições são situações em que o usuário deseja executar um conjunto de instruções ou códigos quando a condição definida ou exigida é satisfeita. O Puppet suporta dois tipos de condições.
A condição do seletor que só pode ser usada dentro dos recursos definidos para escolher o valor correto da máquina.
As condições de instrução são condições mais amplamente usadas no manifesto, o que ajuda a incluir classes adicionais que o usuário deseja incluir no mesmo arquivo de manifesto. Defina um conjunto distinto de recursos dentro de uma classe ou tome outras decisões estruturais.
Seletores
Os seletores são úteis quando o usuário deseja especificar um atributo de recurso e variáveis que são diferentes dos valores padrão com base nos fatos ou outras variáveis. No Puppet, o índice do seletor funciona como um operador triplo de valores múltiplos. Os seletores também são capazes de definir os valores padrão personalizados em nenhum valor, que são definidos no manifesto e correspondem à condição.
$owner = $Sysoperenv ? {
sunos => 'adm',
redhat => 'bin',
default => undef,
}
Em versões posteriores do Puppet 0.25.0, os seletores podem ser usados como expressões regulares.
$owner = $Sysoperenv ? {
/(Linux|Ubuntu)/ => 'bin',
default => undef,
}
No exemplo acima, o seletor $Sysoperenv valor corresponde a Linux ou Ubuntu, então o bin será o resultado selecionado, caso contrário, o usuário será definido como indefinido.
Condição de declaração
A condição de instrução é outro tipo de instrução condicional no Puppet que é muito semelhante à condição de mudança de caso no script Shell. Nesse caso, um conjunto múltiplo de declarações de caso é definido e os valores de entrada fornecidos são comparados a cada condição.
A instrução case que corresponde à condição de entrada fornecida é executada. Esta condição de instrução de caso não tem nenhum valor de retorno. No Puppet, um caso de uso muito comum para a instrução de condição é a execução de um conjunto de bits de código com base no sistema operacional subjacente.
case $ Sysoperenv {
sunos: { include solaris }
redhat: { include redhat }
default: { include generic}
}
A instrução de caso também pode especificar várias condições, separando-as com uma vírgula.
case $Sysoperenv {
development,testing: { include development } testing,production: { include production }
default: { include generic }
}
Declaração If-Else
O Puppet apóia o conceito de operação baseada em condições. Para alcançá-lo, a instrução If / else fornece opções de ramificação com base no valor de retorno da condição. Conforme mostrado no exemplo a seguir -
if $Filename {
file { '/some/file': ensure => present }
} else {
file { '/some/other/file': ensure => present }
}
A última versão do Puppet suporta expressão variável na qual a instrução if também pode se ramificar com base no valor de uma expressão.
if $machine == 'production' {
include ssl
} else {
include nginx
}
Para obter mais diversidade no código e realizar operações condicionais complexas, o Puppet oferece suporte à instrução if / else aninhada, conforme mostrado no código a seguir.
if $ machine == 'production' {
include ssl
} elsif $ machine == 'testing' {
include nginx
} else {
include openssl
}
Recurso Virtual
Recursos virtuais são aqueles que não são enviados ao cliente a menos que sejam realizados.
A seguir está a sintaxe de uso de recursos virtuais no Puppet.
@user { vipin: ensure => present }
No exemplo acima, o usuário vipin é definido virtualmente para realizar a definição que pode ser usada na coleção.
User <| title == vipin |>
Comentários
Os comentários são usados em qualquer bit de código para criar um nó adicional sobre um conjunto de linhas de código e sua funcionalidade. No Puppet, existem atualmente dois tipos de comentários suportados.
- Comentários ao estilo do shell Unix. Eles podem estar em sua própria linha ou na próxima linha.
- Comentários multi-linhas no estilo c.
A seguir está um exemplo de comentário de estilo de shell.
# this is a comment
A seguir está um exemplo de comentário de várias linhas.
/*
This is a comment
*/
operador precedente
A precedência do operador Puppet está em conformidade com a precedência padrão na maioria dos sistemas, da mais alta à mais baixa.
A seguir está a lista de expressões
- ! = não
- / = vezes e dividir
- - + = menos, mais
- << >> = deslocamento para a esquerda e deslocamento para a direita
- ==! = = diferente, igual
- > = <=> <= maior igual, menor ou igual, maior que, menor que
Expressão de Comparação
A expressão de comparação é usada quando o usuário deseja executar um conjunto de instruções quando a condição fornecida é satisfeita. As expressões de comparação incluem testes de igualdade usando a expressão ==.
if $environment == 'development' {
include openssl
} else {
include ssl
}
Exemplo Diferente
if $environment != 'development' {
$otherenvironment = 'testing'
} else {
$otherenvironment = 'production'
}
Expressão Aritmética
$one = 1
$one_thirty = 1.30
$two = 2.034e-2 $result = ((( $two + 2) / $one_thirty) + 4 * 5.45) -
(6 << ($two + 4)) + (0×800 + -9)
Expressão Booleana
Expressões booleanas são possíveis usando or, and, & not.
$one = 1
$two = 2
$var = ( $one < $two ) and ( $one + 1 == $two )
Expressão regular
O Puppet suporta correspondência de expressão regular usando = ~ (correspondência) e! ~ (Não correspondência).
if $website =~ /^www(\d+)\./ {
notice('Welcome web server #$1')
}
Como a correspondência de regex de caso e seletor cria uma variável de escopo limitada para cada regex.
exec { "Test":
command => "/bin/echo now we don’t have openssl installed on machine > /tmp/test.txt",
unless => "/bin/which php"
}
Da mesma forma, podemos usar a menos que, a menos que execute o comando o tempo todo, exceto o comando sob a menos que seja encerrado com êxito.
exec { "Test":
command => "/bin/echo now we don’t have openssl installed on machine > /tmp/test.txt",
unless => "/bin/which php"
}
Trabalhando com Modelos
Os modelos são usados quando se deseja ter uma estrutura pré-definida que será usada em vários módulos no Puppet e esses módulos serão distribuídos em várias máquinas. A primeira etapa para usar o modelo é criar um que renderize o conteúdo do modelo com métodos de modelo.
file { "/etc/tomcat/sites-available/default.conf":
ensure => "present",
content => template("tomcat/vhost.erb")
}
A Puppet faz poucas suposições ao lidar com arquivos locais para garantir a organização e a modularidade. O Puppet procura o template vhost.erb dentro da pasta apache / templates, dentro do diretório modules.
Definição e acionamento de serviços
No Puppet, ele possui um recurso denominado serviço que é capaz de gerenciar o ciclo de vida de todos os serviços executados em qualquer máquina ou ambiente específico. Os recursos de serviço são usados para garantir que os serviços sejam inicializados e habilitados. Eles também são usados para reiniciar o serviço.
Por exemplo, no modelo anterior do tomcat que temos, onde definimos o host virtual apache. Se alguém quiser garantir que o apache seja reiniciado após uma mudança de host virtual, precisamos criar um recurso de serviço para o serviço apache usando o seguinte comando.
service { 'tomcat':
ensure => running,
enable => true
}
Ao definir os recursos, precisamos incluir a opção de notificação para acionar o reinício.
file { "/etc/tomcat/sites-available/default.conf":
ensure => "present",
content => template("vhost.erb"),
notify => Service['tomcat']
}