diff options
author | Richard Maw <richard.maw@codethink.co.uk> | 2013-11-22 13:46:05 +0000 |
---|---|---|
committer | Richard Maw <richard.maw@codethink.co.uk> | 2013-11-29 16:12:33 +0000 |
commit | 400427729b882566d0e394805a306481f0810145 (patch) | |
tree | 1f3aaa20c61b48f80de4f583857d7a830651ec0b | |
parent | de230e7475a0cdd412990398679f23e40db23376 (diff) | |
download | morph-400427729b882566d0e394805a306481f0810145.tar.gz |
plugins: Convert deploy to new classes.
It now does not push branches as this is not necessary to locate the
artifact.
It still makes temporary build branches, since it is assumed that if
you have changes in your workspace, it's preferable for the deploy to
fail, rather than think you've deployed something you haven't.
-rw-r--r-- | morphlib/plugins/deploy_plugin.py | 155 |
1 files changed, 70 insertions, 85 deletions
diff --git a/morphlib/plugins/deploy_plugin.py b/morphlib/plugins/deploy_plugin.py index 825b0124..09405aa4 100644 --- a/morphlib/plugins/deploy_plugin.py +++ b/morphlib/plugins/deploy_plugin.py @@ -15,13 +15,12 @@ import cliapp -import gzip +import contextlib import os import shutil import stat import tarfile import tempfile -import urlparse import uuid import morphlib @@ -266,26 +265,74 @@ class DeployPlugin(cliapp.Plugin): self.app.settings['tempdir-min-space'], '/', 0) - cluster = args[0] + cluster_name = args[0] env_vars = args[1:] - branch_dir = self.other.deduce_system_branch()[1] - root_repo = self.other.get_branch_config(branch_dir, 'branch.root') - root_repo_dir = self.other.find_repository(branch_dir, root_repo) - data = self.other.load_morphology(root_repo_dir, cluster) + ws = morphlib.workspace.open('.') + sb = morphlib.sysbranchdir.open_from_within('.') - if data['kind'] != 'cluster': + build_uuid = uuid.uuid4().hex + + build_command = morphlib.buildcommand.BuildCommand(self.app) + build_command = self.app.hookmgr.call('new-build-command', + build_command) + loader = morphlib.morphloader.MorphologyLoader() + name = morphlib.git.get_user_name(self.app.runcmd) + email = morphlib.git.get_user_email(self.app.runcmd) + build_ref_prefix = self.app.settings['build-ref-prefix'] + + root_repo_dir = morphlib.gitdir.GitDirectory( + sb.get_git_directory_name(sb.root_repository_url)) + mf = morphlib.morphologyfinder.MorphologyFinder(root_repo_dir) + cluster_text, cluster_filename = mf.read_morphology(cluster_name) + cluster_morphology = loader.load_from_string(cluster_text, + filename=cluster_filename) + + if cluster_morphology['kind'] != 'cluster': raise cliapp.AppException( "Error: morph deploy is only supported for cluster" " morphologies.") - for system in data['systems']: - self.deploy_system(system, env_vars) - def deploy_system(self, system, env_vars): + bb = morphlib.buildbranch.BuildBranch(sb, build_ref_prefix, + push_temporary=False) + with contextlib.closing(bb) as bb: + + for gd, build_ref in bb.add_uncommitted_changes(): + self.app.status(msg='Adding uncommitted changes '\ + 'in %(dirname)s to %(ref)s', + dirname=gd.dirname, ref=build_ref, chatty=True) + + for gd in bb.inject_build_refs(loader): + self.app.status(msg='Injecting temporary build refs '\ + 'into morphologies in %(dirname)s', + dirname=gd.dirname, chatty=True) + + for gd, build_ref in bb.update_build_refs(name, email, build_uuid): + self.app.status(msg='Committing changes in %(dirname)s '\ + 'to %(ref)s', + dirname=gd.dirname, ref=build_ref, chatty=True) + + for gd, build_ref, remote in bb.push_build_branches(): + self.app.status(msg='Pushing %(ref)s in %(dirname)s '\ + 'to %(remote)s', + ref=build_ref, dirname=gd.dirname, + remote=remote.get_push_url(), chatty=True) + + for system in cluster_morphology['systems']: + self.deploy_system(build_command, root_repo_dir, + bb.root_repo_url, bb.root_ref, + system, env_vars) + + def deploy_system(self, build_command, root_repo_dir, build_repo, ref, + system, env_vars): + # Find the artifact to build morph = system['morph'] + srcpool = build_command.create_source_pool(build_repo, ref, + morph + '.morph') + artifact = build_command.resolve_artifacts(srcpool) + deploy_defaults = system['deploy-defaults'] deployments = system['deploy'] - for system_id, deploy_params in deployments.iteritems(): user_env = morphlib.util.parse_environment_pairs( os.environ, @@ -308,64 +355,11 @@ class DeployPlugin(cliapp.Plugin): 'for system "%s"' % system_id) morphlib.util.sanitize_environment(final_env) - self.do_deploy(morph, deployment_type, location, final_env) - - def do_deploy(self, system_name, deployment_type, location, env): - # Deduce workspace and system branch and branch root repository. - workspace = self.other.deduce_workspace() - branch, branch_dir = self.other.deduce_system_branch() - branch_root = self.other.get_branch_config(branch_dir, 'branch.root') - branch_uuid = self.other.get_branch_config(branch_dir, 'branch.uuid') - - # Generate a UUID for the build. - build_uuid = uuid.uuid4().hex - - build_command = morphlib.buildcommand.BuildCommand(self.app) - build_command = self.app.hookmgr.call('new-build-command', - build_command) - push = self.app.settings['push-build-branches'] - - self.app.status(msg='Starting build %(uuid)s', uuid=build_uuid) + self.do_deploy(build_command, root_repo_dir, ref, artifact, + deployment_type, location, final_env) - self.app.status(msg='Collecting morphologies involved in ' - 'building %(system)s from %(branch)s', - system=system_name, branch=branch) - - # Find system branch root repository on the local disk. - root_repo = self.other.get_branch_config(branch_dir, 'branch.root') - root_repo_dir = self.other.find_repository(branch_dir, root_repo) - - # Get repositories of morphologies involved in building this system - # from the current system branch. - build_repos = self.other.get_system_build_repos( - branch, branch_dir, branch_root, system_name) - - # Generate temporary build ref names for all these repositories. - self.other.generate_build_ref_names(build_repos, branch_uuid) - - # Create the build refs for all these repositories and commit - # all uncommitted changes to them, updating all references - # to system branch refs to point to the build refs instead. - self.other.update_build_refs(build_repos, branch, build_uuid, push) - - if push: - self.other.push_build_refs(build_repos) - build_branch_root = branch_root - else: - dirname = build_repos[branch_root]['dirname'] - build_branch_root = urlparse.urljoin('file://', dirname) - - # Run the build. - build_ref = build_repos[branch_root]['build-ref'] - srcpool = build_command.create_source_pool( - build_branch_root, - build_ref, - system_name + '.morph') - artifact = build_command.resolve_artifacts(srcpool) - - if push: - self.other.delete_remote_build_refs(build_repos) - + def do_deploy(self, build_command, root_repo_dir, ref, artifact, + deployment_type, location, env): # Create a tempdir for this deployment to work in deploy_tempdir = tempfile.mkdtemp( @@ -405,7 +399,7 @@ class DeployPlugin(cliapp.Plugin): for name in names: self._run_extension( root_repo_dir, - build_ref, + ref, name, '.configure', [system_tree], @@ -415,7 +409,7 @@ class DeployPlugin(cliapp.Plugin): self.app.status(msg='Writing to device') self._run_extension( root_repo_dir, - build_ref, + ref, deployment_type, '.write', [system_tree, location], @@ -428,7 +422,7 @@ class DeployPlugin(cliapp.Plugin): self.app.status(msg='Finished deployment') - def _run_extension(self, repo_dir, ref, name, kind, args, env): + def _run_extension(self, gd, ref, name, kind, args, env): '''Run an extension. The ``kind`` should be either ``.configure`` or ``.write``, @@ -440,8 +434,9 @@ class DeployPlugin(cliapp.Plugin): ''' # Look for extension in the system morphology's repository. - ext = self._cat_file(repo_dir, ref, name + kind) - if ext is None: + try: + ext = gd.get_file_from_ref(ref, name + kind) + except cliapp.AppException: # Not found: look for it in the Morph code. code_dir = os.path.dirname(morphlib.__file__) ext_filename = os.path.join(code_dir, 'exts', name + kind) @@ -465,7 +460,7 @@ class DeployPlugin(cliapp.Plugin): self.app.runcmd( [ext_filename] + args, ['sh', '-c', 'while read l; do echo `date "+%F %T"` $l; done'], - cwd=repo_dir, env=env, stdout=None, stderr=None) + cwd=gd.dirname, env=env, stdout=None, stderr=None) if delete_ext: os.remove(ext_filename) @@ -474,13 +469,3 @@ class DeployPlugin(cliapp.Plugin): st = os.stat(filename) mask = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH return (stat.S_IMODE(st.st_mode) & mask) != 0 - - def _cat_file(self, repo_dir, ref, pathname): - '''Retrieve contents of a file from a git repository.''' - - argv = ['git', 'cat-file', 'blob', '%s:%s' % (ref, pathname)] - try: - return self.app.runcmd(argv, cwd=repo_dir) - except cliapp.AppException: - return None - |