web-dev-qa-db-ja.com

puppetコードの設計:引数を文字列に収集する方法(重複する宣言エラーの可能性を回避する)

Puppet(バージョン5.5)のコードデザインに問題があります。 ucarpを処理するためのコンポーネントモジュールを作成しました。モジュール eyp-systemd を利用して、systemd内にucarpサービスを登録します。ここで、異なるサービス(私の場合は実際にはhaproxyとbind9)を管理する2つの独立したプロファイルモジュールからucarpモジュールを使用したいと思います。基本的にこれは次のようになります。

class ucarp {
  systemd::service { 'ucarp':
    # list of parameters
  }
}

define ucarp::vip {
  # defines a virtual IP to be shared among several nodes
}

# ====================

class profile_haproxy {
  include ::ucarp
  ::ucarp::vip { 'haproxy': }
  # setup haproxy
}

# =====================

class profile_bind9 {
  include ::ucarp
  ::ucarp::vip { 'bind9': }
  # setup bind9
}

これは簡単で、うまく機能します。

ここで実際の問題:ucarp上で実行されるサービスの後にucarpサービスを注文することをお勧めします。これは、afterパラメーターを使用して可能です。

class ucarp(
  Array[String] $after,
) {
  systemd::service { 'ucarp':
    after => $after.join(' '),
    # list of other parameters
  }
}

これには、include ::ucarpをに置き換える必要があります

class { '::ucarp':
  after => ['haproxy'],
}

または

class { '::ucarp':
  after => ['bind9'],
}

それぞれ。もちろん、これはすぐに「重複宣言」エラーにつながります。

私が実際に望んでいるのは、すべてのafterパラメーターをsystemd :: serviceに渡すことができる単一の文字列に収集するクラスucarpの単一のインスタンス化です。 どうすればよいですか?

現在、2つの可能な解決策が思い浮かびます。

  1. フォーク eyp-systemd 、afterパラメーターを削除し、定義されたタイプに置き換えます。 systemd::service::afterは、サービス定義ファイル内の対応するエントリを管理します。これは私が本当にやりたくないことです。一般的に、私はフォージモジュールを変更することを躊躇します。この場合、変更もかなり大きいようです(インターフェイスの変更を含む)。
  2. 何もしないucarpモジュールucarp::order_afterに自分で定義した型を導入します。プロファイルモジュールは、このタイプの仮想インスタンスを定義します。次に、ucarpクラスはpuppetdbクエリを使用して、ucarp::order_afterのすべてのインスタンスを収集できます。ここでの大きな欠点は、エクスポートされたリソースではなく、仮想リソースのみを扱っていることです。したがって、実際にはpuppetdbを関与させる必要はまったくなく、このアプローチは醜い回避策になります。

さらなる解決策はc4f4t0rに触発されています:

  1. 単一のタスクが正しいafterサービスでucarpコンポーネントクラスをインスタンス化することであるucarpプロファイルモジュールを導入します。 afterサービスのリストは、hieraによって提供されます。
     class profile_ucarp(
     Array [String] $ after、
    ){
     class {':: ucarp':
     after => $ after 、
    } 
    }
     profile_ucarp.after:
    -'haproxy' 
    -'bind9' 
    
    他のプロファイルクラスがucarpクラスをインスタンス化する必要はもうありません-潜在的な重複宣言の問題を削除します。このソリューションは、上記の2つよりも優れていると思います。それでも、コードのみに関連する問題を修正するためにhieraを使用することは、hieraの誤用であるため、私は満足していません。

今は考えられない可能性が他にもあるといいのですが。

2
C.Scharfenberg

Contains関数を使用して、クラスパラメータをhieraに配置する必要があります。

プロファイルモジュールでは、クラスのプロファイルを格納するためにhieraを使用していないため、クラスを複製しているため、クラスprofile :: haproxyとprofile :: bindは1つだけにすることができます。

class profile::ucarp {
  contain ::ucarp
  contain ::ucarp::vip
}

class profile::haproxy {
  contain ::haproxy
}

 #now I can create a role using this profiles

class role::elb {
  contain ::profile::ucarp
  contain ::profile::haproxy
}

Hiera内で、ホストの機能に基づいてパラメーターを保存できるようになりました。エラーを回避したい場合は、puppetdocの役割とプロファイルを使用してデザインを確認してみてください。

人形のドキュメントから

Having classes contain other classes can be very useful, especially in larger modules where you want to improve code readability by moving chunks of implementation into separate files.

    However, unlike resources, Puppet does not automatically contain classes when they are declared inside another class. This is because classes can be declared in several places via include and similar functions. Most of these places shouldn’t contain the class, and trying to contain it everywhere would cause huge problems.

    Instead, you must manually contain any classes that need to be contained.
2
c4f4t0r