Esempio n. 1
0
def make_explicit_references(definition: Dict[str, Any],
                             namespace: str) -> Dict[str, Any]:
    if is_compound(definition):
        return {
            'allOf': [
                make_explicit_references(d, namespace)
                for d in definition['allOf']
            ]
        }
    elif type(definition) is not dict:
        return definition
    elif is_ref(definition):
        path, ref = definition['$ref'].split('#', maxsplit=2)
        if not path:
            explicit_reference = f'{namespace}#{ref}'
            log.debug('Making reference to %s explicit as %s', ref,
                      explicit_reference)
            return {'$ref': explicit_reference}
        else:
            return definition
    for k, v in definition.items():
        if is_ref(v):
            path, ref = v['$ref'].split('#', maxsplit=2)
            if not path:
                explicit_reference = f'{namespace}#{ref}'
                log.debug('Making reference to %s explicit as %s', ref,
                          explicit_reference)
                definition[k] = {'$ref': explicit_reference}
        else:
            definition[k] = make_explicit_references(v, namespace)
    return definition
Esempio n. 2
0
def resolve_appgate_state(
        appgate_state: AppgateState,
        api_spec: APISpec,
        reverse: bool = False) -> Dict[str, Dict[str, FrozenSet[str]]]:
    entities = api_spec.entities
    entities_sorted = api_spec.entities_sorted
    total_conflicts = {}
    log.info('[appgate-state] Validating expected state entities')
    log.debug('[appgate-state] Resolving dependencies in order: %s',
              entities_sorted)
    for entity_name in entities_sorted:
        for entity_dependency in entities[entity_name].dependencies:
            log.debug('[appgate-state] Checking dependencies %s for %s.%s',
                      entity_dependency.dependencies, entity_name,
                      entity_dependency.field_path)
            deps_tuple = []
            e1 = appgate_state.entities_set[entity_name]
            for d in entity_dependency.dependencies:
                deps_tuple.append((
                    appgate_state.entities_set[d],
                    entity_dependency.field_path,
                ))
            new_e1, conflicts = resolve_entities(e1, deps_tuple, reverse)
            if conflicts:
                total_conflicts.update(conflicts)
            appgate_state.entities_set[entity_name] = new_e1
    return total_conflicts
Esempio n. 3
0
def resolve_entity(entity: Entity_T,
                   field: str,
                   names: Dict[str, EntityWrapper],
                   ids: Dict[str, EntityWrapper],
                   missing_dependencies: Dict[str, Dict[str, FrozenSet[str]]],
                   reverse: bool = False) -> Optional[EntityWrapper]:
    new_dependencies = set()
    missing_dependencies_set = set()
    log.debug(f'Getting field %s in entity %s', field,
              entity.__class__.__name__)
    dependencies, rest_fields = get_field(entity, field.split('.'))
    if dependencies is None:
        raise Exception(f'Object {entity} has not field {field}.')
    is_iterable = isinstance(dependencies, frozenset)
    if not is_iterable:
        dependencies = frozenset({dependencies})
    for dependency in dependencies:
        if type(dependency) not in PYTHON_TYPES and rest_fields:
            log.debug('dependency %s and rest_fields %s', dependency,
                      rest_fields)
            resolve_entity(dependency, rest_fields, names, ids,
                           missing_dependencies, reverse)
        elif dependency in ids:
            # dependency is an id
            if reverse:
                new_dependencies.add(ids[dependency].name)
            else:
                new_dependencies.add(dependency)
        elif dependency in names and names[dependency].id:
            # dependency is a name
            if reverse:
                new_dependencies.add(dependency)
            else:
                new_dependencies.add(names[dependency].id)
        else:
            missing_dependencies_set.add(dependency)
    if missing_dependencies_set:
        if entity.name not in missing_dependencies:
            missing_dependencies[entity.name] = {}
        missing_dependencies[entity.name][field] = frozenset(
            missing_dependencies_set)
    if new_dependencies:
        if is_iterable:
            return EntityWrapper(
                evolve_rec(entity, field.split('.'),
                           frozenset(new_dependencies)))
        else:
            return EntityWrapper(
                evolve_rec(entity, field.split('.'),
                           list(new_dependencies)[0]))
    return None
Esempio n. 4
0
def get_field(entity: Entity_T,
              paths: List[str]) -> Tuple[Optional[Any], Optional[str]]:
    f: Any = entity
    for i, p in enumerate(paths):
        log.debug('Getting field %s in %s', p,
                  list(entity_t_attribute_names(f)))
        if isinstance(f, frozenset):
            return f, '.'.join(paths[i:])
        f = getattr(f, p, None)
        if f is None:
            if len(paths[i:]):
                # Last field is None, it could an optional field (should be checked here)
                return frozenset(), p
            else:
                return None, '.'.join(paths[i:])
    return f, None
Esempio n. 5
0
async def plan_apply(plan: Plan,
                     namespace: str,
                     k8s_configmap_client: K8SConfigMapClient,
                     entity_client: Optional[EntityClient] = None) -> Plan:
    errors = set()
    for e in plan.create.entities:
        log.info('[appgate-operator/%s] + %s %s [%s]', namespace,
                 type(e.value), e.name, e.id)
        if entity_client:
            try:
                await entity_client.post(e.value)
                name = 'singleton' if e.value._entity_metadata.get(
                    'singleton', False) else e.name
                await k8s_configmap_client.update_entity_generation(
                    key=entity_unique_id(e.value.__class__.__name__, name),
                    generation=e.value.appgate_metadata.current_generation)
            except Exception as err:
                errors.add(f'{e.name} [{e.id}]: {str(err)}')

    for e in plan.modify.entities:
        log.info('[appgate-operator/%s] * %s %s [%s]', namespace,
                 type(e.value), e.name, e.id)
        diff = plan.modifications_diff.get(e.name)
        if diff:
            log.info('[appgate-operator/%s]    DIFF for %s:', namespace,
                     e.name)
            for d in diff:
                log.info('%s', d.rstrip())
        if entity_client:
            try:
                await entity_client.put(e.value)
                name = 'singleton' if e.value._entity_metadata.get(
                    'singleton', False) else e.name
                await k8s_configmap_client.update_entity_generation(
                    key=entity_unique_id(e.value.__class__.__name__, name),
                    generation=e.value.appgate_metadata.current_generation)
            except Exception as err:
                errors.add(f'{e.name} [{e.id}]: {str(err)}')

    for e in plan.delete.entities:
        log.info('[appgate-operator/%s] - %s %s [%s]', namespace,
                 type(e.value), e.name, e.id)
        if entity_client:
            try:
                await entity_client.delete(e.id)
                name = 'singleton' if e.value._entity_metadata.get(
                    'singleton', False) else e.name
                await k8s_configmap_client.delete_entity_generation(
                    entity_unique_id(e.value.__class__.__name__, name))
            except Exception as err:
                errors.add(f'{e.name} [{e.id}]: {str(err)}')

    for e in plan.share.entities:
        log.debug('[appgate-operator/%s] = %s %s [%s]', namespace,
                  type(e.value), e.name, e.id)

    has_errors = len(errors) > 0
    return Plan(create=plan.create,
                share=plan.share,
                delete=plan.delete,
                modify=plan.modify,
                modifications_diff=plan.modifications_diff,
                errors=errors if has_errors else None)