fix: add sensible defaults and defensive property references
Additionally deprecate certain duplicated or unnecessary configuration
parameters, such as:
* compute the download URL for helm and kubectl from the configured
version
* remove the tests/pillar/single.sls reference to
helm:client:bind:address
* remove the helm:client:kubectl:tarball_path configuration value,
since that’s an implementation detail of the formula that shouldn’t
matter to consumers
Fixes salt-formulas/salt-formula-helm#2
diff --git a/README.rst b/README.rst
index 1bf7c33..b3e830f 100644
--- a/README.rst
+++ b/README.rst
@@ -10,6 +10,14 @@
Sample pillars
==============
+See the [pillar.example](pillar.example) for a documented example pillar file.
+
+Example Configurations
+======================
+
+_The following examples demonstrate configuring the formula for different
+use cases._
+
Enable formula, install helm client on node and tiller on Kubernetes (assuming
already configured kubectl config or local cluster endpoint):
@@ -25,7 +33,7 @@
helm:
client:
- version: 2.6.0 # defaults to 2.4.2 currently
+ version: 2.6.0 # defaults to 2.6.2 currently
download_hash: sha256=youneedtocalculatehashandputithere
Don't install tiller and use existing one exposed on some well-known address:
@@ -84,12 +92,16 @@
kubectl:
install: true # installs kubectl 1.6.7 by default
config:
- cluster: # directly translated to cluster definition in kubeconfig
+ # directly translated to cluster definition in kubeconfig
+ cluster:
server: https://kubernetes.example.com
certificate-authority-data: base64_of_ca_certificate
- user: # same for user
+ cluster_name: kubernetes.example
+ # directly translated to user definition in kubeconfig
+ user:
username: admin
password: uberadminpass
+ user_name: admin
Change kubectl download URL and use it with GKE-based cluster:
@@ -102,12 +114,15 @@
download_url: https://dl.k8s.io/v1.6.7/kubernetes-client-linux-amd64.tar.gz
download_hash: sha256=calculate_hash_here
config:
- cluster: # directly translated to cluster definition in kubeconfig
+ # directly translated to cluster definition in kubeconfig
+ cluster:
server: https://3.141.59.265
certificate-authority-data: base64_of_ca_certificate
+ # directly translated to user definition in kubeconfig
user:
auth-provider:
name: gcp
+ user_name: gce_user
gce_service_token: base64_of_json_token_downloaded_from_cloud_console
diff --git a/helm/client.sls b/helm/client.sls
index e37151f..b913efc 100644
--- a/helm/client.sls
+++ b/helm/client.sls
@@ -1,24 +1,26 @@
{%- from "helm/map.jinja" import client with context %}
{%- if client.enabled %}
-{%- set helm_tmp = "/tmp/helm-" + client.version %}
-{%- set helm_bin = "/usr/bin/helm-" + client.version %}
+{%- set helm_tmp = "/tmp/helm-v" + client.version %}
+{%- set helm_bin = "/usr/bin/helm-v" + client.version %}
{%- set kubectl_bin = "/usr/bin/kubectl" %}
{%- set kube_config = "/srv/helm/kubeconfig.yaml" %}
-{%- if client.kubectl.config.gce_service_token %}
-{%- set gce_service_token = "/srv/helm/gce_token.json" %}
-{%- set gce_env_var = "- GOOGLE_APPLICATION_CREDENTIALS: \"{}\"".format(gce_service_token) %}
-{%- set gce_state_arg = "- gce_service_token: \"{}\"".format(gce_service_token) %}
-{%- set gce_require = "- file: \"{}\"".format(gce_service_token) %}
-{%- else %}
+{%- set gce_service_token = None %}
{%- set gce_env_var = "" %}
{%- set gce_state_arg = "" %}
{%- set gce_require = "" %}
+{%- if client.kubectl.install and
+ "gce_service_token" in client.kubectl.config %}
+{%- set gce_service_token = client.kubectl.config.gce_service_token %}
+{%- set gce_service_token_path = "/srv/helm/gce_token.json" %}
+{%- set gce_env_var = "- GOOGLE_APPLICATION_CREDENTIALS: \"{}\"".format(gce_service_token_path) %}
+{%- set gce_state_arg = "- gce_service_token: \"{}\"".format(gce_service_token_path) %}
+{%- set gce_require = "- file: \"{}\"".format(gce_service_token_path) %}
{%- endif %}
{%- set helm_home = "/srv/helm/home" %}
-{%- if client.tiller.host %}
+{%- if "host" in client.tiller %}
{%- set helm_run = "helm --host '{}'".format(client.tiller.host) %}
{%- set tiller_arg = "- tiller_host: \"{}\"".format(client.tiller.host) %}
{%- else %}
@@ -31,7 +33,7 @@
- user: root
- group: root
archive.extracted:
- - source: {{ client.download_url }}
+ - source: https://storage.googleapis.com/kubernetes-helm/helm-v{{ client.version }}-linux-amd64.tar.gz
- source_hash: {{ client.download_hash }}
- archive_format: tar
{%- if grains['saltversioninfo'] < [2016, 11] %}
@@ -54,7 +56,7 @@
/usr/bin/helm:
file.symlink:
- - target: helm-{{ client.version }}
+ - target: helm-v{{ client.version }}
- require:
- file: {{ helm_bin }}
@@ -67,6 +69,7 @@
- require:
- file: /usr/bin/helm
+{%- if client.kubectl.install %}
{{ kube_config }}:
file.managed:
- source: salt://helm/files/kubeconfig.yaml.j2
@@ -75,8 +78,8 @@
- group: root
- template: jinja
-{%- if client.kubectl.config.gce_service_token %}
-{{ gce_service_token }}:
+{%- if gce_service_token %}
+{{ gce_service_token_path }}:
file.managed:
- source: salt://helm/files/gce_token.json.j2
- mode: 400
@@ -84,8 +87,33 @@
- group: root
- template: jinja
- context:
- content: {{ client.kubectl.config.gce_service_token }}
-{%- endif %}
+ content: {{ gce_service_token }}
+{%- endif %}{# gce_service_token #}
+
+extract_kubectl:
+ archive.extracted:
+ - name: {{ helm_tmp }}/kubectl/v{{ client.kubectl.version }}
+ - source: https://dl.k8s.io/v{{ client.kubectl.version }}/kubernetes-client-linux-amd64.tar.gz
+ - source_hash: {{ client.kubectl.download_hash }}
+ - archive_format: tar
+ {%- if grains['saltversioninfo'] < [2016, 11] %}
+ - tar_options: v
+ {%- else %}
+ - options: v
+ {%- endif %}
+ - if_missing: {{ helm_tmp }}/kubectl/v{{ client.kubectl.version }}
+ - require:
+ - file: {{ helm_tmp }}
+
+{{ kubectl_bin }}:
+ file.managed:
+ - source: {{ helm_tmp }}/kubectl/v{{ client.kubectl.version }}/kubernetes/client/bin/kubectl
+ - mode: 555
+ - user: root
+ - group: root
+ - require:
+ - archive: extract_kubectl
+{%- endif %}{# client.kubectl.install #}
helm_env_home_param:
environ.setenv:
@@ -107,13 +135,17 @@
- name: {{ helm_run }} init --upgrade
- env:
- HELM_HOME: {{ helm_home }}
+ {%- if client.kubectl.install %}
- KUBECONFIG: {{ kube_config }}
+ {%- endif %}
{{ gce_env_var }}
- unless: "{{ helm_run }} version --server --short | grep -E 'Server: v{{ client.version }}(\\+|$)'"
- require:
- cmd: prepare_client
+ {%- if client.kubectl.install %}
- file: {{ kube_config }}
- environ: helm_env_kubeconfig_param
+ {%- endif %}
{{ gce_require }}
wait_for_tiller:
@@ -122,15 +154,22 @@
- timeout: 30
- env:
- HELM_HOME: {{ helm_home }}
+ {%- if client.kubectl.install %}
- KUBECONFIG: {{ kube_config }}
+ {%- endif %}
{{ gce_env_var }}
+ {%- if client.kubectl.install or gce_require != "" %}
- require:
+ {%- if client.kubectl.install %}
- file: {{ kube_config }}
+ {%- endif %}
{{ gce_require }}
+ {%- endif %}
- onchanges:
- cmd: install_tiller
{%- endif %}
+{%- if "repos" in client %}
{%- for repo_name, repo_url in client.repos.items() %}
ensure_{{ repo_name }}_repo:
cmd.run:
@@ -141,7 +180,9 @@
- require:
- cmd: prepare_client
{%- endfor %}
+{%- endif %}{# "repos" in client #}
+{%- if "releases" in client %}
{%- set namespaces = [] %}
{%- for release_id, release in client.releases.items() %}
{%- set release_name = release.get('name', release_id) %}
@@ -152,7 +193,9 @@
- name: {{ release_name }}
- chart_name: {{ release['chart'] }}
- namespace: {{ namespace }}
+ {% if client.kubectl.install %}
- kube_config: {{ kube_config }}
+ {% endif %}
{{ tiller_arg }}
{{ gce_state_arg }}
{%- if release.get('version') %}
@@ -168,13 +211,15 @@
{%- endif %}
- cmd: ensure_{{ namespace }}_namespace
{{ gce_require }}
- {%- do namespaces.append((namespace, None)) %}
+ {%- do namespaces.append(namespace) %}
{%- else %}{# not release.enabled #}
absent_{{ release_id }}_release:
helm_release.absent:
- name: {{ release_name }}
- namespace: {{ namespace }}
+ {% if client.kubectl.install %}
- kube_config: {{ kube_config }}
+ {% endif %}
{{ tiller_arg }}
{{ gce_state_arg }}
- require:
@@ -185,47 +230,25 @@
- cmd: prepare_client
{%- endif %}{# release.enabled #}
{%- endfor %}{# release_id, release in client.releases #}
+{%- endif %}{# "releases" in client #}
-{%- if client.kubectl.install %}
-extract_kubectl:
- archive.extracted:
- - name: {{ helm_tmp }}
- - source: {{ client.kubectl.download_url }}
- - source_hash: {{ client.kubectl.download_hash }}
- - archive_format: tar
- {%- if grains['saltversioninfo'] < [2016, 11] %}
- - tar_options: v
- {%- else %}
- - options: v
- {%- endif %}
- - if_missing: {{ helm_tmp }}/{{ client.kubectl.tarball_path }}
- - require:
- - file: {{ helm_tmp }}
-
-{{ kubectl_bin }}:
- file.managed:
- - source: {{ helm_tmp }}/{{ client.kubectl.tarball_path }}
- - mode: 555
- - user: root
- - group: root
- - require:
- - archive: extract_kubectl
-{%- endif %}{# client.kubectl.install #}
-
-{%- for namespace in dict(namespaces) %}
+{%- for namespace in namespaces %}
ensure_{{ namespace }}_namespace:
cmd.run:
- name: kubectl create namespace {{ namespace }}
- unless: kubectl get namespace {{ namespace }}
- env:
- - KUBECONFIG: {{ kube_config }}
{{ gce_env_var }}
+ {%- if client.kubectl.install %}
+ - KUBECONFIG: {{ kube_config }}
+ {%- endif %}
+ {%- if gce_require != "" or client.kubectl.install %}
- require:
- - file: {{ kube_config }}
- - environ: helm_env_kubeconfig_param
{{ gce_require }}
- {%- if client.kubectl.install %}
+ {%- if client.kubectl.install %}
+ - file: {{ kube_config }}
- file: {{ kubectl_bin }}
+ {%- endif %}
{%- endif %}
{%- endfor %}
diff --git a/helm/files/kubeconfig.yaml.j2 b/helm/files/kubeconfig.yaml.j2
index 753362b..1e330ad 100644
--- a/helm/files/kubeconfig.yaml.j2
+++ b/helm/files/kubeconfig.yaml.j2
@@ -1,19 +1,40 @@
{%- from "helm/map.jinja" import client with context %}
{%- set config = client.kubectl.config %}
+{%- set cluster = config.get("cluster", None) %}
+{%- set cluster_name = config.get("cluster_name", "thecluster") %}
+{%- set user_name = config.get("user_name", "theuser") %}
+{%- set context_name = config.get('context_name', "\"\"") %}
+{%- set context = config.get("context", None) %}
+{%- set user = config.get("user", None) %}
apiVersion: v1
-clusters:
-- cluster:
- {{ config.cluster|yaml|indent(4) }}
- name: thecluster
-contexts:
-- context:
- cluster: thecluster
- user: theuser
- name: thecontext
-current-context: thecontext
+
+{%- if cluster is not none %}
+clusters:
+ - name: {{ cluster_name }}
+ cluster:
+ {{ cluster | yaml(False) |indent(6) }}
+{%- else %}
+clusters: []
+{%- endif %}
+
+{%- if context is not none %}
+contexts:
+ - name: {{ context_name }}
+ context:
+ cluster: {{ cluster_name }}
+ user: {{ user_name }}
+{%- else %}
+contexts: []
+{%- endif %}
+
+current-context: {{ context_name }}
kind: Config
preferences: {}
-users:
-- name: theuser
- user:
- {{ config.user|yaml|indent(4) }}
+
+{%- if user is not none %}
+users:
+ - name: {{ user_name }}
+ {{ config.get("user", "") | yaml(false) | indent(4) }}
+{%- else %}
+users: []
+{%- endif %}
\ No newline at end of file
diff --git a/helm/map.jinja b/helm/map.jinja
index 5aa27e2..5eef827 100644
--- a/helm/map.jinja
+++ b/helm/map.jinja
@@ -26,4 +26,21 @@
{%- endif %}
{%- endload %}
-{%- set client = salt['grains.filter_by'](base_defaults, merge=salt['pillar.get']('helm:client')) %}
\ No newline at end of file
+{%- load_yaml as base_config %}
+helm:
+ client:
+ enabled: true
+ version: 2.6.2
+ download_hash: sha256=ba807d6017b612a0c63c093a954c7d63918d3e324bdba335d67b7948439dbca8
+ tiller:
+ install: true
+ namespace: kube-system
+ kubectl:
+ install: true
+ version: 1.6.7
+ download_hash: sha256=54947ef84181e89f9dbacedd54717cbed5cc7f9c36cb37bc8afc9097648e2c91
+ config: {}
+{%- endload %}
+
+{%- set config = salt['pillar.get']('helm:client', base_config.helm.client, merge=true) %}
+{%- set client = salt['grains.filter_by'](base_defaults, merge=config) %}
\ No newline at end of file
diff --git a/metadata/service/client.yml b/metadata/service/client.yml
index ccd42f7..b46a69a 100644
--- a/metadata/service/client.yml
+++ b/metadata/service/client.yml
@@ -7,12 +7,10 @@
client:
enabled: true
version: 2.4.2
- download_url: https://storage.googleapis.com/kubernetes-helm/helm-v${helm:client:version}-linux-amd64.tar.gz
download_hash: sha256=96f74ff04ec7eb38e5f53aba73132bfe4d6b81168f20574dad25a9bcaceec81b
tiller:
install: true
namespace: kube-system
- host:
kubectl:
install: false
download_url: https://dl.k8s.io/v1.6.7/kubernetes-client-linux-amd64.tar.gz
diff --git a/pillar.example b/pillar.example
new file mode 100644
index 0000000..156b411
--- /dev/null
+++ b/pillar.example
@@ -0,0 +1,163 @@
+helm:
+ client:
+
+ #
+ # The version of the Helm client to install
+ #
+ # version: 2.6.2
+
+ #
+ # The hash for the helm client binary. You must calculate the hash for the
+ # version of the binary you install.
+ # Defaults to the SHA 256 hash for the helm-v2.6.2-linux-amd64.tar.gz
+ #
+ #
+ # The binary is downloaded from:
+ #
+ # https://storage.googleapis.com/kubernetes-helm/helm-v[[ client.version ]]-linux-amd64.tar.gz
+ #
+ # Here is an example command you can use to calculate the sha256 hash for
+ # the binary:
+ #
+ # ```
+ # shasum -a 256 /path/to/helm-v[[ client.version ]]-linux.amd64.tar.gz
+ # ```
+ #
+ # download_hash: sha256=ba807d6017b612a0c63c093a954c7d63918d3e324bdba335d67b7948439dbca8
+
+ #
+ # Whether the helm client should be enabled for the target minion or not
+ #
+ # TODO: this should be removed.
+ #
+ enabled: true
+
+ #
+ # Configurations to manage the cluster's Tiller installation
+ #
+ # tiller:
+ #
+ # Whether Tiller should be deployed to the kubernetes cluster as part of
+ # this formaul. Defaults to true.
+ #
+ # install: true
+
+ #
+ # The namespace to which Tiller should be installed (only used if
+ # `helm:client:tiller:install` is set to true).
+ # Defaults to `kube-system`
+ #
+ # naamespace: kube-system
+
+ #
+ # The host IP or name and port for an existing tiller installation that
+ # should be used by the Helm client. Defaults to Helm's default if
+ # unspecified.
+ #
+ # host:
+
+ #
+ # Configurations defined to manage the target minion's kubectl installation
+ #
+ # kubectl:
+ #
+ # Whether kubectl should be installed as part of this formula.
+ # Defaults to false
+ #
+ # install: false
+
+ #
+ # The version of the kubectl binary to install.
+ # Defaults to 1.6.7
+ #
+ # version: 1.6.7
+
+ #
+ # The hash for the kubectl binary version to install. You must calculate
+ # the hash for the version of the binary you install.
+ #
+ #
+ # The binary is downloaded from:
+ #
+ # https://dl.k8s.io/v[[ client.kubectl.version ]]/kubernetes-client-linux-amd64.tar.gz
+ #
+ #
+ # Defaults to the SHA 256 hash for the Linux distribution of version 1.6.7
+ #
+ # Here is an example command you can use to calculate the sha256 hash for
+ # the binary:
+ #
+ # ```
+ # shasum -a 256 /path/to/kubernetes-client-linux-amd64.tar.gz
+ # ```
+ #
+ # download_hash: sha256=54947ef84181e89f9dbacedd54717cbed5cc7f9c36cb37bc8afc9097648e2c91
+
+
+ #
+ # Configuration parameters that should be applied to the kubectl
+ # installation's kubeconfig. Not that this will only be applied to the
+ # kubectl installation managed by this formula.
+ #
+ # While the kubectl tool can be configured to connect to multiple
+ # clusters and allow switching between cluster contexts, this kubectl
+ # configuration managed by this formula will only be configured with
+ # the cluster context details used by this formula.
+ #
+ # config:
+ # cluster:
+ # server: https://kubernetes.example.com
+ # certificate-authority-data: base64_of_ca_certificate
+ # cluster_name: kubernetes.example
+ # context_name: kubernetes-example
+ # user:
+ # username: admin
+ # password: uberadminpass
+ # user_name: admin
+
+
+ #
+ # The mapping of repository names to urls that should be registered and
+ # kept up-to-date with the helm client
+ #
+ repos:
+ mirantisworkloads: https://mirantisworkloads.storage.googleapis.com/
+ incubator: https://kubernetes-charts-incubator.storage.googleapis.com/
+
+ #
+ # The listing of releases that should be managed by the formula. Note that
+ # if configured, the releases listed under this `helm:client:releases` key
+ # will be used as an authoritative, exclusive listing of the releases that
+ # should be configured and deployed to the Tiller installation; any
+ # release existing in the tiller cluster that is not configured here
+ # **will be deleted**
+ #
+ releases:
+ zoo1:
+
+ #
+ # The name of the release
+ #
+ name: my-zookeeper
+
+ #
+ # The repository name and chart name combination for the chart to
+ # release
+ #
+ chart: mirantisworkloads/zookeeper
+
+ #
+ # The version of the helm chart to install
+ #
+ version: 1.2.0
+
+ #
+ # The namespace to which the release should be deployed
+ #
+ namespace: helm-example-namespace
+
+ #
+ # Configuration values that should be supplied to the chart.
+ #
+ values:
+ logLevel: INFO
\ No newline at end of file
diff --git a/tests/pillar/single.sls b/tests/pillar/single.sls
index e8f824c..d2ae52c 100644
--- a/tests/pillar/single.sls
+++ b/tests/pillar/single.sls
@@ -2,18 +2,11 @@
client:
enabled: true
version: 2.6.0
- download_url: https://storage.googleapis.com/kubernetes-helm/helm-v2.6.0-linux-amd64.tar.gz
download_hash: sha256=506e477a9eb61730a2fb1af035357d35f9581a4ffbc093b59e2c2af7ea3beb41
- bind:
- address: 0.0.0.0
tiller:
install: false
host: 10.11.12.13:14151
kubectl:
- install: true # installs kubectl 1.6.7 by default
- download_url: https://dl.k8s.io/v1.6.7/kubernetes-client-linux-amd64.tar.gz
- download_hash: sha256=54947ef84181e89f9dbacedd54717cbed5cc7f9c36cb37bc8afc9097648e2c91
- tarball_path: kubernetes/client/bin/kubectl
config:
cluster: # directly translated to cluster definition in kubeconfig
server: https://kubernetes.example.com