def make_ingress(
        name,
        routespec,
        target,
        data
):
    """
    Returns an ingress, service, endpoint object that'll work for this service
    """

    # move beta imports here,
    # which are more sensitive to kubernetes version
    # and will change when they move out of beta
    from kubernetes.client.models import (
        V1beta1Ingress, V1beta1IngressSpec, V1beta1IngressRule,
        V1beta1HTTPIngressRuleValue, V1beta1HTTPIngressPath,
        V1beta1IngressBackend,
    )

    meta = V1ObjectMeta(
        name=name,
        annotations={
            'hub.jupyter.org/proxy-data': json.dumps(data),
            'hub.jupyter.org/proxy-routespec': routespec,
            'hub.jupyter.org/proxy-target': target
        },
        labels={
            'heritage': 'jupyterhub',
            'component': 'singleuser-server',
            'hub.jupyter.org/proxy-route': 'true'
        }
    )

    if routespec.startswith('/'):
        host = None
        path = routespec
    else:
        host, path = routespec.split('/', 1)

    target_parts = urlparse(target)

    target_ip = target_parts.hostname
    target_port = target_parts.port

    target_is_ip = re.match('^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$', target_ip) is not None

    # Make endpoint object
    if target_is_ip:
        endpoint = V1Endpoints(
            kind='Endpoints',
            metadata=meta,
            subsets=[
                V1EndpointSubset(
                    addresses=[V1EndpointAddress(ip=target_ip)],
                    ports=[V1EndpointPort(port=target_port)]
                )
            ]
        )
    else:
        endpoint = None

    # Make service object
    if target_is_ip:
        service = V1Service(
            kind='Service',
            metadata=meta,
            spec=V1ServiceSpec(
                type='ClusterIP',
                external_name='',
                ports=[V1ServicePort(port=target_port, target_port=target_port)]
            )
        )
    else:
        service = V1Service(
            kind='Service',
            metadata=meta,
            spec=V1ServiceSpec(
                type='ExternalName',
                external_name=target_ip,
                cluster_ip='',
                ports=[V1ServicePort(port=target_port, target_port=target_port)],
            ),
        )

    # Make Ingress object
    ingress = V1beta1Ingress(
        kind='Ingress',
        metadata=meta,
        spec=V1beta1IngressSpec(
            rules=[V1beta1IngressRule(
                host=host,
                http=V1beta1HTTPIngressRuleValue(
                    paths=[
                        V1beta1HTTPIngressPath(
                            path=path,
                            backend=V1beta1IngressBackend(
                                service_name=name,
                                service_port=target_port
                            )
                        )
                    ]
                )
            )]
        )
    )

    return endpoint, service, ingress
Returns an ingress, service, endpoint object that'll work for this service