๐Ÿš€ ์š”์•ฝ

SUMMARY

Deck์„ Go๋กœ ๋งŒ๋“ค๋ฉฐ CLI ๊ตฌ์„ฑ๋ฒ•์„ ๊ณต๋ถ€ํ•˜๋‹ค spf13/cobra๋ฅผ ๋งŒ๋‚ฌ๋‹ค. ์„œ๋ธŒ์ปค๋งจ๋“œ ํŠธ๋ฆฌยทํ”Œ๋ž˜๊ทธ ํŒŒ์‹ฑยท--helpยท์ž๋™์™„์„ฑ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๋”ธ๋ ค์˜ค๋Š” ๊ฑธ ๋ณด๊ณ ์„œ์•ผ, ์˜ˆ์ „์— ์ˆœ์ˆ˜ ์‰˜์Šคํฌ๋ฆฝํŠธ๋กœ CLI๋ฅผ ๋งŒ๋“ค ๋•Œ helpยท๋ฐ˜์‘ํ˜•ยท๋กœ๊ทธ ํฌ๋งท์„ ์†์ˆ˜ ์งœ๋А๋ผ ๊ณ ์ƒํ•˜๊ณ ๋„ ์˜คํ”ˆ์†Œ์Šค CLI๋งŒํผ ์•ˆ ๋‚˜์™”๋˜ ์ด์œ ๊ฐ€ ๋‚ฉ๋“๋๋‹ค. kubectlยทhelmยทkubeadm์ด ์“ฐ๋Š” ๋ฐ”๋กœ ๊ทธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋‹ค.

์‰˜์Šคํฌ๋ฆฝํŠธ๋กœ CLI ํ‰๋‚ด๋ฅผ ๋‚ด๋˜ ์‹œ์ ˆ์—” ์™„์„ฑ๋„๊ฐ€ ๋Š˜ ์•„์‰ฌ์› ๋Š”๋ฐ, ๋Œ์•„๋ณด๋‹ˆ ๊ทธ๊ฒŒ ์˜จ์ „ํžˆ ๋‚ด ํƒ“๋งŒ์€ ์•„๋‹ˆ์—ˆ๋‹ค.

1. ์‰˜์Šคํฌ๋ฆฝํŠธ๋กœ CLI ๋งŒ๋“ค ๋•Œ ์‹œ๊ฐ„์„ ์Ÿ๋˜ ๊ฒƒ๋“ค

๊ทธ๋™์•ˆ ์ž์ž˜ํ•œ ์šด์˜ ๋„๊ตฌ๋Š” ์‰˜์Šคํฌ๋ฆฝํŠธ๋กœ CLI ํ‰๋‚ด๋ฅผ ๋‚ด์™”๋‹ค. case "$1" in ...์œผ๋กœ ์„œ๋ธŒ์ปค๋งจ๋“œ๋ฅผ ๋‚˜๋ˆ„๊ณ , ๋‚˜๋ฆ„ ๊ทธ๋Ÿด์‹ธํ•˜๊ฒŒ ๋งŒ๋“ค๋ ค๊ณ  ์• ๋ฅผ ์ผ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ CLI๋‹ต๊ฒŒ ๋งŒ๋“ค๋ ค๋Š” ๋…ธ๋ ฅ ๋Œ€๋ถ€๋ถ„์ด ์ •์ž‘ ๋ณธ์งˆ๊ณผ ๋ฌด๊ด€ํ•œ ๋ฐ ๋“ค์–ด๊ฐ”๋‹ค.

  • help. --help๋ฅผ ๋ณด์—ฌ์ฃผ๋ ค๊ณ  ์‚ฌ์šฉ๋ฒ•์„ echo๋กœ ์ง์ ‘ ์ฐ์—ˆ๋‹ค. ๋ช…๋ น์„ ๊ณ ์น  ๋•Œ๋งˆ๋‹ค ๊ทธ echo๋„ ๊ฐ™์ด ๊ณ ์ณ์•ผ ํ–ˆ๊ณ , ์•ˆ ๊ณ ์น˜๋ฉด ๋ฌธ์„œ์™€ ์‹ค์ œ ๋™์ž‘์ด ์–ด๊ธ‹๋‚ฌ๋‹ค.
  • ๋ฐ˜์‘ํ˜•(interactive). ๊ฐ’์„ ๋ฌผ์–ด๋ณด๊ณ  ํ™•์ธ๋ฐ›๋Š” ํ”„๋กฌํ”„ํŠธ, ์ž˜๋ชป๋œ ์ž…๋ ฅ ๋˜๋ฌป๊ธฐ ๊ฐ™์€ ๊ฑธ read์™€ while๋กœ ์†์ˆ˜ ์งฐ๋‹ค. ์—”ํ„ฐยท๊ธฐ๋ณธ๊ฐ’ยท์ทจ์†Œ ์ฒ˜๋ฆฌ๋ฅผ ๋งค๋ฒˆ ๋‹ค์‹œ ๋งŒ๋“ค์—ˆ๋‹ค.
  • ๋กœ๊ทธ ํฌ๋งท. ๋ ˆ๋ฒจ(info/warn/error)์— ๋”ฐ๋ผ ์ƒ‰์„ ์ž…ํžˆ๊ณ  ์ ‘๋‘์‚ฌ๋ฅผ ๋ถ™์ด๋Š” ๊ฑธ printf์™€ ANSI ์ฝ”๋“œ๋กœ ์ง์ ‘ ๋งŒ๋“ค์—ˆ๋‹ค. ๋„๊ตฌ๋งˆ๋‹ค ํฌ๋งท์ด ๋ฏธ๋ฌ˜ํ•˜๊ฒŒ ๋‹ฌ๋ผ์กŒ๋‹ค.
  • ํ”Œ๋ž˜๊ทธ ํŒŒ์‹ฑ. --root, --dry-run ํ•˜๋‚˜ ๋ฐ›์œผ๋ ค๊ณ  while [[ $#--gt-0-| -gt 0 ]]; do case ...๋ฅผ ๋ช…๋ น๋งˆ๋‹ค ๋ณต๋ถ™ํ–ˆ๋‹ค. ์ถ•์•ฝ(-n)์ด๋‚˜ ์ˆœ์„œ ๋ฌด๊ด€ ๊ฐ™์€ ๊ฑด ์•Œ์•„์„œ ์•ˆ ๋๋‹ค.
  • ์„œ๋ธŒ์ปค๋งจ๋“œ ํŠธ๋ฆฌ. 2๋‹จ๊ณ„(tool sub action)๋งŒ ๋ผ๋„ case ์•ˆ์— case๋ฅผ ์ค‘์ฒฉํ•ด์•ผ ํ–ˆ๋‹ค.

ํ•˜๋‚˜ํ•˜๋‚˜๋Š” ๋‹ค ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ฌธ์ œ๋Š” ์ด๊ฑธ ์ „๋ถ€, ๋„๊ตฌ๋งˆ๋‹ค, ๋ช…๋ น์ด ๋Š˜ ๋•Œ๋งˆ๋‹ค ๊ณ„์† ์†์œผ๋กœ ์œ ์ง€ํ•ด์•ผ ํ–ˆ๋‹ค๋Š” ๊ฑฐ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ์‹œ๊ฐ„์„ ์Ÿ๊ณ ๋„ ์™„์„ฑ๋„๋Š” kubectl ๊ฐ™์€ ์˜คํ”ˆ์†Œ์Šค CLI ๊ทผ์ฒ˜์—๋„ ๋ชป ๊ฐ”๋‹ค. ๊ทธ๋•Œ๋Š” โ€œ๋‚ด๊ฐ€ ๋ถ€์กฑํ•ด์„œโ€๋ผ๊ณ ๋งŒ ์ƒ๊ฐํ–ˆ๋‹ค.

2. Cobra๋ฅผ ๋ณด๊ณ  ์ด์œ ๋ฅผ ์•Œ์•˜๋‹ค

Deck์„ Go๋กœ ์งœ๋ฉฐ Cobra๋ฅผ ์“ฐ๊ธฐ ์‹œ์ž‘ํ•˜๋‹ˆ, ์œ„์—์„œ ์†์œผ๋กœ ๋งŒ๋“ค๋˜ ๊ฒŒ ์ „๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๊ธฐ๋ณธ์œผ๋กœ ๋“ค์–ด ์žˆ์—ˆ๋‹ค. ๋‚ด๊ฐ€ ๋ถ€์กฑํ–ˆ๋˜ ๊ฒŒ ์•„๋‹ˆ๋ผ, ์‰˜์Šคํฌ๋ฆฝํŠธ์—๋Š” ๊ทธ๊ฑธ ๋Œ€์‹ ํ•ด์ค„ ์ธต์ด ์—†์—ˆ์„ ๋ฟ์ด์—ˆ๋‹ค.

  • ์„œ๋ธŒ์ปค๋งจ๋“œ ํŠธ๋ฆฌ โ€” ๋ช…๋ น ํ•˜๋‚˜๊ฐ€ *cobra.Command๊ณ  AddCommand๋กœ ๋ถ€๋ชจ์— ๋ถ™์ด๋ฉด deck bundle verify ๊ฐ™์€ ๊ฒฝ๋กœ๊ฐ€ ๊ทธ๋ƒฅ ์ƒ๊ธด๋‹ค.
  • ํ”Œ๋ž˜๊ทธ ํŒŒ์‹ฑ โ€” cmd.Flags().Bool("dry-run", false, "...") ํ•œ ์ค„. ์ถ•์•ฝยท์ˆœ์„œ ๋ฌด๊ด€ยทํƒ€์ž… ๊ฒ€์ฆ๊นŒ์ง€ pflag๊ฐ€ ์ฒ˜๋ฆฌํ•œ๋‹ค.
  • --help/Usage โ€” ๋ช…๋ น์˜ Short/Long ํ•„๋“œ์— ์„ค๋ช…์„ ์ ์œผ๋ฉด help๊ฐ€ ์ž๋™ ์ƒ์„ฑ๋œ๋‹ค. ์„ค๋ช…์ด ์ฝ”๋“œ ์˜†์— ์žˆ์œผ๋‹ˆ ์–ด๊ธ‹๋‚  ์ผ์ด ์—†๋‹ค.
  • ์…ธ ์ž๋™์™„์„ฑ โ€” ๋ช…๋ น ํŠธ๋ฆฌ์—์„œ bash/zsh/fish/powershell ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž๋™ ์ƒ์„ฑํ•œ๋‹ค.

๋‚ด๊ฐ€ ์งœ์•ผ ํ•˜๋Š” ๊ฑด โ€œ์ด ๋ช…๋ น์ด ๋ฌด์Šจ ์ผ์„ ํ•˜๋‚˜โ€(RunE ํ•จ์ˆ˜)๋ฟ์ด๊ณ , CLI๋กœ์„œ์˜ ๊ฒฉ์‹์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ฑ„์šด๋‹ค. ์‰˜์Šคํฌ๋ฆฝํŠธ ์‹œ์ ˆ ์ง„์งœ ๋ฌด๊ฑฐ์› ๋˜ ๊ฒŒ ์ด ๊ฒฉ์‹ ์œ ์ง€์˜€๋‹ค๋Š” ๊ฑธ Go๋กœ ์˜ฎ๊ธฐ๊ณ  ๋‚˜์„œ์•ผ ์•Œ์•˜๋‹ค. (๋ฐ˜์‘ํ˜• ํ”„๋กฌํ”„ํŠธ๋‚˜ ์ปฌ๋Ÿฌ ๋กœ๊ทธ๋„ Go ์ƒํƒœ๊ณ„์—” surveyยทfatih/color ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์žˆ์–ด์„œ, ์‰˜๋กœ ์†์ˆ˜ ๋งŒ๋“ค๋˜ ๊ฑธ ๋Œ€๋ถ€๋ถ„ ์กฐ๋ฆฝ์œผ๋กœ ํ•ด๊ฒฐํ•œ๋‹ค.)

3. K8s ์ง„์˜๊ณผ ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ผ๋Š” ์ 

Cobra๋ฅผ ๋งˆ์Œ ํŽธํžˆ ๊ณ ๋ฅธ ๋ฐ์—” ์ด์œ ๊ฐ€ ํ•˜๋‚˜ ๋” ์žˆ์—ˆ๋‹ค. ๋‚ด๊ฐ€ ๋งค์ผ ์“ฐ๋Š” ๋„๊ตฌ๋“ค์ด ์ด๊ฑธ๋กœ ๋งŒ๋“ค์–ด์กŒ๋‹ค. kubectl, helm, kubeadm์ด ์ „๋ถ€ spf13/cobra ๊ธฐ๋ฐ˜์ด๊ณ , ๊ทธ ๋ฐ”๊นฅ์œผ๋กœ๋„ dockerยทghยทhugo๊ฐ€ ๊ฐ™์€ ๊ณ„์—ด์ด๋‹ค. (Kubernetes ์ง„์˜์ด ์›Œ๋‚™ ๋งŽ์ด ์จ์„œ ์‚ฌ์‹ค์ƒ Go CLI์˜ ํ‘œ์ค€์ฒ˜๋Ÿผ ์ž๋ฆฌ ์žก์•˜๋‹ค.)

๋•๋ถ„์— ๋‚ด ๋„๊ตฌ์˜ ์‚ฌ์šฉ๊ฐ์ด ๊ทธ ๋„๊ตฌ๋“ค๊ณผ ๊ฒฐ์„ ๋งž์ถ”๊ฒŒ ๋œ๋‹ค. kubectl <cmd> --help, kubectl completion zsh๊ฐ€ ๋˜๋“ฏ deck <cmd> --help, deck completion zsh๊ฐ€ ๋˜‘๊ฐ™์ด ๋œ๋‹ค. ์“ฐ๋Š” ์‚ฌ๋žŒ์ด ์ƒˆ๋กœ ๋ฐฐ์šธ ๊ฒŒ ์—†๊ณ , ๋‚˜๋„ โ€œkubectl์€ ์ด๊ฑธ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•˜์ง€?โ€ ํ•˜๊ณ  ์ฐธ๊ณ ํ•  ๋ ˆํผ๋Ÿฐ์Šค๊ฐ€ ๋„๋ ค ์žˆ๋‹ค. ์ˆœ์ˆ˜ ์‰˜์Šคํฌ๋ฆฝํŠธ๋กœ๋Š” ์ด ์ผ๊ด€์„ฑ ์ž์ฒด๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ–ˆ๋‹ค.

4. ๋ช…๋ น ํŠธ๋ฆฌ๋ฅผ ์ฝ”๋“œ๋กœ ์„ธ์šฐ๊ธฐ

Deck์˜ ๋ช…๋ น ํŠธ๋ฆฌ๋Š” ๋Œ€๋žต ์ด๋ ‡๊ฒŒ ์žก์•˜๋‹ค. ๋ฃจํŠธ ์•„๋ž˜ ๋™์‚ฌ(apply/bundle/state/โ€ฆ)๋ฅผ ๋ถ™์ด๊ณ , ํ•„์š”ํ•œ ๊ฒƒ๋งŒ 2๋‹จ๊ณ„๋กœ ๋” ๋‚˜๋ˆด๋‹ค.

deck
โ”œโ”€โ”€ apply          # ์›Œํฌํ”Œ๋กœ์šฐ(apply ํŒŒ์ผ)๋ฅผ ๋ฒˆ๋“ค์— ๋Œ€ํ•ด ์‹คํ–‰
โ”œโ”€โ”€ plan           # ์‹คํ–‰ ์ „ ๊ณ„ํš์„ ๋ณด์—ฌ์คŒ (vars ํ•˜์œ„: ์œ ํšจ ๋ณ€์ˆ˜ยท์ปจํ…์ŠคํŠธ ํ™•์ธ)
โ”œโ”€โ”€ bundle
โ”‚   โ”œโ”€โ”€ verify     # ๋ฒˆ๋“ค ๋ฌด๊ฒฐ์„ฑ ๊ฒ€์ฆ
โ”‚   โ””โ”€โ”€ build      # ๋ฒˆ๋“ค ์ƒ์„ฑ
โ”œโ”€โ”€ state
โ”‚   โ”œโ”€โ”€ show       # ์ €์žฅ๋œ apply ์ƒํƒœ ์กฐํšŒ
โ”‚   โ”œโ”€โ”€ list       # ์ƒํƒœ ํŒŒ์ผ ๋ชฉ๋ก
โ”‚   โ””โ”€โ”€ clear      # ์ƒํƒœ ์‚ญ์ œ
โ”œโ”€โ”€ cache          # ์บ์‹œ ๊ด€๋ฆฌ
โ”œโ”€โ”€ serve          # ๋ฐ๋ชฌ/์„œ๋ฒ„ ๋ชจ๋“œ
โ”œโ”€โ”€ ask            # AI ๋ณด์กฐ (login/logout/status ํ•˜์œ„)
โ”œโ”€โ”€ completion     # ์…ธ ์ž๋™์™„์„ฑ ์Šคํฌ๋ฆฝํŠธ ์ƒ์„ฑ
โ””โ”€โ”€ version

์ฝ”๋“œ๋กœ๋Š” ๋ถ€๋ชจ ๋ช…๋ น์„ ๋งŒ๋“ค๊ณ  ์ž์‹์„ ๋ถ™์ด๋Š” ๊ฒŒ ์ „๋ถ€๋‹ค.

// state ๋Š” ๊ทธ ์ž์ฒด๋กœ ์‹คํ–‰ํ•˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ ํ•˜์œ„ ๋ช…๋ น์˜ ๊ทธ๋ฃน์ด๋‹ค.
stateCmd := &cobra.Command{
    Use:   "state",
    Short: "Inspect and clear saved apply state",
}
stateCmd.AddCommand(
    newStateShowCmd(),   // deck state show
    newStateListCmd(),   // deck state list
    newStateClearCmd(),  // deck state clear
)
rootCmd.AddCommand(stateCmd)

case ์ค‘์ฒฉ์ด ์‚ฌ๋ผ์ง€๊ณ  ๋ช…๋ น ํ•˜๋‚˜๊ฐ€ ํŒŒ์ผ ํ•˜๋‚˜๋กœ ๋–จ์–ด์ง„๋‹ค. ์ƒˆ ๋ช…๋ น ์ถ”๊ฐ€๊ฐ€ โ€œํ•จ์ˆ˜ ํ•˜๋‚˜ ์“ฐ๊ณ  AddCommand ํ•œ ์ค„โ€์ด ๋˜๋‹ˆ ๋„๊ตฌ๋ฅผ ํ‚ค์šฐ๋Š” ๋ถ€๋‹ด์ด ํ™• ์ค„์—ˆ๋‹ค. ์‰˜์Šคํฌ๋ฆฝํŠธ ์‹œ์ ˆ case๊ฐ€ ๋ฌด์„œ์›Œ ๊ธฐ๋Šฅ ์ถ”๊ฐ€๋ฅผ ๋ฏธ๋ฃจ๋˜ ๊ฒƒ๊ณผ ์ •๋ฐ˜๋Œ€๋‹ค.

5. helpยท์ž๋™์™„์„ฑยท๋ฌธ์„œ๋ฅผ ๊ณต์งœ๋กœ ์–ป๊ธฐ

Cobra๋ฅผ ์“ฐ๋ฉฐ ์ œ์ผ ์ด๋“ ๋ณธ ๊ฑด ๋ถ€์ˆ˜์ ์œผ๋กœ ๋”ธ๋ ค์˜จ ๊ฒƒ๋“ค์ด์—ˆ๋‹ค.

์ž๋™์™„์„ฑ. deck completion <bash|zsh|fish|powershell>๋กœ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋ฝ‘๋Š”๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ๊ทธ๊ฑธ ์…ธ์— ๊ฑธ๋ฉด deck sta<Tab> โ†’ state๊ฐ€ ๋œ๋‹ค. ๋‚ด๊ฐ€ completion ๋กœ์ง์„ ์ง  ๊ฒŒ ์•„๋‹ˆ๋ผ, ๋ช…๋ น์„ ํŠธ๋ฆฌ๋กœ ์ •์˜ํ–ˆ๋”๋‹ˆ Cobra๊ฐ€ ๋งŒ๋“ค์–ด์คฌ๋‹ค.

๋ฌธ์„œ ์ƒ์„ฑ. Cobra์—” ๋ช…๋ น ํŠธ๋ฆฌ๋ฅผ ๋งˆํฌ๋‹ค์šด์œผ๋กœ ๋ฝ‘์•„์ฃผ๋Š” ๊ธฐ๋Šฅ(cobra/doc)์ด ์žˆ๋‹ค. Deck์—๋Š” ์ด๊ฑธ ๊ฐ์‹ผ ๋‚ด๋ถ€ ๋ช…๋ น์„ ๋‘๊ณ  CLI ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ๋ช…๋ น ์ •์˜์—์„œ ์ž๋™ ์ƒ์„ฑํ•œ๋‹ค. ๋ช…๋ น์„ ๊ณ ์น˜๋ฉด ๋ฌธ์„œ๋„ ๋‹ค์‹œ ๋ฝ‘์œผ๋ฉด ๊ทธ๋งŒ์ด๋ผ โ€œ์ฝ”๋“œ๋Š” ๋ฐ”๋€Œ์—ˆ๋Š”๋ฐ ๋ฌธ์„œ๋Š” ์˜›๋‚  ๊ทธ๋Œ€๋กœโ€์ธ ์‚ฌ๊ณ ๊ฐ€ ์•ˆ ๋‚œ๋‹ค. (์ด ์ž๋™ ์ƒ์„ฑ ๋ฌธ์„œ๋ฅผ ๋ฌธ์„œ ์‚ฌ์ดํŠธ์— ๊ทธ๋Œ€๋กœ ์–น์—ˆ๋‹ค.)

์‰˜์Šคํฌ๋ฆฝํŠธ CLI๊ฐ€ ์˜คํ”ˆ์†Œ์Šค๋งŒํผ ์•ˆ ๋‚˜์™”๋˜ ๊ฑด ์‹ค๋ ฅ ํƒ“์ด๋ผ๊ธฐ๋ณด๋‹ค, ํŠธ๋ฆฌยทํ”Œ๋ž˜๊ทธยทhelpยท์ž๋™์™„์„ฑยท๋กœ๊ทธยท๋ ˆํผ๋Ÿฐ์Šค ๋ฌธ์„œ๋ผ๋Š” ๊ฒฉ์‹์„ ๋งจ์†์œผ๋กœ ๋‹ค ๋– ์•ˆ์•˜๋˜ ํƒ“์ด ์ปธ๋‹ค. Cobra๋กœ ์˜ฎ๊ธฐ๊ณ  ๋‚˜์„  ๋‚ด๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒŒ โ€œ๊ฐ ๋ช…๋ น์ด ํ•˜๋Š” ์ผโ€๋กœ ์ขํ˜€์กŒ๋‹ค.

๐Ÿ”— ์ฐธ๊ณ