diff --git a/.changeset/shiny-rocks-pump.md b/.changeset/shiny-rocks-pump.md new file mode 100644 index 000000000..f76d2d002 --- /dev/null +++ b/.changeset/shiny-rocks-pump.md @@ -0,0 +1,5 @@ +--- +"@kosko/helm": patch +--- + +chore(helm): adjust check logic of chart exists diff --git a/packages/helm/src/__fixtures__/tar/prometheus-25.22.0.tgz b/packages/helm/src/__fixtures__/tar/prometheus-25.22.0.tgz new file mode 100644 index 000000000..0ba7aa24b Binary files /dev/null and b/packages/helm/src/__fixtures__/tar/prometheus-25.22.0.tgz differ diff --git a/packages/helm/src/__tests__/__snapshots__/load.ts.snap b/packages/helm/src/__tests__/__snapshots__/load.ts.snap index 56dfc279f..3900a684c 100644 --- a/packages/helm/src/__tests__/__snapshots__/load.ts.snap +++ b/packages/helm/src/__tests__/__snapshots__/load.ts.snap @@ -1921,6 +1921,1827 @@ exports[`chart is a local path 1`] = ` ] `; +exports[`chart is a local tarball 1`] = ` +[ + { + "apiVersion": "v1", + "automountServiceAccountToken": true, + "kind": "ServiceAccount", + "metadata": { + "labels": { + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "alertmanager", + "app.kubernetes.io/version": "v0.27.0", + "helm.sh/chart": "alertmanager-1.11.0", + }, + "name": "release-name-alertmanager", + "namespace": "default", + }, + }, + { + "apiVersion": "v1", + "kind": "ServiceAccount", + "metadata": { + "labels": { + "app.kubernetes.io/component": "metrics", + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "kube-state-metrics", + "app.kubernetes.io/part-of": "kube-state-metrics", + "app.kubernetes.io/version": "2.12.0", + "helm.sh/chart": "kube-state-metrics-5.20.0", + }, + "name": "release-name-kube-state-metrics", + "namespace": "default", + }, + }, + { + "apiVersion": "v1", + "kind": "ServiceAccount", + "metadata": { + "labels": { + "app.kubernetes.io/component": "metrics", + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "prometheus-node-exporter", + "app.kubernetes.io/part-of": "prometheus-node-exporter", + "app.kubernetes.io/version": "1.8.1", + "helm.sh/chart": "prometheus-node-exporter-4.36.0", + }, + "name": "release-name-prometheus-node-exporter", + "namespace": "default", + }, + }, + { + "apiVersion": "v1", + "automountServiceAccountToken": true, + "kind": "ServiceAccount", + "metadata": { + "labels": { + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "prometheus-pushgateway", + "app.kubernetes.io/version": "v1.8.0", + "helm.sh/chart": "prometheus-pushgateway-2.13.0", + }, + "name": "release-name-prometheus-pushgateway", + "namespace": "default", + }, + }, + { + "apiVersion": "v1", + "kind": "ServiceAccount", + "metadata": { + "annotations": {}, + "labels": { + "app.kubernetes.io/component": "server", + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "prometheus", + "app.kubernetes.io/part-of": "prometheus", + "app.kubernetes.io/version": "v2.53.0", + "helm.sh/chart": "prometheus-25.22.0", + }, + "name": "release-name-prometheus-server", + "namespace": "default", + }, + }, + { + "apiVersion": "v1", + "data": { + "alertmanager.yml": "global: {} +receivers: +- name: default-receiver +route: + group_interval: 5m + group_wait: 10s + receiver: default-receiver + repeat_interval: 3h +templates: +- /etc/alertmanager/*.tmpl +", + }, + "kind": "ConfigMap", + "metadata": { + "labels": { + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "alertmanager", + "app.kubernetes.io/version": "v0.27.0", + "helm.sh/chart": "alertmanager-1.11.0", + }, + "name": "release-name-alertmanager", + "namespace": "default", + }, + }, + { + "apiVersion": "v1", + "data": { + "alerting_rules.yml": "{} +", + "alerts": "{} +", + "allow-snippet-annotations": "false", + "prometheus.yml": "global: + evaluation_interval: 1m + scrape_interval: 1m + scrape_timeout: 10s +rule_files: +- /etc/config/recording_rules.yml +- /etc/config/alerting_rules.yml +- /etc/config/rules +- /etc/config/alerts +scrape_configs: +- job_name: prometheus + static_configs: + - targets: + - localhost:9090 +- bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + job_name: kubernetes-apiservers + kubernetes_sd_configs: + - role: endpoints + relabel_configs: + - action: keep + regex: default;kubernetes;https + source_labels: + - __meta_kubernetes_namespace + - __meta_kubernetes_service_name + - __meta_kubernetes_endpoint_port_name + scheme: https + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + insecure_skip_verify: true +- bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + job_name: kubernetes-nodes + kubernetes_sd_configs: + - role: node + relabel_configs: + - action: labelmap + regex: __meta_kubernetes_node_label_(.+) + - replacement: kubernetes.default.svc:443 + target_label: __address__ + - regex: (.+) + replacement: /api/v1/nodes/$1/proxy/metrics + source_labels: + - __meta_kubernetes_node_name + target_label: __metrics_path__ + scheme: https + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + insecure_skip_verify: true +- bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + job_name: kubernetes-nodes-cadvisor + kubernetes_sd_configs: + - role: node + relabel_configs: + - action: labelmap + regex: __meta_kubernetes_node_label_(.+) + - replacement: kubernetes.default.svc:443 + target_label: __address__ + - regex: (.+) + replacement: /api/v1/nodes/$1/proxy/metrics/cadvisor + source_labels: + - __meta_kubernetes_node_name + target_label: __metrics_path__ + scheme: https + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + insecure_skip_verify: true +- honor_labels: true + job_name: kubernetes-service-endpoints + kubernetes_sd_configs: + - role: endpoints + relabel_configs: + - action: keep + regex: true + source_labels: + - __meta_kubernetes_service_annotation_prometheus_io_scrape + - action: drop + regex: true + source_labels: + - __meta_kubernetes_service_annotation_prometheus_io_scrape_slow + - action: replace + regex: (https?) + source_labels: + - __meta_kubernetes_service_annotation_prometheus_io_scheme + target_label: __scheme__ + - action: replace + regex: (.+) + source_labels: + - __meta_kubernetes_service_annotation_prometheus_io_path + target_label: __metrics_path__ + - action: replace + regex: (.+?)(?::\\d+)?;(\\d+) + replacement: $1:$2 + source_labels: + - __address__ + - __meta_kubernetes_service_annotation_prometheus_io_port + target_label: __address__ + - action: labelmap + regex: __meta_kubernetes_service_annotation_prometheus_io_param_(.+) + replacement: __param_$1 + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + - action: replace + source_labels: + - __meta_kubernetes_namespace + target_label: namespace + - action: replace + source_labels: + - __meta_kubernetes_service_name + target_label: service + - action: replace + source_labels: + - __meta_kubernetes_pod_node_name + target_label: node +- honor_labels: true + job_name: kubernetes-service-endpoints-slow + kubernetes_sd_configs: + - role: endpoints + relabel_configs: + - action: keep + regex: true + source_labels: + - __meta_kubernetes_service_annotation_prometheus_io_scrape_slow + - action: replace + regex: (https?) + source_labels: + - __meta_kubernetes_service_annotation_prometheus_io_scheme + target_label: __scheme__ + - action: replace + regex: (.+) + source_labels: + - __meta_kubernetes_service_annotation_prometheus_io_path + target_label: __metrics_path__ + - action: replace + regex: (.+?)(?::\\d+)?;(\\d+) + replacement: $1:$2 + source_labels: + - __address__ + - __meta_kubernetes_service_annotation_prometheus_io_port + target_label: __address__ + - action: labelmap + regex: __meta_kubernetes_service_annotation_prometheus_io_param_(.+) + replacement: __param_$1 + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + - action: replace + source_labels: + - __meta_kubernetes_namespace + target_label: namespace + - action: replace + source_labels: + - __meta_kubernetes_service_name + target_label: service + - action: replace + source_labels: + - __meta_kubernetes_pod_node_name + target_label: node + scrape_interval: 5m + scrape_timeout: 30s +- honor_labels: true + job_name: prometheus-pushgateway + kubernetes_sd_configs: + - role: service + relabel_configs: + - action: keep + regex: pushgateway + source_labels: + - __meta_kubernetes_service_annotation_prometheus_io_probe +- honor_labels: true + job_name: kubernetes-services + kubernetes_sd_configs: + - role: service + metrics_path: /probe + params: + module: + - http_2xx + relabel_configs: + - action: keep + regex: true + source_labels: + - __meta_kubernetes_service_annotation_prometheus_io_probe + - source_labels: + - __address__ + target_label: __param_target + - replacement: blackbox + target_label: __address__ + - source_labels: + - __param_target + target_label: instance + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + - source_labels: + - __meta_kubernetes_namespace + target_label: namespace + - source_labels: + - __meta_kubernetes_service_name + target_label: service +- honor_labels: true + job_name: kubernetes-pods + kubernetes_sd_configs: + - role: pod + relabel_configs: + - action: keep + regex: true + source_labels: + - __meta_kubernetes_pod_annotation_prometheus_io_scrape + - action: drop + regex: true + source_labels: + - __meta_kubernetes_pod_annotation_prometheus_io_scrape_slow + - action: replace + regex: (https?) + source_labels: + - __meta_kubernetes_pod_annotation_prometheus_io_scheme + target_label: __scheme__ + - action: replace + regex: (.+) + source_labels: + - __meta_kubernetes_pod_annotation_prometheus_io_path + target_label: __metrics_path__ + - action: replace + regex: (\\d+);(([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}) + replacement: '[$2]:$1' + source_labels: + - __meta_kubernetes_pod_annotation_prometheus_io_port + - __meta_kubernetes_pod_ip + target_label: __address__ + - action: replace + regex: (\\d+);((([0-9]+?)(\\.|$)){4}) + replacement: $2:$1 + source_labels: + - __meta_kubernetes_pod_annotation_prometheus_io_port + - __meta_kubernetes_pod_ip + target_label: __address__ + - action: labelmap + regex: __meta_kubernetes_pod_annotation_prometheus_io_param_(.+) + replacement: __param_$1 + - action: labelmap + regex: __meta_kubernetes_pod_label_(.+) + - action: replace + source_labels: + - __meta_kubernetes_namespace + target_label: namespace + - action: replace + source_labels: + - __meta_kubernetes_pod_name + target_label: pod + - action: drop + regex: Pending|Succeeded|Failed|Completed + source_labels: + - __meta_kubernetes_pod_phase + - action: replace + source_labels: + - __meta_kubernetes_pod_node_name + target_label: node +- honor_labels: true + job_name: kubernetes-pods-slow + kubernetes_sd_configs: + - role: pod + relabel_configs: + - action: keep + regex: true + source_labels: + - __meta_kubernetes_pod_annotation_prometheus_io_scrape_slow + - action: replace + regex: (https?) + source_labels: + - __meta_kubernetes_pod_annotation_prometheus_io_scheme + target_label: __scheme__ + - action: replace + regex: (.+) + source_labels: + - __meta_kubernetes_pod_annotation_prometheus_io_path + target_label: __metrics_path__ + - action: replace + regex: (\\d+);(([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}) + replacement: '[$2]:$1' + source_labels: + - __meta_kubernetes_pod_annotation_prometheus_io_port + - __meta_kubernetes_pod_ip + target_label: __address__ + - action: replace + regex: (\\d+);((([0-9]+?)(\\.|$)){4}) + replacement: $2:$1 + source_labels: + - __meta_kubernetes_pod_annotation_prometheus_io_port + - __meta_kubernetes_pod_ip + target_label: __address__ + - action: labelmap + regex: __meta_kubernetes_pod_annotation_prometheus_io_param_(.+) + replacement: __param_$1 + - action: labelmap + regex: __meta_kubernetes_pod_label_(.+) + - action: replace + source_labels: + - __meta_kubernetes_namespace + target_label: namespace + - action: replace + source_labels: + - __meta_kubernetes_pod_name + target_label: pod + - action: drop + regex: Pending|Succeeded|Failed|Completed + source_labels: + - __meta_kubernetes_pod_phase + - action: replace + source_labels: + - __meta_kubernetes_pod_node_name + target_label: node + scrape_interval: 5m + scrape_timeout: 30s +alerting: + alertmanagers: + - kubernetes_sd_configs: + - role: pod + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + relabel_configs: + - source_labels: [__meta_kubernetes_namespace] + regex: default + action: keep + - source_labels: [__meta_kubernetes_pod_label_app_kubernetes_io_instance] + regex: release-name + action: keep + - source_labels: [__meta_kubernetes_pod_label_app_kubernetes_io_name] + regex: alertmanager + action: keep + - source_labels: [__meta_kubernetes_pod_container_port_number] + regex: "9093" + action: keep +", + "recording_rules.yml": "{} +", + "rules": "{} +", + }, + "kind": "ConfigMap", + "metadata": { + "labels": { + "app.kubernetes.io/component": "server", + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "prometheus", + "app.kubernetes.io/part-of": "prometheus", + "app.kubernetes.io/version": "v2.53.0", + "helm.sh/chart": "prometheus-25.22.0", + }, + "name": "release-name-prometheus-server", + "namespace": "default", + }, + }, + { + "apiVersion": "v1", + "kind": "PersistentVolumeClaim", + "metadata": { + "labels": { + "app.kubernetes.io/component": "server", + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "prometheus", + "app.kubernetes.io/part-of": "prometheus", + "app.kubernetes.io/version": "v2.53.0", + "helm.sh/chart": "prometheus-25.22.0", + }, + "name": "release-name-prometheus-server", + "namespace": "default", + }, + "spec": { + "accessModes": [ + "ReadWriteOnce", + ], + "resources": { + "requests": { + "storage": "8Gi", + }, + }, + }, + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "labels": { + "app.kubernetes.io/component": "metrics", + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "kube-state-metrics", + "app.kubernetes.io/part-of": "kube-state-metrics", + "app.kubernetes.io/version": "2.12.0", + "helm.sh/chart": "kube-state-metrics-5.20.0", + }, + "name": "release-name-kube-state-metrics", + }, + "rules": [ + { + "apiGroups": [ + "certificates.k8s.io", + ], + "resources": [ + "certificatesigningrequests", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "", + ], + "resources": [ + "configmaps", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "batch", + ], + "resources": [ + "cronjobs", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "extensions", + "apps", + ], + "resources": [ + "daemonsets", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "extensions", + "apps", + ], + "resources": [ + "deployments", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "", + ], + "resources": [ + "endpoints", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "autoscaling", + ], + "resources": [ + "horizontalpodautoscalers", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "extensions", + "networking.k8s.io", + ], + "resources": [ + "ingresses", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "batch", + ], + "resources": [ + "jobs", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "coordination.k8s.io", + ], + "resources": [ + "leases", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "", + ], + "resources": [ + "limitranges", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "admissionregistration.k8s.io", + ], + "resources": [ + "mutatingwebhookconfigurations", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "", + ], + "resources": [ + "namespaces", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "networking.k8s.io", + ], + "resources": [ + "networkpolicies", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "", + ], + "resources": [ + "nodes", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "", + ], + "resources": [ + "persistentvolumeclaims", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "", + ], + "resources": [ + "persistentvolumes", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "policy", + ], + "resources": [ + "poddisruptionbudgets", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "", + ], + "resources": [ + "pods", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "extensions", + "apps", + ], + "resources": [ + "replicasets", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "", + ], + "resources": [ + "replicationcontrollers", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "", + ], + "resources": [ + "resourcequotas", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "", + ], + "resources": [ + "secrets", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "", + ], + "resources": [ + "services", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "apps", + ], + "resources": [ + "statefulsets", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "storage.k8s.io", + ], + "resources": [ + "storageclasses", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "admissionregistration.k8s.io", + ], + "resources": [ + "validatingwebhookconfigurations", + ], + "verbs": [ + "list", + "watch", + ], + }, + { + "apiGroups": [ + "storage.k8s.io", + ], + "resources": [ + "volumeattachments", + ], + "verbs": [ + "list", + "watch", + ], + }, + ], + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "labels": { + "app.kubernetes.io/component": "server", + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "prometheus", + "app.kubernetes.io/part-of": "prometheus", + "app.kubernetes.io/version": "v2.53.0", + "helm.sh/chart": "prometheus-25.22.0", + }, + "name": "release-name-prometheus-server", + }, + "rules": [ + { + "apiGroups": [ + "", + ], + "resources": [ + "nodes", + "nodes/proxy", + "nodes/metrics", + "services", + "endpoints", + "pods", + "ingresses", + "configmaps", + ], + "verbs": [ + "get", + "list", + "watch", + ], + }, + { + "apiGroups": [ + "extensions", + "networking.k8s.io", + ], + "resources": [ + "ingresses/status", + "ingresses", + ], + "verbs": [ + "get", + "list", + "watch", + ], + }, + { + "apiGroups": [ + "discovery.k8s.io", + ], + "resources": [ + "endpointslices", + ], + "verbs": [ + "get", + "list", + "watch", + ], + }, + { + "nonResourceURLs": [ + "/metrics", + ], + "verbs": [ + "get", + ], + }, + ], + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "labels": { + "app.kubernetes.io/component": "metrics", + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "kube-state-metrics", + "app.kubernetes.io/part-of": "kube-state-metrics", + "app.kubernetes.io/version": "2.12.0", + "helm.sh/chart": "kube-state-metrics-5.20.0", + }, + "name": "release-name-kube-state-metrics", + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "release-name-kube-state-metrics", + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "release-name-kube-state-metrics", + "namespace": "default", + }, + ], + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "labels": { + "app.kubernetes.io/component": "server", + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "prometheus", + "app.kubernetes.io/part-of": "prometheus", + "app.kubernetes.io/version": "v2.53.0", + "helm.sh/chart": "prometheus-25.22.0", + }, + "name": "release-name-prometheus-server", + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "release-name-prometheus-server", + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "release-name-prometheus-server", + "namespace": "default", + }, + ], + }, + { + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "alertmanager", + "app.kubernetes.io/version": "v0.27.0", + "helm.sh/chart": "alertmanager-1.11.0", + }, + "name": "release-name-alertmanager", + "namespace": "default", + }, + "spec": { + "ports": [ + { + "name": "http", + "port": 9093, + "protocol": "TCP", + "targetPort": "http", + }, + ], + "selector": { + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/name": "alertmanager", + }, + "type": "ClusterIP", + }, + }, + { + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "alertmanager", + "app.kubernetes.io/version": "v0.27.0", + "helm.sh/chart": "alertmanager-1.11.0", + }, + "name": "release-name-alertmanager-headless", + "namespace": "default", + }, + "spec": { + "clusterIP": "None", + "ports": [ + { + "name": "http", + "port": 9093, + "protocol": "TCP", + "targetPort": "http", + }, + ], + "selector": { + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/name": "alertmanager", + }, + }, + }, + { + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "annotations": { + "prometheus.io/scrape": "true", + }, + "labels": { + "app.kubernetes.io/component": "metrics", + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "kube-state-metrics", + "app.kubernetes.io/part-of": "kube-state-metrics", + "app.kubernetes.io/version": "2.12.0", + "helm.sh/chart": "kube-state-metrics-5.20.0", + }, + "name": "release-name-kube-state-metrics", + "namespace": "default", + }, + "spec": { + "ports": [ + { + "name": "http", + "port": 8080, + "protocol": "TCP", + "targetPort": 8080, + }, + ], + "selector": { + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/name": "kube-state-metrics", + }, + "type": "ClusterIP", + }, + }, + { + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "annotations": { + "prometheus.io/scrape": "true", + }, + "labels": { + "app.kubernetes.io/component": "metrics", + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "prometheus-node-exporter", + "app.kubernetes.io/part-of": "prometheus-node-exporter", + "app.kubernetes.io/version": "1.8.1", + "helm.sh/chart": "prometheus-node-exporter-4.36.0", + }, + "name": "release-name-prometheus-node-exporter", + "namespace": "default", + }, + "spec": { + "ports": [ + { + "name": "metrics", + "port": 9100, + "protocol": "TCP", + "targetPort": 9100, + }, + ], + "selector": { + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/name": "prometheus-node-exporter", + }, + "type": "ClusterIP", + }, + }, + { + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "annotations": { + "prometheus.io/probe": "pushgateway", + }, + "labels": { + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "prometheus-pushgateway", + "app.kubernetes.io/version": "v1.8.0", + "helm.sh/chart": "prometheus-pushgateway-2.13.0", + }, + "name": "release-name-prometheus-pushgateway", + "namespace": "default", + }, + "spec": { + "ports": [ + { + "name": "http", + "port": 9091, + "protocol": "TCP", + "targetPort": 9091, + }, + ], + "selector": { + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/name": "prometheus-pushgateway", + }, + "type": "ClusterIP", + }, + }, + { + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "labels": { + "app.kubernetes.io/component": "server", + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "prometheus", + "app.kubernetes.io/part-of": "prometheus", + "app.kubernetes.io/version": "v2.53.0", + "helm.sh/chart": "prometheus-25.22.0", + }, + "name": "release-name-prometheus-server", + "namespace": "default", + }, + "spec": { + "ports": [ + { + "name": "http", + "port": 80, + "protocol": "TCP", + "targetPort": 9090, + }, + ], + "selector": { + "app.kubernetes.io/component": "server", + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/name": "prometheus", + }, + "sessionAffinity": "None", + "type": "ClusterIP", + }, + }, + { + "apiVersion": "apps/v1", + "kind": "DaemonSet", + "metadata": { + "labels": { + "app.kubernetes.io/component": "metrics", + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "prometheus-node-exporter", + "app.kubernetes.io/part-of": "prometheus-node-exporter", + "app.kubernetes.io/version": "1.8.1", + "helm.sh/chart": "prometheus-node-exporter-4.36.0", + }, + "name": "release-name-prometheus-node-exporter", + "namespace": "default", + }, + "spec": { + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/name": "prometheus-node-exporter", + }, + }, + "template": { + "metadata": { + "annotations": { + "cluster-autoscaler.kubernetes.io/safe-to-evict": "true", + }, + "labels": { + "app.kubernetes.io/component": "metrics", + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "prometheus-node-exporter", + "app.kubernetes.io/part-of": "prometheus-node-exporter", + "app.kubernetes.io/version": "1.8.1", + "helm.sh/chart": "prometheus-node-exporter-4.36.0", + }, + }, + "spec": { + "automountServiceAccountToken": false, + "containers": [ + { + "args": [ + "--path.procfs=/host/proc", + "--path.sysfs=/host/sys", + "--path.rootfs=/host/root", + "--path.udev.data=/host/root/run/udev/data", + "--web.listen-address=[$(HOST_IP)]:9100", + ], + "env": [ + { + "name": "HOST_IP", + "value": "0.0.0.0", + }, + ], + "image": "quay.io/prometheus/node-exporter:v1.8.1", + "imagePullPolicy": "IfNotPresent", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "httpHeaders": null, + "path": "/", + "port": 9100, + "scheme": "HTTP", + }, + "initialDelaySeconds": 0, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1, + }, + "name": "node-exporter", + "ports": [ + { + "containerPort": 9100, + "name": "metrics", + "protocol": "TCP", + }, + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "httpHeaders": null, + "path": "/", + "port": 9100, + "scheme": "HTTP", + }, + "initialDelaySeconds": 0, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1, + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "readOnlyRootFilesystem": true, + }, + "volumeMounts": [ + { + "mountPath": "/host/proc", + "name": "proc", + "readOnly": true, + }, + { + "mountPath": "/host/sys", + "name": "sys", + "readOnly": true, + }, + { + "mountPath": "/host/root", + "mountPropagation": "HostToContainer", + "name": "root", + "readOnly": true, + }, + ], + }, + ], + "hostNetwork": true, + "hostPID": true, + "nodeSelector": { + "kubernetes.io/os": "linux", + }, + "securityContext": { + "fsGroup": 65534, + "runAsGroup": 65534, + "runAsNonRoot": true, + "runAsUser": 65534, + }, + "serviceAccountName": "release-name-prometheus-node-exporter", + "tolerations": [ + { + "effect": "NoSchedule", + "operator": "Exists", + }, + ], + "volumes": [ + { + "hostPath": { + "path": "/proc", + }, + "name": "proc", + }, + { + "hostPath": { + "path": "/sys", + }, + "name": "sys", + }, + { + "hostPath": { + "path": "/", + }, + "name": "root", + }, + ], + }, + }, + "updateStrategy": { + "rollingUpdate": { + "maxUnavailable": 1, + }, + "type": "RollingUpdate", + }, + }, + }, + { + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/component": "metrics", + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "kube-state-metrics", + "app.kubernetes.io/part-of": "kube-state-metrics", + "app.kubernetes.io/version": "2.12.0", + "helm.sh/chart": "kube-state-metrics-5.20.0", + }, + "name": "release-name-kube-state-metrics", + "namespace": "default", + }, + "spec": { + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/name": "kube-state-metrics", + }, + }, + "strategy": { + "type": "RollingUpdate", + }, + "template": { + "metadata": { + "labels": { + "app.kubernetes.io/component": "metrics", + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "kube-state-metrics", + "app.kubernetes.io/part-of": "kube-state-metrics", + "app.kubernetes.io/version": "2.12.0", + "helm.sh/chart": "kube-state-metrics-5.20.0", + }, + }, + "spec": { + "containers": [ + { + "args": [ + "--port=8080", + "--resources=certificatesigningrequests,configmaps,cronjobs,daemonsets,deployments,endpoints,horizontalpodautoscalers,ingresses,jobs,leases,limitranges,mutatingwebhookconfigurations,namespaces,networkpolicies,nodes,persistentvolumeclaims,persistentvolumes,poddisruptionbudgets,pods,replicasets,replicationcontrollers,resourcequotas,secrets,services,statefulsets,storageclasses,validatingwebhookconfigurations,volumeattachments", + ], + "image": "registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.12.0", + "imagePullPolicy": "IfNotPresent", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "httpHeaders": null, + "path": "/healthz", + "port": 8080, + "scheme": "HTTP", + }, + "initialDelaySeconds": 5, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 5, + }, + "name": "kube-state-metrics", + "ports": [ + { + "containerPort": 8080, + "name": "http", + }, + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "httpHeaders": null, + "path": "/", + "port": 8080, + "scheme": "HTTP", + }, + "initialDelaySeconds": 5, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 5, + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL", + ], + }, + "readOnlyRootFilesystem": true, + }, + }, + ], + "hostNetwork": false, + "securityContext": { + "fsGroup": 65534, + "runAsGroup": 65534, + "runAsNonRoot": true, + "runAsUser": 65534, + "seccompProfile": { + "type": "RuntimeDefault", + }, + }, + "serviceAccountName": "release-name-kube-state-metrics", + }, + }, + }, + }, + { + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "prometheus-pushgateway", + "app.kubernetes.io/version": "v1.8.0", + "helm.sh/chart": "prometheus-pushgateway-2.13.0", + }, + "name": "release-name-prometheus-pushgateway", + "namespace": "default", + }, + "spec": { + "replicas": 1, + "selector": { + "matchLabels": { + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/name": "prometheus-pushgateway", + }, + }, + "strategy": { + "type": "Recreate", + }, + "template": { + "metadata": { + "labels": { + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "prometheus-pushgateway", + "app.kubernetes.io/version": "v1.8.0", + "helm.sh/chart": "prometheus-pushgateway-2.13.0", + }, + }, + "spec": { + "automountServiceAccountToken": true, + "containers": [ + { + "image": "quay.io/prometheus/pushgateway:v1.8.0", + "imagePullPolicy": "IfNotPresent", + "livenessProbe": { + "httpGet": { + "path": "/-/healthy", + "port": 9091, + }, + "initialDelaySeconds": 10, + "timeoutSeconds": 10, + }, + "name": "pushgateway", + "ports": [ + { + "containerPort": 9091, + "name": "metrics", + "protocol": "TCP", + }, + ], + "readinessProbe": { + "httpGet": { + "path": "/-/ready", + "port": 9091, + }, + "initialDelaySeconds": 10, + "timeoutSeconds": 10, + }, + "volumeMounts": [ + { + "mountPath": "/data", + "name": "storage-volume", + "subPath": "", + }, + ], + }, + ], + "securityContext": { + "fsGroup": 65534, + "runAsNonRoot": true, + "runAsUser": 65534, + }, + "serviceAccountName": "release-name-prometheus-pushgateway", + "volumes": [ + { + "emptyDir": {}, + "name": "storage-volume", + }, + ], + }, + }, + }, + }, + { + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app.kubernetes.io/component": "server", + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "prometheus", + "app.kubernetes.io/part-of": "prometheus", + "app.kubernetes.io/version": "v2.53.0", + "helm.sh/chart": "prometheus-25.22.0", + }, + "name": "release-name-prometheus-server", + "namespace": "default", + }, + "spec": { + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app.kubernetes.io/component": "server", + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/name": "prometheus", + }, + }, + "strategy": { + "rollingUpdate": null, + "type": "Recreate", + }, + "template": { + "metadata": { + "labels": { + "app.kubernetes.io/component": "server", + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "prometheus", + "app.kubernetes.io/part-of": "prometheus", + "app.kubernetes.io/version": "v2.53.0", + "helm.sh/chart": "prometheus-25.22.0", + }, + }, + "spec": { + "containers": [ + { + "args": [ + "--watched-dir=/etc/config", + "--reload-url=http://127.0.0.1:9090/-/reload", + ], + "image": "quay.io/prometheus-operator/prometheus-config-reloader:v0.74.0", + "imagePullPolicy": "IfNotPresent", + "name": "prometheus-server-configmap-reload", + "volumeMounts": [ + { + "mountPath": "/etc/config", + "name": "config-volume", + "readOnly": true, + }, + ], + }, + { + "args": [ + "--storage.tsdb.retention.time=15d", + "--config.file=/etc/config/prometheus.yml", + "--storage.tsdb.path=/data", + "--web.console.libraries=/etc/prometheus/console_libraries", + "--web.console.templates=/etc/prometheus/consoles", + "--web.enable-lifecycle", + ], + "image": "quay.io/prometheus/prometheus:v2.53.0", + "imagePullPolicy": "IfNotPresent", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/-/healthy", + "port": 9090, + "scheme": "HTTP", + }, + "initialDelaySeconds": 30, + "periodSeconds": 15, + "successThreshold": 1, + "timeoutSeconds": 10, + }, + "name": "prometheus-server", + "ports": [ + { + "containerPort": 9090, + }, + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/-/ready", + "port": 9090, + "scheme": "HTTP", + }, + "initialDelaySeconds": 30, + "periodSeconds": 5, + "successThreshold": 1, + "timeoutSeconds": 4, + }, + "volumeMounts": [ + { + "mountPath": "/etc/config", + "name": "config-volume", + }, + { + "mountPath": "/data", + "name": "storage-volume", + "subPath": "", + }, + ], + }, + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "securityContext": { + "fsGroup": 65534, + "runAsGroup": 65534, + "runAsNonRoot": true, + "runAsUser": 65534, + }, + "serviceAccountName": "release-name-prometheus-server", + "terminationGracePeriodSeconds": 300, + "volumes": [ + { + "configMap": { + "name": "release-name-prometheus-server", + }, + "name": "config-volume", + }, + { + "name": "storage-volume", + "persistentVolumeClaim": { + "claimName": "release-name-prometheus-server", + }, + }, + ], + }, + }, + }, + }, + { + "apiVersion": "apps/v1", + "kind": "StatefulSet", + "metadata": { + "labels": { + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "alertmanager", + "app.kubernetes.io/version": "v0.27.0", + "helm.sh/chart": "alertmanager-1.11.0", + }, + "name": "release-name-alertmanager", + "namespace": "default", + }, + "spec": { + "minReadySeconds": 0, + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/name": "alertmanager", + }, + }, + "serviceName": "release-name-alertmanager-headless", + "template": { + "metadata": { + "annotations": { + "checksum/config": "0ffaa240c68d32234438f4e611c72640cb1b42bdc76bff12a67266992af87411", + }, + "labels": { + "app.kubernetes.io/instance": "release-name", + "app.kubernetes.io/name": "alertmanager", + }, + }, + "spec": { + "automountServiceAccountToken": true, + "containers": [ + { + "args": [ + "--storage.path=/alertmanager", + "--config.file=/etc/alertmanager/alertmanager.yml", + ], + "env": [ + { + "name": "POD_IP", + "valueFrom": { + "fieldRef": { + "apiVersion": "v1", + "fieldPath": "status.podIP", + }, + }, + }, + ], + "image": "quay.io/prometheus/alertmanager:v0.27.0", + "imagePullPolicy": "IfNotPresent", + "livenessProbe": { + "httpGet": { + "path": "/", + "port": "http", + }, + }, + "name": "alertmanager", + "ports": [ + { + "containerPort": 9093, + "name": "http", + "protocol": "TCP", + }, + ], + "readinessProbe": { + "httpGet": { + "path": "/", + "port": "http", + }, + }, + "resources": {}, + "securityContext": { + "runAsGroup": 65534, + "runAsNonRoot": true, + "runAsUser": 65534, + }, + "volumeMounts": [ + { + "mountPath": "/etc/alertmanager", + "name": "config", + }, + { + "mountPath": "/alertmanager", + "name": "storage", + }, + ], + }, + ], + "securityContext": { + "fsGroup": 65534, + "runAsGroup": 65534, + "runAsNonRoot": true, + "runAsUser": 65534, + }, + "serviceAccountName": "release-name-alertmanager", + "volumes": [ + { + "configMap": { + "name": "release-name-alertmanager", + }, + "name": "config", + }, + ], + }, + }, + "volumeClaimTemplates": [ + { + "metadata": { + "name": "storage", + }, + "spec": { + "accessModes": [ + "ReadWriteOnce", + ], + "resources": { + "requests": { + "storage": "2Gi", + }, + }, + }, + }, + ], + }, + }, +] +`; + exports[`chart is deprecated 1`] = ` [ { diff --git a/packages/helm/src/__tests__/load.ts b/packages/helm/src/__tests__/load.ts index 136baf3a2..6f2728744 100644 --- a/packages/helm/src/__tests__/load.ts +++ b/packages/helm/src/__tests__/load.ts @@ -18,6 +18,7 @@ jest.mock("@kosko/exec-utils", () => { const FIXTURE_DIR = join(__dirname, "../__fixtures__"); const NGINX_CHART = join(FIXTURE_DIR, "nginx"); +const TAR_CHART = join(FIXTURE_DIR, "tar", "prometheus-25.22.0.tgz"); const mockedSpawn = jest.mocked(spawn); @@ -32,6 +33,11 @@ test("chart is a local path", async () => { await expect(result()).resolves.toMatchSnapshot(); }); +test("chart is a local tarball", async () => { + const result = loadChart({ chart: TAR_CHART }); + await expect(result()).resolves.toMatchSnapshot(); +}); + test("chart is remote", async () => { const result = loadChart({ chart: "prometheus", diff --git a/packages/helm/src/load.ts b/packages/helm/src/load.ts index 127e34066..462b5cf44 100644 --- a/packages/helm/src/load.ts +++ b/packages/helm/src/load.ts @@ -247,12 +247,13 @@ async function runHelm(args: readonly string[]) { } } -function getChartManifestPath(path: string) { - return join(path, "Chart.yaml"); -} - -function chartManifestExists(path: string) { - return fileExists(getChartManifestPath(path)); +async function chartManifestExists(path: string) { + try { + return isRecord(await getChartMetadata(path)); + } catch { + // + } + return false; } async function isLocalChart( @@ -270,14 +271,10 @@ async function isLocalChart( async function getChartMetadata( chart: string ): Promise | undefined> { - try { - const { stdout: content } = await runHelm(["show", "chart", chart]); - const metadata = yaml.load(content); + const { stdout: content } = await runHelm(["show", "chart", chart]); + const metadata = yaml.load(content); - if (isRecord(metadata)) return metadata; - } catch (err) { - if (getErrorCode(err) !== "ENOENT") throw err; - } + if (isRecord(metadata)) return metadata; } function getPullArgs(options: PullOptions): string[] {