Example #1
0
def get_virtual_service(virtual_service_name: str, ns: str = "default",
                        version: str = "networking.istio.io/v1alpha3",
                        configuration: Configuration = None,
                        secrets: Secrets = None) -> Dict[str, Any]:
    """
    Get a virtual service identified by `name`

    See https://istio.io/docs/reference/config/istio.networking.v1alpha3/#VirtualService
    """  # noqa: E501
    api = create_k8s_api_client(configuration, secrets)
    url = "/apis/{}/namespaces/{}/virtualservices/{}".format(
        version, ns, virtual_service_name)

    try:
        data, status, headers = api.call_api(
            url,
            "GET",
            header_params={
                "Accept": "application/json"
            },
            auth_settings=['BearerToken'],
            _preload_content=False
        )
    except ApiException as x:
        body = x.body.read(decode_content=True)
        if x.headers.get("Content-Type") == "application/json":
            body = json.loads(body)
        return {
            "status": x.status,
            "body": body,
            "headers": dict(**x.headers)
        }

    return {
        "status": status,
        "body": json.loads(data.read(decode_content=True)),
        "headers": dict(**headers)
    }
Example #2
0
def set_fault(
        virtual_service_name: str,
        routes: List[Dict[str, str]],  # noqa: C901
        fault: Dict[str, Any],
        ns: str = "default",
        version: str = "networking.istio.io/v1alpha3",
        configuration: Configuration = None,
        secrets: Secrets = None) -> Dict[str, Any]:
    """
    Setfault injection on the virtual service identified by `name`

    The `fault` argument must be the object passed as the `spec` property
    of a virtual service resource.

    If a fault already exists, it is updated with the new specification.

    See https://istio.io/docs/reference/config/istio.networking.v1alpha3/#HTTPFaultInjection
    """  # noqa: E501
    result = get_virtual_service(virtual_service_name,
                                 ns=ns,
                                 version=version,
                                 configuration=configuration,
                                 secrets=secrets)
    if result["status"] != 200:
        raise ActivityFailed("Virtual Service '{}' does not exist: {}".format(
            virtual_service_name, str(result["body"])))

    # which destinations to we target?
    expected_destinations = set()
    for route in routes:
        if "destination" in route:
            destination = route["destination"]
            expected_destinations.add(
                (destination["host"], destination.get("subset")))

    # inject a fault block into the targets
    spec = deepcopy(result["body"]["spec"]["http"])
    for i in spec:
        if "route" in i:
            for route in i["route"]:
                if "destination" in route:
                    destination = route["destination"]
                    # not mandatory in response
                    # https://istio.io/latest/docs/reference/config/networking/virtual-service/#Destination  # noqa: E501
                    target = (destination["host"], destination.get("subset"))
                    if target in expected_destinations:
                        i["fault"] = fault
                        break

    api = create_k8s_api_client(configuration, secrets)

    url = "/apis/{}/namespaces/{}/virtualservices/{}".format(
        version, ns, virtual_service_name)
    payload = {
        "apiVersion": version,
        "kind": "VirtualService",
        "metadata": {
            "name": virtual_service_name
        },
        "spec": {
            "http": spec
        }
    }

    try:
        data, status, headers = api.call_api(
            url,
            "PATCH",
            header_params={
                "Content-Type": "application/merge-patch+json",
                "Accept": "application/json"
            },
            body=payload,
            auth_settings=['BearerToken'],
            _preload_content=False)
    except ApiException as x:
        body = x.body
        if x.headers.get("Content-Type") == "application/json":
            body = json.loads(body)
        return {"status": x.status, "body": body, "headers": dict(**x.headers)}

    return {
        "status": status,
        "body": json.loads(data.read(decode_content=True)),
        "headers": dict(**headers)
    }
Example #3
0
def unset_fault(virtual_service_name: str,
                routes: List[Dict[str, str]],
                ns: str = "default",
                version: str = "networking.istio.io/v1alpha3",
                configuration: Configuration = None,
                secrets: Secrets = None) -> Dict[str, Any]:
    """
    Unset fault injection from the virtual service identified by `name`

    The `fault` argument must be the object passed as the `spec` property
    of a virtual service resource.

    See https://istio.io/docs/reference/config/istio.networking.v1alpha3/#HTTPFaultInjection
    """  # noqa: E501
    result = get_virtual_service(virtual_service_name,
                                 ns=ns,
                                 version=version,
                                 configuration=configuration,
                                 secrets=secrets)
    if result["status"] != 200:
        raise ActivityFailed("Virtual Service '{}' does not exist: {}".format(
            virtual_service_name, str(result["body"])))

    # which destinations to we target?
    expected_destinations = set()
    for route in routes:
        if "destination" in route:
            destination = route["destination"]
            expected_destinations.add(
                (destination["host"], destination["subset"]))

    # remove fault block from the targets
    destinations = set()
    spec = deepcopy(result["body"]["spec"]["http"])
    for i in spec:
        if "route" in i:
            for route in i["route"]:
                if "destination" in route:
                    destination = route["destination"]
                    target = (destination["host"], destination["subset"])
                    if target in expected_destinations:
                        i.pop("fault", None)

    api = create_k8s_api_client(configuration, secrets)

    url = "/apis/{}/namespaces/{}/virtualservices/{}".format(
        version, ns, virtual_service_name)
    payload = {
        "apiVersion": version,
        "kind": "VirtualService",
        "metadata": {
            "name": virtual_service_name
        },
        "spec": {
            "http": spec
        }
    }

    data, status, headers = api.call_api(url,
                                         "PATCH",
                                         header_params={
                                             "Content-Type":
                                             "application/merge-patch+json",
                                             "Accept": "application/json"
                                         },
                                         body=payload,
                                         auth_settings=['BearerToken'],
                                         _preload_content=False)

    return {
        "status": status,
        "body": json.loads(data.read(decode_content=True)),
        "headers": dict(**headers)
    }