397 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			397 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
# you may not use this file except in compliance with the License.
 | 
						|
# You may obtain a copy of the License at
 | 
						|
#
 | 
						|
#    http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
#
 | 
						|
# Unless required by applicable law or agreed to in writing, software
 | 
						|
# distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 | 
						|
# implied.
 | 
						|
# See the License for the specific language governing permissions and
 | 
						|
# limitations under the License.
 | 
						|
 | 
						|
import copy
 | 
						|
import warnings
 | 
						|
import json
 | 
						|
 | 
						|
import otc_metadata.data
 | 
						|
 | 
						|
__all__ = ["Services"]
 | 
						|
 | 
						|
BUILTIN_DATA = otc_metadata.data.read_data("services.yaml")
 | 
						|
 | 
						|
 | 
						|
def _normalize_type(service_type):
 | 
						|
    if service_type:
 | 
						|
        return service_type.replace("_", "-")
 | 
						|
 | 
						|
 | 
						|
class Services(object):
 | 
						|
    """Encapsulation of the OTC Services data"""
 | 
						|
 | 
						|
    def __init__(self):
 | 
						|
        self._service_data = BUILTIN_DATA
 | 
						|
 | 
						|
    def _sort_data(self):
 | 
						|
        # Sort every doc item by key
 | 
						|
        sorted_docs = []
 | 
						|
        for doc in self._service_data["documents"]:
 | 
						|
            sorted_docs.append(dict(sorted(doc.items(), key=lambda kv: kv[0])))
 | 
						|
 | 
						|
        # sort docs list by <service_type>_<title>
 | 
						|
        self._service_data["documents"] = sorted(
 | 
						|
            sorted_docs,
 | 
						|
            key=lambda x: f"{x.get('service_type')}{x.get('title')}",
 | 
						|
        )
 | 
						|
        # sort services by <service_type>_<service_title>
 | 
						|
        self._service_data["services"] = sorted(
 | 
						|
            self._service_data["services"],
 | 
						|
            key=lambda x: f"{x.get('service_type')}{x.get('service_title')}",
 | 
						|
        )
 | 
						|
        # sort repositories by <service_type>
 | 
						|
        self._service_data["repositories"] = sorted(
 | 
						|
            self._service_data["repositories"],
 | 
						|
            key=lambda x: f"{x.get('service_type')}",
 | 
						|
        )
 | 
						|
        # sort service categories by <name>_<title>
 | 
						|
        self._service_data["service_categories"] = sorted(
 | 
						|
            self._service_data["service_categories"],
 | 
						|
            key=lambda x: f"{x.get('name')}{x.get('title')}",
 | 
						|
        )
 | 
						|
        other = {'name': 'other', 'title': 'Other'}
 | 
						|
        if other in self._service_data["service_categories"]:
 | 
						|
            self._service_data["service_categories"].remove(other)
 | 
						|
            self._service_data["service_categories"].append(other)
 | 
						|
 | 
						|
    def _rewrite_data(self):
 | 
						|
        otc_metadata.data.rewrite_data("services.yaml", self._service_data)
 | 
						|
 | 
						|
    @property
 | 
						|
    def all_services(self):
 | 
						|
        "Service Categories data listing."
 | 
						|
        return copy.deepcopy(self._service_data["services"])
 | 
						|
 | 
						|
    @property
 | 
						|
    def all_docs(self):
 | 
						|
        "Service Docs data listing."
 | 
						|
        return copy.deepcopy(self._service_data["documents"])
 | 
						|
    
 | 
						|
    @property
 | 
						|
    def all_repositories(self):
 | 
						|
        "Service Repositories data listing."
 | 
						|
        return copy.deepcopy(self._service_data["repositories"])
 | 
						|
 | 
						|
    @property
 | 
						|
    def service_dict(self):
 | 
						|
        "Service Docs data listing."
 | 
						|
        res = dict()
 | 
						|
        for srv in self.all_services:
 | 
						|
            res[srv["service_type"]] = copy.deepcopy(srv)
 | 
						|
        return res
 | 
						|
 | 
						|
    @property
 | 
						|
    def service_categories(self):
 | 
						|
        """List services categories"""
 | 
						|
        res = []
 | 
						|
        for cat in self._service_data["service_categories"]:
 | 
						|
            res.append(copy.deepcopy(cat))
 | 
						|
        return res
 | 
						|
 | 
						|
    def services_by_category(self, category, environment=None):
 | 
						|
        """List services matching category"""
 | 
						|
        res = []
 | 
						|
        for srv in self.all_services:
 | 
						|
            if environment:
 | 
						|
                if "environment" in srv and srv["environment"] != environment:
 | 
						|
                    continue
 | 
						|
            if srv["service_category"] == category:
 | 
						|
                for repositories in self.all_repositories:
 | 
						|
                    if repositories["service_type"] == srv["service_type"]:
 | 
						|
                        srv["repositories"] = repositories["repositories"]
 | 
						|
                res.append(copy.deepcopy(srv))
 | 
						|
        return res
 | 
						|
 | 
						|
    def services_with_docs_by_category(self, category, environment=None):
 | 
						|
        """Retrieve service category docs data
 | 
						|
 | 
						|
        :param str category: Optional Category filter
 | 
						|
        :param str env: Optional service environment. Influeces "repository"
 | 
						|
            field
 | 
						|
        """
 | 
						|
        res = dict()
 | 
						|
        services = self.service_dict
 | 
						|
        for doc in self.all_docs:
 | 
						|
            cat = doc["service_type"]
 | 
						|
            service = services.get(cat)
 | 
						|
            if not service:
 | 
						|
                warnings.warn("No Service defition of type %s" % (cat))
 | 
						|
                continue
 | 
						|
            if category and service["service_category"] != category:
 | 
						|
                continue
 | 
						|
            res.setdefault(cat, service)
 | 
						|
            res_doc = copy.deepcopy(doc)
 | 
						|
            if environment:
 | 
						|
                if "environment" in doc and doc["environment"] != environment:
 | 
						|
                    continue
 | 
						|
            for repositories in self.all_repositories:
 | 
						|
                if repositories["service_type"] == service["service_type"]:
 | 
						|
                    res["repositories"] = repositories["repositories"]
 | 
						|
            res[cat].setdefault("docs", [])
 | 
						|
            res[cat]["docs"].append(res_doc)
 | 
						|
        return res
 | 
						|
 | 
						|
    def service_types_with_doc_types(self, cloud_environment, environment=None):
 | 
						|
        """Retrieve type and title from services and corresponding docs.
 | 
						|
            As well as a list of all available doc types with title.
 | 
						|
 | 
						|
        :param str environment: Optional service environment.
 | 
						|
        """
 | 
						|
        service_list = []
 | 
						|
        docs = []
 | 
						|
 | 
						|
        for service in self.all_services:
 | 
						|
            if "environment" in service:
 | 
						|
                if service["environment"] != environment:
 | 
						|
                    continue
 | 
						|
            cloud_environment_service_check = False
 | 
						|
            for cloud_environment_service in service["cloud_environments"]:
 | 
						|
                if cloud_environment_service["name"] == cloud_environment:
 | 
						|
                    cloud_environment_service_check = True
 | 
						|
                    break
 | 
						|
            if cloud_environment_service_check is False:
 | 
						|
                continue
 | 
						|
            if not service["service_title"]:
 | 
						|
                continue
 | 
						|
            if not service["service_type"]:
 | 
						|
                continue
 | 
						|
 | 
						|
            doc_list = []
 | 
						|
            for doc in self.all_docs:
 | 
						|
                if "environment" in doc:
 | 
						|
                    if doc["environment"] != environment:
 | 
						|
                        continue
 | 
						|
                cloud_environment_doc_check = False
 | 
						|
                for cloud_environment_doc in doc["cloud_environments"]:
 | 
						|
                    if cloud_environment_doc["name"] == cloud_environment:
 | 
						|
                        cloud_environment_doc_check = True
 | 
						|
                        break
 | 
						|
                if cloud_environment_doc_check is False:
 | 
						|
                    continue
 | 
						|
                if doc["service_type"] == service["service_type"]:
 | 
						|
                    doc_list.append({
 | 
						|
                        "title": doc["title"],
 | 
						|
                        "type": doc["type"]
 | 
						|
                    })
 | 
						|
 | 
						|
                new_doc = {
 | 
						|
                    "type": doc["type"],
 | 
						|
                    "title": doc["title"]
 | 
						|
                }
 | 
						|
                type_exists = any(
 | 
						|
                    doc_dict["type"] == new_doc["type"] for doc_dict in docs
 | 
						|
                )
 | 
						|
                if not type_exists:
 | 
						|
                    docs.append(new_doc)
 | 
						|
 | 
						|
            service_list.append({
 | 
						|
                "service_title": service["service_title"],
 | 
						|
                "service_type": service["service_type"],
 | 
						|
                "docs": doc_list
 | 
						|
            })
 | 
						|
 | 
						|
        res = {
 | 
						|
            "services": service_list,
 | 
						|
            "docs": docs
 | 
						|
        }
 | 
						|
 | 
						|
        return res
 | 
						|
 | 
						|
    def docs_by_service_category(self, category, environment=None):
 | 
						|
        """List docs matching category
 | 
						|
 | 
						|
        :param str category: Category name
 | 
						|
        :param str environment: Optional service environment. Influeces "repository"
 | 
						|
            field
 | 
						|
        """
 | 
						|
        res = []
 | 
						|
        services = self.service_dict
 | 
						|
        for doc in self.all_docs:
 | 
						|
            cat = doc["service_type"]
 | 
						|
            service = services.get(cat)
 | 
						|
            if not service:
 | 
						|
                warnings.warn("No Service defition of type %s" % (cat))
 | 
						|
                continue
 | 
						|
            if service["service_category"] == category:
 | 
						|
                for repositories in self.all_repositories:
 | 
						|
                    if repositories["service_type"] == service["service_type"]:
 | 
						|
                        res_doc = copy.deepcopy(doc)
 | 
						|
                        res_doc["repositories"] = repositories["repositories"]
 | 
						|
                        res_doc.update(**service)
 | 
						|
 | 
						|
                        # Get the cloud environments from the document instead of service
 | 
						|
                        res_doc["cloud_environments"] = doc["cloud_environments"]
 | 
						|
                        if environment:
 | 
						|
                            repo_env_filter = []
 | 
						|
                            for repo in repositories["repositories"]:
 | 
						|
                                if repo["environment"] == environment:
 | 
						|
                                    repo_env_filter.append(repo)
 | 
						|
                            res_doc["repositories"] = repo_env_filter
 | 
						|
                        res.append(res_doc)
 | 
						|
        return res
 | 
						|
 | 
						|
    def docs_by_service_type(self, service_type):
 | 
						|
        """List documents of the service
 | 
						|
 | 
						|
        :param str service_type: Service type
 | 
						|
        :returns: generator for documents
 | 
						|
        """
 | 
						|
        for doc in self.all_docs:
 | 
						|
            if doc["service_type"] != service_type:
 | 
						|
                continue
 | 
						|
            yield copy.deepcopy(doc)
 | 
						|
 | 
						|
    def all_docs_full(self, environment):
 | 
						|
        """Return list or documents with full service data"""
 | 
						|
        res = []
 | 
						|
        services = self.service_dict
 | 
						|
        for doc in self.all_docs:
 | 
						|
            cat = doc["service_type"]
 | 
						|
            service = services.get(cat)
 | 
						|
            if not service:
 | 
						|
                warnings.warn("No Service defition of type %s" % (cat))
 | 
						|
                continue
 | 
						|
            
 | 
						|
            for repositories in self.all_repositories:
 | 
						|
                if repositories["service_type"] == service["service_type"]:
 | 
						|
                    res_doc = copy.deepcopy(doc)
 | 
						|
                    res_doc["repositories"] = repositories["repositories"]
 | 
						|
                    res_doc.update(**service)
 | 
						|
 | 
						|
                    # Get the cloud environments from the document instead of service
 | 
						|
                    res_doc["cloud_environments"] = doc["cloud_environments"]
 | 
						|
                    if environment:
 | 
						|
                        repo_env_filter = []
 | 
						|
                        for repo in repositories["repositories"]:
 | 
						|
                            if repo["environment"] == environment:
 | 
						|
                                repo_env_filter.append(repo)
 | 
						|
                        res_doc["repositories"] = repo_env_filter
 | 
						|
                    res.append(res_doc)
 | 
						|
        return res
 | 
						|
 | 
						|
    def docs_html_by_category(self, environment, cloud_environment):
 | 
						|
        """Generate structure for doc-exports repository"""
 | 
						|
        doc_struct = dict()
 | 
						|
        for srv in self.all_services:
 | 
						|
            doc_struct.setdefault(srv["service_category"], [])
 | 
						|
            srv_res = dict(
 | 
						|
                service_title=srv["service_title"],
 | 
						|
                service_type=srv["service_type"],
 | 
						|
                service_category=srv["service_category"],
 | 
						|
                service_environment=environment,
 | 
						|
                docs=[],
 | 
						|
            )
 | 
						|
            if "teams" in srv:
 | 
						|
                srv_res["teams"] = [
 | 
						|
                    x for x in srv["teams"] if x["permission"] == "write"
 | 
						|
                ]
 | 
						|
            srv["repositories"] = []
 | 
						|
            for repositories in self.all_repositories:
 | 
						|
                if repositories["service_type"] == srv["service_type"]:
 | 
						|
                    for single_repo in repositories["repositories"]:
 | 
						|
                        if single_repo["cloud_environments"][0] == cloud_environment:
 | 
						|
                            srv["repositories"].append(single_repo)
 | 
						|
 | 
						|
            if "repositories" in srv and environment:
 | 
						|
                internal_exists = False
 | 
						|
                for repo in srv["repositories"]:
 | 
						|
                    if (
 | 
						|
                        "environment" in repo
 | 
						|
                        and repo["environment"] == environment
 | 
						|
                    ):
 | 
						|
                        srv_res["repository"] = repo["repo"]
 | 
						|
                        if repo["environment"] == "internal":
 | 
						|
                            internal_exists = True
 | 
						|
                # internal repo does not exist
 | 
						|
                # service will be left out from metadata.yaml
 | 
						|
                if not internal_exists:
 | 
						|
                    continue
 | 
						|
            for doc in self.all_docs:
 | 
						|
                if (
 | 
						|
                    "html_location" in doc
 | 
						|
                    and doc["service_type"] == srv_res["service_type"]
 | 
						|
                ):
 | 
						|
                    doc_res = dict(
 | 
						|
                        html_location=doc["html_location"],
 | 
						|
                        rst_location=doc["rst_location"],
 | 
						|
                        title=doc["title"],
 | 
						|
                        type=doc.get("type", "dummy"),
 | 
						|
                        link=doc["link"],
 | 
						|
                    )
 | 
						|
                    if "pdf_name" in doc:
 | 
						|
                        doc_res["pdf_name"] = doc["pdf_name"]
 | 
						|
                    if "hc_location" in doc:
 | 
						|
                        doc_res["hc_location"] = doc["hc_location"]
 | 
						|
                    if "disable_import" in doc:
 | 
						|
                        doc_res["disable_import"] = doc["disable_import"]
 | 
						|
                    else:
 | 
						|
                        doc_res["disable_import"] = False
 | 
						|
                    srv_res["docs"].append(doc_res)
 | 
						|
            if len(srv_res["docs"]) > 0:
 | 
						|
                doc_struct[srv["service_category"]].append(srv_res)
 | 
						|
 | 
						|
        return dict(categories=doc_struct)
 | 
						|
 | 
						|
    def get_service_with_docs_by_service_type(self, service_type):
 | 
						|
        """Retrieve service and service docs by service_type
 | 
						|
 | 
						|
        :param str service_type: Filter by service_type
 | 
						|
        """
 | 
						|
        res = dict()
 | 
						|
        res["service"] = {}
 | 
						|
        docs = []
 | 
						|
        services = self._service_data
 | 
						|
        for doc in services["documents"]:
 | 
						|
            if doc["service_type"] == service_type:
 | 
						|
                docs.append(doc)
 | 
						|
        res["documents"] = docs
 | 
						|
        for service in services["services"]:
 | 
						|
            if service["service_type"] == service_type:
 | 
						|
                res["service"] = service
 | 
						|
                for repositories in self.all_repositories:
 | 
						|
                    if repositories["service_type"] == service["service_type"]:
 | 
						|
                        res["service"]["repositories"] = repositories["repositories"]
 | 
						|
                        break
 | 
						|
                break
 | 
						|
        return res
 | 
						|
    
 | 
						|
    def get_service_with_repo_by_service_type(self, service_type):
 | 
						|
        """Retrieve service with repos by service_type
 | 
						|
 | 
						|
        :param str service_type: Filter by service_type
 | 
						|
        """
 | 
						|
        res = dict()
 | 
						|
        res = {}
 | 
						|
        services = self.all_services
 | 
						|
        for service in services:
 | 
						|
            if service["service_type"] == service_type:
 | 
						|
                res = service
 | 
						|
                for repositories in self.all_repositories:
 | 
						|
                    if repositories["service_type"] == service["service_type"]:
 | 
						|
                        res["repositories"] = repositories["repositories"]
 | 
						|
                        break
 | 
						|
                break
 | 
						|
        return res
 | 
						|
 | 
						|
    def services_with_repos(self):
 | 
						|
        """Retrieve all services with repos
 | 
						|
        """
 | 
						|
        res = []
 | 
						|
        services = self.all_services
 | 
						|
        for i, service in enumerate(services):
 | 
						|
            res.append(service)
 | 
						|
            for repositories in self.all_repositories:
 | 
						|
                if repositories["service_type"] == service["service_type"]:
 | 
						|
                    res[i]["repositories"] = repositories["repositories"]
 | 
						|
                    break
 | 
						|
        return res |