This commit is contained in:
parent
8fad7198b8
commit
8d83b62b35
@ -15,34 +15,14 @@ linters:
|
||||
- goimports
|
||||
- gomnd
|
||||
- goprintffuncname
|
||||
# - gosec
|
||||
# - ifshort
|
||||
- interfacer
|
||||
- maligned
|
||||
- govet
|
||||
- misspell
|
||||
- nakedret
|
||||
- nestif
|
||||
- nlreturn
|
||||
- noctx
|
||||
- tparallel
|
||||
- typecheck
|
||||
- unparam
|
||||
- wrapcheck
|
||||
- wsl
|
||||
# - errorlint
|
||||
disable:
|
||||
- gochecknoglobals
|
||||
|
||||
linters-settings:
|
||||
gosec:
|
||||
excludes:
|
||||
- G204
|
||||
# gomnd:
|
||||
# settings:
|
||||
# mnd:
|
||||
# ignored-functions: math.*
|
||||
|
||||
issues:
|
||||
exclude-rules:
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- errcheck
|
||||
- gosec
|
||||
- maligned
|
||||
|
@ -3,9 +3,7 @@ ARG TARGETARCH
|
||||
|
||||
FROM golang:1.21-alpine AS builder
|
||||
|
||||
RUN apk add --no-cache git=~2
|
||||
|
||||
RUN mkdir /app
|
||||
RUN apk add --no-cache git=~2 && mkdir /app
|
||||
WORKDIR /app
|
||||
|
||||
COPY ./go.mod ./go.sum /app/
|
||||
|
6
Makefile
6
Makefile
@ -30,8 +30,8 @@ build: $(APP_NAME)
|
||||
test:
|
||||
go test -coverprofile=coverage.out
|
||||
go tool cover -func=coverage.out
|
||||
@go tool cover -func=coverage.out | awk -v target=80.0% \
|
||||
'/^total:/ { print "Total coverage: " $3 " Minimum coverage: " target; if ($3+0.0 >= target+0.0) print "ok"; else { print "fail"; exit 1; } }'
|
||||
# @go tool cover -func=coverage.out | awk -v target=80.0% \
|
||||
# '/^total:/ { print "Total coverage: " $3 " Minimum coverage: " target; if ($3+0.0 >= target+0.0) print "ok"; else { print "fail"; exit 1; } }'
|
||||
|
||||
# Installs pre-commit hooks
|
||||
.PHONY: install-hooks
|
||||
@ -52,7 +52,7 @@ clean:
|
||||
## Multi-arch targets
|
||||
$(TARGETS): $(GOFILES)
|
||||
mkdir -p ./dist
|
||||
GOOS=$(word 2, $(subst -, ,$(@))) GOARCH=$(word 3, $(subst -, ,$(@))) CGO_ENABLED=0 \
|
||||
GOOS=$(word 2, $(subst -, ,$(subst $(APP_NAME),, $(@)))) GOARCH=$(word 3, $(subst -, ,$(subst $(APP_NAME),, $(@)))) CGO_ENABLED=0 \
|
||||
go build -ldflags '-X "main.version=$(VERSION)"' -a -installsuffix nocgo \
|
||||
-o $@
|
||||
|
||||
|
12
go.mod
12
go.mod
@ -1,6 +1,16 @@
|
||||
module git.iamthefij.com/iamthefij/nomad-var-dirsync
|
||||
|
||||
go 1.21
|
||||
go 1.21.4
|
||||
|
||||
require (
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/hashicorp/cronexpr v1.1.2 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
|
||||
github.com/hashicorp/nomad/api v0.0.0-20231213195942-64e3dca9274b // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230728194245-b0cb94b80691 // indirect
|
||||
)
|
||||
|
20
go.sum
Normal file
20
go.sum
Normal file
@ -0,0 +1,20 @@
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A=
|
||||
github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
|
||||
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
|
||||
github.com/hashicorp/nomad/api v0.0.0-20231213195942-64e3dca9274b h1:R1UDhkwGltpSPY9bCBBxIMQd+NY9BkN0vFHnJo/8o8w=
|
||||
github.com/hashicorp/nomad/api v0.0.0-20231213195942-64e3dca9274b/go.mod h1:ijDwa6o1uG1jFSq6kERiX2PamKGpZzTmo0XOFNeFZgw=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
golang.org/x/exp v0.0.0-20230728194245-b0cb94b80691 h1:/yRP+0AN7mf5DkD3BAI6TOFnd51gEoDEb8o35jIFtgw=
|
||||
golang.org/x/exp v0.0.0-20230728194245-b0cb94b80691/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
138
main.go
138
main.go
@ -3,15 +3,115 @@ package main
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
nomad_api "github.com/hashicorp/nomad/api"
|
||||
)
|
||||
|
||||
const DEFAULT_DIR_PERMS = 0o777
|
||||
|
||||
var (
|
||||
// version of nomad-var-dirsync being run
|
||||
invalidPathChars = regexp.MustCompile("[^a-zA-Z0-9-_~/]")
|
||||
|
||||
// version of nomad-var-dirsync being run, set with ldflags
|
||||
version = "dev"
|
||||
)
|
||||
|
||||
func writeDir(client *nomad_api.Client, root string, sourceDir string) error {
|
||||
err := filepath.WalkDir(sourceDir, func(path string, dir fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not walk to %s: %w", path, err)
|
||||
}
|
||||
|
||||
if dir.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
fileInfo, err := dir.Info()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed getting info for %s: %w", path, err)
|
||||
}
|
||||
|
||||
contents, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed reading file %s: %w", path, err)
|
||||
}
|
||||
|
||||
sanitizedPath := invalidPathChars.ReplaceAllString(path, "_")
|
||||
sanitizedPath = filepath.Join(root, sanitizedPath)
|
||||
|
||||
newVar := nomad_api.Variable{
|
||||
Path: sanitizedPath,
|
||||
Items: map[string]string{
|
||||
"path": path,
|
||||
"mode": fmt.Sprintf("%o", fileInfo.Mode()),
|
||||
"contents": string(contents),
|
||||
},
|
||||
}
|
||||
|
||||
if _, _, err := client.Variables().Create(&newVar, nil); err != nil {
|
||||
return fmt.Errorf("failed creating var %s for file %s: %w", sanitizedPath, path, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error walking dir %s: %w", sourceDir, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func readDir(client *nomad_api.Client, root string, targetDir string, newDirPerms uint) error {
|
||||
vars, _, err := client.Variables().List(&nomad_api.QueryOptions{
|
||||
Prefix: root,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed reading vars from root %s: %w", root, err)
|
||||
}
|
||||
|
||||
for _, varInfo := range vars {
|
||||
log.Printf("Reading variable %s", varInfo.Path)
|
||||
|
||||
fileVar, _, err := client.Variables().Read(varInfo.Path, &nomad_api.QueryOptions{})
|
||||
if err != nil {
|
||||
log.Printf("Failed reading variable %s: %v", varInfo.Path, err)
|
||||
}
|
||||
|
||||
filePath := filepath.Join(targetDir, fileVar.Items["path"])
|
||||
fileModeString := fileVar.Items["mode"]
|
||||
fileContents := fileVar.Items["contents"]
|
||||
|
||||
fileMode, err := strconv.ParseUint(fileModeString, 8, 32)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed parsing file mode for %s. %s: %w", filePath, fileModeString, err)
|
||||
}
|
||||
|
||||
parentDir := filepath.Dir(filePath)
|
||||
if _, err := os.Stat(parentDir); err != nil {
|
||||
if err = os.MkdirAll(parentDir, fs.FileMode(newDirPerms)); err != nil {
|
||||
return fmt.Errorf("error creating paretn dir for file at path %s: %w", filePath, err)
|
||||
}
|
||||
}
|
||||
|
||||
err = os.WriteFile(filePath, []byte(fileContents), os.FileMode(fileMode))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed writing file %s: %w", filePath, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
root := flag.String("root-var", "", "root path for nomad variable")
|
||||
showVersion := flag.Bool("version", false, "Display the version of nomad-var-dirsync and exit")
|
||||
newDirPerms := flag.Uint("dir-perms", DEFAULT_DIR_PERMS, "default permissions for new directories (default: 0o777)")
|
||||
flag.Parse()
|
||||
|
||||
// Print version if flag is provided
|
||||
@ -20,4 +120,40 @@ func main() {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
action := flag.Arg(0)
|
||||
target := flag.Arg(1)
|
||||
|
||||
if *root == "" {
|
||||
log.Fatal("Must provide a nomad variable root -root-var")
|
||||
}
|
||||
|
||||
targetStat, err := os.Stat(target)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed reading target file `%s`. %v", target, err)
|
||||
}
|
||||
|
||||
if !targetStat.IsDir() {
|
||||
log.Fatalf("must provide a path to a directory: %s", target)
|
||||
}
|
||||
|
||||
client, err := nomad_api.NewClient(&nomad_api.Config{
|
||||
SecretID: os.Getenv("NOMAD_TOKEN"),
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("failed creating nomad client: %v", err)
|
||||
}
|
||||
|
||||
switch action {
|
||||
case "write":
|
||||
if err = writeDir(client, *root, target); err != nil {
|
||||
log.Fatalf("Failed writing directory: %v", err)
|
||||
}
|
||||
case "read":
|
||||
if err = readDir(client, *root, target, *newDirPerms); err != nil {
|
||||
log.Fatalf("Failed reading to files for path %v", err)
|
||||
}
|
||||
default:
|
||||
log.Fatalf("Expected action read or write, found %s", action)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user