Пример #1
0
    def _generate_spec(self, port_spec, selector, owner):
        # generate port spec
        k8s_ports = []

        for port in port_spec or []:
            p = swagger_client.V1ServicePort()
            p.port = int(port["port"])
            p.name = "port-{}".format(p.port)
            p.target_port = int(port["target_port"])
            if "node_port" in port:
                p.node_port = port["node_port"]
            k8s_ports.append(p)

        # service spec
        srv_spec = swagger_client.V1ServiceSpec()
        srv_spec.ports = k8s_ports
        srv_spec.selector = selector
        srv_spec.type = "ClusterIP"

        # generate meta
        meta = swagger_client.V1ObjectMeta()
        meta.name = self.name

        meta.labels = {
            "srv": self.name,
            "tier": "deployment",
            "role": "user"
        }
        meta.annotations = {}

        self.ax_meta = {
            "name": self.name,
            "application": self.namespace,
            "owner": owner,
            "port_spec": port_spec,
            "selector": selector
        }

        # finally the service
        srv = swagger_client.V1Service()
        srv.metadata = meta
        srv.spec = srv_spec

        AXResource.set_ax_meta(srv, self.ax_meta)

        return srv
Пример #2
0
    def _create(self, appname, port_spec, layer7, type):

        srv = swagger_client.V1Service()
        srv.metadata = swagger_client.V1ObjectMeta()
        srv.metadata.name = self.name
        srv.metadata.labels = {
            "app": appname,
            "tier": "deployment",
            "role": "user"
        }
        if layer7:
            srv.metadata.annotations = {
                "service.beta.kubernetes.io/aws-load-balancer-backend-protocol": "http"
            }

        spec = swagger_client.V1ServiceSpec()
        spec.selector = {
            'app': appname
        }
        spec.type = type
        spec.ports = []

        for p in port_spec:
            port = swagger_client.V1ServicePort()
            port.name = p["name"]
            port.port = p["port"]
            port.target_port = p["containerPort"]
            spec.ports.append(port)

        srv.spec = spec

        @parse_kubernetes_exception
        @retry(retry_on_exception=raise_apiexception_else_retry,
               wait_exponential_multiplier=100,
               stop_max_attempt_number=10)
        def create_in_provider(service):
            client = self.get_k8s_client()
            client.api.create_namespaced_service(service, self.namespace)

        create_in_provider(srv)
Пример #3
0
def create_webhook():
    """
    Create a kubernetes service load balancer connecting external traffic to
    axops, with a range of trusted ips
    Data input format:
    {
        "port_spec": [
            {
                "name": "webhook",
                "port": 8443,
                "targetPort": 8087
            }
        ],
        "ip_ranges": ["0.0.0.0/0"]
    }
    :return:
    {
        "ingress": "xxxxxx.us-west-2.elb.amazonaws.com",
        "detail": V1Service
    }
    """
    data = request.get_json()
    port_spec = data.get("port_spec", None)
    ip_ranges = data.get("ip_ranges", ["0.0.0.0/0"])
    if not port_spec:
        raise AXIllegalArgumentException("No port spec provided")
    webhook_svc_name = "axops-webhook"
    srv = swagger_client.V1Service()
    srv.metadata = swagger_client.V1ObjectMeta()
    srv.metadata.name = webhook_svc_name
    srv.metadata.labels = {
        "app": webhook_svc_name,
        "tier": "platform",
        "role": "axcritical"
    }
    spec = swagger_client.V1ServiceSpec()
    spec.selector = {
        'app': "axops-deployment"
    }
    spec.type = "LoadBalancer"
    spec.ports = port_spec
    spec.load_balancer_source_ranges = ip_ranges

    srv.spec = spec

    # Don't have to retry here as creating webhook is a manual process
    # and it is fair to throw proper error message to user and have them
    # retry manually
    need_update = False
    try:
        kubectl.api.create_namespaced_service(body=srv, namespace="axsys")
    except ApiException as ae:
        if ae.status == 409:
            need_update = True
        elif ae.status == 422:
            raise AXIllegalArgumentException("Unable to create webhook due to invalid argument", detail=str(ae))
        else:
            raise AXPlatformException("Unable to create webhook due to Kubernetes internal error", detail=str(ae))
    except Exception as e:
        raise AXPlatformException("Unable to create webhook", detail=str(e))

    if need_update:
        update_body = {
            "spec": {
                "ports": port_spec,
                "load_balancer_source_ranges": ip_ranges
            }
        }
        try:
            kubectl.api.patch_namespaced_service(body=update_body, namespace="axsys", name=webhook_svc_name)
        except Exception as e:
            raise AXPlatformException("Unable to update webhook", detail=str(e))

    trail = 0
    rst = {
        "port_spec": port_spec,
        "ip_ranges": ip_ranges
    }
    while trail < 60:
        time.sleep(3)
        try:
            svc = kubectl.api.read_namespaced_service_status(namespace="axsys", name=webhook_svc_name)
            if svc.status.load_balancer and svc.status.load_balancer.ingress:
                rst["hostname"] = svc.status.load_balancer.ingress[0].hostname
                return jsonify(rst)
        except ApiException:
            pass
        trail += 1
    try:
        kubectl.api.delete_namespaced_service(namespace="axsys", name=webhook_svc_name)
    except ApiException as ae:
        if ae.status != 404:
            raise ae
    raise AXPlatformException("Webhook creation timeout")