mirror of
https://github.com/nabbar/golib.git
synced 2025-10-05 07:46:56 +08:00
11
.github/workflows/go.yml
vendored
11
.github/workflows/go.yml
vendored
@@ -20,13 +20,14 @@ jobs:
|
|||||||
- name: Set up Go 1.x
|
- name: Set up Go 1.x
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: ^1.14
|
go-version: ^1.16
|
||||||
id: go
|
id: go
|
||||||
|
|
||||||
- name: Check out code into the Go module directory
|
- name: Check out code into the Go module directory
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Link workspace with GOPATH
|
- name: Link workspace with GOPATH
|
||||||
|
continue-on-error: false
|
||||||
run: |
|
run: |
|
||||||
sudo mkdir -vp $(dirname ${GOPATH}/src/github.com/${GITHUB_REPOSITORY})
|
sudo mkdir -vp $(dirname ${GOPATH}/src/github.com/${GITHUB_REPOSITORY})
|
||||||
sudo chown -R ${USER}:users $(dirname ${GOPATH}/src/github.com/${GITHUB_REPOSITORY})
|
sudo chown -R ${USER}:users $(dirname ${GOPATH}/src/github.com/${GITHUB_REPOSITORY})
|
||||||
@@ -34,17 +35,19 @@ jobs:
|
|||||||
sudo ln -svf $(pwd) ${GOPATH}/src/github.com/${GITHUB_REPOSITORY}
|
sudo ln -svf $(pwd) ${GOPATH}/src/github.com/${GITHUB_REPOSITORY}
|
||||||
|
|
||||||
- name: Check out tools into the Go module directory
|
- name: Check out tools into the Go module directory
|
||||||
|
continue-on-error: false
|
||||||
run: |
|
run: |
|
||||||
git clone https://github.com/nabbar/gotools.git scripts
|
git clone https://github.com/nabbar/gotools.git scripts
|
||||||
./scripts/prepare
|
./scripts/prepare
|
||||||
|
|
||||||
|
- name: Update vendor or dependancies
|
||||||
|
continue-on-error: false
|
||||||
|
run: ./scripts/ci_depend
|
||||||
|
|
||||||
- name: Check goFmt & goImport
|
- name: Check goFmt & goImport
|
||||||
continue-on-error: false
|
continue-on-error: false
|
||||||
run: ./scripts/ci_format
|
run: ./scripts/ci_format
|
||||||
|
|
||||||
- name: Update vendor or dependancies
|
|
||||||
run: ./scripts/ci_depend
|
|
||||||
|
|
||||||
- name: Check Missing License
|
- name: Check Missing License
|
||||||
continue-on-error: false
|
continue-on-error: false
|
||||||
run: ./scripts/ci_license
|
run: ./scripts/ci_license
|
||||||
|
491
.golangci.yml
491
.golangci.yml
@@ -1,23 +1,88 @@
|
|||||||
# This file contains all available configuration options
|
linters-settings:
|
||||||
# with their default values.
|
dupl:
|
||||||
|
threshold: 100
|
||||||
|
funlen:
|
||||||
|
lines: 250
|
||||||
|
statements: 200
|
||||||
|
gci:
|
||||||
|
local-prefixes: github.com/golangci/golangci-lint
|
||||||
|
goconst:
|
||||||
|
min-len: 2
|
||||||
|
min-occurrences: 2
|
||||||
|
gocyclo:
|
||||||
|
min-complexity: 50
|
||||||
|
goimports:
|
||||||
|
local-prefixes: github.com/golangci/golangci-lint
|
||||||
|
gomnd:
|
||||||
|
settings:
|
||||||
|
mnd:
|
||||||
|
# don't include the "operation" and "assign"
|
||||||
|
checks: argument,case,condition,return
|
||||||
|
govet:
|
||||||
|
check-shadowing: true
|
||||||
|
settings:
|
||||||
|
printf:
|
||||||
|
funcs:
|
||||||
|
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof
|
||||||
|
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf
|
||||||
|
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf
|
||||||
|
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
|
||||||
|
lll:
|
||||||
|
line-length: 140
|
||||||
|
maligned:
|
||||||
|
suggest-new: true
|
||||||
|
misspell:
|
||||||
|
locale: US
|
||||||
|
|
||||||
|
linters:
|
||||||
|
# please, do not use `enable-all`: it's deprecated and will be removed soon.
|
||||||
|
# inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint
|
||||||
|
disable-all: true
|
||||||
|
enable:
|
||||||
|
- bodyclose
|
||||||
|
- deadcode
|
||||||
|
- dogsled
|
||||||
|
- dupl
|
||||||
|
- errcheck
|
||||||
|
- exportloopref
|
||||||
|
- exhaustive
|
||||||
|
- funlen
|
||||||
|
- goconst
|
||||||
|
- gocyclo
|
||||||
|
- gofmt
|
||||||
|
- goimports
|
||||||
|
- gomnd
|
||||||
|
- goprintffuncname
|
||||||
|
- gosec
|
||||||
|
- gosimple
|
||||||
|
- govet
|
||||||
|
- ineffassign
|
||||||
|
- lll
|
||||||
|
- misspell
|
||||||
|
- nakedret
|
||||||
|
- noctx
|
||||||
|
- rowserrcheck
|
||||||
|
- staticcheck
|
||||||
|
- structcheck
|
||||||
|
- stylecheck
|
||||||
|
- typecheck
|
||||||
|
- unconvert
|
||||||
|
- unparam
|
||||||
|
- unused
|
||||||
|
- varcheck
|
||||||
|
|
||||||
# options for analysis running
|
|
||||||
run:
|
run:
|
||||||
# default concurrency is a available CPU number
|
# default concurrency is a available CPU number
|
||||||
concurrency: 4
|
#concurrency: 4
|
||||||
|
|
||||||
# timeout for analysis, e.g. 30s, 5m, default is 1m
|
# timeout for analysis, e.g. 30s, 5m, default is 1m
|
||||||
timeout: 30m
|
timeout: 10m
|
||||||
|
|
||||||
# exit code when at least one issue was found, default is 1
|
# exit code when at least one issue was found, default is 1
|
||||||
issues-exit-code: 0
|
issues-exit-code: 1
|
||||||
|
|
||||||
# include test files or not, default is true
|
# include test files or not, default is true
|
||||||
tests: true
|
tests: false
|
||||||
|
|
||||||
# list of build tags, all linters use it. Default is empty list.
|
# list of build tags, all linters use it. Default is empty list.
|
||||||
build-tags: []
|
#build-tags:
|
||||||
|
# - mytag
|
||||||
# which dirs to skip: issues from them won't be reported;
|
# which dirs to skip: issues from them won't be reported;
|
||||||
# can use regexp here: generated.*, regexp is applied on full path;
|
# can use regexp here: generated.*, regexp is applied on full path;
|
||||||
# default value is empty list, but default dirs are skipped independently
|
# default value is empty list, but default dirs are skipped independently
|
||||||
@@ -25,22 +90,21 @@ run:
|
|||||||
# "/" will be replaced by current OS file path separator to properly work
|
# "/" will be replaced by current OS file path separator to properly work
|
||||||
# on Windows.
|
# on Windows.
|
||||||
skip-dirs:
|
skip-dirs:
|
||||||
- vendor
|
- test/
|
||||||
- test
|
- vendor/
|
||||||
|
- .*
|
||||||
# default is true. Enables skipping of directories:
|
# default is true. Enables skipping of directories:
|
||||||
# vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
|
# vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
|
||||||
skip-dirs-use-default: true
|
#skip-dirs-use-default: true
|
||||||
|
|
||||||
# which files to skip: they will be analyzed, but issues from them
|
# which files to skip: they will be analyzed, but issues from them
|
||||||
# won't be reported. Default value is empty list, but there is
|
# won't be reported. Default value is empty list, but there is
|
||||||
# no need to include all autogenerated files, we confidently recognize
|
# no need to include all autogenerated files, we confidently recognize
|
||||||
# autogenerated files. If it's not please let us know.
|
# autogenerated files. If it's not please let us know.
|
||||||
# "/" will be replaced by current OS file path separator to properly work
|
# "/" will be replaced by current OS file path separator to properly work
|
||||||
# on Windows.
|
# on Windows.
|
||||||
skip-files:
|
#skip-files:
|
||||||
- ".*\\.my\\.go$"
|
# - ".*\\.my\\.go$"
|
||||||
|
# - lib/bad.go
|
||||||
# by default isn't set. If set we pass it to "go list -mod={option}". From "go help modules":
|
# by default isn't set. If set we pass it to "go list -mod={option}". From "go help modules":
|
||||||
# If invoked with -mod=readonly, the go command is disallowed from the implicit
|
# If invoked with -mod=readonly, the go command is disallowed from the implicit
|
||||||
# automatic updating of go.mod described above. Instead, it fails when any changes
|
# automatic updating of go.mod described above. Instead, it fails when any changes
|
||||||
@@ -49,401 +113,20 @@ run:
|
|||||||
# If invoked with -mod=vendor, the go command assumes that the vendor
|
# If invoked with -mod=vendor, the go command assumes that the vendor
|
||||||
# directory holds the correct copies of dependencies and ignores
|
# directory holds the correct copies of dependencies and ignores
|
||||||
# the dependency descriptions in go.mod.
|
# the dependency descriptions in go.mod.
|
||||||
#modules-download-mode: readonly|release|vendor
|
modules-download-mode: vendor
|
||||||
|
|
||||||
# Allow multiple parallel golangci-lint instances running.
|
# Allow multiple parallel golangci-lint instances running.
|
||||||
# If false (default) - golangci-lint acquires file lock on start.
|
# If false (default) - golangci-lint acquires file lock on start.
|
||||||
allow-parallel-runners: false
|
allow-parallel-runners: true
|
||||||
|
|
||||||
|
|
||||||
# output configuration options
|
# output configuration options
|
||||||
output:
|
output:
|
||||||
# colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number"
|
# colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number"
|
||||||
format: colored-line-number
|
format: colored-line-number
|
||||||
|
|
||||||
# print lines of code with issue, default is true
|
# print lines of code with issue, default is true
|
||||||
print-issued-lines: true
|
print-issued-lines: true
|
||||||
|
|
||||||
# print linter name in the end of issue text, default is true
|
# print linter name in the end of issue text, default is true
|
||||||
print-linter-name: true
|
print-linter-name: true
|
||||||
|
|
||||||
# make issues output unique by line, default is true
|
# make issues output unique by line, default is true
|
||||||
uniq-by-line: true
|
uniq-by-line: true
|
||||||
|
|
||||||
# add a prefix to the output file references; default is no prefix
|
# add a prefix to the output file references; default is no prefix
|
||||||
path-prefix: ""
|
path-prefix: ""
|
||||||
|
|
||||||
|
|
||||||
# all available settings of specific linters
|
|
||||||
linters-settings:
|
|
||||||
dogsled:
|
|
||||||
# checks assignments with too many blank identifiers; default is 2
|
|
||||||
max-blank-identifiers: 2
|
|
||||||
dupl:
|
|
||||||
# tokens count to trigger issue, 150 by default
|
|
||||||
threshold: 100
|
|
||||||
errcheck:
|
|
||||||
# report about not checking of errors in type assertions: `a := b.(MyStruct)`;
|
|
||||||
# default is false: such cases aren't reported by default.
|
|
||||||
check-type-assertions: false
|
|
||||||
|
|
||||||
# report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`;
|
|
||||||
# default is false: such cases aren't reported by default.
|
|
||||||
check-blank: false
|
|
||||||
|
|
||||||
# [deprecated] comma-separated list of pairs of the form pkg:regex
|
|
||||||
# the regex is used to ignore names within pkg. (default "fmt:.*").
|
|
||||||
# see https://github.com/kisielk/errcheck#the-deprecated-method for details
|
|
||||||
ignore: fmt:.*,io/ioutil:^Read.*
|
|
||||||
|
|
||||||
# path to a file containing a list of functions to exclude from checking
|
|
||||||
# see https://github.com/kisielk/errcheck#excluding-functions for details
|
|
||||||
# exclude: /path/to/file.txt
|
|
||||||
exhaustive:
|
|
||||||
# indicates that switch statements are to be considered exhaustive if a
|
|
||||||
# 'default' case is present, even if all enum members aren't listed in the
|
|
||||||
# switch
|
|
||||||
default-signifies-exhaustive: false
|
|
||||||
funlen:
|
|
||||||
lines: 1000
|
|
||||||
statements: 100
|
|
||||||
gocognit:
|
|
||||||
# minimal code complexity to report, 30 by default (but we recommend 10-20)
|
|
||||||
min-complexity: 50
|
|
||||||
nestif:
|
|
||||||
# minimal complexity of if statements to report, 5 by default
|
|
||||||
min-complexity: 4
|
|
||||||
goconst:
|
|
||||||
# minimal length of string constant, 3 by default
|
|
||||||
min-len: 3
|
|
||||||
# minimal occurrences count to trigger, 3 by default
|
|
||||||
min-occurrences: 3
|
|
||||||
gocritic:
|
|
||||||
# Which checks should be enabled; can't be combined with 'disabled-checks';
|
|
||||||
# See https://go-critic.github.io/overview#checks-overview
|
|
||||||
# To check which checks are enabled run `GL_DEBUG=gocritic golangci-lint run`
|
|
||||||
# By default list of stable checks is used.
|
|
||||||
# enabled-checks:
|
|
||||||
# - rangeValCopy
|
|
||||||
|
|
||||||
# Which checks should be disabled; can't be combined with 'enabled-checks'; default is empty
|
|
||||||
disabled-checks:
|
|
||||||
- regexpMust
|
|
||||||
|
|
||||||
# Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.
|
|
||||||
# Empty list by default. See https://github.com/go-critic/go-critic#usage -> section "Tags".
|
|
||||||
enabled-tags:
|
|
||||||
- performance
|
|
||||||
disabled-tags:
|
|
||||||
- experimental
|
|
||||||
|
|
||||||
settings: # settings passed to gocritic
|
|
||||||
captLocal: # must be valid enabled check name
|
|
||||||
paramsOnly: true
|
|
||||||
rangeValCopy:
|
|
||||||
sizeThreshold: 32
|
|
||||||
gocyclo:
|
|
||||||
# minimal code complexity to report, 30 by default (but we recommend 10-20)
|
|
||||||
min-complexity: 50
|
|
||||||
godot:
|
|
||||||
# check all top-level comments, not only declarations
|
|
||||||
check-all: false
|
|
||||||
godox:
|
|
||||||
# report any comments starting with keywords, this is useful for TODO or FIXME comments that
|
|
||||||
# might be left in the code accidentally and should be resolved before merging
|
|
||||||
keywords: # default keywords are TODO, BUG, and FIXME, these can be overwritten by this setting
|
|
||||||
- NOTE
|
|
||||||
- OPTIMIZE # marks code that should be optimized before merging
|
|
||||||
- HACK # marks hack-arounds that should be removed before merging
|
|
||||||
gofmt:
|
|
||||||
# simplify code: gofmt with `-s` option, true by default
|
|
||||||
simplify: true
|
|
||||||
goheader:
|
|
||||||
values:
|
|
||||||
const:
|
|
||||||
# define here const type values in format k:v, for example:
|
|
||||||
# YEAR: 2020
|
|
||||||
# COMPANY: MY COMPANY
|
|
||||||
regexp:
|
|
||||||
# define here regexp type values, for example
|
|
||||||
# AUTHOR: .*@mycompany\.com
|
|
||||||
template:
|
|
||||||
# put here copyright header template for source code files, for example:
|
|
||||||
# {{ AUTHOR }} {{ COMPANY }} {{ YEAR }}
|
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at:
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
template-path:
|
|
||||||
# also as alternative of directive 'template' you may put the path to file with the template source
|
|
||||||
goimports:
|
|
||||||
# put imports beginning with prefix after 3rd-party packages;
|
|
||||||
# it's a comma-separated list of prefixes
|
|
||||||
local-prefixes: github.com/org/project
|
|
||||||
golint:
|
|
||||||
# minimal confidence for issues, default is 0.8
|
|
||||||
min-confidence: 0.8
|
|
||||||
gomnd:
|
|
||||||
settings:
|
|
||||||
mnd:
|
|
||||||
# the list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.
|
|
||||||
checks: argument,case,condition,operation,return,assign
|
|
||||||
gomodguard:
|
|
||||||
allowed:
|
|
||||||
modules: # List of allowed modules
|
|
||||||
# - gopkg.in/yaml.v2
|
|
||||||
domains: # List of allowed module domains
|
|
||||||
# - golang.org
|
|
||||||
blocked:
|
|
||||||
modules: # List of blocked modules
|
|
||||||
# - github.com/uudashr/go-module: # Blocked module
|
|
||||||
# recommendations: # Recommended modules that should be used instead (Optional)
|
|
||||||
# - golang.org/x/mod
|
|
||||||
# reason: "`mod` is the official go.mod parser library." # Reason why the recommended module should be used (Optional)
|
|
||||||
versions: # List of blocked module version constraints
|
|
||||||
# - github.com/mitchellh/go-homedir: # Blocked module with version constraint
|
|
||||||
# version: "< 1.1.0" # Version constraint, see https://github.com/Masterminds/semver#basic-comparisons
|
|
||||||
# reason: "testing if blocked version constraint works." # Reason why the version constraint exists. (Optional)
|
|
||||||
govet:
|
|
||||||
# report about shadowed variables
|
|
||||||
check-shadowing: true
|
|
||||||
|
|
||||||
# settings per analyzer
|
|
||||||
settings:
|
|
||||||
printf: # analyzer name, run `go tool vet help` to see all analyzers
|
|
||||||
funcs: # run `go tool vet help printf` to see available settings for `printf` analyzer
|
|
||||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof
|
|
||||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf
|
|
||||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf
|
|
||||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
|
|
||||||
|
|
||||||
# enable or disable analyzers by name
|
|
||||||
enable:
|
|
||||||
- atomicalign
|
|
||||||
enable-all: false
|
|
||||||
disable:
|
|
||||||
- shadow
|
|
||||||
disable-all: false
|
|
||||||
depguard:
|
|
||||||
list-type: blacklist
|
|
||||||
include-go-root: false
|
|
||||||
packages:
|
|
||||||
# - github.com/sirupsen/logrus
|
|
||||||
packages-with-error-message:
|
|
||||||
# specify an error message to output when a blacklisted package is used
|
|
||||||
# - github.com/sirupsen/logrus: "logging is allowed only by logutils.Log"
|
|
||||||
lll:
|
|
||||||
# max line length, lines longer will be reported. Default is 120.
|
|
||||||
# '\t' is counted as 1 character by default, and can be changed with the tab-width option
|
|
||||||
line-length: 240
|
|
||||||
# tab width in spaces. Default to 1.
|
|
||||||
tab-width: 1
|
|
||||||
maligned:
|
|
||||||
# print struct with more effective memory layout or not, false by default
|
|
||||||
suggest-new: true
|
|
||||||
misspell:
|
|
||||||
# Correct spellings using locale preferences for US or UK.
|
|
||||||
# Default is to use a neutral variety of English.
|
|
||||||
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
|
|
||||||
locale: US
|
|
||||||
ignore-words:
|
|
||||||
- someword
|
|
||||||
nakedret:
|
|
||||||
# make an issue if func has more lines of code than this setting and it has naked returns; default is 30
|
|
||||||
max-func-lines: 30
|
|
||||||
prealloc:
|
|
||||||
# XXX: we don't recommend using this linter before doing performance profiling.
|
|
||||||
# For most programs usage of prealloc will be a premature optimization.
|
|
||||||
|
|
||||||
# Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.
|
|
||||||
# True by default.
|
|
||||||
simple: true
|
|
||||||
range-loops: true # Report preallocation suggestions on range loops, true by default
|
|
||||||
for-loops: false # Report preallocation suggestions on for loops, false by default
|
|
||||||
nolintlint:
|
|
||||||
# Enable to ensure that nolint directives are all used. Default is true.
|
|
||||||
allow-unused: false
|
|
||||||
# Disable to ensure that nolint directives don't have a leading space. Default is true.
|
|
||||||
allow-leading-space: true
|
|
||||||
# Exclude following linters from requiring an explanation. Default is [].
|
|
||||||
allow-no-explanation: []
|
|
||||||
# Enable to require an explanation of nonzero length after each nolint directive. Default is false.
|
|
||||||
require-explanation: true
|
|
||||||
# Enable to require nolint directives to mention the specific linter being suppressed. Default is false.
|
|
||||||
require-specific: true
|
|
||||||
rowserrcheck:
|
|
||||||
packages:
|
|
||||||
- github.com/jmoiron/sqlx
|
|
||||||
testpackage:
|
|
||||||
# regexp pattern to skip files
|
|
||||||
skip-regexp: (export|internal)_test\.go
|
|
||||||
unparam:
|
|
||||||
# Inspect exported functions, default is false. Set to true if no external program/library imports your code.
|
|
||||||
# XXX: if you enable this setting, unparam will report a lot of false-positives in text editors:
|
|
||||||
# if it's called for subdir of a project it can't find external interfaces. All text editor integrations
|
|
||||||
# with golangci-lint call it on a directory with the changed file.
|
|
||||||
check-exported: false
|
|
||||||
unused:
|
|
||||||
# treat code as a program (not a library) and report unused exported identifiers; default is false.
|
|
||||||
# XXX: if you enable this setting, unused will report a lot of false-positives in text editors:
|
|
||||||
# if it's called for subdir of a project it can't find funcs usages. All text editor integrations
|
|
||||||
# with golangci-lint call it on a directory with the changed file.
|
|
||||||
check-exported: false
|
|
||||||
whitespace:
|
|
||||||
multi-if: false # Enforces newlines (or comments) after every multi-line if statement
|
|
||||||
multi-func: false # Enforces newlines (or comments) after every multi-line function signature
|
|
||||||
wsl:
|
|
||||||
# If true append is only allowed to be cuddled if appending value is
|
|
||||||
# matching variables, fields or types on line above. Default is true.
|
|
||||||
strict-append: true
|
|
||||||
# Allow calls and assignments to be cuddled as long as the lines have any
|
|
||||||
# matching variables, fields or types. Default is true.
|
|
||||||
allow-assign-and-call: true
|
|
||||||
# Allow multiline assignments to be cuddled. Default is true.
|
|
||||||
allow-multiline-assign: true
|
|
||||||
# Allow declarations (var) to be cuddled.
|
|
||||||
allow-cuddle-declarations: true
|
|
||||||
# Allow trailing comments in ending of blocks
|
|
||||||
allow-trailing-comment: false
|
|
||||||
# Force newlines in end of case at this limit (0 = never).
|
|
||||||
force-case-trailing-whitespace: 0
|
|
||||||
# Force cuddling of err checks with err var assignment
|
|
||||||
force-err-cuddling: false
|
|
||||||
# Allow leading comments to be separated with empty liens
|
|
||||||
allow-separated-leading-comment: false
|
|
||||||
gofumpt:
|
|
||||||
# Choose whether or not to use the extra rules that are disabled
|
|
||||||
# by default
|
|
||||||
extra-rules: false
|
|
||||||
|
|
||||||
# The custom section can be used to define linter plugins to be loaded at runtime. See README doc
|
|
||||||
# for more info.
|
|
||||||
#custom:
|
|
||||||
# Each custom linter should have a unique name.
|
|
||||||
#example:
|
|
||||||
# The path to the plugin *.so. Can be absolute or local. Required for each custom linter
|
|
||||||
#path: /path/to/example.so
|
|
||||||
# The description of the linter. Optional, just for documentation purposes.
|
|
||||||
#description: This is an example usage of a plugin linter.
|
|
||||||
# Intended to point to the repo location of the linter. Optional, just for documentation purposes.
|
|
||||||
#original-url: github.com/golangci/example-linter
|
|
||||||
|
|
||||||
linters:
|
|
||||||
fast: false
|
|
||||||
enable-all: true
|
|
||||||
disable:
|
|
||||||
- gochecknoinits
|
|
||||||
- gochecknoglobals
|
|
||||||
- wsl
|
|
||||||
- golint
|
|
||||||
- gocritic
|
|
||||||
- stylecheck
|
|
||||||
- whitespace
|
|
||||||
- gofumpt
|
|
||||||
- nestif
|
|
||||||
- nolintlint
|
|
||||||
- nlreturn
|
|
||||||
|
|
||||||
issues:
|
|
||||||
# List of regexps of issue texts to exclude, empty list by default.
|
|
||||||
# But independently from this option we use default exclude patterns,
|
|
||||||
# it can be disabled by `exclude-use-default: false`. To list all
|
|
||||||
# excluded by default patterns execute `golangci-lint run --help`
|
|
||||||
exclude:
|
|
||||||
- .*test.*\.go
|
|
||||||
|
|
||||||
|
|
||||||
# Excluding configuration per-path, per-linter, per-text and per-source
|
|
||||||
exclude-rules:
|
|
||||||
# Exclude some linters from running on tests files.
|
|
||||||
- path: _test\.go
|
|
||||||
linters:
|
|
||||||
- gocyclo
|
|
||||||
- errcheck
|
|
||||||
- dupl
|
|
||||||
- gosec
|
|
||||||
|
|
||||||
# Exclude known linters from partially hard-vendored code,
|
|
||||||
# which is impossible to exclude via "nolint" comments.
|
|
||||||
- path: internal/hmac/
|
|
||||||
text: "weak cryptographic primitive"
|
|
||||||
linters:
|
|
||||||
- gosec
|
|
||||||
|
|
||||||
# Exclude some staticcheck messages
|
|
||||||
- linters:
|
|
||||||
- staticcheck
|
|
||||||
text: "SA9003:"
|
|
||||||
|
|
||||||
# Exclude lll issues for long lines with go:generate
|
|
||||||
- linters:
|
|
||||||
- lll
|
|
||||||
source: "^//go:generate "
|
|
||||||
|
|
||||||
# Independently from option `exclude` we use default exclude patterns,
|
|
||||||
# it can be disabled by this option. To list all
|
|
||||||
# excluded by default patterns execute `golangci-lint run --help`.
|
|
||||||
# Default value for this option is true.
|
|
||||||
exclude-use-default: false
|
|
||||||
|
|
||||||
# The default value is false. If set to true exclude and exclude-rules
|
|
||||||
# regular expressions become case sensitive.
|
|
||||||
exclude-case-sensitive: false
|
|
||||||
|
|
||||||
# The list of ids of default excludes to include or disable. By default it's empty.
|
|
||||||
include:
|
|
||||||
- EXC0002 # disable excluding of issues about comments from golint
|
|
||||||
|
|
||||||
# Maximum issues count per one linter. Set to 0 to disable. Default is 50.
|
|
||||||
max-issues-per-linter: 0
|
|
||||||
|
|
||||||
# Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
|
|
||||||
max-same-issues: 0
|
|
||||||
|
|
||||||
# Show only new issues: if there are unstaged changes or untracked files,
|
|
||||||
# only those changes are analyzed, else only changes in HEAD~ are analyzed.
|
|
||||||
# It's a super-useful option for integration of golangci-lint into existing
|
|
||||||
# large codebase. It's not practical to fix all existing issues at the moment
|
|
||||||
# of integration: much better don't allow issues in new code.
|
|
||||||
# Default is false.
|
|
||||||
new: false
|
|
||||||
|
|
||||||
# Show only new issues created after git revision `REV`
|
|
||||||
#new-from-rev: REV
|
|
||||||
|
|
||||||
# Show only new issues created in git patch with set file path.
|
|
||||||
#new-from-patch: path/to/patch/file
|
|
||||||
|
|
||||||
severity:
|
|
||||||
# Default value is empty string.
|
|
||||||
# Set the default severity for issues. If severity rules are defined and the issues
|
|
||||||
# do not match or no severity is provided to the rule this will be the default
|
|
||||||
# severity applied. Severities should match the supported severity names of the
|
|
||||||
# selected out format.
|
|
||||||
# - Code climate: https://docs.codeclimate.com/docs/issues#issue-severity
|
|
||||||
# - Checkstyle: https://checkstyle.sourceforge.io/property_types.html#severity
|
|
||||||
# - Github: https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message
|
|
||||||
default-severity: error
|
|
||||||
|
|
||||||
# The default value is false.
|
|
||||||
# If set to true severity-rules regular expressions become case sensitive.
|
|
||||||
case-sensitive: false
|
|
||||||
|
|
||||||
# Default value is empty list.
|
|
||||||
# When a list of severity rules are provided, severity information will be added to lint
|
|
||||||
# issues. Severity rules have the same filtering capability as exclude rules except you
|
|
||||||
# are allowed to specify one matcher per severity rule.
|
|
||||||
# Only affects out formats that support setting severity information.
|
|
||||||
rules:
|
|
||||||
- linters:
|
|
||||||
- dupl
|
|
||||||
severity: info
|
|
||||||
|
@@ -43,11 +43,9 @@ import (
|
|||||||
type ArchiveType uint8
|
type ArchiveType uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ArchiveTypeUnknown = iota
|
TypeTar = iota + 1
|
||||||
ArchiveTypeZip
|
TypeTarGzip
|
||||||
ArchiveTypeTar
|
TypeGzip
|
||||||
ArchiveTypeTarGzip
|
|
||||||
ArchiveTypeGzip
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func ExtractFile(src, dst libiot.FileProgress, fileNameContain, fileNameRegex string) liberr.Error {
|
func ExtractFile(src, dst libiot.FileProgress, fileNameContain, fileNameRegex string) liberr.Error {
|
||||||
@@ -204,15 +202,16 @@ func ExtractAll(src libiot.FileProgress, originalName, outputPath string, defaul
|
|||||||
func CreateArchive(archiveType ArchiveType, archive libiot.FileProgress, pathContent ...string) (created bool, err liberr.Error) {
|
func CreateArchive(archiveType ArchiveType, archive libiot.FileProgress, pathContent ...string) (created bool, err liberr.Error) {
|
||||||
//@TODO: make function
|
//@TODO: make function
|
||||||
if len(pathContent) < 1 {
|
if len(pathContent) < 1 {
|
||||||
|
//nolint #goerr113
|
||||||
return false, ErrorParamsEmpty.ErrorParent(fmt.Errorf("pathContent is empty"))
|
return false, ErrorParamsEmpty.ErrorParent(fmt.Errorf("pathContent is empty"))
|
||||||
}
|
}
|
||||||
|
|
||||||
switch archiveType {
|
switch archiveType {
|
||||||
case ArchiveTypeGzip:
|
case TypeGzip:
|
||||||
return libgzp.Create(archive, pathContent...)
|
return libgzp.Create(archive, pathContent...)
|
||||||
case ArchiveTypeTar:
|
case TypeTar:
|
||||||
return libtar.Create(archive, pathContent...)
|
return libtar.Create(archive, pathContent...)
|
||||||
case ArchiveTypeTarGzip:
|
case TypeTarGzip:
|
||||||
return libtar.CreateGzip(archive, pathContent...)
|
return libtar.CreateGzip(archive, pathContent...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -34,10 +34,9 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
liberr "github.com/nabbar/golib/errors"
|
liberr "github.com/nabbar/golib/errors"
|
||||||
libiot "github.com/nabbar/golib/ioutils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Create(archive libiot.FileProgress, content ...string) (bool, liberr.Error) {
|
func Create(archive io.WriteSeeker, content ...string) (bool, liberr.Error) {
|
||||||
var (
|
var (
|
||||||
w *gzip.Writer
|
w *gzip.Writer
|
||||||
f *os.File
|
f *os.File
|
||||||
@@ -46,6 +45,7 @@ func Create(archive libiot.FileProgress, content ...string) (bool, liberr.Error)
|
|||||||
)
|
)
|
||||||
|
|
||||||
if len(content) != 1 {
|
if len(content) != 1 {
|
||||||
|
//nolint #goerr113
|
||||||
return false, ErrorParamsMismatching.ErrorParent(fmt.Errorf("content path must be limited to strictly one contents"))
|
return false, ErrorParamsMismatching.ErrorParent(fmt.Errorf("content path must be limited to strictly one contents"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -36,185 +36,125 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
liberr "github.com/nabbar/golib/errors"
|
liberr "github.com/nabbar/golib/errors"
|
||||||
libiot "github.com/nabbar/golib/ioutils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Create(archive libiot.FileProgress, content ...string) (bool, liberr.Error) {
|
func Create(archive io.WriteSeeker, content ...string) (bool, liberr.Error) {
|
||||||
|
|
||||||
var (
|
if _, err := archive.Seek(0, io.SeekStart); err != nil {
|
||||||
t *tar.Writer
|
|
||||||
n int64
|
|
||||||
|
|
||||||
err error
|
|
||||||
lEr = ErrorTarCreateAddFile.Error(nil)
|
|
||||||
)
|
|
||||||
|
|
||||||
if _, err = archive.Seek(0, io.SeekStart); err != nil {
|
|
||||||
return false, ErrorFileSeek.ErrorParent(err)
|
return false, ErrorFileSeek.ErrorParent(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
t = tar.NewWriter(archive)
|
if ok, err := createTar(archive, content...); err != nil || !ok {
|
||||||
|
return ok, err
|
||||||
for i := 0; i < len(content); i++ {
|
|
||||||
if content[i] == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
err = filepath.Walk(content[i], func(file string, inf os.FileInfo, err error) error {
|
|
||||||
var (
|
|
||||||
e error
|
|
||||||
h *tar.Header
|
|
||||||
f *os.File
|
|
||||||
)
|
|
||||||
|
|
||||||
// generate tar header
|
|
||||||
h, e = tar.FileInfoHeader(inf, file)
|
|
||||||
if e != nil {
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// must provide real name
|
|
||||||
// (see https://golang.org/src/archive/tar/common.go?#L626)
|
|
||||||
h.Name = filepath.ToSlash(file)
|
|
||||||
|
|
||||||
// write header
|
|
||||||
if e = t.WriteHeader(h); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// if not a dir, write file content
|
|
||||||
if !inf.IsDir() {
|
|
||||||
f, e = os.Open(file)
|
|
||||||
|
|
||||||
if e != nil {
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, e = io.Copy(t, f); e != nil {
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
n++
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
lEr.AddParent(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if n < 1 {
|
if _, err := archive.Seek(0, io.SeekStart); err != nil {
|
||||||
if lEr.HasParent() {
|
|
||||||
return false, lEr
|
|
||||||
}
|
|
||||||
|
|
||||||
return false, ErrorTarCreate.ErrorParent(fmt.Errorf("no file to add in archive"))
|
|
||||||
} else if !lEr.HasParent() {
|
|
||||||
lEr = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = t.Close(); err != nil {
|
|
||||||
return false, ErrorTarCreate.ErrorParent(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err = archive.Seek(0, io.SeekStart); err != nil {
|
|
||||||
return false, ErrorFileSeek.ErrorParent(err)
|
return false, ErrorFileSeek.ErrorParent(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, lEr
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateGzip(archive libiot.FileProgress, content ...string) (bool, liberr.Error) {
|
func CreateGzip(archive io.WriteSeeker, content ...string) (bool, liberr.Error) {
|
||||||
|
|
||||||
var (
|
if _, err := archive.Seek(0, io.SeekStart); err != nil {
|
||||||
z *gzip.Writer
|
|
||||||
t *tar.Writer
|
|
||||||
n int64
|
|
||||||
|
|
||||||
err error
|
|
||||||
lEr = ErrorTarCreateAddFile.Error(nil)
|
|
||||||
)
|
|
||||||
|
|
||||||
if _, err = archive.Seek(0, io.SeekStart); err != nil {
|
|
||||||
return false, ErrorFileSeek.ErrorParent(err)
|
return false, ErrorFileSeek.ErrorParent(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
z = gzip.NewWriter(archive)
|
z := gzip.NewWriter(archive)
|
||||||
t = tar.NewWriter(z)
|
|
||||||
|
|
||||||
for i := 0; i < len(content); i++ {
|
if ok, err := createTar(z, content...); err != nil || !ok {
|
||||||
if content[i] == "" {
|
return ok, err
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
err = filepath.Walk(content[i], func(file string, inf os.FileInfo, err error) error {
|
|
||||||
var (
|
|
||||||
e error
|
|
||||||
h *tar.Header
|
|
||||||
f *os.File
|
|
||||||
)
|
|
||||||
|
|
||||||
// generate tar header
|
|
||||||
h, e = tar.FileInfoHeader(inf, file)
|
|
||||||
if e != nil {
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// must provide real name
|
|
||||||
// (see https://golang.org/src/archive/tar/common.go?#L626)
|
|
||||||
h.Name = filepath.ToSlash(file)
|
|
||||||
|
|
||||||
// write header
|
|
||||||
if e = t.WriteHeader(h); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// if not a dir, write file content
|
|
||||||
if !inf.IsDir() {
|
|
||||||
f, e = os.Open(file)
|
|
||||||
|
|
||||||
if e != nil {
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, e = io.Copy(t, f); e != nil {
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
n++
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
lEr.AddParent(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if n < 1 {
|
if err := z.Close(); err != nil {
|
||||||
if lEr.HasParent() {
|
|
||||||
return false, lEr
|
|
||||||
}
|
|
||||||
|
|
||||||
return false, ErrorTarCreate.ErrorParent(fmt.Errorf("no file to add in archive"))
|
|
||||||
} else if !lEr.HasParent() {
|
|
||||||
lEr = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = t.Close(); err != nil {
|
|
||||||
return false, ErrorTarCreate.ErrorParent(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = z.Close(); err != nil {
|
|
||||||
return false, ErrorGzipCreate.ErrorParent(err)
|
return false, ErrorGzipCreate.ErrorParent(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = archive.Seek(0, io.SeekStart); err != nil {
|
if _, err := archive.Seek(0, io.SeekStart); err != nil {
|
||||||
return false, ErrorFileSeek.ErrorParent(err)
|
return false, ErrorFileSeek.ErrorParent(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createTar(w io.Writer, content ...string) (bool, liberr.Error) {
|
||||||
|
var (
|
||||||
|
t *tar.Writer
|
||||||
|
n int64
|
||||||
|
|
||||||
|
err error
|
||||||
|
lEr = ErrorTarCreateAddFile.Error(nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
t = tar.NewWriter(w)
|
||||||
|
|
||||||
|
for i := 0; i < len(content); i++ {
|
||||||
|
if content[i] == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
err = filepath.Walk(content[i], func(file string, inf os.FileInfo, err error) error {
|
||||||
|
var (
|
||||||
|
e error
|
||||||
|
h *tar.Header
|
||||||
|
f *os.File
|
||||||
|
)
|
||||||
|
|
||||||
|
// generate tar header
|
||||||
|
h, e = tar.FileInfoHeader(inf, file)
|
||||||
|
if e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// must provide real name
|
||||||
|
// (see https://golang.org/src/archive/tar/common.go?#L626)
|
||||||
|
h.Name = filepath.ToSlash(file)
|
||||||
|
|
||||||
|
// write header
|
||||||
|
if e = t.WriteHeader(h); e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// if not a dir, write file content
|
||||||
|
if !inf.IsDir() {
|
||||||
|
//nolint #gosec
|
||||||
|
/* #nosec */
|
||||||
|
f, e = os.Open(file)
|
||||||
|
|
||||||
|
if e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, e = io.Copy(t, f); e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
n++
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
lEr.AddParent(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if n < 1 {
|
||||||
|
if lEr.HasParent() {
|
||||||
|
return false, lEr
|
||||||
|
}
|
||||||
|
|
||||||
|
//nolint #goerr113
|
||||||
|
return false, ErrorTarCreate.ErrorParent(fmt.Errorf("no file to add in archive"))
|
||||||
|
} else if !lEr.HasParent() {
|
||||||
|
lEr = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = t.Close(); err != nil {
|
||||||
|
return false, ErrorTarCreate.ErrorParent(err)
|
||||||
|
}
|
||||||
|
|
||||||
return true, lEr
|
return true, lEr
|
||||||
}
|
}
|
||||||
|
@@ -107,23 +107,14 @@ func (a *artifactoryModel) request(uri string, bodyResponse interface{}) liberr.
|
|||||||
u *url.URL
|
u *url.URL
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//ctx, cnl = context.WithTimeout(a.ctx, libhtc.TIMEOUT_5_SEC)
|
||||||
|
ctx, cnl = context.WithCancel(a.ctx)
|
||||||
defer func() {
|
defer func() {
|
||||||
if cnl != nil {
|
if cnl != nil {
|
||||||
cnl()
|
cnl()
|
||||||
}
|
}
|
||||||
|
|
||||||
if rsp != nil && rsp.Body != nil {
|
|
||||||
_ = rsp.Body.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
if req != nil && req.Body != nil {
|
|
||||||
_ = req.Body.Close()
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
//ctx, cnl = context.WithTimeout(a.ctx, libhtc.TIMEOUT_5_SEC)
|
|
||||||
ctx, cnl = context.WithCancel(a.ctx)
|
|
||||||
|
|
||||||
u = &url.URL{
|
u = &url.URL{
|
||||||
Scheme: a.endpoint.Scheme,
|
Scheme: a.endpoint.Scheme,
|
||||||
Opaque: a.endpoint.Opaque,
|
Opaque: a.endpoint.Opaque,
|
||||||
@@ -149,15 +140,29 @@ func (a *artifactoryModel) request(uri string, bodyResponse interface{}) liberr.
|
|||||||
return ErrorRequestInit.ErrorParent(e)
|
return ErrorRequestInit.ErrorParent(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if req != nil && req.Body != nil {
|
||||||
|
_ = req.Body.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
if rsp, e = a.Do(req); e != nil {
|
if rsp, e = a.Do(req); e != nil {
|
||||||
return ErrorRequestDo.ErrorParent(e)
|
return ErrorRequestDo.ErrorParent(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
if rsp.StatusCode >= 400 {
|
defer func() {
|
||||||
|
if rsp != nil && rsp.Body != nil {
|
||||||
|
_ = rsp.Body.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if rsp.StatusCode >= http.StatusBadRequest {
|
||||||
|
//nolint #goerr113
|
||||||
return ErrorRequestResponse.ErrorParent(fmt.Errorf("status: %v", rsp.Status))
|
return ErrorRequestResponse.ErrorParent(fmt.Errorf("status: %v", rsp.Status))
|
||||||
}
|
}
|
||||||
|
|
||||||
if rsp.Body == nil {
|
if rsp.Body == nil {
|
||||||
|
//nolint #goerr113
|
||||||
return ErrorRequestResponseBodyEmpty.ErrorParent(fmt.Errorf("status: %v", rsp.Status))
|
return ErrorRequestResponseBodyEmpty.ErrorParent(fmt.Errorf("status: %v", rsp.Status))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,10 +186,12 @@ func (a *artifactoryModel) getStorageList() (sto []ResponseStorage, err liberr.E
|
|||||||
)
|
)
|
||||||
|
|
||||||
if a.regex == "" {
|
if a.regex == "" {
|
||||||
|
//nolint #goerr113
|
||||||
return nil, ErrorParamsEmpty.ErrorParent(fmt.Errorf("regex is empty: %s", a.regex))
|
return nil, ErrorParamsEmpty.ErrorParent(fmt.Errorf("regex is empty: %s", a.regex))
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.group < 1 {
|
if a.group < 1 {
|
||||||
|
//nolint #goerr113
|
||||||
return nil, ErrorParamsEmpty.ErrorParent(fmt.Errorf("group extracted from regex is empty: %s - %v", a.regex, a.group))
|
return nil, ErrorParamsEmpty.ErrorParent(fmt.Errorf("group extracted from regex is empty: %s - %v", a.regex, a.group))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,9 +349,11 @@ func (a *artifactoryModel) Download(dst libiot.FileProgress, containName string,
|
|||||||
return ErrorRequestInit.ErrorParent(e)
|
return ErrorRequestInit.ErrorParent(e)
|
||||||
} else if rsp, e = a.Do(req); e != nil {
|
} else if rsp, e = a.Do(req); e != nil {
|
||||||
return ErrorRequestDo.ErrorParent(e)
|
return ErrorRequestDo.ErrorParent(e)
|
||||||
} else if rsp.StatusCode >= 400 {
|
} else if rsp.StatusCode >= http.StatusBadRequest {
|
||||||
|
//nolint #goerr113
|
||||||
return ErrorRequestResponse.ErrorParent(fmt.Errorf("status: %v", rsp.Status))
|
return ErrorRequestResponse.ErrorParent(fmt.Errorf("status: %v", rsp.Status))
|
||||||
} else if rsp.Body == nil {
|
} else if rsp.Body == nil {
|
||||||
|
//nolint #goerr113
|
||||||
return ErrorRequestResponseBodyEmpty.ErrorParent(fmt.Errorf("status: %v", rsp.Status))
|
return ErrorRequestResponseBodyEmpty.ErrorParent(fmt.Errorf("status: %v", rsp.Status))
|
||||||
} else if _, e := dst.ReadFrom(rsp.Body); e != nil {
|
} else if _, e := dst.ReadFrom(rsp.Body); e != nil {
|
||||||
return ErrorArtifactoryDownload.ErrorParent(e)
|
return ErrorArtifactoryDownload.ErrorParent(e)
|
||||||
|
@@ -71,8 +71,6 @@ func TestGolibAwsHelper(t *testing.T) {
|
|||||||
RunSpecs(t, "Aws Helper Suite")
|
RunSpecs(t, "Aws Helper Suite")
|
||||||
}
|
}
|
||||||
|
|
||||||
const testRegion = "us-east-1"
|
|
||||||
|
|
||||||
var _ = BeforeSuite(func() {
|
var _ = BeforeSuite(func() {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
|
@@ -226,7 +226,7 @@ func (c *awsModel) ResolveEndpoint(service, region string) (sdkaws.Endpoint, err
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.DebugLevel.Logf("Called ResolveEndpoint for service / region '%s' with nil endpoint", service, region)
|
logger.DebugLevel.Logf("Called ResolveEndpoint for service '%s' / region '%s' with nil endpoint", service, region)
|
||||||
return sdkaws.Endpoint{}, ErrorEndpointInvalid.Error(nil)
|
return sdkaws.Endpoint{}, ErrorEndpointInvalid.Error(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -26,10 +26,13 @@
|
|||||||
package object
|
package object
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
//nolint #nosec
|
||||||
/* #nosec */
|
/* #nosec */
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
//nolint #gci
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
sdkaws "github.com/aws/aws-sdk-go-v2/aws"
|
sdkaws "github.com/aws/aws-sdk-go-v2/aws"
|
||||||
@@ -101,8 +104,8 @@ func (cli *client) MultipartPutCustom(partSize libhlp.PartSize, object string, b
|
|||||||
|
|
||||||
/* #nosec */
|
/* #nosec */
|
||||||
h := md5.New()
|
h := md5.New()
|
||||||
if _, err := tmp.WriteTo(h); err != nil {
|
if _, e := tmp.WriteTo(h); e != nil {
|
||||||
return cli.multipartCancel(err, upl.UploadId, object)
|
return cli.multipartCancel(e, upl.UploadId, object)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = tmp.Seek(0, io.SeekStart)
|
_, err = tmp.Seek(0, io.SeekStart)
|
||||||
|
@@ -42,6 +42,7 @@ const maxItemList int32 = 1000
|
|||||||
|
|
||||||
func (cli *client) VersionList(arn string, maxItem int32) (map[string]string, liberr.Error) {
|
func (cli *client) VersionList(arn string, maxItem int32) (map[string]string, liberr.Error) {
|
||||||
if arn == "" {
|
if arn == "" {
|
||||||
|
//nolint #goerr113
|
||||||
return nil, libhlp.ErrorParamsEmpty.ErrorParent(fmt.Errorf("arn is empty"))
|
return nil, libhlp.ErrorParamsEmpty.ErrorParent(fmt.Errorf("arn is empty"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +52,7 @@ func (cli *client) VersionList(arn string, maxItem int32) (map[string]string, li
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
marker = ""
|
marker = ""
|
||||||
res = make(map[string]string, 0)
|
res = make(map[string]string)
|
||||||
)
|
)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
@@ -39,12 +39,6 @@ type Certif struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
InheritDefault bool `mapstructure:"inheritDefault" json:"inheritDefault" yaml:"inheritDefault" toml:"inheritDefault"`
|
|
||||||
VersionMin string `mapstructure:"versionMin" json:"versionMin" yaml:"versionMin" toml:"versionMin"`
|
|
||||||
VersionMax string `mapstructure:"versionMax" json:"versionMax" yaml:"versionMax" toml:"versionMax"`
|
|
||||||
DynmaicSizingDisable bool `mapstructure:"dynamicSizingDisable" json:"dynamicSizingDisable" yaml:"dynamicSizingDisable" toml:"dynamicSizingDisable"`
|
|
||||||
SessionTicketDisable bool `mapstructure:"sessionTicketDisable" json:"sessionTicketDisable" yaml:"sessionTicketDisable" toml:"sessionTicketDisable"`
|
|
||||||
AuthClient string `mapstructure:"authClient" json:"authClient" yaml:"authClient" toml:"authClient"`
|
|
||||||
CurveList []string `mapstructure:"curveList" json:"curveList" yaml:"curveList" toml:"curveList"`
|
CurveList []string `mapstructure:"curveList" json:"curveList" yaml:"curveList" toml:"curveList"`
|
||||||
CipherList []string `mapstructure:"cipherList" json:"cipherList" yaml:"cipherList" toml:"cipherList"`
|
CipherList []string `mapstructure:"cipherList" json:"cipherList" yaml:"cipherList" toml:"cipherList"`
|
||||||
RootCAString []string `mapstructure:"rootCA" json:"rootCA" yaml:"rootCA" toml:"rootCA"`
|
RootCAString []string `mapstructure:"rootCA" json:"rootCA" yaml:"rootCA" toml:"rootCA"`
|
||||||
@@ -53,6 +47,12 @@ type Config struct {
|
|||||||
ClientCAFiles []string `mapstructure:"clientCAFiles" json:"clientCAFiles" yaml:"clientCAFiles" toml:"clientCAFiles"`
|
ClientCAFiles []string `mapstructure:"clientCAFiles" json:"clientCAFiles" yaml:"clientCAFiles" toml:"clientCAFiles"`
|
||||||
CertPairString []Certif `mapstructure:"certPair" json:"certPair" yaml:"certPair" toml:"certPair"`
|
CertPairString []Certif `mapstructure:"certPair" json:"certPair" yaml:"certPair" toml:"certPair"`
|
||||||
CertPairFile []Certif `mapstructure:"certPairFiles" json:"certPairFiles" yaml:"certPairFiles" toml:"certPairFiles"`
|
CertPairFile []Certif `mapstructure:"certPairFiles" json:"certPairFiles" yaml:"certPairFiles" toml:"certPairFiles"`
|
||||||
|
VersionMin string `mapstructure:"versionMin" json:"versionMin" yaml:"versionMin" toml:"versionMin"`
|
||||||
|
VersionMax string `mapstructure:"versionMax" json:"versionMax" yaml:"versionMax" toml:"versionMax"`
|
||||||
|
AuthClient string `mapstructure:"authClient" json:"authClient" yaml:"authClient" toml:"authClient"`
|
||||||
|
InheritDefault bool `mapstructure:"inheritDefault" json:"inheritDefault" yaml:"inheritDefault" toml:"inheritDefault"`
|
||||||
|
DynamicSizingDisable bool `mapstructure:"dynamicSizingDisable" json:"dynamicSizingDisable" yaml:"dynamicSizingDisable" toml:"dynamicSizingDisable"`
|
||||||
|
SessionTicketDisable bool `mapstructure:"sessionTicketDisable" json:"sessionTicketDisable" yaml:"sessionTicketDisable" toml:"sessionTicketDisable"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) Validate() liberr.Error {
|
func (c *Config) Validate() liberr.Error {
|
||||||
@@ -64,6 +64,7 @@ func (c *Config) Validate() liberr.Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, err := range err.(valid.ValidationErrors) {
|
for _, err := range err.(valid.ValidationErrors) {
|
||||||
|
//nolint #goerr113
|
||||||
e.AddParent(fmt.Errorf("config field '%s' is not validated by constraint '%s'", err.StructNamespace(), err.ActualTag()))
|
e.AddParent(fmt.Errorf("config field '%s' is not validated by constraint '%s'", err.StructNamespace(), err.ActualTag()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,6 +84,7 @@ func (c *Config) New() (TLSConfig, liberr.Error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint #gocognit
|
||||||
func (c *Config) NewFrom(cfg TLSConfig) (TLSConfig, liberr.Error) {
|
func (c *Config) NewFrom(cfg TLSConfig) (TLSConfig, liberr.Error) {
|
||||||
var t *config
|
var t *config
|
||||||
|
|
||||||
@@ -103,7 +105,7 @@ func (c *Config) NewFrom(cfg TLSConfig) (TLSConfig, liberr.Error) {
|
|||||||
t.tlsMaxVersion = StringToTlsVersion(c.VersionMax)
|
t.tlsMaxVersion = StringToTlsVersion(c.VersionMax)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.DynmaicSizingDisable {
|
if c.DynamicSizingDisable {
|
||||||
t.dynSizingDisabled = true
|
t.dynSizingDisabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -80,47 +80,47 @@ func New() TLSConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config
|
// Deprecated: use local config and no more globals default config.
|
||||||
func AddRootCAContents(rootContent string) bool {
|
func AddRootCAContents(rootContent string) bool {
|
||||||
return Default.AddRootCAString(rootContent)
|
return Default.AddRootCAString(rootContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config
|
// Deprecated: use local config and no more globals default config.
|
||||||
func AddRootCAFile(rootFile string) liberr.Error {
|
func AddRootCAFile(rootFile string) liberr.Error {
|
||||||
return Default.AddRootCAFile(rootFile)
|
return Default.AddRootCAFile(rootFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config
|
// Deprecated: use local config and no more globals default config.
|
||||||
func AddCACertificateContents(caContent string) bool {
|
func AddCACertificateContents(caContent string) bool {
|
||||||
return Default.AddClientCAString(caContent)
|
return Default.AddClientCAString(caContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config
|
// Deprecated: use local config and no more globals default config.
|
||||||
func AddCACertificateFile(caFile string) liberr.Error {
|
func AddCACertificateFile(caFile string) liberr.Error {
|
||||||
return Default.AddClientCAFile(caFile)
|
return Default.AddClientCAFile(caFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config
|
// Deprecated: use local config and no more globals default config.
|
||||||
func AddCertificatePairString(key, crt string) liberr.Error {
|
func AddCertificatePairString(key, crt string) liberr.Error {
|
||||||
return Default.AddCertificatePairString(key, crt)
|
return Default.AddCertificatePairString(key, crt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config
|
// Deprecated: use local config and no more globals default config.
|
||||||
func AddCertificatePairFile(keyFile, crtFile string) liberr.Error {
|
func AddCertificatePairFile(keyFile, crtFile string) liberr.Error {
|
||||||
return Default.AddCertificatePairFile(keyFile, crtFile)
|
return Default.AddCertificatePairFile(keyFile, crtFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config
|
// Deprecated: use local config and no more globals default config.
|
||||||
func CheckCertificates() bool {
|
func CheckCertificates() bool {
|
||||||
return Default.LenCertificatePair() > 0
|
return Default.LenCertificatePair() > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config
|
// Deprecated: use local config and no more globals default config.
|
||||||
func GetCertificates() []tls.Certificate {
|
func GetCertificates() []tls.Certificate {
|
||||||
return Default.GetCertificatePair()
|
return Default.GetCertificatePair()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config
|
// Deprecated: use local config and no more globals default config.
|
||||||
func AppendCertificates(cert []tls.Certificate) []tls.Certificate {
|
func AppendCertificates(cert []tls.Certificate) []tls.Certificate {
|
||||||
if !CheckCertificates() {
|
if !CheckCertificates() {
|
||||||
return cert
|
return cert
|
||||||
@@ -129,67 +129,67 @@ func AppendCertificates(cert []tls.Certificate) []tls.Certificate {
|
|||||||
return append(cert, GetCertificates()...)
|
return append(cert, GetCertificates()...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config
|
// Deprecated: use local config and no more globals default config.
|
||||||
func GetRootCA() *x509.CertPool {
|
func GetRootCA() *x509.CertPool {
|
||||||
return Default.GetRootCA()
|
return Default.GetRootCA()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config
|
// Deprecated: use local config and no more globals default config.
|
||||||
func GetClientCA() *x509.CertPool {
|
func GetClientCA() *x509.CertPool {
|
||||||
return Default.GetClientCA()
|
return Default.GetClientCA()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config
|
// Deprecated: use local config and no more globals default config.
|
||||||
func SetVersionMin(vers uint16) {
|
func SetVersionMin(vers uint16) {
|
||||||
Default.SetVersionMin(vers)
|
Default.SetVersionMin(vers)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config
|
// Deprecated: use local config and no more globals default config.
|
||||||
func SetVersionMax(vers uint16) {
|
func SetVersionMax(vers uint16) {
|
||||||
Default.SetVersionMax(vers)
|
Default.SetVersionMax(vers)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config
|
// Deprecated: use local config and no more globals default config.
|
||||||
func SetClientAuth(auth string) {
|
func SetClientAuth(auth string) {
|
||||||
Default.SetClientAuth(StringToClientAuth(auth))
|
Default.SetClientAuth(StringToClientAuth(auth))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config
|
// Deprecated: use local config and no more globals default config.
|
||||||
func SetCipherList(cipher []uint16) {
|
func SetCipherList(cipher []uint16) {
|
||||||
Default.SetCipherList(cipher)
|
Default.SetCipherList(cipher)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config
|
// Deprecated: use local config and no more globals default config.
|
||||||
func SetCurve(curves []tls.CurveID) {
|
func SetCurve(curves []tls.CurveID) {
|
||||||
Default.SetCurveList(curves)
|
Default.SetCurveList(curves)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config
|
// Deprecated: use local config and no more globals default config.
|
||||||
func SetDynamicSizing(enable bool) {
|
func SetDynamicSizing(enable bool) {
|
||||||
Default.SetDynamicSizingDisabled(!enable)
|
Default.SetDynamicSizingDisabled(!enable)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config
|
// Deprecated: use local config and no more globals default config.
|
||||||
func SetSessionTicket(enable bool) {
|
func SetSessionTicket(enable bool) {
|
||||||
Default.SetSessionTicketDisabled(!enable)
|
Default.SetSessionTicketDisabled(!enable)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config
|
// Deprecated: use local config and no more globals default config.
|
||||||
func GetTLSConfig(serverName string) *tls.Config {
|
func GetTLSConfig(serverName string) *tls.Config {
|
||||||
return Default.TlsConfig(serverName)
|
return Default.TlsConfig(serverName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config
|
// Deprecated: use local config and no more globals default config.
|
||||||
func GetTlsConfigCertificates() *tls.Config {
|
func GetTlsConfigCertificates() *tls.Config {
|
||||||
return Default.TlsConfig("")
|
return Default.TlsConfig("")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config
|
// Deprecated: use local config and no more globals default config.
|
||||||
func AddCertificateContents(keyContents, certContents string) liberr.Error {
|
func AddCertificateContents(keyContents, certContents string) liberr.Error {
|
||||||
return Default.AddCertificatePairString(keyContents, certContents)
|
return Default.AddCertificatePairString(keyContents, certContents)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use local config and no more globals default config
|
// Deprecated: use local config and no more globals default config.
|
||||||
func AddCertificateFile(keyFile, certFile string) liberr.Error {
|
func AddCertificateFile(keyFile, certFile string) liberr.Error {
|
||||||
return Default.AddCertificatePairFile(keyFile, certFile)
|
return Default.AddCertificatePairFile(keyFile, certFile)
|
||||||
}
|
}
|
||||||
|
@@ -38,20 +38,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
caRoot *x509.CertPool
|
cert []tls.Certificate
|
||||||
cert []tls.Certificate
|
cipherList []uint16
|
||||||
|
curveList []tls.CurveID
|
||||||
tlsMinVersion uint16
|
caRoot *x509.CertPool
|
||||||
tlsMaxVersion uint16
|
clientAuth tls.ClientAuthType
|
||||||
|
clientCA *x509.CertPool
|
||||||
cipherList []uint16
|
tlsMinVersion uint16
|
||||||
curveList []tls.CurveID
|
tlsMaxVersion uint16
|
||||||
|
|
||||||
dynSizingDisabled bool
|
dynSizingDisabled bool
|
||||||
ticketSessionDisabled bool
|
ticketSessionDisabled bool
|
||||||
|
|
||||||
clientAuth tls.ClientAuthType
|
|
||||||
clientCA *x509.CertPool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *config) checkFile(pemFiles ...string) liberr.Error {
|
func (c *config) checkFile(pemFiles ...string) liberr.Error {
|
||||||
@@ -248,12 +244,7 @@ func (c *config) cloneCipherList() []uint16 {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
list := make([]uint16, 0)
|
return append(make([]uint16, 0), c.cipherList...)
|
||||||
for _, v := range c.cipherList {
|
|
||||||
list = append(list, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
return list
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *config) cloneCurveList() []tls.CurveID {
|
func (c *config) cloneCurveList() []tls.CurveID {
|
||||||
@@ -261,12 +252,7 @@ func (c *config) cloneCurveList() []tls.CurveID {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
list := make([]tls.CurveID, 0)
|
return append(make([]tls.CurveID, 0), c.curveList...)
|
||||||
for _, v := range c.curveList {
|
|
||||||
list = append(list, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
return list
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *config) cloneCertificates() []tls.Certificate {
|
func (c *config) cloneCertificates() []tls.Certificate {
|
||||||
@@ -274,12 +260,7 @@ func (c *config) cloneCertificates() []tls.Certificate {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
list := make([]tls.Certificate, 0)
|
return append(make([]tls.Certificate, 0), c.cert...)
|
||||||
for _, v := range c.cert {
|
|
||||||
list = append(list, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
return list
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *config) cloneRootCA() *x509.CertPool {
|
func (c *config) cloneRootCA() *x509.CertPool {
|
||||||
|
@@ -33,12 +33,12 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Deprecated: use StringToCipherKey
|
// Deprecated: use StringToCipherKey.
|
||||||
func GetCipherKey(cipher string) uint16 {
|
func GetCipherKey(cipher string) uint16 {
|
||||||
return StringToCipherKey(cipher)
|
return StringToCipherKey(cipher)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use StringToCurveID
|
// Deprecated: use StringToCurveID.
|
||||||
func GetCurveID(curveRef string) tls.CurveID {
|
func GetCurveID(curveRef string) tls.CurveID {
|
||||||
return StringToCurveID(curveRef)
|
return StringToCurveID(curveRef)
|
||||||
}
|
}
|
||||||
|
@@ -223,6 +223,7 @@ func (c ConfigCluster) GetDGBConfigCluster() dgbcfg.Config {
|
|||||||
d.Quiesce = true
|
d.Quiesce = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint #exhaustive
|
||||||
switch c.SnapshotCompressionType {
|
switch c.SnapshotCompressionType {
|
||||||
case dgbcfg.Snappy:
|
case dgbcfg.Snappy:
|
||||||
d.SnapshotCompressionType = dgbcfg.Snappy
|
d.SnapshotCompressionType = dgbcfg.Snappy
|
||||||
@@ -230,6 +231,7 @@ func (c ConfigCluster) GetDGBConfigCluster() dgbcfg.Config {
|
|||||||
d.SnapshotCompressionType = dgbcfg.NoCompression
|
d.SnapshotCompressionType = dgbcfg.NoCompression
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint #exhaustive
|
||||||
switch c.EntryCompressionType {
|
switch c.EntryCompressionType {
|
||||||
case dgbcfg.Snappy:
|
case dgbcfg.Snappy:
|
||||||
d.EntryCompressionType = dgbcfg.Snappy
|
d.EntryCompressionType = dgbcfg.Snappy
|
||||||
|
@@ -33,7 +33,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"golang.org/x/crypto/ssh/terminal"
|
"golang.org/x/term"
|
||||||
)
|
)
|
||||||
|
|
||||||
func printPrompt(text string) {
|
func printPrompt(text string) {
|
||||||
@@ -87,7 +87,7 @@ func PromptBool(text string) (bool, error) {
|
|||||||
func PromptPassword(text string) (string, error) {
|
func PromptPassword(text string) (string, error) {
|
||||||
printPrompt(text)
|
printPrompt(text)
|
||||||
//nolint #unconvert
|
//nolint #unconvert
|
||||||
res, err := terminal.ReadPassword(int(syscall.Stdin))
|
res, err := term.ReadPassword(int(syscall.Stdin))
|
||||||
fmt.Printf("\n")
|
fmt.Printf("\n")
|
||||||
|
|
||||||
return string(res), err
|
return string(res), err
|
||||||
|
@@ -36,39 +36,43 @@ type Config interface {
|
|||||||
|
|
||||||
Store(key string, cfg interface{})
|
Store(key string, cfg interface{})
|
||||||
Load(key string) interface{}
|
Load(key string) interface{}
|
||||||
|
|
||||||
ObjectStore(key string, obj interface{})
|
|
||||||
ObjectLoad(key string) interface{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConfig(ctx context.Context) Config {
|
func NewConfig(ctx context.Context) Config {
|
||||||
return &configContext{
|
return &configContext{
|
||||||
Context: ctx,
|
Context: ctx,
|
||||||
cfg: &atomic.Value{},
|
cfg: new(atomic.Value),
|
||||||
obj: &atomic.Value{},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type configContext struct {
|
type configContext struct {
|
||||||
context.Context
|
context.Context
|
||||||
cfg *atomic.Value
|
cfg *atomic.Value
|
||||||
obj *atomic.Value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *configContext) Store(key string, cfg interface{}) {
|
func (c configContext) getMap() map[string]*atomic.Value {
|
||||||
var (
|
var (
|
||||||
v interface{}
|
v interface{}
|
||||||
s map[string]*atomic.Value
|
s map[string]*atomic.Value
|
||||||
ok bool
|
ok bool
|
||||||
)
|
)
|
||||||
|
|
||||||
if v = c.cfg.Load(); v == nil {
|
if c.cfg == nil {
|
||||||
s = make(map[string]*atomic.Value, 0)
|
c.cfg = new(atomic.Value)
|
||||||
|
} else if v = c.cfg.Load(); v == nil {
|
||||||
|
s = make(map[string]*atomic.Value)
|
||||||
|
|
||||||
} else if s, ok = v.(map[string]*atomic.Value); !ok {
|
} else if s, ok = v.(map[string]*atomic.Value); !ok {
|
||||||
s = make(map[string]*atomic.Value, 0)
|
s = make(map[string]*atomic.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok = s[key]; !ok {
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *configContext) Store(key string, cfg interface{}) {
|
||||||
|
s := c.getMap()
|
||||||
|
|
||||||
|
if _, ok := s[key]; !ok {
|
||||||
s[key] = &atomic.Value{}
|
s[key] = &atomic.Value{}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,17 +81,9 @@ func (c *configContext) Store(key string, cfg interface{}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *configContext) Load(key string) interface{} {
|
func (c *configContext) Load(key string) interface{} {
|
||||||
var (
|
s := c.getMap()
|
||||||
v interface{}
|
|
||||||
s map[string]*atomic.Value
|
|
||||||
ok bool
|
|
||||||
)
|
|
||||||
|
|
||||||
if v = c.cfg.Load(); v == nil {
|
if _, ok := s[key]; !ok {
|
||||||
return nil
|
|
||||||
} else if s, ok = v.(map[string]*atomic.Value); !ok {
|
|
||||||
return nil
|
|
||||||
} else if _, ok = s[key]; !ok {
|
|
||||||
return nil
|
return nil
|
||||||
} else {
|
} else {
|
||||||
return s[key].Load()
|
return s[key].Load()
|
||||||
@@ -97,10 +93,6 @@ func (c *configContext) Load(key string) interface{} {
|
|||||||
func (c *configContext) Merge(cfg Config) bool {
|
func (c *configContext) Merge(cfg Config) bool {
|
||||||
var (
|
var (
|
||||||
x *configContext
|
x *configContext
|
||||||
vx interface{}
|
|
||||||
ix interface{}
|
|
||||||
sc map[string]*atomic.Value
|
|
||||||
sx map[string]*atomic.Value
|
|
||||||
ok bool
|
ok bool
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -108,68 +100,32 @@ func (c *configContext) Merge(cfg Config) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
sc = make(map[string]*atomic.Value, 0)
|
s := c.getMap()
|
||||||
|
|
||||||
if vx = x.cfg.Load(); vx == nil {
|
for k, v := range x.getMap() {
|
||||||
sx = make(map[string]*atomic.Value, 0)
|
|
||||||
} else if sx, ok = vx.(map[string]*atomic.Value); !ok {
|
|
||||||
sx = make(map[string]*atomic.Value, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, v := range sx {
|
|
||||||
if k == "" || v == nil {
|
if k == "" || v == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
ix = v.Load()
|
if i := v.Load(); i == nil {
|
||||||
if ix == nil {
|
|
||||||
continue
|
continue
|
||||||
|
} else {
|
||||||
|
s[k] = &atomic.Value{}
|
||||||
|
s[k].Store(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
sc[k] = &atomic.Value{}
|
|
||||||
sc[k].Store(ix)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.cfg.Store(sc)
|
c.cfg.Store(s)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Deprecated: use Store.
|
||||||
func (c *configContext) ObjectStore(key string, obj interface{}) {
|
func (c *configContext) ObjectStore(key string, obj interface{}) {
|
||||||
var (
|
c.Store(key, obj)
|
||||||
v interface{}
|
|
||||||
s map[string]*atomic.Value
|
|
||||||
ok bool
|
|
||||||
)
|
|
||||||
|
|
||||||
if v = c.obj.Load(); v == nil {
|
|
||||||
s = make(map[string]*atomic.Value, 0)
|
|
||||||
} else if s, ok = v.(map[string]*atomic.Value); !ok {
|
|
||||||
s = make(map[string]*atomic.Value, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok = s[key]; !ok {
|
|
||||||
s[key] = &atomic.Value{}
|
|
||||||
}
|
|
||||||
|
|
||||||
s[key].Store(obj)
|
|
||||||
c.obj.Store(s)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Deprecated: use Load.
|
||||||
func (c *configContext) ObjectLoad(key string) interface{} {
|
func (c *configContext) ObjectLoad(key string) interface{} {
|
||||||
var (
|
return c.Load(key)
|
||||||
v interface{}
|
|
||||||
s map[string]*atomic.Value
|
|
||||||
ok bool
|
|
||||||
)
|
|
||||||
|
|
||||||
if v = c.obj.Load(); v == nil {
|
|
||||||
return nil
|
|
||||||
} else if s, ok = v.(map[string]*atomic.Value); !ok {
|
|
||||||
return nil
|
|
||||||
} else if _, ok = s[key]; !ok {
|
|
||||||
return nil
|
|
||||||
} else {
|
|
||||||
return s[key].Load()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -27,6 +27,7 @@ package context
|
|||||||
import "context"
|
import "context"
|
||||||
|
|
||||||
func IsolateParent(parent context.Context) context.Context {
|
func IsolateParent(parent context.Context) context.Context {
|
||||||
|
//nolint #govet
|
||||||
x, _ := context.WithCancel(parent)
|
x, _ := context.WithCancel(parent)
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
@@ -30,9 +30,8 @@ import (
|
|||||||
"os/signal"
|
"os/signal"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/nabbar/golib/logger"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
liblog "github.com/nabbar/golib/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
type GinTonic interface {
|
type GinTonic interface {
|
||||||
@@ -102,11 +101,11 @@ func (c *ctxGinTonic) CancelOnSignal(s ...os.Signal) {
|
|||||||
|
|
||||||
select {
|
select {
|
||||||
case <-sc:
|
case <-sc:
|
||||||
logger.InfoLevel.Logf("Os Signal recieved, calling context cancel !")
|
liblog.InfoLevel.Logf("Os Signal received, calling context cancel !")
|
||||||
c.c()
|
c.c()
|
||||||
return
|
return
|
||||||
case <-c.Done():
|
case <-c.Done():
|
||||||
logger.InfoLevel.Logf("Context has been closed...")
|
liblog.InfoLevel.Logf("Context has been closed...")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
@@ -91,7 +91,7 @@ type Error interface {
|
|||||||
IsCodeError(code CodeError) bool
|
IsCodeError(code CodeError) bool
|
||||||
//HasCodeError check if current error or parent has the given error code
|
//HasCodeError check if current error or parent has the given error code
|
||||||
HasCodeError(code CodeError) bool
|
HasCodeError(code CodeError) bool
|
||||||
//GetCodeError return the CodeError value of the curent error
|
//GetCodeError return the CodeError value of the current error
|
||||||
GetCodeError() CodeError
|
GetCodeError() CodeError
|
||||||
//GetCodeErrorParent return a slice of CodeError value of all parent Error and the code of the current Error
|
//GetCodeErrorParent return a slice of CodeError value of all parent Error and the code of the current Error
|
||||||
GetCodeErrorParent() []CodeError
|
GetCodeErrorParent() []CodeError
|
||||||
|
@@ -60,7 +60,7 @@ func (r *DefaultReturn) SetError(code int, msg string, file string, line int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *DefaultReturn) AddParent(code int, msg string, file string, line int) {
|
func (r *DefaultReturn) AddParent(code int, msg string, file string, line int) {
|
||||||
return
|
// nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r DefaultReturn) JSON() []byte {
|
func (r DefaultReturn) JSON() []byte {
|
||||||
@@ -89,6 +89,7 @@ func (r DefaultReturn) GinTonicErrorAbort(ctx *gin.Context, httpCode int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.Errors = append(ctx.Errors, &gin.Error{
|
ctx.Errors = append(ctx.Errors, &gin.Error{
|
||||||
|
//nolint #goerr113
|
||||||
Err: goErr.New(r.Message),
|
Err: goErr.New(r.Message),
|
||||||
Type: gin.ErrorTypeAny,
|
Type: gin.ErrorTypeAny,
|
||||||
})
|
})
|
||||||
|
58
go.mod
58
go.mod
@@ -3,37 +3,93 @@ module github.com/nabbar/golib
|
|||||||
go 1.16
|
go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/DataDog/zstd v1.4.8 // indirect
|
||||||
|
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||||
|
github.com/Masterminds/semver v1.5.0 // indirect
|
||||||
|
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
|
||||||
|
github.com/PuerkitoBio/goquery v1.6.1 // indirect
|
||||||
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect
|
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect
|
||||||
|
github.com/VictoriaMetrics/metrics v1.17.2 // indirect
|
||||||
|
github.com/andybalholm/cascadia v1.2.0 // indirect
|
||||||
|
github.com/aokoli/goutils v1.1.1 // indirect
|
||||||
|
github.com/armon/go-metrics v0.3.6 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2 v1.3.2
|
github.com/aws/aws-sdk-go-v2 v1.3.2
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.1.5
|
github.com/aws/aws-sdk-go-v2/config v1.1.5
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.1.5
|
github.com/aws/aws-sdk-go-v2/credentials v1.1.5
|
||||||
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.6 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/iam v1.3.1
|
github.com/aws/aws-sdk-go-v2/service/iam v1.3.1
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.0.4 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.6 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.2.2 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.5.0
|
github.com/aws/aws-sdk-go-v2/service/s3 v1.5.0
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sso v1.1.5 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sts v1.2.2 // indirect
|
||||||
|
github.com/cockroachdb/errors v1.8.3 // indirect
|
||||||
|
github.com/cockroachdb/pebble v0.0.0-20210406003833-3d4c32f510a8 // indirect
|
||||||
|
github.com/cockroachdb/redact v1.0.9 // indirect
|
||||||
github.com/fatih/color v1.10.0
|
github.com/fatih/color v1.10.0
|
||||||
github.com/fxamacker/cbor/v2 v2.2.0
|
github.com/fxamacker/cbor/v2 v2.2.0
|
||||||
github.com/gin-gonic/gin v1.7.1
|
github.com/gin-gonic/gin v1.7.1
|
||||||
|
github.com/go-asn1-ber/asn1-ber v1.5.3 // indirect
|
||||||
github.com/go-ldap/ldap/v3 v3.3.0
|
github.com/go-ldap/ldap/v3 v3.3.0
|
||||||
github.com/go-ole/go-ole v1.2.5 // indirect
|
github.com/go-ole/go-ole v1.2.5 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.5.0
|
github.com/go-playground/validator/v10 v10.5.0
|
||||||
|
github.com/gobuffalo/envy v1.9.0 // indirect
|
||||||
|
github.com/gobuffalo/packd v1.0.0 // indirect
|
||||||
github.com/gobuffalo/packr v1.30.1
|
github.com/gobuffalo/packr v1.30.1
|
||||||
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
|
github.com/golang/snappy v0.0.3 // indirect
|
||||||
|
github.com/google/btree v1.0.1 // indirect
|
||||||
github.com/google/go-github/v33 v33.0.0
|
github.com/google/go-github/v33 v33.0.0
|
||||||
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
|
github.com/google/uuid v1.2.0 // indirect
|
||||||
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
|
github.com/hashicorp/go-immutable-radix v1.3.0 // indirect
|
||||||
|
github.com/hashicorp/go-msgpack v1.1.5 // indirect
|
||||||
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
github.com/hashicorp/go-retryablehttp v0.6.8
|
github.com/hashicorp/go-retryablehttp v0.6.8
|
||||||
|
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
|
||||||
github.com/hashicorp/go-uuid v1.0.2
|
github.com/hashicorp/go-uuid v1.0.2
|
||||||
github.com/hashicorp/go-version v1.3.0
|
github.com/hashicorp/go-version v1.3.0
|
||||||
|
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
||||||
|
github.com/hashicorp/memberlist v0.2.3 // indirect
|
||||||
|
github.com/huandu/xstrings v1.3.2 // indirect
|
||||||
|
github.com/imdario/mergo v0.3.12 // indirect
|
||||||
|
github.com/jaytaylor/html2text v0.0.0-20200412013138-3577fbdbcff7 // indirect
|
||||||
|
github.com/json-iterator/go v1.1.10 // indirect
|
||||||
|
github.com/klauspost/compress v1.11.13 // indirect
|
||||||
|
github.com/kr/pretty v0.2.1 // indirect
|
||||||
|
github.com/kr/text v0.2.0 // indirect
|
||||||
|
github.com/leodido/go-urn v1.2.1 // indirect
|
||||||
github.com/lni/dragonboat/v3 v3.3.2
|
github.com/lni/dragonboat/v3 v3.3.2
|
||||||
github.com/matcornic/hermes/v2 v2.1.0
|
github.com/matcornic/hermes/v2 v2.1.0
|
||||||
|
github.com/mattn/go-runewidth v0.0.12 // indirect
|
||||||
|
github.com/miekg/dns v1.1.41 // indirect
|
||||||
|
github.com/mitchellh/copystructure v1.1.2 // indirect
|
||||||
|
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||||
github.com/onsi/ginkgo v1.16.1
|
github.com/onsi/ginkgo v1.16.1
|
||||||
github.com/onsi/gomega v1.11.0
|
github.com/onsi/gomega v1.11.0
|
||||||
|
github.com/rivo/uniseg v0.2.0 // indirect
|
||||||
|
github.com/rogpeppe/go-internal v1.8.0 // indirect
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/shirou/gopsutil v3.21.3+incompatible
|
github.com/shirou/gopsutil v3.21.3+incompatible
|
||||||
github.com/sirupsen/logrus v1.8.1
|
github.com/sirupsen/logrus v1.8.1
|
||||||
github.com/spf13/jwalterweatherman v1.1.0
|
github.com/spf13/jwalterweatherman v1.1.0
|
||||||
|
github.com/ugorji/go v1.2.5 // indirect
|
||||||
|
github.com/vanng822/go-premailer v1.20.1 // indirect
|
||||||
github.com/vbauerster/mpb/v5 v5.4.0
|
github.com/vbauerster/mpb/v5 v5.4.0
|
||||||
github.com/xanzy/go-gitlab v0.48.0
|
github.com/xanzy/go-gitlab v0.48.0
|
||||||
github.com/xhit/go-simple-mail v2.2.2+incompatible
|
github.com/xhit/go-simple-mail v2.2.2+incompatible
|
||||||
github.com/xujiajun/nutsdb v0.6.0
|
github.com/xujiajun/nutsdb v0.6.0
|
||||||
github.com/xujiajun/utils v0.0.0-20190123093513-8bf096c4f53b
|
github.com/xujiajun/utils v0.0.0-20190123093513-8bf096c4f53b
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect
|
||||||
|
golang.org/x/exp v0.0.0-20210405174845-4513512abef3 // indirect
|
||||||
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1
|
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1
|
||||||
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602
|
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||||
|
golang.org/x/sys v0.0.0-20210412220455-f1c623a9e750 // indirect
|
||||||
|
golang.org/x/term v0.0.0-20210406210042-72f3dc4e9b72
|
||||||
|
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
|
||||||
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
)
|
)
|
||||||
|
@@ -64,7 +64,8 @@ func GetClientTimeout(serverName string, http2Tr bool, GlobalTimeout time.Durati
|
|||||||
Proxy: http.ProxyFromEnvironment,
|
Proxy: http.ProxyFromEnvironment,
|
||||||
DialContext: dl.DialContext,
|
DialContext: dl.DialContext,
|
||||||
DisableCompression: true,
|
DisableCompression: true,
|
||||||
TLSClientConfig: certificates.GetTLSConfig(serverName),
|
//nolint #staticcheck
|
||||||
|
TLSClientConfig: certificates.GetTLSConfig(serverName),
|
||||||
}
|
}
|
||||||
|
|
||||||
return getclient(tr, http2Tr, GlobalTimeout)
|
return getclient(tr, http2Tr, GlobalTimeout)
|
||||||
|
@@ -35,7 +35,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
|
|
||||||
libtls "github.com/nabbar/golib/certificates"
|
libtls "github.com/nabbar/golib/certificates"
|
||||||
liberr "github.com/nabbar/golib/errors"
|
liberr "github.com/nabbar/golib/errors"
|
||||||
)
|
)
|
||||||
@@ -129,10 +128,37 @@ func (p PoolServerConfig) MapRun(f MapRunPoolServerConfig) PoolServerConfig {
|
|||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint #maligned
|
||||||
type ServerConfig struct {
|
type ServerConfig struct {
|
||||||
getTLSDefault func() libtls.TLSConfig
|
|
||||||
|
// Name is the name of the current server
|
||||||
|
// the configuration allow multipke server, which each one must be identify by a name
|
||||||
|
// If not defined, will use the listen address
|
||||||
|
Name string `mapstructure:"name" json:"name" yaml:"name" toml:"name" validate:"required"`
|
||||||
|
|
||||||
|
// Listen is the local address (ip, hostname, unix socket, ...) with a port
|
||||||
|
// The server will bind with this address only and listen for the port defined
|
||||||
|
Listen string `mapstructure:"listen" json:"listen" yaml:"listen" toml:"listen" validate:"required,hostname_port"`
|
||||||
|
|
||||||
|
// Expose is the address use to call this server. This can be allow to use a single fqdn to multiple server"
|
||||||
|
Expose string `mapstructure:"expose" json:"expose" yaml:"expose" toml:"expose" validate:"required,url"`
|
||||||
|
|
||||||
|
// HandlerKeys is an options to associate current server with a specifc handler defined by the key
|
||||||
|
// This allow to defined multiple server in only one config for different handler to start multiple api
|
||||||
|
HandlerKeys string `mapstructure:"handler_keys" json:"handler_keys" yaml:"handler_keys" toml:"handler_keys"`
|
||||||
|
|
||||||
|
//private
|
||||||
|
getTLSDefault func() libtls.TLSConfig
|
||||||
|
|
||||||
|
//private
|
||||||
getParentContext func() context.Context
|
getParentContext func() context.Context
|
||||||
|
|
||||||
|
// TimeoutCacheInfo defined the validity time of cache for info (name, version, hash)
|
||||||
|
TimeoutCacheInfo time.Duration `mapstructure:"timeout_cache_info" json:"timeout_cache_info" yaml:"timeout_cache_info" toml:"timeout_cache_info"`
|
||||||
|
|
||||||
|
// TimeoutCacheHealth defined the validity time of cache for healthcheck of this server
|
||||||
|
TimeoutCacheHealth time.Duration `mapstructure:"timeout_cache_health" json:"timeout_cache_health" yaml:"timeout_cache_health" toml:"timeout_cache_health"`
|
||||||
|
|
||||||
// Enabled allow to disable a server without clean his configuration
|
// Enabled allow to disable a server without clean his configuration
|
||||||
Disabled bool `mapstructure:"disabled" json:"disabled" yaml:"disabled" toml:"disabled"`
|
Disabled bool `mapstructure:"disabled" json:"disabled" yaml:"disabled" toml:"disabled"`
|
||||||
|
|
||||||
@@ -140,11 +166,13 @@ type ServerConfig struct {
|
|||||||
// y defined if the component for status is mandatory or not
|
// y defined if the component for status is mandatory or not
|
||||||
Mandatory bool `mapstructure:"mandatory" json:"mandatory" yaml:"mandatory" toml:"mandatory"`
|
Mandatory bool `mapstructure:"mandatory" json:"mandatory" yaml:"mandatory" toml:"mandatory"`
|
||||||
|
|
||||||
// TimeoutCacheInfo defined the validity time of cache for info (name, version, hash)
|
// TLSMandatory is a flag to defined that TLS must be valid to start current server.
|
||||||
TimeoutCacheInfo time.Duration `mapstructure:"timeout_cache_info" json:"timeout_cache_info" yaml:"timeout_cache_info" toml:"timeout_cache_info"`
|
TLSMandatory bool `mapstructure:"tls_mandatory" json:"tls_mandatory" yaml:"tls_mandatory" toml:"tls_mandatory"`
|
||||||
|
|
||||||
// TimeoutCacheHealth defined the validity time of cache for healthcheck of this server
|
// TLS is the tls configuration for this server.
|
||||||
TimeoutCacheHealth time.Duration `mapstructure:"timeout_cache_health" json:"timeout_cache_health" yaml:"timeout_cache_health" toml:"timeout_cache_health"`
|
// To allow tls on this server, at least the TLS Config option InheritDefault must be at true and the default TLS config must be set.
|
||||||
|
// If you don't want any tls config, just omit or set an empty struct.
|
||||||
|
TLS libtls.Config `mapstructure:"tls" json:"tls" yaml:"tls" toml:"tls"`
|
||||||
|
|
||||||
/*** http options ***/
|
/*** http options ***/
|
||||||
|
|
||||||
@@ -220,30 +248,6 @@ type ServerConfig struct {
|
|||||||
// be larger than 2^32-1. If the value is zero or larger than the
|
// be larger than 2^32-1. If the value is zero or larger than the
|
||||||
// maximum, a default value will be used instead.
|
// maximum, a default value will be used instead.
|
||||||
MaxUploadBufferPerStream int32 `json:"max_upload_buffer_per_stream" json:"max_upload_buffer_per_stream" yaml:"max_upload_buffer_per_stream" toml:"max_upload_buffer_per_stream"`
|
MaxUploadBufferPerStream int32 `json:"max_upload_buffer_per_stream" json:"max_upload_buffer_per_stream" yaml:"max_upload_buffer_per_stream" toml:"max_upload_buffer_per_stream"`
|
||||||
|
|
||||||
// Name is the name of the current server
|
|
||||||
// the configuration allow multipke server, which each one must be identify by a name
|
|
||||||
// If not defined, will use the listen address
|
|
||||||
Name string `mapstructure:"name" json:"name" yaml:"name" toml:"name" validate:"required"`
|
|
||||||
|
|
||||||
// Listen is the local address (ip, hostname, unix socket, ...) with a port
|
|
||||||
// The server will bind with this address only and listen for the port defined
|
|
||||||
Listen string `mapstructure:"listen" json:"listen" yaml:"listen" toml:"listen" validate:"required,hostname_port"`
|
|
||||||
|
|
||||||
// Expose is the address use to call this server. This can be allow to use a single fqdn to multiple server"
|
|
||||||
Expose string `mapstructure:"expose" json:"expose" yaml:"expose" toml:"expose" validate:"required,url"`
|
|
||||||
|
|
||||||
// HandlerKeys is an options to associate current server with a specifc handler defined by the key
|
|
||||||
// This allow to defined multiple server in only one config for different handler to start multiple api
|
|
||||||
HandlerKeys string `mapstructure:"handler_keys" json:"handler_keys" yaml:"handler_keys" toml:"handler_keys"`
|
|
||||||
|
|
||||||
// TLSMandatory is a flag to defined that TLS must be valid to start current server.
|
|
||||||
TLSMandatory bool `mapstructure:"tls_mandatory" json:"tls_mandatory" yaml:"tls_mandatory" toml:"tls_mandatory"`
|
|
||||||
|
|
||||||
// TLS is the tls configuration for this server.
|
|
||||||
// To allow tls on this server, at least the TLS Config option InheritDefault must be at true and the default TLS config must be set.
|
|
||||||
// If you don't want any tls config, just omit or set an empty struct.
|
|
||||||
TLS libtls.Config `mapstructure:"tls" json:"tls" yaml:"tls" toml:"tls"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ServerConfig) Clone() ServerConfig {
|
func (c *ServerConfig) Clone() ServerConfig {
|
||||||
@@ -319,7 +323,7 @@ func (c ServerConfig) GetListen() *url.URL {
|
|||||||
|
|
||||||
if c.Listen != "" {
|
if c.Listen != "" {
|
||||||
if add, err = url.Parse(c.Listen); err != nil {
|
if add, err = url.Parse(c.Listen); err != nil {
|
||||||
if host, prt, err := net.SplitHostPort(c.Listen); err == nil {
|
if host, prt, e := net.SplitHostPort(c.Listen); e == nil {
|
||||||
add = &url.URL{
|
add = &url.URL{
|
||||||
Host: fmt.Sprintf("%s:%s", host, prt),
|
Host: fmt.Sprintf("%s:%s", host, prt),
|
||||||
}
|
}
|
||||||
|
@@ -36,13 +36,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/nabbar/golib/status"
|
|
||||||
|
|
||||||
"github.com/nabbar/golib/logger"
|
|
||||||
|
|
||||||
"github.com/nabbar/golib/semaphore"
|
|
||||||
|
|
||||||
liberr "github.com/nabbar/golib/errors"
|
liberr "github.com/nabbar/golib/errors"
|
||||||
|
liblog "github.com/nabbar/golib/logger"
|
||||||
|
libsem "github.com/nabbar/golib/semaphore"
|
||||||
|
libsts "github.com/nabbar/golib/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FieldType uint8
|
type FieldType uint8
|
||||||
@@ -82,7 +79,7 @@ type PoolServer interface {
|
|||||||
|
|
||||||
StatusInfo(bindAddress string) (name string, release string, hash string)
|
StatusInfo(bindAddress string) (name string, release string, hash string)
|
||||||
StatusHealth(bindAddress string) error
|
StatusHealth(bindAddress string) error
|
||||||
StatusRoute(prefix string, fctMessage status.FctMessage, sts status.RouteStatus)
|
StatusRoute(prefix string, fctMessage libsts.FctMessage, sts libsts.RouteStatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPool(srv ...Server) PoolServer {
|
func NewPool(srv ...Server) PoolServer {
|
||||||
@@ -353,7 +350,7 @@ func (p pool) ListenMultiHandler(handler map[string]http.Handler) liberr.Error {
|
|||||||
var e liberr.Error
|
var e liberr.Error
|
||||||
|
|
||||||
e = ErrorPoolListen.Error(nil)
|
e = ErrorPoolListen.Error(nil)
|
||||||
logger.InfoLevel.Log("Calling listen for All Servers")
|
liblog.InfoLevel.Log("Calling listen for All Servers")
|
||||||
|
|
||||||
p.MapRun(func(srv Server) {
|
p.MapRun(func(srv Server) {
|
||||||
if len(handler) < 1 {
|
if len(handler) < 1 {
|
||||||
@@ -371,7 +368,7 @@ func (p pool) ListenMultiHandler(handler map[string]http.Handler) liberr.Error {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
logger.InfoLevel.Log("End of Calling listen for All Servers")
|
liblog.InfoLevel.Log("End of Calling listen for All Servers")
|
||||||
|
|
||||||
if !e.HasParent() {
|
if !e.HasParent() {
|
||||||
e = nil
|
e = nil
|
||||||
@@ -380,64 +377,66 @@ func (p pool) ListenMultiHandler(handler map[string]http.Handler) liberr.Error {
|
|||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p pool) Restart() {
|
func (p pool) runMapCommand(f func(sem libsem.Sem, srv Server)) {
|
||||||
if p.Len() < 1 {
|
if p.Len() < 1 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
s semaphore.Sem
|
s libsem.Sem
|
||||||
x context.Context
|
x context.Context
|
||||||
c context.CancelFunc
|
c context.CancelFunc
|
||||||
)
|
)
|
||||||
|
|
||||||
|
x, c = context.WithTimeout(context.Background(), timeoutShutdown)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
c()
|
c()
|
||||||
s.DeferMain()
|
s.DeferMain()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
x, c = context.WithTimeout(context.Background(), timeoutRestart)
|
s = libsem.NewSemaphoreWithContext(x, 0)
|
||||||
s = semaphore.NewSemaphoreWithContext(x, 0)
|
|
||||||
|
|
||||||
p.MapRun(func(srv Server) {
|
p.MapRun(func(srv Server) {
|
||||||
_ = s.NewWorker()
|
_ = s.NewWorker()
|
||||||
go func() {
|
go func(sem libsem.Sem, srv Server) {
|
||||||
defer s.DeferWorker()
|
f(sem, srv)
|
||||||
srv.Restart()
|
}(s, srv)
|
||||||
}()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
_ = s.WaitAll()
|
_ = s.WaitAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p pool) Shutdown() {
|
func (p pool) runMapRestart(sem libsem.Sem, srv Server) {
|
||||||
if p.Len() < 1 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
s semaphore.Sem
|
|
||||||
x context.Context
|
|
||||||
c context.CancelFunc
|
|
||||||
)
|
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
c()
|
if sem != nil {
|
||||||
s.DeferMain()
|
sem.DeferWorker()
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
x, c = context.WithTimeout(context.Background(), timeoutShutdown)
|
if srv != nil {
|
||||||
s = semaphore.NewSemaphoreWithContext(x, 0)
|
srv.Restart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
p.MapRun(func(srv Server) {
|
func (p pool) runMapShutdown(sem libsem.Sem, srv Server) {
|
||||||
_ = s.NewWorker()
|
defer func() {
|
||||||
go func() {
|
if sem != nil {
|
||||||
defer s.DeferWorker()
|
sem.DeferWorker()
|
||||||
srv.Shutdown()
|
}
|
||||||
}()
|
}()
|
||||||
})
|
|
||||||
|
|
||||||
_ = s.WaitAll()
|
if srv != nil {
|
||||||
|
srv.Shutdown()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p pool) Restart() {
|
||||||
|
p.runMapCommand(p.runMapRestart)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p pool) Shutdown() {
|
||||||
|
p.runMapCommand(p.runMapShutdown)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p pool) StatusInfo(bindAddress string) (name string, release string, hash string) {
|
func (p pool) StatusInfo(bindAddress string) (name string, release string, hash string) {
|
||||||
@@ -453,10 +452,11 @@ func (p pool) StatusHealth(bindAddress string) error {
|
|||||||
return s.StatusHealth()
|
return s.StatusHealth()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint #goerr113
|
||||||
return fmt.Errorf("missing server '%s'", bindAddress)
|
return fmt.Errorf("missing server '%s'", bindAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p pool) StatusRoute(keyPrefix string, fctMessage status.FctMessage, sts status.RouteStatus) {
|
func (p pool) StatusRoute(keyPrefix string, fctMessage libsts.FctMessage, sts libsts.RouteStatus) {
|
||||||
p.MapRun(func(srv Server) {
|
p.MapRun(func(srv Server) {
|
||||||
bind := srv.GetBindable()
|
bind := srv.GetBindable()
|
||||||
sts.ComponentNew(fmt.Sprintf("%s-%s", keyPrefix, bind), srv.StatusComponent(fctMessage))
|
sts.ComponentNew(fmt.Sprintf("%s-%s", keyPrefix, bind), srv.StatusComponent(fctMessage))
|
||||||
|
@@ -45,6 +45,8 @@ import (
|
|||||||
"golang.org/x/net/http2"
|
"golang.org/x/net/http2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const _TimeoutWaitingPortFreeing = 500 * time.Microsecond
|
||||||
|
|
||||||
type srvRun struct {
|
type srvRun struct {
|
||||||
err *atomic.Value
|
err *atomic.Value
|
||||||
run *atomic.Value
|
run *atomic.Value
|
||||||
@@ -109,6 +111,7 @@ func (s *srvRun) setErr(e error) {
|
|||||||
if e != nil {
|
if e != nil {
|
||||||
s.err.Store(e)
|
s.err.Store(e)
|
||||||
} else {
|
} else {
|
||||||
|
//nolint #goerr113
|
||||||
s.err.Store(errors.New(""))
|
s.err.Store(errors.New(""))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,6 +144,7 @@ func (s *srvRun) Merge(srv Server) bool {
|
|||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint #gocognit
|
||||||
func (s *srvRun) Listen(cfg *ServerConfig, handler http.Handler) liberr.Error {
|
func (s *srvRun) Listen(cfg *ServerConfig, handler http.Handler) liberr.Error {
|
||||||
ssl, err := cfg.GetTLS()
|
ssl, err := cfg.GetTLS()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -263,6 +267,7 @@ func (s *srvRun) Listen(cfg *ServerConfig, handler http.Handler) liberr.Error {
|
|||||||
s.setRunning(true)
|
s.setRunning(true)
|
||||||
err = s.srv.ListenAndServeTLS("", "")
|
err = s.srv.ListenAndServeTLS("", "")
|
||||||
} else if tlsMandatory {
|
} else if tlsMandatory {
|
||||||
|
//nolint #goerr113
|
||||||
err = fmt.Errorf("missing valid server certificates")
|
err = fmt.Errorf("missing valid server certificates")
|
||||||
} else {
|
} else {
|
||||||
liblog.InfoLevel.Logf("Server '%s' is starting with bindable: %s", name, host)
|
liblog.InfoLevel.Logf("Server '%s' is starting with bindable: %s", name, host)
|
||||||
@@ -333,7 +338,7 @@ func (s *srvRun) PortInUse(listen string) liberr.Error {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
ctx, cnl = context.WithTimeout(context.TODO(), 2*time.Second)
|
ctx, cnl = context.WithTimeout(context.TODO(), _TimeoutWaitingPortFreeing)
|
||||||
con, err = dia.DialContext(ctx, "tcp", listen)
|
con, err = dia.DialContext(ctx, "tcp", listen)
|
||||||
|
|
||||||
if con != nil {
|
if con != nil {
|
||||||
|
@@ -34,24 +34,22 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/nabbar/golib/status"
|
|
||||||
|
|
||||||
liberr "github.com/nabbar/golib/errors"
|
liberr "github.com/nabbar/golib/errors"
|
||||||
|
libsts "github.com/nabbar/golib/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
timeoutShutdown = 10 * time.Second
|
timeoutShutdown = 10 * time.Second
|
||||||
timeoutRestart = 30 * time.Second
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type server struct {
|
type server struct {
|
||||||
run *atomic.Value
|
run *atomic.Value
|
||||||
cfg ServerConfig
|
cfg *atomic.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
type Server interface {
|
type Server interface {
|
||||||
GetConfig() *ServerConfig
|
GetConfig() *ServerConfig
|
||||||
SetConfig(cfg *ServerConfig)
|
SetConfig(cfg *ServerConfig) bool
|
||||||
|
|
||||||
GetName() string
|
GetName() string
|
||||||
GetBindable() string
|
GetBindable() string
|
||||||
@@ -69,16 +67,50 @@ type Server interface {
|
|||||||
|
|
||||||
StatusInfo() (name string, release string, hash string)
|
StatusInfo() (name string, release string, hash string)
|
||||||
StatusHealth() error
|
StatusHealth() error
|
||||||
StatusComponent(message status.FctMessage) status.Component
|
StatusComponent(message libsts.FctMessage) libsts.Component
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServer(cfg *ServerConfig) Server {
|
func NewServer(cfg *ServerConfig) Server {
|
||||||
|
c := new(atomic.Value)
|
||||||
|
c.Store(cfg.Clone())
|
||||||
|
|
||||||
return &server{
|
return &server{
|
||||||
cfg: cfg.Clone(),
|
cfg: c,
|
||||||
run: new(atomic.Value),
|
run: new(atomic.Value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *server) GetConfig() *ServerConfig {
|
||||||
|
if s.cfg == nil {
|
||||||
|
return nil
|
||||||
|
} else if i := s.cfg.Load(); i == nil {
|
||||||
|
return nil
|
||||||
|
} else if c, ok := i.(ServerConfig); !ok {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return &c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *server) SetConfig(cfg *ServerConfig) bool {
|
||||||
|
if cfg == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.cfg == nil {
|
||||||
|
s.cfg = new(atomic.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
c := cfg.Clone()
|
||||||
|
|
||||||
|
if c.Name == "" {
|
||||||
|
c.Name = c.GetListen().Host
|
||||||
|
}
|
||||||
|
|
||||||
|
s.cfg.Store(cfg.Clone())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (s *server) getRun() run {
|
func (s *server) getRun() run {
|
||||||
if s.run == nil {
|
if s.run == nil {
|
||||||
return newRun()
|
return newRun()
|
||||||
@@ -103,32 +135,20 @@ func (s *server) getErr() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) GetConfig() *ServerConfig {
|
|
||||||
return &s.cfg
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *server) SetConfig(cfg *ServerConfig) {
|
|
||||||
s.cfg = cfg.Clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s server) GetName() string {
|
func (s server) GetName() string {
|
||||||
if s.cfg.Name == "" {
|
return s.GetConfig().Name
|
||||||
s.cfg.Name = s.GetBindable()
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.cfg.Name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) GetBindable() string {
|
func (s *server) GetBindable() string {
|
||||||
return s.cfg.GetListen().Host
|
return s.GetConfig().GetListen().Host
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) GetExpose() string {
|
func (s *server) GetExpose() string {
|
||||||
return s.cfg.GetExpose().String()
|
return s.GetConfig().GetExpose().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) GetHandlerKey() string {
|
func (s *server) GetHandlerKey() string {
|
||||||
return s.cfg.GetHandlerKey()
|
return s.GetConfig().GetHandlerKey()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) IsRunning() bool {
|
func (s *server) IsRunning() bool {
|
||||||
@@ -136,12 +156,12 @@ func (s *server) IsRunning() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) IsTLS() bool {
|
func (s *server) IsTLS() bool {
|
||||||
return s.cfg.IsTLS()
|
return s.GetConfig().IsTLS()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) Listen(handler http.Handler) liberr.Error {
|
func (s *server) Listen(handler http.Handler) liberr.Error {
|
||||||
r := s.getRun()
|
r := s.getRun()
|
||||||
e := r.Listen(&s.cfg, handler)
|
e := r.Listen(s.GetConfig(), handler)
|
||||||
s.setRun(r)
|
s.setRun(r)
|
||||||
|
|
||||||
return e
|
return e
|
||||||
@@ -163,12 +183,11 @@ func (s *server) Shutdown() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) Merge(srv Server) bool {
|
func (s *server) Merge(srv Server) bool {
|
||||||
if x, ok := srv.(*server); ok {
|
if x, ok := srv.(*server); !ok {
|
||||||
s.cfg = x.cfg
|
return false
|
||||||
return true
|
} else {
|
||||||
|
return s.SetConfig(x.GetConfig())
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) StatusInfo() (name string, release string, hash string) {
|
func (s *server) StatusInfo() (name string, release string, hash string) {
|
||||||
@@ -180,17 +199,20 @@ func (s *server) StatusInfo() (name string, release string, hash string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) StatusHealth() error {
|
func (s *server) StatusHealth() error {
|
||||||
if !s.cfg.Disabled && s.IsRunning() {
|
c := s.GetConfig()
|
||||||
|
if !c.Disabled && s.IsRunning() {
|
||||||
return nil
|
return nil
|
||||||
} else if s.cfg.Disabled {
|
} else if c.Disabled {
|
||||||
|
//nolint #goerr113
|
||||||
return fmt.Errorf("server disabled")
|
return fmt.Errorf("server disabled")
|
||||||
} else if e := s.getErr(); e != nil {
|
} else if e := s.getErr(); e != nil {
|
||||||
return e
|
return e
|
||||||
} else {
|
} else {
|
||||||
|
//nolint #goerr113
|
||||||
return fmt.Errorf("server is offline -- missing error")
|
return fmt.Errorf("server is offline -- missing error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) StatusComponent(message status.FctMessage) status.Component {
|
func (s *server) StatusComponent(message libsts.FctMessage) libsts.Component {
|
||||||
return status.NewComponent(s.cfg.Mandatory, s.StatusInfo, s.StatusHealth, message, s.cfg.TimeoutCacheInfo, s.cfg.TimeoutCacheHealth)
|
return libsts.NewComponent(s.GetConfig().Mandatory, s.StatusInfo, s.StatusHealth, message, s.GetConfig().TimeoutCacheInfo, s.GetConfig().TimeoutCacheHealth)
|
||||||
}
|
}
|
||||||
|
132
ldap/ldap.go
132
ldap/ldap.go
@@ -59,10 +59,11 @@ func NewLDAP(ctx context.Context, cnf *Config, attributes []string) (*HelperLDAP
|
|||||||
|
|
||||||
return &HelperLDAP{
|
return &HelperLDAP{
|
||||||
Attributes: attributes,
|
Attributes: attributes,
|
||||||
tlsConfig: libcrt.GetTLSConfig(cnf.Uri),
|
//nolint #staticcheck
|
||||||
tlsMode: tlsmode_init,
|
tlsConfig: libcrt.GetTLSConfig(cnf.Uri),
|
||||||
config: cnf.Clone(),
|
tlsMode: _TLSModeInit,
|
||||||
ctx: libctx.IsolateParent(ctx),
|
config: cnf.Clone(),
|
||||||
|
ctx: libctx.IsolateParent(ctx),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,15 +84,15 @@ func (lc *HelperLDAP) ForceTLSMode(tlsMode TLSMode, tlsConfig *tls.Config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch tlsMode {
|
switch tlsMode {
|
||||||
case TLSMODE_TLS:
|
case TLSModeTLS:
|
||||||
lc.tlsMode = TLSMODE_TLS
|
lc.tlsMode = TLSModeTLS
|
||||||
case TLSMODE_STARTTLS:
|
case TLSModeStarttls:
|
||||||
lc.tlsMode = TLSMODE_STARTTLS
|
lc.tlsMode = TLSModeStarttls
|
||||||
case TLSMODE_NONE:
|
case TLSModeNone:
|
||||||
lc.tlsConfig = nil
|
lc.tlsConfig = nil
|
||||||
lc.tlsMode = TLSMODE_NONE
|
lc.tlsMode = TLSModeNone
|
||||||
case tlsmode_init:
|
case _TLSModeInit:
|
||||||
lc.tlsMode = tlsmode_init
|
lc.tlsMode = _TLSModeInit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +176,7 @@ func (lc *HelperLDAP) starttls(l *ldap.Conn) liberr.Error {
|
|||||||
|
|
||||||
func (lc *HelperLDAP) tryConnect() (TLSMode, liberr.Error) {
|
func (lc *HelperLDAP) tryConnect() (TLSMode, liberr.Error) {
|
||||||
if lc == nil {
|
if lc == nil {
|
||||||
return TLSMODE_NONE, ErrorEmptyParams.Error(nil)
|
return TLSModeNone, ErrorEmptyParams.Error(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -192,32 +193,32 @@ func (lc *HelperLDAP) tryConnect() (TLSMode, liberr.Error) {
|
|||||||
if lc.config.Portldaps != 0 {
|
if lc.config.Portldaps != 0 {
|
||||||
l, err = lc.dialTLS()
|
l, err = lc.dialTLS()
|
||||||
|
|
||||||
liblog.DebugLevel.LogErrorCtxf(liblog.DebugLevel, "connecting ldap with tls mode '%s'", err, TLSMODE_TLS.String())
|
liblog.DebugLevel.LogErrorCtxf(liblog.DebugLevel, "connecting ldap with tls mode '%s'", err, TLSModeTLS.String())
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return TLSMODE_TLS, nil
|
return TLSModeTLS, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if lc.config.PortLdap == 0 {
|
if lc.config.PortLdap == 0 {
|
||||||
return tlsmode_init, ErrorLDAPServerConfig.Error(nil)
|
return _TLSModeInit, ErrorLDAPServerConfig.Error(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
l, err = lc.dial()
|
l, err = lc.dial()
|
||||||
liblog.DebugLevel.LogErrorCtxf(liblog.DebugLevel, "connecting ldap with tls mode '%s'", err, TLSMODE_NONE.String())
|
liblog.DebugLevel.LogErrorCtxf(liblog.DebugLevel, "connecting ldap with tls mode '%s'", err, TLSModeNone.String())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return tlsmode_init, err
|
return _TLSModeInit, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = lc.starttls(l)
|
err = lc.starttls(l)
|
||||||
liblog.DebugLevel.LogErrorCtxf(liblog.DebugLevel, "connecting ldap with tls mode '%s'", err, TLSMODE_STARTTLS.String())
|
liblog.DebugLevel.LogErrorCtxf(liblog.DebugLevel, "connecting ldap with tls mode '%s'", err, TLSModeStarttls.String())
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return TLSMODE_STARTTLS, nil
|
return TLSModeStarttls, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return TLSMODE_NONE, nil
|
return TLSModeNone, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lc *HelperLDAP) connect() liberr.Error {
|
func (lc *HelperLDAP) connect() liberr.Error {
|
||||||
@@ -235,7 +236,7 @@ func (lc *HelperLDAP) connect() liberr.Error {
|
|||||||
err liberr.Error
|
err liberr.Error
|
||||||
)
|
)
|
||||||
|
|
||||||
if lc.tlsMode == tlsmode_init {
|
if lc.tlsMode == _TLSModeInit {
|
||||||
m, e := lc.tryConnect()
|
m, e := lc.tryConnect()
|
||||||
|
|
||||||
if e != nil {
|
if e != nil {
|
||||||
@@ -245,7 +246,7 @@ func (lc *HelperLDAP) connect() liberr.Error {
|
|||||||
lc.tlsMode = m
|
lc.tlsMode = m
|
||||||
}
|
}
|
||||||
|
|
||||||
if lc.tlsMode == TLSMODE_TLS {
|
if lc.tlsMode == TLSModeTLS {
|
||||||
l, err = lc.dialTLS()
|
l, err = lc.dialTLS()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if l != nil {
|
if l != nil {
|
||||||
@@ -255,7 +256,7 @@ func (lc *HelperLDAP) connect() liberr.Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if lc.tlsMode == TLSMODE_NONE || lc.tlsMode == TLSMODE_STARTTLS {
|
if lc.tlsMode == TLSModeNone || lc.tlsMode == TLSModeStarttls {
|
||||||
l, err = lc.dial()
|
l, err = lc.dial()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if l != nil {
|
if l != nil {
|
||||||
@@ -265,7 +266,7 @@ func (lc *HelperLDAP) connect() liberr.Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if lc.tlsMode == TLSMODE_STARTTLS {
|
if lc.tlsMode == TLSModeStarttls {
|
||||||
err = lc.starttls(l)
|
err = lc.starttls(l)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if l != nil {
|
if l != nil {
|
||||||
@@ -346,7 +347,7 @@ func (lc *HelperLDAP) Connect() liberr.Error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
liblog.DebugLevel.Logf("Bind success on LDAP server %s with tls mode '%s'", lc.config.ServerAddr(lc.tlsMode == TLSMODE_TLS), lc.tlsMode.String())
|
liblog.DebugLevel.Logf("Bind success on LDAP server %s with tls mode '%s'", lc.config.ServerAddr(lc.tlsMode == TLSModeTLS), lc.tlsMode.String())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,7 +377,7 @@ func (lc *HelperLDAP) runSearch(filter string, attributes []string) (*ldap.Searc
|
|||||||
return nil, ErrorLDAPSearch.ErrorParent(err)
|
return nil, ErrorLDAPSearch.ErrorParent(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
liblog.DebugLevel.Logf("Search success on server '%s' with tls mode '%s', with filter [%s] and attribute %v", lc.config.ServerAddr(lc.tlsMode == TLSMODE_TLS), lc.tlsMode.String(), filter, attributes)
|
liblog.DebugLevel.Logf("Search success on server '%s' with tls mode '%s', with filter [%s] and attribute %v", lc.config.ServerAddr(lc.tlsMode == TLSModeTLS), lc.tlsMode.String(), filter, attributes)
|
||||||
return src, nil
|
return src, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,46 +406,10 @@ func (lc *HelperLDAP) getUserName(username string) (string, liberr.Error) {
|
|||||||
|
|
||||||
//UserInfo used to retrieve the information of a given username.
|
//UserInfo used to retrieve the information of a given username.
|
||||||
func (lc *HelperLDAP) UserInfo(username string) (map[string]string, liberr.Error) {
|
func (lc *HelperLDAP) UserInfo(username string) (map[string]string, liberr.Error) {
|
||||||
var (
|
return lc.UserInfoByField(username, userFieldUid)
|
||||||
err liberr.Error
|
|
||||||
src *ldap.SearchResult
|
|
||||||
userRes map[string]string
|
|
||||||
)
|
|
||||||
|
|
||||||
if username, err = lc.getUserName(username); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
userRes = make(map[string]string)
|
|
||||||
attributes := append(lc.Attributes, "cn")
|
|
||||||
|
|
||||||
src, err = lc.runSearch(fmt.Sprintf(lc.config.FilterUser, userFieldUid, username), attributes)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return userRes, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(src.Entries) != 1 {
|
|
||||||
if len(src.Entries) > 1 {
|
|
||||||
return userRes, ErrorLDAPUserNotUniq.Error(nil)
|
|
||||||
} else {
|
|
||||||
return userRes, ErrorLDAPUserNotFound.Error(nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, attr := range attributes {
|
|
||||||
userRes[attr] = src.Entries[0].GetAttributeValue(attr)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := userRes["DN"]; !ok {
|
|
||||||
userRes["DN"] = src.Entries[0].DN
|
|
||||||
}
|
|
||||||
|
|
||||||
liblog.DebugLevel.Logf("Map info retrieve in ldap server '%s' with tls mode '%s' about user [%s] : %v", lc.config.ServerAddr(lc.tlsMode == TLSMODE_TLS), lc.tlsMode.String(), username, userRes)
|
|
||||||
return userRes, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//UserInfo used to retrieve the information of a given username.
|
//UserInfoByField used to retrieve the information of a given username but use a given field to make the search.
|
||||||
func (lc *HelperLDAP) UserInfoByField(username string, fieldOfUnicValue string) (map[string]string, liberr.Error) {
|
func (lc *HelperLDAP) UserInfoByField(username string, fieldOfUnicValue string) (map[string]string, liberr.Error) {
|
||||||
var (
|
var (
|
||||||
err liberr.Error
|
err liberr.Error
|
||||||
@@ -481,39 +446,16 @@ func (lc *HelperLDAP) UserInfoByField(username string, fieldOfUnicValue string)
|
|||||||
userRes["DN"] = src.Entries[0].DN
|
userRes["DN"] = src.Entries[0].DN
|
||||||
}
|
}
|
||||||
|
|
||||||
liblog.DebugLevel.Logf("Map info retrieve in ldap server '%s' with tls mode '%s' about user [%s] : %v", lc.config.ServerAddr(lc.tlsMode == TLSMODE_TLS), lc.tlsMode.String(), username, userRes)
|
liblog.DebugLevel.Logf("Map info retrieve in ldap server '%s' with tls mode '%s' about user [%s] : %v", lc.config.ServerAddr(lc.tlsMode == TLSModeTLS), lc.tlsMode.String(), username, userRes)
|
||||||
return userRes, nil
|
return userRes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//GroupInfo used to retrieve the information of a given group cn.
|
//GroupInfo used to retrieve the information of a given group cn.
|
||||||
func (lc *HelperLDAP) GroupInfo(groupname string) (map[string]interface{}, liberr.Error) {
|
func (lc *HelperLDAP) GroupInfo(groupname string) (map[string]interface{}, liberr.Error) {
|
||||||
var (
|
return lc.GroupInfoByField(groupname, groupFieldCN)
|
||||||
err liberr.Error
|
|
||||||
src *ldap.SearchResult
|
|
||||||
grpInfo map[string]interface{}
|
|
||||||
)
|
|
||||||
|
|
||||||
src, err = lc.runSearch(fmt.Sprintf(lc.config.FilterGroup, groupFieldCN, groupname), []string{})
|
|
||||||
if err != nil {
|
|
||||||
return grpInfo, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(src.Entries) == 0 {
|
|
||||||
return nil, ErrorLDAPGroupNotFound.Error(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
grpInfo = make(map[string]interface{}, len(src.Entries[0].Attributes))
|
|
||||||
for _, entry := range src.Entries {
|
|
||||||
for _, entryAttribute := range entry.Attributes {
|
|
||||||
grpInfo[entryAttribute.Name] = entryAttribute.Values
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
liblog.DebugLevel.Logf("Info for group [%s] find on server '%s' with tls mode '%s' : %v", groupname, lc.config.ServerAddr(lc.tlsMode == TLSMODE_TLS), lc.tlsMode.String(), grpInfo)
|
|
||||||
return grpInfo, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//GroupInfo used to retrieve the information of a given group cn.
|
//GroupInfoByField used to retrieve the information of a given group cn, but use a given field to make the search.
|
||||||
func (lc *HelperLDAP) GroupInfoByField(groupname string, fieldForUnicValue string) (map[string]interface{}, liberr.Error) {
|
func (lc *HelperLDAP) GroupInfoByField(groupname string, fieldForUnicValue string) (map[string]interface{}, liberr.Error) {
|
||||||
var (
|
var (
|
||||||
err liberr.Error
|
err liberr.Error
|
||||||
@@ -537,7 +479,7 @@ func (lc *HelperLDAP) GroupInfoByField(groupname string, fieldForUnicValue strin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
liblog.DebugLevel.Logf("Info for group [%s] find on server '%s' with tls mode '%s' : %v", groupname, lc.config.ServerAddr(lc.tlsMode == TLSMODE_TLS), lc.tlsMode.String(), grpInfo)
|
liblog.DebugLevel.Logf("Info for group [%s] find on server '%s' with tls mode '%s' : %v", groupname, lc.config.ServerAddr(lc.tlsMode == TLSModeTLS), lc.tlsMode.String(), grpInfo)
|
||||||
return grpInfo, nil
|
return grpInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,13 +504,13 @@ func (lc *HelperLDAP) UserMemberOf(username string) ([]string, liberr.Error) {
|
|||||||
|
|
||||||
for _, entry := range src.Entries {
|
for _, entry := range src.Entries {
|
||||||
for _, mmb := range entry.GetAttributeValues("memberOf") {
|
for _, mmb := range entry.GetAttributeValues("memberOf") {
|
||||||
liblog.DebugLevel.Logf("Group find for uid '%s' on server '%s' with tls mode '%s' : %v", username, lc.config.ServerAddr(lc.tlsMode == TLSMODE_TLS), lc.tlsMode.String(), mmb)
|
liblog.DebugLevel.Logf("Group find for uid '%s' on server '%s' with tls mode '%s' : %v", username, lc.config.ServerAddr(lc.tlsMode == TLSModeTLS), lc.tlsMode.String(), mmb)
|
||||||
mmo := lc.ParseEntries(mmb)
|
mmo := lc.ParseEntries(mmb)
|
||||||
grp = append(grp, mmo["cn"]...)
|
grp = append(grp, mmo["cn"]...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
liblog.DebugLevel.Logf("Groups find for uid '%s' on server '%s' with tls mode '%s' : %v", username, lc.config.ServerAddr(lc.tlsMode == TLSMODE_TLS), lc.tlsMode.String(), grp)
|
liblog.DebugLevel.Logf("Groups find for uid '%s' on server '%s' with tls mode '%s' : %v", username, lc.config.ServerAddr(lc.tlsMode == TLSModeTLS), lc.tlsMode.String(), grp)
|
||||||
return grp, nil
|
return grp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -618,7 +560,7 @@ func (lc *HelperLDAP) UsersOfGroup(groupname string) ([]string, liberr.Error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
liblog.DebugLevel.Logf("Member of groups [%s] find on server '%s' with tls mode '%s' : %v", groupname, lc.config.ServerAddr(lc.tlsMode == TLSMODE_TLS), lc.tlsMode.String(), grp)
|
liblog.DebugLevel.Logf("Member of groups [%s] find on server '%s' with tls mode '%s' : %v", groupname, lc.config.ServerAddr(lc.tlsMode == TLSModeTLS), lc.tlsMode.String(), grp)
|
||||||
return grp, nil
|
return grp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -35,13 +35,13 @@ import (
|
|||||||
type TLSMode uint8
|
type TLSMode uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
tlsmode_init TLSMode = iota
|
_TLSModeInit TLSMode = iota
|
||||||
//TLSModeNone no tls connection.
|
//TLSModeNone no tls connection.
|
||||||
TLSMODE_NONE TLSMode = iota + 1
|
TLSModeNone TLSMode = iota + 1
|
||||||
//TLSModeTLS strict tls connection.
|
//TLSModeTLS strict tls connection.
|
||||||
TLSMODE_TLS
|
TLSModeTLS
|
||||||
//TLSModeStartTLS starttls connection (tls into a no tls connection).
|
//TLSModeStarttls starttls connection (tls into a no tls connection).
|
||||||
TLSMODE_STARTTLS
|
TLSModeStarttls
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -51,17 +51,17 @@ const (
|
|||||||
|
|
||||||
func (m TLSMode) String() string {
|
func (m TLSMode) String() string {
|
||||||
switch m {
|
switch m {
|
||||||
case TLSMODE_STARTTLS:
|
case TLSModeStarttls:
|
||||||
return "starttls"
|
return "starttls"
|
||||||
case TLSMODE_TLS:
|
case TLSModeTLS:
|
||||||
return "tls"
|
return "tls"
|
||||||
case TLSMODE_NONE:
|
case TLSModeNone:
|
||||||
return "none"
|
return "none"
|
||||||
case tlsmode_init:
|
case _TLSModeInit:
|
||||||
return "not defined"
|
return "not defined"
|
||||||
}
|
}
|
||||||
|
|
||||||
return tlsmode_init.String()
|
return _TLSModeInit.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDefaultAttributes() []string {
|
func GetDefaultAttributes() []string {
|
||||||
@@ -123,6 +123,7 @@ func (cnf Config) Validate() errors.Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, err := range err.(validator.ValidationErrors) {
|
for _, err := range err.(validator.ValidationErrors) {
|
||||||
|
//nolint #goerr113
|
||||||
e.AddParent(fmt.Errorf("config field '%s' is not validated by constraint '%s'", err.StructNamespace(), err.ActualTag()))
|
e.AddParent(fmt.Errorf("config field '%s' is not validated by constraint '%s'", err.StructNamespace(), err.ActualTag()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (c) 2020 Nicolas JUHEL
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package mail
|
|
||||||
|
|
||||||
import "io"
|
|
||||||
|
|
||||||
const maxLineChars = 76
|
|
||||||
|
|
||||||
type base64LineWrap struct {
|
|
||||||
writer io.Writer
|
|
||||||
numLineChars int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *base64LineWrap) Write(p []byte) (n int, err error) {
|
|
||||||
n = 0
|
|
||||||
// while we have more chars than are allowed
|
|
||||||
for len(p)+e.numLineChars > maxLineChars {
|
|
||||||
numCharsToWrite := maxLineChars - e.numLineChars
|
|
||||||
// write the chars we can
|
|
||||||
/* #nosec */
|
|
||||||
//nolint #nosec
|
|
||||||
_, _ = e.writer.Write(p[:numCharsToWrite])
|
|
||||||
// write a line break
|
|
||||||
/* #nosec */
|
|
||||||
//nolint #nosec
|
|
||||||
_, _ = e.writer.Write([]byte("\r\n"))
|
|
||||||
// reset the line count
|
|
||||||
e.numLineChars = 0
|
|
||||||
// remove the chars that have been written
|
|
||||||
p = p[numCharsToWrite:]
|
|
||||||
// set the num of chars written
|
|
||||||
n += numCharsToWrite
|
|
||||||
}
|
|
||||||
|
|
||||||
// write what is left
|
|
||||||
/* #nosec */
|
|
||||||
//nolint #nosec
|
|
||||||
_, _ = e.writer.Write(p)
|
|
||||||
e.numLineChars += len(p)
|
|
||||||
n += len(p)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
@@ -28,9 +28,9 @@ package mail
|
|||||||
type ContentType uint8
|
type ContentType uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// TextPlain sets body type to text/plain in message body
|
// ContentPlainText sets body type to text/plain in message body.
|
||||||
ContentPlainText ContentType = iota
|
ContentPlainText ContentType = iota
|
||||||
// TextHTML sets body type to text/html in message body
|
// ContentHTML sets body type to text/html in message body.
|
||||||
ContentHTML
|
ContentHTML
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -44,14 +44,3 @@ func (c ContentType) String() string {
|
|||||||
|
|
||||||
return ContentPlainText.String()
|
return ContentPlainText.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c ContentType) getContentType() string {
|
|
||||||
switch c {
|
|
||||||
case ContentPlainText:
|
|
||||||
return "text/plain"
|
|
||||||
case ContentHTML:
|
|
||||||
return "text/html"
|
|
||||||
}
|
|
||||||
|
|
||||||
return ContentPlainText.getContentType()
|
|
||||||
}
|
|
||||||
|
200
mail/encoder.go
200
mail/encoder.go
@@ -1,200 +0,0 @@
|
|||||||
/*
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (c) 2020 Nicolas JUHEL
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package mail
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"strings"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
type encoder struct {
|
|
||||||
w *bufio.Writer
|
|
||||||
charset string
|
|
||||||
usedChars int
|
|
||||||
}
|
|
||||||
|
|
||||||
// newEncoder returns a new mime header encoder that writes to w. The c
|
|
||||||
// parameter specifies the name of the character set of the text that will be
|
|
||||||
// encoded. The u parameter indicates how many characters have been used
|
|
||||||
// already.
|
|
||||||
func newEncoder(w io.Writer, c string, u int) *encoder {
|
|
||||||
return &encoder{bufio.NewWriter(w), strings.ToUpper(c), u}
|
|
||||||
}
|
|
||||||
|
|
||||||
// encode encodes p using the "Q" encoding and writes it to the underlying
|
|
||||||
// io.Writer. It limits line length to 75 characters.
|
|
||||||
func (e *encoder) encode(p []byte) (n int, err error) {
|
|
||||||
var output bytes.Buffer
|
|
||||||
allPrintable := true
|
|
||||||
|
|
||||||
// some lines we encode end in "
|
|
||||||
//maxLineLength := 75 - 1
|
|
||||||
maxLineLength := 76
|
|
||||||
|
|
||||||
// prevent header injection
|
|
||||||
p = e.secureHeader(p)
|
|
||||||
|
|
||||||
// check to see if we have all printable characters
|
|
||||||
for _, c := range p {
|
|
||||||
if !e.isVchar(c) && !e.isWSP(c) {
|
|
||||||
allPrintable = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// all characters are printable. just do line folding
|
|
||||||
if allPrintable {
|
|
||||||
text := string(p)
|
|
||||||
words := strings.Split(text, " ")
|
|
||||||
|
|
||||||
lineBuffer := ""
|
|
||||||
firstWord := true
|
|
||||||
|
|
||||||
// split the line where necessary
|
|
||||||
for _, word := range words {
|
|
||||||
|
|
||||||
newWord := ""
|
|
||||||
if !firstWord {
|
|
||||||
newWord += " "
|
|
||||||
}
|
|
||||||
newWord += word
|
|
||||||
|
|
||||||
// check line length
|
|
||||||
if (e.usedChars+len(lineBuffer)+len(newWord) /*+len(" ")+len(word)*/) > maxLineLength && (lineBuffer != "" || e.usedChars != 0) {
|
|
||||||
output.WriteString(lineBuffer + "\r\n")
|
|
||||||
|
|
||||||
// first word on newline needs a space in front
|
|
||||||
if !firstWord {
|
|
||||||
lineBuffer = ""
|
|
||||||
} else {
|
|
||||||
lineBuffer = " "
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset since not on the first line anymore
|
|
||||||
e.usedChars = 0
|
|
||||||
}
|
|
||||||
lineBuffer += newWord /*word*/
|
|
||||||
|
|
||||||
firstWord = false
|
|
||||||
}
|
|
||||||
|
|
||||||
output.WriteString(lineBuffer)
|
|
||||||
|
|
||||||
} else {
|
|
||||||
firstLine := true
|
|
||||||
|
|
||||||
// A single encoded word can not be longer than 75 characters
|
|
||||||
if e.usedChars == 0 {
|
|
||||||
maxLineLength = 75
|
|
||||||
}
|
|
||||||
|
|
||||||
wordBegin := "=?" + e.charset + "?Q?"
|
|
||||||
wordEnd := "?="
|
|
||||||
|
|
||||||
lineBuffer := wordBegin
|
|
||||||
|
|
||||||
for i := 0; i < len(p); {
|
|
||||||
// encode the character
|
|
||||||
encodedChar, runeLength := e.encodeChar(p, i)
|
|
||||||
|
|
||||||
// Check line length
|
|
||||||
if len(lineBuffer)+e.usedChars+len(encodedChar) > (maxLineLength - len(wordEnd)) {
|
|
||||||
output.WriteString(lineBuffer + wordEnd + "\r\n")
|
|
||||||
lineBuffer = " " + wordBegin
|
|
||||||
firstLine = false
|
|
||||||
}
|
|
||||||
|
|
||||||
lineBuffer += encodedChar
|
|
||||||
|
|
||||||
i = i + runeLength
|
|
||||||
|
|
||||||
// reset since not on the first line anymore
|
|
||||||
if !firstLine {
|
|
||||||
e.usedChars = 0
|
|
||||||
maxLineLength = 76
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
output.WriteString(lineBuffer + wordEnd)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, _ = e.w.Write(output.Bytes())
|
|
||||||
_ = e.w.Flush()
|
|
||||||
n = output.Len()
|
|
||||||
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// encode takes a string and position in that string and encodes one utf-8
|
|
||||||
// character. It then returns the encoded string and number of runes in the
|
|
||||||
// character.
|
|
||||||
func (e *encoder) encodeChar(text []byte, i int) (encodedString string, runeLength int) {
|
|
||||||
started := false
|
|
||||||
|
|
||||||
for ; i < len(text) && (!utf8.RuneStart(text[i]) || !started); i++ {
|
|
||||||
switch c := text[i]; {
|
|
||||||
case c == ' ':
|
|
||||||
encodedString += "_"
|
|
||||||
case e.isVchar(c) && c != '=' && c != '?' && c != '_':
|
|
||||||
encodedString += string(c)
|
|
||||||
default:
|
|
||||||
encodedString += fmt.Sprintf("=%02X", c)
|
|
||||||
}
|
|
||||||
|
|
||||||
runeLength++
|
|
||||||
|
|
||||||
started = true
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// secureHeader removes all unnecessary values to prevent
|
|
||||||
// header injection
|
|
||||||
func (e *encoder) secureHeader(text []byte) []byte {
|
|
||||||
secureValue := strings.TrimSpace(string(text))
|
|
||||||
secureValue = strings.Replace(secureValue, "\r", "", -1)
|
|
||||||
secureValue = strings.Replace(secureValue, "\n", "", -1)
|
|
||||||
secureValue = strings.Replace(secureValue, "\t", "", -1)
|
|
||||||
|
|
||||||
return []byte(secureValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
// isVchar returns true if c is an RFC 5322 VCHAR character.
|
|
||||||
func (e *encoder) isVchar(c byte) bool {
|
|
||||||
// Visible (printing) characters.
|
|
||||||
return '!' <= c && c <= '~'
|
|
||||||
}
|
|
||||||
|
|
||||||
// isWSP returns true if c is a WSP (white space).
|
|
||||||
// WSP is a space or horizontal tab (RFC5234 Appendix B).
|
|
||||||
func (e *encoder) isWSP(c byte) bool {
|
|
||||||
return c == ' ' || c == '\t'
|
|
||||||
}
|
|
@@ -28,16 +28,16 @@ package mail
|
|||||||
type Encoding uint8
|
type Encoding uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// EncodingNone turns off encoding on the message body
|
// EncodingNone turns off encoding on the message body.
|
||||||
EncodingNone Encoding = iota
|
EncodingNone Encoding = iota
|
||||||
|
|
||||||
// EncodingBinary is equal to EncodingNone, but string is set to binrary instead of none
|
// EncodingBinary is equal to EncodingNone, but string is set to binary instead of none.
|
||||||
EncodingBinary
|
EncodingBinary
|
||||||
|
|
||||||
// EncodingBase64 sets the message body encoding to base64
|
// EncodingBase64 sets the message body encoding to base64.
|
||||||
EncodingBase64
|
EncodingBase64
|
||||||
|
|
||||||
// EncodingQuotedPrintable sets the message body encoding to quoted-printable
|
// EncodingQuotedPrintable sets the message body encoding to quoted-printable.
|
||||||
EncodingQuotedPrintable
|
EncodingQuotedPrintable
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -54,16 +54,3 @@ func (e Encoding) String() string {
|
|||||||
}
|
}
|
||||||
return EncodingNone.String()
|
return EncodingNone.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e Encoding) getEncoding() string {
|
|
||||||
switch e {
|
|
||||||
case EncodingNone, EncodingBinary:
|
|
||||||
return "binary"
|
|
||||||
case EncodingBase64:
|
|
||||||
return "base64"
|
|
||||||
case EncodingQuotedPrintable:
|
|
||||||
return "quoted-printable"
|
|
||||||
}
|
|
||||||
|
|
||||||
return EncodingNone.getEncoding()
|
|
||||||
}
|
|
||||||
|
21
mail/mail.go
21
mail/mail.go
@@ -36,7 +36,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MailDateTimeLayout = time.RFC1123Z
|
DateTimeLayout = time.RFC1123Z
|
||||||
|
|
||||||
headerMimeVersion = "MIME-Version"
|
headerMimeVersion = "MIME-Version"
|
||||||
headerDate = "Date"
|
headerDate = "Date"
|
||||||
@@ -44,17 +44,16 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type mail struct {
|
type mail struct {
|
||||||
headers textproto.MIMEHeader
|
|
||||||
charset string
|
|
||||||
encoding Encoding
|
|
||||||
date time.Time
|
date time.Time
|
||||||
|
attach []File
|
||||||
|
inline []File
|
||||||
|
body []Body
|
||||||
|
charset string
|
||||||
subject string
|
subject string
|
||||||
|
headers textproto.MIMEHeader
|
||||||
|
address *email
|
||||||
|
encoding Encoding
|
||||||
priority Priority
|
priority Priority
|
||||||
|
|
||||||
address *email
|
|
||||||
attach []File
|
|
||||||
inline []File
|
|
||||||
body []Body
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mail) Email() Email {
|
func (m *mail) Email() Email {
|
||||||
@@ -112,7 +111,7 @@ func (m *mail) SetDateString(layout, datetime string) liberr.Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *mail) GetDateString() string {
|
func (m *mail) GetDateString() string {
|
||||||
return m.date.Format(MailDateTimeLayout)
|
return m.date.Format(DateTimeLayout)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mail) AddHeader(key string, values ...string) {
|
func (m *mail) AddHeader(key string, values ...string) {
|
||||||
@@ -182,7 +181,7 @@ func (m *mail) GetHeaders() textproto.MIMEHeader {
|
|||||||
h = m.addHeader(h, key, values...)
|
h = m.addHeader(h, key, values...)
|
||||||
})
|
})
|
||||||
|
|
||||||
for k, _ := range m.headers {
|
for k := range m.headers {
|
||||||
h = m.addHeader(h, k, m.headers.Values(k)...)
|
h = m.addHeader(h, k, m.headers.Values(k)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -34,11 +34,11 @@ const (
|
|||||||
type Priority uint8
|
type Priority uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// PriorityNormal sets the email priority to normal
|
// PriorityNormal sets the email priority to normal.
|
||||||
PriorityNormal Priority = iota
|
PriorityNormal Priority = iota
|
||||||
// PriorityLow sets the email priority to Low
|
// PriorityLow sets the email priority to Low.
|
||||||
PriorityLow
|
PriorityLow
|
||||||
// PriorityHigh sets the email priority to High
|
// PriorityHigh sets the email priority to High.
|
||||||
PriorityHigh
|
PriorityHigh
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -71,9 +71,9 @@ func (p Priority) headerPriority() string {
|
|||||||
func (p Priority) headerImportance() string {
|
func (p Priority) headerImportance() string {
|
||||||
switch p {
|
switch p {
|
||||||
case PriorityLow:
|
case PriorityLow:
|
||||||
return "Low"
|
return PriorityLow.String()
|
||||||
case PriorityHigh:
|
case PriorityHigh:
|
||||||
return "High"
|
return PriorityHigh.String()
|
||||||
case PriorityNormal:
|
case PriorityNormal:
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@@ -84,9 +84,9 @@ func (p Priority) headerImportance() string {
|
|||||||
func (p Priority) headerMSMailPriority() string {
|
func (p Priority) headerMSMailPriority() string {
|
||||||
switch p {
|
switch p {
|
||||||
case PriorityLow:
|
case PriorityLow:
|
||||||
return "Low"
|
return PriorityLow.String()
|
||||||
case PriorityHigh:
|
case PriorityHigh:
|
||||||
return "High"
|
return PriorityHigh.String()
|
||||||
case PriorityNormal:
|
case PriorityNormal:
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
@@ -31,29 +31,32 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/nabbar/golib/smtp"
|
|
||||||
|
|
||||||
"github.com/nabbar/golib/ioutils"
|
|
||||||
|
|
||||||
liberr "github.com/nabbar/golib/errors"
|
liberr "github.com/nabbar/golib/errors"
|
||||||
|
libiot "github.com/nabbar/golib/ioutils"
|
||||||
|
libsmtp "github.com/nabbar/golib/smtp"
|
||||||
simple "github.com/xhit/go-simple-mail"
|
simple "github.com/xhit/go-simple-mail"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
_MinSizeAddr = 4
|
||||||
|
)
|
||||||
|
|
||||||
type Sender interface {
|
type Sender interface {
|
||||||
Close() error
|
Close() error
|
||||||
Send(ctx context.Context, cli smtp.SMTP) liberr.Error
|
Send(ctx context.Context, cli libsmtp.SMTP) liberr.Error
|
||||||
SendClose(ctx context.Context, cli smtp.SMTP) liberr.Error
|
SendClose(ctx context.Context, cli libsmtp.SMTP) liberr.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
type sender struct {
|
type sender struct {
|
||||||
data ioutils.FileProgress
|
data libiot.FileProgress
|
||||||
from string
|
from string
|
||||||
rcpt []string
|
rcpt []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint #gocognit
|
||||||
func (m *mail) Sender() (snd Sender, err liberr.Error) {
|
func (m *mail) Sender() (snd Sender, err liberr.Error) {
|
||||||
e := simple.NewMSG()
|
e := simple.NewMSG()
|
||||||
f := make([]ioutils.FileProgress, 0)
|
f := make([]libiot.FileProgress, 0)
|
||||||
|
|
||||||
switch m.GetPriority() {
|
switch m.GetPriority() {
|
||||||
case PriorityHigh:
|
case PriorityHigh:
|
||||||
@@ -142,7 +145,7 @@ func (m *mail) Sender() (snd Sender, err liberr.Error) {
|
|||||||
|
|
||||||
if len(m.attach) > 0 {
|
if len(m.attach) > 0 {
|
||||||
for _, i := range m.attach {
|
for _, i := range m.attach {
|
||||||
if t, er := ioutils.NewFileProgressTemp(); er != nil {
|
if t, er := libiot.NewFileProgressTemp(); er != nil {
|
||||||
return nil, er
|
return nil, er
|
||||||
} else if _, er := t.ReadFrom(i.data); er != nil {
|
} else if _, er := t.ReadFrom(i.data); er != nil {
|
||||||
return nil, ErrorIORead.ErrorParent(er)
|
return nil, ErrorIORead.ErrorParent(er)
|
||||||
@@ -156,7 +159,7 @@ func (m *mail) Sender() (snd Sender, err liberr.Error) {
|
|||||||
|
|
||||||
if len(m.inline) > 0 {
|
if len(m.inline) > 0 {
|
||||||
for _, i := range m.inline {
|
for _, i := range m.inline {
|
||||||
if t, er := ioutils.NewFileProgressTemp(); er != nil {
|
if t, er := libiot.NewFileProgressTemp(); er != nil {
|
||||||
return nil, er
|
return nil, er
|
||||||
} else if _, er := t.ReadFrom(i.data); er != nil {
|
} else if _, er := t.ReadFrom(i.data); er != nil {
|
||||||
return nil, ErrorIORead.ErrorParent(er)
|
return nil, ErrorIORead.ErrorParent(er)
|
||||||
@@ -206,7 +209,7 @@ func (m *mail) Sender() (snd Sender, err liberr.Error) {
|
|||||||
s.rcpt = append(s.rcpt, m.Email().GetRecipients(RecipientCC)...)
|
s.rcpt = append(s.rcpt, m.Email().GetRecipients(RecipientCC)...)
|
||||||
s.rcpt = append(s.rcpt, m.Email().GetRecipients(RecipientBCC)...)
|
s.rcpt = append(s.rcpt, m.Email().GetRecipients(RecipientBCC)...)
|
||||||
|
|
||||||
if tmp, err := ioutils.NewFileProgressTemp(); err != nil {
|
if tmp, err := libiot.NewFileProgressTemp(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if _, er := tmp.WriteString(e.GetMessage()); er != nil {
|
} else if _, er := tmp.WriteString(e.GetMessage()); er != nil {
|
||||||
return nil, ErrorIOWrite.ErrorParent(er)
|
return nil, ErrorIOWrite.ErrorParent(er)
|
||||||
@@ -222,7 +225,7 @@ func (m *mail) Sender() (snd Sender, err liberr.Error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sender) SendClose(ctx context.Context, cli smtp.SMTP) liberr.Error {
|
func (s *sender) SendClose(ctx context.Context, cli libsmtp.SMTP) liberr.Error {
|
||||||
defer func() {
|
defer func() {
|
||||||
_ = s.Close()
|
_ = s.Close()
|
||||||
}()
|
}()
|
||||||
@@ -234,14 +237,16 @@ func (s *sender) SendClose(ctx context.Context, cli smtp.SMTP) liberr.Error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sender) Send(ctx context.Context, cli smtp.SMTP) liberr.Error {
|
func (s *sender) Send(ctx context.Context, cli libsmtp.SMTP) liberr.Error {
|
||||||
if e := cli.Check(ctx); e != nil {
|
if e := cli.Check(ctx); e != nil {
|
||||||
return ErrorSmtpClient.ErrorParent(e)
|
return ErrorSmtpClient.ErrorParent(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(s.from) < 4 {
|
if len(s.from) < _MinSizeAddr {
|
||||||
|
//nolint #goerr113
|
||||||
return ErrorParamsEmpty.ErrorParent(fmt.Errorf("parameters 'from' is not valid"))
|
return ErrorParamsEmpty.ErrorParent(fmt.Errorf("parameters 'from' is not valid"))
|
||||||
} else if len(s.rcpt) < 1 || len(s.rcpt[0]) < 4 {
|
} else if len(s.rcpt) < 1 || len(s.rcpt[0]) < _MinSizeAddr {
|
||||||
|
//nolint #goerr113
|
||||||
return ErrorParamsEmpty.ErrorParent(fmt.Errorf("parameters 'receipient' is not valid"))
|
return ErrorParamsEmpty.ErrorParent(fmt.Errorf("parameters 'receipient' is not valid"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,83 +0,0 @@
|
|||||||
/*
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (c) 2020 Nicolas JUHEL
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package mail
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/base64"
|
|
||||||
"mime/quotedprintable"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// base64Encode base64 encodes the provided text with line wrapping
|
|
||||||
func base64Encode(text []byte) []byte {
|
|
||||||
// create buffer
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
|
|
||||||
// create base64 encoder that linewraps
|
|
||||||
encoder := base64.NewEncoder(base64.StdEncoding, &base64LineWrap{writer: buf})
|
|
||||||
|
|
||||||
// write the encoded text to buf
|
|
||||||
/* #nosec */
|
|
||||||
//nolint #nosec
|
|
||||||
_, _ = encoder.Write(text)
|
|
||||||
_ = encoder.Close()
|
|
||||||
|
|
||||||
return buf.Bytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
// qpEncode uses the quoted-printable encoding to encode the provided text
|
|
||||||
func qpEncode(text []byte) []byte {
|
|
||||||
// create buffer
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
|
|
||||||
encoder := quotedprintable.NewWriter(buf)
|
|
||||||
|
|
||||||
/* #nosec */
|
|
||||||
//nolint #nosec
|
|
||||||
_, _ = encoder.Write(text)
|
|
||||||
_ = encoder.Close()
|
|
||||||
|
|
||||||
return buf.Bytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
func encodeHeader(text string, charset string, usedChars int) string {
|
|
||||||
// create buffer
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
|
|
||||||
// encode
|
|
||||||
encoder := newEncoder(buf, charset, usedChars)
|
|
||||||
/* #nosec */
|
|
||||||
//nolint #nosec
|
|
||||||
_, _ = encoder.encode([]byte(text))
|
|
||||||
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func escapeQuotes(s string) string {
|
|
||||||
quoteEscaper := strings.NewReplacer("\\", "\\\\", `"`, "\\\"")
|
|
||||||
return quoteEscaper.Replace(s)
|
|
||||||
}
|
|
@@ -28,10 +28,10 @@ package mailer
|
|||||||
import "github.com/matcornic/hermes/v2"
|
import "github.com/matcornic/hermes/v2"
|
||||||
|
|
||||||
type email struct {
|
type email struct {
|
||||||
t Themes
|
|
||||||
d TextDirection
|
|
||||||
p hermes.Product
|
p hermes.Product
|
||||||
b *hermes.Body
|
b *hermes.Body
|
||||||
|
t Themes
|
||||||
|
d TextDirection
|
||||||
c bool
|
c bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -33,27 +33,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (e *email) GenerateHTML() (*bytes.Buffer, liberr.Error) {
|
func (e *email) GenerateHTML() (*bytes.Buffer, liberr.Error) {
|
||||||
var buf = bytes.NewBuffer(make([]byte, 0))
|
return e.generated(e.genHtml)
|
||||||
|
|
||||||
h := hermes.Hermes{
|
|
||||||
Theme: e.t.getHermes(),
|
|
||||||
TextDirection: e.d.getDirection(),
|
|
||||||
Product: e.p,
|
|
||||||
DisableCSSInlining: e.c,
|
|
||||||
}
|
|
||||||
|
|
||||||
if p, e := h.GenerateHTML(hermes.Email{
|
|
||||||
Body: *e.b,
|
|
||||||
}); e != nil {
|
|
||||||
return nil, ErrorMailerHtml.ErrorParent(e)
|
|
||||||
} else {
|
|
||||||
buf.WriteString(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *email) GeneratePlainText() (*bytes.Buffer, liberr.Error) {
|
func (e *email) GeneratePlainText() (*bytes.Buffer, liberr.Error) {
|
||||||
|
return e.generated(e.genText)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e email) generated(f func(h hermes.Hermes, m hermes.Email) (string, error)) (*bytes.Buffer, liberr.Error) {
|
||||||
var buf = bytes.NewBuffer(make([]byte, 0))
|
var buf = bytes.NewBuffer(make([]byte, 0))
|
||||||
|
|
||||||
h := hermes.Hermes{
|
h := hermes.Hermes{
|
||||||
@@ -63,7 +50,7 @@ func (e *email) GeneratePlainText() (*bytes.Buffer, liberr.Error) {
|
|||||||
DisableCSSInlining: e.c,
|
DisableCSSInlining: e.c,
|
||||||
}
|
}
|
||||||
|
|
||||||
if p, e := h.GeneratePlainText(hermes.Email{
|
if p, e := f(h, hermes.Email{
|
||||||
Body: *e.b,
|
Body: *e.b,
|
||||||
}); e != nil {
|
}); e != nil {
|
||||||
return nil, ErrorMailerText.ErrorParent(e)
|
return nil, ErrorMailerText.ErrorParent(e)
|
||||||
@@ -73,3 +60,11 @@ func (e *email) GeneratePlainText() (*bytes.Buffer, liberr.Error) {
|
|||||||
|
|
||||||
return buf, nil
|
return buf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *email) genText(h hermes.Hermes, m hermes.Email) (string, error) {
|
||||||
|
return h.GeneratePlainText(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *email) genHtml(h hermes.Hermes, m hermes.Email) (string, error) {
|
||||||
|
return h.GenerateHTML(m)
|
||||||
|
}
|
||||||
|
@@ -66,6 +66,7 @@ func (o NutsDBOptions) GetNutsDBOptions(dataDir string) nutsdb.Options {
|
|||||||
} else {
|
} else {
|
||||||
d.Dir = dataDir
|
d.Dir = dataDir
|
||||||
|
|
||||||
|
//nolint #exhaustive
|
||||||
switch o.RWMode {
|
switch o.RWMode {
|
||||||
case nutsdb.MMap:
|
case nutsdb.MMap:
|
||||||
d.RWMode = nutsdb.MMap
|
d.RWMode = nutsdb.MMap
|
||||||
@@ -73,6 +74,7 @@ func (o NutsDBOptions) GetNutsDBOptions(dataDir string) nutsdb.Options {
|
|||||||
d.RWMode = nutsdb.FileIO
|
d.RWMode = nutsdb.FileIO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint #exhaustive
|
||||||
switch o.StartFileLoadingMode {
|
switch o.StartFileLoadingMode {
|
||||||
case nutsdb.MMap:
|
case nutsdb.MMap:
|
||||||
d.StartFileLoadingMode = nutsdb.MMap
|
d.StartFileLoadingMode = nutsdb.MMap
|
||||||
@@ -81,6 +83,7 @@ func (o NutsDBOptions) GetNutsDBOptions(dataDir string) nutsdb.Options {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint #exhaustive
|
||||||
switch o.EntryIdxMode {
|
switch o.EntryIdxMode {
|
||||||
case nutsdb.HintKeyAndRAMIdxMode:
|
case nutsdb.HintKeyAndRAMIdxMode:
|
||||||
d.EntryIdxMode = nutsdb.HintKeyAndRAMIdxMode
|
d.EntryIdxMode = nutsdb.HintKeyAndRAMIdxMode
|
||||||
|
@@ -104,7 +104,7 @@ func (s *snap) Save(opt Options, writer io.Writer) liberr.Error {
|
|||||||
_ = t.Close()
|
_ = t.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if _, e = archive.CreateArchive(archive.ArchiveTypeTarGzip, t, s.path); e != nil {
|
if _, e = archive.CreateArchive(archive.TypeTarGzip, t, s.path); e != nil {
|
||||||
return ErrorFolderArchive.Error(e)
|
return ErrorFolderArchive.Error(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -29,12 +29,30 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
const EMPTY_GROUP = "<nil>"
|
const EmptyHandlerGroup = "<nil>"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
defaultRouters = NewRouterList()
|
defaultRouters = NewRouterList(DefaultGinInit)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func DefaultGinInit() *gin.Engine {
|
||||||
|
engine := gin.New()
|
||||||
|
engine.Use(gin.Logger(), gin.Recovery())
|
||||||
|
|
||||||
|
return engine
|
||||||
|
}
|
||||||
|
|
||||||
|
func DefaultGinWithTrustyProxy(trustyProxy []string) *gin.Engine {
|
||||||
|
engine := gin.New()
|
||||||
|
engine.Use(gin.Logger(), gin.Recovery())
|
||||||
|
|
||||||
|
if len(trustyProxy) > 0 {
|
||||||
|
engine.TrustedProxies = trustyProxy
|
||||||
|
}
|
||||||
|
|
||||||
|
return engine
|
||||||
|
}
|
||||||
|
|
||||||
type routerItem struct {
|
type routerItem struct {
|
||||||
method string
|
method string
|
||||||
relative string
|
relative string
|
||||||
@@ -42,6 +60,7 @@ type routerItem struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type routerList struct {
|
type routerList struct {
|
||||||
|
init func() *gin.Engine
|
||||||
list map[string][]routerItem
|
list map[string][]routerItem
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,6 +71,7 @@ type RouterList interface {
|
|||||||
Register(method string, relativePath string, router ...gin.HandlerFunc)
|
Register(method string, relativePath string, router ...gin.HandlerFunc)
|
||||||
RegisterInGroup(group, method string, relativePath string, router ...gin.HandlerFunc)
|
RegisterInGroup(group, method string, relativePath string, router ...gin.HandlerFunc)
|
||||||
Handler(engine *gin.Engine)
|
Handler(engine *gin.Engine)
|
||||||
|
Engine() *gin.Engine
|
||||||
}
|
}
|
||||||
|
|
||||||
func RoutersRegister(method string, relativePath string, router ...gin.HandlerFunc) {
|
func RoutersRegister(method string, relativePath string, router ...gin.HandlerFunc) {
|
||||||
@@ -66,15 +86,16 @@ func RoutersHandler(engine *gin.Engine) {
|
|||||||
defaultRouters.Handler(engine)
|
defaultRouters.Handler(engine)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRouterList() RouterList {
|
func NewRouterList(initGin func() *gin.Engine) RouterList {
|
||||||
return &routerList{
|
return &routerList{
|
||||||
|
init: initGin,
|
||||||
list: make(map[string][]routerItem),
|
list: make(map[string][]routerItem),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l routerList) Handler(engine *gin.Engine) {
|
func (l routerList) Handler(engine *gin.Engine) {
|
||||||
for grpRoute, grpList := range l.list {
|
for grpRoute, grpList := range l.list {
|
||||||
if grpRoute == EMPTY_GROUP {
|
if grpRoute == EmptyHandlerGroup {
|
||||||
for _, r := range grpList {
|
for _, r := range grpList {
|
||||||
engine.Handle(r.method, r.relative, r.router...)
|
engine.Handle(r.method, r.relative, r.router...)
|
||||||
}
|
}
|
||||||
@@ -89,7 +110,7 @@ func (l routerList) Handler(engine *gin.Engine) {
|
|||||||
|
|
||||||
func (l *routerList) RegisterInGroup(group, method string, relativePath string, router ...gin.HandlerFunc) {
|
func (l *routerList) RegisterInGroup(group, method string, relativePath string, router ...gin.HandlerFunc) {
|
||||||
if group == "" {
|
if group == "" {
|
||||||
group = EMPTY_GROUP
|
group = EmptyHandlerGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := l.list[group]; !ok {
|
if _, ok := l.list[group]; !ok {
|
||||||
@@ -106,3 +127,11 @@ func (l *routerList) RegisterInGroup(group, method string, relativePath string,
|
|||||||
func (l *routerList) Register(method string, relativePath string, router ...gin.HandlerFunc) {
|
func (l *routerList) Register(method string, relativePath string, router ...gin.HandlerFunc) {
|
||||||
l.RegisterInGroup("", method, relativePath, router...)
|
l.RegisterInGroup("", method, relativePath, router...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l routerList) Engine() *gin.Engine {
|
||||||
|
if l.init != nil {
|
||||||
|
return l.init()
|
||||||
|
} else {
|
||||||
|
return DefaultGinInit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -44,14 +44,13 @@ func SetGinHandler(fct func(c *gin.Context)) gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Handler(routerList RouterList) http.Handler {
|
func Handler(routerList RouterList) http.Handler {
|
||||||
engine := gin.New()
|
e := routerList.Engine()
|
||||||
engine.Use(gin.Logger(), gin.Recovery())
|
|
||||||
|
|
||||||
if routerList == nil {
|
if routerList == nil {
|
||||||
RoutersHandler(engine)
|
RoutersHandler(e)
|
||||||
} else {
|
} else {
|
||||||
routerList.Handler(engine)
|
routerList.Handler(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
return engine
|
return e
|
||||||
}
|
}
|
||||||
|
11
smtp/dial.go
11
smtp/dial.go
@@ -70,17 +70,6 @@ func (s *smtpClient) dial(ctx context.Context, addr string) (con net.Conn, err l
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *smtpClient) dialStarttls(ctx context.Context, addr string, tlsConfig *tls.Config) (con net.Conn, err liberr.Error) {
|
|
||||||
defer func() {
|
|
||||||
if err != nil && con != nil {
|
|
||||||
_ = con.Close()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
con, err = s.dial(ctx, addr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *smtpClient) client(ctx context.Context, addr string, tlsConfig *tls.Config) (cli *smtp.Client, con net.Conn, err liberr.Error) {
|
func (s *smtpClient) client(ctx context.Context, addr string, tlsConfig *tls.Config) (cli *smtp.Client, con net.Conn, err liberr.Error) {
|
||||||
var e error
|
var e error
|
||||||
|
|
||||||
|
@@ -120,7 +120,7 @@ func (s *smtpClient) Client(ctx context.Context) (*smtp.Client, errors.Error) {
|
|||||||
return s.cli, nil
|
return s.cli, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateLine checks to see if a line has CR or LF as per RFC 5321
|
// validateLine checks to see if a line has CR or LF as per RFC 5321.
|
||||||
func (s smtpClient) validateLine(line string) errors.Error {
|
func (s smtpClient) validateLine(line string) errors.Error {
|
||||||
if strings.ContainsAny(line, "\n\r") {
|
if strings.ContainsAny(line, "\n\r") {
|
||||||
return ErrorSMTPLineCRLF.Error(nil)
|
return ErrorSMTPLineCRLF.Error(nil)
|
||||||
|
@@ -29,10 +29,9 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/nabbar/golib/version"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/nabbar/golib/router"
|
librtr "github.com/nabbar/golib/router"
|
||||||
|
libver "github.com/nabbar/golib/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
const statusOK = "OK"
|
const statusOK = "OK"
|
||||||
@@ -82,8 +81,8 @@ type RouteStatus interface {
|
|||||||
HttpStatusCode(codeOk, codeKO, codeWarning int)
|
HttpStatusCode(codeOk, codeKO, codeWarning int)
|
||||||
|
|
||||||
Get(c *gin.Context)
|
Get(c *gin.Context)
|
||||||
Register(prefix string, register router.RegisterRouter)
|
Register(prefix string, register librtr.RegisterRouter)
|
||||||
RegisterGroup(group, prefix string, register router.RegisterRouterInGroup)
|
RegisterGroup(group, prefix string, register librtr.RegisterRouterInGroup)
|
||||||
|
|
||||||
ComponentNew(key string, cpt Component)
|
ComponentNew(key string, cpt Component)
|
||||||
ComponentDel(key string)
|
ComponentDel(key string)
|
||||||
@@ -102,10 +101,10 @@ func New(Name string, Release string, Hash string, msgOk string, msgKo string, m
|
|||||||
cKO: http.StatusServiceUnavailable,
|
cKO: http.StatusServiceUnavailable,
|
||||||
mWM: msgWarm,
|
mWM: msgWarm,
|
||||||
cWM: http.StatusOK,
|
cWM: http.StatusOK,
|
||||||
c: make(map[string]*atomic.Value, 0),
|
c: make(map[string]*atomic.Value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewVersion(version version.Version, msgOk string, msgKO string, msgWarm string) RouteStatus {
|
func NewVersion(version libver.Version, msgOk string, msgKO string, msgWarm string) RouteStatus {
|
||||||
return New(version.GetPackage(), version.GetRelease(), version.GetBuild(), msgOk, msgKO, msgWarm)
|
return New(version.GetPackage(), version.GetRelease(), version.GetBuild(), msgOk, msgKO, msgWarm)
|
||||||
}
|
}
|
||||||
|
@@ -31,12 +31,11 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
liberr "github.com/nabbar/golib/errors"
|
liberr "github.com/nabbar/golib/errors"
|
||||||
liblog "github.com/nabbar/golib/logger"
|
liblog "github.com/nabbar/golib/logger"
|
||||||
|
librtr "github.com/nabbar/golib/router"
|
||||||
"github.com/gin-gonic/gin"
|
libsem "github.com/nabbar/golib/semaphore"
|
||||||
"github.com/nabbar/golib/router"
|
|
||||||
"github.com/nabbar/golib/semaphore"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type rtrStatus struct {
|
type rtrStatus struct {
|
||||||
@@ -74,7 +73,7 @@ func (r *rtrStatus) cleanPrefix(prefix string) string {
|
|||||||
return path.Clean(strings.TrimRight(path.Join("/", prefix), "/"))
|
return path.Clean(strings.TrimRight(path.Join("/", prefix), "/"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *rtrStatus) Register(prefix string, register router.RegisterRouter) {
|
func (r *rtrStatus) Register(prefix string, register librtr.RegisterRouter) {
|
||||||
prefix = r.cleanPrefix(prefix)
|
prefix = r.cleanPrefix(prefix)
|
||||||
|
|
||||||
var m = r.m
|
var m = r.m
|
||||||
@@ -86,7 +85,7 @@ func (r *rtrStatus) Register(prefix string, register router.RegisterRouter) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *rtrStatus) RegisterGroup(group, prefix string, register router.RegisterRouterInGroup) {
|
func (r *rtrStatus) RegisterGroup(group, prefix string, register librtr.RegisterRouterInGroup) {
|
||||||
prefix = r.cleanPrefix(prefix)
|
prefix = r.cleanPrefix(prefix)
|
||||||
|
|
||||||
var m = r.m
|
var m = r.m
|
||||||
@@ -107,7 +106,7 @@ func (r *rtrStatus) Get(x *gin.Context) {
|
|||||||
key string
|
key string
|
||||||
err liberr.Error
|
err liberr.Error
|
||||||
rsp *Response
|
rsp *Response
|
||||||
sem semaphore.Sem
|
sem libsem.Sem
|
||||||
)
|
)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -130,7 +129,7 @@ func (r *rtrStatus) Get(x *gin.Context) {
|
|||||||
Components: make([]CptResponse, 0),
|
Components: make([]CptResponse, 0),
|
||||||
}
|
}
|
||||||
|
|
||||||
sem = semaphore.NewSemaphoreWithContext(x, 0)
|
sem = libsem.NewSemaphoreWithContext(x, 0)
|
||||||
|
|
||||||
for key, atm = range r.c {
|
for key, atm = range r.c {
|
||||||
if atm == nil {
|
if atm == nil {
|
||||||
@@ -182,7 +181,7 @@ func (r *rtrStatus) Get(x *gin.Context) {
|
|||||||
|
|
||||||
func (r *rtrStatus) ComponentNew(key string, cpt Component) {
|
func (r *rtrStatus) ComponentNew(key string, cpt Component) {
|
||||||
if len(r.c) < 1 {
|
if len(r.c) < 1 {
|
||||||
r.c = make(map[string]*atomic.Value, 0)
|
r.c = make(map[string]*atomic.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := r.c[key]; !ok {
|
if _, ok := r.c[key]; !ok {
|
||||||
|
@@ -75,6 +75,8 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint #gosec
|
||||||
|
/* #nosec */
|
||||||
if file, err := os.OpenFile(LoggerFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666); err != nil {
|
if file, err := os.OpenFile(LoggerFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
} else {
|
} else {
|
||||||
|
Reference in New Issue
Block a user