Example #1
0
def make_ingress(name, routespec, target, labels, 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
    # because of the API changes in 1.16, the import is tried conditionally
    # to keep compatibility with older K8S versions

    try:
        from kubernetes.client.models import (
            ExtensionsV1beta1Ingress,
            ExtensionsV1beta1IngressSpec,
            ExtensionsV1beta1IngressRule,
            ExtensionsV1beta1HTTPIngressRuleValue,
            ExtensionsV1beta1HTTPIngressPath,
            ExtensionsV1beta1IngressBackend,
        )
    except ImportError:
        from kubernetes.client.models import (
            V1beta1Ingress as ExtensionsV1beta1Ingress, V1beta1IngressSpec as
            ExtensionsV1beta1IngressSpec, V1beta1IngressRule as
            ExtensionsV1beta1IngressRule, V1beta1HTTPIngressRuleValue as
            ExtensionsV1beta1HTTPIngressRuleValue, V1beta1HTTPIngressPath as
            ExtensionsV1beta1HTTPIngressPath, V1beta1IngressBackend as
            ExtensionsV1beta1IngressBackend)

    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=labels,
    )

    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(r'^\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 = ExtensionsV1beta1Ingress(
        kind='Ingress',
        metadata=meta,
        spec=ExtensionsV1beta1IngressSpec(rules=[
            ExtensionsV1beta1IngressRule(
                host=host,
                http=ExtensionsV1beta1HTTPIngressRuleValue(paths=[
                    ExtensionsV1beta1HTTPIngressPath(
                        path=path,
                        backend=ExtensionsV1beta1IngressBackend(
                            service_name=name, service_port=target_port))
                ]))
        ]))

    return endpoint, service, ingress
Example #2
0
def make_ingress(name,
                 routespec,
                 target,
                 data,
                 extra_ingress_annotations={},
                 tls_secret_name=None,
                 default_host=None):
    """
    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 (
        ExtensionsV1beta1Ingress, ExtensionsV1beta1IngressSpec,
        ExtensionsV1beta1IngressRule, ExtensionsV1beta1HTTPIngressRuleValue,
        ExtensionsV1beta1HTTPIngressPath, ExtensionsV1beta1IngressBackend,
        ExtensionsV1beta1IngressTLS)

    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 = default_host
        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)
                ],
            ),
        )

    tls = []
    if tls_secret_name:
        tls = [
            ExtensionsV1beta1IngressTLS(hosts=[host],
                                        secret_name=tls_secret_name)
        ]

    # Make Ingress object
    ingress = ExtensionsV1beta1Ingress(
        kind='Ingress',
        metadata=V1ObjectMeta(name=meta.name,
                              annotations={
                                  **extra_ingress_annotations,
                                  **meta.annotations
                              },
                              labels=meta.labels),
        spec=ExtensionsV1beta1IngressSpec(
            tls=tls,
            rules=[
                ExtensionsV1beta1IngressRule(
                    host=host,
                    http=ExtensionsV1beta1HTTPIngressRuleValue(paths=[
                        ExtensionsV1beta1HTTPIngressPath(
                            path=path,
                            backend=ExtensionsV1beta1IngressBackend(
                                service_name=name, service_port=target_port))
                    ]))
            ]))

    return endpoint, service, ingress