Beispiel #1
0
 def __contains__(self, item):
     """
     Check if given resource type exists.
     """
     res = map_res(item)
     if res is not None:
         return self.has_type(res['type'])
Beispiel #2
0
def get_resources(r_type, r_name='_all', ns=None, print_warnings=True):
    rt_info = map_res(r_type)
    get_func = rt_info['get_func']
    yaml_loc = rt_info['yaml_loc']
    need_ns = rt_info['need_ns']

    return get_func(ns, r_name, yaml_loc, need_ns, print_warnings)
Beispiel #3
0
def get_resources(r_type, r_name="_all", ns=None, print_warnings=True):
    rt_info = map_res(r_type)
    get_func = rt_info["get_func"]
    yaml_loc = rt_info["yaml_loc"]
    need_ns = rt_info["need_ns"]

    return get_func(ns, r_name, yaml_loc, need_ns, print_warnings)
Beispiel #4
0
def _suggest_type(incomplete_type):
    """
    Smart matching for type/alias based on incomplete string
    Suggest one type if matched types and aliases belongs to the the same type
    e.g,:
        if incomplete = 'po' return ['po'] instead of ['po', 'pod', 'pods']
        if incomplete = 'ser' return ['service'] instead of ['service','services']
        but
        if incomplete = 'buil' return ['build','buildconfigs','builds','buildconfig']
    """
    fullset = set(
        [t["type"] for t in map]
        + [a for aliases in [t["aliases"] for t in map] for a in aliases]
    )

    match = [f for f in fullset if f.startswith(incomplete_type)]

    if len(match) > 1 and len(match) <= 3:
        unique_types = set([map_res(m)["type"] for m in match])
        if len(unique_types) == 1:
            return list(unique_types)
        else:
            return match
    else:
        return match
Beispiel #5
0
def generate_completions(config, objects, incomplete):
    """
    Given a config, tuple of args, and incomplete input from user, generate a list of completions.

    This function should not print stack traces or do any error logging (without turning it on explicitly)
    since shell completion should be transparent to user.
    """
    try:
        get_method, resource_list = parse.parse_get_resources(objects)
    except Exception as e:
        # Swallow any error since we don't want to spam terminal during autcompletion.
        print(e)
        return []

    # We're completing something like `oc get pod/name`.
    if "/" in incomplete:
        restypein = incomplete.split("/")[0]
        resname = incomplete.split("/")[1]
        restype = map_res(restypein)
        resources = restype['get_func']('items', config.project, '_all',
                                        restype['yaml_loc'],
                                        restype['need_ns'])
        return [
            restypein + "/" + r['res']['metadata']['name'] for r in resources
            if r['res']['metadata']['name'].startswith(resname)
        ]

    if len(resource_list) == 0 and "," in incomplete:
        # This is a NOP like oc
        return []
    elif get_method == parse.Method.SINGLE_TYPE or \
            get_method == parse.Method.ALL:
        # Autocomplete resource names based on the type: oc get pod mypod1 mypod2
        restypein, _ = next(resource_list)
        restype = map_res(restypein)
        resources = restype['get_func']('items', config.project, '_all',
                                        restype['yaml_loc'],
                                        restype['need_ns'])
        return [
            r['res']['metadata']['name'] for r in resources
            if r['res']['metadata']['name'].startswith(incomplete)
        ]
    else:
        # Return completions for resource types
        # TODO: Include aliases
        fullset = set(parse.ALL_TYPES + [t['type'] for t in map])
        return [t for t in fullset if t.startswith(incomplete)]
Beispiel #6
0
def _parse_slash(arg):
    """
    Parses out a single word containing a slash, validates the type is known and returns: type name, resource name
    """
    try:
        o_split = arg.split('/')
        r_type = o_split[0]
        r_name = o_split[1]
        checked_type = map_res(r_type)
        if r_type is None:
            raise ResourceParseError("[ERROR] Invalid object type: " + r_type)
        return checked_type['type'], r_name
    except Exception:
        raise ResourceParseError("[ERROR] Invalid object type: " + arg)
Beispiel #7
0
def parse_get_resources(objects: tuple) -> (Method, ResourceMap):
    """
    Takes a tuple (examples below) of arguments passed to `omg get ...` and parses it into
    manageable class. Returns a tuple containing the Method enum and resource mapping.

    Raises ResourceParseError if it runs into any issues.

    Example object contents:
    ('pod', 'httpd')
    ('pods', 'httpd1', 'httpd2')
    ('dc/httpd', 'pod/httpd1')
    ('routes')
    ('pod,svc')
    """
    method = Method.UNKNOWN
    resources = ResourceMap()

    if len(objects) == 0:
        # We've nothing to parse right now.
        return method, resources

    last_object = []

    # Check first arg to see if we're doing multiple or single resources
    first = objects[0]
    if '/' in first:
        method = Method.MULTI_TYPE_MULTI_RESOURCE
    elif ',' in first:
        method = Method.MULTI_TYPE_SINGLE_RESOURCE
    else:
        method = Method.SINGLE_TYPE

    for o in objects:
        if '/' in o:
            r_type, r_name = _parse_slash(o)
            resources.add_resource(r_type, r_name)
        elif ',' in o:
            pass
        else:
            pass

    for o in objects:
        # Case where we have a '/'
        # e.g omg get pod/httpd
        if '/' in o:
            method = Method.MULTI_TYPE_MULTI_RESOURCE
            if not last_object:
                pre = o.split('/')[0]
                r_type = map_res(pre)['type']
                r_name = o.split('/')[1]
                # If its a valid resource type, append it to objects
                if r_type is not None:
                    resources.add_resource(r_type, r_name)
                else:
                    raise ResourceParseError("[ERROR] Invalid object type: " +
                                             pre)

        # Convert 'all' to list of resource types in a specific order
        elif o == 'all':
            for rt in ALL_TYPES:
                # TODO Simplify to just: last_object.append(rt)?
                check_rt = map_res(rt)
                if check_rt is None:
                    raise ResourceParseError("[ERROR] Invalid object type: " +
                                             rt)
                else:
                    last_object.append(check_rt['type'])

        # Case where we have a ',' e.g `get dc,svc,pod httpd`
        # These all will be resource_types, not names,
        # resource_name will come it next iteration (if any)
        elif ',' in o:
            method = Method.MULTI_TYPE_SINGLE_RESOURCE
            if not last_object:
                r_types = o.split(',')
                # if all is present, we will replace it with all_types
                if 'all' in r_types:
                    ai = r_types.index('all')
                    r_types.remove('all')
                    r_types[ai:ai] = ALL_TYPES
                for rt in r_types:
                    check_rt = map_res(rt)
                    if check_rt is None:
                        raise ResourceParseError(
                            "[ERROR] Invalid object type: " + rt)
                    else:
                        last_object.append(check_rt['type'])
            else:
                # last_object was set, meaning this should be object name
                raise ResourceParseError("[ERROR] Invalid resources to get: " +
                                         objects)

        # Simple word (without , or /)
        # If last_object was not set, means this is a resource_type
        elif not last_object:
            method = Method.SINGLE_TYPE
            check_rt = map_res(o)
            if check_rt is not None:
                last_object = [check_rt['type']]
            else:
                raise ResourceParseError(
                    "[ERROR] Invalid resource type to get: " + o)
        # Simple word (without , or /)
        # If the last_object was set, means we got resource_type last time,
        # and this should be a resource_name.
        elif last_object:
            method = Method.SINGLE_TYPE
            for rt in last_object:
                resources.add_resource(rt, o)
        else:
            # Should never happen
            raise ResourceParseError("[ERROR] Invalid resources to get: " + o)

    if last_object:
        for rt in last_object:
            check_rt = map_res(rt)
            if check_rt is None:
                continue
            r_type = check_rt['type']
            if not resources.has_type(r_type) or len(
                    resources.get_resources(r_type)) == 0:
                method = Method.ALL
                resources.add_resource(r_type, ALL_RESOURCES)

    return method, resources
Beispiel #8
0
def get_main(a):
    # a = args passed from cli
    # Check if -A/--all-namespaces is set
    # else, Set the namespace
    # -n/--namespace takes precedence over current project
    if a.all_namespaces is True:
        ns = '_all'
    else:
        if a.namespace is not None:
            ns = a.namespace
        elif Config().project is not None:
            ns = Config().project
        else:
            ns = None

    # We collect the resources types/names in this dict
    # e.g for `get pod httpd1 httpd2` this will look like:
    #   objects = { 'pod': ['httpd1', 'httpd2'] }
    # e.g, for `get pod,svc` this will look like:
    #   objects = { 'pod': ['_all'], 'service': ['_all'] }
    objects = {}

    last_object = []
    for o in a.objects:
        # Case where we have a '/'
        # e.g omg get pod/httpd
        if '/' in o:
            if not last_object:
                pre = o.split('/')[0]
                r_type = map_res(pre)['type']
                r_name = o.split('/')[1]
                # If its a valid resource type, apppend it to objects
                if r_type is not None:
                    if r_type in objects:
                        objects[r_type].append(r_name)
                    else:
                        objects[r_type] = [r_name]
                else:
                    print("[ERROR] Invalid object type: ", pre)
                    sys.exit(1)
            else:
                # last_object was set, meaning this should be object name
                print(
                    "[ERROR] There is no need to specify a resource type as a separate argument when passing arguments in resource/name form"
                )
                sys.exit(1)

        # Case where we have a ',' e.g `get dc,svc,pod httpd`
        # These all will be resource_types, not names,
        # resource_name will come it next iteration (if any)
        elif ',' in o:
            if not last_object:
                r_types = o.split(',')
                for rt in r_types:
                    check_rt = map_res(rt)
                    if check_rt is None:
                        print("[ERROR] Invalid object type: ", rt)
                        sys.exit(1)
                    else:
                        last_object.append(check_rt['type'])
            else:
                # last_object was set, meaning this should be object name
                print("[ERROR] Invalid resources to get: ", a.objects)
                sys.exit(1)

        # Simple word (without , or /)
        # If last_object was not set, means this is a resource_type
        elif not last_object:
            check_rt = map_res(o)
            if check_rt is not None:
                last_object = [check_rt['type']]
            else:
                print("[ERROR] Invalid resource type to get: ", o)
        # Simple word (without , or /)
        # If the last_object was set, means we got resource_type last time,
        # and this should be a resource_name.
        elif last_object:
            for rt in last_object:
                if rt in objects:
                    objects[rt].append(o)
                else:
                    objects[rt] = [o]
            last_object = []
        else:
            # Should never happen
            print("[ERROR] Invalid resources to get: ", o)
            sys.exit(1)
    # If after going through all the args, we have last_object set
    # means we didn't get a resource_name for these resource_type.
    # i.e, we need to get all names
    if last_object:
        for rt in last_object:
            check_rt = map_res(rt)
            objects[check_rt['type']] = ['_all']

    # Debug
    # print(objects)

    # Object based routing
    # i.e, call the get function for all the requested types
    # then call the output function or simply print if its yaml/json
    for rt in objects.keys():
        rt_info = map_res(rt)
        get_func = rt_info['get_func']
        getout_func = rt_info['getout_func']
        yaml_loc = rt_info['yaml_loc']
        need_ns = rt_info['need_ns']

        # Call the get function to get the resoruces
        res = get_func(rt, ns, objects[rt], yaml_loc, need_ns)

        # Error out if no objects/resources were collected
        if len(res) == 0:
            print('No resources found for type "%s" found in namespace "%s" ' %
                  (rt, ns))
        # Yaml dump if -o yaml
        elif a.output == 'yaml':
            if len(res) == 1:
                print(yaml.dump(res[0]['res']))
            elif len(res) > 1:
                print(
                    yaml.dump({
                        'apiVersion': 'v1',
                        'items': [cp['res'] for cp in res]
                    }))
        # Json dump if -o json
        elif a.output == 'json':
            if len(res) == 1:
                print(json.dumps(res[0]['res'], indent=4))
            elif len(res) > 1:
                print(
                    json.dumps(
                        {
                            'apiVersion': 'v1',
                            'items': [cp['res'] for cp in res]
                        },
                        indent=4))
        # Call the respective output fucntion if -o is not set or -o wide
        elif a.output in [None, 'wide']:
            # If we displaying more than one resource_type,
            # we need to display resource_type with the name (type/name)
            if len(objects) > 1:
                show_type = True
            else:
                show_type = False
            getout_func(rt, ns, res, a.output, show_type)
Beispiel #9
0
def get_main(objects, output, namespace, all_namespaces, show_labels):
    # Check if -A/--all-namespaces is set
    # else, Set the namespace
    # -n/--namespace takes precedence over current project
    if all_namespaces is True:
        ns = "_all"
    else:
        if namespace is not None:
            ns = namespace
        elif Config().project is not None:
            ns = Config().project
        else:
            ns = None

    # Parse get args and get normalized resources to get
    try:
        _, resource_list = parse.parse_get_resources(objects)
    except parse.ResourceParseError as e:
        print(e)
        return

    # Call the get function for all the requested types
    # then call the output function or simply print if its yaml/json

    # Flag to mark if we have already printed something
    printed_something = False

    for r_type, r_name in resource_list:

        res = get_resources(r_type, r_name, ns)

        if len(res) > 0:
            # If printing multiple objects, add a blank line between each
            if printed_something:
                print("")
            # Yaml dump if -o yaml
            if output == "yaml":
                if len(res) == 1:
                    print(yaml.dump(res[0]["res"]))
                elif len(res) > 1:
                    print(
                        yaml.dump({
                            "apiVersion": "v1",
                            "items": [cp["res"] for cp in res]
                        }))
            # Json dump if -o json
            elif output == "json":
                if len(res) == 1:
                    print(json.dumps(res[0]["res"], indent=4))
                elif len(res) > 1:
                    print(
                        json.dumps(
                            {
                                "apiVersion": "v1",
                                "items": [cp["res"] for cp in res]
                            },
                            indent=4,
                        ))
            # Call the respective output function if -o is not set or -o wide
            elif output in [None, "wide"]:
                # If we displaying more than one resource_type,
                # we need to display resource_type with the name (type/name)
                if len(resource_list) > 1:
                    show_type = True
                else:
                    show_type = False
                getout_func = map_res(r_type)["getout_func"]
                getout_func(r_type, ns, res, output, show_type, show_labels)

            # We printed something
            printed_something = True

    # Error out if nothing was printed
    if not printed_something:
        print("No resources found in %s namespace" % ns)
def get_mc(m):
    mc_map = map_res('machineconfig')
    mcs = from_yaml( rt = mc_map['type'], ns = None, names = m,
        yaml_loc = mc_map['yaml_loc'], need_ns = False)
    return([mc['res'] for mc in mcs])
Beispiel #11
0
def get_main(objects, output, namespace, all_namespaces):
    # a = args passed from cli
    # Check if -A/--all-namespaces is set
    # else, Set the namespace
    # -n/--namespace takes precedence over current project
    if all_namespaces is True:
        ns = '_all'
    else:
        if namespace is not None:
            ns = namespace
        elif Config().project is not None:
            ns = Config().project
        else:
            ns = None

    try:
        get_method, resource_list = parse.parse_get_resources(objects)
    except parse.ResourceParseError as e:
        print(e)
        return

    # Object based routing
    # i.e, call the get function for all the requested types
    # then call the output function or simply print if its yaml/json

    # If printing multiple objects, add a blank line between each
    mult_objs_blank_line = False

    for r_type, res_set in resource_list:
        rt_info = map_res(r_type)
        get_func = rt_info['get_func']
        getout_func = rt_info['getout_func']
        yaml_loc = rt_info['yaml_loc']
        need_ns = rt_info['need_ns']

        # Call the get function to get the resoruces
        res = get_func(r_type, ns, res_set, yaml_loc, need_ns)

        # Error out if no objects/resources were collected
        if len(res) == 0 and get_method is not parse.Method.ALL:
            print('No resources found for type "%s" in %s namespace' %
                  (r_type, ns))
        elif len(res) > 0:
            # If printing multiple objects, add a blank line between each
            if mult_objs_blank_line:
                print('')
            # Yaml dump if -o yaml
            if output == 'yaml':
                if len(res) == 1:
                    print(yaml.dump(res[0]['res']))
                elif len(res) > 1:
                    print(
                        yaml.dump({
                            'apiVersion': 'v1',
                            'items': [cp['res'] for cp in res]
                        }))
            # Json dump if -o json
            elif output == 'json':
                if len(res) == 1:
                    print(json.dumps(res[0]['res'], indent=4))
                elif len(res) > 1:
                    print(
                        json.dumps(
                            {
                                'apiVersion': 'v1',
                                'items': [cp['res'] for cp in res]
                            },
                            indent=4))
            # Call the respective output function if -o is not set or -o wide
            elif output in [None, 'wide']:
                # If we displaying more than one resource_type,
                # we need to display resource_type with the name (type/name)

                if len(resource_list) > 1:
                    show_type = True
                else:
                    show_type = False
                getout_func(r_type, ns, res, output, show_type)
            # Flag to print multiple objects
            if not mult_objs_blank_line:
                mult_objs_blank_line = True

    # Error out once if multiple objects/resources requested and none collected
    if not mult_objs_blank_line and get_method == parse.Method.ALL:
        print('No resources found in %s namespace' % ns)
Beispiel #12
0
def _validate_type(t):
    checked_type = map_res(t)
    if checked_type is None:
        raise ResourceParseError("[ERROR] Invalid object type: " + t)
    else:
        return checked_type['type']