Chef (솔로) 레시피를 반복하는 올바른 방법은 무엇입니까?


8

누군가 요리사가 어떻게 작동하는지 설명해 주시겠습니까? 그것은 매우 광범위한 질문이므로 좁히기 위해 사용자 목록을 반복하고 아직 존재하지 않는 경우 각 사용자를 만드는 매우 간단한 레시피가 있습니다. 작동하지 않습니다.

내가 알 수있는 것에서 루프는 내가 예상 한대로 일어나는 것 같습니다. 루프가 완료되면 각 사용자를 만들기위한 bash 명령이 루프에서 반복 될 때마다 한 번씩 실행됩니다. 그러나 bash 명령이 실행될 때 첫 번째 루프 반복의 사용자 값 만있는 것 같습니다.

이 예제와 유사한 변수 데이터를 반복하는 레시피를 작성하는 올바른 방법은 무엇입니까?

레시피는 다음과 같습니다.

node[:users].each do |user|
  puts "in loop for #{user['username']}"
  bash "create_user" do
    user "root"
    code do
      puts "running 'useradd' for #{user['username']}"
      "useradd #{user['username']}"
    end
    not_if do
      puts "checking /etc/passwd for #{user['username']}"
      "cat /etc/passwd | grep #{user['username']}"
    end
  end
end

다음 설정으로 Vagrant를 사용하여 이것을 테스트하고 있습니다.

Vagrant::Config.run do |config|
  config.vm.box = "precise32"
  config.vm.box_url = "http://files.vagrantup.com/precise32.box"
  config.vm.provision :chef_solo do |chef|
    chef.add_recipe "sample"
    chef.json = {
      :users => [
        {:username => 'testA'},
        {:username => 'testB'},
        {:username => 'testC'},
        {:username => 'testD'},
        {:username => 'testE'},
      ],
    }
  end
end

레시피에서 puts 문으로 생성 된 메시지는 다음과 같습니다.

2013-03-08T01:03:46+00:00] INFO: Start handlers complete.
in loop for testA

in loop for testB

in loop for testC

in loop for testD

in loop for testE

[2013-03-08T01:03:46+00:00] INFO: Processing bash[create_user] action run (sample::default line 5)
checking /etc/passwd for testA

[2013-03-08T01:03:46+00:00] INFO: Processing bash[create_user] action run (sample::default line 5)
checking /etc/passwd for testA

[2013-03-08T01:03:46+00:00] INFO: Processing bash[create_user] action run (sample::default line 5)
checking /etc/passwd for testA

[2013-03-08T01:03:46+00:00] INFO: Processing bash[create_user] action run (sample::default line 5)
checking /etc/passwd for testA

[2013-03-08T01:03:46+00:00] INFO: Processing bash[create_user] action run (sample::default line 5)
checking /etc/passwd for testA

[2013-03-08T01:03:46+00:00] INFO: Chef Run complete in 0.026071 seconds

답변:


5

스크립트 이름을 고유하게 만드십시오 ...

bash "create_user_#{user}" do

FWIW, 나는 https://github.com/fnichol/chef-user를 여러 번 사용 하여 속성과 데이터 백을 기반으로 사용자를 생성 / 제거 할 수 있습니다.


정말 간단 해 보입니다. 감사합니다! 사용자 만들기 레시피는 루프가 다른 레시피에서 작동하지 않는 이유를 설명하기 위해 사용했던 예제 일뿐입니다. 다시 감사합니다!
Matthew J Morrison

10

현재보고있는 동작은 Chef 클라이언트 실행의 두 가지 주요 단계 인 컴파일 및 수렴 간의 차이점을 이해하여 설명 할 수 있습니다.

"컴파일"단계 동안 Chef 클라이언트는 레시피에서 코드를 실행하여 자원 콜렉션 을 빌드합니다 . 이것은 Chef에게 시스템에서 목표 상태와 함께 관리하도록 지시 한 자료 목록입니다 . 예를 들어, 디렉토리 자원 /tmp/foo이 존재해야하고 root가 소유해야 한다고 말합니다 .

directory "/tmp/foo" do
  owner "root"
end

"수렴"단계 동안 Chef 클라이언트는 제공자 를 사용하여 각 자원의 현재 상태를로드 한 다음이를 대상 상태와 비교합니다. 다른 경우 Chef는 시스템을 업데이트합니다. 디렉토리 리소스의 경우 Chef는 디렉토리가 존재하지 않는 경우 디렉토리를 만들고 필요한 경우 소유자를 "루트"로 변경합니다.

자원은 이름과 유형으로 고유하게 식별됩니다 directory[/tmp/foo]. 이름이 같지만 속성이 다른 두 개의 리소스가 있으면 문제가 발생하며 Darrin Holst의 답변을 사용하여 문제를 해결할 수 있습니다.

node[:users].each do |user|
  puts "in loop for #{user['username']}"
  bash "create_user_#{user}" do
    user "root"
    code do
      puts "running 'useradd' for #{user['username']}"
      "useradd #{user['username']}"
    end
    not_if do
      puts "checking /etc/passwd for #{user['username']}"
      "cat /etc/passwd | grep #{user['username']}"
    end
  end
end

그러나이 특정 경우 Chef의 사용자 리소스를 사용하면 도움이됩니다. 다음은 레시피를 대체하는 것입니다 (디버깅 메시지 제외).

node[:users].each do |u|
  user u['username'] do
    action :create
  end
end

이것이 bash 리소스 세트보다 나은 이유는 무엇입니까?

  1. 사용자 리소스는 여러 플랫폼에서 동일한 방식으로 작동합니다. "useradd"이외의 다른 것을 사용하여 사용자를 만드는 운영 체제에서도 동일한 레시피가 작동합니다.
  2. 이를 담당하는 공급자는 사용자가 이미 존재하는지 확인하는 방법을 알고 있으므로 not_if가 필요하지 않습니다.
  3. 동일한 공급자를 사용하여 사용자를 제거하고 암호를 잠 그거나 잠금을 해제하며 기존 사용자 계정의 다른 속성을 업데이트 할 수도 있습니다.

그러나 올바른 리소스를 사용해야하는 가장 좋은 이유는 의도를보다 명확하게 전달하기 때문입니다. 귀하의 목표는 아마도 많은 셸 명령을 실행하는 것이 아니라 일부 사용자가 시스템에 있는지 확인하는 것입니다. 이를 수행하는 데 사용 된 명령은 구현 세부 사항 일뿐입니다.

공급자는 이러한 세부 사항을 캡슐화하여 원하는 것을 설명하는 데 자유롭게 집중할 수 있습니다.


1
고마워, 이것은 꽤 많은 것을 명확히합니다. 사용자 생성 레시피는 다른 곳에서 루프가 예상대로 작동하지 않는 이유를 더 잘 이해하기 위해 가지고 놀 수있는 예일뿐입니다.
Matthew J Morrison
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.