Ejemplo n.º 1
0
 def kubernetes_create_connection(address, *args, **kwargs):
     dns_name = address[0]
     if isinstance(dns_name, bytes):
         dns_name = dns_name.decode()
     dns_name = dns_name.split(".")
     if len(dns_name) != 3 or dns_name[2] != "kubernetes":
         return socket_create_connection(address, *args, **kwargs)
     pf = portforward(api.connect_get_namespaced_pod_portforward,
                      dns_name[0],
                      dns_name[1],
                      ports=str(address[1]))
     return pf.socket(address[1])
Ejemplo n.º 2
0
 def kubernetes_create_connection(address, *args, **kwargs):
     dns_name = address[0]
     if isinstance(dns_name, bytes):
         dns_name = dns_name.decode()
     dns_name = dns_name.split(".")
     if dns_name[-1] != 'kubernetes':
         return socket_create_connection(address, *args, **kwargs)
     if len(dns_name) not in (3, 4):
         raise RuntimeError("Unexpected kubernetes DNS name.")
     namespace = dns_name[-2]
     name = dns_name[0]
     port = address[1]
     if len(dns_name) == 4:
         if dns_name[1] in ('svc', 'service'):
             service = api_instance.read_namespaced_service(name, namespace)
             for service_port in service.spec.ports:
                 if service_port.port == port:
                     port = service_port.target_port
                     break
             else:
                 raise RuntimeError("Unable to find service port: %s" %
                                    port)
             label_selector = []
             for key, value in service.spec.selector.items():
                 label_selector.append("%s=%s" % (key, value))
             pods = api_instance.list_namespaced_pod(
                 namespace, label_selector=",".join(label_selector))
             if not pods.items:
                 raise RuntimeError("Unable to find service pods.")
             name = pods.items[0].metadata.name
             if isinstance(port, str):
                 for container in pods.items[0].spec.containers:
                     for container_port in container.ports:
                         if container_port.name == port:
                             port = container_port.container_port
                             break
                     else:
                         continue
                     break
                 else:
                     raise RuntimeError(
                         "Unable to find service port name: %s" % port)
         elif dns_name[1] != 'pod':
             raise RuntimeError("Unsupported resource type: %s" %
                                dns_name[1])
     pf = portforward(api_instance.connect_get_namespaced_pod_portforward,
                      name,
                      namespace,
                      ports=str(port))
     return pf.socket(port)
Ejemplo n.º 3
0
    def connect(self):
        corev1 = client.CoreV1Api(self.api_client)
        service = corev1.read_namespaced_service(self.service, self.namespace)

        label_selector = ','.join(k + '=' + v
                                  for k, v in service.spec.selector.items())

        pods = corev1.list_namespaced_pod(
            namespace=self.namespace,
            label_selector=label_selector,
        )

        self.port_forwarder = portforward(
            corev1.connect_get_namespaced_pod_portforward,
            pods.items[0].metadata.name,
            self.namespace,
            ports=str(self.remote_port),
        )
Ejemplo n.º 4
0
    def test_portforward_raw(self):
        client = api_client.ApiClient(configuration=self.config)
        api = core_v1_api.CoreV1Api(client)

        with open(os.path.join(os.path.dirname(__file__),
                               'port_server.py')) as fh:
            port_server_py = fh.read()
        name = 'portforward-raw-' + short_uuid()
        resp = api.create_namespaced_config_map(
            body={
                'apiVersion': 'v1',
                'kind': 'ConfigMap',
                'metadata': {
                    'name': name,
                },
                'data': {
                    'port-server.py': port_server_py,
                }
            },
            namespace='default',
        )
        resp = api.create_namespaced_pod(
            body={
                'apiVersion': 'v1',
                'kind': 'Pod',
                'metadata': {
                    'name': name
                },
                'spec': {
                    'containers': [
                        {
                            'name':
                            'port-server',
                            'image':
                            'python',
                            'command': [
                                '/opt/port-server.py',
                                '1234',
                                '1235',
                            ],
                            'volumeMounts': [
                                {
                                    'name': 'port-server',
                                    'mountPath': '/opt',
                                    'readOnly': True,
                                },
                            ],
                            'startupProbe': {
                                'tcpSocket': {
                                    'port': 1234,
                                },
                            },
                        },
                    ],
                    'volumes': [
                        {
                            'name': 'port-server',
                            'configMap': {
                                'name': name,
                                'defaultMode': 0o777,
                            },
                        },
                    ],
                },
            },
            namespace='default',
        )
        self.assertEqual(name, resp.metadata.name)
        self.assertTrue(resp.status.phase)

        while True:
            resp = api.read_namespaced_pod(name=name, namespace='default')
            self.assertEqual(name, resp.metadata.name)
            self.assertTrue(resp.status.phase)
            if resp.status.phase != 'Pending':
                break
            time.sleep(1)
        self.assertEqual(resp.status.phase, 'Running')

        pf = portforward(api.connect_get_namespaced_pod_portforward,
                         name,
                         'default',
                         ports='1234,1235,1236')
        self.assertTrue(pf.connected)
        sock1234 = pf.socket(1234)
        sock1235 = pf.socket(1235)
        sock1234.setblocking(True)
        sock1235.setblocking(True)
        sent1234 = b'Test port 1234 forwarding...'
        sent1235 = b'Test port 1235 forwarding...'
        sock1234.sendall(sent1234)
        sock1235.sendall(sent1235)
        reply1234 = b''
        reply1235 = b''
        while True:
            rlist = []
            if sock1234.fileno() != -1:
                rlist.append(sock1234)
            if sock1235.fileno() != -1:
                rlist.append(sock1235)
            if not rlist:
                break
            r, _w, _x = select.select(rlist, [], [], 1)
            if not r:
                break
            if sock1234 in r:
                data = sock1234.recv(1024)
                self.assertNotEqual(data, b'', "Unexpected socket close")
                reply1234 += data
            if sock1235 in r:
                data = sock1235.recv(1024)
                self.assertNotEqual(data, b'', "Unexpected socket close")
                reply1235 += data
        self.assertEqual(reply1234, sent1234)
        self.assertEqual(reply1235, sent1235)
        self.assertTrue(pf.connected)

        sock = pf.socket(1236)
        self.assertRaises(socket.error, sock.sendall, b'This should fail...')
        self.assertIsNotNone(pf.error(1236))
        sock.close()

        for sock in (sock1234, sock1235):
            self.assertTrue(pf.connected)
            sent = b'Another test using fileno %s' % str(
                sock.fileno()).encode()
            sock.sendall(sent)
            reply = b''
            while True:
                r, _w, _x = select.select([sock], [], [], 1)
                if not r:
                    break
                data = sock.recv(1024)
                self.assertNotEqual(data, b'', "Unexpected socket close")
                reply += data
            self.assertEqual(reply, sent)
            sock.close()
        time.sleep(1)
        self.assertFalse(pf.connected)
        self.assertIsNone(pf.error(1234))
        self.assertIsNone(pf.error(1235))

        resp = api.delete_namespaced_pod(name=name, namespace='default')
        resp = api.delete_namespaced_config_map(name=name, namespace='default')
Ejemplo n.º 5
0
def portforward_commands(api_instance):
    name = 'portforward-example'
    resp = None
    try:
        resp = api_instance.read_namespaced_pod(name=name, namespace='default')
    except ApiException as e:
        if e.status != 404:
            print("Unknown error: %s" % e)
            exit(1)

    if not resp:
        print("Pod %s does not exist. Creating it..." % name)
        pod_manifest = {
            'apiVersion': 'v1',
            'kind': 'Pod',
            'metadata': {
                'name': name
            },
            'spec': {
                'containers': [{
                    'image': 'nginx',
                    'name': 'nginx',
                }]
            }
        }
        api_instance.create_namespaced_pod(body=pod_manifest,
                                           namespace='default')
        while True:
            resp = api_instance.read_namespaced_pod(name=name,
                                                    namespace='default')
            if resp.status.phase != 'Pending':
                break
            time.sleep(1)
        print("Done.")

    pf = portforward(
        api_instance.connect_get_namespaced_pod_portforward,
        name,
        'default',
        ports='80',
    )
    http = pf.socket(80)
    http.setblocking(True)
    http.sendall(b'GET / HTTP/1.1\r\n')
    http.sendall(b'Host: 127.0.0.1\r\n')
    http.sendall(b'Connection: close\r\n')
    http.sendall(b'Accept: */*\r\n')
    http.sendall(b'\r\n')
    response = b''
    while True:
        select.select([http], [], [])
        data = http.recv(1024)
        if not data:
            break
        response += data
    http.close()
    print(response.decode('utf-8'))
    error = pf.error(80)
    if error is None:
        print("No port forward errors on port 80.")
    else:
        print("Port 80 has the following error: %s" % error)

    # Monkey patch socket.create_connection which is used by http.client and
    # urllib.request. The same can be done with urllib3.util.connection.create_connection
    # if the "requests" package is used.
    socket_create_connection = socket.create_connection

    def kubernetes_create_connection(address, *args, **kwargs):
        dns_name = address[0]
        if isinstance(dns_name, bytes):
            dns_name = dns_name.decode()
        dns_name = dns_name.split(".")
        if dns_name[-1] != 'kubernetes':
            return socket_create_connection(address, *args, **kwargs)
        if len(dns_name) not in (3, 4):
            raise RuntimeError("Unexpected kubernetes DNS name.")
        namespace = dns_name[-2]
        name = dns_name[0]
        port = address[1]
        if len(dns_name) == 4:
            if dns_name[1] in ('svc', 'service'):
                service = api_instance.read_namespaced_service(name, namespace)
                for service_port in service.spec.ports:
                    if service_port.port == port:
                        port = service_port.target_port
                        break
                else:
                    raise RuntimeError("Unable to find service port: %s" %
                                       port)
                label_selector = []
                for key, value in service.spec.selector.items():
                    label_selector.append("%s=%s" % (key, value))
                pods = api_instance.list_namespaced_pod(
                    namespace, label_selector=",".join(label_selector))
                if not pods.items:
                    raise RuntimeError("Unable to find service pods.")
                name = pods.items[0].metadata.name
                if isinstance(port, str):
                    for container in pods.items[0].spec.containers:
                        for container_port in container.ports:
                            if container_port.name == port:
                                port = container_port.container_port
                                break
                        else:
                            continue
                        break
                    else:
                        raise RuntimeError(
                            "Unable to find service port name: %s" % port)
            elif dns_name[1] != 'pod':
                raise RuntimeError("Unsupported resource type: %s" %
                                   dns_name[1])
        pf = portforward(api_instance.connect_get_namespaced_pod_portforward,
                         name,
                         namespace,
                         ports=str(port))
        return pf.socket(port)

    socket.create_connection = kubernetes_create_connection

    # Access the nginx http server using the
    # "<pod-name>.pod.<namespace>.kubernetes" dns name.
    response = urllib_request.urlopen('http://%s.pod.default.kubernetes' %
                                      name)
    html = response.read().decode('utf-8')
    response.close()
    print('Status Code: %s' % response.code)
    print(html)