---
apiVersion: v1
kind: Namespace
metadata:
  name: ${APP_NAMESPACE}
  labels:
    mesh: ${MESH_NAME}
    gateway: ingress-gw-${APP_NAMESPACE}
    appmesh.k8s.aws/sidecarInjectorWebhook: enabled
---
apiVersion: appmesh.k8s.aws/v1beta2
kind: Mesh
metadata:
  name: ${MESH_NAME}
spec:
  namespaceSelector:
    matchLabels:
      mesh: ${MESH_NAME}
---
apiVersion: appmesh.k8s.aws/v1beta2
kind: VirtualGateway
metadata:
  name: ingress-gw
  namespace: ${APP_NAMESPACE}
spec:
  namespaceSelector:
    matchLabels:
      gateway: ingress-gw-${APP_NAMESPACE}
  podSelector:
    matchLabels:
      app: ingress-gw
  listeners:
    - portMapping:
        port: 8088
        protocol: http
---
apiVersion: appmesh.k8s.aws/v1beta2
kind: GatewayRoute
metadata:
  name: gateway-route-paths
  namespace: ${APP_NAMESPACE}
spec:
  httpRoute:
    match:
      prefix: "/"
    action:
      target:
        virtualService:
          virtualServiceRef:
            name: price-service
---
apiVersion: appmesh.k8s.aws/v1beta2
kind: VirtualNode
metadata:
  name: price-read-node
  namespace: ${APP_NAMESPACE}
spec:
  podSelector:
    matchLabels:
      app: price-read
  listeners:
    - portMapping:
        port: 8080
        protocol: http
      healthCheck:
        protocol: http
        path: "/health"
        healthyThreshold: 2
        unhealthyThreshold: 2
        timeoutMillis: 2000
        intervalMillis: 5000
  serviceDiscovery:
    dns:
      hostname: price-read.${APP_NAMESPACE}.svc.cluster.local
---
apiVersion: appmesh.k8s.aws/v1beta2
kind: VirtualNode
metadata:
  name: price-write-node
  namespace: ${APP_NAMESPACE}
spec:
  podSelector:
    matchLabels:
      app: price-write
  listeners:
    - portMapping:
        port: 8080
        protocol: http
      healthCheck:
        protocol: http
        path: "/health"
        healthyThreshold: 2
        unhealthyThreshold: 2
        timeoutMillis: 2000
        intervalMillis: 5000
  serviceDiscovery:
    dns:
      hostname: price-write.${APP_NAMESPACE}.svc.cluster.local
---
apiVersion: appmesh.k8s.aws/v1beta2
kind: VirtualService
metadata:
  name: price-service
  namespace: ${APP_NAMESPACE}
spec:
  awsName: price-service.${APP_NAMESPACE}.svc.cluster.local
  provider:
    virtualRouter:
      virtualRouterRef:
        name: price-router
---
apiVersion: appmesh.k8s.aws/v1beta2
kind: VirtualRouter
metadata:
  namespace: ${APP_NAMESPACE}
  name: price-router
spec:
  listeners:
    - portMapping:
        port: 8080
        protocol: http
  routes:
    - name: price-read-route
      priority: 10
      httpRoute:
        match:
          prefix: /price
          method: GET
        action:
          weightedTargets:
            - virtualNodeRef:
                name: price-read-node
              weight: 1
    - name: price-write-route
      priority: 10
      httpRoute:
        match:
          prefix: /price
          method: POST
        action:
          weightedTargets:
            - virtualNodeRef:
                name: price-write-node
              weight: 1
---
apiVersion: v1
kind: Service
metadata:
  name: price-write
  namespace: ${APP_NAMESPACE}
spec:
  ports:
    - port: 8080
      name: http
  selector:
    app: price-write
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: price-write
  namespace: ${APP_NAMESPACE}
spec:
  replicas: 1
  selector:
    matchLabels:
      app: price-write
  template:
    metadata:
      labels:
        app: price-write
    spec:
      containers:
        - name: app
          imagePullPolicy: Always
          image: ${PRICE_APP_IMAGE}
          ports:
            - containerPort: 8080
          env:
            - name: PORT
              value: "8080"
            - name: DATABASE_DELAY
              value: "5s"
          resources:
            limits:
              memory: "8M"
---
apiVersion: v1
kind: Service
metadata:
  name: price-read
  namespace: ${APP_NAMESPACE}
spec:
  ports:
    - port: 8080
      name: http
  selector:
    app: price-read
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: price-read
  namespace: ${APP_NAMESPACE}
spec:
  replicas: 1
  selector:
    matchLabels:
      app: price-read
  template:
    metadata:
      labels:
        app: price-read
    spec:
      containers:
        - name: app
          imagePullPolicy: Always
          image: ${PRICE_APP_IMAGE}
          ports:
            - containerPort: 8080
          env:
            - name: PORT
              value: "8080"
---
apiVersion: v1
kind: Service
metadata:
  name: price-service
  namespace: ${APP_NAMESPACE}
spec:
  ports:
    - port: 8080
      name: http
---
apiVersion: v1
kind: Service
metadata:
  name: ingress-gw
  namespace: ${APP_NAMESPACE}
spec:
  type: LoadBalancer
  ports:
    - port: 80
      targetPort: 8088
      name: http
  selector:
    app: ingress-gw
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ingress-gw
  namespace: ${APP_NAMESPACE}
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ingress-gw
  template:
    metadata:
      labels:
        app: ingress-gw
    spec:
      containers:
        - name: envoy
          image: controller-override
          ports:
            - containerPort: 8088
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: vegeta
  namespace: ${APP_NAMESPACE}
spec:
  replicas: 1
  selector:
    matchLabels:
      app: vegeta
  template:
    metadata:
      labels:
        app: vegeta
      annotations:
        appmesh.k8s.aws/sidecarInjectorWebhook: disabled
    spec:
      containers:
      - args:
        image: peterevans/vegeta
        name: vegeta
        stdin: true
        tty: true
        command: ["/bin/sh"]