Initial Commit.

This commit is contained in:
2024-01-15 12:06:13 +13:00
commit 196e17cd29
11 changed files with 542 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
bin
vendor

9
AUTHORS.md Normal file
View File

@@ -0,0 +1,9 @@
# Credits
## Development Lead
- Aaron Guise [guisea](https://github.com/guisea)
## Contributors
None yet. Why not be the first?

81
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,81 @@
# Contributing
Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given.
You can contribute in many ways:
## Types of Contributions
### Report Bugs
Report bugs at https://github.com/guisea/directdnsonly/issues.
If you are reporting a bug, please include:
* Your operating system name and version.
* Any details about your local setup that might be helpful in troubleshooting.
* Detailed steps to reproduce the bug.
### Fix Bugs
Look through the GitHub issues for bugs. Anything tagged with "bug"
is open to whoever wants to implement it.
### Implement Features
Look through the GitHub issues for features. Anything tagged with "feature"
is open to whoever wants to implement it.
### Write Documentation
directdnsonly could always use more documentation, whether as part of the
official directdnsonly docs, in docstrings, or even on the web in blog posts,
articles, and such.
### Submit Feedback
The best way to send feedback is to file an issue at https://github.com/guisea/directdnsonly/issues.
If you are proposing a feature:
* Explain in detail how it would work.
* Keep the scope as narrow as possible, to make it easier to implement.
* Remember that this is a volunteer-driven project, and that contributions
are welcome :)
## Get Started!
Ready to contribute? Here's how to set up `directdnsonly` for local development.
1. Fork the `directdnsonly` repo on GitHub.
2. Clone your fork locally::
```bash
$ git clone git@github.com:your_name_here/directdnsonly.git
```
3. Create a branch for local development::
```bash
$ git checkout -b name-of-your-bugfix-or-feature
```
Now you can make your changes locally.
4. When you're done making changes, check that your changes pass the tests::
```bash
$ make test
```
6. Commit your changes and push your branch to GitHub::
```bash
$ git add .
$ git commit -m "Your detailed description of your changes."
$ git push origin name-of-your-bugfix-or-feature
```
7. Submit a pull request through the GitHub website.
Pull Request Guidelines
-----------------------
Before you submit a pull request, check that it meets these guidelines:
1. The pull request should include tests.
2. If the pull request adds functionality, the docs should be updated. Put
your new functionality into a function with a docstring, and add the
feature to the list in README.md.

40
Dockerfile Normal file
View File

@@ -0,0 +1,40 @@
# Build Stage
FROM lacion/alpine-golang-buildimage:1.13 AS build-stage
LABEL app="build-directdnsonly"
LABEL REPO="https://github.com/guisea/directdnsonly"
ENV PROJPATH=/go/src/github.com/guisea/directdnsonly
# Because of https://github.com/docker/docker/issues/14914
ENV PATH=$PATH:$GOROOT/bin:$GOPATH/bin
ADD . /go/src/github.com/guisea/directdnsonly
WORKDIR /go/src/github.com/guisea/directdnsonly
RUN make build-alpine
# Final Stage
FROM lacion/alpine-base-image:latest
ARG GIT_COMMIT
ARG VERSION
LABEL REPO="https://github.com/guisea/directdnsonly"
LABEL GIT_COMMIT=$GIT_COMMIT
LABEL VERSION=$VERSION
# Because of https://github.com/docker/docker/issues/14914
ENV PATH=$PATH:/opt/directdnsonly/bin
WORKDIR /opt/directdnsonly/bin
COPY --from=build-stage /go/src/github.com/guisea/directdnsonly/bin/directdnsonly /opt/directdnsonly/bin/
RUN chmod +x /opt/directdnsonly/bin/directdnsonly
# Create appuser
RUN adduser -D -g '' directdnsonly
USER directdnsonly
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
CMD ["/opt/directdnsonly/bin/directdnsonly"]

64
Makefile Normal file
View File

@@ -0,0 +1,64 @@
.PHONY: build build-alpine clean test help default
BIN_NAME=directdnsonly
VERSION := $(shell grep "const Version " version/version.go | sed -E 's/.*"(.+)"$$/\1/')
GIT_COMMIT=$(shell git rev-parse HEAD)
GIT_DIRTY=$(shell test -n "`git status --porcelain`" && echo "+CHANGES" || true)
BUILD_DATE=$(shell date '+%Y-%m-%d-%H:%M:%S')
IMAGE_NAME := "guisea/directdnsonly"
default: test
help:
@echo 'Management commands for directdnsonly:'
@echo
@echo 'Usage:'
@echo ' make build Compile the project.'
@echo ' make get-deps runs dep ensure, mostly used for ci.'
@echo ' make build-alpine Compile optimized for alpine linux.'
@echo ' make package Build final docker image with just the go binary inside'
@echo ' make tag Tag image created by package with latest, git commit and version'
@echo ' make test Run tests on a compiled project.'
@echo ' make push Push tagged images to registry'
@echo ' make clean Clean the directory tree.'
@echo
build:
@echo "building ${BIN_NAME} ${VERSION}"
@echo "GOPATH=${GOPATH}"
go build -ldflags "-X github.com/guisea/directdnsonly/version.GitCommit=${GIT_COMMIT}${GIT_DIRTY} -X github.com/guisea/directdnsonly/version.BuildDate=${BUILD_DATE}" -o bin/${BIN_NAME}
get-deps:
dep ensure
build-alpine:
@echo "building ${BIN_NAME} ${VERSION}"
@echo "GOPATH=${GOPATH}"
go build -ldflags '-w -linkmode external -extldflags "-static" -X github.com/guisea/directdnsonly/version.GitCommit=${GIT_COMMIT}${GIT_DIRTY} -X github.com/guisea/directdnsonly/version.BuildDate=${BUILD_DATE}' -o bin/${BIN_NAME}
package:
@echo "building image ${BIN_NAME} ${VERSION} $(GIT_COMMIT)"
docker build --build-arg VERSION=${VERSION} --build-arg GIT_COMMIT=$(GIT_COMMIT) -t $(IMAGE_NAME):local .
tag:
@echo "Tagging: latest ${VERSION} $(GIT_COMMIT)"
docker tag $(IMAGE_NAME):local $(IMAGE_NAME):$(GIT_COMMIT)
docker tag $(IMAGE_NAME):local $(IMAGE_NAME):${VERSION}
docker tag $(IMAGE_NAME):local $(IMAGE_NAME):latest
push: tag
@echo "Pushing docker image to registry: latest ${VERSION} $(GIT_COMMIT)"
docker push $(IMAGE_NAME):$(GIT_COMMIT)
docker push $(IMAGE_NAME):${VERSION}
docker push $(IMAGE_NAME):latest
clean:
@test ! -e bin/${BIN_NAME} || rm bin/${BIN_NAME}
test:
go test ./...

18
README.md Normal file
View File

@@ -0,0 +1,18 @@
# directdnsonly
DNSOnly for Directadmin Multi-server
## Getting started
This project requires Go to be installed. On OS X with Homebrew you can just run `brew install go`.
Running it then should be as simple as:
```console
$ make
$ ./bin/directdnsonly
```
### Testing
``make test``

58
config/config.go Normal file
View File

@@ -0,0 +1,58 @@
package config
import (
"time"
"github.com/spf13/viper"
)
// Provider defines a set of read-only methods for accessing the application
// configuration params as defined in one of the config files.
type Provider interface {
ConfigFileUsed() string
Get(key string) interface{}
GetBool(key string) bool
GetDuration(key string) time.Duration
GetFloat64(key string) float64
GetInt(key string) int
GetInt64(key string) int64
GetSizeInBytes(key string) uint
GetString(key string) string
GetStringMap(key string) map[string]interface{}
GetStringMapString(key string) map[string]string
GetStringMapStringSlice(key string) map[string][]string
GetStringSlice(key string) []string
GetTime(key string) time.Time
InConfig(key string) bool
IsSet(key string) bool
}
var defaultConfig *viper.Viper
// Config returns a default config providers
func Config() Provider {
return defaultConfig
}
// LoadConfigProvider returns a configured viper instance
func LoadConfigProvider(appName string) Provider {
return readViperConfig(appName)
}
func init() {
defaultConfig = readViperConfig("DIRECTDNSONLY")
}
func readViperConfig(appName string) *viper.Viper {
v := viper.New()
v.SetEnvPrefix(appName)
v.AutomaticEnv()
// global defaults
v.SetDefault("json_logs", false)
v.SetDefault("loglevel", "debug")
return v
}

7
go.mod Normal file
View File

@@ -0,0 +1,7 @@
module github.com/guisea/directdnsonly
require (
github.com/sirupsen/logrus v1.4.1
github.com/spf13/viper v1.3.2
)

216
log/log.go Normal file
View File

@@ -0,0 +1,216 @@
package log
import (
"os"
"github.com/sirupsen/logrus"
"github.com/guisea/directdnsonly/config"
)
// Logger defines a set of methods for writing application logs. Derived from and
// inspired by logrus.Entry.
type Logger interface {
Debug(args ...interface{})
Debugf(format string, args ...interface{})
Debugln(args ...interface{})
Error(args ...interface{})
Errorf(format string, args ...interface{})
Errorln(args ...interface{})
Fatal(args ...interface{})
Fatalf(format string, args ...interface{})
Fatalln(args ...interface{})
Info(args ...interface{})
Infof(format string, args ...interface{})
Infoln(args ...interface{})
Panic(args ...interface{})
Panicf(format string, args ...interface{})
Panicln(args ...interface{})
Print(args ...interface{})
Printf(format string, args ...interface{})
Println(args ...interface{})
Warn(args ...interface{})
Warnf(format string, args ...interface{})
Warning(args ...interface{})
Warningf(format string, args ...interface{})
Warningln(args ...interface{})
Warnln(args ...interface{})
}
var defaultLogger *logrus.Logger
func init() {
defaultLogger = newLogrusLogger(config.Config())
}
// NewLogger returns a configured logrus instance
func NewLogger(cfg config.Provider) *logrus.Logger {
return newLogrusLogger(cfg)
}
func newLogrusLogger(cfg config.Provider) *logrus.Logger {
l := logrus.New()
if cfg.GetBool("json_logs") {
l.Formatter = new(logrus.JSONFormatter)
}
l.Out = os.Stderr
switch cfg.GetString("loglevel") {
case "debug":
l.Level = logrus.DebugLevel
case "warning":
l.Level = logrus.WarnLevel
case "info":
l.Level = logrus.InfoLevel
default:
l.Level = logrus.DebugLevel
}
return l
}
// Fields is a map string interface to define fields in the structured log
type Fields map[string]interface{}
// With allow us to define fields in out structured logs
func (f Fields) With(k string, v interface{}) Fields {
f[k] = v
return f
}
// WithFields allow us to define fields in out structured logs
func (f Fields) WithFields(f2 Fields) Fields {
for k, v := range f2 {
f[k] = v
}
return f
}
// WithFields allow us to define fields in out structured logs
func WithFields(fields Fields) Logger {
return defaultLogger.WithFields(logrus.Fields(fields))
}
// Debug package-level convenience method.
func Debug(args ...interface{}) {
defaultLogger.Debug(args...)
}
// Debugf package-level convenience method.
func Debugf(format string, args ...interface{}) {
defaultLogger.Debugf(format, args...)
}
// Debugln package-level convenience method.
func Debugln(args ...interface{}) {
defaultLogger.Debugln(args...)
}
// Error package-level convenience method.
func Error(args ...interface{}) {
defaultLogger.Error(args...)
}
// Errorf package-level convenience method.
func Errorf(format string, args ...interface{}) {
defaultLogger.Errorf(format, args...)
}
// Errorln package-level convenience method.
func Errorln(args ...interface{}) {
defaultLogger.Errorln(args...)
}
// Fatal package-level convenience method.
func Fatal(args ...interface{}) {
defaultLogger.Fatal(args...)
}
// Fatalf package-level convenience method.
func Fatalf(format string, args ...interface{}) {
defaultLogger.Fatalf(format, args...)
}
// Fatalln package-level convenience method.
func Fatalln(args ...interface{}) {
defaultLogger.Fatalln(args...)
}
// Info package-level convenience method.
func Info(args ...interface{}) {
defaultLogger.Info(args...)
}
// Infof package-level convenience method.
func Infof(format string, args ...interface{}) {
defaultLogger.Infof(format, args...)
}
// Infoln package-level convenience method.
func Infoln(args ...interface{}) {
defaultLogger.Infoln(args...)
}
// Panic package-level convenience method.
func Panic(args ...interface{}) {
defaultLogger.Panic(args...)
}
// Panicf package-level convenience method.
func Panicf(format string, args ...interface{}) {
defaultLogger.Panicf(format, args...)
}
// Panicln package-level convenience method.
func Panicln(args ...interface{}) {
defaultLogger.Panicln(args...)
}
// Print package-level convenience method.
func Print(args ...interface{}) {
defaultLogger.Print(args...)
}
// Printf package-level convenience method.
func Printf(format string, args ...interface{}) {
defaultLogger.Printf(format, args...)
}
// Println package-level convenience method.
func Println(args ...interface{}) {
defaultLogger.Println(args...)
}
// Warn package-level convenience method.
func Warn(args ...interface{}) {
defaultLogger.Warn(args...)
}
// Warnf package-level convenience method.
func Warnf(format string, args ...interface{}) {
defaultLogger.Warnf(format, args...)
}
// Warning package-level convenience method.
func Warning(args ...interface{}) {
defaultLogger.Warning(args...)
}
// Warningf package-level convenience method.
func Warningf(format string, args ...interface{}) {
defaultLogger.Warningf(format, args...)
}
// Warningln package-level convenience method.
func Warningln(args ...interface{}) {
defaultLogger.Warningln(args...)
}
// Warnln package-level convenience method.
func Warnln(args ...interface{}) {
defaultLogger.Warnln(args...)
}

26
main.go Normal file
View File

@@ -0,0 +1,26 @@
package main
import (
"flag"
"fmt"
"github.com/guisea/directdnsonly/version"
)
func main() {
versionFlag := flag.Bool("version", false, "Version")
flag.Parse()
if *versionFlag {
fmt.Println("Build Date:", version.BuildDate)
fmt.Println("Git Commit:", version.GitCommit)
fmt.Println("Version:", version.Version)
fmt.Println("Go Version:", version.GoVersion)
fmt.Println("OS / Arch:", version.OsArch)
return
}
fmt.Println("Hello.")
}

21
version/version.go Normal file
View File

@@ -0,0 +1,21 @@
package version
import (
"fmt"
"runtime"
)
// GitCommit returns the git commit that was compiled. This will be filled in by the compiler.
var GitCommit string
// Version returns the main version number that is being run at the moment.
const Version = "0.1.0"
// BuildDate returns the date the binary was built
var BuildDate = ""
// GoVersion returns the version of the go runtime used to compile the binary
var GoVersion = runtime.Version()
// OsArch returns the os and arch used to build the binary
var OsArch = fmt.Sprintf("%s %s", runtime.GOOS, runtime.GOARCH)