first commit
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
.idea
|
||||
build
|
||||
.env
|
||||
4
.gitlab-ci.yml
Normal file
4
.gitlab-ci.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
include:
|
||||
- project: 'astra/microservice-ci'
|
||||
ref: main
|
||||
file: '/templates/microservice.yaml'
|
||||
24
Dockerfile
Normal file
24
Dockerfile
Normal file
@@ -0,0 +1,24 @@
|
||||
FROM kandrusyak/go-build as build
|
||||
LABEL authors="andrusyakka@dopcore.com"
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
ENV CGO_ENABLED 1
|
||||
|
||||
COPY go.mod ./
|
||||
|
||||
RUN go mod download
|
||||
|
||||
COPY . ./
|
||||
|
||||
RUN go build -o ./app
|
||||
|
||||
FROM alpine:edge
|
||||
|
||||
WORKDIR /
|
||||
|
||||
COPY --from=build /app /app
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
CMD ["/app/app"]
|
||||
41
config/config.go
Normal file
41
config/config.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
type ServerConfig struct {
|
||||
Port string
|
||||
ConnectionString string
|
||||
}
|
||||
|
||||
type MSHosts struct {
|
||||
UsersHost string
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Server ServerConfig
|
||||
MSHosts MSHosts
|
||||
}
|
||||
|
||||
func New() *Config {
|
||||
return &Config{
|
||||
Server: ServerConfig{
|
||||
Port: getEnv("PORT", "8080"),
|
||||
ConnectionString: getEnv("CONNECTION_STRING", "test.db"),
|
||||
},
|
||||
MSHosts: MSHosts{
|
||||
UsersHost: getEnv("ASTRA-USERS", "http://localhost:8082"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func getEnv(key string, defaultVal string) string {
|
||||
if value, exists := os.LookupEnv(key); exists {
|
||||
return value
|
||||
}
|
||||
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
var Env = New()
|
||||
23
deploy/.helmignore
Normal file
23
deploy/.helmignore
Normal file
@@ -0,0 +1,23 @@
|
||||
# Patterns to ignore when building packages.
|
||||
# This supports shell glob matching, relative path matching, and
|
||||
# negation (prefixed with !). Only one pattern per line.
|
||||
.DS_Store
|
||||
# Common VCS dirs
|
||||
.git/
|
||||
.gitignore
|
||||
.bzr/
|
||||
.bzrignore
|
||||
.hg/
|
||||
.hgignore
|
||||
.svn/
|
||||
# Common backup files
|
||||
*.swp
|
||||
*.bak
|
||||
*.tmp
|
||||
*.orig
|
||||
*~
|
||||
# Various IDEs
|
||||
.project
|
||||
.idea/
|
||||
*.tmproj
|
||||
.vscode/
|
||||
24
deploy/Chart.yaml
Normal file
24
deploy/Chart.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
apiVersion: v2
|
||||
name: astra-users
|
||||
appVersion: latest
|
||||
description: A Helm chart to deploy app - astra
|
||||
|
||||
# A chart can be either an 'application' or a 'library' chart.
|
||||
#
|
||||
# Application charts are a collection of templates that can be packaged into versioned archives
|
||||
# to be deployed.
|
||||
#
|
||||
# Library charts provide useful utilities or functions for the chart developer. They're included as
|
||||
# a dependency of application charts to inject those utilities and functions into the rendering
|
||||
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
|
||||
type: application
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.1.0
|
||||
|
||||
engine: gotpl
|
||||
|
||||
maintainers:
|
||||
- name: DOP
|
||||
1
deploy/templates/NOTES.txt
Normal file
1
deploy/templates/NOTES.txt
Normal file
@@ -0,0 +1 @@
|
||||
192.168.1.112:8888
|
||||
62
deploy/templates/_helpers.tpl
Normal file
62
deploy/templates/_helpers.tpl
Normal file
@@ -0,0 +1,62 @@
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "astra-frontend.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
If release name contains chart name it will be used as a full name.
|
||||
*/}}
|
||||
{{- define "astra-frontend.fullname" -}}
|
||||
{{- if .Values.fullnameOverride }}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||
{{- if contains $name .Release.Name }}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "astra-frontend.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "astra-frontend.labels" -}}
|
||||
helm.sh/chart: {{ include "astra-frontend.chart" . }}
|
||||
{{ include "astra-frontend.selectorLabels" . }}
|
||||
{{- if .Chart.AppVersion }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "astra-frontend.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "astra-frontend.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "astra-frontend.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.create }}
|
||||
{{- default (include "astra-frontend.fullname" .) .Values.serviceAccount.name }}
|
||||
{{- else }}
|
||||
{{- default "default" .Values.serviceAccount.name }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
39
deploy/templates/deployment.yaml
Normal file
39
deploy/templates/deployment.yaml
Normal file
@@ -0,0 +1,39 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ .Values.app.fullName }}
|
||||
spec:
|
||||
replicas: {{ .Values.replicas }}
|
||||
revisionHistoryLimit: 10
|
||||
selector:
|
||||
matchLabels:
|
||||
app: {{ .Values.app.fullName }}
|
||||
strategy:
|
||||
rollingUpdate:
|
||||
maxSurge: 25%
|
||||
maxUnavailable: 25%
|
||||
type: RollingUpdate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{ .Values.app.fullName }}
|
||||
spec:
|
||||
imagePullSecrets:
|
||||
- name: {{ .Values.images.pullSecret }}
|
||||
containers:
|
||||
- name: {{ .Values.app.fullName }}
|
||||
env:
|
||||
- name: TZ
|
||||
value: Europe/Moscow
|
||||
- name: PORT
|
||||
value: {{ .Values.app.server.port | quote }}
|
||||
- name: CONNECTION_STRING
|
||||
value: /app/test.db
|
||||
{{- .Values.envs | toYaml | nindent 12 }}
|
||||
|
||||
image: {{ .Values.app.image }}:{{ .Chart.AppVersion }}
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: {{ .Values.app.server.port }}
|
||||
protocol: TCP
|
||||
28
deploy/templates/hpa.yaml
Normal file
28
deploy/templates/hpa.yaml
Normal file
@@ -0,0 +1,28 @@
|
||||
{{- if .Values.autoscaling.enabled }}
|
||||
apiVersion: autoscaling/v2beta1
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: {{ include ".Values.app.fullName" . }}
|
||||
labels:
|
||||
app: {{ include ".Values.app.fullName" . }}
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: {{ include ".Values.app.fullName" . }}
|
||||
minReplicas: {{ .Values.autoscaling.minReplicas }}
|
||||
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
|
||||
metrics:
|
||||
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||
{{- end }}
|
||||
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
||||
- type: Resource
|
||||
resource:
|
||||
name: memory
|
||||
targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
61
deploy/templates/ingress.yaml
Normal file
61
deploy/templates/ingress.yaml
Normal file
@@ -0,0 +1,61 @@
|
||||
{{- if .Values.ingress.enabled -}}
|
||||
{{- $fullName := include ".Values.app.fullName" . -}}
|
||||
{{- $svcPort := .Values.app.server.port -}}
|
||||
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
|
||||
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
|
||||
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
{{- else -}}
|
||||
apiVersion: extensions/v1beta1
|
||||
{{- end }}
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ $fullName }}
|
||||
labels:
|
||||
app: {{ $fullName }}
|
||||
{{- with .Values.ingress.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
|
||||
ingressClassName: {{ .Values.ingress.className }}
|
||||
{{- end }}
|
||||
{{- if .Values.ingress.tls }}
|
||||
tls:
|
||||
{{- range .Values.ingress.tls }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
secretName: {{ .secretName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- range .Values.ingress.hosts }}
|
||||
- host: {{ .host | quote }}
|
||||
http:
|
||||
paths:
|
||||
{{- range .paths }}
|
||||
- path: {{ .path }}
|
||||
{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
|
||||
pathType: {{ .pathType }}
|
||||
{{- end }}
|
||||
backend:
|
||||
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
service:
|
||||
name: {{ $fullName }}
|
||||
port:
|
||||
number: {{ $svcPort }}
|
||||
{{- else }}
|
||||
serviceName: {{ $fullName }}
|
||||
servicePort: {{ $svcPort }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
16
deploy/templates/service.yaml
Normal file
16
deploy/templates/service.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ .Values.app.fullName }}
|
||||
namespace: default
|
||||
spec:
|
||||
ports:
|
||||
- port: {{ .Values.app.server.port }}
|
||||
protocol: TCP
|
||||
targetPort: {{ .Values.app.server.port }}
|
||||
selector:
|
||||
app: {{ .Values.app.fullName }}
|
||||
sessionAffinity: None
|
||||
type: ClusterIP
|
||||
status:
|
||||
loadBalancer: {}
|
||||
16
deploy/values.template.yaml
Normal file
16
deploy/values.template.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
app:
|
||||
fullName: ${CI_PROJECT_TITLE}
|
||||
image: docker-registry.dopcore.com/${CI_PROJECT_PATH}
|
||||
server:
|
||||
port: ${SERVICE_PORT}
|
||||
|
||||
replicas: ${SERVICE_REPLICAS}
|
||||
|
||||
images:
|
||||
pullSecret: regcred
|
||||
|
||||
ingress:
|
||||
enabled: false
|
||||
|
||||
autoscaling:
|
||||
enabled: false
|
||||
23
go.mod
Normal file
23
go.mod
Normal file
@@ -0,0 +1,23 @@
|
||||
module astra-events
|
||||
|
||||
go 1.21rc1
|
||||
|
||||
require (
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/labstack/echo/v4 v4.10.2 // indirect
|
||||
github.com/labstack/gommon v0.4.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.17 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||
golang.org/x/crypto v0.6.0 // indirect
|
||||
golang.org/x/net v0.7.0 // indirect
|
||||
golang.org/x/sys v0.5.0 // indirect
|
||||
golang.org/x/text v0.7.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
gorm.io/driver/sqlite v1.5.2 // indirect
|
||||
gorm.io/gorm v1.25.2 // indirect
|
||||
)
|
||||
51
go.sum
Normal file
51
go.sum
Normal file
@@ -0,0 +1,51 @@
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M=
|
||||
github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k=
|
||||
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
|
||||
github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
|
||||
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=
|
||||
github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/sqlite v1.5.2 h1:TpQ+/dqCY4uCigCFyrfnrJnrW9zjpelWVoEVNy5qJkc=
|
||||
gorm.io/driver/sqlite v1.5.2/go.mod h1:qxAuCol+2r6PannQDpOP1FP6ag3mKi4esLnB/jHed+4=
|
||||
gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||
gorm.io/gorm v1.25.2 h1:gs1o6Vsa+oVKG/a9ElL3XgyGfghFfkKA2SInQaCyMho=
|
||||
gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||
71
handler/event.go
Normal file
71
handler/event.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"astra-events/model"
|
||||
"astra-events/services"
|
||||
"github.com/labstack/echo/v4"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func (h *Handler) CreateEvent(c echo.Context) (err error) {
|
||||
newEvent := new(model.Event)
|
||||
event := new(model.CreateEvent)
|
||||
authorId, err := strconv.Atoi(c.Request().Header.Get("UserId"))
|
||||
|
||||
if err != nil {
|
||||
return c.NoContent(http.StatusUnauthorized)
|
||||
}
|
||||
|
||||
if err = c.Bind(event); err != nil {
|
||||
return c.NoContent(http.StatusBadRequest)
|
||||
}
|
||||
|
||||
// TODO: Add gorutine
|
||||
employee, err := services.GetUser(event.EmployeeId, c.Request().Header)
|
||||
if err != nil {
|
||||
return c.HTML(http.StatusBadGateway, err.Error())
|
||||
}
|
||||
author, err := services.GetUser(uint(authorId), c.Request().Header)
|
||||
if err != nil {
|
||||
return c.HTML(http.StatusBadGateway, err.Error())
|
||||
}
|
||||
|
||||
newEvent.Start = event.Start
|
||||
newEvent.End = event.End
|
||||
newEvent.AuthorId = uint(authorId)
|
||||
newEvent.EmployeeId = event.EmployeeId
|
||||
newEvent.MemberId = event.MemberId
|
||||
newEvent.MedicalCardId = event.MedicalCardId
|
||||
newEvent.Status = event.Status
|
||||
|
||||
h.DB.Begin()
|
||||
|
||||
tx := h.DB.Create(&newEvent)
|
||||
|
||||
if tx.RowsAffected == 0 {
|
||||
h.DB.Rollback()
|
||||
return c.NoContent(http.StatusBadGateway)
|
||||
}
|
||||
|
||||
eventsServices := []model.EventsServices{}
|
||||
|
||||
for _, service := range event.Services {
|
||||
eventsServices = append(eventsServices, model.EventsServices{EventId: newEvent.ID, ServiceId: service})
|
||||
}
|
||||
|
||||
tx = h.DB.Create(eventsServices)
|
||||
|
||||
if tx.RowsAffected == 0 {
|
||||
h.DB.Rollback()
|
||||
return c.NoContent(http.StatusBadGateway)
|
||||
}
|
||||
|
||||
h.DB.Commit()
|
||||
|
||||
newEvent.Services = event.Services
|
||||
newEvent.Author = *author
|
||||
newEvent.Employee = *employee
|
||||
|
||||
return c.JSON(http.StatusCreated, newEvent)
|
||||
}
|
||||
7
handler/handler.go
Normal file
7
handler/handler.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package handler
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
type Handler struct {
|
||||
DB *gorm.DB
|
||||
}
|
||||
46
main.go
Normal file
46
main.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"astra-events/config"
|
||||
"astra-events/handler"
|
||||
"astra-events/model"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/labstack/echo/v4/middleware"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
newLogger := logger.New(
|
||||
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
|
||||
logger.Config{
|
||||
SlowThreshold: time.Second, // Slow SQL threshold
|
||||
LogLevel: logger.Info, // Log level
|
||||
IgnoreRecordNotFoundError: true, // Ignore ErrRecordNotFound error for logger
|
||||
ParameterizedQueries: true, // Don't include params in the SQL log
|
||||
Colorful: false, // Disable color
|
||||
},
|
||||
)
|
||||
|
||||
db, err := gorm.Open(sqlite.Open(config.Env.Server.ConnectionString), &gorm.Config{
|
||||
Logger: newLogger,
|
||||
})
|
||||
if err != nil {
|
||||
panic("failed to connect database")
|
||||
}
|
||||
e := echo.New()
|
||||
|
||||
e.Use(middleware.Logger())
|
||||
|
||||
db.AutoMigrate(&model.Event{}, &model.EventsServices{})
|
||||
|
||||
var h = &handler.Handler{DB: db}
|
||||
|
||||
e.POST("/", h.CreateEvent)
|
||||
|
||||
e.Logger.Fatal(e.Start(":" + config.Env.Server.Port))
|
||||
}
|
||||
7
model/card.go
Normal file
7
model/card.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package model
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
type Card struct {
|
||||
gorm.Model
|
||||
}
|
||||
32
model/event.go
Normal file
32
model/event.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Event struct {
|
||||
gorm.Model
|
||||
Start time.Time `json:"start"`
|
||||
End time.Time `json:"end"`
|
||||
Author User `json:"author" gorm:"-"`
|
||||
AuthorId uint `json:"-"`
|
||||
Employee User `json:"employee" gorm:"-"`
|
||||
EmployeeId uint `json:"-"`
|
||||
Member PD `json:"member" gorm:"-"`
|
||||
MemberId uint `json:"-"`
|
||||
Status string `json:"status"`
|
||||
MedicalCard Card `json:"medicalCard" gorm:"-"`
|
||||
MedicalCardId uint `json:"-"`
|
||||
Services []uint `json:"services" gorm:"-"`
|
||||
}
|
||||
|
||||
type CreateEvent struct {
|
||||
Start time.Time `json:"start"`
|
||||
End time.Time `json:"end"`
|
||||
EmployeeId uint `json:"employee_id"`
|
||||
MemberId uint `json:"member_id"`
|
||||
Status string `json:"status"`
|
||||
MedicalCardId uint `json:"medical_card_id"`
|
||||
Services []uint `json:"services"`
|
||||
}
|
||||
9
model/events_services.go
Normal file
9
model/events_services.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package model
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
type EventsServices struct {
|
||||
gorm.Model
|
||||
EventId uint
|
||||
ServiceId uint
|
||||
}
|
||||
7
model/pd.go
Normal file
7
model/pd.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package model
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
type PD struct {
|
||||
gorm.Model
|
||||
}
|
||||
7
model/service.go
Normal file
7
model/service.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package model
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
type Service struct {
|
||||
gorm.Model
|
||||
}
|
||||
20
model/user.go
Normal file
20
model/user.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package model
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
type (
|
||||
User struct {
|
||||
gorm.Model
|
||||
UserName string `json:"userName" gorm:"unique"`
|
||||
Password string `json:"password,omitempty"`
|
||||
FirstName string `json:"firstName"`
|
||||
LastName string `json:"lastName"`
|
||||
}
|
||||
)
|
||||
|
||||
type APIUser struct {
|
||||
UserName string `json:"userName" gorm:"unique"`
|
||||
Password string `json:"password,omitempty"`
|
||||
FirstName string `json:"firstName"`
|
||||
LastName string `json:"lastName"`
|
||||
}
|
||||
105
pkg/api/apiCall.go
Normal file
105
pkg/api/apiCall.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func PostRequest(url string, model any, header http.Header) ([]byte, error) {
|
||||
uJson, err := json.Marshal(model)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client := http.Client{}
|
||||
req, err := http.NewRequest("POST", url, bytes.NewReader(uJson))
|
||||
req.Header = header
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := client.Do(req)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func GetRequest(url string, header http.Header, args ...string) ([]byte, error, *http.Response) {
|
||||
client := http.Client{}
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if len(args) > 0 {
|
||||
req.URL.RawQuery = args[0]
|
||||
}
|
||||
req.Header = header
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
resp, err := client.Do(req)
|
||||
|
||||
if err != nil {
|
||||
return nil, err, nil
|
||||
}
|
||||
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
|
||||
if err != nil {
|
||||
return nil, err, nil
|
||||
}
|
||||
|
||||
return data, nil, resp
|
||||
}
|
||||
|
||||
func PatchRequest(url string, model any, header http.Header) ([]byte, error) {
|
||||
uJson, err := json.Marshal(model)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client := http.Client{}
|
||||
req, err := http.NewRequest("PATCH", url, bytes.NewReader(uJson))
|
||||
req.Header = header
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := client.Do(req)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func DeleteRequest(url string, header http.Header) ([]byte, error) {
|
||||
client := http.Client{}
|
||||
req, err := http.NewRequest("DELETE", url, nil)
|
||||
req.Header = header
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
resp, err := client.Do(req)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
27
pkg/utils/query.go
Normal file
27
pkg/utils/query.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
)
|
||||
|
||||
func ApplySort(tx *gorm.DB, column string, isDesc bool) {
|
||||
tx.Order(clause.OrderByColumn{
|
||||
Column: clause.Column{Name: column},
|
||||
Desc: isDesc,
|
||||
})
|
||||
}
|
||||
|
||||
func ApplyFilters(tx *gorm.DB, column string, value string) {
|
||||
if column != "" && value != "" {
|
||||
tx.Where(column + " LIKE '%" + value + "%'")
|
||||
}
|
||||
}
|
||||
|
||||
func ApplyIdFilter(c echo.Context, tx *gorm.DB) {
|
||||
id := c.Param("id")
|
||||
if id != "" {
|
||||
tx.Where("id = ?", id)
|
||||
}
|
||||
}
|
||||
52
pkg/utils/url.go
Normal file
52
pkg/utils/url.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func GetQueryParam(query url.Values, key string, defaultVal string) string {
|
||||
data := query.Get(key)
|
||||
|
||||
if data == "" {
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
func GetPaginationParams(query url.Values) (int, int) {
|
||||
offset := GetQueryParam(query, "offset", "0")
|
||||
limit := GetQueryParam(query, "limit", "10")
|
||||
|
||||
limitInt, err := strconv.Atoi(limit)
|
||||
|
||||
if err != nil {
|
||||
limitInt = 10
|
||||
}
|
||||
|
||||
offsetInt, err := strconv.Atoi(offset)
|
||||
|
||||
if err != nil {
|
||||
offsetInt = 0
|
||||
}
|
||||
|
||||
return limitInt, offsetInt
|
||||
}
|
||||
|
||||
func GetFilterParams(query url.Values) (string, bool, string, string) {
|
||||
sort := GetQueryParam(query, "sort", "id:asc")
|
||||
filter := GetQueryParam(query, "filter", ":")
|
||||
|
||||
filters := strings.Split(filter, ":")
|
||||
sorts := strings.Split(sort, ":")
|
||||
|
||||
isDesc := false
|
||||
|
||||
if sorts[1] == "desc" {
|
||||
isDesc = true
|
||||
}
|
||||
|
||||
return sorts[0], isDesc, filters[0], filters[1]
|
||||
}
|
||||
33
services/users.go
Normal file
33
services/users.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"astra-events/config"
|
||||
"astra-events/model"
|
||||
"astra-events/pkg/api"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func GetUser(ID uint, header http.Header) (*model.User, error) {
|
||||
id := strconv.Itoa(int(ID))
|
||||
|
||||
data, err, _ := api.GetRequest(
|
||||
config.Env.MSHosts.UsersHost+"/"+id,
|
||||
header)
|
||||
|
||||
if err != nil {
|
||||
return nil, errors.New("Error Request to Users Service")
|
||||
}
|
||||
|
||||
u := new(model.User)
|
||||
|
||||
err = json.Unmarshal(data, &u)
|
||||
|
||||
if err != nil {
|
||||
return nil, errors.New("Bad Response from Users Service")
|
||||
}
|
||||
|
||||
return u, nil
|
||||
}
|
||||
Reference in New Issue
Block a user