Merge pull request #66 from TDabasinskas/master

Implement helm dependency update
This commit is contained in:
Ivan Pedrazas
2018-06-12 10:31:44 +01:00
committed by GitHub
5 changed files with 129 additions and 61 deletions
+1
View File
@@ -27,3 +27,4 @@ drone-helm
*.test
*.out
.vscode
.idea
+39 -6
View File
@@ -31,6 +31,7 @@ pipeline:
Last update of Drone expect you to declare the secrets you want to use:
```YAML
pipeline:
helm_deploy:
image: quay.io/ipedrazas/drone-helm
chart: ./chart/blog
@@ -43,6 +44,7 @@ Last update of Drone expect you to declare the secrets you want to use:
```
Use Kubernetes Certificate Authority Data. Just add the `<prefix>_kubernetes_certificate` secret
```diff
helm_deploy:
image: quay.io/ipedrazas/drone-helm
@@ -61,7 +63,7 @@ Use Kubernetes Certificate Authority Data. Just add the `<prefix>_kubernetes_cer
Values can be passed using the `values_files` key. Use this option to define your values in a set of files
and pass them to `helm`. This option trigger the `-f` or ``--values`` flag in `helm`:
```
```plain
--values valueFiles specify values in a YAML file (can specify multiple) (default [])
```
@@ -84,8 +86,10 @@ pipeline:
Charts can also be fetched from your own private Chart Repository. `helm_repos` accepts a comma separated list of key value pairs where the key is the repository name and the value is the repository url.
For Example:
```
helm_deploy_staging:
```YAML
pipeline:
helm_deploy_staging:
image: quay.io/ipedrazas/drone-helm
skip_tls_verify: true
helm_repos: hb-charts=http://helm-charts.honestbee.com
@@ -98,11 +102,37 @@ helm_deploy_staging:
exclude: [ master ]
```
## Updating Chart dependencies
In some cases, the local Chart might contain external dependencies defined in `./charts/my-chart/requirements.yaml`, e.g.:
```YAML
dependencies:
- name: redis
version: 3.3.6
repository: '@stable'
```
To restore these dependecies before the deployment `update_dependencies` parameter should be used, e.g.:
```YAML
pipeline:
helm_deploy:
image: quay.io/ipedrazas/drone-helm
skip_tls_verify: true
chart: ./charts/my-chart
update_dependencies: true
release: ${DRONE_BRANCH}
values_files: ["global-values.yaml", "myenv-values.yaml"]
when:
branch: [master]
```
## Drone Secrets
There are two secrets you have to create (Note that if you specify the prefix, your secrets have to be created using that prefix):
```Bash
```bash
drone secret add --image=quay.io/ipedrazas/drone-helm \
your-user/your-repo STAGING_API_SERVER https://mykubernetesapiserver
@@ -114,6 +144,7 @@ drone secret add --image=quay.io/ipedrazas/drone-helm \
```
`Prefix` helps you to use the same block in different environments:
```YAML
pipeline:
helm_deploy_staging:
@@ -145,7 +176,6 @@ pipeline_production:
This last block defines how the plugin will deploy
## Testing with Minikube
To test the plugin, you can run `minikube` and just run the docker image as follows:
@@ -169,7 +199,8 @@ KUBERNETES_TOKEN=$(kubectl get secret $(kubectl get sa default -o jsonpath='{.se
```
Run the local image (or replace `drone-helm` with `quay.io/ipedrazas/drone-helm`:
```Bash
```bash
docker run --rm \
-e API_SERVER="https://$(minikube ip):8443" \
-e KUBERNETES_TOKEN="${KUBERNETES_TOKEN}" \
@@ -189,6 +220,7 @@ docker run --rm \
This plugin installs [Tiller](https://github.com/kubernetes/helm/blob/master/docs/architecture.md) in the cluster, if you want to specify the namespace where `tiller` ins installed, use the `tiller_ns` attribute.
The following example will install `tiller` in the `operations` namespace:
```YAML
pipeline_production:
helm_deploy:
@@ -218,6 +250,7 @@ pipeline_production:
when:
branch: [master]
```
Happy Helming!
## Known issues
+33 -27
View File
@@ -134,6 +134,11 @@ func main() {
Usage: "purge on delete",
EnvVar: "PLUGIN_PURGE,PURGE",
},
cli.BoolFlag{
Name: "update-dependencies",
Usage: "update dependency charts based on the contents of requirements.yaml file of the local chart",
EnvVar: "PLUGIN_UPDATE_DEPENDENCIES,UPDATE_DEPENDENCIES",
},
}
if err := app.Run(os.Args); err != nil {
logrus.Fatal(err)
@@ -146,33 +151,34 @@ func run(c *cli.Context) error {
}
plugin := Plugin{
Config: Config{
APIServer: c.String("api_server"),
Token: c.String("token"),
Certificate: c.String("certificate"),
ServiceAccount: c.String("service-account"),
KubeConfig: c.String("kube-config"),
HelmCommand: c.String("helm_command"),
Namespace: c.String("namespace"),
SkipTLSVerify: c.Bool("skip_tls_verify"),
Values: c.String("values"),
ValuesFiles: c.String("values_files"),
Release: c.String("release"),
HelmRepos: c.StringSlice("helm_repos"),
Chart: c.String("chart"),
Version: c.String("chart-version"),
Debug: c.Bool("debug"),
DryRun: c.Bool("dry-run"),
Secrets: c.StringSlice("secrets"),
Prefix: c.String("prefix"),
TillerNs: c.String("tiller-ns"),
Wait: c.Bool("wait"),
RecreatePods: c.Bool("recreate-pods"),
ClientOnly: c.Bool("client-only"),
CanaryImage: c.Bool("canary-image"),
Upgrade: c.Bool("upgrade"),
ReuseValues: c.Bool("reuse-values"),
Timeout: c.String("timeout"),
Force: c.Bool("force"),
APIServer: c.String("api_server"),
Token: c.String("token"),
Certificate: c.String("certificate"),
ServiceAccount: c.String("service-account"),
KubeConfig: c.String("kube-config"),
HelmCommand: c.String("helm_command"),
Namespace: c.String("namespace"),
SkipTLSVerify: c.Bool("skip_tls_verify"),
Values: c.String("values"),
ValuesFiles: c.String("values_files"),
Release: c.String("release"),
HelmRepos: c.StringSlice("helm_repos"),
Chart: c.String("chart"),
Version: c.String("chart-version"),
Debug: c.Bool("debug"),
DryRun: c.Bool("dry-run"),
Secrets: c.StringSlice("secrets"),
Prefix: c.String("prefix"),
TillerNs: c.String("tiller-ns"),
Wait: c.Bool("wait"),
RecreatePods: c.Bool("recreate-pods"),
ClientOnly: c.Bool("client-only"),
CanaryImage: c.Bool("canary-image"),
Upgrade: c.Bool("upgrade"),
ReuseValues: c.Bool("reuse-values"),
Timeout: c.String("timeout"),
Force: c.Bool("force"),
UpdateDependencies: c.Bool("update-dependencies"),
},
}
return plugin.Exec()
+46 -28
View File
@@ -19,34 +19,35 @@ var KUBECONFIG = "/root/.kube/kubeconfig"
type (
// Config maps the params we need to run Helm
Config struct {
APIServer string `json:"api_server"`
Token string `json:"token"`
Certificate string `json:"certificate"`
ServiceAccount string `json:"service_account"`
KubeConfig string `json:"kube_config"`
HelmCommand string `json:"helm_command"`
SkipTLSVerify bool `json:"tls_skip_verify"`
Namespace string `json:"namespace"`
Release string `json:"release"`
Chart string `json:"chart"`
Version string `json:"version"`
Values string `json:"values"`
ValuesFiles string `json:"values_files"`
Debug bool `json:"debug"`
DryRun bool `json:"dry_run"`
Secrets []string `json:"secrets"`
Prefix string `json:"prefix"`
TillerNs string `json:"tiller_ns"`
Wait bool `json:"wait"`
RecreatePods bool `json:"recreate_pods"`
Upgrade bool `json:"upgrade"`
CanaryImage bool `json:"canary_image"`
ClientOnly bool `json:"client_only"`
ReuseValues bool `json:"reuse_values"`
Timeout string `json:"timeout"`
Force bool `json:"force"`
HelmRepos []string `json:"helm_repos"`
Purge bool `json:"purge"`
APIServer string `json:"api_server"`
Token string `json:"token"`
Certificate string `json:"certificate"`
ServiceAccount string `json:"service_account"`
KubeConfig string `json:"kube_config"`
HelmCommand string `json:"helm_command"`
SkipTLSVerify bool `json:"tls_skip_verify"`
Namespace string `json:"namespace"`
Release string `json:"release"`
Chart string `json:"chart"`
Version string `json:"version"`
Values string `json:"values"`
ValuesFiles string `json:"values_files"`
Debug bool `json:"debug"`
DryRun bool `json:"dry_run"`
Secrets []string `json:"secrets"`
Prefix string `json:"prefix"`
TillerNs string `json:"tiller_ns"`
Wait bool `json:"wait"`
RecreatePods bool `json:"recreate_pods"`
Upgrade bool `json:"upgrade"`
CanaryImage bool `json:"canary_image"`
ClientOnly bool `json:"client_only"`
ReuseValues bool `json:"reuse_values"`
Timeout string `json:"timeout"`
Force bool `json:"force"`
HelmRepos []string `json:"helm_repos"`
Purge bool `json:"purge"`
UpdateDependencies bool `json:"update_dependencies"`
}
// Plugin default
Plugin struct {
@@ -206,6 +207,17 @@ func doHelmInit(p *Plugin) []string {
}
func doDependencyUpdate(chart string) []string {
dependencyUpdate := []string{
"dependency",
"update",
chart,
}
return dependencyUpdate
}
// Exec default method
func (p *Plugin) Exec() error {
if p.Config.Debug {
@@ -254,6 +266,12 @@ func (p *Plugin) Exec() error {
}
}
if p.Config.UpdateDependencies {
if err = runCommand(doDependencyUpdate(p.Config.Chart)); err != nil {
return fmt.Errorf("Error updating dependencies: " + err.Error())
}
}
setHelmCommand(p)
if p.Config.Debug {
+10
View File
@@ -292,6 +292,16 @@ func TestDetHelmRepoAdd(t *testing.T) {
}
}
func TestDependencyUpdate(t *testing.T) {
chart := "./chart"
expected := "dependency update ./chart"
result := strings.Join(doDependencyUpdate(chart), " ")
if expected != result {
t.Errorf("Helm cannot update repositories - expected %q - got %q", expected, result)
}
}
func TestHelmAddRepositoryError(t *testing.T) {
_, err := doHelmRepoAdd("drone-helm=bad://drone-helm.example.com:443/stable")
if err == nil {