diff --git a/Cargo.lock b/Cargo.lock index 14de323f..46ab04bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -955,9 +955,9 @@ dependencies = [ [[package]] name = "globwalk" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "178270263374052c40502e9f607134947de75302c1348d1a0e31db67c1691446" +checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" dependencies = [ "bitflags", "ignore", @@ -2140,6 +2140,18 @@ dependencies = [ "rand_hc 0.2.0", ] +[[package]] +name = "rand" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +dependencies = [ + "libc", + "rand_chacha 0.3.0", + "rand_core 0.6.2", + "rand_hc 0.3.0", +] + [[package]] name = "rand_chacha" version = "0.1.1" @@ -2160,6 +2172,16 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rand_chacha" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.2", +] + [[package]] name = "rand_core" version = "0.3.1" @@ -2184,6 +2206,15 @@ dependencies = [ "getrandom 0.1.15", ] +[[package]] +name = "rand_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +dependencies = [ + "getrandom 0.2.2", +] + [[package]] name = "rand_hc" version = "0.1.0" @@ -2202,6 +2233,15 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rand_hc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" +dependencies = [ + "rand_core 0.6.2", +] + [[package]] name = "rand_isaac" version = "0.1.1" @@ -3039,9 +3079,9 @@ dependencies = [ [[package]] name = "tera" -version = "1.5.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1381c83828bedd5ce4e59473110afa5381ffe523406d9ade4b77c9f7be70ff9a" +checksum = "81060acb882480c8793782eb96bc86f5c83d2fc7175ad46c375c6956ef7afa62" dependencies = [ "chrono", "chrono-tz", @@ -3051,7 +3091,7 @@ dependencies = [ "percent-encoding 2.1.0", "pest", "pest_derive", - "rand 0.7.3", + "rand 0.8.3", "regex", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index 0337afff..0ee4e84b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,8 @@ tracing-subscriber = "0.2" sysinfo = "0.16.4" # Jinja2 -tera = "1.3.1" +tera = "1.10.0" +# Json serde = "1.0.114" serde_json = "1.0.57" serde_derive = "1.0" diff --git a/lib/aws/bootstrap/qovery-tf-config.j2.tf b/lib/aws/bootstrap/qovery-tf-config.j2.tf new file mode 100644 index 00000000..b39fc92d --- /dev/null +++ b/lib/aws/bootstrap/qovery-tf-config.j2.tf @@ -0,0 +1,41 @@ +locals { + qovery_tf_config = <(qovery_terraform_config_file: &str) -> Result>>, SimpleError> +where + H: ?Sized, +{ + let qovery_terraform_config = match serde_json::from_str::(qovery_terraform_config_file) { + Ok(x) => x, + Err(e) => { + return Err(SimpleError { + kind: SimpleErrorKind::Other, + message: Some(format!("{:?}", e)), + }) + } + }; + let prometheus_namespace = HelmChartNamespaces::Prometheus; + let loki_namespace = HelmChartNamespaces::Logging; + let loki_service_name = "loki".to_string(); + + // Qovery storage class + let q_storage_class = CommonChart { + chart_info: ChartInfo { + name: "q-storageclass".to_string(), + path: "charts/q-storageclass".to_string(), + ..Default::default() + }, + }; + + let aws_vpc_cni_chart = AwsVpcCniChart { + chart_info: ChartInfo { + name: "aws-vpc-cni".to_string(), + path: "charts/aws-vpc-cni".to_string(), + values: vec![ + ChartSetValue { + key: "image.region".to_string(), + value: qovery_terraform_config.region.clone(), + }, + ChartSetValue { + key: "image.pullPolicy".to_string(), + value: "IfNotPresent".to_string(), + }, + ChartSetValue { + key: "crd.create".to_string(), + value: "false".to_string(), + }, + ChartSetValue { + key: "env.CLUSTER_NAME".to_string(), + value: qovery_terraform_config.cluster_name.clone(), + }, + ChartSetValue { + key: "env.MINIMUM_IP_TARGET".to_string(), + value: "60".to_string(), + }, + ChartSetValue { + key: "env.WARM_IP_TARGET".to_string(), + value: "10".to_string(), + }, + ChartSetValue { + key: "env.MAX_ENI".to_string(), + value: "100".to_string(), + }, + ChartSetValue { + key: "resources.requests.cpu".to_string(), + value: "50".to_string(), + }, + ], + ..Default::default() + }, + }; + + let aws_iam_eks_user_mapper = CommonChart { + chart_info: ChartInfo { + name: "iam-eks-user-mapper".to_string(), + path: "charts/iam-eks-user-mapper".to_string(), + values: vec![ + ChartSetValue { + key: "aws.accessKey".to_string(), + value: qovery_terraform_config.aws_iam_eks_user_mapper_key, + }, + ChartSetValue { + key: "aws.secretKey".to_string(), + value: qovery_terraform_config.aws_iam_eks_user_mapper_secret, + }, + ChartSetValue { + key: "image.region".to_string(), + value: qovery_terraform_config.region.clone(), + }, + ChartSetValue { + key: "syncIamGroup".to_string(), + value: "Admins".to_string(), + }, + // resources limits + ChartSetValue { + key: "resources.limits.cpu".to_string(), + value: "20m".to_string(), + }, + ChartSetValue { + key: "resources.requests.cpu".to_string(), + value: "10m".to_string(), + }, + ChartSetValue { + key: "resources.limits.memory".to_string(), + value: "32Mi".to_string(), + }, + ChartSetValue { + key: "resources.requests.memory".to_string(), + value: "32Mi".to_string(), + }, + ], + ..Default::default() + }, + }; + + let aws_node_term_handler = CommonChart { + chart_info: ChartInfo { + name: "aws-node-term-handler".to_string(), + path: "charts/aws-node-termination-handler".to_string(), + values: vec![ + ChartSetValue { + key: "nameOverride".to_string(), + value: "aws-node-term-handler".to_string(), + }, + ChartSetValue { + key: "fullnameOverride".to_string(), + value: "aws-node-term-handler".to_string(), + }, + ChartSetValue { + key: "enableSpotInterruptionDraining".to_string(), + value: "true".to_string(), + }, + ChartSetValue { + key: "enableScheduledEventDraining".to_string(), + value: "true".to_string(), + }, + ChartSetValue { + key: "deleteLocalData".to_string(), + value: "true".to_string(), + }, + ChartSetValue { + key: "ignoreDaemonSets".to_string(), + value: "true".to_string(), + }, + ChartSetValue { + key: "podTerminationGracePeriod".to_string(), + value: "300".to_string(), + }, + ChartSetValue { + key: "nodeTerminationGracePeriod".to_string(), + value: "120".to_string(), + }, + ], + ..Default::default() + }, + }; + + // Calico for AWS + let aws_calico = CommonChart { + chart_info: ChartInfo { + name: "calico".to_string(), + path: "charts/aws-calico".to_string(), + ..Default::default() + }, + }; + + let cluster_autoscaler = CommonChart { + chart_info: ChartInfo { + name: "cluster-autoscaler".to_string(), + path: "common/charts/cluster-autoscaler".to_string(), + values: vec![ + ChartSetValue { + key: "cloudProvider".to_string(), + value: "aws".to_string(), + }, + ChartSetValue { + key: "awsRegion".to_string(), + value: qovery_terraform_config.region.clone(), + }, + ChartSetValue { + key: "autoDiscovery.clusterName".to_string(), + value: qovery_terraform_config.cluster_name.clone(), + }, + ChartSetValue { + key: "awsAccessKeyID".to_string(), + value: qovery_terraform_config.aws_iam_cluster_autoscaler_key, + }, + ChartSetValue { + key: "awsSecretAccessKey".to_string(), + value: qovery_terraform_config.aws_iam_cluster_autoscaler_secret, + }, + // It's mandatory to get this class to ensure paused infra will behave properly on restore + ChartSetValue { + key: "priorityClassName".to_string(), + value: "system-cluster-critical".to_string(), + }, + // cluster autoscaler options + ChartSetValue { + key: "extraArgs.balance-similar-node-groups".to_string(), + value: "true".to_string(), + }, + // observability + ChartSetValue { + key: "serviceMonitor.enabled".to_string(), + value: qovery_terraform_config.feature_flag_metrics_history.clone(), + }, + ChartSetValue { + key: "serviceMonitor.namespace".to_string(), + value: get_chart_namespace(prometheus_namespace), + }, + // resources limits + ChartSetValue { + key: "resources.limits.cpu".to_string(), + value: "100m".to_string(), + }, + ChartSetValue { + key: "resources.requests.cpu".to_string(), + value: "100m".to_string(), + }, + ChartSetValue { + key: "resources.limits.memory".to_string(), + value: "300Mi".to_string(), + }, + ChartSetValue { + key: "resources.requests.memory".to_string(), + value: "300Mi".to_string(), + }, + ], + ..Default::default() + }, + }; + + let coredns_config = CommonChart { + chart_info: ChartInfo { + name: "coredns-config".to_string(), + path: "charts/coredns-config".to_string(), + values: vec![ + ChartSetValue { + key: "managed_dns".to_string(), + value: qovery_terraform_config.managed_dns_resolvers_terraform_format.clone(), + }, + ChartSetValue { + key: "managed_dns_resolvers".to_string(), + value: qovery_terraform_config.managed_dns_resolvers_terraform_format, + }, + ], + ..Default::default() + }, + }; + + let external_dns = CommonChart { + chart_info: ChartInfo { + name: "externaldns".to_string(), + path: "common/charts/external-dns".to_string(), + values_files: vec!["chart_values/external-dns.yaml".to_string()], + values: vec![ + // resources limits + ChartSetValue { + key: "resources.limits.cpu".to_string(), + value: "50m".to_string(), + }, + ChartSetValue { + key: "resources.requests.cpu".to_string(), + value: "50m".to_string(), + }, + ChartSetValue { + key: "resources.limits.memory".to_string(), + value: "50Mi".to_string(), + }, + ChartSetValue { + key: "resources.requests.memory".to_string(), + value: "50Mi".to_string(), + }, + ], + ..Default::default() + }, + }; + + let promtail = CommonChart { + chart_info: ChartInfo { + name: "promtail".to_string(), + path: "common/charts/promtail".to_string(), + namespace: loki_namespace, + values: vec![ + ChartSetValue { + key: "loki.serviceName".to_string(), + value: loki_service_name.clone(), + }, + // it's mandatory to get this class to ensure paused infra will behave properly on restore + ChartSetValue { + key: "priorityClassName".to_string(), + value: "system-node-critical".to_string(), + }, + // resources limits + ChartSetValue { + key: "resources.limits.cpu".to_string(), + value: "100m".to_string(), + }, + ChartSetValue { + key: "resources.requests.cpu".to_string(), + value: "100m".to_string(), + }, + ChartSetValue { + key: "resources.limits.memory".to_string(), + value: "128Mi".to_string(), + }, + ChartSetValue { + key: "resources.requests.memory".to_string(), + value: "128Mi".to_string(), + }, + ], + ..Default::default() + }, + }; + + let loki = CommonChart { + chart_info: ChartInfo { + name: "loki".to_string(), + path: "common/charts/loki".to_string(), + namespace: loki_namespace, + values_files: vec!["chart_values/loki.yaml".to_string()], + values: vec![ + ChartSetValue { + key: "config.storage_config.aws.s3".to_string(), + value: qovery_terraform_config.loki_storage_config_aws_s3, + }, + ChartSetValue { + key: "config.storage_config.aws.region".to_string(), + value: qovery_terraform_config.region.clone(), + }, + ChartSetValue { + key: "aws_iam_loki_storage_key".to_string(), + value: qovery_terraform_config.aws_iam_loki_storage_key, + }, + ChartSetValue { + key: "aws_iam_loki_storage_secret".to_string(), + value: qovery_terraform_config.aws_iam_loki_storage_secret, + }, + ChartSetValue { + key: "config.storage_config.aws.sse_encryption".to_string(), + value: "true".to_string(), + }, + // resources limits + ChartSetValue { + key: "resources.limits.cpu".to_string(), + value: "100m".to_string(), + }, + ChartSetValue { + key: "resources.requests.cpu".to_string(), + value: "100m".to_string(), + }, + ChartSetValue { + key: "resources.limits.memory".to_string(), + value: "2Gi".to_string(), + }, + ChartSetValue { + key: "resources.requests.memory".to_string(), + value: "1Gi".to_string(), + }, + ], + ..Default::default() + }, + }; + + let mut prometheus_operator = CommonChart { + chart_info: ChartInfo { + name: "prometheus-operator".to_string(), + path: "common/charts/prometheus-operator".to_string(), + namespace: HelmChartNamespaces::Logging, + // high timeout because on bootstrap, it's one of the biggest dependencies and on upgrade, it can takes time + // to upgrade because of the CRD and the number of elements it has to deploy + timeout: "480".to_string(), + values_files: vec!["chart_values/prometheus_operator.yaml".to_string()], + values: vec![ + ChartSetValue { + key: "nameOverride".to_string(), + value: "prometheus-operator".to_string(), + }, + ChartSetValue { + key: "fullnameOverride".to_string(), + value: "prometheus-operator".to_string(), + }, + // Limits kube-state-metrics + ChartSetValue { + key: "kube-state-metrics.resources.limits.cpu".to_string(), + value: "100m".to_string(), + }, + ChartSetValue { + key: "kube-state-metrics.resources.requests.cpu".to_string(), + value: "20m".to_string(), + }, + ChartSetValue { + key: "kube-state-metrics.resources.limits.memory".to_string(), + value: "128Mi".to_string(), + }, + ChartSetValue { + key: "kube-state-metrics.resources.requests.memory".to_string(), + value: "128Mi".to_string(), + }, + // Limits prometheus-node-exporter + ChartSetValue { + key: "prometheus-node-exporter.resources.limits.cpu".to_string(), + value: "20m".to_string(), + }, + ChartSetValue { + key: "prometheus-node-exporter.resources.requests.cpu".to_string(), + value: "10m".to_string(), + }, + ChartSetValue { + key: "prometheus-node-exporter.resources.limits.memory".to_string(), + value: "32Mi".to_string(), + }, + ChartSetValue { + key: "prometheus-node-exporter.resources.requests.memory".to_string(), + value: "32Mi".to_string(), + }, + // Limits kube-state-metrics + ChartSetValue { + key: "kube-state-metrics.resources.limits.cpu".to_string(), + value: "30m".to_string(), + }, + ChartSetValue { + key: "kube-state-metrics.resources.requests.cpu".to_string(), + value: "10m".to_string(), + }, + ChartSetValue { + key: "kube-state-metrics.resources.limits.memory".to_string(), + value: "128Mi".to_string(), + }, + ChartSetValue { + key: "kube-state-metrics.resources.requests.memory".to_string(), + value: "128Mi".to_string(), + }, + // resources limits + ChartSetValue { + key: "prometheusOperator.resources.limits.cpu".to_string(), + value: "1".to_string(), + }, + ChartSetValue { + key: "prometheusOperator.resources.requests.cpu".to_string(), + value: "500m".to_string(), + }, + ChartSetValue { + key: "prometheusOperator.resources.limits.memory".to_string(), + value: "1Gi".to_string(), + }, + ChartSetValue { + key: "prometheusOperator.resources.requests.memory".to_string(), + value: "1Gi".to_string(), + }, + ], + ..Default::default() + }, + }; + if &qovery_terraform_config.test_cluster == "true" { + prometheus_operator.chart_info.values.push(ChartSetValue { + key: "defaultRules.config".to_string(), + value: "{}".to_string(), + }) + } + + let prometheus_adapter = CommonChart { + chart_info: ChartInfo { + name: "prometheus-adapter".to_string(), + path: "common/charts/prometheus-adapter".to_string(), + namespace: HelmChartNamespaces::Logging, + values: vec![ + ChartSetValue { + key: "metricsRelistInterval".to_string(), + value: "30s".to_string(), + }, + ChartSetValue { + key: "prometheus.url".to_string(), + value: format!( + "http://prometheus-operated.{}.svc", + get_chart_namespace(prometheus_namespace) + ), + }, + ChartSetValue { + key: "podDisruptionBudget.enabled".to_string(), + value: "true".to_string(), + }, + ChartSetValue { + key: "podDisruptionBudget.maxUnavailable".to_string(), + value: "1".to_string(), + }, + // resources limits + ChartSetValue { + key: "resources.limits.cpu".to_string(), + value: "100m".to_string(), + }, + ChartSetValue { + key: "resources.requests.cpu".to_string(), + value: "100m".to_string(), + }, + ChartSetValue { + key: "resources.limits.memory".to_string(), + value: "128Mi".to_string(), + }, + ChartSetValue { + key: "resources.requests.memory".to_string(), + value: "128Mi".to_string(), + }, + ], + ..Default::default() + }, + }; + + let metric_server = CommonChart { + chart_info: ChartInfo { + name: "metrics-server".to_string(), + path: "common/charts/metrics-server".to_string(), + values: vec![ + ChartSetValue { + key: "resources.limits.cpu".to_string(), + value: "250m".to_string(), + }, + ChartSetValue { + key: "resources.requests.cpu".to_string(), + value: "250m".to_string(), + }, + ChartSetValue { + key: "resources.limits.memory".to_string(), + value: "256Mi".to_string(), + }, + ChartSetValue { + key: "resources.requests.memory".to_string(), + value: "256Mi".to_string(), + }, + ], + ..Default::default() + }, + }; + + // todo: add custom datasource to values_file + let grafana = CommonChart { + chart_info: ChartInfo { + name: "grafana".to_string(), + path: "common/charts/grafana".to_string(), + namespace: prometheus_namespace, + values_files: vec!["chart_values/grafana.yaml".to_string()], + ..Default::default() + }, + }; + + let cert_manager = CommonChart { + chart_info: ChartInfo { + name: "cert-manager".to_string(), + path: "common/charts/cert-manager".to_string(), + namespace: HelmChartNamespaces::CertManager, + values_files: vec!["chart_values/cert-manager.yaml".to_string()], + values: vec![ + ChartSetValue { + key: "installCRDs".to_string(), + value: "true".to_string(), + }, + ChartSetValue { + key: "replicaCount".to_string(), + value: "2".to_string(), + }, + // https://cert-manager.io/docs/configuration/acme/dns01/#setting-nameservers-for-dns01-self-check + ChartSetValue { + key: "extraArgs".to_string(), + value: "{--dns01-recursive-nameservers-only,--dns01-recursive-nameservers=1.1.1.1:53\\,8.8.8.8:53}" + .to_string(), + }, + ChartSetValue { + key: "prometheus.servicemonitor.enabled".to_string(), + value: qovery_terraform_config.feature_flag_metrics_history.clone(), + }, + ChartSetValue { + key: "prometheus.servicemonitor.prometheusInstance".to_string(), + value: "qovery".to_string(), + }, + // resources limits + ChartSetValue { + key: "resources.limits.cpu".to_string(), + value: "200m".to_string(), + }, + ChartSetValue { + key: "resources.requests.cpu".to_string(), + value: "100m".to_string(), + }, + ChartSetValue { + key: "resources.limits.memory".to_string(), + value: "1Gi".to_string(), + }, + ChartSetValue { + key: "resources.requests.memory".to_string(), + value: "1Gi".to_string(), + }, + // Webhooks resources limits + ChartSetValue { + key: "webhook.resources.limits.cpu".to_string(), + value: "20m".to_string(), + }, + ChartSetValue { + key: "webhook.resources.requests.cpu".to_string(), + value: "20m".to_string(), + }, + ChartSetValue { + key: "webhook.resources.limits.memory".to_string(), + value: "128Mi".to_string(), + }, + ChartSetValue { + key: "webhook.resources.requests.memory".to_string(), + value: "128Mi".to_string(), + }, + // Cainjector resources limits + ChartSetValue { + key: "cainjector.resources.limits.cpu".to_string(), + value: "500m".to_string(), + }, + ChartSetValue { + key: "cainjector.resources.requests.cpu".to_string(), + value: "100m".to_string(), + }, + ChartSetValue { + key: "cainjector.resources.limits.memory".to_string(), + value: "1Gi".to_string(), + }, + ChartSetValue { + key: "cainjector.resources.requests.memory".to_string(), + value: "1Gi".to_string(), + }, + ], + ..Default::default() + }, + }; + + let mut cert_manager_config = CommonChart { + chart_info: ChartInfo { + name: "cert-manager-configs".to_string(), + path: "common/charts/cert-manager-configs".to_string(), + namespace: HelmChartNamespaces::CertManager, + values: vec![ + ChartSetValue { + key: "externalDnsProvider".to_string(), + value: qovery_terraform_config.external_dns_provider.clone(), + }, + ChartSetValue { + key: "acme.letsEncrypt.emailReport".to_string(), + value: qovery_terraform_config.dns_email_report, + }, + ChartSetValue { + key: "acme.letsEncrypt.acmeUrl".to_string(), + value: qovery_terraform_config.acme_server_url, + }, + ChartSetValue { + key: "managedDns".to_string(), + value: qovery_terraform_config.managed_dns_domains_terraform_format, + }, + ], + ..Default::default() + }, + }; + if &qovery_terraform_config.external_dns_provider == "cloudflare" { + cert_manager_config.chart_info.values.push(ChartSetValue { + key: "cloudflare_api_token".to_string(), + value: qovery_terraform_config.cloudflare_api_token, + }); + cert_manager_config.chart_info.values.push(ChartSetValue { + key: "cloudflare_email".to_string(), + value: qovery_terraform_config.cloudflare_email, + }) + } + + let nginx_ingress = CommonChart { + chart_info: ChartInfo { + name: "nginx-ingress".to_string(), + path: "common/charts/nginx-ingress".to_string(), + namespace: HelmChartNamespaces::NginxIngress, + // Because of NLB, svc can take some time to start + timeout: "300".to_string(), + values_files: vec!["chart_values/nginx-ingress.yaml".to_string()], + values: vec![ + // Controller resources limits + ChartSetValue { + key: "controller.resources.limits.cpu".to_string(), + value: "200m".to_string(), + }, + ChartSetValue { + key: "controller.resources.requests.cpu".to_string(), + value: "100m".to_string(), + }, + ChartSetValue { + key: "controller.resources.limits.memory".to_string(), + value: "768Mi".to_string(), + }, + ChartSetValue { + key: "controller.resources.requests.memory".to_string(), + value: "768Mi".to_string(), + }, + // Default backend resources limits + ChartSetValue { + key: "defaultBackend.resources.limits.cpu".to_string(), + value: "20m".to_string(), + }, + ChartSetValue { + key: "defaultBackend.resources.requests.cpu".to_string(), + value: "10m".to_string(), + }, + ChartSetValue { + key: "defaultBackend.resources.limits.memory".to_string(), + value: "32Mi".to_string(), + }, + ChartSetValue { + key: "defaultBackend.resources.requests.memory".to_string(), + value: "32Mi".to_string(), + }, + ], + ..Default::default() + }, + }; + + // todo: add missing parameters + let pleco = CommonChart { + chart_info: ChartInfo { + name: "pleco".to_string(), + path: "common/charts/pleco".to_string(), + values: vec![ + ChartSetValue { + key: "environmentVariables.AWS_ACCESS_KEY_ID".to_string(), + value: qovery_terraform_config.aws_access_key_id, + }, + ChartSetValue { + key: "environmentVariables.AWS_SECRET_ACCESS_KEY".to_string(), + value: qovery_terraform_config.aws_secret_access_key, + }, + ChartSetValue { + key: "environmentVariables.LOG_LEVEL".to_string(), + value: "debug".to_string(), + }, + ], + ..Default::default() + }, + }; + + let qovery_agent = CommonChart { + chart_info: ChartInfo { + name: "qovery-agent".to_string(), + path: "common/charts/qovery-agent".to_string(), + namespace: HelmChartNamespaces::Qovery, + values: vec![ + // todo: directly get version from the engine, not from terraform helper + ChartSetValue { + key: "image.tag".to_string(), + value: qovery_terraform_config.qovery_agent_version, + }, + ChartSetValue { + key: "replicaCount".to_string(), + value: "1".to_string(), + }, + ChartSetValue { + key: "environmentVariables.NATS_HOST_URL".to_string(), + value: qovery_terraform_config.nats_host_url.clone(), + }, + ChartSetValue { + key: "environmentVariables.NATS_USERNAME".to_string(), + value: qovery_terraform_config.nats_username.clone(), + }, + ChartSetValue { + key: "environmentVariables.NATS_PASSWORD".to_string(), + value: qovery_terraform_config.nats_password.clone(), + }, + ChartSetValue { + key: "environmentVariables.LOKI_URL".to_string(), + value: format!( + "http://{}.{}.svc.cluster.local:3100", + loki_service_name, + get_chart_namespace(loki_namespace) + ), + }, + ChartSetValue { + key: "environmentVariables.CLOUD_REGION".to_string(), + value: qovery_terraform_config.region.clone(), + }, + ChartSetValue { + key: "environmentVariables.CLOUD_PROVIDER".to_string(), + value: qovery_terraform_config.cloud_provider.clone(), + }, + ChartSetValue { + key: "environmentVariables.KUBERNETES_ID".to_string(), + value: qovery_terraform_config.cluster_id, + }, + // resources limits + ChartSetValue { + key: "resources.limits.cpu".to_string(), + value: "1".to_string(), + }, + ChartSetValue { + key: "resources.requests.cpu".to_string(), + value: "200m".to_string(), + }, + ChartSetValue { + key: "resources.limits.memory".to_string(), + value: "500Mi".to_string(), + }, + ChartSetValue { + key: "resources.requests.memory".to_string(), + value: "500Mi".to_string(), + }, + ], + ..Default::default() + }, + }; + + let qovery_engine = CommonChart { + chart_info: ChartInfo { + name: "qovery-engine".to_string(), + path: "common/charts/qovery-engine".to_string(), + namespace: HelmChartNamespaces::Qovery, + values: vec![ + // todo: directly get version from the engine, not from terraform + ChartSetValue { + key: "image.tag".to_string(), + value: qovery_terraform_config.qovery_engine_version, + }, + // need kubernetes 1.18, should be well tested before activating it + ChartSetValue { + key: "autoscaler.enabled".to_string(), + value: "false".to_string(), + }, + ChartSetValue { + key: "metrics.enabled".to_string(), + value: "true".to_string(), + }, + ChartSetValue { + key: "volumes.storageClassName".to_string(), + value: "aws-ebs-gp2-0".to_string(), + }, + ChartSetValue { + key: "environmentVariables.NATS_HOST_URL".to_string(), + value: qovery_terraform_config.nats_host_url, + }, + ChartSetValue { + key: "environmentVariables.NATS_USERNAME".to_string(), + value: qovery_terraform_config.nats_username, + }, + ChartSetValue { + key: "environmentVariables.NATS_PASSWORD".to_string(), + value: qovery_terraform_config.nats_password, + }, + ChartSetValue { + key: "environmentVariables.ORGANIZATION".to_string(), + value: qovery_terraform_config.organization_id, + }, + ChartSetValue { + key: "environmentVariables.CLOUD_PROVIDER".to_string(), + value: qovery_terraform_config.cloud_provider, + }, + ChartSetValue { + key: "environmentVariables.REGION".to_string(), + value: qovery_terraform_config.region, + }, + ChartSetValue { + key: "environmentVariables.LIB_ROOT_DIR".to_string(), + value: "/home/qovery/lib".to_string(), + }, + ChartSetValue { + key: "environmentVariables.DOCKER_HOST".to_string(), + value: "tcp://0.0.0.0:2375".to_string(), + }, + // engine resources limits + ChartSetValue { + key: "resources.limits.cpu".to_string(), + value: "1".to_string(), + }, + ChartSetValue { + key: "resources.requests.cpu".to_string(), + value: "500m".to_string(), + }, + ChartSetValue { + key: "resources.limits.memory".to_string(), + value: "512Mi".to_string(), + }, + ChartSetValue { + key: "resources.requests.memory".to_string(), + value: "512Mi".to_string(), + }, + // build resources limits + ChartSetValue { + key: "resources.limits.cpu".to_string(), + value: "1".to_string(), + }, + ChartSetValue { + key: "resources.requests.cpu".to_string(), + value: "500m".to_string(), + }, + ChartSetValue { + key: "resources.limits.memory".to_string(), + value: "4Gi".to_string(), + }, + ChartSetValue { + key: "resources.requests.memory".to_string(), + value: "4Gi".to_string(), + }, + ], + ..Default::default() + }, + }; + + // chart deployment order matters!!! + let level_1: Vec> = vec![ + Box::new(q_storage_class), + Box::new(coredns_config), + Box::new(aws_vpc_cni_chart), + ]; + + let mut level_2: Vec> = vec![]; + + let mut level_3: Vec> = vec![ + Box::new(cluster_autoscaler), + Box::new(aws_iam_eks_user_mapper), + Box::new(aws_calico), + ]; + + let mut level_4: Vec> = vec![ + Box::new(metric_server), + Box::new(aws_node_term_handler), + Box::new(external_dns), + ]; + + let level_5: Vec> = vec![Box::new(nginx_ingress), Box::new(cert_manager), Box::new(pleco)]; + + let mut level_6: Vec> = vec![ + Box::new(cert_manager_config), + Box::new(qovery_agent), + Box::new(qovery_engine), + ]; + + if &qovery_terraform_config.feature_flag_metrics_history == "true" { + level_2.push(Box::new(prometheus_operator)); + level_4.push(Box::new(prometheus_adapter)); + } + if &qovery_terraform_config.feature_flag_log_history == "true" { + level_3.push(Box::new(promtail)); + level_4.push(Box::new(loki)); + } + + if &qovery_terraform_config.feature_flag_metrics_history == "true" + || &qovery_terraform_config.feature_flag_log_history == "true" + { + level_6.push(Box::new(grafana)) + }; + + Ok(vec![level_1, level_2, level_3, level_4, level_5, level_6]) +} + +// AWS CNI + +#[derive(Default)] +pub struct AwsVpcCniChart { + pub chart_info: ChartInfo, +} + +impl HelmChart for AwsVpcCniChart { + fn get_chart_info(&self) -> &ChartInfo { + &self.chart_info + } + + fn pre_exec(&self, kubernetes_config: &Path, envs: &[(String, String)]) -> Result<(), SimpleError> { + let kinds = vec!["daemonSet", "clusterRole", "clusterRoleBinding", "serviceAccount"]; + let mut environment_variables: Vec<(&str, &str)> = envs.iter().map(|x| (x.0.as_str(), x.1.as_str())).collect(); + environment_variables.push(("KUBECONFIG", kubernetes_config.to_str().unwrap())); + + match self.enable_cni_managed_by_helm(kubernetes_config, envs) { + true => { + info!("Enabling AWS CNI support by Helm"); + + for kind in kinds { + info!("setting annotations and labels on {}/aws-node", &kind); + kubectl_exec_with_output( + vec![ + "-n", + "kube-system", + "annotate", + "--overwrite", + kind, + "aws-node", + format!("meta.helm.sh/release-name={}", self.chart_info.name).as_str(), + ], + environment_variables.clone(), + |_| {}, + |_| {}, + )?; + kubectl_exec_with_output( + vec![ + "-n", + "kube-system", + "annotate", + "--overwrite", + kind, + "aws-node", + "meta.helm.sh/release-namespace=kube-system", + ], + environment_variables.clone(), + |_| {}, + |_| {}, + )?; + kubectl_exec_with_output( + vec![ + "-n", + "kube-system", + "label", + "--overwrite", + kind, + "aws-node", + "app.kubernetes.io/managed-by=Helm", + ], + environment_variables.clone(), + |_| {}, + |_| {}, + )? + } + + info!("AWS CNI successfully deployed") + } + false => info!("AWS CNI is already supported by Helm, nothing to do"), + }; + + Ok(()) + } +} + +impl AwsVpcCniChart { + fn enable_cni_managed_by_helm(&self, kubernetes_config: &Path, envs: &[(String, String)]) -> bool { + let environment_variables = envs.iter().map(|x| (x.0.as_str(), x.1.as_str())).collect(); + + match kubectl_exec_get_daemonset( + kubernetes_config, + &self.chart_info.name, + self.namespace().as_str(), + Some("k8s-app=aws-node,app.kubernetes.io/managed-by=Helm"), + environment_variables, + ) { + Ok(_) => true, + Err(_) => false, + } + } +} diff --git a/src/cloud_provider/aws/kubernetes/mod.rs b/src/cloud_provider/aws/kubernetes/mod.rs index 18446eb4..a7cd0572 100644 --- a/src/cloud_provider/aws/kubernetes/mod.rs +++ b/src/cloud_provider/aws/kubernetes/mod.rs @@ -40,6 +40,7 @@ use crate::object_storage::s3::S3; use crate::object_storage::ObjectStorage; use crate::string::terraform_list_format; +pub mod helm_charts; pub mod node; pub mod roles; diff --git a/src/cloud_provider/helm.rs b/src/cloud_provider/helm.rs new file mode 100644 index 00000000..cb4a1c60 --- /dev/null +++ b/src/cloud_provider/helm.rs @@ -0,0 +1,205 @@ +use crate::cloud_provider::helm::HelmAction::Deploy; +use crate::cloud_provider::helm::HelmChartNamespaces::KubeSystem; +use crate::cmd::helm::{helm_exec_uninstall_with_chart_info, helm_exec_upgrade_with_chart_info}; +use crate::cmd::kubectl::kubectl_exec_rollout_restart_deployment; +use crate::error::{SimpleError, SimpleErrorKind}; +use std::path::Path; +use std::{fs, thread}; +use thread::spawn; + +#[derive(Clone)] +pub enum HelmAction { + Deploy, + Destroy, + Skip, +} + +#[derive(Copy, Clone)] +pub enum HelmChartNamespaces { + KubeSystem, + Prometheus, + Logging, + CertManager, + NginxIngress, + Qovery, +} + +#[derive(Clone)] +pub struct ChartSetValue { + pub key: String, + pub value: String, +} + +#[derive(Clone)] +pub struct ChartInfo { + pub name: String, + pub path: String, + pub namespace: HelmChartNamespaces, + pub action: HelmAction, + pub atomic: bool, + pub force_upgrade: bool, + pub timeout: String, + pub dry_run: bool, + pub wait: bool, + pub values: Vec, + pub values_files: Vec, +} + +impl Default for ChartInfo { + fn default() -> ChartInfo { + ChartInfo { + name: "undefined".to_string(), + path: "undefined".to_string(), + namespace: KubeSystem, + action: Deploy, + atomic: true, + force_upgrade: false, + timeout: "300s".to_string(), + dry_run: false, + wait: true, + values: Vec::new(), + values_files: Vec::new(), + } + } +} + +pub fn get_chart_namespace(namespace: HelmChartNamespaces) -> String { + match namespace { + HelmChartNamespaces::KubeSystem => "kube-system", + HelmChartNamespaces::Prometheus => "prometheus", + HelmChartNamespaces::Logging => "logging", + HelmChartNamespaces::CertManager => "cert-manager", + HelmChartNamespaces::NginxIngress => "nginx-ingress", + HelmChartNamespaces::Qovery => "qovery", + } + .to_string() +} + +pub trait HelmChart { + fn check_prerequisites(&self) -> Result<(), SimpleError> { + let chart = self.get_chart_info(); + for file in chart.values_files.iter() { + match fs::metadata(file) { + Ok(_) => {} + Err(e) => { + return Err(SimpleError { + kind: SimpleErrorKind::Other, + message: Some(format!( + "Can't access helm chart override file {} for chart {}. {:?}", + file, chart.name, e + )), + }) + } + } + } + Ok(()) + } + + fn get_chart_info(&self) -> &ChartInfo; + + fn namespace(&self) -> String { + get_chart_namespace(self.get_chart_info().namespace) + } + + fn pre_exec(&self, _kubernetes_config: &Path, _envs: &[(String, String)]) -> Result<(), SimpleError> { + // + Ok(()) + } + + fn run(&self, kubernetes_config: &Path, envs: &[(String, String)]) -> Result<(), SimpleError> { + self.check_prerequisites()?; + self.pre_exec(&kubernetes_config, &envs)?; + match self.exec(&kubernetes_config, &envs) { + Ok(_) => {} + Err(e) => { + error!("Error while deploying chart: {:?}", e.message); + return self.on_deploy_failure(&kubernetes_config, &envs); + } + }; + self.post_exec(&kubernetes_config, &envs)?; + Ok(()) + } + + fn exec(&self, kubernetes_config: &Path, envs: &[(String, String)]) -> Result<(), SimpleError> { + let environment_variables = envs.iter().map(|x| (x.0.as_str(), x.1.as_str())).collect(); + match self.get_chart_info().action { + HelmAction::Deploy => { + helm_exec_upgrade_with_chart_info(kubernetes_config, &environment_variables, self.get_chart_info()) + } + HelmAction::Destroy => { + helm_exec_uninstall_with_chart_info(kubernetes_config, &environment_variables, self.get_chart_info()) + } + HelmAction::Skip => Ok(()), + } + } + + fn post_exec(&self, _kubernetes_config: &Path, _envs: &[(String, String)]) -> Result<(), SimpleError> { + Ok(()) + } + fn on_deploy_failure(&self, _kubernetes_config: &Path, _envs: &[(String, String)]) -> Result<(), SimpleError> { + Ok(()) + } +} + +//todo: implement it +#[allow(unused_must_use)] +pub fn deploy_multiple_charts( + kubernetes_config: &'static Path, + envs: &Vec<(String, String)>, + charts: Vec, +) { + let mut handles = vec![]; + + for chart in charts.into_iter() { + let environment_variables = envs.clone(); + let kubeconfig = kubernetes_config.clone(); + let handle = spawn(move || chart.run(kubeconfig, &environment_variables)); + handles.push(handle); + } + + for handle in handles { + handle.join().unwrap(); + } +} + +// +// Common charts +// + +#[derive(Default)] +pub struct CommonChart { + pub chart_info: ChartInfo, +} + +impl CommonChart {} + +impl HelmChart for CommonChart { + fn get_chart_info(&self) -> &ChartInfo { + &self.chart_info + } +} + +// CoreDNS config + +#[derive(Default)] +pub struct CoreDNSConfigChart { + pub chart_info: ChartInfo, +} + +impl HelmChart for CoreDNSConfigChart { + fn get_chart_info(&self) -> &ChartInfo { + &self.chart_info + } + + // todo: it would be better to avoid rebooting coredns on every run + fn post_exec(&self, kubernetes_config: &Path, envs: &[(String, String)]) -> Result<(), SimpleError> { + let environment_variables = envs.iter().map(|x| (x.0.as_str(), x.1.as_str())).collect(); + + kubectl_exec_rollout_restart_deployment( + kubernetes_config, + &self.chart_info.name, + self.namespace().as_str(), + environment_variables, + ) + } +} diff --git a/src/cloud_provider/mod.rs b/src/cloud_provider/mod.rs index c8d0d4e2..d855cba9 100644 --- a/src/cloud_provider/mod.rs +++ b/src/cloud_provider/mod.rs @@ -11,6 +11,7 @@ pub mod aws; pub mod digitalocean; pub mod environment; pub mod gcp; +pub mod helm; pub mod kubernetes; pub mod metrics; pub mod models; diff --git a/src/cmd/helm.rs b/src/cmd/helm.rs index 523c620b..ae99a111 100644 --- a/src/cmd/helm.rs +++ b/src/cmd/helm.rs @@ -3,6 +3,7 @@ use std::path::Path; use tracing::{error, info, span, Level}; +use crate::cloud_provider::helm::{get_chart_namespace, ChartInfo}; use crate::cmd::structs::{Helm, HelmChart, HelmHistoryRow}; use crate::cmd::utilities::exec_with_envs_and_output; use crate::error::{SimpleError, SimpleErrorKind}; @@ -57,6 +58,97 @@ where .map(|helm_history_row| helm_history_row.clone())) } +pub fn helm_exec_upgrade_with_chart_info

( + kubernetes_config: P, + envs: &Vec<(&str, &str)>, + chart: &ChartInfo, +) -> Result<(), SimpleError> +where + P: AsRef, +{ + let mut args_string: Vec = vec![ + "upgrade", + "-o", + "json", + "--kubeconfig", + kubernetes_config.as_ref().to_str().unwrap(), + "--create-namespace", + "--install", + "--history-max", + "50", + "--namespace", + get_chart_namespace(chart.namespace).as_str(), + ] + .into_iter() + .map(|x| x.to_string()) + .collect(); + + // warn: don't add debug or json output won't work + if chart.atomic { + args_string.push("--atomic".to_string()) + } + if chart.force_upgrade { + args_string.push("--force".to_string()) + } + if chart.dry_run { + args_string.push("--dry-run".to_string()) + } + if chart.wait { + args_string.push("--wait".to_string()) + } + + // overrides and files overrides + for value in &chart.values { + args_string.push("--set".to_string()); + args_string.push(format!("{}={}", value.key, value.value)); + } + for value_file in &chart.values_files { + args_string.push("-f".to_string()); + args_string.push(value_file.clone()); + } + + // add last elements + args_string.push(chart.name.to_string()); + args_string.push(chart.path.to_string()); + + let args = args_string.iter().map(|x| x.as_str()).collect(); + + let mut json_output_string = String::new(); + let mut error_message = String::new(); + match helm_exec_with_output( + args, + envs.clone(), + |out| match out { + Ok(line) => json_output_string = line, + Err(err) => error!("{:?}", err), + }, + |out| match out { + Ok(line) => { + // helm errors are not json formatted unfortunately + if line.contains("has been rolled back") { + error_message = format!("Deployment {} has been rolled back", chart.name); + warn!("{}. {}", &error_message, &line); + } else if line.contains("has been uninstalled") { + error_message = format!("Deployment {} has been uninstalled due to failure", chart.name); + warn!("{}. {}", &error_message, &line); + } else { + error_message = format!("Deployment {} has failed", chart.name); + warn!("{}. {}", &error_message, &line); + } + } + Err(err) => error!("{:?}", err), + }, + ) { + Ok(_) => Ok(()), + Err(e) => { + return Err(SimpleError { + kind: SimpleErrorKind::Other, + message: Some(format!("{}. {:?}", error_message, e.message)), + }) + } + } +} + pub fn helm_exec_upgrade

( kubernetes_config: P, namespace: &str, @@ -105,6 +197,35 @@ where ) } +pub fn helm_exec_uninstall_with_chart_info

( + kubernetes_config: P, + envs: &Vec<(&str, &str)>, + chart: &ChartInfo, +) -> Result<(), SimpleError> +where + P: AsRef, +{ + helm_exec_with_output( + vec![ + "uninstall", + "--kubeconfig", + kubernetes_config.as_ref().to_str().unwrap(), + "--namespace", + get_chart_namespace(chart.namespace).as_str(), + &chart.name, + ], + envs.clone(), + |out| match out { + Ok(line) => info!("{}", line.as_str()), + Err(err) => error!("{}", err), + }, + |out| match out { + Ok(line) => error!("{}", line.as_str()), + Err(err) => error!("{}", err), + }, + ) +} + pub fn helm_exec_uninstall

( kubernetes_config: P, namespace: &str, diff --git a/src/cmd/kubectl.rs b/src/cmd/kubectl.rs index 01cfd90f..603bb73e 100644 --- a/src/cmd/kubectl.rs +++ b/src/cmd/kubectl.rs @@ -697,6 +697,57 @@ where kubectl_exec::(vec!["version", "-o", "json"], kubernetes_config, envs) } +pub fn kubectl_exec_get_daemonset

( + kubernetes_config: P, + name: &str, + namespace: &str, + selectors: Option<&str>, + envs: Vec<(&str, &str)>, +) -> Result, SimpleError> +where + P: AsRef, +{ + let mut args = vec!["-n", namespace, "get", "daemonset", name]; + match selectors { + Some(x) => { + args.push("-l"); + args.push(x); + } + None => {} + }; + args.push("-o"); + args.push("json"); + + kubectl_exec::>(args, kubernetes_config, envs) +} + +pub fn kubectl_exec_rollout_restart_deployment

( + kubernetes_config: P, + name: &str, + namespace: &str, + envs: Vec<(&str, &str)>, +) -> Result<(), SimpleError> +where + P: AsRef, +{ + let mut environment_variables: Vec<(&str, &str)> = envs; + environment_variables.push(("KUBECONFIG", kubernetes_config.as_ref().to_str().unwrap())); + let args = vec!["-n", namespace, "rollout", "restart", "deployment", name]; + + kubectl_exec_with_output( + args, + environment_variables.clone(), + |out| match out { + Ok(line) => info!("{}", line), + Err(err) => error!("{:?}", err), + }, + |out| match out { + Ok(line) => error!("{}", line), + Err(err) => error!("{:?}", err), + }, + ) +} + pub fn kubectl_exec_get_node

( kubernetes_config: P, envs: Vec<(&str, &str)>, diff --git a/src/cmd/structs.rs b/src/cmd/structs.rs index 7d881315..a700ce5b 100644 --- a/src/cmd/structs.rs +++ b/src/cmd/structs.rs @@ -63,6 +63,15 @@ pub struct Metadata { pub uid: String, } +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Daemonset { + pub api_version: String, + pub items: Vec, + pub kind: String, + pub metadata: Metadata, +} + #[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Hash)] #[serde(rename_all = "camelCase")] pub struct KubernetesServiceStatus { diff --git a/src/template.rs b/src/template.rs index a48faf79..a1a91005 100644 --- a/src/template.rs +++ b/src/template.rs @@ -42,6 +42,8 @@ where tera::ErrorKind::CallFilter(x) => format!("call filter: {}", x), tera::ErrorKind::CallTest(x) => format!("call test: {}", x), tera::ErrorKind::__Nonexhaustive => "non exhaustive error".to_string(), + tera::ErrorKind::Io(x) => format!("io error {:?}", x), + tera::ErrorKind::Utf8Conversion { .. } => format!("utf-8 conversion issue"), }; error!("{}", context.clone().into_json()); diff --git a/test_utilities/Cargo.lock b/test_utilities/Cargo.lock index 744a5275..3dca1d4c 100644 --- a/test_utilities/Cargo.lock +++ b/test_utilities/Cargo.lock @@ -941,9 +941,9 @@ dependencies = [ [[package]] name = "globwalk" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "178270263374052c40502e9f607134947de75302c1348d1a0e31db67c1691446" +checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" dependencies = [ "bitflags", "ignore", @@ -2115,6 +2115,18 @@ dependencies = [ "rand_hc 0.2.0", ] +[[package]] +name = "rand" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +dependencies = [ + "libc", + "rand_chacha 0.3.0", + "rand_core 0.6.2", + "rand_hc 0.3.0", +] + [[package]] name = "rand_chacha" version = "0.1.1" @@ -2135,6 +2147,16 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rand_chacha" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.2", +] + [[package]] name = "rand_core" version = "0.3.1" @@ -2159,6 +2181,15 @@ dependencies = [ "getrandom 0.1.16", ] +[[package]] +name = "rand_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +dependencies = [ + "getrandom 0.2.2", +] + [[package]] name = "rand_hc" version = "0.1.0" @@ -2177,6 +2208,15 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rand_hc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" +dependencies = [ + "rand_core 0.6.2", +] + [[package]] name = "rand_isaac" version = "0.1.1" @@ -3012,9 +3052,9 @@ dependencies = [ [[package]] name = "tera" -version = "1.5.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1381c83828bedd5ce4e59473110afa5381ffe523406d9ade4b77c9f7be70ff9a" +checksum = "81060acb882480c8793782eb96bc86f5c83d2fc7175ad46c375c6956ef7afa62" dependencies = [ "chrono", "chrono-tz", @@ -3024,7 +3064,7 @@ dependencies = [ "percent-encoding 2.1.0", "pest", "pest_derive", - "rand 0.7.3", + "rand 0.8.3", "regex", "serde", "serde_json", diff --git a/tests/aws/aws_environment.rs b/tests/aws/aws_environment.rs index b2852718..512f00ba 100644 --- a/tests/aws/aws_environment.rs +++ b/tests/aws/aws_environment.rs @@ -559,6 +559,7 @@ fn deploy_a_not_working_environment_and_after_working_environment() { // #[cfg(feature = "test-aws-self-hosted")] // #[test] +#[allow(dead_code)] // todo: make it work fn deploy_ok_fail_fail_ok_environment() { init(); diff --git a/tests/aws/aws_kubernetes.rs b/tests/aws/aws_kubernetes.rs index 60406685..0518e3eb 100644 --- a/tests/aws/aws_kubernetes.rs +++ b/tests/aws/aws_kubernetes.rs @@ -236,6 +236,7 @@ fn create_and_destroy_eks_cluster_in_us_east_2() { // only enable this test manually when we want to perform and validate upgrade process //#[test] +#[allow(dead_code)] fn create_upgrade_and_destroy_eks_cluster_in_eu_west_3() { let region = "eu-west-3"; let secrets = FuncTestsSecrets::new();