ce7cb702218693d08ea6d83464d2457c9250027c

This commit is contained in:
ms2k 2026-11-12 20:46:28 +09:00
commit 34c5f8963c
252 changed files with 145336 additions and 0 deletions

View file

@ -0,0 +1,102 @@
apiVersion: source.toolkit.fluxcd.io/v1
kind: OCIRepository
metadata:
name: agentgateway-crds
namespace: agentgateway-system
spec:
interval: 1h
url: oci://cr.agentgateway.dev/charts/agentgateway-crds
ref:
digest: sha256:946b739c0fcda4d47a72d1589d184b6fd507772e733cbedf02789bafd0468064
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: agentgateway-crds
namespace: agentgateway-system
spec:
interval: 15m
releaseName: agentgateway-crds
chartRef:
kind: OCIRepository
name: agentgateway-crds
install:
remediation:
retries: 3
upgrade:
strategy:
name: RetryOnFailure
remediation:
retries: 3
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: OCIRepository
metadata:
name: agentgateway
namespace: agentgateway-system
spec:
interval: 1h
url: oci://cr.agentgateway.dev/charts/agentgateway
ref:
digest: sha256:40340d639e35206317c934e9af3e29575cf7c5377b2940679732baac6e108c15
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: agentgateway
namespace: agentgateway-system
spec:
dependsOn:
- name: agentgateway-crds
interval: 15m
releaseName: agentgateway
chartRef:
kind: OCIRepository
name: agentgateway
install:
remediation:
retries: 3
upgrade:
strategy:
name: RetryOnFailure
remediation:
retries: 3
values:
podAnnotations: {}
podLabels:
app.kubernetes.io/part-of: agentgateway
podSecurityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
resources:
requests:
cpu: 50m
memory: 128Mi
limits:
memory: 512Mi
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app.kubernetes.io/name: agentgateway
app.kubernetes.io/instance: agentgateway
topologyKey: kubernetes.io/hostname
controller:
replicaCount: 2
logLevel: info
podDisruptionBudget:
minAvailable: 1
image:
tag: v1.7.0@sha256:87c1363bf0cbc7fdb375866e592294114c8763097d2d0c9fc45fcb1fe00a4ab8
proxy:
image:
tag: v1.7.0@sha256:60216aafb03d37f94e952ff3d51d2f630a65b10ecaebdc0a864882f92610c45b

View file

@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- namespace.yaml
- helm-releases.yaml
- network-policies.yaml

View file

@ -0,0 +1,8 @@
apiVersion: v1
kind: Namespace
metadata:
name: agentgateway-system
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted

View file

@ -0,0 +1,63 @@
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: agentgateway-controller
namespace: agentgateway-system
spec:
endpointSelector:
matchLabels:
app.kubernetes.io/name: agentgateway
app.kubernetes.io/instance: agentgateway
ingress:
- fromEntities:
- host
toPorts:
- ports:
- port: "9092"
protocol: TCP
- port: "9093"
protocol: TCP
- fromEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: agentgateway-system
gateway.networking.k8s.io/gateway-name: agentgateway-proxy
toPorts:
- ports:
- port: "9978"
protocol: TCP
egress:
- toEntities:
- kube-apiserver
toPorts:
- ports:
- port: "6443"
protocol: TCP
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
- port: "53"
protocol: TCP
---
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
name: host-egress-agentgateway-controller
spec:
nodeSelector: {}
egress:
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: agentgateway-system
app.kubernetes.io/name: agentgateway
app.kubernetes.io/instance: agentgateway
toPorts:
- ports:
- port: "9092"
protocol: TCP
- port: "9093"
protocol: TCP

View file

@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- serviceaccounts.yaml
- vso.yaml

View file

@ -0,0 +1,6 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: agentgateway-vso
namespace: agentgateway-system
automountServiceAccountToken: true

View file

@ -0,0 +1,98 @@
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultAuth
metadata:
name: default
namespace: agentgateway-system
spec:
method: kubernetes
mount: kubernetes
kubernetes:
role: agentgateway
serviceAccount: agentgateway-vso
vaultConnectionRef: vault/vault
---
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
name: agentgateway-novita
namespace: agentgateway-system
spec:
type: kv-v2
mount: secret
path: agentgateway/novita
destination:
name: agentgateway-novita
create: true
overwrite: true
transformation:
excludeRaw: true
excludes:
- .*
templates:
Authorization:
text: 'Bearer {{ get .Secrets "api-key" }}'
api_key:
text: '{{ get .Secrets "api-key" }}'
refreshAfter: 1h
rolloutRestartTargets:
- kind: Deployment
name: agentgateway-proxy
- kind: Deployment
name: model-catalog
vaultAuthRef: default
---
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
name: agentgateway-vertex-ai
namespace: agentgateway-system
spec:
type: kv-v2
mount: secret
path: agentgateway/vertex-ai
destination:
name: agentgateway-vertex-ai
create: true
overwrite: true
transformation:
excludeRaw: true
excludes:
- .*
templates:
credentials.json:
text: '{{ get .Secrets "credentials-json" }}'
refreshAfter: 1h
rolloutRestartTargets:
- kind: Deployment
name: agentgateway-proxy
- kind: Deployment
name: vertex-batch
vaultAuthRef: default
---
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
name: quay-cluster-pull
namespace: agentgateway-system
spec:
type: kv-v2
mount: secret
path: quay/robots/cluster_pull
destination:
name: quay-cluster-pull
create: true
overwrite: true
type: kubernetes.io/dockerconfigjson
transformation:
excludeRaw: true
excludes:
- .*
templates:
.dockerconfigjson:
text: >-
{"auths":{"registry.quorate.internal":{"auth":"{{ printf "%s:%s" (get .Secrets "username") (get .Secrets "token") | b64enc }}"}}}
refreshAfter: 1h
rolloutRestartTargets:
- kind: Deployment
name: model-catalog
vaultAuthRef: default

View file

@ -0,0 +1,38 @@
apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayBackend
metadata:
name: vertex-ai
namespace: agentgateway-system
spec:
ai:
provider:
vertexai:
projectId: ms2k-personal
region: global
policies:
auth:
gcp:
type: AccessToken
secretRef:
name: agentgateway-vertex-ai
---
apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayBackend
metadata:
name: novita
namespace: agentgateway-system
spec:
ai:
provider:
custom:
formats:
- type: Completions
path: /openai/v1/chat/completions
host: api.novita.ai
port: 443
policies:
auth:
secretRef:
name: agentgateway-novita
tls:
sni: api.novita.ai

View file

@ -0,0 +1,85 @@
apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayParameters
metadata:
name: agentgateway-proxy
namespace: agentgateway-system
spec:
logging:
format: json
level: info
modelCatalog:
sources:
- configMap:
name: agentgateway-model-costs
key: catalog.json
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
memory: 512Mi
podDisruptionBudget:
spec:
minAvailable: 1
service:
spec:
type: ClusterIP
deployment:
metadata:
labels:
app.kubernetes.io/part-of: agentgateway
spec:
replicas: 2
template:
metadata:
labels:
app.kubernetes.io/part-of: agentgateway
spec:
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
gateway.networking.k8s.io/gateway-name: agentgateway-proxy
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: agentgateway-proxy
namespace: agentgateway-system
spec:
gatewayClassName: agentgateway
infrastructure:
parametersRef:
group: agentgateway.dev
kind: AgentgatewayParameters
name: agentgateway-proxy
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: Same
---
apiVersion: v1
kind: Service
metadata:
name: agentgateway-proxy-metrics
namespace: agentgateway-system
labels:
app.kubernetes.io/name: agentgateway-proxy
app.kubernetes.io/component: metrics
spec:
selector:
gateway.networking.k8s.io/gateway-name: agentgateway-proxy
ports:
- name: metrics
port: 15020
targetPort: 15020
protocol: TCP

View file

@ -0,0 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- gateway.yaml
- backends.yaml
- routes.yaml
- network-policies.yaml
- model-list.yaml

View file

@ -0,0 +1,21 @@
apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayPolicy
metadata:
name: tier-models
namespace: agentgateway-system
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: model-catalog
traffic:
transformation:
response:
body: >-
toJson(json(response.body).merge({"data":
json(response.body).data +
json(response.body).data.filter(m, m.id.startsWith("vertex_ai/")).map(m,
m.merge({"id": "vertex_ai_flex/" + m.id.stripPrefix("vertex_ai/")})) +
json(response.body).data.filter(m, m.id.startsWith("vertex_ai/")).map(m,
m.merge({"id": "vertex_ai_batch/" + m.id.stripPrefix("vertex_ai/")}))
}))

View file

@ -0,0 +1,83 @@
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: agentgateway-proxy
namespace: agentgateway-system
spec:
endpointSelector:
matchLabels:
gateway.networking.k8s.io/gateway-name: agentgateway-proxy
ingress:
- fromEntities:
- host
toPorts:
- ports:
- port: "15020"
protocol: TCP
- port: "15021"
protocol: TCP
- fromEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: victoriametrics
app.kubernetes.io/name: vmagent
app.kubernetes.io/instance: main
toPorts:
- ports:
- port: "15020"
protocol: TCP
egress:
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: agentgateway-system
app.kubernetes.io/name: agentgateway
app.kubernetes.io/instance: agentgateway
toPorts:
- ports:
- port: "9978"
protocol: TCP
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: agentgateway-system
app.kubernetes.io/name: model-catalog
toPorts:
- ports:
- port: "8080"
protocol: TCP
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
- port: "53"
protocol: TCP
- toEntities:
- world
toPorts:
- serverNames:
- api.novita.ai
- oauth2.googleapis.com
- "*.googleapis.com"
ports:
- port: "443"
protocol: TCP
---
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
name: host-egress-agentgateway-proxy
spec:
nodeSelector: {}
egress:
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: agentgateway-system
gateway.networking.k8s.io/gateway-name: agentgateway-proxy
toPorts:
- ports:
- port: "15020"
protocol: TCP
- port: "15021"
protocol: TCP

111
vendor/platform/agentgateway/routes.yaml vendored Normal file
View file

@ -0,0 +1,111 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: model-catalog
namespace: agentgateway-system
spec:
parentRefs:
- name: agentgateway-proxy
rules:
- matches:
- method: GET
path:
type: Exact
value: /v1/models
backendRefs:
- name: model-catalog
port: 8080
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: models
namespace: agentgateway-system
spec:
parentRefs:
- name: agentgateway-proxy
rules:
- matches:
- method: POST
path:
type: Exact
value: /v1/chat/completions
headers:
- name: x-model
type: RegularExpression
value: ^vertex_ai_flex/.+
filters:
- type: RequestHeaderModifier
requestHeaderModifier:
set:
- name: X-Vertex-AI-LLM-Request-Type
value: shared
- name: X-Vertex-AI-LLM-Shared-Request-Type
value: flex
backendRefs:
- group: agentgateway.dev
kind: AgentgatewayBackend
name: vertex-ai
- matches:
- method: POST
path:
type: PathPrefix
value: /v1
headers:
- name: x-model
type: RegularExpression
value: ^vertex_ai/.+
backendRefs:
- group: agentgateway.dev
kind: AgentgatewayBackend
name: vertex-ai
- matches:
- method: POST
path:
type: PathPrefix
value: /v1
headers:
- name: x-model
type: RegularExpression
value: ^novita/.+
backendRefs:
- group: agentgateway.dev
kind: AgentgatewayBackend
name: novita
---
apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayPolicy
metadata:
name: extract-model
namespace: agentgateway-system
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: agentgateway-proxy
traffic:
phase: PreRouting
transformation:
conditional:
- condition: request.method == "POST"
policy:
request:
set:
- name: x-model
value: json(request.body).model
---
apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayPolicy
metadata:
name: strip-provider-prefix
namespace: agentgateway-system
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: models
backend:
ai:
transformations:
- field: model
expression: llmRequest.model.stripPrefix("vertex_ai_flex/").stripPrefix("vertex_ai/").stripPrefix("novita/")

View file

@ -0,0 +1,4 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- relay-admission-pvc.yaml

View file

@ -0,0 +1,12 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: relay-admission-cache
namespace: argo-relay-admission
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn-double
resources:
requests:
storage: 4Gi

View file

@ -0,0 +1,54 @@
# Phase A canary: write an artifact via the executor → VersityGW path.
# Submit after install (not auto-run by Flux):
# kubectl -n argo create -f - <<'EOF'
# apiVersion: argoproj.io/v1alpha1
# kind: Workflow
# metadata:
# generateName: artifact-canary-
# namespace: argo
# spec:
# workflowTemplateRef:
# name: artifact-canary
# EOF
---
apiVersion: argoproj.io/v1alpha1
kind: WorkflowTemplate
metadata:
name: artifact-canary
namespace: argo
labels:
app.kubernetes.io/name: argo-workflow
app.kubernetes.io/instance: argo-workflows
app.kubernetes.io/component: canary
spec:
entrypoint: main
serviceAccountName: argo-workflow
podMetadata:
labels:
app.kubernetes.io/name: argo-workflow
app.kubernetes.io/instance: argo-workflows
app.kubernetes.io/component: canary
templates:
- name: main
container:
image: docker.io/library/busybox:1.37.0@sha256:9532d8c39891ca2ecde4d30d7710e01fb739c87a8b9299685c63704296b16028
command: [sh, -c]
args:
- echo "argo-workflows artifact canary $(date -u +%Y-%m-%dT%H:%M:%SZ)" > /tmp/hello.txt && cat /tmp/hello.txt
resources:
requests:
cpu: 10m
memory: 16Mi
limits:
memory: 32Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
runAsNonRoot: true
runAsUser: 1000
outputs:
artifacts:
- name: hello
path: /tmp/hello.txt

View file

@ -0,0 +1,10 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- canary-workflowtemplate.yaml
- relay-admission-workflowtemplate.yaml
- relay-admission-cronworkflows.yaml
- relay-smtp-deny-workflowtemplate.yaml
- relay-smtp-deny-cronworkflow.yaml
- opnsense-certificate-workflowtemplate.yaml
- opnsense-certificate-cronworkflow.yaml

View file

@ -0,0 +1,20 @@
apiVersion: argoproj.io/v1alpha1
kind: CronWorkflow
metadata:
name: opnsense-certificate-daily
namespace: argo-opnsense-certificate
labels:
app.kubernetes.io/name: opnsense-certificate-rotator
app.kubernetes.io/instance: opnsense-certificate-rotator
spec:
schedules:
- "47 17 * * *"
timezone: UTC
suspend: false
concurrencyPolicy: Forbid
startingDeadlineSeconds: 1800
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 7
workflowSpec:
workflowTemplateRef:
name: opnsense-certificate-rotator

View file

@ -0,0 +1,100 @@
apiVersion: argoproj.io/v1alpha1
kind: WorkflowTemplate
metadata:
name: opnsense-certificate-rotator
namespace: argo-opnsense-certificate
labels:
app.kubernetes.io/name: opnsense-certificate-rotator
app.kubernetes.io/instance: opnsense-certificate-rotator
spec:
entrypoint: rotate
arguments:
parameters:
- name: bootstrap-mode
value: "false"
serviceAccountName: opnsense-certificate-rotator
nodeSelector:
node-role.kubernetes.io/control-plane: "true"
activeDeadlineSeconds: 300
parallelism: 1
synchronization:
mutexes:
- name: opnsense-certificate-rotator
podMetadata:
labels:
app.kubernetes.io/name: opnsense-certificate-rotator
app.kubernetes.io/instance: opnsense-certificate-rotator
securityContext:
fsGroup: 65532
fsGroupChangePolicy: OnRootMismatch
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
seccompProfile:
type: RuntimeDefault
volumes:
- name: opnsense-credentials
secret:
secretName: opnsense-certificate-credentials
defaultMode: 0440
- name: opnsense-bootstrap-ca
secret:
secretName: opnsense-certificate-bootstrap-ca
defaultMode: 0440
- name: vault-ca
secret:
secretName: opnsense-certificate-vault-ca
defaultMode: 0440
- name: opnsense-managed-ca
secret:
secretName: opnsense-certificate-managed-ca
defaultMode: 0440
ttlStrategy:
secondsAfterCompletion: 604800
secondsAfterSuccess: 86400
secondsAfterFailure: 604800
templates:
- name: rotate
container:
image: registry.quorate.internal/quorate/opnsense-certificate-rotator@sha256:f50651bcfc1cba33f4d631205bebfa748f647a400e9bafa69db1411a140b7936
imagePullPolicy: IfNotPresent
command:
- /opnsense-certificate-rotator
env:
- name: OPNSENSE_URL
value: https://10.212.111.120:8443
- name: OPNSENSE_IP_SANS
value: 10.77.102.91,10.212.111.120,10.31.87.181,10.86.169.153,10.146.95.240
- name: BOOTSTRAP_MODE
value: "{{workflow.parameters.bootstrap-mode}}"
- name: RENEW_BEFORE
value: 720h
- name: CERTIFICATE_TTL
value: 2160h
- name: ACTIVATION_TIMEOUT
value: 180s
volumeMounts:
- name: opnsense-credentials
mountPath: /opnsense-credentials
readOnly: true
- name: opnsense-bootstrap-ca
mountPath: /opnsense-bootstrap-ca
readOnly: true
- name: vault-ca
mountPath: /vault-ca
readOnly: true
- name: opnsense-managed-ca
mountPath: /opnsense-managed-ca
readOnly: true
resources:
requests:
cpu: 10m
memory: 32Mi
limits:
memory: 128Mi
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL

View file

@ -0,0 +1,99 @@
apiVersion: argoproj.io/v1alpha1
kind: CronWorkflow
metadata:
name: relay-admission-daily
namespace: argo-relay-admission
labels:
app.kubernetes.io/name: relay-admission-publisher
app.kubernetes.io/instance: relay-admission-publisher
spec:
schedules:
- "23 16 * * *"
timezone: UTC
suspend: false
concurrencyPolicy: Forbid
startingDeadlineSeconds: 1800
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 7
workflowSpec:
workflowTemplateRef:
name: relay-admission-publisher
arguments:
parameters:
- name: sources
value: iplocate-country,iplocate-asn,spamhaus-drop,oci
---
apiVersion: argoproj.io/v1alpha1
kind: CronWorkflow
metadata:
name: relay-admission-maxmind
namespace: argo-relay-admission
labels:
app.kubernetes.io/name: relay-admission-publisher
app.kubernetes.io/instance: relay-admission-publisher
spec:
schedules:
- "23 17 * * 2,5"
timezone: UTC
suspend: false
concurrencyPolicy: Forbid
startingDeadlineSeconds: 1800
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 7
workflowSpec:
workflowTemplateRef:
name: relay-admission-publisher
arguments:
parameters:
- name: sources
value: maxmind-country
---
apiVersion: argoproj.io/v1alpha1
kind: CronWorkflow
metadata:
name: relay-admission-azure
namespace: argo-relay-admission
labels:
app.kubernetes.io/name: relay-admission-publisher
app.kubernetes.io/instance: relay-admission-publisher
spec:
schedules:
- "23 18 * * 0"
timezone: UTC
suspend: false
concurrencyPolicy: Forbid
startingDeadlineSeconds: 1800
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 7
workflowSpec:
workflowTemplateRef:
name: relay-admission-publisher
arguments:
parameters:
- name: sources
value: azure
---
apiVersion: argoproj.io/v1alpha1
kind: CronWorkflow
metadata:
name: relay-admission-reconcile
namespace: argo-relay-admission
labels:
app.kubernetes.io/name: relay-admission-publisher
app.kubernetes.io/instance: relay-admission-publisher
spec:
schedules:
- "23 19 * * 6"
timezone: UTC
suspend: false
concurrencyPolicy: Forbid
startingDeadlineSeconds: 1800
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 7
workflowSpec:
workflowTemplateRef:
name: relay-admission-publisher
arguments:
parameters:
- name: sources
value: tor-exits,aws,gcp,cloudflare,fastly,github,atlassian,digitalocean,linode,vultr

Some files were not shown because too many files have changed in this diff Show more