diff --git a/argocd/capi-capa/aws-credential-manager.yaml b/argocd/capi-capa/aws-credential-manager.yaml new file mode 100644 index 000000000..93c465f7e --- /dev/null +++ b/argocd/capi-capa/aws-credential-manager.yaml @@ -0,0 +1,46 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: aws-credential-manager + namespace: argocd +spec: + project: default + source: + chart: aws-credential-manager + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.1.20 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: capa-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true + + ignoreDifferences: + - jsonPointers: + - /data + kind: Secret + name: aws-credential-manager-apiserver-cert + namespace: capa-system + - group: apiregistration.k8s.io + kind: APIService + name: v1alpha1.ui.openviz.dev + jsonPointers: + - /spec/caBundle + - group: apps + kind: Deployment + name: aws-credential-manager + namespace: capa-system + jsonPointers: + - /spec/template/metadata/annotations/checksum~1apiregistration.yaml + - group: apiextensions.k8s.io + kind: CustomResourceDefinition + name: servicemonitors.monitoring.coreos.com + jsonPointers: + - /metadata/annotations + - /spec diff --git a/argocd/capi-capa/aws-ebs-csi-driver.yaml b/argocd/capi-capa/aws-ebs-csi-driver.yaml new file mode 100644 index 000000000..ea8dd9b14 --- /dev/null +++ b/argocd/capi-capa/aws-ebs-csi-driver.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: aws-ebs-csi-driver + namespace: argocd +spec: + project: default + source: + chart: aws-ebs-csi-driver + repoURL: ghcr.io/appscode-charts + targetRevision: 2.23.0 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: capa-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/capi-capa/aws-load-balancer-controller.yaml b/argocd/capi-capa/aws-load-balancer-controller.yaml new file mode 100644 index 000000000..ec1e2d5d4 --- /dev/null +++ b/argocd/capi-capa/aws-load-balancer-controller.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: aws-load-balancer-controller + namespace: argocd +spec: + project: default + source: + chart: aws-load-balancer-controller + repoURL: ghcr.io/appscode-charts + targetRevision: 1.11.0 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: capa-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/capi-capa/capa-vpc-peering-operator.yaml b/argocd/capi-capa/capa-vpc-peering-operator.yaml new file mode 100644 index 000000000..ef25064a0 --- /dev/null +++ b/argocd/capi-capa/capa-vpc-peering-operator.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: capa-vpc-peering-operator + namespace: argocd +spec: + project: default + source: + chart: capa-vpc-peering-operator + repoURL: ghcr.io/appscode-charts + targetRevision: v2023.12.11 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: capa-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/capi-capa/cluster-autoscaler.yaml b/argocd/capi-capa/cluster-autoscaler.yaml new file mode 100644 index 000000000..53dbba56c --- /dev/null +++ b/argocd/capi-capa/cluster-autoscaler.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: cluster-autoscaler + namespace: argocd +spec: + project: default + source: + chart: cluster-autoscaler + repoURL: ghcr.io/appscode-charts + targetRevision: 9.29.0 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: capi-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/capi-capg/gcp-credential-manager.yaml b/argocd/capi-capg/gcp-credential-manager.yaml new file mode 100644 index 000000000..cc66d78bf --- /dev/null +++ b/argocd/capi-capg/gcp-credential-manager.yaml @@ -0,0 +1,46 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: gcp-credential-manager + namespace: argocd +spec: + project: default + source: + chart: gcp-credential-manager + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.3.11 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: capg-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true + + ignoreDifferences: + - jsonPointers: + - /data + kind: Secret + name: gcp-credential-manager-apiserver-cert + namespace: capg-system + - group: apiregistration.k8s.io + kind: APIService + name: v1alpha1.ui.openviz.dev + jsonPointers: + - /spec/caBundle + - group: apps + kind: Deployment + name: gcp-credential-manager + namespace: capg-system + jsonPointers: + - /spec/template/metadata/annotations/checksum~1apiregistration.yaml + - group: apiextensions.k8s.io + kind: CustomResourceDefinition + name: servicemonitors.monitoring.coreos.com + jsonPointers: + - /metadata/annotations + - /spec diff --git a/argocd/capi-core/capi-catalog.yaml b/argocd/capi-core/capi-catalog.yaml new file mode 100644 index 000000000..fc00a7ec3 --- /dev/null +++ b/argocd/capi-core/capi-catalog.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: capi-catalog + namespace: argocd +spec: + project: default + source: + chart: capi-catalog + repoURL: ghcr.io/appscode-charts + targetRevision: v2024.10.24 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: capi-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/capi-core/capi-ops-manager.yaml b/argocd/capi-core/capi-ops-manager.yaml new file mode 100644 index 000000000..521a04dd0 --- /dev/null +++ b/argocd/capi-core/capi-ops-manager.yaml @@ -0,0 +1,46 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: capi-ops-manager + namespace: argocd +spec: + project: default + source: + chart: capi-ops-manager + repoURL: ghcr.io/appscode-charts + targetRevision: v2024.8.14 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: capi-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true + + ignoreDifferences: + - jsonPointers: + - /data + kind: Secret + name: capi-ops-manager-apiserver-cert + namespace: capi-system + - group: apiregistration.k8s.io + kind: APIService + name: v1alpha1.ui.openviz.dev + jsonPointers: + - /spec/caBundle + - group: apps + kind: Deployment + name: capi-ops-manager + namespace: capi-system + jsonPointers: + - /spec/template/metadata/annotations/checksum~1apiregistration.yaml + - group: apiextensions.k8s.io + kind: CustomResourceDefinition + name: servicemonitors.monitoring.coreos.com + jsonPointers: + - /metadata/annotations + - /spec diff --git a/argocd/capi-core/cluster-presets.yaml b/argocd/capi-core/cluster-presets.yaml new file mode 100644 index 000000000..91efe06f5 --- /dev/null +++ b/argocd/capi-core/cluster-presets.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: cluster-presets + namespace: argocd +spec: + project: default + source: + chart: cluster-presets + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.3.30 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kubeops + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/crossplane/crossplane.yaml b/argocd/crossplane/crossplane.yaml new file mode 100644 index 000000000..f2f37b925 --- /dev/null +++ b/argocd/crossplane/crossplane.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: crossplane + namespace: argocd +spec: + project: default + source: + chart: crossplane + repoURL: ghcr.io/appscode-charts + targetRevision: 1.14.0 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: crossplane-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/crossplane/kubedb-provider-aws.yaml b/argocd/crossplane/kubedb-provider-aws.yaml new file mode 100644 index 000000000..15283d39f --- /dev/null +++ b/argocd/crossplane/kubedb-provider-aws.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: kubedb-provider-aws + namespace: argocd +spec: + project: default + source: + chart: kubedb-provider-aws + repoURL: ghcr.io/appscode-charts + targetRevision: v2024.1.31 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: crossplane-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/crossplane/kubedb-provider-azure.yaml b/argocd/crossplane/kubedb-provider-azure.yaml new file mode 100644 index 000000000..dd898e39f --- /dev/null +++ b/argocd/crossplane/kubedb-provider-azure.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: kubedb-provider-azure + namespace: argocd +spec: + project: default + source: + chart: kubedb-provider-azure + repoURL: ghcr.io/appscode-charts + targetRevision: v2024.1.31 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: crossplane-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/crossplane/kubedb-provider-gcp.yaml b/argocd/crossplane/kubedb-provider-gcp.yaml new file mode 100644 index 000000000..07d7cec30 --- /dev/null +++ b/argocd/crossplane/kubedb-provider-gcp.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: kubedb-provider-gcp + namespace: argocd +spec: + project: default + source: + chart: kubedb-provider-gcp + repoURL: ghcr.io/appscode-charts + targetRevision: v2024.1.31 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: crossplane-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/ocm-hub/cluster-auth-manager.yaml b/argocd/ocm-hub/cluster-auth-manager.yaml new file mode 100644 index 000000000..ab62e9327 --- /dev/null +++ b/argocd/ocm-hub/cluster-auth-manager.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: cluster-auth-manager + namespace: argocd +spec: + project: default + source: + chart: cluster-auth-manager + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.2.16 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: open-cluster-management-addon + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/ocm-hub/cluster-gateway-manager.yaml b/argocd/ocm-hub/cluster-gateway-manager.yaml new file mode 100644 index 000000000..c33740584 --- /dev/null +++ b/argocd/ocm-hub/cluster-gateway-manager.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: cluster-gateway-manager + namespace: argocd +spec: + project: default + source: + chart: cluster-gateway-manager + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.2.16 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: open-cluster-management-addon + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/ocm-hub/cluster-manager-hub.yaml b/argocd/ocm-hub/cluster-manager-hub.yaml new file mode 100644 index 000000000..4f0faed9b --- /dev/null +++ b/argocd/ocm-hub/cluster-manager-hub.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: cluster-manager-hub + namespace: argocd +spec: + project: default + source: + chart: cluster-manager-hub + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.2.16 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: open-cluster-management + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/ocm-hub/cluster-profile-manager.yaml b/argocd/ocm-hub/cluster-profile-manager.yaml new file mode 100644 index 000000000..6ff69f5a4 --- /dev/null +++ b/argocd/ocm-hub/cluster-profile-manager.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: cluster-profile-manager + namespace: argocd +spec: + project: default + source: + chart: cluster-profile-manager + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.2.16 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: open-cluster-management-addon + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/ocm-hub/cluster-proxy-manager.yaml b/argocd/ocm-hub/cluster-proxy-manager.yaml new file mode 100644 index 000000000..a0cfb0910 --- /dev/null +++ b/argocd/ocm-hub/cluster-proxy-manager.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: cluster-proxy-manager + namespace: argocd +spec: + project: default + source: + chart: cluster-proxy-manager + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.2.16 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: open-cluster-management-addon + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/ocm-hub/fluxcd-manager.yaml b/argocd/ocm-hub/fluxcd-manager.yaml new file mode 100644 index 000000000..229d160c2 --- /dev/null +++ b/argocd/ocm-hub/fluxcd-manager.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: fluxcd-manager + namespace: argocd +spec: + project: default + source: + chart: fluxcd-manager + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.2.16 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: open-cluster-management-addon + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/ocm-hub/hub-cluster-robot.yaml b/argocd/ocm-hub/hub-cluster-robot.yaml new file mode 100644 index 000000000..fed480ab2 --- /dev/null +++ b/argocd/ocm-hub/hub-cluster-robot.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: hub-cluster-robot + namespace: argocd +spec: + project: default + source: + chart: hub-cluster-robot + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.2.16 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: open-cluster-management + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/ocm-hub/license-proxyserver-manager.yaml b/argocd/ocm-hub/license-proxyserver-manager.yaml new file mode 100644 index 000000000..e0c21b146 --- /dev/null +++ b/argocd/ocm-hub/license-proxyserver-manager.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: license-proxyserver-manager + namespace: argocd +spec: + project: default + source: + chart: license-proxyserver-manager + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.2.16 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: open-cluster-management-addon + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/ocm-hub/managed-serviceaccount-manager.yaml b/argocd/ocm-hub/managed-serviceaccount-manager.yaml new file mode 100644 index 000000000..8490829fc --- /dev/null +++ b/argocd/ocm-hub/managed-serviceaccount-manager.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: managed-serviceaccount-manager + namespace: argocd +spec: + project: default + source: + chart: managed-serviceaccount-manager + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.2.16 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: open-cluster-management-addon + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/ocm-spoke/cluster-manager-spoke.yaml b/argocd/ocm-spoke/cluster-manager-spoke.yaml new file mode 100644 index 000000000..c0923df06 --- /dev/null +++ b/argocd/ocm-spoke/cluster-manager-spoke.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: cluster-manager-spoke + namespace: argocd +spec: + project: default + source: + chart: cluster-manager-spoke + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.2.16 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: open-cluster-management + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-backup/kubestash.yaml b/argocd/opscenter-backup/kubestash.yaml new file mode 100644 index 000000000..4339aa063 --- /dev/null +++ b/argocd/opscenter-backup/kubestash.yaml @@ -0,0 +1,51 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: kubestash + namespace: argocd +spec: + project: default + source: + chart: kubestash + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.2.26 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: stash + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true + + ignoreDifferences: + - jsonPointers: + - /data + kind: Secret + name: kubestash-apiserver-cert + namespace: stash + - group: admissionregistration.k8s.io + kind: MutatingWebhookConfiguration + name: kubestash-kubestash-operator + jqPathExpressions: + - .webhooks[].clientConfig.caBundle + - group: admissionregistration.k8s.io + kind: ValidatingWebhookConfiguration + name: kubestash-kubestash-operator + jqPathExpressions: + - .webhooks[].clientConfig.caBundle + - group: apps + kind: Deployment + name: kubestash-kubestash-operator-operator + namespace: stash + jsonPointers: + - /spec/template/metadata/annotations/reload + - group: apps + kind: Deployment + name: kubestash-kubestash-operator-webhook-server + namespace: stash + jsonPointers: + - /spec/template/metadata/annotations/reload diff --git a/argocd/opscenter-backup/stash-opscenter.yaml b/argocd/opscenter-backup/stash-opscenter.yaml new file mode 100644 index 000000000..0c5496fb6 --- /dev/null +++ b/argocd/opscenter-backup/stash-opscenter.yaml @@ -0,0 +1,46 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: stash-opscenter + namespace: argocd +spec: + project: default + source: + chart: stash-opscenter + repoURL: ghcr.io/appscode-charts + targetRevision: v2025.7.31 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: stash + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true + + ignoreDifferences: + - jsonPointers: + - /data + kind: Secret + name: stash-opscenter-apiserver-cert + namespace: stash + - group: apiregistration.k8s.io + kind: APIService + name: v1alpha1.ui.openviz.dev + jsonPointers: + - /spec/caBundle + - group: apps + kind: Deployment + name: stash-opscenter + namespace: stash + jsonPointers: + - /spec/template/metadata/annotations/checksum~1apiregistration.yaml + - group: apiextensions.k8s.io + kind: CustomResourceDefinition + name: servicemonitors.monitoring.coreos.com + jsonPointers: + - /metadata/annotations + - /spec diff --git a/argocd/opscenter-backup/stash-presets.yaml b/argocd/opscenter-backup/stash-presets.yaml new file mode 100644 index 000000000..9dae91e7a --- /dev/null +++ b/argocd/opscenter-backup/stash-presets.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: stash-presets + namespace: argocd +spec: + project: default + source: + chart: stash-presets + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.3.30 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: stash + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-backup/stash.yaml b/argocd/opscenter-backup/stash.yaml new file mode 100644 index 000000000..ca6571781 --- /dev/null +++ b/argocd/opscenter-backup/stash.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: stash + namespace: argocd +spec: + project: default + source: + chart: stash + repoURL: ghcr.io/appscode-charts + targetRevision: v2025.7.31 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: stash + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-core/aceshifter.yaml b/argocd/opscenter-core/aceshifter.yaml new file mode 100644 index 000000000..87f08d0b2 --- /dev/null +++ b/argocd/opscenter-core/aceshifter.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: aceshifter + namespace: argocd +spec: + project: default + source: + chart: aceshifter + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.3.30 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kubeops + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-core/flux2.yaml b/argocd/opscenter-core/flux2.yaml new file mode 100644 index 000000000..19d527363 --- /dev/null +++ b/argocd/opscenter-core/flux2.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: flux2 + namespace: argocd +spec: + project: default + source: + chart: flux2 + repoURL: ghcr.io/appscode-charts + targetRevision: 2.17.0 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: flux-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-core/kube-ui-server.yaml b/argocd/opscenter-core/kube-ui-server.yaml new file mode 100644 index 000000000..8eaeeabe6 --- /dev/null +++ b/argocd/opscenter-core/kube-ui-server.yaml @@ -0,0 +1,46 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: kube-ui-server + namespace: argocd +spec: + project: default + source: + chart: kube-ui-server + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.3.30 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kubeops + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true + + ignoreDifferences: + - jsonPointers: + - /data + kind: Secret + name: kube-ui-server-apiserver-cert + namespace: kubeops + - group: apiregistration.k8s.io + kind: APIService + name: v1alpha1.ui.openviz.dev + jsonPointers: + - /spec/caBundle + - group: apps + kind: Deployment + name: kube-ui-server + namespace: kubeops + jsonPointers: + - /spec/template/metadata/annotations/checksum~1apiregistration.yaml + - group: apiextensions.k8s.io + kind: CustomResourceDefinition + name: servicemonitors.monitoring.coreos.com + jsonPointers: + - /metadata/annotations + - /spec diff --git a/argocd/opscenter-core/license-proxyserver.yaml b/argocd/opscenter-core/license-proxyserver.yaml new file mode 100644 index 000000000..9656256b6 --- /dev/null +++ b/argocd/opscenter-core/license-proxyserver.yaml @@ -0,0 +1,41 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: license-proxyserver + namespace: argocd +spec: + project: default + source: + chart: license-proxyserver + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.2.16 + helm: + values: | + platform: + baseURL: https://appscode.com + token: '****************************************' + destination: + server: "https://kubernetes.default.svc" + namespace: kubeops + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true + + ignoreDifferences: + - jsonPointers: + - /data + kind: Secret + name: license-proxyserver-apiserver-cert + namespace: kubeops + - group: apiregistration.k8s.io + kind: APIService + name: v1alpha1.proxyserver.licenses.appscode.com + jsonPointers: + - /spec/caBundle + - group: apiextensions.k8s.io + kind: CustomResourceDefinition + name: servicemonitors.monitoring.coreos.com + jsonPointers: + - /metadata/annotations + - /spec diff --git a/argocd/opscenter-cost/keda-add-ons-http.yaml b/argocd/opscenter-cost/keda-add-ons-http.yaml new file mode 100644 index 000000000..50bff8818 --- /dev/null +++ b/argocd/opscenter-cost/keda-add-ons-http.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: keda-add-ons-http + namespace: argocd +spec: + project: default + source: + chart: keda-add-ons-http + repoURL: ghcr.io/appscode-charts + targetRevision: 0.12.0 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: keda + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-cost/keda.yaml b/argocd/opscenter-cost/keda.yaml new file mode 100644 index 000000000..c0b58f9f0 --- /dev/null +++ b/argocd/opscenter-cost/keda.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: keda + namespace: argocd +spec: + project: default + source: + chart: keda + repoURL: ghcr.io/appscode-charts + targetRevision: 2.19.0 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: keda + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-cost/opencost-grafana-dashboards.yaml b/argocd/opscenter-cost/opencost-grafana-dashboards.yaml new file mode 100644 index 000000000..732639ec5 --- /dev/null +++ b/argocd/opscenter-cost/opencost-grafana-dashboards.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: opencost-grafana-dashboards + namespace: argocd +spec: + project: default + source: + chart: opencost-grafana-dashboards + repoURL: ghcr.io/appscode-charts + targetRevision: v2023.10.1 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: opencost + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-cost/opencost.yaml b/argocd/opscenter-cost/opencost.yaml new file mode 100644 index 000000000..0909b22d8 --- /dev/null +++ b/argocd/opscenter-cost/opencost.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: opencost + namespace: argocd +spec: + project: default + source: + chart: opencost + repoURL: ghcr.io/appscode-charts + targetRevision: 1.18.1 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: opencost + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-datastore/kubedb-opscenter.yaml b/argocd/opscenter-datastore/kubedb-opscenter.yaml new file mode 100644 index 000000000..caa893bdc --- /dev/null +++ b/argocd/opscenter-datastore/kubedb-opscenter.yaml @@ -0,0 +1,46 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: kubedb-opscenter + namespace: argocd +spec: + project: default + source: + chart: kubedb-opscenter + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.2.26 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kubedb + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true + + ignoreDifferences: + - jsonPointers: + - /data + kind: Secret + name: kubedb-opscenter-apiserver-cert + namespace: kubedb + - group: apiregistration.k8s.io + kind: APIService + name: v1alpha1.ui.openviz.dev + jsonPointers: + - /spec/caBundle + - group: apps + kind: Deployment + name: kubedb-opscenter + namespace: kubedb + jsonPointers: + - /spec/template/metadata/annotations/checksum~1apiregistration.yaml + - group: apiextensions.k8s.io + kind: CustomResourceDefinition + name: servicemonitors.monitoring.coreos.com + jsonPointers: + - /metadata/annotations + - /spec diff --git a/argocd/opscenter-datastore/kubedb-ui-presets.yaml b/argocd/opscenter-datastore/kubedb-ui-presets.yaml new file mode 100644 index 000000000..78011eafb --- /dev/null +++ b/argocd/opscenter-datastore/kubedb-ui-presets.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: kubedb-ui-presets + namespace: argocd +spec: + project: default + source: + chart: kubedb-ui-presets + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.3.30 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kubedb + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-datastore/kubedb.yaml b/argocd/opscenter-datastore/kubedb.yaml new file mode 100644 index 000000000..df7cce612 --- /dev/null +++ b/argocd/opscenter-datastore/kubedb.yaml @@ -0,0 +1,130 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: kubedb + namespace: argocd +spec: + project: default + source: + chart: kubedb + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.2.26 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kubedb + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true + + ignoreDifferences: + - jsonPointers: + - /data + kind: Secret + name: kubedb-apiserver-cert + namespace: kubedb + - jsonPointers: + - /data + kind: Secret + name: kubedb-petset-cert + namespace: kubedb + - jsonPointers: + - /data + kind: Secret + name: kubedb-sidekick-cert + namespace: kubedb + - group: admissionregistration.k8s.io + kind: MutatingWebhookConfiguration + name: mutators.petset.appscode.com + jqPathExpressions: + - .webhooks[].clientConfig.caBundle + - group: admissionregistration.k8s.io + kind: MutatingWebhookConfiguration + name: mutators.kubedb.com + jqPathExpressions: + - .webhooks[].clientConfig.caBundle + - group: admissionregistration.k8s.io + kind: MutatingWebhookConfiguration + name: mutators.autoscaling.kubedb.com + jqPathExpressions: + - .webhooks[].clientConfig.caBundle + - group: admissionregistration.k8s.io + kind: MutatingWebhookConfiguration + name: mutators.elasticsearch.kubedb.com + jqPathExpressions: + - .webhooks[].clientConfig.caBundle + - group: admissionregistration.k8s.io + kind: MutatingWebhookConfiguration + name: mutators.schema.kubedb.com + jqPathExpressions: + - .webhooks[].clientConfig.caBundle + - group: admissionregistration.k8s.io + kind: ValidatingWebhookConfiguration + name: validators.autoscaling.kubedb.com + jqPathExpressions: + - .webhooks[].clientConfig.caBundle + - group: admissionregistration.k8s.io + kind: ValidatingWebhookConfiguration + name: validators.elasticsearch.kubedb.com + jqPathExpressions: + - .webhooks[].clientConfig.caBundle + - group: admissionregistration.k8s.io + kind: ValidatingWebhookConfiguration + name: validators.kubedb.com + jqPathExpressions: + - .webhooks[].clientConfig.caBundle + - group: admissionregistration.k8s.io + kind: ValidatingWebhookConfiguration + name: validators.ops.kubedb.com + jqPathExpressions: + - .webhooks[].clientConfig.caBundle + - group: admissionregistration.k8s.io + kind: ValidatingWebhookConfiguration + name: validators.petset.appscode.com + jqPathExpressions: + - .webhooks[].clientConfig.caBundle + - group: admissionregistration.k8s.io + kind: ValidatingWebhookConfiguration + name: validators.schema.kubedb.com + jqPathExpressions: + - .webhooks[].clientConfig.caBundle + - group: apps + kind: StatefulSet + name: kubedb-kubedb-autoscaler + namespace: kubedb + jsonPointers: + - /spec/template/metadata/annotations/reload + - group: apps + kind: StatefulSet + name: kubedb-kubedb-ops-manager + namespace: kubedb + jsonPointers: + - /spec/template/metadata/annotations/reload + - group: apps + kind: StatefulSet + name: kubedb-kubedb-provisioner + namespace: kubedb + jsonPointers: + - /spec/template/metadata/annotations/reload + - group: apps + kind: Deployment + name: kubedb-kubedb-webhook-server + namespace: kubedb + jsonPointers: + - /spec/template/metadata/annotations/reload + - group: apps + kind: Deployment + name: kubedb-petset + namespace: kubedb + jsonPointers: + - /spec/template/metadata/annotations/reload + - group: apps + kind: Deployment + name: kubedb-sidekick + namespace: kubedb + jsonPointers: + - /spec/template/metadata/annotations/reload diff --git a/argocd/opscenter-datastore/prepare-cluster.yaml b/argocd/opscenter-datastore/prepare-cluster.yaml new file mode 100644 index 000000000..11c718707 --- /dev/null +++ b/argocd/opscenter-datastore/prepare-cluster.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: prepare-cluster + namespace: argocd +spec: + project: default + source: + chart: prepare-cluster + repoURL: ghcr.io/appscode-charts + targetRevision: v2023.12.21 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kubedb + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-networking/external-dns-operator.yaml b/argocd/opscenter-networking/external-dns-operator.yaml new file mode 100644 index 000000000..bad7050c8 --- /dev/null +++ b/argocd/opscenter-networking/external-dns-operator.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: external-dns-operator + namespace: argocd +spec: + project: default + source: + chart: external-dns-operator + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.1.15 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kubeops + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-networking/gateway-api.yaml b/argocd/opscenter-networking/gateway-api.yaml new file mode 100644 index 000000000..e3eb38e62 --- /dev/null +++ b/argocd/opscenter-networking/gateway-api.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: gateway-api + namespace: argocd +spec: + project: default + source: + chart: gateway-api + repoURL: ghcr.io/appscode-charts + targetRevision: v2025.3.14 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: envoy-gateway-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-networking/voyager-gateway.yaml b/argocd/opscenter-networking/voyager-gateway.yaml new file mode 100644 index 000000000..83d3d7542 --- /dev/null +++ b/argocd/opscenter-networking/voyager-gateway.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: voyager-gateway + namespace: argocd +spec: + project: default + source: + chart: voyager-gateway + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.1.15 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: envoy-gateway-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-networking/voyager.yaml b/argocd/opscenter-networking/voyager.yaml new file mode 100644 index 000000000..28dc00fa4 --- /dev/null +++ b/argocd/opscenter-networking/voyager.yaml @@ -0,0 +1,55 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: voyager + namespace: argocd +spec: + project: default + source: + chart: voyager + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.3.23 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: voyager + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true + + ignoreDifferences: + - jsonPointers: + - /data + kind: Secret + name: voyager-apiserver-cert + namespace: voyager + - group: admissionregistration.k8s.io + kind: MutatingWebhookConfiguration + name: mutators.voyager.appscode.com + jqPathExpressions: + - .webhooks[].clientConfig.caBundle + - group: admissionregistration.k8s.io + kind: ValidatingWebhookConfiguration + name: validators.voyager.appscode.com + jqPathExpressions: + - .webhooks[].clientConfig.caBundle + - group: apiregistration.k8s.io + kind: APIService + name: v1alpha1.validators.voyager.appscode.com + jsonPointers: + - /spec/caBundle + - group: apiregistration.k8s.io + kind: APIService + name: v1alpha1.mutators.voyager.appscode.com + jsonPointers: + - /spec/caBundle + - group: apps + kind: Deployment + name: voyager-voyager-operator + namespace: voyager + jsonPointers: + - /spec/template/metadata/annotations/reload diff --git a/argocd/opscenter-observability/grafana-operator.yaml b/argocd/opscenter-observability/grafana-operator.yaml new file mode 100644 index 000000000..ba7b75016 --- /dev/null +++ b/argocd/opscenter-observability/grafana-operator.yaml @@ -0,0 +1,46 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: grafana-operator + namespace: argocd +spec: + project: default + source: + chart: grafana-operator + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.3.30 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: monitoring + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true + + ignoreDifferences: + - jsonPointers: + - /data + kind: Secret + name: grafana-operator-apiserver-cert + namespace: monitoring + - group: apiregistration.k8s.io + kind: APIService + name: v1alpha1.ui.openviz.dev + jsonPointers: + - /spec/caBundle + - group: apps + kind: Deployment + name: grafana-operator + namespace: monitoring + jsonPointers: + - /spec/template/metadata/annotations/checksum~1apiregistration.yaml + - group: apiextensions.k8s.io + kind: CustomResourceDefinition + name: servicemonitors.monitoring.coreos.com + jsonPointers: + - /metadata/annotations + - /spec diff --git a/argocd/opscenter-observability/inbox-agent.yaml b/argocd/opscenter-observability/inbox-agent.yaml new file mode 100644 index 000000000..35a60e53b --- /dev/null +++ b/argocd/opscenter-observability/inbox-agent.yaml @@ -0,0 +1,39 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: inbox-agent + namespace: argocd +spec: + project: default + source: + chart: inbox-agent + repoURL: ghcr.io/appscode-charts + targetRevision: v2024.12.30 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: monitoring + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true + + ignoreDifferences: + - jsonPointers: + - /data + kind: Secret + name: inbox-agent-apiserver-cert + namespace: monitoring + - group: admissionregistration.k8s.io + kind: MutatingWebhookConfiguration + name: inbox-agent + jqPathExpressions: + - .webhooks[].clientConfig.caBundle + - group: admissionregistration.k8s.io + kind: ValidatingWebhookConfiguration + name: inbox-agent + jqPathExpressions: + - .webhooks[].clientConfig.caBundle diff --git a/argocd/opscenter-observability/inbox-server.yaml b/argocd/opscenter-observability/inbox-server.yaml new file mode 100644 index 000000000..2574d7199 --- /dev/null +++ b/argocd/opscenter-observability/inbox-server.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: inbox-server + namespace: argocd +spec: + project: default + source: + chart: inbox-server + repoURL: ghcr.io/appscode-charts + targetRevision: v2025.2.28 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: ace + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-observability/inbox-ui.yaml b/argocd/opscenter-observability/inbox-ui.yaml new file mode 100644 index 000000000..e2eab1335 --- /dev/null +++ b/argocd/opscenter-observability/inbox-ui.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: inbox-ui + namespace: argocd +spec: + project: default + source: + chart: inbox-ui + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.3.30 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: ace + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-observability/kube-grafana-dashboards.yaml b/argocd/opscenter-observability/kube-grafana-dashboards.yaml new file mode 100644 index 000000000..2284c0ab8 --- /dev/null +++ b/argocd/opscenter-observability/kube-grafana-dashboards.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: kube-grafana-dashboards + namespace: argocd +spec: + project: default + source: + chart: kube-grafana-dashboards + repoURL: ghcr.io/appscode-charts + targetRevision: v2023.10.1 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: monitoring + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-observability/kube-prometheus-stack.yaml b/argocd/opscenter-observability/kube-prometheus-stack.yaml new file mode 100644 index 000000000..4a300d428 --- /dev/null +++ b/argocd/opscenter-observability/kube-prometheus-stack.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: kube-prometheus-stack + namespace: argocd +spec: + project: default + source: + chart: kube-prometheus-stack + repoURL: ghcr.io/appscode-charts + targetRevision: 69.2.2 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: monitoring + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-observability/metrics-server.yaml b/argocd/opscenter-observability/metrics-server.yaml new file mode 100644 index 000000000..0390c3270 --- /dev/null +++ b/argocd/opscenter-observability/metrics-server.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: metrics-server + namespace: argocd +spec: + project: default + source: + chart: metrics-server + repoURL: ghcr.io/appscode-charts + targetRevision: 3.11.0 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: monitoring + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-observability/monitoring-operator.yaml b/argocd/opscenter-observability/monitoring-operator.yaml new file mode 100644 index 000000000..46f9b79a0 --- /dev/null +++ b/argocd/opscenter-observability/monitoring-operator.yaml @@ -0,0 +1,54 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: monitoring-operator + namespace: argocd +spec: + project: default + source: + chart: monitoring-operator + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.3.30 + helm: + values: | + tolerations: + - key: "role" + operator: "Equal" + value: "worker_node_svc" + effect: "NoSchedule" + monitoring: + agent: "prometheus.io/operator" + serviceMonitor: + labels: + release: prometheus-operator + destination: + server: "https://kubernetes.default.svc" + namespace: monitoring + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true + + ignoreDifferences: + - jsonPointers: + - /data + kind: Secret + name: monitoring-operator-apiserver-cert + namespace: monitoring + - group: apiregistration.k8s.io + kind: APIService + name: v1alpha1.ui.openviz.dev + jsonPointers: + - /spec/caBundle + - group: apps + kind: Deployment + name: monitoring-operator + namespace: monitoring + jsonPointers: + - /spec/template/metadata/annotations/checksum~1apiregistration.yaml + - group: apiextensions.k8s.io + kind: CustomResourceDefinition + name: servicemonitors.monitoring.coreos.com + jsonPointers: + - /metadata/annotations + - /spec diff --git a/argocd/opscenter-observability/panopticon.yaml b/argocd/opscenter-observability/panopticon.yaml new file mode 100644 index 000000000..da9ab5d5d --- /dev/null +++ b/argocd/opscenter-observability/panopticon.yaml @@ -0,0 +1,52 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: panopticon + namespace: argocd +spec: + project: default + source: + chart: panopticon + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.1.15 + helm: + values: | + ace-user-roles: + enabled: false + monitoring: + agent: prometheus.io/operator + enabled: true + serviceMonitor: + labels: + release: kube-prometheus-stack + destination: + server: "https://kubernetes.default.svc" + namespace: monitoring + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true + + ignoreDifferences: + - jsonPointers: + - /data + kind: Secret + name: panopticon-apiserver-cert + namespace: monitoring + - group: apiregistration.k8s.io + kind: APIService + name: v1alpha1.ui.openviz.dev + jsonPointers: + - /spec/caBundle + - group: apps + kind: Deployment + name: panopticon + namespace: monitoring + jsonPointers: + - /spec/template/metadata/annotations/checksum~1apiregistration.yaml + - group: apiextensions.k8s.io + kind: CustomResourceDefinition + name: servicemonitors.monitoring.coreos.com + jsonPointers: + - /metadata/annotations + - /spec diff --git a/argocd/opscenter-observability/prometheus-adapter.yaml b/argocd/opscenter-observability/prometheus-adapter.yaml new file mode 100644 index 000000000..2422e182b --- /dev/null +++ b/argocd/opscenter-observability/prometheus-adapter.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: prometheus-adapter + namespace: argocd +spec: + project: default + source: + chart: prometheus-adapter + repoURL: ghcr.io/appscode-charts + targetRevision: 4.9.0 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: monitoring + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-policy-management/gatekeeper-grafana-dashboards.yaml b/argocd/opscenter-policy-management/gatekeeper-grafana-dashboards.yaml new file mode 100644 index 000000000..26c7b14c7 --- /dev/null +++ b/argocd/opscenter-policy-management/gatekeeper-grafana-dashboards.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: gatekeeper-grafana-dashboards + namespace: argocd +spec: + project: default + source: + chart: gatekeeper-grafana-dashboards + repoURL: ghcr.io/appscode-charts + targetRevision: v2023.10.1 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kubeops + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-policy-management/gatekeeper-library.yaml b/argocd/opscenter-policy-management/gatekeeper-library.yaml new file mode 100644 index 000000000..995c62d2c --- /dev/null +++ b/argocd/opscenter-policy-management/gatekeeper-library.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: gatekeeper-library + namespace: argocd +spec: + project: default + source: + chart: gatekeeper-library + repoURL: ghcr.io/appscode-charts + targetRevision: v2023.10.1 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: gatekeeper-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-policy-management/gatekeeper.yaml b/argocd/opscenter-policy-management/gatekeeper.yaml new file mode 100644 index 000000000..4f0e1967d --- /dev/null +++ b/argocd/opscenter-policy-management/gatekeeper.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: gatekeeper + namespace: argocd +spec: + project: default + source: + chart: gatekeeper + repoURL: ghcr.io/appscode-charts + targetRevision: 3.13.3 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: gatekeeper-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-policy-management/kyverno-policies.yaml b/argocd/opscenter-policy-management/kyverno-policies.yaml new file mode 100644 index 000000000..3b60ebd7f --- /dev/null +++ b/argocd/opscenter-policy-management/kyverno-policies.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: kyverno-policies + namespace: argocd +spec: + project: default + source: + chart: kyverno-policies + repoURL: ghcr.io/appscode-charts + targetRevision: 3.2.5 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kyverno + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-policy-management/kyverno.yaml b/argocd/opscenter-policy-management/kyverno.yaml new file mode 100644 index 000000000..f6714c0dd --- /dev/null +++ b/argocd/opscenter-policy-management/kyverno.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: kyverno + namespace: argocd +spec: + project: default + source: + chart: kyverno + repoURL: ghcr.io/appscode-charts + targetRevision: 3.2.6 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kyverno + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-secret-management/config-syncer.yaml b/argocd/opscenter-secret-management/config-syncer.yaml new file mode 100644 index 000000000..0b32bdbe5 --- /dev/null +++ b/argocd/opscenter-secret-management/config-syncer.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: config-syncer + namespace: argocd +spec: + project: default + source: + chart: config-syncer + repoURL: ghcr.io/appscode-charts + targetRevision: v0.15.4 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kubeops + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-secret-management/csi-secrets-store-provider-azure.yaml b/argocd/opscenter-secret-management/csi-secrets-store-provider-azure.yaml new file mode 100644 index 000000000..d2bcff640 --- /dev/null +++ b/argocd/opscenter-secret-management/csi-secrets-store-provider-azure.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: csi-secrets-store-provider-azure + namespace: argocd +spec: + project: default + source: + chart: csi-secrets-store-provider-azure + repoURL: ghcr.io/appscode-charts + targetRevision: 1.5.2 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kube-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-secret-management/external-secrets.yaml b/argocd/opscenter-secret-management/external-secrets.yaml new file mode 100644 index 000000000..78df9384c --- /dev/null +++ b/argocd/opscenter-secret-management/external-secrets.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: external-secrets + namespace: argocd +spec: + project: default + source: + chart: external-secrets + repoURL: ghcr.io/appscode-charts + targetRevision: 0.9.12 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: external-secrets + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-secret-management/kubevault-opscenter.yaml b/argocd/opscenter-secret-management/kubevault-opscenter.yaml new file mode 100644 index 000000000..5ea39cd85 --- /dev/null +++ b/argocd/opscenter-secret-management/kubevault-opscenter.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: kubevault-opscenter + namespace: argocd +spec: + project: default + source: + chart: kubevault-opscenter + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.2.27 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kubevault + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-secret-management/kubevault.yaml b/argocd/opscenter-secret-management/kubevault.yaml new file mode 100644 index 000000000..e97478220 --- /dev/null +++ b/argocd/opscenter-secret-management/kubevault.yaml @@ -0,0 +1,91 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: kubevault + namespace: argocd +spec: + project: default + source: + chart: kubevault + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.2.27 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kubevault + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true + + ignoreDifferences: + - jsonPointers: + - /data + kind: Secret + name: kubevault-apiserver-cert + namespace: kubevault + - group: admissionregistration.k8s.io + kind: MutatingWebhookConfiguration + name: mutators.engine.kubevault.com + jqPathExpressions: + - .webhooks[].clientConfig.caBundle + - group: admissionregistration.k8s.io + kind: MutatingWebhookConfiguration + name: mutators.kubevault.com + jqPathExpressions: + - .webhooks[].clientConfig.caBundle + - group: admissionregistration.k8s.io + kind: MutatingWebhookConfiguration + name: mutators.policy.kubevault.com + jqPathExpressions: + - .webhooks[].clientConfig.caBundle + - group: admissionregistration.k8s.io + kind: ValidatingWebhookConfiguration + name: validators.engine.kubevault.com + jqPathExpressions: + - .webhooks[].clientConfig.caBundle + - group: admissionregistration.k8s.io + kind: ValidatingWebhookConfiguration + name: validators.kubevault.com + jqPathExpressions: + - .webhooks[].clientConfig.caBundle + - group: apiregistration.k8s.io + kind: APIService + name: v1alpha1.mutators.engine.kubevault.com + jsonPointers: + - /spec/caBundle + - group: apiregistration.k8s.io + kind: APIService + name: v1alpha1.mutators.kubevault.com + jsonPointers: + - /spec/caBundle + - group: apiregistration.k8s.io + kind: APIService + name: v1alpha1.mutators.policy.kubevault.com + jsonPointers: + - /spec/caBundle + - group: apiregistration.k8s.io + kind: APIService + name: v1alpha1.validators.engine.kubevault.com + jsonPointers: + - /spec/caBundle + - group: apiregistration.k8s.io + kind: APIService + name: v1alpha1.validators.kubevault.com + jsonPointers: + - /spec/caBundle + - group: apps + kind: Deployment + name: kubevault-kubevault-operator + namespace: kubevault + jsonPointers: + - /spec/template/metadata/annotations/reload + - group: apps + kind: Deployment + name: kubevault-kubevault-webhook-server + namespace: kubevault + jsonPointers: + - /spec/template/metadata/annotations/reload diff --git a/argocd/opscenter-secret-management/reloader.yaml b/argocd/opscenter-secret-management/reloader.yaml new file mode 100644 index 000000000..1413c089c --- /dev/null +++ b/argocd/opscenter-secret-management/reloader.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: reloader + namespace: argocd +spec: + project: default + source: + chart: reloader + repoURL: ghcr.io/appscode-charts + targetRevision: 2.2.9 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kubeops + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-secret-management/sealed-secrets.yaml b/argocd/opscenter-secret-management/sealed-secrets.yaml new file mode 100644 index 000000000..ab047a13a --- /dev/null +++ b/argocd/opscenter-secret-management/sealed-secrets.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: sealed-secrets + namespace: argocd +spec: + project: default + source: + chart: sealed-secrets + repoURL: ghcr.io/appscode-charts + targetRevision: 2.14.2 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kube-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-secret-management/secrets-store-csi-driver-provider-aws.yaml b/argocd/opscenter-secret-management/secrets-store-csi-driver-provider-aws.yaml new file mode 100644 index 000000000..a2fb1436f --- /dev/null +++ b/argocd/opscenter-secret-management/secrets-store-csi-driver-provider-aws.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: secrets-store-csi-driver-provider-aws + namespace: argocd +spec: + project: default + source: + chart: secrets-store-csi-driver-provider-aws + repoURL: ghcr.io/appscode-charts + targetRevision: 0.3.6 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kube-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-secret-management/secrets-store-csi-driver-provider-gcp.yaml b/argocd/opscenter-secret-management/secrets-store-csi-driver-provider-gcp.yaml new file mode 100644 index 000000000..e9fdb53ff --- /dev/null +++ b/argocd/opscenter-secret-management/secrets-store-csi-driver-provider-gcp.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: secrets-store-csi-driver-provider-gcp + namespace: argocd +spec: + project: default + source: + chart: secrets-store-csi-driver-provider-gcp + repoURL: ghcr.io/appscode-charts + targetRevision: 0.1.0 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kube-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-secret-management/secrets-store-csi-driver-provider-virtual-secrets.yaml b/argocd/opscenter-secret-management/secrets-store-csi-driver-provider-virtual-secrets.yaml new file mode 100644 index 000000000..f6c407c2c --- /dev/null +++ b/argocd/opscenter-secret-management/secrets-store-csi-driver-provider-virtual-secrets.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: secrets-store-csi-driver-provider-virtual-secrets + namespace: argocd +spec: + project: default + source: + chart: secrets-store-csi-driver-provider-virtual-secrets + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.2.27 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kube-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-secret-management/secrets-store-csi-driver.yaml b/argocd/opscenter-secret-management/secrets-store-csi-driver.yaml new file mode 100644 index 000000000..1a10d9b6c --- /dev/null +++ b/argocd/opscenter-secret-management/secrets-store-csi-driver.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: secrets-store-csi-driver + namespace: argocd +spec: + project: default + source: + chart: secrets-store-csi-driver + repoURL: ghcr.io/appscode-charts + targetRevision: 1.4.1 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kube-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-secret-management/vault-secrets-operator.yaml b/argocd/opscenter-secret-management/vault-secrets-operator.yaml new file mode 100644 index 000000000..39344514e --- /dev/null +++ b/argocd/opscenter-secret-management/vault-secrets-operator.yaml @@ -0,0 +1,21 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: vault-secrets-operator + namespace: argocd +spec: + project: default + source: + chart: vault-secrets-operator + repoURL: ghcr.io/appscode-charts + targetRevision: 0.4.3 + helm: + values: | + defaultSecretEngine: false + destination: + server: "https://kubernetes.default.svc" + namespace: vault-secrets-operator-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-secret-management/virtual-secrets-server.yaml b/argocd/opscenter-secret-management/virtual-secrets-server.yaml new file mode 100644 index 000000000..283e48ba6 --- /dev/null +++ b/argocd/opscenter-secret-management/virtual-secrets-server.yaml @@ -0,0 +1,46 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: virtual-secrets-server + namespace: argocd +spec: + project: default + source: + chart: virtual-secrets-server + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.2.27 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kubevault + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true + + ignoreDifferences: + - jsonPointers: + - /data + kind: Secret + name: virtual-secrets-server-apiserver-cert + namespace: kubevault + - group: apiregistration.k8s.io + kind: APIService + name: v1alpha1.ui.openviz.dev + jsonPointers: + - /spec/caBundle + - group: apps + kind: Deployment + name: virtual-secrets-server + namespace: kubevault + jsonPointers: + - /spec/template/metadata/annotations/checksum~1apiregistration.yaml + - group: apiextensions.k8s.io + kind: CustomResourceDefinition + name: servicemonitors.monitoring.coreos.com + jsonPointers: + - /metadata/annotations + - /spec diff --git a/argocd/opscenter-security/cert-manager-csi-driver-cacerts.yaml b/argocd/opscenter-security/cert-manager-csi-driver-cacerts.yaml new file mode 100644 index 000000000..3140f0980 --- /dev/null +++ b/argocd/opscenter-security/cert-manager-csi-driver-cacerts.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: cert-manager-csi-driver-cacerts + namespace: argocd +spec: + project: default + source: + chart: cert-manager-csi-driver-cacerts + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.1.15 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: cert-manager + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-security/cert-manager.yaml b/argocd/opscenter-security/cert-manager.yaml new file mode 100644 index 000000000..c7f55a58b --- /dev/null +++ b/argocd/opscenter-security/cert-manager.yaml @@ -0,0 +1,21 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: cert-manager + namespace: argocd +spec: + project: default + source: + chart: cert-manager + repoURL: ghcr.io/appscode-charts + targetRevision: v1.19.3 + helm: + values: | + installCRDs: "true" + destination: + server: "https://kubernetes.default.svc" + namespace: cert-manager + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-security/falco-ui-server.yaml b/argocd/opscenter-security/falco-ui-server.yaml new file mode 100644 index 000000000..8594bcc6f --- /dev/null +++ b/argocd/opscenter-security/falco-ui-server.yaml @@ -0,0 +1,46 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: falco-ui-server + namespace: argocd +spec: + project: default + source: + chart: falco-ui-server + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.1.15 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: falco + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true + + ignoreDifferences: + - jsonPointers: + - /data + kind: Secret + name: falco-ui-server-apiserver-cert + namespace: falco + - group: apiregistration.k8s.io + kind: APIService + name: v1alpha1.ui.openviz.dev + jsonPointers: + - /spec/caBundle + - group: apps + kind: Deployment + name: falco-ui-server + namespace: falco + jsonPointers: + - /spec/template/metadata/annotations/checksum~1apiregistration.yaml + - group: apiextensions.k8s.io + kind: CustomResourceDefinition + name: servicemonitors.monitoring.coreos.com + jsonPointers: + - /metadata/annotations + - /spec diff --git a/argocd/opscenter-security/falco.yaml b/argocd/opscenter-security/falco.yaml new file mode 100644 index 000000000..658a61bd5 --- /dev/null +++ b/argocd/opscenter-security/falco.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: falco + namespace: argocd +spec: + project: default + source: + chart: falco + repoURL: ghcr.io/appscode-charts + targetRevision: 4.0.0 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: falco + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-security/scanner.yaml b/argocd/opscenter-security/scanner.yaml new file mode 100644 index 000000000..39d07d3a6 --- /dev/null +++ b/argocd/opscenter-security/scanner.yaml @@ -0,0 +1,46 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: scanner + namespace: argocd +spec: + project: default + source: + chart: scanner + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.1.15 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kubeops + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true + + ignoreDifferences: + - jsonPointers: + - /data + kind: Secret + name: scanner-apiserver-cert + namespace: kubeops + - group: apiregistration.k8s.io + kind: APIService + name: v1alpha1.ui.openviz.dev + jsonPointers: + - /spec/caBundle + - group: apps + kind: Deployment + name: scanner + namespace: kubeops + jsonPointers: + - /spec/template/metadata/annotations/checksum~1apiregistration.yaml + - group: apiextensions.k8s.io + kind: CustomResourceDefinition + name: servicemonitors.monitoring.coreos.com + jsonPointers: + - /metadata/annotations + - /spec diff --git a/argocd/opscenter-storage/csi-driver-nfs.yaml b/argocd/opscenter-storage/csi-driver-nfs.yaml new file mode 100644 index 000000000..0446dee73 --- /dev/null +++ b/argocd/opscenter-storage/csi-driver-nfs.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: csi-driver-nfs + namespace: argocd +spec: + project: default + source: + chart: csi-driver-nfs + repoURL: ghcr.io/appscode-charts + targetRevision: v4.7.0 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kube-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-storage/longhorn.yaml b/argocd/opscenter-storage/longhorn.yaml new file mode 100644 index 000000000..6b932372b --- /dev/null +++ b/argocd/opscenter-storage/longhorn.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: longhorn + namespace: argocd +spec: + project: default + source: + chart: longhorn + repoURL: ghcr.io/appscode-charts + targetRevision: 1.7.2 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: longhorn-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-storage/snapshot-controller.yaml b/argocd/opscenter-storage/snapshot-controller.yaml new file mode 100644 index 000000000..6366d5a44 --- /dev/null +++ b/argocd/opscenter-storage/snapshot-controller.yaml @@ -0,0 +1,34 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: snapshot-controller + namespace: argocd +spec: + project: default + source: + chart: snapshot-controller + repoURL: ghcr.io/appscode-charts + targetRevision: 3.0.6 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kubeops + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true + + ignoreDifferences: + - jsonPointers: + - /data + kind: Secret + name: snapshot-controller-apiserver-cert + namespace: kubeops + - group: admissionregistration.k8s.io + kind: MutatingWebhookConfiguration + name: snapshot-validation + jqPathExpressions: + - .webhooks[].clientConfig.caBundle diff --git a/argocd/opscenter-storage/topolvm.yaml b/argocd/opscenter-storage/topolvm.yaml new file mode 100644 index 000000000..d1813ab67 --- /dev/null +++ b/argocd/opscenter-storage/topolvm.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: topolvm + namespace: argocd +spec: + project: default + source: + chart: topolvm + repoURL: ghcr.io/appscode-charts + targetRevision: 15.0.0 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: topolvm-system + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/opscenter-tools/operator-shard-manager.yaml b/argocd/opscenter-tools/operator-shard-manager.yaml new file mode 100644 index 000000000..e85be95fc --- /dev/null +++ b/argocd/opscenter-tools/operator-shard-manager.yaml @@ -0,0 +1,46 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: operator-shard-manager + namespace: argocd +spec: + project: default + source: + chart: operator-shard-manager + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.1.15 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kubeops + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true + + ignoreDifferences: + - jsonPointers: + - /data + kind: Secret + name: operator-shard-manager-apiserver-cert + namespace: kubeops + - group: apiregistration.k8s.io + kind: APIService + name: v1alpha1.ui.openviz.dev + jsonPointers: + - /spec/caBundle + - group: apps + kind: Deployment + name: operator-shard-manager + namespace: kubeops + jsonPointers: + - /spec/template/metadata/annotations/checksum~1apiregistration.yaml + - group: apiextensions.k8s.io + kind: CustomResourceDefinition + name: servicemonitors.monitoring.coreos.com + jsonPointers: + - /metadata/annotations + - /spec diff --git a/argocd/opscenter-tools/sidekick.yaml b/argocd/opscenter-tools/sidekick.yaml new file mode 100644 index 000000000..4bba0aa42 --- /dev/null +++ b/argocd/opscenter-tools/sidekick.yaml @@ -0,0 +1,46 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: sidekick + namespace: argocd +spec: + project: default + source: + chart: sidekick + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.2.16 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kubeops + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true + + ignoreDifferences: + - jsonPointers: + - /data + kind: Secret + name: sidekick-apiserver-cert + namespace: kubeops + - group: apiregistration.k8s.io + kind: APIService + name: v1alpha1.ui.openviz.dev + jsonPointers: + - /spec/caBundle + - group: apps + kind: Deployment + name: sidekick + namespace: kubeops + jsonPointers: + - /spec/template/metadata/annotations/checksum~1apiregistration.yaml + - group: apiextensions.k8s.io + kind: CustomResourceDefinition + name: servicemonitors.monitoring.coreos.com + jsonPointers: + - /metadata/annotations + - /spec diff --git a/argocd/opscenter-tools/supervisor.yaml b/argocd/opscenter-tools/supervisor.yaml new file mode 100644 index 000000000..78cf80850 --- /dev/null +++ b/argocd/opscenter-tools/supervisor.yaml @@ -0,0 +1,46 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: supervisor + namespace: argocd +spec: + project: default + source: + chart: supervisor + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.1.15 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: kubeops + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true + + ignoreDifferences: + - jsonPointers: + - /data + kind: Secret + name: supervisor-apiserver-cert + namespace: kubeops + - group: apiregistration.k8s.io + kind: APIService + name: v1alpha1.ui.openviz.dev + jsonPointers: + - /spec/caBundle + - group: apps + kind: Deployment + name: supervisor + namespace: kubeops + jsonPointers: + - /spec/template/metadata/annotations/checksum~1apiregistration.yaml + - group: apiextensions.k8s.io + kind: CustomResourceDefinition + name: servicemonitors.monitoring.coreos.com + jsonPointers: + - /metadata/annotations + - /spec diff --git a/argocd/saas-core/catalog-manager.yaml b/argocd/saas-core/catalog-manager.yaml new file mode 100644 index 000000000..3092f1e5d --- /dev/null +++ b/argocd/saas-core/catalog-manager.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: catalog-manager + namespace: argocd +spec: + project: default + source: + chart: catalog-manager + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.3.30 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: ace + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/saas-core/service-backend.yaml b/argocd/saas-core/service-backend.yaml new file mode 100644 index 000000000..20de383dc --- /dev/null +++ b/argocd/saas-core/service-backend.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: service-backend + namespace: argocd +spec: + project: default + source: + chart: service-backend + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.3.30 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: ace + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/saas-core/service-gateway-presets.yaml b/argocd/saas-core/service-gateway-presets.yaml new file mode 100644 index 000000000..ba84dd973 --- /dev/null +++ b/argocd/saas-core/service-gateway-presets.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: service-gateway-presets + namespace: argocd +spec: + project: default + source: + chart: service-gateway-presets + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.3.30 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: ace-gw + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true diff --git a/argocd/saas-core/service-provider.yaml b/argocd/saas-core/service-provider.yaml new file mode 100644 index 000000000..ff98cf0d5 --- /dev/null +++ b/argocd/saas-core/service-provider.yaml @@ -0,0 +1,46 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: service-provider + namespace: argocd +spec: + project: default + source: + chart: service-provider + repoURL: ghcr.io/appscode-charts + targetRevision: v2026.3.30 + helm: + values: | + ace-user-roles: + enabled: false + destination: + server: "https://kubernetes.default.svc" + namespace: ace + syncPolicy: + automated: {} + syncOptions: + - CreateNamespace=true + + ignoreDifferences: + - jsonPointers: + - /data + kind: Secret + name: service-provider-apiserver-cert + namespace: ace + - group: apiregistration.k8s.io + kind: APIService + name: v1alpha1.ui.openviz.dev + jsonPointers: + - /spec/caBundle + - group: apps + kind: Deployment + name: service-provider + namespace: ace + jsonPointers: + - /spec/template/metadata/annotations/checksum~1apiregistration.yaml + - group: apiextensions.k8s.io + kind: CustomResourceDefinition + name: servicemonitors.monitoring.coreos.com + jsonPointers: + - /metadata/annotations + - /spec diff --git a/cmd/argocd-gen/go.mod b/cmd/argocd-gen/go.mod new file mode 100644 index 000000000..4c0c4436d --- /dev/null +++ b/cmd/argocd-gen/go.mod @@ -0,0 +1,118 @@ +module go.bytebuilders.dev/installer/cmd/argocd-gen + +go 1.25.0 + +require ( + github.com/spf13/pflag v1.0.10 + helm.sh/helm/v3 v3.20.1 + k8s.io/api v0.35.1 + sigs.k8s.io/yaml v1.6.0 +) + +require ( + dario.cat/mergo v1.0.1 // indirect + github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect + github.com/BurntSushi/toml v1.6.0 // indirect + github.com/MakeNowJust/heredoc v1.0.0 // indirect + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/semver/v3 v3.4.0 // indirect + github.com/Masterminds/sprig/v3 v3.3.0 // indirect + github.com/Masterminds/squirrel v1.5.4 // indirect + github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect + github.com/blang/semver/v4 v4.0.0 // indirect + github.com/chai2010/gettext-go v1.0.2 // indirect + github.com/containerd/containerd v1.7.30 // indirect + github.com/containerd/errdefs v0.3.0 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect + github.com/cyphar/filepath-securejoin v0.6.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/emicklei/go-restful/v3 v3.12.2 // indirect + github.com/evanphx/json-patch v5.9.11+incompatible // indirect + github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect + github.com/fatih/color v1.13.0 // indirect + github.com/fxamacker/cbor/v2 v2.9.0 // indirect + github.com/go-errors/errors v1.4.2 // indirect + github.com/go-gorp/gorp/v3 v3.1.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/swag v0.23.0 // indirect + github.com/gobwas/glob v0.2.3 // indirect + github.com/google/btree v1.1.3 // indirect + github.com/google/gnostic-models v0.7.0 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gosuri/uitable v0.0.4 // indirect + github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/huandu/xstrings v1.5.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jmoiron/sqlx v1.4.0 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.18.0 // indirect + github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect + github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect + github.com/lib/pq v1.10.9 // indirect + github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/moby/term v0.5.2 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect + github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.1 // indirect + github.com/peterbourgon/diskv v2.0.1+incompatible // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/rubenv/sql-migrate v1.8.1 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect + github.com/shopspring/decimal v1.4.0 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/spf13/cast v1.7.0 // indirect + github.com/spf13/cobra v1.10.2 // indirect + github.com/x448/float16 v0.8.4 // indirect + github.com/xlab/treeprint v1.2.0 // indirect + go.yaml.in/yaml/v2 v2.4.3 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/crypto v0.46.0 // indirect + golang.org/x/net v0.48.0 // indirect + golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/sync v0.19.0 // indirect + golang.org/x/sys v0.40.0 // indirect + golang.org/x/term v0.39.0 // indirect + golang.org/x/text v0.33.0 // indirect + golang.org/x/time v0.12.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect + google.golang.org/grpc v1.72.2 // indirect + google.golang.org/protobuf v1.36.8 // indirect + gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/apiextensions-apiserver v0.35.1 // indirect + k8s.io/apimachinery v0.35.1 // indirect + k8s.io/apiserver v0.35.1 // indirect + k8s.io/cli-runtime v0.35.1 // indirect + k8s.io/client-go v0.35.1 // indirect + k8s.io/component-base v0.35.1 // indirect + k8s.io/klog/v2 v2.130.1 // indirect + k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect + k8s.io/kubectl v0.35.1 // indirect + k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect + oras.land/oras-go/v2 v2.6.0 // indirect + sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect + sigs.k8s.io/kustomize/api v0.20.1 // indirect + sigs.k8s.io/kustomize/kyaml v0.20.1 // indirect + sigs.k8s.io/randfill v1.0.0 // indirect + sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect +) diff --git a/cmd/argocd-gen/go.sum b/cmd/argocd-gen/go.sum new file mode 100644 index 000000000..8c9e6116a --- /dev/null +++ b/cmd/argocd-gen/go.sum @@ -0,0 +1,410 @@ +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= +github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= +github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= +github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= +github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= +github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= +github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= +github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM= +github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= +github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= +github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= +github.com/containerd/containerd v1.7.30 h1:/2vezDpLDVGGmkUXmlNPLCCNKHJ5BbC5tJB5JNzQhqE= +github.com/containerd/containerd v1.7.30/go.mod h1:fek494vwJClULlTpExsmOyKCMUAbuVjlFsJQc4/j44M= +github.com/containerd/errdefs v0.3.0 h1:FSZgGOeK4yuT/+DnF07/Olde/q4KBoMsaamhXxIMDp4= +github.com/containerd/errdefs v0.3.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= +github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/distribution/distribution/v3 v3.0.0 h1:q4R8wemdRQDClzoNNStftB2ZAfqOiN6UX90KJc4HjyM= +github.com/distribution/distribution/v3 v3.0.0/go.mod h1:tRNuFoZsUdyRVegq8xGNeds4KLjwLCRin/tTo6i1DhU= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= +github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= +github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= +github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= +github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU= +github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8= +github.com/evanphx/json-patch v5.9.11+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= +github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/foxcpp/go-mockdns v1.2.0 h1:omK3OrHRD1IWJz1FuFBCFquhXslXoF17OvBS6JPzZF0= +github.com/foxcpp/go-mockdns v1.2.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= +github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= +github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= +github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= +github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= +github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= +github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= +github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/golang-lru/arc/v2 v2.0.5 h1:l2zaLDubNhW4XO3LnliVj0GXO3+/CGNJAg1dcN2Fpfw= +github.com/hashicorp/golang-lru/arc/v2 v2.0.5/go.mod h1:ny6zBSQZi2JxIeYcv7kt2sH2PXJtirBN7RDhRpxPkxU= +github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4= +github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= +github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= +github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= +github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= +github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= +github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= +github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ= +github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns= +github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= +github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= +github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= +github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= +github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= +github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= +github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= +github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= +github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= +github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 h1:EaDatTxkdHG+U3Bk4EUr+DZ7fOGwTfezUiUJMaIcaho= +github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5/go.mod h1:fyalQWdtzDBECAQFBJuQe5bzQ02jGd5Qcbgb97Flm7U= +github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 h1:EfpWLLCyXw8PSM2/XNJLjI3Pb27yVE+gIAfeqp8LUCc= +github.com/redis/go-redis/extra/redisotel/v9 v9.0.5/go.mod h1:WZjPDy7VNzn77AAfnAfVjZNvfJTYfPetfZk5yoSTLaQ= +github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM= +github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/rubenv/sql-migrate v1.8.1 h1:EPNwCvjAowHI3TnZ+4fQu3a915OpnQoPAjTXCGOy2U0= +github.com/rubenv/sql-migrate v1.8.1/go.mod h1:BTIKBORjzyxZDS6dzoiw6eAFYJ1iNlGAtjn4LGeVjS8= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= +github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= +github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= +github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/contrib/bridges/prometheus v0.57.0 h1:UW0+QyeyBVhn+COBec3nGhfnFe5lwB0ic1JBVjzhk0w= +go.opentelemetry.io/contrib/bridges/prometheus v0.57.0/go.mod h1:ppciCHRLsyCio54qbzQv0E4Jyth/fLWDTJYfvWpcSVk= +go.opentelemetry.io/contrib/exporters/autoexport v0.57.0 h1:jmTVJ86dP60C01K3slFQa2NQ/Aoi7zA+wy7vMOKD9H4= +go.opentelemetry.io/contrib/exporters/autoexport v0.57.0/go.mod h1:EJBheUMttD/lABFyLXhce47Wr6DPWYReCzaZiXadH7g= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= +go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= +go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0 h1:WzNab7hOOLzdDF/EoWCt4glhrbMPVMOO5JYTmpz36Ls= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0/go.mod h1:hKvJwTzJdp90Vh7p6q/9PAOd55dI6WA6sWj62a/JvSs= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0 h1:S+LdBGiQXtJdowoJoQPEtI52syEP/JYBUpjO49EQhV8= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0/go.mod h1:5KXybFvPGds3QinJWQT7pmXf+TN5YIa7CNYObWRkj50= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 h1:j7ZSD+5yn+lo3sGV69nW04rRR0jhYnBwjuX3r0HvnK0= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0/go.mod h1:WXbYJTUaZXAbYd8lbgGuvih0yuCfOFC5RJoYnoLcGz8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0 h1:t/Qur3vKSkUCcDVaSumWF2PKHt85pc7fRvFuoVT8qFU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0/go.mod h1:Rl61tySSdcOJWoEgYZVtmnKdA0GeKrSqkHC1t+91CH8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0 h1:cMyu9O88joYEaI47CnQkxO1XZdpoTF9fEnW2duIddhw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0/go.mod h1:6Am3rn7P9TVVeXYG+wtcGE7IE1tsQ+bP3AuWcKt/gOI= +go.opentelemetry.io/otel/exporters/prometheus v0.54.0 h1:rFwzp68QMgtzu9PgP3jm9XaMICI6TsofWWPcBDKwlsU= +go.opentelemetry.io/otel/exporters/prometheus v0.54.0/go.mod h1:QyjcV9qDP6VeK5qPyKETvNjmaaEc7+gqjh4SS0ZYzDU= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.8.0 h1:CHXNXwfKWfzS65yrlB2PVds1IBZcdsX8Vepy9of0iRU= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.8.0/go.mod h1:zKU4zUgKiaRxrdovSS2amdM5gOc59slmo/zJwGX+YBg= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.32.0 h1:SZmDnHcgp3zwlPBS2JX2urGYe/jBKEIT6ZedHRUyCz8= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.32.0/go.mod h1:fdWW0HtZJ7+jNpTKUR0GpMEDP69nR8YBJQxNiVCE3jk= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.32.0 h1:cC2yDI3IQd0Udsux7Qmq8ToKAx1XCilTQECZ0KDZyTw= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.32.0/go.mod h1:2PD5Ex6z8CFzDbTdOlwyNIUywRr1DN0ospafJM1wJ+s= +go.opentelemetry.io/otel/log v0.8.0 h1:egZ8vV5atrUWUbnSsHn6vB8R21G2wrKqNiDt3iWertk= +go.opentelemetry.io/otel/log v0.8.0/go.mod h1:M9qvDdUTRCopJcGRKg57+JSQ9LgLBrwwfC32epk5NX8= +go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= +go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= +go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= +go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= +go.opentelemetry.io/otel/sdk/log v0.8.0 h1:zg7GUYXqxk1jnGF/dTdLPrK06xJdrXgqgFLnI4Crxvs= +go.opentelemetry.io/otel/sdk/log v0.8.0/go.mod h1:50iXr0UVwQrYS45KbruFrEt4LvAdCaWWgIrsN3ZQggo= +go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis= +go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= +go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= +go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= +go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= +go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= +go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= +golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= +golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI= +golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg= +golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= +golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= +golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= +golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= +golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= +golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= +golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= +golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA= +golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc= +google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3 h1:1hfbdAfFbkmpg41000wDVqr7jUpK/Yo+LPnIxxGzmkg= +google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950= +google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/grpc v1.72.2 h1:TdbGzwb82ty4OusHWepvFWGLgIbNo1/SUynEN0ssqv8= +google.golang.org/grpc v1.72.2/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= +google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc= +google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo= +gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +helm.sh/helm/v3 v3.20.1 h1:T8PodUaH1UwNvE+imUA2mIKjJItY8g7CVvLVP5g4NzI= +helm.sh/helm/v3 v3.20.1/go.mod h1:Fl1kBaWCpkUrM6IYXPjQ3bdZQfFrogKArqptvueZ6Ww= +k8s.io/api v0.35.1 h1:0PO/1FhlK/EQNVK5+txc4FuhQibV25VLSdLMmGpDE/Q= +k8s.io/api v0.35.1/go.mod h1:28uR9xlXWml9eT0uaGo6y71xK86JBELShLy4wR1XtxM= +k8s.io/apiextensions-apiserver v0.35.1 h1:p5vvALkknlOcAqARwjS20kJffgzHqwyQRM8vHLwgU7w= +k8s.io/apiextensions-apiserver v0.35.1/go.mod h1:2CN4fe1GZ3HMe4wBr25qXyJnJyZaquy4nNlNmb3R7AQ= +k8s.io/apimachinery v0.35.1 h1:yxO6gV555P1YV0SANtnTjXYfiivaTPvCTKX6w6qdDsU= +k8s.io/apimachinery v0.35.1/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns= +k8s.io/apiserver v0.35.1 h1:potxdhhTL4i6AYAa2QCwtlhtB1eCdWQFvJV6fXgJzxs= +k8s.io/apiserver v0.35.1/go.mod h1:BiL6Dd3A2I/0lBnteXfWmCFobHM39vt5+hJQd7Lbpi4= +k8s.io/cli-runtime v0.35.1 h1:uKcXFe8J7AMAM4Gm2JDK4mp198dBEq2nyeYtO+JfGJE= +k8s.io/cli-runtime v0.35.1/go.mod h1:55/hiXIq1C8qIJ3WBrWxEwDLdHQYhBNRdZOz9f7yvTw= +k8s.io/client-go v0.35.1 h1:+eSfZHwuo/I19PaSxqumjqZ9l5XiTEKbIaJ+j1wLcLM= +k8s.io/client-go v0.35.1/go.mod h1:1p1KxDt3a0ruRfc/pG4qT/3oHmUj1AhSHEcxNSGg+OA= +k8s.io/component-base v0.35.1 h1:XgvpRf4srp037QWfGBLFsYMUQJkE5yMa94UsJU7pmcE= +k8s.io/component-base v0.35.1/go.mod h1:HI/6jXlwkiOL5zL9bqA3en1Ygv60F03oEpnuU1G56Bs= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE= +k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ= +k8s.io/kubectl v0.35.1 h1:zP3Er8C5i1dcAFUMh9Eva0kVvZHptXIn/+8NtRWMxwg= +k8s.io/kubectl v0.35.1/go.mod h1:cQ2uAPs5IO/kx8R5s5J3Ihv3VCYwrx0obCXum0CvnXo= +k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= +k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +oras.land/oras-go/v2 v2.6.0 h1:X4ELRsiGkrbeox69+9tzTu492FMUu7zJQW6eJU+I2oc= +oras.land/oras-go/v2 v2.6.0/go.mod h1:magiQDfG6H1O9APp+rOsvCPcW1GD2MM7vgnKY0Y+u1o= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= +sigs.k8s.io/kustomize/api v0.20.1 h1:iWP1Ydh3/lmldBnH/S5RXgT98vWYMaTUL1ADcr+Sv7I= +sigs.k8s.io/kustomize/api v0.20.1/go.mod h1:t6hUFxO+Ph0VxIk1sKp1WS0dOjbPCtLJ4p8aADLwqjM= +sigs.k8s.io/kustomize/kyaml v0.20.1 h1:PCMnA2mrVbRP3NIB6v9kYCAc38uvFLVs8j/CD567A78= +sigs.k8s.io/kustomize/kyaml v0.20.1/go.mod h1:0EmkQHRUsJxY8Ug9Niig1pUMSCGHxQ5RklbpV/Ri6po= +sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= +sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= +sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= +sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= +sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/cmd/argocd-gen/main.go b/cmd/argocd-gen/main.go new file mode 100644 index 000000000..461ea755d --- /dev/null +++ b/cmd/argocd-gen/main.go @@ -0,0 +1,703 @@ +/* +Copyright AppsCode Inc. and Contributors + +Licensed under the AppsCode Community License 1.0.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://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md + +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. +*/ + +package main + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "log" + "os" + "path/filepath" + "sort" + "strings" + "time" + + "github.com/spf13/pflag" + "helm.sh/helm/v3/pkg/action" + "helm.sh/helm/v3/pkg/chart/loader" + "helm.sh/helm/v3/pkg/chartutil" + "helm.sh/helm/v3/pkg/cli" + "helm.sh/helm/v3/pkg/kube" + "helm.sh/helm/v3/pkg/registry" + "helm.sh/helm/v3/pkg/storage" + "helm.sh/helm/v3/pkg/storage/driver" + v1 "k8s.io/api/core/v1" + "sigs.k8s.io/yaml" +) + +var ( + chartName string + chartVersion string + namespace string + releaseName string + repoURL string + outputFile string + renderCount int + installCRDs bool + platformToken string + platformBaseURL string + aceUserRoles bool +) + +func main() { + pflag.StringVar(&chartName, "chart", "", "Chart name (required)") + pflag.StringVar(&chartVersion, "version", "", "Chart version (required)") + pflag.StringVar(&namespace, "namespace", "", "Namespace for the chart (required)") + pflag.StringVar(&releaseName, "release-name", "", "Helm release name (default: chart name)") + pflag.StringVar(&repoURL, "repo-url", "ghcr.io/appscode-charts", "OCI registry URL") + pflag.StringVar(&outputFile, "output", "", "Output file (default: stdout)") + pflag.IntVar(&renderCount, "renders", 3, "Number of times to render the chart") + pflag.BoolVar(&installCRDs, "install-crds", false, "Set installCRDs=true in values") + pflag.StringVar(&platformToken, "platform-token", "", "Set platform.token in values") + pflag.StringVar(&platformBaseURL, "platform-base-url", "", "Set platform.baseURL in values") + pflag.BoolVar(&aceUserRoles, "ace-user-roles", true, "Set ace-user-roles.enabled=false in values") + + pflag.Usage = func() { + fmt.Fprintf(os.Stderr, "Usage: %s [flags]\n\n", os.Args[0]) + fmt.Fprintf(os.Stderr, "Generate ArgoCD Application objects for helm charts.\n") + fmt.Fprintf(os.Stderr, "Renders the chart multiple times using Helm Go SDK, identifies fields\n") + fmt.Fprintf(os.Stderr, "that change between renders, and generates appropriate ignoreDifferences.\n\n") + fmt.Fprintf(os.Stderr, "Flags:\n") + pflag.PrintDefaults() + fmt.Fprintf(os.Stderr, "\nExample:\n") + fmt.Fprintf(os.Stderr, " %s --chart kubedb --version v2026.2.26 --namespace kubedb\n", os.Args[0]) + } + + pflag.Parse() + + if chartName == "" || chartVersion == "" || namespace == "" { + pflag.Usage() + os.Exit(1) + } + + if releaseName == "" { + releaseName = chartName + } + + values := buildValuesMap() + + var manifests []string + for i := 0; i < renderCount; i++ { + m, err := renderChart(releaseName, namespace, values) + if err != nil { + log.Fatalf("Render %d failed: %v", i+1, err) + } + manifests = append(manifests, m) + } + + ignoreRules := findIgnoreDifferences(manifests) + app := generateArgoCDApp(chartName, chartVersion, namespace, ignoreRules, values) + + output, err := yaml.Marshal(app) + if err != nil { + log.Fatalf("Marshal failed: %v", err) + } + + if outputFile != "" { + if err := os.WriteFile(outputFile, output, 0o644); err != nil { + log.Fatalf("Write failed: %v", err) + } + fmt.Fprintf(os.Stderr, "Generated: %s (%d rules)\n", outputFile, len(ignoreRules)) + } else { + os.Stdout.Write(output) + fmt.Fprintf(os.Stderr, "\n# %d ignoreDifferences rules\n", len(ignoreRules)) + } +} + +// renderChart uses Helm Go SDK to pull and render a chart +// Follows https://helm.sh/docs/v3/sdk/examples/ patterns +func renderChart(relName, ns string, vals map[string]interface{}) (string, error) { + settings := cli.New() + + // Step 1: Create OCI registry client + registryClient, err := newRegistryClient(settings) + if err != nil { + return "", fmt.Errorf("registry client: %w", err) + } + + // Step 2: Init action config with memory storage driver (no kube needed for dry-run) + actionConfig, err := initActionConfig(settings, ns, registryClient) + if err != nil { + return "", fmt.Errorf("init config: %w", err) + } + + // Step 3: Create pull client to download the chart from OCI registry + pullClient := action.NewPullWithOpts(action.WithConfig(actionConfig)) + pullClient.Version = chartVersion + pullClient.Settings = settings + pullClient.SetRegistryClient(registryClient) + + tmpDir, err := os.MkdirTemp("", "helm-pull-*") + if err != nil { + return "", fmt.Errorf("temp dir: %w", err) + } + defer os.RemoveAll(tmpDir) + pullClient.DestDir = tmpDir + + chartRef := fmt.Sprintf("oci://%s/%s", repoURL, chartName) + if _, err := pullClient.Run(chartRef); err != nil { + return "", fmt.Errorf("pull %s:%s: %w", chartRef, chartVersion, err) + } + + // Step 4: Load the downloaded chart archive + entries, err := os.ReadDir(tmpDir) + if err != nil { + return "", fmt.Errorf("read pull dir: %w", err) + } + var chartPath string + for _, e := range entries { + if strings.HasSuffix(e.Name(), ".tgz") { + chartPath = filepath.Join(tmpDir, e.Name()) + break + } + } + if chartPath == "" { + return "", fmt.Errorf("no .tgz in %s after pull", tmpDir) + } + + chart, err := loader.Load(chartPath) + if err != nil { + return "", fmt.Errorf("load chart: %w", err) + } + + // Step 5: Create install client for dry-run rendering + installClient := action.NewInstall(actionConfig) + installClient.DryRunOption = "client" + installClient.ReleaseName = relName + installClient.Namespace = ns + installClient.ClientOnly = true + installClient.IncludeCRDs = installCRDs + installClient.Replace = true + installClient.SetRegistryClient(registryClient) + + // Set a modern kube version to satisfy chart version constraints + kv, _ := chartutil.ParseKubeVersion("v1.31.0") + installClient.KubeVersion = kv + + // Step 6: Render + rel, err := installClient.RunWithContext(context.Background(), chart, vals) + if err != nil { + return "", fmt.Errorf("render: %w", err) + } + + return rel.Manifest, nil +} + +// initActionConfig initializes Helm action configuration. +// Uses memory driver so no kube cluster is needed for dry-run. +func initActionConfig(settings *cli.EnvSettings, ns string, rc *registry.Client) (*action.Configuration, error) { + actionConfig := new(action.Configuration) + + // Use memory storage driver - stores releases in-memory only + actionConfig.Releases = storage.Init(driver.NewMemory()) + + // Minimal kube client stub for dry-run mode + actionConfig.KubeClient = &noopKubeClient{} + + // Suppress helm logging + actionConfig.Log = func(format string, v ...interface{}) {} + + // Attach the OCI registry client + actionConfig.RegistryClient = rc + + return actionConfig, nil +} + +// newRegistryClient creates a client for OCI registries (ghcr.io, etc.) +// Following https://helm.sh/docs/v3/sdk/examples/ patterns +func newRegistryClient(settings *cli.EnvSettings) (*registry.Client, error) { + opts := []registry.ClientOption{ + registry.ClientOptDebug(settings.Debug), + registry.ClientOptEnableCache(true), + registry.ClientOptWriter(os.Stderr), + registry.ClientOptCredentialsFile(settings.RegistryConfig), + } + return registry.NewClient(opts...) +} + +// noopKubeClient implements kube.Interface for dry-run mode. +// All methods are no-ops since we only need template rendering. +type noopKubeClient struct{} + +func (c *noopKubeClient) Create(resources kube.ResourceList) (*kube.Result, error) { + return &kube.Result{Created: resources}, nil +} + +func (c *noopKubeClient) Wait(resources kube.ResourceList, timeout time.Duration) error { + return nil +} + +func (c *noopKubeClient) WaitWithJobs(resources kube.ResourceList, timeout time.Duration) error { + return nil +} + +func (c *noopKubeClient) Delete(resources kube.ResourceList) (*kube.Result, []error) { + return &kube.Result{Deleted: resources}, nil +} + +func (c *noopKubeClient) WatchUntilReady(resources kube.ResourceList, timeout time.Duration) error { + return nil +} + +func (c *noopKubeClient) Update(original, target kube.ResourceList, force bool) (*kube.Result, error) { + return &kube.Result{Updated: target}, nil +} + +func (c *noopKubeClient) Build(reader io.Reader, validate bool) (kube.ResourceList, error) { + return kube.ResourceList{}, nil +} + +func (c *noopKubeClient) WaitAndGetCompletedPodPhase(name string, timeout time.Duration) (v1.PodPhase, error) { + return v1.PodSucceeded, nil +} + +func (c *noopKubeClient) IsReachable() error { + return nil +} + +// Resource represents a parsed Kubernetes resource +type Resource struct { + APIVersion string `json:"apiVersion"` + Kind string `json:"kind"` + Metadata map[string]interface{} `json:"metadata"` + Spec interface{} `json:"spec,omitempty"` + Data interface{} `json:"data,omitempty"` + Raw map[string]interface{} `json:"-"` +} + +func (r *Resource) Group() string { + parts := strings.SplitN(r.APIVersion, "/", 2) + if len(parts) == 1 { + return "" + } + return parts[0] +} + +func (r *Resource) Version() string { + parts := strings.SplitN(r.APIVersion, "/", 2) + if len(parts) == 1 { + return parts[0] + } + return parts[1] +} + +func (r *Resource) Name() string { + if n, ok := r.Metadata["name"].(string); ok { + return n + } + return "" +} + +func (r *Resource) NS() string { + if n, ok := r.Metadata["namespace"].(string); ok { + return n + } + return "" +} + +func (r *Resource) Key() string { + return fmt.Sprintf("%s/%s/%s/%s", r.Group(), r.Kind, r.NS(), r.Name()) +} + +func parseResources(rendered string) map[string]*Resource { + resources := make(map[string]*Resource) + docs := strings.Split(rendered, "---") + + for _, doc := range docs { + doc = strings.TrimSpace(doc) + if doc == "" || strings.HasPrefix(doc, "---") { + continue + } + + var raw map[string]interface{} + if err := yaml.Unmarshal([]byte(doc), &raw); err != nil { + continue + } + + res := &Resource{Raw: raw} + res.APIVersion, _ = raw["apiVersion"].(string) + res.Kind, _ = raw["kind"].(string) + res.Metadata, _ = raw["metadata"].(map[string]interface{}) + res.Spec = raw["spec"] + res.Data = raw["data"] + + if res.Kind == "" || res.Name() == "" { + continue + } + + resources[res.Key()] = res + } + + return resources +} + +func diffResources(a, b *Resource) []string { + var diffs []string + + if !deepEqualJSON(a.Data, b.Data) { + if a.Kind == "Secret" { + if isCertificateData(a.Data) || isCertificateData(b.Data) { + diffs = append(diffs, "/data") + } + } + } + + diffs = append(diffs, diffAnnotations(a.Metadata, b.Metadata)...) + + if a.Kind == "MutatingWebhookConfiguration" || a.Kind == "ValidatingWebhookConfiguration" { + if hasWebhookCaBundleDiff(a.Raw, b.Raw) { + diffs = append(diffs, "/webhooks[].clientConfig.caBundle") + } + } + + if a.Kind == "APIService" { + if hasAPICaBundleDiff(a.Spec, b.Spec) { + diffs = append(diffs, "/spec/caBundle") + } + } + + if a.Kind == "Deployment" || a.Kind == "StatefulSet" { + diffs = append(diffs, diffTemplateAnnotations(a.Spec, b.Spec)...) + } + + if a.Kind == "CustomResourceDefinition" { + if !deepEqualJSON(a.Spec, b.Spec) { + diffs = append(diffs, "/spec") + } + if annDiffs := diffAnnotations(a.Metadata, b.Metadata); len(annDiffs) > 0 { + diffs = append(diffs, "/metadata/annotations") + } + } + + return diffs +} + +func isCertificateData(data interface{}) bool { + if data == nil { + return false + } + m, ok := data.(map[string]interface{}) + if !ok { + return false + } + for key := range m { + if key == "ca.crt" || key == "tls.crt" || key == "tls.key" || strings.HasSuffix(key, ".crt") || strings.HasSuffix(key, ".key") { + return true + } + } + return false +} + +func diffAnnotations(metaA, metaB map[string]interface{}) []string { + annA, _ := metaA["annotations"].(map[string]interface{}) + annB, _ := metaB["annotations"].(map[string]interface{}) + if annA == nil || annB == nil { + return nil + } + + var diffs []string + for k, v1 := range annA { + v2, exists := annB[k] + if !exists { + continue + } + if fmt.Sprintf("%v", v1) != fmt.Sprintf("%v", v2) { + encoded := strings.ReplaceAll(k, "/", "~1") + diffs = append(diffs, "/metadata/annotations/"+encoded) + } + } + return diffs +} + +func diffTemplateAnnotations(specA, specB interface{}) []string { + sA, _ := specA.(map[string]interface{}) + sB, _ := specB.(map[string]interface{}) + if sA == nil || sB == nil { + return nil + } + + tplA, _ := sA["template"].(map[string]interface{}) + tplB, _ := sB["template"].(map[string]interface{}) + if tplA == nil || tplB == nil { + return nil + } + + metaA, _ := tplA["metadata"].(map[string]interface{}) + metaB, _ := tplB["metadata"].(map[string]interface{}) + if metaA == nil || metaB == nil { + return nil + } + + annA, _ := metaA["annotations"].(map[string]interface{}) + annB, _ := metaB["annotations"].(map[string]interface{}) + if annA == nil || annB == nil { + return nil + } + + var diffs []string + for k, v1 := range annA { + v2, exists := annB[k] + if !exists { + continue + } + if fmt.Sprintf("%v", v1) != fmt.Sprintf("%v", v2) { + encoded := strings.ReplaceAll(k, "/", "~1") + diffs = append(diffs, "/spec/template/metadata/annotations/"+encoded) + } + } + return diffs +} + +func hasWebhookCaBundleDiff(a, b map[string]interface{}) bool { + webhooksA, _ := a["webhooks"].([]interface{}) + webhooksB, _ := b["webhooks"].([]interface{}) + if len(webhooksA) != len(webhooksB) { + return false + } + for i := 0; i < len(webhooksA); i++ { + whA, _ := webhooksA[i].(map[string]interface{}) + whB, _ := webhooksB[i].(map[string]interface{}) + if whA == nil || whB == nil { + continue + } + ccA, _ := whA["clientConfig"].(map[string]interface{}) + ccB, _ := whB["clientConfig"].(map[string]interface{}) + if ccA == nil || ccB == nil { + continue + } + cbA, _ := ccA["caBundle"].(string) + cbB, _ := ccB["caBundle"].(string) + if cbA != "" && cbB != "" && cbA != cbB { + return true + } + } + return false +} + +func hasAPICaBundleDiff(a, b interface{}) bool { + specA, _ := a.(map[string]interface{}) + specB, _ := b.(map[string]interface{}) + if specA == nil || specB == nil { + return false + } + cbA, _ := specA["caBundle"].(string) + cbB, _ := specB["caBundle"].(string) + return cbA != "" && cbB != "" && cbA != cbB +} + +func deepEqualJSON(a, b interface{}) bool { + if a == nil && b == nil { + return true + } + if a == nil || b == nil { + return false + } + jsonA, _ := json.Marshal(a) + jsonB, _ := json.Marshal(b) + return bytes.Equal(jsonA, jsonB) +} + +type IgnoreRule struct { + Group string + Kind string + Name string + Namespace string + JSONPointers []string + JQPathExpressions []string +} + +func (r IgnoreRule) Key() string { + return fmt.Sprintf("%s/%s/%s", r.Group, r.Kind, r.Name) +} + +func findIgnoreDifferences(renders []string) []IgnoreRule { + if len(renders) < 2 { + return nil + } + + var allParsed []map[string]*Resource + for _, render := range renders { + allParsed = append(allParsed, parseResources(render)) + } + + ruleMap := make(map[string]*IgnoreRule) + + for key, res1 := range allParsed[0] { + for i := 1; i < len(allParsed); i++ { + res2, exists := allParsed[i][key] + if !exists { + continue + } + + diffs := diffResources(res1, res2) + if len(diffs) > 0 { + rule := getOrCreateRule(ruleMap, res1) + for _, d := range diffs { + addPathToRule(rule, d) + } + } + } + } + + var rules []IgnoreRule + for _, r := range ruleMap { + if len(r.JSONPointers) > 0 || len(r.JQPathExpressions) > 0 { + rules = append(rules, *r) + } + } + + sort.Slice(rules, func(i, j int) bool { + return rules[i].Key() < rules[j].Key() + }) + + return rules +} + +func getOrCreateRule(ruleMap map[string]*IgnoreRule, res *Resource) *IgnoreRule { + key := res.Key() + if r, exists := ruleMap[key]; exists { + return r + } + rule := &IgnoreRule{ + Group: res.Group(), + Kind: res.Kind, + Name: res.Name(), + Namespace: res.NS(), + } + ruleMap[key] = rule + return rule +} + +func addPathToRule(rule *IgnoreRule, path string) { + if strings.Contains(path, "caBundle") { + if rule.Kind == "MutatingWebhookConfiguration" || rule.Kind == "ValidatingWebhookConfiguration" { + expr := ".webhooks[].clientConfig.caBundle" + for _, e := range rule.JQPathExpressions { + if e == expr { + return + } + } + rule.JQPathExpressions = append(rule.JQPathExpressions, expr) + return + } + } + + for _, p := range rule.JSONPointers { + if p == path { + return + } + } + rule.JSONPointers = append(rule.JSONPointers, path) +} + +func buildValuesMap() map[string]interface{} { + values := make(map[string]interface{}) + if aceUserRoles { + values["ace-user-roles"] = map[string]interface{}{"enabled": false} + } + if installCRDs { + values["installCRDs"] = true + } + if platformToken != "" || platformBaseURL != "" { + platform := make(map[string]interface{}) + if platformToken != "" { + platform["token"] = platformToken + } + if platformBaseURL != "" { + platform["baseURL"] = platformBaseURL + } + values["platform"] = platform + } + return values +} + +func generateArgoCDApp(chart, version, ns string, rules []IgnoreRule, vals map[string]interface{}) map[string]interface{} { + app := map[string]interface{}{ + "apiVersion": "argoproj.io/v1alpha1", + "kind": "Application", + "metadata": map[string]interface{}{ + "name": chart, + "namespace": "argocd", + }, + "spec": map[string]interface{}{ + "project": "default", + "source": map[string]interface{}{ + "chart": chart, + "repoURL": "ghcr.io/appscode-charts", + "targetRevision": version, + }, + "destination": map[string]interface{}{ + "server": "https://kubernetes.default.svc", + "namespace": ns, + }, + "syncPolicy": map[string]interface{}{ + "automated": map[string]interface{}{}, + "syncOptions": []interface{}{ + "CreateNamespace=true", + }, + }, + }, + } + + if len(vals) > 0 { + spec := app["spec"].(map[string]interface{}) + source := spec["source"].(map[string]interface{}) + valsYAML, _ := yaml.Marshal(vals) + source["helm"] = map[string]interface{}{ + "values": string(valsYAML), + } + } + + if len(rules) > 0 { + var diffs []interface{} + for _, r := range rules { + d := make(map[string]interface{}) + if r.Group != "" { + d["group"] = r.Group + } + d["kind"] = r.Kind + if r.Name != "" { + d["name"] = r.Name + } + if r.Namespace != "" { + d["namespace"] = r.Namespace + } + if len(r.JSONPointers) > 0 { + ptrs := make([]interface{}, len(r.JSONPointers)) + for i, p := range r.JSONPointers { + ptrs[i] = p + } + d["jsonPointers"] = ptrs + } + if len(r.JQPathExpressions) > 0 { + exprs := make([]interface{}, len(r.JQPathExpressions)) + for i, e := range r.JQPathExpressions { + exprs[i] = e + } + d["jqPathExpressions"] = exprs + } + diffs = append(diffs, d) + } + spec := app["spec"].(map[string]interface{}) + spec["ignoreDifferences"] = diffs + } + + return app +} diff --git a/cmd/argocd-gen/main_test.go b/cmd/argocd-gen/main_test.go new file mode 100644 index 000000000..b4cc30ffc --- /dev/null +++ b/cmd/argocd-gen/main_test.go @@ -0,0 +1,950 @@ +/* +Copyright AppsCode Inc. and Contributors + +Licensed under the AppsCode Community License 1.0.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://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md + +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. +*/ + +package main + +import ( + "context" + "fmt" + "io" + "os" + "path/filepath" + "strings" + "testing" + "time" + + "helm.sh/helm/v3/pkg/action" + "helm.sh/helm/v3/pkg/chart/loader" + "helm.sh/helm/v3/pkg/chartutil" + "helm.sh/helm/v3/pkg/cli" + "helm.sh/helm/v3/pkg/kube" + "helm.sh/helm/v3/pkg/registry" + "helm.sh/helm/v3/pkg/storage" + "helm.sh/helm/v3/pkg/storage/driver" + v1 "k8s.io/api/core/v1" + "sigs.k8s.io/yaml" +) + +// Chart represents a helm chart from opscenter-features +type chartEntry struct { + Name string + Version string + Namespace string + RepoURL string + AceUserRoles bool // whether to set ace-user-roles.enabled=false +} + +// All charts referenced by opscenter-features chart +var opscenterCharts = []chartEntry{ + // capi-capa + {"aws-credential-manager", "v2026.1.20", "capa-system", "ghcr.io/appscode-charts", true}, + {"aws-ebs-csi-driver", "2.23.0", "capa-system", "ghcr.io/appscode-charts", true}, + {"aws-load-balancer-controller", "1.11.0", "capa-system", "ghcr.io/appscode-charts", true}, + {"capa-vpc-peering-operator", "v2023.12.11", "capa-system", "ghcr.io/appscode-charts", true}, + {"cluster-autoscaler", "9.29.0", "capi-system", "ghcr.io/appscode-charts", true}, + // capi-capg + {"gcp-credential-manager", "v2026.3.11", "capg-system", "ghcr.io/appscode-charts", true}, + // capi-core + {"capi-catalog", "v2024.10.24", "capi-system", "ghcr.io/appscode-charts", true}, + {"capi-ops-manager", "v2024.8.14", "capi-system", "ghcr.io/appscode-charts", true}, + {"cluster-presets", "v2026.3.30", "kubeops", "ghcr.io/appscode-charts", true}, + // crossplane + {"crossplane", "1.14.0", "crossplane-system", "ghcr.io/appscode-charts", true}, + {"kubedb-provider-aws", "v2024.1.31", "crossplane-system", "ghcr.io/appscode-charts", true}, + {"kubedb-provider-azure", "v2024.1.31", "crossplane-system", "ghcr.io/appscode-charts", true}, + {"kubedb-provider-gcp", "v2024.1.31", "crossplane-system", "ghcr.io/appscode-charts", true}, + // ocm-hub + {"cluster-manager-hub", "v2026.2.16", "open-cluster-management", "ghcr.io/appscode-charts", true}, + {"cluster-gateway-manager", "v2026.2.16", "open-cluster-management-addon", "ghcr.io/appscode-charts", true}, + {"cluster-proxy-manager", "v2026.2.16", "open-cluster-management-addon", "ghcr.io/appscode-charts", true}, + {"cluster-auth-manager", "v2026.2.16", "open-cluster-management-addon", "ghcr.io/appscode-charts", true}, + {"cluster-profile-manager", "v2026.2.16", "open-cluster-management-addon", "ghcr.io/appscode-charts", true}, + {"fluxcd-manager", "v2026.2.16", "open-cluster-management-addon", "ghcr.io/appscode-charts", true}, + {"managed-serviceaccount-manager", "v2026.2.16", "open-cluster-management-addon", "ghcr.io/appscode-charts", true}, + {"hub-cluster-robot", "v2026.2.16", "open-cluster-management", "ghcr.io/appscode-charts", true}, + {"license-proxyserver-manager", "v2026.2.16", "open-cluster-management-addon", "ghcr.io/appscode-charts", true}, + // ocm-spoke + {"cluster-manager-spoke", "v2026.2.16", "open-cluster-management", "ghcr.io/appscode-charts", true}, + // opscenter-backup + {"kubestash", "v2026.2.26", "stash", "ghcr.io/appscode-charts", true}, + {"stash", "v2025.7.31", "stash", "ghcr.io/appscode-charts", true}, + {"stash-opscenter", "v2025.7.31", "stash", "ghcr.io/appscode-charts", true}, + {"stash-presets", "v2026.3.30", "stash", "ghcr.io/appscode-charts", true}, + // opscenter-core + {"aceshifter", "v2026.3.30", "kubeops", "ghcr.io/appscode-charts", true}, + {"flux2", "2.17.0", "flux-system", "ghcr.io/appscode-charts", true}, + {"license-proxyserver", "v2026.2.16", "kubeops", "ghcr.io/appscode-charts", true}, + {"kube-ui-server", "v2026.3.30", "kubeops", "ghcr.io/appscode-charts", true}, + // opscenter-cost + {"opencost", "1.18.1", "opencost", "ghcr.io/appscode-charts", true}, + {"opencost-grafana-dashboards", "v2023.10.1", "opencost", "ghcr.io/appscode-charts", true}, + {"keda", "2.19.0", "keda", "ghcr.io/appscode-charts", true}, + {"keda-add-ons-http", "0.12.0", "keda", "ghcr.io/appscode-charts", true}, + // opscenter-datastore + {"kubedb", "v2026.2.26", "kubedb", "ghcr.io/appscode-charts", true}, + {"kubedb-opscenter", "v2026.2.26", "kubedb", "ghcr.io/appscode-charts", true}, + {"kubedb-ui-presets", "v2026.3.30", "kubedb", "ghcr.io/appscode-charts", true}, + {"prepare-cluster", "v2023.12.21", "kubedb", "ghcr.io/appscode-charts", true}, + // opscenter-networking + {"voyager", "v2026.3.23", "voyager", "ghcr.io/appscode-charts", true}, + {"voyager-gateway", "v2026.1.15", "envoy-gateway-system", "ghcr.io/appscode-charts", true}, + {"gateway-api", "v2025.3.14", "envoy-gateway-system", "ghcr.io/appscode-charts", true}, + {"external-dns-operator", "v2026.1.15", "kubeops", "ghcr.io/appscode-charts", true}, + // opscenter-observability + {"monitoring-operator", "v2026.3.30", "monitoring", "ghcr.io/appscode-charts", true}, + {"grafana-operator", "v2026.3.30", "monitoring", "ghcr.io/appscode-charts", true}, + {"kube-prometheus-stack", "69.2.2", "monitoring", "ghcr.io/appscode-charts", true}, + {"panopticon", "v2026.1.15", "monitoring", "ghcr.io/appscode-charts", true}, + {"metrics-server", "3.11.0", "monitoring", "ghcr.io/appscode-charts", true}, + {"prometheus-adapter", "4.9.0", "monitoring", "ghcr.io/appscode-charts", true}, + {"kube-grafana-dashboards", "v2023.10.1", "monitoring", "ghcr.io/appscode-charts", true}, + {"inbox-server", "v2025.2.28", "ace", "ghcr.io/appscode-charts", true}, + {"inbox-agent", "v2024.12.30", "monitoring", "ghcr.io/appscode-charts", true}, + {"inbox-ui", "v2026.3.30", "ace", "ghcr.io/appscode-charts", true}, + // opscenter-policy-management + {"gatekeeper", "3.13.3", "gatekeeper-system", "ghcr.io/appscode-charts", true}, + {"gatekeeper-library", "v2023.10.1", "gatekeeper-system", "ghcr.io/appscode-charts", true}, + {"gatekeeper-grafana-dashboards", "v2023.10.1", "kubeops", "ghcr.io/appscode-charts", true}, + {"kyverno", "3.2.6", "kyverno", "ghcr.io/appscode-charts", true}, + {"kyverno-policies", "3.2.5", "kyverno", "ghcr.io/appscode-charts", true}, + // opscenter-secret-management + {"kubevault", "v2026.2.27", "kubevault", "ghcr.io/appscode-charts", true}, + {"kubevault-opscenter", "v2026.2.27", "kubevault", "ghcr.io/appscode-charts", true}, + {"external-secrets", "0.9.12", "external-secrets", "ghcr.io/appscode-charts", true}, + {"sealed-secrets", "2.14.2", "kube-system", "ghcr.io/appscode-charts", true}, + {"config-syncer", "v0.15.4", "kubeops", "ghcr.io/appscode-charts", true}, + {"reloader", "2.2.9", "kubeops", "ghcr.io/appscode-charts", true}, + {"vault-secrets-operator", "0.4.3", "vault-secrets-operator-system", "ghcr.io/appscode-charts", true}, + {"secrets-store-csi-driver", "1.4.1", "kube-system", "ghcr.io/appscode-charts", true}, + {"secrets-store-csi-driver-provider-aws", "0.3.6", "kube-system", "ghcr.io/appscode-charts", true}, + {"csi-secrets-store-provider-azure", "1.5.2", "kube-system", "ghcr.io/appscode-charts", true}, + {"secrets-store-csi-driver-provider-gcp", "0.1.0", "kube-system", "ghcr.io/appscode-charts", true}, + {"virtual-secrets-server", "v2026.2.27", "kubevault", "ghcr.io/appscode-charts", true}, + {"secrets-store-csi-driver-provider-virtual-secrets", "v2026.2.27", "kube-system", "ghcr.io/appscode-charts", true}, + // opscenter-security + {"cert-manager", "v1.19.3", "cert-manager", "ghcr.io/appscode-charts", false}, + {"cert-manager-csi-driver-cacerts", "v2026.1.15", "cert-manager", "ghcr.io/appscode-charts", true}, + {"falco", "4.0.0", "falco", "ghcr.io/appscode-charts", true}, + {"falco-ui-server", "v2026.1.15", "falco", "ghcr.io/appscode-charts", true}, + {"scanner", "v2026.1.15", "kubeops", "ghcr.io/appscode-charts", true}, + // opscenter-storage + {"topolvm", "15.0.0", "topolvm-system", "ghcr.io/appscode-charts", true}, + {"longhorn", "1.7.2", "longhorn-system", "ghcr.io/appscode-charts", true}, + {"snapshot-controller", "3.0.6", "kubeops", "ghcr.io/appscode-charts", true}, + {"csi-driver-nfs", "v4.7.0", "kube-system", "ghcr.io/appscode-charts", true}, + // opscenter-tools + {"operator-shard-manager", "v2026.1.15", "kubeops", "ghcr.io/appscode-charts", true}, + {"sidekick", "v2026.2.16", "kubeops", "ghcr.io/appscode-charts", true}, + {"supervisor", "v2026.1.15", "kubeops", "ghcr.io/appscode-charts", true}, + // saas-core + {"catalog-manager", "v2026.3.30", "ace", "ghcr.io/appscode-charts", true}, + {"service-backend", "v2026.3.30", "ace", "ghcr.io/appscode-charts", true}, + {"service-provider", "v2026.3.30", "ace", "ghcr.io/appscode-charts", true}, + {"service-gateway-presets", "v2026.3.30", "ace-gw", "ghcr.io/appscode-charts", true}, +} + +// Charts that are expected to have ignoreDifferences (from helm template double-render analysis) +// These charts produce different certificate/annotation values on each render. +var chartsWithExpectedDifferences = map[string]bool{ + "aws-credential-manager": true, + "capi-ops-manager": true, + "falco-ui-server": true, + "gcp-credential-manager": true, + "grafana-operator": true, + "inbox-agent": true, + "kube-ui-server": true, + "kubedb-opscenter": true, + "kubedb": true, + "kubestash": true, + "kubevault": true, + "license-proxyserver": true, + "monitoring-operator": true, + "operator-shard-manager": true, + "panopticon": true, + "scanner": true, + "service-provider": true, + "sidekick": true, + "snapshot-controller": true, + "stash-opscenter": true, + "supervisor": true, + "virtual-secrets-server": true, + "voyager": true, +} + +// Expected ignoreDifferences kinds for charts that have differences +var expectedDiffKinds = map[string][]string{ + "kubedb": {"Secret", "MutatingWebhookConfiguration", "ValidatingWebhookConfiguration", "Deployment"}, + "kubevault": {"Secret", "MutatingWebhookConfiguration", "ValidatingWebhookConfiguration", "APIService", "Deployment"}, + "kubestash": {"Secret", "MutatingWebhookConfiguration", "ValidatingWebhookConfiguration", "Deployment"}, + "voyager": {"Secret", "MutatingWebhookConfiguration", "ValidatingWebhookConfiguration", "APIService", "Deployment"}, + "license-proxyserver": {"Secret", "APIService"}, + "monitoring-operator": {"Secret", "APIService", "Deployment"}, + "panopticon": {"Secret", "APIService", "Deployment"}, + "scanner": {"Secret", "APIService", "Deployment"}, + "crossplane": {"MutatingWebhookConfiguration", "ValidatingWebhookConfiguration"}, + "gatekeeper": {"MutatingWebhookConfiguration", "ValidatingWebhookConfiguration"}, + "kyverno": {"MutatingWebhookConfiguration", "ValidatingWebhookConfiguration"}, + "keda": {"MutatingWebhookConfiguration", "ValidatingWebhookConfiguration"}, + "external-secrets": {"MutatingWebhookConfiguration", "ValidatingWebhookConfiguration", "Deployment"}, + "cert-manager": {"Secret", "MutatingWebhookConfiguration", "ValidatingWebhookConfiguration"}, + "flux2": {"Secret"}, + "vault-secrets-operator": {"MutatingWebhookConfiguration", "ValidatingWebhookConfiguration", "Deployment"}, + "inbox-agent": {"Secret", "MutatingWebhookConfiguration", "ValidatingWebhookConfiguration"}, + "snapshot-controller": {"Secret", "MutatingWebhookConfiguration"}, +} + +// renderChartForTest is the test helper that renders a chart using Helm SDK +func renderChartForTest(t *testing.T, c chartEntry, renderCount int) []string { + t.Helper() + + settings := cli.New() + + // Create registry client + regClient, err := newTestRegistryClient(settings) + if err != nil { + t.Fatalf("registry client: %v", err) + } + + // Init action config with memory storage + actionConfig := new(action.Configuration) + actionConfig.Releases = storage.Init(driver.NewMemory()) + actionConfig.KubeClient = &testKubeClient{} + actionConfig.Log = func(format string, v ...interface{}) {} + actionConfig.RegistryClient = regClient + + // Build values + values := make(map[string]interface{}) + if c.AceUserRoles { + values["ace-user-roles"] = map[string]interface{}{"enabled": false} + } + + var manifests []string + + for i := 0; i < renderCount; i++ { + // Pull chart + pullClient := action.NewPullWithOpts(action.WithConfig(actionConfig)) + pullClient.Version = c.Version + pullClient.Settings = settings + pullClient.SetRegistryClient(regClient) + + tmpDir := t.TempDir() + pullClient.DestDir = tmpDir + + chartRef := fmt.Sprintf("oci://%s/%s", c.RepoURL, c.Name) + if _, err := pullClient.Run(chartRef); err != nil { + t.Fatalf("pull %s:%s: %v", chartRef, c.Version, err) + } + + // Load chart + var chartPath string + entries, _ := os.ReadDir(tmpDir) + for _, e := range entries { + if strings.HasSuffix(e.Name(), ".tgz") { + chartPath = filepath.Join(tmpDir, e.Name()) + break + } + } + if chartPath == "" { + t.Fatalf("no .tgz found in %s", tmpDir) + } + + chart, err := loader.Load(chartPath) + if err != nil { + t.Fatalf("load chart: %v", err) + } + + // Install (dry-run) + installClient := action.NewInstall(actionConfig) + installClient.DryRunOption = "client" + installClient.ReleaseName = c.Name + installClient.Namespace = c.Namespace + installClient.ClientOnly = true + installClient.IncludeCRDs = true + installClient.Replace = true + installClient.SetRegistryClient(regClient) + + kv, _ := chartutil.ParseKubeVersion("v1.31.0") + installClient.KubeVersion = kv + + rel, err := installClient.RunWithContext(context.Background(), chart, values) + if err != nil { + t.Fatalf("render %s (attempt %d): %v", c.Name, i+1, err) + } + + manifests = append(manifests, rel.Manifest) + } + + return manifests +} + +func newTestRegistryClient(settings *cli.EnvSettings) (*registry.Client, error) { + opts := []registry.ClientOption{ + registry.ClientOptDebug(settings.Debug), + registry.ClientOptEnableCache(true), + registry.ClientOptWriter(os.Stderr), + registry.ClientOptCredentialsFile(settings.RegistryConfig), + } + return registry.NewClient(opts...) +} + +// testKubeClient implements kube.Interface for dry-run mode +type testKubeClient struct{} + +func (c *testKubeClient) Create(resources kube.ResourceList) (*kube.Result, error) { + return &kube.Result{Created: resources}, nil +} + +func (c *testKubeClient) Wait(resources kube.ResourceList, timeout time.Duration) error { + return nil +} + +func (c *testKubeClient) WaitWithJobs(resources kube.ResourceList, timeout time.Duration) error { + return nil +} + +func (c *testKubeClient) Delete(resources kube.ResourceList) (*kube.Result, []error) { + return &kube.Result{Deleted: resources}, nil +} + +func (c *testKubeClient) WatchUntilReady(resources kube.ResourceList, timeout time.Duration) error { + return nil +} + +func (c *testKubeClient) Update(original, target kube.ResourceList, force bool) (*kube.Result, error) { + return &kube.Result{Updated: target}, nil +} + +func (c *testKubeClient) Build(reader io.Reader, validate bool) (kube.ResourceList, error) { + return kube.ResourceList{}, nil +} + +func (c *testKubeClient) WaitAndGetCompletedPodPhase(name string, timeout time.Duration) (v1.PodPhase, error) { + return v1.PodSucceeded, nil +} + +func (c *testKubeClient) IsReachable() error { + return nil +} + +// TestAllOpscenterCharts renders each chart twice and verifies ignoreDifferences +func TestAllOpscenterCharts(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + outDir := t.TempDir() + renderCount := 2 + + for _, c := range opscenterCharts { + t.Run(c.Name, func(t *testing.T) { + manifests := renderChartForTest(t, c, renderCount) + if len(manifests) < 2 { + t.Fatalf("expected at least 2 renders, got %d", len(manifests)) + } + + rules := findIgnoreDifferences(manifests) + + expectedDiff := chartsWithExpectedDifferences[c.Name] + + if expectedDiff && len(rules) == 0 { + t.Errorf("expected ignoreDifferences for %s but got none", c.Name) + } + + if !expectedDiff && len(rules) > 0 { + t.Logf("chart %s has %d unexpected ignoreDifferences rules", c.Name, len(rules)) + // Not a failure - just means we found more differences than expected + } + + // Verify expected kinds if specified + if expectedKinds, ok := expectedDiffKinds[c.Name]; ok { + actualKinds := make(map[string]bool) + for _, r := range rules { + actualKinds[r.Kind] = true + } + for _, ek := range expectedKinds { + if !actualKinds[ek] { + t.Errorf("expected ignoreDifferences for kind %s in %s but not found", ek, c.Name) + } + } + } + + // Generate the ArgoCD Application and verify it's valid YAML + values := make(map[string]interface{}) + if c.AceUserRoles { + values["ace-user-roles"] = map[string]interface{}{"enabled": false} + } + app := generateArgoCDApp(c.Name, c.Version, c.Namespace, rules, values) + + appYAML, err := yaml.Marshal(app) + if err != nil { + t.Fatalf("marshal app: %v", err) + } + + // Write output to file for inspection + outFile := filepath.Join(outDir, c.Name+".yaml") + if err := os.WriteFile(outFile, appYAML, 0o644); err != nil { + t.Fatalf("write output: %v", err) + } + + // Verify app structure + spec, ok := app["spec"].(map[string]interface{}) + if !ok { + t.Fatal("app spec is not a map") + } + + source, ok := spec["source"].(map[string]interface{}) + if !ok { + t.Fatal("source is not a map") + } + + if source["chart"] != c.Name { + t.Errorf("source.chart = %q, want %q", source["chart"], c.Name) + } + if source["targetRevision"] != c.Version { + t.Errorf("source.targetRevision = %q, want %q", source["targetRevision"], c.Version) + } + + dest, ok := spec["destination"].(map[string]interface{}) + if !ok { + t.Fatal("destination is not a map") + } + if dest["namespace"] != c.Namespace { + t.Errorf("destination.namespace = %q, want %q", dest["namespace"], c.Namespace) + } + + t.Logf("generated %d ignoreDifferences rules", len(rules)) + }) + } +} + +// TestSpecificCharts tests key charts in detail +func TestSpecificCharts(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + tests := []struct { + name string + chart chartEntry + wantRuleCount int // minimum expected rules + wantKinds []string + wantSecretNames []string + }{ + { + name: "kubedb", + chart: chartEntry{ + Name: "kubedb", + Version: "v2026.2.26", + Namespace: "kubedb", + RepoURL: "ghcr.io/appscode-charts", + AceUserRoles: true, + }, + wantRuleCount: 10, + wantKinds: []string{"Secret", "MutatingWebhookConfiguration", "ValidatingWebhookConfiguration", "Deployment"}, + wantSecretNames: []string{"kubedb-kubedb-webhook-server-cert", "kubedb-petset-cert", "kubedb-sidekick-cert"}, + }, + { + name: "kubevault", + chart: chartEntry{ + Name: "kubevault", + Version: "v2026.2.27", + Namespace: "kubevault", + RepoURL: "ghcr.io/appscode-charts", + AceUserRoles: true, + }, + wantRuleCount: 5, + wantKinds: []string{"Secret", "APIService", "Deployment"}, + wantSecretNames: []string{"kubevault-kubevault-webhook-server-apiserver-cert"}, + }, + { + name: "kubestash", + chart: chartEntry{ + Name: "kubestash", + Version: "v2026.2.26", + Namespace: "stash", + RepoURL: "ghcr.io/appscode-charts", + AceUserRoles: true, + }, + wantRuleCount: 3, + wantKinds: []string{"Secret", "Deployment"}, + wantSecretNames: []string{"kubestash-kubestash-operator-cert"}, + }, + { + name: "voyager", + chart: chartEntry{ + Name: "voyager", + Version: "v2026.3.23", + Namespace: "voyager", + RepoURL: "ghcr.io/appscode-charts", + AceUserRoles: true, + }, + wantRuleCount: 4, + wantKinds: []string{"Secret", "APIService", "Deployment"}, + wantSecretNames: []string{"voyager-apiserver-cert"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + manifests := renderChartForTest(t, tt.chart, 2) + rules := findIgnoreDifferences(manifests) + + if len(rules) < tt.wantRuleCount { + t.Errorf("got %d rules, want at least %d", len(rules), tt.wantRuleCount) + } + + // Check expected kinds are present + actualKinds := make(map[string]bool) + for _, r := range rules { + actualKinds[r.Kind] = true + } + for _, ek := range tt.wantKinds { + if !actualKinds[ek] { + t.Errorf("expected kind %q not found in rules", ek) + } + } + + // Check secret names + actualSecrets := make(map[string]bool) + for _, r := range rules { + if r.Kind == "Secret" { + actualSecrets[r.Name] = true + } + } + for _, es := range tt.wantSecretNames { + if !actualSecrets[es] { + t.Errorf("expected Secret %q not found in rules", es) + } + } + + // Verify webhook rules use jqPathExpressions + for _, r := range rules { + if r.Kind == "MutatingWebhookConfiguration" || r.Kind == "ValidatingWebhookConfiguration" { + if len(r.JQPathExpressions) == 0 { + t.Errorf("webhook %s has no jqPathExpressions", r.Name) + } + } + } + + // Verify secret rules use jsonPointers with /data + for _, r := range rules { + if r.Kind == "Secret" { + hasData := false + for _, p := range r.JSONPointers { + if p == "/data" { + hasData = true + break + } + } + if !hasData { + t.Errorf("secret %s has no /data jsonPointer", r.Name) + } + } + } + + t.Logf("rules: %d, kinds: %v", len(rules), actualKinds) + }) + } +} + +// TestIgnoreDifferencesStructure validates the structure of generated ignoreDifferences +func TestIgnoreDifferencesStructure(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + c := chartEntry{ + Name: "kubedb", + Version: "v2026.2.26", + Namespace: "kubedb", + RepoURL: "ghcr.io/appscode-charts", + AceUserRoles: true, + } + + manifests := renderChartForTest(t, c, 2) + rules := findIgnoreDifferences(manifests) + + for _, r := range rules { + // Every rule must have a kind + if r.Kind == "" { + t.Error("rule has empty Kind") + } + + // Every rule must have at least one jsonPointer or jqPathExpression + if len(r.JSONPointers) == 0 && len(r.JQPathExpressions) == 0 { + t.Errorf("rule %s/%s has no jsonPointers or jqPathExpressions", r.Kind, r.Name) + } + + // jsonPointers must start with / + for _, p := range r.JSONPointers { + if !strings.HasPrefix(p, "/") { + t.Errorf("jsonPointer %q does not start with /", p) + } + } + + // jqPathExpressions must start with . + for _, e := range r.JQPathExpressions { + if !strings.HasPrefix(e, ".") { + t.Errorf("jqPathExpression %q does not start with .", e) + } + } + } +} + +// TestDiffResourcesUnit tests the diffResources function directly +func TestDiffResourcesUnit(t *testing.T) { + tests := []struct { + name string + a, b *Resource + wantDiff bool + wantPath string + }{ + { + name: "secret with changing cert data", + a: &Resource{ + Kind: "Secret", + Metadata: map[string]interface{}{"name": "test", "namespace": "ns"}, + Data: map[string]interface{}{"tls.crt": "abc123", "tls.key": "def456"}, + Raw: map[string]interface{}{"kind": "Secret", "data": map[string]interface{}{"tls.crt": "abc123"}}, + }, + b: &Resource{ + Kind: "Secret", + Metadata: map[string]interface{}{"name": "test", "namespace": "ns"}, + Data: map[string]interface{}{"tls.crt": "xyz789", "tls.key": "ghi012"}, + Raw: map[string]interface{}{"kind": "Secret", "data": map[string]interface{}{"tls.crt": "xyz789"}}, + }, + wantDiff: true, + wantPath: "/data", + }, + { + name: "deployment with reload annotation", + a: &Resource{ + Kind: "Deployment", + Metadata: map[string]interface{}{"name": "deploy", "namespace": "ns"}, + Spec: map[string]interface{}{ + "template": map[string]interface{}{ + "metadata": map[string]interface{}{ + "annotations": map[string]interface{}{"reload": "abc123"}, + }, + }, + }, + Raw: map[string]interface{}{"kind": "Deployment"}, + }, + b: &Resource{ + Kind: "Deployment", + Metadata: map[string]interface{}{"name": "deploy", "namespace": "ns"}, + Spec: map[string]interface{}{ + "template": map[string]interface{}{ + "metadata": map[string]interface{}{ + "annotations": map[string]interface{}{"reload": "xyz789"}, + }, + }, + }, + Raw: map[string]interface{}{"kind": "Deployment"}, + }, + wantDiff: true, + wantPath: "/spec/template/metadata/annotations/reload", + }, + { + name: "webhook with caBundle", + a: &Resource{ + Kind: "MutatingWebhookConfiguration", + Metadata: map[string]interface{}{"name": "wh"}, + Raw: map[string]interface{}{ + "kind": "MutatingWebhookConfiguration", + "webhooks": []interface{}{ + map[string]interface{}{ + "clientConfig": map[string]interface{}{"caBundle": "abc123"}, + }, + }, + }, + }, + b: &Resource{ + Kind: "MutatingWebhookConfiguration", + Metadata: map[string]interface{}{"name": "wh"}, + Raw: map[string]interface{}{ + "kind": "MutatingWebhookConfiguration", + "webhooks": []interface{}{ + map[string]interface{}{ + "clientConfig": map[string]interface{}{"caBundle": "xyz789"}, + }, + }, + }, + }, + wantDiff: true, + wantPath: "/webhooks[].clientConfig.caBundle", + }, + { + name: "api service with caBundle", + a: &Resource{ + Kind: "APIService", + Metadata: map[string]interface{}{"name": "v1.foo"}, + Spec: map[string]interface{}{"caBundle": "abc123"}, + Raw: map[string]interface{}{"kind": "APIService"}, + }, + b: &Resource{ + Kind: "APIService", + Metadata: map[string]interface{}{"name": "v1.foo"}, + Spec: map[string]interface{}{"caBundle": "xyz789"}, + Raw: map[string]interface{}{"kind": "APIService"}, + }, + wantDiff: true, + wantPath: "/spec/caBundle", + }, + { + name: "identical resources", + a: &Resource{ + Kind: "Deployment", + Metadata: map[string]interface{}{"name": "deploy", "namespace": "ns"}, + Spec: map[string]interface{}{"replicas": 1}, + Raw: map[string]interface{}{"kind": "Deployment"}, + }, + b: &Resource{ + Kind: "Deployment", + Metadata: map[string]interface{}{"name": "deploy", "namespace": "ns"}, + Spec: map[string]interface{}{"replicas": 1}, + Raw: map[string]interface{}{"kind": "Deployment"}, + }, + wantDiff: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + diffs := diffResources(tt.a, tt.b) + + if tt.wantDiff && len(diffs) == 0 { + t.Error("expected differences but got none") + } + + if !tt.wantDiff && len(diffs) > 0 { + t.Errorf("expected no differences but got: %v", diffs) + } + + if tt.wantPath != "" { + found := false + for _, d := range diffs { + if d == tt.wantPath { + found = true + break + } + } + if !found { + t.Errorf("expected path %q not found in diffs: %v", tt.wantPath, diffs) + } + } + }) + } +} + +// TestArgoCDAppStructure verifies the generated ArgoCD Application has correct structure +func TestArgoCDAppStructure(t *testing.T) { + rules := []IgnoreRule{ + { + Group: "admissionregistration.k8s.io", + Kind: "MutatingWebhookConfiguration", + Name: "test-webhook", + JQPathExpressions: []string{".webhooks[].clientConfig.caBundle"}, + }, + { + Kind: "Secret", + Name: "test-cert", + Namespace: "default", + JSONPointers: []string{"/data"}, + }, + } + + app := generateArgoCDApp("test-chart", "v1.0.0", "default", rules, map[string]interface{}{ + "ace-user-roles": map[string]interface{}{"enabled": false}, + }) + + // Verify apiVersion and kind + if app["apiVersion"] != "argoproj.io/v1alpha1" { + t.Errorf("apiVersion = %v, want argoproj.io/v1alpha1", app["apiVersion"]) + } + if app["kind"] != "Application" { + t.Errorf("kind = %v, want Application", app["kind"]) + } + + // Verify metadata + metadata, ok := app["metadata"].(map[string]interface{}) + if !ok { + t.Fatal("metadata is not a map") + } + if metadata["name"] != "test-chart" { + t.Errorf("name = %v, want test-chart", metadata["name"]) + } + if metadata["namespace"] != "argocd" { + t.Errorf("namespace = %v, want argocd", metadata["namespace"]) + } + + // Verify ignoreDifferences is present + spec, ok := app["spec"].(map[string]interface{}) + if !ok { + t.Fatal("spec is not a map") + } + + ignoreDiffs, ok := spec["ignoreDifferences"].([]interface{}) + if !ok { + t.Fatal("ignoreDifferences is not a slice") + } + + if len(ignoreDiffs) != 2 { + t.Errorf("len(ignoreDifferences) = %d, want 2", len(ignoreDiffs)) + } + + // Verify webhook rule has jqPathExpressions + for _, d := range ignoreDiffs { + diff, ok := d.(map[string]interface{}) + if !ok { + continue + } + if diff["kind"] == "MutatingWebhookConfiguration" { + if diff["jqPathExpressions"] == nil { + t.Error("webhook rule missing jqPathExpressions") + } + } + if diff["kind"] == "Secret" { + if diff["jsonPointers"] == nil { + t.Error("secret rule missing jsonPointers") + } + } + } + + // Verify syncPolicy + syncPolicy, ok := spec["syncPolicy"].(map[string]interface{}) + if !ok { + t.Fatal("syncPolicy is not a map") + } + + if syncPolicy["automated"] == nil { + t.Error("syncPolicy.automated is nil") + } + + syncOpts, ok := syncPolicy["syncOptions"].([]interface{}) + if !ok || len(syncOpts) == 0 { + t.Error("syncPolicy.syncOptions is empty") + } +} + +// BenchmarkRenderChart benchmarks chart rendering +func BenchmarkRenderChart(b *testing.B) { + c := chartEntry{ + Name: "kubedb", + Version: "v2026.2.26", + Namespace: "kubedb", + RepoURL: "ghcr.io/appscode-charts", + AceUserRoles: true, + } + + settings := cli.New() + regClient, _ := newTestRegistryClient(settings) + + actionConfig := new(action.Configuration) + actionConfig.Releases = storage.Init(driver.NewMemory()) + actionConfig.KubeClient = &testKubeClient{} + actionConfig.Log = func(format string, v ...interface{}) {} + actionConfig.RegistryClient = regClient + + values := map[string]interface{}{ + "ace-user-roles": map[string]interface{}{"enabled": false}, + } + + for i := 0; i < b.N; i++ { + pullClient := action.NewPullWithOpts(action.WithConfig(actionConfig)) + pullClient.Version = c.Version + pullClient.Settings = settings + pullClient.SetRegistryClient(regClient) + + tmpDir := b.TempDir() + pullClient.DestDir = tmpDir + + chartRef := fmt.Sprintf("oci://%s/%s", c.RepoURL, c.Name) + pullClient.Run(chartRef) + + var chartPath string + entries, _ := os.ReadDir(tmpDir) + for _, e := range entries { + if strings.HasSuffix(e.Name(), ".tgz") { + chartPath = filepath.Join(tmpDir, e.Name()) + break + } + } + + chart, _ := loader.Load(chartPath) + + installClient := action.NewInstall(actionConfig) + installClient.DryRunOption = "client" + installClient.ReleaseName = c.Name + installClient.Namespace = c.Namespace + installClient.ClientOnly = true + installClient.IncludeCRDs = true + installClient.Replace = true + installClient.SetRegistryClient(regClient) + + kv, _ := chartutil.ParseKubeVersion("v1.31.0") + installClient.KubeVersion = kv + + installClient.RunWithContext(context.Background(), chart, values) + } +} + +// Helper to get rule key +func ruleKey(r IgnoreRule) string { + return fmt.Sprintf("%s/%s/%s", r.Group, r.Kind, r.Name) +} + +// diffResources is reused from main.go +func diffResourcesUnit(a, b *Resource) []string { + var diffs []string + + if !deepEqualJSON(a.Data, b.Data) { + if a.Kind == "Secret" { + if isCertificateData(a.Data) || isCertificateData(b.Data) { + diffs = append(diffs, "/data") + } + } + } + + diffs = append(diffs, diffAnnotations(a.Metadata, b.Metadata)...) + + if a.Kind == "MutatingWebhookConfiguration" || a.Kind == "ValidatingWebhookConfiguration" { + if hasWebhookCaBundleDiff(a.Raw, b.Raw) { + diffs = append(diffs, "/webhooks[].clientConfig.caBundle") + } + } + + if a.Kind == "APIService" { + if hasAPICaBundleDiff(a.Spec, b.Spec) { + diffs = append(diffs, "/spec/caBundle") + } + } + + if a.Kind == "Deployment" || a.Kind == "StatefulSet" { + diffs = append(diffs, diffTemplateAnnotations(a.Spec, b.Spec)...) + } + + if a.Kind == "CustomResourceDefinition" { + if !deepEqualJSON(a.Spec, b.Spec) { + diffs = append(diffs, "/spec") + } + if annDiffs := diffAnnotations(a.Metadata, b.Metadata); len(annDiffs) > 0 { + diffs = append(diffs, "/metadata/annotations") + } + } + + return diffs +}