mirror of
https://github.com/khorevaa/kubodin.git
synced 2025-01-17 18:44:40 +02:00
alfa version
This commit is contained in:
parent
f694075ba8
commit
3409afff64
8
.github/workflows/releaser.yaml
vendored
8
.github/workflows/releaser.yaml
vendored
@ -23,12 +23,9 @@ jobs:
|
||||
name: Docker Login
|
||||
if: success() && startsWith(github.ref, 'refs/tags/v')
|
||||
env:
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
||||
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
|
||||
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
|
||||
run: |
|
||||
echo "${DOCKER_PASSWORD}" | docker login --username "${DOCKER_USERNAME}" --password-stdin
|
||||
echo "${GITHUB_TOKEN}" | docker login ghcr.io --username $GITHUB_ACTOR --password-stdin
|
||||
echo "${GITHUB_TOKEN}" | docker login ghcr.io --username $GITHUB_ACTOR --password-stdin
|
||||
-
|
||||
name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v2
|
||||
@ -37,6 +34,7 @@ jobs:
|
||||
args: release --rm-dist
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
|
||||
-
|
||||
name: Clear
|
||||
if: always() && startsWith(github.ref, 'refs/tags/v')
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -2,7 +2,7 @@
|
||||
*.gz
|
||||
*.zip
|
||||
|
||||
|
||||
api/.sequence
|
||||
dist
|
||||
.idea
|
||||
*.logs
|
||||
|
@ -1,11 +1,15 @@
|
||||
project_name: app-template
|
||||
project_name: kubodin
|
||||
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
- GOPRIVATE=github.com/khorevaa/ras-client
|
||||
# - GOPROXY=https://goproxy.io
|
||||
before:
|
||||
hooks:
|
||||
- git config --global url."https://khorevaa:{{ .Env.ACCESS_TOKEN }}@github.com/khorevaa/".insteadOf "https://github.com/khorevaa/"
|
||||
- go mod tidy
|
||||
- go get -u github.com/swaggo/swag/cmd/swag
|
||||
- swag init --parseDependency -g ./main.go
|
||||
builds:
|
||||
- env:
|
||||
- CGO_ENABLED=0
|
||||
@ -32,25 +36,22 @@ changelog:
|
||||
- Merge branch
|
||||
dockers:
|
||||
- image_templates:
|
||||
- 'khorevaa/{{.ProjectName}}:{{ .Tag }}'
|
||||
- 'khorevaa/{{.ProjectName}}:v{{ .Major }}.{{ .Minor }}'
|
||||
- 'khorevaa/{{.ProjectName}}:latest'
|
||||
- 'ghcr.io/khorevaa/{{.ProjectName}}:{{ .Tag }}'
|
||||
- 'ghcr.io/khorevaa/{{.ProjectName}}:v{{ .Major }}.{{ .Minor }}'
|
||||
- 'ghcr.io/khorevaa/{{.ProjectName}}:latest'
|
||||
dockerfile: Dockerfile
|
||||
binaries:
|
||||
- app-template
|
||||
- kubodin
|
||||
build_flag_templates:
|
||||
- "--label=org.label-schema.schema-version=1.0"
|
||||
- "--label=org.label-schema.version={{.Version}}"
|
||||
- "--label=org.label-schema.name={{.ProjectName}}"
|
||||
- "--label=com.github.actions.name={{.ProjectName}}"
|
||||
- "--label=com.github.actions.description=Setup new app-template description"
|
||||
- "--label=com.github.actions.description=API server for Kubernetes & 1C.Enterprise"
|
||||
- "--label=com.github.actions.icon=terminal"
|
||||
- "--label=com.github.actions.color=blue"
|
||||
- "--label=repository=http://github.com/khorevaa/app-template"
|
||||
- "--label=homepage=http://github.com/khorevaa/app-template"
|
||||
- "--label=repository=http://github.com/khorevaa/kubodin"
|
||||
- "--label=homepage=http://github.com/khorevaa/kubodin"
|
||||
- "--label=maintainerAleksey Khorev khorevaa@gmail.com"
|
||||
archives:
|
||||
- name_template: '{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}'
|
||||
|
@ -1,3 +1,3 @@
|
||||
FROM scratch
|
||||
COPY app-template /
|
||||
ENTRYPOINT ["/app-template"]
|
||||
COPY kubodin /
|
||||
ENTRYPOINT ["/kubodin"]
|
91
api/admin.go
Normal file
91
api/admin.go
Normal file
@ -0,0 +1,91 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/khorevaa/kubodin/service"
|
||||
)
|
||||
|
||||
type agentApi struct {
|
||||
service service.Service
|
||||
}
|
||||
|
||||
func (a *agentApi) Routes(r fiber.Router) {
|
||||
|
||||
r.Get("/agent/version", withClient(a.Version))
|
||||
r.Get("/agent/admins", withClient(a.List))
|
||||
r.Post("/agent/admins", withClient(a.RegAgentAdmin))
|
||||
r.Delete("/agent/admins/:admin", withClient(a.UnregAgentAdmin))
|
||||
|
||||
}
|
||||
|
||||
// List получение списка администраторов агента на сервере 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary получение списка администраторов агента на сервере 1С Предприятие
|
||||
// @Description получение списка администраторов агента на сервере 1С Предприятие
|
||||
// @Tags admins,agent
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=serialize.UsersList}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/agent/admins [get]
|
||||
func (a *agentApi) List(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
|
||||
return NoAllowResponse(ctx)
|
||||
}
|
||||
|
||||
// Version получение версии агента на сервере 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary получение версии агента на сервере 1С Предприятие
|
||||
// @Description получение версии агента на сервере 1С Предприятие
|
||||
// @Tags agent
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=string}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/agent/version [get]
|
||||
func (a *agentApi) Version(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
|
||||
return NoAllowResponse(ctx)
|
||||
}
|
||||
|
||||
// RegAgentAdmin выполняет регистрацию нового адмнимистратор на агенте сервера 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary выполняет регистрацию нового адмнимистратор на агенте сервера 1С Предприятиеи
|
||||
// @Description выполняет регистрацию нового адмнимистратор на агенте сервера 1С Предприятие
|
||||
// @Tags admins,agent
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param req body serialize.UserInfo true "user info"
|
||||
// @Success 200 {object} Response{data=serialize.UserInfo}
|
||||
// @Failure 404 {object} Response
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/agent/admins [post]
|
||||
func (a *agentApi) RegAgentAdmin(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
|
||||
return NoAllowResponse(ctx)
|
||||
|
||||
}
|
||||
|
||||
// UnregAgentAdmin Удаление администратора агента на сервере 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary Удаление администратора агента на сервере 1С Предприятие
|
||||
// @Description Удаление администратора агента на сервере 1С Предприятие
|
||||
// @Tags admins,agent
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param admin path string true "admin name"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=string}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/agent/admins/{admin} [delete]
|
||||
func (a *agentApi) UnregAgentAdmin(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
|
||||
return NoAllowResponse(ctx)
|
||||
|
||||
}
|
140
api/app.go
Normal file
140
api/app.go
Normal file
@ -0,0 +1,140 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/khorevaa/kubodin/service"
|
||||
)
|
||||
|
||||
type AppApi struct {
|
||||
service service.Service
|
||||
}
|
||||
|
||||
func (a *AppApi) Routes(r fiber.Router) {
|
||||
|
||||
r.Get("/app", a.List)
|
||||
r.Post("/app", a.Create)
|
||||
|
||||
r.Get("/app/:app", a.Info)
|
||||
r.Post("/app/:app", a.Update)
|
||||
r.Delete("/app/:app", a.Delete)
|
||||
|
||||
router := r.Group("/app/:app")
|
||||
|
||||
parentApi := []route{
|
||||
&clusterApi{service: a.service},
|
||||
&infobasesApi{service: a.service},
|
||||
&sessionsApi{service: a.service},
|
||||
&connectionsApi{service: a.service},
|
||||
&managersApi{service: a.service},
|
||||
&servicesApi{service: a.service},
|
||||
&locksApi{service: a.service},
|
||||
&blockerApi{service: a.service},
|
||||
&processesApi{service: a.service},
|
||||
&licensesApi{service: a.service},
|
||||
&healthAppApi{service: a.service},
|
||||
&agentApi{service: a.service},
|
||||
}
|
||||
|
||||
for _, api := range parentApi {
|
||||
api.Routes(router)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// List Получение списка зарегистрированных серверов 1С.Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary Получение списка зарегистрированных серверов 1С.Предприятие
|
||||
// @Description Получение списка зарегистрированных серверов 1С.Предприятие
|
||||
// @Tags app
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} Response{data=[]models.AppServer}
|
||||
// @Failure 400 {object} Response
|
||||
// @Router /app [get]
|
||||
func (a *AppApi) List(ctx *fiber.Ctx) error {
|
||||
|
||||
apps, err := a.service.GetAppServers()
|
||||
|
||||
if err != nil {
|
||||
return ErrorResponse(ctx, err, "error get app list")
|
||||
}
|
||||
|
||||
return SuccessResponse(ctx, apps)
|
||||
}
|
||||
|
||||
// Info получение информации о зарегистрированном сервере 1С.Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary Получение информации о зарегистрированном сервере 1С.Предприятие
|
||||
// @Description Получение информации о зарегистрированном сервере 1С.Предприятие
|
||||
// @Tags app
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Success 200 {object} Response{data=models.AppServer}
|
||||
// @Failure 400 {object} Response
|
||||
// @Router /app/{app} [get]
|
||||
func (a *AppApi) Info(ctx *fiber.Ctx) error {
|
||||
|
||||
name := ctx.Params("app")
|
||||
|
||||
app, err := a.service.GetAppServer(name)
|
||||
|
||||
if err != nil {
|
||||
return ErrorResponse(ctx, err, "error get app info")
|
||||
}
|
||||
|
||||
return SuccessResponse(ctx, app)
|
||||
|
||||
}
|
||||
|
||||
// Update обновление информации о зарегистрированном сервере 1С.Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary Обновление информации о зарегистрированном сервере 1С.Предприятие
|
||||
// @Description Обновление информации о зарегистрированном сервере 1С.Предприятие
|
||||
// @Tags app
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param req body models.AppServer true "app info"
|
||||
// @Success 200 {object} Response{data=models.AppServer}
|
||||
// @Failure 400 {object} Response
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app} [post]
|
||||
func (a *AppApi) Update(ctx *fiber.Ctx) error {
|
||||
|
||||
return NoAllowResponse(ctx)
|
||||
|
||||
}
|
||||
|
||||
// Create выполняет регистрацию сервера 1С.Предприятие в приложении
|
||||
// Swagger-spec:
|
||||
// @Summary выполняет регистрацию сервера 1С.Предприятие в приложении
|
||||
// @Description выполняет регистрацию сервера 1С.Предприятие в приложении
|
||||
// @Tags app
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param req body models.AppServer true "app info"
|
||||
// @Success 200 {object} Response{data=models.AppServer}
|
||||
// @Failure 400 {object} Response
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app [post]
|
||||
func (a *AppApi) Create(ctx *fiber.Ctx) error {
|
||||
|
||||
return NoAllowResponse(ctx)
|
||||
}
|
||||
|
||||
// Delete выполняет отмену зарегистрирации сервера 1С.Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary Удаление информации о регистрации сервера приложений 1С.Предприятие
|
||||
// @Description Удаление информации о регистрации сервера приложений 1С.Предприятие
|
||||
// @Tags app
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Success 200 {object} Response
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app} [delete]
|
||||
func (a *AppApi) Delete(ctx *fiber.Ctx) error {
|
||||
|
||||
return NoAllowResponse(ctx)
|
||||
}
|
131
api/app_test.go
Normal file
131
api/app_test.go
Normal file
@ -0,0 +1,131 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/khorevaa/kubodin/models"
|
||||
"github.com/steinfletcher/apitest"
|
||||
jsonpath "github.com/steinfletcher/apitest-jsonpath"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type appSuite struct {
|
||||
baseSuite
|
||||
}
|
||||
|
||||
func TestAppTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(appSuite))
|
||||
}
|
||||
|
||||
func (s *appSuite) TestAppList() {
|
||||
|
||||
s.api().
|
||||
Post("/api/v1/app").
|
||||
JSON(&models.AppServer{
|
||||
Name: "test",
|
||||
Addr: "localhost",
|
||||
Port: "1545",
|
||||
}).
|
||||
Expect(s.T()).
|
||||
Assert(jsonpath.Equal(`$.message`, "success")).
|
||||
Status(http.StatusOK).End()
|
||||
|
||||
s.api().Report(apitest.SequenceDiagram()).
|
||||
Get("/api/v1/app").
|
||||
Expect(s.T()).
|
||||
Assert(jsonpath.Equal(`$.message`, "success")).
|
||||
Status(http.StatusOK).
|
||||
End()
|
||||
}
|
||||
|
||||
func (s *appSuite) TestAppReg() {
|
||||
s.api().
|
||||
Post("/api/v1/app").
|
||||
JSON(&models.AppServer{
|
||||
Name: "test",
|
||||
Addr: "localhost",
|
||||
Port: "1545",
|
||||
}).
|
||||
Expect(s.T()).
|
||||
Assert(jsonpath.Equal(`$.message`, "success")).
|
||||
Status(http.StatusOK).End()
|
||||
}
|
||||
|
||||
func (s *appSuite) TestAppUnreg() {
|
||||
s.api().
|
||||
Postf("/api/v1/app/%s", "test").
|
||||
JSON(&models.AppServer{
|
||||
Name: "test",
|
||||
Addr: "localhost",
|
||||
Port: "1546",
|
||||
}).
|
||||
Expect(s.T()).
|
||||
Assert(jsonpath.Equal(`$.message`, "success")).
|
||||
Status(http.StatusOK).
|
||||
End()
|
||||
|
||||
s.api().
|
||||
Deletef("/api/v1/app/%s", "test").
|
||||
Expect(s.T()).
|
||||
Assert(jsonpath.Equal(`$.message`, "success")).
|
||||
Status(http.StatusOK).End()
|
||||
|
||||
}
|
||||
|
||||
func (s *appSuite) TestHealthStatus() {
|
||||
s.api().
|
||||
Get("/api/v1/health").
|
||||
Expect(s.T()).
|
||||
Assert(jsonpath.Equal(`$.status`, true)).
|
||||
Status(http.StatusOK).
|
||||
End()
|
||||
}
|
||||
|
||||
func (s *appSuite) TestHealthReadinessStatus() {
|
||||
s.api().
|
||||
Postf("/api/v1/app/%s", "test").
|
||||
JSON(&models.AppServer{
|
||||
Name: "test",
|
||||
Addr: "localhost",
|
||||
Port: "1546",
|
||||
}).
|
||||
Expect(s.T()).
|
||||
Assert(jsonpath.Equal(`$.message`, "success")).
|
||||
Status(http.StatusOK).End()
|
||||
|
||||
s.api().
|
||||
Get("/api/v1/health/readiness").
|
||||
Expect(s.T()).
|
||||
Assert(jsonpath.Equal(`$.status`, true)).
|
||||
Status(http.StatusOK).
|
||||
End()
|
||||
|
||||
s.api().
|
||||
Deletef("/api/v1/app/%s", "test").
|
||||
Expect(s.T()).
|
||||
Assert(jsonpath.Equal(`$.message`, "success")).
|
||||
Status(http.StatusOK).End()
|
||||
|
||||
}
|
||||
|
||||
func (s *appSuite) TestHealthReadinessStatusBad() {
|
||||
|
||||
s.api().
|
||||
Postf("/api/v1/app/%s", "test").
|
||||
JSON(&models.AppServer{
|
||||
Name: "test",
|
||||
Addr: "localhost",
|
||||
Port: "1545",
|
||||
}).
|
||||
Expect(s.T()).
|
||||
Assert(jsonpath.Equal(`$.message`, "success")).
|
||||
Status(http.StatusOK).End()
|
||||
|
||||
s.api().
|
||||
Get("/api/v1/health/readiness").
|
||||
Expect(s.T()).
|
||||
Assert(jsonpath.Equal(`$.status`, false)).
|
||||
Status(http.StatusServiceUnavailable).
|
||||
End()
|
||||
|
||||
}
|
326
api/blocker.go
Normal file
326
api/blocker.go
Normal file
@ -0,0 +1,326 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/khorevaa/kubodin/service"
|
||||
)
|
||||
|
||||
type blockerApi struct {
|
||||
service service.Service
|
||||
}
|
||||
|
||||
func (a *blockerApi) Routes(r fiber.Router) {
|
||||
|
||||
r.Get("/block", withClient(a.GetBlock))
|
||||
r.Post("/block", withClient(a.PostBlock))
|
||||
|
||||
r.Get("/unblock", withClient(a.GetUnblock))
|
||||
r.Post("/unblock", withClient(a.PostUnblock))
|
||||
|
||||
}
|
||||
|
||||
// Block установка блокировки на информационную базу на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary Установка блокировки на информационную базу на кластере
|
||||
// @Description установка блокировки на информационную базу на кластере
|
||||
// @Tags blocker
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param infobase query string true "infobase uuid or name"
|
||||
// @Param sessions-deny query string true "session deny"
|
||||
// @Param message query string false "message to user"
|
||||
// @Param permission-code query string false "permission code"
|
||||
// @Param denied-parameter query string false "denied parameter"
|
||||
// @Param permission-code query string false "permission code"
|
||||
// @Param scheduled-jobs-deny query bool false "scheduled jobs deny"
|
||||
// @Param denied-from query string false "denied from time"
|
||||
// @Param denied-to query string false "denied to time"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=models.InfobaseUnblocker}
|
||||
// @Failure 400 {object} Response
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/clusters/{cluster}/block [get]
|
||||
func (a *blockerApi) GetBlock(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
|
||||
return NoAllowResponse(ctx)
|
||||
|
||||
}
|
||||
|
||||
// Block Установка блокировки конкретную на информационную базу на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary Установка блокировки на выбранную информационную базу на кластере
|
||||
// @Description Установка блокировки на выбранную информационную базу на кластере
|
||||
// @Tags blocker
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param infobase path string true "infobase uuid or name"
|
||||
// @Param sessions-deny query string true "session deny"
|
||||
// @Param message query string false "message to user"
|
||||
// @Param permission-code query string false "permission code"
|
||||
// @Param denied-parameter query string false "denied parameter"
|
||||
// @Param permission-code query string false "permission code"
|
||||
// @Param scheduled-jobs-deny query bool false "scheduled jobs deny"
|
||||
// @Param denied-from query string false "denied from time"
|
||||
// @Param denied-to query string false "denied to time"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=models.InfobaseUnblocker}
|
||||
// @Failure 400 {object} Response
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/clusters/{cluster}/infobases/{infobase}/block [get]
|
||||
func (a *blockerApi) GetBlockInfobase() {}
|
||||
|
||||
// Block Установка блокировки на произвольную информационную базу на сервер 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary Установка блокировки на произвольную информационную базу на сервер 1С Предприятие
|
||||
// @Description Установка блокировки на произвольную информационную базу на сервер 1С Предприятие
|
||||
// @Tags blocker
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param infobase-id query string true "infobase uuid or name"
|
||||
// @Param sessions-deny query string true "session deny"
|
||||
// @Param message query string false "message to user"
|
||||
// @Param permission-code query string false "permission code"
|
||||
// @Param denied-parameter query string false "denied parameter"
|
||||
// @Param permission-code query string false "permission code"
|
||||
// @Param scheduled-jobs-deny query bool false "scheduled jobs deny"
|
||||
// @Param denied-from query string false "denied from time" default("now")
|
||||
// @Param denied-to query string false "denied to time"
|
||||
// @Param cluster-id query string false "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=models.InfobaseUnblocker}
|
||||
// @Failure 400 {object} Response
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/block [get]
|
||||
func (a *blockerApi) GetlockApp() {}
|
||||
|
||||
// Block Установка блокировки конкретную на информационную базу на сервер 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary Установка блокировки конкретную на информационную базу на сервер 1С Предприятие
|
||||
// @Description Установка блокировки конкретную на информационную базу на сервер 1С Предприятие
|
||||
// @Tags blocker
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param infobase path string true "infobase uuid or name"
|
||||
// @Param sessions-deny query string true "session deny"
|
||||
// @Param message query string false "message to user"
|
||||
// @Param permission-code query string false "permission code"
|
||||
// @Param denied-parameter query string false "denied parameter"
|
||||
// @Param permission-code query string false "permission code"
|
||||
// @Param scheduled-jobs-deny query bool false "scheduled jobs deny"
|
||||
// @Param denied-from query string false "denied from time"
|
||||
// @Param denied-to query string false "denied to time"
|
||||
// @Param cluster-id query string false "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=models.InfobaseUnblocker}
|
||||
// @Failure 400 {object} Response
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/infobases/{infobase}/block [get]
|
||||
func (a *blockerApi) GetBlockAppInfobase() {}
|
||||
|
||||
// Block установка блокировки на информационную базу на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary Установка блокировки на информационную базу на кластере
|
||||
// @Description установка блокировки на информационную базу на кластере
|
||||
// @Tags blocker
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param body body models.InfobaseBlocker true "block info"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=models.InfobaseUnblocker}
|
||||
// @Failure 400 {object} Response
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/clusters/{cluster}/block [post]
|
||||
func (a *blockerApi) PostBlock(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
|
||||
return NoAllowResponse(ctx)
|
||||
|
||||
}
|
||||
|
||||
// Block установка блокировки на конкретную информационную базу на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary Установка блокировки на конкретную информационную базу на кластере
|
||||
// @Description установка блокировки на конкретную информационную базу на кластере
|
||||
// @Tags blocker
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param infobase path string true "infobase uuid or name"
|
||||
// @Param body body models.InfobaseBlocker true "block info"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=models.InfobaseUnblocker}
|
||||
// @Failure 400 {object} Response
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/clusters/{cluster}/infobases/{infobase}/block [post]
|
||||
func (a *blockerApi) PostBlockInfobase() {}
|
||||
|
||||
// Block Установка блокировки на произвольную информационную базу на сервер 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary Установка блокировки на произвольную информационную базу на сервер 1С Предприятие
|
||||
// @Description Установка блокировки на произвольную информационную базу на сервер 1С Предприятие
|
||||
// @Tags blocker
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param body body models.InfobaseBlocker true "block info"
|
||||
// @Param cluster-id query string false "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=models.InfobaseUnblocker}
|
||||
// @Failure 400 {object} Response
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/block [post]
|
||||
func (a *blockerApi) PostBlockApp() {}
|
||||
|
||||
// Block Установка блокировки конкретную на информационную базу на сервер 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary Установка блокировки конкретную на информационную базу на сервер 1С Предприятие
|
||||
// @Description Установка блокировки конкретную на информационную базу на сервер 1С Предприятие
|
||||
// @Tags blocker
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param infobase path string true "infobase uuid or name"
|
||||
// @Param body body models.InfobaseBlocker true "block info"
|
||||
// @Param cluster-id query string false "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=models.InfobaseUnblocker}
|
||||
// @Failure 400 {object} Response
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/infobases/{infobase}/block [post]
|
||||
func (a *blockerApi) PostBlockAppInfobase() {}
|
||||
|
||||
// GetUnblock Снятие блокировки на информационную базу на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary Снятие блокировки на информационную базу на кластере
|
||||
// @Description Снятие блокировки на информационную базу на кластере
|
||||
// @Tags blocker
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param infobase query string true "infobase uuid or name"
|
||||
// @Param sessions-deny query string true "session deny"
|
||||
// @Param denied-parameter query string false "denied parameter"
|
||||
// @Param permission-code query string false "permission code"
|
||||
// @Param scheduled-jobs-deny query bool false "scheduled jobs deny"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=serialize.InfobaseSummaryInfo}
|
||||
// @Failure 400 {object} Response
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/clusters/{cluster}/unblock [get]
|
||||
func (a *blockerApi) GetUnblock(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
return NoAllowResponse(ctx)
|
||||
}
|
||||
|
||||
// GetUnblock Снятие блокировки на информационную базу на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary Снятие блокировки на информационную базу на кластере
|
||||
// @Description Снятие блокировки на информационную базу на кластере
|
||||
// @Tags blocker
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param infobase query string true "infobase uuid or name"
|
||||
// @Param sessions-deny query string true "session deny"
|
||||
// @Param denied-parameter query string false "denied parameter"
|
||||
// @Param permission-code query string false "permission code"
|
||||
// @Param scheduled-jobs-deny query bool false "scheduled jobs deny"
|
||||
// @Param cluster-id query string false "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=serialize.InfobaseSummaryInfo}
|
||||
// @Failure 400 {object} Response
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/unblock [get]
|
||||
func (a *blockerApi) GetUnblockApp() {}
|
||||
|
||||
// PostUnblock Снимает блокировку на информационную базу на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary Снимает блокировку на информационную базу на кластере
|
||||
// @Description Снимает блокировку на информационную базу на кластере
|
||||
// @Tags blocker
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param body body models.InfobaseUnblocker true "unblock info"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=serialize.InfobaseSummaryInfo}
|
||||
// @Failure 400 {object} Response
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/clusters/{cluster}/unblock [post]
|
||||
func (a *blockerApi) PostUnblock(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
return NoAllowResponse(ctx)
|
||||
}
|
||||
|
||||
// PostUnblockApp Снимает блокировку на информационную базу на сервере 1С Прдприятие
|
||||
// Swagger-spec:
|
||||
// @Summary Снимает блокировку на информационную базу на сервере 1С Прдприятие
|
||||
// @Description Снимает блокировку на информационную базу на сервере 1С Прдприятие
|
||||
// @Tags blocker
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param body body models.InfobaseUnblocker true "unblock info"
|
||||
// @Param cluster-id query string false "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=serialize.InfobaseSummaryInfo}
|
||||
// @Failure 400 {object} Response
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/unblock [post]
|
||||
func (a *blockerApi) PostUnblockApp() {}
|
93
api/cluster.go
Normal file
93
api/cluster.go
Normal file
@ -0,0 +1,93 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/khorevaa/kubodin/service"
|
||||
)
|
||||
|
||||
type clusterApi struct {
|
||||
service service.Service
|
||||
}
|
||||
|
||||
func (a *clusterApi) Routes(r fiber.Router) {
|
||||
|
||||
r.Get("/clusters", withClient(a.List))
|
||||
r.Get("/clusters/:cluster", withClient(a.Info))
|
||||
r.Post("/clusters", withClient(a.Reg))
|
||||
r.Delete("/clusters/:cluster", withClient(a.Unreg))
|
||||
|
||||
router := r.Group("/clusters/:cluster")
|
||||
|
||||
parentApi := []route{
|
||||
&infobasesApi{service: a.service},
|
||||
&sessionsApi{service: a.service},
|
||||
&connectionsApi{service: a.service},
|
||||
&managersApi{service: a.service},
|
||||
&servicesApi{service: a.service},
|
||||
&locksApi{service: a.service},
|
||||
&processesApi{service: a.service},
|
||||
&licensesApi{service: a.service},
|
||||
&clusterAdminApi{service: a.service},
|
||||
}
|
||||
|
||||
for _, api := range parentApi {
|
||||
api.Routes(router)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// List получение списка кластеров на сервере 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary получение списка кластеров на сервере 1С Предприятие
|
||||
// @Description получение списка кластеров на сервере 1С Предприятие
|
||||
// @Tags clusters
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=[]serialize.ClusterInfo}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/clusters [get]
|
||||
func (a *clusterApi) List(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
|
||||
list, err := a.service.GetClusters(client)
|
||||
|
||||
if err != nil {
|
||||
return ErrorResponse(ctx, err, "error get clusters")
|
||||
}
|
||||
|
||||
return SuccessResponse(ctx, list)
|
||||
}
|
||||
|
||||
// Info получение информации о кластере на сервере 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary получение информации о кластере на сервере 1С Предприятие
|
||||
// @Description получение информации о кластере на сервере 1С Предприятие
|
||||
// @Tags clusters
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=serialize.ClusterInfo}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/clusters/{cluster} [get]
|
||||
func (a *clusterApi) Info(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
val, err := a.service.GetClusterInfo(client)
|
||||
|
||||
if err != nil {
|
||||
return ErrorResponse(ctx, err, "error get cluster info")
|
||||
}
|
||||
|
||||
return SuccessResponse(ctx, val)
|
||||
}
|
||||
|
||||
func (a *clusterApi) Reg(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
return NoAllowResponse(ctx)
|
||||
}
|
||||
|
||||
func (a *clusterApi) Unreg(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
return NoAllowResponse(ctx)
|
||||
}
|
73
api/clusterAdmin.go
Normal file
73
api/clusterAdmin.go
Normal file
@ -0,0 +1,73 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/khorevaa/kubodin/service"
|
||||
)
|
||||
|
||||
type clusterAdminApi struct {
|
||||
service service.Service
|
||||
}
|
||||
|
||||
func (a *clusterAdminApi) Routes(r fiber.Router) {
|
||||
|
||||
r.Get("/admins", withClient(a.List))
|
||||
r.Post("/admins", withClient(a.Create))
|
||||
r.Delete("/admins/:admin", withClient(a.Delete))
|
||||
|
||||
}
|
||||
|
||||
// List получение списка администраторов кластера
|
||||
// Swagger-spec:
|
||||
// @Summary получение списка администраторов кластера
|
||||
// @Description получение списка администраторов кластера
|
||||
// @Tags admins,clusters
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=serialize.UsersList}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/cluster/{cluster}/admins [get]
|
||||
func (a *clusterAdminApi) List(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
return NoAllowResponse(ctx)
|
||||
}
|
||||
|
||||
// Create выполняет регистрацию нового администратор на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary выполняет регистрацию нового администратор на кластере
|
||||
// @Description выполняет регистрацию нового администратор на кластере
|
||||
// @Tags admins,clusters
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param req body serialize.UserInfo true "user info"
|
||||
// @Success 200 {object} Response{data=serialize.UserInfo}
|
||||
// @Failure 404 {object} Response
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/cluster/{cluster}/admins [post]
|
||||
func (a *clusterAdminApi) Create(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
|
||||
return NoAllowResponse(ctx)
|
||||
|
||||
}
|
||||
|
||||
// Delete Удаление администратора агента на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary Удаление администратора агента на кластере
|
||||
// @Description Удаление администратора агента на кластере
|
||||
// @Tags admins,clusters
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param admin path string true "admin name"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=string}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/cluster/{cluster}/admins/{admin} [delete]
|
||||
func (a *clusterAdminApi) Delete(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
return NoAllowResponse(ctx)
|
||||
}
|
176
api/connections.go
Normal file
176
api/connections.go
Normal file
@ -0,0 +1,176 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/khorevaa/kubodin/service"
|
||||
)
|
||||
|
||||
type connectionsApi struct {
|
||||
service service.Service
|
||||
}
|
||||
|
||||
func (a *connectionsApi) Routes(r fiber.Router) {
|
||||
|
||||
r.Get("/connections", withClient(a.List))
|
||||
r.Post("/connections/terminate", withClient(a.Terminate))
|
||||
r.Delete("/connections/:connection.:process", withClient(a.TerminateOne))
|
||||
|
||||
}
|
||||
|
||||
// List получение списка подключений на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary получение списка подключений на кластере
|
||||
// @Description пполучение списка подключений на кластере
|
||||
// @Tags connections
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Success 200 {object} Response{data=serialize.ConnectionShortInfoList}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/clusters/{cluster}/connections [get]
|
||||
func (a *connectionsApi) List(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
return NoAllowResponse(ctx)
|
||||
}
|
||||
|
||||
// List получение списка подключений для информационной базы на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary получение списка подключений для информационной базы на кластере
|
||||
// @Description получение списка подключений для информационной базы на кластере
|
||||
// @Tags connections
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param infobase path string true "infobase uuid or name"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=serialize.ConnectionShortInfoList}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/clusters/{cluster}/infobases/{infobase}/connections [get]
|
||||
func (a *connectionsApi) ListClusterInfobase() {}
|
||||
|
||||
// List получение списка подключений на сервере 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary получение списка подключений на сервере 1С Предприятие
|
||||
// @Description получение списка подключений на сервере 1С Предприятие
|
||||
// @Tags connections
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster-id query string false "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=serialize.ConnectionShortInfoList}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/connections [get]
|
||||
func (a *connectionsApi) ListApp() {}
|
||||
|
||||
// List получение списка подключений для информационной базы на сервер 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary получение списка подключений для информационной базы на сервер 1С Предприятие
|
||||
// @Description получение списка подключений для информационной базы на сервер 1С Предприятие
|
||||
// @Tags connections
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param infobase path string true "infobase uuid or name"
|
||||
// @Param cluster-id query string false "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=serialize.ConnectionShortInfoList}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/infobases/{infobase}/connections [get]
|
||||
func (a *connectionsApi) ListAppInfobase() {}
|
||||
|
||||
// TerminateOne отключение подключения на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary отключение подключения на кластере
|
||||
// @Description отключение подключения на кластере
|
||||
// @Tags connections
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param connection path string true "connection uuid"
|
||||
// @Param process path string true "process uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Success 200 {object} Response{data=models.TerminateConnectionSig}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/clusters/{cluster}/connections/{connection}.{process} [delete]
|
||||
func (a *connectionsApi) TerminateOne(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
|
||||
return NoAllowResponse(ctx)
|
||||
}
|
||||
|
||||
// TerminateOne отключение подключения на сервере 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary отключение подключения на сервере 1С Предприятие
|
||||
// @Description отключение подключения на сервере 1С Предприятие
|
||||
// @Tags connections
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param connection path string true "connection uuid"
|
||||
// @Param process path string true "process uuid"
|
||||
// @Param cluster-id query string false "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Success 200 {object} Response{data=models.TerminateConnectionSig}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/connections/{connection}.{process} [delete]
|
||||
func (a *connectionsApi) TerminateOneApp() {}
|
||||
|
||||
// Terminate отключение списка подключений на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary отключение списка подключений на кластере
|
||||
// @Description отключение списка подключений или по информационной базе на кластере
|
||||
// @Tags connections
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param req body models.TerminateConnectionsRequest true "request"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Success 200 {object} Response{data=models.TerminateConnectionsResponse}
|
||||
// @Failure 400 {object} Response
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/clusters/{cluster}/connections/terminate [post]
|
||||
func (a *connectionsApi) Terminate(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
|
||||
return NoAllowResponse(ctx)
|
||||
|
||||
}
|
||||
|
||||
// Terminate отключение списка подключений на сервере 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary отключение списка подключений на сервере 1С Предприятие
|
||||
// @Description отключение списка подключений или по информационной базе на сервере 1С Предприятие
|
||||
// @Tags connections
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param req body models.TerminateConnectionsRequest true "request"
|
||||
// @Param cluster-id query string false "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Success 200 {object} Response{data=models.TerminateConnectionsResponse}
|
||||
// @Failure 400 {object} Response
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/connections/terminate [post]
|
||||
func (a *connectionsApi) TerminateApp() {}
|
18
api/handlers.go
Normal file
18
api/handlers.go
Normal file
@ -0,0 +1,18 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
// NotFound returns custom 404 page
|
||||
func NotFound(c *fiber.Ctx) error {
|
||||
return c.Status(404).JSON(Response{
|
||||
Code: 404,
|
||||
Message: "not found",
|
||||
})
|
||||
}
|
||||
|
||||
type HTTPError struct {
|
||||
Status string
|
||||
Message string
|
||||
}
|
103
api/health.go
Normal file
103
api/health.go
Normal file
@ -0,0 +1,103 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/khorevaa/kubodin/models"
|
||||
"github.com/khorevaa/kubodin/service"
|
||||
"time"
|
||||
)
|
||||
|
||||
type healthApi struct {
|
||||
name string
|
||||
version string
|
||||
route string
|
||||
service service.Service
|
||||
}
|
||||
|
||||
func (a *healthApi) Routes(r fiber.Router) {
|
||||
|
||||
r.Get("/health", a.health)
|
||||
r.Get("/health/readiness", a.readiness)
|
||||
}
|
||||
|
||||
// health запрос о состонии приложения
|
||||
// Swagger-spec:
|
||||
// @Summary запрос о состонии приложения
|
||||
// @Description запрос о состонии приложения
|
||||
// @Tags health
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} StatusResponse
|
||||
// @Failure 500 {object} StatusResponse
|
||||
// @Router /health [get]
|
||||
func (a *healthApi) health(ctx *fiber.Ctx) error {
|
||||
|
||||
return NoAllowResponse(ctx)
|
||||
|
||||
}
|
||||
|
||||
// readiness запрос подробного состония приложения
|
||||
// Swagger-spec:
|
||||
// @Summary запрос подробного состония приложения
|
||||
// @Description запрос подробного состония приложения
|
||||
// @Tags health
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} ReadinessCheckStatus
|
||||
// @Failure 500 {object} ReadinessCheckStatus
|
||||
// @Router /health/readiness [get]
|
||||
func (a *healthApi) readiness(ctx *fiber.Ctx) error {
|
||||
|
||||
return NoAllowResponse(ctx)
|
||||
}
|
||||
|
||||
type readinessCheck struct {
|
||||
Name string
|
||||
Version string
|
||||
service service.Service
|
||||
Apps []AppServiceCheckConfig
|
||||
}
|
||||
|
||||
type ReadinessCheckStatus struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
Status bool `json:"status"`
|
||||
Apps []AppServiceStatus `json:"apps"`
|
||||
}
|
||||
|
||||
type serviceStatus struct {
|
||||
Status bool `json:"status"`
|
||||
Error string `json:"errors,omitempty"`
|
||||
}
|
||||
|
||||
type AppServiceCheckConfig struct {
|
||||
App *models.AppServer
|
||||
Host string
|
||||
TimeOut time.Duration `json:"timeout,omitempty"` // default value: 10
|
||||
Headers []HTTPHeader `json:"headers,omitempty"`
|
||||
Ctx *fiber.Ctx
|
||||
}
|
||||
|
||||
type AppServiceStatus struct {
|
||||
Name string `json:"name"`
|
||||
Host string `json:"host"`
|
||||
Status bool `json:"status"`
|
||||
ResponseTime float64 `json:"response_time"`
|
||||
URL string `json:"url"`
|
||||
Error string `json:"errors,omitempty"`
|
||||
}
|
||||
|
||||
// HTTPHeader used to setup webservices integrations
|
||||
type HTTPHeader struct {
|
||||
Key string `json:"key,omitempty"`
|
||||
Value string `json:"Value,omitempty"`
|
||||
}
|
||||
|
||||
type StatusResponse struct {
|
||||
Status bool `json:"status"`
|
||||
Err string `json:"errors,omitempty"`
|
||||
}
|
||||
|
||||
func (r StatusResponse) Error() string {
|
||||
return r.Err
|
||||
}
|
31
api/healthApp.go
Normal file
31
api/healthApp.go
Normal file
@ -0,0 +1,31 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/khorevaa/kubodin/service"
|
||||
)
|
||||
|
||||
type healthAppApi struct {
|
||||
service service.Service
|
||||
}
|
||||
|
||||
func (a *healthAppApi) Routes(r fiber.Router) {
|
||||
|
||||
r.Get("/health", withClient(a.health))
|
||||
}
|
||||
|
||||
// health запрос о состонии сервера приложений 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary запрос о состонии сервера приложений 1С Предприятие
|
||||
// @Description запрос о состонии сервера приложений 1С Предприятие
|
||||
// @Tags app
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} StatusResponse
|
||||
// @Failure 500 {object} StatusResponse
|
||||
// @Router /app/{app}/health [get]
|
||||
func (a *healthAppApi) health(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
|
||||
return NoAllowResponse(ctx)
|
||||
|
||||
}
|
21
api/helpers.go
Normal file
21
api/helpers.go
Normal file
@ -0,0 +1,21 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/khorevaa/kubodin/service"
|
||||
)
|
||||
|
||||
func withClient(fn func(client service.ClientContext, ctx *fiber.Ctx) error) fiber.Handler {
|
||||
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
|
||||
client, err := service.GetClientContext(ctx)
|
||||
|
||||
if err != nil {
|
||||
return ErrorResponse(ctx, err, "error get context client")
|
||||
}
|
||||
|
||||
return fn(client, ctx)
|
||||
|
||||
}
|
||||
}
|
480
api/helpers_test.go
Normal file
480
api/helpers_test.go
Normal file
@ -0,0 +1,480 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
db "github.com/khorevaa/kubodin/database"
|
||||
"github.com/khorevaa/kubodin/models"
|
||||
"github.com/khorevaa/kubodin/ras"
|
||||
"github.com/khorevaa/kubodin/service"
|
||||
"github.com/khorevaa/kubodin/service/cache"
|
||||
rclient "github.com/khorevaa/ras-client"
|
||||
"github.com/khorevaa/ras-client/serialize"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
"github.com/steinfletcher/apitest"
|
||||
"time"
|
||||
)
|
||||
|
||||
// WithRecorderRepository wraps an existing driver with a Recorder
|
||||
func WithRecorderRepository(repository db.Repository, recorder *apitest.Recorder) db.Repository {
|
||||
|
||||
recordingDriver := &recordingRepository{
|
||||
sourceName: "pudge DB",
|
||||
repository: repository,
|
||||
recorder: recorder,
|
||||
}
|
||||
|
||||
return recordingDriver
|
||||
}
|
||||
|
||||
// WithRecorderService wraps an existing driver with a Recorder
|
||||
func WithRecorderService(serv service.Service, recorder *apitest.Recorder) service.Service {
|
||||
|
||||
recordingDriver := &recordingService{
|
||||
sourceName: "service",
|
||||
service: serv,
|
||||
recorder: recorder,
|
||||
}
|
||||
|
||||
return recordingDriver
|
||||
}
|
||||
|
||||
// WithRecorderService wraps an existing driver with a Recorder
|
||||
func WithRecorderCache(c cache.Cache, recorder *apitest.Recorder) cache.Cache {
|
||||
|
||||
recordingDriver := &recordingCache{
|
||||
sourceName: "cache",
|
||||
c: c,
|
||||
recorder: recorder,
|
||||
}
|
||||
|
||||
return recordingDriver
|
||||
}
|
||||
|
||||
// WithRecorderService wraps an existing driver with a Recorder
|
||||
func WithRecorderClient(c rclient.Api, recorder *apitest.Recorder) rclient.Api {
|
||||
|
||||
recordingDriver := &recordingClient{
|
||||
sourceName: "ras",
|
||||
Api: c,
|
||||
recorder: recorder,
|
||||
}
|
||||
|
||||
return recordingDriver
|
||||
}
|
||||
|
||||
// WithRecorderService wraps an existing driver with a Recorder
|
||||
func RecorderStorage(recorder *apitest.Recorder) ras.Storage {
|
||||
|
||||
recordingDriver := &recordingStorage{
|
||||
sourceName: "storage",
|
||||
recorder: recorder,
|
||||
}
|
||||
|
||||
return recordingDriver
|
||||
}
|
||||
|
||||
type recordingStorage struct {
|
||||
recorder *apitest.Recorder
|
||||
sourceName string
|
||||
}
|
||||
|
||||
func (r recordingStorage) Store(id string, addr string, version string) (rclient.Api, bool) {
|
||||
|
||||
client := WithRecorderClient(rclient.NewClient(addr, rclient.WithVersion(version)), r.recorder)
|
||||
return client, false
|
||||
}
|
||||
|
||||
func (r recordingStorage) LoadOrInit(id string, addr string, version string) (rclient.Api, bool) {
|
||||
client := WithRecorderClient(rclient.NewClient(addr, rclient.WithVersion(version)), r.recorder)
|
||||
return client, false
|
||||
}
|
||||
|
||||
func (r recordingStorage) Load(id string) (interface{}, bool) {
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
type recordingClient struct {
|
||||
rclient.Api
|
||||
recorder *apitest.Recorder
|
||||
sourceName string
|
||||
}
|
||||
|
||||
func (r recordingClient) addReq(header string, body ...interface{}) {
|
||||
|
||||
var data string
|
||||
|
||||
if len(body) > 0 {
|
||||
data = toJson(body[0])
|
||||
}
|
||||
|
||||
r.recorder.AddMessageRequest(apitest.MessageRequest{
|
||||
Source: "service",
|
||||
Target: r.sourceName,
|
||||
Header: header,
|
||||
Body: data,
|
||||
Timestamp: time.Now().UTC(),
|
||||
})
|
||||
}
|
||||
|
||||
func (r recordingClient) addResp(header string, body interface{}, err error) {
|
||||
|
||||
var data string
|
||||
|
||||
if err != nil {
|
||||
data = err.Error()
|
||||
} else {
|
||||
data = toJson(body)
|
||||
}
|
||||
|
||||
r.recorder.AddMessageResponse(apitest.MessageResponse{
|
||||
Source: r.sourceName,
|
||||
Target: "service",
|
||||
Header: header,
|
||||
Body: data,
|
||||
Timestamp: time.Now().UTC(),
|
||||
})
|
||||
}
|
||||
|
||||
func (r recordingClient) GetClusters(ctx context.Context) ([]*serialize.ClusterInfo, error) {
|
||||
|
||||
r.addReq("GetClusters")
|
||||
ok, err := r.Api.GetClusters(ctx)
|
||||
r.addResp("GetClusters", ok, err)
|
||||
|
||||
return ok, err
|
||||
|
||||
}
|
||||
|
||||
func (r recordingClient) GetClusterServices(ctx context.Context, cluster uuid.UUID) ([]*serialize.ServiceInfo, error) {
|
||||
|
||||
r.addReq("GetClusterServices",
|
||||
map[string]interface{}{"cluster": cluster})
|
||||
ok, err := r.Api.GetClusterServices(ctx, cluster)
|
||||
r.addResp("GetClusterServices", ok, err)
|
||||
|
||||
return ok, err
|
||||
|
||||
}
|
||||
|
||||
type recordingCache struct {
|
||||
c cache.Cache
|
||||
recorder *apitest.Recorder
|
||||
sourceName string
|
||||
}
|
||||
|
||||
func (r recordingCache) Connect() {
|
||||
r.Connect()
|
||||
}
|
||||
|
||||
func (r recordingCache) Get(key string) (interface{}, bool) {
|
||||
r.addReq("cache get", key)
|
||||
data, ok := r.c.Get(key)
|
||||
r.addResp("cache resp",
|
||||
map[string]interface{}{"data": data, "ok": ok},
|
||||
nil)
|
||||
return data, ok
|
||||
}
|
||||
|
||||
func (r recordingCache) Set(key string, value interface{}) {
|
||||
r.addReq("cache set", map[string]interface{}{key: value})
|
||||
r.c.Set(key, value)
|
||||
}
|
||||
|
||||
func (r recordingCache) Clear(key string) {
|
||||
r.addReq("cache clear", key)
|
||||
r.c.Clear(key)
|
||||
|
||||
}
|
||||
|
||||
func (r recordingCache) HealthCheck() (bool, error) {
|
||||
|
||||
r.addReq("cache HealthCheck")
|
||||
ok, err := r.c.HealthCheck()
|
||||
r.addResp("cache HealthCheck", ok, err)
|
||||
|
||||
return ok, err
|
||||
}
|
||||
|
||||
func (r recordingCache) addReq(header string, body ...interface{}) {
|
||||
|
||||
var data string
|
||||
|
||||
if len(body) > 0 {
|
||||
data = toJson(body[0])
|
||||
}
|
||||
|
||||
r.recorder.AddMessageRequest(apitest.MessageRequest{
|
||||
Source: "service",
|
||||
Target: r.sourceName,
|
||||
Header: header,
|
||||
Body: data,
|
||||
Timestamp: time.Now().UTC(),
|
||||
})
|
||||
}
|
||||
|
||||
func (r recordingCache) addResp(header string, body interface{}, err error) {
|
||||
|
||||
var data string
|
||||
|
||||
if err != nil {
|
||||
data = err.Error()
|
||||
} else {
|
||||
data = toJson(body)
|
||||
}
|
||||
|
||||
r.recorder.AddMessageResponse(apitest.MessageResponse{
|
||||
Source: r.sourceName,
|
||||
Target: "service",
|
||||
Header: header,
|
||||
Body: data,
|
||||
Timestamp: time.Now().UTC(),
|
||||
})
|
||||
}
|
||||
|
||||
type recordingService struct {
|
||||
service service.Service
|
||||
recorder *apitest.Recorder
|
||||
sourceName string
|
||||
}
|
||||
|
||||
func (r recordingService) GetCache() cache.Cache {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r recordingService) License() {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r recordingService) addReq(header string, body ...interface{}) {
|
||||
|
||||
var data string
|
||||
|
||||
if len(body) > 0 {
|
||||
data = toJson(body[0])
|
||||
}
|
||||
|
||||
r.recorder.AddMessageRequest(apitest.MessageRequest{
|
||||
Source: apitest.SystemUnderTestDefaultName,
|
||||
Target: r.sourceName,
|
||||
Header: header,
|
||||
Body: data,
|
||||
Timestamp: time.Now().UTC(),
|
||||
})
|
||||
}
|
||||
|
||||
func (r recordingService) addResp(header string, body interface{}, err error) {
|
||||
|
||||
var data string
|
||||
|
||||
if err != nil {
|
||||
data = err.Error()
|
||||
} else {
|
||||
data = toJson(body)
|
||||
}
|
||||
|
||||
r.recorder.AddMessageResponse(apitest.MessageResponse{
|
||||
Source: r.sourceName,
|
||||
Target: apitest.SystemUnderTestDefaultName,
|
||||
Header: header,
|
||||
Body: data,
|
||||
Timestamp: time.Now().UTC(),
|
||||
})
|
||||
}
|
||||
|
||||
func (r recordingService) Repository() db.Repository {
|
||||
return r.service.Repository()
|
||||
}
|
||||
|
||||
func (r recordingService) GetInfobase(ctt service.ClientContext) (*serialize.InfobaseInfo, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r recordingService) CreateInfobase(ctt service.ClientContext, info *serialize.InfobaseInfo, createDB bool) (*serialize.InfobaseInfo, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r recordingService) UpdateInfobase(ctt service.ClientContext, info *serialize.InfobaseInfo) (*serialize.InfobaseInfo, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r recordingService) DropInfobase(ctt service.ClientContext, deleteDB bool) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r recordingService) GetSessions(ctt service.ClientContext) (serialize.SessionInfoList, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r recordingService) TerminateSession(ctt service.ClientContext, sessionID uuid.UUID, msg string) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r recordingService) GetClusters(ctt service.ClientContext) ([]*serialize.ClusterInfo, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r recordingService) GetClusterInfo(ctt service.ClientContext) (*serialize.ClusterInfo, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r recordingService) GetManagers(ctt service.ClientContext) ([]*serialize.ManagerInfo, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r recordingService) GetInfobases(ctt service.ClientContext) (serialize.InfobaseSummaryList, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r recordingService) GetLocks(ctt service.ClientContext) (serialize.LocksList, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r recordingService) GetConnections(ctt service.ClientContext) (serialize.ConnectionShortInfoList, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r recordingService) GetInfobaseConnections(client service.ClientContext, infobase string) (serialize.ConnectionShortInfoList, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r recordingService) Block(ctt service.ClientContext, blocker *models.InfobaseBlocker) (*models.InfobaseUnblocker, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r recordingService) Unblock(ctt service.ClientContext, unblocker *models.InfobaseUnblocker) (*serialize.InfobaseSummaryInfo, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r recordingService) GetProcesses(ctt service.ClientContext) (serialize.ProcessInfoList, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r recordingService) GetProcessInfo(ctt service.ClientContext) (*serialize.ProcessInfo, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r recordingService) TerminateConnection(ctt service.ClientContext, processID, connectionsID uuid.UUID) (models.ConnectionSig, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r recordingService) GetAppServers() (apps []*models.AppServer, err error) {
|
||||
|
||||
r.addReq("GetAppServers")
|
||||
|
||||
apps, err = r.service.GetAppServers()
|
||||
|
||||
r.addResp("GetAppServers", apps, err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (r recordingService) GetAppServer(name string) (*models.AppServer, error) {
|
||||
r.addReq("GetAppServer", name)
|
||||
|
||||
app, err := r.service.GetAppServer(name)
|
||||
|
||||
r.addResp("GetAppServer", app, err)
|
||||
|
||||
return app, err
|
||||
}
|
||||
|
||||
type recordingRepository struct {
|
||||
repository db.Repository
|
||||
recorder *apitest.Recorder
|
||||
sourceName string
|
||||
}
|
||||
|
||||
func (r recordingRepository) addReq(header string, body interface{}) {
|
||||
|
||||
var data string
|
||||
errBody, ok := body.(error)
|
||||
|
||||
if ok {
|
||||
|
||||
data = errBody.Error()
|
||||
} else {
|
||||
data = toJson(body)
|
||||
}
|
||||
|
||||
r.recorder.AddMessageRequest(apitest.MessageRequest{
|
||||
Source: "service",
|
||||
Target: r.sourceName,
|
||||
Header: header,
|
||||
Body: data,
|
||||
Timestamp: time.Now().UTC(),
|
||||
})
|
||||
}
|
||||
|
||||
func (r recordingRepository) addResp(header string, body interface{}, err error) {
|
||||
|
||||
var data string
|
||||
|
||||
if err != nil {
|
||||
data = err.Error()
|
||||
} else {
|
||||
data = toJson(body)
|
||||
}
|
||||
|
||||
r.recorder.AddMessageResponse(apitest.MessageResponse{
|
||||
Source: r.sourceName,
|
||||
Target: "service",
|
||||
Header: header,
|
||||
Body: data,
|
||||
Timestamp: time.Now().UTC(),
|
||||
})
|
||||
}
|
||||
|
||||
func (r recordingRepository) AddAppServer(app models.AppServer) error {
|
||||
|
||||
err := r.repository.AddAppServer(app)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r recordingRepository) Clear() error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r recordingRepository) Db() string {
|
||||
return r.repository.Db()
|
||||
}
|
||||
|
||||
func (r recordingRepository) GetAppServers() (apps []*models.AppServer, err error) {
|
||||
|
||||
r.addReq("GetAppServers", nil)
|
||||
|
||||
apps, err = r.repository.GetAppServers()
|
||||
|
||||
r.addResp("GetAppServers", apps, err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (r recordingRepository) GetAppServer(name string) (*models.AppServer, error) {
|
||||
|
||||
r.addReq("GetAppServer", name)
|
||||
|
||||
app, err := r.repository.GetAppServer(name)
|
||||
|
||||
r.addResp("GetAppServer", app, err)
|
||||
|
||||
return app, err
|
||||
}
|
||||
|
||||
func (r recordingRepository) DeleteAppServer(appName string) error {
|
||||
|
||||
r.addReq("DeleteAppServer", appName)
|
||||
err := r.repository.DeleteAppServer(appName)
|
||||
r.addResp("DeleteAppServer", nil, err)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func toJson(data interface{}) string {
|
||||
raw, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
return string(raw)
|
||||
}
|
284
api/infobases.go
Normal file
284
api/infobases.go
Normal file
@ -0,0 +1,284 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/khorevaa/kubodin/service"
|
||||
"github.com/khorevaa/ras-client/serialize"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type infobasesApi struct {
|
||||
service service.Service
|
||||
}
|
||||
|
||||
func (a *infobasesApi) Routes(r fiber.Router) {
|
||||
|
||||
r.Get("/infobases", withClient(a.List))
|
||||
r.Post("/infobases", withClient(a.Create))
|
||||
r.Get("/infobases/:infobase", withClient(a.Info))
|
||||
r.Post("/infobases/:infobase", withClient(a.Update))
|
||||
r.Delete("/infobases/:infobase", withClient(a.Drop))
|
||||
|
||||
router := r.Group("/infobases/:infobase")
|
||||
|
||||
parentApi := []route{
|
||||
&sessionsApi{service: a.service},
|
||||
&connectionsApi{service: a.service},
|
||||
&blockerApi{service: a.service},
|
||||
&locksApi{service: a.service},
|
||||
}
|
||||
|
||||
for _, api := range parentApi {
|
||||
api.Routes(router)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// List получение списка информационных баз с кластера
|
||||
// Swagger-spec:
|
||||
// @Summary получение списка информационных баз с кластера
|
||||
// @Description получение списка информационных баз с кластера
|
||||
// @Tags infobases
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=serialize.InfobaseSummaryList}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/clusters/{cluster}/infobases [get]
|
||||
func (a *infobasesApi) List(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
|
||||
list, err := a.service.GetInfobases(client)
|
||||
|
||||
if err != nil {
|
||||
return ErrorResponse(ctx, err, "error get infobases")
|
||||
|
||||
}
|
||||
return SuccessResponse(ctx, list)
|
||||
|
||||
}
|
||||
|
||||
// List получение списка информационных баз с сервера 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary получение списка информационных баз с сервера 1С Предприятие
|
||||
// @Description получение списка информационных баз с сервера 1С Предприятие
|
||||
// @Tags infobases
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster-id query string false "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=serialize.InfobaseSummaryList}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/infobases [get]
|
||||
func (a *infobasesApi) ListApp() {}
|
||||
|
||||
// Info получение информации об информационной базе с кластера
|
||||
// Swagger-spec:
|
||||
// @Summary получение информации об информационной базе с кластера
|
||||
// @Description получение информации об информационной базе с кластера
|
||||
// @Tags infobases
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param infobase path string true "infobase name or uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=serialize.InfobaseInfo}
|
||||
// @Failure 500 {object} Response{data=string}
|
||||
// @Router /app/{app}/clusters/{cluster}/infobases/{infobase} [get]
|
||||
func (a *infobasesApi) Info(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
|
||||
return NoAllowResponse(ctx)
|
||||
|
||||
}
|
||||
|
||||
// Info получение информации об информационной базе с сервера 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary получение информации об информационной базе с сервера 1С Предприятие
|
||||
// @Description получение информации об информационной базе с сервера 1С Предприятие
|
||||
// @Tags infobases
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param infobase path string true "infobase name or uuid"
|
||||
// @Param cluster-id query string false "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=serialize.InfobaseInfo}
|
||||
// @Failure 500 {object} Response{data=string}
|
||||
// @Router /app/{app}/infobases/{infobase} [get]
|
||||
func (a *infobasesApi) InfoApp() {}
|
||||
|
||||
// Update обновление информации об информационной базе на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary обновление информации об информационной базе на кластере
|
||||
// @Description побновление информации об информационной базе на кластере
|
||||
// @Tags infobases
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param infobase path string true "infobase name or uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Param info body serialize.InfobaseInfo true "new info"
|
||||
// @Success 200 {object} Response{data=string}
|
||||
// @Failure 400 {object} Response{data=string}
|
||||
// @Failure 500 {object} Response{data=string}
|
||||
// @Router /app/{app}/clusters/{cluster}/infobases/{infobase} [post]
|
||||
func (a *infobasesApi) Update(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
|
||||
return NoAllowResponse(ctx)
|
||||
|
||||
}
|
||||
|
||||
// Update обновление информации об информационной базе на сервера 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary обновление информации об информационной базе на сервера 1С Предприятие
|
||||
// @Description обновление информации об информационной базе на сервера 1С Предприятие
|
||||
// @Tags infobases
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param infobase path string true "infobase name or uuid"
|
||||
// @Param cluster-id query string false "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Param info body serialize.InfobaseInfo true "new info"
|
||||
// @Success 200 {object} Response{data=string}
|
||||
// @Failure 400 {object} Response{data=string}
|
||||
// @Failure 500 {object} Response{data=string}
|
||||
// @Router /app/{app}/infobases/{infobase} [post]
|
||||
func (a *infobasesApi) UpdateApp() {}
|
||||
|
||||
// Create создание информационной базы на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary оздание информационной базы на кластере
|
||||
// @Description оздание информационной базы на кластере
|
||||
// @Tags infobases
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param create-db query bool false "create server db"
|
||||
// @Param info body serialize.InfobaseInfo true "new info"
|
||||
// @Success 200 {object} Response{data=serialize.InfobaseInfo}
|
||||
// @Failure 400 {object} Response{data=string}
|
||||
// @Failure 500 {object} Response{data=string}
|
||||
// @Router /app/{app}/clusters/{cluster}/infobases [post]
|
||||
func (a *infobasesApi) Create(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
|
||||
var body serialize.InfobaseInfo
|
||||
|
||||
err := ctx.BodyParser(&body)
|
||||
if err != nil {
|
||||
return ErrorResponse(ctx, err, "error body parse infobase info")
|
||||
}
|
||||
|
||||
//err = validateCreateInfobaseInfo(body)
|
||||
//if err != nil {
|
||||
// return ErrorResponse(ctx, err, "validate error")
|
||||
//}
|
||||
|
||||
createDB, _ := strconv.ParseBool(ctx.Query("create-db", "false"))
|
||||
|
||||
info, err := a.service.CreateInfobase(client, &body, createDB)
|
||||
|
||||
if err != nil {
|
||||
return ErrorResponse(ctx, err, "create infobase error")
|
||||
|
||||
}
|
||||
return SuccessResponse(ctx, info)
|
||||
}
|
||||
|
||||
// Create создание информационной базы на сервере 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary создание информационной базы на сервере 1С Предприятие
|
||||
// @Description создание информационной базы на сервере 1С Предприятие
|
||||
// @Tags infobases
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster-id query string false "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param create-db query bool false "create server db"
|
||||
// @Param info body serialize.InfobaseInfo true "new info"
|
||||
// @Success 200 {object} Response{data=serialize.InfobaseInfo}
|
||||
// @Failure 400 {object} Response{data=string}
|
||||
// @Failure 500 {object} Response{data=string}
|
||||
// @Router /app/{app}/infobases [post]
|
||||
func (a *infobasesApi) CreateApp() {}
|
||||
|
||||
// Drop удаляет информационную базу с сервера кластера
|
||||
// Swagger-spec:
|
||||
// @Summary удаляет информационную базу с сервера кластера
|
||||
// @Description удаляет информационную базу с сервера кластера
|
||||
// @Tags infobases
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param infobase path string true "infobase name or uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Param delete-db query bool false "delete server db"
|
||||
// @Success 200 {object} Response{data=string}
|
||||
// @Failure 500 {object} Response{data=string}
|
||||
// @Router /app/{app}/clusters/{cluster}/infobases/{infobase} [delete]
|
||||
func (a *infobasesApi) Drop(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
|
||||
deleteDB, _ := strconv.ParseBool(ctx.Query("delete-db", "false"))
|
||||
err := a.service.DropInfobase(client, deleteDB)
|
||||
|
||||
if err != nil {
|
||||
return ErrorResponse(ctx, err, "drop infobase error")
|
||||
|
||||
}
|
||||
return SuccessResponse(ctx, nil)
|
||||
}
|
||||
|
||||
// DropApp удаляет информационную базу с сервера 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary удаляет информационную базу с сервера 1С Предприятие
|
||||
// @Description удаляет информационную базу с сервера 1С Предприятие
|
||||
// @Tags infobases
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param infobase path string true "infobase name or uuid"
|
||||
// @Param cluster-id query string false "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Param delete-db query bool false "delete server db"
|
||||
// @Success 200 {object} Response{data=string}
|
||||
// @Failure 500 {object} Response{data=string}
|
||||
// @Router /app/{app}/infobases/{infobase} [delete]
|
||||
func (a *infobasesApi) DropApp() {}
|
54
api/licenses.go
Normal file
54
api/licenses.go
Normal file
@ -0,0 +1,54 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/khorevaa/kubodin/service"
|
||||
)
|
||||
|
||||
type licensesApi struct {
|
||||
service service.Service
|
||||
}
|
||||
|
||||
func (a *licensesApi) Routes(r fiber.Router) {
|
||||
|
||||
r.Get("/licenses", withClient(a.List))
|
||||
|
||||
}
|
||||
|
||||
// List получение списка лицензий на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary получение списка лицензий на кластере
|
||||
// @Description получение списка лицензий на кластере
|
||||
// @Tags licenses
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=serialize.LicenseInfoList}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/clusters/{cluster}/licenses [get]
|
||||
func (a *licensesApi) List(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
|
||||
return NoAllowResponse(ctx)
|
||||
|
||||
}
|
||||
|
||||
// List получение списка лицензий на сервере 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary получение списка лицензий на сервере 1С Предприятие
|
||||
// @Description получение списка лицензий на сервере 1С Предприятие
|
||||
// @Tags licenses
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster-id query string false "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=serialize.LicenseInfoList}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/licenses [get]
|
||||
func (a *licensesApi) ListApp() {}
|
91
api/locks.go
Normal file
91
api/locks.go
Normal file
@ -0,0 +1,91 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/khorevaa/kubodin/service"
|
||||
)
|
||||
|
||||
type locksApi struct {
|
||||
service service.Service
|
||||
}
|
||||
|
||||
func (a *locksApi) Routes(r fiber.Router) {
|
||||
|
||||
r.Get("/locks", withClient(a.List))
|
||||
|
||||
}
|
||||
|
||||
// List получение списка блокировок на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary получение списка блокировок на кластере
|
||||
// @Description получение списка блокировок на кластере
|
||||
// @Tags locks
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Success 200 {object} Response{data=serialize.LocksList}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/clusters/{cluster}/locks [get]
|
||||
func (a *locksApi) List(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
|
||||
return NoAllowResponse(ctx)
|
||||
}
|
||||
|
||||
// List получение списка блокировок на сервере 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary получение списка блокировок на сервере 1С Предприятие
|
||||
// @Description получение списка блокировок на сервере 1С Предприятие
|
||||
// @Tags locks
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster-id query string false "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Success 200 {object} Response{data=serialize.LocksList}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/locks [get]
|
||||
func (a *locksApi) ListApp() {}
|
||||
|
||||
// List получение списка блокировок для информационной базы на сервере 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary пполучение списка блокировок для информационной базы на сервере 1С Предприятие
|
||||
// @Description получение списка блокировок для информационной базы на сервере 1С Предприятие
|
||||
// @Tags locks
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param infobase path string true "infobase name or uuid"
|
||||
// @Param cluster-id query string false "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=serialize.LocksList}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/infobases/{infobase}/locks [get]
|
||||
func (a *locksApi) ListAppInfobase() {}
|
||||
|
||||
// List получение списка блокировок для информационной базы на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary получение списка блокировок для информационной базы на кластере
|
||||
// @Description получение списка блокировок для информационной базы на кластере
|
||||
// @Tags locks
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param infobase path string true "infobase name or uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param infobase-usr query string false "infobase user"
|
||||
// @Param infobase-pwd query string false "infobase password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=serialize.LocksList}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/clusters/{cluster}/infobases/{infobase}/locks [get]
|
||||
func (a *locksApi) LisClusterInfobase() {}
|
58
api/managers.go
Normal file
58
api/managers.go
Normal file
@ -0,0 +1,58 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/khorevaa/kubodin/service"
|
||||
)
|
||||
|
||||
type managersApi struct {
|
||||
service service.Service
|
||||
}
|
||||
|
||||
func (a *managersApi) Routes(r fiber.Router) {
|
||||
|
||||
r.Get("/managers", withClient(a.List))
|
||||
r.Get("/managers/:manager", withClient(a.Info))
|
||||
|
||||
}
|
||||
|
||||
// List получение списка менеджеров на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary получение списка менеджеров на кластере
|
||||
// @Description получение списка менеджеров на кластере
|
||||
// @Tags managers
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=[]serialize.ManagerInfo}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/clusters/{cluster}/managers [get]
|
||||
func (a *managersApi) List(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
return NoAllowResponse(ctx)
|
||||
}
|
||||
|
||||
// List получение списка менеджеров на сервере 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary получение списка менеджеров на сервере 1С Предприятие
|
||||
// @Description получение списка менеджеров на сервере 1С Предприятие
|
||||
// @Tags managers
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster-id query string true "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=[]serialize.ManagerInfo}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/managers [get]
|
||||
func (a *managersApi) ListApp() {}
|
||||
|
||||
func (a *managersApi) Info(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
|
||||
return NoAllowResponse(ctx)
|
||||
}
|
91
api/processes.go
Normal file
91
api/processes.go
Normal file
@ -0,0 +1,91 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/khorevaa/kubodin/service"
|
||||
)
|
||||
|
||||
type processesApi struct {
|
||||
service service.Service
|
||||
}
|
||||
|
||||
func (a *processesApi) Routes(r fiber.Router) {
|
||||
|
||||
r.Get("/processes", withClient(a.List))
|
||||
r.Get("/processes/:process", withClient(a.Info))
|
||||
|
||||
}
|
||||
|
||||
// List получение списка процессов на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary получение списка процессов на кластере
|
||||
// @Description получение списка процессов на кластере
|
||||
// @Tags processes
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=[]serialize.ProcessInfo}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/clusters/{cluster}/processes [get]
|
||||
func (a *processesApi) List(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
return NoAllowResponse(ctx)
|
||||
}
|
||||
|
||||
// List получение списка процессов на сервере 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary получение списка процессов на сервере 1С Предприятие
|
||||
// @Description получение списка процессов на сервере 1С Предприятие
|
||||
// @Tags processes
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster-id query string true "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=[]serialize.ProcessInfo}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/processes [get]
|
||||
func (a *processesApi) ListApp() {}
|
||||
|
||||
// Info получение информации опроцессе на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary получение информации опроцессе на кластере
|
||||
// @Description получение информации опроцессе на кластере
|
||||
// @Tags processes
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param process path string true "uuid process"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Success 200 {object} Response{data=serialize.ProcessInfo}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/clusters/{cluster}/processes/{process} [get]
|
||||
func (a *processesApi) Info(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
|
||||
return NoAllowResponse(ctx)
|
||||
|
||||
}
|
||||
|
||||
// Info получение информации опроцессе на сервере 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary получение информации опроцессе на сервере 1С Предприятие
|
||||
// @Description получение информации опроцессе на сервере 1С Предприятие
|
||||
// @Tags processes
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param process path string true "uuid process"
|
||||
// @Param cluster-id query string true "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Success 200 {object} Response{data=serialize.ProcessInfo}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/processes/{process} [get]
|
||||
func (a *processesApi) InfoApp() {}
|
110
api/response.go
Normal file
110
api/response.go
Normal file
@ -0,0 +1,110 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/khorevaa/kubodin/errors"
|
||||
"github.com/khorevaa/ras-client/messages"
|
||||
)
|
||||
|
||||
type Response struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data interface{} `json:"data"`
|
||||
} // @Name Response
|
||||
|
||||
func (r *Response) Error() error {
|
||||
|
||||
err, ok := r.Data.(error)
|
||||
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
func ErrorResponse(ctx *fiber.Ctx, err error, msgAndArgs ...string) error {
|
||||
|
||||
var data interface{}
|
||||
message := messageFromMsgAndArgs(msgAndArgs)
|
||||
|
||||
switch typed := err.(type) {
|
||||
case *messages.EndpointFailure:
|
||||
data = typed
|
||||
case *messages.EndpointMessageFailure:
|
||||
data = typed
|
||||
case *messages.UnknownMessageError:
|
||||
data = typed
|
||||
default:
|
||||
data = err.Error()
|
||||
}
|
||||
|
||||
code := fiber.StatusInternalServerError
|
||||
|
||||
switch errors.GetType(err) {
|
||||
|
||||
case errors.BadRequest:
|
||||
code = fiber.StatusBadRequest
|
||||
|
||||
case errors.Other:
|
||||
data = err.Error()
|
||||
}
|
||||
|
||||
return ctx.Status(code).JSON(&Response{
|
||||
Code: code,
|
||||
Message: message,
|
||||
Data: data,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func NotImplemented(ctx *fiber.Ctx) error {
|
||||
return ErrorResponse(ctx, nil)
|
||||
}
|
||||
|
||||
func SuccessResponse(ctx *fiber.Ctx, data interface{}) error {
|
||||
|
||||
return ctx.Status(fiber.StatusOK).JSON(&Response{
|
||||
Code: fiber.StatusOK,
|
||||
Message: successMessage,
|
||||
Data: data,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
const successMessage = "success"
|
||||
|
||||
func HttpResponse(ctx *fiber.Ctx, data interface{}, err error, errMsgAndArgs ...string) error {
|
||||
|
||||
if err != nil {
|
||||
return ErrorResponse(ctx, err, errMsgAndArgs...)
|
||||
}
|
||||
return SuccessResponse(ctx, data)
|
||||
}
|
||||
|
||||
func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
|
||||
if len(msgAndArgs) == 0 {
|
||||
return ""
|
||||
}
|
||||
if len(msgAndArgs) == 1 {
|
||||
msg := msgAndArgs[0]
|
||||
if msgAsStr, ok := msg.(string); ok {
|
||||
return msgAsStr
|
||||
}
|
||||
return fmt.Sprintf("%+v", msg)
|
||||
}
|
||||
if len(msgAndArgs) > 1 {
|
||||
return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func NoAllowResponse(ctx *fiber.Ctx) error {
|
||||
return ctx.Status(fiber.StatusNotImplemented).JSON(&Response{
|
||||
Code: fiber.StatusNotImplemented,
|
||||
Message: "This api is now allow in Kubodin. Pls buy full version of ODIN",
|
||||
Data: "",
|
||||
})
|
||||
}
|
31
api/routes.go
Normal file
31
api/routes.go
Normal file
@ -0,0 +1,31 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/khorevaa/kubodin/service"
|
||||
)
|
||||
|
||||
type route interface {
|
||||
Routes(r fiber.Router)
|
||||
}
|
||||
|
||||
func Routes(app *fiber.App, s service.Service) {
|
||||
|
||||
// Create a /api/v1 endpoint
|
||||
v1 := app.Group("/api/v1")
|
||||
routes := []route{
|
||||
&AppApi{
|
||||
service: s,
|
||||
},
|
||||
&healthApi{
|
||||
service: s,
|
||||
name: "API Remote Administration for 1S.Enterprise Application Servers",
|
||||
version: "1.0",
|
||||
route: "/api/v1",
|
||||
},
|
||||
}
|
||||
for _, r := range routes {
|
||||
r.Routes(v1)
|
||||
}
|
||||
|
||||
}
|
87
api/server_test.go
Normal file
87
api/server_test.go
Normal file
@ -0,0 +1,87 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
db "github.com/khorevaa/kubodin/database"
|
||||
"github.com/khorevaa/kubodin/ras"
|
||||
"github.com/khorevaa/kubodin/service"
|
||||
"github.com/khorevaa/kubodin/service/cache"
|
||||
"github.com/steinfletcher/apitest"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"io"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var once = sync.Once{}
|
||||
|
||||
type baseSuite struct {
|
||||
suite.Suite
|
||||
}
|
||||
|
||||
func (s *baseSuite) r() *require.Assertions {
|
||||
return s.Require()
|
||||
}
|
||||
|
||||
func (s *baseSuite) api(recorder ...*apitest.Recorder) *apitest.APITest {
|
||||
|
||||
rec := apitest.NewTestRecorder()
|
||||
if len(recorder) > 0 {
|
||||
rec = recorder[0]
|
||||
}
|
||||
once.Do(func() {
|
||||
|
||||
})
|
||||
|
||||
return apitest.New().
|
||||
HandlerFunc(FiberToHandlerFunc(newTestApp(rec))).
|
||||
//Debug().
|
||||
//Report(apitest.SequenceDiagram())
|
||||
Recorder(rec)
|
||||
|
||||
}
|
||||
|
||||
func newTestApp(rec *apitest.Recorder) *fiber.App {
|
||||
|
||||
server := fiber.New()
|
||||
|
||||
memoryCache := &cache.Memory{
|
||||
Expiration: 30 * time.Minute,
|
||||
}
|
||||
|
||||
memoryCache.Connect()
|
||||
|
||||
ras.SetLocalStorage(RecorderStorage(rec))
|
||||
|
||||
rep := WithRecorderRepository(db.NewMemoryRepository(), rec)
|
||||
s, _ := service.NewService(WithRecorderCache(memoryCache, rec), rep)
|
||||
serv := WithRecorderService(s, rec)
|
||||
server.Use(service.Middleware(serv))
|
||||
|
||||
Routes(server, serv)
|
||||
return server
|
||||
|
||||
}
|
||||
|
||||
func FiberToHandlerFunc(app *fiber.App) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
resp, err := app.Test(r)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// copy headers
|
||||
for k, vv := range resp.Header {
|
||||
for _, v := range vv {
|
||||
w.Header().Add(k, v)
|
||||
}
|
||||
}
|
||||
w.WriteHeader(resp.StatusCode)
|
||||
|
||||
if _, err := io.Copy(w, resp.Body); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
58
api/services.go
Normal file
58
api/services.go
Normal file
@ -0,0 +1,58 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/khorevaa/kubodin/service"
|
||||
)
|
||||
|
||||
type servicesApi struct {
|
||||
service service.Service
|
||||
}
|
||||
|
||||
func (a *servicesApi) Routes(r fiber.Router) {
|
||||
|
||||
r.Get("/services", withClient(a.List))
|
||||
r.Get("/services/:service", withClient(a.Info))
|
||||
|
||||
}
|
||||
|
||||
// List получение списка сервисов на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary получение списка сервисов на кластере
|
||||
// @Description получение списка сервисов на кластере
|
||||
// @Tags services
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=[]serialize.ServiceInfo}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/clusters/{cluster}/services [get]
|
||||
func (a *servicesApi) List(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
|
||||
return NoAllowResponse(ctx)
|
||||
}
|
||||
|
||||
// List получение списка сервисов на сервере 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary получение списка сервисов на сервере 1С Предприятие
|
||||
// @Description получение списка сервисов на сервере 1С Предприятие
|
||||
// @Tags services
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster-id query string true "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=[]serialize.ServiceInfo}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/services [get]
|
||||
func (a *servicesApi) ListApp() {}
|
||||
|
||||
func (a *servicesApi) Info(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
return NoAllowResponse(ctx)
|
||||
}
|
41
api/services_test.go
Normal file
41
api/services_test.go
Normal file
@ -0,0 +1,41 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/khorevaa/kubodin/models"
|
||||
"github.com/steinfletcher/apitest"
|
||||
jsonpath "github.com/steinfletcher/apitest-jsonpath"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type servicesSuite struct {
|
||||
baseSuite
|
||||
}
|
||||
|
||||
func TestServiceTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(servicesSuite))
|
||||
}
|
||||
|
||||
func (s *servicesSuite) SetupSuite() {
|
||||
s.api().
|
||||
Post("/api/v1/app").
|
||||
JSON(&models.AppServer{
|
||||
Name: "test",
|
||||
Addr: "localhost",
|
||||
Port: "1546",
|
||||
}).
|
||||
Expect(s.T()).
|
||||
Assert(jsonpath.Equal(`$.message`, "success")).
|
||||
Status(http.StatusOK).End()
|
||||
}
|
||||
|
||||
func (s *servicesSuite) TestServiceList() {
|
||||
s.api().
|
||||
Debug().Report(apitest.SequenceDiagram()).
|
||||
Get("/api/v1/app/test/services").
|
||||
Expect(s.T()).
|
||||
Assert(jsonpath.Equal(`$.message`, "success")).
|
||||
Status(http.StatusOK).
|
||||
End()
|
||||
}
|
144
api/sessions.go
Normal file
144
api/sessions.go
Normal file
@ -0,0 +1,144 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/khorevaa/kubodin/service"
|
||||
)
|
||||
|
||||
type sessionsApi struct {
|
||||
service service.Service
|
||||
}
|
||||
|
||||
func (a *sessionsApi) Routes(r fiber.Router) {
|
||||
|
||||
r.Get("/sessions", withClient(a.List))
|
||||
//r.Get("/sessions/:session", withClient(a.Info))
|
||||
r.Delete("/sessions/:session", withClient(a.TerminateOne))
|
||||
|
||||
r.Post("/sessions/terminate", withClient(a.Terminate))
|
||||
|
||||
}
|
||||
|
||||
// List получение списка сессий на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary получение списка сессий на кластере
|
||||
// @Description получение списка сессий на кластере
|
||||
// @Tags sessions
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=serialize.SessionInfoList}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/clusters/{cluster}/sessions [get]
|
||||
func (a *sessionsApi) List(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
|
||||
return NoAllowResponse(ctx)
|
||||
|
||||
}
|
||||
|
||||
// List получение списка сессий информационной базы на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary получение списка сессий информационной базы на кластере
|
||||
// @Description получение списка сессий информационной базы на кластере
|
||||
// @Tags sessions
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param infobase path string true "infobase uuid or name"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=serialize.SessionInfoList}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/clusters/{cluster}/infobases/{infobase}/sessions [get]
|
||||
func (a *sessionsApi) ListInfobase() {}
|
||||
|
||||
// List получение списка сессий информационной базы на сервере 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary получение списка сессий информационной базы на сервере 1С Предприятие
|
||||
// @Description получение списка сессий информационной базы на сервере 1С Предприятие
|
||||
// @Tags sessions
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param infobase path string true "infobase uuid or name"
|
||||
// @Param cluster-id query string false "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=serialize.SessionInfoList}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/infobases/{infobase}/sessions [get]
|
||||
func (a *sessionsApi) ListAppInfobase() {}
|
||||
|
||||
// List получение списка сессий на сервере 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary получение списка сессий на сервере 1С Предприятие
|
||||
// @Description получение списка сессий на сервере 1С Предприятие
|
||||
// @Tags sessions
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster-id query string false "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response{data=serialize.SessionInfoList}
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/sessions [get]
|
||||
func (a *sessionsApi) ListApp() {}
|
||||
|
||||
func (a *sessionsApi) Info(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
return NoAllowResponse(ctx)
|
||||
|
||||
}
|
||||
|
||||
func (a *sessionsApi) Terminate(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
return NoAllowResponse(ctx)
|
||||
}
|
||||
|
||||
// TerminateOne отключение сессии на кластере
|
||||
// Swagger-spec:
|
||||
// @Summary отключение сессии на кластере
|
||||
// @Description отключение сессии на кластере
|
||||
// @Tags sessions
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param cluster path string true "cluster uuid"
|
||||
// @Param session path string true "session uuid"
|
||||
// @Param msg query string false "message to user"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/clusters/{cluster}/sessions/{session} [delete]
|
||||
func (a *sessionsApi) TerminateOne(client service.ClientContext, ctx *fiber.Ctx) error {
|
||||
|
||||
return NoAllowResponse(ctx)
|
||||
}
|
||||
|
||||
// TerminateOne отключение сессии на сервер 1С Предприятие
|
||||
// Swagger-spec:
|
||||
// @Summary отключение сессии на сервер 1С Предприятие
|
||||
// @Description отключение сессии на сервер 1С Предприятие
|
||||
// @Tags sessions
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param app path string true "app name"
|
||||
// @Param session path string true "session uuid"
|
||||
// @Param msg query string false "message to user"
|
||||
// @Param cluster-id query string false "cluster uuid"
|
||||
// @Param cluster-usr query string false "cluster user"
|
||||
// @Param cluster-pwd query string false "cluster password"
|
||||
// @Param force query bool false "force update ignore cache"
|
||||
// @Success 200 {object} Response
|
||||
// @Failure 500 {object} Response
|
||||
// @Router /app/{app}/sessions/{session} [delete]
|
||||
func (a *sessionsApi) TerminateOneApp() {}
|
@ -1,19 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var Commands = []Command{
|
||||
|
||||
&someCommand{},
|
||||
//&commandWithSub{
|
||||
// sub: []Command{
|
||||
// &subCommand{},
|
||||
// },
|
||||
//},
|
||||
}
|
||||
|
||||
type Command interface {
|
||||
Cmd() *cli.Command
|
||||
}
|
262
cmd/mainCommand.go
Normal file
262
cmd/mainCommand.go
Normal file
@ -0,0 +1,262 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gofiber/fiber/v2/middleware/pprof"
|
||||
"github.com/khorevaa/kubodin/api"
|
||||
db "github.com/khorevaa/kubodin/database"
|
||||
"github.com/khorevaa/kubodin/models"
|
||||
"github.com/khorevaa/kubodin/service"
|
||||
"github.com/khorevaa/kubodin/service/cache"
|
||||
"github.com/mattn/go-colorable"
|
||||
"github.com/mattn/go-isatty"
|
||||
"github.com/urfave/cli/v2"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
swagger "github.com/arsmn/fiber-swagger/v2"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/middleware/logger"
|
||||
rec "github.com/gofiber/fiber/v2/middleware/recover"
|
||||
|
||||
_ "github.com/khorevaa/kubodin/docs" // docs is generated by Swag CLI, you have to import it.
|
||||
)
|
||||
|
||||
type MainCommand struct {
|
||||
debug bool
|
||||
port string
|
||||
|
||||
appServer string
|
||||
|
||||
Version string
|
||||
BuildBy string
|
||||
Date string
|
||||
}
|
||||
|
||||
func (c *MainCommand) Run(context *cli.Context) error {
|
||||
|
||||
server := fiber.New(fiber.Config{
|
||||
DisableStartupMessage: true,
|
||||
})
|
||||
memoryCache := &cache.Memory{
|
||||
Expiration: 30 * time.Minute,
|
||||
}
|
||||
memoryCache.Connect()
|
||||
|
||||
rep := db.NewMemoryRepository()
|
||||
|
||||
addr, port := parseAddr(c.appServer)
|
||||
|
||||
err := rep.AddAppServer(models.AppServer{
|
||||
Name: "default",
|
||||
Addr: addr,
|
||||
Port: port,
|
||||
Description: "default app server",
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Println("ERROR: Connect to ras server")
|
||||
}
|
||||
|
||||
serv, err := service.NewService(memoryCache, rep)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Middleware
|
||||
server.Use(rec.New())
|
||||
server.Use(service.Middleware(serv))
|
||||
|
||||
if c.debug {
|
||||
server.Use(logger.New())
|
||||
server.Use(pprof.New())
|
||||
}
|
||||
|
||||
api.Routes(server, serv)
|
||||
|
||||
server.Use("/docs", swagger.Handler) // default
|
||||
|
||||
// Handle not founds
|
||||
server.Use(api.NotFound)
|
||||
|
||||
go func() {
|
||||
c.startupMessage(c.port, false, c.debug, serv)
|
||||
log.Fatal(server.Listen(c.port)) // go run main.go -port=:3000
|
||||
}()
|
||||
|
||||
gracefullyShutdownInit(server)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *MainCommand) Flags() []cli.Flag {
|
||||
|
||||
return []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Destination: &c.port, Name: "port",
|
||||
Value: "localhost:3001", Usage: "port to listen on"},
|
||||
&cli.StringFlag{
|
||||
Destination: &c.appServer, Name: "server",
|
||||
Value: "localhost:1545", Usage: "ras client address with port"},
|
||||
&cli.BoolFlag{
|
||||
Destination: &c.debug, Name: "debug",
|
||||
Value: false, Usage: "debug mode"},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *MainCommand) startupMessage(addr string, tls bool, debug bool, serv service.Service) {
|
||||
|
||||
if len(os.Getenv("FIBER_PREFORK_CHILD")) > 0 {
|
||||
// Для подчиненных процессов мы не выводим сообщение
|
||||
return
|
||||
}
|
||||
|
||||
var logo string
|
||||
logo += "%s"
|
||||
logo += " ┌───────────────────────────────────────────────────┐\n"
|
||||
logo += " │ %s │\n"
|
||||
logo += " │ %s │\n"
|
||||
logo += " │ %s │\n"
|
||||
logo += " │ %s │\n"
|
||||
logo += " │ %s │\n"
|
||||
logo += " │ %s │\n"
|
||||
logo += " │ │\n"
|
||||
logo += " │ Built by: %s Built at: %s │\n"
|
||||
logo += " │ Cache: %s DB: %s │\n"
|
||||
logo += " └───────────────────────────────────────────────────┘"
|
||||
logo += "%s"
|
||||
|
||||
const (
|
||||
cBlack = "\u001b[90m"
|
||||
// cRed = "\u001b[91m"
|
||||
cCyan = "\u001b[96m"
|
||||
// cGreen = "\u001b[92m"
|
||||
cYellow = "\u001b[93m"
|
||||
// cBlue = "\u001b[94m"
|
||||
// cMagenta = "\u001b[95m"
|
||||
// cWhite = "\u001b[97m"
|
||||
cReset = "\u001b[0m"
|
||||
)
|
||||
|
||||
value := func(s string, width int) string {
|
||||
pad := width - len(s)
|
||||
str := ""
|
||||
for i := 0; i < pad; i++ {
|
||||
str += "."
|
||||
}
|
||||
if s == "Disabled" {
|
||||
str += " " + s
|
||||
} else {
|
||||
str += fmt.Sprintf(" %s%s%s", cYellow, s, cBlack)
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
center := func(s string, width int) string {
|
||||
pad := strconv.Itoa((width - len(s)) / 2)
|
||||
str := fmt.Sprintf("%"+pad+"s", " ")
|
||||
str += s
|
||||
str += fmt.Sprintf("%"+pad+"s", " ")
|
||||
if len(str) < width {
|
||||
str += " "
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
centerValue := func(s string, width int) string {
|
||||
pad := strconv.Itoa((width - len(s)) / 2)
|
||||
str := fmt.Sprintf("%"+pad+"s", " ")
|
||||
str += fmt.Sprintf("%s%s%s", cCyan, s, cBlack)
|
||||
str += fmt.Sprintf("%"+pad+"s", " ")
|
||||
if len(str)-10 < width {
|
||||
str += " "
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
host, port := parseAddr(addr)
|
||||
if host == "" || host == "0.0.0.0" {
|
||||
host = "127.0.0.1"
|
||||
}
|
||||
addr = "http://" + host + ":" + port
|
||||
if tls {
|
||||
addr = "https://" + host + ":" + port
|
||||
}
|
||||
|
||||
t, _ := time.Parse(time.RFC3339, c.Date)
|
||||
|
||||
cacheInfo := "redis"
|
||||
switch serv.GetCache().(type) {
|
||||
case *cache.Memory:
|
||||
cacheInfo = "in memory"
|
||||
}
|
||||
|
||||
dbInfo := "pudge"
|
||||
pprofInfo := ""
|
||||
if debug {
|
||||
pprofInfo = " Pprof: " + addr + "/debug/pprof"
|
||||
}
|
||||
|
||||
switch serv.Repository().(type) {
|
||||
case *db.InMemory:
|
||||
dbInfo = "in memory"
|
||||
}
|
||||
|
||||
mainLogo := fmt.Sprintf(logo,
|
||||
cBlack,
|
||||
centerValue(" KUBODIN "+c.Version, 49),
|
||||
center("Remote Administration", 49),
|
||||
center("for 1S.Enterprise Application Servers", 49),
|
||||
centerValue(" API: "+addr+"/api/v1", 49),
|
||||
centerValue(" Docs: "+addr+"/docs", 49),
|
||||
centerValue(pprofInfo, 49),
|
||||
value(c.BuildBy, 13), value(t.Format("2006-01-02"), 13),
|
||||
value(cacheInfo, 16), value(dbInfo, 19),
|
||||
cReset,
|
||||
)
|
||||
|
||||
out := colorable.NewColorableStdout()
|
||||
if os.Getenv("TERM") == "dumb" ||
|
||||
(!isatty.IsTerminal(os.Stdout.Fd()) &&
|
||||
!isatty.IsCygwinTerminal(os.Stdout.Fd())) {
|
||||
out = colorable.NewNonColorable(os.Stdout)
|
||||
}
|
||||
|
||||
fmt.Fprintln(out, mainLogo)
|
||||
}
|
||||
|
||||
func parseAddr(raw string) (host, port string) {
|
||||
if i := strings.LastIndex(raw, ":"); i != -1 {
|
||||
return raw[:i], raw[i+1:]
|
||||
}
|
||||
return raw, ""
|
||||
}
|
||||
|
||||
func gracefullyShutdownInit(app *fiber.App) {
|
||||
|
||||
// Wait for interrupt signal to gracefully shutdown the server with
|
||||
// setup signal catching
|
||||
quit := make(chan os.Signal, 1)
|
||||
// catch all signals since not explicitly listing
|
||||
signal.Notify(quit, syscall.SIGQUIT, os.Interrupt, os.Kill)
|
||||
|
||||
q := <-quit
|
||||
|
||||
if q != nil {
|
||||
println(fmt.Sprintf("RECEIVED SIGNAL: %s", q))
|
||||
}
|
||||
|
||||
println("Shutdown Server ...")
|
||||
if err := app.Shutdown(); err != nil {
|
||||
log.Println("Server Shutdown:", err)
|
||||
}
|
||||
time.Sleep(2 * time.Second)
|
||||
_ = cli.Exit("Shutdown complete", 0)
|
||||
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
type someCommand struct {
|
||||
}
|
||||
|
||||
func (c *someCommand) run(context *cli.Context) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *someCommand) Cmd() *cli.Command {
|
||||
|
||||
cmd := &cli.Command{
|
||||
//Category: "some_category",
|
||||
Name: "some_command",
|
||||
Usage: "Usage decription",
|
||||
Description: `Full usage description `,
|
||||
Action: c.run,
|
||||
Flags: []cli.Flag{
|
||||
//&cli.StringFlag{
|
||||
// Destination: &c.cluster, Name: "cluster-id",
|
||||
// Value: "", Usage: "cluster uuid for join new work server"},
|
||||
//&cli.StringFlag{
|
||||
// Destination: &c.Name, Name: "name", Aliases: []string{"N"},
|
||||
// Value: "", Usage: "work server name", EnvVars: []string{"SERVER_NAME"}, Required: true},
|
||||
//&cli.StringFlag{
|
||||
// Destination: &c.AgentHost, Name: "host",
|
||||
// Value: "", Usage: "work server agent host", EnvVars: []string{"SERVER_AGENT_HOST"}, Required: true},
|
||||
//&cli.IntFlag{
|
||||
// Destination: &c.AgentPort, Name: "port",
|
||||
// Value: 1540, Usage: "work server agent port", EnvVars: []string{"SERVER_AGENT_HOST"}, DefaultText: "1540"},
|
||||
//&cli.StringFlag{
|
||||
// Destination: &c.PortRange, Name: "port-range",
|
||||
// Value: "1560:1591", Usage: "work server port range", EnvVars: []string{"SERVER_PORT_RANGE"}, DefaultText: "1560:1591"},
|
||||
//&cli.StringFlag{
|
||||
// Destination: &c.Using, Name: "using",
|
||||
// Value: "normal", Usage: "variant of using work server (main, normal)", EnvVars: []string{"SERVER_USING"}, DefaultText: "normal"},
|
||||
//&cli.StringFlag{
|
||||
// Destination: &c.DedicateManagers, Name: "dedicate-managers",
|
||||
// Value: "none", Usage: "вариант размещения менеджеров сервисов (all, none)", EnvVars: []string{"SERVER_DEDICATE_MANAGERS"}, DefaultText: "none"},
|
||||
//&cli.IntFlag{
|
||||
// Destination: &c.ClusterPort, Name: "cluster-port",
|
||||
// Value: 1541, Usage: "номер порта главного менеджера кластера", EnvVars: []string{"SERVER_CLUSTER_PORT"}, DefaultText: "1541"},
|
||||
//&cli.Int64Flag{
|
||||
// Destination: &c.MemoryLimit, Name: "memory-limit",
|
||||
// Value: 0, Usage: "предел использования памяти рабочими процессами (kilobytes)", EnvVars: []string{"SERVER_MEMORY_LIMIT"}},
|
||||
//&cli.Int64Flag{
|
||||
// Destination: &c.ConnectionsLimit, Name: "connections-limit",
|
||||
// Value: 128, Usage: "максимальное количество соединения на рабочий процесс", EnvVars: []string{"SERVER_CONNECTIONS_LIMIT"}, DefaultText: "128"},
|
||||
//&cli.Int64Flag{
|
||||
// Destination: &c.CriticalTotalMemory, Name: "total-memory",
|
||||
// Value: 0, Usage: "максимальный объем памяти процессов рабочего сервера (bytes)", EnvVars: []string{"SERVER_TOTAL_MEMORY"}},
|
||||
},
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
55
database/app.go
Normal file
55
database/app.go
Normal file
@ -0,0 +1,55 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/khorevaa/kubodin/errors"
|
||||
|
||||
"github.com/khorevaa/kubodin/models"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Repository interface {
|
||||
GetAppServers() (apps []*models.AppServer, err error)
|
||||
GetAppServer(name string) (*models.AppServer, error)
|
||||
AddAppServer(app models.AppServer) error
|
||||
DeleteAppServer(appName string) error
|
||||
Db() string
|
||||
Clear() error
|
||||
}
|
||||
|
||||
var (
|
||||
ErrorNotFound = errors.Internal.New("app by id not found")
|
||||
)
|
||||
|
||||
func prepareAppServer(app *models.AppServer) error {
|
||||
|
||||
if len(app.Port) == 0 {
|
||||
app.Port = "1545"
|
||||
}
|
||||
|
||||
if len(app.Name) == 0 {
|
||||
app.Name = app.Addr
|
||||
}
|
||||
|
||||
client, err := app.Client()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, _ := context.WithTimeout(context.Background(), time.Second*10)
|
||||
|
||||
version, err := client.GetAgentVersion(ctx)
|
||||
app.Version = client.Version()
|
||||
|
||||
if err != nil {
|
||||
// При первом получении версии только определяется версия сервиса.
|
||||
// Надо ждать изменений в ras-client, получение версии сервиса в отдельном потоке, а не с первой папыткой открытия endpoint
|
||||
version, err = client.GetAgentVersion(ctx)
|
||||
|
||||
}
|
||||
|
||||
app.AgentVersion = version
|
||||
|
||||
return err
|
||||
}
|
75
database/memory.go
Normal file
75
database/memory.go
Normal file
@ -0,0 +1,75 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"github.com/khorevaa/kubodin/models"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var _ Repository = (*InMemory)(nil)
|
||||
|
||||
type InMemory struct {
|
||||
m *sync.Map
|
||||
}
|
||||
|
||||
func (i *InMemory) GetAppServers() (apps []*models.AppServer, err error) {
|
||||
|
||||
i.m.Range(func(_, val interface{}) bool {
|
||||
app := val.(models.AppServer)
|
||||
apps = append(apps, &app)
|
||||
return true
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (i *InMemory) GetAppServer(name string) (*models.AppServer, error) {
|
||||
app, ok := i.m.Load(name)
|
||||
if !ok {
|
||||
return nil, ErrorNotFound
|
||||
}
|
||||
|
||||
appServer := app.(models.AppServer)
|
||||
|
||||
return &appServer, nil
|
||||
}
|
||||
|
||||
func (i InMemory) SetAppServer(app models.AppServer) error {
|
||||
|
||||
i.m.Store(app.Name, app)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *InMemory) AddAppServer(app models.AppServer) error {
|
||||
|
||||
err := prepareAppServer(&app)
|
||||
|
||||
i.m.Store(app.Name, app)
|
||||
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
func (i *InMemory) DeleteAppServer(appName string) error {
|
||||
_, ok := i.m.LoadAndDelete(appName)
|
||||
if !ok {
|
||||
return ErrorNotFound
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *InMemory) Db() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (i *InMemory) Clear() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewMemoryRepository() Repository {
|
||||
|
||||
return &InMemory{
|
||||
m: &sync.Map{},
|
||||
}
|
||||
|
||||
}
|
6815
docs/docs.go
Normal file
6815
docs/docs.go
Normal file
File diff suppressed because it is too large
Load Diff
6753
docs/swagger.json
Normal file
6753
docs/swagger.json
Normal file
File diff suppressed because it is too large
Load Diff
4347
docs/swagger.yaml
Normal file
4347
docs/swagger.yaml
Normal file
File diff suppressed because it is too large
Load Diff
178
errors/error.go
Normal file
178
errors/error.go
Normal file
@ -0,0 +1,178 @@
|
||||
package errors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
_ error = (*Error)(nil)
|
||||
)
|
||||
|
||||
type Kind uint
|
||||
|
||||
const (
|
||||
Other Kind = iota // Unclassified error. This value is not printed in the error message.
|
||||
Invalid // Invalid operation for this type of item.
|
||||
Permission // Permission denied.
|
||||
IO // External I/O error such as network failure.
|
||||
Exist // Item already exists.
|
||||
Private // Information withheld.
|
||||
Internal // Internal error or inconsistency.
|
||||
Timeout // Link target does not exist.
|
||||
Codec
|
||||
BadRequest
|
||||
BadCommand
|
||||
Runtime
|
||||
|
||||
ToManyClusters
|
||||
ToManyInfobases
|
||||
)
|
||||
|
||||
type ErrorType uint
|
||||
|
||||
func (k Kind) String() string {
|
||||
switch k {
|
||||
case Other:
|
||||
return "other error"
|
||||
case Invalid:
|
||||
return "invalid operation"
|
||||
case Permission:
|
||||
return "permission denied"
|
||||
case IO:
|
||||
return "I/O error"
|
||||
case Exist:
|
||||
return "item already exists"
|
||||
case Private:
|
||||
return "information withheld"
|
||||
case Internal:
|
||||
return "internal error"
|
||||
case Codec:
|
||||
return "codec error"
|
||||
case Timeout:
|
||||
return "timeout error"
|
||||
case BadRequest:
|
||||
return "bad request"
|
||||
}
|
||||
return "unknown error kind"
|
||||
}
|
||||
|
||||
type Error struct {
|
||||
kind Kind
|
||||
err error
|
||||
contextInfo errorContext
|
||||
}
|
||||
|
||||
type errorContext struct {
|
||||
Field string
|
||||
Message string
|
||||
}
|
||||
|
||||
func (e Error) Error() string {
|
||||
return e.err.Error()
|
||||
}
|
||||
|
||||
func (e Error) WithContext(field, message string) error {
|
||||
|
||||
context := errorContext{Field: field, Message: message}
|
||||
return Error{kind: e.kind, err: e.err, contextInfo: context}
|
||||
|
||||
}
|
||||
|
||||
func (e *Error) IsZero() bool {
|
||||
return e.err == nil && e.kind == 0
|
||||
}
|
||||
|
||||
// New creates a new Error
|
||||
func (e Kind) New(msg string) Error {
|
||||
return Error{kind: e, err: errors.New(msg)}
|
||||
}
|
||||
|
||||
// New creates a new Error with formatted message
|
||||
func (e Kind) Newf(msg string, args ...interface{}) Error {
|
||||
err := fmt.Errorf(msg, args...)
|
||||
|
||||
return Error{kind: e, err: err}
|
||||
}
|
||||
|
||||
// Wrap creates a new wrapped error
|
||||
func (e Kind) Wrap(err error, msg string) Error {
|
||||
return e.Wrapf(err, msg)
|
||||
}
|
||||
|
||||
// Wrap creates a new wrapped error with formatted message
|
||||
func (e Kind) Wrapf(err error, msg string, args ...interface{}) Error {
|
||||
newErr := errors.Wrapf(err, msg, args...)
|
||||
|
||||
return Error{kind: e, err: newErr}
|
||||
}
|
||||
|
||||
// Cause gives the original error
|
||||
func Cause(err error) error {
|
||||
return errors.Cause(err)
|
||||
}
|
||||
|
||||
// Wrapf wraps an error with format string
|
||||
func Wrapf(err error, msg string, args ...interface{}) error {
|
||||
|
||||
if err == nil {
|
||||
return err
|
||||
}
|
||||
|
||||
wrappedError := errors.Wrapf(err, msg, args...)
|
||||
if customErr, ok := err.(Error); ok {
|
||||
return Error{
|
||||
kind: customErr.kind,
|
||||
err: wrappedError,
|
||||
contextInfo: customErr.contextInfo,
|
||||
}
|
||||
}
|
||||
|
||||
return Error{kind: Other, err: wrappedError}
|
||||
}
|
||||
|
||||
// AddErrorContext adds a context to an error
|
||||
func AddErrorContext(err error, field, message string) error {
|
||||
context := errorContext{Field: field, Message: message}
|
||||
if customErr, ok := err.(Error); ok {
|
||||
return Error{kind: customErr.kind, err: customErr.err, contextInfo: context}
|
||||
}
|
||||
|
||||
return Error{kind: Other, err: err, contextInfo: context}
|
||||
}
|
||||
|
||||
// GetErrorContext returns the error context
|
||||
func GetErrorContext(err error) map[string]string {
|
||||
emptyContext := errorContext{}
|
||||
if customErr, ok := err.(Error); ok || customErr.contextInfo != emptyContext {
|
||||
|
||||
return map[string]string{"field": customErr.contextInfo.Field, "message": customErr.contextInfo.Message}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetType returns the error type
|
||||
func GetType(err error) Kind {
|
||||
if customErr, ok := err.(Error); ok {
|
||||
return customErr.kind
|
||||
}
|
||||
|
||||
return Other
|
||||
}
|
||||
|
||||
// Is reports whether err is an *Error of the given Kind.
|
||||
// If err is nil then Is returns false.
|
||||
func Is(kind Kind, err error) bool {
|
||||
e, ok := err.(*Error)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if e.kind != Other {
|
||||
return e.kind == kind
|
||||
}
|
||||
if e.err != nil {
|
||||
return Is(kind, e.err)
|
||||
}
|
||||
return false
|
||||
}
|
23
go.mod
Normal file
23
go.mod
Normal file
@ -0,0 +1,23 @@
|
||||
module github.com/khorevaa/kubodin
|
||||
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
|
||||
github.com/arsmn/fiber-swagger/v2 v2.3.0
|
||||
github.com/gofiber/fiber/v2 v2.5.0
|
||||
github.com/khorevaa/ras-client v0.0.0-20201104084928-a9228766f6ed
|
||||
github.com/mattn/go-colorable v0.1.8
|
||||
github.com/mattn/go-isatty v0.0.12
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/recoilme/pudge v1.0.3
|
||||
github.com/satori/go.uuid v1.2.0
|
||||
github.com/steinfletcher/apitest v1.5.2
|
||||
github.com/steinfletcher/apitest-jsonpath v1.6.0
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/swaggo/swag v1.7.0
|
||||
github.com/urfave/cli/v2 v2.3.0
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091 // indirect
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e // indirect
|
||||
)
|
171
go.sum
Normal file
171
go.sum
Normal file
@ -0,0 +1,171 @@
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
|
||||
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
|
||||
github.com/PaesslerAG/gval v1.0.0 h1:GEKnRwkWDdf9dOmKcNrar9EA1bz1z9DqPIO1+iLzhd8=
|
||||
github.com/PaesslerAG/gval v1.0.0/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I=
|
||||
github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8=
|
||||
github.com/PaesslerAG/jsonpath v0.1.1 h1:c1/AToHQMVsduPAa4Vh6xp2U0evy4t8SWp8imEsylIk=
|
||||
github.com/PaesslerAG/jsonpath v0.1.1/go.mod h1:lVboNxFGal/VwW6d9JzIy56bUsYAP6tH/x80vjnCseY=
|
||||
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/andybalholm/brotli v1.0.1 h1:KqhlKozYbRtJvsPrrEeXcO+N2l6NYT5A2QAFmSULpEc=
|
||||
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/arsmn/fiber-swagger/v2 v2.3.0 h1:FC6RvYCBQlV0rbAEuCgxHilWLLNGmN8ClFRlY5l8RSs=
|
||||
github.com/arsmn/fiber-swagger/v2 v2.3.0/go.mod h1:bScnIE8qvQF5/wvsewuwXPkLN23eGQZqqNIyBA6Xd2E=
|
||||
github.com/asaskevich/EventBus v0.0.0-20200907212545-49d423059eef/go.mod h1:JS7hed4L1fj0hXcyEejnW57/7LCetXggd+vwrRnYeII=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
|
||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonreference v0.19.4/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
|
||||
github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM=
|
||||
github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
|
||||
github.com/go-openapi/spec v0.19.14/go.mod h1:gwrgJS15eCUgjLpMjBJmbZezCsw88LmgeEip0M63doA=
|
||||
github.com/go-openapi/spec v0.20.0 h1:HGLc8AJ7ynOxwv0Lq4TsnwLsWMawHAYiJIFzbcML86I=
|
||||
github.com/go-openapi/spec v0.20.0/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFutcFKaVbmU=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.11/go.mod h1:Uc0gKkdR+ojzsEpjh39QChyu92vPgIr72POcgHMAgSY=
|
||||
github.com/go-openapi/swag v0.19.12 h1:Bc0bnY2c3AoF7Gc+IMIAQQsD8fLHjHpc19wXvYuayQI=
|
||||
github.com/go-openapi/swag v0.19.12/go.mod h1:eFdyEBkTdoAf/9RXBvj4cr1nH7GD8Kzo5HTt47gr72M=
|
||||
github.com/gofiber/fiber/v2 v2.3.0/go.mod h1:f8BRRIMjMdRyt2qmJ/0Sea3j3rwwfufPrh9WNBRiVZ0=
|
||||
github.com/gofiber/fiber/v2 v2.5.0 h1:yml405Um7b98EeMjx63OjSFTATLmX985HPWFfNUPV0w=
|
||||
github.com/gofiber/fiber/v2 v2.5.0/go.mod h1:f8BRRIMjMdRyt2qmJ/0Sea3j3rwwfufPrh9WNBRiVZ0=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
|
||||
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 h1:uC1QfSlInpQF+M0ao65imhwqKnz3Q2z/d8PWZRMQvDM=
|
||||
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
|
||||
github.com/k0kubun/pp v3.0.1+incompatible h1:3tqvf7QgUnZ5tXO6pNAZlrvHgl6DvifjDrd9g2S9Z40=
|
||||
github.com/k0kubun/pp v3.0.1+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg=
|
||||
github.com/k0kubun/pp/v3 v3.0.3/go.mod h1:2ol0zQBSPTermAo8igHVJ4d5vTiNmBkCrUdu7wZp4aI=
|
||||
github.com/khorevaa/ras-client v0.0.0-20201104084928-a9228766f6ed h1:D02yuRwXP5R0p1OkmCsaJ7REhuRG0NI1lcLHfr7M8vI=
|
||||
github.com/khorevaa/ras-client v0.0.0-20201104084928-a9228766f6ed/go.mod h1:GYAPHlMkTyZdkgqNWmCfwWsAS8BQfBjxg2r3yQ3rQnY=
|
||||
github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.11.3 h1:dB4Bn0tN3wdCzQxnS8r06kV74qN/TAfaIS0bVE8h3jc=
|
||||
github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
|
||||
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/recoilme/pudge v1.0.3 h1:h/9dEv5fRqtzM4lnO69kUoN+k7ukxxrW9NGb9ug0grM=
|
||||
github.com/recoilme/pudge v1.0.3/go.mod h1:VMvxBLVkrSStldckzCsETBXox3pfovfrnEchafXk8qA=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/steinfletcher/apitest v1.4.10/go.mod h1:0MT98QwexQVvf5pIn3fqiC/+8Nyd7A4RShxuSjnpOcE=
|
||||
github.com/steinfletcher/apitest v1.5.2 h1:o5R0km8ZI6xooSDwsHdDCD9OpEXda7CJeQwyoSrJmPM=
|
||||
github.com/steinfletcher/apitest v1.5.2/go.mod h1:TrZemFOZ1yNgKoAeAsth3Z3vEavTloE1hP/U2PSd3w0=
|
||||
github.com/steinfletcher/apitest-jsonpath v1.6.0 h1:9LsuXIw6Kn66n59UZ8aSvx3AwXNeKW70c/Ds4dU2SL4=
|
||||
github.com/steinfletcher/apitest-jsonpath v1.6.0/go.mod h1:0XJfDbARuf72hqzj5rPz2ou5rZRJkvbFGFuR+OVosO4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14 h1:PyYN9JH5jY9j6av01SpfRMb+1DWg/i3MbGOKPxJ2wjM=
|
||||
github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14/go.mod h1:gxQT6pBGRuIGunNf/+tSOB5OHvguWi8Tbt82WOkf35E=
|
||||
github.com/swaggo/swag v1.7.0 h1:5bCA/MTLQoIqDXXyHfOpMeDvL9j68OY/udlK4pQoo4E=
|
||||
github.com/swaggo/swag v1.7.0/go.mod h1:BdPIL73gvS9NBsdi7M1JOxLvlbfvNRaBP8m6WT6Aajo=
|
||||
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
|
||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||
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/fasthttp v1.18.0 h1:IV0DdMlatq9QO1Cr6wGJPVW1sV1Q8HvZXAIcjorylyM=
|
||||
github.com/valyala/fasthttp v1.18.0/go.mod h1:jjraHZVbKOXftJfsOYoAjaeygpj5hr8ermTRJNroD7A=
|
||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a h1:0R4NLDRDZX6JcmhJgXi5E4b8Wg84ihbmUKp/GvSPEzc=
|
||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||
github.com/xelaj/go-dry v0.0.0-20201004191957-aab3eecf0604 h1:lg5YBv2+xr3j2lfcfahTa+9msjETFlB/b9cRBOe5A/8=
|
||||
github.com/xelaj/go-dry v0.0.0-20201004191957-aab3eecf0604/go.mod h1:6rEJfrv43LMiKiRYh7Zzhv6eystOVUhoYa2YCq2gI4k=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE=
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.0 h1:8pl+sMODzuvGJkmj2W4kZihvVb5mKm8pB/X44PIQHv8=
|
||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201016165138-7b1cca2348c0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201216054612-986b41b23924 h1:QsnDpLLOKwHBBDa8nDws4DYNc/ryVW2vCpxCs09d4PY=
|
||||
golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201210223839-7e3030f88018/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091 h1:DMyOG0U+gKfu8JZzg2UQe9MeaC1X+xQWlAKcRnjxjCw=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20201120155355-20be4ac4bd6e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201217165654-008e477491be/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e h1:4nW4NLDYnU28ojHaHO8OVxFHk/aQ33U01a9cjED+pzE=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
51
main.go
51
main.go
@ -1,7 +1,8 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/khorevaa/go-app-template/cmd"
|
||||
"fmt"
|
||||
"github.com/khorevaa/kubodin/cmd"
|
||||
"github.com/urfave/cli/v2"
|
||||
"log"
|
||||
"os"
|
||||
@ -15,23 +16,38 @@ var (
|
||||
builtBy = ""
|
||||
)
|
||||
|
||||
// main
|
||||
// @title KUBOdin: Remote Administration for 1S.Enterprise Application Servers
|
||||
// @version 1.0
|
||||
// @description KUBOdin Swagger UI
|
||||
// @termsOfService http://swagger.io/terms/
|
||||
// @contact.name API Support
|
||||
// @contact.email khorevaa@yandex.ru
|
||||
// @license.name Apache 2.0
|
||||
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
// @host localhost:3001
|
||||
// @BasePath /api/v1
|
||||
func main() {
|
||||
|
||||
app := &cli.App{
|
||||
Name: "go-app-template",
|
||||
mainCmd := &cmd.MainCommand{
|
||||
Version: version,
|
||||
BuildBy: builtBy,
|
||||
Date: date,
|
||||
}
|
||||
|
||||
app := &cli.App{
|
||||
Name: "kubodin",
|
||||
Version: buildVersion(),
|
||||
Authors: []*cli.Author{
|
||||
{
|
||||
Name: "Aleksey Khorev",
|
||||
},
|
||||
},
|
||||
Usage: "Description for go-app-template",
|
||||
Copyright: "(c) 2021 Khorevaa",
|
||||
//Description: "Command line utilities for server 1S.Enterprise",
|
||||
}
|
||||
|
||||
for _, command := range cmd.Commands {
|
||||
app.Commands = append(app.Commands, command.Cmd())
|
||||
Usage: "Start API server for kubernetes & 1C.Enterprise",
|
||||
Copyright: "(c) 2021 Khorevaa",
|
||||
Description: "API server for Kubernetes & 1C.Enterprise",
|
||||
Flags: mainCmd.Flags(),
|
||||
Action: mainCmd.Run,
|
||||
}
|
||||
|
||||
err := app.Run(os.Args)
|
||||
@ -39,3 +55,18 @@ func main() {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func buildVersion() string {
|
||||
var result = version
|
||||
if commit != "" {
|
||||
result = fmt.Sprintf("%s\ncommit: %s", result, commit)
|
||||
}
|
||||
if date != "" {
|
||||
result = fmt.Sprintf("%s\nbuilt at: %s", result, date)
|
||||
}
|
||||
if builtBy != "" {
|
||||
result = fmt.Sprintf("%s\nbuilt by: %s", result, builtBy)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
49
models/appServer.go
Normal file
49
models/appServer.go
Normal file
@ -0,0 +1,49 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/khorevaa/kubodin/ras"
|
||||
rclient "github.com/khorevaa/ras-client"
|
||||
"net"
|
||||
)
|
||||
|
||||
type AppServer struct {
|
||||
Name string `json:"name"`
|
||||
Addr string `json:"addr"`
|
||||
Port string `json:"port"`
|
||||
Version string `json:"version"`
|
||||
Description string `json:"descr,omitempty" yaml:"descr"`
|
||||
AgentUsr string `json:"agent_usr,omitempty"`
|
||||
AgentPwd string `json:"agent_pwd,omitempty"`
|
||||
AgentVersion string `json:"agent_version,omitempty"`
|
||||
Properties map[string]string `json:"properties,omitempty"`
|
||||
} // @Name AppServer
|
||||
|
||||
func (a *AppServer) init(api rclient.Api, inited bool) {
|
||||
if inited {
|
||||
return
|
||||
}
|
||||
|
||||
if len(a.AgentUsr) > 0 {
|
||||
api.AuthenticateAgent(a.AgentUsr, a.AgentPwd)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *AppServer) Client() (rclient.Api, error) {
|
||||
|
||||
api, inited := ras.LoadOrInit(a.Name, net.JoinHostPort(a.Addr, a.Port), a.Version)
|
||||
a.init(api, inited)
|
||||
|
||||
return api, nil
|
||||
}
|
||||
|
||||
func (a *AppServer) Reload() {
|
||||
|
||||
c, err := a.Client()
|
||||
if err == nil {
|
||||
_ = c.Close()
|
||||
}
|
||||
|
||||
api, inited := ras.Store(a.Name, net.JoinHostPort(a.Addr, a.Port), a.Version)
|
||||
a.init(api, inited)
|
||||
|
||||
}
|
37
models/blocker.go
Normal file
37
models/blocker.go
Normal file
@ -0,0 +1,37 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
uuid "github.com/satori/go.uuid"
|
||||
"time"
|
||||
)
|
||||
|
||||
type InfobaseBlocker struct {
|
||||
Infobase string `query:"infobase" json:"infobase" example:"testdb2"`
|
||||
ClusterID string `query:"cluster-id" json:"cluster_id" example:"80f7f2f6-2feb-46bf-92f4-19294a2f5dc7"`
|
||||
|
||||
Message string `query:"message" json:"message" example:"Обновление информационной базы"`
|
||||
PermissionCode string `query:"permission-code" json:"permission_code" example:"123"`
|
||||
DeniedParameter string `query:"denied-parameter" json:"denied_parameter" example:"code"`
|
||||
ScheduledJobsDeny bool `query:"scheduled-jobs-deny" json:"scheduled_jobs_deny"`
|
||||
SessionsDeny bool `query:"sessions-deny,required" json:"sessions_deny"`
|
||||
Reload bool `query:"reload" json:"reload"`
|
||||
DeniedFrom time.Time `query:"denied-from" json:"denied_from" example:"2020-10-01T08:30:00Z"`
|
||||
DeniedTo time.Time `query:"denied-to" json:"denied_to" example:"2020-10-01T08:30:00Z"`
|
||||
}
|
||||
|
||||
func (b *InfobaseBlocker) Empty() bool {
|
||||
return !b.SessionsDeny && b.DeniedFrom.IsZero() && b.DeniedTo.IsZero() &&
|
||||
len(b.Message) == 0 && len(b.PermissionCode) == 0
|
||||
}
|
||||
|
||||
type InfobaseUnblocker struct {
|
||||
Infobase string `query:"infobase-name" json:"infobase" example:"testdb2"`
|
||||
|
||||
InfobaseID uuid.UUID `query:"infobase-id" json:"infobase_id" example:"80f7f2f6-2feb-46bf-92f4-19294a2f5dc7"`
|
||||
ClusterID uuid.UUID `query:"cluster-id" json:"cluster_id" example:"80f7f2f6-2feb-46bf-92f4-19294a2f5dc7"`
|
||||
|
||||
PermissionCode string `query:"permission-code" json:"permission_code" example:""`
|
||||
DeniedParameter string `query:"denied-parameter" json:"denied_parameter" example:""`
|
||||
ScheduledJobsDeny bool `query:"scheduled-jobs-deny" json:"scheduled_jobs_deny"`
|
||||
SessionsDeny bool `query:"sessions-deny,required" json:"sessions_deny"`
|
||||
}
|
45
models/connectionSig.go
Normal file
45
models/connectionSig.go
Normal file
@ -0,0 +1,45 @@
|
||||
package models
|
||||
|
||||
import uuid "github.com/satori/go.uuid"
|
||||
|
||||
type ConnectionSig struct {
|
||||
ClusterID uuid.UUID `json:"cluster_id" example:"6d6958e1-a96c-4999-a995-698a0298161e"`
|
||||
InfobaseID uuid.UUID `json:"infobase_id" example:"6d6958e1-a96c-4999-a995-698a0298161e"`
|
||||
Process uuid.UUID `json:"process" example:"6d6958e1-a96c-4999-a995-698a0298161e"`
|
||||
UUID uuid.UUID `json:"uuid" example:"6d6958e1-a96c-4999-a995-698a0298161e"`
|
||||
}
|
||||
|
||||
type TerminateConnectionsRequest struct {
|
||||
InfobaseID string `json:"infobase_id" example:"6d6958e1-a96c-4999-a995-698a0298161e or testib2"`
|
||||
Connections []ConnectionSig `json:"connections"`
|
||||
}
|
||||
|
||||
type TerminateConnectionSig struct {
|
||||
ConnectionSig
|
||||
Terminated bool `json:"terminated" example:"false"`
|
||||
Err string `json:"err,omitempty" example:"error terminate connection"`
|
||||
}
|
||||
|
||||
type TerminateConnectionsResponse struct {
|
||||
Count int `json:"count" example:"0"`
|
||||
Connections []TerminateConnectionSig `json:"connections,omitempty"`
|
||||
}
|
||||
|
||||
func (r *TerminateConnectionsResponse) AddResult(sig ConnectionSig, err error) {
|
||||
|
||||
msg := ""
|
||||
terminated := true
|
||||
|
||||
if err != nil {
|
||||
terminated = false
|
||||
msg = err.Error()
|
||||
}
|
||||
|
||||
r.Connections = append(r.Connections, TerminateConnectionSig{
|
||||
ConnectionSig: sig,
|
||||
Terminated: terminated,
|
||||
Err: msg,
|
||||
})
|
||||
|
||||
r.Count++
|
||||
}
|
72
ras/client.go
Normal file
72
ras/client.go
Normal file
@ -0,0 +1,72 @@
|
||||
package ras
|
||||
|
||||
import (
|
||||
rclient "github.com/khorevaa/ras-client"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Storage interface {
|
||||
Store(id string, addr string, version string) (rclient.Api, bool)
|
||||
LoadOrInit(id string, addr string, version string) (rclient.Api, bool)
|
||||
Load(id string) (interface{}, bool)
|
||||
}
|
||||
|
||||
var localStorage = newStorage()
|
||||
|
||||
func newStorage() Storage {
|
||||
return &storage{
|
||||
sMap: &sync.Map{},
|
||||
}
|
||||
}
|
||||
|
||||
type storage struct {
|
||||
sMap *sync.Map
|
||||
}
|
||||
|
||||
func (s *storage) Store(id string, addr string, version string) (rclient.Api, bool) {
|
||||
client := rclient.NewClient(addr, rclient.WithVersion(version))
|
||||
|
||||
s.sMap.Store(id, client)
|
||||
|
||||
return client, false
|
||||
}
|
||||
|
||||
func (s *storage) LoadOrInit(id string, addr string, version string) (rclient.Api, bool) {
|
||||
client, ok := s.sMap.Load(id)
|
||||
|
||||
if !ok {
|
||||
return Store(id, addr, version)
|
||||
}
|
||||
|
||||
c := client.(rclient.Api)
|
||||
|
||||
return c, true
|
||||
}
|
||||
|
||||
func (s *storage) Load(id string) (interface{}, bool) {
|
||||
return s.sMap.Load(id)
|
||||
}
|
||||
|
||||
func SetLocalStorage(s Storage) {
|
||||
localStorage = s
|
||||
}
|
||||
|
||||
func Store(id string, addr string, version string) (rclient.Api, bool) {
|
||||
|
||||
client, _ := localStorage.Store(id, addr, version)
|
||||
|
||||
return client, false
|
||||
}
|
||||
|
||||
func LoadOrInit(id string, addr string, version string) (rclient.Api, bool) {
|
||||
|
||||
client, ok := localStorage.Load(id)
|
||||
|
||||
if !ok {
|
||||
return localStorage.Store(id, addr, version)
|
||||
}
|
||||
|
||||
c := client.(rclient.Api)
|
||||
|
||||
return c, true
|
||||
}
|
10
readme.md
10
readme.md
@ -1,10 +1,10 @@
|
||||
# go-app-template
|
||||
# kubodin
|
||||
|
||||
[![Release](https://img.shields.io/github/release/khorevaa/go-app-template.svg?style=for-the-badge)](https://github.com/khorevaa/go-app-template/releases/latest)
|
||||
[![Release](https://img.shields.io/github/release/khorevaa/kubodin.svg?style=for-the-badge)](https://github.com/khorevaa/kubodin/releases/latest)
|
||||
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=for-the-badge)](/LICENSE.md)
|
||||
[![Build status](https://img.shields.io/github/workflow/status/khorevaa/go-app-template/build?style=for-the-badge)](https://github.com/khorevaa/go-app-template/actions?workflow=releaser)
|
||||
[![Codecov branch](https://img.shields.io/codecov/c/github/khorevaa/go-app-template/master.svg?style=for-the-badge)](https://codecov.io/gh/khorevaa/go-app-template)
|
||||
[![Go Doc](https://img.shields.io/badge/godoc-reference-blue.svg?style=for-the-badge)](http://godoc.org/github.com/khorevaa/go-app-template)
|
||||
[![Build status](https://img.shields.io/github/workflow/status/khorevaa/kubodin/build?style=for-the-badge)](https://github.com/khorevaa/kubodin/actions?workflow=releaser)
|
||||
[![Codecov branch](https://img.shields.io/codecov/c/github/khorevaa/kubodin/master.svg?style=for-the-badge)](https://codecov.io/gh/khorevaa/kubodin)
|
||||
[![Go Doc](https://img.shields.io/badge/godoc-reference-blue.svg?style=for-the-badge)](http://godoc.org/github.com/khorevaa/kubodin)
|
||||
[![SayThanks.io](https://img.shields.io/badge/SayThanks.io-%E2%98%BC-1EAEDB.svg?style=for-the-badge)](https://saythanks.io/to/khorevaa)
|
||||
[![Powered By: GoReleaser](https://img.shields.io/badge/powered%20by-goreleaser-green.svg?style=for-the-badge)](https://github.com/goreleaser)
|
||||
[![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg?style=for-the-badge)](https://conventionalcommits.org)
|
||||
|
39
service/cache.go
Normal file
39
service/cache.go
Normal file
@ -0,0 +1,39 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/khorevaa/ras-client/serialize"
|
||||
)
|
||||
|
||||
func (s service) getFromCache(key string) (interface{}, bool) {
|
||||
//fmt.Sprintf("%s.clusters", ctt.App.Name)
|
||||
return s.cache.Get(key)
|
||||
}
|
||||
|
||||
func (s service) getCacheClusters(appName string) ([]*serialize.ClusterInfo, bool) {
|
||||
|
||||
if clusters, ok := s.cache.Get(fmt.Sprintf(clustersTpl, appName)); ok {
|
||||
return clusters.([]*serialize.ClusterInfo), ok
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (s service) setCacheClusters(appName string, clusters []*serialize.ClusterInfo) {
|
||||
s.cache.Set(fmt.Sprintf(clustersTpl, appName), clusters)
|
||||
}
|
||||
|
||||
func (s service) getCacheInfobases(cluster string) (serialize.InfobaseSummaryList, bool) {
|
||||
|
||||
if list, ok := s.cache.Get(fmt.Sprintf(infobasesTpl, cluster)); ok {
|
||||
return list.(serialize.InfobaseSummaryList), ok
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (s service) setCacheInfobases(cluster string, list serialize.InfobaseSummaryList) {
|
||||
s.cache.Set(fmt.Sprintf(infobasesTpl, cluster), list)
|
||||
}
|
||||
|
||||
func (s service) clearCacheInfobases(cluster string) {
|
||||
s.cache.Clear(fmt.Sprintf(infobasesTpl, cluster))
|
||||
}
|
9
service/cache/cache.go
vendored
Normal file
9
service/cache/cache.go
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
package cache
|
||||
|
||||
type Cache interface {
|
||||
Connect()
|
||||
Get(key string) (interface{}, bool)
|
||||
Set(key string, value interface{})
|
||||
Clear(key string)
|
||||
HealthCheck() (bool, error)
|
||||
}
|
32
service/cache/memory.go
vendored
Normal file
32
service/cache/memory.go
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
memoryCache "github.com/patrickmn/go-cache"
|
||||
)
|
||||
|
||||
type Memory struct {
|
||||
Expiration time.Duration
|
||||
cache *memoryCache.Cache
|
||||
}
|
||||
|
||||
func (m *Memory) HealthCheck() (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
func (m *Memory) Connect() {
|
||||
m.cache = memoryCache.New(m.Expiration*time.Minute, m.Expiration*time.Minute)
|
||||
//log.Println("Using in-memory cache")
|
||||
}
|
||||
|
||||
func (m *Memory) Get(key string) (interface{}, bool) {
|
||||
return m.cache.Get(key)
|
||||
}
|
||||
|
||||
func (m *Memory) Set(key string, value interface{}) {
|
||||
m.cache.Set(key, value, time.Duration(m.Expiration)*time.Minute)
|
||||
}
|
||||
|
||||
func (m *Memory) Clear(key string) {
|
||||
m.cache.Delete(key)
|
||||
}
|
367
service/clientContext.go
Normal file
367
service/clientContext.go
Normal file
@ -0,0 +1,367 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/khorevaa/kubodin/errors"
|
||||
"github.com/khorevaa/kubodin/models"
|
||||
rclient "github.com/khorevaa/ras-client"
|
||||
"github.com/khorevaa/ras-client/serialize"
|
||||
"github.com/recoilme/pudge"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
//var _ rclient.Api = (ClientContext)(nil)
|
||||
|
||||
type ClientContext struct {
|
||||
client rclient.Api
|
||||
App *models.AppServer
|
||||
ctx context.Context
|
||||
requestCtx *fiber.Ctx
|
||||
|
||||
force bool
|
||||
}
|
||||
|
||||
func (c ClientContext) GetApiClient() rclient.Api {
|
||||
return c.client
|
||||
}
|
||||
|
||||
func (c ClientContext) Version() string {
|
||||
return c.client.Version()
|
||||
}
|
||||
|
||||
func (c ClientContext) Close() error {
|
||||
return c.client.Close()
|
||||
}
|
||||
|
||||
func (c ClientContext) AuthenticateAgent(user, password string) {
|
||||
c.client.AuthenticateAgent(user, password)
|
||||
}
|
||||
|
||||
func (c ClientContext) AuthenticateCluster(cluster uuid.UUID, user, password string) {
|
||||
c.client.AuthenticateCluster(cluster, user, password)
|
||||
}
|
||||
|
||||
func (c ClientContext) AuthenticateInfobase(infobase uuid.UUID, user, password string) {
|
||||
c.client.AuthenticateInfobase(infobase, user, password)
|
||||
}
|
||||
|
||||
func (c ClientContext) GetClusters() ([]*serialize.ClusterInfo, error) {
|
||||
return c.client.GetClusters(c.ctx)
|
||||
}
|
||||
|
||||
func (c ClientContext) GetAgentAdmins() (serialize.UsersList, error) {
|
||||
return c.client.GetAgentAdmins(c.ctx)
|
||||
}
|
||||
|
||||
func (c ClientContext) GetAgentVersion() (string, error) {
|
||||
return c.client.GetAgentVersion(c.ctx)
|
||||
}
|
||||
|
||||
func (c ClientContext) RegAgentAdmin(user serialize.UserInfo) error {
|
||||
return c.client.RegAgentAdmin(c.ctx, user)
|
||||
}
|
||||
|
||||
func (c ClientContext) UnregAgentAdmin(user string) error {
|
||||
return c.client.UnregAgentAdmin(c.ctx, user)
|
||||
}
|
||||
|
||||
func (c ClientContext) GetClusterAdmins(cluster uuid.UUID) (serialize.UsersList, error) {
|
||||
c.AddAuth(cluster)
|
||||
return c.client.GetClusterAdmins(c.ctx, cluster)
|
||||
}
|
||||
|
||||
func (c ClientContext) RegClusterAdmin(cluster uuid.UUID, user serialize.UserInfo) error {
|
||||
c.AddAuth(cluster)
|
||||
return c.client.RegClusterAdmin(c.ctx, cluster, user)
|
||||
}
|
||||
|
||||
func (c ClientContext) UnregClusterAdmin(cluster uuid.UUID, user string) error {
|
||||
c.AddAuth(cluster)
|
||||
return c.client.UnregClusterAdmin(c.ctx, cluster, user)
|
||||
}
|
||||
|
||||
func (c ClientContext) GetClusterInfo(cluster uuid.UUID) (serialize.ClusterInfo, error) {
|
||||
c.AddAuth(cluster)
|
||||
return c.client.GetClusterInfo(c.ctx, cluster)
|
||||
}
|
||||
|
||||
func (c ClientContext) GetClusterInfobases(cluster uuid.UUID) (serialize.InfobaseSummaryList, error) {
|
||||
c.AddAuth(cluster)
|
||||
return c.client.GetClusterInfobases(c.ctx, cluster)
|
||||
}
|
||||
|
||||
func (c ClientContext) GetClusterServices(cluster uuid.UUID) ([]*serialize.ServiceInfo, error) {
|
||||
c.AddAuth(cluster)
|
||||
return c.client.GetClusterServices(c.ctx, cluster)
|
||||
}
|
||||
|
||||
func (c ClientContext) GetClusterManagers(cluster uuid.UUID) ([]*serialize.ManagerInfo, error) {
|
||||
c.AddAuth(cluster)
|
||||
return c.client.GetClusterManagers(c.ctx, cluster)
|
||||
}
|
||||
|
||||
func (c ClientContext) GetClusterSessions(cluster uuid.UUID) (serialize.SessionInfoList, error) {
|
||||
c.AddAuth(cluster)
|
||||
return c.client.GetClusterSessions(c.ctx, cluster)
|
||||
}
|
||||
|
||||
func (c ClientContext) GetInfobaseSessions(cluster uuid.UUID, infobase uuid.UUID) (serialize.SessionInfoList, error) {
|
||||
c.AddAuth(cluster, infobase)
|
||||
return c.client.GetInfobaseSessions(c.ctx, cluster, infobase)
|
||||
}
|
||||
|
||||
func (c ClientContext) TerminateSession(cluster uuid.UUID, session uuid.UUID, msg string) error {
|
||||
c.AddAuth(cluster)
|
||||
return c.client.TerminateSession(c.ctx, cluster, session, msg)
|
||||
}
|
||||
|
||||
func (c ClientContext) GetClusterLocks(cluster uuid.UUID) (serialize.LocksList, error) {
|
||||
c.AddAuth(cluster)
|
||||
return c.client.GetClusterLocks(c.ctx, cluster)
|
||||
}
|
||||
|
||||
func (c ClientContext) GetInfobaseLocks(cluster uuid.UUID, infobase uuid.UUID) (serialize.LocksList, error) {
|
||||
c.AddAuth(cluster, infobase)
|
||||
return c.client.GetInfobaseLocks(c.ctx, cluster, infobase)
|
||||
}
|
||||
|
||||
func (c ClientContext) GetSessionLocks(cluster uuid.UUID, infobase uuid.UUID, session uuid.UUID) (serialize.LocksList, error) {
|
||||
c.AddAuth(cluster, infobase)
|
||||
return c.client.GetSessionLocks(c.ctx, cluster, infobase, session)
|
||||
}
|
||||
|
||||
func (c ClientContext) GetConnectionLocks(cluster uuid.UUID, connection uuid.UUID) (serialize.LocksList, error) {
|
||||
c.AddAuth(cluster)
|
||||
return c.client.GetConnectionLocks(c.ctx, cluster, connection)
|
||||
}
|
||||
|
||||
func (c ClientContext) GetClusterConnections(cluster uuid.UUID) (serialize.ConnectionShortInfoList, error) {
|
||||
c.AddAuth(cluster)
|
||||
return c.client.GetClusterConnections(c.ctx, cluster)
|
||||
}
|
||||
|
||||
func (c ClientContext) GetInfobaseConnections(cluster uuid.UUID, infobase uuid.UUID) (serialize.ConnectionShortInfoList, error) {
|
||||
c.AddAuth(cluster, infobase)
|
||||
return c.client.GetInfobaseConnections(c.ctx, cluster, infobase)
|
||||
}
|
||||
|
||||
func (c ClientContext) DisconnectConnection(cluster uuid.UUID, process uuid.UUID, connection uuid.UUID, infobase uuid.UUID) error {
|
||||
c.AddAuth(cluster, infobase)
|
||||
return c.client.DisconnectConnection(c.ctx, cluster, process, connection, infobase)
|
||||
}
|
||||
|
||||
func (c ClientContext) CreateInfobase(cluster uuid.UUID, infobase serialize.InfobaseInfo, mode int) (serialize.InfobaseInfo, error) {
|
||||
|
||||
c.AddAuth(cluster)
|
||||
return c.client.CreateInfobase(c.ctx, cluster, infobase, mode)
|
||||
}
|
||||
|
||||
func (c ClientContext) UpdateSummaryInfobase(cluster uuid.UUID, infobase serialize.InfobaseSummaryInfo) error {
|
||||
c.AddAuth(cluster, infobase.UUID)
|
||||
return c.client.UpdateSummaryInfobase(c.ctx, cluster, infobase)
|
||||
}
|
||||
|
||||
func (c ClientContext) UpdateInfobase(cluster uuid.UUID, infobase serialize.InfobaseInfo) error {
|
||||
c.AddAuth(cluster, infobase.UUID)
|
||||
return c.client.UpdateInfobase(c.ctx, cluster, infobase)
|
||||
}
|
||||
|
||||
func (c ClientContext) DropInfobase(cluster uuid.UUID, infobase uuid.UUID, mode int) error {
|
||||
c.AddAuth(cluster, infobase)
|
||||
return c.client.DropInfobase(c.ctx, cluster, infobase, mode)
|
||||
}
|
||||
|
||||
func (c ClientContext) GetInfobaseInfo(cluster uuid.UUID, infobase uuid.UUID) (serialize.InfobaseInfo, error) {
|
||||
c.AddAuth(cluster, infobase)
|
||||
return c.client.GetInfobaseInfo(c.ctx, cluster, infobase)
|
||||
}
|
||||
|
||||
func (c ClientContext) GetWorkingProcesses(cluster uuid.UUID) (serialize.ProcessInfoList, error) {
|
||||
c.AddAuth(cluster)
|
||||
return c.client.GetWorkingProcesses(c.ctx, cluster)
|
||||
}
|
||||
|
||||
func (c ClientContext) GetWorkingProcessInfo(cluster, process uuid.UUID) (*serialize.ProcessInfo, error) {
|
||||
c.AddAuth(cluster)
|
||||
return c.client.GetWorkingProcessInfo(c.ctx, cluster, process)
|
||||
}
|
||||
|
||||
func (c ClientContext) GetWorkingServers(cluster uuid.UUID) ([]*serialize.ServerInfo, error) {
|
||||
c.AddAuth(cluster)
|
||||
return c.client.GetWorkingServers(c.ctx, cluster)
|
||||
}
|
||||
|
||||
func (c ClientContext) GetWorkingServerInfo(cluster, serverID uuid.UUID) (*serialize.ServerInfo, error) {
|
||||
c.AddAuth(cluster)
|
||||
return c.client.GetWorkingServerInfo(c.ctx, cluster, serverID)
|
||||
}
|
||||
|
||||
func (c ClientContext) RegWorkingServer(cluster uuid.UUID, info *serialize.ServerInfo) (*serialize.ServerInfo, error) {
|
||||
c.AddAuth(cluster)
|
||||
return c.client.RegWorkingServer(c.ctx, cluster, info)
|
||||
}
|
||||
|
||||
func (c ClientContext) UnRegWorkingServer(cluster, serverID uuid.UUID) error {
|
||||
c.AddAuth(cluster)
|
||||
return c.client.UnRegWorkingServer(c.ctx, cluster, serverID)
|
||||
}
|
||||
|
||||
func (c ClientContext) Force() bool {
|
||||
return c.force
|
||||
}
|
||||
|
||||
func (c ClientContext) Context() context.Context {
|
||||
return c.ctx
|
||||
}
|
||||
|
||||
func appServerFromContext(ctx *fiber.Ctx) (*models.AppServer, error) {
|
||||
|
||||
name := ctx.Params("app")
|
||||
|
||||
serviceInterface := ctx.Context().UserValue("service")
|
||||
|
||||
s, ok := serviceInterface.(Service)
|
||||
|
||||
if !ok {
|
||||
return nil, errors.Internal.New("cannot get service from context ")
|
||||
}
|
||||
|
||||
app, err := s.GetAppServer(name)
|
||||
|
||||
if err != nil {
|
||||
|
||||
if err == pudge.ErrKeyNotFound {
|
||||
return nil, errors.BadRequest.Newf("app <%s> not registered", name)
|
||||
}
|
||||
|
||||
return nil, errors.BadRequest.Wrapf(err, "cannot get app <%s>", name)
|
||||
}
|
||||
|
||||
return app, err
|
||||
}
|
||||
|
||||
func GetClientContext(ctx *fiber.Ctx) (ClientContext, error) {
|
||||
|
||||
app, err := appServerFromContext(ctx)
|
||||
if err != nil {
|
||||
return ClientContext{}, err
|
||||
}
|
||||
|
||||
apiClient, err := app.Client()
|
||||
if err != nil {
|
||||
return ClientContext{}, err
|
||||
}
|
||||
|
||||
client := ClientContext{
|
||||
App: app,
|
||||
client: apiClient,
|
||||
requestCtx: ctx,
|
||||
ctx: ctx.Context(),
|
||||
force: GetContextValueOrNil(ctx, "force").Bool(false),
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func NewClientContext(app *models.AppServer, ctx *fiber.Ctx) *ClientContext {
|
||||
|
||||
apiClient, _ := app.Client()
|
||||
|
||||
return &ClientContext{
|
||||
App: app,
|
||||
client: apiClient,
|
||||
requestCtx: ctx,
|
||||
ctx: ctx.Context(),
|
||||
force: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (c ClientContext) GetContextValue(name string, unescape ...bool) (ContextValue, bool) {
|
||||
return GetContextValue(c.requestCtx, name, unescape...)
|
||||
}
|
||||
|
||||
var NeedClusterID = errors.BadRequest.New("need set cluster id")
|
||||
|
||||
func (c ClientContext) GetClusterID() (uuid.UUID, bool) {
|
||||
|
||||
value := GetContextValueOrNil(c.requestCtx, "cluster cluster-id", true)
|
||||
|
||||
id, err := value.UUID()
|
||||
|
||||
if err != nil {
|
||||
return id, false
|
||||
}
|
||||
|
||||
return id, true
|
||||
|
||||
}
|
||||
|
||||
func (c ClientContext) GetClusterIDOrNil() uuid.UUID {
|
||||
id, _ := c.GetClusterID()
|
||||
return id
|
||||
|
||||
}
|
||||
|
||||
func (c ClientContext) GetInfobaseID() (ContextValue, bool) {
|
||||
|
||||
val := GetContextValueOrNil(c.requestCtx, "infobase infobase-id", true)
|
||||
|
||||
return val, !val.Empty()
|
||||
|
||||
}
|
||||
|
||||
func (c ClientContext) AddAuth(cluster uuid.UUID, infobase ...uuid.UUID) {
|
||||
|
||||
c.authCluster(cluster)
|
||||
|
||||
if len(infobase) == 1 {
|
||||
c.authInfobase(infobase[0])
|
||||
}
|
||||
|
||||
}
|
||||
func (c ClientContext) authCluster(cluster uuid.UUID) {
|
||||
|
||||
if cluster == uuid.Nil {
|
||||
return
|
||||
}
|
||||
|
||||
user, _ := c.GetContextValue("cluster-usr", true)
|
||||
|
||||
if len(user) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
pwd, _ := c.GetContextValue("cluster-pwd", true)
|
||||
|
||||
c.client.AuthenticateCluster(cluster, user.String(), pwd.String())
|
||||
|
||||
}
|
||||
|
||||
func (c ClientContext) authInfobase(infobase uuid.UUID) {
|
||||
|
||||
if infobase == uuid.Nil {
|
||||
return
|
||||
}
|
||||
user, _ := c.GetContextValue("infobase-usr", true)
|
||||
|
||||
if len(user) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
pwd, _ := c.GetContextValue("infobase-pwd", true)
|
||||
|
||||
c.client.AuthenticateInfobase(infobase, user.String(), pwd.String())
|
||||
|
||||
}
|
||||
|
||||
func (c ClientContext) HealthCheck() (bool, error) {
|
||||
|
||||
_, err := c.client.GetAgentVersion(c.ctx)
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
27
service/clusters.go
Normal file
27
service/clusters.go
Normal file
@ -0,0 +1,27 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"github.com/khorevaa/kubodin/errors"
|
||||
"github.com/khorevaa/ras-client/serialize"
|
||||
)
|
||||
|
||||
func (s *service) GetClusters(client ClientContext) ([]*serialize.ClusterInfo, error) {
|
||||
|
||||
return s.getClusters(client)
|
||||
}
|
||||
|
||||
func (s *service) GetClusterInfo(client ClientContext) (*serialize.ClusterInfo, error) {
|
||||
|
||||
clusterID, ok := client.GetClusterID()
|
||||
|
||||
if !ok {
|
||||
return nil, errors.BadRequest.New("incorrect or not set <cluster-id>")
|
||||
}
|
||||
|
||||
info, err := client.GetClusterInfo(clusterID)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &info, nil
|
||||
}
|
108
service/contextValue.go
Normal file
108
service/contextValue.go
Normal file
@ -0,0 +1,108 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func GetContextValue(ctx *fiber.Ctx, name string, unescape ...bool) (ContextValue, bool) {
|
||||
|
||||
names := strings.Fields(name)
|
||||
|
||||
var val string
|
||||
|
||||
for _, valName := range names {
|
||||
val = ctx.Params(valName)
|
||||
if len(val) > 0 {
|
||||
break
|
||||
}
|
||||
|
||||
val = ctx.Query(valName)
|
||||
if len(val) > 0 {
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if len(val) == 0 {
|
||||
return "", false
|
||||
}
|
||||
|
||||
urlUnescape := true
|
||||
|
||||
if len(unescape) > 0 {
|
||||
urlUnescape = unescape[0]
|
||||
}
|
||||
|
||||
if urlUnescape {
|
||||
val, _ = url.QueryUnescape(val)
|
||||
}
|
||||
|
||||
return ContextValue(val), len(val) > 0
|
||||
}
|
||||
|
||||
func GetContextValueOrNil(ctx *fiber.Ctx, name string, unescape ...bool) ContextValue {
|
||||
|
||||
val, _ := GetContextValue(ctx, name, unescape...)
|
||||
|
||||
return val
|
||||
}
|
||||
|
||||
func GetClusterID(ctx *fiber.Ctx) (ContextValue, bool) {
|
||||
|
||||
return GetContextValue(ctx, "cluster cluster-id", true)
|
||||
|
||||
}
|
||||
|
||||
func GetInfobaseID(ctx *fiber.Ctx) (ContextValue, bool) {
|
||||
|
||||
return GetContextValue(ctx, "infobase infobase-id", true)
|
||||
|
||||
}
|
||||
|
||||
type ContextValue string
|
||||
|
||||
func (val ContextValue) Empty() bool {
|
||||
return len(val) == 0
|
||||
}
|
||||
|
||||
func (val ContextValue) NotEmpty() bool {
|
||||
return !val.Empty()
|
||||
}
|
||||
|
||||
func (val ContextValue) String() string {
|
||||
return string(val)
|
||||
}
|
||||
|
||||
func (val ContextValue) Bool(defaultVal ...bool) bool {
|
||||
|
||||
var defVal bool
|
||||
|
||||
if len(defaultVal) > 0 {
|
||||
defVal = defaultVal[0]
|
||||
}
|
||||
|
||||
valB, err := strconv.ParseBool(val.String())
|
||||
|
||||
if err != nil {
|
||||
return defVal
|
||||
}
|
||||
|
||||
return valB
|
||||
}
|
||||
|
||||
func (val ContextValue) UUID() (uuid.UUID, error) {
|
||||
return uuid.FromString(val.String())
|
||||
}
|
||||
|
||||
func (val ContextValue) NilUUID() bool {
|
||||
return len(val) > 0 &&
|
||||
uuid.FromStringOrNil(val.String()) == uuid.Nil
|
||||
}
|
||||
|
||||
func (val ContextValue) NotNilUUID() bool {
|
||||
return !val.NilUUID()
|
||||
}
|
153
service/helpers.go
Normal file
153
service/helpers.go
Normal file
@ -0,0 +1,153 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"github.com/khorevaa/kubodin/errors"
|
||||
"github.com/khorevaa/ras-client/serialize"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
func (s service) findInfobaseInList(list serialize.InfobaseSummaryList, infobaseID string) (*serialize.InfobaseSummaryInfo, bool) {
|
||||
|
||||
if id := uuid.FromStringOrNil(infobaseID); id != uuid.Nil {
|
||||
return list.ByID(id)
|
||||
}
|
||||
|
||||
return list.ByName(infobaseID)
|
||||
|
||||
}
|
||||
|
||||
func (s *service) getClusterID(client ClientContext, clusterID ...uuid.UUID) (uuid.UUID, error) {
|
||||
|
||||
if len(clusterID) > 0 &&
|
||||
clusterID[0] != uuid.Nil {
|
||||
return clusterID[0], nil
|
||||
}
|
||||
|
||||
cluster, ok := client.GetClusterID()
|
||||
if ok {
|
||||
return cluster, nil
|
||||
}
|
||||
|
||||
clusters, err := s.getClusters(client)
|
||||
|
||||
if err != nil {
|
||||
return uuid.Nil, err
|
||||
}
|
||||
|
||||
if len(clusters) == 1 {
|
||||
return clusters[0].UUID, nil
|
||||
}
|
||||
|
||||
return uuid.Nil, errors.BadRequest.New("to many clusters. Set <cluster id> value manually")
|
||||
}
|
||||
|
||||
func (s *service) getAnyClusterID(client ClientContext, clusterID ...uuid.UUID) (uuid.UUID, error) {
|
||||
|
||||
if len(clusterID) > 0 &&
|
||||
clusterID[0] != uuid.Nil {
|
||||
return clusterID[0], nil
|
||||
}
|
||||
|
||||
clusters, err := s.getClusters(client)
|
||||
|
||||
if err != nil {
|
||||
return uuid.Nil, err
|
||||
}
|
||||
|
||||
if len(clusters) > 0 {
|
||||
return clusters[0].UUID, nil
|
||||
}
|
||||
|
||||
return uuid.Nil, errors.BadRequest.New("no registered clusters. Set <cluster id> value manually")
|
||||
}
|
||||
|
||||
func (s service) findInfobase(client ClientContext, infobaseID string, clusterID ...uuid.UUID) (*serialize.InfobaseSummaryInfo, error) {
|
||||
|
||||
clusters, err := s.getClusters(client)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(clusterID) == 1 && clusterID[0] != uuid.Nil {
|
||||
list, err := s.getClusterInfobases(client, clusterID[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
summaryInfo, ok := s.findInfobaseInList(list, infobaseID)
|
||||
|
||||
if !ok {
|
||||
return nil, errors.BadRequest.Newf("infobase not found by name or uuid <%s> on cluster <%s>",
|
||||
infobaseID, clusterID[0].String())
|
||||
}
|
||||
|
||||
return summaryInfo, nil
|
||||
}
|
||||
|
||||
var summaryInfoList []*serialize.InfobaseSummaryInfo
|
||||
|
||||
for _, cluster := range clusters {
|
||||
list, err := s.getClusterInfobases(client, cluster.UUID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
summaryInfo, ok := s.findInfobaseInList(list, infobaseID)
|
||||
if ok {
|
||||
summaryInfoList = append(summaryInfoList, summaryInfo)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
switch len(summaryInfoList) {
|
||||
|
||||
case 1:
|
||||
return summaryInfoList[0], nil
|
||||
case 0:
|
||||
return nil, errors.BadRequest.Newf("infobase not found by name or uuid <%s>", infobaseID)
|
||||
default:
|
||||
return nil, errors.BadRequest.Newf("find to many infobases with <%s>."+
|
||||
" Set <cluster-id> value manually", infobaseID)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *service) getClusterInfobases(client ClientContext, clusterID uuid.UUID) (serialize.InfobaseSummaryList, error) {
|
||||
|
||||
cacheKey := clusterID.String()
|
||||
|
||||
if list, ok := s.getCacheInfobases(cacheKey); ok && !client.Force() {
|
||||
return list, nil
|
||||
}
|
||||
|
||||
list, err := client.GetClusterInfobases(clusterID)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.setCacheInfobases(cacheKey, list)
|
||||
|
||||
return list, nil
|
||||
|
||||
}
|
||||
|
||||
func (s *service) getClusters(client ClientContext) ([]*serialize.ClusterInfo, error) {
|
||||
|
||||
cacheKey := client.App.Name
|
||||
|
||||
if list, ok := s.getCacheClusters(cacheKey); ok && !client.Force() {
|
||||
return list, nil
|
||||
}
|
||||
|
||||
list, err := client.GetClusters()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.setCacheClusters(cacheKey, list)
|
||||
|
||||
return list, nil
|
||||
|
||||
}
|
87
service/infobase.go
Normal file
87
service/infobase.go
Normal file
@ -0,0 +1,87 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"github.com/khorevaa/kubodin/errors"
|
||||
"github.com/khorevaa/ras-client/serialize"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
func (s *service) GetInfobases(client ClientContext) (serialize.InfobaseSummaryList, error) {
|
||||
|
||||
cluster, _ := client.GetClusterID()
|
||||
clusterID, _ := s.getClusterID(client, cluster)
|
||||
|
||||
if clusterID != uuid.Nil {
|
||||
return s.getClusterInfobases(client, clusterID)
|
||||
}
|
||||
|
||||
clusters, err := s.getClusters(client)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var listAll serialize.InfobaseSummaryList
|
||||
|
||||
for _, cluster := range clusters {
|
||||
list, err := s.getClusterInfobases(client, cluster.UUID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
listAll = append(listAll, list...)
|
||||
}
|
||||
|
||||
return listAll, nil
|
||||
|
||||
}
|
||||
|
||||
func (s *service) CreateInfobase(client ClientContext, info *serialize.InfobaseInfo, createDB bool) (*serialize.InfobaseInfo, error) {
|
||||
|
||||
cluster, _ := client.GetClusterID()
|
||||
clusterID, err := s.getAnyClusterID(client, cluster)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mode := 0
|
||||
|
||||
if createDB {
|
||||
mode = 1
|
||||
}
|
||||
|
||||
infobaseInfo, err := client.CreateInfobase(clusterID, *info, mode)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.clearCacheInfobases(clusterID.String())
|
||||
|
||||
return &infobaseInfo, nil
|
||||
}
|
||||
|
||||
func (s *service) DropInfobase(client ClientContext, dropDB bool) error {
|
||||
|
||||
infobaseID, _ := client.GetInfobaseID()
|
||||
|
||||
if infobaseID.Empty() {
|
||||
return errors.BadRequest.New("infobase id or name must be set")
|
||||
}
|
||||
|
||||
summaryInfo, err := s.findInfobase(client, infobaseID.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mode := 0
|
||||
|
||||
if dropDB {
|
||||
mode = 1
|
||||
}
|
||||
|
||||
err = client.DropInfobase(summaryInfo.ClusterID, summaryInfo.UUID, mode)
|
||||
|
||||
return err
|
||||
|
||||
}
|
18
service/middleware.go
Normal file
18
service/middleware.go
Normal file
@ -0,0 +1,18 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
// New creates a new middleware handler
|
||||
func Middleware(s Service) fiber.Handler {
|
||||
|
||||
// Return new handler
|
||||
return func(c *fiber.Ctx) (err error) {
|
||||
|
||||
c.Context().SetUserValue("service", s)
|
||||
|
||||
// Return err if exist, else move to next handler
|
||||
return c.Next()
|
||||
}
|
||||
}
|
62
service/service.go
Normal file
62
service/service.go
Normal file
@ -0,0 +1,62 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
db "github.com/khorevaa/kubodin/database"
|
||||
"github.com/khorevaa/kubodin/models"
|
||||
"github.com/khorevaa/kubodin/service/cache"
|
||||
"github.com/khorevaa/ras-client/serialize"
|
||||
)
|
||||
|
||||
const (
|
||||
clustersTpl = "%s.clusters"
|
||||
infobasesTpl = "%s.infobases"
|
||||
)
|
||||
|
||||
var _ Service = (*service)(nil)
|
||||
|
||||
//Service interface allows us to access the CRUD Operations
|
||||
type Service interface {
|
||||
Repository() db.Repository
|
||||
|
||||
CreateInfobase(ctt ClientContext, info *serialize.InfobaseInfo, createDB bool) (*serialize.InfobaseInfo, error)
|
||||
DropInfobase(ctt ClientContext, deleteDB bool) error
|
||||
|
||||
GetInfobases(ctt ClientContext) (serialize.InfobaseSummaryList, error)
|
||||
|
||||
GetClusters(ctt ClientContext) ([]*serialize.ClusterInfo, error)
|
||||
GetClusterInfo(ctt ClientContext) (*serialize.ClusterInfo, error)
|
||||
|
||||
GetAppServers() (apps []*models.AppServer, err error)
|
||||
GetAppServer(name string) (*models.AppServer, error)
|
||||
|
||||
GetCache() cache.Cache
|
||||
}
|
||||
|
||||
func NewService(cache cache.Cache, repository db.Repository) (Service, error) {
|
||||
|
||||
return &service{
|
||||
cache: cache,
|
||||
repository: repository,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type service struct {
|
||||
repository db.Repository
|
||||
cache cache.Cache
|
||||
}
|
||||
|
||||
func (s service) GetCache() cache.Cache {
|
||||
return s.cache
|
||||
}
|
||||
|
||||
func (s *service) Repository() db.Repository {
|
||||
return s.repository
|
||||
}
|
||||
|
||||
func (s *service) GetAppServers() (apps []*models.AppServer, err error) {
|
||||
return s.repository.GetAppServers()
|
||||
}
|
||||
|
||||
func (s *service) GetAppServer(name string) (*models.AppServer, error) {
|
||||
return s.repository.GetAppServer(name)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user