Puppet: Como sobrescrever / redefinir a classe filha externa (usecase e exemplo detalhado)

6

O caso de uso que eu tento ilustrar é quando declarar algum item (eq serviço mysqld) com uma configuração padrão que poderia ser incluída em cada nó (classdown da classe no exemplo, para basenode), e ainda ser capaz de sobrescrever isso mesmo item em alguma classe específica (por exemplo, mysql :: server), para ser incluído por nós específicos (por exemplo, myserver.local)

Eu ilustrei este caso de uso com o exemplo abaixo, onde eu quero desativar o serviço mysql em todos os nós, mas ativá-lo em um nó específico. Mas é claro, a análise do Puppet falha porque o Service [mysql] está incluído duas vezes. E, claro, a classe mysql :: server não tem nenhuma relação com um filho de classe stripdown

Existe uma maneira de substituir o Service ["mysql"], ou marcá-lo como o principal, ou o que for? Eu estava pensando sobre os itens virtuais e a função realize, mas só permite aplicar um item várias vezes, não para redefinir ou substituir.

# In stripdown.pp :
class stripdown {
    service {"mysql": enable => "false", ensure => "stopped" }
}

# In mysql.pp :
class mysql::server {  
    service { mysqld:  
        enable      => true,  
        ensure      => running,  
        hasrestart  => true,  
        hasstatus   => true,  
        path        => "/etc/init.d/mysql",  
        require     => Package["mysql-server"],  
    }
}

# Then nodes in nodes.pp :
node basenode {
    include stripdown
}

node myserver.local inherits basenode {  
    include mysql::server'         # BOOM, fails here because of Service["mysql"] redefinition             
}
    
por Alex F 10.12.2009 / 05:10

4 respostas

2

Tenha isso em mente:

# In stripdown.pp : 
class stripdown {
    service { "mysql": 
         enable => "false", 
         ensure => "stopped" 
    }
}

# In mysql.pp : 
class mysql::server {  

    if defined(Service["mysql"]) {
        Service["mysql"] {  
            enable     => true,  
            ensure     => running,  
            hasrestart => true,  
            hasstatus  => true,  
            path       => "/etc/init.d/mysql",  
            require    => Package["mysql-server"],  
        }
    } else {
        service { "mysql":  
            enable     => true,  
            ensure     => running,  
            hasrestart => true,  
            hasstatus  => true,  
            path       => "/etc/init.d/mysql",  
            require    => Package["mysql-server"],  
        }
    }
}

# Then nodes in nodes.pp : 
node basenode {
    include stripdown 
}

node myserver.local inherits basenode {  
    include mysql::server
}

Isso, é claro, vem com a ressalva de que você já tem o pacote ["mysql-server"] definido em outro lugar, pois ele falhará como foi escrito sem ele devido às instruções require .

O outro erro que encontrei foi que você tinha muitos espaços após as opções. As opções na sub-rotina devem estar alinhadas com no máximo 1 espaço maior que o nome da opção mais longa.

    
por 09.01.2010 / 07:19
2

Sempre que você se encontrar dizendo "Eu quero que esse componente se comporte de uma maneira em um nó, mas de maneira diferente em outro nó", provavelmente você precisa estar olhando para uma definição orientada por variáveis, seja por meio de condicionais na definição de classe ou substituições em um modelo.

Infelizmente, o seu exemplo mostra que você está tentando usar a herança, que é muito mal quebrada no fantoche e causará muito sofrimento aqui, porque uma das coisas que ela quebra é a redefinição variável nos nós.

UPDATE: os detalhes das respostas antigas estão obsoletos

O que estou fazendo a partir de 2.7 é garantir que todas as variáveis usadas por uma classe não sejam variáveis globais, mas sim parâmetros com padrões razoáveis definidos. Você ainda não quer usar a herança incorporada no Puppet, mas agora você pode substituir variáveis específicas diretamente da definição do nó, e você pode até mesmo ter uma forma primitiva de herança manualmente com uma classe variáveis e, em seguida, passá-los para uma chamada de outra classe. Por exemplo, você teria nas definições do seu nó:


node experimental_server {
  # This will still call class 'databases', but will install Postgresql and not Mysql
  # as a default.  You can still override it the same way as with 'databases'
  class { 'mydept::nextgeneration': },
}
node server_with_mysql {
  class { 'databases':
    mysql_enabled => true,
  }
}
node server_with_no_db {
  class { 'databases': # this installs only the clients }
}

class databases (
  # By default, install no servers, just clients
  $pgsql_enabled => false,
  $mysql_enabled => false
)
{
  ...
}

class mydept::nextgeneration (
  # If not explicitly overridden, an undef value passed as a parameter to a class
  # assumes the default value in that class
  $mysql_enabled => undef,
  $pgsql_enabled => true
)
{
  class { 'databases':
    mysql_enabled => $mysql_enabled,
    pgsql_enabled => $pgsql_enabled,
  }
}

Como um comentarista observou, agora há também um novo recurso bacana chamado Hiera, que permite descarregar padrões em uma estrutura de dados separada, e você deve investigar se tiver o Puppet 3.2 disponível. Infelizmente, muitas distribuições do Linux ainda vêm com 2.6 ou 2.7, então isso pode não ser uma opção para você.

Detalhes da resposta anterior preservados abaixo

A maneira que eu geralmente lidei com algo assim é criar um arquivo 'default_parameters.pp' que não tem nada nele, mas atribuições padrão para uma longa lista de variáveis, então nesse caso, ele conteria uma linha como% código%. Este arquivo é então incluído pelo arquivo init.pp do módulo. Em seguida, o arquivo de definições do nó seria algo como:

import "mymodule"

node myserver.local {   # NOTE: no inheritance!
  $mysql_enabled = true
  include mysql::server
}

node otherserver.local {
  include mysql::server
}

Em seguida, na definição de classe para mysql :: server, você verifica se $mysql_enabled = false é true e, em caso afirmativo, use um seletor em $mysql_enabled e enable .

Isso quebra instantaneamente se o nó myserver.local herda qualquer coisa, porque isso irá bloquear o valor das variáveis no tempo de herança, e outras mudanças dentro da definição do nó não terão efeito, mas caso contrário eu uso essa técnica em todo lugar para ter componentes individuais se comportando de maneira diferente sem gerar várias classes.

Se você absolutamente precisa ter herança, mas a lista de máquinas com o mysql ativado é pequena, você pode usar uma rota alternativa: em vez de definir uma variável na definição do nó, construa seu seletor fora de ensure , com o padrão para desabilitar e selecionar fqdns habilitado.

    
por 02.03.2010 / 22:45
0

Dê um presente

# In stripdown.pp : 
class stripdown {
    service { "mysql": 
         enable => "false", 
         ensure => "stopped" 
    }
}

# In mysql.pp : 
class mysql::server inherits stripdown {  
    Service["mysqld"] {  
        enable      => true,  
        ensure      => running,  
        hasrestart  => true,  
        hasstatus   => true,  
        path        => "/etc/init.d/mysql",  
        require     => Package["mysql-server"],  
    } 
}

# Then nodes in nodes.pp : 
node basenode {
    include stripdown 
}

node myserver.local inherits basenode {  
    include mysql::server
}
    
por 10.12.2009 / 05:17
0

Uma coisa que você pode querer olhar é Recursos Virtuais para contornar a definição múltipla de recursos. A documentação sobre esse tópico pode ser encontrada: link

Naturalmente, a outra maneira seria criar objetos de nó simples para cada host que não executasse o mysql e, em seguida, carregasse a classe separada nele.

    
por 08.02.2010 / 14:35