diff --git a/docs/k8s_apps/experimental/ghost.md b/docs/k8s_apps/experimental/ghost.md index c2d4fb715..6ca2bea66 100644 --- a/docs/k8s_apps/experimental/ghost.md +++ b/docs/k8s_apps/experimental/ghost.md @@ -22,17 +22,22 @@ apps: init: enabled: false values: + # admin info + admin_user: "" + admin_email: "" + # smtp info + smtp_host: "" + smtp_user: "" + smtp_port: "" + smtp_protocol: "SMTP" + # smtp from email (verified sender) + smtp_from_address: example.com smtp_password: value_from: env: GHOST_SMTP_PASSWORD backups: # cronjob syntax schedule to run ghost pvc backups pvc_schedule: 10 0 * * * - # cronjob syntax (with SECONDS field) for ghost postgres backups - # must happen at least 10 minutes before pvc backups, to avoid corruption - # due to missing files. This is because the backup shows as completed before - # it actually is - postgres_schedule: 0 0 0 * * * s3: # these are for pushing remote backups of your local s3 storage, for speed and cost optimization endpoint: "" @@ -60,18 +65,10 @@ apps: # affinity_value: "" # hostname that users go to in the browser hostname: "" - # admin username - admin_user: "ghost" - # admin email - admin_email: "" + # admin hostname that users go to in the browser + admin_hostname: "" # title of your title blog_title: "" - # smtp server - smtp_host: "" - # smtp port - smtp_port: "" - # smtp username - smtp_user: "" # ghost mysql pvc capacity mysql_pvc_capacity: 5Gi # ghost pvc capacity @@ -98,6 +95,7 @@ apps: source_repos: - registry-1.docker.io - seaweedfs.github.io/seaweedfs/helm + - https://small-hack.github.io/ghost-helm-chart destination: # automatically includes the app's namespace and argocd's namespace namespaces: [] diff --git a/docs/k8s_apps/libretranslate.md b/docs/k8s_apps/libretranslate.md index 1a6ff138f..48e19ce43 100644 --- a/docs/k8s_apps/libretranslate.md +++ b/docs/k8s_apps/libretranslate.md @@ -4,7 +4,7 @@ ```yaml apps: - libre_translate: + libretranslate: description: | 📖 [link=https://libretranslate.com/]libretranslate[/link] is a self-hosted language translation tool. This is useful as both a web interface like translate.google.com, but also as an API for use with other apps such as Mastodon diff --git a/pyproject.toml b/pyproject.toml index f36562476..36e887044 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "smol_k8s_lab" -version = "7.0.0b2" +version = "7.0.0b4" description = "CLI and TUI to quickly install slimmer Kubernetes distros and then manage apps declaratively using Argo CD" authors = ["Jesse Hitch ", "Max Roby "] diff --git a/smol_k8s_lab/__init__.py b/smol_k8s_lab/__init__.py index a67d04003..ba81d35f9 100755 --- a/smol_k8s_lab/__init__.py +++ b/smol_k8s_lab/__init__.py @@ -32,7 +32,7 @@ from .k8s_apps.networking.netmaker import configure_netmaker from .k8s_apps.operators import setup_operators from .k8s_apps.operators.minio import configure_minio_tenant -from .k8s_apps.social.libre_translate import configure_libretranslate +from .k8s_apps.social.libretranslate import configure_libretranslate from .k8s_apps.valkey import configure_valkey from .k8s_distros import create_k8s_distro, delete_cluster from .tui import launch_config_tui @@ -239,6 +239,7 @@ def main(config: str = "", apps.get('ingress_nginx', {}), apps.get('cert_manager', {}), apps.get('cnpg_operator', {}), + apps.get('pxc_operator', {}), apps['argo_cd'], SECRETS, bw) @@ -270,6 +271,7 @@ def main(config: str = "", apps.pop('minio_operator', {'enabled': False}), apps.pop('seaweedfs', {'enabled': False}), apps.pop('cnpg_operator', {'enabled': False}), + apps.pop('pxc_operator', {'enabled': False}), apps.pop('postgres_operator', {'enabled': False}), apps.pop('openbao', {'enabled': False}), bw) @@ -317,10 +319,10 @@ def main(config: str = "", configure_tempo(argocd, tempo, bw) # set up self hosted translation - libre_translate_dict = apps.pop('libre_translate', {'enabled': False}) - if libre_translate_dict['enabled']: + libretranslate_dict = apps.pop('libretranslate', {'enabled': False}) + if libretranslate_dict['enabled']: libretranslate_api_key = configure_libretranslate( - argocd, libre_translate_dict, bw + argocd, libretranslate_dict, bw ) else: libretranslate_api_key = "" @@ -341,6 +343,7 @@ def main(config: str = "", apps.pop('matrix', {}), apps.pop('peertube', {}), apps.pop('writefreely', {}), + apps.pop('renovate', {}), pvc_storage_class, zitadel_hostname, oidc_obj, diff --git a/smol_k8s_lab/config/default_config.yaml b/smol_k8s_lab/config/default_config.yaml index 48d08e422..2b40fe33f 100644 --- a/smol_k8s_lab/config/default_config.yaml +++ b/smol_k8s_lab/config/default_config.yaml @@ -470,6 +470,8 @@ apps: # set the local s3 provider for forgejo's public data in one bucket # and private database backups in another. can be seaweedfs for now s3_provider: seaweedfs + # storage_class for S3 PVCs + # s3_pvc_storage_class: local-path # how large the backing pvc's capacity should be for minio or seaweedfs s3_pvc_capacity: 10Gi # local s3 endpoint for postgresql backups, backed up constantly @@ -498,6 +500,7 @@ apps: - code.forgejo.org - https://seaweedfs.github.io/seaweedfs/helm - https://small-hack.github.io/cloudnative-pg-cluster-chart + - registry-1.docker.io destination: # automatically includes the app's namespace and argocd's namespace namespaces: [] @@ -542,7 +545,10 @@ apps: project: name: external-secrets-operator source_repos: + # needed for the helm chart - https://charts.external-secrets.io + # needed for the CRDs + - https://github.com/external-secrets/external-secrets # you can remove this one if you're not using bitwarden to store your k8s secrets - https://small-hack.github.io/bitwarden-eso-provider destination: @@ -619,17 +625,22 @@ apps: init: enabled: true values: + # admin info + admin_user: "" + admin_email: "" + # smtp info + smtp_host: "" + smtp_user: "" + smtp_port: "" + smtp_protocol: "SMTP" + # smtp from email (verified sender) + smtp_from_address: example.com smtp_password: value_from: env: GHOST_SMTP_PASSWORD backups: # cronjob syntax schedule to run ghost pvc backups pvc_schedule: 10 0 * * * - # cronjob syntax (with SECONDS field) for ghost postgres backups - # must happen at least 10 minutes before pvc backups, to avoid corruption - # due to missing files. This is because the backup shows as completed before - # it actually is - postgres_schedule: 0 0 0 * * * s3: # these are for pushing remote backups of your local s3 storage, for speed and cost optimization endpoint: "" @@ -657,18 +668,10 @@ apps: # affinity_value: "" # hostname that users go to in the browser hostname: "" - # admin username - admin_user: "ghost" - # admin email - admin_email: "" + # admin hostname that users go to in the browser + admin_hostname: "" # title of your title blog_title: "" - # smtp server - smtp_host: "" - # smtp port - smtp_port: "" - # smtp username - smtp_user: "" # ghost mysql pvc capacity mysql_pvc_capacity: 5Gi # ghost pvc capacity @@ -703,6 +706,7 @@ apps: source_repos: - registry-1.docker.io - seaweedfs.github.io/seaweedfs/helm + - https://small-hack.github.io/ghost-helm-chart destination: # automatically includes the app's namespace and argocd's namespace namespaces: [] @@ -1415,7 +1419,7 @@ apps: # automatically includes the app's namespace and argocd's namespace namespaces: [] - libre_translate: + libretranslate: description: | 📖 [link=https://libretranslate.com/]libretranslate[/link] is a self-hosted language translation tool. This is useful as both a web interface like translate.google.com, but also as an API for use with other apps such as Mastodon @@ -2469,6 +2473,8 @@ apps: s3_endpoint: "" # capacity for the PVC backing your local s3 instance s3_pvc_capacity: 100Gi + # StorageClass for the PVC backing your local s3 instance + s3_storage_class: local-path # git repo to install the Argo CD app from repo: https://github.com/small-hack/argocd-apps @@ -2551,37 +2557,45 @@ apps: renovate: description: | - [magenta]DEMO - UNTESTED[/magenta] - [link=https://docs.renovatebot.com/]Renovate[/link] is a tool for automated dependency updates. It's Multi-platform and multi-language. This is a simple helm chart for running a self-hosted RenovateBot. - enabled: false + enabled: true + init: + enabled: true + values: + renovate_pat: + value_from: + env: RENOVATE_PAT + renovate_github_pat: + value_from: + env: RENOVATE_GITHUB_PAT argo: # secrets keys to make available to Argo CD ApplicationSets - secret_keys: {} + secret_keys: + # At 01:00 every day + cronjob_schedule: 0 1 * * * # git repo to install the Argo CD app from - repo: https://github.com/small-hack/argocd-apps - # path in the argo repo to point to. Trailing slash very important! This - # is an app of apps. Change to "monitoring/kube-prometheus-stack/" to - # only install kube-prometheus-stack (foregoing loki and push gateway) - path: demo/renovate/ + repo: https://git.smallhack.org/small-hack/argocd-apps + # path in the argo repo to point to. Trailing slash very important! + path: renovate/ # either the branch or tag to point at in the argo repo above revision: main # kubernetes cluster to install the k8s app into, defaults to Argo CD default cluster: https://kubernetes.default.svc # namespace to install the k8s app in - namespace: "renovate" + namespace: renovate # recurse directories in the provided git repo directory_recursion: false # source repos for Argo CD App Project (in addition to argo.repo) project: name: renovate source_repos: - - "https://docs.renovatebot.com/helm-charts" + - https://docs.renovatebot.com/helm-charts + - ghcr.io/renovatebot/charts/renovate destination: # automatically includes the app's namespace and argocd's namespace namespaces: - - renovate + - renovate seaweedfs: enabled: false diff --git a/smol_k8s_lab/k8s_apps/__init__.py b/smol_k8s_lab/k8s_apps/__init__.py index 547f5d75e..db4da1461 100644 --- a/smol_k8s_lab/k8s_apps/__init__.py +++ b/smol_k8s_lab/k8s_apps/__init__.py @@ -28,6 +28,7 @@ from .secrets_management.infisical import configure_infisical from .secrets_management.vault import configure_vault from .social.forgejo import configure_forgejo +from .renovate import configure_renovate from .social.ghost import configure_ghost from .social.gotosocial import configure_gotosocial from .social.harbor import configure_harbor @@ -155,6 +156,7 @@ def setup_base_apps(k8s_obj: K8s, ingress_dict: dict = {}, cert_manager_dict: dict = {}, cnpg_operator_dict: dict = {}, + pxc_operator_dict: dict = {}, argocd_dict: dict = {}, plugin_secrets: dict = {}, bw: BwCLI = None) -> ArgoCD: @@ -169,6 +171,7 @@ def setup_base_apps(k8s_obj: K8s, cilium_enabled = cilium_dict.get('enabled', False) ingress_nginx_enabled = ingress_dict.get('enabled', False) cnpg_operator_enabled = cnpg_operator_dict.get('enabled', False) + pxc_operator_enabled = pxc_operator_dict.get('enabled', False) argocd_enabled = argocd_dict.get('enabled', False) cert_manager_enabled = cert_manager_dict.get('enabled', False) argo_secrets_plugin_enabled = argocd_dict['argo']['directory_recursion'] @@ -177,6 +180,7 @@ def setup_base_apps(k8s_obj: K8s, metallb_enabled, cilium_enabled, cnpg_operator_enabled, + pxc_operator_enabled, argocd_enabled, argo_secrets_plugin_enabled) @@ -246,6 +250,7 @@ async def setup_federated_apps( matrix_dict: dict = {}, peertube_dict: dict = {}, writefreely_dict: dict = {}, + renovate_dict: dict = {}, pvc_storage_class: str = "local-path", zitadel_hostname: str = "", zitadel_obj: Zitadel = None, @@ -262,6 +267,10 @@ async def setup_federated_apps( pvc_storage_class, zitadel_obj, bw) + if renovate_dict.get('enabled', False): + await configure_renovate(argocd, + renovate_dict, + bw) # blogging platforms if ghost_dict.get('enabled', False): diff --git a/smol_k8s_lab/k8s_apps/monitoring/grafana_stack.py b/smol_k8s_lab/k8s_apps/monitoring/grafana_stack.py index bc85b98fa..9af9dc40e 100644 --- a/smol_k8s_lab/k8s_apps/monitoring/grafana_stack.py +++ b/smol_k8s_lab/k8s_apps/monitoring/grafana_stack.py @@ -55,7 +55,7 @@ def configure_grafana_stack(argocd: ArgoCD, if init_enabled: # configure backup s3 credentials - backup_vals = process_backup_vals(cfg.get('backups', ''), 'grafana-stack', argocd) + backup_vals = process_backup_vals(cfg.get('backups', ''), 'grafana_stack', argocd) # initial secrets to deploy this app from scratch if init_enabled and not app_installed: diff --git a/smol_k8s_lab/k8s_apps/operators/__init__.py b/smol_k8s_lab/k8s_apps/operators/__init__.py index 5b82e69fd..08ae3e48f 100644 --- a/smol_k8s_lab/k8s_apps/operators/__init__.py +++ b/smol_k8s_lab/k8s_apps/operators/__init__.py @@ -13,6 +13,7 @@ def setup_operators(argocd: ArgoCD, minio_config: dict = {}, seaweed_config: dict = {}, cnpg_config: dict = {}, + pxc_config: dict = {}, pg_config: dict = {}, openbao_config: dict = {}, bitwarden: BwCLI = None) -> None: @@ -24,6 +25,7 @@ def setup_operators(argocd: ArgoCD, - minio operator - seaweedfs - cnpg (cloud native postgres) operator + - pxc (percona mysql) operator - zalando postgres operator - openbao """ @@ -57,6 +59,10 @@ def setup_operators(argocd: ArgoCD, if cnpg_config and cnpg_config.get('enabled', False): argocd.install_app('cnpg-operator', cnpg_config['argo']) + # pxc operator is a mysql operator for creating mysql clusters + if pxc_config and pxc_config.get('enabled', False): + argocd.install_app('pxc-operator', pxc_config['argo']) + # zalando postgres operator is a postgres operator for creating postgresql clusters if pg_config and pg_config.get('enabled', False): configure_postgres_operator(argocd, pg_config, bitwarden) diff --git a/smol_k8s_lab/k8s_apps/renovate.py b/smol_k8s_lab/k8s_apps/renovate.py new file mode 100644 index 000000000..3d46a2506 --- /dev/null +++ b/smol_k8s_lab/k8s_apps/renovate.py @@ -0,0 +1,128 @@ +# internal libraries +from smol_k8s_lab.bitwarden.bw_cli import BwCLI, create_custom_field +from smol_k8s_lab.k8s_tools.argocd_util import ArgoCD +# from smol_k8s_lab.utils.passwords import create_password +from smol_k8s_lab.utils.rich_cli.console_logging import header +from smol_k8s_lab.utils.value_from import extract_secret + +# external libraries +import logging as log + + +async def configure_renovate(argocd: ArgoCD, + cfg: dict, + bitwarden: BwCLI = BwCLI("test","test","test") + ) -> bool: + """ + creates a renovate app and initializes it with secrets if you'd like :) + + required: + argocd - ArgoCD() object for Argo CD operations + cfg - dict, with at least argocd key and init key + + optional: + bitwarden - BwCLI() object with session token to create bitwarden items + """ + # check immediately if the app is installed + app_installed = argocd.check_if_app_exists('renovate') + + # verify if initialization is enabled + init = cfg.get('init', {'enabled': True, 'restore': {'enabled': False}}) + init_enabled = init.get('enabled', True) + + # check if we're restoring and get values for that + restore_dict = init.get('restore', {"enabled": False}) + restore_enabled = restore_dict['enabled'] + + # figure out what header to print + if restore_enabled: + header_start = "Restoring" + else: + if app_installed: + header_start = "Syncing" + else: + header_start = "Setting up" + + header(f"{header_start} [green]renovate[/], so you can keep your dependencies up to date", + '🤖') + + # get any secrets for this app + # secrets = cfg['argo']['secret_keys'] + + # we need namespace immediately + renovate_namespace = cfg['argo']['namespace'] + + if init_enabled: + renovate_pat = extract_secret(init['values'].get('renovate_pat')) + try: + github_pat = extract_secret(init['values'].get('renovate_github_pat')) + except Exception as e: + log.error(str(e)) + github_pat = "happy_halloween" + if not github_pat: + github_pat = "happy_halloween" + + if init_enabled and not app_installed: + argocd.k8s.create_namespace(renovate_namespace) + + if bitwarden and not restore_enabled: + setup_bitwarden_items(argocd, bitwarden, renovate_pat, github_pat) + + # these are standard k8s secrets yaml + elif not bitwarden and not restore_enabled: + # renovate creds k8s secret + argocd.k8s.create_secret('renovate-pat', 'renovate', + {"pat": renovate_pat, + "github_token": github_pat}) + + if not app_installed: + if not init_enabled: + argocd.install_app('renovate', cfg['argo']) + else: + log.info("renovate already installed 🎉") + + if bitwarden and init_enabled: + refresh_bweso(argocd, bitwarden) + + +def setup_bitwarden_items(argocd: ArgoCD, + bitwarden: BwCLI, + renovate_pat: str, + github_pat: str = "") -> None: + + # renovate credentials + renovate_id = bitwarden.create_login( + name='renovate-pat', + item_url="renovate.io", + user='renovate', + password=renovate_pat, + fields=[create_custom_field("github-token", github_pat)] + ) + + # update the renovate values for the argocd appset + argocd.update_appset_secret({'renovate_pat_bitwarden_id': renovate_id}) + + # reload the bitwarden ESO provider + try: + argocd.k8s.reload_deployment('bitwarden-eso-provider', 'external-secrets') + except Exception as e: + log.error( + "Couldn't scale down the [magenta]bitwarden-eso-provider" + "[/] deployment in [green]external-secrets[/] namespace." + f"Recieved: {e}" + ) + + +def refresh_bweso(argocd: ArgoCD, bitwarden: BwCLI) -> None: + """ + if renovate already installed, but bitwarden and init are enabled, still + populate the bitwarden IDs in the appset secret plugin secret + """ + log.debug("Making sure renovate Bitwarden item IDs are in appset " + "secret plugin secret") + + + secrets_id = bitwarden.get_item("renovate-pat-renovate.io", False)[0]['id'] + + # {'renovate_admin_credentials_bitwarden_id': admin_id, + argocd.update_appset_secret({'renovate_secret_bitwarden_id': secrets_id}) diff --git a/smol_k8s_lab/k8s_apps/social/forgejo.py b/smol_k8s_lab/k8s_apps/social/forgejo.py index 48301f148..3994a6566 100644 --- a/smol_k8s_lab/k8s_apps/social/forgejo.py +++ b/smol_k8s_lab/k8s_apps/social/forgejo.py @@ -91,7 +91,7 @@ async def configure_forgejo(argocd: ArgoCD, # configure OIDC if zitadel and not restore_enabled: log.debug("Creating a forgejo OIDC application in Zitadel...") - redirect_uris = f"https://{forgejo_hostname}/auth/callback" + redirect_uris = f"https://{forgejo_hostname}/user/oauth2/Zitadel/callback" logout_uris = [f"https://{forgejo_hostname}"] oidc_creds = zitadel.create_application( "forgejo", @@ -468,6 +468,7 @@ def restore_forgejo(argocd: ArgoCD, if restore_dict.get("cnpg_restore", False): psql_version = restore_dict.get("postgresql_version", 16) s3_endpoint = secrets.get('s3_endpoint', "") + # use official cloudnative Cluster chart parameters restore_cnpg_cluster(argocd.k8s, 'forgejo', forgejo_namespace, @@ -485,24 +486,20 @@ def restore_forgejo(argocd: ArgoCD, ) argocd.k8s.apply_manifests(podconfig_yaml, argocd.namespace) - # then we begin the restic restore of all the forgejo PVCs we lost - for pvc in ['valkey_primary', 'valkey_replica']: - pvc_enabled = secrets.get('valkey_pvc_enabled', 'false') - if pvc_enabled and pvc_enabled.lower() != 'false': - # restores the forgejo pvc - k8up_restore_pvc( - k8s_obj=argocd.k8s, - app='forgejo', - pvc=f'forgejo-{pvc.replace("_","-")}', - namespace='forgejo', - s3_endpoint=s3_backup_endpoint, - s3_bucket=s3_backup_bucket, - access_key_id=access_key_id, - secret_access_key=secret_access_key, - restic_repo_password=restic_repo_password, - snapshot_id=snapshot_ids[f'forgejo_{pvc}'], - pod_config="file-backups-podconfig" - ) + # restores the forgejo pvc + k8up_restore_pvc( + k8s_obj=argocd.k8s, + app='forgejo', + pvc='forgejo', + namespace=forgejo_namespace, + s3_endpoint=s3_backup_endpoint, + s3_bucket=s3_backup_bucket, + access_key_id=access_key_id, + secret_access_key=secret_access_key, + restic_repo_password=restic_repo_password, + snapshot_id=snapshot_ids['forgejo'], + pod_config="backups-podconfig" + ) # todo: from here on out, this could be async to start on other tasks # install forgejo as usual, but wait on it this time diff --git a/smol_k8s_lab/k8s_apps/social/ghost.py b/smol_k8s_lab/k8s_apps/social/ghost.py index e884b3e98..3bea4d012 100644 --- a/smol_k8s_lab/k8s_apps/social/ghost.py +++ b/smol_k8s_lab/k8s_apps/social/ghost.py @@ -7,7 +7,6 @@ k8up_restore_pvc) from smol_k8s_lab.utils.passwords import create_password from smol_k8s_lab.utils.rich_cli.console_logging import sub_header, header -from smol_k8s_lab.utils.run.subproc import subproc from smol_k8s_lab.utils.value_from import extract_secret, process_backup_vals # external libraries @@ -82,6 +81,8 @@ async def configure_ghost(argocd: ArgoCD, mail_user = init_values.get('smtp_user', '') mail_host = init_values.get('smtp_host', '') mail_port = init_values.get('smtp_port', '') + mail_from_address = init_values.get('smtp_from_address', '') + mail_protocol = init_values.get('smtp_protocol', '') mail_pass = extract_secret(init_values.get('smtp_password')) # configure s3 credentials @@ -127,7 +128,10 @@ async def configure_ghost(argocd: ArgoCD, backup_vals['s3_password'], backup_vals['restic_repo_pass'], ghost_admin_username, + ghost_admin_email, mail_host, + mail_protocol, + mail_from_address, mail_port, mail_user, mail_pass, @@ -171,20 +175,6 @@ async def configure_ghost(argocd: ArgoCD, # wait for all the ghost apps to come up, give it extra time argocd.sync_app(app='ghost-web-app', sleep_time=4) argocd.wait_for_app('ghost-web-app') - - # create admin credentials - password = create_user(ghost_admin_username, - ghost_admin_email, - cfg['argo']['namespace']) - if bitwarden: - sub_header("Creating secrets in Bitwarden") - bitwarden.create_login( - name='ghost-admin-credentials', - item_url=ghost_hostname, - user=ghost_admin_username, - password=password, - fields=[create_custom_field("email", ghost_admin_email)] - ) else: log.info("ghost already installed 🎉") @@ -192,45 +182,6 @@ async def configure_ghost(argocd: ArgoCD, refresh_bweso(argocd, ghost_hostname, bitwarden) -def create_user(user: str, email: str, pod_namespace: str) -> str: - """ - given a username, email, and namespace of the ghost pod, we'll create a - new ghost user using a kubectl exec command and then we return - their autogenerated password - """ - sub_header(f"Creating a ghost user for: {user}") - # first, go get the exact name of the pod we need to exec a command on - pod_cmd = ( - f"kubectl get pods -n {pod_namespace} " - "-l app.kubernetes.io/instance=ghost-web-app,app.kubernetes.io/component=web" - " --no-headers " - "-o custom-columns=NAME:.metadata.name" - ) - pod = subproc([pod_cmd]).rstrip() - log.info(f"ghost web app pod is: {pod}") - - # generate a random password - password = create_password() - - # then run the user creation command - cmd = (f'kubectl exec -n {pod_namespace} {pod} -- /bin/sh -c "./ghost ' - '--config-path ../config/config.yaml admin account create ' - f'--username {user} --email {email} --password \'{password}\'"') - - # then process the output from the command - subproc([cmd], shell=True, universal_newlines=True) - - # then run the user promotion (to admin) command - cmd = (f'kubectl exec -n {pod_namespace} {pod} -- /bin/sh -c ' - '"./ghost --config-path ../config/config.yaml admin ' - f'account promote --username {user}"') - - # then process the output from the command - subproc([cmd], shell=True, universal_newlines=True).split()[3] - - return password - - def refresh_bweso(argocd: ArgoCD, ghost_hostname: str, bitwarden: BwCLI) -> None: @@ -290,7 +241,10 @@ def setup_bitwarden_items(argocd: ArgoCD, backups_s3_password: str, restic_repo_pass: str, admin_user: str, + admin_email: str, mail_host: str, + mail_protocol: str, + mail_from_address: str, mail_port: str, mail_user: str, mail_pass: str, @@ -347,35 +301,42 @@ def setup_bitwarden_items(argocd: ArgoCD, ghost_mysql_password = bitwarden.generate() mysql_pass_obj = create_custom_field("mysqlPassword", ghost_mysql_password) + mysql_database_obj = create_custom_field("database", "ghost") + mysql_port_obj = create_custom_field("port", "3306") db_id = bitwarden.create_login( name='ghost-mysql-credentials', item_url=ghost_hostname, user='ghost', password=ghost_mysql_password, - fields=[mysql_pass_obj] + fields=[mysql_pass_obj, mysql_database_obj, mysql_port_obj] ) # SMTP credentials ghost_smtp_host_obj = create_custom_field("smtpHostname", mail_host) ghost_smtp_port_obj = create_custom_field("smtpPort", mail_port) + ghost_smtp_protocol_obj = create_custom_field("smtpProtocol", mail_protocol) + ghost_smtp_from_address_obj = create_custom_field("smtpFromAddress", mail_from_address) smtp_id = bitwarden.create_login( name='ghost-smtp-credentials', item_url=ghost_hostname, user=mail_user, password=mail_pass, - fields=[ghost_smtp_host_obj, ghost_smtp_port_obj] + fields=[ghost_smtp_host_obj, + ghost_smtp_port_obj, + ghost_smtp_protocol_obj, + ghost_smtp_from_address_obj] ) # admin credentials for ghost itself - # admin_password = create_password() - # email_obj = create_custom_field("email", ghost_admin_email) - # admin_id = bitwarden.create_login( - # name='ghost-admin-credentials', - # item_url=ghost_hostname, - # user=ghost_admin_username, - # password=admin_password, - # fields=[email_obj] - # ) + admin_password = create_password() + email_obj = create_custom_field("email", admin_email) + admin_id = bitwarden.create_login( + name='ghost-admin-credentials', + item_url=ghost_hostname, + user=admin_user, + password=admin_password, + fields=[email_obj] + ) # oidc credentials if they were given, else they're probably already there if oidc_creds: @@ -400,6 +361,7 @@ def setup_bitwarden_items(argocd: ArgoCD, 'ghost_oidc_credentials_bitwarden_id': oidc_id, 'ghost_mysql_credentials_bitwarden_id': db_id, 'ghost_s3_admin_credentials_bitwarden_id': s3_admin_id, + 'ghost_admin_credentials_bitwarden_id': admin_id, 'ghost_s3_ghost_credentials_bitwarden_id': s3_id, 'ghost_s3_backups_credentials_bitwarden_id': s3_backups_id}) diff --git a/smol_k8s_lab/k8s_apps/social/libre_translate.py b/smol_k8s_lab/k8s_apps/social/libretranslate.py similarity index 97% rename from smol_k8s_lab/k8s_apps/social/libre_translate.py rename to smol_k8s_lab/k8s_apps/social/libretranslate.py index 87ead8014..734636007 100644 --- a/smol_k8s_lab/k8s_apps/social/libre_translate.py +++ b/smol_k8s_lab/k8s_apps/social/libretranslate.py @@ -50,7 +50,7 @@ def configure_libretranslate(argocd: ArgoCD, '📖') # we need namespace no matter the install type - libre_translate_namespace = cfg['argo']['namespace'] + libretranslate_namespace = cfg['argo']['namespace'] # api key for programatic access to libretranslate: set it to blank just in case api_key = "" @@ -58,7 +58,7 @@ def configure_libretranslate(argocd: ArgoCD, # if the user has chosen to use smol-k8s-lab initialization if not app_installed and init_enabled: # immediately create namespace - argocd.k8s.create_namespace(libre_translate_namespace) + argocd.k8s.create_namespace(libretranslate_namespace) # if bitwarden is enabled, we create login items for each set of credentials if bitwarden and not restore_enabled: diff --git a/smol_k8s_lab/k8s_tools/helm.py b/smol_k8s_lab/k8s_tools/helm.py index eec25370b..c80e610ed 100755 --- a/smol_k8s_lab/k8s_tools/helm.py +++ b/smol_k8s_lab/k8s_tools/helm.py @@ -222,6 +222,7 @@ def prepare_helm(k8s_distro: str, metallb: bool = True, cilium: bool = False, cnpg_operator: bool = False, + pxc_operator: bool = False, argo: bool = False, argo_app_set: bool = False) -> bool: """ diff --git a/smol_k8s_lab/k8s_tools/restores.py b/smol_k8s_lab/k8s_tools/restores.py index b22c431e3..91aaff1b2 100644 --- a/smol_k8s_lab/k8s_tools/restores.py +++ b/smol_k8s_lab/k8s_tools/restores.py @@ -267,11 +267,11 @@ def restore_cnpg_cluster(k8s_obj: K8s, "s3Credentials": { "accessKeyId": { "name": "s3-postgres-credentials", - "key": "accessKeyId" + "key": "ACCESS_KEY_ID" }, "secretAccessKey": { "name": "s3-postgres-credentials", - "key": "secretAccessKey" + "key": "ACCESS_SECRET_KEY" } }, "wal": {"maxParallel": 8} @@ -330,11 +330,11 @@ def restore_cnpg_cluster(k8s_obj: K8s, "s3Credentials": { "accessKeyId": { "name": "s3-postgres-credentials", - "key": "accessKeyId" + "key": "ACCESS_KEY_ID" }, "secretAccessKey": { "name": "s3-postgres-credentials", - "key": "secretAccessKey" + "key": "ACCESS_SECRET_KEY" } }, "wal": {"maxParallel": 8} diff --git a/smol_k8s_lab/utils/value_from.py b/smol_k8s_lab/utils/value_from.py index 6e2d6c16e..55cad3071 100644 --- a/smol_k8s_lab/utils/value_from.py +++ b/smol_k8s_lab/utils/value_from.py @@ -62,6 +62,8 @@ def process_backup_vals(backup_dict: dict, "postgres_schedule": backup_dict.get('postgres_schedule', "0 0 0 * * *") } + log.debug(f"Adding backup appset secret values for {app}") + if app and argocd: argocd.update_appset_secret({ f"{app}_s3_backup_endpoint": return_dict['endpoint'],