Merge pull request #6 from ipedrazas/prefix

Prefix
This commit is contained in:
Ivan Pedrazas
2017-01-09 11:46:11 +00:00
committed by GitHub
7 changed files with 134 additions and 107 deletions
+10 -18
View File
@@ -19,22 +19,14 @@ pipeline:
- TAG=${DRONE_BRANCH}-${DRONE_COMMIT_SHA:0:7}
commands:
- docker login -u="${QUAY_USERNAME}" -p="${QUAY_PASSWORD}" quay.io
- docker build -t image .
- docker tag image quay.io/ipedrazas/drone-helm:latest
- docker build -t image .
# - docker tag image quay.io/ipedrazas/drone-helm:latest
- docker tag image quay.io/ipedrazas/drone-helm:${TAG}
- docker push quay.io/ipedrazas/drone-helm
when:
event: [push]
branch: [master]
helm_deploy:
image: quay.io/ipedrazas/drone-helm
skip_tls_verify: true
chart: stable/redis
release: ${DRONE_BRANCH}-drone-helm
api_server: $STAGING_API_SERVER
debug: true
# when:
# event: [push]
# branch: [master]
slack:
image: plugins/slack
channel: deploys
@@ -42,7 +34,7 @@ pipeline:
template: >
{{ build.author }} finished building *<http://drone.sohohousedigital.com/SohoHouse/{{ repo.name }}/{{ build.number }}|{{ build.branch }} ({{ build.number }})>* of {{ repo.name }} with a {{ build.status }} status
services:
dind:
image: docker:1.12-dind
@@ -50,13 +42,13 @@ services:
command:
- "-s"
- "overlay"
plugin:
name: drone-helm
desc: Execute helm to
desc: Execute helm to
type: deploy
image: quay.io/ipedrazas/drone-helm
labels:
- deploy
- kubernetes
- helm
- helm
+1 -1
View File
@@ -1 +1 @@
eyJhbGciOiJIUzI1NiJ9.d29ya3NwYWNlOgogIGJhc2U6IC9nbwoKcGlwZWxpbmU6CiAgdGVzdDoKICAgIGltYWdlOiBnb2xhbmc6MS42CiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBDR09fRU5BQkxFRD0wCiAgICBjb21tYW5kczoKICAgICAgLSBnbyBnZXQKICAgICAgLSBnbyB0ZXN0IC1jb3ZlciAtY292ZXJwcm9maWxlPWNvdmVyYWdlLm91dAogICAgICAtIGdvIGJ1aWxkIC1sZGZsYWdzICItcyAtdyAtWCBtYWluLmJ1aWxkPSREUk9ORV9CVUlMRF9OVU1CRVIiIC1hIC10YWdzIG5ldGdvCgoKICBidWlsZF9kb2NrZXJfaW1hZ2U6CiAgICBpbWFnZTogZG9ja2VyOjEuMTIKICAgIGVudmlyb25tZW50OgogICAgICAtIERPQ0tFUl9IT1NUPXRjcDovLzEyNy4wLjAuMToyMzc1CiAgICAgIC0gVEFHPSR7RFJPTkVfQlJBTkNIfS0ke0RST05FX0NPTU1JVF9TSEE6MDo3fQogICAgY29tbWFuZHM6CiAgICAgIC0gZG9ja2VyIGxvZ2luIC11PSIke1FVQVlfVVNFUk5BTUV9IiAtcD0iJHtRVUFZX1BBU1NXT1JEfSIgcXVheS5pbwogICAgICAtIGRvY2tlciBidWlsZCAtdCBpbWFnZSAuICAgICAgCiAgICAgIC0gZG9ja2VyIHRhZyBpbWFnZSBxdWF5LmlvL2lwZWRyYXphcy9kcm9uZS1oZWxtOmxhdGVzdAogICAgICAtIGRvY2tlciB0YWcgaW1hZ2UgcXVheS5pby9pcGVkcmF6YXMvZHJvbmUtaGVsbToke1RBR30KICAgICAgLSBkb2NrZXIgcHVzaCBxdWF5LmlvL2lwZWRyYXphcy9kcm9uZS1oZWxtCiAgICB3aGVuOgogICAgIGV2ZW50OiBbcHVzaF0KICAgICBicmFuY2g6IFttYXN0ZXJdCiAgCiAgaGVsbV9kZXBsb3k6ICAgIAogICAgaW1hZ2U6IHF1YXkuaW8vaXBlZHJhemFzL2Ryb25lLWhlbG0gICAgCiAgICBza2lwX3Rsc192ZXJpZnk6IHRydWUKICAgIGNoYXJ0OiBzdGFibGUvcmVkaXMKICAgIHJlbGVhc2U6ICR7RFJPTkVfQlJBTkNIfS1kcm9uZS1oZWxtICAgIAogICAgYXBpX3NlcnZlcjogJFNUQUdJTkdfQVBJX1NFUlZFUgogICAgZGVidWc6IHRydWUKICAKICBzbGFjazoKICAgIGltYWdlOiBwbHVnaW5zL3NsYWNrCiAgICBjaGFubmVsOiBkZXBsb3lzCiAgICB1c2VybmFtZTogZHJvbmUKICAgIHRlbXBsYXRlOiA-CiAgICAgIHt7IGJ1aWxkLmF1dGhvciB9fSBmaW5pc2hlZCBidWlsZGluZyAgKjxodHRwOi8vZHJvbmUuc29ob2hvdXNlZGlnaXRhbC5jb20vU29ob0hvdXNlL3t7IHJlcG8ubmFtZSB9fS97eyBidWlsZC5udW1iZXIgfX18e3sgYnVpbGQuYnJhbmNoIH19ICh7eyBidWlsZC5udW1iZXIgfX0pPiogb2Yge3sgcmVwby5uYW1lIH19ICB3aXRoIGEge3sgYnVpbGQuc3RhdHVzIH19IHN0YXR1cwoKICAgICAgICAKc2VydmljZXM6CiAgZGluZDoKICAgIGltYWdlOiBkb2NrZXI6MS4xMi1kaW5kCiAgICBwcml2aWxlZ2VkOiB0cnVlCiAgICBjb21tYW5kOgogICAgICAtICItcyIKICAgICAgLSAib3ZlcmxheSIKICAKcGx1Z2luOgogIG5hbWU6IGRyb25lLWhlbG0KICBkZXNjOiBFeGVjdXRlIGhlbG0gdG8gCiAgdHlwZTogZGVwbG95CiAgaW1hZ2U6IHF1YXkuaW8vaXBlZHJhemFzL2Ryb25lLWhlbG0KICBsYWJlbHM6CiAgICAtIGRlcGxveQogICAgLSBrdWJlcm5ldGVzCiAgICAtIGhlbG0.lbTVbRgOWKvlqaZY0RVnJO8zw4niLBZ9yOCXqJTKoKA
eyJhbGciOiJIUzI1NiJ9.d29ya3NwYWNlOgogIGJhc2U6IC9nbwoKcGlwZWxpbmU6CiAgdGVzdDoKICAgIGltYWdlOiBnb2xhbmc6MS42CiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBDR09fRU5BQkxFRD0wCiAgICBjb21tYW5kczoKICAgICAgLSBnbyBnZXQKICAgICAgLSBnbyB0ZXN0IC1jb3ZlciAtY292ZXJwcm9maWxlPWNvdmVyYWdlLm91dAogICAgICAtIGdvIGJ1aWxkIC1sZGZsYWdzICItcyAtdyAtWCBtYWluLmJ1aWxkPSREUk9ORV9CVUlMRF9OVU1CRVIiIC1hIC10YWdzIG5ldGdvCgoKICBidWlsZF9kb2NrZXJfaW1hZ2U6CiAgICBpbWFnZTogZG9ja2VyOjEuMTIKICAgIGVudmlyb25tZW50OgogICAgICAtIERPQ0tFUl9IT1NUPXRjcDovLzEyNy4wLjAuMToyMzc1CiAgICAgIC0gVEFHPSR7RFJPTkVfQlJBTkNIfS0ke0RST05FX0NPTU1JVF9TSEE6MDo3fQogICAgY29tbWFuZHM6CiAgICAgIC0gZG9ja2VyIGxvZ2luIC11PSIke1FVQVlfVVNFUk5BTUV9IiAtcD0iJHtRVUFZX1BBU1NXT1JEfSIgcXVheS5pbwogICAgICAtIGRvY2tlciBidWlsZCAtdCBpbWFnZSAuCiAgICAgICMgLSBkb2NrZXIgdGFnIGltYWdlIHF1YXkuaW8vaXBlZHJhemFzL2Ryb25lLWhlbG06bGF0ZXN0CiAgICAgIC0gZG9ja2VyIHRhZyBpbWFnZSBxdWF5LmlvL2lwZWRyYXphcy9kcm9uZS1oZWxtOiR7VEFHfQogICAgICAtIGRvY2tlciBwdXNoIHF1YXkuaW8vaXBlZHJhemFzL2Ryb25lLWhlbG0KICAgICMgd2hlbjoKICAgICMgIGV2ZW50OiBbcHVzaF0KICAgICMgIGJyYW5jaDogW21hc3Rlcl0KCiAgc2xhY2s6CiAgICBpbWFnZTogcGx1Z2lucy9zbGFjawogICAgY2hhbm5lbDogZGVwbG95cwogICAgdXNlcm5hbWU6IGRyb25lCiAgICB0ZW1wbGF0ZTogPgogICAgICB7eyBidWlsZC5hdXRob3IgfX0gZmluaXNoZWQgYnVpbGRpbmcgICo8aHR0cDovL2Ryb25lLnNvaG9ob3VzZWRpZ2l0YWwuY29tL1NvaG9Ib3VzZS97eyByZXBvLm5hbWUgfX0ve3sgYnVpbGQubnVtYmVyIH19fHt7IGJ1aWxkLmJyYW5jaCB9fSAoe3sgYnVpbGQubnVtYmVyIH19KT4qIG9mIHt7IHJlcG8ubmFtZSB9fSAgd2l0aCBhIHt7IGJ1aWxkLnN0YXR1cyB9fSBzdGF0dXMKCgpzZXJ2aWNlczoKICBkaW5kOgogICAgaW1hZ2U6IGRvY2tlcjoxLjEyLWRpbmQKICAgIHByaXZpbGVnZWQ6IHRydWUKICAgIGNvbW1hbmQ6CiAgICAgIC0gIi1zIgogICAgICAtICJvdmVybGF5IgoKcGx1Z2luOgogIG5hbWU6IGRyb25lLWhlbG0KICBkZXNjOiBFeGVjdXRlIGhlbG0gdG8KICB0eXBlOiBkZXBsb3kKICBpbWFnZTogcXVheS5pby9pcGVkcmF6YXMvZHJvbmUtaGVsbQogIGxhYmVsczoKICAgIC0gZGVwbG95CiAgICAtIGt1YmVybmV0ZXMKICAgIC0gaGVsbQo.0Iy83mRnXUfgUp0truytDq8Vvvc0qo2GpGEoWzdS2XI
+2 -26
View File
@@ -1,31 +1,7 @@
FROM alpine:latest
FROM ipedrazas/k8s:latest
MAINTAINER Ivan Pedrazas <ipedrazas@gmail.com>
RUN apk -Uuv add curl bash && rm /var/cache/apk/*
ENV HELM_VERSION v2.1.0
ENV FILENAME helm-${HELM_VERSION}-linux-amd64.tar.gz
ENV KUBECTL v1.5.1
ADD http://storage.googleapis.com/kubernetes-helm/${FILENAME} /tmp
ADD https://storage.googleapis.com/kubernetes-release/release/${KUBECTL}/bin/linux/amd64/kubectl /tmp
RUN tar -zxvf /tmp/${FILENAME} -C /tmp \
&& mv /tmp/linux-amd64/helm /bin/helm \
&& chmod +x /bin/helm \
&& chmod +x /tmp/kubectl \
&& mv /tmp/kubectl /bin/kubectl \
&& rm -rf /tmp
LABEL description="Drone.io plugin for Helm (kubernetes)."
LABEL base="alpine"
LABEL helm=${FILENAME}
LABEL kubectl=${KUBECTL}
COPY drone-helm /bin/drone-helm
COPY kubeconfig /root/.kube/kubeconfig
ENTRYPOINT [ "/bin/drone-helm" ]
ENTRYPOINT [ "/bin/drone-helm" ]
+3 -4
View File
@@ -37,17 +37,16 @@ To test the plugin, you can run `minikube` and just run the docker image as foll
docker run --rm \
-e PLUGIN_API_SERVER=https://192.168.64.5:8443 \
-e PLUGIN_TOKEN="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJrdWJlcm5ld..." \
-e PLUGIN_TOKEN="" \
-e PLUGIN_NAMESPACE=default \
-e PLUGIN_SKIP_TLS_VERIFY=true \
-e PLUGIN_RELEASE=my-release \
-e PLUGIMN_CHART=stable/jenkins \
-e PLUGIMN_CHART=stable/redis \
-e PLUGIN_VALUES="tag=TAG,api=API" \
-e PLUGIN_SECRETS=TAG,API \
-e TAG=v1.0.1 \
-e API=http://myapi \
-e PLUGIN_DEBUG=true \
-e PLUGIN_DRY_RUN=true \
-e DRONE_BUILD_EVENT=delete \
quay.io/ipedrazas/drone-helm
+2 -17
View File
@@ -23,16 +23,6 @@ func main() {
Usage: "add the command Helm has to execute",
EnvVar: "PLUGIN_HELM_COMMAND,HELM_COMMAND",
},
cli.StringFlag{
Name: "api_server",
Usage: "Api Server url",
EnvVar: "PLUGIN_API_SERVER,API_SERVER",
},
cli.StringFlag{
Name: "token",
Usage: "Kubernetes Token",
EnvVar: "PLUGIN_TOKEN,KUBERNETES_TOKEN",
},
cli.StringFlag{
Name: "namespace",
Usage: "Kubernetes namespace",
@@ -68,12 +58,7 @@ func main() {
Usage: "Helm dry-run",
EnvVar: "PLUGIN_DRY_RUN,DRY_RUN",
},
cli.StringSliceFlag{
Name: "secrets",
Usage: "add the secrets used in the values field",
EnvVar: "PLUGIN_SECRETS,SECRETS",
},
cli.StringSliceFlag{
cli.StringFlag{
Name: "prefix",
Usage: "Prefix for all the secrets",
EnvVar: "PLUGIN_PREFIX,PREFIX",
@@ -105,6 +90,6 @@ func run(c *cli.Context) error {
},
}
resolveSecrets(&plugin)
plugin.debug()
return plugin.Exec()
}
+60 -22
View File
@@ -2,13 +2,13 @@ package main
import (
"fmt"
"github.com/alecthomas/template"
"io/ioutil"
"log"
"os"
"os/exec"
"regexp"
"strings"
"github.com/alecthomas/template"
)
var HELM_BIN = "/bin/helm"
@@ -37,7 +37,18 @@ type (
}
)
func setHelmCommand(p *Plugin) {
func setHelmHelp(p *Plugin) {
p.Config.HelmCommand = []string{""}
}
func setDeleteEventCommand(p *Plugin) {
upgrade := make([]string, 2)
upgrade[0] = "delete"
upgrade[1] = p.Config.Release
p.Config.HelmCommand = upgrade
}
func setPushEventCommand(p *Plugin) {
upgrade := make([]string, 2)
upgrade[0] = "upgrade"
upgrade[1] = "--install"
@@ -56,10 +67,25 @@ func setHelmCommand(p *Plugin) {
upgrade = append(upgrade, "--debug")
}
p.Config.HelmCommand = upgrade
}
func setHelmCommand(p *Plugin) {
buildEvent := os.Getenv("DRONE_BUILD_EVENT")
switch buildEvent {
case "push":
setPushEventCommand(p)
case "delete":
setDeleteEventCommand(p)
default:
setHelmHelp(p)
}
}
// Exec default method
func (p *Plugin) Exec() error {
resolveSecrets(p)
if p.Config.APIServer == "" {
return fmt.Errorf("Error: API Server is needed to deploy.")
}
@@ -72,13 +98,13 @@ func (p *Plugin) Exec() error {
p.debug()
}
fmt.Println(p)
init := make([]string, 1)
init[0] = "init"
err := runCommand(init)
if err != nil {
return fmt.Errorf("Error running helm comand: " + strings.Join(init[:], " "))
}
setHelmCommand(p)
if p.Config.Debug {
log.Println("helm comand: " + strings.Join(p.Config.HelmCommand[:], " "))
@@ -110,32 +136,44 @@ func runCommand(params []string) error {
}
func resolveSecrets(p *Plugin) {
if len(p.Config.Secrets) > 0 {
for _, secret := range p.Config.Secrets {
envval := os.Getenv(secret)
p.Config.Values = resolveEnvVar(p.Config.Values, secret, envval)
p.Config.APIServer = resolveEnvVar(p.Config.APIServer, secret, envval)
p.Config.Token = resolveEnvVar(p.Config.Token, secret, envval)
}
}
p.Config.Values = resolveEnvVar(p.Config.Values, p.Config.Prefix)
p.Config.APIServer = resolveEnvVar("${API_SERVER}", p.Config.Prefix)
p.Config.Token = resolveEnvVar("${TOKEN}", p.Config.Prefix)
}
// this functions checks if $VAR or ${VAR} exists and
// returns the text with resolved vars
func resolveEnvVar(key string, envvar string, envval string) string {
if strings.Contains(key, "$"+envvar) {
key = strings.Replace(key, "$"+envvar, envval, -1)
// getEnvVars will return [${TAG} {TAG} TAG]
func getEnvVars(envvars string) [][]string {
re := regexp.MustCompile(`\$(\{?(\w+)\}?)\.?`)
extracted := re.FindAllStringSubmatch(envvars, -1)
return extracted
}
func resolveEnvVar(key string, prefix string) string {
envvars := getEnvVars(key)
return replaceEnvvars(envvars, prefix, key)
}
func replaceEnvvars(envvars [][]string, prefix string, s string) string {
for _, envvar := range envvars {
// [${TAG} {TAG} TAG]
envvarName := envvar[0]
envvarKey := envvar[2]
if prefix != "" {
envvarKey = prefix + "_" + envvarKey
}
envval := os.Getenv(envvarKey)
if strings.Contains(s, envvarName) {
s = strings.Replace(s, envvarName, envval, -1)
}
}
if strings.Contains(key, "${"+envvar+"}") {
key = strings.Replace(key, "${"+envvar+"}", envval, -1)
}
return key
return s
}
func (p *Plugin) debug() {
fmt.Println(p)
// debug env vars
for _, e := range os.Environ() {
fmt.Println(e)
fmt.Println("-Var:--", e)
}
// debug plugin obj
fmt.Printf("Api server: %s \n", p.Config.APIServer)
+56 -19
View File
@@ -41,6 +41,7 @@ func TestInitialiseKubeconfig(t *testing.T) {
}
func TestGetHelmCommand(t *testing.T) {
os.Setenv("DRONE_BUILD_EVENT", "push")
plugin := &Plugin{
Config: Config{
APIServer: "http://myapiserver",
@@ -64,18 +65,14 @@ func TestGetHelmCommand(t *testing.T) {
}
func TestResolveSecrets(t *testing.T) {
secrets := make([]string, 2)
secrets[0] = "TAG"
secrets[1] = "API_SERVER"
tag := "v0.1.1"
api := "http://apiserver"
os.Setenv("TAG", tag)
os.Setenv("API_SERVER", api)
os.Setenv("MY_TAG", tag)
os.Setenv("MY_API_SERVER", api)
os.Setenv("MY_TOKEN", "12345")
plugin := &Plugin{
Config: Config{
APIServer: "${API_SERVER}",
Token: "secret-token",
HelmCommand: nil,
Namespace: "default",
SkipTLSVerify: true,
@@ -83,26 +80,66 @@ func TestResolveSecrets(t *testing.T) {
DryRun: true,
Chart: "./chart/test",
Release: "test-release",
Prefix: "MY",
Values: "image.tag=$TAG,api=${API_SERVER},nameOverride=my-over-app,second.tag=${TAG}",
Secrets: secrets,
},
}
resolveSecrets(plugin)
// test that the subsitution works
if !strings.Contains(plugin.Config.Values, tag) {
t.Errorf("env var %s not resolved %s", secrets[0], tag)
t.Errorf("env var ${TAG} not resolved %s", tag)
}
// test that subistutes more than 1 envvar
if strings.Contains(plugin.Config.Values, secrets[0]) {
t.Errorf("env var %s not resolved %s", secrets[0], tag)
if strings.Contains(plugin.Config.Values, "${TAG}") {
t.Errorf("env var ${TAG} not resolved %s", tag)
}
// // test that the subsitution works with more than one envvar
if strings.Contains(plugin.Config.Values, secrets[1]) {
t.Errorf("env var %s not resolved %s", secrets[1], api)
}
// // test that the subsitution works with more than one envvar
if strings.Contains(plugin.Config.APIServer, secrets[1]) {
t.Errorf("env var %s not resolved %s", secrets[1], api)
if plugin.Config.APIServer != api {
t.Errorf("env var ${API_SERVER} not resolved %s", api)
}
}
func TestGetEnvVars(t *testing.T) {
testText := "this should be ${TAG} now"
result := getEnvVars(testText)
if len(result) == 0 {
t.Error("No envvar was found")
}
envvar := result[0]
if !strings.Contains(envvar[2], "TAG") {
t.Errorf("envvar not found in %s", testText)
}
}
func TestReplaceEnvvars(t *testing.T) {
tag := "tagged"
os.Setenv("MY_TAG", tag)
prefix := "MY"
testText := "this should be ${TAG} now ${TAG}"
result := getEnvVars(testText)
resolved := replaceEnvvars(result, prefix, testText)
if !strings.Contains(resolved, tag) {
t.Errorf("EnvVar MY_TAG no replaced by %s -- %s \n", tag, resolved)
}
}
func TestSetHelmHelp(t *testing.T) {
plugin := &Plugin{
Config: Config{
HelmCommand: nil,
Namespace: "default",
SkipTLSVerify: true,
Debug: true,
DryRun: true,
Chart: "./chart/test",
Release: "test-release",
Prefix: "MY",
Values: "image.tag=$TAG,api=${API_SERVER},nameOverride=my-over-app,second.tag=${TAG}",
},
}
setHelmHelp(plugin)
if plugin.Config.HelmCommand == nil {
t.Error("Helm help is not displayed")
}
}