Add container / kubernetes support with helm
Gitea/ncDocConverter/pipeline/head This commit looks good Details

main v1.1.0
Jonas Letzbor 2023-08-09 17:03:27 +02:00
parent 3ce008c97e
commit afba495440
Signed by: RPJosh
GPG Key ID: 46D72F589702E55A
27 changed files with 447 additions and 322 deletions

10
.dockerignore 100644
View File

@ -0,0 +1,10 @@
**/.git
ncDocConverth-*
# Space for private notes
notes/
# Locally used configuration file
config.yaml
ncConverter.json
config-docker.yaml

1
.gitignore vendored
View File

@ -24,6 +24,7 @@ go.work
# Locally used configuration file # Locally used configuration file
/config.yaml /config.yaml
/ncConverter.json /ncConverter.json
/config-docker.yaml
# Vite build file # Vite build file
/.vite /.vite

23
Dockerfile 100644
View File

@ -0,0 +1,23 @@
# Build go binary
FROM docker.io/golang:1.20-alpine3.17 AS builder
ARG VERSION=0.0.0
WORKDIR /build
# To optimize the cache only copy and install the dependencies inside of the file "go.sum"
COPY go.sum go.mod ./
RUN go mod download
# Copy now all files
COPY . .
# Build the binary
RUN GOOS=linux GOARCH=amd64 go build -o ncDocConverth -ldflags "-X main.version=${VERSION}" ./cmd/ncDocConverth
# Image to run the binary
FROM docker.io/alpine:3.18
COPY --from=builder --chmod=0777 /build/ncDocConverth /app/ncDocConverth
CMD [ "/app/ncDocConverth", "--config", "/config/config.yaml" ]

192
Jenkinsfile vendored
View File

@ -1,41 +1,183 @@
pipeline { // Base class containing the git configuration
agent any class Configuration {
tools { // (Long) Hash value of the current commit
go '1.18' String commitHash;
// Name of the current Branch
String branch;
// The last available tag in the git commit history
String lastTag;
// Tag value of the current commit
String[] currentTags;
// Tag used to update the helm values
String updateTag = ""
String updateFile = ""
String updateFile2 = ""
// Tags returns the tags to apply for the build container image.
def Tags() {
ArrayList rtc = []
// Building on master branch
if (branch == "master" || branch == "main") {
// When building on the master branch always use the provided tags for the current commit
if (currentTags != null) rtc.addAll(currentTags)
// The master branch is used for "release candidate" and "production build"
currentTags.each {
if (it.contains("-rc.")) {
// Update tag "latest-rc" because a tag like "v1.10.0-rc.1" was provided
rtc << "rc-latest"
updateTag = it
updateFile = "rc"
} else {
// The tag is not a rc -> new "production" release
rtc << "latest"
updateTag = it
updateFile = "main"
// Also update the rc when "main" was updated
updateFile2 = "rc"
}
}
// Also push a tag with the current commit hash
rtc << "main-" + commitHash
} else if (branch == "snapshot") {
// For security reasons the tags on the snapshot branch are not used for tagging
rtc << "snapshot-latest"
// Otherwise only push a tag with the current commit hash
rtc << "snapshot-" + commitHash
updateTag = "snapshot-" + commitHash
updateFile = "snapshot"
} else {
currentBuild.result = 'ABORTED'
error("Received not supported branch for building container image: '" + branch + "'")
}
return rtc
}
// Returns the current version of the program that should be used during building
String Version() {
if (branch == "master" || branch == "main") {
return lastTag
} else {
// Otherwiese add a "-snapshot" to the last tagged version
return "" + lastTag.replace("(?<=v\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}).*", "") + "-dev"
}
}
}
// Global variables
def Configuration gitConfig = new Configuration()
def String VERSION
// App used for helm identification and commit message
def String APP_NAME = "ncDocConverter"
pipeline {
agent {
// Use the kubernetes agent
kubernetes {
label 'podman-low'
}
} }
stages { stages {
stage('Initializing variables') {
steps {
script {
gitConfig.commitHash = "${env.GIT_COMMIT}"
gitConfig.branch = "${env.GIT_BRANCH}"
currentTags = sh (
script: 'git tag --points-at HEAD',
returnStdout: true
)
if (currentTags != "") {
gitConfig.currentTags = currentTags.split("\n")
}
gitConfig.lastTag = sh (
script: 'git describe --tags --abbrev=0',
returnStdout: true
).replace("\n", "")
// Apply the current version code
VERSION = gitConfig.Version()
}
}
}
stage('Build') { stage('Build') {
steps { steps {
sh 'go get ./...' echo "Building Version '${VERSION}' and tagging it with '${gitConfig.Tags()}'"
container('podman-low') {
script {
// Script needed to define variables withEnv([ "version=${VERSION}", "commit=${gitConfig.commitHash}" ]) {
script { sh 'buildah bud --layers --build-arg VERSION="${version}" --tag=rpjosh.de/jenkins-ncdocconverter:${commit} \
// Get version of program --cache-to=git.rpjosh.de/build-cache/ncdocconverter --cache-from=git.rpjosh.de/build-cache/ncdocconverter \
VERSION = sh ( -f Dockerfile .'
script: 'cat VERSION', }
returnStdout: true }
).trim() }
// Cross compile }
sh "GOOS=linux GOARCH=amd64 go build -o ncDocConverth-${VERSION}-amd64 ./cmd/ncDocConverth" }
sh "GOOS=linux GOARCH=arm64 go build -o ncDocConverth-${VERSION}-arm64 ./cmd/ncDocConverth"
sh "GOOS=windows GOARCH=arm64 go build -o ncDocConverth-${VERSION}-amd64.exe ./cmd/ncDocConverth" stage('Publish') {
steps {
echo "Publish to docker repository (git.rpjosh.de/rpdb)"
container('podman-low') {
script {
gitConfig.Tags().each {
sh "buildah push rpjosh.de/jenkins-ncdocconverter:${gitConfig.commitHash} docker://git.rpjosh.de/rpjosh-container/ncdocconverter:${it}"
}
}
} }
} }
} }
stage('Deploy') { stage('Deploy') {
// Tags not working with gitea?
//when {
// buildingTag()
//}
steps { steps {
script {
if (env.BRANCH_NAME == "main") { container('podman-low') {
sh 'sudo ./scripts/deploy.sh' script {
configFileProvider([configFile(fileId: 'deployConfig', variable: 'confFile')]) {
script {
// Read the kubernets deploy configuration from the file
def config = readJSON file:"$confFile"
def String url = config.kubernetes.gitHelmValues + APP_NAME + "/" + gitConfig.updateFile + ".yaml"
def String url2 = config.kubernetes.gitHelmValues + APP_NAME + "/" + gitConfig.updateFile2 + ".yaml"
sh "echo Using git URL '${url}'"
// Get the current file content, replace the tag, and push the mmodified tag again
withCredentials([ string(credentialsId: 'GIT_API_KEY', variable: "gitApiKey") ]) {
withEnv([ "url=${url}", "url2=${url2}", "tag=${gitConfig.updateTag}", "file=${gitConfig.updateFile}", "app=${APP_NAME}" ]) {
// Exit when one command does fail in pipe
sh "set -e && set -o pipefail"
if (gitConfig.updateFile == "main") {
echo "Updating git configuration dirctory (${APP_NAME}/${gitConfig.updateFile}.yaml) with tag [${gitConfig.updateTag}]"
sh 'curl -s "https://notNeeded:${gitApiKey}@${url}" | jq -r .content | base64 --decode > tmp_values.yaml'
sh 'curl -s --fail-with-body "https://notNeeded:${gitApiKey}@${url}" -X PUT -H "Content-Type: application/json" -d \
\'{ "content": "\'"$(cat tmp_values.yaml | sed -e \'s/tag: ".*"/tag: "\'$tag\'"/g\' | base64 -w 0)"\'", "message": "[CI] Update image for \'"$app-$file"\'", \
"sha": "\'$(git hash-object tmp_values.yaml | tr -d "\\n")\'" }\' '
}
}
}
}
}
} }
} }
} }
@ -44,7 +186,7 @@ pipeline {
post { post {
success { success {
archiveArtifacts artifacts: 'ncDocConverth-*', fingerprint: true sh 'echo Build finished'
} }
// Clean after build // Clean after build

38
Makefile 100644
View File

@ -0,0 +1,38 @@
# Get the current version
VERSION=$(shell cat ./VERSION)
WORKDIR=$(shell pwd)
UID=$(shell echo $uid)
.PHONY: help
# Output help for every task
help:
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
.DEFAULT_GOAL := help
build: ## Build the container image (with cache)
buildah bud --layers --build-arg VERSION="$(VERSION)" \
--tag=git.rpjosh.de/ncDocConverter:v$(VERSION)-dev \
-f Dockerfile .
build-nc: ## Build the container image (without cache)
buildah bud --layers --no-cache --build-arg VERSION="$(VERSION)" \
--tag=git.rpjosh.de/ncDocConverter:v$(VERSION)-dev \
-f Dockerfile .
run: ## Run the container with
@ make stop > /dev/null 2>&1 || true
@ podman run -it --name ncDocConverter --userns=keep-id --cap-drop ALL -p 40001:40001 -e PORT=40001 \
-e DATA_FILE='./config/data.json' \
-v "$(WORKDIR)/ncConverter.json:/config/data.json" \
-v "$(WORKDIR)/config.yaml:/config/config.yaml" \
git.rpjosh.de/ncDocConverter:v$(VERSION)-dev
stop: ## Stop and removes a previous started container
@ podman stop ncDocConverter; podman rm ncDocConverter
clear-images: ## Remove all previously build images and all intermediate images created by this makefile
podman rmi $$(podman images -a | grep -e '<none>' -e '\/ncdocconverter-.*' | awk '{ print $3 }') -f
# Required secrets:
# Android Key Store (jks) file - androidKeystore
# Android Key Store password (cleartext) - androidKeystorePassword

View File

@ -5,9 +5,9 @@ import (
"net/http" "net/http"
"time" "time"
"rpjosh.de/ncDocConverter/internal/models" "git.rpjosh.de/RPJosh/go-logger"
"rpjosh.de/ncDocConverter/internal/ncworker" "git.rpjosh.de/ncDocConverter/internal/models"
"rpjosh.de/ncDocConverter/pkg/logger" "git.rpjosh.de/ncDocConverter/internal/ncworker"
) )
var version string var version string

View File

@ -5,8 +5,8 @@ import (
"net/http" "net/http"
"runtime/debug" "runtime/debug"
"git.rpjosh.de/RPJosh/go-logger"
"github.com/justinas/nosurf" "github.com/justinas/nosurf"
"rpjosh.de/ncDocConverter/pkg/logger"
) )
func secureHeaders(next http.Handler) http.Handler { func secureHeaders(next http.Handler) http.Handler {

View File

@ -3,9 +3,9 @@ package main
import ( import (
"net/http" "net/http"
"git.rpjosh.de/ncDocConverter/internal/api"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware" "github.com/go-chi/chi/v5/middleware"
"rpjosh.de/ncDocConverter/internal/api"
) )
func (app *WebApplication) routes() http.Handler { func (app *WebApplication) routes() http.Handler {

View File

@ -10,7 +10,7 @@ server:
oneShot: false oneShot: false
# Location of the file with the job configurations # Location of the file with the job configurations
JobFile: "./ncConverter.json" jobFile: "./ncConverter.json"
logging: logging:
# Minimum log Level for printing to the console (debug, info, warning, error, fatal) # Minimum log Level for printing to the console (debug, info, warning, error, fatal)

7
go.mod
View File

@ -1,4 +1,4 @@
module rpjosh.de/ncDocConverter module git.rpjosh.de/ncDocConverter
go 1.18 go 1.18
@ -7,8 +7,13 @@ require (
github.com/go-co-op/gocron v1.18.0 github.com/go-co-op/gocron v1.18.0
github.com/justinas/nosurf v1.1.1 github.com/justinas/nosurf v1.1.1
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
)
require (
git.rpjosh.de/RPJosh/go-logger v1.2.0 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect
golang.org/x/sync v0.1.0 // indirect golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.11.0 // indirect
) )
// https://zhwt.github.io/yaml-to-go/ // https://zhwt.github.io/yaml-to-go/

4
go.sum
View File

@ -1,3 +1,5 @@
git.rpjosh.de/RPJosh/go-logger v1.2.0 h1:Xvd4RDUYbf+pQH7dvCOYomymDGXBFDnN6K7C49QsZPw=
git.rpjosh.de/RPJosh/go-logger v1.2.0/go.mod h1:iD3KaRyOIkYMj7E+xFMn5uDVCzW1lSJQopz1Fl1+BSM=
github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8= github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8=
github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0=
@ -16,6 +18,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cO
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

11
helm/Chart.yaml 100644
View File

@ -0,0 +1,11 @@
apiVersion: v2
name: ncdocconverter
description: A Helm chart for thetool 'ncDocConverter'
type: application
# Helm chart version
version: 0.1.0
# Application version
appVersion: "1.0.0"

View File

@ -0,0 +1,31 @@
{{/*
Expand the name of the chart.
*/}}
{{- define ".name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define ".fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define ".chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}

View File

@ -0,0 +1,9 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include ".fullname" . }}-config
data:
config.yaml: |
server:
oneShot: false
jobFile: /config/data.json

View File

@ -0,0 +1,62 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include ".fullname" . }}
labels:
app: {{ include ".fullname" . }}
spec:
replicas: 1
selector:
matchLabels:
app: {{ include ".fullname" . }}
template:
metadata:
labels:
app: {{ include ".fullname" . }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: {{ include ".fullname" . }}
image: "{{ .Values.image.repository }}:{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
# Limit rights
securityContext:
allowPrivilegeEscalation: false
capabilities: {}
privileged: false
readOnlyRootFilesystem: false
runAsNonRoot: true
volumeMounts:
- name: config-volume
mountPath: /config/
readOnly: true
- name: secrets
mountPath: /config/
readOnly: true
env:
# Aggregator settings
- name: LOGGER_PRINTLEVEL
value: {{ .Values.config.logLevel }}
# Limit provided ressources
resources:
{{- toYaml .Values.resources | nindent 10 }}
volumes:
- name: config-volume
configMap:
name: {{ include ".fullname" . }}-config
items:
- key: config.yaml
path: config.yaml
- name: secrets
secret:
secretName: {{ .Values.dataSecret }}
items:
- key: data.json
path: data.json

30
helm/values.yaml 100644
View File

@ -0,0 +1,30 @@
# Overrides the full name of the chart
fullnameOverride: ""
# Limit provided ressources
resources:
requests:
memory: "30Mi"
cpu: "20m"
limits:
memory: "60Mi"
cpu: "70m"
image:
# Repository to download the image from
repository: git.rpjosh.de/rpjosh-container/ncDocConverter
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion
tag: ""
# Secret to use during fetching the image
imagePullSecrets: []
# Configuration options for the app
config:
# Minimum log level for printing to the console. Possible options are debug,info,warn,error
logLevel: info
# The secret name with the 'ncConverter.json' file as 'data.json' entry
dataSecret: ''

View File

@ -3,15 +3,15 @@ package api
import ( import (
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"rpjosh.de/ncDocConverter/internal/models" "git.rpjosh.de/RPJosh/go-logger"
"rpjosh.de/ncDocConverter/pkg/logger" "git.rpjosh.de/ncDocConverter/internal/models"
) )
type Api struct { type Api struct {
Logger *logger.Logger Logger *logger.Logger
Config *models.WebConfig Config *models.WebConfig
} }
func (api *Api) SetupServer(router *chi.Mux) { func (api *Api) SetupServer(router *chi.Mux) {
api.routes(router) api.routes(router)
} }

View File

@ -5,8 +5,9 @@ import (
"fmt" "fmt"
"os" "os"
"git.rpjosh.de/RPJosh/go-logger"
"git.rpjosh.de/ncDocConverter/pkg/utils"
yaml "gopkg.in/yaml.v3" yaml "gopkg.in/yaml.v3"
"rpjosh.de/ncDocConverter/pkg/logger"
) )
type WebConfig struct { type WebConfig struct {
@ -18,7 +19,7 @@ type Server struct {
Address string `yaml:"address"` Address string `yaml:"address"`
Certificate string `yaml:"certificate"` Certificate string `yaml:"certificate"`
OneShot bool `yaml:"oneShot"` OneShot bool `yaml:"oneShot"`
JobFile string `yaml:"JobFile"` JobFile string `yaml:"jobFile"`
Version string Version string
} }
@ -50,7 +51,7 @@ func getDefaultConfig() *WebConfig {
return &WebConfig{ return &WebConfig{
Server: Server{ Server: Server{
Address: ":4000", Address: ":4000",
JobFile: "./ncConverter.json", JobFile: utils.GetEnvString("DATA_FILE", "./ncConverter.json"),
}, },
Logging: Logging{ Logging: Logging{
PrintLogLevel: "info", PrintLogLevel: "info",
@ -95,13 +96,13 @@ func SetConfig(version string) (*WebConfig, error) {
os.Exit(0) os.Exit(0)
} }
defaultLogger := logger.Logger{ defaultLogger := logger.GetLoggerFromEnv(&logger.Logger{
PrintLevel: logger.GetLevelByName(webConfig.Logging.PrintLogLevel), PrintLevel: logger.GetLevelByName(webConfig.Logging.PrintLogLevel),
LogLevel: logger.GetLevelByName(webConfig.Logging.WriteLogLevel), LogLevel: logger.GetLevelByName(webConfig.Logging.WriteLogLevel),
LogFilePath: webConfig.Logging.LogFilePath, LogFilePath: webConfig.Logging.LogFilePath,
PrintSource: true, PrintSource: true,
} })
logger.SetGlobalLogger(&defaultLogger) logger.SetGlobalLogger(defaultLogger)
return webConfig, err return webConfig, err
} }

View File

@ -12,10 +12,10 @@ import (
"sync" "sync"
"time" "time"
"rpjosh.de/ncDocConverter/internal/models" "git.rpjosh.de/RPJosh/go-logger"
"rpjosh.de/ncDocConverter/internal/nextcloud" "git.rpjosh.de/ncDocConverter/internal/models"
"rpjosh.de/ncDocConverter/pkg/logger" "git.rpjosh.de/ncDocConverter/internal/nextcloud"
"rpjosh.de/ncDocConverter/pkg/utils" "git.rpjosh.de/ncDocConverter/pkg/utils"
) )
type BsJob struct { type BsJob struct {

View File

@ -8,9 +8,9 @@ import (
"sync" "sync"
"time" "time"
"git.rpjosh.de/RPJosh/go-logger"
"git.rpjosh.de/ncDocConverter/internal/models"
"github.com/go-co-op/gocron" "github.com/go-co-op/gocron"
"rpjosh.de/ncDocConverter/internal/models"
"rpjosh.de/ncDocConverter/pkg/logger"
) )
type NcConvertScheduler struct { type NcConvertScheduler struct {

View File

@ -9,10 +9,10 @@ import (
"sync" "sync"
"time" "time"
"rpjosh.de/ncDocConverter/internal/models" "git.rpjosh.de/RPJosh/go-logger"
"rpjosh.de/ncDocConverter/internal/nextcloud" "git.rpjosh.de/ncDocConverter/internal/models"
"rpjosh.de/ncDocConverter/pkg/logger" "git.rpjosh.de/ncDocConverter/internal/nextcloud"
"rpjosh.de/ncDocConverter/pkg/utils" "git.rpjosh.de/ncDocConverter/pkg/utils"
) )
type convertJob struct { type convertJob struct {

View File

@ -13,9 +13,9 @@ import (
"text/template" "text/template"
"time" "time"
"rpjosh.de/ncDocConverter/internal/models" "git.rpjosh.de/RPJosh/go-logger"
"rpjosh.de/ncDocConverter/pkg/logger" "git.rpjosh.de/ncDocConverter/internal/models"
"rpjosh.de/ncDocConverter/web" "git.rpjosh.de/ncDocConverter/web"
) )
// The internal representation of a nextcloud file // The internal representation of a nextcloud file

View File

@ -1,198 +0,0 @@
package logger
import (
"fmt"
"log"
"os"
"runtime"
"strconv"
"strings"
"time"
)
// Level of the log message
type Level uint8
const (
LevelDebug Level = iota
LevelInfo
LevelWarning
LevelError
LevelFatal
)
type Logger struct {
PrintLevel Level
LogLevel Level
LogFilePath string
PrintSource bool
consoleLogger *log.Logger
consoleLoggerErr *log.Logger
fileLogger *log.Logger
logFile *os.File
}
var dLogger Logger
func init() {
dLogger = Logger{
PrintLevel: LevelDebug,
LogLevel: LevelInfo,
LogFilePath: "",
PrintSource: false,
}
dLogger.setup()
}
func (l Logger) Log(level Level, message string, parameters ...any) {
// this function is needed that runtime.Caller(2) is always correct (even on direct call)
l.log(level, message, parameters...)
}
func (l Logger) log(level Level, message string, parameters ...any) {
pc, file, line, ok := runtime.Caller(3)
if !ok {
file = "#unknown"
line = 0
}
// get the name of the level
var levelName string
switch level {
case LevelDebug:
levelName = "DEBUG"
case LevelInfo:
levelName = "INFO "
case LevelWarning:
levelName = "WARN "
case LevelError:
levelName = "ERROR"
case LevelFatal:
levelName = "FATAL"
}
if levelName == "" {
message = fmt.Sprintf("Invalid level value given: %d. Original message: ", level) + message
levelName = "WARN "
level = LevelWarning
}
printMessage := "[" + levelName + "] " + time.Now().Local().Format("2006-01-02 15:04:05") +
getSourceMessage(file, line, pc, l) +
fmt.Sprintf(message, parameters...)
if l.LogLevel <= level && l.fileLogger != nil {
l.fileLogger.Println(printMessage)
l.logFile.Sync()
if level == LevelFatal {
l.CloseFile()
}
}
if l.PrintLevel <= level {
if level == LevelError {
l.consoleLoggerErr.Println(printMessage)
} else if level == LevelFatal {
l.consoleLoggerErr.Fatal(printMessage)
} else {
l.consoleLogger.Println(printMessage)
}
}
}
func getSourceMessage(file string, line int, pc uintptr, l Logger) string {
if !l.PrintSource {
return " - "
}
fileName := file[strings.LastIndex(file, "/")+1:] + ":" + strconv.Itoa(line)
return " (" + fileName + ") - "
}
func (l *Logger) setup() {
// log.Ldate|log.Ltime|log.Lshortfile
l.consoleLogger = log.New(os.Stdout, "", 0)
l.consoleLoggerErr = log.New(os.Stderr, "", 0)
if strings.TrimSpace(l.LogFilePath) != "" {
file, err := os.OpenFile(l.LogFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err == nil {
l.fileLogger = log.New(file, "", 0)
l.logFile = file
} else {
l.Log(LevelError, fmt.Sprintf("Cannot access the log file '%s'\n%s", l.LogFilePath, err.Error()))
}
} else {
l.fileLogger = nil
if l.logFile != nil {
l.logFile.Close()
l.logFile = nil
}
}
}
func (l *Logger) CloseFile() {
if l.logFile != nil {
l.logFile.Close()
l.logFile = nil
l.fileLogger = nil
}
}
func SetGlobalLogger(l *Logger) {
dLogger = *l
dLogger.setup()
}
func GetGlobalLogger() *Logger {
return &dLogger
}
func Debug(message string, parameters ...any) {
dLogger.Log(LevelDebug, message, parameters...)
}
func Info(message string, parameters ...any) {
dLogger.Log(LevelInfo, message, parameters...)
}
func Warning(message string, parameters ...any) {
dLogger.Log(LevelWarning, message, parameters...)
}
func Error(message string, parameters ...any) {
dLogger.Log(LevelError, message, parameters...)
}
func Fatal(message string, parameters ...any) {
dLogger.Log(LevelFatal, message, parameters...)
}
func CloseFile() {
dLogger.CloseFile()
}
// Tries to convert the given level name to the corresponding level code.
// Allowed values are: 'debug', 'info', 'warn', 'warning', 'error', 'panic' and 'fatal'
// If an incorrect level name was given an warning is logged and info will be returned
func GetLevelByName(levelName string) Level {
levelName = strings.ToLower(levelName)
switch levelName {
case "debug":
return LevelDebug
case "info":
return LevelInfo
case "warn", "warning":
return LevelWarning
case "error":
return LevelError
case "panic", "fatal":
return LevelFatal
default:
{
Warning("Unable to parse the level name '%s'. Expected 'debug', 'info', 'warn', 'error' or 'fatal'", levelName)
return LevelInfo
}
}
}

View File

@ -1,6 +1,7 @@
package utils package utils
import ( import (
"os"
"reflect" "reflect"
"unicode" "unicode"
) )
@ -36,3 +37,15 @@ func Copy(source interface{}, destin interface{}) {
reflect.ValueOf(destin).Elem().Set(x) reflect.ValueOf(destin).Elem().Set(x)
} }
} }
// GetEnvString tries to get an environment variable from the system
// as a string value. If the env was not found the given default value
// will be returned
func GetEnvString(name string, defaultValue string) string {
val := defaultValue
if strVal, isSet := os.LookupEnv(name); isSet {
val = strVal
}
return val
}

View File

@ -1,64 +0,0 @@
#!/bin/bash
## This script deploys the build files to the given directory.
##
## You can define all below variables also via environment variables
## with the prefix NC_DOC_CONVERTER_
## Example: NC_DOC_CONVERTER_ROOT_DIRECTORY="/home/ncDocConverter/"
## You can set theses for example in jenkins.
# Directory in which the executable file should be installed
ROOT_DIRECTORY="/usr/share/RPJosh/ncDocConverter/"
# Configuration directory containing the configuration file
CONFIGURATION_DIRECTORY="/etc/ncDocConverter/"
# User to execute the program
USER=ncDocConverter
# The service name for systemctl
SERVICE_NAME=ncDocConverter
# Arch and operating system
ARCH="amd64"
version="$(cat VERSION)"
overwriteVars() {
vars=( ROOT_DIRECTORY CONFIGURATION_DIRECTORY USER SERVICE_NAME )
for var in "${vars[@]}"; do
envVar="NC_DOC_CONVERTER_"$var""
#envVar="$(eval "echo \$$envVar")"
envVar="${!envVar}"
if [ -n "$envVar" ]; then
declare -g $var="$envVar"
fi
done
}
# Overwrite environment variables
overwriteVars
set -e
## Stop service
systemctl is-active --quiet "$SERVICE_NAME" && systemctl stop "$SERVICE_NAME"
## Copy binary
mkdir -p "$ROOT_DIRECTORY"
cp "ncDocConverth-"$version"-"$ARCH"" ""$ROOT_DIRECTORY"ncDocConverth"
chown -R ""$USER":"$USER"" "$ROOT_DIRECTORY"
## Copy configuration
mkdir -p "$CONFIGURATION_DIRECTORY"
if ! [ -e ""$CONFIGURATION_DIRECTORY"config.yaml" ]; then
cp ./configs/config.yaml ""$CONFIGURATION_DIRECTORY"config.yaml.example"
cp ./configs/ncConverter.hjson ""$CONFIGURATION_DIRECTORY"config.hjson.example"
fi
chown -R ""$USER":"$USER"" "$CONFIGURATION_DIRECTORY"
chmod -R 0600 "$CONFIGURATION_DIRECTORY"
chmod 0700 "$CONFIGURATION_DIRECTORY"
## Start service
systemctl start "$SERVICE_NAME"
exit 0

View File

@ -10,6 +10,9 @@ if "%~1"=="-FIXED_CTRL_C" (
GOTO :EOF GOTO :EOF
) )
SET PATH=%PATH%;C:\Windows\System32 SET PATH=%PATH%;C:\Windows\System3
set GOTMPDIR=C:\MYCOMP
nodemon --delay 1s -e go,html --ignore web/app/ --signal SIGKILL --exec go run ./cmd/ncDocConverth || exit 1 set /p version=< VERSION
.\web\app\node_modules\.bin\nodemon --delay 1s -e go,html,yaml --signal SIGKILL --ignore web/app/ --quiet ^
--exec "echo [Restarting] && go run -ldflags ""-X main.version=%VERSION%"" ./cmd/ncDocConverth" -- %args% || "exit 1"

View File

@ -1,3 +1,7 @@
#!/bin/sh #!/bin/sh
nodemon --delay 1s -e go,html,yaml --ignore web/app/ --signal SIGTERM --exec 'go run ./cmd/ncDocConverth || exit 1' GREEN='\033[0;32m'
NC='\033[0m'
nodemon --delay 1s -e go,html,yaml --ignore web/app/ --signal SIGTERM --quiet --exec \
'echo "\n'"$GREEN"'[Restarting]'"$NC"'" && go run -ldflags "-X main.version="$(cat VERSION)"" ./cmd/ncDocConverth' -- "$@" "|| exit 1"