"""make deploy: a dev box's platform stack as ordered stages that are safe to repeat.""" import sys from themelio_dx import compat as themelio_compat from . import argocd, builds, cluster, seeds, storage, mesh, layout from .common import ROOT def aai_inputs(target): sys.path.insert(0, str(ROOT / 'dx/common')) from local_aai import up up.prepare(target) def aai_state(target): sys.path.insert(0, str(ROOT / 'dx/common')) from local_aai import up up.refresh(target) # Bootstrap supplies service namespaces and public trust. Argo then orders the shared # providers, AAI administration and service consumers through child health gates. # Seeds move between the checkout and the cluster around Argo's installation of them. # The delivered commit's images build in the cluster before Argo installs them (decision 0045). STAGES = ( ('kubernetes', lambda target, options: cluster.reconfigure(target, options['ssh'])), ('layout-conversion', lambda target, options: layout.prepare(target)), ('storage', lambda target, options: storage.main(target, options['device'])), ('mesh', lambda target, options: mesh.main(target)), ('argocd-bootstrap', lambda target, options: argocd.bootstrap(target)), ('layout-initialise', lambda target, options: layout.initialise(target)), ('edge', lambda target, options: mesh.edge(target)), ('aai-inputs', lambda target, options: aai_inputs(target)), ('seeds', lambda target, options: seeds.offer(target)), ('images', lambda target, options: builds.main(target, themelio_compat.profiles(target))), ('argocd', lambda target, options: argocd.main(target)), # The pharos Application publishes site-api-trust only after Argo starts the # Site API. Reconcile the gateway trust before route verification. ('edge-final', lambda target, options: mesh.edge(target)), ('aai-state', lambda target, options: aai_state(target)), ('seeds-collect', lambda target, options: seeds.collect(target)), ('storage-check', lambda target, options: storage.test(target, keep=options['keep_probe'])), ('route-check', lambda target, options: mesh.checks(target)), ('layout-ready', lambda target, options: layout.finish(target)), ) # make reconcile: deliver the committed checkout and build only what it changes (decision 0045). RECONCILE = ('argocd-bootstrap', 'aai-inputs', 'images', 'argocd', 'edge-final', 'aai-state') def unleased(target): """Neither command delivers while a takeover borrows the services' Applications.""" from platform_gitops import lease from platform_gitops.kubernetes import Cluster if Cluster(target.kubeconfig).owner(): lease.assert_free(Cluster(target.kubeconfig)) def reconcile(target): if not target.remote or not target.settings.get('ssh'): raise ValueError('make reconcile needs a dev box that make deploy has installed') from .remote import connect connect(target) with target.lock(timeout=60): argocd.preflight() unleased(target) layout.require_ready(target) for name, stage in STAGES: if name in RECONCILE: print('==> ' + name, flush=True) stage(target, {}) print('Delivered and reconciled on ' + target.name + '. Use make deploy for host configuration or profiles.') def main(target, ssh=None, device=None, keep_probe=False, profiles=''): if not target.remote: raise ValueError('make deploy needs TARGET=dev- for a remote Debian dev-box VM') if not ssh and not target.settings: raise ValueError('First deploy needs SSH= and STORAGE_DEVICE=/dev/') # Check the disk before provisioning, so a missing device fails without changing the VM. storage.device(target, device) options = {'ssh': ssh, 'device': device, 'keep_probe': keep_probe} with target.lock(timeout=60): argocd.preflight() if target.settings.get('node_uids'): # An installed dev box may hold a takeover lease; a first deploy has none. from .remote import connect connect(target) layout.resume(target) unleased(target) themelio_compat.profiles(target, profiles) for name, stage in STAGES: print('==> ' + name, flush=True) stage(target, options) print('Platform stack ready on ' + target.name + ': ' + ', '.join(name for name, _ in STAGES) + '. Repeat make deploy TARGET=' + target.name + ' to reconcile it; make takeover TARGET=' + target.name + ' runs your uncommitted application edits on the workstation.')