update live work, adding CI, adding tests for some http functions, upgrading go version
This commit is contained in:
parent
7a7af92bdc
commit
8dd2459240
102
.gitlab-ci.yml
Normal file
102
.gitlab-ci.yml
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
workflow:
|
||||||
|
rules:
|
||||||
|
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
||||||
|
when: never
|
||||||
|
# NO DEPLOYMENT
|
||||||
|
- if: '$CI_COMMIT_TAG == null'
|
||||||
|
variables:
|
||||||
|
IMAGE_TAG: $CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA
|
||||||
|
CONTAINER_IMAGE: $CI_REGISTRY_IMAGE:$IMAGE_TAG
|
||||||
|
# STAGING/PRODUCTION - tags only
|
||||||
|
- if: '$CI_COMMIT_TAG =~ /(alpha)|(beta)|(rc)/'
|
||||||
|
variables:
|
||||||
|
IMAGE_TAG: $CI_COMMIT_TAG
|
||||||
|
CONTAINER_IMAGE: $CI_REGISTRY_IMAGE:$IMAGE_TAG
|
||||||
|
ENVIRONMENT: 'staging'
|
||||||
|
ENVIRONMENT_SHORT: 'stg'
|
||||||
|
- if: '$CI_COMMIT_TAG'
|
||||||
|
variables:
|
||||||
|
IMAGE_TAG: $CI_COMMIT_TAG
|
||||||
|
CONTAINER_IMAGE: $CI_REGISTRY_IMAGE:$IMAGE_TAG
|
||||||
|
ENVIRONMENT: 'production'
|
||||||
|
ENVIRONMENT_SHORT: 'prd'
|
||||||
|
|
||||||
|
variables:
|
||||||
|
SRC_ROOT_PATH: ./app
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- lint
|
||||||
|
- build
|
||||||
|
- test
|
||||||
|
- release
|
||||||
|
|
||||||
|
# ###########################################
|
||||||
|
# Lint
|
||||||
|
# ###########################################
|
||||||
|
|
||||||
|
linter:
|
||||||
|
image: golangci/golangci-lint:v2.0.2-alpine
|
||||||
|
rules:
|
||||||
|
- changes:
|
||||||
|
- .gitlab-ci.yml
|
||||||
|
- app/*
|
||||||
|
- app/*/*
|
||||||
|
when: always
|
||||||
|
stage: lint
|
||||||
|
before_script:
|
||||||
|
- cd $SRC_ROOT_PATH
|
||||||
|
script:
|
||||||
|
- go mod tidy
|
||||||
|
- golangci-lint run --output.code-climate.path gl-code-quality-report.json --path-prefix /app/
|
||||||
|
artifacts:
|
||||||
|
reports:
|
||||||
|
codequality: $SRC_ROOT_PATH/gl-code-quality-report.json
|
||||||
|
|
||||||
|
build:application_test:
|
||||||
|
extends: .build:image
|
||||||
|
stage: build
|
||||||
|
variables:
|
||||||
|
BUILD_TARGET: dev
|
||||||
|
BUILD_IMAGE_DESTINATION: ${CONTAINER_IMAGE}_dev
|
||||||
|
BUILD_ARGS: ""
|
||||||
|
|
||||||
|
# ###########################################
|
||||||
|
# Test
|
||||||
|
# ###########################################
|
||||||
|
go:tests:
|
||||||
|
image: ${CONTAINER_IMAGE}_dev
|
||||||
|
stage: test
|
||||||
|
before_script:
|
||||||
|
- cd $SRC_ROOT_PATH
|
||||||
|
- go mod download
|
||||||
|
- go install github.com/jstemmer/go-junit-report@latest
|
||||||
|
- go install github.com/boumenot/gocover-cobertura@latest
|
||||||
|
script:
|
||||||
|
- echo "Execute tests"
|
||||||
|
- go test ./... -v 2>&1 | go-junit-report > report-gotest.xml
|
||||||
|
- echo "Compute coverage"
|
||||||
|
- go test ./... -v -coverprofile=coverage.txt -covermode count
|
||||||
|
- gocover-cobertura < coverage.txt > report-coverage.xml
|
||||||
|
coverage: '/^coverage: \d+.\d+% of statements/'
|
||||||
|
artifacts:
|
||||||
|
reports:
|
||||||
|
junit: $SRC_ROOT_PATH/report-gotest.xml
|
||||||
|
coverage_report:
|
||||||
|
coverage_format: cobertura
|
||||||
|
path: $SRC_ROOT_PATH/report-coverage.xml
|
||||||
|
|
||||||
|
|
||||||
|
# ###########################################
|
||||||
|
# Build
|
||||||
|
# ###########################################
|
||||||
|
|
||||||
|
build:application:
|
||||||
|
extends: .build:image
|
||||||
|
stage: release
|
||||||
|
rules:
|
||||||
|
- if: '$CI_COMMIT_TAG'
|
||||||
|
when: on_success
|
||||||
|
variables:
|
||||||
|
BUILD_TARGET: prod
|
||||||
|
BUILD_IMAGE_DESTINATION: ${CONTAINER_IMAGE}
|
||||||
|
BUILD_ARGS: ""
|
||||||
5
app/.golangci.toml
Normal file
5
app/.golangci.toml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
version = "2"
|
||||||
|
|
||||||
|
[[linters.exclusions.rules]]
|
||||||
|
linters = [ "errcheck" ]
|
||||||
|
source = "^\\s*defer\\s+"
|
||||||
@ -85,7 +85,7 @@ func GetVersionsByDistributionList(db *sql.DB, d string) ([]null.String, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func checkIfOsExists(os OS, db *sql.DB) bool {
|
func checkIfOsExists(os OS, db *sql.DB) bool {
|
||||||
row := db.QueryRow("Select distribution, version from dashboard_os where distribution = ? and version = ?", os.Distribution, os.Version)
|
row := db.QueryRow("SELECT distribution, version FROM dashboard_os WHERE distribution = ? AND version = ?", os.Distribution, os.Version)
|
||||||
err := row.Scan(&os.Distribution, &os.Version)
|
err := row.Scan(&os.Distribution, &os.Version)
|
||||||
return !errors.Is(err, sql.ErrNoRows)
|
return !errors.Is(err, sql.ErrNoRows)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,10 +6,9 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/go-sql-driver/mysql"
|
"github.com/go-sql-driver/mysql"
|
||||||
_ "github.com/go-sql-driver/mysql"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetDatabaseConnection() *sql.DB {
|
var GetDatabaseConnection = func() *sql.DB {
|
||||||
cfg := mysql.Config{
|
cfg := mysql.Config{
|
||||||
User: os.Getenv("DATABASE_USER"),
|
User: os.Getenv("DATABASE_USER"),
|
||||||
Passwd: os.Getenv("DATABASE_PASSWORD"),
|
Passwd: os.Getenv("DATABASE_PASSWORD"),
|
||||||
|
|||||||
@ -1,37 +1,230 @@
|
|||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/DATA-DOG/go-sqlmock"
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
"gopkg.in/guregu/null.v4"
|
||||||
|
db "infra-dashboard/Database"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"reflect"
|
||||||
|
"regexp"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetOS(t *testing.T) {
|
func TestGetOS(t *testing.T) {
|
||||||
// Create a request to pass to our handler. We don't have any query parameters for now, so we'll
|
// Créer une connexion à la base de données simulée
|
||||||
// pass 'nil' as the third parameter.
|
dbConn, mock, err := sqlmock.New()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
|
||||||
|
}
|
||||||
|
defer dbConn.Close()
|
||||||
|
|
||||||
|
// Simuler la réponse de la base de données
|
||||||
|
mockOSList := []db.OS{
|
||||||
|
{ID: 1, Distribution: null.StringFrom("Ubuntu"), Version: null.StringFrom("22.04"), EndOfSupport: null.StringFrom("2026-04-01")},
|
||||||
|
{ID: 2, Distribution: null.StringFrom("Debian"), Version: null.StringFrom("12"), EndOfSupport: null.StringFrom("2028-04-01")},
|
||||||
|
}
|
||||||
|
|
||||||
|
rows := sqlmock.NewRows([]string{"id", "distribution", "version", "end_of_support"}).
|
||||||
|
AddRow(1, "Ubuntu", "22.04", "2026-04-01").
|
||||||
|
AddRow(2, "Debian", "12", "2028-04-01")
|
||||||
|
|
||||||
|
mock.ExpectQuery(regexp.QuoteMeta("SELECT * FROM dashboard_os")).WillReturnRows(rows)
|
||||||
|
|
||||||
|
// Remplacer la fonction GetDatabaseConnection par une version mockée
|
||||||
|
originalGetDatabaseConnection := db.GetDatabaseConnection
|
||||||
|
db.GetDatabaseConnection = func() *sql.DB {
|
||||||
|
return dbConn
|
||||||
|
}
|
||||||
|
defer func() { db.GetDatabaseConnection = originalGetDatabaseConnection }()
|
||||||
|
|
||||||
|
// Créer une requête HTTP
|
||||||
req, err := http.NewRequest("GET", "/os", nil)
|
req, err := http.NewRequest("GET", "/os", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We create a ResponseRecorder (which satisfies http.ResponseWriter) to record the response.
|
// Créer un ResponseRecorder pour enregistrer la réponse
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
handler := http.HandlerFunc(GetOS)
|
handler := http.HandlerFunc(GetOS)
|
||||||
|
|
||||||
// Our handlers satisfy http.Handler, so we can call their ServeHTTP method
|
// Appeler la fonction GetOS
|
||||||
// directly and pass in our Request and ResponseRecorder.
|
|
||||||
handler.ServeHTTP(rr, req)
|
handler.ServeHTTP(rr, req)
|
||||||
|
|
||||||
// Check the status code is what we expect.
|
// Vérifier le statut de la réponse
|
||||||
if status := rr.Code; status != http.StatusOK {
|
if status := rr.Code; status != http.StatusOK {
|
||||||
t.Errorf("handler returned wrong status code: got %v want %v",
|
t.Errorf("handler returned wrong status code: got %v want %v",
|
||||||
status, http.StatusOK)
|
status, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the response body is what we expect.
|
// Vérifier le type de contenu de la réponse
|
||||||
expected := `{"alive": true}`
|
expectedContentType := "application/json"
|
||||||
if rr.Body.String() != expected {
|
if ct := rr.Header().Get("Content-Type"); ct != expectedContentType {
|
||||||
|
t.Errorf("handler returned wrong content type: got %v want %v",
|
||||||
|
ct, expectedContentType)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vérifier le corps de la réponse
|
||||||
|
var responseOSList []db.OS
|
||||||
|
err = json.NewDecoder(rr.Body).Decode(&responseOSList)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(responseOSList, mockOSList) {
|
||||||
t.Errorf("handler returned unexpected body: got %v want %v",
|
t.Errorf("handler returned unexpected body: got %v want %v",
|
||||||
rr.Body.String(), expected)
|
responseOSList, mockOSList)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vérifier que toutes les attentes ont été satisfaites
|
||||||
|
if err := mock.ExpectationsWereMet(); err != nil {
|
||||||
|
t.Errorf("there were unfulfilled expectations: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetOSbyID(t *testing.T) {
|
||||||
|
// Créer une connexion à la base de données simulée
|
||||||
|
dbConn, mock, err := sqlmock.New()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
|
||||||
|
}
|
||||||
|
defer dbConn.Close()
|
||||||
|
|
||||||
|
// Simuler la réponse de la base de données
|
||||||
|
mockOS := db.OS{
|
||||||
|
ID: 1, Distribution: null.StringFrom("Ubuntu"), Version: null.StringFrom("22.04"), EndOfSupport: null.StringFrom("2026-04-01"),
|
||||||
|
}
|
||||||
|
|
||||||
|
rows := sqlmock.NewRows([]string{"id", "distribution", "version", "end_of_support"}).
|
||||||
|
AddRow(1, "Ubuntu", "22.04", "2026-04-01")
|
||||||
|
|
||||||
|
mock.ExpectQuery(regexp.QuoteMeta("SELECT * FROM dashboard_os where id = ?")).WithArgs(sqlmock.AnyArg()).WillReturnRows(rows)
|
||||||
|
|
||||||
|
// Remplacer la fonction GetDatabaseConnection par une version mockée
|
||||||
|
originalGetDatabaseConnection := db.GetDatabaseConnection
|
||||||
|
db.GetDatabaseConnection = func() *sql.DB {
|
||||||
|
return dbConn
|
||||||
|
}
|
||||||
|
defer func() { db.GetDatabaseConnection = originalGetDatabaseConnection }()
|
||||||
|
|
||||||
|
// Créer une requête HTTP
|
||||||
|
req, err := http.NewRequest("GET", "/os/1", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ajouter les paramètres de la route
|
||||||
|
req = mux.SetURLVars(req, map[string]string{"id": "1"})
|
||||||
|
|
||||||
|
// Créer un ResponseRecorder pour enregistrer la réponse
|
||||||
|
rr := httptest.NewRecorder()
|
||||||
|
handler := http.HandlerFunc(GetOSbyID)
|
||||||
|
|
||||||
|
// Appeler la fonction GetOS
|
||||||
|
handler.ServeHTTP(rr, req)
|
||||||
|
|
||||||
|
// Vérifier le statut de la réponse
|
||||||
|
if status := rr.Code; status != http.StatusOK {
|
||||||
|
t.Errorf("handler returned wrong status code: got %v want %v",
|
||||||
|
status, http.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vérifier le type de contenu de la réponse
|
||||||
|
expectedContentType := "application/json"
|
||||||
|
if ct := rr.Header().Get("Content-Type"); ct != expectedContentType {
|
||||||
|
t.Errorf("handler returned wrong content type: got %v want %v",
|
||||||
|
ct, expectedContentType)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vérifier le corps de la réponse
|
||||||
|
var responseOS db.OS
|
||||||
|
err = json.NewDecoder(rr.Body).Decode(&responseOS)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Error decoding json request", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(responseOS, mockOS) {
|
||||||
|
t.Errorf("handler returned unexpected body: got %v want %v",
|
||||||
|
responseOS, mockOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vérifier que toutes les attentes ont été satisfaites
|
||||||
|
if err := mock.ExpectationsWereMet(); err != nil {
|
||||||
|
t.Errorf("there were unfulfilled expectations: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetDistributionList(t *testing.T) {
|
||||||
|
// Créer une connexion à la base de données simulée
|
||||||
|
dbConn, mock, err := sqlmock.New()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
|
||||||
|
}
|
||||||
|
defer dbConn.Close()
|
||||||
|
|
||||||
|
// Simuler la réponse de la base de données
|
||||||
|
mockDistributionList := []null.String{}
|
||||||
|
mockDistributionList = append(mockDistributionList, null.StringFrom("Ubuntu"))
|
||||||
|
mockDistributionList = append(mockDistributionList, null.StringFrom("Debian"))
|
||||||
|
|
||||||
|
rows := sqlmock.NewRows([]string{"distribution"}).
|
||||||
|
AddRow("Ubuntu").
|
||||||
|
AddRow("Debian")
|
||||||
|
|
||||||
|
mock.ExpectQuery(regexp.QuoteMeta("SELECT DISTINCT distribution FROM dashboard_os")).WillReturnRows(rows)
|
||||||
|
|
||||||
|
// Remplacer la fonction GetDatabaseConnection par une version mockée
|
||||||
|
originalGetDatabaseConnection := db.GetDatabaseConnection
|
||||||
|
db.GetDatabaseConnection = func() *sql.DB {
|
||||||
|
return dbConn
|
||||||
|
}
|
||||||
|
defer func() { db.GetDatabaseConnection = originalGetDatabaseConnection }()
|
||||||
|
|
||||||
|
// Créer une requête HTTP
|
||||||
|
req, err := http.NewRequest("GET", "/os/distribution", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Créer un ResponseRecorder pour enregistrer la réponse
|
||||||
|
rr := httptest.NewRecorder()
|
||||||
|
handler := http.HandlerFunc(GetDistributionList)
|
||||||
|
|
||||||
|
// Appeler la fonction GetOS
|
||||||
|
handler.ServeHTTP(rr, req)
|
||||||
|
|
||||||
|
// Vérifier le statut de la réponse
|
||||||
|
if status := rr.Code; status != http.StatusOK {
|
||||||
|
t.Errorf("handler returned wrong status code: got %v want %v",
|
||||||
|
status, http.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vérifier le type de contenu de la réponse
|
||||||
|
expectedContentType := "application/json"
|
||||||
|
if ct := rr.Header().Get("Content-Type"); ct != expectedContentType {
|
||||||
|
t.Errorf("handler returned wrong content type: got %v want %v",
|
||||||
|
ct, expectedContentType)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vérifier le corps de la réponse
|
||||||
|
var responseOSList []null.String
|
||||||
|
err = json.NewDecoder(rr.Body).Decode(&responseOSList)
|
||||||
|
log.Println(responseOSList)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(responseOSList, mockDistributionList) {
|
||||||
|
t.Errorf("handler returned unexpected body: got %v want %v",
|
||||||
|
responseOSList, mockDistributionList)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vérifier que toutes les attentes ont été satisfaites
|
||||||
|
if err := mock.ExpectationsWereMet(); err != nil {
|
||||||
|
t.Errorf("there were unfulfilled expectations: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,10 @@ func RequestHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
t := time.Now()
|
t := time.Now()
|
||||||
logRequest(t, r, 418)
|
logRequest(t, r, 418)
|
||||||
w.WriteHeader(http.StatusTeapot)
|
w.WriteHeader(http.StatusTeapot)
|
||||||
fmt.Fprint(w, "Bip Boop I'm a teapot")
|
_, err := fmt.Fprint(w, "Bip Boop I'm a teapot")
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Something went wrong with the teapot")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func HealthHandler(w http.ResponseWriter, _ *http.Request) {
|
func HealthHandler(w http.ResponseWriter, _ *http.Request) {
|
||||||
|
|||||||
59
app/Http/utils_test.go
Normal file
59
app/Http/utils_test.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestHealthHandler(t *testing.T) {
|
||||||
|
req := httptest.NewRequest(http.MethodGet, "/healthcheck", nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
HealthHandler(w, req)
|
||||||
|
res := w.Result()
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
data, err := io.ReadAll(res.Body)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Expected error to be nil, got %v", err)
|
||||||
|
}
|
||||||
|
if res.StatusCode != http.StatusOK {
|
||||||
|
t.Errorf("Expected status code 200, got %v", res.StatusCode)
|
||||||
|
}
|
||||||
|
if string(data) != "OK" {
|
||||||
|
t.Errorf("Expected 'OK', got %v", string(data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRequestHandler(t *testing.T) {
|
||||||
|
req := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
RequestHandler(w, req)
|
||||||
|
res := w.Result()
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
_, err := io.ReadAll(res.Body)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Expected error to be nil, got %v", err)
|
||||||
|
}
|
||||||
|
if res.StatusCode != http.StatusTeapot {
|
||||||
|
t.Errorf("Expected status code 418, got %v", res.StatusCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNotFound(t *testing.T) {
|
||||||
|
req := httptest.NewRequest(http.MethodGet, "/metrics", nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
NotFound(w, req)
|
||||||
|
res := w.Result()
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
_, err := io.ReadAll(res.Body)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Expected error to be nil, got %v", err)
|
||||||
|
}
|
||||||
|
if res.StatusCode != http.StatusNotFound {
|
||||||
|
t.Errorf("Expected status code 404, got %v", res.StatusCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
26
app/go.mod
26
app/go.mod
@ -1,32 +1,12 @@
|
|||||||
module infra-dashboard
|
module infra-dashboard
|
||||||
|
|
||||||
go 1.23.1
|
go 1.24.2
|
||||||
|
|
||||||
toolchain go1.23.3
|
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/alexflint/go-arg v1.5.1
|
github.com/DATA-DOG/go-sqlmock v1.5.2
|
||||||
github.com/go-sql-driver/mysql v1.8.1
|
github.com/go-sql-driver/mysql v1.8.1
|
||||||
github.com/gorilla/mux v1.8.1
|
github.com/gorilla/mux v1.8.1
|
||||||
github.com/joho/godotenv v1.5.1
|
|
||||||
gopkg.in/guregu/null.v4 v4.0.0
|
gopkg.in/guregu/null.v4 v4.0.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require filippo.io/edwards25519 v1.1.0 // indirect
|
||||||
filippo.io/edwards25519 v1.1.0 // indirect
|
|
||||||
github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect
|
|
||||||
github.com/alexflint/go-scalar v1.2.0 // indirect
|
|
||||||
github.com/google/go-cmp v0.6.0 // indirect
|
|
||||||
golang.org/x/exp/typeparams v0.0.0-20231108232855-2478ac86f678 // indirect
|
|
||||||
golang.org/x/mod v0.22.0 // indirect
|
|
||||||
golang.org/x/sync v0.9.0 // indirect
|
|
||||||
golang.org/x/sys v0.27.0 // indirect
|
|
||||||
golang.org/x/telemetry v0.0.0-20241106142447-58a1122356f5 // indirect
|
|
||||||
golang.org/x/text v0.20.0 // indirect
|
|
||||||
golang.org/x/tools v0.27.1-0.20241219162658-575221bfbda3 // indirect
|
|
||||||
golang.org/x/tools/gopls v0.17.1 // indirect
|
|
||||||
golang.org/x/vuln v1.0.4 // indirect
|
|
||||||
honnef.co/go/tools v0.5.1 // indirect
|
|
||||||
mvdan.cc/gofumpt v0.7.0 // indirect
|
|
||||||
mvdan.cc/xurls/v2 v2.5.0 // indirect
|
|
||||||
)
|
|
||||||
|
|||||||
46
app/go.sum
46
app/go.sum
@ -1,51 +1,11 @@
|
|||||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||||
github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs=
|
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
|
||||||
github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
|
||||||
github.com/alexflint/go-arg v1.5.1 h1:nBuWUCpuRy0snAG+uIJ6N0UvYxpxA0/ghA/AaHxlT8Y=
|
|
||||||
github.com/alexflint/go-arg v1.5.1/go.mod h1:A7vTJzvjoaSTypg4biM5uYNTkJ27SkNTArtYXnlqVO8=
|
|
||||||
github.com/alexflint/go-scalar v1.2.0 h1:WR7JPKkeNpnYIOfHRa7ivM21aWAdHD0gEWHCx+WQBRw=
|
|
||||||
github.com/alexflint/go-scalar v1.2.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o=
|
|
||||||
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/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
|
||||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE=
|
||||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
|
||||||
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/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
golang.org/x/exp/typeparams v0.0.0-20231108232855-2478ac86f678 h1:1P7xPZEwZMoBoz0Yze5Nx2/4pxj6nw9ZqHWXqP0iRgQ=
|
|
||||||
golang.org/x/exp/typeparams v0.0.0-20231108232855-2478ac86f678/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
|
|
||||||
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
|
|
||||||
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
|
||||||
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
|
|
||||||
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
|
||||||
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
|
||||||
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
|
||||||
golang.org/x/telemetry v0.0.0-20241106142447-58a1122356f5 h1:TCDqnvbBsFapViksHcHySl/sW4+rTGNIAoJJesHRuMM=
|
|
||||||
golang.org/x/telemetry v0.0.0-20241106142447-58a1122356f5/go.mod h1:8nZWdGp9pq73ZI//QJyckMQab3yq7hoWi7SI0UIusVI=
|
|
||||||
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
|
||||||
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
|
||||||
golang.org/x/tools v0.27.1-0.20241219162658-575221bfbda3 h1:kgwdasJRsdDWYgWcEgMF424DiXwwXHSb3V8xVTi//i8=
|
|
||||||
golang.org/x/tools v0.27.1-0.20241219162658-575221bfbda3/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q=
|
|
||||||
golang.org/x/tools/gopls v0.17.1 h1:Mt/DSfnnSe3dyf6MH/dZZ0iww+viHNhAFc4rEYDiOAw=
|
|
||||||
golang.org/x/tools/gopls v0.17.1/go.mod h1:niea3AFBDJrqLpvDQ8vjmtzjGcT44nAoYm/vd34SaH4=
|
|
||||||
golang.org/x/vuln v1.0.4 h1:SP0mPeg2PmGCu03V+61EcQiOjmpri2XijexKdzv8Z1I=
|
|
||||||
golang.org/x/vuln v1.0.4/go.mod h1:NbJdUQhX8jY++FtuhrXs2Eyx0yePo9pF7nPlIjo9aaQ=
|
|
||||||
gopkg.in/guregu/null.v4 v4.0.0 h1:1Wm3S1WEA2I26Kq+6vcW+w0gcDo44YKYD7YIEJNHDjg=
|
gopkg.in/guregu/null.v4 v4.0.0 h1:1Wm3S1WEA2I26Kq+6vcW+w0gcDo44YKYD7YIEJNHDjg=
|
||||||
gopkg.in/guregu/null.v4 v4.0.0/go.mod h1:YoQhUrADuG3i9WqesrCmpNRwm1ypAgSHYqoOcTu/JrI=
|
gopkg.in/guregu/null.v4 v4.0.0/go.mod h1:YoQhUrADuG3i9WqesrCmpNRwm1ypAgSHYqoOcTu/JrI=
|
||||||
gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
honnef.co/go/tools v0.5.1 h1:4bH5o3b5ZULQ4UrBmP+63W9r7qIkqJClEA9ko5YKx+I=
|
|
||||||
honnef.co/go/tools v0.5.1/go.mod h1:e9irvo83WDG9/irijV44wr3tbhcFeRnfpVlRqVwpzMs=
|
|
||||||
mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU=
|
|
||||||
mvdan.cc/gofumpt v0.7.0/go.mod h1:txVFJy/Sc/mvaycET54pV8SW8gWxTlUuGHVEcncmNUo=
|
|
||||||
mvdan.cc/xurls/v2 v2.5.0 h1:lyBNOm8Wo71UknhUs4QTFUNNMyxy2JEIaKKo0RWOh+8=
|
|
||||||
mvdan.cc/xurls/v2 v2.5.0/go.mod h1:yQgaGQ1rFtJUzkmKiHYSSfuQxqfYmd//X6PxvholpeE=
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user