def __init__(self, config_path=XprConfigParser.DEFAULT_CONFIG_PATH): super().__init__() self.config = XprConfigParser(config_path)["packages_setup"] self.logger = XprLogger() dependency_config_file = self.config[self.DEPENDENCY_SECTION][ self.DEPENDENCY_CONFIG_FILE] if not os.path.exists(dependency_config_file): self.logger.error(("Unable to find the dependency js" "file at the mentioned path")) raise PackageFailedException("Invalid dependency config file") try: with open(dependency_config_file) as config_fs: dependency_config = json.load(config_fs) except EnvironmentError as err: self.logger.fatal(err) raise PackageFailedException("Invalid config file") self.graph = nx.DiGraph() edges = list() for key in dependency_config: for value in dependency_config[key]: edges.append((key, value)) self.graph.add_edges_from(edges) if not nx.is_directed_acyclic_graph(self.graph): self.logger.fatal(("Unable to handle dependencies due to cyclic " "loop")) self.graph = None raise PackageFailedException("Cyclic Dependency Found")
def setup_kong(self): """ Start Kong service which provide Admin and Proxy API """ self.logger.info("Creating kong docker image") try: docker_client = docker.from_env() docker_client.containers.run( image="kong:1.2.1", detach=True, name=self.SERVICE_NAME, network=self.NETWORK_NAME, ports={"8000/tcp": "8000", "8443/tcp": "8443", "8001/tcp": "8001", "8444/tcp": "8444"}, environment=["KONG_DATABASE=cassandra", f"KONG_PG_HOST={self.DATABASE_NAME}", f"KONG_CASSANDRA_CONTACT_POINTS={self.DATABASE_NAME}", "KONG_PROXY_ACCESS_LOG=/dev/stdout", "KONG_ADMIN_ACCESS_LOG=/dev/stdout", "KONG_PROXY_ERROR_LOG=/dev/stderr", "KONG_ADMIN_ERROR_LOG=/dev/stderr", "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl"] ) except (docker.errors.NotFound, docker.errors.APIError): error_msg = "Kong service creation failed" self.logger.error(error_msg) raise PackageFailedException(error_msg) self.logger.info("Kong service has been created")
def setup_kong_db(self): """ Create database docker for kong """ self.logger.info("Creating database docker for kong") try: docker_client = docker.from_env() mount_path = self.config[self.CONFIG_KONG_KEY][ self.CONFIG_MOUNT_PATH] docker_client.containers.run( image="cassandra:3", name=self.DATABASE_NAME, detach=True, network=self.NETWORK_NAME, volumes={mount_path: {'bind': '/var/lib/cassandra', 'mode': 'rw'}}, ports={"9042/tcp": "9042"}) self.logger.info( "Cassandra docker is booting up. Waiting 60s for warm up") time.sleep(60) self.logger.info("Migrating database") docker_client.containers.run( image="kong:1.2.1", remove=True, network=self.NETWORK_NAME, environment=["KONG_DATABASE=cassandra", f"KONG_PG_HOST={self.DATABASE_NAME}", f"KONG_CASSANDRA_CONTACT_POINTS={self.DATABASE_NAME}"], command=["kong", "migrations", "bootstrap"]) self.logger.info("Migration completed") except (docker.errors.APIError, docker.errors.NotFound): error_msg = "Database Creation Failed" self.logger.error(error_msg) raise PackageFailedException(error_msg) self.logger.info("Database docker for kong created")
def run(self, package_to_install: str, execution_type: ExecutionType, parameters: dict = None): """ Perform provided execution type on the given package name Args: parameters(dict): Additional parameters package_to_install(str): name of the package to install. Must match the supported package names execution_type(ExecutionType): Type of execution """ if not self.package_dependency.check_if_supported(package_to_install): self.logger.error( "Unsupported Package Name : {}".format(package_to_install)) return False dependency_list = self.package_dependency.get_dependency( package_to_install) self.logger.info(dependency_list) response = self.execute_recursive(dependency_list, 0, execution_type, parameters=parameters) if not response: raise PackageFailedException("Package installation failed!!") self.logger.info( "{} installed successfully".format(package_to_install)) return True
def uninstall(self, **kwargs): """ Remove docker distribution Returns: True, if setup is successful. False Otherwise Raises: PackageFailedException """ """ cd $PWD/config/harbor docker-compose up -d """ harbor_tmp_dir = self.config[self.CONFIG_SECTION][ self.HARBOR_TMP_FOLDER] harbor_dir = os.path.join(harbor_tmp_dir, "harbor") try: os.chdir(harbor_dir) except OSError: self.logger("{} not found.".format(harbor_dir)) raise PackageFailedException( "{} not found. Required for stopping".format(harbor_dir)) self.execute_command("/usr/local/bin/docker-compose up -d") return True
def execute_command_with_output(self, command): self.logger.info(f"Running command: {command}") try: return self.executor.execute_with_output(command) except CommandExecutionFailedException: self.logger.error("Command failed {}".format(command)) raise PackageFailedException( "Base Ubuntu Package Installation Failed")
def setup_kong_docker_network(self): """ Create network for Kong """ self.logger.info("Creating network for kong") try: docker_client = docker.from_env() docker_client.networks.create(self.NETWORK_NAME) except docker.errors.APIError: self.logger.error("Network Creation Failed") raise PackageFailedException(f"Docker Network Creation Failed") self.logger.info("Network Creation completed")
def get_dependency(self, package_name: str) -> list: """ List of dependencies Args: package_name(str): Name of the package Returns: list: List of dependencies required for the package_name installation """ if not self.check_if_supported(package_name=package_name): self.logger.error( "{} package not present in config".format(package_name)) return list() self.logger.info(("Running Topological sorting on " "Package Dependency Graph")) try: topological_sort_list = list( reversed(list(nx.topological_sort(self.graph)))) except nx.NetworkXError as error: self.logger.error(error) raise PackageFailedException("Topological sort is defined for " "directed graphs only") except nx.NetworkXUnfeasible as error: self.logger.error(error) raise PackageFailedException( "Not a directed acyclic graph (DAG) " "and hence no topological sort exists") descendants = nx.descendants(self.graph, package_name) dependent_packages = [] for pkg in topological_sort_list: if pkg in descendants and pkg != self.NONE_PACKAGE: dependent_packages.append(pkg) if package_name != self.NONE_PACKAGE: dependent_packages.append(package_name) return dependent_packages
def install(self, **kwargs): """ Sets up docker distribution in a VM Returns: True, if setup is successful. False Otherwise Raises: PackageFailedException """ current_directory = os.getcwd() harbor_folder = self.config[self.CONFIG_SECTION][self.HARBOR_TMP_FOLDER] try: if not os.path.exists(harbor_folder): os.makedirs(harbor_folder) except OSError: self.logger.error("Can not create directory") raise PackageFailedException("Harbor temp folder can't be created") self.execute_command( "wget https://storage.googleapis.com/harbor-releases/" "release-1.7.0/harbor-online-installer-v1.7.5.tgz -O " "{}/harbor.tgz".format(harbor_folder)) os.chdir(harbor_folder) self.execute_command("tar xvf harbor.tgz".format()) extracted_folder = os.path.join(harbor_folder, "harbor") try: os.chdir(extracted_folder) except OSError: self.logger.error("Harbor Folder not found") raise PackageFailedException("Harbor Folder not found") os.chdir(current_directory) shutil.copy(self.config[self.CONFIG_SECTION][self.HARBOR_CFG_FILE], extracted_folder) shutil.copy(self.config[self.CONFIG_SECTION][self.HARBOR_COMPOSE_FILE], extracted_folder) os.chdir(extracted_folder) self.execute_command("/bin/bash install.sh") os.chdir(current_directory) return True
def status(self, **kwargs): """ Checks status of the installed package Returns: True, if setup is successful. False Otherwise Raises: PackageFailedException """ status_command = "dpkg -s {}".format(' '.join( self.config[self.BASE_UBUNTU_SECTION][self.PKG_LIST_KEY])) try: (code, _, _) = self.executor.execute_with_output(status_command) # Check all packages are present if code == 0: return True except CommandExecutionFailedException: self.logger.error("Command failed {}".format(status_command)) raise PackageFailedException( "Base Ubuntu Package Installation Failed") return False
def main(): parser = parse_arguments() args = parser.parse_args() package_manager = PackageManager(args.conf) if args.type and args.parameters: # Check if args.parameters is a valid dict try: parameters = ast.literal_eval(args.parameters) except (ValueError, TypeError): raise PackageFailedException( "Parameter provided is not valid dict") package_manager.run(package_to_install=str(args.package), execution_type=args.type, parameters=parameters) elif args.type: package_manager.run(package_to_install=str(args.package), execution_type=args.type) elif args.list: package_list = package_manager.list() print("Supported Package List : {}".format(package_list)) else: parser.print_usage()