executable_kubectl-invoke 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. #!/usr/bin/env -S guile --no-auto-compile -e main -s
  2. !#
  3. (use-modules (json)
  4. (srfi srfi-1)
  5. (srfi srfi-37)
  6. (guix scripts))
  7. (define %options
  8. (list
  9. (option '(#\d "dry-run") #f #f
  10. (lambda (opt name arg result)
  11. (values (alist-cons 'dry-run? #t result)
  12. #f)))
  13. (option '(#\N "host-network") #f #f
  14. (lambda (opt name arg result)
  15. (values (alist-cons 'host-network? #t result)
  16. #f)))
  17. (option '(#\n "namespace") #t #f
  18. (lambda (opt name arg result)
  19. (alist-cons 'namespace arg result)))
  20. (option '(#\H "host") #t #f
  21. (lambda (opt name arg result)
  22. (alist-cons 'host arg result)))
  23. (option '(#\f "format") #t #f
  24. (lambda (opt name arg result)
  25. (alist-cons 'format arg result)))
  26. (option '(#\u "uid") #t #f
  27. (lambda (opt name arg result)
  28. (alist-cons 'uid arg result)))
  29. (option '(#\g "gid") #t #f
  30. (lambda (opt name arg result)
  31. (alist-cons 'gid arg result)))
  32. (option '(#\m "machinectl") #t #f
  33. (lambda (opt name arg result)
  34. (alist-cons 'machinectl arg result)))
  35. (option '(#\s "sudo") #t #f
  36. (lambda (opt name arg result)
  37. (alist-cons 'sudo arg result)))
  38. (option '(#\C "cpu") #t #f
  39. (lambda (opt name arg result)
  40. (alist-cons 'cpu arg result)))
  41. (option '(#\M "memory") #t #f
  42. (lambda (opt name arg result)
  43. (alist-cons 'memory arg result)))
  44. (option '(#\i "image") #t #f
  45. (lambda (opt name arg result)
  46. (alist-cons 'image arg result)))
  47. (option '(#\S "spec") #t #f
  48. (lambda (opt name arg result)
  49. (alist-cons 'spec arg result)))))
  50. (define %default-options
  51. '(()))
  52. (define (random-string)
  53. (fold string-append "" (map number->string (map random (cdr (iota 19))))))
  54. (define (main args)
  55. (define opts
  56. (parse-command-line args %options
  57. (list %default-options)))
  58. (define dry-run? (assoc-ref opts 'dry-run?))
  59. (define host-network? (assoc-ref opts 'host-network?))
  60. (define namespace (assoc-ref opts 'namespace))
  61. (define host (assoc-ref opts 'host))
  62. (define format
  63. (or (assoc-ref opts 'format)
  64. "busybox"))
  65. (define uid (assoc-ref opts 'uid))
  66. (define gid (assoc-ref opts 'gid))
  67. (define machinectl (assoc-ref opts 'machinectl))
  68. (define sudo (assoc-ref opts 'sudo))
  69. (define cpu (assoc-ref opts 'cpu))
  70. (define memory (assoc-ref opts 'memory))
  71. (define image (assoc-ref opts 'image))
  72. (define spec
  73. (let ((spec (assoc-ref opts 'spec)))
  74. (if spec
  75. (json-string->scm spec)
  76. '())))
  77. (case (string->symbol format)
  78. ((busybox)
  79. (let ((labels '(("app.kubernetes.io/name" . "busybox"))))
  80. (apply system*
  81. `(,@(if dry-run? '("echo") '())
  82. "kubectl"
  83. "run"
  84. "--rm=true"
  85. "--stdin=true"
  86. "--tty=true"
  87. ,@(if namespace
  88. (list (string-append "--namespace=" namespace))
  89. '())
  90. ,(string-append "--labels="
  91. (string-join
  92. (map (lambda (label)
  93. (string-append (first label)
  94. "="
  95. (cdr label)))
  96. labels)
  97. ","))
  98. ,@(if host
  99. (list
  100. (string-concatenate
  101. (list
  102. "--overrides="
  103. (scm->json-string
  104. `(("spec"
  105. ("tolerations"
  106. .
  107. #((("effect" . "NoSchedule")
  108. ("value" . "true")
  109. ("operator" . "Equal")
  110. ("key" . "unschedulable"))))
  111. ("nodeSelector"
  112. ("kubernetes.io/hostname" . ,host)))
  113. ("apiVersion" . "v1"))))))
  114. '())
  115. ,(string-append "busybox-" (random-string))
  116. "--image=busybox"
  117. "/bin/sh"))))
  118. ((nixery)
  119. (let ((labels '(("app.kubernetes.io/name" . "nixery"))))
  120. (apply system*
  121. `(,@(if dry-run? '("echo") '())
  122. "kubectl"
  123. "run"
  124. "--rm=true"
  125. "--stdin=true"
  126. "--tty=true"
  127. ,@(if namespace
  128. (list (string-append "--namespace=" namespace))
  129. '())
  130. ,(string-append "--labels="
  131. (string-join
  132. (map (lambda (label)
  133. (string-append (first label)
  134. "="
  135. (cdr label)))
  136. labels)
  137. ","))
  138. ,@(if host
  139. (list
  140. (string-concatenate
  141. (list
  142. "--overrides="
  143. (scm->json-string
  144. `(("spec"
  145. ("hostNetwork" . ,host-network?)
  146. ("tolerations"
  147. .
  148. #((("effect" . "NoSchedule")
  149. ("value" . "true")
  150. ("operator" . "Equal")
  151. ("key" . "unschedulable"))))
  152. ("nodeSelector"
  153. ("kubernetes.io/hostname" . ,host))
  154. ,@spec)
  155. ("apiVersion" . "v1"))))))
  156. '())
  157. ,(string-append "nixery-" (random-string))
  158. ,(string-append "--image=" (if image image "nixery.dev/shell"))
  159. "/bin/bash"))))
  160. ((netshoot)
  161. (let ((labels '(("app.kubernetes.io/name" . "netshoot"))))
  162. (apply system*
  163. `(,@(if dry-run? '("echo") '())
  164. "kubectl"
  165. "run"
  166. "--rm=true"
  167. "--stdin=true"
  168. "--tty=true"
  169. ,@(if namespace
  170. (list (string-append "--namespace=" namespace))
  171. '())
  172. ,(string-append "--labels="
  173. (string-join
  174. (map (lambda (label)
  175. (string-append (first label)
  176. "="
  177. (cdr label)))
  178. labels)
  179. ","))
  180. ,@(if host
  181. (list
  182. (string-concatenate
  183. (list
  184. "--overrides="
  185. (scm->json-string
  186. `(("spec"
  187. ("tolerations"
  188. .
  189. #((("effect" . "NoSchedule")
  190. ("value" . "true")
  191. ("operator" . "Equal")
  192. ("key" . "unschedulable"))))
  193. ("nodeSelector"
  194. ("kubernetes.io/hostname" . ,host)))
  195. ("apiVersion" . "v1"))))))
  196. '())
  197. ,(string-append "netshoot-" (random-string))
  198. "--image=nicolaka/netshoot"
  199. "/bin/bash"))))
  200. ((nanoserver)
  201. (let ((labels '(("app.kubernetes.io/name" . "nanoserver"))))
  202. (apply system*
  203. `(,@(if dry-run? '("echo") '())
  204. "kubectl"
  205. "run"
  206. "--rm=true"
  207. "--stdin=true"
  208. "--tty=true"
  209. ,@(if namespace
  210. (list (string-append "--namespace=" namespace))
  211. '())
  212. ,(string-append "--labels="
  213. (string-join
  214. (map (lambda (label)
  215. (string-append (first label)
  216. "="
  217. (cdr label)))
  218. labels)
  219. ","))
  220. ,@(if host
  221. (list
  222. (string-concatenate
  223. (list
  224. "--overrides="
  225. (scm->json-string
  226. `(("spec"
  227. ("tolerations"
  228. .
  229. #((("effect" . "NoSchedule")
  230. ("value" . "true")
  231. ("operator" . "Equal")
  232. ("key" . "unschedulable"))))
  233. ("nodeSelector"
  234. ("kubernetes.io/hostname" . ,host)))
  235. ("apiVersion" . "v1"))))))
  236. '())
  237. ,(string-append "nanoserver-" (random-string))
  238. "--image=mcr.microsoft.com/windows/nanoserver:ltsc2022"))))
  239. ((shell)
  240. (let ((labels '(("app.kubernetes.io/name" . "nsenter"))))
  241. (apply system*
  242. `(,@(if dry-run? '("echo") '())
  243. "kubectl"
  244. "run"
  245. "--rm=true"
  246. "--stdin=true"
  247. "--tty=true"
  248. ,@(if namespace
  249. (list (string-append "--namespace=" namespace))
  250. '())
  251. ,(string-append "--labels="
  252. (string-join
  253. (map (lambda (label)
  254. (string-append (first label)
  255. "="
  256. (cdr label)))
  257. labels)
  258. ","))
  259. ,@(if host
  260. (list
  261. (string-concatenate
  262. (list
  263. "--overrides="
  264. (scm->json-string
  265. `(("spec"
  266. ("tolerations"
  267. .
  268. #((("operator" . "Exists")
  269. ("key" . "CriticalAddonsOnly"))
  270. (("operator" . "Exists")
  271. ("effect" . "NoExecute"))))
  272. ("containers"
  273. .
  274. #((("resources"
  275. ("requests"
  276. ,@(if memory
  277. (list (cons "memory" memory))
  278. (list (cons "memory" "256Mi")))
  279. ,@(if cpu
  280. (list (cons "cpu" cpu))
  281. (list (cons "cpu" "100m"))))
  282. ("limits"
  283. ,@(if memory
  284. (list (cons "memory" memory))
  285. (list (cons "memory" "256Mi")))
  286. ,@(if cpu
  287. (list (cons "cpu" cpu))
  288. (list (cons "cpu" "100m")))))
  289. ("command"
  290. .
  291. #("nsenter"
  292. "--target"
  293. "1"
  294. "--mount"
  295. "--uts"
  296. "--ipc"
  297. "--net"
  298. "--pid"
  299. "--no-fork"
  300. ,@(if uid
  301. (list "-S" uid)
  302. '())
  303. ,@(if gid
  304. (list "-G" gid)
  305. '())
  306. ,@(cond
  307. (machinectl
  308. (list "sh" "-l" "-c"
  309. (string-join (list "machinectl" "shell"
  310. (string-append machinectl "@")))))
  311. (sudo
  312. (list "sh" "-l" "-c"
  313. (string-join (list "sudo" "-u" sudo "-i"))))
  314. (else
  315. '("/bin/sh" "-l")))))
  316. ("tty" . #t)
  317. ("stdinOnce" . #t)
  318. ("stdin" . #t)
  319. ("name" . "nsenter")
  320. ("image" . "docker.io/library/alpine")
  321. ("securityContext" ("privileged" . #t)))))
  322. ("hostNetwork" . #t)
  323. ("hostPID" . #t)
  324. ("nodeName" . ,host)))))))
  325. '())
  326. "--image=docker.io/library/alpine"
  327. ,(string-append "shell-" (random-string))))))))