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
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)
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")