executable_kubectl-invoke 14 KB

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