как лениво определить класс в манифесте марионетки - PullRequest
0 голосов

У меня есть система с разными ролями, AB C. Существует класс daemon::conf, который определяет conf и объединяет конфигурации всех аргументов классов, например,

class daemon::conf (
  global_config = {}
  a_config      = {}
  b_config      = {}
  c_config      = {}
) {
concat::fragment {...}
}

Итак, когда я делаю это:

class hg_mysystem::mycluster::hybrid {
  include daemon::A
  include daemon::B
}

Я хочу иметь:

$ cat /etc/mysystem/config
[Global]
...
[A]
...
[B]
...

каждый демон определяется как daemon::A, daemon::B, daemon::C, но они вызывают daemon::conf со своими собственными параметрами, которые либо определены в hiera внутри файлов .pp манифеста. Теперь мне нужно создать узел с 2 или 3 ролями (написание include daemon::A;include daemon::B et c), но у меня проблема с переопределением класса, потому что daemon :: conf определен во всех AB и C.

Моя первая мысль заключалась в том, чтобы определить класс на одном узле и добавить if defined(Class['daemon::conf']) {add argument to the defined class} else {class{'daemon::conf'...}}, но я не знаю, как создать динамическую c переменную hiera из манифеста или как выполнить назначение стиля hiera из манифест. Я также искал, как выполнить ленивую инициализацию класса с этими виртуальными ресурсами, но я не понимаю, как это может помочь, когда реализация не отменяет аргумент, а осознает, что вы делаете только это realise Class['daemon::conf'], а не realise Class['daemon::conf'] {b_config={...}}. Есть ли способ реструктурировать daemon::conf с подклассами, которые уведомляют другой класс, который строит conf на основе данных классов.

Изменить:

Я следил за второй подход и разделение daemon::conf на daemon::conf, daemon::conf::A, daemon::conf::B

class daemon::conf (...) {
  concat { '/etc/daemon/conf':
    owner   => 'root',
    group   => 'root',
    mode    => '0664',
    require => Package['daemon'],
  }

  Concat::Fragment <<| target == '/etc/daemon/config' |>>

  concat::fragment { 'daemon.conf':
    tag     => "daemon.conf",
    target  => '/etc/daemon/config',
    order   => '01',
    content => template('daemon/daemon.conf.erb'),
  }
}

define daemon::conf::A (...) {
  include ::daemon::conf

  @@concat::fragment { "${::hostname}.daemon.conf":
    tag     => "daemon.conf",
    target  => '/etc/daemon/config',
    order   => '20',
    content => template('daemon/daemon.conf-A.erb'),
  }

}

class daemon::conf::B (...) {
  include ::daemon::conf

  concat::fragment { $::hostname:
    tag     => "daemon.conf",
    target  => '/etc/daemon/config',
    order   => '10',
    content => template('daemon/daemon.conf-B.erb'),
  }

}

class daemon::A (
  $A_addr,
  $port,
) {
  include ::daemon::conf

  daemon::conf::A { $::hostname:
    addr => $A_addr,
    port => $port,
  }
}

class daemon::B (
  $B_rack_loc,
) {
  include ::daemon::conf

  class {'::daemon::conf::B':
    B_config => {
      B_rack_location => $B_rack_loc,
    }
  }
}

Запуск марионетки на 3 узлах в одной группе хостов, я должен получить:

[user@hostname1: ~]$ cat /etc/daemon/config
[Global]
...
[B]
loc = row RO, rack RA, host hostname1
[A/hostname1 ip]
addr=...
port=...
[A/hostname2 ip]
addr=...
port=...
[A/hostname3 ip]
addr=...
port=...

Но вместо этого я получаю несколько конфигураций роли B, а также всех 3 хостов. Какую ошибку мне сделать и как ее исправить? Спасибо. Следует ли изменить выражение «<< | | >>»?

1 Ответ

2 голосов
/ 09 июля 2020

Любое решение должно учитывать тот факт, что значения всех параметров данного класса определяются при первой оценке объявления этого класса, независимо от того, является ли объявление ресурсоподобным или включить-подобный. Множественные объявления разрешены только в том случае, если все они оцениваются после первого использования одной из включаемых форм, и это одна из причин, по которым в большинстве случаев следует избегать объявления классов, подобных ресурсам.

* 1004 принять эти соображения во внимание. Можно было бы инвертировать logi c: вместо того, чтобы каждый класс daemon::X объявлял daemon::conf, объявлять его один раз централизованно и передавать ему список ролей для настройки. Затем пусть он объявит соответствующие классы daemon::conf::X на основе списка ролей:
class daemon::conf (
  $global_config = {}
  $roles =         []
) {
  concat { ... }
  concat::fragment {...}
  $roles.each { |$role|
    contain "daemon::conf::${role}"
  }
}

Другой способ - вообще освободить центральный класс daemon::conf от ответственности за объявление конфигурации для каждой роли. Это возможно, потому что вы используете Concat для создания конфигурации из фрагментов. Одна из ключевых особенностей puppetlabs :: concat заключается в том, что concat::fragment s могут быть объявлены независимо друг от друга и concat, объявляющего файл, в который они вносят:

class daemon::conf (
  $global_config = {}
) {
  concat { ... }
  concat::fragment {...}  # general configuration only
}

class daemon::a::conf (...) {
  concat::fragment {...}  # daemon A configs
}

class daemon::b::conf (...) {
  concat::fragment {...}  # daemon B configs
}

class daemon::a (...) {
  include daemon::conf     # (maybe)
  contain daemon::a::conf
  # ...
}

class daemon::b (...) {
  include daemon::conf     # (maybe)
  contain daemon::b::conf
  # ...
}

...
...