Consul 템플릿 플러그인으로 사용자 정의 스크립트 실행

Consul 템플릿 플러그인으로 사용자 정의 스크립트 실행 (Execute Custom Scripts with Consul Template Plugins)

어떤 경우에는 작업을 다른 시스템으로 넘기는 플러그인을 작성해야 할 수도 있어요. 특히 Consul Template의 "표준 라이브러리"에 맞지 않지만 여러 인스턴스에서 공유해야 하는 작업에 유용해요.

출처: 문서

본문

어떤 사용 사례에서는 작업을 다른 시스템으로 오프로드하는 플러그인을 작성해야 할 필요가 있을 수 있어요. 이는 특히 Consul Template의 "표준 라이브러리(standard library)"에 맞지 않으면서도 여러 인스턴스에서 공유해야 하는 작업에 유용해요.

Consul Template 플러그인은 다음 API를 가져야 해요:

$ NAME [INPUT...]
  • NAME — 플러그인의 이름이며, 이진 파일(binary)의 이름이기도 해요. 전체 경로 또는 프로그램 이름만 지정할 수 있어요. 상속된 PATH로 셸에서 실행되므로, 예를 들어 cat 플러그인은 PATH에서 찾은 첫 번째 cat 실행 파일을 실행해요.
  • INPUT — 템플릿에서 오는 입력이에요. plugin 함수에 전달된 모든 인자마다 하나의 INPUT이 존재해요. 인자에 공백이 포함되어 있으면 그 공백은 셸이 인자를 인용한 것처럼 전달돼요.

중요 참고 사항 (Important notes)

  • 플러그인은 사용자가 제공한 스크립트를 실행하고 Consul 또는 Vault의 잠재적으로 민감한 데이터를 전달해요. Consul Template이 검증하거나 보호하는 것은 없으므로, 템플릿 작성자가 필요한 모든 예방 조치와 고려 사항을 직접 취해야 해요.
  • 플러그인 출력은 stdout에 문자열로 반환되어야 해요. 출력으로 파싱되는 것은 stdout뿐이에요. Consul Template이 값을 반환할 때 오류가 발생하지 않도록 모든 오류와 디버깅 메시지는 stderr에 기록해요. stderr로의 출력은 플러그인이 0이 아닌 종료 코드를 반환할 때만 표시된다는 점에 유의하세요.
  • 항상 exit 0을 사용해요. 그렇지 않으면 Consul Template이 플러그인 실행이 실패했다고 간주해요.
  • 빈 입력 케이스가 올바르게 처리되도록 해요. (다단계 실행(Multi-phase execution) 참고)
  • 플러그인에 파이프된 데이터는 명시적으로 주어진 매개변수 뒤에 추가돼요. 예를 들어 {{ "sample-data" | plugin "my-plugin" "some-parameter" }}는 my-plugin some-parameter sample-data를 호출해요.

예시 (Examples)

다음 예시 플러그인은 밑줄로 시작하는 모든 JSON 키를 제거하고 JSON 문자열을 반환해요:

func main() {
  arg := []byte(os.Args[1])

  var parsed map[string]interface{}
  if err := json.Unmarshal(arg, &parsed); err != nil {
    fmt.Fprintln(os.Stderr, fmt.Sprintf("err: %s", err))
    os.Exit(1)
  }

  for k, _ := range parsed {
    if string(k[0]) == "_" {
      delete(parsed, k)
    }
  }

  result, err := json.Marshal(parsed)
  if err != nil {
    fmt.Fprintln(os.Stderr, fmt.Sprintf("err: %s", err))
    os.Exit(1)
  }

  fmt.Fprintln(os.Stdout, fmt.Sprintf("%s", result))
  os.Exit(0)
}
#! /usr/bin/env ruby
require "json"

if ARGV.empty?
  puts JSON.fast_generate({})
  Kernel.exit(0)
end

hash = JSON.parse(ARGV.first)
hash.reject! { |k, _| k.start_with?("_")  }
puts JSON.fast_generate(hash)
Kernel.exit(0)

더 알아보기 (Learn more)