go (#13)
Some checks are pending
ci/woodpecker/push/woodpecker Pipeline is pending
ci/woodpecker/tag/woodpecker Pipeline was successful

Co-authored-by: SebClem <seb6596@gmail.com>
Reviewed-on: #13
This commit is contained in:
sebclem 2023-07-04 16:38:22 +02:00
parent fd7d6f3ba5
commit 7a51a48cd2
8 changed files with 291 additions and 166 deletions

View File

@ -6,6 +6,7 @@ pipeline:
cache_from: git.sebclem.fr/sebclem/${CI_REPO_NAME}
registry: git.sebclem.fr
dry_run: true
auto_tag: true
logins:
- registry: https://git.sebclem.fr
username:
@ -19,7 +20,7 @@ pipeline:
image: woodpeckerci/plugin-docker-buildx
settings:
platforms: linux/amd64
tag: latest
auto_tag: true
repo: git.sebclem.fr/sebclem/${CI_REPO_NAME}
cache_from: git.sebclem.fr/sebclem/${CI_REPO_NAME}
logins:
@ -29,5 +30,5 @@ pipeline:
password:
from_secret: docker_token
when:
environment: production
event: deployment
event:
- tag

View File

@ -1,12 +1,24 @@
FROM python:3.11.4-slim
FROM golang:1.20.5-alpine AS build-stage
RUN apt-get update && apt-get install -y git toilet \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY *.go ./
RUN CGO_ENABLED=0 GOOS=linux go build -o /entrypoint
FROM python:3.11.4-slim AS runtime-stage
# RUN apt-get update && apt-get install -y git toilet \
# && rm -rf /var/lib/apt/lists/*
# renovate: datasource=pypi depName=ansible
ENV ANSIBLE_VERSION=8.1.0
RUN pip3 install --no-cache-dir ansible==${ANSIBLE_VERSION} dnspython passlib netaddr
COPY entrypoint /bin/entrypoint
COPY --from=build-stage /entrypoint /bin/entrypoint
ENTRYPOINT [ "/bin/entrypoint" ]

View File

@ -6,39 +6,43 @@ kind: pipeline
name: default
steps:
- name: Check ansible syntax
image: harbor.sebclem.fr/sebclem/drone-ansible-runner
check-ansible-syntax:
image: git.sebclem.fr/sebclem/woodpecker-ansible-runner
pull: true
settings:
playbook: sites.yml
playbook: playbooks/install.yml
galaxy_file: roles/requirements.yml
check_syntax: true
vault_token:
from_secret: ansible_vault_password
private_key:
from_secret: ansible_private_key
from_secret: ansible_vault_token
when:
event:
- push
- custom
- event: "push"
branch: [main, master]
- event: [pull_request, manual, deployment]
- name: Run ansible playbook
image: harbor.sebclem.fr/sebclem/drone-ansible-runner
run-ansible-playbook:
image: git.sebclem.fr/sebclem/woodpecker-ansible-runner
pull: true
settings:
verbosity: ${verbosity=1}
verbosity: ${verbosity=0}
diff: ${diff=false}
check: ${check=false}
limit: ${limit}
tags: ${tags}
playbook: sites.yml
playbook: playbooks/install.yml
galaxy_file: roles/requirements.yml
check_syntax: true
vault_token:
from_secret: ansible_vault_password
from_secret: ansible_vault_token
private_key:
from_secret: ansible_private_key
limit: harbor.home
when:
event:
- promote
- rollback
- custom
environment: production
event: deployment
when:
- event: "push"
branch: [main, master]
- event: [pull_request, manual, deployment]
```

View File

@ -1,82 +0,0 @@
#!/bin/bash
check=${PLUGIN_CHECK_SYNTAX:-false}
verbosity=${PLUGIN_VERBOSITY:-0}
C_RESET="\e[39m"
C_RED="\e[31m"
C_YELLOW="\e[33m"
C_BLUE="\e[34m"
run_command(){
echo "➡️ $@"
$@
}
echo -e "${C_BLUE}"
toilet -f smblock Woodpecker Ansible
toilet -f smblock " Runner"
echo -e "${C_RESET}"
if [ -z "$PLUGIN_PLAYBOOK" ]; then
echo -e "⚠️ ${C_RED}'playbook' setting not defined, ABORT!${C_RESET}"
exit 1
fi
if [ -z "$PLUGIN_PRIVATE_KEY" ]; then
echo -e "⚠️ ${C_YELLOW}[WARN] 'private_key' setting not defined !${C_RESET}"
else
run_command "mkdir /root/.ssh"
echo "$PLUGIN_PRIVATE_KEY" > /root/.ssh/id_ed25519
run_command chmod 400 /root/.ssh/id_ed25519
fi
args=("$PLUGIN_PLAYBOOK")
if [ -n "$PLUGIN_VAULT_TOKEN" ]; then
echo "💼 Adding vault token to 'credentials/ci_vault_token'"
run_command "mkdir credentials"
echo "$PLUGIN_VAULT_TOKEN" > credentials/ci_vault_token
args+=("--vault-password-file=credentials/ci_vault_token")
echo "⚙️ Clean ansible.cfg"
echo "➡️ sed -i '/vault_password_file.*/d' ./ansible.cfg"
sed -i '/vault_password_file.*/d' ./ansible.cfg
echo ""
fi
if [ -f "ansible-ci.cfg" ]; then
echo "⚙️ ansible-ci.cfg is present, using it."
rm ansible.cfg
mv ansible-ci.cfg ansible.cfg
echo ""
fi
if [ -n "$PLUGIN_GALAXY_FILE" ]; then
echo "🚀 Installing Galaxy dependencies ($PLUGIN_GALAXY_FILE)"
run_command "ansible-galaxy install -r $PLUGIN_GALAXY_FILE --force"
echo ""
fi
if [[ $check = true ]]; then
args+=("--syntax-check")
fi
if [[ $verbosity != "0" ]]; then
verb="-"
for i in `seq 1 $verbosity`; do
verb+="v"
done
args+=("$verb")
fi
if [[ -n "$PLUGIN_LIMIT" ]]; then
args+=("--limit" "$PLUGIN_LIMIT")
fi
if [[ -n "$PLUGIN_TAGS" ]]; then
args+=("--tags" "$PLUGIN_TAGS")
fi
run_command "export ANSIBLE_HOST_KEY_CHECKING=False"
echo "➡️ ansible-playbook ${args[@]}"
ansible-playbook "${args[@]}"

219
entrypoint.go Normal file
View File

@ -0,0 +1,219 @@
package main
import (
"os"
"os/exec"
"strconv"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
type pluginConfig struct {
check_syntax bool
check bool
diff bool
verbosity int64
limit *string
tags *string
privateKey *string
vaultToken *string
galaxyFile *string
playbook *string
}
func runCommand(sugar *zap.SugaredLogger, args ...string) {
sugar.Infof("➡️ %s", args)
cmd := exec.Command(args[0], args[1:]...)
cmd.Env = os.Environ()
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
os.Exit(1)
}
}
func getPluginConfig(sugar *zap.SugaredLogger) pluginConfig {
config := pluginConfig{}
check_syntax, present := os.LookupEnv("PLUGIN_CHECK_SYNTAX")
if !present {
config.check_syntax = false
} else {
converted, err := strconv.ParseBool(check_syntax)
if err != nil {
sugar.Fatal(err)
}
config.check_syntax = converted
}
check, present := os.LookupEnv("PLUGIN_CHECK")
if !present {
config.check = false
} else {
converted, err := strconv.ParseBool(check)
if err != nil {
sugar.Fatal(err)
}
config.check = converted
}
diff, present := os.LookupEnv("PLUGIN_DIFF")
if !present {
config.diff = false
} else {
converted, err := strconv.ParseBool(diff)
if err != nil {
sugar.Fatal(err)
}
config.diff = converted
}
verbosity, present := os.LookupEnv("PLUGIN_VERBOSITY")
if !present {
config.verbosity = 0
} else {
converted, err := strconv.ParseInt(verbosity, 10, 0)
if err != nil {
sugar.Fatal(err)
}
config.verbosity = converted
}
limit, present := os.LookupEnv("PLUGIN_LIMIT")
if !present {
config.limit = nil
} else {
config.limit = &limit
}
tags, present := os.LookupEnv("PLUGIN_TAGS")
if !present {
config.tags = nil
} else {
config.tags = &tags
}
privateKey, present := os.LookupEnv("PLUGIN_PRIVATE_KEY")
if !present {
sugar.Warn("⚠️ 'private_key' setting not defined !")
config.privateKey = nil
} else {
config.privateKey = &privateKey
}
vaultToken, present := os.LookupEnv("PLUGIN_VAULT_TOKEN")
if !present {
config.vaultToken = nil
} else {
config.vaultToken = &vaultToken
}
galaxyFile, present := os.LookupEnv("PLUGIN_GALAXY_FILE")
if !present {
config.galaxyFile = nil
} else {
config.galaxyFile = &galaxyFile
}
playbook, present := os.LookupEnv("PLUGIN_PLAYBOOK")
if !present {
sugar.Fatal("⚠️ 'playbook' setting not defined, ABORT!")
} else {
config.playbook = &playbook
}
return config
}
func main() {
// encoderConfig := zapcore.EncoderConfig{
// MessageKey: "message",
// LevelKey: "level",
// EncodeLevel: zapcore.CapitalColorLevelEncoder,
// EncodeDuration: zapcore.StringDurationEncoder,
// EncodeCaller: zapcore.ShortCallerEncoder,
// }
// encoder := zapcore.NewConsoleEncoder(encoderConfig)
// core := zapcore.NewCore(encoder, os.Stdout, zapcore.InfoLevel)
config := zap.NewProductionConfig()
config.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
config.EncoderConfig.TimeKey = ""
config.Encoding = "console"
config.DisableCaller = true
config.DisableStacktrace = true
logger, _ := config.Build()
defer logger.Sync()
sugar := logger.Sugar()
sugar.Info("Woodpecker Ansible Runner")
pluginConfig := getPluginConfig(sugar)
if pluginConfig.privateKey != nil {
runCommand(sugar, "mkdir", "/root/.ssh")
err := os.WriteFile("/root/.ssh/id_ed25519", []byte(*pluginConfig.privateKey), 0400)
if err != nil {
sugar.Fatal(err)
}
}
args := []string{*pluginConfig.playbook}
if pluginConfig.vaultToken != nil {
sugar.Info("💼 Adding vault token to 'credentials/ci_vault_token'")
runCommand(sugar, "mkdir", "credentials")
err := os.WriteFile("credentials/ci_vault_token", []byte(*pluginConfig.vaultToken), 0644)
if err != nil {
sugar.Fatal(err)
}
args = append(args, "--vault-password-file=credentials/ci_vault_token")
sugar.Info("⚙️ Clean ansible.cfg")
runCommand(sugar, "sed", "-i", "/vault_password_file.*/d", "./ansible.cfg")
}
if _, err := os.Stat("ansible-ci.cfg"); err == nil {
sugar.Info("⚙️ ansible-ci.cfg is present, using it.")
os.Remove("ansible.cfg")
os.Rename("ansible-ci.cfg", "ansible.cfg")
}
if pluginConfig.galaxyFile != nil {
sugar.Infof("🚀 Installing Galaxy dependencies (%s)", *pluginConfig.galaxyFile)
runCommand(sugar, "ansible-galaxy", "install", "-r", *pluginConfig.galaxyFile, "--force")
}
if pluginConfig.check_syntax {
args = append(args, "--syntax-check")
}
if pluginConfig.check {
args = append(args, "--check")
}
if pluginConfig.diff {
args = append(args, "--diff")
}
if pluginConfig.verbosity != 0 {
verb := "-"
for i := 0; i < int(pluginConfig.verbosity); i++ {
verb += "v"
}
args = append(args, verb)
}
if pluginConfig.limit != nil {
args = append(args, "--limit", *pluginConfig.limit)
}
if pluginConfig.tags != nil {
args = append(args, "--tags", *pluginConfig.tags)
}
// runCommand(sugar, "export", "ANSIBLE_HOST_KEY_CHECKING=False")
command := append([]string{"ansible-playbook"}, args...)
runCommand(sugar, command...)
}

10
go.mod Normal file
View File

@ -0,0 +1,10 @@
module woodpecker-ansible-runner
go 1.20
require go.uber.org/zap v1.24.0
require (
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
)

18
go.sum Normal file
View File

@ -0,0 +1,18 @@
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

57
old.yml
View File

@ -1,57 +0,0 @@
name: Build Docker
kind: pipeline
type: docker
steps:
- name: Only build image
image: plugins/docker
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: harbor.sebclem.fr/sebclem/drone-ansible-runner
cache_from: harbor.sebclem.fr/sebclem/drone-ansible-runner
registry: harbor.sebclem.fr
tags: latest
dry_run: true
when:
target:
exclude:
- production
- name: Build and Push docker
image: plugins/docker
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: harbor.sebclem.fr/sebclem/drone-ansible-runner
cache_from: harbor.sebclem.fr/sebclem/drone-ansible-runner
registry: harbor.sebclem.fr
tags: latest
when:
target:
- production
- name: Notify
image: drillster/drone-email
settings:
host:
from_secret: mail_host
username:
from_secret: mail_username
password:
from_secret: mail_password
from:
from_secret: mail_from
when:
status: [ changed, failure ]
trigger:
event:
- push
- custom
- promote
- rollback