2019-10-28 13:31:40 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"flag"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
"text/template"
|
|
|
|
|
2019-10-28 14:05:33 +00:00
|
|
|
"github.com/Masterminds/sprig"
|
2019-10-28 13:31:40 +00:00
|
|
|
"github.com/drone/drone-go/drone"
|
|
|
|
"golang.org/x/oauth2"
|
|
|
|
)
|
|
|
|
|
|
|
|
const secretEnvPrefix = "DRONE_SECRET_"
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
tplpath := flag.String("t", "template.yml", "Template file")
|
|
|
|
outpath := flag.String("o", ".drone.yml", "Output .drone.yml")
|
|
|
|
flag.Parse()
|
|
|
|
|
|
|
|
// Get drone server and token
|
|
|
|
|
|
|
|
server := os.Getenv("DRONE_SERVER")
|
|
|
|
if server == "" {
|
|
|
|
fatal("DRONE_SERVER missing or empty")
|
|
|
|
}
|
|
|
|
|
|
|
|
token := os.Getenv("DRONE_TOKEN")
|
|
|
|
if token == "" {
|
|
|
|
fatal("DRONE_TOKEN missing or empty")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Authenticate and connect to drone.io server
|
|
|
|
|
|
|
|
config := new(oauth2.Config)
|
|
|
|
auther := config.Client(
|
|
|
|
oauth2.NoContext,
|
|
|
|
&oauth2.Token{
|
|
|
|
AccessToken: token,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
client := drone.NewClient(server, auther)
|
|
|
|
|
|
|
|
user, err := client.Self()
|
|
|
|
if err != nil {
|
|
|
|
fatal("Connection to drone.io failed: %s", err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get project
|
|
|
|
|
|
|
|
projectname := flag.Arg(0)
|
|
|
|
if projectname == "" {
|
|
|
|
fatal("Repository name missing or empty")
|
|
|
|
}
|
|
|
|
|
|
|
|
parts := strings.SplitN(projectname, "/", 2)
|
|
|
|
if len(parts) < 2 {
|
|
|
|
parts = []string{user.Login, projectname}
|
|
|
|
}
|
|
|
|
namespace := parts[0]
|
|
|
|
reponame := parts[1]
|
|
|
|
|
|
|
|
// Enable repository on Drone.io
|
|
|
|
repo, err := client.RepoEnable(namespace, reponame)
|
|
|
|
if err != nil {
|
|
|
|
fatal("Error enabling repository %s/%s: %s", namespace, reponame, err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get secrets
|
|
|
|
|
|
|
|
for _, env := range os.Environ() {
|
|
|
|
// Check for the magic prefix
|
|
|
|
if !strings.HasPrefix(env, secretEnvPrefix) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// Split key=val
|
|
|
|
parts := strings.SplitN(env, "=", 2)
|
|
|
|
|
|
|
|
// Ignore weird values
|
|
|
|
if len(parts) < 2 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
secretName := strings.ToLower(parts[0][len(secretEnvPrefix):])
|
|
|
|
secretValue := parts[1]
|
|
|
|
|
2019-10-28 14:05:33 +00:00
|
|
|
tpl, err := template.New("secret-" + secretName).Funcs(sprig.TxtFuncMap()).Parse(secretValue)
|
2019-10-28 13:31:40 +00:00
|
|
|
if err != nil {
|
|
|
|
fatal("Secret %s is an invalid template: %s", parts[0], err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
var builder strings.Builder
|
|
|
|
err = tpl.Execute(&builder, repo)
|
|
|
|
if err != nil {
|
|
|
|
fatal("Error while building secret %s: %s", secretName, err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add secret to project
|
|
|
|
client.SecretCreate(repo.Namespace, repo.Name, &drone.Secret{
|
|
|
|
Name: secretName,
|
|
|
|
Data: secretValue,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read template file
|
|
|
|
|
|
|
|
tpl, err := template.ParseFiles(*tplpath)
|
|
|
|
if err != nil {
|
|
|
|
fatal("Cannot read template file: %s", err.Error())
|
|
|
|
}
|
|
|
|
|
2019-10-28 14:05:33 +00:00
|
|
|
// Add sprig functions
|
|
|
|
|
|
|
|
tpl = tpl.Funcs(sprig.TxtFuncMap())
|
|
|
|
|
2019-10-28 13:31:40 +00:00
|
|
|
// Create output file
|
|
|
|
|
|
|
|
outfile, err := os.Create(*outpath)
|
|
|
|
if err != nil {
|
|
|
|
fatal("Cannot create output file: %s", err.Error())
|
|
|
|
}
|
|
|
|
defer outfile.Close()
|
|
|
|
|
|
|
|
// Generate output from template
|
|
|
|
|
|
|
|
err = tpl.Execute(outfile, repo)
|
|
|
|
if err != nil {
|
|
|
|
fatal("Error processing template: %s", err.Error())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func fatal(msg string, args ...interface{}) {
|
|
|
|
fmt.Fprintf(os.Stderr, "FATAL: "+msg+"\n", args...)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|