mirror of
https://github.com/ipedrazas/drone-helm.git
synced 2026-06-04 10:15:19 +08:00
Merge pull request #66 from TDabasinskas/master
Implement helm dependency update
This commit is contained in:
@@ -27,3 +27,4 @@ drone-helm
|
||||
*.test
|
||||
*.out
|
||||
.vscode
|
||||
.idea
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user