|
20 | 20 | "kustomize", |
21 | 21 | kustomize_gitops = "gitops", |
22 | 22 | ) |
| 23 | +load("//skylib:kubeconfig.bzl", "KubeconfigInfo") |
23 | 24 | load("//skylib:push.bzl", "k8s_container_push") |
24 | 25 |
|
25 | 26 | def _runfiles(ctx, f): |
@@ -275,219 +276,6 @@ def k8s_deploy( |
275 | 276 | visibility = visibility, |
276 | 277 | ) |
277 | 278 |
|
278 | | -KubeconfigInfo = provider(fields = [ |
279 | | - "server", |
280 | | - "cluster", |
281 | | - "user", |
282 | | -]) |
283 | | - |
284 | | -def _kubeconfig_file_impl(ctx): |
285 | | - kubeconfig_file = ctx.actions.declare_file(ctx.label.name) |
286 | | - ctx.actions.symlink(output = kubeconfig_file, target_file = ctx.file.config) |
287 | | - files = depset(direct = [kubeconfig_file]) |
288 | | - runfiles = ctx.runfiles(files = [kubeconfig_file]) |
289 | | - return [ |
290 | | - DefaultInfo(files = files, runfiles = runfiles), |
291 | | - KubeconfigInfo( |
292 | | - server = ctx.attr.server, |
293 | | - cluster = ctx.attr.cluster, |
294 | | - user = ctx.attr.user, |
295 | | - ), |
296 | | - ] |
297 | | - |
298 | | -kubeconfig_file = rule( |
299 | | - implementation = _kubeconfig_file_impl, |
300 | | - attrs = { |
301 | | - "config": attr.label( |
302 | | - doc = "Config file.", |
303 | | - allow_single_file = True, |
304 | | - mandatory = True, |
305 | | - ), |
306 | | - "server": attr.string( |
307 | | - doc = "Optional Kubernetes server url.", |
308 | | - mandatory = False, |
309 | | - ), |
310 | | - "cluster": attr.string( |
311 | | - doc = "Optional Kubernetes cluster name.", |
312 | | - mandatory = False, |
313 | | - ), |
314 | | - "user": attr.string( |
315 | | - doc = "Optional Kubernetes user name.", |
316 | | - mandatory = True, |
317 | | - ), |
318 | | - }, |
319 | | - provides = [DefaultInfo, KubeconfigInfo], |
320 | | -) |
321 | | - |
322 | | -_KUBECONFIG_BUILD_TEMPLATE = """# Generated by kubeconfig repostiory rule |
323 | | -
|
324 | | -load("@com_adobe_rules_gitops//skylib:k8s.bzl", "kubeconfig_file") |
325 | | -
|
326 | | -exports_files(["kubectl"]) |
327 | | -
|
328 | | -kubeconfig_file( |
329 | | - name = "kubeconfig", |
330 | | - config = ":config", |
331 | | - server = "{server}", |
332 | | - cluster = "{cluster}", |
333 | | - user = "{user}", |
334 | | - visibility = ["//visibility:public"], |
335 | | -) |
336 | | -""" |
337 | | - |
338 | | -# kubectl template |
339 | | -def _kubectl_config(repository_ctx, args): |
340 | | - kubectl = repository_ctx.path("kubectl") |
341 | | - kubeconfig_yaml = repository_ctx.path("config") |
342 | | - exec_result = repository_ctx.execute( |
343 | | - [kubectl, "--kubeconfig", kubeconfig_yaml, "config"] + args, |
344 | | - environment = { |
345 | | - # prevent kubectl config to stumble on shared .kube/config.lock file |
346 | | - "HOME": str(repository_ctx.path(".")), |
347 | | - }, |
348 | | - quiet = True, |
349 | | - ) |
350 | | - if exec_result.return_code != 0: |
351 | | - fail("Error executing kubectl config %s" % " ".join(args)) |
352 | | - |
353 | | -def _kubeconfig_impl(repository_ctx): |
354 | | - """Find local kubernetes certificates""" |
355 | | - |
356 | | - # find and symlink kubectl |
357 | | - kubectl = repository_ctx.which("kubectl") |
358 | | - if not kubectl: |
359 | | - fail("Unable to find kubectl executable. PATH=%s" % repository_ctx.path) |
360 | | - repository_ctx.symlink(kubectl, "kubectl") |
361 | | - |
362 | | - home = repository_ctx.path(repository_ctx.os.environ["HOME"]) |
363 | | - |
364 | | - # use provided user name or fall back to current os user name |
365 | | - if repository_ctx.attr.user: |
366 | | - user = repository_ctx.attr.user |
367 | | - elif "USER" in repository_ctx.os.environ: |
368 | | - user = repository_ctx.os.environ["USER"] |
369 | | - else: |
370 | | - exec_result = repository_ctx.execute(["whoami"]) |
371 | | - if exec_result.return_code != 0: |
372 | | - fail("Error detecting current user") |
373 | | - user = exec_result.stdout.rstrip() |
374 | | - |
375 | | - token = None |
376 | | - ca_crt = None |
377 | | - kubecert_cert = None |
378 | | - kubecert_key = None |
379 | | - server = repository_ctx.attr.server |
380 | | - config = None |
381 | | - |
382 | | - # check service account first |
383 | | - serviceaccount = repository_ctx.path("/var/run/secrets/kubernetes.io/serviceaccount") |
384 | | - if serviceaccount.exists: |
385 | | - ca_crt = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" |
386 | | - token_file = serviceaccount.get_child("token") |
387 | | - if token_file.exists: |
388 | | - exec_result = repository_ctx.execute(["cat", token_file.realpath]) |
389 | | - if exec_result.return_code != 0: |
390 | | - fail("Error reading user token") |
391 | | - token = exec_result.stdout.rstrip() |
392 | | - |
393 | | - # use master url from the environemnt |
394 | | - if "KUBERNETES_SERVICE_HOST" in repository_ctx.os.environ: |
395 | | - server = "https://%s:%s" % ( |
396 | | - repository_ctx.os.environ["KUBERNETES_SERVICE_HOST"], |
397 | | - repository_ctx.os.environ["KUBERNETES_SERVICE_PORT"], |
398 | | - ) |
399 | | - else: |
400 | | - # fall back to the default |
401 | | - server = "https://kubernetes.default" |
402 | | - else: |
403 | | - # check kubectl config file |
404 | | - config = home.get_child(".kube").get_child("config") |
405 | | - |
406 | | - if config and config.exists: |
407 | | - # symlink ~/.kube/config if this file exists |
408 | | - repository_ctx.symlink(config, repository_ctx.path("config")) |
409 | | - else: |
410 | | - # generate new config file service account token or certificates |
411 | | - certs = home.get_child(".kube").get_child("certs") |
412 | | - ca_crt = certs.get_child("ca.crt").realpath |
413 | | - kubecert_cert = certs.get_child("kubecert.cert") |
414 | | - kubecert_key = certs.get_child("kubecert.key") |
415 | | - |
416 | | - # config set-cluster {cluster} \ |
417 | | - # --certificate-authority=... \ |
418 | | - # --server=https://dev3.k8s.tubemogul.info:443 \ |
419 | | - # --embed-certs", |
420 | | - _kubectl_config(repository_ctx, [ |
421 | | - "set-cluster", |
422 | | - repository_ctx.attr.cluster, |
423 | | - "--server", |
424 | | - server, |
425 | | - "--certificate-authority", |
426 | | - ca_crt, |
427 | | - ]) |
428 | | - |
429 | | - # config set-credentials {user} --token=...", |
430 | | - if token: |
431 | | - _kubectl_config(repository_ctx, [ |
432 | | - "set-credentials", |
433 | | - user, |
434 | | - "--token", |
435 | | - token, |
436 | | - ]) |
437 | | - |
438 | | - # config set-credentials {user} --client-certificate=...", |
439 | | - if kubecert_cert and kubecert_cert.exists: |
440 | | - _kubectl_config(repository_ctx, [ |
441 | | - "set-credentials", |
442 | | - user, |
443 | | - "--client-certificate", |
444 | | - kubecert_cert.realpath, |
445 | | - ]) |
446 | | - |
447 | | - # config set-credentials {user} --client-key=...", |
448 | | - if kubecert_key and kubecert_key.exists: |
449 | | - _kubectl_config(repository_ctx, [ |
450 | | - "set-credentials", |
451 | | - user, |
452 | | - "--client-key", |
453 | | - kubecert_key.realpath, |
454 | | - ]) |
455 | | - |
456 | | - # export repostory contents |
457 | | - repository_ctx.file("BUILD", _KUBECONFIG_BUILD_TEMPLATE.format( |
458 | | - cluster = repository_ctx.attr.cluster, |
459 | | - server = repository_ctx.attr.server, |
460 | | - user = user, |
461 | | - ), False) |
462 | | - |
463 | | - return { |
464 | | - "cluster": repository_ctx.attr.cluster, |
465 | | - "server": repository_ctx.attr.server, |
466 | | - "user": user, |
467 | | - } |
468 | | - |
469 | | -kubeconfig = repository_rule( |
470 | | - attrs = { |
471 | | - "cluster": attr.string( |
472 | | - mandatory = True, |
473 | | - ), |
474 | | - "server": attr.string( |
475 | | - mandatory = False, |
476 | | - ), |
477 | | - "user": attr.string( |
478 | | - mandatory = False, |
479 | | - ), |
480 | | - }, |
481 | | - environ = [ |
482 | | - "HOME", |
483 | | - "USER", |
484 | | - "KUBERNETES_SERVICE_HOST", |
485 | | - "KUBERNETES_SERVICE_PORT", |
486 | | - ], |
487 | | - local = True, |
488 | | - implementation = _kubeconfig_impl, |
489 | | -) |
490 | | - |
491 | 279 | def _stamp(ctx, string, output): |
492 | 280 | stamps = [ctx.file._info_file] |
493 | 281 | stamp_args = [ |
|
0 commit comments