Compare commits
No commits in common. "main" and "demo-alpr" have entirely different histories.
@ -30,7 +30,7 @@ RUN export CGO_ENABLED=0 && \
|
||||
COPY . .
|
||||
|
||||
RUN sed -i '/replace/d' go.mod
|
||||
RUN if [ ! -f swagger/index.html ]; then timeout 15 bee run -gendoc=true -downdoc=true; fi
|
||||
RUN if [ ! -f swagger/index.html ]; then timeout 15 bee run --gendoc=true --downdoc=true; fi
|
||||
RUN bee generate routers
|
||||
RUN bee generate docs
|
||||
RUN bee pack
|
||||
|
11
Makefile
11
Makefile
@ -21,20 +21,15 @@ clean:
|
||||
rm -rf oc-datacenter.tar.gz
|
||||
|
||||
docker:
|
||||
DOCKER_BUILDKIT=1 docker build -t oc-datacenter -f Dockerfile . --build-arg=HOST=$(HOST)
|
||||
docker tag oc-datacenter:latest oc/oc-datacenter:0.0.1
|
||||
DOCKER_BUILDKIT=1 docker build -t oc/oc-datacenter:0.0.1 -f Dockerfile .
|
||||
docker tag oc/oc-datacenter:0.0.1 oc/oc-datacenter:latest
|
||||
|
||||
publish-kind:
|
||||
kind load docker-image oc/oc-datacenter:0.0.1 --name opencloud | true
|
||||
kind load docker-image oc/oc-datacenter:0.0.1 --name opencloud
|
||||
|
||||
publish-registry:
|
||||
@echo "TODO"
|
||||
|
||||
docker-deploy:
|
||||
docker compose up -d
|
||||
|
||||
run-docker: docker publish-kind publish-registry docker-deploy
|
||||
|
||||
all: docker publish-kind publish-registry
|
||||
|
||||
.PHONY: build run clean docker publish-kind publish-registry
|
||||
|
@ -9,8 +9,6 @@ type Config struct {
|
||||
KubeCA string
|
||||
KubeCert string
|
||||
KubeData string
|
||||
MinioRootKey string
|
||||
MinioRootSecret string
|
||||
}
|
||||
|
||||
var instance *Config
|
||||
|
@ -10,13 +10,10 @@ import (
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
oclib "cloud.o-forge.io/core/oc-lib"
|
||||
|
||||
beego "github.com/beego/beego/v2/server/web"
|
||||
jwt "github.com/golang-jwt/jwt/v5"
|
||||
"gopkg.in/yaml.v2"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
)
|
||||
|
||||
type KubeInfo struct {
|
||||
@ -42,21 +39,22 @@ type KubeconfigToken struct {
|
||||
Kind string `yaml:"kind"`
|
||||
Preferences string `yaml:"preferences"`
|
||||
CurrentContext string `yaml:"current-context"`
|
||||
Clusters []struct {
|
||||
Cluster struct {
|
||||
Clusters []struct{
|
||||
Cluster struct{
|
||||
CA string `yaml:"certificate-authority-data"`
|
||||
Server string `yaml:"server"`
|
||||
|
||||
} `yaml:"cluster"`
|
||||
Name string `yaml:"name"`
|
||||
} `yaml:"clusters"`
|
||||
Contexts []struct {
|
||||
Context struct {
|
||||
Contexts []struct{
|
||||
Context struct{
|
||||
Cluster string `yaml:"cluster"`
|
||||
User string `yaml:"user"`
|
||||
} `yaml:"context"`
|
||||
Name string `yaml:"name"`
|
||||
} `yaml:"contexts"`
|
||||
Users []struct {
|
||||
Users []struct{
|
||||
Name string `yaml:"name"`
|
||||
User struct {
|
||||
Token string `yaml:"token"`
|
||||
@ -64,6 +62,8 @@ type KubeconfigToken struct {
|
||||
} `yaml:"users"`
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Operations about the admiralty objects of the datacenter
|
||||
type AdmiraltyController struct {
|
||||
beego.Controller
|
||||
@ -77,7 +77,7 @@ func (c *AdmiraltyController) GetAllTargets() {
|
||||
serv, err := infrastructure.NewService()
|
||||
if err != nil {
|
||||
// change code to 500
|
||||
HandleControllerErrors(c.Controller, 500, &err, nil)
|
||||
HandleControllerErrors(c.Controller,500,&err,nil)
|
||||
// c.Ctx.Output.SetStatus(500)
|
||||
// c.ServeJSON()
|
||||
// c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
@ -106,14 +106,8 @@ func (c *AdmiraltyController) GetOneTarget() {
|
||||
}
|
||||
|
||||
res, err := serv.GetTargets(c.Ctx.Request.Context())
|
||||
if err != nil {
|
||||
c.Ctx.Output.SetStatus(500)
|
||||
c.ServeJSON()
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
return
|
||||
}
|
||||
id = "target-" + id
|
||||
found := slices.Contains(res, id)
|
||||
id = "target-"+id
|
||||
found := slices.Contains(res,id)
|
||||
if !found {
|
||||
c.Ctx.Output.SetStatus(404)
|
||||
c.ServeJSON()
|
||||
@ -123,40 +117,12 @@ func (c *AdmiraltyController) GetOneTarget() {
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title DeleteAdmiraltySession
|
||||
// @Description find one Admiralty Target
|
||||
// @Param execution path string true "the name of the target to get"
|
||||
// @Success 200
|
||||
// @router /targets/:execution [delete]
|
||||
func (c *AdmiraltyController) DeleteAdmiraltySession() {
|
||||
id := c.Ctx.Input.Param(":execution")
|
||||
serv, err := infrastructure.NewService()
|
||||
if err != nil {
|
||||
// change code to 500
|
||||
c.Ctx.Output.SetStatus(500)
|
||||
c.ServeJSON()
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
return
|
||||
}
|
||||
|
||||
err = serv.DeleteNamespace(c.Ctx.Request.Context(), id)
|
||||
if err != nil {
|
||||
c.Ctx.Output.SetStatus(500)
|
||||
c.ServeJSON()
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = id
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title CreateAdmiraltySource
|
||||
// @Title CreateSource
|
||||
// @Description Create an Admiralty Source on remote cluster
|
||||
// @Param execution path string true "execution id of the workflow"
|
||||
// @Success 201
|
||||
// @router /source/:execution [post]
|
||||
func (c *AdmiraltyController) CreateAdmiraltySource() {
|
||||
func (c *AdmiraltyController) CreateSource() {
|
||||
|
||||
execution := c.Ctx.Input.Param(":execution")
|
||||
fmt.Println("execution :: ", execution)
|
||||
@ -171,14 +137,8 @@ func (c *AdmiraltyController) CreateAdmiraltySource() {
|
||||
return
|
||||
}
|
||||
|
||||
res, err := serv.CreateAdmiraltySource(c.Ctx.Request.Context(), execution)
|
||||
res, err := serv.CreateAdmiraltySource(c.Ctx.Request.Context(),execution)
|
||||
if err != nil {
|
||||
if apierrors.IsAlreadyExists(err) {
|
||||
c.Ctx.Output.SetStatus(409)
|
||||
c.Data["json"] = map[string]string{"info": "A source already exists for this namespace : " + execution}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
// change code to 500
|
||||
c.Ctx.Output.SetStatus(500)
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
@ -188,13 +148,8 @@ func (c *AdmiraltyController) CreateAdmiraltySource() {
|
||||
|
||||
// TODO : Return a description of the created resource
|
||||
var respData map[string]interface{}
|
||||
err = json.Unmarshal(res, &respData)
|
||||
if err != nil {
|
||||
c.Ctx.Output.SetStatus(500)
|
||||
c.ServeJSON()
|
||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(res,&respData)
|
||||
|
||||
c.Ctx.Output.SetStatus(201)
|
||||
c.Data["json"] = respData
|
||||
c.ServeJSON()
|
||||
@ -204,21 +159,13 @@ func (c *AdmiraltyController) CreateAdmiraltySource() {
|
||||
// @Title CreateAdmiraltyTarget
|
||||
// @Description Create an Admiralty Target in the namespace associated to the executionID
|
||||
// @Param execution path string true "execution id of the workflow"
|
||||
// @Param peer path string true "peerId of the peer the target points to"
|
||||
// @Success 201
|
||||
// @router /target/:execution/:peer [post]
|
||||
func (c *AdmiraltyController) CreateAdmiraltyTarget() {
|
||||
// @router /target/:execution [post]
|
||||
func (c *AdmiraltyController) CreateAdmiraltyTarget(){
|
||||
var data map[string]interface{}
|
||||
|
||||
execution := c.Ctx.Input.Param(":execution")
|
||||
peerId := c.Ctx.Input.Param(":peer")
|
||||
|
||||
if execution == "" || peerId == "" {
|
||||
c.Ctx.Output.SetStatus(400)
|
||||
c.Data["json"] = map[string]string{"error": "parameters can be empty " + "execution: " + execution + " peer: " + peerId}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
|
||||
serv, err := infrastructure.NewService()
|
||||
if err != nil {
|
||||
@ -229,7 +176,7 @@ func (c *AdmiraltyController) CreateAdmiraltyTarget() {
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := serv.CreateAdmiraltyTarget(c.Ctx.Request.Context(), execution, peerId)
|
||||
resp, err := serv.CreateAdmiraltyTarget(c.Ctx.Request.Context(),execution)
|
||||
if err != nil {
|
||||
// change code to 500
|
||||
c.Ctx.Output.SetStatus(500)
|
||||
@ -242,12 +189,12 @@ func (c *AdmiraltyController) CreateAdmiraltyTarget() {
|
||||
fmt.Println(resp)
|
||||
fmt.Println(err)
|
||||
c.Ctx.Output.SetStatus(401)
|
||||
c.Data["json"] = map[string]string{"error": "Could not perform the action"}
|
||||
c.Data["json"] = map[string]string{"error" : "Could not perform the action" }
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
|
||||
err = json.Unmarshal(resp, &data)
|
||||
err = json.Unmarshal(resp,&data)
|
||||
if err != nil {
|
||||
// change code to 500
|
||||
c.Ctx.Output.SetStatus(500)
|
||||
@ -263,15 +210,14 @@ func (c *AdmiraltyController) CreateAdmiraltyTarget() {
|
||||
|
||||
// @Title GetKubeSecret
|
||||
// @Description Retrieve the secret created from a Kubeconfig that will be associated to an Admiralty Target
|
||||
|
||||
// @Param execution path string true "execution id of the workflow"
|
||||
// @Param peer path string true "UUID of the peer to which the resource is linked"
|
||||
// @Success 200
|
||||
// @router /secret/:execution/:peer [get]
|
||||
func (c *AdmiraltyController) GetKubeSecret() {
|
||||
// @router /secret/:execution [get]
|
||||
func(c *AdmiraltyController) GetKubeSecret() {
|
||||
var data map[string]interface{}
|
||||
|
||||
execution := c.Ctx.Input.Param(":execution")
|
||||
peerId := c.Ctx.Input.Param(":peer")
|
||||
|
||||
serv, err := infrastructure.NewService()
|
||||
if err != nil {
|
||||
@ -282,7 +228,7 @@ func (c *AdmiraltyController) GetKubeSecret() {
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := serv.GetKubeconfigSecret(c.Ctx.Request.Context(), execution, peerId)
|
||||
resp, err := serv.GetKubeconfigSecret(c.Ctx.Request.Context(),execution)
|
||||
if err != nil {
|
||||
// change code to 500
|
||||
c.Ctx.Output.SetStatus(500)
|
||||
@ -296,7 +242,7 @@ func (c *AdmiraltyController) GetKubeSecret() {
|
||||
return
|
||||
}
|
||||
|
||||
err = json.Unmarshal(resp, &data)
|
||||
err = json.Unmarshal(resp,&data)
|
||||
if err != nil {
|
||||
// change code to 500
|
||||
c.Ctx.Output.SetStatus(500)
|
||||
@ -309,14 +255,14 @@ func (c *AdmiraltyController) GetKubeSecret() {
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
|
||||
// @Title CreateKubeSecret
|
||||
// @Description Creat a secret from a Kubeconfig that will be associated to an Admiralty Target
|
||||
|
||||
// @Param execution path string true "execution id of the workflow"
|
||||
// @Param peer path string true "UUID of the peer to which the resource is linked"
|
||||
// @Param kubeconfig body controllers.RemoteKubeconfig true "Kubeconfig to use when creating secret"
|
||||
// @Success 201
|
||||
// @router /secret/:execution/:peer [post]
|
||||
// @router /secret/:execution [post]
|
||||
func (c *AdmiraltyController) CreateKubeSecret() {
|
||||
var kubeconfig RemoteKubeconfig
|
||||
var respData map[string]interface{}
|
||||
@ -333,8 +279,9 @@ func (c *AdmiraltyController) CreateKubeSecret() {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
execution := c.Ctx.Input.Param(":execution")
|
||||
peerId := c.Ctx.Input.Param(":peer")
|
||||
|
||||
|
||||
serv, err := infrastructure.NewService()
|
||||
if err != nil {
|
||||
@ -345,7 +292,7 @@ func (c *AdmiraltyController) CreateKubeSecret() {
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := serv.CreateKubeconfigSecret(c.Ctx.Request.Context(), *kubeconfig.Data, execution, peerId)
|
||||
resp, err := serv.CreateKubeconfigSecret(c.Ctx.Request.Context(),*kubeconfig.Data,execution)
|
||||
if err != nil {
|
||||
// change code to 500
|
||||
c.Ctx.Output.SetStatus(500)
|
||||
@ -354,7 +301,7 @@ func (c *AdmiraltyController) CreateKubeSecret() {
|
||||
return
|
||||
}
|
||||
|
||||
err = json.Unmarshal(resp, &respData)
|
||||
err = json.Unmarshal(resp,&respData)
|
||||
c.Ctx.Output.SetStatus(201)
|
||||
c.Data["json"] = respData
|
||||
c.ServeJSON()
|
||||
@ -364,13 +311,13 @@ func (c *AdmiraltyController) CreateKubeSecret() {
|
||||
// @name GetAdmiraltyNodes
|
||||
// @description Allows user to test if an admiralty connection has already been established : Target and valid Secret set up on the local host and Source set up on remote host
|
||||
// @Param execution path string true "execution id of the workflow"
|
||||
// @Param peer path string true "UUID of the peer to which the resource is linked"
|
||||
// @Success 200
|
||||
// @router /node/:execution/:peer [get]
|
||||
func (c *AdmiraltyController) GetNodeReady() {
|
||||
// @router /node/:execution [get]
|
||||
func (c *AdmiraltyController) GetNodeReady(){
|
||||
var secret v1.Secret
|
||||
|
||||
execution := c.Ctx.Input.Param(":execution")
|
||||
peerId := c.Ctx.Input.Param(":peer")
|
||||
|
||||
|
||||
serv, err := infrastructure.NewService()
|
||||
if err != nil {
|
||||
@ -381,7 +328,7 @@ func (c *AdmiraltyController) GetNodeReady() {
|
||||
return
|
||||
}
|
||||
|
||||
node, err := serv.GetOneNode(c.Ctx.Request.Context(), execution, peerId)
|
||||
node, err := serv.GetOneNode(c.Ctx.Request.Context(),execution)
|
||||
if err != nil {
|
||||
// change code to 500
|
||||
c.Ctx.Output.SetStatus(500)
|
||||
@ -392,13 +339,13 @@ func (c *AdmiraltyController) GetNodeReady() {
|
||||
if node == nil {
|
||||
c.Ctx.Output.SetStatus(404)
|
||||
c.Data["json"] = map[string]string{
|
||||
"node": "the node for " + execution + " can't be found, make sure both target and source resources are set up on local and remote hosts",
|
||||
"error" : "the node for " + execution + " can't be found, make sure both target and source resources are set up on local and remote hosts",
|
||||
}
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := serv.GetKubeconfigSecret(c.Ctx.Request.Context(), execution, peerId)
|
||||
resp, err := serv.GetKubeconfigSecret(c.Ctx.Request.Context(),execution)
|
||||
if err != nil {
|
||||
// change code to 500
|
||||
c.Ctx.Output.SetStatus(500)
|
||||
@ -413,14 +360,15 @@ func (c *AdmiraltyController) GetNodeReady() {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// Extract JWT token RS265 encoded
|
||||
var editedKubeconfig map[string]interface{}
|
||||
json.Unmarshal(resp, &secret)
|
||||
json.Unmarshal(resp,&secret)
|
||||
byteEditedKubeconfig := secret.Data["config"]
|
||||
err = yaml.Unmarshal(byteEditedKubeconfig, &editedKubeconfig)
|
||||
err = yaml.Unmarshal(byteEditedKubeconfig,&editedKubeconfig)
|
||||
// err = json.Unmarshal(byteEditedKubeconfig,&editedKubeconfig)
|
||||
if err != nil {
|
||||
fmt.Println("Error while retrieving the kubeconfig from secret-", execution)
|
||||
fmt.Println("Error while retrieving the kubeconfig from secret-",execution)
|
||||
fmt.Println(err)
|
||||
c.Ctx.Output.SetStatus(500)
|
||||
c.Data["json"] = err
|
||||
@ -432,7 +380,7 @@ func (c *AdmiraltyController) GetNodeReady() {
|
||||
if err != nil {
|
||||
fmt.Println("Error while trying to retrieve token for kubeconfing")
|
||||
fmt.Println(err)
|
||||
HandleControllerErrors(c.Controller, 500, &err, nil)
|
||||
HandleControllerErrors(c.Controller,500,&err,nil)
|
||||
}
|
||||
|
||||
// Decode token
|
||||
@ -445,20 +393,19 @@ func (c *AdmiraltyController) GetNodeReady() {
|
||||
}
|
||||
|
||||
if *isExpired {
|
||||
c.Data["json"] = map[string]interface{}{
|
||||
"token": "token in the secret is expired and must be regenerated",
|
||||
"node": node,
|
||||
c.Data["json"] = map[string]string{
|
||||
"token" : "token in the secret is expired and must be regenerated",
|
||||
}
|
||||
c.Ctx.Output.SetStatus(410)
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
c.Data["json"] = map[string]interface{}{"node": node, "token": true}
|
||||
c.Data["json"] = map[string]bool{"ok": true}
|
||||
c.ServeJSON()
|
||||
|
||||
}
|
||||
|
||||
func retrieveTokenFromKonfig(editedKubeconfig map[string]interface{}) (string, error) {
|
||||
func retrieveTokenFromKonfig(editedKubeconfig map[string]interface{}) (string,error) {
|
||||
var kubeUsers []KubeUser
|
||||
b, err := yaml.Marshal(editedKubeconfig["users"])
|
||||
if err != nil {
|
||||
@ -466,7 +413,7 @@ func retrieveTokenFromKonfig(editedKubeconfig map[string]interface{}) (string, e
|
||||
fmt.Println(err)
|
||||
return "", err
|
||||
}
|
||||
err = yaml.Unmarshal(b, &kubeUsers)
|
||||
err = yaml.Unmarshal(b,&kubeUsers)
|
||||
if err != nil {
|
||||
fmt.Println("Error while unmarshalling users attribute from kubeconfig")
|
||||
fmt.Println(err)
|
||||
@ -478,9 +425,7 @@ func retrieveTokenFromKonfig(editedKubeconfig map[string]interface{}) (string, e
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func isTokenExpired(token string) (*bool, error) {
|
||||
logger := oclib.GetLogger()
|
||||
|
||||
func isTokenExpired(token string) (*bool, error){
|
||||
t, _, err := new(jwt.Parser).ParseUnverified(token, jwt.MapClaims{})
|
||||
if err != nil {
|
||||
fmt.Println("couldn't decode token")
|
||||
@ -492,10 +437,7 @@ func isTokenExpired(token string) (*bool, error) {
|
||||
fmt.Println("Error while checking token's expiration time")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
logger.Debug().Msg("Expiration date : " + expiration.UTC().Format("2006-01-02T15:04:05"))
|
||||
logger.Debug().Msg(fmt.Sprint("Now : ", time.Now().Unix()))
|
||||
logger.Debug().Msg(fmt.Sprint("Token : ", expiration.Unix()))
|
||||
fmt.Println("Expiration date : " + expiration.UTC().Format("2006-01-02T15:04:05"))
|
||||
|
||||
expired := expiration.Unix() < time.Now().Unix()
|
||||
|
||||
@ -512,6 +454,7 @@ func (c *AdmiraltyController) GetAdmiraltyKubeconfig() {
|
||||
|
||||
execution := c.Ctx.Input.Param(":execution")
|
||||
|
||||
|
||||
serv, err := infrastructure.NewService()
|
||||
if err != nil {
|
||||
// change code to 500
|
||||
@ -521,7 +464,7 @@ func (c *AdmiraltyController) GetAdmiraltyKubeconfig() {
|
||||
return
|
||||
}
|
||||
|
||||
generatedToken, err := serv.GenerateToken(c.Ctx.Request.Context(), execution, 3600)
|
||||
generatedToken, err := serv.GenerateToken(c.Ctx.Request.Context(),execution,3600)
|
||||
if err != nil {
|
||||
fmt.Println("Couldn't generate a token for ns-", execution)
|
||||
fmt.Println(err)
|
||||
@ -553,11 +496,12 @@ func (c *AdmiraltyController) GetAdmiraltyKubeconfig() {
|
||||
c.Data["json"] = map[string]string{
|
||||
"data": encodedKubeconfig,
|
||||
}
|
||||
json.NewEncoder(c.Ctx.ResponseWriter)
|
||||
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
func NewHostKubeWithToken(token string) (*models.KubeConfigValue, error) {
|
||||
|
||||
func NewHostKubeWithToken(token string) (*models.KubeConfigValue, error){
|
||||
if len(token) == 0 {
|
||||
return nil, fmt.Errorf("you didn't provide a token to be inserted in the Kubeconfig")
|
||||
}
|
||||
@ -588,7 +532,7 @@ func NewHostKubeWithToken(token string) (*models.KubeConfigValue, error) {
|
||||
},
|
||||
},
|
||||
Users: []models.KubeconfigUser{
|
||||
{
|
||||
models.KubeconfigUser{
|
||||
Name: "default",
|
||||
User: models.KubeconfigUserKeyPair{
|
||||
Token: token,
|
||||
|
@ -4,19 +4,14 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"oc-datacenter/infrastructure"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
oclib "cloud.o-forge.io/core/oc-lib"
|
||||
"cloud.o-forge.io/core/oc-lib/dbs"
|
||||
"cloud.o-forge.io/core/oc-lib/models/booking"
|
||||
"cloud.o-forge.io/core/oc-lib/models/utils"
|
||||
"cloud.o-forge.io/core/oc-lib/tools"
|
||||
b "cloud.o-forge.io/core/oc-lib/models/booking"
|
||||
beego "github.com/beego/beego/v2/server/web"
|
||||
"github.com/gorilla/websocket"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
@ -113,27 +108,6 @@ func (o *BookingController) Get() {
|
||||
o.ServeJSON()
|
||||
}
|
||||
|
||||
var upgrader = websocket.Upgrader{
|
||||
CheckOrigin: func(r *http.Request) bool { return true }, // allow all origins
|
||||
}
|
||||
|
||||
// @Title Log
|
||||
// @Description find booking by id
|
||||
// @Param id path string true "the id you want to get"
|
||||
// @Success 200 {booking} models.booking
|
||||
// @router /:id [get]
|
||||
func (o *BookingController) Log() {
|
||||
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
|
||||
id := o.Ctx.Input.Param(":id")
|
||||
conn, err := upgrader.Upgrade(o.Ctx.ResponseWriter, o.Ctx.Request, nil)
|
||||
if err != nil {
|
||||
o.Ctx.WriteString("WebSocket upgrade failed: " + err.Error())
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
infrastructure.NewPrometheusService().Stream(id, 1*time.Second, user, peerID, groups, conn)
|
||||
}
|
||||
|
||||
// @Title Update
|
||||
// @Description create computes
|
||||
// @Param id path string true "the compute id you want to get"
|
||||
@ -155,7 +129,7 @@ func (o *BookingController) Put() {
|
||||
o.ServeJSON()
|
||||
return
|
||||
}
|
||||
booking := book.Data.(*booking.Booking)
|
||||
booking := book.Data.(*b.Booking)
|
||||
if time.Now().After(booking.ExpectedStartDate) {
|
||||
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.BOOKING), user, peerID, groups, nil).UpdateOne(res, id)
|
||||
} else {
|
||||
@ -196,10 +170,12 @@ func (o *BookingController) Check() {
|
||||
"error": errors.New("invalid date format"),
|
||||
}
|
||||
} else {
|
||||
bks := &booking.Booking{} // create a new booking object
|
||||
booking := &b.Booking{} // create a new booking object
|
||||
isAvailable, err2 := booking.Check(id, date, &date2, 1) // check if the booking is available
|
||||
fmt.Println(isAvailable, err2)
|
||||
code := 200
|
||||
err := ""
|
||||
if isAvailable, err2 := bks.Check(id, date, &date2, 1); !isAvailable {
|
||||
if !isAvailable {
|
||||
code = 409
|
||||
err = "booking not available"
|
||||
if err2 != nil {
|
||||
@ -208,7 +184,7 @@ func (o *BookingController) Check() {
|
||||
}
|
||||
o.Data["json"] = map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"is_available": true,
|
||||
"is_available": isAvailable,
|
||||
},
|
||||
"code": code,
|
||||
"error": err,
|
||||
@ -236,51 +212,17 @@ func (o *BookingController) Post() {
|
||||
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
|
||||
err := json.Unmarshal(o.Ctx.Input.CopyBody(10000000), &resp)
|
||||
if err != nil {
|
||||
o.Data["json"] = map[string]interface{}{
|
||||
"data": nil,
|
||||
"code": 422,
|
||||
"error": err,
|
||||
}
|
||||
o.ServeJSON()
|
||||
return
|
||||
}
|
||||
if resp.ResourceType == tools.COMPUTE_RESOURCE {
|
||||
// later should check... health for any such as docker...
|
||||
res := oclib.NewRequest(oclib.LibDataEnum(oclib.COMPUTE_RESOURCE), user, peerID, groups, nil).LoadOne(resp.ResourceID)
|
||||
if res.Err != "" {
|
||||
o.Data["json"] = map[string]interface{}{
|
||||
"data": nil,
|
||||
"code": res.Code,
|
||||
"error": res.Err,
|
||||
}
|
||||
o.ServeJSON()
|
||||
return
|
||||
}
|
||||
/*serv, err := infrastructure.NewServiceByType(res.ToComputeResource().Infrastructure.String())
|
||||
if err != nil {
|
||||
o.Data["json"] = map[string]interface{}{
|
||||
"data": nil,
|
||||
"code": 500,
|
||||
"error": err,
|
||||
}
|
||||
o.ServeJSON()
|
||||
return
|
||||
}
|
||||
if err := serv.CheckHealth(); err != nil {
|
||||
o.Data["json"] = map[string]interface{}{
|
||||
"data": nil,
|
||||
"code": 500,
|
||||
"error": err,
|
||||
}
|
||||
o.ServeJSON()
|
||||
return
|
||||
}*/
|
||||
fmt.Println("Error unmarshalling")
|
||||
fmt.Println(err)
|
||||
fmt.Println(resp)
|
||||
}
|
||||
|
||||
dc_id := resp.ResourceID
|
||||
// delete all previous bookings
|
||||
isDraft := o.Ctx.Input.Query("is_draft")
|
||||
res := oclib.NewRequest(oclib.LibDataEnum(oclib.BOOKING), user, peerID, groups, nil).Search(&dbs.Filters{And: map[string][]dbs.Filter{
|
||||
"workflow_id": {{Operator: dbs.EQUAL.String(), Value: resp.WorkflowID}},
|
||||
"resource_id": {{Operator: dbs.EQUAL.String(), Value: resp.ResourceID}},
|
||||
"resource_id": {{Operator: dbs.EQUAL.String(), Value: dc_id}},
|
||||
}}, "", isDraft == "true")
|
||||
if res.Code != 200 {
|
||||
o.Data["json"] = map[string]interface{}{
|
||||
@ -304,16 +246,10 @@ func (o *BookingController) Post() {
|
||||
o.ServeJSON()
|
||||
return
|
||||
}
|
||||
if b.Data.(*booking.Booking).ResourceType == tools.COMPUTE_RESOURCE {
|
||||
go func() {
|
||||
time.Sleep(time.Until(b.Data.(*booking.Booking).ExpectedStartDate))
|
||||
infrastructure.NewPrometheusService().Stream(b.Data.GetID(), 1*time.Second, user, peerID, groups, nil)
|
||||
}()
|
||||
}
|
||||
|
||||
if err := o.createNamespace(resp.ExecutionsID); err != nil {
|
||||
/*if err := o.createNamespace(resp.ExecutionsID); err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
}*/
|
||||
|
||||
o.Data["json"] = map[string]interface{}{
|
||||
"data": []interface{}{b},
|
||||
@ -323,116 +259,6 @@ func (o *BookingController) Post() {
|
||||
o.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title ExtendForNamespace
|
||||
// @Description ExtendForNamespace booking
|
||||
// @Param namespace path string "targetted namespace"
|
||||
// @Param resource_id path string "resource id"
|
||||
// @Param end_date path string "the booking end date" format "2006-01-02T15:04:05"
|
||||
// @Param is_draft query string false "draft wished"
|
||||
// @Success 200 {object} models.object
|
||||
// @router /extend/:resource_id/from_namespace/:namespace/to/:duration [post]
|
||||
func (o *BookingController) ExtendForNamespace() {
|
||||
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
|
||||
resourceID := o.Ctx.Input.Param(":resource_id")
|
||||
namespace := o.Ctx.Input.Param(":namespace")
|
||||
duration, err := strconv.Atoi(o.Ctx.Input.Param(":duration"))
|
||||
if err != nil {
|
||||
o.Data["json"] = map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"is_available": false,
|
||||
},
|
||||
"code": 400,
|
||||
"error": errors.New("invalid date format"),
|
||||
}
|
||||
} else {
|
||||
o.extend(duration, resourceID, "executions_id", namespace, user, peerID, groups)
|
||||
}
|
||||
}
|
||||
|
||||
// @Title ExtendForExecution
|
||||
// @Description ExtendForExecution booking
|
||||
// @Param namespace path string "targetted namespace"
|
||||
// @Param resource_id path string "resource id"
|
||||
// @Param end_date path string "the booking end date" format "2006-01-02T15:04:05"
|
||||
// @Param is_draft query string false "draft wished"
|
||||
// @Success 200 {object} models.object
|
||||
// @router /extend/:resource_id/from_execution/:execution_id/to/:duration [post]
|
||||
func (o *BookingController) ExtendForExecution() {
|
||||
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
|
||||
resourceID := o.Ctx.Input.Param(":resource_id")
|
||||
executionID := o.Ctx.Input.Param(":execution_id")
|
||||
duration, err := strconv.Atoi(o.Ctx.Input.Param(":duration"))
|
||||
if err != nil {
|
||||
o.Data["json"] = map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"is_available": false,
|
||||
},
|
||||
"code": 400,
|
||||
"error": errors.New("invalid date format"),
|
||||
}
|
||||
} else {
|
||||
o.extend(duration, resourceID, "execution_id", executionID, user, peerID, groups)
|
||||
}
|
||||
}
|
||||
|
||||
func (o *BookingController) extend(duration int, resourceID string, key string, namespace string, user string, peerID string, groups []string) {
|
||||
/*
|
||||
* This function is used to check if a booking is available for a specific datacenter.
|
||||
* It takes the following parameters:
|
||||
* - id: the id of the datacenter
|
||||
* - start_date: the start date of the booking/search/execution/:id
|
||||
* - end_date: the end date of the booking
|
||||
*/
|
||||
|
||||
req := oclib.NewRequest(oclib.LibDataEnum(oclib.BOOKING), user, peerID, groups, nil)
|
||||
res := req.Search(&dbs.Filters{
|
||||
Or: map[string][]dbs.Filter{
|
||||
"expected_end_date": {
|
||||
{Operator: dbs.GTE.String(), Value: time.Now()},
|
||||
{Operator: dbs.EQUAL.String(), Value: bson.TypeNull},
|
||||
},
|
||||
},
|
||||
And: map[string][]dbs.Filter{
|
||||
"resource_id": {{Operator: dbs.EQUAL.String(), Value: resourceID}},
|
||||
key: {{Operator: dbs.EQUAL.String(), Value: namespace}},
|
||||
"expected_start_date": {{Operator: dbs.GTE.String(), Value: time.Now()}},
|
||||
},
|
||||
}, "", false)
|
||||
if res.Err == "" && len(res.Data) > 0 {
|
||||
var id string
|
||||
datas := []utils.DBObject{}
|
||||
for _, b := range res.Data {
|
||||
book := b.(*booking.Booking)
|
||||
if book.ExpectedEndDate != nil {
|
||||
bb := book.ExpectedEndDate.Add(time.Duration(duration) * time.Second)
|
||||
if isAvailable, err := (&booking.Booking{}).Check(id, (*book.ExpectedEndDate).Add(1*time.Second), &bb, 1); isAvailable && err == nil {
|
||||
book.ExpectedEndDate = &bb
|
||||
result := req.UpdateOne(book.Serialize(book), book.GetID())
|
||||
datas = append(datas, result.Data)
|
||||
}
|
||||
}
|
||||
}
|
||||
o.Data["json"] = map[string]interface{}{
|
||||
"data": datas,
|
||||
"code": 200,
|
||||
"error": "",
|
||||
}
|
||||
o.ServeJSON()
|
||||
return
|
||||
} else if res.Err == "" {
|
||||
o.Data["json"] = map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"is_available": false,
|
||||
},
|
||||
"code": 400,
|
||||
"error": errors.New("can't find any booking to extend"),
|
||||
}
|
||||
} else {
|
||||
o.Data["json"] = res
|
||||
}
|
||||
o.ServeJSON()
|
||||
}
|
||||
|
||||
func (o *BookingController) createNamespace(ns string) error {
|
||||
/*
|
||||
* This function is used to create a namespace.
|
||||
@ -468,5 +294,6 @@ func (o *BookingController) createNamespace(ns string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("ROLLLLLE BIND")
|
||||
return serv.CreateRoleBinding(o.Ctx.Request.Context(), ns, "argo-role-binding", role)
|
||||
}
|
||||
|
@ -1,122 +0,0 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"oc-datacenter/infrastructure"
|
||||
|
||||
oclib "cloud.o-forge.io/core/oc-lib"
|
||||
"cloud.o-forge.io/core/oc-lib/models/live"
|
||||
beego "github.com/beego/beego/v2/server/web"
|
||||
)
|
||||
|
||||
type MinioController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
|
||||
// @Title CreateServiceAccounnt
|
||||
// @Description Add a new ServiceAccount to a Minio server using its ID and an execution ID
|
||||
// @Success 200
|
||||
// @Param executions path string true "The executionsID of the execution"
|
||||
// @Param minioId path string true "The ID of the Minio you want to reach"
|
||||
// @router /serviceaccount/:minioId/:executions [post]
|
||||
func (m *MinioController) CreateServiceAccount() {
|
||||
_, peerID, _ := oclib.ExtractTokenInfo(*m.Ctx.Request)
|
||||
// This part is solely for dev purposes and should be removed once test on
|
||||
|
||||
|
||||
executionsId := m.Ctx.Input.Param(":executions")
|
||||
minioId := m.Ctx.Input.Param(":minioId")
|
||||
|
||||
// retrieve the live storage with the minioId
|
||||
s := oclib.NewRequest(oclib.LibDataEnum(oclib.STORAGE_RESOURCE), "", "", []string{}, nil).LoadOne(minioId)
|
||||
if s.Err != "" {
|
||||
m.Ctx.Output.SetStatus(400)
|
||||
m.Data["json"] = map[string]interface{}{"error":s.Err}
|
||||
m.ServeJSON()
|
||||
return
|
||||
}
|
||||
|
||||
live := findLiveStorage(minioId, peerID)
|
||||
if live == nil {
|
||||
m.Ctx.Output.SetStatus(404)
|
||||
m.Data["json"] = map[string]interface{}{"error":"could not find the Minio instance " + s.Err}
|
||||
m.ServeJSON()
|
||||
return
|
||||
}
|
||||
|
||||
url := live.Source
|
||||
service := infrastructure.NewMinioService(url)
|
||||
|
||||
// call the method ctrating the svcacc
|
||||
err := service.CreateClient()
|
||||
if err != nil {
|
||||
m.Ctx.Output.SetStatus(500)
|
||||
m.Data["json"] = map[string]interface{}{"error":"could not create the client for " + minioId + " : " + err.Error()}
|
||||
m.ServeJSON()
|
||||
return
|
||||
}
|
||||
|
||||
access, secret, err := service.CreateCredentials(executionsId)
|
||||
if err != nil {
|
||||
m.Ctx.Output.SetStatus(500)
|
||||
m.Data["json"] = map[string]interface{}{"error":"could not create the service account for " + minioId + " : " + err.Error()}
|
||||
m.ServeJSON()
|
||||
return
|
||||
}
|
||||
|
||||
// test if the namespace exists
|
||||
k, err := infrastructure.NewService()
|
||||
if err != nil {
|
||||
m.Ctx.Output.SetStatus(500)
|
||||
m.Data["json"] = map[string]string{"error": err.Error()}
|
||||
m.ServeJSON()
|
||||
return
|
||||
}
|
||||
|
||||
ns, err := k.GetNamespace(m.Ctx.Request.Context(), executionsId)
|
||||
if ns == nil {
|
||||
m.Ctx.Output.SetStatus(403)
|
||||
m.Data["json"] = map[string]string{"error":"Could not find the namespace corresponding to executionsID " + executionsId}
|
||||
m.ServeJSON()
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
m.Ctx.Output.SetStatus(500)
|
||||
m.Data["json"] = map[string]string{"error": "Error when trying to check if namespace " + executionsId + " exists : " + err.Error()}
|
||||
m.ServeJSON()
|
||||
return
|
||||
}
|
||||
|
||||
// store the credentials in the namespace
|
||||
err = k.CreateSecret(m.Ctx.Request.Context(), minioId, executionsId, access, secret)
|
||||
if err != nil {
|
||||
m.Ctx.Output.SetStatus(500)
|
||||
m.Data["json"] = map[string]string{"error": "Error when storing Minio serviceAccount credentials in namespace " + executionsId + " exists : " + err.Error()}
|
||||
m.ServeJSON()
|
||||
return
|
||||
}
|
||||
|
||||
m.Data["json"] = map[string]string{"success": "created secret " + executionsId + "-secret-sa in namespace ns-" + executionsId}
|
||||
m.ServeJSON()
|
||||
}
|
||||
|
||||
func findLiveStorage(storageId string, peerId string) *live.LiveStorage {
|
||||
res := oclib.NewRequest(oclib.LibDataEnum(oclib.LIVE_STORAGE),"",peerId,[]string{},nil).LoadAll(false)
|
||||
if res.Err != "" {
|
||||
l := oclib.GetLogger()
|
||||
l.Error().Msg(res.Err)
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, dbo := range res.Data {
|
||||
r := oclib.NewRequest(oclib.LibDataEnum(oclib.LIVE_STORAGE),"","",[]string{},nil).LoadOne(dbo.GetID())
|
||||
l := r.ToLiveStorage()
|
||||
for _, id := range l.ResourcesID {
|
||||
if id == storageId {
|
||||
return l
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
2
env.env
2
env.env
@ -1,4 +1,4 @@
|
||||
KUBERNETES_SERVICE_HOST=192.168.47.20
|
||||
KUBERNETES_SERVICE_HOST=192.168.1.169
|
||||
KUBE_CA="LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkekNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdGMyVnkKZG1WeUxXTmhRREUzTWpNeE1USXdNell3SGhjTk1qUXdPREE0TVRBeE16VTJXaGNOTXpRd09EQTJNVEF4TXpVMgpXakFqTVNFd0h3WURWUVFEREJock0zTXRjMlZ5ZG1WeUxXTmhRREUzTWpNeE1USXdNell3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFTVlk3ZHZhNEdYTVdkMy9jMlhLN3JLYjlnWXgyNSthaEE0NmkyNVBkSFAKRktQL2UxSVMyWVF0dzNYZW1TTUQxaStZdzJSaVppNUQrSVZUamNtNHdhcnFvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVWtlUVJpNFJiODduME5yRnZaWjZHClc2SU55NnN3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUlnRXA5ck04WmdNclRZSHYxZjNzOW5DZXZZeWVVa3lZUk4KWjUzazdoaytJS1FDSVFDbk05TnVGKzlTakIzNDFacGZ5ays2NEpWdkpSM3BhcmVaejdMd2lhNm9kdz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
|
||||
KUBE_CERT="LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrVENDQVRlZ0F3SUJBZ0lJWUxWNkFPQkdrU1F3Q2dZSUtvWkl6ajBFQXdJd0l6RWhNQjhHQTFVRUF3d1kKYXpOekxXTnNhV1Z1ZEMxallVQXhOekl6TVRFeU1ETTJNQjRYRFRJME1EZ3dPREV3TVRNMU5sb1hEVEkxTURndwpPREV3TVRNMU5sb3dNREVYTUJVR0ExVUVDaE1PYzNsemRHVnRPbTFoYzNSbGNuTXhGVEFUQmdOVkJBTVRESE41CmMzUmxiVHBoWkcxcGJqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJGQ2Q1MFdPeWdlQ2syQzcKV2FrOWY4MVAvSkJieVRIajRWOXBsTEo0ck5HeHFtSjJOb2xROFYxdUx5RjBtOTQ2Nkc0RmRDQ2dqaXFVSk92Swp3NVRPNnd5alNEQkdNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBakFmCkJnTlZIU01FR0RBV2dCVFJkOFI5cXVWK2pjeUVmL0ovT1hQSzMyS09XekFLQmdncWhrak9QUVFEQWdOSUFEQkYKQWlFQTArbThqTDBJVldvUTZ0dnB4cFo4NVlMalF1SmpwdXM0aDdnSXRxS3NmUVVDSUI2M2ZNdzFBMm5OVWU1TgpIUGZOcEQwSEtwcVN0Wnk4djIyVzliYlJUNklZCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJlRENDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdFkyeHAKWlc1MExXTmhRREUzTWpNeE1USXdNell3SGhjTk1qUXdPREE0TVRBeE16VTJXaGNOTXpRd09EQTJNVEF4TXpVMgpXakFqTVNFd0h3WURWUVFEREJock0zTXRZMnhwWlc1MExXTmhRREUzTWpNeE1USXdNell3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFRc3hXWk9pbnIrcVp4TmFEQjVGMGsvTDF5cE01VHAxOFRaeU92ektJazQKRTFsZWVqUm9STW0zNmhPeVljbnN3d3JoNnhSUnBpMW5RdGhyMzg0S0Z6MlBvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVTBYZkVmYXJsZm8zTWhIL3lmemx6Cnl0OWlqbHN3Q2dZSUtvWkl6ajBFQXdJRFNRQXdSZ0loQUxJL2dNYnNMT3MvUUpJa3U2WHVpRVMwTEE2cEJHMXgKcnBlTnpGdlZOekZsQWlFQW1wdjBubjZqN3M0MVI0QzFNMEpSL0djNE53MHdldlFmZWdEVGF1R2p3cFk9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
|
||||
KUBE_DATA="LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU5ZS1BFb1dhd1NKUzJlRW5oWmlYMk5VZlY1ZlhKV2krSVNnV09TNFE5VTlvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFVUozblJZN0tCNEtUWUx0WnFUMS96VS84a0Z2Sk1lUGhYMm1Vc25pczBiR3FZblkyaVZEeApYVzR2SVhTYjNqcm9iZ1YwSUtDT0twUWs2OHJEbE03ckRBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo="
|
88
go.mod
88
go.mod
@ -1,22 +1,18 @@
|
||||
module oc-datacenter
|
||||
|
||||
go 1.24.2
|
||||
go 1.23.0
|
||||
|
||||
toolchain go1.24.4
|
||||
toolchain go1.23.3
|
||||
|
||||
require (
|
||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250626142041-d58dc5602416
|
||||
github.com/beego/beego/v2 v2.3.8
|
||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250219142942-5111c9c8bec7
|
||||
github.com/beego/beego/v2 v2.3.1
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2
|
||||
github.com/gorilla/websocket v1.5.3
|
||||
github.com/minio/madmin-go/v4 v4.1.1
|
||||
github.com/minio/minio-go/v7 v7.0.94
|
||||
github.com/necmettindev/randomstring v0.1.0
|
||||
go.mongodb.org/mongo-driver v1.17.4
|
||||
go.mongodb.org/mongo-driver v1.17.1
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
k8s.io/api v0.32.3
|
||||
k8s.io/apimachinery v0.32.3
|
||||
k8s.io/client-go v0.32.3
|
||||
k8s.io/api v0.32.1
|
||||
k8s.io/apimachinery v0.32.1
|
||||
k8s.io/client-go v0.32.1
|
||||
)
|
||||
|
||||
require (
|
||||
@ -24,85 +20,63 @@ require (
|
||||
github.com/biter777/countries v1.7.5 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/ebitengine/purego v0.8.4 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
|
||||
github.com/go-ini/ini v1.67.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.6 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||
github.com/go-openapi/swag v0.23.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.26.0 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/go-playground/validator/v10 v10.22.1 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/golang/snappy v1.0.0 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/gnostic-models v0.6.8 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/goraz/onion v0.1.3 // indirect
|
||||
github.com/hashicorp/golang-lru v1.0.2 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
|
||||
github.com/klauspost/compress v1.17.11 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/minio/md5-simd v1.1.2 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/montanaflynn/stats v0.7.1 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/nats-io/nats.go v1.43.0 // indirect
|
||||
github.com/nats-io/nkeys v0.4.11 // indirect
|
||||
github.com/nats-io/nats.go v1.37.0 // indirect
|
||||
github.com/nats-io/nkeys v0.4.7 // indirect
|
||||
github.com/nats-io/nuid v1.0.1 // indirect
|
||||
github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
||||
github.com/prometheus/client_golang v1.22.0 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.65.0 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/prometheus/prom2json v1.4.2 // indirect
|
||||
github.com/prometheus/prometheus v0.304.1 // indirect
|
||||
github.com/prometheus/client_golang v1.20.5 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.60.1 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/robfig/cron v1.2.0 // indirect
|
||||
github.com/rs/xid v1.6.0 // indirect
|
||||
github.com/rs/zerolog v1.34.0 // indirect
|
||||
github.com/safchain/ethtool v0.6.1 // indirect
|
||||
github.com/secure-io/sio-go v0.3.1 // indirect
|
||||
github.com/rs/zerolog v1.33.0 // indirect
|
||||
github.com/shiena/ansicolor v0.0.0-20230509054315-a9deabde6e02 // indirect
|
||||
github.com/shirou/gopsutil/v4 v4.25.5 // indirect
|
||||
github.com/smartystreets/goconvey v1.7.2 // indirect
|
||||
github.com/tinylib/msgp v1.3.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.15 // indirect
|
||||
github.com/tklauser/numcpus v0.10.0 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||
github.com/xdg-go/scram v1.1.2 // indirect
|
||||
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
golang.org/x/crypto v0.39.0 // indirect
|
||||
golang.org/x/net v0.41.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sync v0.15.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/term v0.32.0 // indirect
|
||||
golang.org/x/text v0.26.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
golang.org/x/crypto v0.28.0 // indirect
|
||||
golang.org/x/net v0.30.0 // indirect
|
||||
golang.org/x/oauth2 v0.23.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/sys v0.26.0 // indirect
|
||||
golang.org/x/term v0.25.0 // indirect
|
||||
golang.org/x/text v0.19.0 // indirect
|
||||
golang.org/x/time v0.7.0 // indirect
|
||||
google.golang.org/protobuf v1.35.1 // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
|
191
go.sum
191
go.sum
@ -1,14 +1,8 @@
|
||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250624102227-e600fedcab06 h1:+RSv62uIC7wsmibsp1XTanQMNznNeOGgPpfhb6ZHT4c=
|
||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250624102227-e600fedcab06/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250626135921-34b7cdcf06b0 h1:FGWOxAAw3Zh19A2FUeAbttsfuFJ3JDli/un9iCu6uD8=
|
||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250626135921-34b7cdcf06b0/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250626142041-d58dc5602416 h1:C51EHyggOm2QZ7INqhKOiyapTIbtRi8y2eJjVXzdtnM=
|
||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250626142041-d58dc5602416/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI=
|
||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250219142942-5111c9c8bec7 h1:fh6SzBPenzIxufIIzExtx4jEE4OhFposqn3EbHFr92Q=
|
||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250219142942-5111c9c8bec7/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/beego/beego/v2 v2.3.1 h1:7MUKMpJYzOXtCUsTEoXOxsDV/UcHw6CPbaWMlthVNsc=
|
||||
github.com/beego/beego/v2 v2.3.1/go.mod h1:5cqHsOHJIxkq44tBpRvtDe59GuVRVv/9/tyVDxd5ce4=
|
||||
github.com/beego/beego/v2 v2.3.8 h1:wplhB1pF4TxR+2SS4PUej8eDoH4xGfxuHfS7wAk9VBc=
|
||||
github.com/beego/beego/v2 v2.3.8/go.mod h1:8vl9+RrXqvodrl9C8yivX1e6le6deCK6RWeq8R7gTTg=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/biter777/countries v1.7.5 h1:MJ+n3+rSxWQdqVJU8eBy9RqcdH6ePPn4PJHocVWUa+Q=
|
||||
@ -18,14 +12,11 @@ github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
|
||||
github.com/coreos/etcd v3.3.17+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw=
|
||||
github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||
github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE03qmvRTNfbw=
|
||||
github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
|
||||
@ -36,19 +27,14 @@ github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv
|
||||
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
||||
github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc=
|
||||
github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc=
|
||||
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
|
||||
github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
|
||||
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
|
||||
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
|
||||
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
|
||||
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
|
||||
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
|
||||
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
|
||||
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
|
||||
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
|
||||
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
|
||||
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
@ -59,42 +45,35 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA=
|
||||
github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
|
||||
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs=
|
||||
github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
|
||||
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
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/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
|
||||
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
|
||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/goraz/onion v0.1.3 h1:KhyvbDA2b70gcz/d5izfwTiOH8SmrvV43AsVzpng3n0=
|
||||
github.com/goraz/onion v0.1.3/go.mod h1:XEmz1XoBz+wxTgWB8NwuvRm4RAu3vKxvrmYtzK+XCuQ=
|
||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
|
||||
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
@ -107,40 +86,28 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
|
||||
github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
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/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 h1:PpXWgLPs+Fqr325bN2FD2ISlRRztXibcX6e8f5FR5Dc=
|
||||
github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/minio/madmin-go/v4 v4.1.1 h1:Y7JHamjTwnyvXO9aike5SC0c0sNsbs/NpG37c525oe4=
|
||||
github.com/minio/madmin-go/v4 v4.1.1/go.mod h1:16tMDVIHWcp1zrmL6XrgCwPlZC7kB3UNNs5GDNnjYLQ=
|
||||
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
||||
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
|
||||
github.com/minio/minio-go/v7 v7.0.94 h1:1ZoksIKPyaSt64AVOyaQvhDOgVC3MfZsWM6mZXRUGtM=
|
||||
github.com/minio/minio-go/v7 v7.0.94/go.mod h1:71t2CqDt3ThzESgZUlU1rBN54mksGGlkLcFgguDnnAc=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
@ -157,62 +124,38 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/nats-io/nats.go v1.37.0 h1:07rauXbVnnJvv1gfIyghFEo6lUcYRY0WXc3x7x0vUxE=
|
||||
github.com/nats-io/nats.go v1.37.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8=
|
||||
github.com/nats-io/nats.go v1.43.0 h1:uRFZ2FEoRvP64+UUhaTokyS18XBCR/xM2vQZKO4i8ug=
|
||||
github.com/nats-io/nats.go v1.43.0/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g=
|
||||
github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI=
|
||||
github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc=
|
||||
github.com/nats-io/nkeys v0.4.11 h1:q44qGV008kYd9W1b1nEBkNzvnWxtRSQ7A8BoqRrcfa0=
|
||||
github.com/nats-io/nkeys v0.4.11/go.mod h1:szDimtgmfOi9n25JpfIdGw12tZFYXqhGxjhVxsatHVE=
|
||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/necmettindev/randomstring v0.1.0 h1:HeU/mfLCd/5E9At7xznbTeEw5YldGW92fvK8lWtvPwE=
|
||||
github.com/necmettindev/randomstring v0.1.0/go.mod h1:h2nX9Jl0TLImuMt++XfLStVr8N76BmmP5D5EhLq0KEQ=
|
||||
github.com/ogier/pflag v0.0.1/go.mod h1:zkFki7tvTa0tafRvTBIZTvzYyAu6kQhPZFnshFFPE+g=
|
||||
github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
|
||||
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
|
||||
github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
|
||||
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
|
||||
github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys=
|
||||
github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c h1:dAMKvw0MlJT1GshSTtih8C2gDs04w8dReiOGXrGLNoY=
|
||||
github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
|
||||
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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
|
||||
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
|
||||
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/prometheus/prom2json v1.4.2 h1:PxCTM+Whqi/eykO1MKsEL0p/zMpxp9ybpsmdFamw6po=
|
||||
github.com/prometheus/prom2json v1.4.2/go.mod h1:zuvPm7u3epZSbXPWHny6G+o8ETgu6eAK3oPr6yFkRWE=
|
||||
github.com/prometheus/prometheus v0.304.1 h1:e4kpJMb2Vh/PcR6LInake+ofcvFYHT+bCfmBvOkaZbY=
|
||||
github.com/prometheus/prometheus v0.304.1/go.mod h1:ioGx2SGKTY+fLnJSQCdTHqARVldGNS8OlIe3kvp98so=
|
||||
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
|
||||
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc=
|
||||
github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw=
|
||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
|
||||
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
|
||||
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
||||
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
|
||||
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
||||
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
|
||||
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
|
||||
github.com/safchain/ethtool v0.6.1 h1:mhRnXE1H8fV8TTXh/HdqE4tXtb57r//BQh5pPYMuM5k=
|
||||
github.com/safchain/ethtool v0.6.1/go.mod h1:JzoNbG8xeg/BeVeVoMCtCb3UPWoppZZbFpA+1WFh+M0=
|
||||
github.com/secure-io/sio-go v0.3.1 h1:dNvY9awjabXTYGsTF1PiCySl9Ltofk9GA3VdWlo7rRc=
|
||||
github.com/secure-io/sio-go v0.3.1/go.mod h1:+xbkjDzPjwh4Axd07pRKSNriS9SCiYksWnZqdnfpQxs=
|
||||
github.com/shiena/ansicolor v0.0.0-20230509054315-a9deabde6e02 h1:v9ezJDHA1XGxViAUSIoO/Id7Fl63u6d0YmsAm+/p2hs=
|
||||
github.com/shiena/ansicolor v0.0.0-20230509054315-a9deabde6e02/go.mod h1:RF16/A3L0xSa0oSERcnhd8Pu3IXSDZSK2gmGIMsttFE=
|
||||
github.com/shirou/gopsutil/v4 v4.25.5 h1:rtd9piuSMGeU8g1RMXjZs9y9luK5BwtnG7dZaQUJAsc=
|
||||
github.com/shirou/gopsutil/v4 v4.25.5/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c=
|
||||
github.com/skarademir/naturalsort v0.0.0-20150715044055-69a5d87bef62/go.mod h1:oIdVclZaltY1Nf7OQUkg1/2jImBJ+ZfKZuDIRSwk3p0=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
|
||||
@ -223,15 +166,14 @@ github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/tinylib/msgp v1.3.0 h1:ULuf7GPooDaIlbyvgAxBV/FI7ynli6LZ1/nVUNu+0ww=
|
||||
github.com/tinylib/msgp v1.3.0/go.mod h1:ykjzy2wzgrlvpDCRc4LA8UXy6D8bzMSuAF3WD57Gok0=
|
||||
github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4=
|
||||
github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4=
|
||||
github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso=
|
||||
github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||
@ -245,20 +187,15 @@ github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfS
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
go.mongodb.org/mongo-driver v1.17.1 h1:Wic5cJIwJgSpBhe3lx3+/RybR5PiYRMpVFgO7cOHyIM=
|
||||
go.mongodb.org/mongo-driver v1.17.1/go.mod h1:wwWm/+BuOddhcq3n68LKRmgk2wXzmF6s0SFOa0GINL4=
|
||||
go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw=
|
||||
go.mongodb.org/mongo-driver v1.17.4/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
|
||||
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-20191112222119-e1110fd1c708/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
|
||||
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
||||
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
||||
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
@ -269,60 +206,55 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
||||
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
||||
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
||||
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
|
||||
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
|
||||
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
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-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/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-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
||||
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
||||
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
|
||||
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
|
||||
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.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
||||
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
||||
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
||||
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
|
||||
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
|
||||
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
||||
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
||||
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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
||||
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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=
|
||||
@ -334,14 +266,15 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls=
|
||||
k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k=
|
||||
k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U=
|
||||
k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
|
||||
k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU=
|
||||
k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY=
|
||||
k8s.io/api v0.32.1 h1:f562zw9cy+GvXzXf0CKlVQ7yHJVYzLfL6JAS4kOAaOc=
|
||||
k8s.io/api v0.32.1/go.mod h1:/Yi/BqkuueW1BgpoePYBRdDYfjPF5sgTr5+YqDZra5k=
|
||||
k8s.io/apimachinery v0.32.1 h1:683ENpaCBjma4CYqsmZyhEzrGz6cjn1MY/X2jB2hkZs=
|
||||
k8s.io/apimachinery v0.32.1/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
|
||||
k8s.io/client-go v0.32.1 h1:otM0AxdhdBIaQh7l1Q0jQpmo7WOFIk5FFa4bg6YMdUU=
|
||||
k8s.io/client-go v0.32.1/go.mod h1:aTTKZY7MdxUaJ/KiUs8D+GssR9zJZi77ZqtzcGXIiDg=
|
||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
|
||||
|
@ -15,29 +15,18 @@ type Infrastructure interface {
|
||||
CreateServiceAccount(ctx context.Context, ns string) error
|
||||
CreateRoleBinding(ctx context.Context, ns string, roleBinding string, role string) error
|
||||
CreateRole(ctx context.Context, ns string, role string, groups [][]string, resources [][]string, verbs [][]string) error
|
||||
GetTargets(ctx context.Context) ([]string, error)
|
||||
CreateAdmiraltySource(context context.Context, executionId string) ([]byte, error)
|
||||
CreateKubeconfigSecret(context context.Context, kubeconfig string, executionId string, peerId string) ([]byte, error)
|
||||
GetKubeconfigSecret(context context.Context, executionId string, peerId string) ([]byte, error)
|
||||
CreateAdmiraltyTarget(context context.Context, executionId string, peerId string) ([]byte, error)
|
||||
GetOneNode(context context.Context, executionID string, peerId string) (*v1.Node, error)
|
||||
GetNamespace(context context.Context, executionID string) (*v1.Namespace, error)
|
||||
CreateSecret(context context.Context, minioId string, executionID string, access string, secret string) error
|
||||
CheckHealth() error
|
||||
GetTargets(ctx context.Context) ([]string,error)
|
||||
CreateAdmiraltySource(context context.Context,executionId string) ([]byte, error)
|
||||
CreateKubeconfigSecret(context context.Context,kubeconfig string, executionId string) ([]byte, error)
|
||||
GetKubeconfigSecret(context context.Context,executionId string) ([]byte, error)
|
||||
CreateAdmiraltyTarget(context context.Context,executionId string)([]byte,error)
|
||||
GetOneNode(context context.Context,executionID string) (*v1.Node, error)
|
||||
}
|
||||
|
||||
var _service = map[string]func() (Infrastructure, error){
|
||||
"kubernetes": NewKubernetesService,
|
||||
}
|
||||
|
||||
func NewServiceByType(t string) (Infrastructure, error) {
|
||||
service, ok := _service[t]
|
||||
if !ok {
|
||||
return nil, errors.New("service not found")
|
||||
}
|
||||
return service()
|
||||
}
|
||||
|
||||
func NewService() (Infrastructure, error) {
|
||||
service, ok := _service[conf.GetConfig().Mode]
|
||||
if !ok {
|
||||
@ -45,3 +34,4 @@ func NewService() (Infrastructure, error) {
|
||||
}
|
||||
return service()
|
||||
}
|
||||
|
||||
|
@ -1,58 +1,29 @@
|
||||
package infrastructure
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"oc-datacenter/conf"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
oclib "cloud.o-forge.io/core/oc-lib"
|
||||
authv1 "k8s.io/api/authentication/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
apply "k8s.io/client-go/applyconfigurations/core/v1"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
var gvrSources = schema.GroupVersionResource{Group: "multicluster.admiralty.io", Version: "v1alpha1", Resource: "sources"}
|
||||
var gvrTargets = schema.GroupVersionResource{Group: "multicluster.admiralty.io", Version: "v1alpha1", Resource: "targets"}
|
||||
|
||||
|
||||
type KubernetesService struct {
|
||||
Set *kubernetes.Clientset
|
||||
}
|
||||
|
||||
func NewDynamicClient() (*dynamic.DynamicClient, error) {
|
||||
config := &rest.Config{
|
||||
Host: conf.GetConfig().KubeHost + ":" + conf.GetConfig().KubePort,
|
||||
TLSClientConfig: rest.TLSClientConfig{
|
||||
CAData: []byte(conf.GetConfig().KubeCA),
|
||||
CertData: []byte(conf.GetConfig().KubeCert),
|
||||
KeyData: []byte(conf.GetConfig().KubeData),
|
||||
},
|
||||
}
|
||||
|
||||
dynamicClient, err := dynamic.NewForConfig(config)
|
||||
if err != nil {
|
||||
return nil, errors.New("Error creating Dynamic client: " + err.Error())
|
||||
}
|
||||
if dynamicClient == nil {
|
||||
return nil, errors.New("Error creating Dynamic client: dynamicClient is nil")
|
||||
}
|
||||
|
||||
return dynamicClient, nil
|
||||
}
|
||||
|
||||
func NewKubernetesService() (Infrastructure, error) {
|
||||
config := &rest.Config{
|
||||
Host: conf.GetConfig().KubeHost + ":" + conf.GetConfig().KubePort,
|
||||
@ -62,7 +33,6 @@ func NewKubernetesService() (Infrastructure, error) {
|
||||
KeyData: []byte(conf.GetConfig().KubeData),
|
||||
},
|
||||
}
|
||||
|
||||
// Create clientset
|
||||
clientset, err := kubernetes.NewForConfig(config)
|
||||
fmt.Println("NewForConfig", clientset, err)
|
||||
@ -112,9 +82,6 @@ func (k *KubernetesService) CreateNamespace(ctx context.Context, ns string) erro
|
||||
namespace := &v1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: ns,
|
||||
Labels: map[string]string{
|
||||
"multicluster-scheduler": "enabled",
|
||||
},
|
||||
},
|
||||
}
|
||||
// Create the namespace
|
||||
@ -199,33 +166,10 @@ func (k *KubernetesService) CreateRoleBinding(ctx context.Context, ns string, ro
|
||||
}
|
||||
|
||||
func (k *KubernetesService) DeleteNamespace(ctx context.Context, ns string) error {
|
||||
targetGVR := schema.GroupVersionResource{
|
||||
Group: "multicluster.admiralty.io",
|
||||
Version: "v1alpha1",
|
||||
Resource: "targets",
|
||||
}
|
||||
|
||||
// Delete the Target
|
||||
dyn, err := NewDynamicClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = dyn.Resource(targetGVR).Namespace(ns).Delete(context.TODO(), "target-"+ns, metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = k.Set.CoreV1().ServiceAccounts(ns).Delete(context.TODO(), "sa-"+ns, metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Delete the namespace
|
||||
if err := k.Set.CoreV1().Namespaces().Delete(ctx, ns, metav1.DeleteOptions{}); err != nil {
|
||||
return errors.New("Error deleting namespace: " + err.Error())
|
||||
}
|
||||
LockKill.Lock()
|
||||
Kill = append(Kill, ns)
|
||||
LockKill.Unlock()
|
||||
fmt.Println("Namespace deleted successfully!")
|
||||
return nil
|
||||
}
|
||||
@ -305,8 +249,8 @@ func (k *KubernetesService) GetTargets(ctx context.Context) ([]string, error) {
|
||||
// - have declared the same namespace as the one where the pods are created in the local cluster
|
||||
//
|
||||
// - have delcared a serviceAccount with sufficient permission to create pods
|
||||
func (k *KubernetesService) CreateAdmiraltyTarget(context context.Context, executionId string, peerId string) ([]byte, error) {
|
||||
exists, err := k.GetKubeconfigSecret(context, executionId, peerId)
|
||||
func (k *KubernetesService) CreateAdmiraltyTarget(context context.Context, executionId string) ([]byte, error) {
|
||||
exists, err := k.GetKubeconfigSecret(context, executionId)
|
||||
if err != nil {
|
||||
fmt.Println("Error verifying kube-secret before creating target")
|
||||
return nil, err
|
||||
@ -317,31 +261,32 @@ func (k *KubernetesService) CreateAdmiraltyTarget(context context.Context, execu
|
||||
return nil, nil // Maybe we could create a wrapper for errors and add more info to have
|
||||
}
|
||||
|
||||
targetName := "target-" + getConcatenatedName(peerId, executionId)
|
||||
target := map[string]interface{}{
|
||||
"apiVersion": "multicluster.admiralty.io/v1alpha1",
|
||||
"kind": "Target",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": targetName,
|
||||
"namespace": executionId,
|
||||
"labels": map[string]interface{}{
|
||||
"peer": peerId,
|
||||
},
|
||||
},
|
||||
"spec": map[string]interface{}{
|
||||
"kubeconfigSecret": map[string]string{
|
||||
"name": "kube-secret-" + getConcatenatedName(peerId, executionId),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
res, err := dynamicClientApply(executionId, targetName, gvrTargets, context, target)
|
||||
var targetManifest string
|
||||
var tpl bytes.Buffer
|
||||
tmpl, err := template.New("target").
|
||||
Parse("{\"apiVersion\": \"multicluster.admiralty.io/v1alpha1\", \"kind\": \"Target\", \"metadata\": {\"name\": \"target-{{.ExecutionId}}\"}, \"spec\": { \"kubeconfigSecret\" :{\"name\": \"kube-secret-{{.ExecutionId}}\"}} }")
|
||||
if err != nil {
|
||||
return nil, errors.New("Error when trying to apply Target definition :" + err.Error())
|
||||
fmt.Println("Error creating the template for the target Manifest")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
err = tmpl.Execute(&tpl, map[string]string{"ExecutionId": executionId})
|
||||
targetManifest = tpl.String()
|
||||
resp, err := postCDRapiKube(
|
||||
*k.Set,
|
||||
context,
|
||||
"/apis/multicluster.admiralty.io/v1alpha1/namespaces/"+executionId+"/targets",
|
||||
[]byte(targetManifest),
|
||||
map[string]string{"fieldManager": "kubectl-client-side-apply"},
|
||||
map[string]string{"fieldValidation": "Strict"},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("Error trying to create a Source on remote cluster : ", err, " : ", resp)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// Admiralty Source allows a cluster to receive pods from a remote cluster
|
||||
@ -353,30 +298,39 @@ func (k *KubernetesService) CreateAdmiraltyTarget(context context.Context, execu
|
||||
// to rather contact the oc-datacenter from the remote cluster to create the source
|
||||
// locally and retrieve the token for the serviceAccount
|
||||
func (k *KubernetesService) CreateAdmiraltySource(context context.Context, executionId string) ([]byte, error) {
|
||||
|
||||
source := map[string]interface{}{
|
||||
"apiVersion": "multicluster.admiralty.io/v1alpha1",
|
||||
"kind": "Source",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "source-" + executionId,
|
||||
"namespace": executionId,
|
||||
},
|
||||
"spec": map[string]interface{}{
|
||||
"serviceAccountName": "sa-" + executionId,
|
||||
},
|
||||
}
|
||||
|
||||
res, err := dynamicClientApply(executionId, "source-"+executionId, gvrSources, context, source)
|
||||
var sourceManifest string
|
||||
var tpl bytes.Buffer
|
||||
tmpl, err := template.New("source").
|
||||
Parse("{\"apiVersion\": \"multicluster.admiralty.io/v1alpha1\", \"kind\": \"Source\", \"metadata\": {\"name\": \"source-{{.ExecutionId}}\"}, \"spec\": {\"serviceAccountName\": \"sa-{{.ExecutionId}}\"} }")
|
||||
if err != nil {
|
||||
return nil, errors.New("Error when trying to apply Source definition :" + err.Error())
|
||||
fmt.Println("Error creating the template for the source Manifest")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
err = tmpl.Execute(&tpl, map[string]string{"ExecutionId": executionId})
|
||||
sourceManifest = tpl.String()
|
||||
|
||||
resp, err := postCDRapiKube(
|
||||
*k.Set,
|
||||
context,
|
||||
"/apis/multicluster.admiralty.io/v1alpha1/namespaces/"+executionId+"/sources",
|
||||
[]byte(sourceManifest),
|
||||
map[string]string{"fieldManager": "kubectl-client-side-apply"},
|
||||
map[string]string{"fieldValidation": "Strict"},
|
||||
)
|
||||
|
||||
// We can add more info to the log with the content of resp if not nil
|
||||
if err != nil {
|
||||
fmt.Println("Error trying to create a Source on remote cluster : ", err, " : ", resp)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// Create a secret from a kubeconfing. Use it to create the secret binded to an Admiralty
|
||||
// target, which must contain the serviceAccount's token value
|
||||
func (k *KubernetesService) CreateKubeconfigSecret(context context.Context, kubeconfig string, executionId string, peerId string) ([]byte, error) {
|
||||
func (k *KubernetesService) CreateKubeconfigSecret(context context.Context, kubeconfig string, executionId string) ([]byte, error) {
|
||||
config, err := base64.StdEncoding.DecodeString(kubeconfig)
|
||||
// config, err := base64.RawStdEncoding.DecodeString(kubeconfig)
|
||||
if err != nil {
|
||||
@ -385,34 +339,32 @@ func (k *KubernetesService) CreateKubeconfigSecret(context context.Context, kube
|
||||
return nil, err
|
||||
}
|
||||
|
||||
secretApplyConfig := apply.Secret("kube-secret-"+getConcatenatedName(peerId, executionId),
|
||||
executionId).
|
||||
WithData(map[string][]byte{
|
||||
secretManifest := &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "kube-secret-" + executionId,
|
||||
Namespace: executionId,
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"config": config,
|
||||
},
|
||||
)
|
||||
|
||||
// exists, err := k.GetKubeconfigSecret(context,executionId)
|
||||
// if err != nil {
|
||||
// fmt.Println("Error verifying if kube secret exists in namespace ", executionId)
|
||||
// return nil, err
|
||||
// }
|
||||
// if exists != nil {
|
||||
// fmt.Println("kube-secret already exists in namespace", executionId)
|
||||
// fmt.Println("Overriding existing kube-secret with a newer resource")
|
||||
// // TODO : implement DeleteKubeConfigSecret(executionID)
|
||||
// deleted, err := k.DeleteKubeConfigSecret(executionId)
|
||||
// _ = deleted
|
||||
// _ = err
|
||||
// }
|
||||
}
|
||||
|
||||
exists, err := k.GetKubeconfigSecret(context, executionId)
|
||||
if err != nil {
|
||||
fmt.Println("Error verifying if kube secret exists in namespace ", executionId)
|
||||
return nil, err
|
||||
}
|
||||
if exists != nil {
|
||||
fmt.Println("kube-secret already exists in namespace", executionId)
|
||||
fmt.Println("Overriding existing kube-secret with a newer resource")
|
||||
// TODO : implement DeleteKubeConfigSecret(executionID)
|
||||
deleted, err := k.DeleteKubeConfigSecret(executionId)
|
||||
_ = deleted
|
||||
_ = err
|
||||
}
|
||||
resp, err := k.Set.CoreV1().
|
||||
Secrets(executionId).
|
||||
Apply(context,
|
||||
secretApplyConfig,
|
||||
metav1.ApplyOptions{
|
||||
FieldManager: "admiralty-manager",
|
||||
})
|
||||
Create(context, secretManifest, metav1.CreateOptions{})
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("Error while trying to contact API to get secret kube-secret-" + executionId)
|
||||
@ -429,10 +381,10 @@ func (k *KubernetesService) CreateKubeconfigSecret(context context.Context, kube
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (k *KubernetesService) GetKubeconfigSecret(context context.Context, executionId string, peerId string) ([]byte, error) {
|
||||
func (k *KubernetesService) GetKubeconfigSecret(context context.Context, executionId string) ([]byte, error) {
|
||||
resp, err := k.Set.CoreV1().
|
||||
Secrets(executionId).
|
||||
Get(context, "kube-secret-"+getConcatenatedName(peerId, executionId), metav1.GetOptions{})
|
||||
Get(context, "kube-secret-"+executionId, metav1.GetOptions{})
|
||||
|
||||
if err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
@ -460,21 +412,6 @@ func (k *KubernetesService) DeleteKubeConfigSecret(executionID string) ([]byte,
|
||||
return []byte{}, nil
|
||||
}
|
||||
|
||||
func (k *KubernetesService) GetNamespace(context context.Context, executionID string)(*v1.Namespace,error){
|
||||
resp, err := k.Set.CoreV1().Namespaces().Get(context,executionID,metav1.GetOptions{})
|
||||
if apierrors.IsNotFound(err) {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
logger := oclib.GetLogger()
|
||||
logger.Error().Msg("An error occured when trying to get namespace " + executionID + " : " + err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
|
||||
func getCDRapiKube(client kubernetes.Clientset, ctx context.Context, path string) ([]byte, error) {
|
||||
resp, err := client.RESTClient().Get().
|
||||
AbsPath(path).
|
||||
@ -488,80 +425,32 @@ func getCDRapiKube(client kubernetes.Clientset, ctx context.Context, path string
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func dynamicClientApply(executionId string, resourceName string, resourceDefinition schema.GroupVersionResource, ctx context.Context, object map[string]interface{}) ([]byte, error) {
|
||||
cli, err := NewDynamicClient()
|
||||
if err != nil {
|
||||
return nil, errors.New("Could not retrieve dynamic client when creating Admiralty Source : " + err.Error())
|
||||
func postCDRapiKube(client kubernetes.Clientset, ctx context.Context, path string, body []byte, params ...map[string]string) ([]byte, error) {
|
||||
req := client.RESTClient().
|
||||
Post().
|
||||
AbsPath(path).
|
||||
Body(body)
|
||||
|
||||
for _, param := range params {
|
||||
for k, v := range param {
|
||||
req = req.Param(k, v)
|
||||
}
|
||||
}
|
||||
|
||||
res, err := cli.Resource(resourceDefinition).
|
||||
Namespace(executionId).
|
||||
Apply(ctx,
|
||||
resourceName,
|
||||
&unstructured.Unstructured{Object: object},
|
||||
metav1.ApplyOptions{
|
||||
FieldManager: "kubectl-client-side-apply",
|
||||
},
|
||||
)
|
||||
resp, err := req.DoRaw(ctx)
|
||||
|
||||
if err != nil {
|
||||
o, err := json.Marshal(object)
|
||||
fmt.Println("Error from k8s API when applying "+fmt.Sprint(string(o))+" to "+gvrSources.String()+" : ", err)
|
||||
fmt.Println("Error from k8s API when posting "+string(body)+" to "+path+" : ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// We can add more info to the log with the content of resp if not nil
|
||||
resByte, err := json.Marshal(res)
|
||||
if err != nil {
|
||||
// fmt.Println("Error trying to create a Source on remote cluster : ", err , " : ", res)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resByte, nil
|
||||
|
||||
}
|
||||
|
||||
func (k *KubernetesService) CheckHealth() error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// Check API server connectivity
|
||||
_, err := k.Set.ServerVersion()
|
||||
if err != nil {
|
||||
return fmt.Errorf("API server unreachable: %v", err)
|
||||
}
|
||||
|
||||
// Check nodes status
|
||||
nodes, err := k.Set.CoreV1().Nodes().List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list nodes: %v", err)
|
||||
}
|
||||
for _, node := range nodes.Items {
|
||||
for _, condition := range node.Status.Conditions {
|
||||
if condition.Type == "Ready" && condition.Status != "True" {
|
||||
return fmt.Errorf("node %s not ready", node.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Optional: Check if all pods in kube-system are running
|
||||
pods, err := k.Set.CoreV1().Pods("kube-system").List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list pods: %v", err)
|
||||
}
|
||||
for _, pod := range pods.Items {
|
||||
if pod.Status.Phase != "Running" && pod.Status.Phase != "Succeeded" {
|
||||
return fmt.Errorf("pod %s in namespace kube-system is %s", pod.Name, pod.Status.Phase)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// Returns the Kubernetes' Node object corresponding to the executionID if it exists on this host
|
||||
//
|
||||
// The node is created when an admiralty Target (on host) can connect to an admiralty Source (on remote)
|
||||
func (k *KubernetesService) GetOneNode(context context.Context, executionID string, peerId string) (*v1.Node, error) {
|
||||
concatenatedName := getConcatenatedName(peerId, executionID)
|
||||
|
||||
func (k *KubernetesService) GetOneNode(context context.Context, executionID string) (*v1.Node, error) {
|
||||
res, err := k.Set.CoreV1().
|
||||
Nodes().
|
||||
List(
|
||||
@ -575,45 +464,10 @@ func (k *KubernetesService) GetOneNode(context context.Context, executionID stri
|
||||
}
|
||||
|
||||
for _, node := range res.Items {
|
||||
if isNode := strings.Contains(node.Name, "admiralty-"+executionID+"-target-"+concatenatedName+"-"); isNode {
|
||||
if isNode := strings.Contains(node.Name, "admiralty-"+executionID+"-target-"+executionID+"-"); isNode {
|
||||
return &node, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (k *KubernetesService) CreateSecret(context context.Context, minioId string, executionID string, access string, secret string) error {
|
||||
|
||||
data := map[string][]byte{
|
||||
"access-key": []byte(access),
|
||||
"secret-key": []byte(secret),
|
||||
}
|
||||
|
||||
s := v1.Secret{
|
||||
Type: v1.SecretTypeOpaque,
|
||||
Data: data,
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: minioId+"-secret-s3",
|
||||
},
|
||||
}
|
||||
|
||||
_, err := k.Set.CoreV1().Secrets(executionID).Create(context,&s,metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
logger := oclib.GetLogger()
|
||||
logger.Error().Msg("An error happened when creating the secret holding minio credentials in namespace " + executionID + " : " + err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Returns a concatenation of the peerId and namespace in order for
|
||||
// kubernetes ressources to have a unique name, under 63 characters
|
||||
// and yet identify which peer they are created for
|
||||
func getConcatenatedName(peerId string, namespace string) string {
|
||||
s := strings.Split(namespace, "-")[:2]
|
||||
n := s[0] + "-" + s[1]
|
||||
|
||||
return peerId + "-" + n
|
||||
}
|
||||
|
@ -1,106 +0,0 @@
|
||||
package infrastructure
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"oc-datacenter/conf"
|
||||
|
||||
"github.com/minio/madmin-go/v4"
|
||||
"github.com/minio/minio-go/v7/pkg/credentials"
|
||||
|
||||
"github.com/necmettindev/randomstring"
|
||||
)
|
||||
|
||||
type MinioService struct{
|
||||
Url string
|
||||
RootKey string
|
||||
RootSecret string
|
||||
MinioClient *madmin.AdminClient
|
||||
}
|
||||
|
||||
type StatementEntry struct {
|
||||
Effect string `json:"Effect"`
|
||||
Action []string `json:"Action"`
|
||||
Resource string `json:"Resource"`
|
||||
}
|
||||
|
||||
type PolicyDocument struct {
|
||||
Version string `json:"Version"`
|
||||
Statement []StatementEntry `json:"Statement"`
|
||||
}
|
||||
|
||||
|
||||
func NewMinioService(url string) *MinioService {
|
||||
return &MinioService{
|
||||
Url: url,
|
||||
RootKey: conf.GetConfig().MinioRootKey,
|
||||
RootSecret: conf.GetConfig().MinioRootSecret,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MinioService) CreateClient() error {
|
||||
cred := credentials.NewStaticV4(m.RootKey,m.RootSecret,"")
|
||||
cli, err := madmin.NewWithOptions(m.Url, &madmin.Options{Creds: cred, Secure: false}) // Maybe in the future we should use the secure option ?
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.MinioClient = cli
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MinioService) CreateCredentials(executionId string) (string,string,error){
|
||||
|
||||
policy := PolicyDocument{
|
||||
Version: "2012-10-17",
|
||||
Statement: []StatementEntry{
|
||||
{
|
||||
Effect: "Allow",
|
||||
Action: []string{"s3:GetObject", "s3:PutObject"},
|
||||
Resource: "arn:aws:s3:::"+executionId+"/*",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
p, err := json.Marshal(policy)
|
||||
if err != nil {
|
||||
return "","",err
|
||||
}
|
||||
|
||||
randAccess, randSecret := getRandomCreds()
|
||||
|
||||
req := madmin.AddServiceAccountReq{
|
||||
Policy: p,
|
||||
TargetUser: m.RootKey,
|
||||
AccessKey: randAccess,
|
||||
SecretKey: randSecret,
|
||||
}
|
||||
|
||||
res, err := m.MinioClient.AddServiceAccount(context.Background(), req)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
|
||||
return res.AccessKey, res.SecretKey, nil
|
||||
|
||||
}
|
||||
|
||||
func getRandomCreds() (string, string){
|
||||
opts := randomstring.GenerationOptions{
|
||||
Length: 20,
|
||||
}
|
||||
|
||||
a, _ := randomstring.GenerateString(opts)
|
||||
|
||||
opts.Length = 40
|
||||
s, _ := randomstring.GenerateString(opts)
|
||||
|
||||
return a,s
|
||||
|
||||
}
|
||||
|
||||
func (m *MinioService) CreateBucket(executionId string) error {
|
||||
|
||||
return nil
|
||||
}
|
@ -1,203 +0,0 @@
|
||||
package infrastructure
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"slices"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
oclib "cloud.o-forge.io/core/oc-lib"
|
||||
"cloud.o-forge.io/core/oc-lib/dbs"
|
||||
"cloud.o-forge.io/core/oc-lib/models/booking"
|
||||
"cloud.o-forge.io/core/oc-lib/models/common/models"
|
||||
"cloud.o-forge.io/core/oc-lib/models/live"
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
type MetricsSnapshot struct {
|
||||
From string `json:"origin"`
|
||||
Metrics []Metric `json:"metrics"`
|
||||
}
|
||||
|
||||
type Metric struct {
|
||||
Name string `json:"name"`
|
||||
Value float64 `json:"value"`
|
||||
Error error `json:"error"`
|
||||
}
|
||||
|
||||
type PrometheusResponse struct {
|
||||
Status string `json:"status"`
|
||||
Data struct {
|
||||
ResultType string `json:"resultType"`
|
||||
Result []struct {
|
||||
Metric map[string]string `json:"metric"`
|
||||
Value []interface{} `json:"value"` // [timestamp, value]
|
||||
} `json:"result"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
var queriesMetrics = []string{
|
||||
"rate(container_cpu_usage_seconds_total{namespace=\"%s\"}[1m]) * 100",
|
||||
"container_memory_usage_bytes{namespace=\"%s\"}",
|
||||
"(container_fs_usage_bytes{namespace=\"%s\"}) / (container_fs_limit_bytes{namespace=\"%s\"}) * 100",
|
||||
"DCGM_FI_DEV_GPU_UTIL{namespace=\"%s\"}",
|
||||
// "system_load_average",
|
||||
"rate(container_fs_reads_bytes_total{namespace=\"%s\"}[1m])",
|
||||
"rate(container_fs_writes_bytes_total{namespace=\"%s\"}[1m])",
|
||||
"rate(container_network_receive_bytes_total{namespace=\"%s\"}[1m])",
|
||||
"rate(container_network_transmit_bytes_total{namespace=\"%s\"}[1m])",
|
||||
// "system_network_latency_ms",
|
||||
"rate(http_requests_total{namespace=\"%s\"}[1m])",
|
||||
"(rate(http_requests_total{status=~\"5..\", namespace=\"%s\"}[1m]) / rate(http_requests_total{namespace=\"%s\"}[1m])) * 100",
|
||||
// "app_mean_time_to_repair_seconds",
|
||||
// "app_mean_time_between_failure_seconds",
|
||||
}
|
||||
|
||||
type PrometheusService struct {
|
||||
}
|
||||
|
||||
func NewPrometheusService() *PrometheusService {
|
||||
return &PrometheusService{}
|
||||
}
|
||||
|
||||
func (p *PrometheusService) queryPrometheus(promURL string, expr string, namespace string) models.Metric {
|
||||
metric := models.Metric{Name: expr, Value: -1}
|
||||
resp, err := http.Get(promURL + "/api/v1/query?query=" + url.QueryEscape(fmt.Sprintf(expr, namespace)))
|
||||
if err != nil {
|
||||
metric.Error = err
|
||||
} else {
|
||||
defer resp.Body.Close()
|
||||
if body, err := io.ReadAll(resp.Body); err == nil {
|
||||
var result PrometheusResponse
|
||||
if err = json.Unmarshal(body, &result); err == nil && len(result.Data.Result) > 0 && len(result.Data.Result[0].Value) == 2 {
|
||||
metric.Value, metric.Error = strconv.ParseFloat(fmt.Sprintf("%s", result.Data.Result[0].Value[1]), 64)
|
||||
}
|
||||
}
|
||||
}
|
||||
return metric
|
||||
}
|
||||
|
||||
func (p *PrometheusService) Call(book *booking.Booking, user string, peerID string, groups []string) (*booking.Booking, map[string]models.MetricsSnapshot) {
|
||||
var wg sync.WaitGroup
|
||||
|
||||
metrics := map[string]models.MetricsSnapshot{}
|
||||
// get all booking... from executions_id == namespace typed datacenter.
|
||||
|
||||
cUAccess := oclib.NewRequest(oclib.LibDataEnum(oclib.LIVE_DATACENTER), user, peerID, groups, nil)
|
||||
cRAccess := oclib.NewRequest(oclib.LibDataEnum(oclib.COMPUTE_RESOURCE), user, peerID, groups, nil)
|
||||
|
||||
rr := cRAccess.LoadOne(book.ResourceID)
|
||||
if rr.Err != "" {
|
||||
fmt.Errorf("can't proceed because of unfound resource %s : %s", book.ResourceID, rr.Err)
|
||||
return book, metrics
|
||||
}
|
||||
computeRes := rr.ToComputeResource()
|
||||
for _, instance := range computeRes.Instances {
|
||||
res := cUAccess.Search(&dbs.Filters{
|
||||
And: map[string][]dbs.Filter{
|
||||
"source": {{Operator: dbs.EQUAL.String(), Value: instance.Source}},
|
||||
"abstractlive.resources_id": {{Operator: dbs.EQUAL.String(), Value: computeRes.GetID()}},
|
||||
},
|
||||
}, "", false)
|
||||
if res.Err != "" {
|
||||
continue
|
||||
}
|
||||
for _, r := range res.Data {
|
||||
// TODO watch out ... to not exec on an absent datacenter...
|
||||
if r.(*live.LiveDatacenter).MonitorPath == "" {
|
||||
continue
|
||||
}
|
||||
wg.Add(1)
|
||||
snapshot := models.MetricsSnapshot{From: instance.Source, Metrics: []models.Metric{}}
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for _, expr := range queriesMetrics {
|
||||
snapshot.Metrics = append(snapshot.Metrics,
|
||||
p.queryPrometheus(r.(*live.LiveDatacenter).MonitorPath, expr, book.ExecutionsID))
|
||||
}
|
||||
metrics[instance.Name] = snapshot
|
||||
}()
|
||||
}
|
||||
}
|
||||
wg.Wait()
|
||||
return book, metrics
|
||||
}
|
||||
|
||||
var LockKill = &sync.Mutex{}
|
||||
|
||||
// TODO kill procedure
|
||||
func (p *PrometheusService) Stream(bookingID string, interval time.Duration, user string, peerID string, groups []string, websocket *websocket.Conn) {
|
||||
|
||||
max := 100
|
||||
bookIDS := []string{}
|
||||
mets := map[string][]models.MetricsSnapshot{}
|
||||
bAccess := oclib.NewRequest(oclib.LibDataEnum(oclib.BOOKING), user, peerID, groups, nil)
|
||||
book := bAccess.LoadOne(bookingID)
|
||||
if book.Err != "" {
|
||||
fmt.Errorf("stop because of empty : %s", book.Err)
|
||||
}
|
||||
f := func(e *booking.Booking) bool {
|
||||
if e.ExpectedEndDate == nil {
|
||||
return true
|
||||
}
|
||||
return time.Now().Before(*e.ExpectedEndDate)
|
||||
}
|
||||
for f(book.Data.(*booking.Booking)) {
|
||||
if slices.Contains(Kill, book.Data.(*booking.Booking).ExecutionsID) {
|
||||
newKill := []string{}
|
||||
for _, k := range Kill {
|
||||
if k != book.Data.(*booking.Booking).ExecutionsID {
|
||||
newKill = append(newKill, k)
|
||||
}
|
||||
}
|
||||
LockKill.Lock()
|
||||
Kill = newKill
|
||||
LockKill.Unlock()
|
||||
break
|
||||
}
|
||||
|
||||
go func() {
|
||||
book, metrics := p.Call(book.Data.(*booking.Booking), user, peerID, groups)
|
||||
for k, v := range metrics {
|
||||
if me, ok := mets[k]; !ok {
|
||||
mets[k] = []models.MetricsSnapshot{v}
|
||||
} else {
|
||||
me = append(me, v)
|
||||
mets[k] = me
|
||||
}
|
||||
}
|
||||
bookIDS = append(bookIDS, bookingID)
|
||||
if websocket != nil {
|
||||
(*websocket).WriteJSON(metrics)
|
||||
}
|
||||
if len(bookIDS) != max {
|
||||
return
|
||||
}
|
||||
if book.ExecutionMetrics == nil {
|
||||
book.ExecutionMetrics = mets
|
||||
} else {
|
||||
for kk, vv := range mets {
|
||||
if em, ok := book.ExecutionMetrics[kk]; !ok {
|
||||
book.ExecutionMetrics[kk] = vv
|
||||
} else {
|
||||
em = append(em, vv...)
|
||||
book.ExecutionMetrics[kk] = em
|
||||
}
|
||||
}
|
||||
}
|
||||
book.GetAccessor(nil).UpdateOne(book, bookingID)
|
||||
bookIDS = []string{}
|
||||
|
||||
}()
|
||||
time.Sleep(interval)
|
||||
}
|
||||
}
|
||||
|
||||
var Kill = []string{}
|
||||
|
||||
// should add a datacenter... under juridiction... of opencloud...
|
5
main.go
5
main.go
@ -36,11 +36,6 @@ func main() {
|
||||
if err == nil {
|
||||
conf.GetConfig().KubeData = string(sDec)
|
||||
}
|
||||
|
||||
conf.GetConfig().MinioRootKey = o.GetStringDefault("MINIO_ADMIN_ACCESS","")
|
||||
conf.GetConfig().MinioRootSecret = o.GetStringDefault("MINIO_ADMIN_SECRET","")
|
||||
|
||||
|
||||
// feed the library with the loaded config
|
||||
oclib.SetConfig(
|
||||
o.GetStringDefault("MONGO_URL", "mongodb://127.0.0.1:27017"),
|
||||
|
@ -19,7 +19,7 @@ func init() {
|
||||
beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"],
|
||||
beego.ControllerComments{
|
||||
Method: "GetNodeReady",
|
||||
Router: `/node/:execution/:peer`,
|
||||
Router: `/node/:execution`,
|
||||
AllowHTTPMethods: []string{"get"},
|
||||
MethodParams: param.Make(),
|
||||
Filters: nil,
|
||||
@ -28,7 +28,7 @@ func init() {
|
||||
beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"],
|
||||
beego.ControllerComments{
|
||||
Method: "GetKubeSecret",
|
||||
Router: `/secret/:execution/:peer`,
|
||||
Router: `/secret/:execution`,
|
||||
AllowHTTPMethods: []string{"get"},
|
||||
MethodParams: param.Make(),
|
||||
Filters: nil,
|
||||
@ -37,7 +37,7 @@ func init() {
|
||||
beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"],
|
||||
beego.ControllerComments{
|
||||
Method: "CreateKubeSecret",
|
||||
Router: `/secret/:execution/:peer`,
|
||||
Router: `/secret/:execution`,
|
||||
AllowHTTPMethods: []string{"post"},
|
||||
MethodParams: param.Make(),
|
||||
Filters: nil,
|
||||
@ -45,7 +45,7 @@ func init() {
|
||||
|
||||
beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"],
|
||||
beego.ControllerComments{
|
||||
Method: "CreateAdmiraltySource",
|
||||
Method: "CreateSource",
|
||||
Router: `/source/:execution`,
|
||||
AllowHTTPMethods: []string{"post"},
|
||||
MethodParams: param.Make(),
|
||||
@ -55,7 +55,7 @@ func init() {
|
||||
beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"],
|
||||
beego.ControllerComments{
|
||||
Method: "CreateAdmiraltyTarget",
|
||||
Router: `/target/:execution/:peer`,
|
||||
Router: `/target/:execution`,
|
||||
AllowHTTPMethods: []string{"post"},
|
||||
MethodParams: param.Make(),
|
||||
Filters: nil,
|
||||
@ -79,15 +79,6 @@ func init() {
|
||||
Filters: nil,
|
||||
Params: nil})
|
||||
|
||||
beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"],
|
||||
beego.ControllerComments{
|
||||
Method: "DeleteAdmiraltySession",
|
||||
Router: `/targets/:execution`,
|
||||
AllowHTTPMethods: []string{"delete"},
|
||||
MethodParams: param.Make(),
|
||||
Filters: nil,
|
||||
Params: nil})
|
||||
|
||||
beego.GlobalControllerRouter["oc-datacenter/controllers:BookingController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:BookingController"],
|
||||
beego.ControllerComments{
|
||||
Method: "GetAll",
|
||||
@ -115,15 +106,6 @@ func init() {
|
||||
Filters: nil,
|
||||
Params: nil})
|
||||
|
||||
beego.GlobalControllerRouter["oc-datacenter/controllers:BookingController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:BookingController"],
|
||||
beego.ControllerComments{
|
||||
Method: "Log",
|
||||
Router: `/:id`,
|
||||
AllowHTTPMethods: []string{"get"},
|
||||
MethodParams: param.Make(),
|
||||
Filters: nil,
|
||||
Params: nil})
|
||||
|
||||
beego.GlobalControllerRouter["oc-datacenter/controllers:BookingController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:BookingController"],
|
||||
beego.ControllerComments{
|
||||
Method: "Put",
|
||||
@ -142,24 +124,6 @@ func init() {
|
||||
Filters: nil,
|
||||
Params: nil})
|
||||
|
||||
beego.GlobalControllerRouter["oc-datacenter/controllers:BookingController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:BookingController"],
|
||||
beego.ControllerComments{
|
||||
Method: "ExtendForExecution",
|
||||
Router: `/extend/:resource_id/from_execution/:execution_id/to/:duration`,
|
||||
AllowHTTPMethods: []string{"post"},
|
||||
MethodParams: param.Make(),
|
||||
Filters: nil,
|
||||
Params: nil})
|
||||
|
||||
beego.GlobalControllerRouter["oc-datacenter/controllers:BookingController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:BookingController"],
|
||||
beego.ControllerComments{
|
||||
Method: "ExtendForNamespace",
|
||||
Router: `/extend/:resource_id/from_namespace/:namespace/to/:duration`,
|
||||
AllowHTTPMethods: []string{"post"},
|
||||
MethodParams: param.Make(),
|
||||
Filters: nil,
|
||||
Params: nil})
|
||||
|
||||
beego.GlobalControllerRouter["oc-datacenter/controllers:BookingController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:BookingController"],
|
||||
beego.ControllerComments{
|
||||
Method: "Search",
|
||||
@ -196,15 +160,6 @@ func init() {
|
||||
Filters: nil,
|
||||
Params: nil})
|
||||
|
||||
beego.GlobalControllerRouter["oc-datacenter/controllers:MinioController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:MinioController"],
|
||||
beego.ControllerComments{
|
||||
Method: "CreateServiceAccount",
|
||||
Router: `/serviceaccount/:minioId/:executions`,
|
||||
AllowHTTPMethods: []string{"post"},
|
||||
MethodParams: param.Make(),
|
||||
Filters: nil,
|
||||
Params: nil})
|
||||
|
||||
beego.GlobalControllerRouter["oc-datacenter/controllers:SessionController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:SessionController"],
|
||||
beego.ControllerComments{
|
||||
Method: "GetToken",
|
||||
|
@ -39,11 +39,6 @@ func init() {
|
||||
&controllers.AdmiraltyController{},
|
||||
),
|
||||
),
|
||||
beego.NSNamespace("/minio",
|
||||
beego.NSInclude(
|
||||
&controllers.MinioController{},
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
beego.AddNamespace(ns)
|
||||
|
Loading…
Reference in New Issue
Block a user