def __pull_out_type_from_schema(self, schema, field):

        # static 경고 무시용.
        dummy = self._me

        schema_to_string = str(schema)
        schema_to_dict = json.loads(schema_to_string)

        data_list = schema_to_dict["data"]

        for row in data_list:
            try:
                # 하나의 schema data로부터 id를 추출.
                row_id = row["id"]

                # id가 persistentVolume인지를 확인.
                if row_id == PersistentVolumesConstant.PERSISTENT_VOLUME:
                    # resourceFields를 추출.
                    resource_fields = row["resourceFields"]
                    # resourceFields로부터 field에 해당하는 Data를 추출.
                    field_values = resource_fields[field]

                    # field에 해당하는 data로부터 type을 추출.
                    return field_values["type"]

            except Exception as ex:
                DummyError("Invalid schema." + "\n" + schema, ex)

        raise DummyError("field type doesn't exist in schema." + "\nfield:" + field + "\n" + schema)
    def __targets_refactoring(self, application, clusters_mapping,
                              projects_mapping):
        """
        대상 application 의 targets 의 target 정보를 기반으로 cluster 와 project 명을 추출하고,
        추출한 cluster, project 명을 target 에 넣어준다.\n
        :param application: 대상 application
        :param clusters_mapping: cluster 명을 추출할 cluster mapping data
        :param projects_mapping: project 명을 추출할 project mapping data
        :return: refactoring 한 targets
        """

        refactoring_result = []
        targets = application['targets']

        for target in targets:
            # project id 추출
            project_id = target['projectId']

            #  cluster id 추출
            colon_index = project_id.find(':')
            if colon_index == -1:
                raise DummyError("[targets.clusterId] has not colon.\n" +
                                 project_id)

            cluster_id = project_id[:colon_index]

            # cluster id 를 기반으로 해당 cluster 의 row 습득.
            cluster_row = self._me.__find_by_key_then_get_row(
                clusters_mapping, 'id', cluster_id)
            if cluster_row is None:
                raise DummyError("[clusters] does not include this id.\nid:" +
                                 cluster_id)

            # project id 를 기반으로 해당 project 의 row 습득.
            project_row = self._me.__find_by_key_then_get_row(
                projects_mapping, 'id', project_id)
            if cluster_row is None:
                raise DummyError("[projects] does not include this id.\nid:" +
                                 project_id)

            # cluster row 로부터 name 을 추출.
            target[Constant.CLUSTER_NAME] = cluster_row['name']

            # project row 로부터 name 을 추출.
            target[Constant.PROJECT_NAME] = project_row['name']

            # refactoring 한 target 을 결과 list 에 추가.
            refactoring_result.append(target.copy())

        return refactoring_result
    def __pull_out_field_name(self, options):
        """
        View로부터 받은 payload로부터 Volume Source의 Field Name을 추출한다.\n
        :param options: View로부터 받은 payload
        :return: 추출한 Field Name.
        """

        # static 경고 무시용.
        dummy = self._me

        # volume source mapping을 습득.
        volume_sources = PersistentVolumesConstant.VOLUME_SOURCE_DICTIONARY[PersistentVolumesConstant.VOLUME_SOURCE]

        # volume source mapping을 순회하면서 field를 추출하여 반환.
        for volume_source_value in volume_sources.values():
            try:
                # 현재의 field명을 습득.
                current_field = volume_source_value[PersistentVolumesConstant.FIELD]
                # 현재 field명에 해당하는 정보가 options에 있는지 확인.
                # 만약 없을 경우, KeyError Exception이 발생하여 건너뛰게 됨.
                checker = options[current_field]
                # 있을 경우, 현재의 field를 반환.
                return current_field

            # 해당 field명에 부합하는 Data가 없을 경우, Key Error가 발생. 이 경우 무시.
            except KeyError:
                pass

        # 어느 Field에도 해당하지 않을 경우, Error를 반환함.
        # 보통은 부정적인 접근이나 또는 Coding Error로 인해 발생. ( Coding Error로 인한 발생이 거의 대부분일듯. )
        raise DummyError("volume source field doesn't exist. please check your data." + "\n" + json.dumps(options))
    def __refactoring_field(self, persistent_volume, field_name):

        # static 경고 제거용.
        dummy = self._me

        can_write_plugin = persistent_volume[field_name]

        if field_name == "hostPath":
            deeper = PersistentVolumesConstant.VOLUME_SOURCE_DICTIONARY[
                PersistentVolumesConstant.VOLUME_SOURCE]
            deeper = deeper[PersistentVolumesConstant.TITLE_HOST_PATH]
            deeper = deeper[PersistentVolumesConstant.CONFIGURATION]
            deeper = deeper["kind"]
            deeper = deeper["items"]
            for item in deeper:

                if item["value"] == can_write_plugin["kind"]:
                    deeper = item["label"]
                    break

                deeper = None

            # TODO: error 내용 제대로 쓸 필요 있음.
            if deeper is None:
                raise DummyError("error..")

            can_write_plugin["kind"] = deeper

        return can_write_plugin
    def add_form_persistent_volume(self, storage_classes):

        # 원본 data의 변동을 막기 위해 임시로 storage class dictionary를 복사한다.
        storage_classes_template_dict = PersistentVolumeConstant.VOLUME_SOURCE_DICTIONARY[
            PersistentVolumeConstant.VOLUME_SOURCE].copy()

        result_view_write = {
            PersistentVolumeConstant.TITLE: "Add Persistent Volume"
            , PersistentVolumeConstant.VOLUME_SOURCES: self._me.__remove_unsupported(storage_classes_template_dict)
            , PersistentVolumeConstant.VOLUME_SOURCES_STRING: json.dumps(
                self._me.__remove_unsupported(storage_classes_template_dict))
            , PersistentVolumeConstant.SELECTOR_OPERATOR: json.dumps(self._me.__get_volume_node_selector_operator())
            , PersistentVolumeConstant.ACCESS_MODES: PersistentVolumeConstant.FORM_ACCESS_MODES
        }

        # RestObject 를 dictionary 객체로 변환
        try:
            dict_storage_classes = JsonUtility.call().to_dictionary(storage_classes)
        except DummyError as de:
            raise de

        # dictionary 로부터 'data' dictionary를 추출.
        try:
            storage_classes_mapping = dict_storage_classes['data']
        except KeyError:
            raise DummyError("storageClass['data'] row is not eixsts. please check your data.")

        result_view_write[PersistentVolumeConstant.STORAGE_CLASSES] = \
            self._me.__get_all_storage_class_id(storage_classes_mapping)

        return result_view_write
Exemple #6
0
    def _detail_persistent_volume(self, options):

        # API로부터 특정 persistent volume만을 추출.
        persistent_volume = self._me.__caller.list_persistent_volumes(options)

        # 특정 persistent volume을 가공 처리.
        # 실제 결과는 1개이지만, list 형식으로 불려오게 됨.
        models = self._me.__lister.list_persistent_volumes(persistent_volume)
        if len(models) > 1:
            DummyError("Results are too many.")

        # list로부터 결과를 추출.
        model = self._me.__rower.row_persistent_volume(models[0])

        return model
    def list_persistent_volumes(self, persistent_volumes):
        """
        API로부터 얻은 모든 Persistent Volumes를 View에 맞추어서 가공하여 반환한다.\n
        :param persistent_volumes: API로부터 얻은 모든 Persistent Volumes.
        :return: 가공 결과.
        """

        result_persistent_volumes = []

        # RestObject 를 dictionary 객체로 변환
        try:
            dict_persistent_volumes = JsonUtility.call().to_dictionary(
                persistent_volumes)
        except DummyError as de:
            raise de

        # dictionary로부터 data를 추출
        try:
            persistent_volumes_mapping = dict_persistent_volumes['data']
        except KeyError:
            raise DummyError(
                "persistent_volumes['data'] row is not eixsts. please check your data."
            )

        for persistent_volume in persistent_volumes_mapping:
            can_write_persistent_volume = persistent_volume.copy()

            # 해당 persistent volume의 삭제 가능 여부 flag setting.
            can_write_persistent_volume[
                PersistentVolumesConstant.CAN_REMOVE] = self.__can_remove(
                    persistent_volume)

            try:
                # Persistent Volume의 Source 를 얻음.
                can_write_persistent_volume[
                    PersistentVolumesConstant.SOURCE] = self.__getSource(
                        persistent_volume)

            # source가 존재하지 않을 경우 무시.
            except Exception as e:
                raise e

            result_persistent_volumes.append(
                can_write_persistent_volume.copy())

        return result_persistent_volumes
    def string_to_datetime(self, string, formatting):
        """
        시간 문자열을 <datetime> 형식으로 변환.\n
        :param string: 시간 문자열.
        :param formatting: 변환 규칙.
        :return: <datetime> 형식의 시간.
        """
        # static 경고 방지용.
        dummy = self._me

        try:
            return DateTime.strptime(string, formatting)

        except Exception as e:
            DummyError("fail to convert from string to date." + "\n" +
                       "reason: " + str(e) + "\n" + "date string: " + string +
                       "\n" + "format: " + formatting)
    def datetime_to_string(self, date, formatting):
        """
        <datetime> 형식의 시간을 문자열로 변환.\n
        :param date: <datetime> 형식의 시간.
        :param formatting: 변환 규칙.
        :return: 시간 문자열.
        """
        # static 경고 방지용.
        dummy = self._me

        try:
            return date.strftime(formatting)

        except Exception as e:
            DummyError("fail to convert from date to string." + "\n" +
                       "reason: " + str(e) + "\n" + "date: " + str(date) +
                       "\n" + "format: " + formatting)
    def __to_application_id(self, application):
        """
        대상 application 으로부터 application id 를 추출한다.\n
        :param application: 대상 application
        :return: 대상 application 의 id
        """

        # static 경고 제거용.
        dummy = self._me

        template_version_id = application['templateVersionId']
        last_hyphen_index = template_version_id.rfind('-')

        if last_hyphen_index == -1:
            raise DummyError("application 의 templateVersionId 에 - 이 없습니다.")

        return template_version_id[:last_hyphen_index]
    def list_catalogs(self, catalogs):
        """
        모든 catalog 를 불러온다.\n
        :param catalogs: API 로부터 얻은 모든 catalog
        :return: 가공 처리가 완료된 catalog list
        """

        # static 경고 방지용.
        dummy = self._me

        result_catalogs = []

        # RestObject 를 dictionary 객체로 변환
        try:
            dict_catalogs = JsonUtility.call().to_dictionary(catalogs)
        except DummyError as de:
            raise de

        # dictionary 로부터 'data' dictionary 를 추출.
        try:
            catalogs_mapping = dict_catalogs['data']
        except KeyError:
            raise DummyError(
                "catalogs['data'] row is not eixsts. please check your data.")

        try:
            for cata in catalogs_mapping:
                # catalog 를 복제한다.
                can_write_catalog = copy.copy(cata)

                # 해당 catalog 는 Clone 이 가능한지 여부를 넣는다.
                catalog_name = can_write_catalog[CatalogConstant.NAME_STRING]
                can_write_catalog[CatalogConstant.CAN_CLONE_STRING] \
                    = not CatalogConstant.isDefaultCatalog(catalog_name)

                # catalog 에 scope 를 추가한다.
                can_write_catalog[
                    CatalogConstant.SCOPE] = CatalogConstant.CATALOG_SCOPE

                # refactoring 이 완료된 catalog 를 결과 list 에 추가한다.
                result_catalogs.append(can_write_catalog.copy())
        except Exception as e:
            raise Exception("unknown exception...\n" + e)

        return result_catalogs
    def filter_multi_cluster_application_templates(self, apps_templates, opts):
        """
        모든 Multi-Cluster Applications의 Templates를 임의의 Catalog 명으로 Filtering한다.\n
        :param apps_templates: 모든 Multi-Cluster Application의 Templates.
        :param opts: Filtering 및 모든 Multi-Cluster Applications의 Templates의 API 호출시의 options.
        :return: Filtering이 완료된 Multi-Cluster Applications의 Templates List.
        """
        # category name을 추출한다.
        category_name = opts['category']

        result_templates = {
            Constant.CATEGORY_COUNT_DICTIONARY: {
                "All": 0,
            },
            Constant.CATEGORY_FOCUS: category_name,
            Constant.DATA: {},
        }

        # RestObject 를 dictionary 로 변환
        try:
            dict_templates = JsonUtility.call().to_dictionary(apps_templates)
        except DummyError as de:
            raise de

        # dictionary 로부터 'data' dictionary 를 추출.
        try:
            templates_mapping = dict_templates['data']
        except:
            raise DummyError(
                "[data] row is not eixsts. please check your data.\n")

        for templ in templates_mapping:
            # apps_templates 를 복제한다.
            can_write_template = templ.copy()

            # 각 Category 에 따른 갯수 추가.
            self.__calculate_category_count(templ, result_templates)

            # Category 를 result mapping 에 분류하여 삽입.
            self.__classify_category(can_write_template,
                                     result_templates[Constant.DATA],
                                     category_name)

        return result_templates
    def to_dictionary(self, source):
        """
        임의의 data 를 dictionary 형식의로 변환한다.\n
        임의의 data 는 dictionary 형태로 변환할 수 있는 모형이여야 하며, 그렇지 않으면 예외를 발생시킨다.\n
        :param source: 변환 대싱인 임의의 data
        :exception: 변환 실패, DummyException 발생
        :return: 변환이 완료된 dictionary 객체
        """

        try:
            try:
                return self.__literal_evaluation(source)
            # 만일 ast library 를 이용한 변환을 실패하였을 경우.
            except Exception as e:
                return self.__json_dumps_then_loads(source)
        # 만일 json library 를 사용한 변환에도 실패했을 경우.
        except (TypeError or json.JSONDecodeError) as e:
            # 변환 실패 exception 을 발생시킨다.
            raise DummyError(
                "this source can't convert to dinctionary. please check your source."
                + "\n" + source, e)
Exemple #14
0
    def list_storage_classes(self, storage_classes):
        """
        API로부터 얻은 Storage Classes를 View에 맞게 가공하여 반환한다.\n
        :param storage_classes: API로부터 얻은 Storage Classes.
        :return: 가공된 Storage Classes List.
        """

        result_storage_classes = []

        # RestObject를 dictionary 객체로 변환
        try:
            dict_storage_classes = JsonUtility.call().to_dictionary(
                storage_classes)
        except DummyError as de:
            raise de

        try:
            storage_classes_mapping = dict_storage_classes['data']
        except KeyError:
            raise DummyError(
                "persistent_volumes['data'] row is not eixsts. please check your data."
            )

        for storage_class in storage_classes_mapping:
            can_write_storage_class = storage_class.copy()

            # storage class의 상태를 active로 설정. (default)
            # TODO: 추후 화면 출력 Table을 Template화 하면, 상태를 넣을 필요가 있기 때문에 넣어준다. ( 사실 상태가 존재하지 않음. )
            can_write_storage_class[
                StorageClassesConstant.
                STATE_STRING] = StorageClassesConstant.DEFAULT_STATE

            # 화면에 출력할 title을 습득.
            can_write_storage_class[
                StorageClassesConstant.PROVISIONER] = self.__get_provisioner(
                    storage_class)

            result_storage_classes.append(can_write_storage_class.copy())

        return result_storage_classes
    def multi_cluster_application_templates(self, apps_templates):
        """
        모든 apps_templates multi-cluster appllications 을 불러온다.\n
        :param apps_templates: API 로부터 얻은 templates multi-cluster applications
        :return: 가공 처리가 완료된 apps_templates multi-cluster applications
        """

        result_templates = {
            Constant.CATEGORY_COUNT_DICTIONARY: {
                "All": 0,
            },
            Constant.CATEGORY_FOCUS: "All",
            Constant.DATA: {},
        }

        # RestObject 를 dictionary 로 변환
        try:
            dict_templates = JsonUtility.call().to_dictionary(apps_templates)
        except DummyError as de:
            raise de

        # dictionary 로부터 'data' dictionary 를 추출.
        try:
            templates_mapping = dict_templates['data']
        except:
            raise DummyError(
                "[data] row is not eixsts. please check your data.")

        for templ in templates_mapping:
            # apps_templates 를 복제한다.
            can_write_template = copy.copy(templ)

            # 각 Category 에 따른 갯수 추가.
            self.__calculate_category_count(templ, result_templates)

            # Category 를 result mapping 에 분류하여 삽입.
            self.__classify_category(can_write_template,
                                     result_templates[Constant.DATA])

        return result_templates
Exemple #16
0
    def __get_provisioner(self, storage_class):
        """
        API로부터 얻은 data 중, provisioner에 해당하는 title을 습득한다.\n
        :param storage_class: provisioner를 추출할 API로부터 얻은 data.
        :return: 습득한 title.
        """

        # static 경고 제거용.
        dummy = self._me

        provisioner = storage_class[StorageClassesConstant.PROVISIONER]

        STORAGE_CLASSES = StorageClassesConstant.STORAGE_CLASS_DICTIONARY[
            StorageClassesConstant.STORAGE_CLASS]
        for one_class in STORAGE_CLASSES.values():

            # provisioner 값을 기반으로 title 을 반환한다.
            if one_class[StorageClassesConstant.PROVISIONER] == provisioner:
                return one_class[StorageClassesConstant.TITLE]

        # 어느 field에도 해당하는 내용이 없을 경우, DummyEvolume)xception을 발생시킴.
        raise DummyError("invalid data --- provisioner does not exists." +
                         "\n" + "data:" + json.dumps(storage_class))
    def __pull_out_configuration(self, persistent_volume):
        """
        임의의 Persistent Volume의 정보를 기반으로 source를 추출하고, 해당 source의 configuration을 반환한다.\n
        :param persistent_volume: 임의의 persistent volume.
        :return: 해당 persistent volume에 맞는 configurtaion template.
        """

        # static 경고 제거용.
        dummy = self._me

        VOLUME_SOURCES = PersistentVolumesConstant.VOLUME_SOURCE_DICTIONARY[
            PersistentVolumesConstant.VOLUME_SOURCE]
        for value in VOLUME_SOURCES.values():
            # field 명을 습득한다.
            field_name = value[PersistentVolumesConstant.FIELD]

            # 해당 field가 존재하므로 configuration을 반환.
            if field_name in persistent_volume and value[
                    PersistentVolumesConstant.SUPPORTED]:
                return value[PersistentVolumesConstant.CONFIGURATION]

        # 어느 field에도 해당하는 내용이 없는 경우, DummyException을 발생시킴.
        raise DummyError("invalid data -- source does not exists." + "\n" +
                         "data:" + json.dumps(persistent_volume))
    def __getSource(self, persistent_volume):
        """
        임의의 Persistent volume의 정보를 기반으로 source를 파악하여 source field를 생성 및 값을 입력한다.\n
        :param persistent_volume: 임의의 Persistent Volume.
        :return 해당 persistent volume에 맞는 title.
        """

        # static 경고 제거용.
        dummy = self._me

        VOLUME_SOURCES = PersistentVolumesConstant.VOLUME_SOURCE_DICTIONARY[
            PersistentVolumesConstant.VOLUME_SOURCE]
        for value in VOLUME_SOURCES.values():
            # field 명을 습득한다.
            field_name = value[PersistentVolumesConstant.FIELD]

            # 해당 field가 존재하므로 field의 title을 반환.
            if field_name in persistent_volume and value[
                    PersistentVolumesConstant.SUPPORTED]:
                return value[PersistentVolumesConstant.TITLE]

        # 어느 field에도 해당하는 내용이 없을 경우, DummyException을 발생시킴.
        raise DummyError("invalid data --- source does not exists." + "\n" +
                         "data:" + json.dumps(persistent_volume))
    def replace_range(self, value, old, new, start, end):
        """
        임의의 문자열로부터 일정 범위 내에서 특정 문자열을 replace 하는 함수이다.\n
        :param value: 대상 문자열
        :param old: replace 할 대상의 단어
        :param new: replace 할 단어
        :param start: 임의의 문자열의 시작 범위
        :param end: 임의의 문자열의 종료 범위
        :return: 대체 완료한 문자열
        """

        # static 경고 방지용.
        dummy = self._me

        # start 또는 end 가 정수가 아닌 경우.
        if not isinstance(start, int) or not isinstance(end, int):
            raise TypeError("start or end value are not digit.")

        # start 가 end 보다 큰 경우.
        if start > end:
            raise DummyError("end value is greater than start value.")

        # start 또는 end 가 음수인 경우.
        if start < 0 or end < 0:
            raise DummyError("start or end value is less than 0")

        # start 또는 end 가 대상 문자열의 길이보다 큰 경우.
        VALUE_LENGTH = len(value)
        if start >= VALUE_LENGTH or end >= VALUE_LENGTH:
            raise DummyError(
                "start or end value is greater than target value length.")

        # [start:end] 범위 외의 문자열을 따로 저장.
        prefix = value[:start]
        suffix = value[end:]

        # [start:end] 범위 내의 문자열 습득.
        range_string = value[start:end]
        result_string = ''

        OLD_LENGTH = len(old)

        while True:
            # old 문자열이 있는 시작 index 습득.
            start_index = range_string.find(old)

            # old 문자열이 더 이상 발견되지 않을 경우 종료.
            if start_index == -1:
                break

            # old 문자열의 시작점 이전 부분을 입력.
            result_string += range_string[:start_index]

            # old 문자열의 시작 위치에 new 문자열을 입력.
            result_string += new

            # 대상 문자열에서 old 문자열 이후의 문자열들을 저장.
            start_index += OLD_LENGTH
            range_string = range_string[start_index:]

        result_string = prefix + result_string + suffix
        return result_string
    def list_applications(self, multi_cluster_apps, projects, clusters,
                          template_apps):
        """
        모든 multi-cluster application 을 불러온다.\n
        projects 와 clusters 가 필요한 이유는 multi-cluster application 의 대상이 되고있는 project 와 cluster 명을 얻기 위해서이다.\n
        :param template_apps: API 로부터 얻은 모든 multi-cluster application teamplates
        :param multi_cluster_apps: API 로부터 얻은 모든 multi-cluster application
        :param projects: API 로부터 얻은 projects
        :param clusters: API 로부터 얻은 clusters
        :return: 가공 처리가 완료된 multi-cluster application list
        """
        result_multi_cluster_applications = []

        # RestObject 를 dictionary 객체로 변환
        try:
            dict_multi_cluster_apps = JsonUtility.call().to_dictionary(
                multi_cluster_apps)
            dict_projects = JsonUtility.call().to_dictionary(projects)
            dict_clusters = JsonUtility.call().to_dictionary(clusters)
            dict_template_apps = JsonUtility.call().to_dictionary(
                template_apps)
        except DummyError as de:
            raise de

        # 각 dictionary 로부터 'data' dictionary 를 추출.
        try:
            multi_cluster_apps_mapping = dict_multi_cluster_apps['data']
            projects_mapping = dict_projects['data']
            clusters_mapping = dict_clusters['data']
            template_apps_mapping = dict_template_apps['data']

        except:
            raise DummyError(
                "[data] row is not eixsts. please check your data.")

        try:
            for application in multi_cluster_apps_mapping:
                # application 을 복제한다.
                can_write_application = copy.copy(application)

                # application id 를 추출한다.
                application_id = self._me.__to_application_id(application)

                # application id 를 이용하여, template 로부터 row 를 추출한다.
                template_row = self._me.__find_by_key_then_get_row(
                    template_apps_mapping, 'id', application_id)

                if template_row is not None:
                    # application 으로부터 apps_templates version 을 추출한다.
                    can_write_application[Constant.TEMPLATE_VERSION] \
                        = self._me.__to_template_version(application)

                    # icon link 를 추출한다.
                    can_write_application['iconLink'] = template_row['links'][
                        'icon']

                    # template의 latest(default) version 을 추출한다.
                    can_write_application[
                        Constant.
                        LATEST_VERSION] = template_row['defaultVersion']

                # application 을 이용하여 targets 를 refactoring 한다.
                refactoring = self._me.__targets_refactoring(
                    application, clusters_mapping, projects_mapping)
                can_write_application['targets'] = refactoring.copy()

                # refactoring 이 완료된 application 을 결과 list 에 추가한다.
                result_multi_cluster_applications.append(
                    can_write_application.copy())
        except DummyError as de:
            raise de
        except Exception as e:
            raise Exception("unknown exception...\n" + e)

        return result_multi_cluster_applications