web-dev-qa-db-ja.com

削除せずに人形でディレクトリツリーを再帰的に作成する

ディレクトリ構造を作成したい/var/www/apps/example/current/publicパペットを使用して存在しない場合。すでに存在する場合は、ディレクトリの内容を削除しません。どうすればよいですか?以下は私がこれまでに持っているものです:

file { "/var/www/apps/example/current/public":
  owner => 'deploy',
  group => 'users',
  ensure => "directory",
  purge => false,
  recurse => true
}

これは私に与えます

 Cannot create /var/www/apps/example/current/public; parent directory /var/www/apps/example/current does not exist
14
Kyle Decot

recurseパラメータでは、親ディレクトリを作成できません。 ownermodeなどのプロパティ値をディレクトリの内容とサブディレクトリに再帰的に適用するために使用されます。

file { '/var/www':
    owner   => 'www-data',
    recurse => true,
}

実際、Puppetは現在、すべての親ディレクトリを自動的に作成することはできません。代わりに、関連するすべてのディレクトリをリソースとして追加する必要があります。

file { [ '/var/www/apps',
         '/var/www/apps/example',
         '/var/www/apps/example/current',
         '/var/www/apps/example/current/public', ]:
           ensure => directory,
           ...
}

既存のコンテンツは悪用されません。 purgeパラメータを渡す必要はありません。

19
Felix Frank

"define"を使用すると、次のようになります。

mymodule::recursive_dir { "My Directory" :
   drive => "C:",
   path  => "/path/to/folder",
}

Mymodule.rbで「定義」を定義する場所:

define mymodule::recursive_dir ($drive, $path) {
  $folders = split($path, "/")
  $folders.each |$index, $folder| {
    $calculated_folder = inline_template("<%= @folders[0, @index + 1].join('/') %>")
    $full_path = "${drive}${calculated_folder}"
    if (! defined(File[$full_path]) and $full_path != $drive) {
      file { $full_path :
        ensure => directory,
      }
    }
  }
}

これは、パスを分割し、パスを元に戻すときに各ディレクトリを作成します。ドライブ自体を作成しないようにしてください。

1
NickRamirez

AnthonyYに感謝します。

私は彼の関数のコードをどこに置くかわからなかったので、私の研究の結果、新しい構文を使用してすべてを書き直しましたが、彼のロジックは保持しています。

それをすべて処理するのにしばらくかかったので、ここに投稿するのが良いと思いました。 ...私は彼の答えにコメントとしてそれを追加したでしょうが、どうやらそれを行うにはゼロではなく50ポイントが必要なようです。

コードは、次のようにPuppet環境ディレクトリ内の独自のファイルに保存する必要があります。

lib/puppet/functions/parentdirs.rb

...完全なパスは次のようになります(Ubuntuサーバー18.04では、Puppetパッケージを使用し、レポパッケージは使用しません)。

/etc/puppetlabs/code/environments/testing/lib/puppet/functions/parentdirs.rb

...他の場所に置くことができるようですが、これは私がやったことです。

ファイルが.rb、ではない.pp(Rubyコードであり、Puppetではないため))。

ほとんどの情報は https://puppet.com/docs/puppet/5.5/functions_Ruby_overview.html とサブページから入手しました。

使用法は元の関数と同じであり、コメントで多少再説明されています

# Returns an array of the parent directories to the given file or directory. This can then be passed to File to create the directory tree require for a dynamic path value.
# Parameter 2 is an optional, higher level of the same path. These higher level directories will not be in the array.
# Example 1: parameter 1 is '/var/www/mysite'; parameter 2 is not given; returns array ['/var', '/var/www']
# Example 2: parameter 1 is '/var/www/mysite'; parameter 2 is '/var'; returns array ['/var/www']

Puppet::Functions.create_function(:parentdirs) do

  dispatch :parents do
    required_param 'String', :target_dir
    optional_param 'String', :dir_until
    return_type 'Array'
  end


  def parents(target_dir, dir_until = '')

    cur = File.dirname(target_dir)
    result = []

    begin
        result.unshift(cur)
        last = cur
        cur = File.dirname(cur)
    end while cur != last and !cur.end_with?('/') and cur != dir_until

    return result

  end

end
0
Colin Conway

これは、mkdir -p $(dirname $file_path)を実行するための純粋なパペットソリューションです。

$file_path = '/tmp/foo/bar/bob.conf' # assumes file_path is Stdlib::Unixpath
# strip leading '/' then split and loop
$dirs = $file_path[1,-1].dirname.split('/').reduce([]) |$memo, $subdir| {
    $_dir =  $memo.empty ? { 
        true    => "/${subdir}",
        default => "${$memo[-1]}/${subdir}",
    }     
    concat($memo, $_dir)
}
file {$dirs:
    ensure => directory,
}
0
balder

良い解決策を見つけようとしましたが失敗しました。だから私は自分で方法を見つけました。うまくいけば、それは他の人々にとって有用です。

次の関数は親ディレクトリのリストを生成し、そのリストを使用して親フォルダーを作成できます。最初の引数は、親ディレクトリを検索するための開始点として使用されるパスです。 2番目の引数はオプションであり、検索を停止するための終了点(排他的)として使用されます。

module Puppet::Parser::Functions
  newfunction(:parentdirs, :type => :rvalue, :doc => <<-EOS
    Build a list of all its parent directories.
    EOS
  ) do |arguments|

    raise(Puppet::ParseError, "parentdirs(): Wrong number of arguments " +
      "given (#{arguments.size} for 1)") if arguments.size < 1

    $dir_until = arguments.size > 1 ? arguments[1] : nil
    $cur = File.dirname(arguments[0])
    $result = []
    begin
        $result.unshift($cur)
        $last = $cur
        $cur = File.dirname($cur)
    end while $cur != $last and !$cur.end_with?('/') and $cur != $dir_until

    return $result
  end
end

使用方法の例を次に示します。

$my_folder = '/var/www/apps/example/current/public'
$parent_dirs = parentdirs($my_folder, '/var/www/apps')
file { $parent_dirs:
  ensure => 'directory',
  owner => 'deploy',
  group => 'users'
}
file { $my_folder:
  ensure => 'directory',
  owner => 'deploy',
  group => 'anonymous'
}

上記のコードは、 '/ var/www/apps/example/current/public'を作成する前に、 '/ var/www/apps/example/current'および '/ var/www/apps/example/current'を作成してから '/ var/www/apps/example '以上は変更されません。

Windowsでのみテストしました。しかし、それはLinux環境で動作するはずです。

これは理想的ではありません。しかし、手動ですべての親を1つずつリストするよりはましです。

0
AnthonyY

Puppetが親ディレクトリを作成しないことは事実ですが、これを行うファイルのようなプロバイダーを簡単に作成できます。例として、POSIXシステムで基本的に「mkdir -p」を実行するカスタムタイプとプロバイダーを作成しました: https://docs.puppetlabs.com/puppet/latest/reference/lang_namespaces.html

ただし、Puppetがデフォルトでこれを行わないことには、本当に十分な理由があります。これは、エージェントがrootとして実行されるため、Puppetが複数のディレクトリにまたがるアクセス許可の責任を負いたくないためです。/var/wwwか何かをプロビジョニングしている場合、それは悪いことです。

再利用ファイルパラメータは、実際にはディレクトリツリーパラメータを管理するためのものです。 https://docs.puppetlabs.com/references/latest/type.html#file-attribute-recurse

ディレクトリツリーを作成し、たとえばsource => 'puppet:///' uriを使用して提供できます。recurseをtrueに設定すると、提供されるディレクトリツリーで設定されているすべてのファイルモードが使用されます。

0
Jeff Malnick