def _default_deploy(self, app_name, app_run_id, remote_container_name): """do template substitution across everything in `k8s-templates` dir replaces things with $ with the vars from template.substitute also patches deployment if interactive mode is set """ # we'll make a subfolder of where this job will live self.job_sub_dir = self._track_deployed_job(app_name, app_run_id) for path, dirs, filenames in os.walk("k8s-templates"): for filename in filenames: with open(os.path.join(path, filename)) as f: template = Template(f.read()) out = template.substitute( image=remote_container_name, app=app_name, run=app_run_id, namespace=self.namespace, **config_helpers.get_template_parameters(self.config)) # some templates are still in yaml form by the time # they reach this point, so ignore a ValueError due to # no json obj avail try: out = self._ensure_correct_data_types(json.loads(out)) except ValueError: pass if self.args["--interactive"]: # every pod will be made to `sleep infinity & wait` out = self._patch_template_spec(out) self._apply_template(out, filename)
def test_get_empty_template_params(): config = { "namespace": "foo", "registry": "bar", constants.TEMPLATE_PARAMETERS: {} } assert get_template_parameters(config) == {}
def test_get_template_params(): config = { "namespace": "foo", "registry": "bar", constants.TEMPLATE_PARAMETERS: { "epochs": "10", "num_workers": "4" } } assert get_template_parameters(config) == \ {"epochs": "10", "num_workers": "4"}
def _deploy_new_container(self): """Substitutes image, app, run data into k8s-template selected. Can also launch user into interactive shell with --interactive flag """ app_name = self.config['name'] self.namespace = self.config['namespace'] remote_container_name = files.fetch_action_arg( 'push', 'last_remote_container') if remote_container_name is None: raise ValueError("No image found to deploy with. Run a plain " "`mlt deploy` to fix this. Most common reason " "for this is a --no-push was used before " "any image was available to use.") print("Deploying {}".format(remote_container_name)) kubernetes_helpers.ensure_namespace_exists(self.namespace) # do template substitution across everything in `k8s-templates` dir # replaces things with $ with the vars from template.substitute # also patches deployment if interactive mode is set self.interactive_deployment_found = False app_run_id = str(uuid.uuid4()) for path, dirs, filenames in os.walk("k8s-templates"): self.file_count = len(filenames) for filename in filenames: with open(os.path.join(path, filename)) as f: template = Template(f.read()) out = template.substitute( image=remote_container_name, app=app_name, run=app_run_id, **config_helpers.get_template_parameters(self.config)) interactive, out = self._check_for_interactive_deployment( out, filename) self._apply_template(out, filename) if interactive: interactive_podname = self._get_most_recent_podname() print("\nInspect created objects by running:\n" "$ kubectl get --namespace={} all\n".format(self.namespace)) self._update_app_run_id(app_run_id) # After everything is deployed we'll make a kubectl exec # call into our debug container if interactive mode if self.args["--interactive"] and self.interactive_deployment_found: self._exec_into_pod(interactive_podname) elif not self.interactive_deployment_found and \ self.args['--interactive']: raise ValueError("Unable to find deployment to run interactively. " "Multiple deployment files found and bad " "<kube_spec> argument passed.")