# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Config for routing to a CloudRun service using the SNI gateway.
#
# This will be automated as a controller, but useful to see the actual config and also
# debug or create custom entries. The controller will operate on 'create if it doesn't exist' mode, i.e. users can
# either create their own config (ahead of time) or edit or patch the created config.

# K_SERVICE is the first component of the CloudRun URL - example fortio-cr-icq63pqnqq-uc
# WORKLOAD_NAME is the name of the CloudRun service - in this case fortio-cr
# WORKLOAD_NAMESPACE is the k8s namespace where the CR service is 'attached'

# TODO: replace K_SERVICE with K_SERVICE_BASE_URL, WORKLOAD_NAME with K_SERVICE

# Each CloudRun service is mapped to one Service. The new K8S Gateway API is
# not using DestinationRule-style subsetting, we want to represent each CR region
# as a separate subset that can be selected with the Gateawy API or VirtualService.
apiVersion: v1
kind: Service
metadata:
  name: ${K_SERVICE}
  namespace: ${WORKLOAD_NAMESPACE}
  labels:
    service.istio.io/canonical-name: ${WORKLOAD_NAME}
    mesh-cloudrun: ${WORKLOAD_NAME}
spec:
  # Service name matches the actual service name in CloudRun.
  # This is used to acccess only the service in cloudrun, in a region. Can be used as a subset
  # TODO: auto-create this if it doesn't exist, in SNIGate
  ports:
    # Port corresponds to the CloudRun app port - default is 8080
    # TODO: support custom ports in cloudrun
    - port: 8080
      name: http
      # TargetPort is the fixed port for the SNI router.
      targetPort: 15443
  selector:
    app: ${WORKLOAD_NAME}
---
# When doing auto-registration, the Service and VirtualService should be 'create if it doesn't exist', i.e. user can
# customize or replace it, we'll just create the initial/default version.
apiVersion: v1
kind: Service
metadata:
  name: ${WORKLOAD_NAME}
  namespace: ${WORKLOAD_NAMESPACE}
  labels:
    service.istio.io/canonical-name: ${WORKLOAD_NAME}
    mesh-cloudrun: ${WORKLOAD_NAME}
spec:
  ports:
    - port: 80
      name: http
      targetPort: 15443
    - port: 8080
      name: http-8080
      targetPort: 15443
    - port: 8079
      name: grpc
      targetPort: 15443
  selector:
    app: ${WORKLOAD_NAME}
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ${WORKLOAD_NAME}
  namespace: ${WORKLOAD_NAMESPACE}
  labels:
    service.istio.io/canonical-name: ${WORKLOAD_NAME}
    mesh-cloudrun: ${WORKLOAD_NAME}
spec:
  hosts:
    - ${WORKLOAD_NAME}
    - ${WORKLOAD_NAME}.${WORKLOAD_NAMESPACE}
    - ${WORKLOAD_NAME}.${WORKLOAD_NAMESPACE}.svc
  http:
    - route:
        - destination:
            host: ${K_SERVICE}
---
# The registered cloudrun service only support mTLS, don't generate extra
# config for 'permissive' or plain.
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: ${K_SERVICE}
  namespace: ${WORKLOAD_NAMESPACE}
spec:
  host: ${K_SERVICE}.${WORKLOAD_NAMESPACE}.svc.cluster.local
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL
---
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: ${K_SERVICE}
  namespace: ${WORKLOAD_NAMESPACE}
spec:
  selector:
    matchLabels:
      app: ${WORKLOAD_NAME}
  portLevelMtls:
    15003:
      mode: STRICT

---
apiVersion: networking.istio.io/v1alpha3
kind: WorkloadEntry
metadata:
  name: ${WORKLOAD_NAME}-sni
  namespace: ${WORKLOAD_NAMESPACE}
spec:
  labels:
    service.istio.io/canonical-name: ${WORKLOAD_NAME}
    app: ${WORKLOAD_NAME}
  serviceAccount: default
  address: ${SNI_GATE_IP}
  ports:
    http: 15442
---

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  namespace: ${WORKLOAD_NAMESPACE}
  name: ${K_SERVICE}
  labels:
     service.istio.io/canonical-name: ${WORKLOAD_NAME}
#    topology.istio.io/network: hbone
spec:
  hosts:
    - ${K_SERVICE}.${WORKLOAD_NAMESPACE}.svc.cluster.local
  location: MESH_INTERNAL
  ports:
    - number: 8080
      name: http
      protocol: HTTP
      #targetPort: 15443
  resolution: STATIC
  workloadSelector:
    labels:
      app: ${WORKLOAD_NAME}

---
# Sidecar entry - when automating, it'll be 'create if missing', not reconciled, i.e. users can modify it.
# This is needed until Istiod has native support for HBONE.
apiVersion: networking.istio.io/v1alpha3
kind: Sidecar
metadata:
  name: ${K_SERVICE}
  namespace: ${WORKLOAD_NAMESPACE}
spec:
  workloadSelector:
    labels:
      app: ${WORKLOAD_NAME}
  #  egress:
  #    - hosts:
  #        # For now, visibility only on same namespace and istio-system.
  #        - ${WORKLOAD_NAMESPACE}/*
  #        - istio-system/*
  ingress:
    - port:
        number: 15003
        protocol: HTTP
        name: http-testsidecar2
      bind: 127.0.0.1
      defaultEndpoint: 127.0.0.1:8080
      captureMode: NONE
