---
# Source: provider/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: akash-provider
  namespace: akash-services
  labels:
    helm.sh/chart: provider-19.0.0
    app.kubernetes.io/name: provider
    app.kubernetes.io/instance: akash-provider
    app.kubernetes.io/version: "0.16.0"
    app.kubernetes.io/managed-by: Helm
automountServiceAccountToken: true
---
# Source: provider/templates/secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: akash-provider-keys
  namespace: akash-services
type: "Opaque"
data:
  key.txt: 
  key-pass.txt:
---
# Source: provider/templates/configmap-init.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: akash-provider-init
  namespace: akash-services
  labels:
    app: akash-provider
    helm.sh/chart: provider-19.0.0
    app.kubernetes.io/name: provider
    app.kubernetes.io/instance: akash-provider
    app.kubernetes.io/version: "0.16.0"
    app.kubernetes.io/managed-by: Helm
data:
  # Debug config
  AKASH_DEBUG: "false"
  AP_YES: "true"
  
  # Boot config
  AKASH_BOOT_KEYS: "/boot-keys"
  
  # Cosmos-SDK client config
  AKASH_HOME: "/root/.akash"
  AKASH_FROM: ""
  AKASH_NODE: "https://akash-rpc.polkachu.com:443"
  AKASH_CHAIN_ID: "akashnet-2"
  AKASH_KEYRING_BACKEND: "test"
  AKASH_BROADCAST_MODE: "block"
  AKASH_YES: "true"
  AKASH_GAS_PRICES: "0.025uakt"
  AKASH_GAS: "auto"
  AKASH_GAS_ADJUSTMENT: "1.5"
  AP_MINIMUM_GAS_PRICES: "0.0025uakt"
  AKASH_LOG_LEVEL: "info"
---
# Source: provider/templates/configmap-main.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: akash-provider-main
  namespace: akash-services
  labels:
    app: akash-provider
    helm.sh/chart: provider-19.0.0
    app.kubernetes.io/name: provider
    app.kubernetes.io/instance: akash-provider
    app.kubernetes.io/version: "0.16.0"
    app.kubernetes.io/managed-by: Helm
data:
  # Debug config
  AKASH_DEBUG: "false"
  
  # Boot config
  AKASH_BOOT_KEYS: "/boot-keys"
  
  # Cosmos-SDK client config
  AKASH_HOME: "/root/.akash"
  AKASH_FROM: ""
  AKASH_NODE: "https://akash-rpc.polkachu.com:443"
  AKASH_CHAIN_ID: "akashnet-2"
  AKASH_KEYRING_BACKEND: "test"
  AKASH_BROADCAST_MODE: "block"
  AKASH_VERSION: "0.16.0"
  AKASH_YES: "true"
  AKASH_LOG_LEVEL: "info"
  
  # Akash IP operator config
  AKASH_IP_OPERATOR: "false"
  
  # Akash provider config
  AKASH_DEPLOYMENT_INGRESS_DOMAIN: "ingress."
  DEPLOYMENT_NETWORK_POLICIES_ENABLED: "false"
  AKASH_DEPLOYMENT_INGRESS_STATIC_HOSTS: "true"
  AKASH_DEPLOYMENT_BLOCKED_HOSTNAMES: ""
  AKASH_CLUSTER_NODE_PORT_QUANTITY: "2500"
  AKASH_GAS_PRICES: "0.025uakt"
  AKASH_GAS: "auto"
  AKASH_GAS_ADJUSTMENT: "1.5"
  AP_MINIMUM_GAS_PRICES: "0.0025uakt"
  # AKASH_CLUSTER_PUBLIC_HOSTNAME need to stay as this makes to
  # 'akash provider lease-status` under the forwarded_ports (nodePorts).
  # This is NOT used for connecting to K8s cluster itself (6443/tcp).
  # akash-provider uses kubeconfig to connect to K8s cluster.
  AKASH_CLUSTER_PUBLIC_HOSTNAME: "provider."
  AKASH_BID_PRICE_STRATEGY: "scale"
  
  # Bid pricing config
  AKASH_BID_PRICE_CPU_SCALE: "0.004"
  AKASH_BID_PRICE_MEMORY_SCALE: "0.0016"
  AKASH_BID_PRICE_ENDPOINT_SCALE: ""
  AKASH_BID_PRICE_STORAGE_SCALE: "0.00016,beta2=0.00016"
  AKASH_BID_PRICE_IP_SCALE: "60"
  
  # Overcommit percentages
  AKASH_OVERCOMMIT_PCT_CPU: "0"
  AKASH_OVERCOMMIT_PCT_MEM: "0"
  AKASH_OVERCOMMIT_PCT_STORAGE: "0"
  
  # Cluster config
  AKASH_CLUSTER_K8S: "true"
  KUBE_CONFIG: "/root/.akash/.kube/config"
  AKASH_DEPLOYMENT_RUNTIME_CLASS: "none"
  
  # Financial config
  AKASH_WITHDRAWAL_PERIOD: "1h"
  AKASH_MINIMUM_BALANCE: "10000000"
  AKASH_BID_DEPOSIT: "500000uakt"
  AKASH_TX_BROADCAST_TIMEOUT: "60s"
  
  # Monitor config
  AKASH_MONITOR_MAX_RETRIES: "2304"
  AKASH_MONITOR_RETRY_PERIOD: "30s"
  AKASH_MONITOR_RETRY_PERIOD_JITTER: "15s"
  AKASH_MONITOR_HEALTHCHECK_PERIOD: "10s"
  AKASH_MONITOR_HEALTHCHECK_PERIOD_JITTER: "5s"

  # Gateway API config
  AP_INGRESS_MODE: "ingress"
  AP_GATEWAY_NAME: "akash-gateway"
  AP_GATEWAY_NAMESPACE: "akash-gateway"
  AP_GATEWAY_IMPLEMENTATION: "nginx"
---
# Source: provider/templates/configmap-scripts.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: akash-provider-script
  namespace: akash-services
data:
  init.sh: |
    #!/bin/bash
    # Filename: init.sh
    
    set -x
    
    
    
    ##
    # Import key
    ##
    cat "$AKASH_BOOT_KEYS/key-pass.txt" | { cat ; echo ; } | provider-services --home="$AKASH_HOME" keys import --keyring-backend="$AKASH_KEYRING_BACKEND"  "$AKASH_FROM" "$AKASH_BOOT_KEYS/key.txt"
    
    ##
    # Wait for RPC
    ##
    /scripts/wait_for_rpc.sh
    
    ##
    # Create/Update Provider
    ##
    /scripts/create_provider.sh
    
    ##
    # Create/Update Provider certs
    ##
    /scripts/refresh_provider_cert.sh
    
  wait_for_rpc.sh: |
    #!/bin/bash
    # Filename: wait_for_rpc.sh
    
    set -x
    
    # Abort early if essential image dependencies are not present:
    type curl || exit 1
    type jq || exit 1
    type nc || exit 1
    test -e /etc/ssl/certs/ca-certificates.crt || exit 1
    
    solo_ip=$(echo $AKASH_NODE | cut -d":" -f2 | cut -d"/" -f3)
    port=$(echo $AKASH_NODE | cut -d":" -f3 | cut -d"/" -f1)
    if [[ $AKASH_NODE != "http://akash-node-1:26657" ]]; then
      nc -z -v -w5 $solo_ip $port
    fi
    until [[ $(curl -s $AKASH_NODE/status | jq -r .result.sync_info.catching_up) == "false" ]]; do sleep 15; echo "Akash node not ready. Retrying";  done
    
    # Check Akash RPC node isn't running behind too much and abort if it does.
    DATE_AKASH=$(curl -s $AKASH_NODE/status | jq -r '.result.sync_info.latest_block_time')
    TS_AKASH=$(date +%s --date "$DATE_AKASH")
    TS=$(date +%s)
    DIFF=$(echo "$TS - $TS_AKASH" | bc)
    if [[ "$DIFF" -gt 30 ]]; then
      echo "Akash RPC $AKASH_NODE is running $DIFF seconds behind."
      echo "ACTION: Make sure your system time in synchronized and/or check your Akash RPC node."
      exit 1
    elif [[ "$DIFF" -lt -30 ]]; then
      echo "Akash RPC $AKASH_NODE is running $DIFF seconds ahead."
      echo "ACTION: Make sure your system time in synchronized and/or check your Akash RPC node."
      exit 1
    else
      echo "Last block Akash RPC $AKASH_NODE seen was $DIFF seconds ago => OK"
    fi
    
  create_provider.sh: |
    #!/bin/bash
    # Filename: create_provider.sh
    
    set -x
    
    ##
    # Create Provider
    ##
    
    cat <<EOT > provider.yaml
    host: https://provider.:8443
    attributes:
    info:
      email: 
      website: 
    owner: 
    EOT
    
    # Figure the provider address in case the user passes `--from=<key_name>` instead of `--from=<akash1...>` address.
    PROVIDER_ADDRESS="$(provider-services keys show $AKASH_FROM -a)"
    if [[ -z "$PROVIDER_ADDRESS" ]]; then
      echo "PROVIDER_ADDRESS variable is empty. Something went wrong"
      exit 1
    fi
    
    provider-services query provider get $PROVIDER_ADDRESS -o json
    if [[ $? -ne 0 ]]; then
      echo "Could not find provider: $PROVIDER_ADDRES on the blockchain when querying Akash RPC node: $AKASH_NODE"
      echo "Attempting to create a new provider ..."
      provider-services tx provider create provider.yaml
    fi
    
    ##
    # Update Provider
    ##
    
    echo "Checking whether provider.yaml needs to be updated on the chain ..."
    diff --color -Nur <(cat provider.yaml | awk '/attributes:/{print;flag=1;next}/^  - key:/{if(flag)sub("  ","");print;next}flag&&/^    /{sub("    ","  ");print;next}{flag=0;print}' | sort) <(provider-services query provider get $PROVIDER_ADDRESS -o text | sed -e 's/"//g' -e 's/host_uri:/host:/g' | sort)
    rc=$?
    if [[ $rc -ne 0 ]]; then
      echo "Updating provider info in the blockchain in 10 seconds ..."
      sleep 10s
      provider-services tx provider update provider.yaml
    fi
    
  refresh_provider_cert.sh: |
    #!/bin/bash
    # Filename: refresh_provider_cert.sh
    
    set -x
    
    # Figure the provider address in case the user passes `--from=<key_name>` instead of `--from=<akash1...>` address.
    PROVIDER_ADDRESS="$(provider-services keys show $AKASH_FROM -a)"
    if [[ -z "$PROVIDER_ADDRESS" ]]; then
      echo "PROVIDER_ADDRESS variable is empty. Something went wrong"
      exit 1
    fi
    
    CERT_SYMLINK="${AKASH_HOME}/${PROVIDER_ADDRESS}.pem"
    CERT_REAL_PATH="/config/provider.pem"
    rm -vf "$CERT_SYMLINK"
    # provider cert is coming from the configmap
    ln -sv "$CERT_REAL_PATH" "$CERT_SYMLINK"
    # 0 = yes; otherwise do not (re-)generate new provider certificate, unless
    GEN_NEW_CERT=1
    
    # Check whether the certificate is present and valid on the blockchain
    if [[ -f "${CERT_REAL_PATH}" ]]; then
      LOCAL_CERT_SN="$(cat "${CERT_REAL_PATH}" | openssl x509 -serial -noout | cut -d'=' -f2)"
      LOCAL_CERT_SN_DECIMAL=$(echo "obase=10; ibase=16; $LOCAL_CERT_SN" | bc)
      REMOTE_CERT_STATUS="$(AKASH_OUTPUT=json provider-services query cert list --owner $PROVIDER_ADDRESS --state valid --serial $LOCAL_CERT_SN_DECIMAL --reverse | jq -r '.certificates[0].certificate.state')"
      echo "Provider certificate serial number: ${LOCAL_CERT_SN:-unknown}, status on chain: ${REMOTE_CERT_STATUS:-unknown}"
    else
      echo "${CERT_REAL_PATH} file is missing."
      GEN_NEW_CERT=0
    fi
    
    if [[ -z "$LOCAL_CERT_SN" ]]; then
      echo "LOCAL_CERT_SN variable is empty. Most likely ${CERT_REAL_PATH} file is empty or malformed."
      GEN_NEW_CERT=0
    fi
    
    if [[ "valid" != "$REMOTE_CERT_STATUS" ]]; then
      echo "No valid certificate found for provider: $PROVIDER_ADDRESS"
      GEN_NEW_CERT=0
    
      echo "It might as well be that the current certificate was expired/revoked, thus, it should be safe to delete it locally"
    fi
    
    # generate a new cert if the current one expires sooner than 7 days
    AKASH_OUTPUT=json provider-services query cert list --owner $PROVIDER_ADDRESS --state valid --reverse | jq -r '.certificates[0].certificate.cert' | openssl base64 -A -d | openssl x509 -checkend 604800 -noout 2>/dev/null 1>&2
    rc=$?
    if [[ $rc -ne 0 ]]; then
      echo "Certificate expires in less than 7 days, so going to generate a new one."
      GEN_NEW_CERT=0
    fi
    
    # check if current local cert has expired
    # TODO: should probably add a healthCheck which would keep doing this every 5 minutes to bounce the pod if cert got expired
    openssl x509 -checkend 604800 -noout -in "${CERT_REAL_PATH}" 2>/dev/null 1>&2
    rc=$?
    if [[ $rc -ne 0 ]]; then
      echo "Certificate expires in less than 7 days, so going to generate a new one."
      GEN_NEW_CERT=0
    fi
    
    if [[ "$GEN_NEW_CERT" -eq "0" ]]; then
      echo "Removing the old certificate before generating a new one"
      # It's also a good idea to delete it as otherwise, we'd have to add `--overwrite` to `provider-services tx cert generate server` command later.
      rm -vf "${CERT_REAL_PATH}"
    
      echo "Generating new provider certificate"
      provider-services tx cert generate server provider.
    
      echo "Publishing new provider certificate"
      provider-services tx cert publish server
    fi
    
  run.sh: |
    #!/bin/bash
    
    # fail fast should these packages be missing
    type curl || exit 1
    type jq || exit 1
    type awk || exit 1
    type bc || exit 1
    
    ##
    # Wait for RPC
    ##
    /scripts/wait_for_rpc.sh
    
    ##
    # Create/Update Provider certs
    ##
    /scripts/refresh_provider_cert.sh
    
    # Build provider-services run command with optional certificate issuer flags
    PROVIDER_CMD="/usr/bin/provider-services run"
    
    # Add certificate issuer flags if enabled (HTTP challenge default, DNS providers optional)
    if [[ "${AP_CERT_ISSUER_ENABLED}" == "true" ]]; then
        PROVIDER_CMD="${PROVIDER_CMD} --cert-issuer-enabled=true"
        
        if [[ -n "${AP_CERT_ISSUER_EMAIL}" ]]; then
            PROVIDER_CMD="${PROVIDER_CMD} --cert-issuer-email=${AP_CERT_ISSUER_EMAIL}"
        fi
        
        if [[ -n "${AP_CERT_ISSUER_CA_DIR_URL}" ]]; then
            PROVIDER_CMD="${PROVIDER_CMD} --cert-issuer-ca-dir-url=${AP_CERT_ISSUER_CA_DIR_URL}"
        fi
        
        if [[ -n "${AP_CERT_ISSUER_DNS_PROVIDERS}" ]]; then
            PROVIDER_CMD="${PROVIDER_CMD} --cert-issuer-dns-providers=${AP_CERT_ISSUER_DNS_PROVIDERS}"
        fi
        
        if [[ -n "${AP_CERT_ISSUER_HTTP_CHALLENGE_PORT}" ]]; then
            PROVIDER_CMD="${PROVIDER_CMD} --cert-issuer-http-challenge-port=${AP_CERT_ISSUER_HTTP_CHALLENGE_PORT}"
        fi
    fi
    
    # Debug: Print the final command to see all flags
    echo "=== Provider Command Debug ==="
    echo "AP_CERT_ISSUER_ENABLED: ${AP_CERT_ISSUER_ENABLED}"
    echo "AP_CERT_ISSUER_EMAIL: ${AP_CERT_ISSUER_EMAIL}"
    echo "AP_CERT_ISSUER_CA_DIR_URL: ${AP_CERT_ISSUER_CA_DIR_URL}"
    echo "AP_CERT_ISSUER_DNS_PROVIDERS: ${AP_CERT_ISSUER_DNS_PROVIDERS}"
    echo "AP_CERT_ISSUER_HTTP_CHALLENGE_PORT: ${AP_CERT_ISSUER_HTTP_CHALLENGE_PORT}"
    echo "Final command: ${PROVIDER_CMD}"
    echo "=============================="
    
    # Start provider-services and monitor its output
    runcmd=${PROVIDER_CMD}
    
    run_debug=${AKASH_DEBUG:-false}
    dlv_port=${AKASH_DEBUG_DELVE_PORT:-2345}
    
    if [[ $run_debug == "true" ]]; then
        if command /go/bin/dlv; then
            runcmd="/go/bin/dlv --listen=:${dlv_port} --headless=true --api-version=2 --log exec -- ${PROVIDER_CMD}"
        else
            echo "AKASH_DEBUG is set, but no dlv is present in the image. check if docker image has debug suffix"
        fi
    fi
    
    ${runcmd}
    
  liveness_checks.sh: |
    #!/bin/bash
    
    # Ensure the script fails if any part of a pipeline fails
    set -o pipefail
    
    # Check provider certificate expiration
    if ! openssl x509 -in /config/provider.pem -checkend 3600 -noout > /dev/null; then
      echo "certificate will expire in 1h, restarting"
      exit 1
    fi
    
    # Provider API /status check
    if ! timeout 30s curl -o /dev/null -fsk https://127.0.0.1:8443/status; then
      echo "api /status check failed"
      exit 1
    fi
    
    # Provider gRPC check
    if ! timeout 30s curl -k -v --http2-prior-knowledge https://127.0.0.1:8444 2>&1 | grep -qi 'application/grpc'; then
      echo "gRPC check failed"
      exit 1
    fi
    
    # RPC node sync check - DISABLED
    # current_time=$(date -u +%s)
    # latest_block_time_str=$(curl -s $AKASH_NODE/status | jq -r '.result.sync_info.latest_block_time')
    # latest_block_time=$(date -u -d "$latest_block_time_str" +%s)
    
    # Allow for a 60 seconds drift
    # let "time_diff = current_time - latest_block_time"
    # if [ "$time_diff" -gt 60 ] || [ "$time_diff" -lt -60 ]; then
    #   echo "RPC node sync check failed"
    #   exit 1
    # fi
    
    echo "All checks passed"
    exit 0
---
# Source: provider/templates/storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: akash-provider-local-storage
  labels:
    app: akash-provider
    helm.sh/chart: provider-19.0.0
    app.kubernetes.io/name: provider
    app.kubernetes.io/instance: akash-provider
    app.kubernetes.io/version: "0.16.0"
    app.kubernetes.io/managed-by: Helm
provisioner: rancher.io/local-path
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Retain
---
# Source: provider/templates/rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: akash-provider-admin
  namespace: akash-services
subjects:
  - kind: ServiceAccount
    name: akash-provider
    namespace: akash-services
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io
---
# Source: provider/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: akash-provider
  namespace: akash-services
  labels:
    akash.network: "true"
    app.kubernetes.io/component: operator
    helm.sh/chart: provider-19.0.0
    app.kubernetes.io/name: provider
    app.kubernetes.io/instance: akash-provider
    app.kubernetes.io/version: "0.16.0"
    app.kubernetes.io/managed-by: Helm
spec:
  type: ClusterIP
  ports:
  - name: api
    protocol: TCP
    port: 8443
    targetPort: api
  - name: grpc
    protocol: TCP
    port: 8444
    targetPort: grpc
  selector:
    app: akash-provider
    app.kubernetes.io/name: provider
    app.kubernetes.io/instance: akash-provider
---
# Source: provider/templates/statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: akash-provider
  namespace: akash-services
  labels:
    app: akash-provider
    helm.sh/chart: provider-19.0.0
    app.kubernetes.io/name: provider
    app.kubernetes.io/instance: akash-provider
    app.kubernetes.io/version: "0.16.0"
    app.kubernetes.io/managed-by: Helm
spec:
  replicas: 1
  #strategy:
  #  type: OnDelete
  serviceName: akash-provider
  selector:
    matchLabels:
      app: akash-provider
      app.kubernetes.io/name: provider
      app.kubernetes.io/instance: akash-provider
  volumeClaimTemplates:
    - metadata:
        name: home
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 10Gi
        storageClassName: akash-provider-local-storage
  template:
    metadata:
      annotations:
        checksum/cm-scripts: a52df2b11b64130d3f0fdf58f550867718c3aecb5d0acef5674121f59884bcab
      labels:
        app: akash-provider
        app.kubernetes.io/name: provider
        app.kubernetes.io/instance: akash-provider
    spec:
      serviceAccountName: akash-provider
      securityContext:
        {}
      initContainers:
        - name: init
          securityContext:
            {}
          image: "ghcr.io/akash-network/provider:0.16.0"
          args: ["/bin/bash", "/scripts/init.sh"]
          imagePullPolicy: IfNotPresent
          resources:
            limits:
              cpu: 2000m
              memory: 4096Mi
            requests:
              cpu: 1000m
              memory: 2048Mi
          envFrom:
            - configMapRef:
                name: akash-provider-init

          volumeMounts:
            - name: scripts
              mountPath: /scripts
              readOnly: true
            - name: keys
              mountPath: /boot-keys
              readOnly: true
            - name: provider-config-volume
              mountPath: /config
            - name: home
              mountPath: "/root/.akash"
      containers:
        - name: provider
          securityContext:
            {}
          image: "ghcr.io/akash-network/provider:0.16.0"
          args: ["/bin/bash", "/scripts/run.sh"]
          imagePullPolicy: IfNotPresent
          resources:
            limits:
              cpu: 2000m
              memory: 4096Mi
            requests:
              cpu: 1000m
              memory: 2048Mi
          envFrom:
            - configMapRef:
                name: akash-provider-main
            - name: AP_INGRESS_MODE
              valueFrom:
                configMapKeyRef:
                  name: akash-provider-main
                  key: AP_INGRESS_MODE
            - name: AP_GATEWAY_NAME
              valueFrom:
                configMapKeyRef:
                  name: akash-provider-main
                  key: AP_GATEWAY_NAME
            - name: AP_GATEWAY_NAMESPACE
              valueFrom:
                configMapKeyRef:
                  name: akash-provider-main
                  key: AP_GATEWAY_NAMESPACE
            - name: AP_GATEWAY_IMPLEMENTATION
              valueFrom:
                configMapKeyRef:
                  name: akash-provider-main
                  key: AP_GATEWAY_IMPLEMENTATION

          ports:
            - name: api
              containerPort: 8443
              protocol: TCP
            - name: grpc
              containerPort: 8444
              protocol: TCP

          livenessProbe:
            exec:
              command:
              - sh
              - -c
              - /scripts/liveness_checks.sh
            initialDelaySeconds: 240
            periodSeconds: 30
            failureThreshold: 1
            timeoutSeconds: 30

          volumeMounts:
            - name: scripts
              mountPath: /scripts
              readOnly: true
            - name: keys
              mountPath: /boot-keys
              readOnly: true
            - name: provider-config-volume
              mountPath: /config
            - name: home
              mountPath: "/root/.akash"
      volumes:
        - name: scripts
          configMap:
            name: akash-provider-script
            defaultMode: 0744
        - name: keys
          secret:
            secretName: akash-provider-keys
        - name: provider-config-volume
          hostPath:
            path: /root/.akash/k8s-config
            type: DirectoryOrCreate
        - name: home
          persistentVolumeClaim:
            claimName: akash-provider-home
---
# Source: provider/templates/configmap-pricing.yaml
# Conditional ConfigMap for optional main container values
