mirror of
https://github.com/typeable/octopod.git
synced 2024-09-11 14:56:38 +03:00
New control scripts (#108)
* add app and deployment overrides info scripts * overrides/keys scripts * add new scripts to the chart config * archive using scaling * archive check script + README * fix timings values + up contolscripts version * Get rid of kubectl calls * remove tags * remove status mode * rename tag_check to config_check * remove default values logic, optional name, additional checks at helm init * bump chart and app version * add keys sorting * ingress.host to ingress.hostname hardcode * add default override for wordpress * parametrize ingress host key * add gzip static + etag * config_check: logs to stderr + proper user notifications * fix bug with empty value key not being shown * rename app-env-override and deployment-override cli options * rename env configuration for octopod
This commit is contained in:
parent
a2c8ab0915
commit
c8ac911f6b
@ -2,8 +2,8 @@ apiVersion: v2
|
|||||||
name: octopod
|
name: octopod
|
||||||
description: An opensource self-hosted solution for managing multiple deployments in a Kubernetes cluster.
|
description: An opensource self-hosted solution for managing multiple deployments in a Kubernetes cluster.
|
||||||
type: application
|
type: application
|
||||||
version: 0.5.1
|
version: 0.6.0
|
||||||
appVersion: 1.3.1
|
appVersion: 1.4
|
||||||
keywords:
|
keywords:
|
||||||
- kubernetes
|
- kubernetes
|
||||||
- octopod
|
- octopod
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
{{- $octopodAppAuthPassword := include "octopodUiAuthSecret" . -}}
|
{{- $octopodAppAuthPassword := include "octopodUiAuthSecret" . -}}
|
||||||
|
{{- $etag := sha256sum (now | date "Mon Jan 2 15:04:05 MSK 2021") -}}
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ConfigMap
|
kind: ConfigMap
|
||||||
metadata:
|
metadata:
|
||||||
@ -14,11 +15,10 @@ data:
|
|||||||
index index.html;
|
index index.html;
|
||||||
error_page 404 =200 /index.html;
|
error_page 404 =200 /index.html;
|
||||||
charset utf-8;
|
charset utf-8;
|
||||||
gzip on;
|
location ~* \.(html|css|js|xml)$ {
|
||||||
gzip_disable msie6;
|
gzip_static on;
|
||||||
gzip_buffers 32 4k;
|
add_header 'ETag' '{{ $etag }}';
|
||||||
gzip_comp_level 3;
|
}
|
||||||
gzip_types text/plain text/css application/json application/x-javascript application/javascript text/xml application/xml application/rss+xml text/javascript image/svg+xml application/vnd.ms-f ontobject application/x-font-ttf font/opentype;
|
|
||||||
}
|
}
|
||||||
config.json: |
|
config.json: |
|
||||||
{
|
{
|
||||||
|
@ -16,8 +16,13 @@ data:
|
|||||||
CHECKING_COMMAND: {{ printf "%s/check" (include "controlScriptsPath" .) | quote }}
|
CHECKING_COMMAND: {{ printf "%s/check" (include "controlScriptsPath" .) | quote }}
|
||||||
CLEANUP_COMMAND: {{ printf "%s/cleanup" (include "controlScriptsPath" .) | quote }}
|
CLEANUP_COMMAND: {{ printf "%s/cleanup" (include "controlScriptsPath" .) | quote }}
|
||||||
ARCHIVE_CHECKING_COMMAND: {{ printf "%s/archive_check" (include "controlScriptsPath" .) | quote }}
|
ARCHIVE_CHECKING_COMMAND: {{ printf "%s/archive_check" (include "controlScriptsPath" .) | quote }}
|
||||||
CONFIG_CHECKING_COMMAND: {{ printf "%s/tag_check" (include "controlScriptsPath" .) | quote }}
|
CONFIG_CHECKING_COMMAND: {{ printf "%s/config_check" (include "controlScriptsPath" .) | quote }}
|
||||||
INFO_COMMAND: {{ printf "%s/info" (include "controlScriptsPath" .) | quote }}
|
INFO_COMMAND: {{ printf "%s/info" (include "controlScriptsPath" .) | quote }}
|
||||||
|
DEPLOYMENT_CONFIG_COMMAND: {{ printf "%s/deployment_overrides" (include "controlScriptsPath" .) | quote }}
|
||||||
|
DEPLOYMENT_KEYS_COMMAND: {{ printf "%s/deployment_keys" (include "controlScriptsPath" .) | quote }}
|
||||||
|
APPLICATION_CONFIG_COMMAND: {{ printf "%s/app_overrides" (include "controlScriptsPath" .) | quote }}
|
||||||
|
APPLICATION_KEYS_COMMAND: {{ printf "%s/app_keys" (include "controlScriptsPath" .) | quote }}
|
||||||
|
UNARCHIVE_COMMAND: {{ printf "%s/unarchive" (include "controlScriptsPath" .) | quote }}
|
||||||
{{- range $name, $value := .Values.octopod.env }}
|
{{- range $name, $value := .Values.octopod.env }}
|
||||||
{{ $name }}: {{ $value | quote }}
|
{{ $name }}: {{ $value | quote }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
@ -79,27 +79,28 @@ octopod:
|
|||||||
projectName: Octopod
|
projectName: Octopod
|
||||||
deploymentNamespace: octopod-deployment
|
deploymentNamespace: octopod-deployment
|
||||||
baseDomain: ""
|
baseDomain: ""
|
||||||
statusUpdateTimeout: 600
|
statusUpdateTimeout: "600"
|
||||||
archiveRetention: 1209600
|
archiveRetention: "1209600"
|
||||||
migrations:
|
migrations:
|
||||||
enabled: true
|
enabled: true
|
||||||
env:
|
env:
|
||||||
HELM_BIN: "/utils/helm"
|
HELM_BIN: "/utils/helm"
|
||||||
KUBECTL_BIN: "/utils/kubectl"
|
|
||||||
DEFAULTS: |
|
DEFAULTS: |
|
||||||
{
|
{
|
||||||
"chart_name": "wordpress",
|
"chart_name": "wordpress",
|
||||||
"chart_repo_name": "bitnami",
|
"chart_repo_name": "bitnami",
|
||||||
"chart_repo_url": "https://charts.bitnami.com/bitnami",
|
"chart_repo_url": "https://charts.bitnami.com/bitnami",
|
||||||
"chart_version": "12.0.0",
|
"chart_version": "12.0.0",
|
||||||
"default_overrides": []
|
"default_overrides": [
|
||||||
|
"ingress.enabled=true"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
vaultEnv: {}
|
vaultEnv: {}
|
||||||
controlScripts:
|
controlScripts:
|
||||||
image:
|
image:
|
||||||
repository: typeable/octopod-helm-control-scripts
|
repository: typeable/octopod-helm-control-scripts
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
tag: 0.1.0
|
tag: 0.2.0
|
||||||
sqitch:
|
sqitch:
|
||||||
image:
|
image:
|
||||||
repository: typeable/sqitch
|
repository: typeable/sqitch
|
||||||
|
2
helm-control-scripts/Cargo.lock
generated
2
helm-control-scripts/Cargo.lock
generated
@ -465,7 +465,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "helm-control-scripts"
|
name = "helm-control-scripts"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dkregistry",
|
"dkregistry",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "helm-control-scripts"
|
name = "helm-control-scripts"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
authors = ["Aleksei Sizov <a.sizov@typeable.io>"]
|
authors = ["Aleksei Sizov <a.sizov@typeable.io>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
@ -54,5 +54,25 @@ name = "init"
|
|||||||
path = "src/init.rs"
|
path = "src/init.rs"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "tag_check"
|
name = "config_check"
|
||||||
path = "src/tag_check.rs"
|
path = "src/config_check.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "app_overrides"
|
||||||
|
path = "src/app_overrides.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "deployment_overrides"
|
||||||
|
path = "src/deployment_overrides.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "deployment_keys"
|
||||||
|
path = "src/deployment_keys.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "app_keys"
|
||||||
|
path = "src/app_keys.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "unarchive"
|
||||||
|
path = "src/unarchive.rs"
|
||||||
|
@ -1,17 +1,13 @@
|
|||||||
FROM alpine:3
|
FROM alpine:3
|
||||||
ARG HELM_BIN=/utils/helm
|
ARG HELM_BIN=/utils/helm
|
||||||
ARG KUBECTL_BIN=/utils/kubectl
|
|
||||||
ENV HELM_BIN=$HELM_BIN
|
ENV HELM_BIN=$HELM_BIN
|
||||||
ENV KUBECTL_BIN=$KUBECTL_BIN
|
|
||||||
|
|
||||||
ADD https://get.helm.sh/helm-v3.6.0-linux-amd64.tar.gz /tmp/helm.tar.gz
|
ADD https://get.helm.sh/helm-v3.6.0-linux-amd64.tar.gz /tmp/helm.tar.gz
|
||||||
ADD https://dl.k8s.io/release/v1.21.0/bin/linux/amd64/kubectl $KUBECTL_BIN
|
|
||||||
|
|
||||||
RUN tar -xf /tmp/helm.tar.gz -C /tmp &&\
|
RUN tar -xf /tmp/helm.tar.gz -C /tmp &&\
|
||||||
mkdir -p /utils &&\
|
mkdir -p /utils &&\
|
||||||
cp /tmp/linux-amd64/helm $HELM_BIN &&\
|
cp /tmp/linux-amd64/helm $HELM_BIN &&\
|
||||||
chmod +x $HELM_BIN &&\
|
chmod +x $HELM_BIN &&\
|
||||||
chmod +x $KUBECTL_BIN &&\
|
|
||||||
rm -r /tmp/*
|
rm -r /tmp/*
|
||||||
|
|
||||||
ADD target/x86_64-unknown-linux-musl/release/archive /utils/
|
ADD target/x86_64-unknown-linux-musl/release/archive /utils/
|
||||||
@ -22,4 +18,9 @@ ADD target/x86_64-unknown-linux-musl/release/create /utils/
|
|||||||
ADD target/x86_64-unknown-linux-musl/release/info /utils/
|
ADD target/x86_64-unknown-linux-musl/release/info /utils/
|
||||||
ADD target/x86_64-unknown-linux-musl/release/update /utils/
|
ADD target/x86_64-unknown-linux-musl/release/update /utils/
|
||||||
ADD target/x86_64-unknown-linux-musl/release/init /utils/
|
ADD target/x86_64-unknown-linux-musl/release/init /utils/
|
||||||
ADD target/x86_64-unknown-linux-musl/release/tag_check /utils/
|
ADD target/x86_64-unknown-linux-musl/release/config_check /utils/
|
||||||
|
ADD target/x86_64-unknown-linux-musl/release/app_overrides /utils/
|
||||||
|
ADD target/x86_64-unknown-linux-musl/release/app_keys /utils/
|
||||||
|
ADD target/x86_64-unknown-linux-musl/release/deployment_overrides /utils/
|
||||||
|
ADD target/x86_64-unknown-linux-musl/release/deployment_keys /utils/
|
||||||
|
ADD target/x86_64-unknown-linux-musl/release/unarchive /utils/
|
||||||
|
@ -7,13 +7,18 @@ You can get pre-built docker images from [hub.docker.com/r/typeable/octopod-gene
|
|||||||
|
|
||||||
- create – a script to install a helm release
|
- create – a script to install a helm release
|
||||||
- update – a script to upgrade a helm release
|
- update – a script to upgrade a helm release
|
||||||
- archive – a script to uninstall a helm release
|
- archive – a script to scale to zero all deployments and statefulsets
|
||||||
|
- archive_check – a script to check if all resources scaled to zero correctly
|
||||||
|
- unarchive - scale all deployments and statefulsets back (right now it will only scale to 1 and not to previous value)
|
||||||
- info – a script to print comma-separated pairs which will be placed as links in the Octopod Web UI
|
- info – a script to print comma-separated pairs which will be placed as links in the Octopod Web UI
|
||||||
- cleanup – a script to delete dangling PVCs and letsencrypt certs left after `helm uninstall` command
|
- cleanup – a script to delete dangling PVCs and letsencrypt certs left after `helm uninstall` command
|
||||||
- check – a script to check if resources created by helm are healthy. Right now only deployments and statefuls sets are checked
|
- check – a script to check if resources created by helm are healthy. Right now only deployments and statefuls sets are checked
|
||||||
- archive_check – a script to check if `helm uninstall` really deleted the release
|
|
||||||
- init – a script to initialize something. This is the only script not run by Octopod, but as an init container.
|
- init – a script to initialize something. This is the only script not run by Octopod, but as an init container.
|
||||||
- tag_check – a script to check that images in helm release are present in registries before invoking create script
|
- config_check – a script to check that configuration (such as image tag name) passed to Octopod is correct. This script is invoked before deployment creation.
|
||||||
|
- app_overrides - a scirpt which returns a list of default app overrides wichh were passed in default_overrides parameter described below.
|
||||||
|
- deployment_overrides - a scirpt which returns a list of default deployment overrides from default paramaters option.
|
||||||
|
- deployment_keys - a scripts which returns a list of the possible deployment overrides keys user can use.
|
||||||
|
- app_keys - a scripts which returns a list of the possible app overrides keys. These are parsed from an output of the `helm show values` command.
|
||||||
|
|
||||||
### Parameters
|
### Parameters
|
||||||
|
|
||||||
@ -22,10 +27,11 @@ All scipts accept common parametes which are passed by Octopod when it invokes t
|
|||||||
Also, several environment variables are used to parametrize the default behavior:
|
Also, several environment variables are used to parametrize the default behavior:
|
||||||
|
|
||||||
- HELM_BIN – the path to the `helm` executable
|
- HELM_BIN – the path to the `helm` executable
|
||||||
- KUBECTL_BIN – the path to the `kubectl` executable
|
|
||||||
- HELM_USER – the (optional) user for a private helm registry
|
- HELM_USER – the (optional) user for a private helm registry
|
||||||
- HELM_PASS – the (optional) password for a private helm registry
|
- HELM_PASS – the (optional) password for a private helm registry
|
||||||
- DEFAUTLS – the json with the default parameters (described below)
|
- DEFAUTLS – the json with the default parameters (described below)
|
||||||
|
- HELM_ON_INIT_ONLY - run helm add and update repository as a part of init script execution only. Otherwise `helm repo add` and `helm repo update` will be executed every time before any other helm command.
|
||||||
|
- INGRESS_HOST_KEY - key name which will be populated with domain name generated for the Octopod deployment. Defaults to `ingress.hostname`.
|
||||||
|
|
||||||
#### Default parameters
|
#### Default parameters
|
||||||
- default_overrides – an array with key-value pairs which will be passed as a `--set` flags for helm for each deployment
|
- default_overrides – an array with key-value pairs which will be passed as a `--set` flags for helm for each deployment
|
||||||
@ -34,4 +40,4 @@ Also, several environment variables are used to parametrize the default behavior
|
|||||||
- chart_version – the version of a chart you want to install
|
- chart_version – the version of a chart you want to install
|
||||||
- chart_name – the name of a chart you want to install
|
- chart_name – the name of a chart you want to install
|
||||||
|
|
||||||
These parameters, if set up in the `DEFAULTS` variable, will be passed to every deployment unless overridden in the "deployment overrides" section of an Octopod deployment configuration.
|
These parameters, if set up in the `DEFAULTS` variable, will be passed to every deployment unless overridden in the "deployment overrides" section of an Octopod deployment configuration.
|
||||||
|
31
helm-control-scripts/src/app_keys.rs
Normal file
31
helm-control-scripts/src/app_keys.rs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
use helm_control_scripts::lib::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut log_builder = Builder::from_default_env();
|
||||||
|
log_builder.target(Target::Stderr).filter(None, LevelFilter::Info).init();
|
||||||
|
info!("Utils version {}", env!("CARGO_PKG_VERSION"));
|
||||||
|
let envs = EnvVars::parse();
|
||||||
|
info!("Env variables received {:?}", &envs);
|
||||||
|
let cli_opts = CliOpts::from_args();
|
||||||
|
info!("Cli options received {:?}", &cli_opts);
|
||||||
|
let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &envs);
|
||||||
|
helm_init(&envs, &deployment_parameters);
|
||||||
|
let helm_values = HelmCmd {
|
||||||
|
name: envs.helm_bin,
|
||||||
|
mode: HelmMode::ShowValues,
|
||||||
|
release_name: String::from(""),
|
||||||
|
namespace: String::from(""),
|
||||||
|
deployment_parameters: deployment_parameters,
|
||||||
|
overrides: vec![],
|
||||||
|
};
|
||||||
|
info!("Generated Helm args: {:?}", &helm_values.args());
|
||||||
|
match helm_values.run_stdout() {
|
||||||
|
Ok(status) => {
|
||||||
|
print!("{}", print_keys(helm_values_as_keys(status)));
|
||||||
|
}
|
||||||
|
Err(status) => {
|
||||||
|
error!("Error during helm execution");
|
||||||
|
panic!("{:?}", status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
helm-control-scripts/src/app_overrides.rs
Normal file
11
helm-control-scripts/src/app_overrides.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
use helm_control_scripts::lib::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut log_builder = Builder::from_default_env();
|
||||||
|
log_builder.target(Target::Stderr).filter(None, LevelFilter::Info).init();
|
||||||
|
info!("Utils version {}", env!("CARGO_PKG_VERSION"));
|
||||||
|
let envs = EnvVars::parse();
|
||||||
|
info!("Env variables received {:?}", &envs);
|
||||||
|
let default_values: DefaultValues = serde_json::from_str(&envs.defaults).unwrap();
|
||||||
|
print!("{}", print_kv(default_values.app_overrides()));
|
||||||
|
}
|
@ -6,24 +6,45 @@ fn main() {
|
|||||||
info!("Utils version {}", env!("CARGO_PKG_VERSION"));
|
info!("Utils version {}", env!("CARGO_PKG_VERSION"));
|
||||||
let envs = EnvVars::parse();
|
let envs = EnvVars::parse();
|
||||||
info!("Env variables received {:?}", &envs);
|
info!("Env variables received {:?}", &envs);
|
||||||
let default_values: DefaultValues = serde_json::from_str(&envs.defaults).unwrap();
|
|
||||||
let cli_opts = CliOpts::from_args();
|
let cli_opts = CliOpts::from_args();
|
||||||
info!("Cli options received {:?}", &cli_opts);
|
info!("Cli options received {:?}", &cli_opts);
|
||||||
let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &default_values, &envs);
|
let overrides = match overrides(&cli_opts, &envs) {
|
||||||
let helm_cmd = HelmCmd {
|
Some(inner) => inner,
|
||||||
|
None => vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &envs);
|
||||||
|
let namespace = String::from(&cli_opts.namespace);
|
||||||
|
let release_name = match cli_opts.name {
|
||||||
|
Some(name) => name,
|
||||||
|
None => {
|
||||||
|
error!("mandatory name argument was not provided");
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let helm_template = HelmCmd {
|
||||||
name: envs.helm_bin,
|
name: envs.helm_bin,
|
||||||
mode: HelmMode::Uninstall,
|
mode: HelmMode::Template,
|
||||||
release_name: cli_opts.name,
|
release_name: release_name,
|
||||||
release_domain: String::from(""),
|
|
||||||
namespace: cli_opts.namespace,
|
namespace: cli_opts.namespace,
|
||||||
deployment_parameters: deployment_parameters,
|
deployment_parameters: deployment_parameters,
|
||||||
overrides: vec![],
|
overrides: overrides,
|
||||||
default_values: vec![],
|
|
||||||
image_tag: String::from("")
|
|
||||||
};
|
};
|
||||||
info!("Generated Helm args: {:?}", &helm_cmd.args());
|
info!("Generated Helm args: {:?}", &helm_template.args());
|
||||||
match helm_cmd.run() {
|
match helm_template.run_stdout() {
|
||||||
Ok(_status) => info!("Success!"),
|
Ok(status) => {
|
||||||
|
let (deployments, statefulsets, _ingresses, _old_ingresses) = match parse_to_k8s(status) {
|
||||||
|
Ok((deployments, statefulsets, ingresses, old_ingresses)) => (deployments, statefulsets, ingresses, old_ingresses),
|
||||||
|
Err(err) => panic!("{}", err)
|
||||||
|
};
|
||||||
|
match scale(deployments, statefulsets, namespace, 0) {
|
||||||
|
Ok(_status) => info!("Success!"),
|
||||||
|
Err(status) => {
|
||||||
|
error!("Error checking statuses");
|
||||||
|
panic!("{}", status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Err(status) => {
|
Err(status) => {
|
||||||
error!("Error during helm execution");
|
error!("Error during helm execution");
|
||||||
panic!("{:?}", status);
|
panic!("{:?}", status);
|
||||||
|
@ -4,28 +4,50 @@ fn main() {
|
|||||||
let mut log_builder = Builder::from_default_env();
|
let mut log_builder = Builder::from_default_env();
|
||||||
log_builder.target(Target::Stdout).filter(None, LevelFilter::Info).init();
|
log_builder.target(Target::Stdout).filter(None, LevelFilter::Info).init();
|
||||||
info!("Utils version {}", env!("CARGO_PKG_VERSION"));
|
info!("Utils version {}", env!("CARGO_PKG_VERSION"));
|
||||||
let cli_opts = CliOpts::from_args();
|
|
||||||
let envs = EnvVars::parse();
|
let envs = EnvVars::parse();
|
||||||
info!("Env variables received {:?}", &envs);
|
info!("Env variables received {:?}", &envs);
|
||||||
let default_values: DefaultValues = serde_json::from_str(&envs.defaults).unwrap();
|
let cli_opts = CliOpts::from_args();
|
||||||
let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &default_values, &envs);
|
info!("Cli options received {:?}", &cli_opts);
|
||||||
let helm_cmd = HelmCmd {
|
let overrides = match overrides(&cli_opts, &envs) {
|
||||||
|
Some(inner) => inner,
|
||||||
|
None => vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &envs);
|
||||||
|
let namespace = String::from(&cli_opts.namespace);
|
||||||
|
let release_name = match cli_opts.name {
|
||||||
|
Some(name) => name,
|
||||||
|
None => {
|
||||||
|
error!("mandatory name argument was not provided");
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let helm_template = HelmCmd {
|
||||||
name: envs.helm_bin,
|
name: envs.helm_bin,
|
||||||
mode: HelmMode::Status,
|
mode: HelmMode::Template,
|
||||||
release_name: cli_opts.name,
|
release_name: release_name,
|
||||||
release_domain: String::from(""),
|
|
||||||
namespace: cli_opts.namespace,
|
namespace: cli_opts.namespace,
|
||||||
deployment_parameters: deployment_parameters,
|
deployment_parameters: deployment_parameters,
|
||||||
overrides: vec![],
|
overrides: overrides,
|
||||||
default_values: vec![],
|
|
||||||
image_tag: String::from("")
|
|
||||||
};
|
};
|
||||||
info!("Generated Helm args: {:?}", &helm_cmd.args());
|
info!("Generated Helm args: {:?}", &helm_template.args());
|
||||||
match helm_cmd.run() {
|
match helm_template.run_stdout() {
|
||||||
Ok(_status) => {
|
Ok(status) => {
|
||||||
error!("Release is still present in cluster");
|
let (deployments, statefulsets, _ingresses, _old_ingresses) = match parse_to_k8s(status) {
|
||||||
panic!();
|
Ok((deployments, statefulsets, ingresses, old_ingresses)) => (deployments, statefulsets, ingresses, old_ingresses),
|
||||||
},
|
Err(err) => panic!("{}", err)
|
||||||
Err(_status) => info!("Success!"),
|
};
|
||||||
|
match check_all(deployments, statefulsets, namespace) {
|
||||||
|
Ok(status) => {
|
||||||
|
error!("Deployment hasn't scaled down correctly");
|
||||||
|
panic!("{:?}", status);
|
||||||
|
},
|
||||||
|
Err(_status) => info!("Success!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(status) => {
|
||||||
|
error!("Error during helm execution");
|
||||||
|
panic!("{:?}", status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,35 +6,29 @@ fn main() {
|
|||||||
info!("Utils version {}", env!("CARGO_PKG_VERSION"));
|
info!("Utils version {}", env!("CARGO_PKG_VERSION"));
|
||||||
let envs = EnvVars::parse();
|
let envs = EnvVars::parse();
|
||||||
info!("Env variables received {:?}", &envs);
|
info!("Env variables received {:?}", &envs);
|
||||||
let default_values: DefaultValues = serde_json::from_str(&envs.defaults).unwrap();
|
|
||||||
let cli_opts = CliOpts::from_args();
|
let cli_opts = CliOpts::from_args();
|
||||||
info!("Cli options received {:?}", &cli_opts);
|
info!("Cli options received {:?}", &cli_opts);
|
||||||
let overrides = match overrides(&cli_opts) {
|
let overrides = match overrides(&cli_opts, &envs) {
|
||||||
Some(inner) => inner,
|
Some(inner) => inner,
|
||||||
None => vec![],
|
None => vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
let domain_name = domain_name(&cli_opts);
|
let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &envs);
|
||||||
info!("Domain generated for deployment: {}", &domain_name);
|
let namespace = String::from(&cli_opts.namespace);
|
||||||
let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &default_values, &envs);
|
let release_name = match cli_opts.name {
|
||||||
let image_tag = match cli_opts.tag {
|
Some(name) => name,
|
||||||
Some(tag) => tag,
|
|
||||||
None => {
|
None => {
|
||||||
error!("mandatory tag argument was not provided");
|
error!("mandatory name argument was not provided");
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let namespace = String::from(&cli_opts.namespace);
|
|
||||||
let helm_template = HelmCmd {
|
let helm_template = HelmCmd {
|
||||||
name: envs.helm_bin,
|
name: envs.helm_bin,
|
||||||
mode: HelmMode::Template,
|
mode: HelmMode::Template,
|
||||||
release_name: cli_opts.name,
|
release_name: release_name,
|
||||||
release_domain: domain_name,
|
|
||||||
namespace: cli_opts.namespace,
|
namespace: cli_opts.namespace,
|
||||||
deployment_parameters: deployment_parameters,
|
deployment_parameters: deployment_parameters,
|
||||||
overrides: overrides,
|
overrides: overrides,
|
||||||
default_values: default_values.default_overrides,
|
|
||||||
image_tag: image_tag
|
|
||||||
};
|
};
|
||||||
info!("Generated Helm args: {:?}", &helm_template.args());
|
info!("Generated Helm args: {:?}", &helm_template.args());
|
||||||
match helm_template.run_stdout() {
|
match helm_template.run_stdout() {
|
||||||
@ -47,7 +41,7 @@ fn main() {
|
|||||||
Ok(_status) => info!("Success!"),
|
Ok(_status) => info!("Success!"),
|
||||||
Err(status) => {
|
Err(status) => {
|
||||||
error!("Error checking statuses");
|
error!("Error checking statuses");
|
||||||
panic!("{}", status);
|
panic!("{:?}", status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,16 +6,77 @@ fn main() {
|
|||||||
info!("Utils version {}", env!("CARGO_PKG_VERSION"));
|
info!("Utils version {}", env!("CARGO_PKG_VERSION"));
|
||||||
let envs = EnvVars::parse();
|
let envs = EnvVars::parse();
|
||||||
info!("Env variables received {:?}", &envs);
|
info!("Env variables received {:?}", &envs);
|
||||||
let default_values: DefaultValues = serde_json::from_str(&envs.defaults).unwrap();
|
|
||||||
let cli_opts = CliOpts::from_args();
|
let cli_opts = CliOpts::from_args();
|
||||||
info!("Cli options received {:?}", &cli_opts);
|
info!("Cli options received {:?}", &cli_opts);
|
||||||
let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &default_values, &envs);
|
let overrides = match overrides(&cli_opts, &envs) {
|
||||||
let kubectl_cmd = KubectlCmd {
|
Some(inner) => inner,
|
||||||
name: envs.kubectl_bin,
|
None => vec![],
|
||||||
release_name: cli_opts.name,
|
};
|
||||||
|
|
||||||
|
let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &envs);
|
||||||
|
let namespace = String::from(&cli_opts.namespace);
|
||||||
|
let release_name = match cli_opts.name {
|
||||||
|
Some(name) => name,
|
||||||
|
None => {
|
||||||
|
error!("mandatory name argument was not provided");
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
helm_init(&envs, &deployment_parameters);
|
||||||
|
let helm_cmd = HelmCmd {
|
||||||
|
name: envs.helm_bin.clone(),
|
||||||
|
mode: HelmMode::Uninstall,
|
||||||
|
release_name: release_name.clone(),
|
||||||
|
namespace: cli_opts.namespace.clone(),
|
||||||
|
deployment_parameters: deployment_parameters.clone(),
|
||||||
|
overrides: vec![],
|
||||||
|
};
|
||||||
|
let helm_template = HelmCmd {
|
||||||
|
name: envs.helm_bin,
|
||||||
|
mode: HelmMode::Template,
|
||||||
|
release_name: release_name.clone(),
|
||||||
namespace: cli_opts.namespace,
|
namespace: cli_opts.namespace,
|
||||||
deployment_parameters: deployment_parameters,
|
deployment_parameters: deployment_parameters,
|
||||||
|
overrides: overrides,
|
||||||
};
|
};
|
||||||
kubectl_cmd.run();
|
info!("Generated Helm args: {:?}", &helm_cmd.args());
|
||||||
info!("Success!");
|
match helm_template.run_stdout() {
|
||||||
|
Ok(status) => {
|
||||||
|
let (_deployments, _statefulsets, ingresses, old_ingresses) = match parse_to_k8s(status) {
|
||||||
|
Ok((deployments, statefulsets, ingresses, old_ingresses)) => (deployments, statefulsets, ingresses, old_ingresses),
|
||||||
|
Err(err) => panic!("{}", err)
|
||||||
|
};
|
||||||
|
match helm_cmd.run() {
|
||||||
|
Ok(_status) => {
|
||||||
|
match delete_pvcs(&namespace, &format!("app.kubernetes.io/instance={}", release_name)) {
|
||||||
|
Ok(_status) => info!("All pvcs were deleted successfully"),
|
||||||
|
Err(err) => {
|
||||||
|
error!("Error deleting pvcs");
|
||||||
|
panic!("{:?}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
match ingresses_to_secrets(ingresses, old_ingresses) {
|
||||||
|
Some(secrets) => {
|
||||||
|
for secret in secrets {
|
||||||
|
match delete_secret(&namespace, &secret) {
|
||||||
|
Ok(_status) => info!("Successfully deleted secret {}", &secret),
|
||||||
|
Err(error) => error!("Can't delete secret {}\n {}", &secret, error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => info!("No secrets to delete")
|
||||||
|
}
|
||||||
|
info!("Success!");
|
||||||
|
},
|
||||||
|
Err(status) => {
|
||||||
|
error!("Error during helm uninstall");
|
||||||
|
panic!("{:?}", status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(status) => {
|
||||||
|
error!("Error during helm templating");
|
||||||
|
panic!("{:?}", status);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,39 +2,33 @@ use helm_control_scripts::lib::*;
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut log_builder = Builder::from_default_env();
|
let mut log_builder = Builder::from_default_env();
|
||||||
log_builder.target(Target::Stdout).filter(None, LevelFilter::Info).init();
|
log_builder.target(Target::Stderr).filter(None, LevelFilter::Info).init();
|
||||||
info!("Utils version {}", env!("CARGO_PKG_VERSION"));
|
info!("Utils version {}", env!("CARGO_PKG_VERSION"));
|
||||||
let envs = EnvVars::parse();
|
let envs = EnvVars::parse();
|
||||||
info!("Env variables received {:?}", &envs);
|
info!("Env variables received {:?}", &envs);
|
||||||
let default_values: DefaultValues = serde_json::from_str(&envs.defaults).unwrap();
|
|
||||||
let cli_opts = CliOpts::from_args();
|
let cli_opts = CliOpts::from_args();
|
||||||
info!("Cli options received {:?}", &cli_opts);
|
info!("Cli options received {:?}", &cli_opts);
|
||||||
let overrides = match overrides(&cli_opts) {
|
let overrides = match overrides(&cli_opts, &envs) {
|
||||||
Some(inner) => inner,
|
Some(inner) => inner,
|
||||||
None => vec![],
|
None => vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
let domain_name = domain_name(&cli_opts);
|
let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &envs);
|
||||||
info!("Domain generated for deployment: {}", &domain_name);
|
helm_init(&envs, &deployment_parameters);
|
||||||
let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &default_values, &envs);
|
let release_name = match cli_opts.name {
|
||||||
let image_tag = match cli_opts.tag {
|
Some(name) => name,
|
||||||
Some(tag) => tag,
|
|
||||||
None => {
|
None => {
|
||||||
error!("mandatory tag argument was not provided");
|
error!("mandatory name argument was not provided");
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
helm_init(&envs, &deployment_parameters);
|
|
||||||
let helm_template = HelmCmd {
|
let helm_template = HelmCmd {
|
||||||
name: envs.helm_bin,
|
name: envs.helm_bin,
|
||||||
mode: HelmMode::Template,
|
mode: HelmMode::Template,
|
||||||
release_name: cli_opts.name,
|
release_name: release_name,
|
||||||
release_domain: domain_name,
|
|
||||||
namespace: cli_opts.namespace,
|
namespace: cli_opts.namespace,
|
||||||
deployment_parameters: deployment_parameters,
|
deployment_parameters: deployment_parameters,
|
||||||
overrides: overrides,
|
overrides: overrides,
|
||||||
default_values: default_values.default_overrides,
|
|
||||||
image_tag: image_tag
|
|
||||||
};
|
};
|
||||||
match helm_template.run_stdout() {
|
match helm_template.run_stdout() {
|
||||||
Ok(status) => {
|
Ok(status) => {
|
||||||
@ -46,10 +40,16 @@ fn main() {
|
|||||||
Some(images) => {
|
Some(images) => {
|
||||||
match check_images(images) {
|
match check_images(images) {
|
||||||
Ok(_) => info!("Success!"),
|
Ok(_) => info!("Success!"),
|
||||||
Err(err) => panic!("{}", err),
|
Err(err) => {
|
||||||
|
println!("Error checking images. Are they present in the registry?");
|
||||||
|
panic!("{}", err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => panic!("No images found!"),
|
None => {
|
||||||
|
println!("No images found in pods' declarations");
|
||||||
|
panic!("No images found!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(status) => {
|
Err(status) => {
|
@ -6,34 +6,29 @@ fn main() {
|
|||||||
info!("Utils version {}", env!("CARGO_PKG_VERSION"));
|
info!("Utils version {}", env!("CARGO_PKG_VERSION"));
|
||||||
let envs = EnvVars::parse();
|
let envs = EnvVars::parse();
|
||||||
info!("Env variables received {:?}", &envs);
|
info!("Env variables received {:?}", &envs);
|
||||||
let default_values: DefaultValues = serde_json::from_str(&envs.defaults).unwrap();
|
|
||||||
let cli_opts = CliOpts::from_args();
|
let cli_opts = CliOpts::from_args();
|
||||||
info!("Cli options received {:?}", &cli_opts);
|
info!("Cli options received {:?}", &cli_opts);
|
||||||
let overrides = match overrides(&cli_opts) {
|
let overrides = match overrides(&cli_opts, &envs) {
|
||||||
Some(inner) => inner,
|
Some(inner) => inner,
|
||||||
None => vec![],
|
None => vec![],
|
||||||
};
|
};
|
||||||
let domain_name = domain_name(&cli_opts);
|
|
||||||
info!("Domain generated for deployment: {}", &domain_name);
|
let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &envs);
|
||||||
let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &default_values, &envs);
|
helm_init(&envs, &deployment_parameters);
|
||||||
let image_tag = match cli_opts.tag {
|
let release_name = match cli_opts.name {
|
||||||
Some(tag) => tag,
|
Some(name) => name,
|
||||||
None => {
|
None => {
|
||||||
error!("mandatory tag argument was not provided");
|
error!("mandatory name argument was not provided");
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
helm_init(&envs, &deployment_parameters);
|
|
||||||
let helm_cmd = HelmCmd {
|
let helm_cmd = HelmCmd {
|
||||||
name: envs.helm_bin,
|
name: envs.helm_bin,
|
||||||
mode: HelmMode::UpgradeInstall,
|
mode: HelmMode::UpgradeInstall,
|
||||||
release_name: cli_opts.name,
|
release_name: release_name,
|
||||||
release_domain: domain_name,
|
|
||||||
namespace: cli_opts.namespace,
|
namespace: cli_opts.namespace,
|
||||||
deployment_parameters: deployment_parameters,
|
deployment_parameters: deployment_parameters,
|
||||||
overrides: overrides,
|
overrides: overrides,
|
||||||
default_values: default_values.default_overrides,
|
|
||||||
image_tag: image_tag,
|
|
||||||
};
|
};
|
||||||
info!("Generated Helm args: {:?}", &helm_cmd.args());
|
info!("Generated Helm args: {:?}", &helm_cmd.args());
|
||||||
match helm_cmd.run() {
|
match helm_cmd.run() {
|
||||||
|
11
helm-control-scripts/src/deployment_keys.rs
Normal file
11
helm-control-scripts/src/deployment_keys.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
use helm_control_scripts::lib::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut log_builder = Builder::from_default_env();
|
||||||
|
log_builder.target(Target::Stderr).filter(None, LevelFilter::Info).init();
|
||||||
|
info!("Utils version {}", env!("CARGO_PKG_VERSION"));
|
||||||
|
let envs = EnvVars::parse();
|
||||||
|
info!("Env variables received {:?}", &envs);
|
||||||
|
let default_values: DefaultValues = serde_json::from_str(&envs.defaults).unwrap();
|
||||||
|
print!("{}", print_keys(Some(default_values.deployment_keys())));
|
||||||
|
}
|
11
helm-control-scripts/src/deployment_overrides.rs
Normal file
11
helm-control-scripts/src/deployment_overrides.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
use helm_control_scripts::lib::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut log_builder = Builder::from_default_env();
|
||||||
|
log_builder.target(Target::Stderr).filter(None, LevelFilter::Info).init();
|
||||||
|
info!("Utils version {}", env!("CARGO_PKG_VERSION"));
|
||||||
|
let envs = EnvVars::parse();
|
||||||
|
info!("Env variables received {:?}", &envs);
|
||||||
|
let default_values: DefaultValues = serde_json::from_str(&envs.defaults).unwrap();
|
||||||
|
print!("{}", print_kv(Some(default_values.deployment_overrides())));
|
||||||
|
}
|
@ -6,36 +6,30 @@ fn main() {
|
|||||||
info!("Utils version {}", env!("CARGO_PKG_VERSION"));
|
info!("Utils version {}", env!("CARGO_PKG_VERSION"));
|
||||||
let envs = EnvVars::parse();
|
let envs = EnvVars::parse();
|
||||||
info!("Env variables received {:?}", &envs);
|
info!("Env variables received {:?}", &envs);
|
||||||
let default_values: DefaultValues = serde_json::from_str(&envs.defaults).unwrap();
|
|
||||||
let cli_opts = CliOpts::from_args();
|
let cli_opts = CliOpts::from_args();
|
||||||
info!("Cli options received {:?}", &cli_opts);
|
info!("Cli options received {:?}", &cli_opts);
|
||||||
let overrides = match overrides(&cli_opts) {
|
let overrides = match overrides(&cli_opts, &envs) {
|
||||||
Some(inner) => inner,
|
Some(inner) => inner,
|
||||||
None => vec![],
|
None => vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
let domain_name = domain_name(&cli_opts);
|
let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &envs);
|
||||||
info!("Domain generated for deployment: {}", &domain_name);
|
helm_init(&envs, &deployment_parameters);
|
||||||
let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &default_values, &envs);
|
let release_name = match cli_opts.name {
|
||||||
let image_tag = match cli_opts.tag {
|
Some(name) => name,
|
||||||
Some(tag) => tag,
|
|
||||||
None => {
|
None => {
|
||||||
error!("mandatory tag argument was not provided");
|
error!("mandatory name argument was not provided");
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let default_name = String::from(&cli_opts.name);
|
let default_name = String::from(&release_name);
|
||||||
helm_init(&envs, &deployment_parameters);
|
|
||||||
let helm_template = HelmCmd {
|
let helm_template = HelmCmd {
|
||||||
name: envs.helm_bin,
|
name: envs.helm_bin,
|
||||||
mode: HelmMode::Template,
|
mode: HelmMode::Template,
|
||||||
release_name: cli_opts.name,
|
release_name: release_name,
|
||||||
release_domain: domain_name,
|
|
||||||
namespace: cli_opts.namespace,
|
namespace: cli_opts.namespace,
|
||||||
deployment_parameters: deployment_parameters,
|
deployment_parameters: deployment_parameters,
|
||||||
overrides: overrides,
|
overrides: overrides,
|
||||||
default_values: default_values.default_overrides,
|
|
||||||
image_tag: image_tag
|
|
||||||
};
|
};
|
||||||
match helm_template.run_stdout() {
|
match helm_template.run_stdout() {
|
||||||
Ok(status) => {
|
Ok(status) => {
|
||||||
|
@ -1,24 +1,28 @@
|
|||||||
pub mod lib {
|
pub mod lib {
|
||||||
pub use std::io::prelude::*;
|
pub use std::io::prelude::*;
|
||||||
pub use std::process::{Command, ExitStatus, Stdio};
|
pub use std::process::{Command, ExitStatus, Stdio};
|
||||||
|
pub use std::error::Error;
|
||||||
|
pub use std::fmt;
|
||||||
pub use structopt::StructOpt;
|
pub use structopt::StructOpt;
|
||||||
pub use env_logger::{Builder, Target};
|
pub use env_logger::{Builder, Target};
|
||||||
pub use log::{LevelFilter, info, warn, error};
|
pub use log::{LevelFilter, info, warn, error};
|
||||||
pub use serde::{Serialize, Deserialize};
|
pub use serde::{Serialize, Deserialize};
|
||||||
|
pub use serde_json::json;
|
||||||
pub use std::error;
|
pub use std::error;
|
||||||
pub use yaml_rust::{YamlLoader, YamlEmitter};
|
pub use yaml_rust::{YamlLoader, YamlEmitter, Yaml};
|
||||||
pub use k8s_openapi::api::{
|
pub use k8s_openapi::api::{
|
||||||
apps::v1::{Deployment, StatefulSet},
|
apps::v1::{Deployment, StatefulSet},
|
||||||
networking::v1::Ingress,
|
networking::v1::Ingress,
|
||||||
networking::v1beta1::Ingress as OldIngress
|
networking::v1beta1::Ingress as OldIngress,
|
||||||
|
core::v1::{PersistentVolumeClaim, Secret}
|
||||||
};
|
};
|
||||||
pub use kube::{
|
pub use kube::{
|
||||||
api::{Api, ListParams, ResourceExt},
|
api::{Api, ListParams, ResourceExt, Patch, PatchParams, DeleteParams},
|
||||||
Client,
|
Client,
|
||||||
};
|
};
|
||||||
pub use dkregistry::{
|
pub use dkregistry::{
|
||||||
v2::Client as RegClient,
|
v2::Client as RegClient,
|
||||||
errors::Error
|
errors::Error as RegError,
|
||||||
};
|
};
|
||||||
pub use regex::Regex;
|
pub use regex::Regex;
|
||||||
|
|
||||||
@ -32,25 +36,25 @@ pub mod lib {
|
|||||||
#[structopt(long)]
|
#[structopt(long)]
|
||||||
pub namespace: String,
|
pub namespace: String,
|
||||||
#[structopt(long)]
|
#[structopt(long)]
|
||||||
pub name: String,
|
pub name: Option<String>,
|
||||||
#[structopt(long)]
|
#[structopt(long)]
|
||||||
pub tag: Option<String>,
|
pub tag: Option<String>,
|
||||||
#[structopt(long)]
|
#[structopt(long)]
|
||||||
pub app_env_override: Vec<String>,
|
pub application_config: Vec<String>,
|
||||||
#[structopt(long)]
|
#[structopt(long)]
|
||||||
pub deployment_override: Vec<String>,
|
pub deployment_config: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
pub struct EnvVars {
|
pub struct EnvVars {
|
||||||
pub helm_bin: String,
|
pub helm_bin: String,
|
||||||
pub kubectl_bin: String,
|
|
||||||
pub defaults: String, //json of DefaultValues
|
pub defaults: String, //json of DefaultValues
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub helm_user: String,
|
pub helm_user: String,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub helm_pass: String,
|
pub helm_pass: String,
|
||||||
pub helm_on_init_only: Option<bool>,
|
pub helm_on_init_only: Option<bool>,
|
||||||
|
pub ingress_host_key: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EnvVars {
|
impl EnvVars {
|
||||||
@ -66,6 +70,12 @@ pub mod lib {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
struct HelmRepo {
|
||||||
|
name: String,
|
||||||
|
url: String
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
pub struct DefaultValues {
|
pub struct DefaultValues {
|
||||||
pub default_overrides: Vec<String>,
|
pub default_overrides: Vec<String>,
|
||||||
@ -75,7 +85,42 @@ pub mod lib {
|
|||||||
pub chart_name: String,
|
pub chart_name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
impl DefaultValues {
|
||||||
|
pub fn app_overrides(&self) -> Option<Vec<(String,String)>> {
|
||||||
|
if self.default_overrides.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let mut overrides: Vec<(String,String)> = Vec::new();
|
||||||
|
for app_override in &self.default_overrides {
|
||||||
|
let split_override = app_override.split('=').collect::<Vec<_>>();
|
||||||
|
overrides.push((split_override.first().unwrap().to_string(), split_override.last().unwrap().to_string()));
|
||||||
|
}
|
||||||
|
Some(overrides)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn deployment_overrides(&self) -> Vec<(String,String)> {
|
||||||
|
vec![
|
||||||
|
(String::from("chart_repo_url"), self.chart_repo_url.clone()),
|
||||||
|
(String::from("chart_repo_name"), self.chart_repo_name.clone()),
|
||||||
|
(String::from("chart_version"), self.chart_version.clone()),
|
||||||
|
(String::from("chart_name"), self.chart_name.clone()),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
pub fn deployment_keys(&self) -> Vec<String> {
|
||||||
|
let mut keys: Vec<String> = vec![
|
||||||
|
String::from("chart_repo_url"),
|
||||||
|
String::from("chart_repo_name"),
|
||||||
|
String::from("chart_version"),
|
||||||
|
String::from("chart_name"),
|
||||||
|
String::from("chart_repo_user"),
|
||||||
|
String::from("chart_repo_pass"),
|
||||||
|
];
|
||||||
|
keys.sort();
|
||||||
|
keys
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct HelmDeploymentParameters {
|
pub struct HelmDeploymentParameters {
|
||||||
pub chart_repo_url: String,
|
pub chart_repo_url: String,
|
||||||
pub chart_repo_name: String,
|
pub chart_repo_name: String,
|
||||||
@ -86,30 +131,23 @@ pub mod lib {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl HelmDeploymentParameters {
|
impl HelmDeploymentParameters {
|
||||||
pub fn new(cli_opts: &CliOpts, default_values: &DefaultValues, envs: &EnvVars) -> Self {
|
pub fn new(cli_opts: &CliOpts, envs: &EnvVars) -> Self {
|
||||||
let mut default_parameters = Self {
|
let mut deployment_parameters = Self::default();
|
||||||
chart_repo_url: default_values.chart_repo_url.clone(),
|
deployment_parameters.chart_repo_user = envs.helm_user.clone();
|
||||||
chart_repo_name: default_values.chart_repo_name.clone(),
|
deployment_parameters.chart_repo_pass = envs.helm_pass.clone();
|
||||||
chart_repo_user: envs.helm_user.clone(),
|
for deployment_override in cli_opts.deployment_config.clone().into_iter() {
|
||||||
chart_repo_pass: envs.helm_pass.clone(),
|
let split_override = deployment_override.split('=').collect::<Vec<_>>();
|
||||||
chart_version: default_values.chart_version.clone(),
|
match split_override.first().unwrap().as_ref() {
|
||||||
chart_name: default_values.chart_name.clone(),
|
"chart_repo_url" => deployment_parameters.chart_repo_url = split_override.last().unwrap().to_string(),
|
||||||
};
|
"chart_repo_name" => deployment_parameters.chart_repo_name = split_override.last().unwrap().to_string(),
|
||||||
if cli_opts.deployment_override.is_empty() {
|
"chart_version" => deployment_parameters.chart_version = split_override.last().unwrap().to_string(),
|
||||||
return default_parameters;
|
"chart_name" => deployment_parameters.chart_name = split_override.last().unwrap().to_string(),
|
||||||
} else {
|
"chart_repo_user" => deployment_parameters.chart_repo_user = split_override.last().unwrap().to_string(),
|
||||||
for deployment_override in cli_opts.deployment_override.clone().into_iter() {
|
"chart_repo_pass" => deployment_parameters.chart_repo_pass = split_override.last().unwrap().to_string(),
|
||||||
let split_override = deployment_override.split('=').collect::<Vec<_>>();
|
_ => continue,
|
||||||
match split_override.first().unwrap().as_ref() {
|
|
||||||
"chart_repo_url" => default_parameters.chart_repo_url = split_override.last().unwrap().to_string(),
|
|
||||||
"chart_repo_name" => default_parameters.chart_repo_name = split_override.last().unwrap().to_string(),
|
|
||||||
"chart_version" => default_parameters.chart_version = split_override.last().unwrap().to_string(),
|
|
||||||
"chart_name" => default_parameters.chart_name = split_override.last().unwrap().to_string(),
|
|
||||||
_ => continue,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return default_parameters;
|
|
||||||
}
|
}
|
||||||
|
return deployment_parameters;
|
||||||
}
|
}
|
||||||
pub fn new_env_only(default_values: &DefaultValues, envs: &EnvVars) -> Self {
|
pub fn new_env_only(default_values: &DefaultValues, envs: &EnvVars) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -126,12 +164,9 @@ pub mod lib {
|
|||||||
pub name: String,
|
pub name: String,
|
||||||
pub mode: HelmMode,
|
pub mode: HelmMode,
|
||||||
pub release_name: String,
|
pub release_name: String,
|
||||||
pub release_domain: String,
|
|
||||||
pub namespace: String,
|
pub namespace: String,
|
||||||
pub deployment_parameters: HelmDeploymentParameters,
|
pub deployment_parameters: HelmDeploymentParameters,
|
||||||
pub overrides: Vec<String>,
|
pub overrides: Vec<String>,
|
||||||
pub default_values: Vec<String>,
|
|
||||||
pub image_tag: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HelmCmd {
|
impl HelmCmd {
|
||||||
@ -167,6 +202,13 @@ pub mod lib {
|
|||||||
args.extend(chart_version);
|
args.extend(chart_version);
|
||||||
args.extend(self.set_flag_values());
|
args.extend(self.set_flag_values());
|
||||||
},
|
},
|
||||||
|
HelmMode::ShowValues => {
|
||||||
|
args.extend(namespace);
|
||||||
|
args.push(String::from("show"));
|
||||||
|
args.push(String::from("values"));
|
||||||
|
args.push(chart_location);
|
||||||
|
args.extend(chart_version);
|
||||||
|
},
|
||||||
HelmMode::RepoAdd => {
|
HelmMode::RepoAdd => {
|
||||||
args.push(String::from("repo"));
|
args.push(String::from("repo"));
|
||||||
args.push(String::from("add"));
|
args.push(String::from("add"));
|
||||||
@ -180,12 +222,12 @@ pub mod lib {
|
|||||||
args.push(String::from("repo"));
|
args.push(String::from("repo"));
|
||||||
args.push(String::from("update"));
|
args.push(String::from("update"));
|
||||||
},
|
},
|
||||||
HelmMode::Status => {
|
HelmMode::RepoList => {
|
||||||
args.extend(namespace);
|
args.push(String::from("repo"));
|
||||||
args.push(String::from("status"));
|
args.push(String::from("list"));
|
||||||
args.push(String::from(&self.release_name));
|
args.push(String::from("-o"));
|
||||||
|
args.push(String::from("json"));
|
||||||
},
|
},
|
||||||
_ => panic!("This helm mode is not expected"),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return args;
|
return args;
|
||||||
@ -193,9 +235,6 @@ pub mod lib {
|
|||||||
fn set_flag_values(&self) -> Vec<String> {
|
fn set_flag_values(&self) -> Vec<String> {
|
||||||
let mut values = Vec::new();
|
let mut values = Vec::new();
|
||||||
let mut set_values = Vec::new();
|
let mut set_values = Vec::new();
|
||||||
values.push(format!("image.tag={}", &self.image_tag));
|
|
||||||
values.push(format!("ingress.host={}", &self.release_domain));
|
|
||||||
values.extend(self.default_values.clone());
|
|
||||||
values.extend(self.overrides.clone());
|
values.extend(self.overrides.clone());
|
||||||
for value in values.into_iter() {
|
for value in values.into_iter() {
|
||||||
set_values.push(String::from("--set"));
|
set_values.push(String::from("--set"));
|
||||||
@ -236,58 +275,8 @@ pub mod lib {
|
|||||||
Template,
|
Template,
|
||||||
RepoAdd,
|
RepoAdd,
|
||||||
RepoUpdate,
|
RepoUpdate,
|
||||||
Status,
|
RepoList,
|
||||||
}
|
ShowValues,
|
||||||
|
|
||||||
pub struct KubectlCmd {
|
|
||||||
pub name: String,
|
|
||||||
pub release_name: String,
|
|
||||||
pub namespace: String,
|
|
||||||
pub deployment_parameters: HelmDeploymentParameters,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl KubectlCmd {
|
|
||||||
pub fn args(&self, cmd_type: &str) -> Vec<String> {
|
|
||||||
let mut args: Vec<String> = Vec::new();
|
|
||||||
let namespace = vec![String::from("-n"), String::from(&self.namespace),];
|
|
||||||
let cert_secret_name = format!("{}-{}-tls", &self.release_name, &self.deployment_parameters.chart_name);
|
|
||||||
let label = vec![String::from("-l"), format!("app.kubernetes.io/instance={}", &self.release_name)];
|
|
||||||
args.extend(namespace);
|
|
||||||
args.push(String::from("delete"));
|
|
||||||
match cmd_type {
|
|
||||||
"pvc" => {
|
|
||||||
args.push(String::from("pvc"));
|
|
||||||
args.extend(label);
|
|
||||||
return args;
|
|
||||||
},
|
|
||||||
"cert" => {
|
|
||||||
args.push(String::from("secret"));
|
|
||||||
args.push(cert_secret_name);
|
|
||||||
return args;
|
|
||||||
},
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn run(&self) {
|
|
||||||
info!("Starting pvc cleanup");
|
|
||||||
info!("kubectl args: {:?}", &self.args("pvc"));
|
|
||||||
let kubectl_pvc = Command::new(&self.name)
|
|
||||||
.args(&self.args("pvc"))
|
|
||||||
.output()
|
|
||||||
.expect("Failed to run");
|
|
||||||
info!("kubectl stdout:\n {}", String::from_utf8(kubectl_pvc.stdout).unwrap());
|
|
||||||
info!("kubectl stderr:\n {}", String::from_utf8(kubectl_pvc.stderr).unwrap());
|
|
||||||
info!("Starting certificates cleanup");
|
|
||||||
info!("kubectl args: {:?}", &self.args("pvc"));
|
|
||||||
let kubectl_cert = Command::new(&self.name)
|
|
||||||
.args(&self.args("cert"))
|
|
||||||
.output()
|
|
||||||
.expect("Failed to run");
|
|
||||||
info!("kubectl stdout:\n {}", String::from_utf8(kubectl_cert.stdout).unwrap());
|
|
||||||
info!("kubectl stderr:\n {}", String::from_utf8(kubectl_cert.stderr).unwrap());
|
|
||||||
assert!(kubectl_pvc.status.success());
|
|
||||||
assert!(kubectl_cert.status.success());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_value(value: String) -> Result<String, String> {
|
fn check_value(value: String) -> Result<String, String> {
|
||||||
@ -298,9 +287,14 @@ pub mod lib {
|
|||||||
Err(format!("Override value {} is malformed", value))
|
Err(format!("Override value {} is malformed", value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn overrides(cli_opts: &CliOpts) -> Option<Vec<String>> {
|
pub fn overrides(cli_opts: &CliOpts, envs: &EnvVars) -> Option<Vec<String>> {
|
||||||
let mut overrides_opts = Vec::new();
|
let mut overrides_opts = Vec::new();
|
||||||
overrides_opts.extend(&cli_opts.app_env_override);
|
overrides_opts.extend(&cli_opts.application_config);
|
||||||
|
let ingress_override = match &envs.ingress_host_key {
|
||||||
|
Some(key) => format!("{}={}", &key, domain_name(&cli_opts)),
|
||||||
|
None => format!("ingress.hostname={}", domain_name(&cli_opts)),
|
||||||
|
};
|
||||||
|
overrides_opts.push(&ingress_override);
|
||||||
if overrides_opts.is_empty() {
|
if overrides_opts.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
@ -311,8 +305,13 @@ pub mod lib {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn domain_name(cli_opts: &CliOpts) -> String {
|
fn domain_name(cli_opts: &CliOpts) -> String {
|
||||||
format!("{}.{}", &cli_opts.name, &cli_opts.base_domain)
|
match &cli_opts.name {
|
||||||
|
Some(name) => {
|
||||||
|
return format!("{}.{}", name, &cli_opts.base_domain);
|
||||||
|
},
|
||||||
|
None => panic!("No name argument provided")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub fn parse_to_k8s(yaml: String) -> Result<(Vec<Deployment>, Vec<StatefulSet>, Vec<Ingress>, Vec<OldIngress>), serde_yaml::Error> {
|
pub fn parse_to_k8s(yaml: String) -> Result<(Vec<Deployment>, Vec<StatefulSet>, Vec<Ingress>, Vec<OldIngress>), serde_yaml::Error> {
|
||||||
let docs = YamlLoader::load_from_str(&yaml).unwrap();
|
let docs = YamlLoader::load_from_str(&yaml).unwrap();
|
||||||
@ -356,8 +355,37 @@ pub mod lib {
|
|||||||
}
|
}
|
||||||
return Ok((deployments, statefulsets, ingresses, old_ingresses));
|
return Ok((deployments, statefulsets, ingresses, old_ingresses));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct NoReplicasError(String);
|
||||||
|
|
||||||
|
impl fmt::Display for NoReplicasError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "Deployment {} doesn't have any replicas", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Error for NoReplicasError {}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum KubeError {
|
||||||
|
NoReplicasError(NoReplicasError),
|
||||||
|
KubeApiError(kube::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<NoReplicasError> for KubeError {
|
||||||
|
fn from(error: NoReplicasError) -> Self {
|
||||||
|
KubeError::NoReplicasError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<kube::Error> for KubeError {
|
||||||
|
fn from(error: kube::Error) -> Self {
|
||||||
|
KubeError::KubeApiError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn check_deployment(namespace: &str, name: &str) -> Result<(), kube::Error> {
|
async fn check_deployment(namespace: &str, name: &str) -> Result<(), KubeError> {
|
||||||
let client = Client::try_default().await?;
|
let client = Client::try_default().await?;
|
||||||
let api: Api<Deployment> = Api::namespaced(client, &namespace);
|
let api: Api<Deployment> = Api::namespaced(client, &namespace);
|
||||||
let deployment = api.get(&name).await?;
|
let deployment = api.get(&name).await?;
|
||||||
@ -366,22 +394,22 @@ pub mod lib {
|
|||||||
match status.available_replicas {
|
match status.available_replicas {
|
||||||
Some(replicas) => {
|
Some(replicas) => {
|
||||||
if !replicas >= 1 {
|
if !replicas >= 1 {
|
||||||
panic!("Deployment {} doesn't have any replicas", &name);
|
return Err(KubeError::NoReplicasError(NoReplicasError(name.to_string())));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
panic!("Deployment {} doesn't have any replicas", &name);
|
return Err(KubeError::NoReplicasError(NoReplicasError(name.to_string())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
panic!("Unable to get status for deployment {}", &name);
|
return Err(KubeError::NoReplicasError(NoReplicasError(name.to_string())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn check_statefulset(namespace: &str, name: &str) -> Result<(), kube::Error> {
|
async fn check_statefulset(namespace: &str, name: &str) -> Result<(), KubeError> {
|
||||||
let client = Client::try_default().await?;
|
let client = Client::try_default().await?;
|
||||||
let api: Api<StatefulSet> = Api::namespaced(client, &namespace);
|
let api: Api<StatefulSet> = Api::namespaced(client, &namespace);
|
||||||
let statefulset = api.get(&name).await?;
|
let statefulset = api.get(&name).await?;
|
||||||
@ -390,21 +418,21 @@ pub mod lib {
|
|||||||
match status.current_replicas {
|
match status.current_replicas {
|
||||||
Some(replicas) => {
|
Some(replicas) => {
|
||||||
if !replicas >= 1 {
|
if !replicas >= 1 {
|
||||||
panic!("StatefulSet {} doesn't have any replicas", &name);
|
return Err(KubeError::NoReplicasError(NoReplicasError(name.to_string())));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
panic!("StatefulSet {} doesn't have any replicas", &name);
|
return Err(KubeError::NoReplicasError(NoReplicasError(name.to_string())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
panic!("Unable to get status for StatefulSet {}", &name);
|
return Err(KubeError::NoReplicasError(NoReplicasError(name.to_string())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub fn check_all(deployments: Vec<Deployment>, statefulsets: Vec<StatefulSet>, namespace: String) -> Result<(), Box<dyn error::Error>> {
|
pub fn check_all(deployments: Vec<Deployment>, statefulsets: Vec<StatefulSet>, namespace: String) -> Result<(), KubeError> {
|
||||||
if deployments.is_empty() {
|
if deployments.is_empty() {
|
||||||
info!("No deployments to check");
|
info!("No deployments to check");
|
||||||
}else{
|
}else{
|
||||||
@ -412,7 +440,7 @@ pub mod lib {
|
|||||||
match check_deployment(&namespace, &deploy.name()) {
|
match check_deployment(&namespace, &deploy.name()) {
|
||||||
Ok(status) => status,
|
Ok(status) => status,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
return Err(Box::new(err));
|
return Err(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -425,7 +453,7 @@ pub mod lib {
|
|||||||
match check_statefulset(&namespace, &statefulset.name()) {
|
match check_statefulset(&namespace, &statefulset.name()) {
|
||||||
Ok(status) => status,
|
Ok(status) => status,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
return Err(Box::new(err));
|
return Err(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -506,6 +534,18 @@ pub mod lib {
|
|||||||
}
|
}
|
||||||
return out_string;
|
return out_string;
|
||||||
}
|
}
|
||||||
|
pub fn print_keys(vals: Option<Vec<String>>) -> String {
|
||||||
|
let mut out_string = String::from("");
|
||||||
|
match vals {
|
||||||
|
Some(values) => {
|
||||||
|
for value in values {
|
||||||
|
out_string.push_str(&format!("{}\n", value));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => return out_string
|
||||||
|
}
|
||||||
|
return out_string;
|
||||||
|
}
|
||||||
//TODO: Generics!!!
|
//TODO: Generics!!!
|
||||||
pub fn deployments_statefulsets_to_images(deployments: Vec<Deployment>, statefulsets: Vec<StatefulSet>) -> Option<Vec<String>> {
|
pub fn deployments_statefulsets_to_images(deployments: Vec<Deployment>, statefulsets: Vec<StatefulSet>) -> Option<Vec<String>> {
|
||||||
let mut images: Vec<String> = Vec::new();
|
let mut images: Vec<String> = Vec::new();
|
||||||
@ -564,7 +604,7 @@ pub mod lib {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn check_image(registry: &str, repository: &str, tag: &str) -> Result<(), dkregistry::errors::Error> {
|
async fn check_image(registry: &str, repository: &str, tag: &str) -> Result<(), RegError> {
|
||||||
let client = RegClient::configure()
|
let client = RegClient::configure()
|
||||||
.insecure_registry(false)
|
.insecure_registry(false)
|
||||||
.registry(registry)
|
.registry(registry)
|
||||||
@ -598,7 +638,7 @@ pub mod lib {
|
|||||||
info!("Checking image: {} {} {}", registry, repository, tag);
|
info!("Checking image: {} {} {}", registry, repository, tag);
|
||||||
(registry, repository, tag)
|
(registry, repository, tag)
|
||||||
}
|
}
|
||||||
pub fn check_images(images: Vec<String>) -> Result<(), dkregistry::errors::Error> {
|
pub fn check_images(images: Vec<String>) -> Result<(), RegError> {
|
||||||
for image in images {
|
for image in images {
|
||||||
let (registry, repository, tag) = parse_image_name(&image);
|
let (registry, repository, tag) = parse_image_name(&image);
|
||||||
match check_image(®istry, &repository, &tag) {
|
match check_image(®istry, &repository, &tag) {
|
||||||
@ -613,23 +653,17 @@ pub mod lib {
|
|||||||
name: String::from(&envs.helm_bin),
|
name: String::from(&envs.helm_bin),
|
||||||
mode: HelmMode::RepoAdd,
|
mode: HelmMode::RepoAdd,
|
||||||
release_name: String::from(""),
|
release_name: String::from(""),
|
||||||
release_domain: String::from(""),
|
|
||||||
namespace: String::from(""),
|
namespace: String::from(""),
|
||||||
deployment_parameters: deployment_parameters.clone(),
|
deployment_parameters: deployment_parameters.clone(),
|
||||||
overrides: vec![],
|
overrides: vec![],
|
||||||
default_values: vec![],
|
|
||||||
image_tag: String::from(""),
|
|
||||||
};
|
};
|
||||||
let helm_repo_update = HelmCmd {
|
let helm_repo_update = HelmCmd {
|
||||||
name: String::from(&envs.helm_bin),
|
name: String::from(&envs.helm_bin),
|
||||||
mode: HelmMode::RepoUpdate,
|
mode: HelmMode::RepoUpdate,
|
||||||
release_name: String::from(""),
|
release_name: String::from(""),
|
||||||
release_domain: String::from(""),
|
|
||||||
namespace: String::from(""),
|
namespace: String::from(""),
|
||||||
deployment_parameters: deployment_parameters.clone(),
|
deployment_parameters: deployment_parameters.clone(),
|
||||||
overrides: vec![],
|
overrides: vec![],
|
||||||
default_values: vec![],
|
|
||||||
image_tag: String::from(""),
|
|
||||||
};
|
};
|
||||||
match helm_repo_add.run() {
|
match helm_repo_add.run() {
|
||||||
Ok(_status) => info!("Repo add success!"),
|
Ok(_status) => info!("Repo add success!"),
|
||||||
@ -652,14 +686,215 @@ pub mod lib {
|
|||||||
if *enabled {
|
if *enabled {
|
||||||
info!("Skipping helm initialization, it must be initialied on init");
|
info!("Skipping helm initialization, it must be initialied on init");
|
||||||
} else {
|
} else {
|
||||||
info!("Starting helm initialization");
|
if helm_repo_exists(&envs, &deployment_parameters) {
|
||||||
helm_repo_add_update(&envs, &deployment_parameters);
|
info!("Skipping helm initialization, because requested repo was already added");
|
||||||
|
} else {
|
||||||
|
info!("Starting helm initialization");
|
||||||
|
helm_repo_add_update(&envs, &deployment_parameters);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
info!("Starting helm initialization");
|
if helm_repo_exists(&envs, &deployment_parameters) {
|
||||||
helm_repo_add_update(&envs, &deployment_parameters);
|
info!("Skipping helm initialization, because requested repo was already added");
|
||||||
|
} else {
|
||||||
|
info!("Starting helm initialization");
|
||||||
|
helm_repo_add_update(&envs, &deployment_parameters);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn helm_repo_exists(envs: &EnvVars, deployment_parameters: &HelmDeploymentParameters) -> bool {
|
||||||
|
let chart_repo_url = String::from(&deployment_parameters.chart_repo_url);
|
||||||
|
let chart_repo_name = String::from(&deployment_parameters.chart_repo_name);
|
||||||
|
let helm_repo_list = HelmCmd {
|
||||||
|
name: String::from(&envs.helm_bin),
|
||||||
|
mode: HelmMode::RepoList,
|
||||||
|
release_name: String::from(""),
|
||||||
|
namespace: String::from(""),
|
||||||
|
deployment_parameters: deployment_parameters.clone(),
|
||||||
|
overrides: vec![],
|
||||||
|
};
|
||||||
|
match helm_repo_list.run_stdout() {
|
||||||
|
Ok(list) => {
|
||||||
|
let helm_repos: Vec<HelmRepo> = serde_json::from_str(&list).unwrap();
|
||||||
|
for repo in helm_repos {
|
||||||
|
if repo.name == chart_repo_name && repo.url == chart_repo_url {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(_err) => {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
pub fn helm_values_as_keys(yaml: String) -> Option<Vec<String>> {
|
||||||
|
let mut keys: Vec<String> = Vec::new();
|
||||||
|
let docs = YamlLoader::load_from_str(&yaml).unwrap();
|
||||||
|
let docs_hash = &docs[0].clone().into_hash().unwrap();
|
||||||
|
for doc in docs_hash {
|
||||||
|
match doc.1.as_hash() {
|
||||||
|
Some(hash) => {
|
||||||
|
if hash.is_empty() {
|
||||||
|
keys.push(format!("{}", doc.0.as_str().unwrap()));
|
||||||
|
}else{
|
||||||
|
for doc_2 in hash {
|
||||||
|
match doc_2.1.as_hash() {
|
||||||
|
Some(hash_2) => {
|
||||||
|
if hash_2.is_empty() {
|
||||||
|
keys.push(format!("{}.{}", doc.0.as_str().unwrap(), doc_2.0.as_str().unwrap()));
|
||||||
|
}else{
|
||||||
|
for key in hash_2.keys() {
|
||||||
|
keys.push(format!("{}.{}.{}", doc.0.as_str().unwrap(), doc_2.0.as_str().unwrap(), key.as_str().unwrap()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => keys.push(format!("{}.{}", doc.0.as_str().unwrap(), doc_2.0.as_str().unwrap()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => keys.push(format!("{}", doc.0.as_str().unwrap())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if keys.is_empty() {
|
||||||
|
None
|
||||||
|
}else{
|
||||||
|
keys.sort();
|
||||||
|
Some(keys)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[tokio::main]
|
||||||
|
async fn scale_deployment(namespace: &str, name: &str, replicas: i32) -> Result<(), kube::Error> {
|
||||||
|
let client = Client::try_default().await?;
|
||||||
|
let api: Api<Deployment> = Api::namespaced(client, &namespace);
|
||||||
|
let deployment = api.get(&name).await?;
|
||||||
|
let mut spec = match deployment.spec {
|
||||||
|
Some(spec) => spec,
|
||||||
|
None => panic!("Deployment without any spec!")
|
||||||
|
};
|
||||||
|
spec.replicas = Some(replicas);
|
||||||
|
let patched_deployment = Deployment {
|
||||||
|
metadata: deployment.metadata,
|
||||||
|
spec: Some(spec),
|
||||||
|
status: None
|
||||||
|
};
|
||||||
|
let patch = Patch::Merge(patched_deployment);
|
||||||
|
let patch_params = PatchParams::apply("octopod");
|
||||||
|
api.patch(&name, &patch_params, &patch).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
#[tokio::main]
|
||||||
|
async fn scale_statefulset(namespace: &str, name: &str, replicas: i32) -> Result<(), kube::Error> {
|
||||||
|
let client = Client::try_default().await?;
|
||||||
|
let api: Api<StatefulSet> = Api::namespaced(client, &namespace);
|
||||||
|
let statefulset = api.get(&name).await?;
|
||||||
|
let mut spec = match statefulset.spec {
|
||||||
|
Some(spec) => spec,
|
||||||
|
None => panic!("StatefulSet without any spec!")
|
||||||
|
};
|
||||||
|
spec.replicas = Some(replicas);
|
||||||
|
let patched_statefulset = StatefulSet {
|
||||||
|
metadata: statefulset.metadata,
|
||||||
|
spec: Some(spec),
|
||||||
|
status: None
|
||||||
|
};
|
||||||
|
let patch = Patch::Merge(patched_statefulset);
|
||||||
|
let patch_params = PatchParams::apply("octopod");
|
||||||
|
api.patch(&name, &patch_params, &patch).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
pub fn scale(deployments: Vec<Deployment>, statefulsets: Vec<StatefulSet>, namespace: String, replicas: i32) -> Result<(), Box<dyn error::Error>> {
|
||||||
|
if deployments.is_empty() {
|
||||||
|
info!("No deployments to check");
|
||||||
|
}else{
|
||||||
|
for deploy in deployments {
|
||||||
|
match scale_deployment(&namespace, &deploy.name(), replicas) {
|
||||||
|
Ok(status) => status,
|
||||||
|
Err(err) => {
|
||||||
|
return Err(Box::new(err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if statefulsets.is_empty() {
|
||||||
|
info!("No statefulsets to check");
|
||||||
|
}else{
|
||||||
|
for statefulset in statefulsets {
|
||||||
|
match scale_statefulset(&namespace, &statefulset.name(), replicas) {
|
||||||
|
Ok(status) => status,
|
||||||
|
Err(err) => {
|
||||||
|
return Err(Box::new(err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
pub fn ingresses_to_secrets(new_ingresses: Vec<Ingress>, old_ingresses: Vec<OldIngress>) -> Option<Vec<String>> {
|
||||||
|
let mut secrets: Vec<String> = Vec::new();
|
||||||
|
if new_ingresses.is_empty() {
|
||||||
|
for ingress in old_ingresses {
|
||||||
|
match &ingress.spec {
|
||||||
|
Some(spec) => {
|
||||||
|
if spec.tls.is_empty() {
|
||||||
|
continue
|
||||||
|
}else{
|
||||||
|
for tls in &spec.tls {
|
||||||
|
match &tls.secret_name {
|
||||||
|
Some(secret) => secrets.push(String::from(secret)),
|
||||||
|
None => continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
for ingress in new_ingresses {
|
||||||
|
match &ingress.spec {
|
||||||
|
Some(spec) => {
|
||||||
|
if spec.tls.is_empty() {
|
||||||
|
continue
|
||||||
|
}else{
|
||||||
|
for tls in &spec.tls {
|
||||||
|
match &tls.secret_name {
|
||||||
|
Some(secret) => secrets.push(String::from(secret)),
|
||||||
|
None => continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if secrets.is_empty() {
|
||||||
|
None
|
||||||
|
}else{
|
||||||
|
Some(secrets)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[tokio::main]
|
||||||
|
pub async fn delete_pvcs(namespace: &str, selector: &str) -> Result<(), kube::Error> {
|
||||||
|
let client = Client::try_default().await?;
|
||||||
|
let api: Api<PersistentVolumeClaim> = Api::namespaced(client, &namespace);
|
||||||
|
let pvc_list = ListParams::default().labels(selector);
|
||||||
|
api.delete_collection(&DeleteParams::default(), &pvc_list).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
#[tokio::main]
|
||||||
|
pub async fn delete_secret(namespace: &str, secret: &str) -> Result<(), kube::Error> {
|
||||||
|
let client = Client::try_default().await?;
|
||||||
|
let api: Api<Secret> = Api::namespaced(client, &namespace);
|
||||||
|
api.delete(&secret, &DeleteParams::default()).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
53
helm-control-scripts/src/unarchive.rs
Normal file
53
helm-control-scripts/src/unarchive.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
use helm_control_scripts::lib::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut log_builder = Builder::from_default_env();
|
||||||
|
log_builder.target(Target::Stdout).filter(None, LevelFilter::Info).init();
|
||||||
|
info!("Utils version {}", env!("CARGO_PKG_VERSION"));
|
||||||
|
let envs = EnvVars::parse();
|
||||||
|
info!("Env variables received {:?}", &envs);
|
||||||
|
let cli_opts = CliOpts::from_args();
|
||||||
|
info!("Cli options received {:?}", &cli_opts);
|
||||||
|
let overrides = match overrides(&cli_opts, &envs) {
|
||||||
|
Some(inner) => inner,
|
||||||
|
None => vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
let deployment_parameters = HelmDeploymentParameters::new(&cli_opts, &envs);
|
||||||
|
let namespace = String::from(&cli_opts.namespace);
|
||||||
|
let release_name = match cli_opts.name {
|
||||||
|
Some(name) => name,
|
||||||
|
None => {
|
||||||
|
error!("mandatory name argument was not provided");
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let helm_template = HelmCmd {
|
||||||
|
name: envs.helm_bin,
|
||||||
|
mode: HelmMode::Template,
|
||||||
|
release_name: release_name,
|
||||||
|
namespace: cli_opts.namespace,
|
||||||
|
deployment_parameters: deployment_parameters,
|
||||||
|
overrides: overrides,
|
||||||
|
};
|
||||||
|
info!("Generated Helm args: {:?}", &helm_template.args());
|
||||||
|
match helm_template.run_stdout() {
|
||||||
|
Ok(status) => {
|
||||||
|
let (deployments, statefulsets, _ingresses, _old_ingresses) = match parse_to_k8s(status) {
|
||||||
|
Ok((deployments, statefulsets, ingresses, old_ingresses)) => (deployments, statefulsets, ingresses, old_ingresses),
|
||||||
|
Err(err) => panic!("{}", err)
|
||||||
|
};
|
||||||
|
match scale(deployments, statefulsets, namespace, 1) {
|
||||||
|
Ok(_status) => info!("Success!"),
|
||||||
|
Err(status) => {
|
||||||
|
error!("Error checking statuses");
|
||||||
|
panic!("{}", status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(status) => {
|
||||||
|
error!("Error during helm execution");
|
||||||
|
panic!("{:?}", status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user