class Run(object): debug = False dryrun = False nulecule_base = None answers_data = {GLOBAL_CONF: {}} tmpdir = None answers_file = None provider = DEFAULT_PROVIDER installed = False plugins = [] update = False app_path = None target_path = None app_id = None app = None answers_output = None kwargs = None def __init__(self, answers, APP, dryrun = False, debug = False, stop = False, **kwargs): self.debug = debug self.dryrun = dryrun self.stop = stop self.kwargs = kwargs if "answers_output" in kwargs: self.answers_output = kwargs["answers_output"] if os.environ and "IMAGE" in os.environ: self.app_path = APP APP = os.environ["IMAGE"] del os.environ["IMAGE"] elif "image" in kwargs: logger.warning("Setting image to %s" % kwargs["image"]) self.app_path = APP APP = kwargs["image"] del kwargs["image"] self.kwargs = kwargs if APP and os.path.exists(APP): self.app_path = APP else: if not self.app_path: self.app_path = os.getcwd() install = Install(answers, APP, dryrun = dryrun, target_path = self.app_path) install.install() self.nulecule_base = Nulecule_Base(target_path=self.app_path) if "ask" in kwargs: self.nulecule_base.ask = kwargs["ask"] workdir = None if "workdir" in kwargs: workdir = kwargs["workdir"] self.utils = Utils(self.app_path, workdir) if not "workdir" in kwargs: kwargs["workdir"] = self.utils.workdir self.answers_file = answers self.plugin = Plugin() self.plugin.load_plugins() def _dispatchGraph(self): if not "graph" in self.nulecule_base.mainfile_data: raise Exception("Graph not specified in %s" % MAIN_FILE) for graph_item in self.nulecule_base.mainfile_data["graph"]: component = graph_item.get("name") if not component: raise ValueError("Component name missing in graph") if self.utils.isExternal(graph_item): self.kwargs["image"] = self.utils.getSourceImage(graph_item) component_run = Run(self.answers_file, self.utils.getExternalAppDir(component), self.dryrun, self.debug, self.stop, **self.kwargs) ret = component_run.run() if self.answers_output: self.nulecule_base.loadAnswers(ret) else: self._processComponent(component, graph_item) def _applyTemplate(self, data, component): template = Template(data) config = self.nulecule_base.getValues(component) logger.debug("Config: %s ", config) output = None while not output: try: logger.debug(config) output = template.substitute(config) except KeyError as ex: name = ex.args[0] logger.debug("Artifact contains unknown parameter %s, asking for it", name) config[name] = self.utils.askFor(name, {"description": "Missing parameter '%s', provide the value or fix your %s" % (name, MAIN_FILE)}) if not len(config[name]): raise Exception("Artifact contains unknown parameter %s" % name) self.nulecule_base.loadAnswers({component: {name: config[name]}}) return output def _processArtifacts(self, component, provider, provider_name = None): if not provider_name: provider_name = str(provider) artifacts = self.nulecule_base.getArtifacts(component) artifact_provider_list = [] if not provider_name in artifacts: raise Exception("Data for provider \"%s\" are not part of this app" % provider_name) dst_dir = os.path.join(self.utils.workdir, component) data = None for artifact in artifacts[provider_name]: if "inherit" in artifact: logger.debug("Inheriting from %s", artifact["inherit"]) for item in artifact["inherit"]: inherited_artifacts, _ = self._processArtifacts(component, provider, item) artifact_provider_list += inherited_artifacts continue artifact_path = self.utils.sanitizePath(artifact) data = provider.loadArtifact(os.path.join(self.app_path, artifact_path)) logger.debug("Templating artifact %s/%s", self.app_path, artifact_path) data = self._applyTemplate(data, component) artifact_dst = os.path.join(dst_dir, artifact_path) provider.saveArtifact(artifact_dst, data) artifact_provider_list.append(artifact_path) return artifact_provider_list, dst_dir def _processComponent(self, component, graph_item): logger.debug("Processing component %s", component) provider_class = self.plugin.getProvider(self.nulecule_base.provider) dst_dir = os.path.join(self.utils.workdir, component) provider = provider_class(self.nulecule_base.getValues(component), dst_dir, self.dryrun) if provider: logger.info("Using provider %s for component %s", self.nulecule_base.provider, component) else: raise Exception("Something is broken - couldn't get the provider") provider.artifacts, dst_dir = self._processArtifacts(component, provider) try: provider.init() if self.stop: provider.undeploy() else: provider.deploy() except ProviderFailedException as ex: logger.error(ex) sys.exit(1) def run(self): self.nulecule_base.loadMainfile(os.path.join(self.nulecule_base.target_path, MAIN_FILE)) self.nulecule_base.checkSpecVersion() self.nulecule_base.loadAnswers(self.answers_file) self.nulecule_base.checkAllArtifacts() config = self.nulecule_base.get() if "provider" in config: self.provider = config["provider"] self._dispatchGraph() #Think about this a bit more probably - it's (re)written for all components... if self.answers_output: self.nulecule_base.writeAnswers(self.answers_output) return self.nulecule_base.answers_data return None
class Install(object): dryrun = False params = None answers_file = None docker_cli = "docker" answers_file_values = {} def __init__( self, answers, APP, nodeps=False, update=False, target_path=None, dryrun=False, answers_format=ANSWERS_FILE_SAMPLE_FORMAT, **kwargs): self.dryrun = dryrun self.kwargs = kwargs app = APP # FIXME self.nulecule_base = Nulecule_Base( nodeps, update, target_path, dryrun, answers_format) if os.path.exists(app): logger.info("App path is %s, will be populated to %s", app, target_path) app = self._loadApp(app) else: logger.info("App name is %s, will be populated to %s", app, target_path) printStatus("Loading app %s ." % app) if not target_path: if self.nulecule_base.app_path: self.nulecule_base.target_path = self.nulecule_base.app_path else: self.nulecule_base.target_path = os.getcwd() self.utils = Utils(self.nulecule_base.target_path) self.nulecule_base.app = app self.answers_file = answers self.docker_cli = Utils.getDockerCli(self.dryrun) def _loadApp(self, app_path): self.nulecule_base.app_path = app_path if not os.path.basename(app_path) == MAIN_FILE: app_path = os.path.join(app_path, MAIN_FILE) mainfile_data = self.nulecule_base.loadMainfile(app_path) app = os.environ["IMAGE"] if "IMAGE" in os.environ else mainfile_data["id"] logger.debug("Setting path to %s", self.nulecule_base.app_path) return app def _copyFromContainer(self, image): image = self.nulecule_base.getImageURI(image) name = "%s-%s" % (self.utils.getComponentName(image), ''.join(random.sample(string.letters, 6))) logger.debug("Creating a container with name %s", name) # Workaround docker bug BZ1252168 by using run instead of create create = [self.docker_cli, "run", "--name", name, "--entrypoint", "/bin/true", image] logger.debug(" ".join(create)) subprocess.call(create) cp = [self.docker_cli, "cp", "%s:/%s" % (name, APP_ENT_PATH), self.utils.tmpdir] logger.debug(cp) if not subprocess.call(cp): logger.debug("Application entity data copied to %s", self.utils.tmpdir) printStatus("Copied app successfully.") rm = [self.docker_cli, "rm", name] subprocess.call(rm) def _populateApp(self, src=None, dst=None): logger.info("Copying app %s", self.utils.getComponentName(self.nulecule_base.app)) if not src: src = os.path.join(self.utils.tmpdir, APP_ENT_PATH) if not dst: dst = self.nulecule_base.target_path distutils.dir_util.copy_tree(src, dst, update=(not self.nulecule_base.update)) def _fromImage(self): return not self.nulecule_base.app_path or \ self.nulecule_base.target_path == self.nulecule_base.app_path def install(self): answerContent = self.nulecule_base.loadAnswers(self.answers_file) printAnswerFile(json.dumps(answerContent)) mainfile_dir = self.nulecule_base.app_path if not self.dryrun: if self._fromImage(): self.nulecule_base.pullApp() self._copyFromContainer(self.nulecule_base.app) mainfile_dir = self.utils.getTmpAppDir() current_app_id = None if os.path.isfile(self.nulecule_base.getMainfilePath()): current_app_id = Utils.getAppId(self.nulecule_base.getMainfilePath()) printStatus("Loading app_id %s ." % current_app_id) if current_app_id: tmp_mainfile_path = os.path.join(mainfile_dir, MAIN_FILE) self.nulecule_base.loadMainfile(tmp_mainfile_path) logger.debug("%s path for pulled image: %s", MAIN_FILE, tmp_mainfile_path) if current_app_id != self.nulecule_base.app_id: msg = ("You are trying to overwrite existing app %s with " "app %s - clear or change current directory." % (current_app_id, self.nulecule_base.app_id)) raise Exception(msg) elif self._fromImage(): logger.warning("Using DRY-RUN together with install from image " "may result in unexpected behaviour") if self.nulecule_base.update or \ (not self.dryrun and not os.path.exists(self.nulecule_base.getMainfilePath())): if self._fromImage(): self._populateApp() else: logger.info("Copying content of directory %s to %s", self.nulecule_base.app_path, self.nulecule_base.target_path) self._populateApp(src=self.nulecule_base.app_path) mainfile_path = os.path.join(self.nulecule_base.target_path, MAIN_FILE) if not self.nulecule_base.mainfile_data: self.nulecule_base.loadMainfile(mainfile_path) logger.debug("App ID: %s", self.nulecule_base.app_id) self.nulecule_base.checkSpecVersion() printStatus("Checking all artifacts") self.nulecule_base.checkAllArtifacts() printStatus("Loading Nulecule file.") if not self.nulecule_base.nodeps: logger.info("Installing dependencies for %s", self.nulecule_base.app_id) self.answers_file_values = self._installDependencies() printStatus("All dependencies installed successfully.") logger.debug(self.answers_file_values) answerContent = self.nulecule_base.loadAnswers(self.answers_file_values) logger.debug(self.nulecule_base.answers_data) if self.nulecule_base.write_sample_answers: self.nulecule_base.writeAnswersSample() printAnswerFile(json.dumps(answerContent)) printStatus("Install Successful.") return None def _installDependencies(self): values = {} for graph_item in self.nulecule_base.mainfile_data["graph"]: component = graph_item.get("name") if not component: raise ValueError("Component name missing in graph") if not self.utils.isExternal(graph_item): values[component] = self.nulecule_base.getValues( component, skip_asking=True) logger.debug("Component %s is part of the app", component) logger.debug("Values: %s", values) continue logger.info("Component %s is external dependency", component) image_name = self.utils.getSourceImage(graph_item) component_path = self.utils.getExternalAppDir(component) mainfile_component_path = os.path.join(component_path, MAIN_FILE) logger.debug("Component path: %s", component_path) if not os.path.isfile(mainfile_component_path) or self.nulecule_base.update: printStatus("Pulling %s ..." % image_name) component_app = Install( self.nulecule_base.answers_data, image_name, self.nulecule_base.nodeps, self.nulecule_base.update, component_path, self.dryrun) component_app.install() values = Utils.update(values, component_app.answers_file_values) printStatus("Component %s installed successfully." % component) logger.debug("Component installed into %s", component_path) else: printStatus("Component %s already installed." % component) logger.info("Component %s already exists at %s - remove the directory " "or use --update option" % (component, component_path)) return values
class Run(object): debug = False dryrun = False nulecule_base = None answers_data = {GLOBAL_CONF: {}} tmpdir = None answers_file = None provider = DEFAULT_PROVIDER installed = False plugins = [] update = False app_path = None target_path = None app_id = None app = None answers_output = None kwargs = None def __init__( self, answers, APP, dryrun=False, debug=False, stop=False, answers_format=ANSWERS_FILE_SAMPLE_FORMAT, **kwargs): self.debug = debug self.dryrun = dryrun self.stop = stop self.kwargs = kwargs self.cli_provider = None if "answers_output" in kwargs: self.answers_output = kwargs["answers_output"] if "cli_provider" in kwargs: self.cli_provider = kwargs["cli_provider"] if os.environ and "IMAGE" in os.environ: self.app_path = APP APP = os.environ["IMAGE"] del os.environ["IMAGE"] elif "image" in kwargs: logger.warning("Setting image to %s" % kwargs["image"]) self.app_path = APP APP = kwargs["image"] del kwargs["image"] self.kwargs = kwargs if APP and os.path.exists(APP): self.app_path = APP else: if not self.app_path: self.app_path = os.getcwd() install = Install( answers, APP, dryrun=dryrun, target_path=self.app_path, answers_format=answers_format) install.install() printStatus("Install Successful.") self.nulecule_base = Nulecule_Base( target_path=self.app_path, dryrun=dryrun, file_format=answers_format, cli_provider=self.cli_provider) if "ask" in kwargs: self.nulecule_base.ask = kwargs["ask"] workdir = None if "workdir" in kwargs: workdir = kwargs["workdir"] self.utils = Utils(self.app_path, workdir) if "workdir" not in kwargs: kwargs["workdir"] = self.utils.workdir self.answers_file = answers self.plugin = Plugin() self.plugin.load_plugins() def _dispatchGraph(self): if "graph" not in self.nulecule_base.mainfile_data: printErrorStatus("Graph not specified in %s." % MAIN_FILE) raise Exception("Graph not specified in %s" % MAIN_FILE) for graph_item in self.nulecule_base.mainfile_data["graph"]: component = graph_item.get("name") if not component: printErrorStatus("Component name missing in graph.") raise ValueError("Component name missing in graph") if self.utils.isExternal(graph_item): self.kwargs["image"] = self.utils.getSourceImage(graph_item) component_run = Run(self.answers_file, self.utils.getExternalAppDir( component), self.dryrun, self.debug, self.stop, **self.kwargs) ret = component_run.run() if self.answers_output: self.nulecule_base.loadAnswers(ret) else: self._processComponent(component, graph_item) def _applyTemplate(self, data, component): template = Template(data) if self.stop: config = self.nulecule_base.getValues(component, skip_asking=True) else: config = self.nulecule_base.getValues(component) logger.debug("Config: %s ", config) output = None while not output: try: logger.debug(config) output = template.substitute(config) except KeyError as ex: name = ex.args[0] logger.debug( "Artifact contains unknown parameter %s, asking for it", name) try: config[name] = self.utils.askFor( name, {"description": "Missing parameter '%s', provide the value or fix your %s" % ( name, MAIN_FILE)}) except EOFError: raise Exception("Artifact contains unknown parameter %s" % name) if not len(config[name]): printErrorStatus("Artifact contains unknown parameter %s." % name) raise Exception("Artifact contains unknown parameter %s" % name) self.nulecule_base.loadAnswers({component: {name: config[name]}}) return output def _processArtifacts(self, component, provider, provider_name=None): if not provider_name: provider_name = str(provider) artifacts = self.nulecule_base.getArtifacts(component) artifact_provider_list = [] if provider_name not in artifacts: msg = "Data for provider \"%s\" are not part of this app" % provider_name raise Exception(msg) dst_dir = os.path.join(self.utils.workdir, component) data = None for artifact in artifacts[provider_name]: if "inherit" in artifact: logger.debug("Inheriting from %s", artifact["inherit"]) for item in artifact["inherit"]: inherited_artifacts, _ = self._processArtifacts( component, provider, item) artifact_provider_list += inherited_artifacts continue artifact_path = self.utils.sanitizePath(artifact) data = provider.loadArtifact(os.path.join(self.app_path, artifact_path)) logger.debug("Templating artifact %s/%s", self.app_path, artifact_path) data = self._applyTemplate(data, component) artifact_dst = os.path.join(dst_dir, artifact_path) provider.saveArtifact(artifact_dst, data) artifact_provider_list.append(artifact_path) return artifact_provider_list, dst_dir def _processComponent(self, component, graph_item): logger.debug( "Processing component '%s' and graph item '%s'", component, graph_item) provider_class = self.plugin.getProvider(self.nulecule_base.provider) dst_dir = os.path.join(self.utils.workdir, component) if self.stop: component_values = self.nulecule_base.getValues(component, skip_asking=True) else: component_values = self.nulecule_base.getValues(component) provider = provider_class(component_values, dst_dir, self.dryrun) if provider: printStatus("Deploying component %s ..." % component) logger.info("Using provider %s for component %s", self.nulecule_base.provider, component) else: raise Exception("Something is broken - couldn't get the provider") provider.artifacts, dst_dir = self._processArtifacts(component, provider) try: provider.init() if self.stop: provider.undeploy() else: provider.deploy() except ProviderFailedException as ex: printErrorStatus(ex) logger.error(ex) raise def run(self): self.nulecule_base.loadMainfile( os.path.join(self.nulecule_base.target_path, MAIN_FILE)) self.nulecule_base.checkSpecVersion() self.nulecule_base.loadAnswers(self.answers_file) self.nulecule_base.checkAllArtifacts() self._dispatchGraph() # Think about this a bit more probably - it's (re)written for all components... if self.answers_output: self.nulecule_base.writeAnswers(self.answers_output) return self.nulecule_base.answers_data return None
class Install(object): dryrun = False params = None answers_file = None docker_cli = "docker" def __init__(self, answers, APP, nodeps=False, update=False, target_path=None, dryrun=False, **kwargs): self.dryrun = dryrun self.kwargs = kwargs app = APP #FIXME self.nulecule_base = Nulecule_Base(nodeps, update, target_path, dryrun) if os.path.exists(app): logger.info("App path is %s, will be populated to %s", app, target_path) app = self._loadApp(app) else: logger.info("App name is %s, will be populated to %s", app, target_path) if not target_path: if self.nulecule_base.app_path: self.nulecule_base.target_path = self.nulecule_base.app_path else: self.nulecule_base.target_path = os.getcwd() self.utils = Utils(self.nulecule_base.target_path) self.nulecule_base.app = app self.answers_file = answers self.docker_cli = Utils.getDockerCli(self.dryrun) def _loadApp(self, app_path): self.nulecule_base.app_path = app_path if not os.path.basename(app_path) == MAIN_FILE: app_path = os.path.join(app_path, MAIN_FILE) mainfile_data = self.nulecule_base.loadMainfile(app_path) app = os.environ["IMAGE"] if "IMAGE" in os.environ else mainfile_data[ "id"] logger.debug("Setting path to %s", self.nulecule_base.app_path) return app def _copyFromContainer(self, image): image = self.nulecule_base.getImageURI(image) name = "%s-%s" % (self.utils.getComponentName(image), ''.join( random.sample(string.letters, 6))) logger.debug("Creating a container with name %s", name) create = [self.docker_cli, "create", "--name", name, image, "nop"] subprocess.call(create) cp = [ self.docker_cli, "cp", "%s:/%s" % (name, APP_ENT_PATH), self.utils.tmpdir ] logger.debug(cp) if not subprocess.call(cp): logger.debug("Application entity data copied to %s", self.utils.tmpdir) rm = [self.docker_cli, "rm", name] subprocess.call(rm) def _populateApp(self, src=None, dst=None): logger.info("Copying app %s", self.utils.getComponentName(self.nulecule_base.app)) if not src: src = os.path.join(self.utils.tmpdir, APP_ENT_PATH) if not dst: dst = self.nulecule_base.target_path distutils.dir_util.copy_tree(src, dst, update=(not self.nulecule_base.update)) def _fromImage(self): return not self.nulecule_base.app_path or self.nulecule_base.target_path == self.nulecule_base.app_path def install(self): self.nulecule_base.loadAnswers(self.answers_file) mainfile_dir = self.nulecule_base.app_path if not self.dryrun: if self._fromImage(): self.nulecule_base.pullApp() self._copyFromContainer(self.nulecule_base.app) mainfile_dir = self.utils.getTmpAppDir() current_app_id = None if os.path.isfile(self.nulecule_base.getMainfilePath()): current_app_id = Utils.getAppId( self.nulecule_base.getMainfilePath()) if current_app_id: tmp_mainfile_path = os.path.join(mainfile_dir, MAIN_FILE) self.nulecule_base.loadMainfile(tmp_mainfile_path) logger.debug("%s path for pulled image: %s", MAIN_FILE, tmp_mainfile_path) if current_app_id != self.nulecule_base.app_id: raise Exception( "You are trying to overwrite existing app %s with app %s - clear or change current directory." % (current_app_id, self.nulecule_base.app_id)) elif self._fromImage(): logger.warning( "Using DRY-RUN together with install from image may result in unexpected behaviour" ) if self.nulecule_base.update or ( not self.dryrun and not os.path.exists(self.nulecule_base.getMainfilePath())): if self._fromImage(): self._populateApp() else: logger.info("Copying content of directory %s to %s", self.nulecule_base.app_path, self.nulecule_base.target_path) self._populateApp(src=self.nulecule_base.app_path) mainfile_path = os.path.join(self.nulecule_base.target_path, MAIN_FILE) if not self.nulecule_base.mainfile_data: self.nulecule_base.loadMainfile(mainfile_path) logger.debug("App ID: %s", self.nulecule_base.app_id) self.nulecule_base.checkSpecVersion() self.nulecule_base.checkAllArtifacts() values = {} if not self.nulecule_base.nodeps: logger.info("Installing dependencies for %s", self.nulecule_base.app_id) values = self._installDependencies() logger.debug(values) self.nulecule_base.loadAnswers(values) logger.debug(self.nulecule_base.answers_data) if self.nulecule_base.write_sample_answers: self.nulecule_base.writeAnswersSample() return values def _installDependencies(self): values = {} for graph_item in self.nulecule_base.mainfile_data["graph"]: component = graph_item.get("name") if not component: raise ValueError("Component name missing in graph") if not self.utils.isExternal(graph_item): values[component] = self.nulecule_base.getValues( component, skip_asking=True) logger.debug("Component %s is part of the app", component) logger.debug("Values: %s", values) continue logger.info("Component %s is external dependency", component) image_name = self.utils.getSourceImage(graph_item) component_path = self.utils.getExternalAppDir(component) mainfile_component_path = os.path.join(component_path, MAIN_FILE) logger.debug("Component path: %s", component_path) if not os.path.isfile( mainfile_component_path) or self.nulecule_base.update: logger.info("Pulling %s", image_name) component_app = Install(self.nulecule_base.answers_data, image_name, self.nulecule_base.nodeps, self.nulecule_base.update, component_path, self.dryrun) values = Utils.update(values, component_app.install()) logger.info("Component installed into %s", component_path) else: logger.info( "Component %s already exists at %s - remove the directory or use --update option", component, component_path) return values
class Install(object): dryrun = False params = None answers_file = None def __init__(self, answers, APP, nodeps = False, update = False, target_path = None, dryrun = False, **kwargs): self.dryrun = dryrun self.kwargs = kwargs app = APP #FIXME self.nulecule_base = Nulecule_Base(nodeps, update, target_path) if os.path.exists(app): logger.info("App path is %s, will be populated to %s", app, target_path) app = self._loadApp(app) else: logger.info("App name is %s, will be populated to %s", app, target_path) if not target_path: if self.nulecule_base.app_path: self.nulecule_base.target_path = self.nulecule_base.app_path else: self.nulecule_base.target_path = os.getcwd() self.utils = Utils(self.nulecule_base.target_path) self.nulecule_base.app = app self.answers_file = answers def _loadApp(self, app_path): self.nulecule_base.app_path = app_path if not os.path.basename(app_path) == MAIN_FILE: app_path = os.path.join(app_path, MAIN_FILE) mainfile_data = self.nulecule_base.loadMainfile(app_path) app = os.environ["IMAGE"] if "IMAGE" in os.environ else mainfile_data["id"] logger.debug("Setting path to %s", self.nulecule_base.app_path) return app def _copyFromContainer(self, image): image = self.nulecule_base.getImageURI(image) name = "%s-%s" % (self.utils.getComponentName(image), ''.join(random.sample(string.letters, 6))) logger.debug("Creating a container with name %s", name) create = ["docker", "create", "--name", name, image, "nop"] subprocess.call(create) cp = ["docker", "cp", "%s:/%s" % (name, APP_ENT_PATH), self.utils.tmpdir] logger.debug(cp) if not subprocess.call(cp): logger.debug("Application entity data copied to %s", self.utils.tmpdir) rm = ["docker", "rm", name] subprocess.call(rm) def _populateApp(self, src = None, dst = None): logger.info("Copying app %s", self.utils.getComponentName(self.nulecule_base.app)) if not src: src = os.path.join(self.utils.tmpdir, APP_ENT_PATH) if not dst: dst = self.nulecule_base.target_path distutils.dir_util.copy_tree(src, dst, update=(not self.nulecule_base.update)) def install(self): self.nulecule_base.loadAnswers(self.answers_file) if self.nulecule_base.app_path and not self.nulecule_base.target_path == self.nulecule_base.app_path: logger.info("Copying content of directory %s to %s", self.nulecule_base.app_path, self.nulecule_base.target_path) self._populateApp(src=self.nulecule_base.app_path) mainfile_path = os.path.join(self.nulecule_base.target_path, MAIN_FILE) if not self.nulecule_base.app_path and (self.nulecule_base.update or not os.path.exists(mainfile_path)): self.nulecule_base.pullApp() self._copyFromContainer(self.nulecule_base.app) mainfile_path = os.path.join(self.utils.getTmpAppDir(), MAIN_FILE) logger.debug("%s path for pulled image: %s", MAIN_FILE, mainfile_path) self.nulecule_base.loadMainfile(mainfile_path) logger.debug("App ID: %s", self.nulecule_base.app_id) self._populateApp() else: logger.info("Component data exist in %s, skipping population...", self.nulecule_base.target_path) if not self.nulecule_base.mainfile_data: self.nulecule_base.loadMainfile(mainfile_path) self.nulecule_base.checkSpecVersion() self.nulecule_base.checkAllArtifacts() values = {} if not self.nulecule_base.nodeps: logger.info("Installing dependencies for %s", self.nulecule_base.app_id) values = self._installDependencies() logger.debug(values) self.nulecule_base.loadAnswers(values) logger.debug(self.nulecule_base.answers_data) if self.nulecule_base.write_sample_answers: self.nulecule_base.writeAnswersSample() return values def _installDependencies(self): values = {} for graph_item in self.nulecule_base.mainfile_data["graph"]: component = graph_item.get("name") if not component: raise ValueError("Component name missing in graph") if not self.utils.isExternal(graph_item): values[component] = self.nulecule_base.getValues(component, skip_asking = True) logger.debug("Component %s is part of the app", component) logger.debug("Values: %s", values) continue logger.info("Component %s is external dependency", component) image_name = self.utils.getSourceImage(graph_item) component_path = self.utils.getExternalAppDir(component) mainfile_component_path = os.path.join(component_path, MAIN_FILE) logger.debug("Component path: %s", component_path) if not os.path.isfile(mainfile_component_path) or self.nulecule_base.update: logger.info("Pulling %s", image_name) component_app = Install(self.nulecule_base.answers_data, image_name, self.nulecule_base.nodeps, self.nulecule_base.update, component_path, self.dryrun) values = Utils.update(values, component_app.install()) logger.info("Component installed into %s", component_path) else: logger.info("Component %s already exists at %s - remove the directory or use --update option", component, component_path) return values